M68k.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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. #include "M68k.h"
  13. #include "clang/Basic/Builtins.h"
  14. #include "clang/Basic/Diagnostic.h"
  15. #include "clang/Basic/TargetBuiltins.h"
  16. #include "llvm/ADT/StringExtras.h"
  17. #include "llvm/ADT/StringRef.h"
  18. #include "llvm/ADT/StringSwitch.h"
  19. #include "llvm/Support/TargetParser.h"
  20. #include <cstdint>
  21. #include <cstring>
  22. #include <limits>
  23. #include <optional>
  24. namespace clang {
  25. namespace targets {
  26. M68kTargetInfo::M68kTargetInfo(const llvm::Triple &Triple,
  27. const TargetOptions &)
  28. : TargetInfo(Triple) {
  29. std::string Layout;
  30. // M68k is Big Endian
  31. Layout += "E";
  32. // FIXME how to wire it with the used object format?
  33. Layout += "-m:e";
  34. // M68k pointers are always 32 bit wide even for 16-bit CPUs
  35. Layout += "-p:32:16:32";
  36. // M68k integer data types
  37. Layout += "-i8:8:8-i16:16:16-i32:16:32";
  38. // FIXME no floats at the moment
  39. // The registers can hold 8, 16, 32 bits
  40. Layout += "-n8:16:32";
  41. // 16 bit alignment for both stack and aggregate
  42. // in order to conform to ABI used by GCC
  43. Layout += "-a:0:16-S16";
  44. resetDataLayout(Layout);
  45. SizeType = UnsignedInt;
  46. PtrDiffType = SignedInt;
  47. IntPtrType = SignedInt;
  48. }
  49. bool M68kTargetInfo::setCPU(const std::string &Name) {
  50. StringRef N = Name;
  51. CPU = llvm::StringSwitch<CPUKind>(N)
  52. .Case("generic", CK_68000)
  53. .Case("M68000", CK_68000)
  54. .Case("M68010", CK_68010)
  55. .Case("M68020", CK_68020)
  56. .Case("M68030", CK_68030)
  57. .Case("M68040", CK_68040)
  58. .Case("M68060", CK_68060)
  59. .Default(CK_Unknown);
  60. return CPU != CK_Unknown;
  61. }
  62. void M68kTargetInfo::getTargetDefines(const LangOptions &Opts,
  63. MacroBuilder &Builder) const {
  64. using llvm::Twine;
  65. Builder.defineMacro("__m68k__");
  66. Builder.defineMacro("mc68000");
  67. Builder.defineMacro("__mc68000");
  68. Builder.defineMacro("__mc68000__");
  69. // For sub-architecture
  70. switch (CPU) {
  71. case CK_68010:
  72. Builder.defineMacro("mc68010");
  73. Builder.defineMacro("__mc68010");
  74. Builder.defineMacro("__mc68010__");
  75. break;
  76. case CK_68020:
  77. Builder.defineMacro("mc68020");
  78. Builder.defineMacro("__mc68020");
  79. Builder.defineMacro("__mc68020__");
  80. break;
  81. case CK_68030:
  82. Builder.defineMacro("mc68030");
  83. Builder.defineMacro("__mc68030");
  84. Builder.defineMacro("__mc68030__");
  85. break;
  86. case CK_68040:
  87. Builder.defineMacro("mc68040");
  88. Builder.defineMacro("__mc68040");
  89. Builder.defineMacro("__mc68040__");
  90. break;
  91. case CK_68060:
  92. Builder.defineMacro("mc68060");
  93. Builder.defineMacro("__mc68060");
  94. Builder.defineMacro("__mc68060__");
  95. break;
  96. default:
  97. break;
  98. }
  99. if (CPU >= CK_68020) {
  100. Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
  101. Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
  102. Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
  103. }
  104. }
  105. ArrayRef<Builtin::Info> M68kTargetInfo::getTargetBuiltins() const {
  106. // FIXME: Implement.
  107. return std::nullopt;
  108. }
  109. bool M68kTargetInfo::hasFeature(StringRef Feature) const {
  110. // FIXME elaborate moar
  111. return Feature == "M68000";
  112. }
  113. const char *const M68kTargetInfo::GCCRegNames[] = {
  114. "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
  115. "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
  116. "pc"};
  117. ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const {
  118. return llvm::ArrayRef(GCCRegNames);
  119. }
  120. ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const {
  121. // No aliases.
  122. return std::nullopt;
  123. }
  124. bool M68kTargetInfo::validateAsmConstraint(
  125. const char *&Name, TargetInfo::ConstraintInfo &info) const {
  126. switch (*Name) {
  127. case 'a': // address register
  128. case 'd': // data register
  129. info.setAllowsRegister();
  130. return true;
  131. case 'I': // constant integer in the range [1,8]
  132. info.setRequiresImmediate(1, 8);
  133. return true;
  134. case 'J': // constant signed 16-bit integer
  135. info.setRequiresImmediate(std::numeric_limits<int16_t>::min(),
  136. std::numeric_limits<int16_t>::max());
  137. return true;
  138. case 'K': // constant that is NOT in the range of [-0x80, 0x80)
  139. info.setRequiresImmediate();
  140. return true;
  141. case 'L': // constant integer in the range [-8,-1]
  142. info.setRequiresImmediate(-8, -1);
  143. return true;
  144. case 'M': // constant that is NOT in the range of [-0x100, 0x100]
  145. info.setRequiresImmediate();
  146. return true;
  147. case 'N': // constant integer in the range [24,31]
  148. info.setRequiresImmediate(24, 31);
  149. return true;
  150. case 'O': // constant integer 16
  151. info.setRequiresImmediate(16);
  152. return true;
  153. case 'P': // constant integer in the range [8,15]
  154. info.setRequiresImmediate(8, 15);
  155. return true;
  156. case 'C':
  157. ++Name;
  158. switch (*Name) {
  159. case '0': // constant integer 0
  160. info.setRequiresImmediate(0);
  161. return true;
  162. case 'i': // constant integer
  163. case 'j': // integer constant that doesn't fit in 16 bits
  164. info.setRequiresImmediate();
  165. return true;
  166. default:
  167. break;
  168. }
  169. break;
  170. default:
  171. break;
  172. }
  173. return false;
  174. }
  175. std::optional<std::string>
  176. M68kTargetInfo::handleAsmEscapedChar(char EscChar) const {
  177. char C;
  178. switch (EscChar) {
  179. case '.':
  180. case '#':
  181. C = EscChar;
  182. break;
  183. case '/':
  184. C = '%';
  185. break;
  186. case '$':
  187. C = 's';
  188. break;
  189. case '&':
  190. C = 'd';
  191. break;
  192. default:
  193. return std::nullopt;
  194. }
  195. return std::string(1, C);
  196. }
  197. std::string M68kTargetInfo::convertConstraint(const char *&Constraint) const {
  198. if (*Constraint == 'C')
  199. // Two-character constraint; add "^" hint for later parsing
  200. return std::string("^") + std::string(Constraint++, 2);
  201. return std::string(1, *Constraint);
  202. }
  203. const char *M68kTargetInfo::getClobbers() const {
  204. // FIXME: Is this really right?
  205. return "";
  206. }
  207. TargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const {
  208. return TargetInfo::VoidPtrBuiltinVaList;
  209. }
  210. } // namespace targets
  211. } // namespace clang