#include "M68k.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/TargetParser.h"
#include <cstdint>
#include <cstring>
#include <limits>
namespace clang {
namespace targets {
M68kTargetInfo::M68kTargetInfo(const llvm::Triple &Triple,
const TargetOptions &)
: TargetInfo(Triple) {
std::string Layout;
Layout += "E";
Layout += "-m:e";
Layout += "-p:32:16:32";
Layout += "-i8:8:8-i16:16:16-i32:16:32";
Layout += "-n8:16:32";
Layout += "-a:0:16-S16";
resetDataLayout(Layout);
SizeType = UnsignedInt;
PtrDiffType = SignedInt;
IntPtrType = SignedInt;
}
bool M68kTargetInfo::setCPU(const std::string &Name) {
StringRef N = Name;
CPU = llvm::StringSwitch<CPUKind>(N)
.Case("generic", CK_68000)
.Case("M68000", CK_68000)
.Case("M68010", CK_68010)
.Case("M68020", CK_68020)
.Case("M68030", CK_68030)
.Case("M68040", CK_68040)
.Case("M68060", CK_68060)
.Default(CK_Unknown);
return CPU != CK_Unknown;
}
void M68kTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
using llvm::Twine;
Builder.defineMacro("__m68k__");
Builder.defineMacro("mc68000");
Builder.defineMacro("__mc68000");
Builder.defineMacro("__mc68000__");
switch (CPU) {
case CK_68010:
Builder.defineMacro("mc68010");
Builder.defineMacro("__mc68010");
Builder.defineMacro("__mc68010__");
break;
case CK_68020:
Builder.defineMacro("mc68020");
Builder.defineMacro("__mc68020");
Builder.defineMacro("__mc68020__");
break;
case CK_68030:
Builder.defineMacro("mc68030");
Builder.defineMacro("__mc68030");
Builder.defineMacro("__mc68030__");
break;
case CK_68040:
Builder.defineMacro("mc68040");
Builder.defineMacro("__mc68040");
Builder.defineMacro("__mc68040__");
break;
case CK_68060:
Builder.defineMacro("mc68060");
Builder.defineMacro("__mc68060");
Builder.defineMacro("__mc68060__");
break;
default:
break;
}
}
ArrayRef<Builtin::Info> M68kTargetInfo::getTargetBuiltins() const {
return None;
}
bool M68kTargetInfo::hasFeature(StringRef Feature) const {
return Feature == "M68000";
}
const char *const M68kTargetInfo::GCCRegNames[] = {
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
"pc"};
ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}
ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const {
return None;
}
bool M68kTargetInfo::validateAsmConstraint(
const char *&Name, TargetInfo::ConstraintInfo &info) const {
switch (*Name) {
case 'a': case 'd': info.setAllowsRegister();
return true;
case 'I': info.setRequiresImmediate(1, 8);
return true;
case 'J': info.setRequiresImmediate(std::numeric_limits<int16_t>::min(),
std::numeric_limits<int16_t>::max());
return true;
case 'K': info.setRequiresImmediate();
return true;
case 'L': info.setRequiresImmediate(-8, -1);
return true;
case 'M': info.setRequiresImmediate();
return true;
case 'N': info.setRequiresImmediate(24, 31);
return true;
case 'O': info.setRequiresImmediate(16);
return true;
case 'P': info.setRequiresImmediate(8, 15);
return true;
case 'C':
++Name;
switch (*Name) {
case '0': info.setRequiresImmediate(0);
return true;
case 'i': case 'j': info.setRequiresImmediate();
return true;
default:
break;
}
break;
default:
break;
}
return false;
}
llvm::Optional<std::string>
M68kTargetInfo::handleAsmEscapedChar(char EscChar) const {
char C;
switch (EscChar) {
case '.':
case '#':
C = EscChar;
break;
case '/':
C = '%';
break;
case '$':
C = 's';
break;
case '&':
C = 'd';
break;
default:
return llvm::None;
}
return std::string(1, C);
}
std::string M68kTargetInfo::convertConstraint(const char *&Constraint) const {
if (*Constraint == 'C')
return std::string("^") + std::string(Constraint++, 2);
return std::string(1, *Constraint);
}
const char *M68kTargetInfo::getClobbers() const {
return "";
}
TargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const {
return TargetInfo::VoidPtrBuiltinVaList;
}
} }