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