xref: /llvm-project/clang/lib/Basic/Targets/M68k.cpp (revision ca79ff07d8ae7a0c2531bfdb1cb623e25e5bd486)
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