1 //===-- M68kBaseInfo.h - Top level definitions for M68k MC ------*- 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 /// \file
10 /// This file contains small standalone helper functions and enum definitions
11 /// for the M68k target useful for the compiler back-end and the MC
12 /// libraries.  As such, it deliberately does not include references to LLVM
13 /// core code gen types, passes, etc..
14 ///
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KBASEINFO_H
18 #define LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KBASEINFO_H
19 
20 #include "M68kMCTargetDesc.h"
21 
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/Support/DataTypes.h"
24 #include "llvm/Support/Endian.h"
25 #include "llvm/Support/ErrorHandling.h"
26 
27 #define GET_INSTRINFO_MI_OPS_INFO
28 #define GET_INSTRINFO_OPERAND_TYPES_ENUM
29 #define GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP
30 #include "M68kGenInstrInfo.inc"
31 
32 namespace llvm {
33 
34 namespace M68k {
35 
36 /// Enums for memory operand decoding. Supports these forms:
37 /// (d,An)
38 /// (d,An,Xn)
39 /// ([bd,An],Xn,od)
40 /// ([bd,An,Xn],od)
41 /// TODO Implement scaling other than 1
42 enum { MemDisp = 0, MemBase = 1, MemIndex = 2, MemOuter = 3 };
43 
44 /// Enums for pc-relative memory operand decoding. Supports these forms:
45 /// (d,PC)
46 /// (d,PC,Xn)
47 /// ([bd,PC],Xn,od)
48 /// ([bd,PC,Xn],od)
49 enum { PCRelDisp = 0, PCRelIndex = 1, PCRelOuter = 2 };
50 
51 enum class MemAddrModeKind : unsigned {
52   j = 1, // (An)
53   o,     // (An)+
54   e,     // -(An)
55   p,     // (d,An)
56   f,     // (d,An,Xn.L)
57   F,     // (d,An,Xn.W)
58   g,     // (d,An,Xn.L,SCALE)
59   G,     // (d,An,Xn.W,SCALE)
60   u,     // ([bd,An],Xn.L,SCALE,od)
61   U,     // ([bd,An],Xn.W,SCALE,od)
62   v,     // ([bd,An,Xn.L,SCALE],od)
63   V,     // ([bd,An,Xn.W,SCALE],od)
64   b,     // abs.L
65   B,     // abs.W
66   q,     // (d,PC)
67   k,     // (d,PC,Xn.L)
68   K,     // (d,PC,Xn.W)
69   l,     // (d,PC,Xn.L,SCALE)
70   L,     // (d,PC,Xn.W,SCALE)
71   x,     // ([bd,PC],Xn.L,SCALE,od)
72   X,     // ([bd,PC],Xn.W,SCALE,od)
73   y,     // ([bd,PC,Xn.L,SCALE],od)
74   Y      // ([bd,PC,Xn.W,SCALE],od)
75 };
76 
77 // On a LE host:
78 // MSB                   LSB    MSB                   LSB
79 // | 0x12 0x34 | 0xAB 0xCD | -> | 0xAB 0xCD | 0x12 0x34 |
80 // (On a BE host nothing changes)
81 template <typename value_t> value_t swapWord(value_t Val) {
82   const unsigned NumWords = sizeof(Val) / 2;
83   if (NumWords <= 1)
84     return Val;
85   Val = support::endian::byte_swap(Val, support::big);
86   value_t NewVal = 0;
87   for (unsigned i = 0U; i != NumWords; ++i) {
88     uint16_t Part = (Val >> (i * 16)) & 0xFFFF;
89     Part = support::endian::byte_swap(Part, support::big);
90     NewVal |= (Part << (i * 16));
91   }
92   return NewVal;
93 }
94 } // namespace M68k
95 
96 namespace M68kBeads {
97 enum {
98   Ctrl = 0x0,
99   Bits1 = 0x1,
100   Bits2 = 0x2,
101   Bits3 = 0x3,
102   Bits4 = 0x4,
103   DAReg = 0x5,
104   DA = 0x6,
105   Reg = 0x7,
106   DReg = 0x8,
107   Disp8 = 0x9,
108   Imm8 = 0xA,
109   Imm16 = 0xB,
110   Imm32 = 0xC,
111   Imm3 = 0xD,
112 };
113 
114 // Ctrl payload
115 enum {
116   Term = 0x0,
117   Ignore = 0x1,
118 };
119 } // namespace M68kBeads
120 
121 /// This namespace holds all of the target specific flags that instruction info
122 /// tracks.
123 namespace M68kII {
124 /// Target Operand Flag enum.
125 enum TOF {
126 
127   MO_NO_FLAG,
128 
129   /// On a symbol operand this indicates that the immediate is the absolute
130   /// address of the symbol.
131   MO_ABSOLUTE_ADDRESS,
132 
133   /// On a symbol operand this indicates that the immediate is the pc-relative
134   /// address of the symbol.
135   MO_PC_RELATIVE_ADDRESS,
136 
137   /// On a symbol operand this indicates that the immediate is the offset to
138   /// the GOT entry for the symbol name from the base of the GOT.
139   ///
140   ///    name@GOT
141   MO_GOT,
142 
143   /// On a symbol operand this indicates that the immediate is the offset to
144   /// the location of the symbol name from the base of the GOT.
145   ///
146   ///    name@GOTOFF
147   MO_GOTOFF,
148 
149   /// On a symbol operand this indicates that the immediate is offset to the
150   /// GOT entry for the symbol name from the current code location.
151   ///
152   ///    name@GOTPCREL
153   MO_GOTPCREL,
154 
155   /// On a symbol operand this indicates that the immediate is offset to the
156   /// PLT entry of symbol name from the current code location.
157   ///
158   ///    name@PLT
159   MO_PLT,
160 
161   /// On a symbol operand, this indicates that the immediate is the offset to
162   /// the slot in GOT which stores the information for accessing the TLS
163   /// variable. This is used when operating in Global Dynamic mode.
164   ///    name@TLSGD
165   MO_TLSGD,
166 
167   /// On a symbol operand, this indicates that the immediate is the offset to
168   /// variable within the thread local storage when operating in Local Dynamic
169   /// mode.
170   ///    name@TLSLD
171   MO_TLSLD,
172 
173   /// On a symbol operand, this indicates that the immediate is the offset to
174   /// the slot in GOT which stores the information for accessing the TLS
175   /// variable. This is used when operating in Local Dynamic mode.
176   ///    name@TLSLDM
177   MO_TLSLDM,
178 
179   /// On a symbol operand, this indicates that the immediate is the offset to
180   /// the variable within the thread local storage when operating in Initial
181   /// Exec mode.
182   ///    name@TLSIE
183   MO_TLSIE,
184 
185   /// On a symbol operand, this indicates that the immediate is the offset to
186   /// the variable within in the thread local storage when operating in Local
187   /// Exec mode.
188   ///    name@TLSLE
189   MO_TLSLE,
190 
191 }; // enum TOF
192 
193 /// Return true if the specified TargetFlag operand is a reference to a stub
194 /// for a global, not the global itself.
195 inline static bool isGlobalStubReference(unsigned char TargetFlag) {
196   switch (TargetFlag) {
197   default:
198     return false;
199   case M68kII::MO_GOTPCREL: // pc-relative GOT reference.
200   case M68kII::MO_GOT:      // normal GOT reference.
201     return true;
202   }
203 }
204 
205 /// Return True if the specified GlobalValue is a direct reference for a
206 /// symbol.
207 inline static bool isDirectGlobalReference(unsigned char Flag) {
208   switch (Flag) {
209   default:
210     return false;
211   case M68kII::MO_NO_FLAG:
212   case M68kII::MO_ABSOLUTE_ADDRESS:
213   case M68kII::MO_PC_RELATIVE_ADDRESS:
214     return true;
215   }
216 }
217 
218 /// Return true if the specified global value reference is relative to a 32-bit
219 /// PIC base (M68kISD::GLOBAL_BASE_REG). If this is true, the addressing mode
220 /// has the PIC base register added in.
221 inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) {
222   switch (TargetFlag) {
223   default:
224     return false;
225   case M68kII::MO_GOTOFF: // isPICStyleGOT: local global.
226   case M68kII::MO_GOT:    // isPICStyleGOT: other global.
227     return true;
228   }
229 }
230 
231 /// Return True if the specified GlobalValue requires PC addressing mode.
232 inline static bool isPCRelGlobalReference(unsigned char Flag) {
233   switch (Flag) {
234   default:
235     return false;
236   case M68kII::MO_GOTPCREL:
237   case M68kII::MO_PC_RELATIVE_ADDRESS:
238     return true;
239   }
240 }
241 
242 /// Return True if the Block is referenced using PC
243 inline static bool isPCRelBlockReference(unsigned char Flag) {
244   switch (Flag) {
245   default:
246     return false;
247   case M68kII::MO_PC_RELATIVE_ADDRESS:
248     return true;
249   }
250 }
251 
252 static inline bool isAddressRegister(unsigned RegNo) {
253   switch (RegNo) {
254   case M68k::WA0:
255   case M68k::WA1:
256   case M68k::WA2:
257   case M68k::WA3:
258   case M68k::WA4:
259   case M68k::WA5:
260   case M68k::WA6:
261   case M68k::WSP:
262   case M68k::A0:
263   case M68k::A1:
264   case M68k::A2:
265   case M68k::A3:
266   case M68k::A4:
267   case M68k::A5:
268   case M68k::A6:
269   case M68k::SP:
270     return true;
271   default:
272     return false;
273   }
274 }
275 
276 static inline bool hasMultiMIOperands(unsigned Op, unsigned LogicalOpIdx) {
277   return M68k::getLogicalOperandSize(Op, LogicalOpIdx) > 1;
278 }
279 
280 static inline unsigned getMaskedSpillRegister(unsigned order) {
281   switch (order) {
282   default:
283     return 0;
284   case 0:
285     return M68k::D0;
286   case 1:
287     return M68k::D1;
288   case 2:
289     return M68k::D2;
290   case 3:
291     return M68k::D3;
292   case 4:
293     return M68k::D4;
294   case 5:
295     return M68k::D5;
296   case 6:
297     return M68k::D6;
298   case 7:
299     return M68k::D7;
300   case 8:
301     return M68k::A0;
302   case 9:
303     return M68k::A1;
304   case 10:
305     return M68k::A2;
306   case 11:
307     return M68k::A3;
308   case 12:
309     return M68k::A4;
310   case 13:
311     return M68k::A5;
312   case 14:
313     return M68k::A6;
314   case 15:
315     return M68k::SP;
316   }
317 }
318 
319 } // namespace M68kII
320 
321 } // namespace llvm
322 
323 #endif // LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KBASEINFO_H
324