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_MCTARGETDESC_ARMBASEINFO_H |
17 | #define LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMBASEINFO_H |
18 | |
19 | #include "ARMMCTargetDesc.h" |
20 | #include "llvm/Support/ErrorHandling.h" |
21 | #include "Utils/ARMBaseInfo.h" |
22 | |
23 | namespace llvm { |
24 | |
25 | namespace ARM_PROC { |
26 | enum IMod { |
27 | IE = 2, |
28 | ID = 3 |
29 | }; |
30 | |
31 | enum IFlags { |
32 | F = 1, |
33 | I = 2, |
34 | A = 4 |
35 | }; |
36 | |
37 | inline static const char *IFlagsToString(unsigned val) { |
38 | switch (val) { |
39 | default: llvm_unreachable("Unknown iflags operand" ); |
40 | case F: return "f" ; |
41 | case I: return "i" ; |
42 | case A: return "a" ; |
43 | } |
44 | } |
45 | |
46 | inline static const char *IModToString(unsigned val) { |
47 | switch (val) { |
48 | default: llvm_unreachable("Unknown imod operand" ); |
49 | case IE: return "ie" ; |
50 | case ID: return "id" ; |
51 | } |
52 | } |
53 | } |
54 | |
55 | namespace ARM_MB { |
56 | // The Memory Barrier Option constants map directly to the 4-bit encoding of |
57 | // the option field for memory barrier operations. |
58 | enum MemBOpt { |
59 | RESERVED_0 = 0, |
60 | OSHLD = 1, |
61 | OSHST = 2, |
62 | OSH = 3, |
63 | RESERVED_4 = 4, |
64 | NSHLD = 5, |
65 | NSHST = 6, |
66 | NSH = 7, |
67 | RESERVED_8 = 8, |
68 | ISHLD = 9, |
69 | ISHST = 10, |
70 | ISH = 11, |
71 | RESERVED_12 = 12, |
72 | LD = 13, |
73 | ST = 14, |
74 | SY = 15 |
75 | }; |
76 | |
77 | inline static const char *MemBOptToString(unsigned val, bool HasV8) { |
78 | switch (val) { |
79 | default: llvm_unreachable("Unknown memory operation" ); |
80 | case SY: return "sy" ; |
81 | case ST: return "st" ; |
82 | case LD: return HasV8 ? "ld" : "#0xd" ; |
83 | case RESERVED_12: return "#0xc" ; |
84 | case ISH: return "ish" ; |
85 | case ISHST: return "ishst" ; |
86 | case ISHLD: return HasV8 ? "ishld" : "#0x9" ; |
87 | case RESERVED_8: return "#0x8" ; |
88 | case NSH: return "nsh" ; |
89 | case NSHST: return "nshst" ; |
90 | case NSHLD: return HasV8 ? "nshld" : "#0x5" ; |
91 | case RESERVED_4: return "#0x4" ; |
92 | case OSH: return "osh" ; |
93 | case OSHST: return "oshst" ; |
94 | case OSHLD: return HasV8 ? "oshld" : "#0x1" ; |
95 | case RESERVED_0: return "#0x0" ; |
96 | } |
97 | } |
98 | } // namespace ARM_MB |
99 | |
100 | namespace ARM_TSB { |
101 | enum TraceSyncBOpt { |
102 | CSYNC = 0 |
103 | }; |
104 | |
105 | inline static const char *TraceSyncBOptToString(unsigned val) { |
106 | switch (val) { |
107 | default: |
108 | llvm_unreachable("Unknown trace synchronization barrier operation" ); |
109 | case CSYNC: return "csync" ; |
110 | } |
111 | } |
112 | } // namespace ARM_TSB |
113 | |
114 | namespace ARM_ISB { |
115 | enum InstSyncBOpt { |
116 | RESERVED_0 = 0, |
117 | RESERVED_1 = 1, |
118 | RESERVED_2 = 2, |
119 | RESERVED_3 = 3, |
120 | RESERVED_4 = 4, |
121 | RESERVED_5 = 5, |
122 | RESERVED_6 = 6, |
123 | RESERVED_7 = 7, |
124 | RESERVED_8 = 8, |
125 | RESERVED_9 = 9, |
126 | RESERVED_10 = 10, |
127 | RESERVED_11 = 11, |
128 | RESERVED_12 = 12, |
129 | RESERVED_13 = 13, |
130 | RESERVED_14 = 14, |
131 | SY = 15 |
132 | }; |
133 | |
134 | inline static const char *InstSyncBOptToString(unsigned val) { |
135 | switch (val) { |
136 | default: |
137 | llvm_unreachable("Unknown memory operation" ); |
138 | case RESERVED_0: return "#0x0" ; |
139 | case RESERVED_1: return "#0x1" ; |
140 | case RESERVED_2: return "#0x2" ; |
141 | case RESERVED_3: return "#0x3" ; |
142 | case RESERVED_4: return "#0x4" ; |
143 | case RESERVED_5: return "#0x5" ; |
144 | case RESERVED_6: return "#0x6" ; |
145 | case RESERVED_7: return "#0x7" ; |
146 | case RESERVED_8: return "#0x8" ; |
147 | case RESERVED_9: return "#0x9" ; |
148 | case RESERVED_10: return "#0xa" ; |
149 | case RESERVED_11: return "#0xb" ; |
150 | case RESERVED_12: return "#0xc" ; |
151 | case RESERVED_13: return "#0xd" ; |
152 | case RESERVED_14: return "#0xe" ; |
153 | case SY: return "sy" ; |
154 | } |
155 | } |
156 | } // namespace ARM_ISB |
157 | |
158 | /// isARMLowRegister - Returns true if the register is a low register (r0-r7). |
159 | /// |
160 | static inline bool isARMLowRegister(unsigned Reg) { |
161 | using namespace ARM; |
162 | switch (Reg) { |
163 | case R0: case R1: case R2: case R3: |
164 | case R4: case R5: case R6: case R7: |
165 | return true; |
166 | default: |
167 | return false; |
168 | } |
169 | } |
170 | |
171 | /// ARMII - This namespace holds all of the target specific flags that |
172 | /// instruction info tracks. |
173 | /// |
174 | namespace ARMII { |
175 | |
176 | /// ARM Index Modes |
177 | enum IndexMode { |
178 | IndexModeNone = 0, |
179 | IndexModePre = 1, |
180 | IndexModePost = 2, |
181 | IndexModeUpd = 3 |
182 | }; |
183 | |
184 | /// ARM Addressing Modes |
185 | enum AddrMode { |
186 | AddrModeNone = 0, |
187 | AddrMode1 = 1, |
188 | AddrMode2 = 2, |
189 | AddrMode3 = 3, |
190 | AddrMode4 = 4, |
191 | AddrMode5 = 5, |
192 | AddrMode6 = 6, |
193 | AddrModeT1_1 = 7, |
194 | AddrModeT1_2 = 8, |
195 | AddrModeT1_4 = 9, |
196 | AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data |
197 | AddrModeT2_i12 = 11, |
198 | AddrModeT2_i8 = 12, // +/- i8 |
199 | AddrModeT2_i8pos = 13, // + i8 |
200 | AddrModeT2_i8neg = 14, // - i8 |
201 | AddrModeT2_so = 15, |
202 | AddrModeT2_pc = 16, // +/- i12 for pc relative data |
203 | AddrModeT2_i8s4 = 17, // i8 * 4 |
204 | AddrMode_i12 = 18, |
205 | AddrMode5FP16 = 19, // i8 * 2 |
206 | AddrModeT2_ldrex = 20, // i8 * 4, with unscaled offset in MCInst |
207 | AddrModeT2_i7s4 = 21, // i7 * 4 |
208 | AddrModeT2_i7s2 = 22, // i7 * 2 |
209 | AddrModeT2_i7 = 23, // i7 * 1 |
210 | }; |
211 | |
212 | inline static const char *AddrModeToString(AddrMode addrmode) { |
213 | switch (addrmode) { |
214 | case AddrModeNone: return "AddrModeNone" ; |
215 | case AddrMode1: return "AddrMode1" ; |
216 | case AddrMode2: return "AddrMode2" ; |
217 | case AddrMode3: return "AddrMode3" ; |
218 | case AddrMode4: return "AddrMode4" ; |
219 | case AddrMode5: return "AddrMode5" ; |
220 | case AddrMode5FP16: return "AddrMode5FP16" ; |
221 | case AddrMode6: return "AddrMode6" ; |
222 | case AddrModeT1_1: return "AddrModeT1_1" ; |
223 | case AddrModeT1_2: return "AddrModeT1_2" ; |
224 | case AddrModeT1_4: return "AddrModeT1_4" ; |
225 | case AddrModeT1_s: return "AddrModeT1_s" ; |
226 | case AddrModeT2_i12: return "AddrModeT2_i12" ; |
227 | case AddrModeT2_i8: return "AddrModeT2_i8" ; |
228 | case AddrModeT2_i8pos: return "AddrModeT2_i8pos" ; |
229 | case AddrModeT2_i8neg: return "AddrModeT2_i8neg" ; |
230 | case AddrModeT2_so: return "AddrModeT2_so" ; |
231 | case AddrModeT2_pc: return "AddrModeT2_pc" ; |
232 | case AddrModeT2_i8s4: return "AddrModeT2_i8s4" ; |
233 | case AddrMode_i12: return "AddrMode_i12" ; |
234 | case AddrModeT2_ldrex:return "AddrModeT2_ldrex" ; |
235 | case AddrModeT2_i7s4: return "AddrModeT2_i7s4" ; |
236 | case AddrModeT2_i7s2: return "AddrModeT2_i7s2" ; |
237 | case AddrModeT2_i7: return "AddrModeT2_i7" ; |
238 | } |
239 | } |
240 | |
241 | /// Target Operand Flag enum. |
242 | enum TOF { |
243 | //===------------------------------------------------------------------===// |
244 | // ARM Specific MachineOperand flags. |
245 | |
246 | MO_NO_FLAG = 0, |
247 | |
248 | /// MO_LO16 - On a symbol operand, this represents a relocation containing |
249 | /// lower 16 bit of the address. Used only via movw instruction. |
250 | MO_LO16 = 0x1, |
251 | |
252 | /// MO_HI16 - On a symbol operand, this represents a relocation containing |
253 | /// higher 16 bit of the address. Used only via movt instruction. |
254 | MO_HI16 = 0x2, |
255 | |
256 | /// MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects |
257 | /// just that part of the flag set. |
258 | MO_OPTION_MASK = 0xf03, |
259 | |
260 | /// MO_COFFSTUB - On a symbol operand "FOO", this indicates that the |
261 | /// reference is actually to the ".refptr.FOO" symbol. This is used for |
262 | /// stub symbols on windows. |
263 | MO_COFFSTUB = 0x4, |
264 | |
265 | /// MO_GOT - On a symbol operand, this represents a GOT relative relocation. |
266 | MO_GOT = 0x8, |
267 | |
268 | /// MO_SBREL - On a symbol operand, this represents a static base relative |
269 | /// relocation. Used in movw and movt instructions. |
270 | MO_SBREL = 0x10, |
271 | |
272 | /// MO_DLLIMPORT - On a symbol operand, this represents that the reference |
273 | /// to the symbol is for an import stub. This is used for DLL import |
274 | /// storage class indication on Windows. |
275 | MO_DLLIMPORT = 0x20, |
276 | |
277 | /// MO_SECREL - On a symbol operand this indicates that the immediate is |
278 | /// the offset from beginning of section. |
279 | /// |
280 | /// This is the TLS offset for the COFF/Windows TLS mechanism. |
281 | MO_SECREL = 0x40, |
282 | |
283 | /// MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it |
284 | /// represents a symbol which, if indirect, will get special Darwin mangling |
285 | /// as a non-lazy-ptr indirect symbol (i.e. "L_FOO$non_lazy_ptr"). Can be |
286 | /// combined with MO_LO16, MO_HI16 or MO_NO_FLAG (in a constant-pool, for |
287 | /// example). |
288 | MO_NONLAZY = 0x80, |
289 | |
290 | /// MO_LO_0_7 - On a symbol operand, this represents a relocation containing |
291 | /// bits 0 through 7 of the address. Used only with Thumb1 MOV and ADD |
292 | // instructions. |
293 | MO_LO_0_7 = 0x100, |
294 | |
295 | /// MO_LO_8_15 - On a symbol operand, this represents a relocation |
296 | /// containing |
297 | /// bits 8 through 15 of the address. Used only with Thumb1 MOV and ADD |
298 | // instructions. |
299 | MO_LO_8_15 = 0x200, |
300 | |
301 | /// MO_HI_0_7 - On a symbol operand, this represents a relocation containing |
302 | /// bits 16 through 23 of the address. Used only with Thumb1 MOV and ADD |
303 | // instructions. |
304 | MO_HI_0_7 = 0x400, |
305 | |
306 | /// MO_HI_8_15 - On a symbol operand, this represents a relocation |
307 | /// containing |
308 | /// bits 24 through 31 of the address. Used only with Thumb1 MOV and ADD |
309 | // instructions. |
310 | MO_HI_8_15 = 0x800 |
311 | }; |
312 | |
313 | enum { |
314 | //===------------------------------------------------------------------===// |
315 | // Instruction Flags. |
316 | |
317 | //===------------------------------------------------------------------===// |
318 | // This four-bit field describes the addressing mode used. |
319 | AddrModeMask = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h |
320 | |
321 | // IndexMode - Unindex, pre-indexed, or post-indexed are valid for load |
322 | // and store ops only. Generic "updating" flag is used for ld/st multiple. |
323 | // The index mode enums are declared in ARMBaseInfo.h |
324 | IndexModeShift = 5, |
325 | IndexModeMask = 3 << IndexModeShift, |
326 | |
327 | //===------------------------------------------------------------------===// |
328 | // Instruction encoding formats. |
329 | // |
330 | FormShift = 7, |
331 | FormMask = 0x3f << FormShift, |
332 | |
333 | // Pseudo instructions |
334 | Pseudo = 0 << FormShift, |
335 | |
336 | // Multiply instructions |
337 | MulFrm = 1 << FormShift, |
338 | |
339 | // Branch instructions |
340 | BrFrm = 2 << FormShift, |
341 | BrMiscFrm = 3 << FormShift, |
342 | |
343 | // Data Processing instructions |
344 | DPFrm = 4 << FormShift, |
345 | DPSoRegFrm = 5 << FormShift, |
346 | |
347 | // Load and Store |
348 | LdFrm = 6 << FormShift, |
349 | StFrm = 7 << FormShift, |
350 | LdMiscFrm = 8 << FormShift, |
351 | StMiscFrm = 9 << FormShift, |
352 | LdStMulFrm = 10 << FormShift, |
353 | |
354 | LdStExFrm = 11 << FormShift, |
355 | |
356 | // Miscellaneous arithmetic instructions |
357 | ArithMiscFrm = 12 << FormShift, |
358 | SatFrm = 13 << FormShift, |
359 | |
360 | // Extend instructions |
361 | ExtFrm = 14 << FormShift, |
362 | |
363 | // VFP formats |
364 | VFPUnaryFrm = 15 << FormShift, |
365 | VFPBinaryFrm = 16 << FormShift, |
366 | VFPConv1Frm = 17 << FormShift, |
367 | VFPConv2Frm = 18 << FormShift, |
368 | VFPConv3Frm = 19 << FormShift, |
369 | VFPConv4Frm = 20 << FormShift, |
370 | VFPConv5Frm = 21 << FormShift, |
371 | VFPLdStFrm = 22 << FormShift, |
372 | VFPLdStMulFrm = 23 << FormShift, |
373 | VFPMiscFrm = 24 << FormShift, |
374 | |
375 | // Thumb format |
376 | ThumbFrm = 25 << FormShift, |
377 | |
378 | // Miscelleaneous format |
379 | MiscFrm = 26 << FormShift, |
380 | |
381 | // NEON formats |
382 | NGetLnFrm = 27 << FormShift, |
383 | NSetLnFrm = 28 << FormShift, |
384 | NDupFrm = 29 << FormShift, |
385 | NLdStFrm = 30 << FormShift, |
386 | N1RegModImmFrm= 31 << FormShift, |
387 | N2RegFrm = 32 << FormShift, |
388 | NVCVTFrm = 33 << FormShift, |
389 | NVDupLnFrm = 34 << FormShift, |
390 | N2RegVShLFrm = 35 << FormShift, |
391 | N2RegVShRFrm = 36 << FormShift, |
392 | N3RegFrm = 37 << FormShift, |
393 | N3RegVShFrm = 38 << FormShift, |
394 | NVExtFrm = 39 << FormShift, |
395 | NVMulSLFrm = 40 << FormShift, |
396 | NVTBLFrm = 41 << FormShift, |
397 | N3RegCplxFrm = 43 << FormShift, |
398 | |
399 | //===------------------------------------------------------------------===// |
400 | // Misc flags. |
401 | |
402 | // UnaryDP - Indicates this is a unary data processing instruction, i.e. |
403 | // it doesn't have a Rn operand. |
404 | UnaryDP = 1 << 13, |
405 | |
406 | // Xform16Bit - Indicates this Thumb2 instruction may be transformed into |
407 | // a 16-bit Thumb instruction if certain conditions are met. |
408 | Xform16Bit = 1 << 14, |
409 | |
410 | // ThumbArithFlagSetting - The instruction is a 16-bit flag setting Thumb |
411 | // instruction. Used by the parser to determine whether to require the 'S' |
412 | // suffix on the mnemonic (when not in an IT block) or preclude it (when |
413 | // in an IT block). |
414 | ThumbArithFlagSetting = 1 << 19, |
415 | |
416 | // Whether an instruction can be included in an MVE tail-predicated loop, |
417 | // though extra validity checks may need to be performed too. |
418 | ValidForTailPredication = 1 << 20, |
419 | |
420 | // Whether an instruction writes to the top/bottom half of a vector element |
421 | // and leaves the other half untouched. |
422 | RetainsPreviousHalfElement = 1 << 21, |
423 | |
424 | // Whether the instruction produces a scalar result from vector operands. |
425 | HorizontalReduction = 1 << 22, |
426 | |
427 | // Whether this instruction produces a vector result that is larger than |
428 | // its input, typically reading from the top/bottom halves of the input(s). |
429 | DoubleWidthResult = 1 << 23, |
430 | |
431 | // The vector element size for MVE instructions. 00 = i8, 01 = i16, 10 = i32 |
432 | // and 11 = i64. This is the largest type if multiple are present, so a |
433 | // MVE_VMOVLs8bh is ize 01=i16, as it extends from a i8 to a i16. There are |
434 | // some caveats so cannot be used blindly, such as exchanging VMLADAVA's and |
435 | // complex instructions, which may use different input lanes. |
436 | VecSizeShift = 24, |
437 | VecSize = 3 << VecSizeShift, |
438 | |
439 | //===------------------------------------------------------------------===// |
440 | // Code domain. |
441 | DomainShift = 15, |
442 | DomainMask = 15 << DomainShift, |
443 | DomainGeneral = 0 << DomainShift, |
444 | DomainVFP = 1 << DomainShift, |
445 | DomainNEON = 2 << DomainShift, |
446 | DomainNEONA8 = 4 << DomainShift, |
447 | DomainMVE = 8 << DomainShift, |
448 | |
449 | //===------------------------------------------------------------------===// |
450 | // Field shifts - such shifts are used to set field while generating |
451 | // machine instructions. |
452 | // |
453 | // FIXME: This list will need adjusting/fixing as the MC code emitter |
454 | // takes shape and the ARMCodeEmitter.cpp bits go away. |
455 | ShiftTypeShift = 4, |
456 | |
457 | M_BitShift = 5, |
458 | ShiftImmShift = 5, |
459 | ShiftShift = 7, |
460 | N_BitShift = 7, |
461 | ImmHiShift = 8, |
462 | SoRotImmShift = 8, |
463 | = 8, |
464 | ExtRotImmShift = 10, |
465 | RegRdLoShift = 12, |
466 | RegRdShift = 12, |
467 | RegRdHiShift = 16, |
468 | RegRnShift = 16, |
469 | S_BitShift = 20, |
470 | W_BitShift = 21, |
471 | AM3_I_BitShift = 22, |
472 | D_BitShift = 22, |
473 | U_BitShift = 23, |
474 | P_BitShift = 24, |
475 | I_BitShift = 25, |
476 | CondShift = 28 |
477 | }; |
478 | |
479 | } // end namespace ARMII |
480 | |
481 | } // end namespace llvm; |
482 | |
483 | #endif |
484 | |