15eb7a581SMin-Yih Hsu //===--- M68k.cpp - Implement M68k targets feature support-------------===// 25eb7a581SMin-Yih Hsu // 35eb7a581SMin-Yih Hsu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45eb7a581SMin-Yih Hsu // See https://llvm.org/LICENSE.txt for license information. 55eb7a581SMin-Yih Hsu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65eb7a581SMin-Yih Hsu // 75eb7a581SMin-Yih Hsu //===----------------------------------------------------------------------===// 85eb7a581SMin-Yih Hsu // 95eb7a581SMin-Yih Hsu // This file implements M68k TargetInfo objects. 105eb7a581SMin-Yih Hsu // 115eb7a581SMin-Yih Hsu //===----------------------------------------------------------------------===// 125eb7a581SMin-Yih Hsu 135eb7a581SMin-Yih Hsu #include "M68k.h" 145eb7a581SMin-Yih Hsu #include "clang/Basic/Builtins.h" 155eb7a581SMin-Yih Hsu #include "clang/Basic/Diagnostic.h" 165eb7a581SMin-Yih Hsu #include "clang/Basic/TargetBuiltins.h" 175eb7a581SMin-Yih Hsu #include "llvm/ADT/StringExtras.h" 185eb7a581SMin-Yih Hsu #include "llvm/ADT/StringRef.h" 195eb7a581SMin-Yih Hsu #include "llvm/ADT/StringSwitch.h" 208e3d7cf5SArchibald Elliott #include "llvm/TargetParser/TargetParser.h" 21dccf5c7dSMin-Yih Hsu #include <cstdint> 225eb7a581SMin-Yih Hsu #include <cstring> 23dccf5c7dSMin-Yih Hsu #include <limits> 24a1580d7bSKazu Hirata #include <optional> 255eb7a581SMin-Yih Hsu 265eb7a581SMin-Yih Hsu namespace clang { 275eb7a581SMin-Yih Hsu namespace targets { 285eb7a581SMin-Yih Hsu 295eb7a581SMin-Yih Hsu M68kTargetInfo::M68kTargetInfo(const llvm::Triple &Triple, 309b617081SMin-Yih Hsu const TargetOptions &Opts) 319b617081SMin-Yih Hsu : TargetInfo(Triple), TargetOpts(Opts) { 325eb7a581SMin-Yih Hsu 330542d152SKazu Hirata std::string Layout; 345eb7a581SMin-Yih Hsu 355eb7a581SMin-Yih Hsu // M68k is Big Endian 365eb7a581SMin-Yih Hsu Layout += "E"; 375eb7a581SMin-Yih Hsu 385eb7a581SMin-Yih Hsu // FIXME how to wire it with the used object format? 395eb7a581SMin-Yih Hsu Layout += "-m:e"; 405eb7a581SMin-Yih Hsu 418d3f112fSRicky Taylor // M68k pointers are always 32 bit wide even for 16-bit CPUs 428d3f112fSRicky Taylor Layout += "-p:32:16:32"; 435eb7a581SMin-Yih Hsu 445eb7a581SMin-Yih Hsu // M68k integer data types 455eb7a581SMin-Yih Hsu Layout += "-i8:8:8-i16:16:16-i32:16:32"; 465eb7a581SMin-Yih Hsu 475eb7a581SMin-Yih Hsu // FIXME no floats at the moment 485eb7a581SMin-Yih Hsu 495eb7a581SMin-Yih Hsu // The registers can hold 8, 16, 32 bits 505eb7a581SMin-Yih Hsu Layout += "-n8:16:32"; 515eb7a581SMin-Yih Hsu 525eb7a581SMin-Yih Hsu // 16 bit alignment for both stack and aggregate 535eb7a581SMin-Yih Hsu // in order to conform to ABI used by GCC 545eb7a581SMin-Yih Hsu Layout += "-a:0:16-S16"; 555eb7a581SMin-Yih Hsu 565eb7a581SMin-Yih Hsu resetDataLayout(Layout); 575eb7a581SMin-Yih Hsu 585eb7a581SMin-Yih Hsu SizeType = UnsignedInt; 595eb7a581SMin-Yih Hsu PtrDiffType = SignedInt; 605eb7a581SMin-Yih Hsu IntPtrType = SignedInt; 615eb7a581SMin-Yih Hsu } 625eb7a581SMin-Yih Hsu 635eb7a581SMin-Yih Hsu bool M68kTargetInfo::setCPU(const std::string &Name) { 645eb7a581SMin-Yih Hsu StringRef N = Name; 655eb7a581SMin-Yih Hsu CPU = llvm::StringSwitch<CPUKind>(N) 665eb7a581SMin-Yih Hsu .Case("generic", CK_68000) 675eb7a581SMin-Yih Hsu .Case("M68000", CK_68000) 685eb7a581SMin-Yih Hsu .Case("M68010", CK_68010) 695eb7a581SMin-Yih Hsu .Case("M68020", CK_68020) 705eb7a581SMin-Yih Hsu .Case("M68030", CK_68030) 715eb7a581SMin-Yih Hsu .Case("M68040", CK_68040) 725eb7a581SMin-Yih Hsu .Case("M68060", CK_68060) 735eb7a581SMin-Yih Hsu .Default(CK_Unknown); 745eb7a581SMin-Yih Hsu return CPU != CK_Unknown; 755eb7a581SMin-Yih Hsu } 765eb7a581SMin-Yih Hsu 775eb7a581SMin-Yih Hsu void M68kTargetInfo::getTargetDefines(const LangOptions &Opts, 785eb7a581SMin-Yih Hsu MacroBuilder &Builder) const { 795eb7a581SMin-Yih Hsu using llvm::Twine; 805eb7a581SMin-Yih Hsu 815eb7a581SMin-Yih Hsu Builder.defineMacro("__m68k__"); 825eb7a581SMin-Yih Hsu 83230558e4SMin-Yih Hsu DefineStd(Builder, "mc68000", Opts); 845eb7a581SMin-Yih Hsu 855eb7a581SMin-Yih Hsu // For sub-architecture 865eb7a581SMin-Yih Hsu switch (CPU) { 875eb7a581SMin-Yih Hsu case CK_68010: 88230558e4SMin-Yih Hsu DefineStd(Builder, "mc68010", Opts); 895eb7a581SMin-Yih Hsu break; 905eb7a581SMin-Yih Hsu case CK_68020: 91230558e4SMin-Yih Hsu DefineStd(Builder, "mc68020", Opts); 925eb7a581SMin-Yih Hsu break; 935eb7a581SMin-Yih Hsu case CK_68030: 94230558e4SMin-Yih Hsu DefineStd(Builder, "mc68030", Opts); 955eb7a581SMin-Yih Hsu break; 965eb7a581SMin-Yih Hsu case CK_68040: 97230558e4SMin-Yih Hsu DefineStd(Builder, "mc68040", Opts); 985eb7a581SMin-Yih Hsu break; 995eb7a581SMin-Yih Hsu case CK_68060: 100230558e4SMin-Yih Hsu DefineStd(Builder, "mc68060", Opts); 1015eb7a581SMin-Yih Hsu break; 1025eb7a581SMin-Yih Hsu default: 1035eb7a581SMin-Yih Hsu break; 1045eb7a581SMin-Yih Hsu } 1052784b243SBrad Smith 1062784b243SBrad Smith if (CPU >= CK_68020) { 1072784b243SBrad Smith Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 1082784b243SBrad Smith Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 1092784b243SBrad Smith Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 1102784b243SBrad Smith } 1119b617081SMin-Yih Hsu 1129b617081SMin-Yih Hsu // Floating point 1139b617081SMin-Yih Hsu if (TargetOpts.FeatureMap.lookup("isa-68881") || 1149b617081SMin-Yih Hsu TargetOpts.FeatureMap.lookup("isa-68882")) 1159b617081SMin-Yih Hsu Builder.defineMacro("__HAVE_68881__"); 1165eb7a581SMin-Yih Hsu } 1175eb7a581SMin-Yih Hsu 118*ca79ff07SChandler Carruth ArrayRef<Builtin::Info> M68kTargetInfo::getTargetBuiltins() const { 1195eb7a581SMin-Yih Hsu // FIXME: Implement. 120*ca79ff07SChandler Carruth return {}; 1215eb7a581SMin-Yih Hsu } 1225eb7a581SMin-Yih Hsu 1235eb7a581SMin-Yih Hsu bool M68kTargetInfo::hasFeature(StringRef Feature) const { 1245eb7a581SMin-Yih Hsu // FIXME elaborate moar 1255eb7a581SMin-Yih Hsu return Feature == "M68000"; 1265eb7a581SMin-Yih Hsu } 1275eb7a581SMin-Yih Hsu 1285eb7a581SMin-Yih Hsu const char *const M68kTargetInfo::GCCRegNames[] = { 1295eb7a581SMin-Yih Hsu "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", 1304f0b5d5eSJim Lin "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", 1315eb7a581SMin-Yih Hsu "pc"}; 1325eb7a581SMin-Yih Hsu 1335eb7a581SMin-Yih Hsu ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const { 134a3c248dbSserge-sans-paille return llvm::ArrayRef(GCCRegNames); 1355eb7a581SMin-Yih Hsu } 1365eb7a581SMin-Yih Hsu 1374f0b5d5eSJim Lin const TargetInfo::GCCRegAlias M68kTargetInfo::GCCRegAliases[] = { 1384f0b5d5eSJim Lin {{"bp"}, "a5"}, 1394f0b5d5eSJim Lin {{"fp"}, "a6"}, 1404f0b5d5eSJim Lin {{"usp", "ssp", "isp", "a7"}, "sp"}, 1414f0b5d5eSJim Lin }; 1424f0b5d5eSJim Lin 1435eb7a581SMin-Yih Hsu ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const { 1444f0b5d5eSJim Lin return llvm::ArrayRef(GCCRegAliases); 1455eb7a581SMin-Yih Hsu } 1465eb7a581SMin-Yih Hsu 1475eb7a581SMin-Yih Hsu bool M68kTargetInfo::validateAsmConstraint( 1485eb7a581SMin-Yih Hsu const char *&Name, TargetInfo::ConstraintInfo &info) const { 1495eb7a581SMin-Yih Hsu switch (*Name) { 1505eb7a581SMin-Yih Hsu case 'a': // address register 1515eb7a581SMin-Yih Hsu case 'd': // data register 1525eb7a581SMin-Yih Hsu info.setAllowsRegister(); 1535eb7a581SMin-Yih Hsu return true; 154dccf5c7dSMin-Yih Hsu case 'I': // constant integer in the range [1,8] 155dccf5c7dSMin-Yih Hsu info.setRequiresImmediate(1, 8); 1565eb7a581SMin-Yih Hsu return true; 157dccf5c7dSMin-Yih Hsu case 'J': // constant signed 16-bit integer 158dccf5c7dSMin-Yih Hsu info.setRequiresImmediate(std::numeric_limits<int16_t>::min(), 159dccf5c7dSMin-Yih Hsu std::numeric_limits<int16_t>::max()); 160dccf5c7dSMin-Yih Hsu return true; 161dccf5c7dSMin-Yih Hsu case 'K': // constant that is NOT in the range of [-0x80, 0x80) 162dccf5c7dSMin-Yih Hsu info.setRequiresImmediate(); 163dccf5c7dSMin-Yih Hsu return true; 164dccf5c7dSMin-Yih Hsu case 'L': // constant integer in the range [-8,-1] 165dccf5c7dSMin-Yih Hsu info.setRequiresImmediate(-8, -1); 166dccf5c7dSMin-Yih Hsu return true; 167dccf5c7dSMin-Yih Hsu case 'M': // constant that is NOT in the range of [-0x100, 0x100] 168dccf5c7dSMin-Yih Hsu info.setRequiresImmediate(); 169dccf5c7dSMin-Yih Hsu return true; 170dccf5c7dSMin-Yih Hsu case 'N': // constant integer in the range [24,31] 171dccf5c7dSMin-Yih Hsu info.setRequiresImmediate(24, 31); 172dccf5c7dSMin-Yih Hsu return true; 173dccf5c7dSMin-Yih Hsu case 'O': // constant integer 16 174dccf5c7dSMin-Yih Hsu info.setRequiresImmediate(16); 175dccf5c7dSMin-Yih Hsu return true; 176dccf5c7dSMin-Yih Hsu case 'P': // constant integer in the range [8,15] 177dccf5c7dSMin-Yih Hsu info.setRequiresImmediate(8, 15); 178dccf5c7dSMin-Yih Hsu return true; 179dccf5c7dSMin-Yih Hsu case 'C': 180dccf5c7dSMin-Yih Hsu ++Name; 181dccf5c7dSMin-Yih Hsu switch (*Name) { 182dccf5c7dSMin-Yih Hsu case '0': // constant integer 0 183dccf5c7dSMin-Yih Hsu info.setRequiresImmediate(0); 184dccf5c7dSMin-Yih Hsu return true; 185dccf5c7dSMin-Yih Hsu case 'i': // constant integer 186dccf5c7dSMin-Yih Hsu case 'j': // integer constant that doesn't fit in 16 bits 187dccf5c7dSMin-Yih Hsu info.setRequiresImmediate(); 188dccf5c7dSMin-Yih Hsu return true; 189dccf5c7dSMin-Yih Hsu default: 190dccf5c7dSMin-Yih Hsu break; 1915eb7a581SMin-Yih Hsu } 192dccf5c7dSMin-Yih Hsu break; 1937335cd05SMin-Yih Hsu case 'Q': // address register indirect addressing 1947335cd05SMin-Yih Hsu case 'U': // address register indirect w/ constant offset addressing 1957335cd05SMin-Yih Hsu // TODO: Handle 'S' (basically 'm' when pc-rel is enforced) when 1967335cd05SMin-Yih Hsu // '-mpcrel' flag is properly handled by the driver. 1977335cd05SMin-Yih Hsu info.setAllowsMemory(); 1987335cd05SMin-Yih Hsu return true; 199dccf5c7dSMin-Yih Hsu default: 200dccf5c7dSMin-Yih Hsu break; 201dccf5c7dSMin-Yih Hsu } 2025eb7a581SMin-Yih Hsu return false; 2035eb7a581SMin-Yih Hsu } 2045eb7a581SMin-Yih Hsu 2056ad0788cSKazu Hirata std::optional<std::string> 2066685a3f3SMin-Yih Hsu M68kTargetInfo::handleAsmEscapedChar(char EscChar) const { 2076685a3f3SMin-Yih Hsu char C; 2086685a3f3SMin-Yih Hsu switch (EscChar) { 2096685a3f3SMin-Yih Hsu case '.': 2106685a3f3SMin-Yih Hsu case '#': 2116685a3f3SMin-Yih Hsu C = EscChar; 2126685a3f3SMin-Yih Hsu break; 2136685a3f3SMin-Yih Hsu case '/': 2146685a3f3SMin-Yih Hsu C = '%'; 2156685a3f3SMin-Yih Hsu break; 2166685a3f3SMin-Yih Hsu case '$': 2176685a3f3SMin-Yih Hsu C = 's'; 2186685a3f3SMin-Yih Hsu break; 2196685a3f3SMin-Yih Hsu case '&': 2206685a3f3SMin-Yih Hsu C = 'd'; 2216685a3f3SMin-Yih Hsu break; 2226685a3f3SMin-Yih Hsu default: 223eeee3feeSKazu Hirata return std::nullopt; 2246685a3f3SMin-Yih Hsu } 2256685a3f3SMin-Yih Hsu 2266685a3f3SMin-Yih Hsu return std::string(1, C); 2276685a3f3SMin-Yih Hsu } 2286685a3f3SMin-Yih Hsu 229dccf5c7dSMin-Yih Hsu std::string M68kTargetInfo::convertConstraint(const char *&Constraint) const { 230dccf5c7dSMin-Yih Hsu if (*Constraint == 'C') 231dccf5c7dSMin-Yih Hsu // Two-character constraint; add "^" hint for later parsing 232dccf5c7dSMin-Yih Hsu return std::string("^") + std::string(Constraint++, 2); 233dccf5c7dSMin-Yih Hsu 234dccf5c7dSMin-Yih Hsu return std::string(1, *Constraint); 235dccf5c7dSMin-Yih Hsu } 236dccf5c7dSMin-Yih Hsu 23742d758bfSStoorx std::string_view M68kTargetInfo::getClobbers() const { 2385eb7a581SMin-Yih Hsu // FIXME: Is this really right? 2395eb7a581SMin-Yih Hsu return ""; 2405eb7a581SMin-Yih Hsu } 2415eb7a581SMin-Yih Hsu 24259437cb7SMin-Yih Hsu TargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const { 24359437cb7SMin-Yih Hsu return TargetInfo::VoidPtrBuiltinVaList; 2445eb7a581SMin-Yih Hsu } 2455eb7a581SMin-Yih Hsu 246fd4f9629SMin-Yih Hsu TargetInfo::CallingConvCheckResult 247fd4f9629SMin-Yih Hsu M68kTargetInfo::checkCallingConvention(CallingConv CC) const { 248fd4f9629SMin-Yih Hsu switch (CC) { 249fd4f9629SMin-Yih Hsu case CC_C: 250fd4f9629SMin-Yih Hsu case CC_M68kRTD: 251fd4f9629SMin-Yih Hsu return CCCR_OK; 252fd4f9629SMin-Yih Hsu default: 253fd4f9629SMin-Yih Hsu return TargetInfo::checkCallingConvention(CC); 254fd4f9629SMin-Yih Hsu } 255fd4f9629SMin-Yih Hsu } 2565eb7a581SMin-Yih Hsu } // namespace targets 2575eb7a581SMin-Yih Hsu } // namespace clang 258