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