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) 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. 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. 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. 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. 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 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 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 276fe6060f1SDimitry Andric static inline bool hasMultiMIOperands(unsigned Op, unsigned LogicalOpIdx) { 277fe6060f1SDimitry Andric return M68k::getLogicalOperandSize(Op, LogicalOpIdx) > 1; 278fe6060f1SDimitry Andric } 279fe6060f1SDimitry Andric 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