mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-04 21:31:03 +00:00
[AArch64] Add v8.1a atomic instructions
Patch by: Tom Coxon Reviewers: t.p.northover Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D8501 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238818 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
01cf1d3ef3
commit
1e7e9b1881
@ -8841,6 +8841,178 @@ class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
|
||||
[(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
|
||||
} // end of 'let Predicates = [HasCrypto]'
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// v8.1 atomic instructions extension:
|
||||
// * CAS
|
||||
// * CASP
|
||||
// * SWP
|
||||
// * LDOPregister<OP>, and aliases STOPregister<OP>
|
||||
|
||||
// Instruction encodings:
|
||||
//
|
||||
// 31 30|29 24|23|22|21|20 16|15|14 10|9 5|4 0
|
||||
// CAS SZ |001000|1 |A |1 |Rs |R |11111 |Rn |Rt
|
||||
// CASP 0|SZ|001000|0 |A |1 |Rs |R |11111 |Rn |Rt
|
||||
// SWP SZ |111000|A |R |1 |Rs |1 |OPC|00|Rn |Rt
|
||||
// LD SZ |111000|A |R |1 |Rs |0 |OPC|00|Rn |Rt
|
||||
// ST SZ |111000|A |R |1 |Rs |0 |OPC|00|Rn |11111
|
||||
|
||||
// Instruction syntax:
|
||||
//
|
||||
// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
|
||||
// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
|
||||
// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
|
||||
// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
|
||||
// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
|
||||
// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
|
||||
// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
|
||||
// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
|
||||
// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
|
||||
// ST<OP>{<order>} <Xs>, [<Xn|SP>]
|
||||
|
||||
let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
|
||||
class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
|
||||
string cstr, list<dag> pattern>
|
||||
: I<oops, iops, asm, operands, cstr, pattern> {
|
||||
bits<2> Sz;
|
||||
bit NP;
|
||||
bit Acq;
|
||||
bit Rel;
|
||||
bits<5> Rs;
|
||||
bits<5> Rn;
|
||||
bits<5> Rt;
|
||||
let Inst{31-30} = Sz;
|
||||
let Inst{29-24} = 0b001000;
|
||||
let Inst{23} = NP;
|
||||
let Inst{22} = Acq;
|
||||
let Inst{21} = 0b1;
|
||||
let Inst{20-16} = Rs;
|
||||
let Inst{15} = Rel;
|
||||
let Inst{14-10} = 0b11111;
|
||||
let Inst{9-5} = Rn;
|
||||
let Inst{4-0} = Rt;
|
||||
}
|
||||
|
||||
class BaseCAS<string order, string size, RegisterClass RC>
|
||||
: BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
|
||||
"cas" # order # size, "\t$Rs, $Rt, [$Rn]",
|
||||
"$out = $Rs",[]> {
|
||||
let NP = 1;
|
||||
}
|
||||
|
||||
multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
|
||||
let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS<order, "b", GPR32>;
|
||||
let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS<order, "h", GPR32>;
|
||||
let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS<order, "", GPR32>;
|
||||
let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS<order, "", GPR64>;
|
||||
}
|
||||
|
||||
class BaseCASP<string order, string size, RegisterOperand RC>
|
||||
: BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
|
||||
"casp" # order # size, "\t$Rs, $Rt, [$Rn]",
|
||||
"$out = $Rs",[]> {
|
||||
let NP = 0;
|
||||
}
|
||||
|
||||
multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
|
||||
let Sz = 0b00, Acq = Acq, Rel = Rel in
|
||||
def s : BaseCASP<order, "", WSeqPairClassOperand>;
|
||||
let Sz = 0b01, Acq = Acq, Rel = Rel in
|
||||
def d : BaseCASP<order, "", XSeqPairClassOperand>;
|
||||
}
|
||||
|
||||
let Predicates = [HasV8_1a] in
|
||||
class BaseSWP<string order, string size, RegisterClass RC>
|
||||
: I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
|
||||
"\t$Rs, $Rt, [$Rn]","",[]> {
|
||||
bits<2> Sz;
|
||||
bit Acq;
|
||||
bit Rel;
|
||||
bits<5> Rs;
|
||||
bits<3> opc = 0b000;
|
||||
bits<5> Rn;
|
||||
bits<5> Rt;
|
||||
let Inst{31-30} = Sz;
|
||||
let Inst{29-24} = 0b111000;
|
||||
let Inst{23} = Acq;
|
||||
let Inst{22} = Rel;
|
||||
let Inst{21} = 0b1;
|
||||
let Inst{20-16} = Rs;
|
||||
let Inst{15} = 0b1;
|
||||
let Inst{14-12} = opc;
|
||||
let Inst{11-10} = 0b00;
|
||||
let Inst{9-5} = Rn;
|
||||
let Inst{4-0} = Rt;
|
||||
}
|
||||
|
||||
multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
|
||||
let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP<order, "b", GPR32>;
|
||||
let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP<order, "h", GPR32>;
|
||||
let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP<order, "", GPR32>;
|
||||
let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP<order, "", GPR64>;
|
||||
}
|
||||
|
||||
let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
|
||||
class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
|
||||
: I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
|
||||
"\t$Rs, $Rt, [$Rn]","",[]> {
|
||||
bits<2> Sz;
|
||||
bit Acq;
|
||||
bit Rel;
|
||||
bits<5> Rs;
|
||||
bits<3> opc;
|
||||
bits<5> Rn;
|
||||
bits<5> Rt;
|
||||
let Inst{31-30} = Sz;
|
||||
let Inst{29-24} = 0b111000;
|
||||
let Inst{23} = Acq;
|
||||
let Inst{22} = Rel;
|
||||
let Inst{21} = 0b1;
|
||||
let Inst{20-16} = Rs;
|
||||
let Inst{15} = 0b0;
|
||||
let Inst{14-12} = opc;
|
||||
let Inst{11-10} = 0b00;
|
||||
let Inst{9-5} = Rn;
|
||||
let Inst{4-0} = Rt;
|
||||
}
|
||||
|
||||
multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
|
||||
string order> {
|
||||
let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
|
||||
def b : BaseLDOPregister<op, order, "b", GPR32>;
|
||||
let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
|
||||
def h : BaseLDOPregister<op, order, "h", GPR32>;
|
||||
let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
|
||||
def s : BaseLDOPregister<op, order, "", GPR32>;
|
||||
let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
|
||||
def d : BaseLDOPregister<op, order, "", GPR64>;
|
||||
}
|
||||
|
||||
let Predicates = [HasV8_1a] in
|
||||
class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
|
||||
Instruction inst> :
|
||||
InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
|
||||
|
||||
multiclass STOPregister<string asm, string instr> {
|
||||
def : BaseSTOPregister<asm # "lb", GPR32, WZR,
|
||||
!cast<Instruction>(instr # "Lb")>;
|
||||
def : BaseSTOPregister<asm # "lh", GPR32, WZR,
|
||||
!cast<Instruction>(instr # "Lh")>;
|
||||
def : BaseSTOPregister<asm # "l", GPR32, WZR,
|
||||
!cast<Instruction>(instr # "Ls")>;
|
||||
def : BaseSTOPregister<asm # "l", GPR64, XZR,
|
||||
!cast<Instruction>(instr # "Ld")>;
|
||||
def : BaseSTOPregister<asm # "b", GPR32, WZR,
|
||||
!cast<Instruction>(instr # "b")>;
|
||||
def : BaseSTOPregister<asm # "h", GPR32, WZR,
|
||||
!cast<Instruction>(instr # "h")>;
|
||||
def : BaseSTOPregister<asm, GPR32, WZR,
|
||||
!cast<Instruction>(instr # "s")>;
|
||||
def : BaseSTOPregister<asm, GPR64, XZR,
|
||||
!cast<Instruction>(instr # "d")>;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Allow the size specifier tokens to be upper case, not just lower.
|
||||
def : TokenAlias<".8B", ".8b">;
|
||||
def : TokenAlias<".4H", ".4h">;
|
||||
|
@ -745,6 +745,74 @@ def CRC32CHrr : BaseCRC32<0, 0b01, 1, GPR32, int_aarch64_crc32ch, "crc32ch">;
|
||||
def CRC32CWrr : BaseCRC32<0, 0b10, 1, GPR32, int_aarch64_crc32cw, "crc32cw">;
|
||||
def CRC32CXrr : BaseCRC32<1, 0b11, 1, GPR64, int_aarch64_crc32cx, "crc32cx">;
|
||||
|
||||
// v8.1 atomic CAS
|
||||
defm CAS : CompareAndSwap<0, 0, "">;
|
||||
defm CASA : CompareAndSwap<1, 0, "a">;
|
||||
defm CASL : CompareAndSwap<0, 1, "l">;
|
||||
defm CASAL : CompareAndSwap<1, 1, "al">;
|
||||
|
||||
// v8.1 atomic CASP
|
||||
defm CASP : CompareAndSwapPair<0, 0, "">;
|
||||
defm CASPA : CompareAndSwapPair<1, 0, "a">;
|
||||
defm CASPL : CompareAndSwapPair<0, 1, "l">;
|
||||
defm CASPAL : CompareAndSwapPair<1, 1, "al">;
|
||||
|
||||
// v8.1 atomic SWP
|
||||
defm SWP : Swap<0, 0, "">;
|
||||
defm SWPA : Swap<1, 0, "a">;
|
||||
defm SWPL : Swap<0, 1, "l">;
|
||||
defm SWPAL : Swap<1, 1, "al">;
|
||||
|
||||
// v8.1 atomic LD<OP>(register). Performs load and then ST<OP>(register)
|
||||
defm LDADD : LDOPregister<0b000, "add", 0, 0, "">;
|
||||
defm LDADDA : LDOPregister<0b000, "add", 1, 0, "a">;
|
||||
defm LDADDL : LDOPregister<0b000, "add", 0, 1, "l">;
|
||||
defm LDADDAL : LDOPregister<0b000, "add", 1, 1, "al">;
|
||||
|
||||
defm LDCLR : LDOPregister<0b001, "clr", 0, 0, "">;
|
||||
defm LDCLRA : LDOPregister<0b001, "clr", 1, 0, "a">;
|
||||
defm LDCLRL : LDOPregister<0b001, "clr", 0, 1, "l">;
|
||||
defm LDCLRAL : LDOPregister<0b001, "clr", 1, 1, "al">;
|
||||
|
||||
defm LDEOR : LDOPregister<0b010, "eor", 0, 0, "">;
|
||||
defm LDEORA : LDOPregister<0b010, "eor", 1, 0, "a">;
|
||||
defm LDEORL : LDOPregister<0b010, "eor", 0, 1, "l">;
|
||||
defm LDEORAL : LDOPregister<0b010, "eor", 1, 1, "al">;
|
||||
|
||||
defm LDSET : LDOPregister<0b011, "set", 0, 0, "">;
|
||||
defm LDSETA : LDOPregister<0b011, "set", 1, 0, "a">;
|
||||
defm LDSETL : LDOPregister<0b011, "set", 0, 1, "l">;
|
||||
defm LDSETAL : LDOPregister<0b011, "set", 1, 1, "al">;
|
||||
|
||||
defm LDSMAX : LDOPregister<0b100, "smax", 0, 0, "">;
|
||||
defm LDSMAXA : LDOPregister<0b100, "smax", 1, 0, "a">;
|
||||
defm LDSMAXL : LDOPregister<0b100, "smax", 0, 1, "l">;
|
||||
defm LDSMAXAL : LDOPregister<0b100, "smax", 1, 1, "al">;
|
||||
|
||||
defm LDSMIN : LDOPregister<0b101, "smin`", 0, 0, "">;
|
||||
defm LDSMINA : LDOPregister<0b101, "smin", 1, 0, "a">;
|
||||
defm LDSMINL : LDOPregister<0b101, "smin", 0, 1, "l">;
|
||||
defm LDSMINAL : LDOPregister<0b101, "smin", 1, 1, "al">;
|
||||
|
||||
defm LDUMAX : LDOPregister<0b110, "umax", 0, 0, "">;
|
||||
defm LDUMAXA : LDOPregister<0b110, "umax", 1, 0, "a">;
|
||||
defm LDUMAXL : LDOPregister<0b110, "umax", 0, 1, "l">;
|
||||
defm LDUMAXAL : LDOPregister<0b110, "umax", 1, 1, "al">;
|
||||
|
||||
defm LDUMIN : LDOPregister<0b111, "umin", 0, 0, "">;
|
||||
defm LDUMINA : LDOPregister<0b111, "umin", 1, 0, "a">;
|
||||
defm LDUMINL : LDOPregister<0b111, "umin", 0, 1, "l">;
|
||||
defm LDUMINAL : LDOPregister<0b111, "umin", 1, 1, "al">;
|
||||
|
||||
// v8.1 atomic ST<OP>(register) as aliases to "LD<OP>(register) when Rt=xZR"
|
||||
defm : STOPregister<"stadd","LDADD">; // STADDx
|
||||
defm : STOPregister<"stclr","LDCLR">; // STCLRx
|
||||
defm : STOPregister<"steor","LDEOR">; // STEORx
|
||||
defm : STOPregister<"stset","LDSET">; // STSETx
|
||||
defm : STOPregister<"stsmax","LDSMAX">;// STSMAXx
|
||||
defm : STOPregister<"stsmin","LDSMIN">;// STSMINx
|
||||
defm : STOPregister<"stumax","LDUMAX">;// STUMAXx
|
||||
defm : STOPregister<"stumin","LDUMIN">;// STUMINx
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Logical instructions.
|
||||
|
@ -26,8 +26,12 @@ let Namespace = "AArch64" in {
|
||||
def hsub : SubRegIndex<16>;
|
||||
def ssub : SubRegIndex<32>;
|
||||
def dsub : SubRegIndex<32>;
|
||||
def sube32 : SubRegIndex<32>;
|
||||
def subo32 : SubRegIndex<32>;
|
||||
def qhisub : SubRegIndex<64>;
|
||||
def qsub : SubRegIndex<64>;
|
||||
def sube64 : SubRegIndex<64>;
|
||||
def subo64 : SubRegIndex<64>;
|
||||
// Note: Code depends on these having consecutive numbers
|
||||
def dsub0 : SubRegIndex<64>;
|
||||
def dsub1 : SubRegIndex<64>;
|
||||
@ -592,3 +596,40 @@ def FPR16Op : RegisterOperand<FPR16, "printOperand">;
|
||||
def FPR32Op : RegisterOperand<FPR32, "printOperand">;
|
||||
def FPR64Op : RegisterOperand<FPR64, "printOperand">;
|
||||
def FPR128Op : RegisterOperand<FPR128, "printOperand">;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ARMv8.1a atomic CASP register operands
|
||||
|
||||
|
||||
def WSeqPairs : RegisterTuples<[sube32, subo32],
|
||||
[(rotl GPR32, 0), (rotl GPR32, 1)]>;
|
||||
def XSeqPairs : RegisterTuples<[sube64, subo64],
|
||||
[(rotl GPR64, 0), (rotl GPR64, 1)]>;
|
||||
|
||||
def WSeqPairsClass : RegisterClass<"AArch64", [untyped], 32,
|
||||
(add WSeqPairs)>{
|
||||
let Size = 64;
|
||||
}
|
||||
def XSeqPairsClass : RegisterClass<"AArch64", [untyped], 64,
|
||||
(add XSeqPairs)>{
|
||||
let Size = 128;
|
||||
}
|
||||
|
||||
|
||||
let RenderMethod = "addRegOperands", ParserMethod="tryParseGPRSeqPair" in {
|
||||
def WSeqPairsAsmOperandClass : AsmOperandClass { let Name = "WSeqPair"; }
|
||||
def XSeqPairsAsmOperandClass : AsmOperandClass { let Name = "XSeqPair"; }
|
||||
}
|
||||
|
||||
def WSeqPairClassOperand :
|
||||
RegisterOperand<WSeqPairsClass, "printGPRSeqPairsClassOperand<32>"> {
|
||||
let ParserMatchClass = WSeqPairsAsmOperandClass;
|
||||
}
|
||||
def XSeqPairClassOperand :
|
||||
RegisterOperand<XSeqPairsClass, "printGPRSeqPairsClassOperand<64>"> {
|
||||
let ParserMatchClass = XSeqPairsAsmOperandClass;
|
||||
}
|
||||
|
||||
|
||||
//===----- END: v8.1a atomic CASP register operands -----------------------===//
|
||||
|
@ -107,6 +107,7 @@ private:
|
||||
OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
|
||||
OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
|
||||
bool tryParseVectorRegister(OperandVector &Operands);
|
||||
OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
|
||||
|
||||
public:
|
||||
enum AArch64MatchResultTy {
|
||||
@ -875,6 +876,16 @@ public:
|
||||
return Kind == k_Register && !Reg.isVector &&
|
||||
AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
|
||||
}
|
||||
bool isWSeqPair() const {
|
||||
return Kind == k_Register && !Reg.isVector &&
|
||||
AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
|
||||
Reg.RegNum);
|
||||
}
|
||||
bool isXSeqPair() const {
|
||||
return Kind == k_Register && !Reg.isVector &&
|
||||
AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
|
||||
Reg.RegNum);
|
||||
}
|
||||
|
||||
bool isGPR64sp0() const {
|
||||
return Kind == k_Register && !Reg.isVector &&
|
||||
@ -4354,3 +4365,77 @@ unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
|
||||
return Match_Success;
|
||||
return Match_InvalidOperand;
|
||||
}
|
||||
|
||||
|
||||
AArch64AsmParser::OperandMatchResultTy
|
||||
AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
|
||||
|
||||
SMLoc S = getLoc();
|
||||
|
||||
if (getParser().getTok().isNot(AsmToken::Identifier)) {
|
||||
Error(S, "expected register");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
int FirstReg = tryParseRegister();
|
||||
if (FirstReg == -1) {
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
const MCRegisterClass &WRegClass =
|
||||
AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
|
||||
const MCRegisterClass &XRegClass =
|
||||
AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
|
||||
|
||||
bool isXReg = XRegClass.contains(FirstReg),
|
||||
isWReg = WRegClass.contains(FirstReg);
|
||||
if (!isXReg && !isWReg) {
|
||||
Error(S, "expected first even register of a "
|
||||
"consecutive same-size even/odd register pair");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
const MCRegisterInfo *RI = getContext().getRegisterInfo();
|
||||
unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
|
||||
|
||||
if (FirstEncoding & 0x1) {
|
||||
Error(S, "expected first even register of a "
|
||||
"consecutive same-size even/odd register pair");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
SMLoc M = getLoc();
|
||||
if (getParser().getTok().isNot(AsmToken::Comma)) {
|
||||
Error(M, "expected comma");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
// Eat the comma
|
||||
getParser().Lex();
|
||||
|
||||
SMLoc E = getLoc();
|
||||
int SecondReg = tryParseRegister();
|
||||
if (SecondReg ==-1) {
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
|
||||
(isXReg && !XRegClass.contains(SecondReg)) ||
|
||||
(isWReg && !WRegClass.contains(SecondReg))) {
|
||||
Error(E,"expected second odd register of a "
|
||||
"consecutive same-size even/odd register pair");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
unsigned Pair = 0;
|
||||
if(isXReg) {
|
||||
Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
|
||||
&AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
|
||||
} else {
|
||||
Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
|
||||
&AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
|
||||
}
|
||||
|
||||
Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
|
||||
getContext()));
|
||||
|
||||
return MatchOperand_Success;
|
||||
}
|
||||
|
@ -169,6 +169,14 @@ static DecodeStatus DecodeVecShiftL16Imm(llvm::MCInst &Inst, unsigned Imm,
|
||||
uint64_t Addr, const void *Decoder);
|
||||
static DecodeStatus DecodeVecShiftL8Imm(llvm::MCInst &Inst, unsigned Imm,
|
||||
uint64_t Addr, const void *Decoder);
|
||||
static DecodeStatus DecodeWSeqPairsClassRegisterClass(MCInst &Inst,
|
||||
unsigned RegNo,
|
||||
uint64_t Addr,
|
||||
const void *Decoder);
|
||||
static DecodeStatus DecodeXSeqPairsClassRegisterClass(MCInst &Inst,
|
||||
unsigned RegNo,
|
||||
uint64_t Addr,
|
||||
const void *Decoder);
|
||||
|
||||
static bool Check(DecodeStatus &Out, DecodeStatus In) {
|
||||
switch (In) {
|
||||
@ -1543,3 +1551,35 @@ static DecodeStatus DecodeTestAndBranch(llvm::MCInst &Inst, uint32_t insn,
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeGPRSeqPairsClassRegisterClass(MCInst &Inst,
|
||||
unsigned RegClassID,
|
||||
unsigned RegNo,
|
||||
uint64_t Addr,
|
||||
const void *Decoder) {
|
||||
// Register number must be even (see CASP instruction)
|
||||
if (RegNo & 0x1)
|
||||
return Fail;
|
||||
|
||||
unsigned Register = AArch64MCRegisterClasses[RegClassID].getRegister(RegNo);
|
||||
Inst.addOperand(MCOperand::createReg(Register));
|
||||
return Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeWSeqPairsClassRegisterClass(MCInst &Inst,
|
||||
unsigned RegNo,
|
||||
uint64_t Addr,
|
||||
const void *Decoder) {
|
||||
return DecodeGPRSeqPairsClassRegisterClass(Inst,
|
||||
AArch64::WSeqPairsClassRegClassID,
|
||||
RegNo, Addr, Decoder);
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeXSeqPairsClassRegisterClass(MCInst &Inst,
|
||||
unsigned RegNo,
|
||||
uint64_t Addr,
|
||||
const void *Decoder) {
|
||||
return DecodeGPRSeqPairsClassRegisterClass(Inst,
|
||||
AArch64::XSeqPairsClassRegClassID,
|
||||
RegNo, Addr, Decoder);
|
||||
}
|
||||
|
@ -19,5 +19,5 @@
|
||||
type = Library
|
||||
name = AArch64Disassembler
|
||||
parent = AArch64
|
||||
required_libraries = AArch64Info AArch64Utils MC MCDisassembler Support
|
||||
required_libraries = AArch64Desc AArch64Info AArch64Utils MC MCDisassembler Support
|
||||
add_to_library_groups = AArch64
|
||||
|
@ -1113,7 +1113,7 @@ void AArch64InstPrinter::printPrefetchOp(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
unsigned prfop = MI->getOperand(OpNum).getImm();
|
||||
bool Valid;
|
||||
StringRef Name =
|
||||
StringRef Name =
|
||||
AArch64PRFM::PRFMMapper().toString(prfop, STI.getFeatureBits(), Valid);
|
||||
if (Valid)
|
||||
O << Name;
|
||||
@ -1177,6 +1177,23 @@ static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride = 1) {
|
||||
return Reg;
|
||||
}
|
||||
|
||||
template<unsigned size>
|
||||
void AArch64InstPrinter::printGPRSeqPairsClassOperand(const MCInst *MI,
|
||||
unsigned OpNum,
|
||||
const MCSubtargetInfo &STI,
|
||||
raw_ostream &O) {
|
||||
static_assert(size == 64 || size == 32,
|
||||
"Template parameter must be either 32 or 64");
|
||||
unsigned Reg = MI->getOperand(OpNum).getReg();
|
||||
|
||||
unsigned Sube = (size == 32) ? AArch64::sube32 : AArch64::sube64;
|
||||
unsigned Subo = (size == 32) ? AArch64::subo32 : AArch64::subo64;
|
||||
|
||||
unsigned Even = MRI.getSubReg(Reg, Sube);
|
||||
unsigned Odd = MRI.getSubReg(Reg, Subo);
|
||||
O << getRegisterName(Even) << ", " << getRegisterName(Odd);
|
||||
}
|
||||
|
||||
void AArch64InstPrinter::printVectorList(const MCInst *MI, unsigned OpNum,
|
||||
const MCSubtargetInfo &STI,
|
||||
raw_ostream &O,
|
||||
@ -1298,10 +1315,10 @@ void AArch64InstPrinter::printBarrierOption(const MCInst *MI, unsigned OpNo,
|
||||
bool Valid;
|
||||
StringRef Name;
|
||||
if (Opcode == AArch64::ISB)
|
||||
Name = AArch64ISB::ISBMapper().toString(Val, STI.getFeatureBits(),
|
||||
Name = AArch64ISB::ISBMapper().toString(Val, STI.getFeatureBits(),
|
||||
Valid);
|
||||
else
|
||||
Name = AArch64DB::DBarrierMapper().toString(Val, STI.getFeatureBits(),
|
||||
Name = AArch64DB::DBarrierMapper().toString(Val, STI.getFeatureBits(),
|
||||
Valid);
|
||||
if (Valid)
|
||||
O << Name;
|
||||
@ -1337,7 +1354,7 @@ void AArch64InstPrinter::printSystemPStateField(const MCInst *MI, unsigned OpNo,
|
||||
unsigned Val = MI->getOperand(OpNo).getImm();
|
||||
|
||||
bool Valid;
|
||||
StringRef Name =
|
||||
StringRef Name =
|
||||
AArch64PState::PStateMapper().toString(Val, STI.getFeatureBits(), Valid);
|
||||
if (Valid)
|
||||
O << StringRef(Name.str()).upper();
|
||||
|
@ -153,6 +153,10 @@ protected:
|
||||
const MCSubtargetInfo &STI, raw_ostream &O);
|
||||
void printSIMDType10Operand(const MCInst *MI, unsigned OpNum,
|
||||
const MCSubtargetInfo &STI, raw_ostream &O);
|
||||
template<unsigned size>
|
||||
void printGPRSeqPairsClassOperand(const MCInst *MI, unsigned OpNum,
|
||||
const MCSubtargetInfo &STI,
|
||||
raw_ostream &O);
|
||||
};
|
||||
|
||||
class AArch64AppleInstPrinter : public AArch64InstPrinter {
|
||||
|
179
test/MC/AArch64/armv8.1a-atomic.s
Normal file
179
test/MC/AArch64/armv8.1a-atomic.s
Normal file
@ -0,0 +1,179 @@
|
||||
// RUN: not llvm-mc -triple aarch64-none-linux-gnu -mattr=+v8.1a -show-encoding < %s 2> %t | FileCheck %s
|
||||
// RUN: FileCheck --check-prefix=CHECK-ERROR <%t %s
|
||||
.text
|
||||
|
||||
//8 bits
|
||||
casb w0, w1, [x2]
|
||||
casab w0, w1, [x2]
|
||||
caslb w0, w1, [x2]
|
||||
casalb w0, w1, [x2]
|
||||
|
||||
//CHECK: casb w0, w1, [x2] // encoding: [0x41,0x7c,0xa0,0x08]
|
||||
//CHECK: casab w0, w1, [x2] // encoding: [0x41,0x7c,0xe0,0x08]
|
||||
//CHECK: caslb w0, w1, [x2] // encoding: [0x41,0xfc,0xa0,0x08]
|
||||
//CHECK: casalb w0, w1, [x2] // encoding: [0x41,0xfc,0xe0,0x08]
|
||||
|
||||
casb w0, w1, [w2]
|
||||
casalb x0, x1, [x2]
|
||||
//CHECK-ERROR: error: invalid operand for instruction
|
||||
//CHECK-ERROR: casb w0, w1, [w2]
|
||||
//CHECK-ERROR: ^
|
||||
//CHECK-ERROR: error: invalid operand for instruction
|
||||
//CHECK-ERROR: casalb x0, x1, [x2]
|
||||
//CHECK-ERROR: ^
|
||||
|
||||
//16 bits
|
||||
cash w0, w1, [x2]
|
||||
casah w0, w1, [x2]
|
||||
caslh w0, w1, [x2]
|
||||
casalh w0, w1, [x2]
|
||||
|
||||
//CHECK: cash w0, w1, [x2] // encoding: [0x41,0x7c,0xa0,0x48]
|
||||
//CHECK: casah w0, w1, [x2] // encoding: [0x41,0x7c,0xe0,0x48]
|
||||
//CHECK: caslh w0, w1, [x2] // encoding: [0x41,0xfc,0xa0,0x48]
|
||||
//CHECK: casalh w0, w1, [x2] // encoding: [0x41,0xfc,0xe0,0x48]
|
||||
|
||||
//32 bits
|
||||
cas w0, w1, [x2]
|
||||
casa w0, w1, [x2]
|
||||
casl w0, w1, [x2]
|
||||
casal w0, w1, [x2]
|
||||
|
||||
//CHECK: cas w0, w1, [x2] // encoding: [0x41,0x7c,0xa0,0x88]
|
||||
//CHECK: casa w0, w1, [x2] // encoding: [0x41,0x7c,0xe0,0x88]
|
||||
//CHECK: casl w0, w1, [x2] // encoding: [0x41,0xfc,0xa0,0x88]
|
||||
//CHECK: casal w0, w1, [x2] // encoding: [0x41,0xfc,0xe0,0x88]
|
||||
|
||||
cas w0, w1, [w2]
|
||||
casl w0, x1, [x2]
|
||||
|
||||
//CHECK-ERROR: error: invalid operand for instruction
|
||||
//CHECK-ERROR: cas w0, w1, [w2]
|
||||
//CHECK-ERROR: ^
|
||||
//CHECK-ERROR: error: invalid operand for instruction
|
||||
//CHECK-ERROR: casl w0, x1, [x2]
|
||||
//CHECK-ERROR: ^
|
||||
|
||||
//64 bits
|
||||
cas x0, x1, [x2]
|
||||
casa x0, x1, [x2]
|
||||
casl x0, x1, [x2]
|
||||
casal x0, x1, [x2]
|
||||
|
||||
//CHECK: cas x0, x1, [x2] // encoding: [0x41,0x7c,0xa0,0xc8]
|
||||
//CHECK: casa x0, x1, [x2] // encoding: [0x41,0x7c,0xe0,0xc8]
|
||||
//CHECK: casl x0, x1, [x2] // encoding: [0x41,0xfc,0xa0,0xc8]
|
||||
//CHECK: casal x0, x1, [x2] // encoding: [0x41,0xfc,0xe0,0xc8]
|
||||
|
||||
casa x0, x1, [w2]
|
||||
casal x0, w1, [x2]
|
||||
|
||||
//CHECK-ERROR: error: invalid operand for instruction
|
||||
//CHECK-ERROR: casa x0, x1, [w2]
|
||||
//CHECK-ERROR: ^
|
||||
//CHECK-ERROR: error: invalid operand for instruction
|
||||
//CHECK-ERROR: casal x0, w1, [x2]
|
||||
//CHECK-ERROR: ^
|
||||
|
||||
// LD<OP> intructions
|
||||
ldadda x0, x1, [x2]
|
||||
ldclrl x0, x1, [x2]
|
||||
ldeoral x0, x1, [x2]
|
||||
ldset x0, x1, [x2]
|
||||
ldsmaxa w0, w1, [x2]
|
||||
ldsminlb w0, w1, [x2]
|
||||
ldumaxalh w0, w1, [x2]
|
||||
ldumin w0, w1, [x2]
|
||||
//CHECK: ldadda x0, x1, [x2] // encoding: [0x41,0x00,0xa0,0xf8]
|
||||
//CHECK: ldclrl x0, x1, [x2] // encoding: [0x41,0x10,0x60,0xf8]
|
||||
//CHECK: ldeoral x0, x1, [x2] // encoding: [0x41,0x20,0xe0,0xf8]
|
||||
//CHECK: ldset x0, x1, [x2] // encoding: [0x41,0x30,0x20,0xf8]
|
||||
//CHECK: ldsmaxa w0, w1, [x2] // encoding: [0x41,0x40,0xa0,0xb8]
|
||||
//CHECK: ldsminlb w0, w1, [x2] // encoding: [0x41,0x50,0x60,0x38]
|
||||
//CHECK: ldumaxalh w0, w1, [x2] // encoding: [0x41,0x60,0xe0,0x78]
|
||||
//CHECK: ldumin w0, w1, [x2] // encoding: [0x41,0x70,0x20,0xb8]
|
||||
|
||||
// ST<OP> intructions: aliases to LD<OP>
|
||||
stADDlb w0, [x2]
|
||||
stclrlh w0, [x2]
|
||||
steorl w0, [x2]
|
||||
stsetl x0, [x2]
|
||||
stsmaxb w0, [x2]
|
||||
stsminh w0, [x2]
|
||||
stumax w0, [x2]
|
||||
stumin x0, [x2]
|
||||
//CHECK: staddlb w0, [x2] // encoding: [0x5f,0x00,0x60,0x38]
|
||||
//CHECK: stclrlh w0, [x2] // encoding: [0x5f,0x10,0x60,0x78]
|
||||
//CHECK: steorl w0, [x2] // encoding: [0x5f,0x20,0x60,0xb8]
|
||||
//CHECK: stsetl x0, [x2] // encoding: [0x5f,0x30,0x60,0xf8]
|
||||
//CHECK: stsmaxb w0, [x2] // encoding: [0x5f,0x40,0x20,0x38]
|
||||
//CHECK: stsminh w0, [x2] // encoding: [0x5f,0x50,0x20,0x78]
|
||||
//CHECK: stumax w0, [x2] // encoding: [0x5f,0x60,0x20,0xb8]
|
||||
//CHECK: stumin x0, [x2] // encoding: [0x5f,0x70,0x20,0xf8]
|
||||
|
||||
ldsmax x0, x1, [w2]
|
||||
ldeorl w0, w1, [w2]
|
||||
//CHECK-ERROR: error: invalid operand for instruction
|
||||
//CHECK-ERROR: ldsmax x0, x1, [w2]
|
||||
//CHECK-ERROR: ^
|
||||
//CHECK-ERROR: error: invalid operand for instruction
|
||||
//CHECK-ERROR: ldeorl w0, w1, [w2]
|
||||
//CHECK-ERROR: ^
|
||||
|
||||
//SWP instruction
|
||||
swp x0, x1, [x2]
|
||||
swpb w0, w1, [x2]
|
||||
swplh w0, w1, [x2]
|
||||
swpal x0, x1, [sp]
|
||||
//CHECK: swp x0, x1, [x2] // encoding: [0x41,0x80,0x20,0xf8]
|
||||
//CHECK: swpb w0, w1, [x2] // encoding: [0x41,0x80,0x20,0x38]
|
||||
//CHECK: swplh w0, w1, [x2] // encoding: [0x41,0x80,0x60,0x78]
|
||||
//CHECK: swpal x0, x1, [sp] // encoding: [0xe1,0x83,0xe0,0xf8]
|
||||
|
||||
swp x0, x1, [w2]
|
||||
swp x0, x1, [xzr]
|
||||
//CHECK-ERROR: error: invalid operand for instruction
|
||||
//CHECK-ERROR: swp x0, x1, [w2]
|
||||
//CHECK-ERROR: ^
|
||||
//CHECK-ERROR: error: invalid operand for instruction
|
||||
//CHECK-ERROR: swp x0, x1, [xzr]
|
||||
//CHECK-ERROR: ^
|
||||
|
||||
//CASP instruction
|
||||
casp x0, x1, x2, x3, [x4]
|
||||
casp w0, w1, w2, w3, [x4]
|
||||
//CHECK: casp x0, x1, x2, x3, [x4] // encoding: [0x82,0x7c,0x20,0x48]
|
||||
//CHECK: casp w0, w1, w2, w3, [x4] // encoding: [0x82,0x7c,0x20,0x08]
|
||||
|
||||
casp x1, x2, x4, x5, [x6]
|
||||
casp x0, x1, x3, x4, [x5]
|
||||
casp x0, x2, x4, x5, [x6]
|
||||
casp x0, x1, x2, x4, [x5]
|
||||
casp x0, w1, x2, x3, [x5]
|
||||
casp w0, x1, x2, x3, [x5]
|
||||
casp w0, x1, w2, w3, [x5]
|
||||
casp x0, x1, w2, w3, [x5]
|
||||
//CHECK-ERROR: error: expected first even register of a consecutive same-size even/odd register pair
|
||||
//CHECK-ERROR: casp x1, x2, x4, x5, [x6]
|
||||
//CHECK-ERROR: ^
|
||||
//CHECK-ERROR: error: expected first even register of a consecutive same-size even/odd register pair
|
||||
//CHECK-ERROR: casp x0, x1, x3, x4, [x5]
|
||||
//CHECK-ERROR: ^
|
||||
//CHECK-ERROR: error: expected second odd register of a consecutive same-size even/odd register pair
|
||||
//CHECK-ERROR: casp x0, x2, x4, x5, [x6]
|
||||
//CHECK-ERROR: ^
|
||||
//CHECK-ERROR: error: expected second odd register of a consecutive same-size even/odd register pair
|
||||
//CHECK-ERROR: casp x0, x1, x2, x4, [x5]
|
||||
//CHECK-ERROR: ^
|
||||
//CHECK-ERROR: error: expected second odd register of a consecutive same-size even/odd register pair
|
||||
//CHECK-ERROR: casp x0, w1, x2, x3, [x5]
|
||||
//CHECK-ERROR: ^
|
||||
//CHECK-ERROR: error: expected second odd register of a consecutive same-size even/odd register pair
|
||||
//CHECK-ERROR: casp w0, x1, x2, x3, [x5]
|
||||
//CHECK-ERROR: ^
|
||||
//CHECK-ERROR: error: expected second odd register of a consecutive same-size even/odd register pair
|
||||
//CHECK-ERROR: casp w0, x1, w2, w3, [x5]
|
||||
//CHECK-ERROR: ^
|
||||
//CHECK-ERROR: error: invalid operand for instruction
|
||||
//CHECK-ERROR: casp x0, x1, w2, w3, [x5]
|
||||
//CHECK-ERROR: ^
|
83
test/MC/Disassembler/AArch64/armv8.1a-atomic.txt
Normal file
83
test/MC/Disassembler/AArch64/armv8.1a-atomic.txt
Normal file
@ -0,0 +1,83 @@
|
||||
# RUN: llvm-mc -triple aarch64-none-linux-gnu -mattr=+v8.1a --disassemble < %s | FileCheck %s
|
||||
|
||||
0x41,0x7c,0xa0,0x08
|
||||
0x41,0x7c,0xe0,0x08
|
||||
0x41,0xfc,0xa0,0x08
|
||||
0x41,0xfc,0xe0,0x08
|
||||
0x41,0x7c,0xa0,0x48
|
||||
0x41,0x7c,0xe0,0x48
|
||||
0x41,0xfc,0xa0,0x48
|
||||
0x41,0xfc,0xe0,0x48
|
||||
# CHECK: casb w0, w1, [x2]
|
||||
# CHECK: casab w0, w1, [x2]
|
||||
# CHECK: caslb w0, w1, [x2]
|
||||
# CHECK: casalb w0, w1, [x2]
|
||||
# CHECK: cash w0, w1, [x2]
|
||||
# CHECK: casah w0, w1, [x2]
|
||||
# CHECK: caslh w0, w1, [x2]
|
||||
# CHECK: casalh w0, w1, [x2]
|
||||
|
||||
0x41,0x7c,0xa0,0x88
|
||||
0x41,0x7c,0xe0,0x88
|
||||
0x41,0xfc,0xa0,0x88
|
||||
0x41,0xfc,0xe0,0x88
|
||||
0x41,0x7c,0xa0,0xc8
|
||||
0x41,0x7c,0xe0,0xc8
|
||||
0x41,0xfc,0xa0,0xc8
|
||||
0x41,0xfc,0xe0,0xc8
|
||||
# CHECK: cas w0, w1, [x2]
|
||||
# CHECK: casa w0, w1, [x2]
|
||||
# CHECK: casl w0, w1, [x2]
|
||||
# CHECK: casal w0, w1, [x2]
|
||||
# CHECK: cas x0, x1, [x2]
|
||||
# CHECK: casa x0, x1, [x2]
|
||||
# CHECK: casl x0, x1, [x2]
|
||||
# CHECK: casal x0, x1, [x2]
|
||||
|
||||
0x41,0x80,0x20,0xf8
|
||||
0x41,0x80,0x20,0x38
|
||||
0x41,0x80,0x60,0x78
|
||||
0xe1,0x83,0xe0,0xf8
|
||||
# CHECK: swp x0, x1, [x2]
|
||||
# CHECK: swpb w0, w1, [x2]
|
||||
# CHECK: swplh w0, w1, [x2]
|
||||
# CHECK: swpal x0, x1, [sp]
|
||||
|
||||
0x41,0x00,0xa0,0xf8
|
||||
0x41,0x10,0x60,0xf8
|
||||
0x41,0x20,0xe0,0xf8
|
||||
0x41,0x30,0x20,0xf8
|
||||
0x41,0x40,0xa0,0xb8
|
||||
0x41,0x50,0x60,0x38
|
||||
0x41,0x60,0xe0,0x78
|
||||
0x41,0x70,0x20,0xb8
|
||||
# CHECK: ldadda x0, x1, [x2]
|
||||
# CHECK: ldclrl x0, x1, [x2]
|
||||
# CHECK: ldeoral x0, x1, [x2]
|
||||
# CHECK: ldset x0, x1, [x2]
|
||||
# CHECK: ldsmaxa w0, w1, [x2]
|
||||
# CHECK: ldsminlb w0, w1, [x2]
|
||||
# CHECK: ldumaxalh w0, w1, [x2]
|
||||
# CHECK: ldumin w0, w1, [x2]
|
||||
|
||||
0x5f,0x00,0x60,0x38
|
||||
0x5f,0x10,0x60,0x78
|
||||
0x5f,0x20,0x60,0xb8
|
||||
0x5f,0x30,0x60,0xf8
|
||||
0x5f,0x40,0x20,0x38
|
||||
0x5f,0x50,0x20,0x78
|
||||
0x5f,0x60,0x20,0xb8
|
||||
0x5f,0x70,0x20,0xf8
|
||||
# CHECK: staddlb w0, [x2]
|
||||
# CHECK: stclrlh w0, [x2]
|
||||
# CHECK: steorl w0, [x2]
|
||||
# CHECK: stsetl x0, [x2]
|
||||
# CHECK: stsmaxb w0, [x2]
|
||||
# CHECK: stsminh w0, [x2]
|
||||
# CHECK: stumax w0, [x2]
|
||||
# CHECK: stumin x0, [x2]
|
||||
|
||||
0x82,0x7c,0x20,0x48
|
||||
0x82,0x7c,0x20,0x08
|
||||
# CHECK: casp x0, x1, x2, x3, [x4]
|
||||
# CHECK: casp w0, w1, w2, w3, [x4]
|
Loading…
x
Reference in New Issue
Block a user