ARMInstPrinter.cpp revision 35636281c7ab6eb128b4ced6bf7ae0b6b8458dd2
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#include "ARMGenAsmWriter.inc" 26 27void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) { 28 // Check for MOVs and print canonical forms, instead. 29 if (MI->getOpcode() == ARM::MOVs) { 30 // FIXME: Thumb variants? 31 const MCOperand &Dst = MI->getOperand(0); 32 const MCOperand &MO1 = MI->getOperand(1); 33 const MCOperand &MO2 = MI->getOperand(2); 34 const MCOperand &MO3 = MI->getOperand(3); 35 36 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm())); 37 printSBitModifierOperand(MI, 6, O); 38 printPredicateOperand(MI, 4, O); 39 40 O << '\t' << getRegisterName(Dst.getReg()) 41 << ", " << getRegisterName(MO1.getReg()); 42 43 if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx) 44 return; 45 46 O << ", "; 47 48 if (MO2.getReg()) { 49 O << getRegisterName(MO2.getReg()); 50 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); 51 } else { 52 O << "#" << ARM_AM::getSORegOffset(MO3.getImm()); 53 } 54 return; 55 } 56 57 // A8.6.123 PUSH 58 if ((MI->getOpcode() == ARM::STM_UPD || MI->getOpcode() == ARM::t2STM_UPD) && 59 MI->getOperand(0).getReg() == ARM::SP) { 60 const MCOperand &MO1 = MI->getOperand(2); 61 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) { 62 O << '\t' << "push"; 63 printPredicateOperand(MI, 3, O); 64 O << '\t'; 65 printRegisterList(MI, 5, O); 66 return; 67 } 68 } 69 70 // A8.6.122 POP 71 if ((MI->getOpcode() == ARM::LDM_UPD || MI->getOpcode() == ARM::t2LDM_UPD) && 72 MI->getOperand(0).getReg() == ARM::SP) { 73 const MCOperand &MO1 = MI->getOperand(2); 74 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) { 75 O << '\t' << "pop"; 76 printPredicateOperand(MI, 3, O); 77 O << '\t'; 78 printRegisterList(MI, 5, O); 79 return; 80 } 81 } 82 83 // A8.6.355 VPUSH 84 if ((MI->getOpcode() == ARM::VSTMS_UPD || MI->getOpcode() ==ARM::VSTMD_UPD) && 85 MI->getOperand(0).getReg() == ARM::SP) { 86 const MCOperand &MO1 = MI->getOperand(2); 87 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) { 88 O << '\t' << "vpush"; 89 printPredicateOperand(MI, 3, O); 90 O << '\t'; 91 printRegisterList(MI, 5, O); 92 return; 93 } 94 } 95 96 // A8.6.354 VPOP 97 if ((MI->getOpcode() == ARM::VLDMS_UPD || MI->getOpcode() ==ARM::VLDMD_UPD) && 98 MI->getOperand(0).getReg() == ARM::SP) { 99 const MCOperand &MO1 = MI->getOperand(2); 100 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) { 101 O << '\t' << "vpop"; 102 printPredicateOperand(MI, 3, O); 103 O << '\t'; 104 printRegisterList(MI, 5, O); 105 return; 106 } 107 } 108 109 printInstruction(MI, O); 110 } 111 112void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 113 raw_ostream &O, const char *Modifier) { 114 const MCOperand &Op = MI->getOperand(OpNo); 115 if (Op.isReg()) { 116 unsigned Reg = Op.getReg(); 117 O << getRegisterName(Reg); 118 } else if (Op.isImm()) { 119 assert((Modifier && !strcmp(Modifier, "call")) || 120 ((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported")); 121 O << '#' << Op.getImm(); 122 } else { 123 if (Modifier && Modifier[0] != 0 && strcmp(Modifier, "call") != 0) 124 llvm_unreachable("Unsupported modifier"); 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/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov' 162/// followed by an 'orr' to materialize. 163void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum, 164 raw_ostream &O) { 165 // FIXME: REMOVE this method. 166 abort(); 167} 168 169// so_reg is a 4-operand unit corresponding to register forms of the A5.1 170// "Addressing Mode 1 - Data-processing operands" forms. This includes: 171// REG 0 0 - e.g. R5 172// REG REG 0,SH_OPC - e.g. R5, ROR R3 173// REG 0 IMM,SH_OPC - e.g. R5, LSL #3 174void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum, 175 raw_ostream &O) { 176 const MCOperand &MO1 = MI->getOperand(OpNum); 177 const MCOperand &MO2 = MI->getOperand(OpNum+1); 178 const MCOperand &MO3 = MI->getOperand(OpNum+2); 179 180 O << getRegisterName(MO1.getReg()); 181 182 // Print the shift opc. 183 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm()); 184 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 185 if (MO2.getReg()) { 186 O << ' ' << getRegisterName(MO2.getReg()); 187 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); 188 } else if (ShOpc != ARM_AM::rrx) { 189 O << " #" << ARM_AM::getSORegOffset(MO3.getImm()); 190 } 191} 192 193 194void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op, 195 raw_ostream &O) { 196 const MCOperand &MO1 = MI->getOperand(Op); 197 const MCOperand &MO2 = MI->getOperand(Op+1); 198 const MCOperand &MO3 = MI->getOperand(Op+2); 199 200 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 201 printOperand(MI, Op, O); 202 return; 203 } 204 205 O << "[" << getRegisterName(MO1.getReg()); 206 207 if (!MO2.getReg()) { 208 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. 209 O << ", #" 210 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 211 << ARM_AM::getAM2Offset(MO3.getImm()); 212 O << "]"; 213 return; 214 } 215 216 O << ", " 217 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 218 << getRegisterName(MO2.getReg()); 219 220 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) 221 O << ", " 222 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) 223 << " #" << ShImm; 224 O << "]"; 225} 226 227void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI, 228 unsigned OpNum, 229 raw_ostream &O) { 230 const MCOperand &MO1 = MI->getOperand(OpNum); 231 const MCOperand &MO2 = MI->getOperand(OpNum+1); 232 233 if (!MO1.getReg()) { 234 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm()); 235 O << '#' 236 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 237 << ImmOffs; 238 return; 239 } 240 241 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 242 << getRegisterName(MO1.getReg()); 243 244 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) 245 O << ", " 246 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm())) 247 << " #" << ShImm; 248} 249 250void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum, 251 raw_ostream &O) { 252 const MCOperand &MO1 = MI->getOperand(OpNum); 253 const MCOperand &MO2 = MI->getOperand(OpNum+1); 254 const MCOperand &MO3 = MI->getOperand(OpNum+2); 255 256 O << '[' << getRegisterName(MO1.getReg()); 257 258 if (MO2.getReg()) { 259 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm()) 260 << getRegisterName(MO2.getReg()) << ']'; 261 return; 262 } 263 264 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) 265 O << ", #" 266 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm())) 267 << ImmOffs; 268 O << ']'; 269} 270 271void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI, 272 unsigned OpNum, 273 raw_ostream &O) { 274 const MCOperand &MO1 = MI->getOperand(OpNum); 275 const MCOperand &MO2 = MI->getOperand(OpNum+1); 276 277 if (MO1.getReg()) { 278 O << (char)ARM_AM::getAM3Op(MO2.getImm()) 279 << getRegisterName(MO1.getReg()); 280 return; 281 } 282 283 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm()); 284 O << '#' 285 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) 286 << ImmOffs; 287} 288 289 290void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum, 291 raw_ostream &O, 292 const char *Modifier) { 293 const MCOperand &MO2 = MI->getOperand(OpNum+1); 294 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); 295 if (Modifier && strcmp(Modifier, "submode") == 0) { 296 O << ARM_AM::getAMSubModeStr(Mode); 297 } else if (Modifier && strcmp(Modifier, "wide") == 0) { 298 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); 299 if (Mode == ARM_AM::ia) 300 O << ".w"; 301 } else { 302 printOperand(MI, OpNum, O); 303 } 304} 305 306void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum, 307 raw_ostream &O, 308 const char *Modifier) { 309 const MCOperand &MO1 = MI->getOperand(OpNum); 310 const MCOperand &MO2 = MI->getOperand(OpNum+1); 311 312 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 313 printOperand(MI, OpNum, O); 314 return; 315 } 316 317 O << "[" << getRegisterName(MO1.getReg()); 318 319 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) { 320 O << ", #" 321 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm())) 322 << ImmOffs*4; 323 } 324 O << "]"; 325} 326 327void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum, 328 raw_ostream &O) { 329 const MCOperand &MO1 = MI->getOperand(OpNum); 330 const MCOperand &MO2 = MI->getOperand(OpNum+1); 331 332 O << "[" << getRegisterName(MO1.getReg()); 333 if (MO2.getImm()) { 334 // FIXME: Both darwin as and GNU as violate ARM docs here. 335 O << ", :" << (MO2.getImm() << 3); 336 } 337 O << "]"; 338} 339 340void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI, 341 unsigned OpNum, 342 raw_ostream &O) { 343 const MCOperand &MO = MI->getOperand(OpNum); 344 if (MO.getReg() == 0) 345 O << "!"; 346 else 347 O << ", " << getRegisterName(MO.getReg()); 348} 349 350void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum, 351 raw_ostream &O, 352 const char *Modifier) { 353 // All instructions using addrmodepc are pseudos and should have been 354 // handled explicitly in printInstructionThroughMCStreamer(). If one got 355 // here, it wasn't, so something's wrong. 356 llvm_unreachable("Unhandled PC-relative pseudo-instruction!"); 357} 358 359void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI, 360 unsigned OpNum, 361 raw_ostream &O) { 362 const MCOperand &MO = MI->getOperand(OpNum); 363 uint32_t v = ~MO.getImm(); 364 int32_t lsb = CountTrailingZeros_32(v); 365 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb; 366 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!"); 367 O << '#' << lsb << ", #" << width; 368} 369 370void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum, 371 raw_ostream &O) { 372 unsigned val = MI->getOperand(OpNum).getImm(); 373 O << ARM_MB::MemBOptToString(val); 374} 375 376void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum, 377 raw_ostream &O) { 378 unsigned ShiftOp = MI->getOperand(OpNum).getImm(); 379 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp); 380 switch (Opc) { 381 case ARM_AM::no_shift: 382 return; 383 case ARM_AM::lsl: 384 O << ", lsl #"; 385 break; 386 case ARM_AM::asr: 387 O << ", asr #"; 388 break; 389 default: 390 assert(0 && "unexpected shift opcode for shift immediate operand"); 391 } 392 O << ARM_AM::getSORegOffset(ShiftOp); 393} 394 395void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, 396 raw_ostream &O) { 397 O << "{"; 398 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { 399 if (i != OpNum) O << ", "; 400 O << getRegisterName(MI->getOperand(i).getReg()); 401 } 402 O << "}"; 403} 404 405void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum, 406 raw_ostream &O) { 407 const MCOperand &Op = MI->getOperand(OpNum); 408 unsigned option = Op.getImm(); 409 unsigned mode = option & 31; 410 bool changemode = option >> 5 & 1; 411 unsigned AIF = option >> 6 & 7; 412 unsigned imod = option >> 9 & 3; 413 if (imod == 2) 414 O << "ie"; 415 else if (imod == 3) 416 O << "id"; 417 O << '\t'; 418 if (imod > 1) { 419 if (AIF & 4) O << 'a'; 420 if (AIF & 2) O << 'i'; 421 if (AIF & 1) O << 'f'; 422 if (AIF > 0 && changemode) O << ", "; 423 } 424 if (changemode) 425 O << '#' << mode; 426} 427 428void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum, 429 raw_ostream &O) { 430 const MCOperand &Op = MI->getOperand(OpNum); 431 unsigned Mask = Op.getImm(); 432 if (Mask) { 433 O << '_'; 434 if (Mask & 8) O << 'f'; 435 if (Mask & 4) O << 's'; 436 if (Mask & 2) O << 'x'; 437 if (Mask & 1) O << 'c'; 438 } 439} 440 441void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum, 442 raw_ostream &O) { 443 const MCOperand &Op = MI->getOperand(OpNum); 444 O << '#'; 445 if (Op.getImm() < 0) 446 O << '-' << (-Op.getImm() - 1); 447 else 448 O << Op.getImm(); 449} 450 451void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum, 452 raw_ostream &O) { 453 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 454 if (CC != ARMCC::AL) 455 O << ARMCondCodeToString(CC); 456} 457 458void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI, 459 unsigned OpNum, 460 raw_ostream &O) { 461 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 462 O << ARMCondCodeToString(CC); 463} 464 465void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum, 466 raw_ostream &O) { 467 if (MI->getOperand(OpNum).getReg()) { 468 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR && 469 "Expect ARM CPSR register!"); 470 O << 's'; 471 } 472} 473 474 475 476void ARMInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNum, 477 raw_ostream &O, 478 const char *Modifier) { 479 // FIXME: remove this. 480 abort(); 481} 482 483void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum, 484 raw_ostream &O) { 485 O << MI->getOperand(OpNum).getImm(); 486} 487 488 489void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum, 490 raw_ostream &O) { 491 llvm_unreachable("Unhandled PC-relative pseudo-instruction!"); 492} 493 494void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, 495 raw_ostream &O) { 496 O << "#" << MI->getOperand(OpNum).getImm() * 4; 497} 498 499void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum, 500 raw_ostream &O) { 501 // (3 - the number of trailing zeros) is the number of then / else. 502 unsigned Mask = MI->getOperand(OpNum).getImm(); 503 unsigned CondBit0 = Mask >> 4 & 1; 504 unsigned NumTZ = CountTrailingZeros_32(Mask); 505 assert(NumTZ <= 3 && "Invalid IT mask!"); 506 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) { 507 bool T = ((Mask >> Pos) & 1) == CondBit0; 508 if (T) 509 O << 't'; 510 else 511 O << 'e'; 512 } 513} 514 515void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op, 516 raw_ostream &O) { 517 const MCOperand &MO1 = MI->getOperand(Op); 518 const MCOperand &MO2 = MI->getOperand(Op+1); 519 O << "[" << getRegisterName(MO1.getReg()); 520 O << ", " << getRegisterName(MO2.getReg()) << "]"; 521} 522 523void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op, 524 raw_ostream &O, 525 unsigned Scale) { 526 const MCOperand &MO1 = MI->getOperand(Op); 527 const MCOperand &MO2 = MI->getOperand(Op+1); 528 const MCOperand &MO3 = MI->getOperand(Op+2); 529 530 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 531 printOperand(MI, Op, O); 532 return; 533 } 534 535 O << "[" << getRegisterName(MO1.getReg()); 536 if (MO3.getReg()) 537 O << ", " << getRegisterName(MO3.getReg()); 538 else if (unsigned ImmOffs = MO2.getImm()) 539 O << ", #" << ImmOffs * Scale; 540 O << "]"; 541} 542 543void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op, 544 raw_ostream &O) { 545 printThumbAddrModeRI5Operand(MI, Op, O, 1); 546} 547 548void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op, 549 raw_ostream &O) { 550 printThumbAddrModeRI5Operand(MI, Op, O, 2); 551} 552 553void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op, 554 raw_ostream &O) { 555 printThumbAddrModeRI5Operand(MI, Op, O, 4); 556} 557 558void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op, 559 raw_ostream &O) { 560 const MCOperand &MO1 = MI->getOperand(Op); 561 const MCOperand &MO2 = MI->getOperand(Op+1); 562 O << "[" << getRegisterName(MO1.getReg()); 563 if (unsigned ImmOffs = MO2.getImm()) 564 O << ", #" << ImmOffs*4; 565 O << "]"; 566} 567 568void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum, 569 raw_ostream &O) { 570 O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg()); 571 if (MI->getOpcode() == ARM::t2TBH) 572 O << ", lsl #1"; 573 O << ']'; 574} 575 576// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 577// register with shift forms. 578// REG 0 0 - e.g. R5 579// REG IMM, SH_OPC - e.g. R5, LSL #3 580void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum, 581 raw_ostream &O) { 582 const MCOperand &MO1 = MI->getOperand(OpNum); 583 const MCOperand &MO2 = MI->getOperand(OpNum+1); 584 585 unsigned Reg = MO1.getReg(); 586 O << getRegisterName(Reg); 587 588 // Print the shift opc. 589 assert(MO2.isImm() && "Not a valid t2_so_reg value!"); 590 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm()); 591 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 592 if (ShOpc != ARM_AM::rrx) 593 O << " #" << ARM_AM::getSORegOffset(MO2.getImm()); 594} 595 596void ARMInstPrinter::printT2AddrModeImm12Operand(const MCInst *MI, 597 unsigned OpNum, 598 raw_ostream &O) { 599 const MCOperand &MO1 = MI->getOperand(OpNum); 600 const MCOperand &MO2 = MI->getOperand(OpNum+1); 601 602 O << "[" << getRegisterName(MO1.getReg()); 603 604 unsigned OffImm = MO2.getImm(); 605 if (OffImm) // Don't print +0. 606 O << ", #" << OffImm; 607 O << "]"; 608} 609 610void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI, 611 unsigned OpNum, 612 raw_ostream &O) { 613 const MCOperand &MO1 = MI->getOperand(OpNum); 614 const MCOperand &MO2 = MI->getOperand(OpNum+1); 615 616 O << "[" << getRegisterName(MO1.getReg()); 617 618 int32_t OffImm = (int32_t)MO2.getImm(); 619 // Don't print +0. 620 if (OffImm < 0) 621 O << ", #-" << -OffImm; 622 else if (OffImm > 0) 623 O << ", #" << OffImm; 624 O << "]"; 625} 626 627void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI, 628 unsigned OpNum, 629 raw_ostream &O) { 630 const MCOperand &MO1 = MI->getOperand(OpNum); 631 const MCOperand &MO2 = MI->getOperand(OpNum+1); 632 633 O << "[" << getRegisterName(MO1.getReg()); 634 635 int32_t OffImm = (int32_t)MO2.getImm() / 4; 636 // Don't print +0. 637 if (OffImm < 0) 638 O << ", #-" << -OffImm * 4; 639 else if (OffImm > 0) 640 O << ", #" << OffImm * 4; 641 O << "]"; 642} 643 644void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI, 645 unsigned OpNum, 646 raw_ostream &O) { 647 const MCOperand &MO1 = MI->getOperand(OpNum); 648 int32_t OffImm = (int32_t)MO1.getImm(); 649 // Don't print +0. 650 if (OffImm < 0) 651 O << "#-" << -OffImm; 652 else if (OffImm > 0) 653 O << "#" << OffImm; 654} 655 656void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, 657 unsigned OpNum, 658 raw_ostream &O) { 659 const MCOperand &MO1 = MI->getOperand(OpNum); 660 int32_t OffImm = (int32_t)MO1.getImm() / 4; 661 // Don't print +0. 662 if (OffImm < 0) 663 O << "#-" << -OffImm * 4; 664 else if (OffImm > 0) 665 O << "#" << OffImm * 4; 666} 667 668void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI, 669 unsigned OpNum, 670 raw_ostream &O) { 671 const MCOperand &MO1 = MI->getOperand(OpNum); 672 const MCOperand &MO2 = MI->getOperand(OpNum+1); 673 const MCOperand &MO3 = MI->getOperand(OpNum+2); 674 675 O << "[" << getRegisterName(MO1.getReg()); 676 677 assert(MO2.getReg() && "Invalid so_reg load / store address!"); 678 O << ", " << getRegisterName(MO2.getReg()); 679 680 unsigned ShAmt = MO3.getImm(); 681 if (ShAmt) { 682 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); 683 O << ", lsl #" << ShAmt; 684 } 685 O << "]"; 686} 687 688void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, 689 raw_ostream &O) { 690 O << '#' << (float)MI->getOperand(OpNum).getFPImm(); 691} 692 693void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, 694 raw_ostream &O) { 695 O << '#' << MI->getOperand(OpNum).getFPImm(); 696} 697 698void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum, 699 raw_ostream &O) { 700 unsigned EncodedImm = MI->getOperand(OpNum).getImm(); 701 unsigned EltBits; 702 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits); 703 O << "#0x" << utohexstr(Val); 704} 705