-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[LLVM][AArch64]Add assembly/disassembly for compare-and-branch instr… #113461
Conversation
…ctions (llvm#112726) This patch adds the assembly/disassembly for the following instructions: CBB<cc>, CBH<cc>, CB<cc>(immediate), CB<cc>(register) CBBLE, CBBLO, CBBLS, CBBLT CBHLE, CBHLO, CBHLS, CBHLT CBGE, CBHS, CBLE, CBLS (immediate) CBLE, CBLO, CBLS, CBLT(register) According to [1] [1]https://developer.arm.com/documentation/ddi0602 Co-authored-by: Momchil Velikov momchil.velikov@arm.com Co-authored-by: Spencer Abson spencer.abson@arm.com This patch was reverted(git commit 83c6e2f) and is being submitted again with the fix for buildbot failure in: https://lab.llvm.org/buildbot/#/builders/25/builds/3493
@llvm/pr-subscribers-backend-aarch64 @llvm/pr-subscribers-mc Author: None (CarolineConcatto) Changes…uctions (#112726) This patch adds the assembly/disassembly for the following instructions: CBB<cc>, CBH<cc>, According to [1] [1]https://developer.arm.com/documentation/ddi0602 Co-authored-by: Momchil Velikov momchil.velikov@arm.com This patch was reverted(git commit 83c6e2f) and is being submitted again with the fix for buildbot failure in: Patch is 64.57 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/113461.diff 16 Files Affected:
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index b690a41621f10d..9dd417314fbb86 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -388,6 +388,46 @@ def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
let ParserMatchClass = AsmImmRange<0, 65535>;
}
+def uimm6_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
+ let ParserMatchClass = UImm6Operand;
+}
+
+def uimm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 64; }]> {
+ let ParserMatchClass = UImm6Operand;
+}
+
+def UImm6Plus1Operand : AsmOperandClass {
+ let Name = "UImm6P1";
+ let DiagnosticType = "InvalidImm1_64";
+ let RenderMethod = "addImmOperands";
+ let ParserMethod = "tryParseAdjImm0_63<-1>";
+ let PredicateMethod = "isImmInRange<0,63>";
+}
+
+def UImm6Minus1Operand : AsmOperandClass {
+ let Name = "UImm6M1";
+ let DiagnosticType = "InvalidImmM1_62";
+ let RenderMethod = "addImmOperands";
+ let ParserMethod = "tryParseAdjImm0_63<1>";
+ let PredicateMethod = "isImmInRange<0,63>";
+}
+
+def uimm6p1_32b : Operand<i32> {
+ let ParserMatchClass = UImm6Plus1Operand;
+}
+
+def uimm6p1_64b : Operand<i64> {
+ let ParserMatchClass = UImm6Plus1Operand;
+}
+
+def uimm6m1_32b : Operand<i32> {
+ let ParserMatchClass = UImm6Minus1Operand;
+}
+
+def uimm6m1_64b : Operand<i64> {
+ let ParserMatchClass = UImm6Minus1Operand;
+}
+
def SImm9Operand : SImmOperand<9>;
def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
let ParserMatchClass = SImm9Operand;
@@ -657,6 +697,7 @@ class PCRelLabel<int N> : BranchTarget<N> {
def BranchTarget14Operand : BranchTarget<14>;
def BranchTarget26Operand : BranchTarget<26>;
def PCRelLabel19Operand : PCRelLabel<19>;
+def PCRelLabel9Operand : PCRelLabel<9>;
def MovWSymbolG3AsmOperand : AsmOperandClass {
let Name = "MovWSymbolG3";
@@ -2158,6 +2199,17 @@ def am_brcond : Operand<OtherVT> {
let OperandType = "OPERAND_PCREL";
}
+// Conditional branch target. 9-bit immediate. The low two bits of the target
+// offset are implied zero and so are not part of the immediate.
+def am_brcmpcond : Operand<OtherVT> {
+ let EncoderMethod = "getCondCompBranchTargetOpValue";
+ let DecoderMethod = "DecodePCRelLabel9";
+ let PrintMethod = "printAlignedLabel";
+ let ParserMatchClass = PCRelLabel9Operand;
+ let OperandType = "OPERAND_PCREL";
+}
+
+
class BranchCond<bit bit4, string mnemonic>
: I<(outs), (ins ccode:$cond, am_brcond:$target),
mnemonic, ".$cond\t$target", "",
@@ -12911,6 +12963,89 @@ class MulAccumCPA<bit isSub, string asm>
let Inst{31} = 0b1;
}
+
+//----------------------------------------------------------------------------
+// 2024 Armv9.6 Extensions
+//----------------------------------------------------------------------------
+
+//---
+// Compare-and-branch instructions.
+//---
+
+class BaseCmpBranchRegister<RegisterClass regtype, bit sf, bits<3> cc,
+ bits<2>sz, string asm>
+ : I<(outs), (ins regtype:$Rt, regtype:$Rm, am_brcmpcond:$target),
+ asm, "\t$Rt, $Rm, $target", "",
+ []>,
+ Sched<[WriteBr]> {
+ let isBranch = 1;
+ let isTerminator = 1;
+
+ bits<5> Rm;
+ bits<5> Rt;
+ bits<9> target;
+ let Inst{31} = sf;
+ let Inst{30-24} = 0b1110100;
+ let Inst{23-21} = cc;
+ let Inst{20-16} = Rm;
+ let Inst{15-14} = sz;
+ let Inst{13-5} = target;
+ let Inst{4-0} = Rt;
+}
+
+multiclass CmpBranchRegister<bits<3> cc, string asm> {
+ def Wrr : BaseCmpBranchRegister<GPR32, 0b0, cc, 0b00, asm>;
+ def Xrr : BaseCmpBranchRegister<GPR64, 0b1, cc, 0b00, asm>;
+}
+
+class BaseCmpBranchImmediate<RegisterClass regtype, bit sf, bits<3> cc,
+ Operand imm_ty, string asm>
+ : I<(outs), (ins regtype:$Rt, imm_ty:$imm, am_brcmpcond:$target),
+ asm, "\t$Rt, $imm, $target", "",
+ []>,
+ Sched<[WriteBr]> {
+ let isBranch = 1;
+ let isTerminator = 1;
+
+ bits<5> Rt;
+ bits<6> imm;
+ bits<9> target;
+ let Inst{31} = sf;
+ let Inst{30-24} = 0b1110101;
+ let Inst{23-21} = cc;
+ let Inst{20-15} = imm;
+ let Inst{14} = 0b0;
+ let Inst{13-5} = target;
+ let Inst{4-0} = Rt;
+}
+
+multiclass CmpBranchImmediate<bits<3> cc, string imm_ty, string asm> {
+ def Wri : BaseCmpBranchImmediate<GPR32, 0b0, cc, !cast<Operand>(imm_ty # "_32b"), asm>;
+ def Xri : BaseCmpBranchImmediate<GPR64, 0b1, cc, !cast<Operand>(imm_ty # "_64b"), asm>;
+}
+
+multiclass CmpBranchImmediateAlias<string mnemonic, string insn, string imm_ty> {
+ def : InstAlias<mnemonic # "\t$Rt, $imm, $target",
+ (!cast<Instruction>(insn # "Wri") GPR32:$Rt,
+ !cast<Operand>(imm_ty # "_32b"):$imm,
+ am_brcmpcond:$target), 0>;
+ def : InstAlias<mnemonic # "\t$Rt, $imm, $target",
+ (!cast<Instruction>(insn # "Xri") GPR64:$Rt,
+ !cast<Operand>(imm_ty # "_64b"):$imm,
+ am_brcmpcond:$target), 0>;
+}
+
+multiclass CmpBranchWRegisterAlias<string mnemonic, string insn> {
+ def : InstAlias<mnemonic # "\t$Rt, $Rm, $target",
+ (!cast<Instruction>(insn # "Wrr") GPR32:$Rm, GPR32:$Rt, am_brcmpcond:$target), 0>;
+}
+
+multiclass CmpBranchRegisterAlias<string mnemonic, string insn> {
+ defm : CmpBranchWRegisterAlias<mnemonic, insn>;
+
+ def : InstAlias<mnemonic # "\t$Rt, $Rm, $target",
+ (!cast<Instruction>(insn # "Xrr") GPR64:$Rm, GPR64:$Rt, am_brcmpcond:$target), 0>;
+}
//----------------------------------------------------------------------------
// Allow the size specifier tokens to be upper case, not just lower.
def : TokenAlias<".4B", ".4b">; // Add dot product
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 63f239020179b2..99e3ed31643b6e 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -10423,6 +10423,57 @@ defm : PromoteBinaryv8f16Tov4f32<any_fdiv, FDIVv4f32>;
defm : PromoteBinaryv8f16Tov4f32<any_fmul, FMULv4f32>;
defm : PromoteBinaryv8f16Tov4f32<any_fsub, FSUBv4f32>;
+let Predicates = [HasCMPBR] in {
+ defm CBGT : CmpBranchRegister<0b000, "cbgt">;
+ defm CBGE : CmpBranchRegister<0b001, "cbge">;
+ defm CBHI : CmpBranchRegister<0b010, "cbhi">;
+ defm CBHS : CmpBranchRegister<0b011, "cbhs">;
+ defm CBEQ : CmpBranchRegister<0b110, "cbeq">;
+ defm CBNE : CmpBranchRegister<0b111, "cbne">;
+
+ def CBHGTWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b000, 0b11, "cbhgt">;
+ def CBHGEWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b001, 0b11, "cbhge">;
+ def CBHHIWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b010, 0b11, "cbhhi">;
+ def CBHHSWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b011, 0b11, "cbhhs">;
+ def CBHEQWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b110, 0b11, "cbheq">;
+ def CBHNEWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b111, 0b11, "cbhne">;
+
+ def CBBGTWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b000, 0b10, "cbbgt">;
+ def CBBGEWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b001, 0b10, "cbbge">;
+ def CBBHIWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b010, 0b10, "cbbhi">;
+ def CBBHSWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b011, 0b10, "cbbhs">;
+ def CBBEQWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b110, 0b10, "cbbeq">;
+ def CBBNEWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b111, 0b10, "cbbne">;
+
+ defm CBGT : CmpBranchImmediate<0b000, "uimm6", "cbgt">;
+ defm CBLT : CmpBranchImmediate<0b001, "uimm6", "cblt">;
+ defm CBHI : CmpBranchImmediate<0b010, "uimm6", "cbhi">;
+ defm CBLO : CmpBranchImmediate<0b011, "uimm6", "cblo">;
+ defm CBEQ : CmpBranchImmediate<0b110, "uimm6", "cbeq">;
+ defm CBNE : CmpBranchImmediate<0b111, "uimm6", "cbne">;
+
+ defm : CmpBranchImmediateAlias<"cbge", "CBGT", "uimm6p1">;
+ defm : CmpBranchImmediateAlias<"cbhs", "CBHI", "uimm6p1">;
+ defm : CmpBranchImmediateAlias<"cble", "CBLT", "uimm6m1">;
+ defm : CmpBranchImmediateAlias<"cbls", "CBLO", "uimm6m1">;
+
+ defm : CmpBranchRegisterAlias<"cble", "CBGE">;
+ defm : CmpBranchRegisterAlias<"cblo", "CBHI">;
+ defm : CmpBranchRegisterAlias<"cbls", "CBHS">;
+ defm : CmpBranchRegisterAlias<"cblt", "CBGT">;
+
+ defm : CmpBranchWRegisterAlias<"cbble", "CBBGE">;
+ defm : CmpBranchWRegisterAlias<"cbblo", "CBBHI">;
+ defm : CmpBranchWRegisterAlias<"cbbls", "CBBHS">;
+ defm : CmpBranchWRegisterAlias<"cbblt", "CBBGT">;
+
+ defm : CmpBranchWRegisterAlias<"cbhle", "CBHGE">;
+ defm : CmpBranchWRegisterAlias<"cbhlo", "CBHHI">;
+ defm : CmpBranchWRegisterAlias<"cbhls", "CBHHS">;
+ defm : CmpBranchWRegisterAlias<"cbhlt", "CBHGT">;
+} // HasCMPBR
+
+
//===-----------------------------------------------------===//
// Atomic floating-point in-memory instructions (FEAT_LSFE)
//===-----------------------------------------------------===//
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 9fb3501286e531..a46c7b3aef6e48 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -2092,6 +2092,20 @@ class AArch64Operand : public MCParsedAsmOperand {
Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
}
+ void addPCRelLabel9Operands(MCInst &Inst, unsigned N) const {
+ // Branch operands don't encode the low bits, so shift them off
+ // here. If it's a label, however, just put it on directly as there's
+ // not enough information now to do anything.
+ assert(N == 1 && "Invalid number of operands!");
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
+ if (!MCE) {
+ addExpr(Inst, getImm());
+ return;
+ }
+ assert(MCE && "Invalid constant immediate operand!");
+ Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
+ }
+
void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
// Branch operands don't encode the low bits, so shift them off
// here. If it's a label, however, just put it on directly as there's
@@ -5987,6 +6001,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
return Error(Loc, "immediate must be an integer in range [1, 32].");
case Match_InvalidImm1_64:
return Error(Loc, "immediate must be an integer in range [1, 64].");
+ case Match_InvalidImmM1_62:
+ return Error(Loc, "immediate must be an integer in range [-1, 62].");
case Match_InvalidMemoryIndexedRange2UImm0:
return Error(Loc, "vector select offset must be the immediate range 0:1.");
case Match_InvalidMemoryIndexedRange2UImm1:
@@ -6757,6 +6773,7 @@ bool AArch64AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidImm1_16:
case Match_InvalidImm1_32:
case Match_InvalidImm1_64:
+ case Match_InvalidImmM1_62:
case Match_InvalidMemoryIndexedRange2UImm0:
case Match_InvalidMemoryIndexedRange2UImm1:
case Match_InvalidMemoryIndexedRange2UImm2:
@@ -8224,3 +8241,37 @@ ParseStatus AArch64AsmParser::tryParseImmRange(OperandVector &Operands) {
AArch64Operand::CreateImmRange(ImmFVal, ImmLVal, S, E, getContext()));
return ParseStatus::Success;
}
+
+template <int Adj>
+ParseStatus AArch64AsmParser::tryParseAdjImm0_63(OperandVector &Operands) {
+ SMLoc S = getLoc();
+
+ parseOptionalToken(AsmToken::Hash);
+ bool IsNegative = parseOptionalToken(AsmToken::Minus);
+
+ if (getTok().isNot(AsmToken::Integer))
+ return ParseStatus::NoMatch;
+
+ const MCExpr *Ex;
+ if (getParser().parseExpression(Ex))
+ return ParseStatus::NoMatch;
+
+ int64_t Imm = dyn_cast<MCConstantExpr>(Ex)->getValue();
+ if (IsNegative)
+ Imm = -Imm;
+
+ // We want an adjusted immediate in the range [0, 63]. If we don't have one,
+ // return a value, which is certain to trigger a error message about invalid
+ // immediate range instead of a non-descriptive invalid operand error.
+ static_assert(Adj == 1 || Adj == -1, "Unsafe immediate adjustment");
+ if (Imm == INT64_MIN || Imm == INT64_MAX || Imm + Adj < 0 || Imm + Adj > 63)
+ Imm = -2;
+ else
+ Imm += Adj;
+
+ SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
+ Operands.push_back(AArch64Operand::CreateImm(
+ MCConstantExpr::create(Imm, getContext()), S, E, getContext()));
+
+ return ParseStatus::Success;
+}
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 8e2dc3d217cb9f..2fe02f546629e8 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -80,6 +80,9 @@ static DecodeStatus DecodePCRelLabel16(MCInst &Inst, unsigned Imm,
static DecodeStatus DecodePCRelLabel19(MCInst &Inst, unsigned Imm,
uint64_t Address,
const MCDisassembler *Decoder);
+static DecodeStatus DecodePCRelLabel9(MCInst &Inst, unsigned Imm,
+ uint64_t Address,
+ const MCDisassembler *Decoder);
static DecodeStatus DecodeMemExtend(MCInst &Inst, unsigned Imm,
uint64_t Address,
const MCDisassembler *Decoder);
@@ -488,6 +491,20 @@ static DecodeStatus DecodePCRelLabel19(MCInst &Inst, unsigned Imm,
return Success;
}
+static DecodeStatus DecodePCRelLabel9(MCInst &Inst, unsigned Imm, uint64_t Addr,
+ const MCDisassembler *Decoder) {
+ int64_t ImmVal = Imm;
+
+ // Sign-extend 9-bit immediate.
+ if (ImmVal & (1 << (9 - 1)))
+ ImmVal |= ~((1LL << 9) - 1);
+
+ if (!Decoder->tryAddingSymbolicOperand(Inst, (ImmVal * 4), Addr,
+ /*IsBranch=*/true, 0, 0, 4))
+ Inst.addOperand(MCOperand::createImm(ImmVal));
+ return Success;
+}
+
static DecodeStatus DecodeMemExtend(MCInst &Inst, unsigned Imm,
uint64_t Address,
const MCDisassembler *Decoder) {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
index adc6c5bf4ed171..1fdd2b08c904cc 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
@@ -66,6 +66,7 @@ class AArch64AsmBackend : public MCAsmBackend {
{"fixup_aarch64_ldst_imm12_scale16", 10, 12, 0},
{"fixup_aarch64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal},
{"fixup_aarch64_movw", 5, 16, 0},
+ {"fixup_aarch64_pcrel_branch9", 5, 9, PCRelFlagVal},
{"fixup_aarch64_pcrel_branch14", 5, 14, PCRelFlagVal},
{"fixup_aarch64_pcrel_branch16", 5, 16, PCRelFlagVal},
{"fixup_aarch64_pcrel_branch19", 5, 19, PCRelFlagVal},
@@ -120,6 +121,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
return 2;
case AArch64::fixup_aarch64_movw:
+ case AArch64::fixup_aarch64_pcrel_branch9:
case AArch64::fixup_aarch64_pcrel_branch14:
case AArch64::fixup_aarch64_pcrel_branch16:
case AArch64::fixup_aarch64_add_imm12:
@@ -307,6 +309,14 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target,
}
return Value;
}
+ case AArch64::fixup_aarch64_pcrel_branch9:
+ // Signed 11-bit(9bits + 2 shifts) label
+ if (!isInt<11>(SignedValue))
+ Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
+ // Low two bits are not encoded (4-byte alignment assumed).
+ if (Value & 0b11)
+ Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
+ return (Value >> 2) & 0x1ff;
case AArch64::fixup_aarch64_pcrel_branch14:
// Signed 16-bit immediate
if (!isInt<16>(SignedValue))
@@ -391,6 +401,7 @@ unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) con
return 8;
case AArch64::fixup_aarch64_movw:
+ case AArch64::fixup_aarch64_pcrel_branch9:
case AArch64::fixup_aarch64_pcrel_branch14:
case AArch64::fixup_aarch64_pcrel_branch16:
case AArch64::fixup_aarch64_add_imm12:
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
index 1a7a175404a64b..83aac6fdae7290 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -188,6 +188,11 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
Ctx.reportError(Fixup.getLoc(),
"relocation of PAC/AUT instructions is not supported");
return ELF::R_AARCH64_NONE;
+ case AArch64::fixup_aarch64_pcrel_branch9:
+ Ctx.reportError(
+ Fixup.getLoc(),
+ "relocation of compare-and-branch instructions not supported");
+ return ELF::R_AARCH64_NONE;
case AArch64::fixup_aarch64_pcrel_branch19:
return R_CLS(CONDBR19);
default:
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h
index fdee2d5ad2bf30..113dbe1634e765 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h
@@ -40,6 +40,9 @@ enum Fixups {
// FIXME: comment
fixup_aarch64_movw,
+ // The high 9 bits of a 11-bit pc-relative immediate.
+ fixup_aarch64_pcrel_branch9,
+
// The high 14 bits of a 21-bit pc-relative immediate.
fixup_aarch64_pcrel_branch14,
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
index 61b83847666908..760e09dc6fdac9 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
@@ -88,6 +88,12 @@ class AArch64MCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ /// getCondCompBranchTargetOpValue - Return the encoded value for a
+ /// conditional compare-and-branch target.
+ uint32_t getCondCompBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
/// getPAuthPCRelOpValue - Return the encoded value for a pointer
/// authentication pc-relative operand.
uint32_t getPAuthPCRelOpValue(const MCInst &MI, unsigned OpIdx,
@@ -333,6 +339,27 @@ uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue(
return 0;
}
+/// getCondCompBranchTargetOpValue - Return the encoded value for a conditional
+/// compare-and-branch target.
+uint32_t AArch64MCCodeEmitter::getCondCompBranchTargetOpValue(
+ const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(OpIdx);
+
+ // If the destination is an immediate, we have nothing to do.
+ if (MO.isImm())
+ return MO.getImm();
+ assert(MO.isExpr() && "Unexpected target type!");
+
+ MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch9);
+ Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
+
+ ++MCNumFixups;
+
+ // All of the information is in the fixup.
+ return 0;
+}
+
/// getPAuthPCRelOpValue - Return the encoded value for a pointer
/// authentication pc-relative operand.
uint32_t
diff --git a/llvm/test/MC/AArch64/CMPBR/cmpbr-diagnostics.s b/llvm/test/MC/AArch64/CMPBR/cmpbr-diagnostics.s
new file mode 100644
index 00000000000000..f8a6c165c5c323
--- /dev/null
+++ b/llvm/test/MC/AArch64/CMPBR/cmpbr-diagnostics.s
@@ -0,0 +1,507 @@
+// RUN: not llvm-mc -triple=aarch64 -filetype=obj -show-encoding -mattr=+cmpbr 2>&1 < %s | FileCheck %s
+
+//------------------------------------------------------------------------------
+// Incorrect label
+
+// -- cbgt
+
+cbgt x5, x5, #-1025
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset
+// CHECK-NEXT: cbgt x5, x5, #-1025
+// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}:
+
+cbgt w5, w5, #1021
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset
+// CHECK...
[truncated]
|
You can test this locally with the following command:git-clang-format --diff 699ce16b6284377e0cd9969b9f95e7367632a622 0e436c0b5fd7533bc9b644942d9e97cb0b5fa887 --extensions h,cpp -- llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp llvm/lib/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp View the diff from clang-format here.diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
index 1fdd2b08c9..9ec91b21a9 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
@@ -66,7 +66,7 @@ public:
{"fixup_aarch64_ldst_imm12_scale16", 10, 12, 0},
{"fixup_aarch64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal},
{"fixup_aarch64_movw", 5, 16, 0},
- {"fixup_aarch64_pcrel_branch9", 5, 9, PCRelFlagVal},
+ {"fixup_aarch64_pcrel_branch9", 5, 9, PCRelFlagVal},
{"fixup_aarch64_pcrel_branch14", 5, 14, PCRelFlagVal},
{"fixup_aarch64_pcrel_branch16", 5, 16, PCRelFlagVal},
{"fixup_aarch64_pcrel_branch19", 5, 19, PCRelFlagVal},
|
if (ImmVal & (1 << (9 - 1))) | ||
ImmVal |= ~((1LL << 9) - 1); | ||
|
||
if (!Decoder->tryAddingSymbolicOperand(Inst, (ImmVal * 4), Addr, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
It'd be very nice to include in the commit message information about what was fixed, e.g.
"Replaced a shift left of a possibly negative value with a multiplication in DecodePCRelLabel9"
…llvm#113461) …uctions (llvm#112726) This patch adds the assembly/disassembly for the following instructions: CBB<cc>, CBH<cc>, CB<cc>(immediate), CB<cc>(register) CBBLE, CBBLO, CBBLS, CBBLT CBHLE, CBHLO, CBHLS, CBHLT CBGE, CBHS, CBLE, CBLS (immediate) CBLE, CBLO, CBLS, CBLT(register) According to [1] [1]https://developer.arm.com/documentation/ddi0602 Co-authored-by: Momchil Velikov momchil.velikov@arm.com Co-authored-by: Spencer Abson spencer.abson@arm.com This patch was reverted(git commit 83c6e2f) and is being submitted again with the fix for buildbot failure in: https://lab.llvm.org/buildbot/#/builders/25/builds/3493 The fix was to replaced a shift left of a possibly negative value with a multiplication in DecodePCRelLabel9. Because int64_t ImmVal is signed it needed to replace: (ImmVal << 2) with : (ImmVal * 4)
…uctions (#112726)
This patch adds the assembly/disassembly for the following instructions:
CBB, CBH,
CB(immediate), CB(register)
CBBLE, CBBLO, CBBLS, CBBLT
CBHLE, CBHLO, CBHLS, CBHLT
CBGE, CBHS, CBLE, CBLS (immediate)
CBLE, CBLO, CBLS, CBLT(register)
According to [1]
[1]https://developer.arm.com/documentation/ddi0602
Co-authored-by: Momchil Velikov momchil.velikov@arm.com
Co-authored-by: Spencer Abson spencer.abson@arm.com
This patch was reverted(git commit 83c6e2f) and is being submitted again with the fix for buildbot failure in:
https://lab.llvm.org/buildbot/#/builders/25/builds/3493
The fix was to replaced a shift left of a possibly negative value with a multiplication in DecodePCRelLabel9.
Because int64_t ImmVal is signed it needed to replace:
(ImmVal << 2)
with :
(ImmVal * 4)