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" 20*06c3fb27SDimitry Andric #include "llvm/TargetParser/TargetParser.h" 21fe6060f1SDimitry Andric #include <cstdint> 22fe6060f1SDimitry Andric #include <cstring> 23fe6060f1SDimitry Andric #include <limits> 24bdd1243dSDimitry Andric #include <optional> 25fe6060f1SDimitry Andric 26fe6060f1SDimitry Andric namespace clang { 27fe6060f1SDimitry Andric namespace targets { 28fe6060f1SDimitry Andric 29fe6060f1SDimitry Andric M68kTargetInfo::M68kTargetInfo(const llvm::Triple &Triple, 30*06c3fb27SDimitry Andric const TargetOptions &Opts) 31*06c3fb27SDimitry Andric : TargetInfo(Triple), TargetOpts(Opts) { 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 } 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric if (CPU >= CK_68020) { 119bdd1243dSDimitry Andric Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 120bdd1243dSDimitry Andric Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 121bdd1243dSDimitry Andric Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 122bdd1243dSDimitry Andric } 123*06c3fb27SDimitry Andric 124*06c3fb27SDimitry Andric // Floating point 125*06c3fb27SDimitry Andric if (TargetOpts.FeatureMap.lookup("isa-68881") || 126*06c3fb27SDimitry Andric TargetOpts.FeatureMap.lookup("isa-68882")) 127*06c3fb27SDimitry Andric Builder.defineMacro("__HAVE_68881__"); 128fe6060f1SDimitry Andric } 129fe6060f1SDimitry Andric 130fe6060f1SDimitry Andric ArrayRef<Builtin::Info> M68kTargetInfo::getTargetBuiltins() const { 131fe6060f1SDimitry Andric // FIXME: Implement. 132bdd1243dSDimitry Andric return std::nullopt; 133fe6060f1SDimitry Andric } 134fe6060f1SDimitry Andric 135fe6060f1SDimitry Andric bool M68kTargetInfo::hasFeature(StringRef Feature) const { 136fe6060f1SDimitry Andric // FIXME elaborate moar 137fe6060f1SDimitry Andric return Feature == "M68000"; 138fe6060f1SDimitry Andric } 139fe6060f1SDimitry Andric 140fe6060f1SDimitry Andric const char *const M68kTargetInfo::GCCRegNames[] = { 141fe6060f1SDimitry Andric "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", 142fe6060f1SDimitry Andric "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", 143fe6060f1SDimitry Andric "pc"}; 144fe6060f1SDimitry Andric 145fe6060f1SDimitry Andric ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const { 146bdd1243dSDimitry Andric return llvm::ArrayRef(GCCRegNames); 147fe6060f1SDimitry Andric } 148fe6060f1SDimitry Andric 149fe6060f1SDimitry Andric ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const { 150fe6060f1SDimitry Andric // No aliases. 151bdd1243dSDimitry Andric return std::nullopt; 152fe6060f1SDimitry Andric } 153fe6060f1SDimitry Andric 154fe6060f1SDimitry Andric bool M68kTargetInfo::validateAsmConstraint( 155fe6060f1SDimitry Andric const char *&Name, TargetInfo::ConstraintInfo &info) const { 156fe6060f1SDimitry Andric switch (*Name) { 157fe6060f1SDimitry Andric case 'a': // address register 158fe6060f1SDimitry Andric case 'd': // data register 159fe6060f1SDimitry Andric info.setAllowsRegister(); 160fe6060f1SDimitry Andric return true; 161fe6060f1SDimitry Andric case 'I': // constant integer in the range [1,8] 162fe6060f1SDimitry Andric info.setRequiresImmediate(1, 8); 163fe6060f1SDimitry Andric return true; 164fe6060f1SDimitry Andric case 'J': // constant signed 16-bit integer 165fe6060f1SDimitry Andric info.setRequiresImmediate(std::numeric_limits<int16_t>::min(), 166fe6060f1SDimitry Andric std::numeric_limits<int16_t>::max()); 167fe6060f1SDimitry Andric return true; 168fe6060f1SDimitry Andric case 'K': // constant that is NOT in the range of [-0x80, 0x80) 169fe6060f1SDimitry Andric info.setRequiresImmediate(); 170fe6060f1SDimitry Andric return true; 171fe6060f1SDimitry Andric case 'L': // constant integer in the range [-8,-1] 172fe6060f1SDimitry Andric info.setRequiresImmediate(-8, -1); 173fe6060f1SDimitry Andric return true; 174fe6060f1SDimitry Andric case 'M': // constant that is NOT in the range of [-0x100, 0x100] 175fe6060f1SDimitry Andric info.setRequiresImmediate(); 176fe6060f1SDimitry Andric return true; 177fe6060f1SDimitry Andric case 'N': // constant integer in the range [24,31] 178fe6060f1SDimitry Andric info.setRequiresImmediate(24, 31); 179fe6060f1SDimitry Andric return true; 180fe6060f1SDimitry Andric case 'O': // constant integer 16 181fe6060f1SDimitry Andric info.setRequiresImmediate(16); 182fe6060f1SDimitry Andric return true; 183fe6060f1SDimitry Andric case 'P': // constant integer in the range [8,15] 184fe6060f1SDimitry Andric info.setRequiresImmediate(8, 15); 185fe6060f1SDimitry Andric return true; 186fe6060f1SDimitry Andric case 'C': 187fe6060f1SDimitry Andric ++Name; 188fe6060f1SDimitry Andric switch (*Name) { 189fe6060f1SDimitry Andric case '0': // constant integer 0 190fe6060f1SDimitry Andric info.setRequiresImmediate(0); 191fe6060f1SDimitry Andric return true; 192fe6060f1SDimitry Andric case 'i': // constant integer 193fe6060f1SDimitry Andric case 'j': // integer constant that doesn't fit in 16 bits 194fe6060f1SDimitry Andric info.setRequiresImmediate(); 195fe6060f1SDimitry Andric return true; 196fe6060f1SDimitry Andric default: 197fe6060f1SDimitry Andric break; 198fe6060f1SDimitry Andric } 199fe6060f1SDimitry Andric break; 200*06c3fb27SDimitry Andric case 'Q': // address register indirect addressing 201*06c3fb27SDimitry Andric case 'U': // address register indirect w/ constant offset addressing 202*06c3fb27SDimitry Andric // TODO: Handle 'S' (basically 'm' when pc-rel is enforced) when 203*06c3fb27SDimitry Andric // '-mpcrel' flag is properly handled by the driver. 204*06c3fb27SDimitry Andric info.setAllowsMemory(); 205*06c3fb27SDimitry Andric return true; 206fe6060f1SDimitry Andric default: 207fe6060f1SDimitry Andric break; 208fe6060f1SDimitry Andric } 209fe6060f1SDimitry Andric return false; 210fe6060f1SDimitry Andric } 211fe6060f1SDimitry Andric 212bdd1243dSDimitry Andric std::optional<std::string> 213fe6060f1SDimitry Andric M68kTargetInfo::handleAsmEscapedChar(char EscChar) const { 214fe6060f1SDimitry Andric char C; 215fe6060f1SDimitry Andric switch (EscChar) { 216fe6060f1SDimitry Andric case '.': 217fe6060f1SDimitry Andric case '#': 218fe6060f1SDimitry Andric C = EscChar; 219fe6060f1SDimitry Andric break; 220fe6060f1SDimitry Andric case '/': 221fe6060f1SDimitry Andric C = '%'; 222fe6060f1SDimitry Andric break; 223fe6060f1SDimitry Andric case '$': 224fe6060f1SDimitry Andric C = 's'; 225fe6060f1SDimitry Andric break; 226fe6060f1SDimitry Andric case '&': 227fe6060f1SDimitry Andric C = 'd'; 228fe6060f1SDimitry Andric break; 229fe6060f1SDimitry Andric default: 230bdd1243dSDimitry Andric return std::nullopt; 231fe6060f1SDimitry Andric } 232fe6060f1SDimitry Andric 233fe6060f1SDimitry Andric return std::string(1, C); 234fe6060f1SDimitry Andric } 235fe6060f1SDimitry Andric 236fe6060f1SDimitry Andric std::string M68kTargetInfo::convertConstraint(const char *&Constraint) const { 237fe6060f1SDimitry Andric if (*Constraint == 'C') 238fe6060f1SDimitry Andric // Two-character constraint; add "^" hint for later parsing 239fe6060f1SDimitry Andric return std::string("^") + std::string(Constraint++, 2); 240fe6060f1SDimitry Andric 241fe6060f1SDimitry Andric return std::string(1, *Constraint); 242fe6060f1SDimitry Andric } 243fe6060f1SDimitry Andric 244*06c3fb27SDimitry Andric std::string_view M68kTargetInfo::getClobbers() const { 245fe6060f1SDimitry Andric // FIXME: Is this really right? 246fe6060f1SDimitry Andric return ""; 247fe6060f1SDimitry Andric } 248fe6060f1SDimitry Andric 249fe6060f1SDimitry Andric TargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const { 250fe6060f1SDimitry Andric return TargetInfo::VoidPtrBuiltinVaList; 251fe6060f1SDimitry Andric } 252fe6060f1SDimitry Andric 253fe6060f1SDimitry Andric } // namespace targets 254fe6060f1SDimitry Andric } // namespace clang 255