Skip to content

Commit

Permalink
[AArch64] Enable ARMv8.3-A pointer authentication
Browse files Browse the repository at this point in the history
Add assembler and disassembler support for the ARMv8.3-A pointer
authentication instructions.

Differential Revision: https://reviews.llvm.org/D36517

llvm-svn: 310709
  • Loading branch information
sparker-arm committed Aug 11, 2017
1 parent d7129f9 commit 6d42de7
Show file tree
Hide file tree
Showing 11 changed files with 663 additions and 7 deletions.
128 changes: 128 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ def GPR32as64 : RegisterOperand<GPR32> {
// are encoded as the eight bit value 'abcdefgh'.
def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }

// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
def SImm10s8Operand : AsmOperandClass {
let Name = "SImm10s8";
let DiagnosticType = "InvalidMemoryIndexedSImm10";
}

//===----------------------------------------------------------------------===//
// Operand Definitions.
Expand Down Expand Up @@ -216,6 +221,12 @@ def adrlabel : Operand<i64> {
let ParserMatchClass = AdrOperand;
}

def simm10Scaled : Operand<i64> {
let ParserMatchClass = SImm10s8Operand;
let DecoderMethod = "DecodeSImm<10>";
let PrintMethod = "printImmScale<8>";
}

// simm9 predicate - True if the immediate is in the range [-256, 255].
def SImm9Operand : AsmOperandClass {
let Name = "SImm9";
Expand Down Expand Up @@ -913,6 +924,17 @@ class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
let Inst{7-5} = opc;
}

class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
: SimpleSystemI<0, (ins), asm, "", pattern>,
Sched<[]> {
bits<4> CRm;
let CRm = 0b0011;
let Inst{31-12} = 0b11010101000000110010;
let Inst{11-8} = CRm;
let Inst{7-5} = op2;
let Inst{4-0} = 0b11111;
}

// MRS/MSR system instructions. These have different operand classes because
// a different subset of registers can be accessed through each instruction.
def MRSSystemRegisterOperand : AsmOperandClass {
Expand Down Expand Up @@ -1110,6 +1132,72 @@ class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
let Inst{4-0} = Rt;
}

class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
list<dag> pattern>
: I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
let Inst{31-25} = 0b1101011;
let Inst{20-11} = 0b1111100001;
let Inst{10} = M;
let Inst{4-0} = 0b11111;
}

class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
: AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
bits<5> Rn;
bits<5> Rm;
let Inst{24-22} = 0b100;
let Inst{21} = op;
let Inst{9-5} = Rn;
let Inst{4-0} = Rm;
}

class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
: AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
bits<5> Rn;
let Inst{24} = 0;
let Inst{23-21} = opc;
let Inst{9-5} = Rn;
}

class AuthReturn<bits<3> op, bits<1> M, string asm>
: AuthBase<M, (outs), (ins), asm, "", []> {
let Inst{24} = 0;
let Inst{23-21} = op;
let Inst{9-0} = 0b1111111111;
}

let mayLoad = 1 in
class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
string operands, string cstr, Operand opr>
: I<oops, iops, asm, operands, "", []>, Sched<[]> {
bits<10> offset;
bits<5> Rn;
bits<5> Rt;
let Inst{31-24} = 0b11111000;
let Inst{23} = M;
let Inst{22} = offset{9};
let Inst{21} = 1;
let Inst{20-12} = offset{8-0};
let Inst{11} = W;
let Inst{10} = 1;
let Inst{9-5} = Rn;
let Inst{4-0} = Rt;
}

multiclass AuthLoad<bit M, string asm, Operand opr> {
def indexed : BaseAuthLoad<M, 0, (outs GPR64:$Rt), (ins GPR64sp:$Rn, opr:$offset),
asm, "\t$Rt, [$Rn, $offset]", "", opr>;
def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
(ins GPR64sp:$Rn, opr:$offset),
asm, "\t$Rt, [$Rn, $offset]!",
"$Rn = $wback,@earlyclobber $wback", opr> {
let DecoderMethod = "DecodeAuthLoadWriteback";
}

def : InstAlias<asm # "\t$Rt, [$Rn]",
(!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
}

//---
// Conditional branch instruction.
//---
Expand Down Expand Up @@ -1332,6 +1420,46 @@ class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
let Inst{31} = 1;
}

