summaryrefslogtreecommitdiff
path: root/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp')
-rw-r--r--lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp232
1 files changed, 208 insertions, 24 deletions
diff --git a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
index bdf71b095fda..26e41215afc6 100644
--- a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
+++ b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
@@ -282,6 +282,13 @@ void AArch64InstPrinter::printInst(const MCInst *MI, raw_ostream &O,
return;
}
+ // Instruction TSB is specified as a one operand instruction, but 'csync' is
+ // not encoded, so for printing it is treated as a special case here:
+ if (Opcode == AArch64::TSB) {
+ O << "\ttsb\tcsync";
+ return;
+ }
+
if (!printAliasInstr(MI, STI, O))
printInstruction(MI, STI, O);
@@ -907,20 +914,13 @@ void AArch64InstPrinter::printAddSubImm(const MCInst *MI, unsigned OpNum,
}
}
-void AArch64InstPrinter::printLogicalImm32(const MCInst *MI, unsigned OpNum,
- const MCSubtargetInfo &STI,
- raw_ostream &O) {
- uint64_t Val = MI->getOperand(OpNum).getImm();
- O << "#0x";
- O.write_hex(AArch64_AM::decodeLogicalImmediate(Val, 32));
-}
-
-void AArch64InstPrinter::printLogicalImm64(const MCInst *MI, unsigned OpNum,
- const MCSubtargetInfo &STI,
- raw_ostream &O) {
+template <typename T>
+void AArch64InstPrinter::printLogicalImm(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
uint64_t Val = MI->getOperand(OpNum).getImm();
O << "#0x";
- O.write_hex(AArch64_AM::decodeLogicalImmediate(Val, 64));
+ O.write_hex(AArch64_AM::decodeLogicalImmediate(Val, 8 * sizeof(T)));
}
void AArch64InstPrinter::printShifter(const MCInst *MI, unsigned OpNum,
@@ -976,12 +976,9 @@ void AArch64InstPrinter::printArithExtend(const MCInst *MI, unsigned OpNum,
O << " #" << ShiftVal;
}
-void AArch64InstPrinter::printMemExtend(const MCInst *MI, unsigned OpNum,
- raw_ostream &O, char SrcRegKind,
- unsigned Width) {
- unsigned SignExtend = MI->getOperand(OpNum).getImm();
- unsigned DoShift = MI->getOperand(OpNum + 1).getImm();
-
+static void printMemExtendImpl(bool SignExtend, bool DoShift,
+ unsigned Width, char SrcRegKind,
+ raw_ostream &O) {
// sxtw, sxtx, uxtw or lsl (== uxtx)
bool IsLSL = !SignExtend && SrcRegKind == 'x';
if (IsLSL)
@@ -993,6 +990,32 @@ void AArch64InstPrinter::printMemExtend(const MCInst *MI, unsigned OpNum,
O << " #" << Log2_32(Width / 8);
}
+void AArch64InstPrinter::printMemExtend(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O, char SrcRegKind,
+ unsigned Width) {
+ bool SignExtend = MI->getOperand(OpNum).getImm();
+ bool DoShift = MI->getOperand(OpNum + 1).getImm();
+ printMemExtendImpl(SignExtend, DoShift, Width, SrcRegKind, O);
+}
+
+template <bool SignExtend, int ExtWidth, char SrcRegKind, char Suffix>
+void AArch64InstPrinter::printRegWithShiftExtend(const MCInst *MI,
+ unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ printOperand(MI, OpNum, STI, O);
+ if (Suffix == 's' || Suffix == 'd')
+ O << '.' << Suffix;
+ else
+ assert(Suffix == 0 && "Unsupported suffix size");
+
+ bool DoShift = ExtWidth != 8;
+ if (SignExtend || DoShift || SrcRegKind == 'w') {
+ O << ", ";
+ printMemExtendImpl(SignExtend, DoShift, ExtWidth, SrcRegKind, O);
+ }
+}
+
void AArch64InstPrinter::printCondCode(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O) {
@@ -1045,15 +1068,22 @@ void AArch64InstPrinter::printAMIndexedWB(const MCInst *MI, unsigned OpNum,
O << ']';
}
+template <bool IsSVEPrefetch>
void AArch64InstPrinter::printPrefetchOp(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O) {
unsigned prfop = MI->getOperand(OpNum).getImm();
- auto PRFM = AArch64PRFM::lookupPRFMByEncoding(prfop);
- if (PRFM)
+ if (IsSVEPrefetch) {
+ if (auto PRFM = AArch64SVEPRFM::lookupSVEPRFMByEncoding(prfop)) {
+ O << PRFM->Name;
+ return;
+ }
+ } else if (auto PRFM = AArch64PRFM::lookupPRFMByEncoding(prfop)) {
O << PRFM->Name;
- else
- O << '#' << formatImm(prfop);
+ return;
+ }
+
+ O << '#' << formatImm(prfop);
}
void AArch64InstPrinter::printPSBHintOp(const MCInst *MI, unsigned OpNum,
@@ -1118,6 +1148,41 @@ static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride = 1) {
case AArch64::Q31:
Reg = AArch64::Q0;
break;
+ case AArch64::Z0: Reg = AArch64::Z1; break;
+ case AArch64::Z1: Reg = AArch64::Z2; break;
+ case AArch64::Z2: Reg = AArch64::Z3; break;
+ case AArch64::Z3: Reg = AArch64::Z4; break;
+ case AArch64::Z4: Reg = AArch64::Z5; break;
+ case AArch64::Z5: Reg = AArch64::Z6; break;
+ case AArch64::Z6: Reg = AArch64::Z7; break;
+ case AArch64::Z7: Reg = AArch64::Z8; break;
+ case AArch64::Z8: Reg = AArch64::Z9; break;
+ case AArch64::Z9: Reg = AArch64::Z10; break;
+ case AArch64::Z10: Reg = AArch64::Z11; break;
+ case AArch64::Z11: Reg = AArch64::Z12; break;
+ case AArch64::Z12: Reg = AArch64::Z13; break;
+ case AArch64::Z13: Reg = AArch64::Z14; break;
+ case AArch64::Z14: Reg = AArch64::Z15; break;
+ case AArch64::Z15: Reg = AArch64::Z16; break;
+ case AArch64::Z16: Reg = AArch64::Z17; break;
+ case AArch64::Z17: Reg = AArch64::Z18; break;
+ case AArch64::Z18: Reg = AArch64::Z19; break;
+ case AArch64::Z19: Reg = AArch64::Z20; break;
+ case AArch64::Z20: Reg = AArch64::Z21; break;
+ case AArch64::Z21: Reg = AArch64::Z22; break;
+ case AArch64::Z22: Reg = AArch64::Z23; break;
+ case AArch64::Z23: Reg = AArch64::Z24; break;
+ case AArch64::Z24: Reg = AArch64::Z25; break;
+ case AArch64::Z25: Reg = AArch64::Z26; break;
+ case AArch64::Z26: Reg = AArch64::Z27; break;
+ case AArch64::Z27: Reg = AArch64::Z28; break;
+ case AArch64::Z28: Reg = AArch64::Z29; break;
+ case AArch64::Z29: Reg = AArch64::Z30; break;
+ case AArch64::Z30: Reg = AArch64::Z31; break;
+ // Vector lists can wrap around.
+ case AArch64::Z31:
+ Reg = AArch64::Z0;
+ break;
}
}
return Reg;
@@ -1152,12 +1217,15 @@ void AArch64InstPrinter::printVectorList(const MCInst *MI, unsigned OpNum,
// list).
unsigned NumRegs = 1;
if (MRI.getRegClass(AArch64::DDRegClassID).contains(Reg) ||
+ MRI.getRegClass(AArch64::ZPR2RegClassID).contains(Reg) ||
MRI.getRegClass(AArch64::QQRegClassID).contains(Reg))
NumRegs = 2;
else if (MRI.getRegClass(AArch64::DDDRegClassID).contains(Reg) ||
+ MRI.getRegClass(AArch64::ZPR3RegClassID).contains(Reg) ||
MRI.getRegClass(AArch64::QQQRegClassID).contains(Reg))
NumRegs = 3;
else if (MRI.getRegClass(AArch64::DDDDRegClassID).contains(Reg) ||
+ MRI.getRegClass(AArch64::ZPR4RegClassID).contains(Reg) ||
MRI.getRegClass(AArch64::QQQQRegClassID).contains(Reg))
NumRegs = 4;
@@ -1166,6 +1234,8 @@ void AArch64InstPrinter::printVectorList(const MCInst *MI, unsigned OpNum,
Reg = FirstReg;
else if (unsigned FirstReg = MRI.getSubReg(Reg, AArch64::qsub0))
Reg = FirstReg;
+ else if (unsigned FirstReg = MRI.getSubReg(Reg, AArch64::zsub0))
+ Reg = FirstReg;
// If it's a D-reg, we need to promote it to the equivalent Q-reg before
// printing (otherwise getRegisterName fails).
@@ -1176,7 +1246,11 @@ void AArch64InstPrinter::printVectorList(const MCInst *MI, unsigned OpNum,
}
for (unsigned i = 0; i < NumRegs; ++i, Reg = getNextVectorRegister(Reg)) {
- O << getRegisterName(Reg, AArch64::vreg) << LayoutSuffix;
+ if (MRI.getRegClass(AArch64::ZPRRegClassID).contains(Reg))
+ O << getRegisterName(Reg) << LayoutSuffix;
+ else
+ O << getRegisterName(Reg, AArch64::vreg) << LayoutSuffix;
+
if (i + 1 != NumRegs)
O << ", ";
}
@@ -1262,6 +1336,9 @@ void AArch64InstPrinter::printBarrierOption(const MCInst *MI, unsigned OpNo,
if (Opcode == AArch64::ISB) {
auto ISB = AArch64ISB::lookupISBByEncoding(Val);
Name = ISB ? ISB->Name : "";
+ } else if (Opcode == AArch64::TSB) {
+ auto TSB = AArch64TSB::lookupTSBByEncoding(Val);
+ Name = TSB ? TSB->Name : "";
} else {
auto DB = AArch64DB::lookupDBByEncoding(Val);
Name = DB ? DB->Name : "";
@@ -1340,6 +1417,16 @@ void AArch64InstPrinter::printComplexRotationOp(const MCInst *MI, unsigned OpNo,
O << "#" << (Val * Angle) + Remainder;
}
+void AArch64InstPrinter::printSVEPattern(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ unsigned Val = MI->getOperand(OpNum).getImm();
+ if (auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByEncoding(Val))
+ O << Pat->Name;
+ else
+ O << '#' << formatImm(Val);
+}
+
template <char suffix>
void AArch64InstPrinter::printSVERegOp(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
@@ -1359,4 +1446,101 @@ void AArch64InstPrinter::printSVERegOp(const MCInst *MI, unsigned OpNum,
O << getRegisterName(Reg);
if (suffix != 0)
O << '.' << suffix;
-} \ No newline at end of file
+}
+
+template <typename T>
+void AArch64InstPrinter::printImmSVE(T Value, raw_ostream &O) {
+ typename std::make_unsigned<T>::type HexValue = Value;
+
+ if (getPrintImmHex())
+ O << '#' << formatHex((uint64_t)HexValue);
+ else
+ O << '#' << formatDec(Value);
+
+ if (CommentStream) {
+ // Do the opposite to that used for instruction operands.
+ if (getPrintImmHex())
+ *CommentStream << '=' << formatDec(HexValue) << '\n';
+ else
+ *CommentStream << '=' << formatHex((uint64_t)Value) << '\n';
+ }
+}
+
+template <typename T>
+void AArch64InstPrinter::printImm8OptLsl(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ unsigned UnscaledVal = MI->getOperand(OpNum).getImm();
+ unsigned Shift = MI->getOperand(OpNum + 1).getImm();
+ assert(AArch64_AM::getShiftType(Shift) == AArch64_AM::LSL &&
+ "Unexepected shift type!");
+
+ // #0 lsl #8 is never pretty printed
+ if ((UnscaledVal == 0) && (AArch64_AM::getShiftValue(Shift) != 0)) {
+ O << '#' << formatImm(UnscaledVal);
+ printShifter(MI, OpNum + 1, STI, O);
+ return;
+ }
+
+ T Val;
+ if (std::is_signed<T>())
+ Val = (int8_t)UnscaledVal * (1 << AArch64_AM::getShiftValue(Shift));
+ else
+ Val = (uint8_t)UnscaledVal * (1 << AArch64_AM::getShiftValue(Shift));
+
+ printImmSVE(Val, O);
+}
+
+template <typename T>
+void AArch64InstPrinter::printSVELogicalImm(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ typedef typename std::make_signed<T>::type SignedT;
+ typedef typename std::make_unsigned<T>::type UnsignedT;
+
+ uint64_t Val = MI->getOperand(OpNum).getImm();
+ UnsignedT PrintVal = AArch64_AM::decodeLogicalImmediate(Val, 64);
+
+ // Prefer the default format for 16bit values, hex otherwise.
+ if ((int16_t)PrintVal == (SignedT)PrintVal)
+ printImmSVE((T)PrintVal, O);
+ else if ((uint16_t)PrintVal == PrintVal)
+ printImmSVE(PrintVal, O);
+ else
+ O << '#' << formatHex((uint64_t)PrintVal);
+}
+
+template <int Width>
+void AArch64InstPrinter::printZPRasFPR(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ unsigned Base;
+ switch (Width) {
+ case 8: Base = AArch64::B0; break;
+ case 16: Base = AArch64::H0; break;
+ case 32: Base = AArch64::S0; break;
+ case 64: Base = AArch64::D0; break;
+ case 128: Base = AArch64::Q0; break;
+ default:
+ llvm_unreachable("Unsupported width");
+ }
+ unsigned Reg = MI->getOperand(OpNum).getReg();
+ O << getRegisterName(Reg - AArch64::Z0 + Base);
+}
+
+template <unsigned ImmIs0, unsigned ImmIs1>
+void AArch64InstPrinter::printExactFPImm(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ auto *Imm0Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmIs0);
+ auto *Imm1Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmIs1);
+ unsigned Val = MI->getOperand(OpNum).getImm();
+ O << "#" << (Val ? Imm1Desc->Repr : Imm0Desc->Repr);
+}
+
+void AArch64InstPrinter::printGPR64as32(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ unsigned Reg = MI->getOperand(OpNum).getReg();
+ O << getRegisterName(getWRegFromXReg(Reg));
+}