Skip to content

Commit 934b109

Browse files
ostannardtmatheson-arm
authored andcommitted
[AArch64] Add FEAT_PAuthLR assembler support
Add assembly/disassembly support for the new PAuthLR instructions introduced in Armv9.5-A: - AUTIASPPC/AUTIBSPPC - PACIASPPC/PACIBSPPC - PACNBIASPPC/PACNBIBSPPC - RETAASPPC/RETABSPPC - PACM Documentation for these instructions can be found here: https://developer.arm.com/documentation/ddi0602/2023-09/Base-Instructions/
1 parent 92dc23c commit 934b109

15 files changed

+518
-4
lines changed

llvm/lib/Target/AArch64/AArch64.td

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -622,8 +622,13 @@ def FeatureLdpAlignedOnly : SubtargetFeature<"ldp-aligned-only", "HasLdpAlignedO
622622
def FeatureStpAlignedOnly : SubtargetFeature<"stp-aligned-only", "HasStpAlignedOnly",
623623
"true", "In order to emit stp, first check if the store will be aligned to 2 * element_size">;
624624

625+
// AArch64 2023 Architecture Extensions (v9.5-A)
626+
625627
def FeatureCPA : SubtargetFeature<"cpa", "HasCPA", "true",
626-
"Enable ARMv9.5-A Checked Pointer Arithmetic (FEAT_CPA)">;
628+
"Enable Armv9.5-A Checked Pointer Arithmetic (FEAT_CPA)">;
629+
630+
def FeaturePAuthLR : SubtargetFeature<"pauth-lr", "HasPAuthLR",
631+
"true", "Enable Armv9.5-A PAC enhancements (FEAT_PAuth_LR)">;
627632

628633
//===----------------------------------------------------------------------===//
629634
// Architectures.
@@ -810,7 +815,7 @@ def SMEUnsupported : AArch64Unsupported {
810815
SME2Unsupported.F);
811816
}
812817

813-
let F = [HasPAuth] in
818+
let F = [HasPAuth, HasPAuthLR] in
814819
def PAUnsupported : AArch64Unsupported;
815820

816821
include "AArch64SchedA53.td"

llvm/lib/Target/AArch64/AArch64InstrFormats.td

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2368,6 +2368,80 @@ class ClearAuth<bits<1> data, string asm>
23682368
let Inst{4-0} = Rd;
23692369
}
23702370

