xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/Utils/ARMBaseInfo.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===-- ARMBaseInfo.h - Top level definitions for ARM ---*- 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 ARM 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_ARM_UTILS_ARMBASEINFO_H
170b57cec5SDimitry Andric #define LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
200b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
21*06c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
220b57cec5SDimitry Andric #include "MCTargetDesc/ARMMCTargetDesc.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace llvm {
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric // Enums corresponding to ARM condition codes
270b57cec5SDimitry Andric namespace ARMCC {
280b57cec5SDimitry Andric // The CondCodes constants map directly to the 4-bit encoding of the
290b57cec5SDimitry Andric // condition field for predicated instructions.
300b57cec5SDimitry Andric enum CondCodes { // Meaning (integer)          Meaning (floating-point)
310b57cec5SDimitry Andric   EQ,            // Equal                      Equal
320b57cec5SDimitry Andric   NE,            // Not equal                  Not equal, or unordered
330b57cec5SDimitry Andric   HS,            // Carry set                  >, ==, or unordered
340b57cec5SDimitry Andric   LO,            // Carry clear                Less than
350b57cec5SDimitry Andric   MI,            // Minus, negative            Less than
360b57cec5SDimitry Andric   PL,            // Plus, positive or zero     >, ==, or unordered
370b57cec5SDimitry Andric   VS,            // Overflow                   Unordered
380b57cec5SDimitry Andric   VC,            // No overflow                Not unordered
390b57cec5SDimitry Andric   HI,            // Unsigned higher            Greater than, or unordered
400b57cec5SDimitry Andric   LS,            // Unsigned lower or same     Less than or equal
410b57cec5SDimitry Andric   GE,            // Greater than or equal      Greater than or equal
420b57cec5SDimitry Andric   LT,            // Less than                  Less than, or unordered
430b57cec5SDimitry Andric   GT,            // Greater than               Greater than
440b57cec5SDimitry Andric   LE,            // Less than or equal         <, ==, or unordered
450b57cec5SDimitry Andric   AL             // Always (unconditional)     Always (unconditional)
460b57cec5SDimitry Andric };
470b57cec5SDimitry Andric 
getOppositeCondition(CondCodes CC)480b57cec5SDimitry Andric inline static CondCodes getOppositeCondition(CondCodes CC) {
490b57cec5SDimitry Andric   switch (CC) {
500b57cec5SDimitry Andric   default: llvm_unreachable("Unknown condition code");
510b57cec5SDimitry Andric   case EQ: return NE;
520b57cec5SDimitry Andric   case NE: return EQ;
530b57cec5SDimitry Andric   case HS: return LO;
540b57cec5SDimitry Andric   case LO: return HS;
550b57cec5SDimitry Andric   case MI: return PL;
560b57cec5SDimitry Andric   case PL: return MI;
570b57cec5SDimitry Andric   case VS: return VC;
580b57cec5SDimitry Andric   case VC: return VS;
590b57cec5SDimitry Andric   case HI: return LS;
600b57cec5SDimitry Andric   case LS: return HI;
610b57cec5SDimitry Andric   case GE: return LT;
620b57cec5SDimitry Andric   case LT: return GE;
630b57cec5SDimitry Andric   case GT: return LE;
640b57cec5SDimitry Andric   case LE: return GT;
650b57cec5SDimitry Andric   }
660b57cec5SDimitry Andric }
67480093f4SDimitry Andric 
68480093f4SDimitry Andric /// getSwappedCondition - assume the flags are set by MI(a,b), return
69480093f4SDimitry Andric /// the condition code if we modify the instructions such that flags are
70480093f4SDimitry Andric /// set by MI(b,a).
getSwappedCondition(ARMCC::CondCodes CC)71480093f4SDimitry Andric inline static ARMCC::CondCodes getSwappedCondition(ARMCC::CondCodes CC) {
72480093f4SDimitry Andric   switch (CC) {
73480093f4SDimitry Andric   default: return ARMCC::AL;
74480093f4SDimitry Andric   case ARMCC::EQ: return ARMCC::EQ;
75480093f4SDimitry Andric   case ARMCC::NE: return ARMCC::NE;
76480093f4SDimitry Andric   case ARMCC::HS: return ARMCC::LS;
77480093f4SDimitry Andric   case ARMCC::LO: return ARMCC::HI;
78480093f4SDimitry Andric   case ARMCC::HI: return ARMCC::LO;
79480093f4SDimitry Andric   case ARMCC::LS: return ARMCC::HS;
80480093f4SDimitry Andric   case ARMCC::GE: return ARMCC::LE;
81480093f4SDimitry Andric   case ARMCC::LT: return ARMCC::GT;
82480093f4SDimitry Andric   case ARMCC::GT: return ARMCC::LT;
83480093f4SDimitry Andric   case ARMCC::LE: return ARMCC::GE;
84480093f4SDimitry Andric   }
85480093f4SDimitry Andric }
860b57cec5SDimitry Andric } // end namespace ARMCC
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric namespace ARMVCC {
890b57cec5SDimitry Andric   enum VPTCodes {
900b57cec5SDimitry Andric     None = 0,
910b57cec5SDimitry Andric     Then,
920b57cec5SDimitry Andric     Else
930b57cec5SDimitry Andric   };
945ffd83dbSDimitry Andric } // namespace ARMVCC
95480093f4SDimitry Andric 
965ffd83dbSDimitry Andric namespace ARM {
975ffd83dbSDimitry Andric   /// Mask values for IT and VPT Blocks, to be used by MCOperands.
985ffd83dbSDimitry Andric   /// Note that this is different from the "real" encoding used by the
995ffd83dbSDimitry Andric   /// instructions. In this encoding, the lowest set bit indicates the end of
1005ffd83dbSDimitry Andric   /// the encoding, and above that, "1" indicates an else, while "0" indicates
1015ffd83dbSDimitry Andric   /// a then.
1025ffd83dbSDimitry Andric   ///   Tx = x100
1035ffd83dbSDimitry Andric   ///   Txy = xy10
1045ffd83dbSDimitry Andric   ///   Txyz = xyz1
1055ffd83dbSDimitry Andric   enum class PredBlockMask {
1065ffd83dbSDimitry Andric     T = 0b1000,
1075ffd83dbSDimitry Andric     TT = 0b0100,
1085ffd83dbSDimitry Andric     TE = 0b1100,
1095ffd83dbSDimitry Andric     TTT = 0b0010,
1105ffd83dbSDimitry Andric     TTE = 0b0110,
1115ffd83dbSDimitry Andric     TEE = 0b1110,
1125ffd83dbSDimitry Andric     TET = 0b1010,
1135ffd83dbSDimitry Andric     TTTT = 0b0001,
1145ffd83dbSDimitry Andric     TTTE = 0b0011,
1155ffd83dbSDimitry Andric     TTEE = 0b0111,
1165ffd83dbSDimitry Andric     TTET = 0b0101,
1175ffd83dbSDimitry Andric     TEEE = 0b1111,
1185ffd83dbSDimitry Andric     TEET = 0b1101,
1195ffd83dbSDimitry Andric     TETT = 0b1001,
1205ffd83dbSDimitry Andric     TETE = 0b1011
121480093f4SDimitry Andric   };
1225ffd83dbSDimitry Andric } // namespace ARM
123480093f4SDimitry Andric 
1245ffd83dbSDimitry Andric // Expands a PredBlockMask by adding an E or a T at the end, depending on Kind.
1255ffd83dbSDimitry Andric // e.g ExpandPredBlockMask(T, Then) = TT, ExpandPredBlockMask(TT, Else) = TTE,
1265ffd83dbSDimitry Andric // and so on.
1275ffd83dbSDimitry Andric ARM::PredBlockMask expandPredBlockMask(ARM::PredBlockMask BlockMask,
1285ffd83dbSDimitry Andric                                        ARMVCC::VPTCodes Kind);
1290b57cec5SDimitry Andric 
ARMVPTPredToString(ARMVCC::VPTCodes CC)1300b57cec5SDimitry Andric inline static const char *ARMVPTPredToString(ARMVCC::VPTCodes CC) {
1310b57cec5SDimitry Andric   switch (CC) {
1320b57cec5SDimitry Andric   case ARMVCC::None:  return "none";
1330b57cec5SDimitry Andric   case ARMVCC::Then:  return "t";
1340b57cec5SDimitry Andric   case ARMVCC::Else:  return "e";
1350b57cec5SDimitry Andric   }
1360b57cec5SDimitry Andric   llvm_unreachable("Unknown VPT code");
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
ARMVectorCondCodeFromString(StringRef CC)1390b57cec5SDimitry Andric inline static unsigned ARMVectorCondCodeFromString(StringRef CC) {
1400b57cec5SDimitry Andric   return StringSwitch<unsigned>(CC.lower())
1410b57cec5SDimitry Andric     .Case("t", ARMVCC::Then)
1420b57cec5SDimitry Andric     .Case("e", ARMVCC::Else)
1430b57cec5SDimitry Andric     .Default(~0U);
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric 
ARMCondCodeToString(ARMCC::CondCodes CC)1460b57cec5SDimitry Andric inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) {
1470b57cec5SDimitry Andric   switch (CC) {
1480b57cec5SDimitry Andric   case ARMCC::EQ:  return "eq";
1490b57cec5SDimitry Andric   case ARMCC::NE:  return "ne";
1500b57cec5SDimitry Andric   case ARMCC::HS:  return "hs";
1510b57cec5SDimitry Andric   case ARMCC::LO:  return "lo";
1520b57cec5SDimitry Andric   case ARMCC::MI:  return "mi";
1530b57cec5SDimitry Andric   case ARMCC::PL:  return "pl";
1540b57cec5SDimitry Andric   case ARMCC::VS:  return "vs";
1550b57cec5SDimitry Andric   case ARMCC::VC:  return "vc";
1560b57cec5SDimitry Andric   case ARMCC::HI:  return "hi";
1570b57cec5SDimitry Andric   case ARMCC::LS:  return "ls";
1580b57cec5SDimitry Andric   case ARMCC::GE:  return "ge";
1590b57cec5SDimitry Andric   case ARMCC::LT:  return "lt";
1600b57cec5SDimitry Andric   case ARMCC::GT:  return "gt";
1610b57cec5SDimitry Andric   case ARMCC::LE:  return "le";
1620b57cec5SDimitry Andric   case ARMCC::AL:  return "al";
1630b57cec5SDimitry Andric   }
1640b57cec5SDimitry Andric   llvm_unreachable("Unknown condition code");
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric 
ARMCondCodeFromString(StringRef CC)1670b57cec5SDimitry Andric inline static unsigned ARMCondCodeFromString(StringRef CC) {
1680b57cec5SDimitry Andric   return StringSwitch<unsigned>(CC.lower())
1690b57cec5SDimitry Andric     .Case("eq", ARMCC::EQ)
1700b57cec5SDimitry Andric     .Case("ne", ARMCC::NE)
1710b57cec5SDimitry Andric     .Case("hs", ARMCC::HS)
1720b57cec5SDimitry Andric     .Case("cs", ARMCC::HS)
1730b57cec5SDimitry Andric     .Case("lo", ARMCC::LO)
1740b57cec5SDimitry Andric     .Case("cc", ARMCC::LO)
1750b57cec5SDimitry Andric     .Case("mi", ARMCC::MI)
1760b57cec5SDimitry Andric     .Case("pl", ARMCC::PL)
1770b57cec5SDimitry Andric     .Case("vs", ARMCC::VS)
1780b57cec5SDimitry Andric     .Case("vc", ARMCC::VC)
1790b57cec5SDimitry Andric     .Case("hi", ARMCC::HI)
1800b57cec5SDimitry Andric     .Case("ls", ARMCC::LS)
1810b57cec5SDimitry Andric     .Case("ge", ARMCC::GE)
1820b57cec5SDimitry Andric     .Case("lt", ARMCC::LT)
1830b57cec5SDimitry Andric     .Case("gt", ARMCC::GT)
1840b57cec5SDimitry Andric     .Case("le", ARMCC::LE)
1850b57cec5SDimitry Andric     .Case("al", ARMCC::AL)
1860b57cec5SDimitry Andric     .Default(~0U);
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric // System Registers
1900b57cec5SDimitry Andric namespace ARMSysReg {
1910b57cec5SDimitry Andric   struct MClassSysReg {
1920b57cec5SDimitry Andric     const char *Name;
1930b57cec5SDimitry Andric     uint16_t M1Encoding12;
1940b57cec5SDimitry Andric     uint16_t M2M3Encoding8;
1950b57cec5SDimitry Andric     uint16_t Encoding;
1960b57cec5SDimitry Andric     FeatureBitset FeaturesRequired;
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric     // return true if FeaturesRequired are all present in ActiveFeatures
hasRequiredFeaturesMClassSysReg1990b57cec5SDimitry Andric     bool hasRequiredFeatures(FeatureBitset ActiveFeatures) const {
2000b57cec5SDimitry Andric       return (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
2010b57cec5SDimitry Andric     }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric     // returns true if TestFeatures are all present in FeaturesRequired
isInRequiredFeaturesMClassSysReg2040b57cec5SDimitry Andric     bool isInRequiredFeatures(FeatureBitset TestFeatures) const {
2050b57cec5SDimitry Andric       return (FeaturesRequired & TestFeatures) == TestFeatures;
2060b57cec5SDimitry Andric     }
2070b57cec5SDimitry Andric   };
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric   #define GET_MCLASSSYSREG_DECL
2100b57cec5SDimitry Andric   #include "ARMGenSystemRegister.inc"
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   // lookup system register using 12-bit SYSm value.
2130b57cec5SDimitry Andric   // Note: the search is uniqued using M1 mask
2140b57cec5SDimitry Andric   const MClassSysReg *lookupMClassSysRegBy12bitSYSmValue(unsigned SYSm);
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   // returns APSR with _<bits> qualifier.
2170b57cec5SDimitry Andric   // Note: ARMv7-M deprecates using MSR APSR without a _<bits> qualifier
2180b57cec5SDimitry Andric   const MClassSysReg *lookupMClassSysRegAPSRNonDeprecated(unsigned SYSm);
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   // lookup system registers using 8-bit SYSm value
2210b57cec5SDimitry Andric   const MClassSysReg *lookupMClassSysRegBy8bitSYSmValue(unsigned SYSm);
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric } // end namespace ARMSysReg
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric // Banked Registers
2260b57cec5SDimitry Andric namespace ARMBankedReg {
2270b57cec5SDimitry Andric   struct BankedReg {
2280b57cec5SDimitry Andric     const char *Name;
2290b57cec5SDimitry Andric     uint16_t Encoding;
2300b57cec5SDimitry Andric   };
2310b57cec5SDimitry Andric   #define GET_BANKEDREG_DECL
2320b57cec5SDimitry Andric   #include "ARMGenSystemRegister.inc"
2330b57cec5SDimitry Andric } // end namespace ARMBankedReg
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric } // end namespace llvm
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H
238