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