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