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