1//===-- AArch64BaseInfo.h - Top level definitions for AArch64 ---*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains small standalone helper functions and enum definitions for
10// the AArch64 target useful for the compiler back-end and the MC libraries.
11// As such, it deliberately does not include references to LLVM core
12// code gen types, passes, etc..
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64BASEINFO_H
17#define LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64BASEINFO_H
18
19// FIXME: Is it easiest to fix this layering violation by moving the .inc
20// #includes from AArch64MCTargetDesc.h to here?
21#include "MCTargetDesc/AArch64MCTargetDesc.h" // For AArch64::X0 and friends.
22#include "llvm/ADT/APFloat.h"
23#include "llvm/ADT/APSInt.h"
24#include "llvm/ADT/BitmaskEnum.h"
25#include "llvm/ADT/STLExtras.h"
26#include "llvm/ADT/StringSwitch.h"
27#include "llvm/ADT/StringTable.h"
28#include "llvm/Support/ErrorHandling.h"
29#include "llvm/TargetParser/SubtargetFeature.h"
30
31namespace llvm {
32
33inline static MCRegister getWRegFromXReg(MCRegister Reg) {
34 switch (Reg.id()) {
35 case AArch64::X0: return AArch64::W0;
36 case AArch64::X1: return AArch64::W1;
37 case AArch64::X2: return AArch64::W2;
38 case AArch64::X3: return AArch64::W3;
39 case AArch64::X4: return AArch64::W4;
40 case AArch64::X5: return AArch64::W5;
41 case AArch64::X6: return AArch64::W6;
42 case AArch64::X7: return AArch64::W7;
43 case AArch64::X8: return AArch64::W8;
44 case AArch64::X9: return AArch64::W9;
45 case AArch64::X10: return AArch64::W10;
46 case AArch64::X11: return AArch64::W11;
47 case AArch64::X12: return AArch64::W12;
48 case AArch64::X13: return AArch64::W13;
49 case AArch64::X14: return AArch64::W14;
50 case AArch64::X15: return AArch64::W15;
51 case AArch64::X16: return AArch64::W16;
52 case AArch64::X17: return AArch64::W17;
53 case AArch64::X18: return AArch64::W18;
54 case AArch64::X19: return AArch64::W19;
55 case AArch64::X20: return AArch64::W20;
56 case AArch64::X21: return AArch64::W21;
57 case AArch64::X22: return AArch64::W22;
58 case AArch64::X23: return AArch64::W23;
59 case AArch64::X24: return AArch64::W24;
60 case AArch64::X25: return AArch64::W25;
61 case AArch64::X26: return AArch64::W26;
62 case AArch64::X27: return AArch64::W27;
63 case AArch64::X28: return AArch64::W28;
64 case AArch64::FP: return AArch64::W29;
65 case AArch64::LR: return AArch64::W30;
66 case AArch64::SP: return AArch64::WSP;
67 case AArch64::XZR: return AArch64::WZR;
68 }
69 // For anything else, return it unchanged.
70 return Reg;
71}
72
73inline static MCRegister getXRegFromWReg(MCRegister Reg) {
74 switch (Reg.id()) {
75 case AArch64::W0: return AArch64::X0;
76 case AArch64::W1: return AArch64::X1;
77 case AArch64::W2: return AArch64::X2;
78 case AArch64::W3: return AArch64::X3;
79 case AArch64::W4: return AArch64::X4;
80 case AArch64::W5: return AArch64::X5;
81 case AArch64::W6: return AArch64::X6;
82 case AArch64::W7: return AArch64::X7;
83 case AArch64::W8: return AArch64::X8;
84 case AArch64::W9: return AArch64::X9;
85 case AArch64::W10: return AArch64::X10;
86 case AArch64::W11: return AArch64::X11;
87 case AArch64::W12: return AArch64::X12;
88 case AArch64::W13: return AArch64::X13;
89 case AArch64::W14: return AArch64::X14;
90 case AArch64::W15: return AArch64::X15;
91 case AArch64::W16: return AArch64::X16;
92 case AArch64::W17: return AArch64::X17;
93 case AArch64::W18: return AArch64::X18;
94 case AArch64::W19: return AArch64::X19;
95 case AArch64::W20: return AArch64::X20;
96 case AArch64::W21: return AArch64::X21;
97 case AArch64::W22: return AArch64::X22;
98 case AArch64::W23: return AArch64::X23;
99 case AArch64::W24: return AArch64::X24;
100 case AArch64::W25: return AArch64::X25;
101 case AArch64::W26: return AArch64::X26;
102 case AArch64::W27: return AArch64::X27;
103 case AArch64::W28: return AArch64::X28;
104 case AArch64::W29: return AArch64::FP;
105 case AArch64::W30: return AArch64::LR;
106 case AArch64::WSP: return AArch64::SP;
107 case AArch64::WZR: return AArch64::XZR;
108 }
109 // For anything else, return it unchanged.
110 return Reg;
111}
112
113inline static MCRegister getXRegFromXRegTuple(MCRegister RegTuple) {
114 switch (RegTuple.id()) {
115 case AArch64::X0_X1_X2_X3_X4_X5_X6_X7: return AArch64::X0;
116 case AArch64::X2_X3_X4_X5_X6_X7_X8_X9: return AArch64::X2;
117 case AArch64::X4_X5_X6_X7_X8_X9_X10_X11: return AArch64::X4;
118 case AArch64::X6_X7_X8_X9_X10_X11_X12_X13: return AArch64::X6;
119 case AArch64::X8_X9_X10_X11_X12_X13_X14_X15: return AArch64::X8;
120 case AArch64::X10_X11_X12_X13_X14_X15_X16_X17: return AArch64::X10;
121 case AArch64::X12_X13_X14_X15_X16_X17_X18_X19: return AArch64::X12;
122 case AArch64::X14_X15_X16_X17_X18_X19_X20_X21: return AArch64::X14;
123 case AArch64::X16_X17_X18_X19_X20_X21_X22_X23: return AArch64::X16;
124 case AArch64::X18_X19_X20_X21_X22_X23_X24_X25: return AArch64::X18;
125 case AArch64::X20_X21_X22_X23_X24_X25_X26_X27: return AArch64::X20;
126 case AArch64::X22_X23_X24_X25_X26_X27_X28_FP: return AArch64::X22;
127 }
128 // For anything else, return it unchanged.
129 return RegTuple;
130}
131
132static inline MCRegister getBRegFromDReg(MCRegister Reg) {
133 switch (Reg.id()) {
134 case AArch64::D0: return AArch64::B0;
135 case AArch64::D1: return AArch64::B1;
136 case AArch64::D2: return AArch64::B2;
137 case AArch64::D3: return AArch64::B3;
138 case AArch64::D4: return AArch64::B4;
139 case AArch64::D5: return AArch64::B5;
140 case AArch64::D6: return AArch64::B6;
141 case AArch64::D7: return AArch64::B7;
142 case AArch64::D8: return AArch64::B8;
143 case AArch64::D9: return AArch64::B9;
144 case AArch64::D10: return AArch64::B10;
145 case AArch64::D11: return AArch64::B11;
146 case AArch64::D12: return AArch64::B12;
147 case AArch64::D13: return AArch64::B13;
148 case AArch64::D14: return AArch64::B14;
149 case AArch64::D15: return AArch64::B15;
150 case AArch64::D16: return AArch64::B16;
151 case AArch64::D17: return AArch64::B17;
152 case AArch64::D18: return AArch64::B18;
153 case AArch64::D19: return AArch64::B19;
154 case AArch64::D20: return AArch64::B20;
155 case AArch64::D21: return AArch64::B21;
156 case AArch64::D22: return AArch64::B22;
157 case AArch64::D23: return AArch64::B23;
158 case AArch64::D24: return AArch64::B24;
159 case AArch64::D25: return AArch64::B25;
160 case AArch64::D26: return AArch64::B26;
161 case AArch64::D27: return AArch64::B27;
162 case AArch64::D28: return AArch64::B28;
163 case AArch64::D29: return AArch64::B29;
164 case AArch64::D30: return AArch64::B30;
165 case AArch64::D31: return AArch64::B31;
166 }
167 // For anything else, return it unchanged.
168 return Reg;
169}
170
171static inline MCRegister getDRegFromBReg(MCRegister Reg) {
172 switch (Reg.id()) {
173 case AArch64::B0: return AArch64::D0;
174 case AArch64::B1: return AArch64::D1;
175 case AArch64::B2: return AArch64::D2;
176 case AArch64::B3: return AArch64::D3;
177 case AArch64::B4: return AArch64::D4;
178 case AArch64::B5: return AArch64::D5;
179 case AArch64::B6: return AArch64::D6;
180 case AArch64::B7: return AArch64::D7;
181 case AArch64::B8: return AArch64::D8;
182 case AArch64::B9: return AArch64::D9;
183 case AArch64::B10: return AArch64::D10;
184 case AArch64::B11: return AArch64::D11;
185 case AArch64::B12: return AArch64::D12;
186 case AArch64::B13: return AArch64::D13;
187 case AArch64::B14: return AArch64::D14;
188 case AArch64::B15: return AArch64::D15;
189 case AArch64::B16: return AArch64::D16;
190 case AArch64::B17: return AArch64::D17;
191 case AArch64::B18: return AArch64::D18;
192 case AArch64::B19: return AArch64::D19;
193 case AArch64::B20: return AArch64::D20;
194 case AArch64::B21: return AArch64::D21;
195 case AArch64::B22: return AArch64::D22;
196 case AArch64::B23: return AArch64::D23;
197 case AArch64::B24: return AArch64::D24;
198 case AArch64::B25: return AArch64::D25;
199 case AArch64::B26: return AArch64::D26;
200 case AArch64::B27: return AArch64::D27;
201 case AArch64::B28: return AArch64::D28;
202 case AArch64::B29: return AArch64::D29;
203 case AArch64::B30: return AArch64::D30;
204 case AArch64::B31: return AArch64::D31;
205 }
206 // For anything else, return it unchanged.
207 return Reg;
208}
209
210static inline bool atomicBarrierDroppedOnZero(unsigned Opcode) {
211 switch (Opcode) {
212 case AArch64::LDADDAB: case AArch64::LDADDAH:
213 case AArch64::LDADDAW: case AArch64::LDADDAX:
214 case AArch64::LDADDALB: case AArch64::LDADDALH:
215 case AArch64::LDADDALW: case AArch64::LDADDALX:
216 case AArch64::LDCLRAB: case AArch64::LDCLRAH:
217 case AArch64::LDCLRAW: case AArch64::LDCLRAX:
218 case AArch64::LDCLRALB: case AArch64::LDCLRALH:
219 case AArch64::LDCLRALW: case AArch64::LDCLRALX:
220 case AArch64::LDEORAB: case AArch64::LDEORAH:
221 case AArch64::LDEORAW: case AArch64::LDEORAX:
222 case AArch64::LDEORALB: case AArch64::LDEORALH:
223 case AArch64::LDEORALW: case AArch64::LDEORALX:
224 case AArch64::LDSETAB: case AArch64::LDSETAH:
225 case AArch64::LDSETAW: case AArch64::LDSETAX:
226 case AArch64::LDSETALB: case AArch64::LDSETALH:
227 case AArch64::LDSETALW: case AArch64::LDSETALX:
228 case AArch64::LDSMAXAB: case AArch64::LDSMAXAH:
229 case AArch64::LDSMAXAW: case AArch64::LDSMAXAX:
230 case AArch64::LDSMAXALB: case AArch64::LDSMAXALH:
231 case AArch64::LDSMAXALW: case AArch64::LDSMAXALX:
232 case AArch64::LDSMINAB: case AArch64::LDSMINAH:
233 case AArch64::LDSMINAW: case AArch64::LDSMINAX:
234 case AArch64::LDSMINALB: case AArch64::LDSMINALH:
235 case AArch64::LDSMINALW: case AArch64::LDSMINALX:
236 case AArch64::LDUMAXAB: case AArch64::LDUMAXAH:
237 case AArch64::LDUMAXAW: case AArch64::LDUMAXAX:
238 case AArch64::LDUMAXALB: case AArch64::LDUMAXALH:
239 case AArch64::LDUMAXALW: case AArch64::LDUMAXALX:
240 case AArch64::LDUMINAB: case AArch64::LDUMINAH:
241 case AArch64::LDUMINAW: case AArch64::LDUMINAX:
242 case AArch64::LDUMINALB: case AArch64::LDUMINALH:
243 case AArch64::LDUMINALW: case AArch64::LDUMINALX:
244 case AArch64::SWPAB: case AArch64::SWPAH:
245 case AArch64::SWPAW: case AArch64::SWPAX:
246 case AArch64::SWPALB: case AArch64::SWPALH:
247 case AArch64::SWPALW: case AArch64::SWPALX:
248 return true;
249 }
250 return false;
251}
252
253inline unsigned CheckFixedPointOperandConstant(APFloat &FVal, unsigned RegWidth,
254 bool isReciprocal) {
255 // An FCVT[SU] instruction performs: convertToInt(Val * 2^fbits) where fbits
256 // is between 1 and 32 for a destination w-register, or 1 and 64 for an
257 // x-register.
258 //
259 // By this stage, we've detected (fp_to_[su]int (fmul Val, THIS_NODE)) so we
260 // want THIS_NODE to be 2^fbits. This is much easier to deal with using
261 // integers.
262 bool IsExact;
263
264 if (isReciprocal)
265 if (!FVal.getExactInverse(Inv: &FVal))
266 return 0;
267
268 // fbits is between 1 and 64 in the worst-case, which means the fmul
269 // could have 2^64 as an actual operand. Need 65 bits of precision.
270 APSInt IntVal(65, true);
271 FVal.convertToInteger(Result&: IntVal, RM: APFloat::rmTowardZero, IsExact: &IsExact);
272
273 // N.b. isPowerOf2 also checks for > 0.
274 if (!IsExact || !IntVal.isPowerOf2())
275 return 0;
276 unsigned FBits = IntVal.logBase2();
277
278 // Checks above should have guaranteed that we haven't lost information in
279 // finding FBits, but it must still be in range.
280 if (FBits == 0 || FBits > RegWidth)
281 return 0;
282 return FBits;
283}
284
285namespace AArch64CC {
286
287// The CondCodes constants map directly to the 4-bit encoding of the condition
288// field for predicated instructions.
289enum CondCode { // Meaning (integer) Meaning (floating-point)
290 EQ = 0x0, // Equal Equal
291 NE = 0x1, // Not equal Not equal, or unordered
292 HS = 0x2, // Unsigned higher or same >, ==, or unordered
293 LO = 0x3, // Unsigned lower Less than
294 MI = 0x4, // Minus, negative Less than
295 PL = 0x5, // Plus, positive or zero >, ==, or unordered
296 VS = 0x6, // Overflow Unordered
297 VC = 0x7, // No overflow Not unordered
298 HI = 0x8, // Unsigned higher Greater than, or unordered
299 LS = 0x9, // Unsigned lower or same Less than or equal
300 GE = 0xa, // Greater than or equal Greater than or equal
301 LT = 0xb, // Less than Less than, or unordered
302 GT = 0xc, // Greater than Greater than
303 LE = 0xd, // Less than or equal <, ==, or unordered
304 AL = 0xe, // Always (unconditional) Always (unconditional)
305 NV = 0xf, // Always (unconditional) Always (unconditional)
306 // Note the NV exists purely to disassemble 0b1111. Execution is "always".
307 Invalid,
308
309 // Common aliases used for SVE.
310 ANY_ACTIVE = NE, // (!Z)
311 FIRST_ACTIVE = MI, // ( N)
312 LAST_ACTIVE = LO, // (!C)
313 NONE_ACTIVE = EQ // ( Z)
314};
315
316inline static const char *getCondCodeName(CondCode Code) {
317 switch (Code) {
318 default: llvm_unreachable("Unknown condition code");
319 case EQ: return "eq";
320 case NE: return "ne";
321 case HS: return "hs";
322 case LO: return "lo";
323 case MI: return "mi";
324 case PL: return "pl";
325 case VS: return "vs";
326 case VC: return "vc";
327 case HI: return "hi";
328 case LS: return "ls";
329 case GE: return "ge";
330 case LT: return "lt";
331 case GT: return "gt";
332 case LE: return "le";
333 case AL: return "al";
334 case NV: return "nv";
335 }
336}
337
338inline static CondCode getInvertedCondCode(CondCode Code) {
339 // To reverse a condition it's necessary to only invert the low bit:
340
341 return static_cast<CondCode>(static_cast<unsigned>(Code) ^ 0x1);
342}
343
344/// getSwappedCondition - assume the flags are set by MI(a,b), return
345/// the condition code if we modify the instructions such that flags are
346/// set by MI(b,a).
347inline static CondCode getSwappedCondition(CondCode CC) {
348 switch (CC) {
349 default:
350 return AL;
351 case EQ:
352 return EQ;
353 case NE:
354 return NE;
355 case HS:
356 return LS;
357 case LO:
358 return HI;
359 case HI:
360 return LO;
361 case LS:
362 return HS;
363 case GE:
364 return LE;
365 case LT:
366 return GT;
367 case GT:
368 return LT;
369 case LE:
370 return GE;
371 }
372}
373
374/// Given a condition code, return NZCV flags that would satisfy that condition.
375/// The flag bits are in the format expected by the ccmp instructions.
376/// Note that many different flag settings can satisfy a given condition code,
377/// this function just returns one of them.
378inline static unsigned getNZCVToSatisfyCondCode(CondCode Code) {
379 // NZCV flags encoded as expected by ccmp instructions, ARMv8 ISA 5.5.7.
380 enum { N = 8, Z = 4, C = 2, V = 1 };
381 switch (Code) {
382 default: llvm_unreachable("Unknown condition code");
383 case EQ: return Z; // Z == 1
384 case NE: return 0; // Z == 0
385 case HS: return C; // C == 1
386 case LO: return 0; // C == 0
387 case MI: return N; // N == 1
388 case PL: return 0; // N == 0
389 case VS: return V; // V == 1
390 case VC: return 0; // V == 0
391 case HI: return C; // C == 1 && Z == 0
392 case LS: return 0; // C == 0 || Z == 1
393 case GE: return 0; // N == V
394 case LT: return N; // N != V
395 case GT: return 0; // Z == 0 && N == V
396 case LE: return Z; // Z == 1 || N != V
397 }
398}
399
400/// True, if a given condition code can be used in a fused compare-and-branch
401/// instructions, false otherwise.
402inline static bool isValidCBCond(AArch64CC::CondCode Code) {
403 switch (Code) {
404 default:
405 return false;
406 case AArch64CC::EQ:
407 case AArch64CC::NE:
408 case AArch64CC::HS:
409 case AArch64CC::LO:
410 case AArch64CC::HI:
411 case AArch64CC::LS:
412 case AArch64CC::GE:
413 case AArch64CC::LT:
414 case AArch64CC::GT:
415 case AArch64CC::LE:
416 return true;
417 }
418}
419
420} // end namespace AArch64CC
421
422struct SysAlias {
423 StringTable::Offset Name;
424 uint16_t Encoding;
425 FeatureBitset FeaturesRequired;
426
427 constexpr SysAlias(StringTable::Offset N, uint16_t E)
428 : Name(N), Encoding(E) {}
429 constexpr SysAlias(StringTable::Offset N, uint16_t E, FeatureBitset F)
430 : Name(N), Encoding(E), FeaturesRequired(F) {}
431
432 bool haveFeatures(FeatureBitset ActiveFeatures) const {
433 return ActiveFeatures[llvm::AArch64::FeatureAll] ||
434 (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
435 }
436
437 FeatureBitset getRequiredFeatures() const { return FeaturesRequired; }
438};
439
440#define GET_SysAliasRegUse_DECL
441#include "AArch64GenSystemOperands.inc"
442
443struct SysAliasReg : SysAlias {
444 bool NeedsReg;
445 constexpr SysAliasReg(StringTable::Offset N, uint16_t E, bool R)
446 : SysAlias(N, E), NeedsReg(R) {}
447 constexpr SysAliasReg(StringTable::Offset N, uint16_t E, bool R,
448 FeatureBitset F)
449 : SysAlias(N, E, F), NeedsReg(R) {}
450};
451
452struct SysAliasOptionalReg : SysAlias {
453 SysAliasRegUse RegUse;
454 constexpr SysAliasOptionalReg(StringTable::Offset N, uint16_t E,
455 SysAliasRegUse R)
456 : SysAlias(N, E), RegUse(R) {}
457 constexpr SysAliasOptionalReg(StringTable::Offset N, uint16_t E,
458 SysAliasRegUse R, FeatureBitset F)
459 : SysAlias(N, E, F), RegUse(R) {}
460};
461
462struct TLBIPSysAlias : SysAliasOptionalReg {
463 bool AllowWithTLBID;
464
465 constexpr TLBIPSysAlias(StringTable::Offset N, uint16_t E, SysAliasRegUse R,
466 FeatureBitset F, bool AllowWithTLBID)
467 : SysAliasOptionalReg(N, E, R, F), AllowWithTLBID(AllowWithTLBID) {}
468
469 bool haveFeatures(FeatureBitset ActiveFeatures) const {
470 return SysAliasOptionalReg::haveFeatures(ActiveFeatures) &&
471 (ActiveFeatures[llvm::AArch64::FeatureAll] ||
472 ActiveFeatures[llvm::AArch64::FeatureD128] ||
473 (AllowWithTLBID && ActiveFeatures[llvm::AArch64::FeatureTLBID]));
474 }
475};
476
477struct SysAliasImm : SysAlias {
478 uint16_t ImmValue;
479 constexpr SysAliasImm(StringTable::Offset N, uint16_t E, uint16_t I)
480 : SysAlias(N, E), ImmValue(I) {}
481 constexpr SysAliasImm(StringTable::Offset N, uint16_t E, uint16_t I,
482 FeatureBitset F)
483 : SysAlias(N, E, F), ImmValue(I) {}
484};
485
486namespace AArch64SVCR {
487 struct SVCR : SysAlias{
488 using SysAlias::SysAlias;
489 };
490#define GET_SVCRValues_DECL
491#define GET_SVCRsList_DECL
492#include "AArch64GenSystemOperands.inc"
493}
494
495namespace AArch64AT{
496 struct AT : SysAlias {
497 using SysAlias::SysAlias;
498 };
499#define GET_ATValues_DECL
500#define GET_ATsList_DECL
501#include "AArch64GenSystemOperands.inc"
502}
503
504namespace AArch64DB {
505 struct DB : SysAlias {
506 using SysAlias::SysAlias;
507 };
508#define GET_DBValues_DECL
509#define GET_DBsList_DECL
510#include "AArch64GenSystemOperands.inc"
511}
512
513namespace AArch64DBnXS {
514 struct DBnXS : SysAliasImm {
515 using SysAliasImm::SysAliasImm;
516 };
517#define GET_DBnXSValues_DECL
518#define GET_DBnXSsList_DECL
519#include "AArch64GenSystemOperands.inc"
520}
521
522namespace AArch64DC {
523 struct DC : SysAlias {
524 using SysAlias::SysAlias;
525 };
526#define GET_DCValues_DECL
527#define GET_DCsList_DECL
528#include "AArch64GenSystemOperands.inc"
529}
530
531namespace AArch64IC {
532 struct IC : SysAliasReg {
533 using SysAliasReg::SysAliasReg;
534 };
535#define GET_ICValues_DECL
536#define GET_ICsList_DECL
537#include "AArch64GenSystemOperands.inc"
538}
539
540namespace AArch64ISB {
541 struct ISB : SysAlias {
542 using SysAlias::SysAlias;
543 };
544#define GET_ISBValues_DECL
545#define GET_ISBsList_DECL
546#include "AArch64GenSystemOperands.inc"
547}
548
549namespace AArch64TSB {
550 struct TSB : SysAlias {
551 using SysAlias::SysAlias;
552 };
553#define GET_TSBValues_DECL
554#define GET_TSBsList_DECL
555#include "AArch64GenSystemOperands.inc"
556}
557
558namespace AArch64PRFM {
559 struct PRFM : SysAlias {
560 using SysAlias::SysAlias;
561 };
562#define GET_PRFMValues_DECL
563#define GET_PRFMsList_DECL
564#include "AArch64GenSystemOperands.inc"
565}
566
567namespace AArch64SVEPRFM {
568 struct SVEPRFM : SysAlias {
569 using SysAlias::SysAlias;
570 };
571#define GET_SVEPRFMValues_DECL
572#define GET_SVEPRFMsList_DECL
573#include "AArch64GenSystemOperands.inc"
574}
575
576namespace AArch64RPRFM {
577struct RPRFM : SysAlias {
578 using SysAlias::SysAlias;
579};
580#define GET_RPRFMValues_DECL
581#define GET_RPRFMsList_DECL
582#include "AArch64GenSystemOperands.inc"
583} // namespace AArch64RPRFM
584
585namespace AArch64SVEPredPattern {
586 struct SVEPREDPAT {
587 StringTable::Offset Name;
588 uint16_t Encoding;
589 };
590#define GET_SVEPREDPATValues_DECL
591#define GET_SVEPREDPATsList_DECL
592#include "AArch64GenSystemOperands.inc"
593}
594
595namespace AArch64SVEVecLenSpecifier {
596 struct SVEVECLENSPECIFIER {
597 StringTable::Offset Name;
598 uint16_t Encoding;
599 };
600#define GET_SVEVECLENSPECIFIERValues_DECL
601#define GET_SVEVECLENSPECIFIERsList_DECL
602#include "AArch64GenSystemOperands.inc"
603} // namespace AArch64SVEVecLenSpecifier
604
605/// Return the number of active elements for VL1 to VL256 predicate pattern,
606/// zero for all other patterns.
607inline unsigned getNumElementsFromSVEPredPattern(unsigned Pattern) {
608 switch (Pattern) {
609 default:
610 return 0;
611 case AArch64SVEPredPattern::vl1:
612 case AArch64SVEPredPattern::vl2:
613 case AArch64SVEPredPattern::vl3:
614 case AArch64SVEPredPattern::vl4:
615 case AArch64SVEPredPattern::vl5:
616 case AArch64SVEPredPattern::vl6:
617 case AArch64SVEPredPattern::vl7:
618 case AArch64SVEPredPattern::vl8:
619 return Pattern;
620 case AArch64SVEPredPattern::vl16:
621 return 16;
622 case AArch64SVEPredPattern::vl32:
623 return 32;
624 case AArch64SVEPredPattern::vl64:
625 return 64;
626 case AArch64SVEPredPattern::vl128:
627 return 128;
628 case AArch64SVEPredPattern::vl256:
629 return 256;
630 }
631}
632
633/// Return specific VL predicate pattern based on the number of elements.
634inline std::optional<unsigned>
635getSVEPredPatternFromNumElements(unsigned MinNumElts) {
636 switch (MinNumElts) {
637 default:
638 return std::nullopt;
639 case 1:
640 case 2:
641 case 3:
642 case 4:
643 case 5:
644 case 6:
645 case 7:
646 case 8:
647 return MinNumElts;
648 case 16:
649 return AArch64SVEPredPattern::vl16;
650 case 32:
651 return AArch64SVEPredPattern::vl32;
652 case 64:
653 return AArch64SVEPredPattern::vl64;
654 case 128:
655 return AArch64SVEPredPattern::vl128;
656 case 256:
657 return AArch64SVEPredPattern::vl256;
658 }
659}
660
661/// An enum to describe what types of loops we should attempt to tail-fold:
662/// Disabled: None
663/// Reductions: Loops containing reductions
664/// Recurrences: Loops with first-order recurrences, i.e. that would
665/// require a SVE splice instruction
666/// Reverse: Reverse loops
667/// Simple: Loops that are not reversed and don't contain reductions
668/// or first-order recurrences.
669/// All: All
670enum class TailFoldingOpts : uint8_t {
671 Disabled = 0x00,
672 Simple = 0x01,
673 Reductions = 0x02,
674 Recurrences = 0x04,
675 Reverse = 0x08,
676 All = Reductions | Recurrences | Simple | Reverse
677};
678
679LLVM_DECLARE_ENUM_AS_BITMASK(TailFoldingOpts,
680 /* LargestValue */ (long)TailFoldingOpts::Reverse);
681
682namespace AArch64ExactFPImm {
683struct ExactFPImm {
684 int Enum;
685 StringTable::Offset Repr;
686};
687#define GET_ExactFPImmValues_DECL
688#define GET_ExactFPImmsList_DECL
689#include "AArch64GenSystemOperands.inc"
690}
691
692namespace AArch64PState {
693 struct PStateImm0_15 : SysAlias{
694 using SysAlias::SysAlias;
695 };
696#define GET_PStateImm0_15Values_DECL
697#define GET_PStateImm0_15sList_DECL
698#include "AArch64GenSystemOperands.inc"
699
700 struct PStateImm0_1 : SysAlias{
701 using SysAlias::SysAlias;
702 };
703#define GET_PStateImm0_1Values_DECL
704#define GET_PStateImm0_1sList_DECL
705#include "AArch64GenSystemOperands.inc"
706}
707
708namespace AArch64PSBHint {
709 struct PSB : SysAlias {
710 using SysAlias::SysAlias;
711 };
712#define GET_PSBValues_DECL
713#define GET_PSBsList_DECL
714#include "AArch64GenSystemOperands.inc"
715}
716
717namespace AArch64PHint {
718struct PHint {
719 StringTable::Offset Name;
720 unsigned Encoding;
721 FeatureBitset FeaturesRequired;
722
723 bool haveFeatures(FeatureBitset ActiveFeatures) const {
724 return ActiveFeatures[llvm::AArch64::FeatureAll] ||
725 (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
726 }
727};
728
729#define GET_PHintValues_DECL
730#define GET_PHintsList_DECL
731#include "AArch64GenSystemOperands.inc"
732
733const PHint *lookupPHintByName(StringRef);
734const PHint *lookupPHintByEncoding(uint16_t);
735} // namespace AArch64PHint
736
737namespace AArch64BTIHint {
738 struct BTI : SysAlias {
739 using SysAlias::SysAlias;
740 };
741#define GET_BTIValues_DECL
742#define GET_BTIsList_DECL
743#include "AArch64GenSystemOperands.inc"
744}
745
746namespace AArch64CMHPriorityHint {
747struct CMHPriorityHint : SysAlias {
748 using SysAlias::SysAlias;
749};
750#define GET_CMHPRIORITYHINT_DECL
751#include "AArch64GenSystemOperands.inc"
752} // namespace AArch64CMHPriorityHint
753
754namespace AArch64TIndexHint {
755struct TIndex : SysAlias {
756 using SysAlias::SysAlias;
757};
758#define GET_TINDEX_DECL
759#include "AArch64GenSystemOperands.inc"
760} // namespace AArch64TIndexHint
761
762namespace AArch64SME {
763enum ToggleCondition : unsigned {
764 Always,
765 IfCallerIsStreaming,
766 IfCallerIsNonStreaming
767};
768}
769
770namespace AArch64SE {
771 enum ShiftExtSpecifiers {
772 Invalid = -1,
773 LSL,
774 MSL,
775 LSR,
776 ASR,
777 ROR,
778
779 UXTB,
780 UXTH,
781 UXTW,
782 UXTX,
783
784 SXTB,
785 SXTH,
786 SXTW,
787 SXTX
788 };
789}
790
791namespace AArch64Layout {
792 enum VectorLayout {
793 Invalid = -1,
794 VL_8B,
795 VL_4H,
796 VL_2S,
797 VL_1D,
798
799 VL_16B,
800 VL_8H,
801 VL_4S,
802 VL_2D,
803
804 // Bare layout for the 128-bit vector
805 // (only show ".b", ".h", ".s", ".d" without vector number)
806 VL_B,
807 VL_H,
808 VL_S,
809 VL_D
810 };
811}
812
813inline static const char *
814AArch64VectorLayoutToString(AArch64Layout::VectorLayout Layout) {
815 switch (Layout) {
816 case AArch64Layout::VL_8B: return ".8b";
817 case AArch64Layout::VL_4H: return ".4h";
818 case AArch64Layout::VL_2S: return ".2s";
819 case AArch64Layout::VL_1D: return ".1d";
820 case AArch64Layout::VL_16B: return ".16b";
821 case AArch64Layout::VL_8H: return ".8h";
822 case AArch64Layout::VL_4S: return ".4s";
823 case AArch64Layout::VL_2D: return ".2d";
824 case AArch64Layout::VL_B: return ".b";
825 case AArch64Layout::VL_H: return ".h";
826 case AArch64Layout::VL_S: return ".s";
827 case AArch64Layout::VL_D: return ".d";
828 default: llvm_unreachable("Unknown Vector Layout");
829 }
830}
831
832inline static AArch64Layout::VectorLayout
833AArch64StringToVectorLayout(StringRef LayoutStr) {
834 return StringSwitch<AArch64Layout::VectorLayout>(LayoutStr)
835 .Case(S: ".8b", Value: AArch64Layout::VL_8B)
836 .Case(S: ".4h", Value: AArch64Layout::VL_4H)
837 .Case(S: ".2s", Value: AArch64Layout::VL_2S)
838 .Case(S: ".1d", Value: AArch64Layout::VL_1D)
839 .Case(S: ".16b", Value: AArch64Layout::VL_16B)
840 .Case(S: ".8h", Value: AArch64Layout::VL_8H)
841 .Case(S: ".4s", Value: AArch64Layout::VL_4S)
842 .Case(S: ".2d", Value: AArch64Layout::VL_2D)
843 .Case(S: ".b", Value: AArch64Layout::VL_B)
844 .Case(S: ".h", Value: AArch64Layout::VL_H)
845 .Case(S: ".s", Value: AArch64Layout::VL_S)
846 .Case(S: ".d", Value: AArch64Layout::VL_D)
847 .Default(Value: AArch64Layout::Invalid);
848}
849
850namespace AArch64SysReg {
851 struct SysReg {
852 StringTable::Offset Name;
853 unsigned Encoding;
854 bool Readable;
855 bool Writeable;
856 FeatureBitset FeaturesRequired;
857
858 bool haveFeatures(FeatureBitset ActiveFeatures) const {
859 return ActiveFeatures[llvm::AArch64::FeatureAll] ||
860 (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
861 }
862 };
863
864#define GET_SysRegsList_DECL
865#define GET_SysRegValues_DECL
866#include "AArch64GenSystemOperands.inc"
867
868 uint32_t parseGenericRegister(StringRef Name);
869 std::string genericRegisterString(uint32_t Bits);
870}
871
872namespace AArch64TLBI {
873struct TLBI : SysAliasOptionalReg {
874 using SysAliasOptionalReg::SysAliasOptionalReg;
875};
876#define GET_TLBITable_DECL
877#include "AArch64GenSystemOperands.inc"
878}
879
880namespace AArch64TLBIP {
881struct TLBIP : TLBIPSysAlias {
882 using TLBIPSysAlias::TLBIPSysAlias;
883};
884#define GET_TLBIPTable_DECL
885#include "AArch64GenSystemOperands.inc"
886} // namespace AArch64TLBIP
887
888namespace AArch64GIC {
889struct GIC : SysAliasReg {
890 using SysAliasReg::SysAliasReg;
891};
892#define GET_GICTable_DECL
893#include "AArch64GenSystemOperands.inc"
894} // namespace AArch64GIC
895
896namespace AArch64GICR {
897struct GICR : SysAliasReg {
898 using SysAliasReg::SysAliasReg;
899};
900#define GET_GICRTable_DECL
901#include "AArch64GenSystemOperands.inc"
902} // namespace AArch64GICR
903
904namespace AArch64GSB {
905struct GSB : SysAlias {
906 using SysAlias::SysAlias;
907};
908#define GET_GSBTable_DECL
909#include "AArch64GenSystemOperands.inc"
910} // namespace AArch64GSB
911
912namespace AArch64PLBI {
913struct PLBI : SysAliasOptionalReg {
914 using SysAliasOptionalReg::SysAliasOptionalReg;
915};
916#define GET_PLBITable_DECL
917#include "AArch64GenSystemOperands.inc"
918} // namespace AArch64PLBI
919
920namespace AArch64II {
921/// Target Operand Flag enum.
922enum TOF {
923 //===------------------------------------------------------------------===//
924 // AArch64 Specific MachineOperand flags.
925
926 MO_NO_FLAG,
927
928 MO_FRAGMENT = 0x7,
929
930 /// MO_PAGE - A symbol operand with this flag represents the pc-relative
931 /// offset of the 4K page containing the symbol. This is used with the
932 /// ADRP instruction.
933 MO_PAGE = 1,
934
935 /// MO_PAGEOFF - A symbol operand with this flag represents the offset of
936 /// that symbol within a 4K page. This offset is added to the page address
937 /// to produce the complete address.
938 MO_PAGEOFF = 2,
939
940 /// MO_G3 - A symbol operand with this flag (granule 3) represents the high
941 /// 16-bits of a 64-bit address, used in a MOVZ or MOVK instruction
942 MO_G3 = 3,
943
944 /// MO_G2 - A symbol operand with this flag (granule 2) represents the bits
945 /// 32-47 of a 64-bit address, used in a MOVZ or MOVK instruction
946 MO_G2 = 4,
947
948 /// MO_G1 - A symbol operand with this flag (granule 1) represents the bits
949 /// 16-31 of a 64-bit address, used in a MOVZ or MOVK instruction
950 MO_G1 = 5,
951
952 /// MO_G0 - A symbol operand with this flag (granule 0) represents the bits
953 /// 0-15 of a 64-bit address, used in a MOVZ or MOVK instruction
954 MO_G0 = 6,
955
956 /// MO_HI12 - This flag indicates that a symbol operand represents the bits
957 /// 13-24 of a 64-bit address, used in a arithmetic immediate-shifted-left-
958 /// by-12-bits instruction.
959 MO_HI12 = 7,
960
961 /// MO_COFFSTUB - On a symbol operand "FOO", this indicates that the
962 /// reference is actually to the ".refptr.FOO" symbol. This is used for
963 /// stub symbols on windows.
964 MO_COFFSTUB = 0x8,
965
966 /// MO_GOT - This flag indicates that a symbol operand represents the
967 /// address of the GOT entry for the symbol, rather than the address of
968 /// the symbol itself.
969 MO_GOT = 0x10,
970
971 /// MO_NC - Indicates whether the linker is expected to check the symbol
972 /// reference for overflow. For example in an ADRP/ADD pair of relocations
973 /// the ADRP usually does check, but not the ADD.
974 MO_NC = 0x20,
975
976 /// MO_TLS - Indicates that the operand being accessed is some kind of
977 /// thread-local symbol. On Darwin, only one type of thread-local access
978 /// exists (pre linker-relaxation), but on ELF the TLSModel used for the
979 /// referee will affect interpretation.
980 MO_TLS = 0x40,
981
982 /// MO_DLLIMPORT - On a symbol operand, this represents that the reference
983 /// to the symbol is for an import stub. This is used for DLL import
984 /// storage class indication on Windows.
985 MO_DLLIMPORT = 0x80,
986
987 /// MO_S - Indicates that the bits of the symbol operand represented by
988 /// MO_G0 etc are signed.
989 MO_S = 0x100,
990
991 /// MO_PREL - Indicates that the bits of the symbol operand represented by
992 /// MO_G0 etc are PC relative.
993 MO_PREL = 0x200,
994
995 /// MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag
996 /// in bits 56-63.
997 /// On a FrameIndex operand, indicates that the underlying memory is tagged
998 /// with an unknown tag value (MTE); this needs to be lowered either to an
999 /// SP-relative load or store instruction (which do not check tags), or to
1000 /// an LDG instruction to obtain the tag value.
1001 MO_TAGGED = 0x400,
1002
1003 /// MO_ARM64EC_CALLMANGLE - Operand refers to the Arm64EC-mangled version
1004 /// of a symbol, not the original. For dllimport symbols, this means it
1005 /// uses "__imp_aux". For other symbols, this means it uses the mangled
1006 /// ("#" prefix for C) name.
1007 MO_ARM64EC_CALLMANGLE = 0x800,
1008};
1009} // end namespace AArch64II
1010
1011//===----------------------------------------------------------------------===//
1012// v8.3a Pointer Authentication
1013//
1014
1015namespace AArch64PACKey {
1016enum ID : uint8_t {
1017 IA = 0,
1018 IB = 1,
1019 DA = 2,
1020 DB = 3,
1021 LAST = DB
1022};
1023} // namespace AArch64PACKey
1024
1025/// Return 2-letter identifier string for numeric key ID.
1026inline static StringRef AArch64PACKeyIDToString(AArch64PACKey::ID KeyID) {
1027 switch (KeyID) {
1028 case AArch64PACKey::IA:
1029 return StringRef("ia");
1030 case AArch64PACKey::IB:
1031 return StringRef("ib");
1032 case AArch64PACKey::DA:
1033 return StringRef("da");
1034 case AArch64PACKey::DB:
1035 return StringRef("db");
1036 }
1037 llvm_unreachable("Unhandled AArch64PACKey::ID enum");
1038}
1039
1040/// Return numeric key ID for 2-letter identifier string.
1041inline static std::optional<AArch64PACKey::ID>
1042AArch64StringToPACKeyID(StringRef Name) {
1043 if (Name == "ia")
1044 return AArch64PACKey::IA;
1045 if (Name == "ib")
1046 return AArch64PACKey::IB;
1047 if (Name == "da")
1048 return AArch64PACKey::DA;
1049 if (Name == "db")
1050 return AArch64PACKey::DB;
1051 return std::nullopt;
1052}
1053
1054inline static unsigned getBTIHintNum(bool CallTarget, bool JumpTarget) {
1055 unsigned HintNum = 32;
1056 if (CallTarget)
1057 HintNum |= 2;
1058 if (JumpTarget)
1059 HintNum |= 4;
1060 assert(HintNum != 32 && "No target kinds!");
1061 return HintNum;
1062}
1063
1064namespace AArch64 {
1065// The number of bits in a SVE register is architecturally defined
1066// to be a multiple of this value. If <M x t> has this number of bits,
1067// a <n x M x t> vector can be stored in a SVE register without any
1068// redundant bits. If <M x t> has this number of bits divided by P,
1069// a <n x M x t> vector is stored in a SVE register by placing index i
1070// in index i*P of a <n x (M*P) x t> vector. The other elements of the
1071// <n x (M*P) x t> vector (such as index 1) are undefined.
1072static constexpr unsigned SVEBitsPerBlock = 128;
1073static constexpr unsigned SVEMaxBitsPerVector = 2048;
1074} // end namespace AArch64
1075} // end namespace llvm
1076
1077#endif
1078