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(S: "t" , Value: ARMVCC::Then) |
142 | .Case(S: "e" , Value: ARMVCC::Else) |
143 | .Default(Value: ~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(S: "eq" , Value: ARMCC::EQ) |
170 | .Case(S: "ne" , Value: ARMCC::NE) |
171 | .Case(S: "hs" , Value: ARMCC::HS) |
172 | .Case(S: "cs" , Value: ARMCC::HS) |
173 | .Case(S: "lo" , Value: ARMCC::LO) |
174 | .Case(S: "cc" , Value: ARMCC::LO) |
175 | .Case(S: "mi" , Value: ARMCC::MI) |
176 | .Case(S: "pl" , Value: ARMCC::PL) |
177 | .Case(S: "vs" , Value: ARMCC::VS) |
178 | .Case(S: "vc" , Value: ARMCC::VC) |
179 | .Case(S: "hi" , Value: ARMCC::HI) |
180 | .Case(S: "ls" , Value: ARMCC::LS) |
181 | .Case(S: "ge" , Value: ARMCC::GE) |
182 | .Case(S: "lt" , Value: ARMCC::LT) |
183 | .Case(S: "gt" , Value: ARMCC::GT) |
184 | .Case(S: "le" , Value: ARMCC::LE) |
185 | .Case(S: "al" , Value: ARMCC::AL) |
186 | .Default(Value: ~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 | |