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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Basic/Targets/M68k.cpp