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 <cstring>
22 
23 namespace clang {
24 namespace targets {
25 
26 M68kTargetInfo::M68kTargetInfo(const llvm::Triple &Triple,
27                                const TargetOptions &)
28     : TargetInfo(Triple) {
29 
30   std::string Layout = "";
31 
32   // M68k is Big Endian
33   Layout += "E";
34 
35   // FIXME how to wire it with the used object format?
36   Layout += "-m:e";
37 
38   // M68k pointers are always 32 bit wide even for 16 bit cpus
39   Layout += "-p:32:32";
40 
41   // M68k integer data types
42   Layout += "-i8:8:8-i16:16:16-i32:16:32";
43 
44   // FIXME no floats at the moment
45 
46   // The registers can hold 8, 16, 32 bits
47   Layout += "-n8:16:32";
48 
49   // 16 bit alignment for both stack and aggregate
50   // in order to conform to ABI used by GCC
51   Layout += "-a:0:16-S16";
52 
53   resetDataLayout(Layout);
54 
55   SizeType = UnsignedInt;
56   PtrDiffType = SignedInt;
57   IntPtrType = SignedInt;
58 }
59 
60 bool M68kTargetInfo::setCPU(const std::string &Name) {
61   StringRef N = Name;
62   CPU = llvm::StringSwitch<CPUKind>(N)
63             .Case("generic", CK_68000)
64             .Case("M68000", CK_68000)
65             .Case("M68010", CK_68010)
66             .Case("M68020", CK_68020)
67             .Case("M68030", CK_68030)
68             .Case("M68040", CK_68040)
69             .Case("M68060", CK_68060)
70             .Default(CK_Unknown);
71   return CPU != CK_Unknown;
72 }
73 
74 void M68kTargetInfo::getTargetDefines(const LangOptions &Opts,
75                                       MacroBuilder &Builder) const {
76   using llvm::Twine;
77 
78   Builder.defineMacro("__m68k__");
79 
80   Builder.defineMacro("mc68000");
81   Builder.defineMacro("__mc68000");
82   Builder.defineMacro("__mc68000__");
83 
84   // For sub-architecture
85   switch (CPU) {
86   case CK_68010:
87     Builder.defineMacro("mc68010");
88     Builder.defineMacro("__mc68010");
89     Builder.defineMacro("__mc68010__");
90     break;
91   case CK_68020:
92     Builder.defineMacro("mc68020");
93     Builder.defineMacro("__mc68020");
94     Builder.defineMacro("__mc68020__");
95     break;
96   case CK_68030:
97     Builder.defineMacro("mc68030");
98     Builder.defineMacro("__mc68030");
99     Builder.defineMacro("__mc68030__");
100     break;
101   case CK_68040:
102     Builder.defineMacro("mc68040");
103     Builder.defineMacro("__mc68040");
104     Builder.defineMacro("__mc68040__");
105     break;
106   case CK_68060:
107     Builder.defineMacro("mc68060");
108     Builder.defineMacro("__mc68060");
109     Builder.defineMacro("__mc68060__");
110     break;
111   default:
112     break;
113   }
114 }
115 
116 ArrayRef<Builtin::Info> M68kTargetInfo::getTargetBuiltins() const {
117   // FIXME: Implement.
118   return None;
119 }
120 
121 bool M68kTargetInfo::hasFeature(StringRef Feature) const {
122   // FIXME elaborate moar
123   return Feature == "M68000";
124 }
125 
126 const char *const M68kTargetInfo::GCCRegNames[] = {
127     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
128     "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
129     "pc"};
130 
131 ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const {
132   return llvm::makeArrayRef(GCCRegNames);
133 }
134 
135 ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const {
136   // No aliases.
137   return None;
138 }
139 
140 bool M68kTargetInfo::validateAsmConstraint(
141     const char *&Name, TargetInfo::ConstraintInfo &info) const {
142   switch (*Name) {
143   case 'a': // address register
144   case 'd': // data register
145   case 'f': // floating point register
146     info.setAllowsRegister();
147     return true;
148   case 'K': // the constant 1
149   case 'L': // constant -1^20 .. 1^19
150   case 'M': // constant 1-4:
151     return true;
152   }
153   // FIXME: Support all constraints like 'N', 'O', 'P', 'R'
154   return false;
155 }
156 
157 const char *M68kTargetInfo::getClobbers() const {
158   // FIXME: Is this really right?
159   return "";
160 }
161 
162 TargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const {
163   return TargetInfo::VoidPtrBuiltinVaList;
164 }
165 
166 } // namespace targets
167 } // namespace clang
168