2371+
// v9.5-A FEAT_PAuth_LR
2372+
2373+
class SignAuthFixedRegs<bits<5> opcode2, bits<6> opcode, string asm>
2374+
: I<(outs), (ins), asm, "", "", []>,
2375+
Sched<[WriteI, ReadI]> {
2376+
let Inst{31} = 0b1; // sf
2377+
let Inst{30} = 0b1;
2378+
let Inst{29} = 0b0; // S
2379+
let Inst{28-21} = 0b11010110;
2380+
let Inst{20-16} = opcode2;
2381+
let Inst{15-10} = opcode;
2382+
let Inst{9-5} = 0b11111; // Rn
2383+
let Inst{4-0} = 0b11110; // Rd
2384+
}
2385+
2386+
def PAuthPCRelLabel16Operand : PCRelLabel<16> {
2387+
let Name = "PAuthPCRelLabel16";
2388+
let PredicateMethod = "isPAuthPCRelLabel16Operand";
2389+
}
2390+
def am_pauth_pcrel : Operand<OtherVT> {
2391+
let EncoderMethod = "getPAuthPCRelOpValue";
2392+
let DecoderMethod = "DecodePCRelLabel16";
2393+
let PrintMethod = "printAlignedLabel";
2394+
let ParserMatchClass = PAuthPCRelLabel16Operand;
2395+
let OperandType = "OPERAND_PCREL";
2396+
}
2397+
2398+
class SignAuthPCRel<bits<2> opc, string asm>
2399+
: I<(outs), (ins am_pauth_pcrel:$label), asm, "\t$label", "", []>,
2400+
Sched<[]> {
2401+
bits<16> label;
2402+
let Inst{31} = 0b1; // sf
2403+
let Inst{30-23} = 0b11100111;
2404+
let Inst{22-21} = opc;
2405+
let Inst{20-5} = label; // imm
2406+
let Inst{4-0} = 0b11111; // Rd
2407+
}
2408+
2409+
class SignAuthOneReg<bits<5> opcode2, bits<6> opcode, string asm>
2410+
: I<(outs), (ins GPR64:$Rn), asm, "\t$Rn", "", []>,
2411+
Sched<[]> {
2412+
bits<5> Rn;
2413+
let Inst{31} = 0b1; // sf
2414+
let Inst{30} = 0b1;
2415+
let Inst{29} = 0b0; // S
2416+
let Inst{28-21} = 0b11010110;
2417+
let Inst{20-16} = opcode2;
2418+
let Inst{15-10} = opcode;
2419+
let Inst{9-5} = Rn;
2420+
let Inst{4-0} = 0b11110; // Rd
2421+
}
2422+
2423+
class SignAuthReturnPCRel<bits<3> opc, bits<5> op2, string asm>
2424+
: I<(outs), (ins am_pauth_pcrel:$label), asm, "\t$label", "", []>,
2425+
Sched<[WriteAtomic]> {
2426+
bits<16> label;
2427+
let Inst{31-24} = 0b01010101;
2428+
let Inst{23-21} = opc;
2429+
let Inst{20-5} = label; // imm16
2430+
let Inst{4-0} = op2;
2431+
}
2432+
2433+
class SignAuthReturnReg<bits<6> op3, string asm>
2434+
: I<(outs), (ins GPR64common:$Rm), asm, "\t$Rm", "", []>,
2435+
Sched<[WriteAtomic]> {
2436+
bits<5> Rm;
2437+
let Inst{31-25} = 0b1101011;
2438+
let Inst{24-21} = 0b0010; // opc
2439+
let Inst{20-16} = 0b11111; // op2
2440+
let Inst{15-10} = op3;
2441+
let Inst{9-5} = 0b11111; // Rn
2442+
let Inst{4-0} = Rm; // op4 (Rm)
2443+
}
2444+
23712445
// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
23722446
class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
23732447
: I<(outs), iops, asm, ops, "", []>,

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ def HasLOR : Predicate<"Subtarget->hasLOR()">,
6161
def HasPAuth : Predicate<"Subtarget->hasPAuth()">,
6262
AssemblerPredicateWithAll<(all_of FeaturePAuth), "pauth">;
6363

64+
def HasPAuthLR : Predicate<"Subtarget->hasPAuthLR()">,
65+
AssemblerPredicateWithAll<(all_of FeaturePAuthLR), "pauth-lr">;
66+
6467
def HasJS : Predicate<"Subtarget->hasJS()">,
6568
AssemblerPredicateWithAll<(all_of FeatureJS), "jsconv">;
6669

@@ -1646,6 +1649,42 @@ let Predicates = [HasPAuth] in {
16461649

16471650
}
16481651

