[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:
Vladimir Sukharev 2015-06-02 10:58:41 +00:00
parent 01cf1d3ef3
commit 1e7e9b1881
10 changed files with 694 additions and 5 deletions

View File

@ -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">;

View File

@ -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.

View File

@ -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 -----------------------===//

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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();

View File

@ -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 {

View 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: ^

View 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]