Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/Basic/Targets/M68k.cpp
Line
Count
Source (jump to first uncovered line)
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
0
    : TargetInfo(Triple), TargetOpts(Opts) {
32
33
0
  std::string Layout;
34
35
  // M68k is Big Endian
36
0
  Layout += "E";
37
38
  // FIXME how to wire it with the used object format?
39
0
  Layout += "-m:e";
40
41
  // M68k pointers are always 32 bit wide even for 16-bit CPUs
42
0
  Layout += "-p:32:16:32";
43
44
  // M68k integer data types
45
0
  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
0
  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
0
  Layout += "-a:0:16-S16";
55
56
0
  resetDataLayout(Layout);
57
58
0
  SizeType = UnsignedInt;
59
0
  PtrDiffType = SignedInt;
60
0
  IntPtrType = SignedInt;
61
0
}
62
63
0
bool M68kTargetInfo::setCPU(const std::string &Name) {
64
0
  StringRef N = Name;
65
0
  CPU = llvm::StringSwitch<CPUKind>(N)
66
0
            .Case("generic", CK_68000)
67
0
            .Case("M68000", CK_68000)
68
0
            .Case("M68010", CK_68010)
69
0
            .Case("M68020", CK_68020)
70
0
            .Case("M68030", CK_68030)
71
0
            .Case("M68040", CK_68040)
72
0
            .Case("M68060", CK_68060)
73
0
            .Default(CK_Unknown);
74
0
  return CPU != CK_Unknown;
75
0
}
76
77
void M68kTargetInfo::getTargetDefines(const LangOptions &Opts,
78
0
                                      MacroBuilder &Builder) const {
79
0
  using llvm::Twine;
80
81
0
  Builder.defineMacro("__m68k__");
82
83
0
  DefineStd(Builder, "mc68000", Opts);
84
85
  // For sub-architecture
86
0
  switch (CPU) {
87
0
  case CK_68010:
88
0
    DefineStd(Builder, "mc68010", Opts);
89
0
    break;
90
0
  case CK_68020:
91
0
    DefineStd(Builder, "mc68020", Opts);
92
0
    break;
93
0
  case CK_68030:
94
0
    DefineStd(Builder, "mc68030", Opts);
95
0
    break;
96
0
  case CK_68040:
97
0
    DefineStd(Builder, "mc68040", Opts);
98
0
    break;
99
0
  case CK_68060:
100
0
    DefineStd(Builder, "mc68060", Opts);
101
0
    break;
102
0
  default:
103
0
    break;
104
0
  }
105
106
0
  if (CPU >= CK_68020) {
107
0
    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
108
0
    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
109
0
    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
110
0
  }
111
112
  // Floating point
113
0
  if (TargetOpts.FeatureMap.lookup("isa-68881") ||
114
0
      TargetOpts.FeatureMap.lookup("isa-68882"))
115
0
    Builder.defineMacro("__HAVE_68881__");
116
0
}
117
118
0
ArrayRef<Builtin::Info> M68kTargetInfo::getTargetBuiltins() const {
119
  // FIXME: Implement.
120
0
  return std::nullopt;
121
0
}
122
123
0
bool M68kTargetInfo::hasFeature(StringRef Feature) const {
124
  // FIXME elaborate moar
125
0
  return Feature == "M68000";
126
0
}
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
0
ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const {
134
0
  return llvm::ArrayRef(GCCRegNames);
135
0
}
136
137
0
ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const {
138
  // No aliases.
139
0
  return std::nullopt;
140
0
}
141
142
bool M68kTargetInfo::validateAsmConstraint(
143
0
    const char *&Name, TargetInfo::ConstraintInfo &info) const {
144
0
  switch (*Name) {
145
0
  case 'a': // address register
146
0
  case 'd': // data register
147
0
    info.setAllowsRegister();
148
0
    return true;
149
0
  case 'I': // constant integer in the range [1,8]
150
0
    info.setRequiresImmediate(1, 8);
151
0
    return true;
152
0
  case 'J': // constant signed 16-bit integer
153
0
    info.setRequiresImmediate(std::numeric_limits<int16_t>::min(),
154
0
                              std::numeric_limits<int16_t>::max());
155
0
    return true;
156
0
  case 'K': // constant that is NOT in the range of [-0x80, 0x80)
157
0
    info.setRequiresImmediate();
158
0
    return true;
159
0
  case 'L': // constant integer in the range [-8,-1]
160
0
    info.setRequiresImmediate(-8, -1);
161
0
    return true;
162
0
  case 'M': // constant that is NOT in the range of [-0x100, 0x100]
163
0
    info.setRequiresImmediate();
164
0
    return true;
165
0
  case 'N': // constant integer in the range [24,31]
166
0
    info.setRequiresImmediate(24, 31);
167
0
    return true;
168
0
  case 'O': // constant integer 16
169
0
    info.setRequiresImmediate(16);
170
0
    return true;
171
0
  case 'P': // constant integer in the range [8,15]
172
0
    info.setRequiresImmediate(8, 15);
173
0
    return true;
174
0
  case 'C':
175
0
    ++Name;
176
0
    switch (*Name) {
177
0
    case '0': // constant integer 0
178
0
      info.setRequiresImmediate(0);
179
0
      return true;
180
0
    case 'i': // constant integer
181
0
    case 'j': // integer constant that doesn't fit in 16 bits
182
0
      info.setRequiresImmediate();
183
0
      return true;
184
0
    default:
185
0
      break;
186
0
    }
187
0
    break;
188
0
  case 'Q': // address register indirect addressing
189
0
  case 'U': // address register indirect w/ constant offset addressing
190
    // TODO: Handle 'S' (basically 'm' when pc-rel is enforced) when
191
    // '-mpcrel' flag is properly handled by the driver.
192
0
    info.setAllowsMemory();
193
0
    return true;
194
0
  default:
195
0
    break;
196
0
  }
197
0
  return false;
198
0
}
199
200
std::optional<std::string>
201
0
M68kTargetInfo::handleAsmEscapedChar(char EscChar) const {
202
0
  char C;
203
0
  switch (EscChar) {
204
0
  case '.':
205
0
  case '#':
206
0
    C = EscChar;
207
0
    break;
208
0
  case '/':
209
0
    C = '%';
210
0
    break;
211
0
  case '$':
212
0
    C = 's';
213
0
    break;
214
0
  case '&':
215
0
    C = 'd';
216
0
    break;
217
0
  default:
218
0
    return std::nullopt;
219
0
  }
220
221
0
  return std::string(1, C);
222
0
}
223
224
0
std::string M68kTargetInfo::convertConstraint(const char *&Constraint) const {
225
0
  if (*Constraint == 'C')
226
    // Two-character constraint; add "^" hint for later parsing
227
0
    return std::string("^") + std::string(Constraint++, 2);
228
229
0
  return std::string(1, *Constraint);
230
0
}
231
232
0
std::string_view M68kTargetInfo::getClobbers() const {
233
  // FIXME: Is this really right?
234
0
  return "";
235
0
}
236
237
0
TargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const {
238
0
  return TargetInfo::VoidPtrBuiltinVaList;
239
0
}
240
241
TargetInfo::CallingConvCheckResult
242
0
M68kTargetInfo::checkCallingConvention(CallingConv CC) const {
243
0
  switch (CC) {
244
0
  case CC_C:
245
0
  case CC_M68kRTD:
246
0
    return CCCR_OK;
247
0
  default:
248
0
    return TargetInfo::checkCallingConvention(CC);
249
0
  }
250
0
}
251
} // namespace targets
252
} // namespace clang