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 // On a LE host:
52 // MSB                   LSB    MSB                   LSB
53 // | 0x12 0x34 | 0xAB 0xCD | -> | 0xAB 0xCD | 0x12 0x34 |
54 // (On a BE host nothing changes)
55 template <typename value_t> value_t swapWord(value_t Val) {
56   const unsigned NumWords = sizeof(Val) / 2;
57   if (NumWords <= 1)
58     return Val;
59   Val = support::endian::byte_swap(Val, support::big);
60   value_t NewVal = 0;
61   for (unsigned i = 0U; i != NumWords; ++i) {
62     uint16_t Part = (Val >> (i * 16)) & 0xFFFF;
63     Part = support::endian::byte_swap(Part, support::big);
64     NewVal |= (Part << (i * 16));
65   }
66   return NewVal;
67 }
68 } // namespace M68k
69 
70 namespace M68kBeads {
71 enum {
72   Ctrl = 0x0,
73   Bits1 = 0x1,
74   Bits2 = 0x2,
75   Bits3 = 0x3,
76   Bits4 = 0x4,
77   DAReg = 0x5,
78   DA = 0x6,
79   Reg = 0x7,
80   DReg = 0x8,
81   Disp8 = 0x9,
82   Imm8 = 0xA,
83   Imm16 = 0xB,
84   Imm32 = 0xC,
85   Imm3 = 0xD,
86 };
87 
88 // Ctrl payload
89 enum {
90   Term = 0x0,
91   Ignore = 0x1,
92 };
93 } // namespace M68kBeads
94 
95 /// This namespace holds all of the target specific flags that instruction info
96 /// tracks.
97 namespace M68kII {
98 /// Target Operand Flag enum.
99 enum TOF {
100 
101   MO_NO_FLAG,
102 
103   /// On a symbol operand this indicates that the immediate is the absolute
104   /// address of the symbol.
105   MO_ABSOLUTE_ADDRESS,
106 
107   /// On a symbol operand this indicates that the immediate is the pc-relative
108   /// address of the symbol.
109   MO_PC_RELATIVE_ADDRESS,
110 
111   /// On a symbol operand this indicates that the immediate is the offset to
112   /// the GOT entry for the symbol name from the base of the GOT.
113   ///
114   ///    name@GOT
115   MO_GOT,
116 
117   /// On a symbol operand this indicates that the immediate is the offset to
118   /// the location of the symbol name from the base of the GOT.
119   ///
120   ///    name@GOTOFF
121   MO_GOTOFF,
122 
123   /// On a symbol operand this indicates that the immediate is offset to the
124   /// GOT entry for the symbol name from the current code location.
125   ///
126   ///    name@GOTPCREL
127   MO_GOTPCREL,
128 
129   /// On a symbol operand this indicates that the immediate is offset to the
130   /// PLT entry of symbol name from the current code location.
131   ///
132   ///    name@PLT
133   MO_PLT,
134 }; // enum TOF
135 
136 /// Return true if the specified TargetFlag operand is a reference to a stub
137 /// for a global, not the global itself.
138 inline static bool isGlobalStubReference(unsigned char TargetFlag) {
139   switch (TargetFlag) {
140   default:
141     return false;
142   case M68kII::MO_GOTPCREL: // pc-relative GOT reference.
143   case M68kII::MO_GOT:      // normal GOT reference.
144     return true;
145   }
146 }
147 
148 /// Return True if the specified GlobalValue is a direct reference for a
149 /// symbol.
150 inline static bool isDirectGlobalReference(unsigned char Flag) {
151   switch (Flag) {
152   default:
153     return false;
154   case M68kII::MO_NO_FLAG:
155   case M68kII::MO_ABSOLUTE_ADDRESS:
156   case M68kII::MO_PC_RELATIVE_ADDRESS:
157     return true;
158   }
159 }
160 
161 /// Return true if the specified global value reference is relative to a 32-bit
162 /// PIC base (M68kISD::GLOBAL_BASE_REG). If this is true, the addressing mode
163 /// has the PIC base register added in.
164 inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) {
165   switch (TargetFlag) {
166   default:
167     return false;
168   case M68kII::MO_GOTOFF: // isPICStyleGOT: local global.
169   case M68kII::MO_GOT:    // isPICStyleGOT: other global.
170     return true;
171   }
172 }
173 
174 /// Return True if the specified GlobalValue requires PC addressing mode.
175 inline static bool isPCRelGlobalReference(unsigned char Flag) {
176   switch (Flag) {
177   default:
178     return false;
179   case M68kII::MO_GOTPCREL:
180   case M68kII::MO_PC_RELATIVE_ADDRESS:
181     return true;
182   }
183 }
184 
185 /// Return True if the Block is referenced using PC
186 inline static bool isPCRelBlockReference(unsigned char Flag) {
187   switch (Flag) {
188   default:
189     return false;
190   case M68kII::MO_PC_RELATIVE_ADDRESS:
191     return true;
192   }
193 }
194 
195 static inline bool isAddressRegister(unsigned RegNo) {
196   switch (RegNo) {
197   case M68k::WA0:
198   case M68k::WA1:
199   case M68k::WA2:
200   case M68k::WA3:
201   case M68k::WA4:
202   case M68k::WA5:
203   case M68k::WA6:
204   case M68k::WSP:
205   case M68k::A0:
206   case M68k::A1:
207   case M68k::A2:
208   case M68k::A3:
209   case M68k::A4:
210   case M68k::A5:
211   case M68k::A6:
212   case M68k::SP:
213     return true;
214   default:
215     return false;
216   }
217 }
218 
219 static inline bool hasMultiMIOperands(unsigned Op, unsigned LogicalOpIdx) {
220   return M68k::getLogicalOperandSize(Op, LogicalOpIdx) > 1;
221 }
222 
223 static inline unsigned getMaskedSpillRegister(unsigned order) {
224   switch (order) {
225   default:
226     return 0;
227   case 0:
228     return M68k::D0;
229   case 1:
230     return M68k::D1;
231   case 2:
232     return M68k::D2;
233   case 3:
234     return M68k::D3;
235   case 4:
236     return M68k::D4;
237   case 5:
238     return M68k::D5;
239   case 6:
240     return M68k::D6;
241   case 7:
242     return M68k::D7;
243   case 8:
244     return M68k::A0;
245   case 9:
246     return M68k::A1;
247   case 10:
248     return M68k::A2;
249   case 11:
250     return M68k::A3;
251   case 12:
252     return M68k::A4;
253   case 13:
254     return M68k::A5;
255   case 14:
256     return M68k::A6;
257   case 15:
258     return M68k::SP;
259   }
260 }
261 
262 } // namespace M68kII
263 
264 } // namespace llvm
265 
266 #endif // LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KBASEINFO_H
267