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