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