diff options
| author | Koakuma <koachan@protonmail.com> | 2025-01-30 00:10:28 +0700 |
|---|---|---|
| committer | Koakuma <koachan@protonmail.com> | 2025-01-30 00:10:28 +0700 |
| commit | 7e08dfcfb499128773174581bcb387459946b957 (patch) | |
| tree | 2ed5312c11f136fd181145cefc0103f21d5ad72c | |
| parent | 0bbfd96a3a8e9cf2d4e79ef0826f7c189a017598 (diff) | |
| parent | fc000d206e9714344d895d5f9254e8f9690504db (diff) | |
[𝘀𝗽𝗿] initial versionusers/koachan/spr/sparc-add-ias-flag-handling-for-isa-levels
Created using spr 1.3.4
| -rw-r--r-- | clang/lib/Driver/ToolChains/Clang.cpp | 32 | ||||
| -rw-r--r-- | clang/test/Driver/sparc-ias-Wa.s | 60 | ||||
| -rw-r--r-- | llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 70 | ||||
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrAliases.td | 6 | ||||
| -rw-r--r-- | llvm/test/MC/Sparc/sparc-synthetic-instructions.s | 36 |
5 files changed, 204 insertions, 0 deletions
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 518113e20cb0..832766e2f848 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2593,6 +2593,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, bool UseNoExecStack = false; bool Msa = false; const char *MipsTargetFeature = nullptr; + llvm::SmallVector<const char *> SparcTargetFeatures; StringRef ImplicitIt; for (const Arg *A : Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler, @@ -2738,6 +2739,31 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, if (MipsTargetFeature) continue; break; + + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::sparcv9: + if (Value == "--undeclared-regs") { + // LLVM already allows undeclared use of G registers, so this option + // becomes a no-op. This solely exists for GNU compatibility. + // TODO implement --no-undeclared-regs + continue; + } + SparcTargetFeatures = + llvm::StringSwitch<llvm::SmallVector<const char *>>(Value) + .Case("-Av8", {"-v8plus"}) + .Case("-Av8plus", {"+v8plus", "+v9"}) + .Case("-Av8plusa", {"+v8plus", "+v9", "+vis"}) + .Case("-Av8plusb", {"+v8plus", "+v9", "+vis", "+vis2"}) + .Case("-Av8plusd", {"+v8plus", "+v9", "+vis", "+vis2", "+vis3"}) + .Case("-Av9", {"+v9"}) + .Case("-Av9a", {"+v9", "+vis"}) + .Case("-Av9b", {"+v9", "+vis", "+vis2"}) + .Case("-Av9d", {"+v9", "+vis", "+vis2", "+vis3"}) + .Default({}); + if (!SparcTargetFeatures.empty()) + continue; + break; } if (Value == "-force_cpusubtype_ALL") { @@ -2842,6 +2868,12 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, CmdArgs.push_back("-target-feature"); CmdArgs.push_back(MipsTargetFeature); } + if (!SparcTargetFeatures.empty()) { + for (const char *Feature : SparcTargetFeatures) { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back(Feature); + } + } // forward -fembed-bitcode to assmebler if (C.getDriver().embedBitcodeEnabled() || diff --git a/clang/test/Driver/sparc-ias-Wa.s b/clang/test/Driver/sparc-ias-Wa.s new file mode 100644 index 000000000000..79456c02935b --- /dev/null +++ b/clang/test/Driver/sparc-ias-Wa.s @@ -0,0 +1,60 @@ +// RUN: %clang --target=sparc-linux-gnu -### -fintegrated-as -c %s -Wa,-Av8 2>&1 | \ +// RUN: FileCheck -check-prefix=V8 %s +// V8: -cc1as +// V8: "-target-feature" "-v8plus" + +// RUN: %clang --target=sparc-linux-gnu -### -fintegrated-as -c %s -Wa,-Av8plus 2>&1 | \ +// RUN: FileCheck -check-prefix=V8PLUS %s +// V8PLUS: -cc1as +// V8PLUS: "-target-feature" "+v8plus" +// V8PLUS: "-target-feature" "+v9" + +// RUN: %clang --target=sparc-linux-gnu -### -fintegrated-as -c %s -Wa,-Av8plusa 2>&1 | \ +// RUN: FileCheck -check-prefix=V8PLUSA %s +// V8PLUSA: -cc1as +// V8PLUSA: "-target-feature" "+v8plus" +// V8PLUSA: "-target-feature" "+v9" +// V8PLUSA: "-target-feature" "+vis" + +// RUN: %clang --target=sparc-linux-gnu -### -fintegrated-as -c %s -Wa,-Av8plusb 2>&1 | \ +// RUN: FileCheck -check-prefix=V8PLUSB %s +// V8PLUSB: -cc1as +// V8PLUSB: "-target-feature" "+v8plus" +// V8PLUSB: "-target-feature" "+v9" +// V8PLUSB: "-target-feature" "+vis" +// V8PLUSB: "-target-feature" "+vis2" + +// RUN: %clang --target=sparc-linux-gnu -### -fintegrated-as -c %s -Wa,-Av8plusd 2>&1 | \ +// RUN: FileCheck -check-prefix=V8PLUSD %s +// V8PLUSD: -cc1as +// V8PLUSD: "-target-feature" "+v8plus" +// V8PLUSD: "-target-feature" "+v9" +// V8PLUSD: "-target-feature" "+vis" +// V8PLUSD: "-target-feature" "+vis2" +// V8PLUSD: "-target-feature" "+vis3" + +// RUN: %clang --target=sparc-linux-gnu -### -fintegrated-as -c %s -Wa,-Av9 2>&1 | \ +// RUN: FileCheck -check-prefix=V9 %s +// V9: -cc1as +// V9: "-target-feature" "+v9" + +// RUN: %clang --target=sparc-linux-gnu -### -fintegrated-as -c %s -Wa,-Av9a 2>&1 | \ +// RUN: FileCheck -check-prefix=V9A %s +// V9A: -cc1as +// V9A: "-target-feature" "+v9" +// V9A: "-target-feature" "+vis" + +// RUN: %clang --target=sparc-linux-gnu -### -fintegrated-as -c %s -Wa,-Av9b 2>&1 | \ +// RUN: FileCheck -check-prefix=V9B %s +// V9B: -cc1as +// V9B: "-target-feature" "+v9" +// V9B: "-target-feature" "+vis" +// V9B: "-target-feature" "+vis2" + +// RUN: %clang --target=sparc-linux-gnu -### -fintegrated-as -c %s -Wa,-Av9d 2>&1 | \ +// RUN: FileCheck -check-prefix=V9D %s +// V9D: -cc1as +// V9D: "-target-feature" "+v9" +// V9D: "-target-feature" "+vis" +// V9D: "-target-feature" "+vis2" +// V9D: "-target-feature" "+vis3" diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index bc239480baa8..879f2ed88496 100644 --- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -130,6 +130,9 @@ class SparcAsmParser : public MCTargetAsmParser { bool expandSET(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); + bool expandSETSW(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); + bool expandSETX(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); @@ -734,6 +737,69 @@ bool SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc, return false; } +bool SparcAsmParser::expandSETSW(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + MCOperand MCRegOp = Inst.getOperand(0); + MCOperand MCValOp = Inst.getOperand(1); + assert(MCRegOp.isReg()); + assert(MCValOp.isImm() || MCValOp.isExpr()); + + // the imm operand can be either an expression or an immediate. + bool IsImm = Inst.getOperand(1).isImm(); + int64_t ImmValue = IsImm ? MCValOp.getImm() : 0; + const MCExpr *ValExpr = IsImm ? MCConstantExpr::create(ImmValue, getContext()) + : MCValOp.getExpr(); + + bool IsSmallImm = IsImm && isInt<13>(ImmValue); + bool NoLowBitsImm = IsImm && ((ImmValue & 0x3FF) == 0); + + MCOperand PrevReg = MCOperand::createReg(Sparc::G0); + + if (!isInt<32>(ImmValue)) { + return Error(IDLoc, + "set: argument must be between -2147483648 and 2147483647"); + } + + // Very small immediates can be expressed without emitting a sethi. + if (!IsSmallImm) { + // sethi %hi(val), rd + Instructions.push_back( + MCInstBuilder(SP::SETHIi) + .addReg(MCRegOp.getReg()) + .addExpr(adjustPICRelocation(SparcMCExpr::VK_Sparc_HI, ValExpr))); + + PrevReg = MCRegOp; + } + + // If the immediate has the lower bits set or is small, we need to emit an or. + if (!NoLowBitsImm || IsSmallImm) { + const MCExpr *Expr = + IsSmallImm ? ValExpr + : adjustPICRelocation(SparcMCExpr::VK_Sparc_LO, ValExpr); + + // or rd, %lo(val), rd + Instructions.push_back(MCInstBuilder(SP::ORri) + .addReg(MCRegOp.getReg()) + .addReg(PrevReg.getReg()) + .addExpr(Expr)); + + // If it's a small immediate there's nothing more to do. + if (IsSmallImm) + return false; + } + + // Large negative or non-immediate expressions would need an sra. + if (!IsImm || ImmValue < 0) { + // sra rd, %g0, rd + Instructions.push_back(MCInstBuilder(SP::SRArr) + .addReg(MCRegOp.getReg()) + .addReg(MCRegOp.getReg()) + .addReg(Sparc::G0)); + } + + return false; +} + bool SparcAsmParser::expandSETX(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { MCOperand MCRegOp = Inst.getOperand(0); @@ -826,6 +892,10 @@ bool SparcAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, if (expandSET(Inst, IDLoc, Instructions)) return true; break; + case SP::SETSW: + if (expandSETSW(Inst, IDLoc, Instructions)) + return true; + break; case SP::SETX: if (expandSETX(Inst, IDLoc, Instructions)) return true; diff --git a/llvm/lib/Target/Sparc/SparcInstrAliases.td b/llvm/lib/Target/Sparc/SparcInstrAliases.td index 673a2db59b09..b7232cc06616 100644 --- a/llvm/lib/Target/Sparc/SparcInstrAliases.td +++ b/llvm/lib/Target/Sparc/SparcInstrAliases.td @@ -450,6 +450,10 @@ def : InstAlias<"save", (SAVErr G0, G0, G0)>; // def : InstAlias<"set $val, $rd", (ORri IntRegs:$rd, (SETHIi (HI22 imm:$val)), (LO10 imm:$val))>; def SET : AsmPseudoInst<(outs IntRegs:$rd), (ins i32imm:$val), "set $val, $rd">; +// setsw value, rd +// (turns into a sequence of sethi+or+sra, depending on the value) +def SETSW : AsmPseudoInst<(outs IntRegs:$rd), (ins i32imm:$val), "setsw $val, $rd">; + // setx value, tmp, rd // (turns into a sequence of sethi+or+shift, depending on the value) def SETX : AsmPseudoInst<(outs I64Regs:$rd), @@ -605,6 +609,8 @@ def : InstAlias<"unimp", (UNIMP 0), 0>; // interchangeable with `unimp` all the time. def : MnemonicAlias<"illtrap", "unimp">; +def : MnemonicAlias<"setuw", "set">; + def : MnemonicAlias<"iflush", "flush">; def : MnemonicAlias<"stub", "stb">; diff --git a/llvm/test/MC/Sparc/sparc-synthetic-instructions.s b/llvm/test/MC/Sparc/sparc-synthetic-instructions.s index 5652f8684195..f679ee72baf5 100644 --- a/llvm/test/MC/Sparc/sparc-synthetic-instructions.s +++ b/llvm/test/MC/Sparc/sparc-synthetic-instructions.s @@ -54,6 +54,42 @@ ! CHECK: ! fixup A - offset: 0, value: %lo(2147483647), kind: fixup_sparc_lo10 set 2147483647, %o1 + !! setuw is a mnemonic alias for set. + ! CHECK: sethi %hi(32768), %g1 ! encoding: [0x03,0b00AAAAAA,A,A] + ! CHECK: ! fixup A - offset: 0, value: %hi(32768), kind: fixup_sparc_hi22 + setuw 32768, %g1 + ! CHECK: mov 1, %g1 ! encoding: [0x82,0x10,0x20,0x01] + setuw 1, %g1 + + ! CHECK: sethi %hi(32768), %g1 ! encoding: [0x03,0b00AAAAAA,A,A] + ! CHECK: ! fixup A - offset: 0, value: %hi(32768), kind: fixup_sparc_hi22 + setsw 32768, %g1 + ! CHECK: mov 1, %g1 ! encoding: [0x82,0x10,0x20,0x01] + setsw 1, %g1 + ! CHECK: mov -1, %g1 ! encoding: [0x82,0x10,0x3f,0xff] + setsw -1, %g1 + ! CHECK: sethi %hi(-32768), %g1 ! encoding: [0x03,0b00AAAAAA,A,A] + ! CHECK: ! fixup A - offset: 0, value: %hi(-32768), kind: fixup_sparc_hi22 + ! CHECK: sra %g1, %g0, %g1 ! encoding: [0x83,0x38,0x40,0x00] + setsw -32768, %g1 + ! CHECK: sethi %hi(2147483647), %o1 ! encoding: [0x13,0b00AAAAAA,A,A] + ! CHECK: ! fixup A - offset: 0, value: %hi(2147483647), kind: fixup_sparc_hi22 + ! CHECK: or %o1, %lo(2147483647), %o1 ! encoding: [0x92,0x12,0b011000AA,A] + ! CHECK: ! fixup A - offset: 0, value: %lo(2147483647), kind: fixup_sparc_lo10 + setsw 2147483647, %o1 + ! CHECK: sethi %hi(-2147483647), %o1 ! encoding: [0x13,0b00AAAAAA,A,A] + ! CHECK: ! fixup A - offset: 0, value: %hi(-2147483647), kind: fixup_sparc_hi22 + ! CHECK: or %o1, %lo(-2147483647), %o1 ! encoding: [0x92,0x12,0b011000AA,A] + ! CHECK: ! fixup A - offset: 0, value: %lo(-2147483647), kind: fixup_sparc_lo10 + ! CHECK: sra %o1, %g0, %o1 ! encoding: [0x93,0x3a,0x40,0x00] + setsw -2147483647, %o1 + ! CHECK: sethi %hi(.Ltmp0), %o1 ! encoding: [0x13,0b00AAAAAA,A,A] + ! CHECK: ! fixup A - offset: 0, value: %hi(.Ltmp0), kind: fixup_sparc_hi22 + ! CHECK: or %o1, %lo(.Ltmp0), %o1 ! encoding: [0x92,0x12,0b011000AA,A] + ! CHECK: ! fixup A - offset: 0, value: %lo(.Ltmp0), kind: fixup_sparc_lo10 + ! CHECK: sra %o1, %g0, %o1 ! encoding: [0x93,0x3a,0x40,0x00] + setsw ., %o1 + ! CHECK: xnor %g1, %g0, %g2 ! encoding: [0x84,0x38,0x40,0x00] not %g1, %g2 ! CHECK: xnor %g1, %g0, %g1 ! encoding: [0x82,0x38,0x40,0x00] |
