xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/M68k/MCTargetDesc/M68kBaseInfo.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
104eeddc0SDimitry Andric //===-- M68kBaseInfo.h - Top level definitions for M68k MC ------*- C++ -*-===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric ///
9fe6060f1SDimitry Andric /// \file
10fe6060f1SDimitry Andric /// This file contains small standalone helper functions and enum definitions
11fe6060f1SDimitry Andric /// for the M68k target useful for the compiler back-end and the MC
12fe6060f1SDimitry Andric /// libraries.  As such, it deliberately does not include references to LLVM
13fe6060f1SDimitry Andric /// core code gen types, passes, etc..
14fe6060f1SDimitry Andric ///
15fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
16fe6060f1SDimitry Andric 
17fe6060f1SDimitry Andric #ifndef LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KBASEINFO_H
18fe6060f1SDimitry Andric #define LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KBASEINFO_H
19fe6060f1SDimitry Andric 
20fe6060f1SDimitry Andric #include "M68kMCTargetDesc.h"
21fe6060f1SDimitry Andric 
22fe6060f1SDimitry Andric #include "llvm/MC/MCExpr.h"
23fe6060f1SDimitry Andric #include "llvm/Support/DataTypes.h"
24bdd1243dSDimitry Andric #include "llvm/Support/Endian.h"
25fe6060f1SDimitry Andric #include "llvm/Support/ErrorHandling.h"
26fe6060f1SDimitry Andric 
27fe6060f1SDimitry Andric #define GET_INSTRINFO_MI_OPS_INFO
28fe6060f1SDimitry Andric #define GET_INSTRINFO_OPERAND_TYPES_ENUM
29fe6060f1SDimitry Andric #define GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP
30fe6060f1SDimitry Andric #include "M68kGenInstrInfo.inc"
31fe6060f1SDimitry Andric 
32fe6060f1SDimitry Andric namespace llvm {
33fe6060f1SDimitry Andric 
34fe6060f1SDimitry Andric namespace M68k {
35fe6060f1SDimitry Andric 
36fe6060f1SDimitry Andric /// Enums for memory operand decoding. Supports these forms:
37fe6060f1SDimitry Andric /// (d,An)
38fe6060f1SDimitry Andric /// (d,An,Xn)
39fe6060f1SDimitry Andric /// ([bd,An],Xn,od)
40fe6060f1SDimitry Andric /// ([bd,An,Xn],od)
41fe6060f1SDimitry Andric /// TODO Implement scaling other than 1
42fe6060f1SDimitry Andric enum { MemDisp = 0, MemBase = 1, MemIndex = 2, MemOuter = 3 };
43fe6060f1SDimitry Andric 
44fe6060f1SDimitry Andric /// Enums for pc-relative memory operand decoding. Supports these forms:
45fe6060f1SDimitry Andric /// (d,PC)
46fe6060f1SDimitry Andric /// (d,PC,Xn)
47fe6060f1SDimitry Andric /// ([bd,PC],Xn,od)
48fe6060f1SDimitry Andric /// ([bd,PC,Xn],od)
49fe6060f1SDimitry Andric enum { PCRelDisp = 0, PCRelIndex = 1, PCRelOuter = 2 };
50bdd1243dSDimitry Andric 
5106c3fb27SDimitry Andric enum class MemAddrModeKind : unsigned {
5206c3fb27SDimitry Andric   j = 1, // (An)
5306c3fb27SDimitry Andric   o,     // (An)+
5406c3fb27SDimitry Andric   e,     // -(An)
5506c3fb27SDimitry Andric   p,     // (d,An)
5606c3fb27SDimitry Andric   f,     // (d,An,Xn.L)
5706c3fb27SDimitry Andric   F,     // (d,An,Xn.W)
5806c3fb27SDimitry Andric   g,     // (d,An,Xn.L,SCALE)
5906c3fb27SDimitry Andric   G,     // (d,An,Xn.W,SCALE)
6006c3fb27SDimitry Andric   u,     // ([bd,An],Xn.L,SCALE,od)
6106c3fb27SDimitry Andric   U,     // ([bd,An],Xn.W,SCALE,od)
6206c3fb27SDimitry Andric   v,     // ([bd,An,Xn.L,SCALE],od)
6306c3fb27SDimitry Andric   V,     // ([bd,An,Xn.W,SCALE],od)
6406c3fb27SDimitry Andric   b,     // abs.L
6506c3fb27SDimitry Andric   B,     // abs.W
6606c3fb27SDimitry Andric   q,     // (d,PC)
6706c3fb27SDimitry Andric   k,     // (d,PC,Xn.L)
6806c3fb27SDimitry Andric   K,     // (d,PC,Xn.W)
6906c3fb27SDimitry Andric   l,     // (d,PC,Xn.L,SCALE)
7006c3fb27SDimitry Andric   L,     // (d,PC,Xn.W,SCALE)
7106c3fb27SDimitry Andric   x,     // ([bd,PC],Xn.L,SCALE,od)
7206c3fb27SDimitry Andric   X,     // ([bd,PC],Xn.W,SCALE,od)
7306c3fb27SDimitry Andric   y,     // ([bd,PC,Xn.L,SCALE],od)
7406c3fb27SDimitry Andric   Y      // ([bd,PC,Xn.W,SCALE],od)
7506c3fb27SDimitry Andric };
7606c3fb27SDimitry Andric 
77bdd1243dSDimitry Andric // On a LE host:
78bdd1243dSDimitry Andric // MSB                   LSB    MSB                   LSB
79bdd1243dSDimitry Andric // | 0x12 0x34 | 0xAB 0xCD | -> | 0xAB 0xCD | 0x12 0x34 |
80bdd1243dSDimitry Andric // (On a BE host nothing changes)
swapWord(value_t Val)81bdd1243dSDimitry Andric template <typename value_t> value_t swapWord(value_t Val) {
82bdd1243dSDimitry Andric   const unsigned NumWords = sizeof(Val) / 2;
83bdd1243dSDimitry Andric   if (NumWords <= 1)
84bdd1243dSDimitry Andric     return Val;
85*5f757f3fSDimitry Andric   Val = support::endian::byte_swap(Val, llvm::endianness::big);
86bdd1243dSDimitry Andric   value_t NewVal = 0;
87bdd1243dSDimitry Andric   for (unsigned i = 0U; i != NumWords; ++i) {
88bdd1243dSDimitry Andric     uint16_t Part = (Val >> (i * 16)) & 0xFFFF;
89*5f757f3fSDimitry Andric     Part = support::endian::byte_swap(Part, llvm::endianness::big);
90bdd1243dSDimitry Andric     NewVal |= (Part << (i * 16));
91bdd1243dSDimitry Andric   }
92bdd1243dSDimitry Andric   return NewVal;
93bdd1243dSDimitry Andric }
94fe6060f1SDimitry Andric } // namespace M68k
95fe6060f1SDimitry Andric 
96fe6060f1SDimitry Andric namespace M68kBeads {
97fe6060f1SDimitry Andric enum {
98fe6060f1SDimitry Andric   Ctrl = 0x0,
99fe6060f1SDimitry Andric   Bits1 = 0x1,
100fe6060f1SDimitry Andric   Bits2 = 0x2,
101fe6060f1SDimitry Andric   Bits3 = 0x3,
102fe6060f1SDimitry Andric   Bits4 = 0x4,
103fe6060f1SDimitry Andric   DAReg = 0x5,
104fe6060f1SDimitry Andric   DA = 0x6,
105fe6060f1SDimitry Andric   Reg = 0x7,
106fe6060f1SDimitry Andric   DReg = 0x8,
107fe6060f1SDimitry Andric   Disp8 = 0x9,
108fe6060f1SDimitry Andric   Imm8 = 0xA,
109fe6060f1SDimitry Andric   Imm16 = 0xB,
110fe6060f1SDimitry Andric   Imm32 = 0xC,
111fe6060f1SDimitry Andric   Imm3 = 0xD,
112fe6060f1SDimitry Andric };
113fe6060f1SDimitry Andric 
114fe6060f1SDimitry Andric // Ctrl payload
115fe6060f1SDimitry Andric enum {
116fe6060f1SDimitry Andric   Term = 0x0,
117fe6060f1SDimitry Andric   Ignore = 0x1,
118fe6060f1SDimitry Andric };
119fe6060f1SDimitry Andric } // namespace M68kBeads
120fe6060f1SDimitry Andric 
121fe6060f1SDimitry Andric /// This namespace holds all of the target specific flags that instruction info
122fe6060f1SDimitry Andric /// tracks.
123fe6060f1SDimitry Andric namespace M68kII {
124fe6060f1SDimitry Andric /// Target Operand Flag enum.
125fe6060f1SDimitry Andric enum TOF {
126fe6060f1SDimitry Andric 
127fe6060f1SDimitry Andric   MO_NO_FLAG,
128fe6060f1SDimitry Andric 
129fe6060f1SDimitry Andric   /// On a symbol operand this indicates that the immediate is the absolute
130fe6060f1SDimitry Andric   /// address of the symbol.
131fe6060f1SDimitry Andric   MO_ABSOLUTE_ADDRESS,
132fe6060f1SDimitry Andric 
133fe6060f1SDimitry Andric   /// On a symbol operand this indicates that the immediate is the pc-relative
134fe6060f1SDimitry Andric   /// address of the symbol.
135fe6060f1SDimitry Andric   MO_PC_RELATIVE_ADDRESS,
136fe6060f1SDimitry Andric 
137fe6060f1SDimitry Andric   /// On a symbol operand this indicates that the immediate is the offset to
138fe6060f1SDimitry Andric   /// the GOT entry for the symbol name from the base of the GOT.
139fe6060f1SDimitry Andric   ///
140fe6060f1SDimitry Andric   ///    name@GOT
141fe6060f1SDimitry Andric   MO_GOT,
142fe6060f1SDimitry Andric 
143fe6060f1SDimitry Andric   /// On a symbol operand this indicates that the immediate is the offset to
144fe6060f1SDimitry Andric   /// the location of the symbol name from the base of the GOT.
145fe6060f1SDimitry Andric   ///
146fe6060f1SDimitry Andric   ///    name@GOTOFF
147fe6060f1SDimitry Andric   MO_GOTOFF,
148fe6060f1SDimitry Andric 
149fe6060f1SDimitry Andric   /// On a symbol operand this indicates that the immediate is offset to the
150fe6060f1SDimitry Andric   /// GOT entry for the symbol name from the current code location.
151fe6060f1SDimitry Andric   ///
152fe6060f1SDimitry Andric   ///    name@GOTPCREL
153fe6060f1SDimitry Andric   MO_GOTPCREL,
154fe6060f1SDimitry Andric 
155fe6060f1SDimitry Andric   /// On a symbol operand this indicates that the immediate is offset to the
156fe6060f1SDimitry Andric   /// PLT entry of symbol name from the current code location.
157fe6060f1SDimitry Andric   ///
158fe6060f1SDimitry Andric   ///    name@PLT
159fe6060f1SDimitry Andric   MO_PLT,
16006c3fb27SDimitry Andric 
16106c3fb27SDimitry Andric   /// On a symbol operand, this indicates that the immediate is the offset to
16206c3fb27SDimitry Andric   /// the slot in GOT which stores the information for accessing the TLS
16306c3fb27SDimitry Andric   /// variable. This is used when operating in Global Dynamic mode.
16406c3fb27SDimitry Andric   ///    name@TLSGD
16506c3fb27SDimitry Andric   MO_TLSGD,
16606c3fb27SDimitry Andric 
16706c3fb27SDimitry Andric   /// On a symbol operand, this indicates that the immediate is the offset to
16806c3fb27SDimitry Andric   /// variable within the thread local storage when operating in Local Dynamic
16906c3fb27SDimitry Andric   /// mode.
17006c3fb27SDimitry Andric   ///    name@TLSLD
17106c3fb27SDimitry Andric   MO_TLSLD,
17206c3fb27SDimitry Andric 
17306c3fb27SDimitry Andric   /// On a symbol operand, this indicates that the immediate is the offset to
17406c3fb27SDimitry Andric   /// the slot in GOT which stores the information for accessing the TLS
17506c3fb27SDimitry Andric   /// variable. This is used when operating in Local Dynamic mode.
17606c3fb27SDimitry Andric   ///    name@TLSLDM
17706c3fb27SDimitry Andric   MO_TLSLDM,
17806c3fb27SDimitry Andric 
17906c3fb27SDimitry Andric   /// On a symbol operand, this indicates that the immediate is the offset to
18006c3fb27SDimitry Andric   /// the variable within the thread local storage when operating in Initial
18106c3fb27SDimitry Andric   /// Exec mode.
18206c3fb27SDimitry Andric   ///    name@TLSIE
18306c3fb27SDimitry Andric   MO_TLSIE,
18406c3fb27SDimitry Andric 
18506c3fb27SDimitry Andric   /// On a symbol operand, this indicates that the immediate is the offset to
18606c3fb27SDimitry Andric   /// the variable within in the thread local storage when operating in Local
18706c3fb27SDimitry Andric   /// Exec mode.
18806c3fb27SDimitry Andric   ///    name@TLSLE
18906c3fb27SDimitry Andric   MO_TLSLE,
19006c3fb27SDimitry Andric 
191fe6060f1SDimitry Andric }; // enum TOF
192fe6060f1SDimitry Andric 
193fe6060f1SDimitry Andric /// Return true if the specified TargetFlag operand is a reference to a stub
194fe6060f1SDimitry Andric /// for a global, not the global itself.
isGlobalStubReference(unsigned char TargetFlag)195fe6060f1SDimitry Andric inline static bool isGlobalStubReference(unsigned char TargetFlag) {
196fe6060f1SDimitry Andric   switch (TargetFlag) {
197fe6060f1SDimitry Andric   default:
198fe6060f1SDimitry Andric     return false;
199fe6060f1SDimitry Andric   case M68kII::MO_GOTPCREL: // pc-relative GOT reference.
200fe6060f1SDimitry Andric   case M68kII::MO_GOT:      // normal GOT reference.
201fe6060f1SDimitry Andric     return true;
202fe6060f1SDimitry Andric   }
203fe6060f1SDimitry Andric }
204fe6060f1SDimitry Andric 
205fe6060f1SDimitry Andric /// Return True if the specified GlobalValue is a direct reference for a
206fe6060f1SDimitry Andric /// symbol.
isDirectGlobalReference(unsigned char Flag)207fe6060f1SDimitry Andric inline static bool isDirectGlobalReference(unsigned char Flag) {
208fe6060f1SDimitry Andric   switch (Flag) {
209fe6060f1SDimitry Andric   default:
210fe6060f1SDimitry Andric     return false;
211fe6060f1SDimitry Andric   case M68kII::MO_NO_FLAG:
212fe6060f1SDimitry Andric   case M68kII::MO_ABSOLUTE_ADDRESS:
213fe6060f1SDimitry Andric   case M68kII::MO_PC_RELATIVE_ADDRESS:
214fe6060f1SDimitry Andric     return true;
215fe6060f1SDimitry Andric   }
216fe6060f1SDimitry Andric }
217fe6060f1SDimitry Andric 
218fe6060f1SDimitry Andric /// Return true if the specified global value reference is relative to a 32-bit
219fe6060f1SDimitry Andric /// PIC base (M68kISD::GLOBAL_BASE_REG). If this is true, the addressing mode
220fe6060f1SDimitry Andric /// has the PIC base register added in.
isGlobalRelativeToPICBase(unsigned char TargetFlag)221fe6060f1SDimitry Andric inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) {
222fe6060f1SDimitry Andric   switch (TargetFlag) {
223fe6060f1SDimitry Andric   default:
224fe6060f1SDimitry Andric     return false;
225fe6060f1SDimitry Andric   case M68kII::MO_GOTOFF: // isPICStyleGOT: local global.
226fe6060f1SDimitry Andric   case M68kII::MO_GOT:    // isPICStyleGOT: other global.
227fe6060f1SDimitry Andric     return true;
228fe6060f1SDimitry Andric   }
229fe6060f1SDimitry Andric }
230fe6060f1SDimitry Andric 
231fe6060f1SDimitry Andric /// Return True if the specified GlobalValue requires PC addressing mode.
isPCRelGlobalReference(unsigned char Flag)232fe6060f1SDimitry Andric inline static bool isPCRelGlobalReference(unsigned char Flag) {
233fe6060f1SDimitry Andric   switch (Flag) {
234fe6060f1SDimitry Andric   default:
235fe6060f1SDimitry Andric     return false;
236fe6060f1SDimitry Andric   case M68kII::MO_GOTPCREL:
237fe6060f1SDimitry Andric   case M68kII::MO_PC_RELATIVE_ADDRESS:
238fe6060f1SDimitry Andric     return true;
239fe6060f1SDimitry Andric   }
240fe6060f1SDimitry Andric }
241fe6060f1SDimitry Andric 
242fe6060f1SDimitry Andric /// Return True if the Block is referenced using PC
isPCRelBlockReference(unsigned char Flag)243fe6060f1SDimitry Andric inline static bool isPCRelBlockReference(unsigned char Flag) {
244fe6060f1SDimitry Andric   switch (Flag) {
245fe6060f1SDimitry Andric   default:
246fe6060f1SDimitry Andric     return false;
247fe6060f1SDimitry Andric   case M68kII::MO_PC_RELATIVE_ADDRESS:
248fe6060f1SDimitry Andric     return true;
249fe6060f1SDimitry Andric   }
250fe6060f1SDimitry Andric }
251fe6060f1SDimitry Andric 
isAddressRegister(unsigned RegNo)252fe6060f1SDimitry Andric static inline bool isAddressRegister(unsigned RegNo) {
253fe6060f1SDimitry Andric   switch (RegNo) {
254fe6060f1SDimitry Andric   case M68k::WA0:
255fe6060f1SDimitry Andric   case M68k::WA1:
256fe6060f1SDimitry Andric   case M68k::WA2:
257fe6060f1SDimitry Andric   case M68k::WA3:
258fe6060f1SDimitry Andric   case M68k::WA4:
259fe6060f1SDimitry Andric   case M68k::WA5:
260fe6060f1SDimitry Andric   case M68k::WA6:
261fe6060f1SDimitry Andric   case M68k::WSP:
262fe6060f1SDimitry Andric   case M68k::A0:
263fe6060f1SDimitry Andric   case M68k::A1:
264fe6060f1SDimitry Andric   case M68k::A2:
265fe6060f1SDimitry Andric   case M68k::A3:
266fe6060f1SDimitry Andric   case M68k::A4:
267fe6060f1SDimitry Andric   case M68k::A5:
268fe6060f1SDimitry Andric   case M68k::A6:
269fe6060f1SDimitry Andric   case M68k::SP:
270fe6060f1SDimitry Andric     return true;
271fe6060f1SDimitry Andric   default:
272fe6060f1SDimitry Andric     return false;
273fe6060f1SDimitry Andric   }
274fe6060f1SDimitry Andric }
275fe6060f1SDimitry Andric 
hasMultiMIOperands(unsigned Op,unsigned LogicalOpIdx)276fe6060f1SDimitry Andric static inline bool hasMultiMIOperands(unsigned Op, unsigned LogicalOpIdx) {
277fe6060f1SDimitry Andric   return M68k::getLogicalOperandSize(Op, LogicalOpIdx) > 1;
278fe6060f1SDimitry Andric }
279fe6060f1SDimitry Andric 
getMaskedSpillRegister(unsigned order)280fe6060f1SDimitry Andric static inline unsigned getMaskedSpillRegister(unsigned order) {
281fe6060f1SDimitry Andric   switch (order) {
282fe6060f1SDimitry Andric   default:
283fe6060f1SDimitry Andric     return 0;
284fe6060f1SDimitry Andric   case 0:
285fe6060f1SDimitry Andric     return M68k::D0;
286fe6060f1SDimitry Andric   case 1:
287fe6060f1SDimitry Andric     return M68k::D1;
288fe6060f1SDimitry Andric   case 2:
289fe6060f1SDimitry Andric     return M68k::D2;
290fe6060f1SDimitry Andric   case 3:
291fe6060f1SDimitry Andric     return M68k::D3;
292fe6060f1SDimitry Andric   case 4:
293fe6060f1SDimitry Andric     return M68k::D4;
294fe6060f1SDimitry Andric   case 5:
295fe6060f1SDimitry Andric     return M68k::D5;
296fe6060f1SDimitry Andric   case 6:
297fe6060f1SDimitry Andric     return M68k::D6;
298fe6060f1SDimitry Andric   case 7:
299fe6060f1SDimitry Andric     return M68k::D7;
300fe6060f1SDimitry Andric   case 8:
301fe6060f1SDimitry Andric     return M68k::A0;
302fe6060f1SDimitry Andric   case 9:
303fe6060f1SDimitry Andric     return M68k::A1;
304fe6060f1SDimitry Andric   case 10:
305fe6060f1SDimitry Andric     return M68k::A2;
306fe6060f1SDimitry Andric   case 11:
307fe6060f1SDimitry Andric     return M68k::A3;
308fe6060f1SDimitry Andric   case 12:
309fe6060f1SDimitry Andric     return M68k::A4;
310fe6060f1SDimitry Andric   case 13:
311fe6060f1SDimitry Andric     return M68k::A5;
312fe6060f1SDimitry Andric   case 14:
313fe6060f1SDimitry Andric     return M68k::A6;
314fe6060f1SDimitry Andric   case 15:
315fe6060f1SDimitry Andric     return M68k::SP;
316fe6060f1SDimitry Andric   }
317fe6060f1SDimitry Andric }
318fe6060f1SDimitry Andric 
319fe6060f1SDimitry Andric } // namespace M68kII
320fe6060f1SDimitry Andric 
321fe6060f1SDimitry Andric } // namespace llvm
322fe6060f1SDimitry Andric 
32304eeddc0SDimitry Andric #endif // LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KBASEINFO_H
324