llvm.org GIT mirror llvm / fc2b3d0
[AArch64][ARM] Armv8.4-A: Trace synchronization barrier instruction This adds the Armv8.4-A Trace synchronization barrier (TSB) instruction. Differential Revision: https://reviews.llvm.org/D48918 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336418 91177308-0d34-0410-b5e6-96231b3b80d8 Sjoerd Meijer 2 years ago
19 changed file(s) with 248 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
1919 AssemblerPredicate<"HasV8_2aOps", "armv8.2a">;
2020 def HasV8_3a : Predicate<"Subtarget->hasV8_3aOps()">,
2121 AssemblerPredicate<"HasV8_3aOps", "armv8.3a">;
22 def HasV8_4a : Predicate<"Subtarget->hasV8_4aOps()">,
23 AssemblerPredicate<"HasV8_4aOps", "armv8.4a">;
2224 def HasFPARMv8 : Predicate<"Subtarget->hasFPARMv8()">,
2325 AssemblerPredicate<"FeatureFPARMv8", "fp-armv8">;
2426 def HasNEON : Predicate<"Subtarget->hasNEON()">,
448450
449451 def ISB : CRmSystemI
450452 [(int_aarch64_isb (i32 imm32_0_15:$CRm))]>;
453
454 def TSB : CRmSystemI {
455 let CRm = 0b0010;
456 let Inst{12} = 0;
457 let Predicates = [HasV8_4a];
458 }
451459 }
452460
453461 // ARMv8.2 Dot Product
140140 }
141141
142142 def : ISB<"sy", 0xf>;
143
144 //===----------------------------------------------------------------------===//
145 // TSB (Trace synchronization barrier) instruction options.
146 //===----------------------------------------------------------------------===//
147
148 class TSB encoding> : SearchableTable{
149 let SearchableFields = ["Name", "Encoding"];
150 let EnumValueField = "Encoding";
151
152 string Name = name;
153 bits<4> Encoding;
154 let Encoding = encoding;
155
156 code Requires = [{ {AArch64::HasV8_4aOps} }];
157 }
158
159 def : TSB<"csync", 0>;
143160
144161 //===----------------------------------------------------------------------===//
145162 // PRFM (prefetch) instruction options.
26452645 Str += "ARMv8.1a";
26462646 else if (FBS[AArch64::HasV8_2aOps])
26472647 Str += "ARMv8.2a";
2648 else if (FBS[AArch64::HasV8_3aOps])
2649 Str += "ARMv8.3a";
2650 else if (FBS[AArch64::HasV8_4aOps])
2651 Str += "ARMv8.4a";
26482652 else
26492653 Str += "(unknown)";
26502654 }
27552759 MCAsmParser &Parser = getParser();
27562760 const AsmToken &Tok = Parser.getTok();
27572761
2762 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2763 TokError("'csync' operand expected");
2764 return MatchOperand_ParseFail;
27582765 // Can be either a #imm style literal or an option name
2759 if (parseOptionalToken(AsmToken::Hash) ||
2760 Tok.is(AsmToken::Integer)) {
2766 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
27612767 // Immediate operand.
27622768 const MCExpr *ImmVal;
27632769 SMLoc ExprLoc = getLoc();
27832789 return MatchOperand_ParseFail;
27842790 }
27852791
2792 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
27862793 // The only valid named option for ISB is 'sy'
27872794 auto DB = AArch64DB::lookupDBByName(Tok.getString());
27882795 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
27892796 TokError("'sy' or #imm operand expected");
27902797 return MatchOperand_ParseFail;
2791 } else if (!DB) {
2798 // The only valid named option for TSB is 'csync'
2799 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
2800 TokError("'csync' operand expected");
2801 return MatchOperand_ParseFail;
2802 } else if (!DB && !TSB) {
27922803 TokError("invalid barrier option name");
27932804 return MatchOperand_ParseFail;
27942805 }
27952806
27962807 Operands.push_back(AArch64Operand::CreateBarrier(
2797 DB->Encoding, Tok.getString(), getLoc(), getContext()));
2808 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
27982809 Parser.Lex(); // Consume the option
27992810
28002811 return MatchOperand_Success;
278278 if (Opcode == AArch64::CompilerBarrier) {
279279 O << '\t' << MAI.getCommentString() << " COMPILER BARRIER";
280280 printAnnotation(O, Annot);
281 return;
282 }
283
284 // Instruction TSB is specified as a one operand instruction, but 'csync' is
285 // not encoded, so for printing it is treated as a special case here:
286 if (Opcode == AArch64::TSB) {
287 O << "\ttsb\tcsync";
281288 return;
282289 }
283290
13281335 if (Opcode == AArch64::ISB) {
13291336 auto ISB = AArch64ISB::lookupISBByEncoding(Val);
13301337 Name = ISB ? ISB->Name : "";
1338 } else if (Opcode == AArch64::TSB) {
1339 auto TSB = AArch64TSB::lookupTSBByEncoding(Val);
1340 Name = TSB ? TSB->Name : "";
13311341 } else {
13321342 auto DB = AArch64DB::lookupDBByEncoding(Val);
13331343 Name = DB ? DB->Name : "";
5252 #include "AArch64GenSystemOperands.inc"
5353 }
5454 }
55
56 namespace llvm {
57 namespace AArch64TSB {
58 #define GET_TSB_IMPL
59 #include "AArch64GenSystemOperands.inc"
60 }
61 }
62
5563 namespace llvm {
5664 namespace AArch64PRFM {
5765 #define GET_PRFM_IMPL
326326 #include "AArch64GenSystemOperands.inc"
327327 }
328328
329 namespace AArch64TSB {
330 struct TSB : SysAlias {
331 using SysAlias::SysAlias;
332 };
333 #define GET_TSB_DECL
334 #include "AArch64GenSystemOperands.inc"
335 }
336
329337 namespace AArch64PRFM {
330338 struct PRFM : SysAlias {
331339 using SysAlias::SysAlias;
48184818 let DecoderMethod = "DecodeInstSyncBarrierOption";
48194819 }
48204820
4821 def TraceSyncBarrierOptOperand : AsmOperandClass {
4822 let Name = "TraceSyncBarrierOpt";
4823 let ParserMethod = "parseTraceSyncBarrierOptOperand";
4824 }
4825 def tsb_opt : Operand {
4826 let PrintMethod = "printTraceSyncBOption";
4827 let ParserMatchClass = TraceSyncBarrierOptOperand;
4828 }
4829
48214830 // Memory barriers protect the atomic sequences
48224831 let hasSideEffects = 1 in {
48234832 def DMB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
48444853 let Inst{31-4} = 0xf57ff06;
48454854 let Inst{3-0} = opt;
48464855 }
4856
4857 let hasNoSchedulingInfo = 1 in
4858 def TSB : AInoP<(outs), (ins tsb_opt:$opt), MiscFrm, NoItinerary,
4859 "tsb", "\t$opt", []>, Requires<[IsARM, HasV8_4a]> {
4860 let Inst{31-0} = 0xe320f012;
4861 }
4862
48474863 }
48484864
48494865 let usesCustomInserter = 1, Defs = [CPSR] in {
32133213 bits<4> opt;
32143214 let Inst{31-4} = 0xf3bf8f6;
32153215 let Inst{3-0} = opt;
3216 }
3217
3218 let hasNoSchedulingInfo = 1 in
3219 def t2TSB : T2I<(outs), (ins tsb_opt:$opt), NoItinerary,
3220 "tsb", "\t$opt", []>, Requires<[IsThumb, HasV8_4a]> {
3221 let Inst{31-0} = 0xf3af8012;
32163222 }
32173223 }
32183224
526526 OperandMatchResultTy parseCoprocRegOperand(OperandVector &);
527527 OperandMatchResultTy parseCoprocOptionOperand(OperandVector &);
528528 OperandMatchResultTy parseMemBarrierOptOperand(OperandVector &);
529 OperandMatchResultTy parseTraceSyncBarrierOptOperand(OperandVector &);
529530 OperandMatchResultTy parseInstSyncBarrierOptOperand(OperandVector &);
530531 OperandMatchResultTy parseProcIFlagsOperand(OperandVector &);
531532 OperandMatchResultTy parseMSRMaskOperand(OperandVector &);
645646 k_Immediate,
646647 k_MemBarrierOpt,
647648 k_InstSyncBarrierOpt,
649 k_TraceSyncBarrierOpt,
648650 k_Memory,
649651 k_PostIndexRegister,
650652 k_MSRMask,
695697 ARM_ISB::InstSyncBOpt Val;
696698 };
697699
700 struct TSBOptOp {
701 ARM_TSB::TraceSyncBOpt Val;
702 };
703
698704 struct IFlagsOp {
699705 ARM_PROC::IFlags Val;
700706 };
791797 struct CoprocOptionOp CoprocOption;
792798 struct MBOptOp MBOpt;
793799 struct ISBOptOp ISBOpt;
800 struct TSBOptOp TSBOpt;
794801 struct ITMaskOp ITMask;
795802 struct IFlagsOp IFlags;
796803 struct MMaskOp MMask;
880887 return ISBOpt.Val;
881888 }
882889
890 ARM_TSB::TraceSyncBOpt getTraceSyncBarrierOpt() const {
891 assert(Kind == k_TraceSyncBarrierOpt && "Invalid access!");
892 return TSBOpt.Val;
893 }
894
883895 ARM_PROC::IFlags getProcIFlags() const {
884896 assert(Kind == k_ProcIFlags && "Invalid access!");
885897 return IFlags.Val;
11561168 bool isToken() const override { return Kind == k_Token; }
11571169 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
11581170 bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; }
1171 bool isTraceSyncBarrierOpt() const { return Kind == k_TraceSyncBarrierOpt; }
11591172 bool isMem() const override {
11601173 if (Kind != k_Memory)
11611174 return false;
22912304 Inst.addOperand(MCOperand::createImm(unsigned(getInstSyncBarrierOpt())));
22922305 }
22932306
2307 void addTraceSyncBarrierOptOperands(MCInst &Inst, unsigned N) const {
2308 assert(N == 1 && "Invalid number of operands!");
2309 Inst.addOperand(MCOperand::createImm(unsigned(getTraceSyncBarrierOpt())));
2310 }
2311
22942312 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
22952313 assert(N == 1 && "Invalid number of operands!");
22962314 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
31413159 CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, SMLoc S) {
31423160 auto Op = make_unique(k_InstSyncBarrierOpt);
31433161 Op->ISBOpt.Val = Opt;
3162 Op->StartLoc = S;
3163 Op->EndLoc = S;
3164 return Op;
3165 }
3166
3167 static std::unique_ptr
3168 CreateTraceSyncBarrierOpt(ARM_TSB::TraceSyncBOpt Opt, SMLoc S) {
3169 auto Op = make_unique(k_TraceSyncBarrierOpt);
3170 Op->TSBOpt.Val = Opt;
31443171 Op->StartLoc = S;
31453172 Op->EndLoc = S;
31463173 return Op;
32143241 break;
32153242 case k_InstSyncBarrierOpt:
32163243 OS << "";
3244 break;
3245 case k_TraceSyncBarrierOpt:
3246 OS << "";
32173247 break;
32183248 case k_Memory:
32193249 OS << "
42044234 return MatchOperand_Success;
42054235 }
42064236
4237 OperandMatchResultTy
4238 ARMAsmParser::parseTraceSyncBarrierOptOperand(OperandVector &Operands) {
4239 MCAsmParser &Parser = getParser();
4240 SMLoc S = Parser.getTok().getLoc();
4241 const AsmToken &Tok = Parser.getTok();
4242
4243 if (Tok.isNot(AsmToken::Identifier))
4244 return MatchOperand_NoMatch;
4245
4246 if (!Tok.getString().equals_lower("csync"))
4247 return MatchOperand_NoMatch;
4248
4249 Parser.Lex(); // Eat identifier token.
4250
4251 Operands.push_back(ARMOperand::CreateTraceSyncBarrierOpt(ARM_TSB::CSYNC, S));
4252 return MatchOperand_Success;
4253 }
4254
42074255 /// parseInstSyncBarrierOptOperand - Try to parse ISB inst sync barrier options.
42084256 OperandMatchResultTy
42094257 ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) {
56795727 Mnemonic != "isb" && Mnemonic != "pld" && Mnemonic != "pli" &&
56805728 Mnemonic != "pldw" && Mnemonic != "ldc2" && Mnemonic != "ldc2l" &&
56815729 Mnemonic != "stc2" && Mnemonic != "stc2l" &&
5730 Mnemonic != "tsb" &&
56825731 !Mnemonic.startswith("rfe") && !Mnemonic.startswith("srs");
56835732 } else if (isThumbOne()) {
56845733 if (hasV6MOps())
268268 }
269269 break;
270270 }
271 case ARM::TSB:
272 case ARM::t2TSB:
273 O << "\ttsb\tcsync";
274 return;
271275 }
272276
273277 if (!printAliasInstr(MI, STI, O))
695699 O << ARM_ISB::InstSyncBOptToString(val);
696700 }
697701
702 void ARMInstPrinter::printTraceSyncBOption(const MCInst *MI, unsigned OpNum,
703 const MCSubtargetInfo &STI,
704 raw_ostream &O) {
705 unsigned val = MI->getOperand(OpNum).getImm();
706 O << ARM_TSB::TraceSyncBOptToString(val);
707 }
708
698709 void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
699710 const MCSubtargetInfo &STI,
700711 raw_ostream &O) {
9393 const MCSubtargetInfo &STI, raw_ostream &O);
9494 void printInstSyncBOption(const MCInst *MI, unsigned OpNum,
9595 const MCSubtargetInfo &STI, raw_ostream &O);
96 void printTraceSyncBOption(const MCInst *MI, unsigned OpNum,
97 const MCSubtargetInfo &STI, raw_ostream &O);
9698 void printShiftImmOperand(const MCInst *MI, unsigned OpNum,
9799 const MCSubtargetInfo &STI, raw_ostream &O);
98100 void printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum,
9797 }
9898 } // namespace ARM_MB
9999
100 namespace ARM_TSB {
101 enum TraceSyncBOpt {
102 CSYNC = 0
103 };
104
105 inline static const char *TraceSyncBOptToString(unsigned val) {
106 switch (val) {
107 default:
108 llvm_unreachable("Unknown trace synchronization barrier operation");
109 case CSYNC: return "csync";
110 }
111 }
112 } // namespace ARM_TSB
113
100114 namespace ARM_ISB {
101115 enum InstSyncBOpt {
102116 RESERVED_0 = 0,
0 // RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.4a < %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
1
2 //------------------------------------------------------------------------------
3 // ARMV8.4-A Debug, Trace and PMU Extensions
4 //------------------------------------------------------------------------------
5
6 tsb
7 tsb foo
8 tsb #0
9 tsb 0
10
11 //CHECK-ERROR: error: too few operands for instruction
12 //CHECK-ERROR: tsb
13 //CHECK-ERROR: ^
14 //CHECK-ERROR: error: 'csync' operand expected
15 //CHECK-ERROR: tsb foo
16 //CHECK-ERROR: ^
17 //CHECK-ERROR: error: 'csync' operand expected
18 //CHECK-ERROR: tsb #0
19 //CHECK-ERROR: ^
20 //CHECK-ERROR: error: 'csync' operand expected
21 //CHECK-ERROR: tsb 0
22 //CHECK-ERROR: ^
1212 mrs x0, TRFCR_EL2
1313 mrs x0, TRFCR_EL12
1414
15 tsb csync
16
1517 //CHECK: msr TRFCR_EL1, x0 // encoding: [0x20,0x12,0x18,0xd5]
1618 //CHECK: msr TRFCR_EL2, x0 // encoding: [0x20,0x12,0x1c,0xd5]
1719 //CHECK: msr TRFCR_EL12, x0 // encoding: [0x20,0x12,0x1d,0xd5]
1921 //CHECK: mrs x0, TRFCR_EL1 // encoding: [0x20,0x12,0x38,0xd5]
2022 //CHECK: mrs x0, TRFCR_EL2 // encoding: [0x20,0x12,0x3c,0xd5]
2123 //CHECK: mrs x0, TRFCR_EL12 // encoding: [0x20,0x12,0x3d,0xd5]
24
25 //CHECK: tsb csync // encoding: [0x5f,0x22,0x03,0xd5]
2226
2327 //CHECK-ERROR: error: expected writable system register or pstate
2428 //CHECK-ERROR: msr TRFCR_EL1, x0
3943 //CHECK-ERROR: error: expected readable system register
4044 //CHECK-ERROR: mrs x0, TRFCR_EL12
4145 //CHECK-ERROR: ^
46
47 //CHECK-ERROR: error: instruction requires: armv8.4a
0 // RUN: not llvm-mc -triple arm -mattr=+v8.4a -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
1 // RUN: not llvm-mc -triple thumb -mattr=+v8.4a -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
2
3 tsb
4 tsb 0
5 tsb #0
6 tsb foo
7
8 //CHECK-ERROR: error: too few operands for instruction
9 //CHECK-ERROR: tsb
10 //CHECK-ERROR: ^
11 //CHECK-ERROR: error: invalid operand for instruction
12 //CHECK-ERROR: tsb 0
13 //CHECK-ERROR: ^
14 //CHECK-ERROR: error: invalid operand for instruction
15 //CHECK-ERROR: tsb #0
16 //CHECK-ERROR: ^
17 //CHECK-ERROR: error: invalid operand for instruction
18 //CHECK-ERROR: tsb foo
19 //CHECK-ERROR: ^
0 // RUN: llvm-mc -triple arm -mattr=+v8.4a -show-encoding < %s | FileCheck %s --check-prefix=CHECK-A32
1 // RUN: llvm-mc -triple thumb -mattr=+v8.4a -show-encoding < %s | FileCheck %s --check-prefix=CHECK-T32
2 // RUN: not llvm-mc -triple arm -mattr=-v8.4a -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NO-V84
3
4 tsb csync
5
6 //CHECK-A32: tsb csync @ encoding: [0x12,0xf0,0x20,0xe3]
7 //CHECK-T32: tsb csync @ encoding: [0xaf,0xf3,0x12,0x80]
8
9 //CHECK-NO-V84: error: invalid instruction
10 //CHECK-NO-V84: tsb csync
11 //CHECK-NO-V84: ^
66 [0x20,0x12,0x38,0xd5]
77 [0x20,0x12,0x3c,0xd5]
88 [0x20,0x12,0x3d,0xd5]
9 [0x5f,0x22,0x03,0xd5]
910
1011 #CHECK: msr TRFCR_EL1, x0
1112 #CHECK: msr TRFCR_EL2, x0
1314 #CHECK: mrs x0, TRFCR_EL1
1415 #CHECK: mrs x0, TRFCR_EL2
1516 #CHECK: mrs x0, TRFCR_EL12
17 #CHECK: tsb csync
1618
1719 #CHECK-NO-V84: msr S3_0_C1_C2_1, x0
1820 #CHECK-NO-V84: msr S3_4_C1_C2_1, x0
2022 #CHECK-NO-V84: mrs x0, S3_0_C1_C2_1
2123 #CHECK-NO-V84: mrs x0, S3_4_C1_C2_1
2224 #CHECK-NO-V84: mrs x0, S3_5_C1_C2_1
25 #CHECK-NO-V84: hint #18
0 # RUN: llvm-mc -triple arm-none-linux-gnu -mattr=+v8.4a --disassemble < %s | FileCheck %s
1 # RUN: not llvm-mc -triple arm-none-linux-gnu -mattr=-v8.4a --disassemble < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NO-V84
2
3 [0x12,0xf0,0x20,0xe3]
4
5 #CHECK: tsb csync
6
7 #CHECK-NO-V84: warning: invalid instruction encoding
8 #CHECK-NO-V84: [0x12,0xf0,0x20,0xe3]
9 #CHECK-NO-V84: ^
0 # RUN: llvm-mc -triple thumb-none-linux-gnu -mattr=+v8.4a --disassemble < %s | FileCheck %s
1 # RUN: not llvm-mc -triple thumb-none-linux-gnu -mattr=-v8.4a --disassemble < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NO-V84
2
3 [0xaf,0xf3,0x12,0x80]
4
5 #CHECK: tsb csync
6
7 #CHECK-NO-V84: warning: invalid instruction encoding
8 #CHECK-NO-V84: [0xaf,0xf3,0x12,0x80]
9 #CHECK-NO-V84: ^