| 1 | //===--- Sparc.cpp - Implement Sparc target 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 Sparc TargetInfo objects. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "Sparc.h" |
| 14 | #include "Targets.h" |
| 15 | #include "clang/Basic/MacroBuilder.h" |
| 16 | #include "llvm/ADT/StringSwitch.h" |
| 17 | |
| 18 | using namespace clang; |
| 19 | using namespace clang::targets; |
| 20 | |
| 21 | const char *const SparcTargetInfo::GCCRegNames[] = { |
| 22 | // Integer registers |
| 23 | "r0" , "r1" , "r2" , "r3" , "r4" , "r5" , "r6" , "r7" , "r8" , "r9" , "r10" , |
| 24 | "r11" , "r12" , "r13" , "r14" , "r15" , "r16" , "r17" , "r18" , "r19" , "r20" , "r21" , |
| 25 | "r22" , "r23" , "r24" , "r25" , "r26" , "r27" , "r28" , "r29" , "r30" , "r31" , |
| 26 | |
| 27 | // Floating-point registers |
| 28 | "f0" , "f1" , "f2" , "f3" , "f4" , "f5" , "f6" , "f7" , "f8" , "f9" , "f10" , |
| 29 | "f11" , "f12" , "f13" , "f14" , "f15" , "f16" , "f17" , "f18" , "f19" , "f20" , "f21" , |
| 30 | "f22" , "f23" , "f24" , "f25" , "f26" , "f27" , "f28" , "f29" , "f30" , "f31" , "f32" , |
| 31 | "f34" , "f36" , "f38" , "f40" , "f42" , "f44" , "f46" , "f48" , "f50" , "f52" , "f54" , |
| 32 | "f56" , "f58" , "f60" , "f62" , |
| 33 | }; |
| 34 | |
| 35 | ArrayRef<const char *> SparcTargetInfo::getGCCRegNames() const { |
| 36 | return llvm::ArrayRef(GCCRegNames); |
| 37 | } |
| 38 | |
| 39 | const TargetInfo::GCCRegAlias SparcTargetInfo::GCCRegAliases[] = { |
| 40 | {.Aliases: {"g0" }, .Register: "r0" }, {.Aliases: {"g1" }, .Register: "r1" }, {.Aliases: {"g2" }, .Register: "r2" }, {.Aliases: {"g3" }, .Register: "r3" }, |
| 41 | {.Aliases: {"g4" }, .Register: "r4" }, {.Aliases: {"g5" }, .Register: "r5" }, {.Aliases: {"g6" }, .Register: "r6" }, {.Aliases: {"g7" }, .Register: "r7" }, |
| 42 | {.Aliases: {"o0" }, .Register: "r8" }, {.Aliases: {"o1" }, .Register: "r9" }, {.Aliases: {"o2" }, .Register: "r10" }, {.Aliases: {"o3" }, .Register: "r11" }, |
| 43 | {.Aliases: {"o4" }, .Register: "r12" }, {.Aliases: {"o5" }, .Register: "r13" }, {.Aliases: {"o6" , "sp" }, .Register: "r14" }, {.Aliases: {"o7" }, .Register: "r15" }, |
| 44 | {.Aliases: {"l0" }, .Register: "r16" }, {.Aliases: {"l1" }, .Register: "r17" }, {.Aliases: {"l2" }, .Register: "r18" }, {.Aliases: {"l3" }, .Register: "r19" }, |
| 45 | {.Aliases: {"l4" }, .Register: "r20" }, {.Aliases: {"l5" }, .Register: "r21" }, {.Aliases: {"l6" }, .Register: "r22" }, {.Aliases: {"l7" }, .Register: "r23" }, |
| 46 | {.Aliases: {"i0" }, .Register: "r24" }, {.Aliases: {"i1" }, .Register: "r25" }, {.Aliases: {"i2" }, .Register: "r26" }, {.Aliases: {"i3" }, .Register: "r27" }, |
| 47 | {.Aliases: {"i4" }, .Register: "r28" }, {.Aliases: {"i5" }, .Register: "r29" }, {.Aliases: {"i6" , "fp" }, .Register: "r30" }, {.Aliases: {"i7" }, .Register: "r31" }, |
| 48 | }; |
| 49 | |
| 50 | ArrayRef<TargetInfo::GCCRegAlias> SparcTargetInfo::getGCCRegAliases() const { |
| 51 | return llvm::ArrayRef(GCCRegAliases); |
| 52 | } |
| 53 | |
| 54 | bool SparcTargetInfo::hasFeature(StringRef Feature) const { |
| 55 | return llvm::StringSwitch<bool>(Feature) |
| 56 | .Case(S: "softfloat" , Value: SoftFloat) |
| 57 | .Case(S: "sparc" , Value: true) |
| 58 | .Default(Value: false); |
| 59 | } |
| 60 | |
| 61 | struct SparcCPUInfo { |
| 62 | llvm::StringLiteral Name; |
| 63 | SparcTargetInfo::CPUKind Kind; |
| 64 | SparcTargetInfo::CPUGeneration Generation; |
| 65 | }; |
| 66 | |
| 67 | static constexpr SparcCPUInfo CPUInfo[] = { |
| 68 | {.Name: {"v8" }, .Kind: SparcTargetInfo::CK_V8, .Generation: SparcTargetInfo::CG_V8}, |
| 69 | {.Name: {"supersparc" }, .Kind: SparcTargetInfo::CK_SUPERSPARC, .Generation: SparcTargetInfo::CG_V8}, |
| 70 | {.Name: {"sparclite" }, .Kind: SparcTargetInfo::CK_SPARCLITE, .Generation: SparcTargetInfo::CG_V8}, |
| 71 | {.Name: {"f934" }, .Kind: SparcTargetInfo::CK_F934, .Generation: SparcTargetInfo::CG_V8}, |
| 72 | {.Name: {"hypersparc" }, .Kind: SparcTargetInfo::CK_HYPERSPARC, .Generation: SparcTargetInfo::CG_V8}, |
| 73 | {.Name: {"sparclite86x" }, |
| 74 | .Kind: SparcTargetInfo::CK_SPARCLITE86X, |
| 75 | .Generation: SparcTargetInfo::CG_V8}, |
| 76 | {.Name: {"sparclet" }, .Kind: SparcTargetInfo::CK_SPARCLET, .Generation: SparcTargetInfo::CG_V8}, |
| 77 | {.Name: {"tsc701" }, .Kind: SparcTargetInfo::CK_TSC701, .Generation: SparcTargetInfo::CG_V8}, |
| 78 | {.Name: {"v9" }, .Kind: SparcTargetInfo::CK_V9, .Generation: SparcTargetInfo::CG_V9}, |
| 79 | {.Name: {"ultrasparc" }, .Kind: SparcTargetInfo::CK_ULTRASPARC, .Generation: SparcTargetInfo::CG_V9}, |
| 80 | {.Name: {"ultrasparc3" }, .Kind: SparcTargetInfo::CK_ULTRASPARC3, .Generation: SparcTargetInfo::CG_V9}, |
| 81 | {.Name: {"niagara" }, .Kind: SparcTargetInfo::CK_NIAGARA, .Generation: SparcTargetInfo::CG_V9}, |
| 82 | {.Name: {"niagara2" }, .Kind: SparcTargetInfo::CK_NIAGARA2, .Generation: SparcTargetInfo::CG_V9}, |
| 83 | {.Name: {"niagara3" }, .Kind: SparcTargetInfo::CK_NIAGARA3, .Generation: SparcTargetInfo::CG_V9}, |
| 84 | {.Name: {"niagara4" }, .Kind: SparcTargetInfo::CK_NIAGARA4, .Generation: SparcTargetInfo::CG_V9}, |
| 85 | {.Name: {"ma2100" }, .Kind: SparcTargetInfo::CK_MYRIAD2100, .Generation: SparcTargetInfo::CG_V8}, |
| 86 | {.Name: {"ma2150" }, .Kind: SparcTargetInfo::CK_MYRIAD2150, .Generation: SparcTargetInfo::CG_V8}, |
| 87 | {.Name: {"ma2155" }, .Kind: SparcTargetInfo::CK_MYRIAD2155, .Generation: SparcTargetInfo::CG_V8}, |
| 88 | {.Name: {"ma2450" }, .Kind: SparcTargetInfo::CK_MYRIAD2450, .Generation: SparcTargetInfo::CG_V8}, |
| 89 | {.Name: {"ma2455" }, .Kind: SparcTargetInfo::CK_MYRIAD2455, .Generation: SparcTargetInfo::CG_V8}, |
| 90 | {.Name: {"ma2x5x" }, .Kind: SparcTargetInfo::CK_MYRIAD2x5x, .Generation: SparcTargetInfo::CG_V8}, |
| 91 | {.Name: {"ma2080" }, .Kind: SparcTargetInfo::CK_MYRIAD2080, .Generation: SparcTargetInfo::CG_V8}, |
| 92 | {.Name: {"ma2085" }, .Kind: SparcTargetInfo::CK_MYRIAD2085, .Generation: SparcTargetInfo::CG_V8}, |
| 93 | {.Name: {"ma2480" }, .Kind: SparcTargetInfo::CK_MYRIAD2480, .Generation: SparcTargetInfo::CG_V8}, |
| 94 | {.Name: {"ma2485" }, .Kind: SparcTargetInfo::CK_MYRIAD2485, .Generation: SparcTargetInfo::CG_V8}, |
| 95 | {.Name: {"ma2x8x" }, .Kind: SparcTargetInfo::CK_MYRIAD2x8x, .Generation: SparcTargetInfo::CG_V8}, |
| 96 | {.Name: {"leon2" }, .Kind: SparcTargetInfo::CK_LEON2, .Generation: SparcTargetInfo::CG_V8}, |
| 97 | {.Name: {"at697e" }, .Kind: SparcTargetInfo::CK_LEON2_AT697E, .Generation: SparcTargetInfo::CG_V8}, |
| 98 | {.Name: {"at697f" }, .Kind: SparcTargetInfo::CK_LEON2_AT697F, .Generation: SparcTargetInfo::CG_V8}, |
| 99 | {.Name: {"leon3" }, .Kind: SparcTargetInfo::CK_LEON3, .Generation: SparcTargetInfo::CG_V8}, |
| 100 | {.Name: {"ut699" }, .Kind: SparcTargetInfo::CK_LEON3_UT699, .Generation: SparcTargetInfo::CG_V8}, |
| 101 | {.Name: {"gr712rc" }, .Kind: SparcTargetInfo::CK_LEON3_GR712RC, .Generation: SparcTargetInfo::CG_V8}, |
| 102 | {.Name: {"leon4" }, .Kind: SparcTargetInfo::CK_LEON4, .Generation: SparcTargetInfo::CG_V8}, |
| 103 | {.Name: {"gr740" }, .Kind: SparcTargetInfo::CK_LEON4_GR740, .Generation: SparcTargetInfo::CG_V8}, |
| 104 | }; |
| 105 | |
| 106 | SparcTargetInfo::CPUGeneration |
| 107 | SparcTargetInfo::getCPUGeneration(CPUKind Kind) const { |
| 108 | if (Kind == CK_GENERIC) |
| 109 | return CG_V8; |
| 110 | const SparcCPUInfo *Item = llvm::find_if( |
| 111 | Range: CPUInfo, P: [Kind](const SparcCPUInfo &Info) { return Info.Kind == Kind; }); |
| 112 | if (Item == std::end(arr: CPUInfo)) |
| 113 | llvm_unreachable("Unexpected CPU kind" ); |
| 114 | return Item->Generation; |
| 115 | } |
| 116 | |
| 117 | SparcTargetInfo::CPUKind SparcTargetInfo::getCPUKind(StringRef Name) const { |
| 118 | const SparcCPUInfo *Item = llvm::find_if( |
| 119 | Range: CPUInfo, P: [Name](const SparcCPUInfo &Info) { return Info.Name == Name; }); |
| 120 | |
| 121 | if (Item == std::end(arr: CPUInfo)) |
| 122 | return CK_GENERIC; |
| 123 | return Item->Kind; |
| 124 | } |
| 125 | |
| 126 | void SparcTargetInfo::fillValidCPUList( |
| 127 | SmallVectorImpl<StringRef> &Values) const { |
| 128 | for (const SparcCPUInfo &Info : CPUInfo) |
| 129 | Values.push_back(Elt: Info.Name); |
| 130 | } |
| 131 | |
| 132 | void SparcTargetInfo::getTargetDefines(const LangOptions &Opts, |
| 133 | MacroBuilder &Builder) const { |
| 134 | DefineStd(Builder, MacroName: "sparc" , Opts); |
| 135 | Builder.defineMacro(Name: "__REGISTER_PREFIX__" , Value: "" ); |
| 136 | |
| 137 | if (SoftFloat) |
| 138 | Builder.defineMacro(Name: "SOFT_FLOAT" , Value: "1" ); |
| 139 | } |
| 140 | |
| 141 | void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts, |
| 142 | MacroBuilder &Builder) const { |
| 143 | SparcTargetInfo::getTargetDefines(Opts, Builder); |
| 144 | if (getTriple().isOSSolaris()) |
| 145 | Builder.defineMacro(Name: "__sparcv8" ); |
| 146 | else { |
| 147 | switch (getCPUGeneration(Kind: CPU)) { |
| 148 | case CG_V8: |
| 149 | Builder.defineMacro(Name: "__sparcv8" ); |
| 150 | Builder.defineMacro(Name: "__sparcv8__" ); |
| 151 | break; |
| 152 | case CG_V9: |
| 153 | Builder.defineMacro(Name: "__sparc_v9__" ); |
| 154 | break; |
| 155 | } |
| 156 | } |
| 157 | if (getCPUGeneration(Kind: CPU) == CG_V9) { |
| 158 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1" ); |
| 159 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2" ); |
| 160 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" ); |
| 161 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8" ); |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts, |
| 166 | MacroBuilder &Builder) const { |
| 167 | SparcTargetInfo::getTargetDefines(Opts, Builder); |
| 168 | Builder.defineMacro(Name: "__sparcv9" ); |
| 169 | Builder.defineMacro(Name: "__arch64__" ); |
| 170 | // Solaris doesn't need these variants, but the BSDs do. |
| 171 | if (!getTriple().isOSSolaris()) { |
| 172 | Builder.defineMacro(Name: "__sparc64__" ); |
| 173 | Builder.defineMacro(Name: "__sparc_v9__" ); |
| 174 | Builder.defineMacro(Name: "__sparcv9__" ); |
| 175 | } |
| 176 | |
| 177 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1" ); |
| 178 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2" ); |
| 179 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" ); |
| 180 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8" ); |
| 181 | } |
| 182 | |
| 183 | void SparcV9TargetInfo::fillValidCPUList( |
| 184 | SmallVectorImpl<StringRef> &Values) const { |
| 185 | for (const SparcCPUInfo &Info : CPUInfo) |
| 186 | if (Info.Generation == CG_V9) |
| 187 | Values.push_back(Elt: Info.Name); |
| 188 | } |
| 189 | |