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