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