ARMInstPrinter.cpp revision 57caad7a33ff145b71545f10dcfbbf2fd0f595d3
19a0c85e640a08174569a303db22981612f05d385Douglas Gregor//===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===// 29a0c85e640a08174569a303db22981612f05d385Douglas Gregor// 31ca6ae865cc632e9f626faacd4937e666eb05f6bDouglas Gregor// The LLVM Compiler Infrastructure 49a0c85e640a08174569a303db22981612f05d385Douglas Gregor// 59a0c85e640a08174569a303db22981612f05d385Douglas Gregor// This file is distributed under the University of Illinois Open Source 69a0c85e640a08174569a303db22981612f05d385Douglas Gregor// License. See LICENSE.TXT for details. 79a0c85e640a08174569a303db22981612f05d385Douglas Gregor// 89a0c85e640a08174569a303db22981612f05d385Douglas Gregor//===----------------------------------------------------------------------===// 99a0c85e640a08174569a303db22981612f05d385Douglas Gregor// 109a0c85e640a08174569a303db22981612f05d385Douglas Gregor// This class prints an ARM MCInst to a .s file. 119a0c85e640a08174569a303db22981612f05d385Douglas Gregor// 129a0c85e640a08174569a303db22981612f05d385Douglas Gregor//===----------------------------------------------------------------------===// 139a0c85e640a08174569a303db22981612f05d385Douglas Gregor 149a0c85e640a08174569a303db22981612f05d385Douglas Gregor#define DEBUG_TYPE "asm-printer" 159a0c85e640a08174569a303db22981612f05d385Douglas Gregor#include "ARMBaseInfo.h" 16834389b87451b24618513b907b4dfb5b00d211f3Douglas Gregor#include "ARMInstPrinter.h" 17148299f5eb05828937b883e4eba622c3363b4725Benjamin Kramer#include "ARMAddressingModes.h" 189a0c85e640a08174569a303db22981612f05d385Douglas Gregor#include "llvm/MC/MCInst.h" 199a0c85e640a08174569a303db22981612f05d385Douglas Gregor#include "llvm/MC/MCAsmInfo.h" 209a0c85e640a08174569a303db22981612f05d385Douglas Gregor#include "llvm/MC/MCExpr.h" 219a0c85e640a08174569a303db22981612f05d385Douglas Gregor#include "llvm/ADT/StringExtras.h" 229a0c85e640a08174569a303db22981612f05d385Douglas Gregor#include "llvm/Support/raw_ostream.h" 23b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregorusing namespace llvm; 24ab0b4f1d66de54b4c3102b96d56964510361ba7dDouglas Gregor 25ab0b4f1d66de54b4c3102b96d56964510361ba7dDouglas Gregor#define GET_INSTRUCTION_NAME 26ab0b4f1d66de54b4c3102b96d56964510361ba7dDouglas Gregor#include "ARMGenAsmWriter.inc" 27b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregor 28b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas GregorStringRef ARMInstPrinter::getOpcodeName(unsigned Opcode) const { 29b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregor return getInstructionName(Opcode); 30ab0b4f1d66de54b4c3102b96d56964510361ba7dDouglas Gregor} 31ab0b4f1d66de54b4c3102b96d56964510361ba7dDouglas Gregor 32b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas GregorStringRef ARMInstPrinter::getRegName(unsigned RegNo) const { 33b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregor return getRegisterName(RegNo); 341ca6ae865cc632e9f626faacd4937e666eb05f6bDouglas Gregor} 35b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregor 36b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregorvoid ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) { 37ab0b4f1d66de54b4c3102b96d56964510361ba7dDouglas Gregor 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::printNegZeroOperand(const MCInst *MI, unsigned OpNum, 421 raw_ostream &O) { 422 const MCOperand &Op = MI->getOperand(OpNum); 423 O << '#'; 424 if (Op.getImm() < 0) 425 O << '-' << (-Op.getImm() - 1); 426 else 427 O << Op.getImm(); 428} 429 430void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum, 431 raw_ostream &O) { 432 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 433 if (CC != ARMCC::AL) 434 O << ARMCondCodeToString(CC); 435} 436 437void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI, 438 unsigned OpNum, 439 raw_ostream &O) { 440 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 441 O << ARMCondCodeToString(CC); 442} 443 444void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum, 445 raw_ostream &O) { 446 if (MI->getOperand(OpNum).getReg()) { 447 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR && 448 "Expect ARM CPSR register!"); 449 O << 's'; 450 } 451} 452 453void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum, 454 raw_ostream &O) { 455 O << MI->getOperand(OpNum).getImm(); 456} 457 458void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum, 459 raw_ostream &O) { 460 O << "p" << MI->getOperand(OpNum).getImm(); 461} 462 463void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum, 464 raw_ostream &O) { 465 O << "c" << MI->getOperand(OpNum).getImm(); 466} 467 468void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum, 469 raw_ostream &O) { 470 llvm_unreachable("Unhandled PC-relative pseudo-instruction!"); 471} 472 473void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, 474 raw_ostream &O) { 475 O << "#" << MI->getOperand(OpNum).getImm() * 4; 476} 477 478void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum, 479 raw_ostream &O) { 480 // (3 - the number of trailing zeros) is the number of then / else. 481 unsigned Mask = MI->getOperand(OpNum).getImm(); 482 unsigned CondBit0 = Mask >> 4 & 1; 483 unsigned NumTZ = CountTrailingZeros_32(Mask); 484 assert(NumTZ <= 3 && "Invalid IT mask!"); 485 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) { 486 bool T = ((Mask >> Pos) & 1) == CondBit0; 487 if (T) 488 O << 't'; 489 else 490 O << 'e'; 491 } 492} 493 494void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op, 495 raw_ostream &O) { 496 const MCOperand &MO1 = MI->getOperand(Op); 497 const MCOperand &MO2 = MI->getOperand(Op + 1); 498 499 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 500 printOperand(MI, Op, O); 501 return; 502 } 503 504 O << "[" << getRegisterName(MO1.getReg()); 505 if (unsigned RegNum = MO2.getReg()) 506 O << ", " << getRegisterName(RegNum); 507 O << "]"; 508} 509 510void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI, 511 unsigned Op, 512 raw_ostream &O, 513 unsigned Scale) { 514 const MCOperand &MO1 = MI->getOperand(Op); 515 const MCOperand &MO2 = MI->getOperand(Op + 1); 516 517 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 518 printOperand(MI, Op, O); 519 return; 520 } 521 522 O << "[" << getRegisterName(MO1.getReg()); 523 if (unsigned ImmOffs = MO2.getImm()) 524 O << ", #" << ImmOffs * Scale; 525 O << "]"; 526} 527 528void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI, 529 unsigned Op, 530 raw_ostream &O) { 531 printThumbAddrModeImm5SOperand(MI, Op, O, 1); 532} 533 534void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI, 535 unsigned Op, 536 raw_ostream &O) { 537 printThumbAddrModeImm5SOperand(MI, Op, O, 2); 538} 539 540void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI, 541 unsigned Op, 542 raw_ostream &O) { 543 printThumbAddrModeImm5SOperand(MI, Op, O, 4); 544} 545 546void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op, 547 raw_ostream &O) { 548 printThumbAddrModeImm5SOperand(MI, Op, O, 4); 549} 550 551// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 552// register with shift forms. 553// REG 0 0 - e.g. R5 554// REG IMM, SH_OPC - e.g. R5, LSL #3 555void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum, 556 raw_ostream &O) { 557 const MCOperand &MO1 = MI->getOperand(OpNum); 558 const MCOperand &MO2 = MI->getOperand(OpNum+1); 559 560 unsigned Reg = MO1.getReg(); 561 O << getRegisterName(Reg); 562 563 // Print the shift opc. 564 assert(MO2.isImm() && "Not a valid t2_so_reg value!"); 565 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm()); 566 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 567 if (ShOpc != ARM_AM::rrx) 568 O << " #" << ARM_AM::getSORegOffset(MO2.getImm()); 569} 570 571void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum, 572 raw_ostream &O) { 573 const MCOperand &MO1 = MI->getOperand(OpNum); 574 const MCOperand &MO2 = MI->getOperand(OpNum+1); 575 576 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 577 printOperand(MI, OpNum, O); 578 return; 579 } 580 581 O << "[" << getRegisterName(MO1.getReg()); 582 583 int32_t OffImm = (int32_t)MO2.getImm(); 584 bool isSub = OffImm < 0; 585 // Special value for #-0. All others are normal. 586 if (OffImm == INT32_MIN) 587 OffImm = 0; 588 if (isSub) 589 O << ", #-" << -OffImm; 590 else if (OffImm > 0) 591 O << ", #" << OffImm; 592 O << "]"; 593} 594 595void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI, 596 unsigned OpNum, 597 raw_ostream &O) { 598 const MCOperand &MO1 = MI->getOperand(OpNum); 599 const MCOperand &MO2 = MI->getOperand(OpNum+1); 600 601 O << "[" << getRegisterName(MO1.getReg()); 602 603 int32_t OffImm = (int32_t)MO2.getImm(); 604 // Don't print +0. 605 if (OffImm < 0) 606 O << ", #-" << -OffImm; 607 else if (OffImm > 0) 608 O << ", #" << OffImm; 609 O << "]"; 610} 611 612void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI, 613 unsigned OpNum, 614 raw_ostream &O) { 615 const MCOperand &MO1 = MI->getOperand(OpNum); 616 const MCOperand &MO2 = MI->getOperand(OpNum+1); 617 618 O << "[" << getRegisterName(MO1.getReg()); 619 620 int32_t OffImm = (int32_t)MO2.getImm() / 4; 621 // Don't print +0. 622 if (OffImm < 0) 623 O << ", #-" << -OffImm * 4; 624 else if (OffImm > 0) 625 O << ", #" << OffImm * 4; 626 O << "]"; 627} 628 629void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI, 630 unsigned OpNum, 631 raw_ostream &O) { 632 const MCOperand &MO1 = MI->getOperand(OpNum); 633 int32_t OffImm = (int32_t)MO1.getImm(); 634 // Don't print +0. 635 if (OffImm < 0) 636 O << "#-" << -OffImm; 637 else if (OffImm > 0) 638 O << "#" << OffImm; 639} 640 641void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, 642 unsigned OpNum, 643 raw_ostream &O) { 644 const MCOperand &MO1 = MI->getOperand(OpNum); 645 int32_t OffImm = (int32_t)MO1.getImm() / 4; 646 // Don't print +0. 647 if (OffImm < 0) 648 O << "#-" << -OffImm * 4; 649 else if (OffImm > 0) 650 O << "#" << OffImm * 4; 651} 652 653void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI, 654 unsigned OpNum, 655 raw_ostream &O) { 656 const MCOperand &MO1 = MI->getOperand(OpNum); 657 const MCOperand &MO2 = MI->getOperand(OpNum+1); 658 const MCOperand &MO3 = MI->getOperand(OpNum+2); 659 660 O << "[" << getRegisterName(MO1.getReg()); 661 662 assert(MO2.getReg() && "Invalid so_reg load / store address!"); 663 O << ", " << getRegisterName(MO2.getReg()); 664 665 unsigned ShAmt = MO3.getImm(); 666 if (ShAmt) { 667 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); 668 O << ", lsl #" << ShAmt; 669 } 670 O << "]"; 671} 672 673void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, 674 raw_ostream &O) { 675 const MCOperand &MO = MI->getOperand(OpNum); 676 O << '#'; 677 if (MO.isFPImm()) { 678 O << (float)MO.getFPImm(); 679 } else { 680 union { 681 uint32_t I; 682 float F; 683 } FPUnion; 684 685 FPUnion.I = MO.getImm(); 686 O << FPUnion.F; 687 } 688} 689 690void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, 691 raw_ostream &O) { 692 const MCOperand &MO = MI->getOperand(OpNum); 693 O << '#'; 694 if (MO.isFPImm()) { 695 O << MO.getFPImm(); 696 } else { 697 // We expect the binary encoding of a floating point number here. 698 union { 699 uint64_t I; 700 double D; 701 } FPUnion; 702 703 FPUnion.I = MO.getImm(); 704 O << FPUnion.D; 705 } 706} 707 708void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum, 709 raw_ostream &O) { 710 unsigned EncodedImm = MI->getOperand(OpNum).getImm(); 711 unsigned EltBits; 712 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits); 713 O << "#0x" << utohexstr(Val); 714} 715