forked from OSchip/llvm-project
237 lines
6.1 KiB
C++
237 lines
6.1 KiB
C++
//===--- M68k.cpp - Implement M68k targets feature support-------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements M68k TargetInfo objects.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#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 = "";
|
|
|
|
// M68k is Big Endian
|
|
Layout += "E";
|
|
|
|
// FIXME how to wire it with the used object format?
|
|
Layout += "-m:e";
|
|
|
|
// M68k pointers are always 32 bit wide even for 16 bit cpus
|
|
Layout += "-p:32:32";
|
|
|
|
// M68k integer data types
|
|
Layout += "-i8:8:8-i16:16:16-i32:16:32";
|
|
|
|
// FIXME no floats at the moment
|
|
|
|
// The registers can hold 8, 16, 32 bits
|
|
Layout += "-n8:16:32";
|
|
|
|
// 16 bit alignment for both stack and aggregate
|
|
// in order to conform to ABI used by GCC
|
|
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__");
|
|
|
|
// For sub-architecture
|
|
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 {
|
|
// FIXME: Implement.
|
|
return None;
|
|
}
|
|
|
|
bool M68kTargetInfo::hasFeature(StringRef Feature) const {
|
|
// FIXME elaborate moar
|
|
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 {
|
|
// No aliases.
|
|
return None;
|
|
}
|
|
|
|
bool M68kTargetInfo::validateAsmConstraint(
|
|
const char *&Name, TargetInfo::ConstraintInfo &info) const {
|
|
switch (*Name) {
|
|
case 'a': // address register
|
|
case 'd': // data register
|
|
info.setAllowsRegister();
|
|
return true;
|
|
case 'I': // constant integer in the range [1,8]
|
|
info.setRequiresImmediate(1, 8);
|
|
return true;
|
|
case 'J': // constant signed 16-bit integer
|
|
info.setRequiresImmediate(std::numeric_limits<int16_t>::min(),
|
|
std::numeric_limits<int16_t>::max());
|
|
return true;
|
|
case 'K': // constant that is NOT in the range of [-0x80, 0x80)
|
|
info.setRequiresImmediate();
|
|
return true;
|
|
case 'L': // constant integer in the range [-8,-1]
|
|
info.setRequiresImmediate(-8, -1);
|
|
return true;
|
|
case 'M': // constant that is NOT in the range of [-0x100, 0x100]
|
|
info.setRequiresImmediate();
|
|
return true;
|
|
case 'N': // constant integer in the range [24,31]
|
|
info.setRequiresImmediate(24, 31);
|
|
return true;
|
|
case 'O': // constant integer 16
|
|
info.setRequiresImmediate(16);
|
|
return true;
|
|
case 'P': // constant integer in the range [8,15]
|
|
info.setRequiresImmediate(8, 15);
|
|
return true;
|
|
case 'C':
|
|
++Name;
|
|
switch (*Name) {
|
|
case '0': // constant integer 0
|
|
info.setRequiresImmediate(0);
|
|
return true;
|
|
case 'i': // constant integer
|
|
case 'j': // integer constant that doesn't fit in 16 bits
|
|
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')
|
|
// Two-character constraint; add "^" hint for later parsing
|
|
return std::string("^") + std::string(Constraint++, 2);
|
|
|
|
return std::string(1, *Constraint);
|
|
}
|
|
|
|
const char *M68kTargetInfo::getClobbers() const {
|
|
// FIXME: Is this really right?
|
|
return "";
|
|
}
|
|
|
|
TargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const {
|
|
return TargetInfo::VoidPtrBuiltinVaList;
|
|
}
|
|
|
|
} // namespace targets
|
|
} // namespace clang
|