10b57cec5SDimitry Andric //===-- AArch64BaseInfo.h - Top level definitions for AArch64 ---*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains small standalone helper functions and enum definitions for
100b57cec5SDimitry Andric // the AArch64 target useful for the compiler back-end and the MC libraries.
110b57cec5SDimitry Andric // As such, it deliberately does not include references to LLVM core
120b57cec5SDimitry Andric // code gen types, passes, etc..
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64BASEINFO_H
170b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64BASEINFO_H
180b57cec5SDimitry Andric
190b57cec5SDimitry Andric // FIXME: Is it easiest to fix this layering violation by moving the .inc
200b57cec5SDimitry Andric // #includes from AArch64MCTargetDesc.h to here?
210b57cec5SDimitry Andric #include "MCTargetDesc/AArch64MCTargetDesc.h" // For AArch64::X0 and friends.
2206c3fb27SDimitry Andric #include "llvm/ADT/BitmaskEnum.h"
230b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
240b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
250b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
2606c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric namespace llvm {
290b57cec5SDimitry Andric
getWRegFromXReg(unsigned Reg)300b57cec5SDimitry Andric inline static unsigned getWRegFromXReg(unsigned Reg) {
310b57cec5SDimitry Andric switch (Reg) {
320b57cec5SDimitry Andric case AArch64::X0: return AArch64::W0;
330b57cec5SDimitry Andric case AArch64::X1: return AArch64::W1;
340b57cec5SDimitry Andric case AArch64::X2: return AArch64::W2;
350b57cec5SDimitry Andric case AArch64::X3: return AArch64::W3;
360b57cec5SDimitry Andric case AArch64::X4: return AArch64::W4;
370b57cec5SDimitry Andric case AArch64::X5: return AArch64::W5;
380b57cec5SDimitry Andric case AArch64::X6: return AArch64::W6;
390b57cec5SDimitry Andric case AArch64::X7: return AArch64::W7;
400b57cec5SDimitry Andric case AArch64::X8: return AArch64::W8;
410b57cec5SDimitry Andric case AArch64::X9: return AArch64::W9;
420b57cec5SDimitry Andric case AArch64::X10: return AArch64::W10;
430b57cec5SDimitry Andric case AArch64::X11: return AArch64::W11;
440b57cec5SDimitry Andric case AArch64::X12: return AArch64::W12;
450b57cec5SDimitry Andric case AArch64::X13: return AArch64::W13;
460b57cec5SDimitry Andric case AArch64::X14: return AArch64::W14;
470b57cec5SDimitry Andric case AArch64::X15: return AArch64::W15;
480b57cec5SDimitry Andric case AArch64::X16: return AArch64::W16;
490b57cec5SDimitry Andric case AArch64::X17: return AArch64::W17;
500b57cec5SDimitry Andric case AArch64::X18: return AArch64::W18;
510b57cec5SDimitry Andric case AArch64::X19: return AArch64::W19;
520b57cec5SDimitry Andric case AArch64::X20: return AArch64::W20;
530b57cec5SDimitry Andric case AArch64::X21: return AArch64::W21;
540b57cec5SDimitry Andric case AArch64::X22: return AArch64::W22;
550b57cec5SDimitry Andric case AArch64::X23: return AArch64::W23;
560b57cec5SDimitry Andric case AArch64::X24: return AArch64::W24;
570b57cec5SDimitry Andric case AArch64::X25: return AArch64::W25;
580b57cec5SDimitry Andric case AArch64::X26: return AArch64::W26;
590b57cec5SDimitry Andric case AArch64::X27: return AArch64::W27;
600b57cec5SDimitry Andric case AArch64::X28: return AArch64::W28;
610b57cec5SDimitry Andric case AArch64::FP: return AArch64::W29;
620b57cec5SDimitry Andric case AArch64::LR: return AArch64::W30;
630b57cec5SDimitry Andric case AArch64::SP: return AArch64::WSP;
640b57cec5SDimitry Andric case AArch64::XZR: return AArch64::WZR;
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric // For anything else, return it unchanged.
670b57cec5SDimitry Andric return Reg;
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric
getXRegFromWReg(unsigned Reg)700b57cec5SDimitry Andric inline static unsigned getXRegFromWReg(unsigned Reg) {
710b57cec5SDimitry Andric switch (Reg) {
720b57cec5SDimitry Andric case AArch64::W0: return AArch64::X0;
730b57cec5SDimitry Andric case AArch64::W1: return AArch64::X1;
740b57cec5SDimitry Andric case AArch64::W2: return AArch64::X2;
750b57cec5SDimitry Andric case AArch64::W3: return AArch64::X3;
760b57cec5SDimitry Andric case AArch64::W4: return AArch64::X4;
770b57cec5SDimitry Andric case AArch64::W5: return AArch64::X5;
780b57cec5SDimitry Andric case AArch64::W6: return AArch64::X6;
790b57cec5SDimitry Andric case AArch64::W7: return AArch64::X7;
800b57cec5SDimitry Andric case AArch64::W8: return AArch64::X8;
810b57cec5SDimitry Andric case AArch64::W9: return AArch64::X9;
820b57cec5SDimitry Andric case AArch64::W10: return AArch64::X10;
830b57cec5SDimitry Andric case AArch64::W11: return AArch64::X11;
840b57cec5SDimitry Andric case AArch64::W12: return AArch64::X12;
850b57cec5SDimitry Andric case AArch64::W13: return AArch64::X13;
860b57cec5SDimitry Andric case AArch64::W14: return AArch64::X14;
870b57cec5SDimitry Andric case AArch64::W15: return AArch64::X15;
880b57cec5SDimitry Andric case AArch64::W16: return AArch64::X16;
890b57cec5SDimitry Andric case AArch64::W17: return AArch64::X17;
900b57cec5SDimitry Andric case AArch64::W18: return AArch64::X18;
910b57cec5SDimitry Andric case AArch64::W19: return AArch64::X19;
920b57cec5SDimitry Andric case AArch64::W20: return AArch64::X20;
930b57cec5SDimitry Andric case AArch64::W21: return AArch64::X21;
940b57cec5SDimitry Andric case AArch64::W22: return AArch64::X22;
950b57cec5SDimitry Andric case AArch64::W23: return AArch64::X23;
960b57cec5SDimitry Andric case AArch64::W24: return AArch64::X24;
970b57cec5SDimitry Andric case AArch64::W25: return AArch64::X25;
980b57cec5SDimitry Andric case AArch64::W26: return AArch64::X26;
990b57cec5SDimitry Andric case AArch64::W27: return AArch64::X27;
1000b57cec5SDimitry Andric case AArch64::W28: return AArch64::X28;
1010b57cec5SDimitry Andric case AArch64::W29: return AArch64::FP;
1020b57cec5SDimitry Andric case AArch64::W30: return AArch64::LR;
1030b57cec5SDimitry Andric case AArch64::WSP: return AArch64::SP;
1040b57cec5SDimitry Andric case AArch64::WZR: return AArch64::XZR;
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric // For anything else, return it unchanged.
1070b57cec5SDimitry Andric return Reg;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric
getXRegFromXRegTuple(unsigned RegTuple)1106e75b2fbSDimitry Andric inline static unsigned getXRegFromXRegTuple(unsigned RegTuple) {
1116e75b2fbSDimitry Andric switch (RegTuple) {
1126e75b2fbSDimitry Andric case AArch64::X0_X1_X2_X3_X4_X5_X6_X7: return AArch64::X0;
1136e75b2fbSDimitry Andric case AArch64::X2_X3_X4_X5_X6_X7_X8_X9: return AArch64::X2;
1146e75b2fbSDimitry Andric case AArch64::X4_X5_X6_X7_X8_X9_X10_X11: return AArch64::X4;
1156e75b2fbSDimitry Andric case AArch64::X6_X7_X8_X9_X10_X11_X12_X13: return AArch64::X6;
1166e75b2fbSDimitry Andric case AArch64::X8_X9_X10_X11_X12_X13_X14_X15: return AArch64::X8;
1176e75b2fbSDimitry Andric case AArch64::X10_X11_X12_X13_X14_X15_X16_X17: return AArch64::X10;
1186e75b2fbSDimitry Andric case AArch64::X12_X13_X14_X15_X16_X17_X18_X19: return AArch64::X12;
1196e75b2fbSDimitry Andric case AArch64::X14_X15_X16_X17_X18_X19_X20_X21: return AArch64::X14;
1206e75b2fbSDimitry Andric case AArch64::X16_X17_X18_X19_X20_X21_X22_X23: return AArch64::X16;
1216e75b2fbSDimitry Andric case AArch64::X18_X19_X20_X21_X22_X23_X24_X25: return AArch64::X18;
1226e75b2fbSDimitry Andric case AArch64::X20_X21_X22_X23_X24_X25_X26_X27: return AArch64::X20;
1236e75b2fbSDimitry Andric case AArch64::X22_X23_X24_X25_X26_X27_X28_FP: return AArch64::X22;
1246e75b2fbSDimitry Andric }
1256e75b2fbSDimitry Andric // For anything else, return it unchanged.
1266e75b2fbSDimitry Andric return RegTuple;
1276e75b2fbSDimitry Andric }
1286e75b2fbSDimitry Andric
getBRegFromDReg(unsigned Reg)1290b57cec5SDimitry Andric static inline unsigned getBRegFromDReg(unsigned Reg) {
1300b57cec5SDimitry Andric switch (Reg) {
1310b57cec5SDimitry Andric case AArch64::D0: return AArch64::B0;
1320b57cec5SDimitry Andric case AArch64::D1: return AArch64::B1;
1330b57cec5SDimitry Andric case AArch64::D2: return AArch64::B2;
1340b57cec5SDimitry Andric case AArch64::D3: return AArch64::B3;
1350b57cec5SDimitry Andric case AArch64::D4: return AArch64::B4;
1360b57cec5SDimitry Andric case AArch64::D5: return AArch64::B5;
1370b57cec5SDimitry Andric case AArch64::D6: return AArch64::B6;
1380b57cec5SDimitry Andric case AArch64::D7: return AArch64::B7;
1390b57cec5SDimitry Andric case AArch64::D8: return AArch64::B8;
1400b57cec5SDimitry Andric case AArch64::D9: return AArch64::B9;
1410b57cec5SDimitry Andric case AArch64::D10: return AArch64::B10;
1420b57cec5SDimitry Andric case AArch64::D11: return AArch64::B11;
1430b57cec5SDimitry Andric case AArch64::D12: return AArch64::B12;
1440b57cec5SDimitry Andric case AArch64::D13: return AArch64::B13;
1450b57cec5SDimitry Andric case AArch64::D14: return AArch64::B14;
1460b57cec5SDimitry Andric case AArch64::D15: return AArch64::B15;
1470b57cec5SDimitry Andric case AArch64::D16: return AArch64::B16;
1480b57cec5SDimitry Andric case AArch64::D17: return AArch64::B17;
1490b57cec5SDimitry Andric case AArch64::D18: return AArch64::B18;
1500b57cec5SDimitry Andric case AArch64::D19: return AArch64::B19;
1510b57cec5SDimitry Andric case AArch64::D20: return AArch64::B20;
1520b57cec5SDimitry Andric case AArch64::D21: return AArch64::B21;
1530b57cec5SDimitry Andric case AArch64::D22: return AArch64::B22;
1540b57cec5SDimitry Andric case AArch64::D23: return AArch64::B23;
1550b57cec5SDimitry Andric case AArch64::D24: return AArch64::B24;
1560b57cec5SDimitry Andric case AArch64::D25: return AArch64::B25;
1570b57cec5SDimitry Andric case AArch64::D26: return AArch64::B26;
1580b57cec5SDimitry Andric case AArch64::D27: return AArch64::B27;
1590b57cec5SDimitry Andric case AArch64::D28: return AArch64::B28;
1600b57cec5SDimitry Andric case AArch64::D29: return AArch64::B29;
1610b57cec5SDimitry Andric case AArch64::D30: return AArch64::B30;
1620b57cec5SDimitry Andric case AArch64::D31: return AArch64::B31;
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric // For anything else, return it unchanged.
1650b57cec5SDimitry Andric return Reg;
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric
getDRegFromBReg(unsigned Reg)1690b57cec5SDimitry Andric static inline unsigned getDRegFromBReg(unsigned Reg) {
1700b57cec5SDimitry Andric switch (Reg) {
1710b57cec5SDimitry Andric case AArch64::B0: return AArch64::D0;
1720b57cec5SDimitry Andric case AArch64::B1: return AArch64::D1;
1730b57cec5SDimitry Andric case AArch64::B2: return AArch64::D2;
1740b57cec5SDimitry Andric case AArch64::B3: return AArch64::D3;
1750b57cec5SDimitry Andric case AArch64::B4: return AArch64::D4;
1760b57cec5SDimitry Andric case AArch64::B5: return AArch64::D5;
1770b57cec5SDimitry Andric case AArch64::B6: return AArch64::D6;
1780b57cec5SDimitry Andric case AArch64::B7: return AArch64::D7;
1790b57cec5SDimitry Andric case AArch64::B8: return AArch64::D8;
1800b57cec5SDimitry Andric case AArch64::B9: return AArch64::D9;
1810b57cec5SDimitry Andric case AArch64::B10: return AArch64::D10;
1820b57cec5SDimitry Andric case AArch64::B11: return AArch64::D11;
1830b57cec5SDimitry Andric case AArch64::B12: return AArch64::D12;
1840b57cec5SDimitry Andric case AArch64::B13: return AArch64::D13;
1850b57cec5SDimitry Andric case AArch64::B14: return AArch64::D14;
1860b57cec5SDimitry Andric case AArch64::B15: return AArch64::D15;
1870b57cec5SDimitry Andric case AArch64::B16: return AArch64::D16;
1880b57cec5SDimitry Andric case AArch64::B17: return AArch64::D17;
1890b57cec5SDimitry Andric case AArch64::B18: return AArch64::D18;
1900b57cec5SDimitry Andric case AArch64::B19: return AArch64::D19;
1910b57cec5SDimitry Andric case AArch64::B20: return AArch64::D20;
1920b57cec5SDimitry Andric case AArch64::B21: return AArch64::D21;
1930b57cec5SDimitry Andric case AArch64::B22: return AArch64::D22;
1940b57cec5SDimitry Andric case AArch64::B23: return AArch64::D23;
1950b57cec5SDimitry Andric case AArch64::B24: return AArch64::D24;
1960b57cec5SDimitry Andric case AArch64::B25: return AArch64::D25;
1970b57cec5SDimitry Andric case AArch64::B26: return AArch64::D26;
1980b57cec5SDimitry Andric case AArch64::B27: return AArch64::D27;
1990b57cec5SDimitry Andric case AArch64::B28: return AArch64::D28;
2000b57cec5SDimitry Andric case AArch64::B29: return AArch64::D29;
2010b57cec5SDimitry Andric case AArch64::B30: return AArch64::D30;
2020b57cec5SDimitry Andric case AArch64::B31: return AArch64::D31;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric // For anything else, return it unchanged.
2050b57cec5SDimitry Andric return Reg;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric
atomicBarrierDroppedOnZero(unsigned Opcode)2080b57cec5SDimitry Andric static inline bool atomicBarrierDroppedOnZero(unsigned Opcode) {
2090b57cec5SDimitry Andric switch (Opcode) {
2100b57cec5SDimitry Andric case AArch64::LDADDAB: case AArch64::LDADDAH:
2110b57cec5SDimitry Andric case AArch64::LDADDAW: case AArch64::LDADDAX:
2120b57cec5SDimitry Andric case AArch64::LDADDALB: case AArch64::LDADDALH:
2130b57cec5SDimitry Andric case AArch64::LDADDALW: case AArch64::LDADDALX:
2140b57cec5SDimitry Andric case AArch64::LDCLRAB: case AArch64::LDCLRAH:
2150b57cec5SDimitry Andric case AArch64::LDCLRAW: case AArch64::LDCLRAX:
2160b57cec5SDimitry Andric case AArch64::LDCLRALB: case AArch64::LDCLRALH:
2170b57cec5SDimitry Andric case AArch64::LDCLRALW: case AArch64::LDCLRALX:
2180b57cec5SDimitry Andric case AArch64::LDEORAB: case AArch64::LDEORAH:
2190b57cec5SDimitry Andric case AArch64::LDEORAW: case AArch64::LDEORAX:
2200b57cec5SDimitry Andric case AArch64::LDEORALB: case AArch64::LDEORALH:
2210b57cec5SDimitry Andric case AArch64::LDEORALW: case AArch64::LDEORALX:
2220b57cec5SDimitry Andric case AArch64::LDSETAB: case AArch64::LDSETAH:
2230b57cec5SDimitry Andric case AArch64::LDSETAW: case AArch64::LDSETAX:
2240b57cec5SDimitry Andric case AArch64::LDSETALB: case AArch64::LDSETALH:
2250b57cec5SDimitry Andric case AArch64::LDSETALW: case AArch64::LDSETALX:
2260b57cec5SDimitry Andric case AArch64::LDSMAXAB: case AArch64::LDSMAXAH:
2270b57cec5SDimitry Andric case AArch64::LDSMAXAW: case AArch64::LDSMAXAX:
2280b57cec5SDimitry Andric case AArch64::LDSMAXALB: case AArch64::LDSMAXALH:
2290b57cec5SDimitry Andric case AArch64::LDSMAXALW: case AArch64::LDSMAXALX:
2300b57cec5SDimitry Andric case AArch64::LDSMINAB: case AArch64::LDSMINAH:
2310b57cec5SDimitry Andric case AArch64::LDSMINAW: case AArch64::LDSMINAX:
2320b57cec5SDimitry Andric case AArch64::LDSMINALB: case AArch64::LDSMINALH:
2330b57cec5SDimitry Andric case AArch64::LDSMINALW: case AArch64::LDSMINALX:
2340b57cec5SDimitry Andric case AArch64::LDUMAXAB: case AArch64::LDUMAXAH:
2350b57cec5SDimitry Andric case AArch64::LDUMAXAW: case AArch64::LDUMAXAX:
2360b57cec5SDimitry Andric case AArch64::LDUMAXALB: case AArch64::LDUMAXALH:
2370b57cec5SDimitry Andric case AArch64::LDUMAXALW: case AArch64::LDUMAXALX:
2380b57cec5SDimitry Andric case AArch64::LDUMINAB: case AArch64::LDUMINAH:
2390b57cec5SDimitry Andric case AArch64::LDUMINAW: case AArch64::LDUMINAX:
2400b57cec5SDimitry Andric case AArch64::LDUMINALB: case AArch64::LDUMINALH:
2410b57cec5SDimitry Andric case AArch64::LDUMINALW: case AArch64::LDUMINALX:
2420b57cec5SDimitry Andric case AArch64::SWPAB: case AArch64::SWPAH:
2430b57cec5SDimitry Andric case AArch64::SWPAW: case AArch64::SWPAX:
2440b57cec5SDimitry Andric case AArch64::SWPALB: case AArch64::SWPALH:
2450b57cec5SDimitry Andric case AArch64::SWPALW: case AArch64::SWPALX:
2460b57cec5SDimitry Andric return true;
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric return false;
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric namespace AArch64CC {
2520b57cec5SDimitry Andric
2530b57cec5SDimitry Andric // The CondCodes constants map directly to the 4-bit encoding of the condition
2540b57cec5SDimitry Andric // field for predicated instructions.
2550b57cec5SDimitry Andric enum CondCode { // Meaning (integer) Meaning (floating-point)
2560b57cec5SDimitry Andric EQ = 0x0, // Equal Equal
2570b57cec5SDimitry Andric NE = 0x1, // Not equal Not equal, or unordered
2580b57cec5SDimitry Andric HS = 0x2, // Unsigned higher or same >, ==, or unordered
2590b57cec5SDimitry Andric LO = 0x3, // Unsigned lower Less than
2600b57cec5SDimitry Andric MI = 0x4, // Minus, negative Less than
2610b57cec5SDimitry Andric PL = 0x5, // Plus, positive or zero >, ==, or unordered
2620b57cec5SDimitry Andric VS = 0x6, // Overflow Unordered
2630b57cec5SDimitry Andric VC = 0x7, // No overflow Not unordered
2640b57cec5SDimitry Andric HI = 0x8, // Unsigned higher Greater than, or unordered
2650b57cec5SDimitry Andric LS = 0x9, // Unsigned lower or same Less than or equal
2660b57cec5SDimitry Andric GE = 0xa, // Greater than or equal Greater than or equal
2670b57cec5SDimitry Andric LT = 0xb, // Less than Less than, or unordered
2680b57cec5SDimitry Andric GT = 0xc, // Greater than Greater than
2690b57cec5SDimitry Andric LE = 0xd, // Less than or equal <, ==, or unordered
2700b57cec5SDimitry Andric AL = 0xe, // Always (unconditional) Always (unconditional)
2710b57cec5SDimitry Andric NV = 0xf, // Always (unconditional) Always (unconditional)
2720b57cec5SDimitry Andric // Note the NV exists purely to disassemble 0b1111. Execution is "always".
273480093f4SDimitry Andric Invalid,
274480093f4SDimitry Andric
275480093f4SDimitry Andric // Common aliases used for SVE.
276480093f4SDimitry Andric ANY_ACTIVE = NE, // (!Z)
277480093f4SDimitry Andric FIRST_ACTIVE = MI, // ( N)
278480093f4SDimitry Andric LAST_ACTIVE = LO, // (!C)
279480093f4SDimitry Andric NONE_ACTIVE = EQ // ( Z)
2800b57cec5SDimitry Andric };
2810b57cec5SDimitry Andric
getCondCodeName(CondCode Code)2820b57cec5SDimitry Andric inline static const char *getCondCodeName(CondCode Code) {
2830b57cec5SDimitry Andric switch (Code) {
2840b57cec5SDimitry Andric default: llvm_unreachable("Unknown condition code");
2850b57cec5SDimitry Andric case EQ: return "eq";
2860b57cec5SDimitry Andric case NE: return "ne";
2870b57cec5SDimitry Andric case HS: return "hs";
2880b57cec5SDimitry Andric case LO: return "lo";
2890b57cec5SDimitry Andric case MI: return "mi";
2900b57cec5SDimitry Andric case PL: return "pl";
2910b57cec5SDimitry Andric case VS: return "vs";
2920b57cec5SDimitry Andric case VC: return "vc";
2930b57cec5SDimitry Andric case HI: return "hi";
2940b57cec5SDimitry Andric case LS: return "ls";
2950b57cec5SDimitry Andric case GE: return "ge";
2960b57cec5SDimitry Andric case LT: return "lt";
2970b57cec5SDimitry Andric case GT: return "gt";
2980b57cec5SDimitry Andric case LE: return "le";
2990b57cec5SDimitry Andric case AL: return "al";
3000b57cec5SDimitry Andric case NV: return "nv";
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric
getInvertedCondCode(CondCode Code)3040b57cec5SDimitry Andric inline static CondCode getInvertedCondCode(CondCode Code) {
3050b57cec5SDimitry Andric // To reverse a condition it's necessary to only invert the low bit:
3060b57cec5SDimitry Andric
3070b57cec5SDimitry Andric return static_cast<CondCode>(static_cast<unsigned>(Code) ^ 0x1);
3080b57cec5SDimitry Andric }
3090b57cec5SDimitry Andric
3100b57cec5SDimitry Andric /// Given a condition code, return NZCV flags that would satisfy that condition.
3110b57cec5SDimitry Andric /// The flag bits are in the format expected by the ccmp instructions.
3120b57cec5SDimitry Andric /// Note that many different flag settings can satisfy a given condition code,
3130b57cec5SDimitry Andric /// this function just returns one of them.
getNZCVToSatisfyCondCode(CondCode Code)3140b57cec5SDimitry Andric inline static unsigned getNZCVToSatisfyCondCode(CondCode Code) {
3150b57cec5SDimitry Andric // NZCV flags encoded as expected by ccmp instructions, ARMv8 ISA 5.5.7.
3160b57cec5SDimitry Andric enum { N = 8, Z = 4, C = 2, V = 1 };
3170b57cec5SDimitry Andric switch (Code) {
3180b57cec5SDimitry Andric default: llvm_unreachable("Unknown condition code");
3190b57cec5SDimitry Andric case EQ: return Z; // Z == 1
3200b57cec5SDimitry Andric case NE: return 0; // Z == 0
3210b57cec5SDimitry Andric case HS: return C; // C == 1
3220b57cec5SDimitry Andric case LO: return 0; // C == 0
3230b57cec5SDimitry Andric case MI: return N; // N == 1
3240b57cec5SDimitry Andric case PL: return 0; // N == 0
3250b57cec5SDimitry Andric case VS: return V; // V == 1
3260b57cec5SDimitry Andric case VC: return 0; // V == 0
3270b57cec5SDimitry Andric case HI: return C; // C == 1 && Z == 0
3280b57cec5SDimitry Andric case LS: return 0; // C == 0 || Z == 1
3290b57cec5SDimitry Andric case GE: return 0; // N == V
3300b57cec5SDimitry Andric case LT: return N; // N != V
3310b57cec5SDimitry Andric case GT: return 0; // Z == 0 && N == V
3320b57cec5SDimitry Andric case LE: return Z; // Z == 1 || N != V
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric }
335bdd1243dSDimitry Andric
3360b57cec5SDimitry Andric } // end namespace AArch64CC
3370b57cec5SDimitry Andric
3380b57cec5SDimitry Andric struct SysAlias {
3390b57cec5SDimitry Andric const char *Name;
3400b57cec5SDimitry Andric uint16_t Encoding;
3410b57cec5SDimitry Andric FeatureBitset FeaturesRequired;
3420b57cec5SDimitry Andric
SysAliasSysAlias3438bcb0991SDimitry Andric constexpr SysAlias(const char *N, uint16_t E) : Name(N), Encoding(E) {}
SysAliasSysAlias3448bcb0991SDimitry Andric constexpr SysAlias(const char *N, uint16_t E, FeatureBitset F)
3458bcb0991SDimitry Andric : Name(N), Encoding(E), FeaturesRequired(F) {}
3460b57cec5SDimitry Andric
haveFeaturesSysAlias3470b57cec5SDimitry Andric bool haveFeatures(FeatureBitset ActiveFeatures) const {
348753f127fSDimitry Andric return ActiveFeatures[llvm::AArch64::FeatureAll] ||
349753f127fSDimitry Andric (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
3500b57cec5SDimitry Andric }
3510b57cec5SDimitry Andric
getRequiredFeaturesSysAlias3520b57cec5SDimitry Andric FeatureBitset getRequiredFeatures() const { return FeaturesRequired; }
3530b57cec5SDimitry Andric };
3540b57cec5SDimitry Andric
3550b57cec5SDimitry Andric struct SysAliasReg : SysAlias {
3560b57cec5SDimitry Andric bool NeedsReg;
SysAliasRegSysAliasReg3578bcb0991SDimitry Andric constexpr SysAliasReg(const char *N, uint16_t E, bool R)
3588bcb0991SDimitry Andric : SysAlias(N, E), NeedsReg(R) {}
SysAliasRegSysAliasReg3598bcb0991SDimitry Andric constexpr SysAliasReg(const char *N, uint16_t E, bool R, FeatureBitset F)
3608bcb0991SDimitry Andric : SysAlias(N, E, F), NeedsReg(R) {}
3610b57cec5SDimitry Andric };
3620b57cec5SDimitry Andric
363e8d8bef9SDimitry Andric struct SysAliasImm : SysAlias {
364e8d8bef9SDimitry Andric uint16_t ImmValue;
SysAliasImmSysAliasImm365e8d8bef9SDimitry Andric constexpr SysAliasImm(const char *N, uint16_t E, uint16_t I)
366e8d8bef9SDimitry Andric : SysAlias(N, E), ImmValue(I) {}
SysAliasImmSysAliasImm367e8d8bef9SDimitry Andric constexpr SysAliasImm(const char *N, uint16_t E, uint16_t I, FeatureBitset F)
368e8d8bef9SDimitry Andric : SysAlias(N, E, F), ImmValue(I) {}
369e8d8bef9SDimitry Andric };
370e8d8bef9SDimitry Andric
371fe6060f1SDimitry Andric namespace AArch64SVCR {
372fe6060f1SDimitry Andric struct SVCR : SysAlias{
373fe6060f1SDimitry Andric using SysAlias::SysAlias;
374fe6060f1SDimitry Andric };
375fe6060f1SDimitry Andric #define GET_SVCR_DECL
376fe6060f1SDimitry Andric #include "AArch64GenSystemOperands.inc"
377fe6060f1SDimitry Andric }
378fe6060f1SDimitry Andric
3790b57cec5SDimitry Andric namespace AArch64AT{
3800b57cec5SDimitry Andric struct AT : SysAlias {
3810b57cec5SDimitry Andric using SysAlias::SysAlias;
3820b57cec5SDimitry Andric };
3830b57cec5SDimitry Andric #define GET_AT_DECL
3840b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric
3870b57cec5SDimitry Andric namespace AArch64DB {
3880b57cec5SDimitry Andric struct DB : SysAlias {
3890b57cec5SDimitry Andric using SysAlias::SysAlias;
3900b57cec5SDimitry Andric };
3910b57cec5SDimitry Andric #define GET_DB_DECL
3920b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric
395e8d8bef9SDimitry Andric namespace AArch64DBnXS {
396e8d8bef9SDimitry Andric struct DBnXS : SysAliasImm {
397e8d8bef9SDimitry Andric using SysAliasImm::SysAliasImm;
398e8d8bef9SDimitry Andric };
399e8d8bef9SDimitry Andric #define GET_DBNXS_DECL
400e8d8bef9SDimitry Andric #include "AArch64GenSystemOperands.inc"
401e8d8bef9SDimitry Andric }
402e8d8bef9SDimitry Andric
4030b57cec5SDimitry Andric namespace AArch64DC {
4040b57cec5SDimitry Andric struct DC : SysAlias {
4050b57cec5SDimitry Andric using SysAlias::SysAlias;
4060b57cec5SDimitry Andric };
4070b57cec5SDimitry Andric #define GET_DC_DECL
4080b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric
4110b57cec5SDimitry Andric namespace AArch64IC {
4120b57cec5SDimitry Andric struct IC : SysAliasReg {
4130b57cec5SDimitry Andric using SysAliasReg::SysAliasReg;
4140b57cec5SDimitry Andric };
4150b57cec5SDimitry Andric #define GET_IC_DECL
4160b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric
4190b57cec5SDimitry Andric namespace AArch64ISB {
4200b57cec5SDimitry Andric struct ISB : SysAlias {
4210b57cec5SDimitry Andric using SysAlias::SysAlias;
4220b57cec5SDimitry Andric };
4230b57cec5SDimitry Andric #define GET_ISB_DECL
4240b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
4250b57cec5SDimitry Andric }
4260b57cec5SDimitry Andric
4270b57cec5SDimitry Andric namespace AArch64TSB {
4280b57cec5SDimitry Andric struct TSB : SysAlias {
4290b57cec5SDimitry Andric using SysAlias::SysAlias;
4300b57cec5SDimitry Andric };
4310b57cec5SDimitry Andric #define GET_TSB_DECL
4320b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
4330b57cec5SDimitry Andric }
4340b57cec5SDimitry Andric
4350b57cec5SDimitry Andric namespace AArch64PRFM {
4360b57cec5SDimitry Andric struct PRFM : SysAlias {
4370b57cec5SDimitry Andric using SysAlias::SysAlias;
4380b57cec5SDimitry Andric };
4390b57cec5SDimitry Andric #define GET_PRFM_DECL
4400b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric
4430b57cec5SDimitry Andric namespace AArch64SVEPRFM {
4440b57cec5SDimitry Andric struct SVEPRFM : SysAlias {
4450b57cec5SDimitry Andric using SysAlias::SysAlias;
4460b57cec5SDimitry Andric };
4470b57cec5SDimitry Andric #define GET_SVEPRFM_DECL
4480b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
4490b57cec5SDimitry Andric }
4500b57cec5SDimitry Andric
451bdd1243dSDimitry Andric namespace AArch64RPRFM {
452bdd1243dSDimitry Andric struct RPRFM : SysAlias {
453bdd1243dSDimitry Andric using SysAlias::SysAlias;
454bdd1243dSDimitry Andric };
455bdd1243dSDimitry Andric #define GET_RPRFM_DECL
456bdd1243dSDimitry Andric #include "AArch64GenSystemOperands.inc"
457bdd1243dSDimitry Andric } // namespace AArch64RPRFM
458bdd1243dSDimitry Andric
4590b57cec5SDimitry Andric namespace AArch64SVEPredPattern {
4600b57cec5SDimitry Andric struct SVEPREDPAT {
4610b57cec5SDimitry Andric const char *Name;
4620b57cec5SDimitry Andric uint16_t Encoding;
4630b57cec5SDimitry Andric };
4640b57cec5SDimitry Andric #define GET_SVEPREDPAT_DECL
4650b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric
468bdd1243dSDimitry Andric namespace AArch64SVEVecLenSpecifier {
469bdd1243dSDimitry Andric struct SVEVECLENSPECIFIER {
470bdd1243dSDimitry Andric const char *Name;
471bdd1243dSDimitry Andric uint16_t Encoding;
472bdd1243dSDimitry Andric };
473bdd1243dSDimitry Andric #define GET_SVEVECLENSPECIFIER_DECL
474bdd1243dSDimitry Andric #include "AArch64GenSystemOperands.inc"
475bdd1243dSDimitry Andric } // namespace AArch64SVEVecLenSpecifier
476bdd1243dSDimitry Andric
477349cc55cSDimitry Andric /// Return the number of active elements for VL1 to VL256 predicate pattern,
478349cc55cSDimitry Andric /// zero for all other patterns.
getNumElementsFromSVEPredPattern(unsigned Pattern)479349cc55cSDimitry Andric inline unsigned getNumElementsFromSVEPredPattern(unsigned Pattern) {
480349cc55cSDimitry Andric switch (Pattern) {
481349cc55cSDimitry Andric default:
482349cc55cSDimitry Andric return 0;
483349cc55cSDimitry Andric case AArch64SVEPredPattern::vl1:
484349cc55cSDimitry Andric case AArch64SVEPredPattern::vl2:
485349cc55cSDimitry Andric case AArch64SVEPredPattern::vl3:
486349cc55cSDimitry Andric case AArch64SVEPredPattern::vl4:
487349cc55cSDimitry Andric case AArch64SVEPredPattern::vl5:
488349cc55cSDimitry Andric case AArch64SVEPredPattern::vl6:
489349cc55cSDimitry Andric case AArch64SVEPredPattern::vl7:
490349cc55cSDimitry Andric case AArch64SVEPredPattern::vl8:
491349cc55cSDimitry Andric return Pattern;
492349cc55cSDimitry Andric case AArch64SVEPredPattern::vl16:
493349cc55cSDimitry Andric return 16;
494349cc55cSDimitry Andric case AArch64SVEPredPattern::vl32:
495349cc55cSDimitry Andric return 32;
496349cc55cSDimitry Andric case AArch64SVEPredPattern::vl64:
497349cc55cSDimitry Andric return 64;
498349cc55cSDimitry Andric case AArch64SVEPredPattern::vl128:
499349cc55cSDimitry Andric return 128;
500349cc55cSDimitry Andric case AArch64SVEPredPattern::vl256:
501349cc55cSDimitry Andric return 256;
502349cc55cSDimitry Andric }
503349cc55cSDimitry Andric }
504349cc55cSDimitry Andric
505349cc55cSDimitry Andric /// Return specific VL predicate pattern based on the number of elements.
506bdd1243dSDimitry Andric inline std::optional<unsigned>
getSVEPredPatternFromNumElements(unsigned MinNumElts)50704eeddc0SDimitry Andric getSVEPredPatternFromNumElements(unsigned MinNumElts) {
508349cc55cSDimitry Andric switch (MinNumElts) {
509349cc55cSDimitry Andric default:
510bdd1243dSDimitry Andric return std::nullopt;
511349cc55cSDimitry Andric case 1:
512349cc55cSDimitry Andric case 2:
51304eeddc0SDimitry Andric case 3:
514349cc55cSDimitry Andric case 4:
51504eeddc0SDimitry Andric case 5:
51604eeddc0SDimitry Andric case 6:
51704eeddc0SDimitry Andric case 7:
518349cc55cSDimitry Andric case 8:
51904eeddc0SDimitry Andric return MinNumElts;
520349cc55cSDimitry Andric case 16:
521349cc55cSDimitry Andric return AArch64SVEPredPattern::vl16;
522349cc55cSDimitry Andric case 32:
523349cc55cSDimitry Andric return AArch64SVEPredPattern::vl32;
524349cc55cSDimitry Andric case 64:
525349cc55cSDimitry Andric return AArch64SVEPredPattern::vl64;
526349cc55cSDimitry Andric case 128:
527349cc55cSDimitry Andric return AArch64SVEPredPattern::vl128;
528349cc55cSDimitry Andric case 256:
529349cc55cSDimitry Andric return AArch64SVEPredPattern::vl256;
530349cc55cSDimitry Andric }
531349cc55cSDimitry Andric }
532349cc55cSDimitry Andric
53306c3fb27SDimitry Andric /// An enum to describe what types of loops we should attempt to tail-fold:
53406c3fb27SDimitry Andric /// Disabled: None
53506c3fb27SDimitry Andric /// Reductions: Loops containing reductions
53606c3fb27SDimitry Andric /// Recurrences: Loops with first-order recurrences, i.e. that would
53706c3fb27SDimitry Andric /// require a SVE splice instruction
53806c3fb27SDimitry Andric /// Reverse: Reverse loops
53906c3fb27SDimitry Andric /// Simple: Loops that are not reversed and don't contain reductions
54006c3fb27SDimitry Andric /// or first-order recurrences.
54106c3fb27SDimitry Andric /// All: All
54206c3fb27SDimitry Andric enum class TailFoldingOpts : uint8_t {
54306c3fb27SDimitry Andric Disabled = 0x00,
54406c3fb27SDimitry Andric Simple = 0x01,
54506c3fb27SDimitry Andric Reductions = 0x02,
54606c3fb27SDimitry Andric Recurrences = 0x04,
54706c3fb27SDimitry Andric Reverse = 0x08,
54806c3fb27SDimitry Andric All = Reductions | Recurrences | Simple | Reverse
54906c3fb27SDimitry Andric };
55006c3fb27SDimitry Andric
55106c3fb27SDimitry Andric LLVM_DECLARE_ENUM_AS_BITMASK(TailFoldingOpts,
55206c3fb27SDimitry Andric /* LargestValue */ (long)TailFoldingOpts::Reverse);
55306c3fb27SDimitry Andric
5540b57cec5SDimitry Andric namespace AArch64ExactFPImm {
5550b57cec5SDimitry Andric struct ExactFPImm {
5560b57cec5SDimitry Andric const char *Name;
5570b57cec5SDimitry Andric int Enum;
5580b57cec5SDimitry Andric const char *Repr;
5590b57cec5SDimitry Andric };
5600b57cec5SDimitry Andric #define GET_EXACTFPIMM_DECL
5610b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric
5640b57cec5SDimitry Andric namespace AArch64PState {
565bdd1243dSDimitry Andric struct PStateImm0_15 : SysAlias{
5660b57cec5SDimitry Andric using SysAlias::SysAlias;
5670b57cec5SDimitry Andric };
568bdd1243dSDimitry Andric #define GET_PSTATEIMM0_15_DECL
569bdd1243dSDimitry Andric #include "AArch64GenSystemOperands.inc"
570bdd1243dSDimitry Andric
571bdd1243dSDimitry Andric struct PStateImm0_1 : SysAlias{
572bdd1243dSDimitry Andric using SysAlias::SysAlias;
573bdd1243dSDimitry Andric };
574bdd1243dSDimitry Andric #define GET_PSTATEIMM0_1_DECL
5750b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric
5780b57cec5SDimitry Andric namespace AArch64PSBHint {
5790b57cec5SDimitry Andric struct PSB : SysAlias {
5800b57cec5SDimitry Andric using SysAlias::SysAlias;
5810b57cec5SDimitry Andric };
5820b57cec5SDimitry Andric #define GET_PSB_DECL
5830b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
5840b57cec5SDimitry Andric }
5850b57cec5SDimitry Andric
5860b57cec5SDimitry Andric namespace AArch64BTIHint {
5870b57cec5SDimitry Andric struct BTI : SysAlias {
5880b57cec5SDimitry Andric using SysAlias::SysAlias;
5890b57cec5SDimitry Andric };
5900b57cec5SDimitry Andric #define GET_BTI_DECL
5910b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
5920b57cec5SDimitry Andric }
5930b57cec5SDimitry Andric
5940b57cec5SDimitry Andric namespace AArch64SE {
5950b57cec5SDimitry Andric enum ShiftExtSpecifiers {
5960b57cec5SDimitry Andric Invalid = -1,
5970b57cec5SDimitry Andric LSL,
5980b57cec5SDimitry Andric MSL,
5990b57cec5SDimitry Andric LSR,
6000b57cec5SDimitry Andric ASR,
6010b57cec5SDimitry Andric ROR,
6020b57cec5SDimitry Andric
6030b57cec5SDimitry Andric UXTB,
6040b57cec5SDimitry Andric UXTH,
6050b57cec5SDimitry Andric UXTW,
6060b57cec5SDimitry Andric UXTX,
6070b57cec5SDimitry Andric
6080b57cec5SDimitry Andric SXTB,
6090b57cec5SDimitry Andric SXTH,
6100b57cec5SDimitry Andric SXTW,
6110b57cec5SDimitry Andric SXTX
6120b57cec5SDimitry Andric };
6130b57cec5SDimitry Andric }
6140b57cec5SDimitry Andric
6150b57cec5SDimitry Andric namespace AArch64Layout {
6160b57cec5SDimitry Andric enum VectorLayout {
6170b57cec5SDimitry Andric Invalid = -1,
6180b57cec5SDimitry Andric VL_8B,
6190b57cec5SDimitry Andric VL_4H,
6200b57cec5SDimitry Andric VL_2S,
6210b57cec5SDimitry Andric VL_1D,
6220b57cec5SDimitry Andric
6230b57cec5SDimitry Andric VL_16B,
6240b57cec5SDimitry Andric VL_8H,
6250b57cec5SDimitry Andric VL_4S,
6260b57cec5SDimitry Andric VL_2D,
6270b57cec5SDimitry Andric
6280b57cec5SDimitry Andric // Bare layout for the 128-bit vector
6290b57cec5SDimitry Andric // (only show ".b", ".h", ".s", ".d" without vector number)
6300b57cec5SDimitry Andric VL_B,
6310b57cec5SDimitry Andric VL_H,
6320b57cec5SDimitry Andric VL_S,
6330b57cec5SDimitry Andric VL_D
6340b57cec5SDimitry Andric };
6350b57cec5SDimitry Andric }
6360b57cec5SDimitry Andric
6370b57cec5SDimitry Andric inline static const char *
AArch64VectorLayoutToString(AArch64Layout::VectorLayout Layout)6380b57cec5SDimitry Andric AArch64VectorLayoutToString(AArch64Layout::VectorLayout Layout) {
6390b57cec5SDimitry Andric switch (Layout) {
6400b57cec5SDimitry Andric case AArch64Layout::VL_8B: return ".8b";
6410b57cec5SDimitry Andric case AArch64Layout::VL_4H: return ".4h";
6420b57cec5SDimitry Andric case AArch64Layout::VL_2S: return ".2s";
6430b57cec5SDimitry Andric case AArch64Layout::VL_1D: return ".1d";
6440b57cec5SDimitry Andric case AArch64Layout::VL_16B: return ".16b";
6450b57cec5SDimitry Andric case AArch64Layout::VL_8H: return ".8h";
6460b57cec5SDimitry Andric case AArch64Layout::VL_4S: return ".4s";
6470b57cec5SDimitry Andric case AArch64Layout::VL_2D: return ".2d";
6480b57cec5SDimitry Andric case AArch64Layout::VL_B: return ".b";
6490b57cec5SDimitry Andric case AArch64Layout::VL_H: return ".h";
6500b57cec5SDimitry Andric case AArch64Layout::VL_S: return ".s";
6510b57cec5SDimitry Andric case AArch64Layout::VL_D: return ".d";
6520b57cec5SDimitry Andric default: llvm_unreachable("Unknown Vector Layout");
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric }
6550b57cec5SDimitry Andric
6560b57cec5SDimitry Andric inline static AArch64Layout::VectorLayout
AArch64StringToVectorLayout(StringRef LayoutStr)6570b57cec5SDimitry Andric AArch64StringToVectorLayout(StringRef LayoutStr) {
6580b57cec5SDimitry Andric return StringSwitch<AArch64Layout::VectorLayout>(LayoutStr)
6590b57cec5SDimitry Andric .Case(".8b", AArch64Layout::VL_8B)
6600b57cec5SDimitry Andric .Case(".4h", AArch64Layout::VL_4H)
6610b57cec5SDimitry Andric .Case(".2s", AArch64Layout::VL_2S)
6620b57cec5SDimitry Andric .Case(".1d", AArch64Layout::VL_1D)
6630b57cec5SDimitry Andric .Case(".16b", AArch64Layout::VL_16B)
6640b57cec5SDimitry Andric .Case(".8h", AArch64Layout::VL_8H)
6650b57cec5SDimitry Andric .Case(".4s", AArch64Layout::VL_4S)
6660b57cec5SDimitry Andric .Case(".2d", AArch64Layout::VL_2D)
6670b57cec5SDimitry Andric .Case(".b", AArch64Layout::VL_B)
6680b57cec5SDimitry Andric .Case(".h", AArch64Layout::VL_H)
6690b57cec5SDimitry Andric .Case(".s", AArch64Layout::VL_S)
6700b57cec5SDimitry Andric .Case(".d", AArch64Layout::VL_D)
6710b57cec5SDimitry Andric .Default(AArch64Layout::Invalid);
6720b57cec5SDimitry Andric }
6730b57cec5SDimitry Andric
6740b57cec5SDimitry Andric namespace AArch64SysReg {
6750b57cec5SDimitry Andric struct SysReg {
6760b57cec5SDimitry Andric const char *Name;
677349cc55cSDimitry Andric const char *AltName;
6780b57cec5SDimitry Andric unsigned Encoding;
6790b57cec5SDimitry Andric bool Readable;
6800b57cec5SDimitry Andric bool Writeable;
6810b57cec5SDimitry Andric FeatureBitset FeaturesRequired;
6820b57cec5SDimitry Andric
haveFeaturesSysReg6830b57cec5SDimitry Andric bool haveFeatures(FeatureBitset ActiveFeatures) const {
68481ad6265SDimitry Andric return ActiveFeatures[llvm::AArch64::FeatureAll] ||
68581ad6265SDimitry Andric (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
6860b57cec5SDimitry Andric }
6870b57cec5SDimitry Andric };
6880b57cec5SDimitry Andric
6890b57cec5SDimitry Andric #define GET_SYSREG_DECL
6900b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
6910b57cec5SDimitry Andric
6920b57cec5SDimitry Andric const SysReg *lookupSysRegByName(StringRef);
6930b57cec5SDimitry Andric const SysReg *lookupSysRegByEncoding(uint16_t);
6940b57cec5SDimitry Andric
6950b57cec5SDimitry Andric uint32_t parseGenericRegister(StringRef Name);
6960b57cec5SDimitry Andric std::string genericRegisterString(uint32_t Bits);
6970b57cec5SDimitry Andric }
6980b57cec5SDimitry Andric
6990b57cec5SDimitry Andric namespace AArch64TLBI {
7000b57cec5SDimitry Andric struct TLBI : SysAliasReg {
7010b57cec5SDimitry Andric using SysAliasReg::SysAliasReg;
7020b57cec5SDimitry Andric };
703e8d8bef9SDimitry Andric #define GET_TLBITable_DECL
7040b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
7050b57cec5SDimitry Andric }
7060b57cec5SDimitry Andric
7070b57cec5SDimitry Andric namespace AArch64PRCTX {
7080b57cec5SDimitry Andric struct PRCTX : SysAliasReg {
7090b57cec5SDimitry Andric using SysAliasReg::SysAliasReg;
7100b57cec5SDimitry Andric };
7110b57cec5SDimitry Andric #define GET_PRCTX_DECL
7120b57cec5SDimitry Andric #include "AArch64GenSystemOperands.inc"
7130b57cec5SDimitry Andric }
7140b57cec5SDimitry Andric
7150b57cec5SDimitry Andric namespace AArch64II {
7160b57cec5SDimitry Andric /// Target Operand Flag enum.
7170b57cec5SDimitry Andric enum TOF {
7180b57cec5SDimitry Andric //===------------------------------------------------------------------===//
7190b57cec5SDimitry Andric // AArch64 Specific MachineOperand flags.
7200b57cec5SDimitry Andric
7210b57cec5SDimitry Andric MO_NO_FLAG,
7220b57cec5SDimitry Andric
7230b57cec5SDimitry Andric MO_FRAGMENT = 0x7,
7240b57cec5SDimitry Andric
7250b57cec5SDimitry Andric /// MO_PAGE - A symbol operand with this flag represents the pc-relative
7260b57cec5SDimitry Andric /// offset of the 4K page containing the symbol. This is used with the
7270b57cec5SDimitry Andric /// ADRP instruction.
7280b57cec5SDimitry Andric MO_PAGE = 1,
7290b57cec5SDimitry Andric
7300b57cec5SDimitry Andric /// MO_PAGEOFF - A symbol operand with this flag represents the offset of
7310b57cec5SDimitry Andric /// that symbol within a 4K page. This offset is added to the page address
7320b57cec5SDimitry Andric /// to produce the complete address.
7330b57cec5SDimitry Andric MO_PAGEOFF = 2,
7340b57cec5SDimitry Andric
7350b57cec5SDimitry Andric /// MO_G3 - A symbol operand with this flag (granule 3) represents the high
7360b57cec5SDimitry Andric /// 16-bits of a 64-bit address, used in a MOVZ or MOVK instruction
7370b57cec5SDimitry Andric MO_G3 = 3,
7380b57cec5SDimitry Andric
7390b57cec5SDimitry Andric /// MO_G2 - A symbol operand with this flag (granule 2) represents the bits
7400b57cec5SDimitry Andric /// 32-47 of a 64-bit address, used in a MOVZ or MOVK instruction
7410b57cec5SDimitry Andric MO_G2 = 4,
7420b57cec5SDimitry Andric
7430b57cec5SDimitry Andric /// MO_G1 - A symbol operand with this flag (granule 1) represents the bits
7440b57cec5SDimitry Andric /// 16-31 of a 64-bit address, used in a MOVZ or MOVK instruction
7450b57cec5SDimitry Andric MO_G1 = 5,
7460b57cec5SDimitry Andric
7470b57cec5SDimitry Andric /// MO_G0 - A symbol operand with this flag (granule 0) represents the bits
7480b57cec5SDimitry Andric /// 0-15 of a 64-bit address, used in a MOVZ or MOVK instruction
7490b57cec5SDimitry Andric MO_G0 = 6,
7500b57cec5SDimitry Andric
7510b57cec5SDimitry Andric /// MO_HI12 - This flag indicates that a symbol operand represents the bits
7520b57cec5SDimitry Andric /// 13-24 of a 64-bit address, used in a arithmetic immediate-shifted-left-
7530b57cec5SDimitry Andric /// by-12-bits instruction.
7540b57cec5SDimitry Andric MO_HI12 = 7,
7550b57cec5SDimitry Andric
7560b57cec5SDimitry Andric /// MO_COFFSTUB - On a symbol operand "FOO", this indicates that the
757e8d8bef9SDimitry Andric /// reference is actually to the ".refptr.FOO" symbol. This is used for
7580b57cec5SDimitry Andric /// stub symbols on windows.
7590b57cec5SDimitry Andric MO_COFFSTUB = 0x8,
7600b57cec5SDimitry Andric
7610b57cec5SDimitry Andric /// MO_GOT - This flag indicates that a symbol operand represents the
7620b57cec5SDimitry Andric /// address of the GOT entry for the symbol, rather than the address of
7630b57cec5SDimitry Andric /// the symbol itself.
7640b57cec5SDimitry Andric MO_GOT = 0x10,
7650b57cec5SDimitry Andric
7660b57cec5SDimitry Andric /// MO_NC - Indicates whether the linker is expected to check the symbol
7670b57cec5SDimitry Andric /// reference for overflow. For example in an ADRP/ADD pair of relocations
7680b57cec5SDimitry Andric /// the ADRP usually does check, but not the ADD.
7690b57cec5SDimitry Andric MO_NC = 0x20,
7700b57cec5SDimitry Andric
7710b57cec5SDimitry Andric /// MO_TLS - Indicates that the operand being accessed is some kind of
7720b57cec5SDimitry Andric /// thread-local symbol. On Darwin, only one type of thread-local access
7730b57cec5SDimitry Andric /// exists (pre linker-relaxation), but on ELF the TLSModel used for the
7740b57cec5SDimitry Andric /// referee will affect interpretation.
7750b57cec5SDimitry Andric MO_TLS = 0x40,
7760b57cec5SDimitry Andric
7770b57cec5SDimitry Andric /// MO_DLLIMPORT - On a symbol operand, this represents that the reference
7780b57cec5SDimitry Andric /// to the symbol is for an import stub. This is used for DLL import
7790b57cec5SDimitry Andric /// storage class indication on Windows.
7800b57cec5SDimitry Andric MO_DLLIMPORT = 0x80,
7810b57cec5SDimitry Andric
7820b57cec5SDimitry Andric /// MO_S - Indicates that the bits of the symbol operand represented by
7830b57cec5SDimitry Andric /// MO_G0 etc are signed.
7840b57cec5SDimitry Andric MO_S = 0x100,
7858bcb0991SDimitry Andric
7868bcb0991SDimitry Andric /// MO_PREL - Indicates that the bits of the symbol operand represented by
7878bcb0991SDimitry Andric /// MO_G0 etc are PC relative.
7888bcb0991SDimitry Andric MO_PREL = 0x200,
7898bcb0991SDimitry Andric
7908bcb0991SDimitry Andric /// MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag
7918bcb0991SDimitry Andric /// in bits 56-63.
7928bcb0991SDimitry Andric /// On a FrameIndex operand, indicates that the underlying memory is tagged
7938bcb0991SDimitry Andric /// with an unknown tag value (MTE); this needs to be lowered either to an
7948bcb0991SDimitry Andric /// SP-relative load or store instruction (which do not check tags), or to
7958bcb0991SDimitry Andric /// an LDG instruction to obtain the tag value.
7968bcb0991SDimitry Andric MO_TAGGED = 0x400,
797bdd1243dSDimitry Andric
7987a6dacacSDimitry Andric /// MO_ARM64EC_CALLMANGLE - Operand refers to the Arm64EC-mangled version
7997a6dacacSDimitry Andric /// of a symbol, not the original. For dllimport symbols, this means it
8007a6dacacSDimitry Andric /// uses "__imp_aux". For other symbols, this means it uses the mangled
8017a6dacacSDimitry Andric /// ("#" prefix for C) name.
8027a6dacacSDimitry Andric MO_ARM64EC_CALLMANGLE = 0x800,
8030b57cec5SDimitry Andric };
8040b57cec5SDimitry Andric } // end namespace AArch64II
8050b57cec5SDimitry Andric
806bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
807bdd1243dSDimitry Andric // v8.3a Pointer Authentication
808bdd1243dSDimitry Andric //
809bdd1243dSDimitry Andric
810bdd1243dSDimitry Andric namespace AArch64PACKey {
811bdd1243dSDimitry Andric enum ID : uint8_t {
812bdd1243dSDimitry Andric IA = 0,
813bdd1243dSDimitry Andric IB = 1,
814bdd1243dSDimitry Andric DA = 2,
815bdd1243dSDimitry Andric DB = 3,
816bdd1243dSDimitry Andric LAST = DB
817bdd1243dSDimitry Andric };
818bdd1243dSDimitry Andric } // namespace AArch64PACKey
819bdd1243dSDimitry Andric
820bdd1243dSDimitry Andric /// Return 2-letter identifier string for numeric key ID.
AArch64PACKeyIDToString(AArch64PACKey::ID KeyID)821bdd1243dSDimitry Andric inline static StringRef AArch64PACKeyIDToString(AArch64PACKey::ID KeyID) {
822bdd1243dSDimitry Andric switch (KeyID) {
823bdd1243dSDimitry Andric case AArch64PACKey::IA:
824bdd1243dSDimitry Andric return StringRef("ia");
825bdd1243dSDimitry Andric case AArch64PACKey::IB:
826bdd1243dSDimitry Andric return StringRef("ib");
827bdd1243dSDimitry Andric case AArch64PACKey::DA:
828bdd1243dSDimitry Andric return StringRef("da");
829bdd1243dSDimitry Andric case AArch64PACKey::DB:
830bdd1243dSDimitry Andric return StringRef("db");
831bdd1243dSDimitry Andric }
8325f757f3fSDimitry Andric llvm_unreachable("Unhandled AArch64PACKey::ID enum");
833bdd1243dSDimitry Andric }
834bdd1243dSDimitry Andric
835bdd1243dSDimitry Andric /// Return numeric key ID for 2-letter identifier string.
836bdd1243dSDimitry Andric inline static std::optional<AArch64PACKey::ID>
AArch64StringToPACKeyID(StringRef Name)837bdd1243dSDimitry Andric AArch64StringToPACKeyID(StringRef Name) {
838bdd1243dSDimitry Andric if (Name == "ia")
839bdd1243dSDimitry Andric return AArch64PACKey::IA;
840bdd1243dSDimitry Andric if (Name == "ib")
841bdd1243dSDimitry Andric return AArch64PACKey::IB;
842bdd1243dSDimitry Andric if (Name == "da")
843bdd1243dSDimitry Andric return AArch64PACKey::DA;
844bdd1243dSDimitry Andric if (Name == "db")
845bdd1243dSDimitry Andric return AArch64PACKey::DB;
846bdd1243dSDimitry Andric return std::nullopt;
847bdd1243dSDimitry Andric }
848bdd1243dSDimitry Andric
849480093f4SDimitry Andric namespace AArch64 {
850480093f4SDimitry Andric // The number of bits in a SVE register is architecturally defined
851480093f4SDimitry Andric // to be a multiple of this value. If <M x t> has this number of bits,
852480093f4SDimitry Andric // a <n x M x t> vector can be stored in a SVE register without any
853480093f4SDimitry Andric // redundant bits. If <M x t> has this number of bits divided by P,
854480093f4SDimitry Andric // a <n x M x t> vector is stored in a SVE register by placing index i
855480093f4SDimitry Andric // in index i*P of a <n x (M*P) x t> vector. The other elements of the
856480093f4SDimitry Andric // <n x (M*P) x t> vector (such as index 1) are undefined.
857480093f4SDimitry Andric static constexpr unsigned SVEBitsPerBlock = 128;
8585ffd83dbSDimitry Andric static constexpr unsigned SVEMaxBitsPerVector = 2048;
859480093f4SDimitry Andric } // end namespace AArch64
8600b57cec5SDimitry Andric } // end namespace llvm
8610b57cec5SDimitry Andric
8620b57cec5SDimitry Andric #endif
863