summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoakuma <koachan@protonmail.com>2025-01-30 00:10:28 +0700
committerKoakuma <koachan@protonmail.com>2025-01-30 00:10:28 +0700
commit7e08dfcfb499128773174581bcb387459946b957 (patch)
tree2ed5312c11f136fd181145cefc0103f21d5ad72c
parent0bbfd96a3a8e9cf2d4e79ef0826f7c189a017598 (diff)
parentfc000d206e9714344d895d5f9254e8f9690504db (diff)
Created using spr 1.3.4
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp32
-rw-r--r--clang/test/Driver/sparc-ias-Wa.s60
-rw-r--r--llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp70
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrAliases.td6
-rw-r--r--llvm/test/MC/Sparc/sparc-synthetic-instructions.s36
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]