ARMInstPrinter.cpp revision 41ad0c4c730bdbd4ec3a03868b81a56b6b1b01a1
1//===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This class prints an ARM MCInst to a .s file. 11// 12//===----------------------------------------------------------------------===// 13 14#define DEBUG_TYPE "asm-printer" 15#include "ARMBaseInfo.h" 16#include "ARMInstPrinter.h" 17#include "ARMAddressingModes.h" 18#include "llvm/MC/MCInst.h" 19#include "llvm/MC/MCAsmInfo.h" 20#include "llvm/MC/MCExpr.h" 21#include "llvm/ADT/StringExtras.h" 22#include "llvm/Support/raw_ostream.h" 23using namespace llvm; 24 25#define GET_INSTRUCTION_NAME 26#include "ARMGenAsmWriter.inc" 27 28StringRef ARMInstPrinter::getOpcodeName(unsigned Opcode) const { 29 return getInstructionName(Opcode); 30} 31 32 33void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) { 34 unsigned Opcode = MI->getOpcode(); 35 36 // Check for MOVs and print canonical forms, instead. 37 if (Opcode == ARM::MOVs) { 38 // FIXME: Thumb variants? 39 const MCOperand &Dst = MI->getOperand(0); 40 const MCOperand &MO1 = MI->getOperand(1); 41 const MCOperand &MO2 = MI->getOperand(2); 42 const MCOperand &MO3 = MI->getOperand(3); 43 44 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm())); 45 printSBitModifierOperand(MI, 6, O); 46 printPredicateOperand(MI, 4, O); 47 48 O << '\t' << getRegisterName(Dst.getReg()) 49 << ", " << getRegisterName(MO1.getReg()); 50 51 if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx) 52 return; 53 54 O << ", "; 55 56 if (MO2.getReg()) { 57 O << getRegisterName(MO2.getReg()); 58 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); 59 } else { 60 O << "#" << ARM_AM::getSORegOffset(MO3.getImm()); 61 } 62 return; 63 } 64 65 // A8.6.123 PUSH 66 if ((Opcode == ARM::STMDB_UPD || Opcode == ARM::t2STMDB_UPD) && 67 MI->getOperand(0).getReg() == ARM::SP) { 68 O << '\t' << "push"; 69 printPredicateOperand(MI, 2, O); 70 if (Opcode == ARM::t2STMDB_UPD) 71 O << ".w"; 72 O << '\t'; 73 printRegisterList(MI, 4, O); 74 return; 75 } 76 77 // A8.6.122 POP 78 if ((Opcode == ARM::LDMIA_UPD || Opcode == ARM::t2LDMIA_UPD) && 79 MI->getOperand(0).getReg() == ARM::SP) { 80 O << '\t' << "pop"; 81 printPredicateOperand(MI, 2, O); 82 if (Opcode == ARM::t2LDMIA_UPD) 83 O << ".w"; 84 O << '\t'; 85 printRegisterList(MI, 4, O); 86 return; 87 } 88 89 // A8.6.355 VPUSH 90 if ((Opcode == ARM::VSTMSDB_UPD || Opcode == ARM::VSTMDDB_UPD) && 91 MI->getOperand(0).getReg() == ARM::SP) { 92 O << '\t' << "vpush"; 93 printPredicateOperand(MI, 2, O); 94 O << '\t'; 95 printRegisterList(MI, 4, O); 96 return; 97 } 98 99 // A8.6.354 VPOP 100 if ((Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMDIA_UPD) && 101 MI->getOperand(0).getReg() == ARM::SP) { 102 O << '\t' << "vpop"; 103 printPredicateOperand(MI, 2, O); 104 O << '\t'; 105 printRegisterList(MI, 4, O); 106 return; 107 } 108 109 printInstruction(MI, O); 110} 111 112void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 113 raw_ostream &O) { 114 const MCOperand &Op = MI->getOperand(OpNo); 115 if (Op.isReg()) { 116 unsigned Reg = Op.getReg(); 117 O << getRegisterName(Reg); 118 } else if (Op.isImm()) { 119 O << '#' << Op.getImm(); 120 } else { 121 assert(Op.isExpr() && "unknown operand kind in printOperand"); 122 O << *Op.getExpr(); 123 } 124} 125 126static void printSOImm(raw_ostream &O, int64_t V, raw_ostream *CommentStream, 127 const MCAsmInfo *MAI) { 128 // Break it up into two parts that make up a shifter immediate. 129 V = ARM_AM::getSOImmVal(V); 130 assert(V != -1 && "Not a valid so_imm value!"); 131 132 unsigned Imm = ARM_AM::getSOImmValImm(V); 133 unsigned Rot = ARM_AM::getSOImmValRot(V); 134 135 // Print low-level immediate formation info, per 136 // A5.1.3: "Data-processing operands - Immediate". 137 if (Rot) { 138 O << "#" << Imm << ", " << Rot; 139 // Pretty printed version. 140 if (CommentStream) 141 *CommentStream << (int)ARM_AM::rotr32(Imm, Rot) << "\n"; 142 } else { 143 O << "#" << Imm; 144 } 145} 146 147 148/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit 149/// immediate in bits 0-7. 150void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum, 151 raw_ostream &O) { 152 const MCOperand &MO = MI->getOperand(OpNum); 153 assert(MO.isImm() && "Not a valid so_imm value!"); 154 printSOImm(O, MO.getImm(), CommentStream, &MAI); 155} 156 157// so_reg is a 4-operand unit corresponding to register forms of the A5.1 158// "Addressing Mode 1 - Data-processing operands" forms. This includes: 159// REG 0 0 - e.g. R5 160// REG REG 0,SH_OPC - e.g. R5, ROR R3 161// REG 0 IMM,SH_OPC - e.g. R5, LSL #3 162void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum, 163 raw_ostream &O) { 164 const MCOperand &MO1 = MI->getOperand(OpNum); 165 const MCOperand &MO2 = MI->getOperand(OpNum+1); 166 const MCOperand &MO3 = MI->getOperand(OpNum+2); 167 168 O << getRegisterName(MO1.getReg()); 169 170 // Print the shift opc. 171 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm()); 172 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 173 if (MO2.getReg()) { 174 O << ' ' << getRegisterName(MO2.getReg()); 175 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); 176 } else if (ShOpc != ARM_AM::rrx) { 177 O << " #" << ARM_AM::getSORegOffset(MO3.getImm()); 178 } 179} 180 181 182void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op, 183 raw_ostream &O) { 184 const MCOperand &MO1 = MI->getOperand(Op); 185 const MCOperand &MO2 = MI->getOperand(Op+1); 186 const MCOperand &MO3 = MI->getOperand(Op+2); 187 188 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 189 printOperand(MI, Op, O); 190 return; 191 } 192 193 O << "[" << getRegisterName(MO1.getReg()); 194 195 if (!MO2.getReg()) { 196 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. 197 O << ", #" 198 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 199 << ARM_AM::getAM2Offset(MO3.getImm()); 200 O << "]"; 201 return; 202 } 203 204 O << ", " 205 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 206 << getRegisterName(MO2.getReg()); 207 208 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) 209 O << ", " 210 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) 211 << " #" << ShImm; 212 O << "]"; 213} 214 215void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI, 216 unsigned OpNum, 217 raw_ostream &O) { 218 const MCOperand &MO1 = MI->getOperand(OpNum); 219 const MCOperand &MO2 = MI->getOperand(OpNum+1); 220 221 if (!MO1.getReg()) { 222 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm()); 223 O << '#' 224 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 225 << ImmOffs; 226 return; 227 } 228 229 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 230 << getRegisterName(MO1.getReg()); 231 232 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) 233 O << ", " 234 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm())) 235 << " #" << ShImm; 236} 237 238void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum, 239 raw_ostream &O) { 240 const MCOperand &MO1 = MI->getOperand(OpNum); 241 const MCOperand &MO2 = MI->getOperand(OpNum+1); 242 const MCOperand &MO3 = MI->getOperand(OpNum+2); 243 244 O << '[' << getRegisterName(MO1.getReg()); 245 246 if (MO2.getReg()) { 247 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm()) 248 << getRegisterName(MO2.getReg()) << ']'; 249 return; 250 } 251 252 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) 253 O << ", #" 254 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm())) 255 << ImmOffs; 256 O << ']'; 257} 258 259void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI, 260 unsigned OpNum, 261 raw_ostream &O) { 262 const MCOperand &MO1 = MI->getOperand(OpNum); 263 const MCOperand &MO2 = MI->getOperand(OpNum+1); 264 265 if (MO1.getReg()) { 266 O << (char)ARM_AM::getAM3Op(MO2.getImm()) 267 << getRegisterName(MO1.getReg()); 268 return; 269 } 270 271 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm()); 272 O << '#' 273 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) 274 << ImmOffs; 275} 276 277void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum, 278 raw_ostream &O) { 279 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum) 280 .getImm()); 281 O << ARM_AM::getAMSubModeStr(Mode); 282} 283 284void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum, 285 raw_ostream &O) { 286 const MCOperand &MO1 = MI->getOperand(OpNum); 287 const MCOperand &MO2 = MI->getOperand(OpNum+1); 288 289 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 290 printOperand(MI, OpNum, O); 291 return; 292 } 293 294 O << "[" << getRegisterName(MO1.getReg()); 295 296 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) { 297 O << ", #" 298 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm())) 299 << ImmOffs * 4; 300 } 301 O << "]"; 302} 303 304void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum, 305 raw_ostream &O) { 306 const MCOperand &MO1 = MI->getOperand(OpNum); 307 const MCOperand &MO2 = MI->getOperand(OpNum+1); 308 309 O << "[" << getRegisterName(MO1.getReg()); 310 if (MO2.getImm()) { 311 // FIXME: Both darwin as and GNU as violate ARM docs here. 312 O << ", :" << (MO2.getImm() << 3); 313 } 314 O << "]"; 315} 316 317void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI, 318 unsigned OpNum, 319 raw_ostream &O) { 320 const MCOperand &MO = MI->getOperand(OpNum); 321 if (MO.getReg() == 0) 322 O << "!"; 323 else 324 O << ", " << getRegisterName(MO.getReg()); 325} 326 327void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI, 328 unsigned OpNum, 329 raw_ostream &O) { 330 const MCOperand &MO = MI->getOperand(OpNum); 331 uint32_t v = ~MO.getImm(); 332 int32_t lsb = CountTrailingZeros_32(v); 333 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb; 334 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!"); 335 O << '#' << lsb << ", #" << width; 336} 337 338void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum, 339 raw_ostream &O) { 340 unsigned val = MI->getOperand(OpNum).getImm(); 341 O << ARM_MB::MemBOptToString(val); 342} 343 344void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum, 345 raw_ostream &O) { 346 unsigned ShiftOp = MI->getOperand(OpNum).getImm(); 347 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp); 348 switch (Opc) { 349 case ARM_AM::no_shift: 350 return; 351 case ARM_AM::lsl: 352 O << ", lsl #"; 353 break; 354 case ARM_AM::asr: 355 O << ", asr #"; 356 break; 357 default: 358 assert(0 && "unexpected shift opcode for shift immediate operand"); 359 } 360 O << ARM_AM::getSORegOffset(ShiftOp); 361} 362 363void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, 364 raw_ostream &O) { 365 O << "{"; 366 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { 367 if (i != OpNum) O << ", "; 368 O << getRegisterName(MI->getOperand(i).getReg()); 369 } 370 O << "}"; 371} 372 373void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum, 374 raw_ostream &O) { 375 const MCOperand &Op = MI->getOperand(OpNum); 376 if (Op.getImm()) 377 O << "be"; 378 else 379 O << "le"; 380} 381 382void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum, 383 raw_ostream &O) { 384 const MCOperand &Op = MI->getOperand(OpNum); 385 unsigned option = Op.getImm(); 386 unsigned mode = option & 31; 387 bool changemode = option >> 5 & 1; 388 unsigned AIF = option >> 6 & 7; 389 unsigned imod = option >> 9 & 3; 390 if (imod == 2) 391 O << "ie"; 392 else if (imod == 3) 393 O << "id"; 394 O << '\t'; 395 if (imod > 1) { 396 if (AIF & 4) O << 'a'; 397 if (AIF & 2) O << 'i'; 398 if (AIF & 1) O << 'f'; 399 if (AIF > 0 && changemode) O << ", "; 400 } 401 if (changemode) 402 O << '#' << mode; 403} 404 405void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum, 406 raw_ostream &O) { 407 const MCOperand &Op = MI->getOperand(OpNum); 408 unsigned Mask = Op.getImm(); 409 if (Mask) { 410 O << '_'; 411 if (Mask & 8) O << 'f'; 412 if (Mask & 4) O << 's'; 413 if (Mask & 2) O << 'x'; 414 if (Mask & 1) O << 'c'; 415 } 416} 417 418void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum, 419 raw_ostream &O) { 420 const MCOperand &Op = MI->getOperand(OpNum); 421 O << '#'; 422 if (Op.getImm() < 0) 423 O << '-' << (-Op.getImm() - 1); 424 else 425 O << Op.getImm(); 426} 427 428void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum, 429 raw_ostream &O) { 430 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 431 if (CC != ARMCC::AL) 432 O << ARMCondCodeToString(CC); 433} 434 435void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI, 436 unsigned OpNum, 437 raw_ostream &O) { 438 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 439 O << ARMCondCodeToString(CC); 440} 441 442void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum, 443 raw_ostream &O) { 444 if (MI->getOperand(OpNum).getReg()) { 445 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR && 446 "Expect ARM CPSR register!"); 447 O << 's'; 448 } 449} 450 451void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum, 452 raw_ostream &O) { 453 O << MI->getOperand(OpNum).getImm(); 454} 455 456void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum, 457 raw_ostream &O) { 458 llvm_unreachable("Unhandled PC-relative pseudo-instruction!"); 459} 460 461void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, 462 raw_ostream &O) { 463 O << "#" << MI->getOperand(OpNum).getImm() * 4; 464} 465 466void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum, 467 raw_ostream &O) { 468 // (3 - the number of trailing zeros) is the number of then / else. 469 unsigned Mask = MI->getOperand(OpNum).getImm(); 470 unsigned CondBit0 = Mask >> 4 & 1; 471 unsigned NumTZ = CountTrailingZeros_32(Mask); 472 assert(NumTZ <= 3 && "Invalid IT mask!"); 473 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) { 474 bool T = ((Mask >> Pos) & 1) == CondBit0; 475 if (T) 476 O << 't'; 477 else 478 O << 'e'; 479 } 480} 481 482void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op, 483 raw_ostream &O) { 484 const MCOperand &MO1 = MI->getOperand(Op); 485 const MCOperand &MO2 = MI->getOperand(Op+1); 486 O << "[" << getRegisterName(MO1.getReg()); 487 O << ", " << getRegisterName(MO2.getReg()) << "]"; 488} 489 490void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op, 491 raw_ostream &O, 492 unsigned Scale) { 493 const MCOperand &MO1 = MI->getOperand(Op); 494 const MCOperand &MO2 = MI->getOperand(Op+1); 495 const MCOperand &MO3 = MI->getOperand(Op+2); 496 497 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 498 printOperand(MI, Op, O); 499 return; 500 } 501 502 O << "[" << getRegisterName(MO1.getReg()); 503 if (MO3.getReg()) 504 O << ", " << getRegisterName(MO3.getReg()); 505 else if (unsigned ImmOffs = MO2.getImm()) 506 O << ", #" << ImmOffs * Scale; 507 O << "]"; 508} 509 510void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op, 511 raw_ostream &O) { 512 printThumbAddrModeRI5Operand(MI, Op, O, 1); 513} 514 515void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op, 516 raw_ostream &O) { 517 printThumbAddrModeRI5Operand(MI, Op, O, 2); 518} 519 520void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op, 521 raw_ostream &O) { 522 printThumbAddrModeRI5Operand(MI, Op, O, 4); 523} 524 525void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op, 526 raw_ostream &O) { 527 const MCOperand &MO1 = MI->getOperand(Op); 528 const MCOperand &MO2 = MI->getOperand(Op+1); 529 O << "[" << getRegisterName(MO1.getReg()); 530 if (unsigned ImmOffs = MO2.getImm()) 531 O << ", #" << ImmOffs*4; 532 O << "]"; 533} 534 535// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 536// register with shift forms. 537// REG 0 0 - e.g. R5 538// REG IMM, SH_OPC - e.g. R5, LSL #3 539void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum, 540 raw_ostream &O) { 541 const MCOperand &MO1 = MI->getOperand(OpNum); 542 const MCOperand &MO2 = MI->getOperand(OpNum+1); 543 544 unsigned Reg = MO1.getReg(); 545 O << getRegisterName(Reg); 546 547 // Print the shift opc. 548 assert(MO2.isImm() && "Not a valid t2_so_reg value!"); 549 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm()); 550 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 551 if (ShOpc != ARM_AM::rrx) 552 O << " #" << ARM_AM::getSORegOffset(MO2.getImm()); 553} 554 555void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum, 556 raw_ostream &O) { 557 const MCOperand &MO1 = MI->getOperand(OpNum); 558 const MCOperand &MO2 = MI->getOperand(OpNum+1); 559 560 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 561 printOperand(MI, OpNum, O); 562 return; 563 } 564 565 O << "[" << getRegisterName(MO1.getReg()); 566 567 int32_t OffImm = (int32_t)MO2.getImm(); 568 bool isSub = OffImm < 0; 569 // Special value for #-0. All others are normal. 570 if (OffImm == INT32_MIN) 571 OffImm = 0; 572 if (isSub) 573 O << ", #-" << -OffImm; 574 else if (OffImm > 0) 575 O << ", #" << OffImm; 576 O << "]"; 577} 578 579void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI, 580 unsigned OpNum, 581 raw_ostream &O) { 582 const MCOperand &MO1 = MI->getOperand(OpNum); 583 const MCOperand &MO2 = MI->getOperand(OpNum+1); 584 585 O << "[" << getRegisterName(MO1.getReg()); 586 587 int32_t OffImm = (int32_t)MO2.getImm(); 588 // Don't print +0. 589 if (OffImm < 0) 590 O << ", #-" << -OffImm; 591 else if (OffImm > 0) 592 O << ", #" << OffImm; 593 O << "]"; 594} 595 596void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI, 597 unsigned OpNum, 598 raw_ostream &O) { 599 const MCOperand &MO1 = MI->getOperand(OpNum); 600 const MCOperand &MO2 = MI->getOperand(OpNum+1); 601 602 O << "[" << getRegisterName(MO1.getReg()); 603 604 int32_t OffImm = (int32_t)MO2.getImm() / 4; 605 // Don't print +0. 606 if (OffImm < 0) 607 O << ", #-" << -OffImm * 4; 608 else if (OffImm > 0) 609 O << ", #" << OffImm * 4; 610 O << "]"; 611} 612 613void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI, 614 unsigned OpNum, 615 raw_ostream &O) { 616 const MCOperand &MO1 = MI->getOperand(OpNum); 617 int32_t OffImm = (int32_t)MO1.getImm(); 618 // Don't print +0. 619 if (OffImm < 0) 620 O << "#-" << -OffImm; 621 else if (OffImm > 0) 622 O << "#" << OffImm; 623} 624 625void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, 626 unsigned OpNum, 627 raw_ostream &O) { 628 const MCOperand &MO1 = MI->getOperand(OpNum); 629 int32_t OffImm = (int32_t)MO1.getImm() / 4; 630 // Don't print +0. 631 if (OffImm < 0) 632 O << "#-" << -OffImm * 4; 633 else if (OffImm > 0) 634 O << "#" << OffImm * 4; 635} 636 637void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI, 638 unsigned OpNum, 639 raw_ostream &O) { 640 const MCOperand &MO1 = MI->getOperand(OpNum); 641 const MCOperand &MO2 = MI->getOperand(OpNum+1); 642 const MCOperand &MO3 = MI->getOperand(OpNum+2); 643 644 O << "[" << getRegisterName(MO1.getReg()); 645 646 assert(MO2.getReg() && "Invalid so_reg load / store address!"); 647 O << ", " << getRegisterName(MO2.getReg()); 648 649 unsigned ShAmt = MO3.getImm(); 650 if (ShAmt) { 651 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); 652 O << ", lsl #" << ShAmt; 653 } 654 O << "]"; 655} 656 657void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, 658 raw_ostream &O) { 659 O << '#' << (float)MI->getOperand(OpNum).getFPImm(); 660} 661 662void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, 663 raw_ostream &O) { 664 O << '#' << MI->getOperand(OpNum).getFPImm(); 665} 666 667void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum, 668 raw_ostream &O) { 669 unsigned EncodedImm = MI->getOperand(OpNum).getImm(); 670 unsigned EltBits; 671 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits); 672 O << "#0x" << utohexstr(Val); 673} 674