1652+
// v9.5-A pointer authentication extensions
1653+
1654+
// Always accept "pacm" as an alias for "hint #39", but don't emit it when
1655+
// disassembling if we don't have the pauth-lr feature.
1656+
let CRm = 0b0100 in {
1657+
def PACM : SystemNoOperands<0b111, "hint\t#39">;
1658+
}
1659+
def : InstAlias<"pacm", (PACM), 0>;
1660+
1661+
let Predicates = [HasPAuthLR] in {
1662+
let Defs = [LR], Uses = [LR, SP] in {
1663+
// opcode2, opcode, asm
1664+
def PACIASPPC : SignAuthFixedRegs<0b00001, 0b101000, "paciasppc">;
1665+
def PACIBSPPC : SignAuthFixedRegs<0b00001, 0b101001, "pacibsppc">;
1666+
def PACNBIASPPC : SignAuthFixedRegs<0b00001, 0b100000, "pacnbiasppc">;
1667+
def PACNBIBSPPC : SignAuthFixedRegs<0b00001, 0b100001, "pacnbibsppc">;
1668+
// opc, asm
1669+
def AUTIASPPCi : SignAuthPCRel<0b00, "autiasppc">;
1670+
def AUTIBSPPCi : SignAuthPCRel<0b01, "autibsppc">;
1671+
// opcode2, opcode, asm
1672+
def AUTIASPPCr : SignAuthOneReg<0b00001, 0b100100, "autiasppc">;
1673+
def AUTIBSPPCr : SignAuthOneReg<0b00001, 0b100101, "autibsppc">;
1674+
}
1675+
1676+
let Uses = [LR, SP], isReturn = 1, isTerminator = 1, isBarrier = 1 in {
1677+
// opc, op2, asm
1678+
def RETAASPPCi : SignAuthReturnPCRel<0b000, 0b11111, "retaasppc">;
1679+
def RETABSPPCi : SignAuthReturnPCRel<0b001, 0b11111, "retabsppc">;
1680+
// op3, asm
1681+
def RETAASPPCr : SignAuthReturnReg<0b000010, "retaasppc">;
1682+
def RETABSPPCr : SignAuthReturnReg<0b000011, "retabsppc">;
1683+
}
1684+
def : InstAlias<"pacm", (PACM), 1>;
1685+
}
1686+
1687+
16491688
// v8.3a floating point conversion for javascript
16501689
let Predicates = [HasJS, HasFPARMv8], Defs = [NZCV] in
16511690
def FJCVTZS : BaseFPToIntegerUnscaled<0b01, 0b11, 0b110, FPR64, GPR32,

llvm/lib/Target/AArch64/AArch64SchedA64FX.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def A64FXModel : SchedMachineModel {
2222

2323
list<Predicate> UnsupportedFeatures = !listconcat(SMEUnsupported.F, SVEUnsupported.F,
2424
[HasMTE, HasMatMulInt8, HasBF16,
25-
HasPAuth, HasCPA]);
25+
HasPAuth, HasPAuthLR, HasCPA]);
2626
let FullInstRWOverlapCheck = 0;
2727
}
2828

llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def NeoverseN2Model : SchedMachineModel {
1919
let CompleteModel = 1;
2020

2121
list<Predicate> UnsupportedFeatures = !listconcat(SMEUnsupported.F,
22-
[HasSVE2p1, HasCPA]);
22+
[HasSVE2p1, HasPAuthLR, HasCPA]);
2323
}
2424

2525
//===----------------------------------------------------------------------===//

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,21 @@ class AArch64Operand : public MCParsedAsmOperand {
16961696
return DiagnosticPredicateTy::Match;
16971697
}
16981698

1699+
bool isPAuthPCRelLabel16Operand() const {
1700+
// PAuth PCRel16 operands are similar to regular branch targets, but only
1701+
// negative values are allowed for concrete immediates as signing instr
1702+
// should be in a lower address.
1703+
if (!isImm())
1704+
return false;
1705+
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1706+
if (!MCE)
1707+
return true;
1708+
int64_t Val = MCE->getValue();
1709+
if (Val & 0b11)
1710+
return false;
1711+
return (Val <= 0) && (Val > -(1 << 18));
1712+
}
1713+
16991714
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
17001715
// Add as immediates when possible. Null MCExpr = 0.
17011716
if (!Expr)
@@ -1997,6 +2012,19 @@ class AArch64Operand : public MCParsedAsmOperand {
19972012
Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
19982013
}
19992014

