14 #define DEBUG_TYPE "asm-printer"
26 #include "ARMGenAsmWriter.inc"
33 assert((imm & ~0x1f) == 0 &&
"Invalid shift encoding");
42 unsigned ShImm,
bool UseMarkup) {
47 assert (!(ShOpc ==
ARM_AM::ror && !ShImm) &&
"Cannot have ror #0");
86 case 0: O <<
"\tnop";
break;
87 case 1: O <<
"\tyield";
break;
88 case 2: O <<
"\twfe";
break;
89 case 3: O <<
"\twfi";
break;
90 case 4: O <<
"\tsev";
break;
103 if (Opcode == ARM::t2HINT)
162 case ARM::t2STMDB_UPD:
167 if (Opcode == ARM::t2STMDB_UPD)
176 case ARM::STR_PRE_IMM:
191 case ARM::t2LDMIA_UPD:
196 if (Opcode == ARM::t2LDMIA_UPD)
205 case ARM::LDR_POST_IMM:
219 case ARM::VSTMSDB_UPD:
220 case ARM::VSTMDDB_UPD:
222 O <<
'\t' <<
"vpush";
232 case ARM::VLDMSIA_UPD:
233 case ARM::VLDMDIA_UPD:
245 bool Writeback =
true;
257 if (Writeback) O <<
"!";
270 case ARM::LDREXD:
case ARM::STREXD:
271 case ARM::LDAEXD:
case ARM::STLEXD:
273 bool isStore = Opcode == ARM::STREXD || Opcode == ARM::STLEXD;
304 }
else if (Op.
isImm()) {
309 assert(Op.
isExpr() &&
"unknown operand kind in printOperand");
314 if (BranchTarget && BranchTarget->EvaluateAsAbsolute(Address)) {
333 O <<
markup(
"<mem:") <<
"[pc, ";
335 int32_t OffImm = (int32_t)MO1.
getImm();
336 bool isSub = OffImm < 0;
339 if (OffImm == INT32_MIN)
400 O <<
markup(
"<mem:") <<
"[";
429 O <<
markup(
"<mem:") <<
"[";
440 O <<
markup(
"<mem:") <<
"[";
460 "Should be pre or offset index op");
498 O <<
markup(
"<mem:") <<
"[";
500 O <<
"], " <<
markup(
">");
518 bool AlwaysPrintImm0) {
523 O <<
markup(
"<mem:") <<
'[';
537 if (AlwaysPrintImm0 || ImmOffs || (op ==
ARM_AM::sub)) {
548 template <
bool AlwaysPr
intImm0>
589 unsigned Imm = MO.
getImm();
591 <<
'#' << ((Imm & 256) ?
"" :
"-") << (Imm & 0xff)
600 O << (MO2.
getImm() ?
"" :
"-");
608 unsigned Imm = MO.
getImm();
610 <<
'#' << ((Imm & 256) ?
"" :
"-") << ((Imm & 0xff) << 2)
622 template <
bool AlwaysPr
intImm0>
633 O <<
markup(
"<mem:") <<
"[";
638 if (AlwaysPrintImm0 || ImmOffs || Op ==
ARM_AM::sub) {
654 O <<
markup(
"<mem:") <<
"[";
657 O <<
":" << (MO2.
getImm() << 3);
665 O <<
markup(
"<mem:") <<
"[";
686 uint32_t v = ~MO.
getImm();
689 assert(MO.
isImm() &&
"Not a valid bf_inv_mask_imm value!");
710 bool isASR = (ShiftOp & (1 << 5)) != 0;
711 unsigned Amt = ShiftOp & 0x1f;
715 <<
"#" << (Amt == 0 ? 32 : Amt)
731 assert(Imm > 0 && Imm < 32 &&
"Invalid PKH shift immediate value!");
732 O <<
", lsl " <<
markup(
"<imm:") <<
"#" << Imm <<
markup(
">");
741 assert(Imm > 0 && Imm <= 32 &&
"Invalid PKH shift immediate value!");
742 O <<
", asr " <<
markup(
"<imm:") <<
"#" << Imm <<
markup(
">");
749 if (i != OpNum) O <<
", ";
783 for (
int i=2; i >= 0; --i)
784 if (IFlags & (1 << i))
794 unsigned SpecRegRBit = Op.
getImm() >> 4;
795 unsigned Mask = Op.
getImm() & 0xf;
798 unsigned SYSm = Op.
getImm();
802 if (Opcode == ARM::t2MRS_M)
807 case 0x800: O <<
"apsr";
return;
808 case 0x400: O <<
"apsr_g";
return;
809 case 0xc00: O <<
"apsr_nzcvqg";
return;
811 case 0x801: O <<
"iapsr";
return;
812 case 0x401: O <<
"iapsr_g";
return;
813 case 0xc01: O <<
"iapsr_nzcvqg";
return;
815 case 0x802: O <<
"eapsr";
return;
816 case 0x402: O <<
"eapsr_g";
return;
817 case 0xc02: O <<
"eapsr_nzcvqg";
return;
819 case 0x803: O <<
"xpsr";
return;
820 case 0x403: O <<
"xpsr_g";
return;
821 case 0xc03: O <<
"xpsr_nzcvqg";
return;
823 case 0x805: O <<
"ipsr";
return;
825 case 0x806: O <<
"epsr";
return;
827 case 0x807: O <<
"iepsr";
return;
829 case 0x808: O <<
"msp";
return;
831 case 0x809: O <<
"psp";
return;
833 case 0x810: O <<
"primask";
return;
835 case 0x811: O <<
"basepri";
return;
837 case 0x812: O <<
"basepri_max";
return;
839 case 0x813: O <<
"faultmask";
return;
841 case 0x814: O <<
"control";
return;
847 if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
851 case 4: O <<
"g";
return;
852 case 8: O <<
"nzcvq";
return;
853 case 12: O <<
"nzcvqg";
return;
864 if (Mask & 8) O <<
'f';
865 if (Mask & 4) O <<
's';
866 if (Mask & 2) O <<
'x';
867 if (Mask & 1) O <<
'c';
875 if ((
unsigned)CC == 15)
892 "Expect ARM CPSR register!");
922 template<
unsigned scale>
932 int32_t OffImm = (int32_t)MO.
getImm() << scale;
935 if (OffImm == INT32_MIN)
938 O <<
"#-" << -OffImm;
955 <<
"#" <<
formatImm((Imm == 0 ? 32 : Imm))
964 unsigned CondBit0 = Firstcond & 1;
966 assert(NumTZ <= 3 &&
"Invalid IT mask!");
967 for (
unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
968 bool T = ((Mask >> Pos) & 1) == CondBit0;
986 O <<
markup(
"<mem:") <<
"[";
988 if (
unsigned RegNum = MO2.
getReg()) {
1007 O <<
markup(
"<mem:") <<
"[";
1009 if (
unsigned ImmOffs = MO2.
getImm()) {
1054 assert(MO2.
isImm() &&
"Not a valid t2_so_reg value!");
1059 template <
bool AlwaysPr
intImm0>
1070 O <<
markup(
"<mem:") <<
"[";
1073 int32_t OffImm = (int32_t)MO2.
getImm();
1074 bool isSub = OffImm < 0;
1076 if (OffImm == INT32_MIN)
1084 else if (AlwaysPrintImm0 || OffImm > 0) {
1093 template<
bool AlwaysPr
intImm0>
1100 O <<
markup(
"<mem:") <<
"[";
1103 int32_t OffImm = (int32_t)MO2.
getImm();
1104 bool isSub = OffImm < 0;
1106 if (OffImm == INT32_MIN)
1113 }
else if (AlwaysPrintImm0 || OffImm > 0) {
1122 template<
bool AlwaysPr
intImm0>
1134 O <<
markup(
"<mem:") <<
"[";
1137 int32_t OffImm = (int32_t)MO2.
getImm();
1138 bool isSub = OffImm < 0;
1140 assert(((OffImm & 0x3) == 0) &&
"Not a valid immediate!");
1143 if (OffImm == INT32_MIN)
1150 }
else if (AlwaysPrintImm0 || OffImm > 0) {
1165 O <<
markup(
"<mem:") <<
"[";
1180 int32_t OffImm = (int32_t)MO1.
getImm();
1181 O <<
", " <<
markup(
"<imm:");
1182 if (OffImm == INT32_MIN)
1184 else if (OffImm < 0)
1185 O <<
"#-" << -OffImm;
1195 int32_t OffImm = (int32_t)MO1.
getImm();
1197 assert(((OffImm & 0x3) == 0) &&
"Not a valid immediate!");
1199 O <<
", " <<
markup(
"<imm:");
1200 if (OffImm == INT32_MIN)
1202 else if (OffImm < 0)
1203 O <<
"#-" << -OffImm;
1216 O <<
markup(
"<mem:") <<
"[";
1219 assert(MO2.
getReg() &&
"Invalid so_reg load / store address!");
1223 unsigned ShAmt = MO3.
getImm();
1225 assert(ShAmt <= 3 &&
"Not a valid Thumb2 addressing mode!");
1270 default: assert (0 &&
"illegal ror immediate!");
1271 case 1: O <<
"8";
break;
1272 case 2: O <<
"16";
break;
1273 case 3: O <<
"24";
break;
void printAM3PostIndexOp(const MCInst *MI, unsigned Op, raw_ostream &O)
void printCPSIMod(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printThumbAddrModeImm5SOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O, unsigned Scale)
void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printThumbAddrModeImm5S2Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printRegisterList(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printVectorListTwo(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static unsigned char getAM3Offset(unsigned AM3Opc)
void printPKHASRShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O)
ARMInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI)
void printCImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static MCOperand CreateReg(unsigned Reg)
void printVectorListFourSpaced(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printAddrMode2OffsetOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
void printMandatoryPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printAddrMode7Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printCPSIFlag(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static const char * getShiftOpcStr(ShiftOpc Op)
void printVectorListFour(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printT2AddrModeImm0_1020s4Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printSORegRegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printVectorListTwoSpaced(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static unsigned translateShiftImm(unsigned imm)
format_object1< int64_t > formatImm(const int64_t Value) const
Utility function to print immediates in decimal or hex.
static unsigned getAM3IdxMode(unsigned AM3Opc)
void printAddrMode2Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
#define llvm_unreachable(msg)
void printFBits16(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printLdStmModeOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static AMSubMode getAM4SubMode(unsigned Mode)
void printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O)
enable_if_c< std::numeric_limits< T >::is_integer &&!std::numeric_limits< T >::is_signed, std::size_t >::type countLeadingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the most significant bit to the least stopping at the first 1...
void printVectorListThreeSpaced(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printVectorListThree(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printAddrMode6Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
unsigned getReg() const
getReg - Returns the register number.
void printT2AddrModeImm8Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
enable_if_c< std::numeric_limits< T >::is_integer &&!std::numeric_limits< T >::is_signed, std::size_t >::type countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1...
raw_ostream & write_hex(unsigned long long N)
write_hex - Output N in hexadecimal, without any prefix or padding.
void printThumbAddrModeImm5S4Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printPostIdxRegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static const char * getRegisterName(unsigned RegNo)
void printThumbLdrLabelOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
MCRegisterClass - Base class of TargetRegisterClass.
void printPostIdxImm8Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printMemBOption(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static unsigned getAM2IdxMode(unsigned AM2Opc)
void printGPRPairOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printCoprocOptionImm(const MCInst *MI, unsigned OpNum, raw_ostream &O)
const MCExpr * getExpr() const
void printPostIdxImm8s4Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printFPImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static const char * InstSyncBOptToString(unsigned val)
void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
StringRef markup(StringRef s) const
Utility functions to make adding mark ups simpler.
const MCRegisterClass & getRegClass(unsigned i) const
Returns the register class associated with the enumeration value. See class MCOperandInfo.
static unsigned char getAM5Offset(unsigned AM5Opc)
unsigned getSubReg(unsigned Reg, unsigned Idx) const
Returns the physical register number of sub-register "Index" for physical register RegNo...
void printThumbITMask(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printVectorListFourAllLanes(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printInstruction(const MCInst *MI, raw_ostream &O)
virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot)
void printNEONModImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printVectorIndex(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printPCLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printT2SOOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printSBitModifierOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static const char * getAddrOpcStr(AddrOpc Op)
void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, const MCRegisterClass *RC) const
Return a super-register of the specified register Reg so its sub-register of index SubIdx is Reg...
static const char * ARMCondCodeToString(ARMCC::CondCodes CC)
static const char * IModToString(unsigned val)
static AddrOpc getAM2Op(unsigned AM2Opc)
void printMSRMaskOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printAddrMode6OffsetOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
uint64_t getFeatureBits() const
void printSORegImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void setOpcode(unsigned Op)
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void printAddrModeTBB(const MCInst *MI, unsigned OpNum, raw_ostream &O)
bool contains(unsigned Reg) const
static unsigned getAM2Offset(unsigned AM2Opc)
void printVectorListOne(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printInstSyncBOption(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printAddrMode3OffsetOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printShiftImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printRotImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printVectorListTwoSpacedAllLanes(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printFBits32(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printAddrModeTBH(const MCInst *MI, unsigned OpNum, raw_ostream &O)
unsigned getOpcode() const
static void printRegImmShift(raw_ostream &O, ARM_AM::ShiftOpc ShOpc, unsigned ShImm, bool UseMarkup)
Prints the shift value with an immediate value.
static const char * MemBOptToString(unsigned val, bool HasV8)
void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static AddrOpc getAM3Op(unsigned AM3Opc)
void printAddrMode3Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printSetendOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static const char * IFlagsToString(unsigned val)
void printThumbSRImm(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static const char * getAMSubModeStr(AMSubMode Mode)
void printVectorListThreeSpacedAllLanes(const MCInst *MI, unsigned OpNum, raw_ostream &O)
bool UseMarkup
True if we are printing marked up assembly.
void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printAddrMode5Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printThumbAddrModeImm5S1Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
unsigned getNumOperands() const
void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printVectorListOneAllLanes(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printPImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static AddrOpc getAM5Op(unsigned AM5Opc)
void printNoHashImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printVectorListThreeAllLanes(const MCInst *MI, unsigned OpNum, raw_ostream &O)
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const
printRegName - Print the assembler register name.
void printImmPlusOneOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
static ShiftOpc getAM2ShiftOpc(unsigned AM2Opc)
static unsigned getSORegOffset(unsigned Op)
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
void setAvailableFeatures(uint64_t Value)
void printVectorListTwoAllLanes(const MCInst *MI, unsigned OpNum, raw_ostream &O)
void printVectorListFourSpacedAllLanes(const MCInst *MI, unsigned OpNum, raw_ostream &O)
uint64_t getAvailableFeatures() const
void addOperand(const MCOperand &Op)
void printAdrLabelOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
const MCRegisterInfo & MRI
void printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op, raw_ostream &O, bool AlwaysPrintImm0)
static float getFPImmFloat(unsigned Imm)
const MCOperand & getOperand(unsigned i) const
static ShiftOpc getSORegShOp(unsigned Op)
const MCRegisterInfo & MRI
static uint64_t decodeNEONModImm(unsigned ModImm, unsigned &EltBits)