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 AArch64PRFM {
550 struct PRFM : SysAlias {
551 using SysAlias::SysAlias;
552 };
553#define GET_PRFMValues_DECL
554#define GET_PRFMsList_DECL
555#include "AArch64GenSystemOperands.inc"
556}
557
558namespace AArch64SVEPRFM {
559 struct SVEPRFM : SysAlias {
560 using SysAlias::SysAlias;
561 };
562#define GET_SVEPRFMValues_DECL
563#define GET_SVEPRFMsList_DECL
564#include "AArch64GenSystemOperands.inc"
565}
566
567namespace AArch64RPRFM {
568struct RPRFM : SysAlias {
569 using SysAlias::SysAlias;
570};
571#define GET_RPRFMValues_DECL
572#define GET_RPRFMsList_DECL
573#include "AArch64GenSystemOperands.inc"
574} // namespace AArch64RPRFM
575
576namespace AArch64SVEPredPattern {
577 struct SVEPREDPAT {
578 StringTable::Offset Name;
579 uint16_t Encoding;
580 };
581#define GET_SVEPREDPATValues_DECL
582#define GET_SVEPREDPATsList_DECL
583#include "AArch64GenSystemOperands.inc"
584}
585
586namespace AArch64SVEVecLenSpecifier {
587 struct SVEVECLENSPECIFIER {
588 StringTable::Offset Name;
589 uint16_t Encoding;
590 };
591#define GET_SVEVECLENSPECIFIERValues_DECL
592#define GET_SVEVECLENSPECIFIERsList_DECL
593#include "AArch64GenSystemOperands.inc"
594} // namespace AArch64SVEVecLenSpecifier
595
596/// Return the number of active elements for VL1 to VL256 predicate pattern,
597/// zero for all other patterns.
598inline unsigned getNumElementsFromSVEPredPattern(unsigned Pattern) {
599 switch (Pattern) {
600 default:
601 return 0;
602 case AArch64SVEPredPattern::vl1:
603 case AArch64SVEPredPattern::vl2:
604 case AArch64SVEPredPattern::vl3:
605 case AArch64SVEPredPattern::vl4:
606 case AArch64SVEPredPattern::vl5:
607 case AArch64SVEPredPattern::vl6:
608 case AArch64SVEPredPattern::vl7:
609 case AArch64SVEPredPattern::vl8:
610 return Pattern;
611 case AArch64SVEPredPattern::vl16:
612 return 16;
613 case AArch64SVEPredPattern::vl32:
614 return 32;
615 case AArch64SVEPredPattern::vl64:
616 return 64;
617 case AArch64SVEPredPattern::vl128:
618 return 128;
619 case AArch64SVEPredPattern::vl256:
620 return 256;
621 }
622}
623
624/// Return specific VL predicate pattern based on the number of elements.
625inline std::optional<unsigned>
626getSVEPredPatternFromNumElements(unsigned MinNumElts) {
627 switch (MinNumElts) {
628 default:
629 return std::nullopt;
630 case 1:
631 case 2:
632 case 3:
633 case 4:
634 case 5:
635 case 6:
636 case 7:
637 case 8:
638 return MinNumElts;
639 case 16:
640 return AArch64SVEPredPattern::vl16;
641 case 32:
642 return AArch64SVEPredPattern::vl32;
643 case 64:
644 return AArch64SVEPredPattern::vl64;
645 case 128:
646 return AArch64SVEPredPattern::vl128;
647 case 256:
648 return AArch64SVEPredPattern::vl256;
649 }
650}
651
652/// An enum to describe what types of loops we should attempt to tail-fold:
653/// Disabled: None
654/// Reductions: Loops containing reductions
655/// Recurrences: Loops with first-order recurrences, i.e. that would
656/// require a SVE splice instruction
657/// Reverse: Reverse loops
658/// Simple: Loops that are not reversed and don't contain reductions
659/// or first-order recurrences.
660/// All: All
661enum class TailFoldingOpts : uint8_t {
662 Disabled = 0x00,
663 Simple = 0x01,
664 Reductions = 0x02,
665 Recurrences = 0x04,
666 Reverse = 0x08,
667 All = Reductions | Recurrences | Simple | Reverse
668};
669
670LLVM_DECLARE_ENUM_AS_BITMASK(TailFoldingOpts,
671 /* LargestValue */ (long)TailFoldingOpts::Reverse);
672
673namespace AArch64ExactFPImm {
674struct ExactFPImm {
675 int Enum;
676 StringTable::Offset Repr;
677};
678#define GET_ExactFPImmValues_DECL
679#define GET_ExactFPImmsList_DECL
680#include "AArch64GenSystemOperands.inc"
681}
682
683namespace AArch64PState {
684 struct PStateImm0_15 : SysAlias{
685 using SysAlias::SysAlias;
686 };
687#define GET_PStateImm0_15Values_DECL
688#define GET_PStateImm0_15sList_DECL
689#include "AArch64GenSystemOperands.inc"
690
691 struct PStateImm0_1 : SysAlias{
692 using SysAlias::SysAlias;
693 };
694#define GET_PStateImm0_1Values_DECL
695#define GET_PStateImm0_1sList_DECL
696#include "AArch64GenSystemOperands.inc"
697}
698
699namespace AArch64TIndexHint {
700struct TIndex : SysAlias {
701 using SysAlias::SysAlias;
702};
703#define GET_TINDEX_DECL
704#include "AArch64GenSystemOperands.inc"
705} // namespace AArch64TIndexHint
706
707namespace AArch64SME {
708enum ToggleCondition : unsigned {
709 Always,
710 IfCallerIsStreaming,
711 IfCallerIsNonStreaming
712};
713}
714
715namespace AArch64SE {
716 enum ShiftExtSpecifiers {
717 Invalid = -1,
718 LSL,
719 MSL,
720 LSR,
721 ASR,
722 ROR,
723
724 UXTB,
725 UXTH,
726 UXTW,
727 UXTX,
728
729 SXTB,
730 SXTH,
731 SXTW,
732 SXTX
733 };
734}
735
736namespace AArch64Layout {
737 enum VectorLayout {
738 Invalid = -1,
739 VL_8B,
740 VL_4H,
741 VL_2S,
742 VL_1D,
743
744 VL_16B,
745 VL_8H,
746 VL_4S,
747 VL_2D,
748
749 // Bare layout for the 128-bit vector
750 // (only show ".b", ".h", ".s", ".d" without vector number)
751 VL_B,
752 VL_H,
753 VL_S,
754 VL_D
755 };
756}
757
758inline static const char *
759AArch64VectorLayoutToString(AArch64Layout::VectorLayout Layout) {
760 switch (Layout) {
761 case AArch64Layout::VL_8B: return ".8b";
762 case AArch64Layout::VL_4H: return ".4h";
763 case AArch64Layout::VL_2S: return ".2s";
764 case AArch64Layout::VL_1D: return ".1d";
765 case AArch64Layout::VL_16B: return ".16b";
766 case AArch64Layout::VL_8H: return ".8h";
767 case AArch64Layout::VL_4S: return ".4s";
768 case AArch64Layout::VL_2D: return ".2d";
769 case AArch64Layout::VL_B: return ".b";
770 case AArch64Layout::VL_H: return ".h";
771 case AArch64Layout::VL_S: return ".s";
772 case AArch64Layout::VL_D: return ".d";
773 default: llvm_unreachable("Unknown Vector Layout");
774 }
775}
776
777inline static AArch64Layout::VectorLayout
778AArch64StringToVectorLayout(StringRef LayoutStr) {
779 return StringSwitch<AArch64Layout::VectorLayout>(LayoutStr)
780 .Case(S: ".8b", Value: AArch64Layout::VL_8B)
781 .Case(S: ".4h", Value: AArch64Layout::VL_4H)
782 .Case(S: ".2s", Value: AArch64Layout::VL_2S)
783 .Case(S: ".1d", Value: AArch64Layout::VL_1D)
784 .Case(S: ".16b", Value: AArch64Layout::VL_16B)
785 .Case(S: ".8h", Value: AArch64Layout::VL_8H)
786 .Case(S: ".4s", Value: AArch64Layout::VL_4S)
787 .Case(S: ".2d", Value: AArch64Layout::VL_2D)
788 .Case(S: ".b", Value: AArch64Layout::VL_B)
789 .Case(S: ".h", Value: AArch64Layout::VL_H)
790 .Case(S: ".s", Value: AArch64Layout::VL_S)
791 .Case(S: ".d", Value: AArch64Layout::VL_D)
792 .Default(Value: AArch64Layout::Invalid);
793}
794
795namespace AArch64SysReg {
796 struct SysReg {
797 StringTable::Offset Name;
798 unsigned Encoding;
799 bool Readable;
800 bool Writeable;
801 FeatureBitset FeaturesRequired;
802
803 bool haveFeatures(FeatureBitset ActiveFeatures) const {
804 return ActiveFeatures[llvm::AArch64::FeatureAll] ||
805 (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
806 }
807 };
808
809#define GET_SysRegsList_DECL
810#define GET_SysRegValues_DECL
811#include "AArch64GenSystemOperands.inc"
812
813 uint32_t parseGenericRegister(StringRef Name);
814 std::string genericRegisterString(uint32_t Bits);
815}
816
817namespace AArch64TLBI {
818struct TLBI : SysAliasOptionalReg {
819 using SysAliasOptionalReg::SysAliasOptionalReg;
820};
821#define GET_TLBITable_DECL
822#include "AArch64GenSystemOperands.inc"
823}
824
825namespace AArch64TLBIP {
826struct TLBIP : TLBIPSysAlias {
827 using TLBIPSysAlias::TLBIPSysAlias;
828};
829#define GET_TLBIPTable_DECL
830#include "AArch64GenSystemOperands.inc"
831} // namespace AArch64TLBIP
832
833namespace AArch64GIC {
834struct GIC : SysAliasReg {
835 using SysAliasReg::SysAliasReg;
836};
837#define GET_GICTable_DECL
838#include "AArch64GenSystemOperands.inc"
839} // namespace AArch64GIC
840
841namespace AArch64GICR {
842struct GICR : SysAliasReg {
843 using SysAliasReg::SysAliasReg;
844};
845#define GET_GICRTable_DECL
846#include "AArch64GenSystemOperands.inc"
847} // namespace AArch64GICR
848
849namespace AArch64GSB {
850struct GSB : SysAlias {
851 using SysAlias::SysAlias;
852};
853#define GET_GSBTable_DECL
854#include "AArch64GenSystemOperands.inc"
855} // namespace AArch64GSB
856
857namespace AArch64PLBI {
858struct PLBI : SysAliasOptionalReg {
859 using SysAliasOptionalReg::SysAliasOptionalReg;
860};
861#define GET_PLBITable_DECL
862#include "AArch64GenSystemOperands.inc"
863} // namespace AArch64PLBI
864
865namespace AArch64II {
866/// Target Operand Flag enum.
867enum TOF {
868 //===------------------------------------------------------------------===//
869 // AArch64 Specific MachineOperand flags.
870
871 MO_NO_FLAG,
872
873 MO_FRAGMENT = 0x7,
874
875 /// MO_PAGE - A symbol operand with this flag represents the pc-relative
876 /// offset of the 4K page containing the symbol. This is used with the
877 /// ADRP instruction.
878 MO_PAGE = 1,
879
880 /// MO_PAGEOFF - A symbol operand with this flag represents the offset of
881 /// that symbol within a 4K page. This offset is added to the page address
882 /// to produce the complete address.
883 MO_PAGEOFF = 2,
884
885 /// MO_G3 - A symbol operand with this flag (granule 3) represents the high
886 /// 16-bits of a 64-bit address, used in a MOVZ or MOVK instruction
887 MO_G3 = 3,
888
889 /// MO_G2 - A symbol operand with this flag (granule 2) represents the bits
890 /// 32-47 of a 64-bit address, used in a MOVZ or MOVK instruction
891 MO_G2 = 4,
892
893 /// MO_G1 - A symbol operand with this flag (granule 1) represents the bits
894 /// 16-31 of a 64-bit address, used in a MOVZ or MOVK instruction
895 MO_G1 = 5,
896
897 /// MO_G0 - A symbol operand with this flag (granule 0) represents the bits
898 /// 0-15 of a 64-bit address, used in a MOVZ or MOVK instruction
899 MO_G0 = 6,
900
901 /// MO_HI12 - This flag indicates that a symbol operand represents the bits
902 /// 13-24 of a 64-bit address, used in a arithmetic immediate-shifted-left-
903 /// by-12-bits instruction.
904 MO_HI12 = 7,
905
906 /// MO_COFFSTUB - On a symbol operand "FOO", this indicates that the
907 /// reference is actually to the ".refptr.FOO" symbol. This is used for
908 /// stub symbols on windows.
909 MO_COFFSTUB = 0x8,
910
911 /// MO_GOT - This flag indicates that a symbol operand represents the
912 /// address of the GOT entry for the symbol, rather than the address of
913 /// the symbol itself.
914 MO_GOT = 0x10,
915
916 /// MO_NC - Indicates whether the linker is expected to check the symbol
917 /// reference for overflow. For example in an ADRP/ADD pair of relocations
918 /// the ADRP usually does check, but not the ADD.
919 MO_NC = 0x20,
920
921 /// MO_TLS - Indicates that the operand being accessed is some kind of
922 /// thread-local symbol. On Darwin, only one type of thread-local access
923 /// exists (pre linker-relaxation), but on ELF the TLSModel used for the
924 /// referee will affect interpretation.
925 MO_TLS = 0x40,
926
927 /// MO_DLLIMPORT - On a symbol operand, this represents that the reference
928 /// to the symbol is for an import stub. This is used for DLL import
929 /// storage class indication on Windows.
930 MO_DLLIMPORT = 0x80,
931
932 /// MO_S - Indicates that the bits of the symbol operand represented by
933 /// MO_G0 etc are signed.
934 MO_S = 0x100,
935
936 /// MO_PREL - Indicates that the bits of the symbol operand represented by
937 /// MO_G0 etc are PC relative.
938 MO_PREL = 0x200,
939
940 /// MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag
941 /// in bits 56-63.
942 /// On a FrameIndex operand, indicates that the underlying memory is tagged
943 /// with an unknown tag value (MTE); this needs to be lowered either to an
944 /// SP-relative load or store instruction (which do not check tags), or to
945 /// an LDG instruction to obtain the tag value.
946 MO_TAGGED = 0x400,
947
948 /// MO_ARM64EC_CALLMANGLE - Operand refers to the Arm64EC-mangled version
949 /// of a symbol, not the original. For dllimport symbols, this means it
950 /// uses "__imp_aux". For other symbols, this means it uses the mangled
951 /// ("#" prefix for C) name.
952 MO_ARM64EC_CALLMANGLE = 0x800,
953};
954} // end namespace AArch64II
955
956//===----------------------------------------------------------------------===//
957// v8.3a Pointer Authentication
958//
959
960namespace AArch64PACKey {
961enum ID : uint8_t {
962 IA = 0,
963 IB = 1,
964 DA = 2,
965 DB = 3,
966 LAST = DB
967};
968} // namespace AArch64PACKey
969
970/// Return 2-letter identifier string for numeric key ID.
971inline static StringRef AArch64PACKeyIDToString(AArch64PACKey::ID KeyID) {
972 switch (KeyID) {
973 case AArch64PACKey::IA:
974 return StringRef("ia");
975 case AArch64PACKey::IB:
976 return StringRef("ib");
977 case AArch64PACKey::DA:
978 return StringRef("da");
979 case AArch64PACKey::DB:
980 return StringRef("db");
981 }
982 llvm_unreachable("Unhandled AArch64PACKey::ID enum");
983}
984
985/// Return numeric key ID for 2-letter identifier string.
986inline static std::optional<AArch64PACKey::ID>
987AArch64StringToPACKeyID(StringRef Name) {
988 if (Name == "ia")
989 return AArch64PACKey::IA;
990 if (Name == "ib")
991 return AArch64PACKey::IB;
992 if (Name == "da")
993 return AArch64PACKey::DA;
994 if (Name == "db")
995 return AArch64PACKey::DB;
996 return std::nullopt;
997}
998
999inline static unsigned getBTIHintNum(bool CallTarget, bool JumpTarget) {
1000 unsigned HintNum = 32;
1001 if (CallTarget)
1002 HintNum |= 2;
1003 if (JumpTarget)
1004 HintNum |= 4;
1005 assert(HintNum != 32 && "No target kinds!");
1006 return HintNum;
1007}
1008
1009namespace AArch64 {
1010// The number of bits in a SVE register is architecturally defined
1011// to be a multiple of this value. If <M x t> has this number of bits,
1012// a <n x M x t> vector can be stored in a SVE register without any
1013// redundant bits. If <M x t> has this number of bits divided by P,
1014// a <n x M x t> vector is stored in a SVE register by placing index i
1015// in index i*P of a <n x (M*P) x t> vector. The other elements of the
1016// <n x (M*P) x t> vector (such as index 1) are undefined.
1017static constexpr unsigned SVEBitsPerBlock = 128;
1018static constexpr unsigned SVEMaxBitsPerVector = 2048;
1019} // end namespace AArch64
1020} // end namespace llvm
1021
1022#endif
1023