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