2015+
void addPAuthPCRelLabel16Operands(MCInst &Inst, unsigned N) const {
2016+
// PC-relative operands don't encode the low bits, so shift them off
2017+
// here. If it's a label, however, just put it on directly as there's
2018+
// not enough information now to do anything.
2019+
assert(N == 1 && "Invalid number of operands!");
2020+
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
2021+
if (!MCE) {
2022+
addExpr(Inst, getImm());
2023+
return;
2024+
}
2025+
Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
2026+
}
2027+
20002028
void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
20012029
// Branch operands don't encode the low bits, so shift them off
20022030
// here. If it's a label, however, just put it on directly as there's

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ static DecodeStatus DecodeFixedPointScaleImm32(MCInst &Inst, unsigned Imm,
165165
static DecodeStatus DecodeFixedPointScaleImm64(MCInst &Inst, unsigned Imm,
166166
uint64_t Address,
167167
const MCDisassembler *Decoder);
168+
static DecodeStatus DecodePCRelLabel16(MCInst &Inst, unsigned Imm,
169+
uint64_t Address,
170+
const MCDisassembler *Decoder);
168171
static DecodeStatus DecodePCRelLabel19(MCInst &Inst, unsigned Imm,
169172
uint64_t Address,
170173
const MCDisassembler *Decoder);
@@ -887,6 +890,21 @@ static DecodeStatus DecodeFixedPointScaleImm64(MCInst &Inst, unsigned Imm,
887890
return Success;
888891
}
889892

893+
static DecodeStatus DecodePCRelLabel16(MCInst &Inst, unsigned Imm,
894+
uint64_t Addr,
895+
const MCDisassembler *Decoder) {
896+
// Immediate is encoded as the top 16-bits of an unsigned 18-bit negative
897+
// PC-relative offset.
898+
int64_t ImmVal = Imm;
899+
if (ImmVal < 0 || ImmVal > (1 << 16))
900+
return Fail;
901+
ImmVal = -ImmVal;
902+
if (!Decoder->tryAddingSymbolicOperand(Inst, (ImmVal << 2), Addr,
903+
/*IsBranch=*/false, 0, 0, 4))
904+
Inst.addOperand(MCOperand::createImm(ImmVal));
905+
return Success;
906+
}
907+
890908
static DecodeStatus DecodePCRelLabel19(MCInst &Inst, unsigned Imm,
891909
uint64_t Addr,
892910
const MCDisassembler *Decoder) {

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class AArch64AsmBackend : public MCAsmBackend {
6767
{"fixup_aarch64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal},
6868
{"fixup_aarch64_movw", 5, 16, 0},
6969
{"fixup_aarch64_pcrel_branch14", 5, 14, PCRelFlagVal},
70+
{"fixup_aarch64_pcrel_branch16", 5, 16, PCRelFlagVal},
7071
{"fixup_aarch64_pcrel_branch19", 5, 19, PCRelFlagVal},
7172
{"fixup_aarch64_pcrel_branch26", 0, 26, PCRelFlagVal},
7273
{"fixup_aarch64_pcrel_call26", 0, 26, PCRelFlagVal}};
@@ -121,6 +122,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
121122

122123
case AArch64::fixup_aarch64_movw:
123124
case AArch64::fixup_aarch64_pcrel_branch14:
125+
case AArch64::fixup_aarch64_pcrel_branch16:
124126
case AArch64::fixup_aarch64_add_imm12:
125127
case AArch64::fixup_aarch64_ldst_imm12_scale1:
126128
case AArch64::fixup_aarch64_ldst_imm12_scale2:
@@ -314,6 +316,17 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target,
314316
if (Value & 0x3)
315317
Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
316318
return (Value >> 2) & 0x3fff;
319+
case AArch64::fixup_aarch64_pcrel_branch16:
320+
// Unsigned PC-relative offset, so invert the negative immediate.
321+
SignedValue = -SignedValue;
322+
Value = static_cast<uint64_t>(SignedValue);
323+
// Check valid 18-bit unsigned range.
324+
if (SignedValue < 0 || SignedValue > ((1 << 18) - 1))
325+
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
326+
// Low two bits are not encoded (4-byte alignment assumed).
327+
if (Value & 0b11)
328+
Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
329+
return (Value >> 2) & 0xffff;
317330
case AArch64::fixup_aarch64_pcrel_branch26:
318331
case AArch64::fixup_aarch64_pcrel_call26:
319332
if (TheTriple.isOSBinFormatCOFF() && !IsResolved && SignedValue != 0) {
@@ -380,6 +393,7 @@ unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) con
380393

381394
case AArch64::fixup_aarch64_movw:
382395
case AArch64::fixup_aarch64_pcrel_branch14:
396+
case AArch64::fixup_aarch64_pcrel_branch16:
383397
case AArch64::fixup_aarch64_add_imm12:
384398
case AArch64::fixup_aarch64_ldst_imm12_scale1:
385399
case AArch64::fixup_aarch64_ldst_imm12_scale2:

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
186186
return R_CLS(LD_PREL_LO19);
187187
case AArch64::fixup_aarch64_pcrel_branch14:
188188
return R_CLS(TSTBR14);
189+
case AArch64::fixup_aarch64_pcrel_branch16:
190+
Ctx.reportError(Fixup.getLoc(),
191+
"relocation of PAC/AUT instructions is not supported");
192+
return ELF::R_AARCH64_NONE;
189193
case AArch64::fixup_aarch64_pcrel_branch19:
190194
return R_CLS(CONDBR19);
191195
default:

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ enum Fixups {
4343
// The high 14 bits of a 21-bit pc-relative immediate.
4444
fixup_aarch64_pcrel_branch14,
4545

46+
// The high 16 bits of a 18-bit unsigned PC-relative immediate. Used by
47+
// pointer authentication, only within a function, so no relocation can be
48+
// generated.
49+
fixup_aarch64_pcrel_branch16,
50+
4651
// The high 19 bits of a 21-bit pc-relative immediate. Same encoding as
4752
// fixup_aarch64_pcrel_adrhi, except this is use by b.cc and generates
4853
// relocations directly when necessary.

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ class AArch64MCCodeEmitter : public MCCodeEmitter {
8888
SmallVectorImpl<MCFixup> &Fixups,
8989
const MCSubtargetInfo &STI) const;
9090

91+
/// getPAuthPCRelOpValue - Return the encoded value for a pointer
92+
/// authentication pc-relative operand.
93+
uint32_t getPAuthPCRelOpValue(const MCInst &MI, unsigned OpIdx,
94+
SmallVectorImpl<MCFixup> &Fixups,
95+
const MCSubtargetInfo &STI) const;
96+
9197
/// getLoadLiteralOpValue - Return the encoded value for a load-literal
9298
/// pc-relative address.
9399
uint32_t getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx,
@@ -327,6 +333,29 @@ uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue(
327333
return 0;
328334
}
329335

336+
/// getPAuthPCRelOpValue - Return the encoded value for a pointer
337+
/// authentication pc-relative operand.
338+
uint32_t
339+
AArch64MCCodeEmitter::getPAuthPCRelOpValue(const MCInst &MI, unsigned OpIdx,
340+
SmallVectorImpl<MCFixup> &Fixups,
341+
const MCSubtargetInfo &STI) const {
342+
const MCOperand &MO = MI.getOperand(OpIdx);
343+
344+
// If the destination is an immediate, invert sign as it's a negative value
345+
// that should be encoded as unsigned
346+
if (MO.isImm())
347+
return -(MO.getImm());
348+
assert(MO.isExpr() && "Unexpected target type!");
349+
350+
MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch16);
351+
Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
352+
353+
++MCNumFixups;
354+
355+
// All of the information is in the fixup.
356+
return 0;
357+
}
358+
330359
/// getLoadLiteralOpValue - Return the encoded value for a load-literal
331360
/// pc-relative address.
332361
uint32_t

0 commit comments

Comments
 (0)