258 lines · cpp
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-exception6//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 "llvm/ADT/StringRef.h"17#include "llvm/ADT/StringSwitch.h"18#include "llvm/TargetParser/TargetParser.h"19#include <cstdint>20#include <cstring>21#include <limits>22#include <optional>23 24namespace clang {25namespace targets {26 27M68kTargetInfo::M68kTargetInfo(const llvm::Triple &Triple,28 const TargetOptions &Opts)29 : TargetInfo(Triple), TargetOpts(Opts) {30 31 std::string Layout;32 33 // M68k is Big Endian34 Layout += "E";35 36 // FIXME how to wire it with the used object format?37 Layout += "-m:e";38 39 // M68k pointers are always 32 bit wide even for 16-bit CPUs40 Layout += "-p:32:16:32";41 42 // M68k integer data types43 Layout += "-i8:8:8-i16:16:16-i32:16:32";44 45 // FIXME no floats at the moment46 47 // The registers can hold 8, 16, 32 bits48 Layout += "-n8:16:32";49 50 // 16 bit alignment for both stack and aggregate51 // in order to conform to ABI used by GCC52 Layout += "-a:0:16-S16";53 54 resetDataLayout(Layout);55 56 SizeType = UnsignedInt;57 PtrDiffType = SignedInt;58 IntPtrType = SignedInt;59 IntAlign = LongAlign = PointerAlign = 16;60}61 62bool 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 76void M68kTargetInfo::getTargetDefines(const LangOptions &Opts,77 MacroBuilder &Builder) const {78 using llvm::Twine;79 80 Builder.defineMacro("__m68k__");81 82 DefineStd(Builder, "mc68000", Opts);83 84 // For sub-architecture85 switch (CPU) {86 case CK_68010:87 DefineStd(Builder, "mc68010", Opts);88 break;89 case CK_68020:90 DefineStd(Builder, "mc68020", Opts);91 break;92 case CK_68030:93 DefineStd(Builder, "mc68030", Opts);94 break;95 case CK_68040:96 DefineStd(Builder, "mc68040", Opts);97 break;98 case CK_68060:99 DefineStd(Builder, "mc68060", Opts);100 break;101 default:102 break;103 }104 105 if (CPU >= CK_68020) {106 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");107 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");108 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");109 }110 111 // Floating point112 if (TargetOpts.FeatureMap.lookup("isa-68881") ||113 TargetOpts.FeatureMap.lookup("isa-68882"))114 Builder.defineMacro("__HAVE_68881__");115}116 117llvm::SmallVector<Builtin::InfosShard>118M68kTargetInfo::getTargetBuiltins() const {119 // FIXME: Implement.120 return {};121}122 123bool M68kTargetInfo::hasFeature(StringRef Feature) const {124 // FIXME elaborate moar125 return Feature == "M68000";126}127 128const char *const M68kTargetInfo::GCCRegNames[] = {129 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",130 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",131 "pc"};132 133ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const {134 return llvm::ArrayRef(GCCRegNames);135}136 137const TargetInfo::GCCRegAlias M68kTargetInfo::GCCRegAliases[] = {138 {{"bp"}, "a5"},139 {{"fp"}, "a6"},140 {{"usp", "ssp", "isp", "a7"}, "sp"},141};142 143ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const {144 return llvm::ArrayRef(GCCRegAliases);145}146 147bool M68kTargetInfo::validateAsmConstraint(148 const char *&Name, TargetInfo::ConstraintInfo &info) const {149 switch (*Name) {150 case 'a': // address register151 case 'd': // data register152 info.setAllowsRegister();153 return true;154 case 'I': // constant integer in the range [1,8]155 info.setRequiresImmediate(1, 8);156 return true;157 case 'J': // constant signed 16-bit integer158 info.setRequiresImmediate(std::numeric_limits<int16_t>::min(),159 std::numeric_limits<int16_t>::max());160 return true;161 case 'K': // constant that is NOT in the range of [-0x80, 0x80)162 info.setRequiresImmediate();163 return true;164 case 'L': // constant integer in the range [-8,-1]165 info.setRequiresImmediate(-8, -1);166 return true;167 case 'M': // constant that is NOT in the range of [-0x100, 0x100]168 info.setRequiresImmediate();169 return true;170 case 'N': // constant integer in the range [24,31]171 info.setRequiresImmediate(24, 31);172 return true;173 case 'O': // constant integer 16174 info.setRequiresImmediate(16);175 return true;176 case 'P': // constant integer in the range [8,15]177 info.setRequiresImmediate(8, 15);178 return true;179 case 'C':180 ++Name;181 switch (*Name) {182 case '0': // constant integer 0183 info.setRequiresImmediate(0);184 return true;185 case 'i': // constant integer186 case 'j': // integer constant that doesn't fit in 16 bits187 info.setRequiresImmediate();188 return true;189 default:190 break;191 }192 break;193 case 'Q': // address register indirect addressing194 case 'U': // address register indirect w/ constant offset addressing195 // TODO: Handle 'S' (basically 'm' when pc-rel is enforced) when196 // '-mpcrel' flag is properly handled by the driver.197 info.setAllowsMemory();198 return true;199 default:200 break;201 }202 return false;203}204 205std::optional<std::string>206M68kTargetInfo::handleAsmEscapedChar(char EscChar) const {207 char C;208 switch (EscChar) {209 case '.':210 case '#':211 C = EscChar;212 break;213 case '/':214 C = '%';215 break;216 case '$':217 C = 's';218 break;219 case '&':220 C = 'd';221 break;222 default:223 return std::nullopt;224 }225 226 return std::string(1, C);227}228 229std::string M68kTargetInfo::convertConstraint(const char *&Constraint) const {230 if (*Constraint == 'C')231 // Two-character constraint; add "^" hint for later parsing232 return std::string("^") + std::string(Constraint++, 2);233 234 return std::string(1, *Constraint);235}236 237std::string_view M68kTargetInfo::getClobbers() const {238 // FIXME: Is this really right?239 return "";240}241 242TargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const {243 return TargetInfo::VoidPtrBuiltinVaList;244}245 246TargetInfo::CallingConvCheckResult247M68kTargetInfo::checkCallingConvention(CallingConv CC) const {248 switch (CC) {249 case CC_C:250 case CC_M68kRTD:251 return CCCR_OK;252 default:253 return TargetInfo::checkCallingConvention(CC);254 }255}256} // namespace targets257} // namespace clang258