ARMInstPrinter.cpp revision cde4ce411b1ace4a80ea1dd38df97e8508aed0c9
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 32void ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 33 OS << 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.2.3: Data-processing (immediate), and 140 // A5.2.4: Modified immediate constants in ARM instructions 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 185//===--------------------------------------------------------------------===// 186// Addressing Mode #2 187//===--------------------------------------------------------------------===// 188 189void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op, 190 raw_ostream &O) { 191 const MCOperand &MO1 = MI->getOperand(Op); 192 const MCOperand &MO2 = MI->getOperand(Op+1); 193 const MCOperand &MO3 = MI->getOperand(Op+2); 194 195 O << "[" << getRegisterName(MO1.getReg()); 196 197 if (!MO2.getReg()) { 198 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. 199 O << ", #" 200 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 201 << ARM_AM::getAM2Offset(MO3.getImm()); 202 O << "]"; 203 return; 204 } 205 206 O << ", " 207 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 208 << getRegisterName(MO2.getReg()); 209 210 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) 211 O << ", " 212 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) 213 << " #" << ShImm; 214 O << "]"; 215} 216 217void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op, 218 raw_ostream &O) { 219 const MCOperand &MO1 = MI->getOperand(Op); 220 const MCOperand &MO2 = MI->getOperand(Op+1); 221 const MCOperand &MO3 = MI->getOperand(Op+2); 222 223 O << "[" << getRegisterName(MO1.getReg()) << "], "; 224 225 if (!MO2.getReg()) { 226 unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm()); 227 O << '#' 228 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 229 << ImmOffs; 230 return; 231 } 232 233 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 234 << getRegisterName(MO2.getReg()); 235 236 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) 237 O << ", " 238 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) 239 << " #" << ShImm; 240} 241 242void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op, 243 raw_ostream &O) { 244 const MCOperand &MO1 = MI->getOperand(Op); 245 246 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 247 printOperand(MI, Op, O); 248 return; 249 } 250 251 const MCOperand &MO3 = MI->getOperand(Op+2); 252 unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm()); 253 254 if (IdxMode == ARMII::IndexModePost) { 255 printAM2PostIndexOp(MI, Op, O); 256 return; 257 } 258 printAM2PreOrOffsetIndexOp(MI, Op, O); 259} 260 261void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI, 262 unsigned OpNum, 263 raw_ostream &O) { 264 const MCOperand &MO1 = MI->getOperand(OpNum); 265 const MCOperand &MO2 = MI->getOperand(OpNum+1); 266 267 if (!MO1.getReg()) { 268 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm()); 269 O << '#' 270 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 271 << ImmOffs; 272 return; 273 } 274 275 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 276 << getRegisterName(MO1.getReg()); 277 278 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) 279 O << ", " 280 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm())) 281 << " #" << ShImm; 282} 283 284//===--------------------------------------------------------------------===// 285// Addressing Mode #3 286//===--------------------------------------------------------------------===// 287 288void ARMInstPrinter::printAM3PostIndexOp(const MCInst *MI, unsigned Op, 289 raw_ostream &O) { 290 const MCOperand &MO1 = MI->getOperand(Op); 291 const MCOperand &MO2 = MI->getOperand(Op+1); 292 const MCOperand &MO3 = MI->getOperand(Op+2); 293 294 O << "[" << getRegisterName(MO1.getReg()) << "], "; 295 296 if (MO2.getReg()) { 297 O << (char)ARM_AM::getAM3Op(MO3.getImm()) 298 << getRegisterName(MO2.getReg()); 299 return; 300 } 301 302 unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()); 303 O << '#' 304 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm())) 305 << ImmOffs; 306} 307 308void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op, 309 raw_ostream &O) { 310 const MCOperand &MO1 = MI->getOperand(Op); 311 const MCOperand &MO2 = MI->getOperand(Op+1); 312 const MCOperand &MO3 = MI->getOperand(Op+2); 313 314 O << '[' << getRegisterName(MO1.getReg()); 315 316 if (MO2.getReg()) { 317 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm()) 318 << getRegisterName(MO2.getReg()) << ']'; 319 return; 320 } 321 322 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) 323 O << ", #" 324 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm())) 325 << ImmOffs; 326 O << ']'; 327} 328 329void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op, 330 raw_ostream &O) { 331 const MCOperand &MO3 = MI->getOperand(Op+2); 332 unsigned IdxMode = ARM_AM::getAM3IdxMode(MO3.getImm()); 333 334 if (IdxMode == ARMII::IndexModePost) { 335 printAM3PostIndexOp(MI, Op, O); 336 return; 337 } 338 printAM3PreOrOffsetIndexOp(MI, Op, O); 339} 340 341void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI, 342 unsigned OpNum, 343 raw_ostream &O) { 344 const MCOperand &MO1 = MI->getOperand(OpNum); 345 const MCOperand &MO2 = MI->getOperand(OpNum+1); 346 347 if (MO1.getReg()) { 348 O << (char)ARM_AM::getAM3Op(MO2.getImm()) 349 << getRegisterName(MO1.getReg()); 350 return; 351 } 352 353 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm()); 354 O << '#' 355 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) 356 << ImmOffs; 357} 358 359void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum, 360 raw_ostream &O) { 361 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum) 362 .getImm()); 363 O << ARM_AM::getAMSubModeStr(Mode); 364} 365 366void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum, 367 raw_ostream &O) { 368 const MCOperand &MO1 = MI->getOperand(OpNum); 369 const MCOperand &MO2 = MI->getOperand(OpNum+1); 370 371 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 372 printOperand(MI, OpNum, O); 373 return; 374 } 375 376 O << "[" << getRegisterName(MO1.getReg()); 377 378 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) { 379 O << ", #" 380 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm())) 381 << ImmOffs * 4; 382 } 383 O << "]"; 384} 385 386void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum, 387 raw_ostream &O) { 388 const MCOperand &MO1 = MI->getOperand(OpNum); 389 const MCOperand &MO2 = MI->getOperand(OpNum+1); 390 391 O << "[" << getRegisterName(MO1.getReg()); 392 if (MO2.getImm()) { 393 // FIXME: Both darwin as and GNU as violate ARM docs here. 394 O << ", :" << (MO2.getImm() << 3); 395 } 396 O << "]"; 397} 398 399void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum, 400 raw_ostream &O) { 401 const MCOperand &MO1 = MI->getOperand(OpNum); 402 O << "[" << getRegisterName(MO1.getReg()) << "]"; 403} 404 405void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI, 406 unsigned OpNum, 407 raw_ostream &O) { 408 const MCOperand &MO = MI->getOperand(OpNum); 409 if (MO.getReg() == 0) 410 O << "!"; 411 else 412 O << ", " << getRegisterName(MO.getReg()); 413} 414 415void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI, 416 unsigned OpNum, 417 raw_ostream &O) { 418 const MCOperand &MO = MI->getOperand(OpNum); 419 uint32_t v = ~MO.getImm(); 420 int32_t lsb = CountTrailingZeros_32(v); 421 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb; 422 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!"); 423 O << '#' << lsb << ", #" << width; 424} 425 426void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum, 427 raw_ostream &O) { 428 unsigned val = MI->getOperand(OpNum).getImm(); 429 O << ARM_MB::MemBOptToString(val); 430} 431 432void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum, 433 raw_ostream &O) { 434 unsigned ShiftOp = MI->getOperand(OpNum).getImm(); 435 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp); 436 switch (Opc) { 437 case ARM_AM::no_shift: 438 return; 439 case ARM_AM::lsl: 440 O << ", lsl #"; 441 break; 442 case ARM_AM::asr: 443 O << ", asr #"; 444 break; 445 default: 446 assert(0 && "unexpected shift opcode for shift immediate operand"); 447 } 448 O << ARM_AM::getSORegOffset(ShiftOp); 449} 450 451void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, 452 raw_ostream &O) { 453 O << "{"; 454 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { 455 if (i != OpNum) O << ", "; 456 O << getRegisterName(MI->getOperand(i).getReg()); 457 } 458 O << "}"; 459} 460 461void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum, 462 raw_ostream &O) { 463 const MCOperand &Op = MI->getOperand(OpNum); 464 if (Op.getImm()) 465 O << "be"; 466 else 467 O << "le"; 468} 469 470void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum, 471 raw_ostream &O) { 472 const MCOperand &Op = MI->getOperand(OpNum); 473 O << ARM_PROC::IModToString(Op.getImm()); 474} 475 476void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum, 477 raw_ostream &O) { 478 const MCOperand &Op = MI->getOperand(OpNum); 479 unsigned IFlags = Op.getImm(); 480 for (int i=2; i >= 0; --i) 481 if (IFlags & (1 << i)) 482 O << ARM_PROC::IFlagsToString(1 << i); 483} 484 485void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum, 486 raw_ostream &O) { 487 const MCOperand &Op = MI->getOperand(OpNum); 488 unsigned SpecRegRBit = Op.getImm() >> 4; 489 unsigned Mask = Op.getImm() & 0xf; 490 491 if (SpecRegRBit) 492 O << "spsr"; 493 else 494 O << "cpsr"; 495 496 if (Mask) { 497 O << '_'; 498 if (Mask & 8) O << 'f'; 499 if (Mask & 4) O << 's'; 500 if (Mask & 2) O << 'x'; 501 if (Mask & 1) O << 'c'; 502 } 503} 504 505void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum, 506 raw_ostream &O) { 507 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 508 if (CC != ARMCC::AL) 509 O << ARMCondCodeToString(CC); 510} 511 512void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI, 513 unsigned OpNum, 514 raw_ostream &O) { 515 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 516 O << ARMCondCodeToString(CC); 517} 518 519void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum, 520 raw_ostream &O) { 521 if (MI->getOperand(OpNum).getReg()) { 522 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR && 523 "Expect ARM CPSR register!"); 524 O << 's'; 525 } 526} 527 528void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum, 529 raw_ostream &O) { 530 O << MI->getOperand(OpNum).getImm(); 531} 532 533void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum, 534 raw_ostream &O) { 535 O << "p" << MI->getOperand(OpNum).getImm(); 536} 537 538void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum, 539 raw_ostream &O) { 540 O << "c" << MI->getOperand(OpNum).getImm(); 541} 542 543void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum, 544 raw_ostream &O) { 545 llvm_unreachable("Unhandled PC-relative pseudo-instruction!"); 546} 547 548void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, 549 raw_ostream &O) { 550 O << "#" << MI->getOperand(OpNum).getImm() * 4; 551} 552 553void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum, 554 raw_ostream &O) { 555 // (3 - the number of trailing zeros) is the number of then / else. 556 unsigned Mask = MI->getOperand(OpNum).getImm(); 557 unsigned CondBit0 = Mask >> 4 & 1; 558 unsigned NumTZ = CountTrailingZeros_32(Mask); 559 assert(NumTZ <= 3 && "Invalid IT mask!"); 560 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) { 561 bool T = ((Mask >> Pos) & 1) == CondBit0; 562 if (T) 563 O << 't'; 564 else 565 O << 'e'; 566 } 567} 568 569void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op, 570 raw_ostream &O) { 571 const MCOperand &MO1 = MI->getOperand(Op); 572 const MCOperand &MO2 = MI->getOperand(Op + 1); 573 574 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 575 printOperand(MI, Op, O); 576 return; 577 } 578 579 O << "[" << getRegisterName(MO1.getReg()); 580 if (unsigned RegNum = MO2.getReg()) 581 O << ", " << getRegisterName(RegNum); 582 O << "]"; 583} 584 585void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI, 586 unsigned Op, 587 raw_ostream &O, 588 unsigned Scale) { 589 const MCOperand &MO1 = MI->getOperand(Op); 590 const MCOperand &MO2 = MI->getOperand(Op + 1); 591 592 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 593 printOperand(MI, Op, O); 594 return; 595 } 596 597 O << "[" << getRegisterName(MO1.getReg()); 598 if (unsigned ImmOffs = MO2.getImm()) 599 O << ", #" << ImmOffs * Scale; 600 O << "]"; 601} 602 603void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI, 604 unsigned Op, 605 raw_ostream &O) { 606 printThumbAddrModeImm5SOperand(MI, Op, O, 1); 607} 608 609void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI, 610 unsigned Op, 611 raw_ostream &O) { 612 printThumbAddrModeImm5SOperand(MI, Op, O, 2); 613} 614 615void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI, 616 unsigned Op, 617 raw_ostream &O) { 618 printThumbAddrModeImm5SOperand(MI, Op, O, 4); 619} 620 621void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op, 622 raw_ostream &O) { 623 printThumbAddrModeImm5SOperand(MI, Op, O, 4); 624} 625 626// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 627// register with shift forms. 628// REG 0 0 - e.g. R5 629// REG IMM, SH_OPC - e.g. R5, LSL #3 630void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum, 631 raw_ostream &O) { 632 const MCOperand &MO1 = MI->getOperand(OpNum); 633 const MCOperand &MO2 = MI->getOperand(OpNum+1); 634 635 unsigned Reg = MO1.getReg(); 636 O << getRegisterName(Reg); 637 638 // Print the shift opc. 639 assert(MO2.isImm() && "Not a valid t2_so_reg value!"); 640 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm()); 641 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 642 if (ShOpc != ARM_AM::rrx) 643 O << " #" << ARM_AM::getSORegOffset(MO2.getImm()); 644} 645 646void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum, 647 raw_ostream &O) { 648 const MCOperand &MO1 = MI->getOperand(OpNum); 649 const MCOperand &MO2 = MI->getOperand(OpNum+1); 650 651 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 652 printOperand(MI, OpNum, O); 653 return; 654 } 655 656 O << "[" << getRegisterName(MO1.getReg()); 657 658 int32_t OffImm = (int32_t)MO2.getImm(); 659 bool isSub = OffImm < 0; 660 // Special value for #-0. All others are normal. 661 if (OffImm == INT32_MIN) 662 OffImm = 0; 663 if (isSub) 664 O << ", #-" << -OffImm; 665 else if (OffImm > 0) 666 O << ", #" << OffImm; 667 O << "]"; 668} 669 670void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI, 671 unsigned OpNum, 672 raw_ostream &O) { 673 const MCOperand &MO1 = MI->getOperand(OpNum); 674 const MCOperand &MO2 = MI->getOperand(OpNum+1); 675 676 O << "[" << getRegisterName(MO1.getReg()); 677 678 int32_t OffImm = (int32_t)MO2.getImm(); 679 // Don't print +0. 680 if (OffImm < 0) 681 O << ", #-" << -OffImm; 682 else if (OffImm > 0) 683 O << ", #" << OffImm; 684 O << "]"; 685} 686 687void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI, 688 unsigned OpNum, 689 raw_ostream &O) { 690 const MCOperand &MO1 = MI->getOperand(OpNum); 691 const MCOperand &MO2 = MI->getOperand(OpNum+1); 692 693 O << "[" << getRegisterName(MO1.getReg()); 694 695 int32_t OffImm = (int32_t)MO2.getImm() / 4; 696 // Don't print +0. 697 if (OffImm < 0) 698 O << ", #-" << -OffImm * 4; 699 else if (OffImm > 0) 700 O << ", #" << OffImm * 4; 701 O << "]"; 702} 703 704void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI, 705 unsigned OpNum, 706 raw_ostream &O) { 707 const MCOperand &MO1 = MI->getOperand(OpNum); 708 int32_t OffImm = (int32_t)MO1.getImm(); 709 // Don't print +0. 710 if (OffImm < 0) 711 O << "#-" << -OffImm; 712 else if (OffImm > 0) 713 O << "#" << OffImm; 714} 715 716void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, 717 unsigned OpNum, 718 raw_ostream &O) { 719 const MCOperand &MO1 = MI->getOperand(OpNum); 720 int32_t OffImm = (int32_t)MO1.getImm() / 4; 721 // Don't print +0. 722 if (OffImm < 0) 723 O << "#-" << -OffImm * 4; 724 else if (OffImm > 0) 725 O << "#" << OffImm * 4; 726} 727 728void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI, 729 unsigned OpNum, 730 raw_ostream &O) { 731 const MCOperand &MO1 = MI->getOperand(OpNum); 732 const MCOperand &MO2 = MI->getOperand(OpNum+1); 733 const MCOperand &MO3 = MI->getOperand(OpNum+2); 734 735 O << "[" << getRegisterName(MO1.getReg()); 736 737 assert(MO2.getReg() && "Invalid so_reg load / store address!"); 738 O << ", " << getRegisterName(MO2.getReg()); 739 740 unsigned ShAmt = MO3.getImm(); 741 if (ShAmt) { 742 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); 743 O << ", lsl #" << ShAmt; 744 } 745 O << "]"; 746} 747 748void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, 749 raw_ostream &O) { 750 const MCOperand &MO = MI->getOperand(OpNum); 751 O << '#'; 752 if (MO.isFPImm()) { 753 O << (float)MO.getFPImm(); 754 } else { 755 union { 756 uint32_t I; 757 float F; 758 } FPUnion; 759 760 FPUnion.I = MO.getImm(); 761 O << FPUnion.F; 762 } 763} 764 765void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, 766 raw_ostream &O) { 767 const MCOperand &MO = MI->getOperand(OpNum); 768 O << '#'; 769 if (MO.isFPImm()) { 770 O << MO.getFPImm(); 771 } else { 772 // We expect the binary encoding of a floating point number here. 773 union { 774 uint64_t I; 775 double D; 776 } FPUnion; 777 778 FPUnion.I = MO.getImm(); 779 O << FPUnion.D; 780 } 781} 782 783void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum, 784 raw_ostream &O) { 785 unsigned EncodedImm = MI->getOperand(OpNum).getImm(); 786 unsigned EltBits; 787 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits); 788 O << "#0x" << utohexstr(Val); 789} 790