Skip to content

Commit dc84337

Browse files
[LLVM][AArch64]Add assembly/disassembly for compare-and-branch instructions (#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 [email protected] Co-authored-by: Spencer Abson [email protected]
1 parent b90ea5c commit dc84337

16 files changed

+1528
-1
lines changed

llvm/lib/Target/AArch64/AArch64InstrFormats.td

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,46 @@ def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
388388
let ParserMatchClass = AsmImmRange<0, 65535>;
389389
}
390390

391+
def uimm6_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
392+
let ParserMatchClass = UImm6Operand;
393+
}
394+
395+
def uimm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 64; }]> {
396+
let ParserMatchClass = UImm6Operand;
397+
}
398+
399+
def UImm6Plus1Operand : AsmOperandClass {
400+
let Name = "UImm6P1";
401+
let DiagnosticType = "InvalidImm1_64";
402+
let RenderMethod = "addImmOperands";
403+
let ParserMethod = "tryParseAdjImm0_63<-1>";
404+
let PredicateMethod = "isImmInRange<0,63>";
405+
}
406+
407+
def UImm6Minus1Operand : AsmOperandClass {
408+
let Name = "UImm6M1";
409+
let DiagnosticType = "InvalidImmM1_62";
410+
let RenderMethod = "addImmOperands";
411+
let ParserMethod = "tryParseAdjImm0_63<1>";
412+
let PredicateMethod = "isImmInRange<0,63>";
413+
}
414+
415+
def uimm6p1_32b : Operand<i32> {
416+
let ParserMatchClass = UImm6Plus1Operand;
417+
}
418+
419+
def uimm6p1_64b : Operand<i64> {
420+
let ParserMatchClass = UImm6Plus1Operand;
421+
}
422+
423+
def uimm6m1_32b : Operand<i32> {
424+
let ParserMatchClass = UImm6Minus1Operand;
425+
}
426+
427+
def uimm6m1_64b : Operand<i64> {
428+
let ParserMatchClass = UImm6Minus1Operand;
429+
}
430+
391431
def SImm9Operand : SImmOperand<9>;
392432
def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
393433
let ParserMatchClass = SImm9Operand;
@@ -657,6 +697,7 @@ class PCRelLabel<int N> : BranchTarget<N> {
657697
def BranchTarget14Operand : BranchTarget<14>;
658698
def BranchTarget26Operand : BranchTarget<26>;
659699
def PCRelLabel19Operand : PCRelLabel<19>;
700+
def PCRelLabel9Operand : PCRelLabel<9>;
660701

661702
def MovWSymbolG3AsmOperand : AsmOperandClass {
662703
let Name = "MovWSymbolG3";
@@ -2134,6 +2175,17 @@ def am_brcond : Operand<OtherVT> {
21342175
let OperandType = "OPERAND_PCREL";
21352176
}
21362177

2178+
// Conditional branch target. 9-bit immediate. The low two bits of the target
2179+
// offset are implied zero and so are not part of the immediate.
2180+
def am_brcmpcond : Operand<OtherVT> {
2181+
let EncoderMethod = "getCondCompBranchTargetOpValue";
2182+
let DecoderMethod = "DecodePCRelLabel9";
2183+
let PrintMethod = "printAlignedLabel";
2184+
let ParserMatchClass = PCRelLabel9Operand;
2185+
let OperandType = "OPERAND_PCREL";
2186+
}
2187+
2188+
21372189
class BranchCond<bit bit4, string mnemonic>
21382190
: I<(outs), (ins ccode:$cond, am_brcond:$target),
21392191
mnemonic, ".$cond\t$target", "",
@@ -12607,6 +12659,89 @@ class MulAccumCPA<bit isSub, string asm>
1260712659
let Inst{31} = 0b1;
1260812660
}
1260912661

12662+
12663+
//----------------------------------------------------------------------------
12664+
// 2024 Armv9.6 Extensions
12665+
//----------------------------------------------------------------------------
12666+
12667+
//---
12668+
// Compare-and-branch instructions.
12669+
//---
12670+
12671+
class BaseCmpBranchRegister<RegisterClass regtype, bit sf, bits<3> cc,
12672+
bits<2>sz, string asm>
12673+
: I<(outs), (ins regtype:$Rt, regtype:$Rm, am_brcmpcond:$target),
12674+
asm, "\t$Rt, $Rm, $target", "",
12675+
[]>,
12676+
Sched<[WriteBr]> {
12677+
let isBranch = 1;
12678+
let isTerminator = 1;
12679+
12680+
bits<5> Rm;
12681+
bits<5> Rt;
12682+
bits<9> target;
12683+
let Inst{31} = sf;
12684+
let Inst{30-24} = 0b1110100;
12685+
let Inst{23-21} = cc;
12686+
let Inst{20-16} = Rm;
12687+
let Inst{15-14} = sz;
12688+
let Inst{13-5} = target;
12689+
let Inst{4-0} = Rt;
12690+
}
12691+
12692+
multiclass CmpBranchRegister<bits<3> cc, string asm> {
12693+
def Wrr : BaseCmpBranchRegister<GPR32, 0b0, cc, 0b00, asm>;
12694+
def Xrr : BaseCmpBranchRegister<GPR64, 0b1, cc, 0b00, asm>;
12695+
}
12696+
12697+
class BaseCmpBranchImmediate<RegisterClass regtype, bit sf, bits<3> cc,
12698+
Operand imm_ty, string asm>
12699+
: I<(outs), (ins regtype:$Rt, imm_ty:$imm, am_brcmpcond:$target),
12700+
asm, "\t$Rt, $imm, $target", "",
12701+
[]>,
12702+
Sched<[WriteBr]> {
12703+
let isBranch = 1;
12704+
let isTerminator = 1;
12705+
12706+
bits<5> Rt;
12707+
bits<6> imm;
12708+
bits<9> target;
12709+
let Inst{31} = sf;
12710+
let Inst{30-24} = 0b1110101;
12711+
let Inst{23-21} = cc;
12712+
let Inst{20-15} = imm;
12713+
let Inst{14} = 0b0;
12714+
let Inst{13-5} = target;
12715+
let Inst{4-0} = Rt;
12716+
}
12717+
12718+
multiclass CmpBranchImmediate<bits<3> cc, string imm_ty, string asm> {
12719+
def Wri : BaseCmpBranchImmediate<GPR32, 0b0, cc, !cast<Operand>(imm_ty # "_32b"), asm>;
12720+
def Xri : BaseCmpBranchImmediate<GPR64, 0b1, cc, !cast<Operand>(imm_ty # "_64b"), asm>;
12721+
}
12722+
12723+
multiclass CmpBranchImmediateAlias<string mnemonic, string insn, string imm_ty> {
12724+
def : InstAlias<mnemonic # "\t$Rt, $imm, $target",
12725+
(!cast<Instruction>(insn # "Wri") GPR32:$Rt,
12726+
!cast<Operand>(imm_ty # "_32b"):$imm,
12727+
am_brcmpcond:$target), 0>;
12728+
def : InstAlias<mnemonic # "\t$Rt, $imm, $target",
12729+
(!cast<Instruction>(insn # "Xri") GPR64:$Rt,
12730+
!cast<Operand>(imm_ty # "_64b"):$imm,
12731+
am_brcmpcond:$target), 0>;
12732+
}
12733+
12734+
multiclass CmpBranchWRegisterAlias<string mnemonic, string insn> {
12735+
def : InstAlias<mnemonic # "\t$Rt, $Rm, $target",
12736+
(!cast<Instruction>(insn # "Wrr") GPR32:$Rm, GPR32:$Rt, am_brcmpcond:$target), 0>;
12737+
}
12738+
12739+
multiclass CmpBranchRegisterAlias<string mnemonic, string insn> {
12740+
defm : CmpBranchWRegisterAlias<mnemonic, insn>;
12741+
12742+
def : InstAlias<mnemonic # "\t$Rt, $Rm, $target",
12743+
(!cast<Instruction>(insn # "Xrr") GPR64:$Rm, GPR64:$Rt, am_brcmpcond:$target), 0>;
12744+
}
1261012745
//----------------------------------------------------------------------------
1261112746
// Allow the size specifier tokens to be upper case, not just lower.
1261212747
def : TokenAlias<".4B", ".4b">; // Add dot product

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10299,6 +10299,57 @@ defm : PromoteBinaryv8f16Tov4f32<any_fdiv, FDIVv4f32>;
1029910299
defm : PromoteBinaryv8f16Tov4f32<any_fmul, FMULv4f32>;
1030010300
defm : PromoteBinaryv8f16Tov4f32<any_fsub, FSUBv4f32>;
1030110301

10302+
let Predicates = [HasCMPBR] in {
10303+
defm CBGT : CmpBranchRegister<0b000, "cbgt">;
10304+
defm CBGE : CmpBranchRegister<0b001, "cbge">;
10305+
defm CBHI : CmpBranchRegister<0b010, "cbhi">;
10306+
defm CBHS : CmpBranchRegister<0b011, "cbhs">;
10307+
defm CBEQ : CmpBranchRegister<0b110, "cbeq">;
10308+
defm CBNE : CmpBranchRegister<0b111, "cbne">;
10309+
10310+
def CBHGTWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b000, 0b11, "cbhgt">;
10311+
def CBHGEWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b001, 0b11, "cbhge">;
10312+
def CBHHIWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b010, 0b11, "cbhhi">;
10313+
def CBHHSWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b011, 0b11, "cbhhs">;
10314+
def CBHEQWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b110, 0b11, "cbheq">;
10315+
def CBHNEWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b111, 0b11, "cbhne">;
10316+
10317+
def CBBGTWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b000, 0b10, "cbbgt">;
10318+
def CBBGEWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b001, 0b10, "cbbge">;
10319+
def CBBHIWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b010, 0b10, "cbbhi">;
10320+
def CBBHSWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b011, 0b10, "cbbhs">;
10321+
def CBBEQWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b110, 0b10, "cbbeq">;
10322+
def CBBNEWrr : BaseCmpBranchRegister<GPR32, 0b0, 0b111, 0b10, "cbbne">;
10323+
10324+
defm CBGT : CmpBranchImmediate<0b000, "uimm6", "cbgt">;
10325+
defm CBLT : CmpBranchImmediate<0b001, "uimm6", "cblt">;
10326+
defm CBHI : CmpBranchImmediate<0b010, "uimm6", "cbhi">;
10327+
defm CBLO : CmpBranchImmediate<0b011, "uimm6", "cblo">;
10328+
defm CBEQ : CmpBranchImmediate<0b110, "uimm6", "cbeq">;
10329+
defm CBNE : CmpBranchImmediate<0b111, "uimm6", "cbne">;
10330+
10331+
defm : CmpBranchImmediateAlias<"cbge", "CBGT", "uimm6p1">;
10332+
defm : CmpBranchImmediateAlias<"cbhs", "CBHI", "uimm6p1">;
10333+
defm : CmpBranchImmediateAlias<"cble", "CBLT", "uimm6m1">;
10334+
defm : CmpBranchImmediateAlias<"cbls", "CBLO", "uimm6m1">;
10335+
10336+
defm : CmpBranchRegisterAlias<"cble", "CBGE">;
10337+
defm : CmpBranchRegisterAlias<"cblo", "CBHI">;
10338+
defm : CmpBranchRegisterAlias<"cbls", "CBHS">;
10339+
defm : CmpBranchRegisterAlias<"cblt", "CBGT">;
10340+
10341+
defm : CmpBranchWRegisterAlias<"cbble", "CBBGE">;
10342+
defm : CmpBranchWRegisterAlias<"cbblo", "CBBHI">;
10343+
defm : CmpBranchWRegisterAlias<"cbbls", "CBBHS">;
10344+
defm : CmpBranchWRegisterAlias<"cbblt", "CBBGT">;
10345+
10346+
defm : CmpBranchWRegisterAlias<"cbhle", "CBHGE">;
10347+
defm : CmpBranchWRegisterAlias<"cbhlo", "CBHHI">;
10348+
defm : CmpBranchWRegisterAlias<"cbhls", "CBHHS">;
10349+
defm : CmpBranchWRegisterAlias<"cbhlt", "CBHGT">;
10350+
} // HasCMPBR
10351+
10352+
1030210353
//===-----------------------------------------------------===//
1030310354
// Atomic floating-point in-memory instructions (FEAT_LSFE)
1030410355
//===-----------------------------------------------------===//

llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
286286
ParseStatus tryParseSVEVecLenSpecifier(OperandVector &Operands);
287287
ParseStatus tryParseGPR64x8(OperandVector &Operands);
288288
ParseStatus tryParseImmRange(OperandVector &Operands);
289+
template <int> ParseStatus tryParseAdjImm0_63(OperandVector &Operands);
289290

290291
public:
291292
enum AArch64MatchResultTy {
@@ -2070,6 +2071,20 @@ class AArch64Operand : public MCParsedAsmOperand {
20702071
Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
20712072
}
20722073

2074+
void addPCRelLabel9Operands(MCInst &Inst, unsigned N) const {
2075+
// Branch operands don't encode the low bits, so shift them off
2076+
// here. If it's a label, however, just put it on directly as there's
2077+
// not enough information now to do anything.
2078+
assert(N == 1 && "Invalid number of operands!");
2079+
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
2080+
if (!MCE) {
2081+
addExpr(Inst, getImm());
2082+
return;
2083+
}
2084+
assert(MCE && "Invalid constant immediate operand!");
2085+
Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
2086+
}
2087+
20732088
void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
20742089
// Branch operands don't encode the low bits, so shift them off
20752090
// here. If it's a label, however, just put it on directly as there's
@@ -5926,6 +5941,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
59265941
return Error(Loc, "immediate must be an integer in range [1, 32].");
59275942
case Match_InvalidImm1_64:
59285943
return Error(Loc, "immediate must be an integer in range [1, 64].");
5944+
case Match_InvalidImmM1_62:
5945+
return Error(Loc, "immediate must be an integer in range [-1, 62].");
59295946
case Match_InvalidMemoryIndexedRange2UImm0:
59305947
return Error(Loc, "vector select offset must be the immediate range 0:1.");
59315948
case Match_InvalidMemoryIndexedRange2UImm1:
@@ -6696,6 +6713,7 @@ bool AArch64AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
66966713
case Match_InvalidImm1_16:
66976714
case Match_InvalidImm1_32:
66986715
case Match_InvalidImm1_64:
6716+
case Match_InvalidImmM1_62:
66996717
case Match_InvalidMemoryIndexedRange2UImm0:
67006718
case Match_InvalidMemoryIndexedRange2UImm1:
67016719
case Match_InvalidMemoryIndexedRange2UImm2:
@@ -8163,3 +8181,37 @@ ParseStatus AArch64AsmParser::tryParseImmRange(OperandVector &Operands) {
81638181
AArch64Operand::CreateImmRange(ImmFVal, ImmLVal, S, E, getContext()));
81648182
return ParseStatus::Success;
81658183
}
8184+
8185+
template <int Adj>
8186+
ParseStatus AArch64AsmParser::tryParseAdjImm0_63(OperandVector &Operands) {
8187+
SMLoc S = getLoc();
8188+
8189+
parseOptionalToken(AsmToken::Hash);
8190+
bool IsNegative = parseOptionalToken(AsmToken::Minus);
8191+
8192+
if (getTok().isNot(AsmToken::Integer))
8193+
return ParseStatus::NoMatch;
8194+
8195+
const MCExpr *Ex;
8196+
if (getParser().parseExpression(Ex))
8197+
return ParseStatus::NoMatch;
8198+
8199+
int64_t Imm = dyn_cast<MCConstantExpr>(Ex)->getValue();
8200+
if (IsNegative)
8201+
Imm = -Imm;
8202+
8203+
// We want an adjusted immediate in the range [0, 63]. If we don't have one,
8204+
// return a value, which is certain to trigger a error message about invalid
8205+
// immediate range instead of a non-descriptive invalid operand error.
8206+
static_assert(Adj == 1 || Adj == -1, "Unsafe immediate adjustment");
8207+
if (Imm == INT64_MIN || Imm == INT64_MAX || Imm + Adj < 0 || Imm + Adj > 63)
8208+
Imm = -2;
8209+
else
8210+
Imm += Adj;
8211+
8212+
SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
8213+
Operands.push_back(AArch64Operand::CreateImm(
8214+
MCConstantExpr::create(Imm, getContext()), S, E, getContext()));
8215+
8216+
return ParseStatus::Success;
8217+
}

llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ static DecodeStatus DecodePCRelLabel16(MCInst &Inst, unsigned Imm,
8080
static DecodeStatus DecodePCRelLabel19(MCInst &Inst, unsigned Imm,
8181
uint64_t Address,
8282
const MCDisassembler *Decoder);
83+
static DecodeStatus DecodePCRelLabel9(MCInst &Inst, unsigned Imm,
84+
uint64_t Address,
85+
const MCDisassembler *Decoder);
8386
static DecodeStatus DecodeMemExtend(MCInst &Inst, unsigned Imm,
8487
uint64_t Address,
8588
const MCDisassembler *Decoder);
@@ -488,6 +491,20 @@ static DecodeStatus DecodePCRelLabel19(MCInst &Inst, unsigned Imm,
488491
return Success;
489492
}
490493

494+
static DecodeStatus DecodePCRelLabel9(MCInst &Inst, unsigned Imm, uint64_t Addr,
495+
const MCDisassembler *Decoder) {
496+
int64_t ImmVal = Imm;
497+
498+
// Sign-extend 9-bit immediate.
499+
if (ImmVal & (1 << (9 - 1)))
500+
ImmVal |= ~((1LL << 9) - 1);
501+
502+
if (!Decoder->tryAddingSymbolicOperand(Inst, (ImmVal << 2), Addr,
503+
/*IsBranch=*/true, 0, 0, 4))
504+
Inst.addOperand(MCOperand::createImm(ImmVal));
505+
return Success;
506+
}
507+
491508
static DecodeStatus DecodeMemExtend(MCInst &Inst, unsigned Imm,
492509
uint64_t Address,
493510
const MCDisassembler *Decoder) {

llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class AArch64AsmBackend : public MCAsmBackend {
6666
{"fixup_aarch64_ldst_imm12_scale16", 10, 12, 0},
6767
{"fixup_aarch64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal},
6868
{"fixup_aarch64_movw", 5, 16, 0},
69+
{"fixup_aarch64_pcrel_branch9", 5, 9, PCRelFlagVal},
6970
{"fixup_aarch64_pcrel_branch14", 5, 14, PCRelFlagVal},
7071
{"fixup_aarch64_pcrel_branch16", 5, 16, PCRelFlagVal},
7172
{"fixup_aarch64_pcrel_branch19", 5, 19, PCRelFlagVal},
@@ -120,6 +121,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
120121
return 2;
121122

122123
case AArch64::fixup_aarch64_movw:
124+
case AArch64::fixup_aarch64_pcrel_branch9:
123125
case AArch64::fixup_aarch64_pcrel_branch14:
124126
case AArch64::fixup_aarch64_pcrel_branch16:
125127
case AArch64::fixup_aarch64_add_imm12:
@@ -307,6 +309,14 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target,
307309
}
308310
return Value;
309311
}
312+
case AArch64::fixup_aarch64_pcrel_branch9:
313+
// Signed 11-bit(9bits + 2 shifts) label
314+
if (!isInt<11>(SignedValue))
315+
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
316+
// Low two bits are not encoded (4-byte alignment assumed).
317+
if (Value & 0b11)
318+
Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
319+
return (Value >> 2) & 0x1ff;
310320
case AArch64::fixup_aarch64_pcrel_branch14:
311321
// Signed 16-bit immediate
312322
if (!isInt<16>(SignedValue))
@@ -391,6 +401,7 @@ unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) con
391401
return 8;
392402

393403
case AArch64::fixup_aarch64_movw:
404+
case AArch64::fixup_aarch64_pcrel_branch9:
394405
case AArch64::fixup_aarch64_pcrel_branch14:
395406
case AArch64::fixup_aarch64_pcrel_branch16:
396407
case AArch64::fixup_aarch64_add_imm12:

llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
190190
Ctx.reportError(Fixup.getLoc(),
191191
"relocation of PAC/AUT instructions is not supported");
192192
return ELF::R_AARCH64_NONE;
193+
case AArch64::fixup_aarch64_pcrel_branch9:
194+
Ctx.reportError(
195+
Fixup.getLoc(),
196+
"relocation of compare-and-branch instructions not supported");
197+
return ELF::R_AARCH64_NONE;
193198
case AArch64::fixup_aarch64_pcrel_branch19:
194199
return R_CLS(CONDBR19);
195200
default:

llvm/lib/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ enum Fixups {
4040
// FIXME: comment
4141
fixup_aarch64_movw,
4242

43+
// The high 9 bits of a 11-bit pc-relative immediate.
44+
fixup_aarch64_pcrel_branch9,
45+
4346
// The high 14 bits of a 21-bit pc-relative immediate.
4447
fixup_aarch64_pcrel_branch14,
4548

0 commit comments

Comments
 (0)