1 //===--- M68k.cpp - Implement M68k targets feature support-------------===// 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 implements M68k TargetInfo objects. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "M68k.h" 14 #include "clang/Basic/Builtins.h" 15 #include "clang/Basic/Diagnostic.h" 16 #include "clang/Basic/TargetBuiltins.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/ADT/StringSwitch.h" 20 #include "llvm/Support/TargetParser.h" 21 #include <cstdint> 22 #include <cstring> 23 #include <limits> 24 #include <optional> 25 26 namespace clang { 27 namespace targets { 28 29 M68kTargetInfo::M68kTargetInfo(const llvm::Triple &Triple, 30 const TargetOptions &) 31 : TargetInfo(Triple) { 32 33 std::string Layout; 34 35 // M68k is Big Endian 36 Layout += "E"; 37 38 // FIXME how to wire it with the used object format? 39 Layout += "-m:e"; 40 41 // M68k pointers are always 32 bit wide even for 16-bit CPUs 42 Layout += "-p:32:16:32"; 43 44 // M68k integer data types 45 Layout += "-i8:8:8-i16:16:16-i32:16:32"; 46 47 // FIXME no floats at the moment 48 49 // The registers can hold 8, 16, 32 bits 50 Layout += "-n8:16:32"; 51 52 // 16 bit alignment for both stack and aggregate 53 // in order to conform to ABI used by GCC 54 Layout += "-a:0:16-S16"; 55 56 resetDataLayout(Layout); 57 58 SizeType = UnsignedInt; 59 PtrDiffType = SignedInt; 60 IntPtrType = SignedInt; 61 } 62 63 bool M68kTargetInfo::setCPU(const std::string &Name) { 64 StringRef N = Name; 65 CPU = llvm::StringSwitch<CPUKind>(N) 66 .Case("generic", CK_68000) 67 .Case("M68000", CK_68000) 68 .Case("M68010", CK_68010) 69 .Case("M68020", CK_68020) 70 .Case("M68030", CK_68030) 71 .Case("M68040", CK_68040) 72 .Case("M68060", CK_68060) 73 .Default(CK_Unknown); 74 return CPU != CK_Unknown; 75 } 76 77 void M68kTargetInfo::getTargetDefines(const LangOptions &Opts, 78 MacroBuilder &Builder) const { 79 using llvm::Twine; 80 81 Builder.defineMacro("__m68k__"); 82 83 Builder.defineMacro("mc68000"); 84 Builder.defineMacro("__mc68000"); 85 Builder.defineMacro("__mc68000__"); 86 87 // For sub-architecture 88 switch (CPU) { 89 case CK_68010: 90 Builder.defineMacro("mc68010"); 91 Builder.defineMacro("__mc68010"); 92 Builder.defineMacro("__mc68010__"); 93 break; 94 case CK_68020: 95 Builder.defineMacro("mc68020"); 96 Builder.defineMacro("__mc68020"); 97 Builder.defineMacro("__mc68020__"); 98 break; 99 case CK_68030: 100 Builder.defineMacro("mc68030"); 101 Builder.defineMacro("__mc68030"); 102 Builder.defineMacro("__mc68030__"); 103 break; 104 case CK_68040: 105 Builder.defineMacro("mc68040"); 106 Builder.defineMacro("__mc68040"); 107 Builder.defineMacro("__mc68040__"); 108 break; 109 case CK_68060: 110 Builder.defineMacro("mc68060"); 111 Builder.defineMacro("__mc68060"); 112 Builder.defineMacro("__mc68060__"); 113 break; 114 default: 115 break; 116 } 117 118 if (CPU >= CK_68020) { 119 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 120 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 121 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 122 } 123 } 124 125 ArrayRef<Builtin::Info> M68kTargetInfo::getTargetBuiltins() const { 126 // FIXME: Implement. 127 return std::nullopt; 128 } 129 130 bool M68kTargetInfo::hasFeature(StringRef Feature) const { 131 // FIXME elaborate moar 132 return Feature == "M68000"; 133 } 134 135 const char *const M68kTargetInfo::GCCRegNames[] = { 136 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", 137 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", 138 "pc"}; 139 140 ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const { 141 return llvm::ArrayRef(GCCRegNames); 142 } 143 144 ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const { 145 // No aliases. 146 return std::nullopt; 147 } 148 149 bool M68kTargetInfo::validateAsmConstraint( 150 const char *&Name, TargetInfo::ConstraintInfo &info) const { 151 switch (*Name) { 152 case 'a': // address register 153 case 'd': // data register 154 info.setAllowsRegister(); 155 return true; 156 case 'I': // constant integer in the range [1,8] 157 info.setRequiresImmediate(1, 8); 158 return true; 159 case 'J': // constant signed 16-bit integer 160 info.setRequiresImmediate(std::numeric_limits<int16_t>::min(), 161 std::numeric_limits<int16_t>::max()); 162 return true; 163 case 'K': // constant that is NOT in the range of [-0x80, 0x80) 164 info.setRequiresImmediate(); 165 return true; 166 case 'L': // constant integer in the range [-8,-1] 167 info.setRequiresImmediate(-8, -1); 168 return true; 169 case 'M': // constant that is NOT in the range of [-0x100, 0x100] 170 info.setRequiresImmediate(); 171 return true; 172 case 'N': // constant integer in the range [24,31] 173 info.setRequiresImmediate(24, 31); 174 return true; 175 case 'O': // constant integer 16 176 info.setRequiresImmediate(16); 177 return true; 178 case 'P': // constant integer in the range [8,15] 179 info.setRequiresImmediate(8, 15); 180 return true; 181 case 'C': 182 ++Name; 183 switch (*Name) { 184 case '0': // constant integer 0 185 info.setRequiresImmediate(0); 186 return true; 187 case 'i': // constant integer 188 case 'j': // integer constant that doesn't fit in 16 bits 189 info.setRequiresImmediate(); 190 return true; 191 default: 192 break; 193 } 194 break; 195 default: 196 break; 197 } 198 return false; 199 } 200 201 std::optional<std::string> 202 M68kTargetInfo::handleAsmEscapedChar(char EscChar) const { 203 char C; 204 switch (EscChar) { 205 case '.': 206 case '#': 207 C = EscChar; 208 break; 209 case '/': 210 C = '%'; 211 break; 212 case '$': 213 C = 's'; 214 break; 215 case '&': 216 C = 'd'; 217 break; 218 default: 219 return std::nullopt; 220 } 221 222 return std::string(1, C); 223 } 224 225 std::string M68kTargetInfo::convertConstraint(const char *&Constraint) const { 226 if (*Constraint == 'C') 227 // Two-character constraint; add "^" hint for later parsing 228 return std::string("^") + std::string(Constraint++, 2); 229 230 return std::string(1, *Constraint); 231 } 232 233 const char *M68kTargetInfo::getClobbers() const { 234 // FIXME: Is this really right? 235 return ""; 236 } 237 238 TargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const { 239 return TargetInfo::VoidPtrBuiltinVaList; 240 } 241 242 } // namespace targets 243 } // namespace clang 244