ARMInstPrinter.cpp revision e2189144d45be78a89f0daf3df3cf12e38221d86
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::printAddrMode6OffsetOperand(const MCInst *MI, 321 unsigned OpNum, 322 raw_ostream &O) { 323 const MCOperand &MO = MI->getOperand(OpNum); 324 if (MO.getReg() == 0) 325 O << "!"; 326 else 327 O << ", " << getRegisterName(MO.getReg()); 328} 329 330void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI, 331 unsigned OpNum, 332 raw_ostream &O) { 333 const MCOperand &MO = MI->getOperand(OpNum); 334 uint32_t v = ~MO.getImm(); 335 int32_t lsb = CountTrailingZeros_32(v); 336 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb; 337 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!"); 338 O << '#' << lsb << ", #" << width; 339} 340 341void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum, 342 raw_ostream &O) { 343 unsigned val = MI->getOperand(OpNum).getImm(); 344 O << ARM_MB::MemBOptToString(val); 345} 346 347void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum, 348 raw_ostream &O) { 349 unsigned ShiftOp = MI->getOperand(OpNum).getImm(); 350 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp); 351 switch (Opc) { 352 case ARM_AM::no_shift: 353 return; 354 case ARM_AM::lsl: 355 O << ", lsl #"; 356 break; 357 case ARM_AM::asr: 358 O << ", asr #"; 359 break; 360 default: 361 assert(0 && "unexpected shift opcode for shift immediate operand"); 362 } 363 O << ARM_AM::getSORegOffset(ShiftOp); 364} 365 366void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, 367 raw_ostream &O) { 368 O << "{"; 369 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { 370 if (i != OpNum) O << ", "; 371 O << getRegisterName(MI->getOperand(i).getReg()); 372 } 373 O << "}"; 374} 375 376void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum, 377 raw_ostream &O) { 378 const MCOperand &Op = MI->getOperand(OpNum); 379 if (Op.getImm()) 380 O << "be"; 381 else 382 O << "le"; 383} 384 385void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum, 386 raw_ostream &O) { 387 const MCOperand &Op = MI->getOperand(OpNum); 388 O << ARM_PROC::IModToString(Op.getImm()); 389} 390 391void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum, 392 raw_ostream &O) { 393 const MCOperand &Op = MI->getOperand(OpNum); 394 unsigned IFlags = Op.getImm(); 395 for (int i=2; i >= 0; --i) 396 if (IFlags & (1 << i)) 397 O << ARM_PROC::IFlagsToString(1 << i); 398} 399 400void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum, 401 raw_ostream &O) { 402 const MCOperand &Op = MI->getOperand(OpNum); 403 unsigned SpecRegRBit = Op.getImm() >> 4; 404 unsigned Mask = Op.getImm() & 0xf; 405 406 if (SpecRegRBit) 407 O << "spsr"; 408 else 409 O << "cpsr"; 410 411 if (Mask) { 412 O << '_'; 413 if (Mask & 8) O << 'f'; 414 if (Mask & 4) O << 's'; 415 if (Mask & 2) O << 'x'; 416 if (Mask & 1) O << 'c'; 417 } 418} 419 420void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum, 421 raw_ostream &O) { 422 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 423 if (CC != ARMCC::AL) 424 O << ARMCondCodeToString(CC); 425} 426 427void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI, 428 unsigned OpNum, 429 raw_ostream &O) { 430 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 431 O << ARMCondCodeToString(CC); 432} 433 434void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum, 435 raw_ostream &O) { 436 if (MI->getOperand(OpNum).getReg()) { 437 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR && 438 "Expect ARM CPSR register!"); 439 O << 's'; 440 } 441} 442 443void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum, 444 raw_ostream &O) { 445 O << MI->getOperand(OpNum).getImm(); 446} 447 448void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum, 449 raw_ostream &O) { 450 O << "p" << MI->getOperand(OpNum).getImm(); 451} 452 453void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum, 454 raw_ostream &O) { 455 O << "c" << MI->getOperand(OpNum).getImm(); 456} 457 458void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum, 459 raw_ostream &O) { 460 llvm_unreachable("Unhandled PC-relative pseudo-instruction!"); 461} 462 463void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, 464 raw_ostream &O) { 465 O << "#" << MI->getOperand(OpNum).getImm() * 4; 466} 467 468void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum, 469 raw_ostream &O) { 470 // (3 - the number of trailing zeros) is the number of then / else. 471 unsigned Mask = MI->getOperand(OpNum).getImm(); 472 unsigned CondBit0 = Mask >> 4 & 1; 473 unsigned NumTZ = CountTrailingZeros_32(Mask); 474 assert(NumTZ <= 3 && "Invalid IT mask!"); 475 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) { 476 bool T = ((Mask >> Pos) & 1) == CondBit0; 477 if (T) 478 O << 't'; 479 else 480 O << 'e'; 481 } 482} 483 484void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op, 485 raw_ostream &O) { 486 const MCOperand &MO1 = MI->getOperand(Op); 487 const MCOperand &MO2 = MI->getOperand(Op + 1); 488 489 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 490 printOperand(MI, Op, O); 491 return; 492 } 493 494 O << "[" << getRegisterName(MO1.getReg()); 495 if (unsigned RegNum = MO2.getReg()) 496 O << ", " << getRegisterName(RegNum); 497 O << "]"; 498} 499 500void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI, 501 unsigned Op, 502 raw_ostream &O, 503 unsigned Scale) { 504 const MCOperand &MO1 = MI->getOperand(Op); 505 const MCOperand &MO2 = MI->getOperand(Op + 1); 506 507 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 508 printOperand(MI, Op, O); 509 return; 510 } 511 512 O << "[" << getRegisterName(MO1.getReg()); 513 if (unsigned ImmOffs = MO2.getImm()) 514 O << ", #" << ImmOffs * Scale; 515 O << "]"; 516} 517 518void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI, 519 unsigned Op, 520 raw_ostream &O) { 521 printThumbAddrModeImm5SOperand(MI, Op, O, 1); 522} 523 524void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI, 525 unsigned Op, 526 raw_ostream &O) { 527 printThumbAddrModeImm5SOperand(MI, Op, O, 2); 528} 529 530void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI, 531 unsigned Op, 532 raw_ostream &O) { 533 printThumbAddrModeImm5SOperand(MI, Op, O, 4); 534} 535 536void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op, 537 raw_ostream &O) { 538 printThumbAddrModeImm5SOperand(MI, Op, O, 4); 539} 540 541// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 542// register with shift forms. 543// REG 0 0 - e.g. R5 544// REG IMM, SH_OPC - e.g. R5, LSL #3 545void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum, 546 raw_ostream &O) { 547 const MCOperand &MO1 = MI->getOperand(OpNum); 548 const MCOperand &MO2 = MI->getOperand(OpNum+1); 549 550 unsigned Reg = MO1.getReg(); 551 O << getRegisterName(Reg); 552 553 // Print the shift opc. 554 assert(MO2.isImm() && "Not a valid t2_so_reg value!"); 555 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm()); 556 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 557 if (ShOpc != ARM_AM::rrx) 558 O << " #" << ARM_AM::getSORegOffset(MO2.getImm()); 559} 560 561void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum, 562 raw_ostream &O) { 563 const MCOperand &MO1 = MI->getOperand(OpNum); 564 const MCOperand &MO2 = MI->getOperand(OpNum+1); 565 566 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 567 printOperand(MI, OpNum, O); 568 return; 569 } 570 571 O << "[" << getRegisterName(MO1.getReg()); 572 573 int32_t OffImm = (int32_t)MO2.getImm(); 574 bool isSub = OffImm < 0; 575 // Special value for #-0. All others are normal. 576 if (OffImm == INT32_MIN) 577 OffImm = 0; 578 if (isSub) 579 O << ", #-" << -OffImm; 580 else if (OffImm > 0) 581 O << ", #" << OffImm; 582 O << "]"; 583} 584 585void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI, 586 unsigned OpNum, 587 raw_ostream &O) { 588 const MCOperand &MO1 = MI->getOperand(OpNum); 589 const MCOperand &MO2 = MI->getOperand(OpNum+1); 590 591 O << "[" << getRegisterName(MO1.getReg()); 592 593 int32_t OffImm = (int32_t)MO2.getImm(); 594 // Don't print +0. 595 if (OffImm < 0) 596 O << ", #-" << -OffImm; 597 else if (OffImm > 0) 598 O << ", #" << OffImm; 599 O << "]"; 600} 601 602void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI, 603 unsigned OpNum, 604 raw_ostream &O) { 605 const MCOperand &MO1 = MI->getOperand(OpNum); 606 const MCOperand &MO2 = MI->getOperand(OpNum+1); 607 608 O << "[" << getRegisterName(MO1.getReg()); 609 610 int32_t OffImm = (int32_t)MO2.getImm() / 4; 611 // Don't print +0. 612 if (OffImm < 0) 613 O << ", #-" << -OffImm * 4; 614 else if (OffImm > 0) 615 O << ", #" << OffImm * 4; 616 O << "]"; 617} 618 619void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI, 620 unsigned OpNum, 621 raw_ostream &O) { 622 const MCOperand &MO1 = MI->getOperand(OpNum); 623 int32_t OffImm = (int32_t)MO1.getImm(); 624 // Don't print +0. 625 if (OffImm < 0) 626 O << "#-" << -OffImm; 627 else if (OffImm > 0) 628 O << "#" << OffImm; 629} 630 631void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, 632 unsigned OpNum, 633 raw_ostream &O) { 634 const MCOperand &MO1 = MI->getOperand(OpNum); 635 int32_t OffImm = (int32_t)MO1.getImm() / 4; 636 // Don't print +0. 637 if (OffImm < 0) 638 O << "#-" << -OffImm * 4; 639 else if (OffImm > 0) 640 O << "#" << OffImm * 4; 641} 642 643void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI, 644 unsigned OpNum, 645 raw_ostream &O) { 646 const MCOperand &MO1 = MI->getOperand(OpNum); 647 const MCOperand &MO2 = MI->getOperand(OpNum+1); 648 const MCOperand &MO3 = MI->getOperand(OpNum+2); 649 650 O << "[" << getRegisterName(MO1.getReg()); 651 652 assert(MO2.getReg() && "Invalid so_reg load / store address!"); 653 O << ", " << getRegisterName(MO2.getReg()); 654 655 unsigned ShAmt = MO3.getImm(); 656 if (ShAmt) { 657 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); 658 O << ", lsl #" << ShAmt; 659 } 660 O << "]"; 661} 662 663void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, 664 raw_ostream &O) { 665 const MCOperand &MO = MI->getOperand(OpNum); 666 O << '#'; 667 if (MO.isFPImm()) { 668 O << (float)MO.getFPImm(); 669 } else { 670 union { 671 uint32_t I; 672 float F; 673 } FPUnion; 674 675 FPUnion.I = MO.getImm(); 676 O << FPUnion.F; 677 } 678} 679 680void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, 681 raw_ostream &O) { 682 const MCOperand &MO = MI->getOperand(OpNum); 683 O << '#'; 684 if (MO.isFPImm()) { 685 O << MO.getFPImm(); 686 } else { 687 // We expect the binary encoding of a floating point number here. 688 union { 689 uint64_t I; 690 double D; 691 } FPUnion; 692 693 FPUnion.I = MO.getImm(); 694 O << FPUnion.D; 695 } 696} 697 698void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum, 699 raw_ostream &O) { 700 unsigned EncodedImm = MI->getOperand(OpNum).getImm(); 701 unsigned EltBits; 702 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits); 703 O << "#0x" << utohexstr(Val); 704} 705