From 1e7e9b1881fbc718b814ace5162cdcc50c927a14 Mon Sep 17 00:00:00 2001 From: Vladimir Sukharev Date: Tue, 2 Jun 2015 10:58:41 +0000 Subject: [PATCH] [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 --- lib/Target/AArch64/AArch64InstrFormats.td | 172 +++++++++++++++++ lib/Target/AArch64/AArch64InstrInfo.td | 68 +++++++ lib/Target/AArch64/AArch64RegisterInfo.td | 41 ++++ .../AArch64/AsmParser/AArch64AsmParser.cpp | 85 +++++++++ .../Disassembler/AArch64Disassembler.cpp | 40 ++++ lib/Target/AArch64/Disassembler/LLVMBuild.txt | 2 +- .../InstPrinter/AArch64InstPrinter.cpp | 25 ++- .../AArch64/InstPrinter/AArch64InstPrinter.h | 4 + test/MC/AArch64/armv8.1a-atomic.s | 179 ++++++++++++++++++ .../Disassembler/AArch64/armv8.1a-atomic.txt | 83 ++++++++ 10 files changed, 694 insertions(+), 5 deletions(-) create mode 100644 test/MC/AArch64/armv8.1a-atomic.s create mode 100644 test/MC/Disassembler/AArch64/armv8.1a-atomic.txt diff --git a/lib/Target/AArch64/AArch64InstrFormats.td b/lib/Target/AArch64/AArch64InstrFormats.td index 6c9fc9a45a8..1fe9c7f8cc5 100644 --- a/lib/Target/AArch64/AArch64InstrFormats.td +++ b/lib/Target/AArch64/AArch64InstrFormats.td @@ -8841,6 +8841,178 @@ class SHAInstSS 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, and aliases STOPregister + +// 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{}[] , , [] +// CAS{} , , [] +// CASP{} , , , , [] +// CASP{} , , , , [] +// SWP{}[] , , [] +// SWP{} , , [] +// LD{}[] , , [] +// LD{} , , [] +// ST{}[] , [] +// ST{} , [] + +let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in +class BaseCASEncoding pattern> + : I { + 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 + : 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 Acq, bits<1> Rel, string order> { + let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS; + let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS; + let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS; + let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS; +} + +class BaseCASP + : 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 Acq, bits<1> Rel, string order> { + let Sz = 0b00, Acq = Acq, Rel = Rel in + def s : BaseCASP; + let Sz = 0b01, Acq = Acq, Rel = Rel in + def d : BaseCASP; +} + +let Predicates = [HasV8_1a] in +class BaseSWP + : 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 Acq, bits<1> Rel, string order> { + let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP; + let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP; + let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP; + let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP; +} + +let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in +class BaseLDOPregister + : 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 opc, string op, bits<1> Acq, bits<1> Rel, + string order> { + let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in + def b : BaseLDOPregister; + let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in + def h : BaseLDOPregister; + let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in + def s : BaseLDOPregister; + let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in + def d : BaseLDOPregister; +} + +let Predicates = [HasV8_1a] in +class BaseSTOPregister : + InstAlias; + +multiclass STOPregister { + def : BaseSTOPregister(instr # "Lb")>; + def : BaseSTOPregister(instr # "Lh")>; + def : BaseSTOPregister(instr # "Ls")>; + def : BaseSTOPregister(instr # "Ld")>; + def : BaseSTOPregister(instr # "b")>; + def : BaseSTOPregister(instr # "h")>; + def : BaseSTOPregister(instr # "s")>; + def : BaseSTOPregister(instr # "d")>; +} + +//---------------------------------------------------------------------------- // Allow the size specifier tokens to be upper case, not just lower. def : TokenAlias<".8B", ".8b">; def : TokenAlias<".4H", ".4h">; diff --git a/lib/Target/AArch64/AArch64InstrInfo.td b/lib/Target/AArch64/AArch64InstrInfo.td index 752a8399b81..99f231a1e0e 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.td +++ b/lib/Target/AArch64/AArch64InstrInfo.td @@ -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(register). Performs load and then ST(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(register) as aliases to "LD(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. diff --git a/lib/Target/AArch64/AArch64RegisterInfo.td b/lib/Target/AArch64/AArch64RegisterInfo.td index d5ff3f1f337..b2efca02337 100644 --- a/lib/Target/AArch64/AArch64RegisterInfo.td +++ b/lib/Target/AArch64/AArch64RegisterInfo.td @@ -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; def FPR32Op : RegisterOperand; def FPR64Op : RegisterOperand; def FPR128Op : RegisterOperand; + + +//===----------------------------------------------------------------------===// +// 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"> { + let ParserMatchClass = WSeqPairsAsmOperandClass; +} +def XSeqPairClassOperand : + RegisterOperand"> { + let ParserMatchClass = XSeqPairsAsmOperandClass; +} + + +//===----- END: v8.1a atomic CASP register operands -----------------------===// diff --git a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 93611163459..41615b6ede0 100644 --- a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -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; +} diff --git a/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp index a1ed703d1bf..359c2e734e2 100644 --- a/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ b/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -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); +} diff --git a/lib/Target/AArch64/Disassembler/LLVMBuild.txt b/lib/Target/AArch64/Disassembler/LLVMBuild.txt index 62827e8f50e..73665eb5701 100644 --- a/lib/Target/AArch64/Disassembler/LLVMBuild.txt +++ b/lib/Target/AArch64/Disassembler/LLVMBuild.txt @@ -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 diff --git a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp index bf1aeca78cc..d7ea6f86c3f 100644 --- a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp +++ b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp @@ -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 +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(); diff --git a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h index c2077a0fe55..15dee978e22 100644 --- a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h +++ b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h @@ -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 + void printGPRSeqPairsClassOperand(const MCInst *MI, unsigned OpNum, + const MCSubtargetInfo &STI, + raw_ostream &O); }; class AArch64AppleInstPrinter : public AArch64InstPrinter { diff --git a/test/MC/AArch64/armv8.1a-atomic.s b/test/MC/AArch64/armv8.1a-atomic.s new file mode 100644 index 00000000000..224943b59f1 --- /dev/null +++ b/test/MC/AArch64/armv8.1a-atomic.s @@ -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 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 intructions: aliases to LD + 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: ^ diff --git a/test/MC/Disassembler/AArch64/armv8.1a-atomic.txt b/test/MC/Disassembler/AArch64/armv8.1a-atomic.txt new file mode 100644 index 00000000000..67c6954c567 --- /dev/null +++ b/test/MC/Disassembler/AArch64/armv8.1a-atomic.txt @@ -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] -- 2.34.1