xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/Utils/ARMBaseInfo.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-- ARMBaseInfo.h - Top level definitions for ARM ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains small standalone helper functions and enum definitions for
10 // the ARM target useful for the compiler back-end and the MC libraries.
11 // As such, it deliberately does not include references to LLVM core
12 // code gen types, passes, etc..
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H
17 #define LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H
18 
19 #include "llvm/ADT/StringSwitch.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/TargetParser/SubtargetFeature.h"
22 #include "MCTargetDesc/ARMMCTargetDesc.h"
23 
24 namespace llvm {
25 
26 // Enums corresponding to ARM condition codes
27 namespace ARMCC {
28 // The CondCodes constants map directly to the 4-bit encoding of the
29 // condition field for predicated instructions.
30 enum CondCodes { // Meaning (integer)          Meaning (floating-point)
31   EQ,            // Equal                      Equal
32   NE,            // Not equal                  Not equal, or unordered
33   HS,            // Carry set                  >, ==, or unordered
34   LO,            // Carry clear                Less than
35   MI,            // Minus, negative            Less than
36   PL,            // Plus, positive or zero     >, ==, or unordered
37   VS,            // Overflow                   Unordered
38   VC,            // No overflow                Not unordered
39   HI,            // Unsigned higher            Greater than, or unordered
40   LS,            // Unsigned lower or same     Less than or equal
41   GE,            // Greater than or equal      Greater than or equal
42   LT,            // Less than                  Less than, or unordered
43   GT,            // Greater than               Greater than
44   LE,            // Less than or equal         <, ==, or unordered
45   AL             // Always (unconditional)     Always (unconditional)
46 };
47 
48 inline static CondCodes getOppositeCondition(CondCodes CC) {
49   switch (CC) {
50   default: llvm_unreachable("Unknown condition code");
51   case EQ: return NE;
52   case NE: return EQ;
53   case HS: return LO;
54   case LO: return HS;
55   case MI: return PL;
56   case PL: return MI;
57   case VS: return VC;
58   case VC: return VS;
59   case HI: return LS;
60   case LS: return HI;
61   case GE: return LT;
62   case LT: return GE;
63   case GT: return LE;
64   case LE: return GT;
65   }
66 }
67 
68 /// getSwappedCondition - assume the flags are set by MI(a,b), return
69 /// the condition code if we modify the instructions such that flags are
70 /// set by MI(b,a).
71 inline static ARMCC::CondCodes getSwappedCondition(ARMCC::CondCodes CC) {
72   switch (CC) {
73   default: return ARMCC::AL;
74   case ARMCC::EQ: return ARMCC::EQ;
75   case ARMCC::NE: return ARMCC::NE;
76   case ARMCC::HS: return ARMCC::LS;
77   case ARMCC::LO: return ARMCC::HI;
78   case ARMCC::HI: return ARMCC::LO;
79   case ARMCC::LS: return ARMCC::HS;
80   case ARMCC::GE: return ARMCC::LE;
81   case ARMCC::LT: return ARMCC::GT;
82   case ARMCC::GT: return ARMCC::LT;
83   case ARMCC::LE: return ARMCC::GE;
84   }
85 }
86 } // end namespace ARMCC
87 
88 namespace ARMVCC {
89   enum VPTCodes {
90     None = 0,
91     Then,
92     Else
93   };
94 } // namespace ARMVCC
95 
96 namespace ARM {
97   /// Mask values for IT and VPT Blocks, to be used by MCOperands.
98   /// Note that this is different from the "real" encoding used by the
99   /// instructions. In this encoding, the lowest set bit indicates the end of
100   /// the encoding, and above that, "1" indicates an else, while "0" indicates
101   /// a then.
102   ///   Tx = x100
103   ///   Txy = xy10
104   ///   Txyz = xyz1
105   enum class PredBlockMask {
106     T = 0b1000,
107     TT = 0b0100,
108     TE = 0b1100,
109     TTT = 0b0010,
110     TTE = 0b0110,
111     TEE = 0b1110,
112     TET = 0b1010,
113     TTTT = 0b0001,
114     TTTE = 0b0011,
115     TTEE = 0b0111,
116     TTET = 0b0101,
117     TEEE = 0b1111,
118     TEET = 0b1101,
119     TETT = 0b1001,
120     TETE = 0b1011
121   };
122 } // namespace ARM
123 
124 // Expands a PredBlockMask by adding an E or a T at the end, depending on Kind.
125 // e.g ExpandPredBlockMask(T, Then) = TT, ExpandPredBlockMask(TT, Else) = TTE,
126 // and so on.
127 ARM::PredBlockMask expandPredBlockMask(ARM::PredBlockMask BlockMask,
128                                        ARMVCC::VPTCodes Kind);
129 
130 inline static const char *ARMVPTPredToString(ARMVCC::VPTCodes CC) {
131   switch (CC) {
132   case ARMVCC::None:  return "none";
133   case ARMVCC::Then:  return "t";
134   case ARMVCC::Else:  return "e";
135   }
136   llvm_unreachable("Unknown VPT code");
137 }
138 
139 inline static unsigned ARMVectorCondCodeFromString(StringRef CC) {
140   return StringSwitch<unsigned>(CC.lower())
141     .Case("t", ARMVCC::Then)
142     .Case("e", ARMVCC::Else)
143     .Default(~0U);
144 }
145 
146 inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) {
147   switch (CC) {
148   case ARMCC::EQ:  return "eq";
149   case ARMCC::NE:  return "ne";
150   case ARMCC::HS:  return "hs";
151   case ARMCC::LO:  return "lo";
152   case ARMCC::MI:  return "mi";
153   case ARMCC::PL:  return "pl";
154   case ARMCC::VS:  return "vs";
155   case ARMCC::VC:  return "vc";
156   case ARMCC::HI:  return "hi";
157   case ARMCC::LS:  return "ls";
158   case ARMCC::GE:  return "ge";
159   case ARMCC::LT:  return "lt";
160   case ARMCC::GT:  return "gt";
161   case ARMCC::LE:  return "le";
162   case ARMCC::AL:  return "al";
163   }
164   llvm_unreachable("Unknown condition code");
165 }
166 
167 inline static unsigned ARMCondCodeFromString(StringRef CC) {
168   return StringSwitch<unsigned>(CC.lower())
169     .Case("eq", ARMCC::EQ)
170     .Case("ne", ARMCC::NE)
171     .Case("hs", ARMCC::HS)
172     .Case("cs", ARMCC::HS)
173     .Case("lo", ARMCC::LO)
174     .Case("cc", ARMCC::LO)
175     .Case("mi", ARMCC::MI)
176     .Case("pl", ARMCC::PL)
177     .Case("vs", ARMCC::VS)
178     .Case("vc", ARMCC::VC)
179     .Case("hi", ARMCC::HI)
180     .Case("ls", ARMCC::LS)
181     .Case("ge", ARMCC::GE)
182     .Case("lt", ARMCC::LT)
183     .Case("gt", ARMCC::GT)
184     .Case("le", ARMCC::LE)
185     .Case("al", ARMCC::AL)
186     .Default(~0U);
187 }
188 
189 // System Registers
190 namespace ARMSysReg {
191   struct MClassSysReg {
192     const char *Name;
193     uint16_t M1Encoding12;
194     uint16_t M2M3Encoding8;
195     uint16_t Encoding;
196     FeatureBitset FeaturesRequired;
197 
198     // return true if FeaturesRequired are all present in ActiveFeatures
199     bool hasRequiredFeatures(FeatureBitset ActiveFeatures) const {
200       return (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
201     }
202 
203     // returns true if TestFeatures are all present in FeaturesRequired
204     bool isInRequiredFeatures(FeatureBitset TestFeatures) const {
205       return (FeaturesRequired & TestFeatures) == TestFeatures;
206     }
207   };
208 
209   #define GET_MCLASSSYSREG_DECL
210   #include "ARMGenSystemRegister.inc"
211 
212   // lookup system register using 12-bit SYSm value.
213   // Note: the search is uniqued using M1 mask
214   const MClassSysReg *lookupMClassSysRegBy12bitSYSmValue(unsigned SYSm);
215 
216   // returns APSR with _<bits> qualifier.
217   // Note: ARMv7-M deprecates using MSR APSR without a _<bits> qualifier
218   const MClassSysReg *lookupMClassSysRegAPSRNonDeprecated(unsigned SYSm);
219 
220   // lookup system registers using 8-bit SYSm value
221   const MClassSysReg *lookupMClassSysRegBy8bitSYSmValue(unsigned SYSm);
222 
223 } // end namespace ARMSysReg
224 
225 // Banked Registers
226 namespace ARMBankedReg {
227   struct BankedReg {
228     const char *Name;
229     uint16_t Encoding;
230   };
231   #define GET_BANKEDREG_DECL
232   #include "ARMGenSystemRegister.inc"
233 } // end namespace ARMBankedReg
234 
235 } // end namespace llvm
236 
237 #endif // LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H
238