Mips.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. //===--- Mips.h - Declare Mips target feature support -----------*- C++ -*-===//
  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 declares Mips TargetInfo objects.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H
  13. #define LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H
  14. #include "clang/Basic/TargetInfo.h"
  15. #include "clang/Basic/TargetOptions.h"
  16. #include "llvm/ADT/Triple.h"
  17. #include "llvm/Support/Compiler.h"
  18. namespace clang {
  19. namespace targets {
  20. class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
  21. void setDataLayout() {
  22. StringRef Layout;
  23. if (ABI == "o32")
  24. Layout = "m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64";
  25. else if (ABI == "n32")
  26. Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128";
  27. else if (ABI == "n64")
  28. Layout = "m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128";
  29. else
  30. llvm_unreachable("Invalid ABI");
  31. if (BigEndian)
  32. resetDataLayout(("E-" + Layout).str());
  33. else
  34. resetDataLayout(("e-" + Layout).str());
  35. }
  36. static const Builtin::Info BuiltinInfo[];
  37. std::string CPU;
  38. bool IsMips16;
  39. bool IsMicromips;
  40. bool IsNan2008;
  41. bool IsAbs2008;
  42. bool IsSingleFloat;
  43. bool IsNoABICalls;
  44. bool CanUseBSDABICalls;
  45. enum MipsFloatABI { HardFloat, SoftFloat } FloatABI;
  46. enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev;
  47. bool HasMSA;
  48. bool DisableMadd4;
  49. bool UseIndirectJumpHazard;
  50. protected:
  51. enum FPModeEnum { FPXX, FP32, FP64 } FPMode;
  52. std::string ABI;
  53. public:
  54. MipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
  55. : TargetInfo(Triple), IsMips16(false), IsMicromips(false),
  56. IsNan2008(false), IsAbs2008(false), IsSingleFloat(false),
  57. IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat),
  58. DspRev(NoDSP), HasMSA(false), DisableMadd4(false),
  59. UseIndirectJumpHazard(false), FPMode(FPXX) {
  60. TheCXXABI.set(TargetCXXABI::GenericMIPS);
  61. if (Triple.isMIPS32())
  62. setABI("o32");
  63. else if (Triple.getEnvironment() == llvm::Triple::GNUABIN32)
  64. setABI("n32");
  65. else
  66. setABI("n64");
  67. CPU = ABI == "o32" ? "mips32r2" : "mips64r2";
  68. CanUseBSDABICalls = Triple.isOSFreeBSD() ||
  69. Triple.isOSOpenBSD();
  70. }
  71. bool isIEEE754_2008Default() const {
  72. return CPU == "mips32r6" || CPU == "mips64r6";
  73. }
  74. bool isFP64Default() const {
  75. return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64";
  76. }
  77. bool isNan2008() const override { return IsNan2008; }
  78. bool processorSupportsGPR64() const;
  79. StringRef getABI() const override { return ABI; }
  80. bool setABI(const std::string &Name) override {
  81. if (Name == "o32") {
  82. setO32ABITypes();
  83. ABI = Name;
  84. return true;
  85. }
  86. if (Name == "n32") {
  87. setN32ABITypes();
  88. ABI = Name;
  89. return true;
  90. }
  91. if (Name == "n64") {
  92. setN64ABITypes();
  93. ABI = Name;
  94. return true;
  95. }
  96. return false;
  97. }
  98. void setO32ABITypes() {
  99. Int64Type = SignedLongLong;
  100. IntMaxType = Int64Type;
  101. LongDoubleFormat = &llvm::APFloat::IEEEdouble();
  102. LongDoubleWidth = LongDoubleAlign = 64;
  103. LongWidth = LongAlign = 32;
  104. MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
  105. PointerWidth = PointerAlign = 32;
  106. PtrDiffType = SignedInt;
  107. SizeType = UnsignedInt;
  108. SuitableAlign = 64;
  109. }
  110. void setN32N64ABITypes() {
  111. LongDoubleWidth = LongDoubleAlign = 128;
  112. LongDoubleFormat = &llvm::APFloat::IEEEquad();
  113. if (getTriple().isOSFreeBSD()) {
  114. LongDoubleWidth = LongDoubleAlign = 64;
  115. LongDoubleFormat = &llvm::APFloat::IEEEdouble();
  116. }
  117. MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
  118. SuitableAlign = 128;
  119. }
  120. void setN64ABITypes() {
  121. setN32N64ABITypes();
  122. if (getTriple().isOSOpenBSD()) {
  123. Int64Type = SignedLongLong;
  124. } else {
  125. Int64Type = SignedLong;
  126. }
  127. IntMaxType = Int64Type;
  128. LongWidth = LongAlign = 64;
  129. PointerWidth = PointerAlign = 64;
  130. PtrDiffType = SignedLong;
  131. SizeType = UnsignedLong;
  132. }
  133. void setN32ABITypes() {
  134. setN32N64ABITypes();
  135. Int64Type = SignedLongLong;
  136. IntMaxType = Int64Type;
  137. LongWidth = LongAlign = 32;
  138. PointerWidth = PointerAlign = 32;
  139. PtrDiffType = SignedInt;
  140. SizeType = UnsignedInt;
  141. }
  142. bool isValidCPUName(StringRef Name) const override;
  143. void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
  144. bool setCPU(const std::string &Name) override {
  145. CPU = Name;
  146. return isValidCPUName(Name);
  147. }
  148. const std::string &getCPU() const { return CPU; }
  149. bool
  150. initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
  151. StringRef CPU,
  152. const std::vector<std::string> &FeaturesVec) const override {
  153. if (CPU.empty())
  154. CPU = getCPU();
  155. if (CPU == "octeon")
  156. Features["mips64r2"] = Features["cnmips"] = true;
  157. else if (CPU == "octeon+")
  158. Features["mips64r2"] = Features["cnmips"] = Features["cnmipsp"] = true;
  159. else
  160. Features[CPU] = true;
  161. return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
  162. }
  163. unsigned getISARev() const;
  164. void getTargetDefines(const LangOptions &Opts,
  165. MacroBuilder &Builder) const override;
  166. ArrayRef<Builtin::Info> getTargetBuiltins() const override;
  167. bool hasFeature(StringRef Feature) const override;
  168. BuiltinVaListKind getBuiltinVaListKind() const override {
  169. return TargetInfo::VoidPtrBuiltinVaList;
  170. }
  171. ArrayRef<const char *> getGCCRegNames() const override {
  172. static const char *const GCCRegNames[] = {
  173. // CPU register names
  174. // Must match second column of GCCRegAliases
  175. "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10",
  176. "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20",
  177. "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30",
  178. "$31",
  179. // Floating point register names
  180. "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9",
  181. "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18",
  182. "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",
  183. "$f28", "$f29", "$f30", "$f31",
  184. // Hi/lo and condition register names
  185. "hi", "lo", "", "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5",
  186. "$fcc6", "$fcc7", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi",
  187. "$ac3lo",
  188. // MSA register names
  189. "$w0", "$w1", "$w2", "$w3", "$w4", "$w5", "$w6", "$w7", "$w8", "$w9",
  190. "$w10", "$w11", "$w12", "$w13", "$w14", "$w15", "$w16", "$w17", "$w18",
  191. "$w19", "$w20", "$w21", "$w22", "$w23", "$w24", "$w25", "$w26", "$w27",
  192. "$w28", "$w29", "$w30", "$w31",
  193. // MSA control register names
  194. "$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify",
  195. "$msarequest", "$msamap", "$msaunmap"
  196. };
  197. return llvm::makeArrayRef(GCCRegNames);
  198. }
  199. bool validateAsmConstraint(const char *&Name,
  200. TargetInfo::ConstraintInfo &Info) const override {
  201. switch (*Name) {
  202. default:
  203. return false;
  204. case 'r': // CPU registers.
  205. case 'd': // Equivalent to "r" unless generating MIPS16 code.
  206. case 'y': // Equivalent to "r", backward compatibility only.
  207. case 'f': // floating-point registers.
  208. case 'c': // $25 for indirect jumps
  209. case 'l': // lo register
  210. case 'x': // hilo register pair
  211. Info.setAllowsRegister();
  212. return true;
  213. case 'I': // Signed 16-bit constant
  214. case 'J': // Integer 0
  215. case 'K': // Unsigned 16-bit constant
  216. case 'L': // Signed 32-bit constant, lower 16-bit zeros (for lui)
  217. case 'M': // Constants not loadable via lui, addiu, or ori
  218. case 'N': // Constant -1 to -65535
  219. case 'O': // A signed 15-bit constant
  220. case 'P': // A constant between 1 go 65535
  221. return true;
  222. case 'R': // An address that can be used in a non-macro load or store
  223. Info.setAllowsMemory();
  224. return true;
  225. case 'Z':
  226. if (Name[1] == 'C') { // An address usable by ll, and sc.
  227. Info.setAllowsMemory();
  228. Name++; // Skip over 'Z'.
  229. return true;
  230. }
  231. return false;
  232. }
  233. }
  234. std::string convertConstraint(const char *&Constraint) const override {
  235. std::string R;
  236. switch (*Constraint) {
  237. case 'Z': // Two-character constraint; add "^" hint for later parsing.
  238. if (Constraint[1] == 'C') {
  239. R = std::string("^") + std::string(Constraint, 2);
  240. Constraint++;
  241. return R;
  242. }
  243. break;
  244. }
  245. return TargetInfo::convertConstraint(Constraint);
  246. }
  247. const char *getClobbers() const override {
  248. // In GCC, $1 is not widely used in generated code (it's used only in a few
  249. // specific situations), so there is no real need for users to add it to
  250. // the clobbers list if they want to use it in their inline assembly code.
  251. //
  252. // In LLVM, $1 is treated as a normal GPR and is always allocatable during
  253. // code generation, so using it in inline assembly without adding it to the
  254. // clobbers list can cause conflicts between the inline assembly code and
  255. // the surrounding generated code.
  256. //
  257. // Another problem is that LLVM is allowed to choose $1 for inline assembly
  258. // operands, which will conflict with the ".set at" assembler option (which
  259. // we use only for inline assembly, in order to maintain compatibility with
  260. // GCC) and will also conflict with the user's usage of $1.
  261. //
  262. // The easiest way to avoid these conflicts and keep $1 as an allocatable
  263. // register for generated code is to automatically clobber $1 for all inline
  264. // assembly code.
  265. //
  266. // FIXME: We should automatically clobber $1 only for inline assembly code
  267. // which actually uses it. This would allow LLVM to use $1 for inline
  268. // assembly operands if the user's assembly code doesn't use it.
  269. return "~{$1}";
  270. }
  271. bool handleTargetFeatures(std::vector<std::string> &Features,
  272. DiagnosticsEngine &Diags) override {
  273. IsMips16 = false;
  274. IsMicromips = false;
  275. IsNan2008 = isIEEE754_2008Default();
  276. IsAbs2008 = isIEEE754_2008Default();
  277. IsSingleFloat = false;
  278. FloatABI = HardFloat;
  279. DspRev = NoDSP;
  280. FPMode = isFP64Default() ? FP64 : FPXX;
  281. for (const auto &Feature : Features) {
  282. if (Feature == "+single-float")
  283. IsSingleFloat = true;
  284. else if (Feature == "+soft-float")
  285. FloatABI = SoftFloat;
  286. else if (Feature == "+mips16")
  287. IsMips16 = true;
  288. else if (Feature == "+micromips")
  289. IsMicromips = true;
  290. else if (Feature == "+dsp")
  291. DspRev = std::max(DspRev, DSP1);
  292. else if (Feature == "+dspr2")
  293. DspRev = std::max(DspRev, DSP2);
  294. else if (Feature == "+msa")
  295. HasMSA = true;
  296. else if (Feature == "+nomadd4")
  297. DisableMadd4 = true;
  298. else if (Feature == "+fp64")
  299. FPMode = FP64;
  300. else if (Feature == "-fp64")
  301. FPMode = FP32;
  302. else if (Feature == "+fpxx")
  303. FPMode = FPXX;
  304. else if (Feature == "+nan2008")
  305. IsNan2008 = true;
  306. else if (Feature == "-nan2008")
  307. IsNan2008 = false;
  308. else if (Feature == "+abs2008")
  309. IsAbs2008 = true;
  310. else if (Feature == "-abs2008")
  311. IsAbs2008 = false;
  312. else if (Feature == "+noabicalls")
  313. IsNoABICalls = true;
  314. else if (Feature == "+use-indirect-jump-hazard")
  315. UseIndirectJumpHazard = true;
  316. }
  317. setDataLayout();
  318. return true;
  319. }
  320. int getEHDataRegisterNumber(unsigned RegNo) const override {
  321. if (RegNo == 0)
  322. return 4;
  323. if (RegNo == 1)
  324. return 5;
  325. return -1;
  326. }
  327. bool isCLZForZeroUndef() const override { return false; }
  328. ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
  329. static const TargetInfo::GCCRegAlias O32RegAliases[] = {
  330. {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"},
  331. {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"},
  332. {{"a3"}, "$7"}, {{"t0"}, "$8"}, {{"t1"}, "$9"},
  333. {{"t2"}, "$10"}, {{"t3"}, "$11"}, {{"t4"}, "$12"},
  334. {{"t5"}, "$13"}, {{"t6"}, "$14"}, {{"t7"}, "$15"},
  335. {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"},
  336. {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"},
  337. {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"},
  338. {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"},
  339. {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},
  340. {{"ra"}, "$31"}
  341. };
  342. static const TargetInfo::GCCRegAlias NewABIRegAliases[] = {
  343. {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"},
  344. {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"},
  345. {{"a3"}, "$7"}, {{"a4"}, "$8"}, {{"a5"}, "$9"},
  346. {{"a6"}, "$10"}, {{"a7"}, "$11"}, {{"t0"}, "$12"},
  347. {{"t1"}, "$13"}, {{"t2"}, "$14"}, {{"t3"}, "$15"},
  348. {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"},
  349. {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"},
  350. {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"},
  351. {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"},
  352. {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},
  353. {{"ra"}, "$31"}
  354. };
  355. if (ABI == "o32")
  356. return llvm::makeArrayRef(O32RegAliases);
  357. return llvm::makeArrayRef(NewABIRegAliases);
  358. }
  359. bool hasInt128Type() const override {
  360. return (ABI == "n32" || ABI == "n64") || getTargetOpts().ForceEnableInt128;
  361. }
  362. unsigned getUnwindWordWidth() const override;
  363. bool validateTarget(DiagnosticsEngine &Diags) const override;
  364. bool hasBitIntType() const override { return true; }
  365. };
  366. } // namespace targets
  367. } // namespace clang
  368. #endif // LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H