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