Index: lib/Target/AArch64/AArch64InstrFormats.td =================================================================== --- lib/Target/AArch64/AArch64InstrFormats.td +++ lib/Target/AArch64/AArch64InstrFormats.td @@ -8631,3 +8631,141 @@ def : TokenAlias<".S", ".s">; def : TokenAlias<".D", ".d">; def : TokenAlias<".Q", ".q">; + +//---------------------------------------------------------------------------- +// v8.1 atomic instructions extension: +// * CAS +// * CASP +// * LD +// * SWP + +// 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 +// LD SZ |111000|A |R |1 |Rs |0 |OPC|00|Rn |Rt +// SWP SZ |111000|A |R |1 |Rs |1 |OPC|00|Rn |Rt + +// Instruction syntax: +// +// CAS{}[] , , [] +// CAS{} , , [] +// CASP{} , , , , [] +// CASP{} , , , , [] +// LD{}[] , , [] +// LD{} , , [] +// SWP{}[] , , [] +// SWP{} , , [] + + +let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in +class BaseCASEncoding pattern> + : I { + bits<2> Sz; + bit NP; + bit A; + bit R; + 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} = A; + let Inst{21} = 0b1; + let Inst{20-16} = Rs; + let Inst{15} = R; + 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 = $Rt",[]> { + let NP = 1; +} + +let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in +class BaseLD + : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size, "\t$Rs, $Rt, [$Rn]","",[]> { + bits<2> Sz; + bit A; + bit R; + 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} = A; + let Inst{22} = R; + 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 LDOp { + let opc = 0b000 in def _add : BaseLD<"add" , order, size, RC>; + let opc = 0b001 in def _clr : BaseLD<"clr" , order, size, RC>; + let opc = 0b010 in def _eor : BaseLD<"eor" , order, size, RC>; + let opc = 0b011 in def _set : BaseLD<"set" , order, size, RC>; + let opc = 0b100 in def _smax : BaseLD<"smax", order, size, RC>; + let opc = 0b101 in def _smin : BaseLD<"smin", order, size, RC>; + let opc = 0b110 in def _umax : BaseLD<"umax", order, size, RC>; + let opc = 0b111 in def _umin : BaseLD<"umin", order, size, RC>; +} + +// Aliases for LD +let Predicates = [HasV8_1a] in +class BaseAliasLD : + InstAlias; + +multiclass BaseAliasLDOp { + def : BaseAliasLD<"st" # asm # "lb", GPR32, WZR, !cast("LD" # _B_release_ # asm)>; + def : BaseAliasLD<"st" # asm # "lh", GPR32, WZR, !cast("LD" # _H_release_ # asm)>; + def : BaseAliasLD<"st" # asm # "l", GPR32, WZR, !cast("LD" # _S_release_ # asm)>; + def : BaseAliasLD<"st" # asm # "l", GPR64, XZR, !cast("LD" # _D_release_ # asm)>; + def : BaseAliasLD<"st" # asm # "b", GPR32, WZR, !cast("LD" # _B_no_order_ # asm)>; + def : BaseAliasLD<"st" # asm # "h", GPR32, WZR, !cast("LD" # _H_no_order_ # asm)>; + def : BaseAliasLD<"st" # asm # "", GPR32, WZR, !cast("LD" # _S_no_order_ # asm)>; + def : BaseAliasLD<"st" # asm # "", GPR64, XZR, !cast("LD" # _D_no_order_ # asm)>; +} + +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 A; + bit R; + 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} = A; + let Inst{22} = R; + 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; +} + +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; +} Index: lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.td +++ lib/Target/AArch64/AArch64InstrInfo.td @@ -727,6 +727,80 @@ 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 +multiclass CASOrder { + let A = 0b1, R = 0b0 in def _acquire : BaseCAS<"a",size,RC>; + let A = 0b0, R = 0b1 in def _release : BaseCAS<"l",size,RC>; + let A = 0b1, R = 0b1 in def _acquire_and_release : BaseCAS<"al",size,RC>; + let A = 0b0, R = 0b0 in def _no_order : BaseCAS<"",size,RC>; +} + +multiclass CASOrderSize { + let Sz = 0b00 in defm _B : CASOrder<"b",GPR32>; + let Sz = 0b01 in defm _H : CASOrder<"h",GPR32>; + let Sz = 0b10 in defm _S : CASOrder<"",GPR32>; + let Sz = 0b11 in defm _D : CASOrder<"",GPR64>; +} + +defm CAS : CASOrderSize; + +// v8.1 atomic SWP +multiclass SWPOrder { + let A = 0b1, R = 0b0 in def _acquire : BaseSWP<"a",size,RC>; + let A = 0b0, R = 0b1 in def _release : BaseSWP<"l",size,RC>; + let A = 0b1, R = 0b1 in def _acquire_and_release : BaseSWP<"al",size,RC>; + let A = 0b0, R = 0b0 in def _no_order : BaseSWP<"",size,RC>; +} + +multiclass SWPOrderSize { + let Sz = 0b00 in defm _B : SWPOrder<"b",GPR32>; + let Sz = 0b01 in defm _H : SWPOrder<"h",GPR32>; + let Sz = 0b10 in defm _S : SWPOrder<"",GPR32>; + let Sz = 0b11 in defm _D : SWPOrder<"",GPR64>; +} + +defm SWP : SWPOrderSize; + +// v8.1 atomic LD +multiclass LDOpOrder { + let A = 0b1, R = 0b0 in defm _acquire : LDOp<"a", size, RC>; + let A = 0b0, R = 0b1 in defm _release : LDOp<"l", size, RC>; + let A = 0b1, R = 0b1 in defm _acquire_and_release : LDOp<"al", size, RC>; + let A = 0b0, R = 0b0 in defm _no_order : LDOp<"", size, RC>; +} + +multiclass LDOpOrderSize { + let Sz = 0b00 in defm _B : LDOpOrder<"b", GPR32>; + let Sz = 0b01 in defm _H : LDOpOrder<"h", GPR32>; + let Sz = 0b10 in defm _S : LDOpOrder<"", GPR32>; + let Sz = 0b11 in defm _D : LDOpOrder<"", GPR64>; +} + +defm LD : LDOpOrderSize; + +defm : BaseAliasLDOp<"add">; +defm : BaseAliasLDOp<"clr">; +defm : BaseAliasLDOp<"eor">; +defm : BaseAliasLDOp<"set">; +defm : BaseAliasLDOp<"smax">; +defm : BaseAliasLDOp<"smin">; +defm : BaseAliasLDOp<"umax">; +defm : BaseAliasLDOp<"umin">; + +// v8.1 atomic CASP +multiclass CASPOrder { + let A = 0b1, R = 0b0 in def _acquire : BaseCASP<"a",size,RC>; + let A = 0b0, R = 0b1 in def _release : BaseCASP<"l",size,RC>; + let A = 0b1, R = 0b1 in def _acquire_and_release : BaseCASP<"al",size,RC>; + let A = 0b0, R = 0b0 in def _no_order : BaseCASP<"",size,RC>; +} + +multiclass CASPOrderSize { + let Sz = 0b00 in defm _S : CASPOrder<"",ConsecutivePairClassOperand32>; + let Sz = 0b01 in defm _D : CASPOrder<"",ConsecutivePairClassOperand64>; +} + +defm CASP : CASPOrderSize; //===----------------------------------------------------------------------===// // Logical instructions. Index: lib/Target/AArch64/AArch64RegisterInfo.td =================================================================== --- lib/Target/AArch64/AArch64RegisterInfo.td +++ lib/Target/AArch64/AArch64RegisterInfo.td @@ -592,3 +592,37 @@ def FPR32Op : RegisterOperand; def FPR64Op : RegisterOperand; def FPR128Op : RegisterOperand; + + +//===----------------------------------------------------------------------===// +// ARMv8.1a atomic CASP register operands + + +let Namespace = "AArch64" in { + def sube32 : SubRegIndex<32>; + def subo32 : SubRegIndex<32>; + def sube64 : SubRegIndex<64>; + def subo64 : SubRegIndex<64>; +} + +def Pair32 : RegisterTuples<[sube32, subo32], [(rotl GPR32, 0), (rotl GPR32, 1)]>; +def Pair64 : RegisterTuples<[sube64, subo64], [(rotl GPR64, 0), (rotl GPR64, 1)]>; + +def Pair32Class : RegisterClass<"AArch64", [untyped], 32, (add Pair32)> {let Size = 64;} +def Pair64Class : RegisterClass<"AArch64", [untyped], 64, (add Pair64)> {let Size = 128;} + + +let RenderMethod = "addRegOperands", ParserMethod="tryParsePair" in { + def Pair32AsmOperandClass : AsmOperandClass { let Name = "Pair32"; } + def Pair64AsmOperandClass : AsmOperandClass { let Name = "Pair64"; } +} + +def ConsecutivePairClassOperand32 : RegisterOperand"> { + let ParserMatchClass = Pair32AsmOperandClass; +} +def ConsecutivePairClassOperand64 : RegisterOperand"> { + let ParserMatchClass = Pair64AsmOperandClass; +} + + +//===----- END: v8.1a atomic CASP register operands -----------------------===// Index: lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -106,6 +106,7 @@ OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands); OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands); bool tryParseVectorRegister(OperandVector &Operands); + OperandMatchResultTy tryParsePair(OperandVector &Operands); public: enum AArch64MatchResultTy { @@ -874,7 +875,14 @@ return Kind == k_Register && !Reg.isVector && AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum); } - + bool isPair32() const { + return Kind == k_Register && !Reg.isVector && + AArch64MCRegisterClasses[AArch64::Pair32ClassRegClassID].contains(Reg.RegNum); + } + bool isPair64() const { + return Kind == k_Register && !Reg.isVector && + AArch64MCRegisterClasses[AArch64::Pair64ClassRegClassID].contains(Reg.RegNum); + } bool isGPR64sp0() const { return Kind == k_Register && !Reg.isVector && AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum); @@ -4292,3 +4300,75 @@ return Match_Success; return Match_InvalidOperand; } + + +AArch64AsmParser::OperandMatchResultTy +AArch64AsmParser::tryParsePair(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 register"); + return MatchOperand_ParseFail; + } + + const MCRegisterInfo *RI = getContext().getRegisterInfo(); + unsigned FirstEncoding = RI->getEncodingValue(FirstReg); + + if (FirstEncoding & 0x1) { + Error(S, "Expected even register"); + 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 consecutive registers"); + return MatchOperand_ParseFail; + } + + unsigned Pair = 0; + if (isXReg) { + Pair = AArch64MCRegisterClasses[AArch64::Pair64ClassRegClassID].getRegister( + FirstEncoding); + } else { + Pair = AArch64MCRegisterClasses[AArch64::Pair32ClassRegClassID].getRegister( + FirstEncoding); + } + + Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(), + getContext())); + + return MatchOperand_Success; +} Index: lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp =================================================================== --- lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -169,6 +169,10 @@ uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftL8Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); +static DecodeStatus DecodePair32ClassRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Addr, const void *Decoder); +static DecodeStatus DecodePair64ClassRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Addr, const void *Decoder); static bool Check(DecodeStatus &Out, DecodeStatus In) { switch (In) { @@ -1543,3 +1547,29 @@ return Success; } + +static DecodeStatus DecodePair32ClassRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Addr, + const void *Decoder) { + // Register number must be even (see CASP instruction) + if (RegNo & 0x1) + return Fail; + + unsigned Register = AArch64MCRegisterClasses[AArch64::Pair32ClassRegClassID]. + getRegister(RegNo); + Inst.addOperand(MCOperand::CreateReg(Register)); + return Success; +} + +static DecodeStatus DecodePair64ClassRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Addr, + const void *Decoder) { + // Register number must be even (see CASP instruction) + if (RegNo & 0x1) + return Fail; + + unsigned Register = AArch64MCRegisterClasses[AArch64::Pair64ClassRegClassID]. + getRegister(RegNo); + Inst.addOperand(MCOperand::CreateReg(Register)); + return Success; +} Index: lib/Target/AArch64/Disassembler/LLVMBuild.txt =================================================================== --- lib/Target/AArch64/Disassembler/LLVMBuild.txt +++ 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 Index: lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h =================================================================== --- lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h +++ lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h @@ -116,6 +116,8 @@ void printMRSSystemRegister(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printSystemPStateField(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printSIMDType10Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + template + void printConsecutivePairClassOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); }; class AArch64AppleInstPrinter : public AArch64InstPrinter { Index: lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp =================================================================== --- lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp +++ lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp @@ -1151,6 +1151,19 @@ return Reg; } +template +void AArch64InstPrinter::printConsecutivePairClassOperand(const MCInst *MI, unsigned OpNum, 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, raw_ostream &O, StringRef LayoutSuffix) { Index: test/MC/AArch64/armv8-extension-atomic.s =================================================================== --- /dev/null +++ test/MC/AArch64/armv8-extension-atomic.s @@ -0,0 +1,163 @@ +// 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] +//CHECK-ERROR: error: Expected even register +//CHECK-ERROR: casp x1, x2, x4, x5, [x6] +//CHECK-ERROR: ^ +//CHECK-ERROR: error: Expected even register +//CHECK-ERROR: casp x0, x1, x3, x4, [x5] +//CHECK-ERROR: ^ +//CHECK-ERROR: error: Expected consecutive registers +//CHECK-ERROR: casp x0, x2, x4, x5, [x6] +//CHECK-ERROR: ^ +//CHECK-ERROR: error: Expected consecutive registers +//CHECK-ERROR: casp x0, x1, x2, x4, [x5] +//CHECK-ERROR: ^ Index: test/MC/Disassembler/AArch64/armv8-extension-atomic.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/AArch64/armv8-extension-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]