class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
: I<(outs GPR64:$Rd), (ins GPR64sp:$Rn), asm, "\t$Rd, $Rn", "",
[]>,
Sched<[WriteI, ReadI]> {
bits<5> Rd;
bits<5> Rn;
let Inst{31-15} = 0b11011010110000010;
let Inst{14-12} = opcode_prefix;
let Inst{11-10} = opcode;
let Inst{9-5} = Rn;
let Inst{4-0} = Rd;
}

class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
: I<(outs GPR64:$Rd), (ins), asm, "\t$Rd", "", []>, Sched<[]> {
bits<5> Rd;
let Inst{31-15} = 0b11011010110000010;
let Inst{14-12} = opcode_prefix;
let Inst{11-10} = opcode;
let Inst{9-5} = 0b11111;
let Inst{4-0} = Rd;
}

class SignAuthTwoOperand<bits<4> opc, string asm,
SDPatternOperator OpNode>
: I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
asm, "\t$Rd, $Rn, $Rm", "",
[(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
Sched<[WriteI, ReadI, ReadI]> {
bits<5> Rd;
bits<5> Rn;
bits<5> Rm;
let Inst{31-21} = 0b10011010110;
let Inst{20-16} = Rm;
let Inst{15-14} = 0b00;
let Inst{13-10} = opc;
let Inst{9-5} = Rn;
let Inst{4-0} = Rd;
}

//---
// Basic two-operand data processing instructions.
//---
Expand Down
66 changes: 66 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,72 @@ let Predicates = [HasRCPC] in {
def LDAPRX : RCPCLoad<0b11, "ldapr", GPR64>;
}

let Predicates = [HasV8_3a] in {
// v8.3a Pointer Authentication
let Uses = [LR], Defs = [LR] in {
def PACIAZ : SystemNoOperands<0b000, "paciaz">;
def PACIBZ : SystemNoOperands<0b010, "pacibz">;
def AUTIAZ : SystemNoOperands<0b100, "autiaz">;
def AUTIBZ : SystemNoOperands<0b110, "autibz">;
}
let Uses = [LR, SP], Defs = [LR] in {
def PACIASP : SystemNoOperands<0b001, "paciasp">;
def PACIBSP : SystemNoOperands<0b011, "pacibsp">;
def AUTIASP : SystemNoOperands<0b101, "autiasp">;
def AUTIBSP : SystemNoOperands<0b111, "autibsp">;
}
let Uses = [X16, X17], Defs = [X17], CRm = 0b0001 in {
def PACIA1716 : SystemNoOperands<0b000, "pacia1716">;
def PACIB1716 : SystemNoOperands<0b010, "pacib1716">;
def AUTIA1716 : SystemNoOperands<0b100, "autia1716">;
def AUTIB1716 : SystemNoOperands<0b110, "autib1716">;
}

let Uses = [LR], Defs = [LR], CRm = 0b0000 in {
def XPACLRI : SystemNoOperands<0b111, "xpaclri">;
}

multiclass SignAuth<bits<3> prefix, bits<3> prefix_z, string asm> {
def IA : SignAuthOneData<prefix, 0b00, !strconcat(asm, "ia")>;
def IB : SignAuthOneData<prefix, 0b01, !strconcat(asm, "ib")>;
def DA : SignAuthOneData<prefix, 0b10, !strconcat(asm, "da")>;
def DB : SignAuthOneData<prefix, 0b11, !strconcat(asm, "db")>;
def IZA : SignAuthZero<prefix_z, 0b00, !strconcat(asm, "iza")>;
def DZA : SignAuthZero<prefix_z, 0b10, !strconcat(asm, "dza")>;
def IZB : SignAuthZero<prefix_z, 0b01, !strconcat(asm, "izb")>;
def DZB : SignAuthZero<prefix_z, 0b11, !strconcat(asm, "dzb")>;
}

defm PAC : SignAuth<0b000, 0b010, "pac">;
defm AUT : SignAuth<0b001, 0b011, "aut">;

def XPACI : SignAuthZero<0b100, 0b00, "xpaci">;
def XPACD : SignAuthZero<0b100, 0b01, "xpacd">;
def PACGA : SignAuthTwoOperand<0b1100, "pacga", null_frag>;

// Combined Instructions
def BRAA : AuthBranchTwoOperands<0, 0, "braa">;
def BRAB : AuthBranchTwoOperands<0, 1, "brab">;
def BLRAA : AuthBranchTwoOperands<1, 0, "blraa">;
def BLRAB : AuthBranchTwoOperands<1, 1, "blrab">;

def BRAAZ : AuthOneOperand<0b000, 0, "braaz">;
def BRABZ : AuthOneOperand<0b000, 1, "brabz">;
def BLRAAZ : AuthOneOperand<0b001, 0, "blraaz">;
def BLRABZ : AuthOneOperand<0b001, 1, "blrabz">;

let isReturn = 1 in {
def RETAA : AuthReturn<0b010, 0, "retaa">;
def RETAB : AuthReturn<0b010, 1, "retab">;
def ERETAA : AuthReturn<0b100, 0, "eretaa">;
def ERETAB : AuthReturn<0b100, 1, "eretab">;
}

defm LDRAA : AuthLoad<0, "ldraa", simm10Scaled>;
defm LDRAB : AuthLoad<1, "ldrab", simm10Scaled>;

} // HasV8_3A

def : InstAlias<"clrex", (CLREX 0xf)>;
def : InstAlias<"isb", (ISB 0xf)>;

Expand Down
12 changes: 6 additions & 6 deletions llvm/lib/Target/AArch64/AArch64SchedThunderX.td
Original file line number Diff line number Diff line change
Expand Up @@ -239,20 +239,20 @@ def : ReadAdvance<ReadID, 1, [WriteImm, WriteI,
//---
// Branch
//---
def : InstRW<[THXT8XWriteBR], (instregex "^B")>;
def : InstRW<[THXT8XWriteBR], (instregex "^BL")>;
def : InstRW<[THXT8XWriteBR], (instregex "^B.*")>;
def : InstRW<[THXT8XWriteBR], (instregex "^B$")>;
def : InstRW<[THXT8XWriteBR], (instregex "^BL$")>;
def : InstRW<[THXT8XWriteBR], (instregex "^B..$")>;
def : InstRW<[THXT8XWriteBR], (instregex "^CBNZ")>;
def : InstRW<[THXT8XWriteBR], (instregex "^CBZ")>;
def : InstRW<[THXT8XWriteBR], (instregex "^TBNZ")>;
def : InstRW<[THXT8XWriteBR], (instregex "^TBZ")>;
def : InstRW<[THXT8XWriteBRR], (instregex "^BR")>;
def : InstRW<[THXT8XWriteBRR], (instregex "^BLR")>;
def : InstRW<[THXT8XWriteBRR], (instregex "^BR$")>;
def : InstRW<[THXT8XWriteBRR], (instregex "^BLR$")>;

//---
// Ret
//---
def : InstRW<[THXT8XWriteRET], (instregex "^RET")>;
def : InstRW<[THXT8XWriteRET], (instregex "^RET$")>;

//---
// Miscellaneous
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AArch64/AArch64SchedThunderX2T99.td
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ def : WriteRes<WriteAtomic, []> {
//---
def : InstRW<[THX2T99Write_1Cyc_I2], (instrs B, BL, BR, BLR)>;
def : InstRW<[THX2T99Write_1Cyc_I2], (instrs RET)>;
def : InstRW<[THX2T99Write_1Cyc_I2], (instregex "^B.*")>;
def : InstRW<[THX2T99Write_1Cyc_I2], (instregex "^B..$")>;
def : InstRW<[THX2T99Write_1Cyc_I2],
(instregex "^CBZ", "^CBNZ", "^TBZ", "^TBNZ")>;

Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/Target/AArch64/AArch64SystemOperands.td
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,21 @@ def : RWSysReg<"VDISR_EL2", 0b11, 0b100, 0b1100, 0b0001, 0b001>;
def : RWSysReg<"VSESR_EL2", 0b11, 0b100, 0b0101, 0b0010, 0b011>;
}

// v8.3a "Pointer authentication extension" registers
// Op0 Op1 CRn CRm Op2
let Requires = [{ {AArch64::HasV8_3aOps} }] in {
def : RWSysReg<"APIAKeyLo_EL1", 0b11, 0b000, 0b0010, 0b0001, 0b000>;
def : RWSysReg<"APIAKeyHi_EL1", 0b11, 0b000, 0b0010, 0b0001, 0b001>;
def : RWSysReg<"APIBKeyLo_EL1", 0b11, 0b000, 0b0010, 0b0001, 0b010>;
def : RWSysReg<"APIBKeyHi_EL1", 0b11, 0b000, 0b0010, 0b0001, 0b011>;
def : RWSysReg<"APDAKeyLo_EL1", 0b11, 0b000, 0b0010, 0b0010, 0b000>;
def : RWSysReg<"APDAKeyHi_EL1", 0b11, 0b000, 0b0010, 0b0010, 0b001>;
def : RWSysReg<"APDBKeyLo_EL1", 0b11, 0b000, 0b0010, 0b0010, 0b010>;
def : RWSysReg<"APDBKeyHi_EL1", 0b11, 0b000, 0b0010, 0b0010, 0b011>;
def : RWSysReg<"APGAKeyLo_EL1", 0b11, 0b000, 0b0010, 0b0011, 0b000>;
def : RWSysReg<"APGAKeyHi_EL1", 0b11, 0b000, 0b0010, 0b0011, 0b001>;
}

// Cyclone specific system registers
// Op0 Op1 CRn CRm Op2
let Requires = [{ {AArch64::ProcCyclone} }] in
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,15 @@ class AArch64Operand : public MCParsedAsmOperand {
int64_t Val = MCE->getValue();
return (Val >= -256 && Val < 256);
}
bool isSImm10s8() const {
if (!isImm())
return false;
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
if (!MCE)
return false;
int64_t Val = MCE->getValue();
return (Val >= -4096 && Val < 4089 && (Val & 7) == 0);
}
bool isSImm7s4() const {
if (!isImm())
return false;
Expand Down Expand Up @@ -1213,6 +1222,12 @@ class AArch64Operand : public MCParsedAsmOperand {
Inst.addOperand(MCOperand::createImm(MCE->getValue()));
}

void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
}

void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Expand Down Expand Up @@ -3299,6 +3314,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
"expected compatible register or floating-point constant");
case Match_InvalidMemoryIndexedSImm9:
return Error(Loc, "index must be an integer in range [-256, 255].");
case Match_InvalidMemoryIndexedSImm10:
return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
case Match_InvalidMemoryIndexed4SImm7:
return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
case Match_InvalidMemoryIndexed8SImm7:
Expand Down Expand Up @@ -3766,6 +3783,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidMemoryIndexed8SImm7:
case Match_InvalidMemoryIndexed16SImm7:
case Match_InvalidMemoryIndexedSImm9:
case Match_InvalidMemoryIndexedSImm10:
case Match_InvalidImm0_1:
case Match_InvalidImm0_7:
case Match_InvalidImm0_15:
Expand Down
42 changes: 42 additions & 0 deletions llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ static DecodeStatus DecodeXSeqPairsClassRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Addr,
const void *Decoder);
template<int Bits>
static DecodeStatus DecodeSImm(llvm::MCInst &Inst, uint64_t Imm,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeAuthLoadWriteback(llvm::MCInst &Inst, uint32_t insn,
uint64_t Address,
const void *Decoder);

static bool Check(DecodeStatus &Out, DecodeStatus In) {
switch (In) {
Expand Down Expand Up @@ -1588,3 +1594,39 @@ static DecodeStatus DecodeXSeqPairsClassRegisterClass(MCInst &Inst,
AArch64::XSeqPairsClassRegClassID,
RegNo, Addr, Decoder);
}

template<int Bits>
static DecodeStatus DecodeSImm(llvm::MCInst &Inst, uint64_t Imm,
uint64_t Address, const void *Decoder) {
if (Imm & ~((1LL << Bits) - 1))
return Fail;

// Imm is a signed immediate, so sign extend it.
if (Imm & (1 << (Bits - 1)))
Imm |= ~((1LL << Bits) - 1);

Inst.addOperand(MCOperand::createImm(Imm));
return Success;
}

static DecodeStatus DecodeAuthLoadWriteback(llvm::MCInst &Inst, uint32_t insn,
uint64_t Address,
const void *Decoder) {
unsigned Rt = fieldFromInstruction(insn, 0, 5);
unsigned Rn = fieldFromInstruction(insn, 5, 5);
unsigned Imm9 = fieldFromInstruction(insn, 12, 9);
unsigned S = fieldFromInstruction(insn, 22, 1);

unsigned Imm = Imm9 | (S << 9);

// Address writeback
DecodeGPR64spRegisterClass(Inst, Rn, Address, Decoder);
// Destination
DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder);
// Address
DecodeGPR64spRegisterClass(Inst, Rn, Address, Decoder);
// Offset
DecodeSImm<10>(Inst, Imm, Address, Decoder);

return Success;
}
Loading

0 comments on commit 6d42de7

Please sign in to comment.