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