ARMInstPrinter.cpp revision 638d1ca07a09c765bd088465d991df39cfdf818f
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 == 0 || Modifier[0] == 0) && "No modifiers supported"); 120 O << '#' << Op.getImm(); 121 } else { 122 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); 123 assert(Op.isExpr() && "unknown operand kind in printOperand"); 124 O << *Op.getExpr(); 125 } 126} 127 128static void printSOImm(raw_ostream &O, int64_t V, raw_ostream *CommentStream, 129 const MCAsmInfo *MAI) { 130 // Break it up into two parts that make up a shifter immediate. 131 V = ARM_AM::getSOImmVal(V); 132 assert(V != -1 && "Not a valid so_imm value!"); 133 134 unsigned Imm = ARM_AM::getSOImmValImm(V); 135 unsigned Rot = ARM_AM::getSOImmValRot(V); 136 137 // Print low-level immediate formation info, per 138 // A5.1.3: "Data-processing operands - Immediate". 139 if (Rot) { 140 O << "#" << Imm << ", " << Rot; 141 // Pretty printed version. 142 if (CommentStream) 143 *CommentStream << (int)ARM_AM::rotr32(Imm, Rot) << "\n"; 144 } else { 145 O << "#" << Imm; 146 } 147} 148 149 150/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit 151/// immediate in bits 0-7. 152void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum, 153 raw_ostream &O) { 154 const MCOperand &MO = MI->getOperand(OpNum); 155 assert(MO.isImm() && "Not a valid so_imm value!"); 156 printSOImm(O, MO.getImm(), CommentStream, &MAI); 157} 158 159/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov' 160/// followed by an 'orr' to materialize. 161void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum, 162 raw_ostream &O) { 163 // FIXME: REMOVE this method. 164 abort(); 165} 166 167// so_reg is a 4-operand unit corresponding to register forms of the A5.1 168// "Addressing Mode 1 - Data-processing operands" forms. This includes: 169// REG 0 0 - e.g. R5 170// REG REG 0,SH_OPC - e.g. R5, ROR R3 171// REG 0 IMM,SH_OPC - e.g. R5, LSL #3 172void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum, 173 raw_ostream &O) { 174 const MCOperand &MO1 = MI->getOperand(OpNum); 175 const MCOperand &MO2 = MI->getOperand(OpNum+1); 176 const MCOperand &MO3 = MI->getOperand(OpNum+2); 177 178 O << getRegisterName(MO1.getReg()); 179 180 // Print the shift opc. 181 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm()); 182 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 183 if (MO2.getReg()) { 184 O << ' ' << getRegisterName(MO2.getReg()); 185 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); 186 } else if (ShOpc != ARM_AM::rrx) { 187 O << " #" << ARM_AM::getSORegOffset(MO3.getImm()); 188 } 189} 190 191 192void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op, 193 raw_ostream &O) { 194 const MCOperand &MO1 = MI->getOperand(Op); 195 const MCOperand &MO2 = MI->getOperand(Op+1); 196 const MCOperand &MO3 = MI->getOperand(Op+2); 197 198 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 199 printOperand(MI, Op, O); 200 return; 201 } 202 203 O << "[" << getRegisterName(MO1.getReg()); 204 205 if (!MO2.getReg()) { 206 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. 207 O << ", #" 208 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 209 << ARM_AM::getAM2Offset(MO3.getImm()); 210 O << "]"; 211 return; 212 } 213 214 O << ", " 215 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 216 << getRegisterName(MO2.getReg()); 217 218 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) 219 O << ", " 220 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) 221 << " #" << ShImm; 222 O << "]"; 223} 224 225void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI, 226 unsigned OpNum, 227 raw_ostream &O) { 228 const MCOperand &MO1 = MI->getOperand(OpNum); 229 const MCOperand &MO2 = MI->getOperand(OpNum+1); 230 231 if (!MO1.getReg()) { 232 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm()); 233 O << '#' 234 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 235 << ImmOffs; 236 return; 237 } 238 239 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 240 << getRegisterName(MO1.getReg()); 241 242 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) 243 O << ", " 244 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm())) 245 << " #" << ShImm; 246} 247 248void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum, 249 raw_ostream &O) { 250 const MCOperand &MO1 = MI->getOperand(OpNum); 251 const MCOperand &MO2 = MI->getOperand(OpNum+1); 252 const MCOperand &MO3 = MI->getOperand(OpNum+2); 253 254 O << '[' << getRegisterName(MO1.getReg()); 255 256 if (MO2.getReg()) { 257 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm()) 258 << getRegisterName(MO2.getReg()) << ']'; 259 return; 260 } 261 262 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) 263 O << ", #" 264 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm())) 265 << ImmOffs; 266 O << ']'; 267} 268 269void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI, 270 unsigned OpNum, 271 raw_ostream &O) { 272 const MCOperand &MO1 = MI->getOperand(OpNum); 273 const MCOperand &MO2 = MI->getOperand(OpNum+1); 274 275 if (MO1.getReg()) { 276 O << (char)ARM_AM::getAM3Op(MO2.getImm()) 277 << getRegisterName(MO1.getReg()); 278 return; 279 } 280 281 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm()); 282 O << '#' 283 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) 284 << ImmOffs; 285} 286 287 288void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum, 289 raw_ostream &O, 290 const char *Modifier) { 291 const MCOperand &MO2 = MI->getOperand(OpNum+1); 292 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); 293 if (Modifier && strcmp(Modifier, "submode") == 0) { 294 O << ARM_AM::getAMSubModeStr(Mode); 295 } else if (Modifier && strcmp(Modifier, "wide") == 0) { 296 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); 297 if (Mode == ARM_AM::ia) 298 O << ".w"; 299 } else { 300 printOperand(MI, OpNum, O); 301 } 302} 303 304void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum, 305 raw_ostream &O, 306 const char *Modifier) { 307 const MCOperand &MO1 = MI->getOperand(OpNum); 308 const MCOperand &MO2 = MI->getOperand(OpNum+1); 309 310 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 311 printOperand(MI, OpNum, O); 312 return; 313 } 314 315 O << "[" << getRegisterName(MO1.getReg()); 316 317 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) { 318 O << ", #" 319 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm())) 320 << ImmOffs*4; 321 } 322 O << "]"; 323} 324 325void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum, 326 raw_ostream &O) { 327 const MCOperand &MO1 = MI->getOperand(OpNum); 328 const MCOperand &MO2 = MI->getOperand(OpNum+1); 329 330 O << "[" << getRegisterName(MO1.getReg()); 331 if (MO2.getImm()) { 332 // FIXME: Both darwin as and GNU as violate ARM docs here. 333 O << ", :" << (MO2.getImm() << 3); 334 } 335 O << "]"; 336} 337 338void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI, 339 unsigned OpNum, 340 raw_ostream &O) { 341 const MCOperand &MO = MI->getOperand(OpNum); 342 if (MO.getReg() == 0) 343 O << "!"; 344 else 345 O << ", " << getRegisterName(MO.getReg()); 346} 347 348void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum, 349 raw_ostream &O, 350 const char *Modifier) { 351 // All instructions using addrmodepc are pseudos and should have been 352 // handled explicitly in printInstructionThroughMCStreamer(). If one got 353 // here, it wasn't, so something's wrong. 354 llvm_unreachable("Unhandled PC-relative pseudo-instruction!"); 355} 356 357void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI, 358 unsigned OpNum, 359 raw_ostream &O) { 360 const MCOperand &MO = MI->getOperand(OpNum); 361 uint32_t v = ~MO.getImm(); 362 int32_t lsb = CountTrailingZeros_32(v); 363 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb; 364 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!"); 365 O << '#' << lsb << ", #" << width; 366} 367 368void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum, 369 raw_ostream &O) { 370 unsigned val = MI->getOperand(OpNum).getImm(); 371 O << ARM_MB::MemBOptToString(val); 372} 373 374void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum, 375 raw_ostream &O) { 376 unsigned ShiftOp = MI->getOperand(OpNum).getImm(); 377 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp); 378 switch (Opc) { 379 case ARM_AM::no_shift: 380 return; 381 case ARM_AM::lsl: 382 O << ", lsl #"; 383 break; 384 case ARM_AM::asr: 385 O << ", asr #"; 386 break; 387 default: 388 assert(0 && "unexpected shift opcode for shift immediate operand"); 389 } 390 O << ARM_AM::getSORegOffset(ShiftOp); 391} 392 393void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, 394 raw_ostream &O) { 395 O << "{"; 396 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { 397 if (i != OpNum) O << ", "; 398 O << getRegisterName(MI->getOperand(i).getReg()); 399 } 400 O << "}"; 401} 402 403void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum, 404 raw_ostream &O) { 405 const MCOperand &Op = MI->getOperand(OpNum); 406 if (Op.getImm()) 407 O << "be"; 408 else 409 O << "le"; 410} 411 412void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum, 413 raw_ostream &O) { 414 const MCOperand &Op = MI->getOperand(OpNum); 415 unsigned option = Op.getImm(); 416 unsigned mode = option & 31; 417 bool changemode = option >> 5 & 1; 418 unsigned AIF = option >> 6 & 7; 419 unsigned imod = option >> 9 & 3; 420 if (imod == 2) 421 O << "ie"; 422 else if (imod == 3) 423 O << "id"; 424 O << '\t'; 425 if (imod > 1) { 426 if (AIF & 4) O << 'a'; 427 if (AIF & 2) O << 'i'; 428 if (AIF & 1) O << 'f'; 429 if (AIF > 0 && changemode) O << ", "; 430 } 431 if (changemode) 432 O << '#' << mode; 433} 434 435void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum, 436 raw_ostream &O) { 437 const MCOperand &Op = MI->getOperand(OpNum); 438 unsigned Mask = Op.getImm(); 439 if (Mask) { 440 O << '_'; 441 if (Mask & 8) O << 'f'; 442 if (Mask & 4) O << 's'; 443 if (Mask & 2) O << 'x'; 444 if (Mask & 1) O << 'c'; 445 } 446} 447 448void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum, 449 raw_ostream &O) { 450 const MCOperand &Op = MI->getOperand(OpNum); 451 O << '#'; 452 if (Op.getImm() < 0) 453 O << '-' << (-Op.getImm() - 1); 454 else 455 O << Op.getImm(); 456} 457 458void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum, 459 raw_ostream &O) { 460 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 461 if (CC != ARMCC::AL) 462 O << ARMCondCodeToString(CC); 463} 464 465void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI, 466 unsigned OpNum, 467 raw_ostream &O) { 468 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 469 O << ARMCondCodeToString(CC); 470} 471 472void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum, 473 raw_ostream &O) { 474 if (MI->getOperand(OpNum).getReg()) { 475 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR && 476 "Expect ARM CPSR register!"); 477 O << 's'; 478 } 479} 480 481 482 483void ARMInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNum, 484 raw_ostream &O, 485 const char *Modifier) { 486 // FIXME: remove this. 487 abort(); 488} 489 490void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum, 491 raw_ostream &O) { 492 O << MI->getOperand(OpNum).getImm(); 493} 494 495 496void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum, 497 raw_ostream &O) { 498 llvm_unreachable("Unhandled PC-relative pseudo-instruction!"); 499} 500 501void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, 502 raw_ostream &O) { 503 O << "#" << MI->getOperand(OpNum).getImm() * 4; 504} 505 506void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum, 507 raw_ostream &O) { 508 // (3 - the number of trailing zeros) is the number of then / else. 509 unsigned Mask = MI->getOperand(OpNum).getImm(); 510 unsigned CondBit0 = Mask >> 4 & 1; 511 unsigned NumTZ = CountTrailingZeros_32(Mask); 512 assert(NumTZ <= 3 && "Invalid IT mask!"); 513 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) { 514 bool T = ((Mask >> Pos) & 1) == CondBit0; 515 if (T) 516 O << 't'; 517 else 518 O << 'e'; 519 } 520} 521 522void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op, 523 raw_ostream &O) { 524 const MCOperand &MO1 = MI->getOperand(Op); 525 const MCOperand &MO2 = MI->getOperand(Op+1); 526 O << "[" << getRegisterName(MO1.getReg()); 527 O << ", " << getRegisterName(MO2.getReg()) << "]"; 528} 529 530void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op, 531 raw_ostream &O, 532 unsigned Scale) { 533 const MCOperand &MO1 = MI->getOperand(Op); 534 const MCOperand &MO2 = MI->getOperand(Op+1); 535 const MCOperand &MO3 = MI->getOperand(Op+2); 536 537 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 538 printOperand(MI, Op, O); 539 return; 540 } 541 542 O << "[" << getRegisterName(MO1.getReg()); 543 if (MO3.getReg()) 544 O << ", " << getRegisterName(MO3.getReg()); 545 else if (unsigned ImmOffs = MO2.getImm()) 546 O << ", #" << ImmOffs * Scale; 547 O << "]"; 548} 549 550void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op, 551 raw_ostream &O) { 552 printThumbAddrModeRI5Operand(MI, Op, O, 1); 553} 554 555void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op, 556 raw_ostream &O) { 557 printThumbAddrModeRI5Operand(MI, Op, O, 2); 558} 559 560void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op, 561 raw_ostream &O) { 562 printThumbAddrModeRI5Operand(MI, Op, O, 4); 563} 564 565void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op, 566 raw_ostream &O) { 567 const MCOperand &MO1 = MI->getOperand(Op); 568 const MCOperand &MO2 = MI->getOperand(Op+1); 569 O << "[" << getRegisterName(MO1.getReg()); 570 if (unsigned ImmOffs = MO2.getImm()) 571 O << ", #" << ImmOffs*4; 572 O << "]"; 573} 574 575void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum, 576 raw_ostream &O) { 577 O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg()); 578 if (MI->getOpcode() == ARM::t2TBH) 579 O << ", lsl #1"; 580 O << ']'; 581} 582 583// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 584// register with shift forms. 585// REG 0 0 - e.g. R5 586// REG IMM, SH_OPC - e.g. R5, LSL #3 587void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum, 588 raw_ostream &O) { 589 const MCOperand &MO1 = MI->getOperand(OpNum); 590 const MCOperand &MO2 = MI->getOperand(OpNum+1); 591 592 unsigned Reg = MO1.getReg(); 593 O << getRegisterName(Reg); 594 595 // Print the shift opc. 596 assert(MO2.isImm() && "Not a valid t2_so_reg value!"); 597 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm()); 598 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 599 if (ShOpc != ARM_AM::rrx) 600 O << " #" << ARM_AM::getSORegOffset(MO2.getImm()); 601} 602 603void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum, 604 raw_ostream &O) { 605 const MCOperand &MO1 = MI->getOperand(OpNum); 606 const MCOperand &MO2 = MI->getOperand(OpNum+1); 607 608 O << "[" << getRegisterName(MO1.getReg()); 609 610 unsigned OffImm = MO2.getImm(); 611 if (OffImm) // Don't print +0. 612 O << ", #" << OffImm; 613 O << "]"; 614} 615 616void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI, 617 unsigned OpNum, 618 raw_ostream &O) { 619 const MCOperand &MO1 = MI->getOperand(OpNum); 620 const MCOperand &MO2 = MI->getOperand(OpNum+1); 621 622 O << "[" << getRegisterName(MO1.getReg()); 623 624 int32_t OffImm = (int32_t)MO2.getImm(); 625 // Don't print +0. 626 if (OffImm < 0) 627 O << ", #-" << -OffImm; 628 else if (OffImm > 0) 629 O << ", #" << OffImm; 630 O << "]"; 631} 632 633void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI, 634 unsigned OpNum, 635 raw_ostream &O) { 636 const MCOperand &MO1 = MI->getOperand(OpNum); 637 const MCOperand &MO2 = MI->getOperand(OpNum+1); 638 639 O << "[" << getRegisterName(MO1.getReg()); 640 641 int32_t OffImm = (int32_t)MO2.getImm() / 4; 642 // Don't print +0. 643 if (OffImm < 0) 644 O << ", #-" << -OffImm * 4; 645 else if (OffImm > 0) 646 O << ", #" << OffImm * 4; 647 O << "]"; 648} 649 650void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI, 651 unsigned OpNum, 652 raw_ostream &O) { 653 const MCOperand &MO1 = MI->getOperand(OpNum); 654 int32_t OffImm = (int32_t)MO1.getImm(); 655 // Don't print +0. 656 if (OffImm < 0) 657 O << "#-" << -OffImm; 658 else if (OffImm > 0) 659 O << "#" << OffImm; 660} 661 662void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, 663 unsigned OpNum, 664 raw_ostream &O) { 665 const MCOperand &MO1 = MI->getOperand(OpNum); 666 int32_t OffImm = (int32_t)MO1.getImm() / 4; 667 // Don't print +0. 668 if (OffImm < 0) 669 O << "#-" << -OffImm * 4; 670 else if (OffImm > 0) 671 O << "#" << OffImm * 4; 672} 673 674void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI, 675 unsigned OpNum, 676 raw_ostream &O) { 677 const MCOperand &MO1 = MI->getOperand(OpNum); 678 const MCOperand &MO2 = MI->getOperand(OpNum+1); 679 const MCOperand &MO3 = MI->getOperand(OpNum+2); 680 681 O << "[" << getRegisterName(MO1.getReg()); 682 683 assert(MO2.getReg() && "Invalid so_reg load / store address!"); 684 O << ", " << getRegisterName(MO2.getReg()); 685 686 unsigned ShAmt = MO3.getImm(); 687 if (ShAmt) { 688 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); 689 O << ", lsl #" << ShAmt; 690 } 691 O << "]"; 692} 693 694void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, 695 raw_ostream &O) { 696 O << '#' << (float)MI->getOperand(OpNum).getFPImm(); 697} 698 699void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, 700 raw_ostream &O) { 701 O << '#' << MI->getOperand(OpNum).getFPImm(); 702} 703 704void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum, 705 raw_ostream &O) { 706 unsigned EncodedImm = MI->getOperand(OpNum).getImm(); 707 unsigned EltBits; 708 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits); 709 O << "#0x" << utohexstr(Val); 710} 711