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