[llvm] [LLVM][AArch64]Add assembly/disassembly for compare-and-branch instr… (PR #113461)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 23 07:14:52 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mc
Author: None (CarolineConcatto)
<details>
<summary>Changes</summary>
…uctions (#<!-- -->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 83c6e2f8f4d3) and is being submitted again with the fix for buildbot failure in:
https://lab.llvm.org/buildbot/#/builders/25/builds/3493
---
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:
- (modified) llvm/lib/Target/AArch64/AArch64InstrFormats.td (+135)
- (modified) llvm/lib/Target/AArch64/AArch64InstrInfo.td (+51)
- (modified) llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (+51)
- (modified) llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp (+17)
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp (+11)
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp (+5)
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h (+3)
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp (+27)
- (added) llvm/test/MC/AArch64/CMPBR/cmpbr-diagnostics.s (+507)
- (added) llvm/test/MC/AArch64/CMPBR/cmpbr.s (+282)
- (added) llvm/test/MC/AArch64/CMPBR/cmpbr_aliases-diagnostics.s (+25)
- (added) llvm/test/MC/AArch64/CMPBR/cmpbr_aliases.s (+74)
- (added) llvm/test/MC/AArch64/CMPBR/cmpbr_lbl.s (+320)
- (modified) llvm/test/MC/AArch64/directive-arch-negative.s (+5)
- (modified) llvm/test/MC/AArch64/directive-arch.s (+5)
- (modified) llvm/test/MC/AArch64/directive-arch_extension-negative.s (+9-1)
``````````diff
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]
``````````
</details>
https://github.com/llvm/llvm-project/pull/113461
More information about the llvm-commits
mailing list