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