ARMInstPrinter.cpp revision 98c5ddabca1debf935a07d14d0cbc9732374bdb8
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===// 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// The LLVM Compiler Infrastructure 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This file is distributed under the University of Illinois Open Source 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// License. See LICENSE.TXT for details. 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===// 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This class prints an ARM MCInst to a .s file. 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===// 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define DEBUG_TYPE "asm-printer" 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "ARMInstPrinter.h" 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "MCTargetDesc/ARMBaseInfo.h" 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "MCTargetDesc/ARMAddressingModes.h" 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "llvm/MC/MCInst.h" 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "llvm/MC/MCAsmInfo.h" 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "llvm/MC/MCExpr.h" 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "llvm/ADT/StringExtras.h" 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "llvm/Support/raw_ostream.h" 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace llvm; 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define GET_INSTRUCTION_NAME 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "ARMGenAsmWriter.inc" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing. 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/// 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/// getSORegOffset returns an integer from 0-31, but '0' should actually be printed 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/// 32 as the immediate shouldbe within the range 1-32. 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic unsigned translateShiftImm(unsigned imm) { 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (imm == 0) 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return 32; 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return imm; 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 393c827367444ee418f129b2c238299f49d3264554Jarkko PoyryARMInstPrinter::ARMInstPrinter(const MCAsmInfo &MAI, 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const MCSubtargetInfo &STI) : 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry MCInstPrinter(MAI) { 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Initialize the set of available features. 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setAvailableFeatures(STI.getFeatureBits()); 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 463c827367444ee418f129b2c238299f49d3264554Jarkko PoyryStringRef ARMInstPrinter::getOpcodeName(unsigned Opcode) const { 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getInstructionName(Opcode); 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry OS << getRegisterName(RegNo); 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry StringRef Annot) { 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry unsigned Opcode = MI->getOpcode(); 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Check for MOVs and print canonical forms, instead. 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (Opcode == ARM::MOVsr) { 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // FIXME: Thumb variants? 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const MCOperand &Dst = MI->getOperand(0); 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const MCOperand &MO1 = MI->getOperand(1); 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const MCOperand &MO2 = MI->getOperand(2); 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const MCOperand &MO3 = MI->getOperand(3); 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm())); 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printSBitModifierOperand(MI, 6, O); 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printPredicateOperand(MI, 4, O); 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t' << getRegisterName(Dst.getReg()) 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ", " << getRegisterName(MO1.getReg()); 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << ", " << getRegisterName(MO2.getReg()); 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (CommentStream) printAnnotation(*CommentStream, Annot); 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return; 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (Opcode == ARM::MOVsi) { 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // FIXME: Thumb variants? 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const MCOperand &Dst = MI->getOperand(0); 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const MCOperand &MO1 = MI->getOperand(1); 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const MCOperand &MO2 = MI->getOperand(2); 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm())); 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printSBitModifierOperand(MI, 5, O); 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printPredicateOperand(MI, 3, O); 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t' << getRegisterName(Dst.getReg()) 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ", " << getRegisterName(MO1.getReg()); 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx) { 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (CommentStream) printAnnotation(*CommentStream, Annot); 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return; 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << ", #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm())); 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (CommentStream) printAnnotation(*CommentStream, Annot); 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return; 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // A8.6.123 PUSH 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((Opcode == ARM::STMDB_UPD || Opcode == ARM::t2STMDB_UPD) && 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry MI->getOperand(0).getReg() == ARM::SP) { 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t' << "push"; 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printPredicateOperand(MI, 2, O); 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (Opcode == ARM::t2STMDB_UPD) 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << ".w"; 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t'; 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printRegisterList(MI, 4, O); 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (CommentStream) printAnnotation(*CommentStream, Annot); 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return; 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (Opcode == ARM::STR_PRE_IMM && MI->getOperand(2).getReg() == ARM::SP && 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry MI->getOperand(3).getImm() == -4) { 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t' << "push"; 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printPredicateOperand(MI, 4, O); 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << "\t{" << getRegisterName(MI->getOperand(1).getReg()) << "}"; 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (CommentStream) printAnnotation(*CommentStream, Annot); 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return; 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // A8.6.122 POP 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((Opcode == ARM::LDMIA_UPD || Opcode == ARM::t2LDMIA_UPD) && 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry MI->getOperand(0).getReg() == ARM::SP) { 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t' << "pop"; 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printPredicateOperand(MI, 2, O); 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (Opcode == ARM::t2LDMIA_UPD) 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << ".w"; 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t'; 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printRegisterList(MI, 4, O); 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (CommentStream) printAnnotation(*CommentStream, Annot); 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return; 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (Opcode == ARM::LDR_POST_IMM && MI->getOperand(2).getReg() == ARM::SP && 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry MI->getOperand(4).getImm() == 4) { 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t' << "pop"; 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printPredicateOperand(MI, 5, O); 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << "\t{" << getRegisterName(MI->getOperand(0).getReg()) << "}"; 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (CommentStream) printAnnotation(*CommentStream, Annot); 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return; 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // A8.6.355 VPUSH 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((Opcode == ARM::VSTMSDB_UPD || Opcode == ARM::VSTMDDB_UPD) && 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry MI->getOperand(0).getReg() == ARM::SP) { 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t' << "vpush"; 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printPredicateOperand(MI, 2, O); 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t'; 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printRegisterList(MI, 4, O); 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (CommentStream) printAnnotation(*CommentStream, Annot); 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return; 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // A8.6.354 VPOP 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMDIA_UPD) && 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry MI->getOperand(0).getReg() == ARM::SP) { 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t' << "vpop"; 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printPredicateOperand(MI, 2, O); 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry O << '\t'; 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printRegisterList(MI, 4, O); 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (CommentStream) printAnnotation(*CommentStream, Annot); 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return; 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (Opcode == ARM::tLDMIA) { 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool Writeback = true; 170 unsigned BaseReg = MI->getOperand(0).getReg(); 171 for (unsigned i = 3; i < MI->getNumOperands(); ++i) { 172 if (MI->getOperand(i).getReg() == BaseReg) 173 Writeback = false; 174 } 175 176 O << "\tldm"; 177 178 printPredicateOperand(MI, 1, O); 179 O << '\t' << getRegisterName(BaseReg); 180 if (Writeback) O << "!"; 181 O << ", "; 182 printRegisterList(MI, 3, O); 183 if (CommentStream) printAnnotation(*CommentStream, Annot); 184 return; 185 } 186 187 // Thumb1 NOP 188 if (Opcode == ARM::tMOVr && MI->getOperand(0).getReg() == ARM::R8 && 189 MI->getOperand(1).getReg() == ARM::R8) { 190 O << "\tnop"; 191 printPredicateOperand(MI, 2, O); 192 if (CommentStream) printAnnotation(*CommentStream, Annot); 193 return; 194 } 195 196 printInstruction(MI, O); 197 if (CommentStream) printAnnotation(*CommentStream, Annot); 198} 199 200void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 201 raw_ostream &O) { 202 const MCOperand &Op = MI->getOperand(OpNo); 203 if (Op.isReg()) { 204 unsigned Reg = Op.getReg(); 205 O << getRegisterName(Reg); 206 } else if (Op.isImm()) { 207 O << '#' << Op.getImm(); 208 } else { 209 assert(Op.isExpr() && "unknown operand kind in printOperand"); 210 O << *Op.getExpr(); 211 } 212} 213 214// so_reg is a 4-operand unit corresponding to register forms of the A5.1 215// "Addressing Mode 1 - Data-processing operands" forms. This includes: 216// REG 0 0 - e.g. R5 217// REG REG 0,SH_OPC - e.g. R5, ROR R3 218// REG 0 IMM,SH_OPC - e.g. R5, LSL #3 219void ARMInstPrinter::printSORegRegOperand(const MCInst *MI, unsigned OpNum, 220 raw_ostream &O) { 221 const MCOperand &MO1 = MI->getOperand(OpNum); 222 const MCOperand &MO2 = MI->getOperand(OpNum+1); 223 const MCOperand &MO3 = MI->getOperand(OpNum+2); 224 225 O << getRegisterName(MO1.getReg()); 226 227 // Print the shift opc. 228 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm()); 229 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 230 if (ShOpc == ARM_AM::rrx) 231 return; 232 233 O << ' ' << getRegisterName(MO2.getReg()); 234 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); 235} 236 237void ARMInstPrinter::printSORegImmOperand(const MCInst *MI, unsigned OpNum, 238 raw_ostream &O) { 239 const MCOperand &MO1 = MI->getOperand(OpNum); 240 const MCOperand &MO2 = MI->getOperand(OpNum+1); 241 242 O << getRegisterName(MO1.getReg()); 243 244 // Print the shift opc. 245 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm()); 246 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 247 if (ShOpc == ARM_AM::rrx) 248 return; 249 O << " #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm())); 250} 251 252 253//===--------------------------------------------------------------------===// 254// Addressing Mode #2 255//===--------------------------------------------------------------------===// 256 257void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op, 258 raw_ostream &O) { 259 const MCOperand &MO1 = MI->getOperand(Op); 260 const MCOperand &MO2 = MI->getOperand(Op+1); 261 const MCOperand &MO3 = MI->getOperand(Op+2); 262 263 O << "[" << getRegisterName(MO1.getReg()); 264 265 if (!MO2.getReg()) { 266 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. 267 O << ", #" 268 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 269 << ARM_AM::getAM2Offset(MO3.getImm()); 270 O << "]"; 271 return; 272 } 273 274 O << ", " 275 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 276 << getRegisterName(MO2.getReg()); 277 278 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) 279 O << ", " 280 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) 281 << " #" << ShImm; 282 O << "]"; 283} 284 285void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op, 286 raw_ostream &O) { 287 const MCOperand &MO1 = MI->getOperand(Op); 288 const MCOperand &MO2 = MI->getOperand(Op+1); 289 const MCOperand &MO3 = MI->getOperand(Op+2); 290 291 O << "[" << getRegisterName(MO1.getReg()) << "], "; 292 293 if (!MO2.getReg()) { 294 unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm()); 295 O << '#' 296 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 297 << ImmOffs; 298 return; 299 } 300 301 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 302 << getRegisterName(MO2.getReg()); 303 304 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) 305 O << ", " 306 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) 307 << " #" << ShImm; 308} 309 310void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op, 311 raw_ostream &O) { 312 const MCOperand &MO1 = MI->getOperand(Op); 313 314 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 315 printOperand(MI, Op, O); 316 return; 317 } 318 319 const MCOperand &MO3 = MI->getOperand(Op+2); 320 unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm()); 321 322 if (IdxMode == ARMII::IndexModePost) { 323 printAM2PostIndexOp(MI, Op, O); 324 return; 325 } 326 printAM2PreOrOffsetIndexOp(MI, Op, O); 327} 328 329void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI, 330 unsigned OpNum, 331 raw_ostream &O) { 332 const MCOperand &MO1 = MI->getOperand(OpNum); 333 const MCOperand &MO2 = MI->getOperand(OpNum+1); 334 335 if (!MO1.getReg()) { 336 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm()); 337 O << '#' 338 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 339 << ImmOffs; 340 return; 341 } 342 343 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 344 << getRegisterName(MO1.getReg()); 345 346 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) 347 O << ", " 348 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm())) 349 << " #" << ShImm; 350} 351 352//===--------------------------------------------------------------------===// 353// Addressing Mode #3 354//===--------------------------------------------------------------------===// 355 356void ARMInstPrinter::printAM3PostIndexOp(const MCInst *MI, unsigned Op, 357 raw_ostream &O) { 358 const MCOperand &MO1 = MI->getOperand(Op); 359 const MCOperand &MO2 = MI->getOperand(Op+1); 360 const MCOperand &MO3 = MI->getOperand(Op+2); 361 362 O << "[" << getRegisterName(MO1.getReg()) << "], "; 363 364 if (MO2.getReg()) { 365 O << (char)ARM_AM::getAM3Op(MO3.getImm()) 366 << getRegisterName(MO2.getReg()); 367 return; 368 } 369 370 unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()); 371 O << '#' 372 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm())) 373 << ImmOffs; 374} 375 376void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op, 377 raw_ostream &O) { 378 const MCOperand &MO1 = MI->getOperand(Op); 379 const MCOperand &MO2 = MI->getOperand(Op+1); 380 const MCOperand &MO3 = MI->getOperand(Op+2); 381 382 O << '[' << getRegisterName(MO1.getReg()); 383 384 if (MO2.getReg()) { 385 O << ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm())) 386 << getRegisterName(MO2.getReg()) << ']'; 387 return; 388 } 389 390 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) 391 O << ", #" 392 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm())) 393 << ImmOffs; 394 O << ']'; 395} 396 397void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op, 398 raw_ostream &O) { 399 const MCOperand &MO3 = MI->getOperand(Op+2); 400 unsigned IdxMode = ARM_AM::getAM3IdxMode(MO3.getImm()); 401 402 if (IdxMode == ARMII::IndexModePost) { 403 printAM3PostIndexOp(MI, Op, O); 404 return; 405 } 406 printAM3PreOrOffsetIndexOp(MI, Op, O); 407} 408 409void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI, 410 unsigned OpNum, 411 raw_ostream &O) { 412 const MCOperand &MO1 = MI->getOperand(OpNum); 413 const MCOperand &MO2 = MI->getOperand(OpNum+1); 414 415 if (MO1.getReg()) { 416 O << getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) 417 << getRegisterName(MO1.getReg()); 418 return; 419 } 420 421 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm()); 422 O << '#' 423 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) 424 << ImmOffs; 425} 426 427void ARMInstPrinter::printPostIdxImm8Operand(const MCInst *MI, 428 unsigned OpNum, 429 raw_ostream &O) { 430 const MCOperand &MO = MI->getOperand(OpNum); 431 unsigned Imm = MO.getImm(); 432 O << '#' << ((Imm & 256) ? "" : "-") << (Imm & 0xff); 433} 434 435void ARMInstPrinter::printPostIdxRegOperand(const MCInst *MI, unsigned OpNum, 436 raw_ostream &O) { 437 const MCOperand &MO1 = MI->getOperand(OpNum); 438 const MCOperand &MO2 = MI->getOperand(OpNum+1); 439 440 O << (MO2.getImm() ? "" : "-") << getRegisterName(MO1.getReg()); 441} 442 443void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst *MI, 444 unsigned OpNum, 445 raw_ostream &O) { 446 const MCOperand &MO = MI->getOperand(OpNum); 447 unsigned Imm = MO.getImm(); 448 O << '#' << ((Imm & 256) ? "" : "-") << ((Imm & 0xff) << 2); 449} 450 451 452void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum, 453 raw_ostream &O) { 454 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum) 455 .getImm()); 456 O << ARM_AM::getAMSubModeStr(Mode); 457} 458 459void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum, 460 raw_ostream &O) { 461 const MCOperand &MO1 = MI->getOperand(OpNum); 462 const MCOperand &MO2 = MI->getOperand(OpNum+1); 463 464 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 465 printOperand(MI, OpNum, O); 466 return; 467 } 468 469 O << "[" << getRegisterName(MO1.getReg()); 470 471 unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm()); 472 unsigned Op = ARM_AM::getAM5Op(MO2.getImm()); 473 if (ImmOffs || Op == ARM_AM::sub) { 474 O << ", #" 475 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm())) 476 << ImmOffs * 4; 477 } 478 O << "]"; 479} 480 481void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum, 482 raw_ostream &O) { 483 const MCOperand &MO1 = MI->getOperand(OpNum); 484 const MCOperand &MO2 = MI->getOperand(OpNum+1); 485 486 O << "[" << getRegisterName(MO1.getReg()); 487 if (MO2.getImm()) { 488 // FIXME: Both darwin as and GNU as violate ARM docs here. 489 O << ", :" << (MO2.getImm() << 3); 490 } 491 O << "]"; 492} 493 494void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum, 495 raw_ostream &O) { 496 const MCOperand &MO1 = MI->getOperand(OpNum); 497 O << "[" << getRegisterName(MO1.getReg()) << "]"; 498} 499 500void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI, 501 unsigned OpNum, 502 raw_ostream &O) { 503 const MCOperand &MO = MI->getOperand(OpNum); 504 if (MO.getReg() == 0) 505 O << "!"; 506 else 507 O << ", " << getRegisterName(MO.getReg()); 508} 509 510void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI, 511 unsigned OpNum, 512 raw_ostream &O) { 513 const MCOperand &MO = MI->getOperand(OpNum); 514 uint32_t v = ~MO.getImm(); 515 int32_t lsb = CountTrailingZeros_32(v); 516 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb; 517 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!"); 518 O << '#' << lsb << ", #" << width; 519} 520 521void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum, 522 raw_ostream &O) { 523 unsigned val = MI->getOperand(OpNum).getImm(); 524 O << ARM_MB::MemBOptToString(val); 525} 526 527void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum, 528 raw_ostream &O) { 529 unsigned ShiftOp = MI->getOperand(OpNum).getImm(); 530 bool isASR = (ShiftOp & (1 << 5)) != 0; 531 unsigned Amt = ShiftOp & 0x1f; 532 if (isASR) 533 O << ", asr #" << (Amt == 0 ? 32 : Amt); 534 else if (Amt) 535 O << ", lsl #" << Amt; 536} 537 538void ARMInstPrinter::printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum, 539 raw_ostream &O) { 540 unsigned Imm = MI->getOperand(OpNum).getImm(); 541 if (Imm == 0) 542 return; 543 assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!"); 544 O << ", lsl #" << Imm; 545} 546 547void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum, 548 raw_ostream &O) { 549 unsigned Imm = MI->getOperand(OpNum).getImm(); 550 // A shift amount of 32 is encoded as 0. 551 if (Imm == 0) 552 Imm = 32; 553 assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!"); 554 O << ", asr #" << Imm; 555} 556 557void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, 558 raw_ostream &O) { 559 O << "{"; 560 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { 561 if (i != OpNum) O << ", "; 562 O << getRegisterName(MI->getOperand(i).getReg()); 563 } 564 O << "}"; 565} 566 567void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum, 568 raw_ostream &O) { 569 const MCOperand &Op = MI->getOperand(OpNum); 570 if (Op.getImm()) 571 O << "be"; 572 else 573 O << "le"; 574} 575 576void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum, 577 raw_ostream &O) { 578 const MCOperand &Op = MI->getOperand(OpNum); 579 O << ARM_PROC::IModToString(Op.getImm()); 580} 581 582void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum, 583 raw_ostream &O) { 584 const MCOperand &Op = MI->getOperand(OpNum); 585 unsigned IFlags = Op.getImm(); 586 for (int i=2; i >= 0; --i) 587 if (IFlags & (1 << i)) 588 O << ARM_PROC::IFlagsToString(1 << i); 589} 590 591void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum, 592 raw_ostream &O) { 593 const MCOperand &Op = MI->getOperand(OpNum); 594 unsigned SpecRegRBit = Op.getImm() >> 4; 595 unsigned Mask = Op.getImm() & 0xf; 596 597 // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as 598 // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively. 599 if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) { 600 O << "APSR_"; 601 switch (Mask) { 602 default: assert(0); 603 case 4: O << "g"; return; 604 case 8: O << "nzcvq"; return; 605 case 12: O << "nzcvqg"; return; 606 } 607 llvm_unreachable("Unexpected mask value!"); 608 } 609 610 if (SpecRegRBit) 611 O << "SPSR"; 612 else 613 O << "CPSR"; 614 615 if (Mask) { 616 O << '_'; 617 if (Mask & 8) O << 'f'; 618 if (Mask & 4) O << 's'; 619 if (Mask & 2) O << 'x'; 620 if (Mask & 1) O << 'c'; 621 } 622} 623 624void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum, 625 raw_ostream &O) { 626 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 627 if (CC != ARMCC::AL) 628 O << ARMCondCodeToString(CC); 629} 630 631void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI, 632 unsigned OpNum, 633 raw_ostream &O) { 634 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 635 O << ARMCondCodeToString(CC); 636} 637 638void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum, 639 raw_ostream &O) { 640 if (MI->getOperand(OpNum).getReg()) { 641 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR && 642 "Expect ARM CPSR register!"); 643 O << 's'; 644 } 645} 646 647void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum, 648 raw_ostream &O) { 649 O << MI->getOperand(OpNum).getImm(); 650} 651 652void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum, 653 raw_ostream &O) { 654 O << "p" << MI->getOperand(OpNum).getImm(); 655} 656 657void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum, 658 raw_ostream &O) { 659 O << "c" << MI->getOperand(OpNum).getImm(); 660} 661 662void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum, 663 raw_ostream &O) { 664 llvm_unreachable("Unhandled PC-relative pseudo-instruction!"); 665} 666 667void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, 668 raw_ostream &O) { 669 O << "#" << MI->getOperand(OpNum).getImm() * 4; 670} 671 672void ARMInstPrinter::printThumbSRImm(const MCInst *MI, unsigned OpNum, 673 raw_ostream &O) { 674 unsigned Imm = MI->getOperand(OpNum).getImm(); 675 O << "#" << (Imm == 0 ? 32 : Imm); 676} 677 678void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum, 679 raw_ostream &O) { 680 // (3 - the number of trailing zeros) is the number of then / else. 681 unsigned Mask = MI->getOperand(OpNum).getImm(); 682 unsigned CondBit0 = Mask >> 4 & 1; 683 unsigned NumTZ = CountTrailingZeros_32(Mask); 684 assert(NumTZ <= 3 && "Invalid IT mask!"); 685 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) { 686 bool T = ((Mask >> Pos) & 1) == CondBit0; 687 if (T) 688 O << 't'; 689 else 690 O << 'e'; 691 } 692} 693 694void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op, 695 raw_ostream &O) { 696 const MCOperand &MO1 = MI->getOperand(Op); 697 const MCOperand &MO2 = MI->getOperand(Op + 1); 698 699 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 700 printOperand(MI, Op, O); 701 return; 702 } 703 704 O << "[" << getRegisterName(MO1.getReg()); 705 if (unsigned RegNum = MO2.getReg()) 706 O << ", " << getRegisterName(RegNum); 707 O << "]"; 708} 709 710void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI, 711 unsigned Op, 712 raw_ostream &O, 713 unsigned Scale) { 714 const MCOperand &MO1 = MI->getOperand(Op); 715 const MCOperand &MO2 = MI->getOperand(Op + 1); 716 717 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 718 printOperand(MI, Op, O); 719 return; 720 } 721 722 O << "[" << getRegisterName(MO1.getReg()); 723 if (unsigned ImmOffs = MO2.getImm()) 724 O << ", #" << ImmOffs * Scale; 725 O << "]"; 726} 727 728void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI, 729 unsigned Op, 730 raw_ostream &O) { 731 printThumbAddrModeImm5SOperand(MI, Op, O, 1); 732} 733 734void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI, 735 unsigned Op, 736 raw_ostream &O) { 737 printThumbAddrModeImm5SOperand(MI, Op, O, 2); 738} 739 740void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI, 741 unsigned Op, 742 raw_ostream &O) { 743 printThumbAddrModeImm5SOperand(MI, Op, O, 4); 744} 745 746void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op, 747 raw_ostream &O) { 748 printThumbAddrModeImm5SOperand(MI, Op, O, 4); 749} 750 751// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 752// register with shift forms. 753// REG 0 0 - e.g. R5 754// REG IMM, SH_OPC - e.g. R5, LSL #3 755void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum, 756 raw_ostream &O) { 757 const MCOperand &MO1 = MI->getOperand(OpNum); 758 const MCOperand &MO2 = MI->getOperand(OpNum+1); 759 760 unsigned Reg = MO1.getReg(); 761 O << getRegisterName(Reg); 762 763 // Print the shift opc. 764 assert(MO2.isImm() && "Not a valid t2_so_reg value!"); 765 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm()); 766 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 767 if (ShOpc != ARM_AM::rrx) 768 O << " #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm())); 769} 770 771void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum, 772 raw_ostream &O) { 773 const MCOperand &MO1 = MI->getOperand(OpNum); 774 const MCOperand &MO2 = MI->getOperand(OpNum+1); 775 776 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 777 printOperand(MI, OpNum, O); 778 return; 779 } 780 781 O << "[" << getRegisterName(MO1.getReg()); 782 783 int32_t OffImm = (int32_t)MO2.getImm(); 784 bool isSub = OffImm < 0; 785 // Special value for #-0. All others are normal. 786 if (OffImm == INT32_MIN) 787 OffImm = 0; 788 if (isSub) 789 O << ", #-" << -OffImm; 790 else if (OffImm > 0) 791 O << ", #" << OffImm; 792 O << "]"; 793} 794 795void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI, 796 unsigned OpNum, 797 raw_ostream &O) { 798 const MCOperand &MO1 = MI->getOperand(OpNum); 799 const MCOperand &MO2 = MI->getOperand(OpNum+1); 800 801 O << "[" << getRegisterName(MO1.getReg()); 802 803 int32_t OffImm = (int32_t)MO2.getImm(); 804 // Don't print +0. 805 if (OffImm < 0) 806 O << ", #-" << -OffImm; 807 else if (OffImm > 0) 808 O << ", #" << OffImm; 809 O << "]"; 810} 811 812void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI, 813 unsigned OpNum, 814 raw_ostream &O) { 815 const MCOperand &MO1 = MI->getOperand(OpNum); 816 const MCOperand &MO2 = MI->getOperand(OpNum+1); 817 818 O << "[" << getRegisterName(MO1.getReg()); 819 820 int32_t OffImm = (int32_t)MO2.getImm() / 4; 821 // Don't print +0. 822 if (OffImm < 0) 823 O << ", #-" << -OffImm * 4; 824 else if (OffImm > 0) 825 O << ", #" << OffImm * 4; 826 O << "]"; 827} 828 829void ARMInstPrinter::printT2AddrModeImm0_1020s4Operand(const MCInst *MI, 830 unsigned OpNum, 831 raw_ostream &O) { 832 const MCOperand &MO1 = MI->getOperand(OpNum); 833 const MCOperand &MO2 = MI->getOperand(OpNum+1); 834 835 O << "[" << getRegisterName(MO1.getReg()); 836 if (MO2.getImm()) 837 O << ", #" << MO2.getImm() * 4; 838 O << "]"; 839} 840 841void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI, 842 unsigned OpNum, 843 raw_ostream &O) { 844 const MCOperand &MO1 = MI->getOperand(OpNum); 845 int32_t OffImm = (int32_t)MO1.getImm(); 846 // Don't print +0. 847 if (OffImm < 0) 848 O << "#-" << -OffImm; 849 else if (OffImm > 0) 850 O << "#" << OffImm; 851} 852 853void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, 854 unsigned OpNum, 855 raw_ostream &O) { 856 const MCOperand &MO1 = MI->getOperand(OpNum); 857 int32_t OffImm = (int32_t)MO1.getImm() / 4; 858 // Don't print +0. 859 if (OffImm != 0) { 860 O << ", "; 861 if (OffImm < 0) 862 O << "#-" << -OffImm * 4; 863 else if (OffImm > 0) 864 O << "#" << OffImm * 4; 865 } 866} 867 868void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI, 869 unsigned OpNum, 870 raw_ostream &O) { 871 const MCOperand &MO1 = MI->getOperand(OpNum); 872 const MCOperand &MO2 = MI->getOperand(OpNum+1); 873 const MCOperand &MO3 = MI->getOperand(OpNum+2); 874 875 O << "[" << getRegisterName(MO1.getReg()); 876 877 assert(MO2.getReg() && "Invalid so_reg load / store address!"); 878 O << ", " << getRegisterName(MO2.getReg()); 879 880 unsigned ShAmt = MO3.getImm(); 881 if (ShAmt) { 882 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); 883 O << ", lsl #" << ShAmt; 884 } 885 O << "]"; 886} 887 888void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, 889 raw_ostream &O) { 890 const MCOperand &MO = MI->getOperand(OpNum); 891 O << '#'; 892 if (MO.isFPImm()) { 893 O << (float)MO.getFPImm(); 894 } else { 895 union { 896 uint32_t I; 897 float F; 898 } FPUnion; 899 900 FPUnion.I = MO.getImm(); 901 O << FPUnion.F; 902 } 903} 904 905void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, 906 raw_ostream &O) { 907 const MCOperand &MO = MI->getOperand(OpNum); 908 O << '#'; 909 if (MO.isFPImm()) { 910 O << MO.getFPImm(); 911 } else { 912 // We expect the binary encoding of a floating point number here. 913 union { 914 uint64_t I; 915 double D; 916 } FPUnion; 917 918 FPUnion.I = MO.getImm(); 919 O << FPUnion.D; 920 } 921} 922 923void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum, 924 raw_ostream &O) { 925 unsigned EncodedImm = MI->getOperand(OpNum).getImm(); 926 unsigned EltBits; 927 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits); 928 O << "#0x" << utohexstr(Val); 929} 930 931void ARMInstPrinter::printImmPlusOneOperand(const MCInst *MI, unsigned OpNum, 932 raw_ostream &O) { 933 unsigned Imm = MI->getOperand(OpNum).getImm(); 934 O << "#" << Imm + 1; 935} 936 937void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum, 938 raw_ostream &O) { 939 unsigned Imm = MI->getOperand(OpNum).getImm(); 940 if (Imm == 0) 941 return; 942 O << ", ror #"; 943 switch (Imm) { 944 default: assert (0 && "illegal ror immediate!"); 945 case 1: O << "8"; break; 946 case 2: O << "16"; break; 947 case 3: O << "24"; break; 948 } 949} 950