Skip to content

Commit

Permalink
[SPARC][IAS] Add SETX pseudoinstruction
Browse files Browse the repository at this point in the history
This adds the v9 SETX pseudoinstruction for convenient loading of 64-bit values.

Reviewed By: barannikov88

Differential Revision: https://reviews.llvm.org/D157230
  • Loading branch information
koachan authored and brad0 committed Aug 22, 2023
1 parent 9fee2ac commit c8c5f31
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 0 deletions.
81 changes: 81 additions & 0 deletions llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
Expand All @@ -28,6 +29,7 @@
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
Expand Down Expand Up @@ -119,6 +121,9 @@ class SparcAsmParser : public MCTargetAsmParser {
bool expandSET(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);

bool expandSETX(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);

SMLoc getLoc() const { return getParser().getTok().getLoc(); }

public:
Expand Down Expand Up @@ -643,6 +648,78 @@ bool SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc,
return false;
}

bool SparcAsmParser::expandSETX(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions) {
MCOperand MCRegOp = Inst.getOperand(0);
MCOperand MCValOp = Inst.getOperand(1);
MCOperand MCTmpOp = Inst.getOperand(2);
assert(MCRegOp.isReg() && MCTmpOp.isReg());
assert(MCValOp.isImm() || MCValOp.isExpr());

// the imm operand can be either an expression or an immediate.
bool IsImm = MCValOp.isImm();
int64_t ImmValue = IsImm ? MCValOp.getImm() : 0;

const MCExpr *ValExpr = IsImm ? MCConstantExpr::create(ImmValue, getContext())
: MCValOp.getExpr();

// Very small immediates can be expressed directly as a single `or`.
if (IsImm && isInt<13>(ImmValue)) {
// or rd, val, rd
Instructions.push_back(MCInstBuilder(SP::ORri)
.addReg(MCRegOp.getReg())
.addReg(Sparc::G0)
.addExpr(ValExpr));
return false;
}

// Otherwise, first we set the lower half of the register.

// sethi %hi(val), rd
Instructions.push_back(
MCInstBuilder(SP::SETHIi)
.addReg(MCRegOp.getReg())
.addExpr(adjustPICRelocation(SparcMCExpr::VK_Sparc_HI, ValExpr)));
// or rd, %lo(val), rd
Instructions.push_back(
MCInstBuilder(SP::ORri)
.addReg(MCRegOp.getReg())
.addReg(MCRegOp.getReg())
.addExpr(adjustPICRelocation(SparcMCExpr::VK_Sparc_LO, ValExpr)));

// Small positive immediates can be expressed as a single `sethi`+`or`
// combination, so we can just return here.
if (IsImm && isUInt<32>(ImmValue))
return false;

// For bigger immediates, we need to generate the upper half, then shift and
// merge it with the lower half that has just been generated above.

// sethi %hh(val), tmp
Instructions.push_back(
MCInstBuilder(SP::SETHIi)
.addReg(MCTmpOp.getReg())
.addExpr(adjustPICRelocation(SparcMCExpr::VK_Sparc_HH, ValExpr)));
// or tmp, %hm(val), tmp
Instructions.push_back(
MCInstBuilder(SP::ORri)
.addReg(MCTmpOp.getReg())
.addReg(MCTmpOp.getReg())
.addExpr(adjustPICRelocation(SparcMCExpr::VK_Sparc_HM, ValExpr)));
// sllx tmp, 32, tmp
Instructions.push_back(MCInstBuilder(SP::SLLXri)
.addReg(MCTmpOp.getReg())
.addReg(MCTmpOp.getReg())
.addImm(32));
// or tmp, rd, rd
Instructions.push_back(MCInstBuilder(SP::ORrr)
.addReg(MCRegOp.getReg())
.addReg(MCTmpOp.getReg())
.addReg(MCRegOp.getReg()));

return false;
}

bool SparcAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out,
Expand All @@ -663,6 +740,10 @@ bool SparcAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
if (expandSET(Inst, IDLoc, Instructions))
return true;
break;
case SP::SETX:
if (expandSETX(Inst, IDLoc, Instructions))
return true;
break;
}

for (const MCInst &I : Instructions) {
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/Sparc/SparcInstrAliases.td
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,13 @@ 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">;

// setx value, tmp, rd
// (turns into a sequence of sethi+or+shift, depending on the value)
def SETX : AsmPseudoInst<(outs I64Regs:$rd),
(ins i64imm:$val, I64Regs:$tmp),
"setx $val, $tmp, $rd">,
Requires<[Is64Bit, HasV9]>;

// not rd -> xnor rd, %g0, rd
def : InstAlias<"not $rd", (XNORrr IntRegs:$rd, IntRegs:$rd, G0), 0>;

Expand Down
80 changes: 80 additions & 0 deletions llvm/test/MC/Sparc/sparcv9-synthetic-instructions.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
! RUN: not llvm-mc %s -arch=sparc -show-encoding 2>&1 | FileCheck %s --check-prefix=V8
! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s --check-prefix=V9

! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: setx 1, %g1, %o1
! V9: mov 1, %o1 ! encoding: [0x92,0x10,0x20,0x01]
setx 1, %g1, %o1

! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: setx (0+1), %g1, %o1
! V9: mov 1, %o1 ! encoding: [0x92,0x10,0x20,0x01]
setx (0+1), %g1, %o1

! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: setx -1, %g1, %o1
! V9: mov -1, %o1 ! encoding: [0x92,0x10,0x3f,0xff]
setx -1, %g1, %o1

! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: setx (0-1), %g1, %o1
! V9: mov -1, %o1 ! encoding: [0x92,0x10,0x3f,0xff]
setx (0-1), %g1, %o1

! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: setx 0xffffffff, %g1, %o1
! V9: sethi %hi(4294967295), %o1 ! encoding: [0x13,0b00AAAAAA,A,A]
! V9: ! fixup A - offset: 0, value: %hi(4294967295), kind: fixup_sparc_hi22
! V9: or %o1, %lo(4294967295), %o1 ! encoding: [0x92,0x12,0b011000AA,A]
! V9: ! fixup A - offset: 0, value: %lo(4294967295), kind: fixup_sparc_lo10
setx 0xffffffff, %g1, %o1

! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: setx (0xffff0000+0x0000ffff), %g1, %o1
! V9: sethi %hi(4294967295), %o1 ! encoding: [0x13,0b00AAAAAA,A,A]
! V9: ! fixup A - offset: 0, value: %hi(4294967295), kind: fixup_sparc_hi22
! V9: or %o1, %lo(4294967295), %o1 ! encoding: [0x92,0x12,0b011000AA,A]
! V9: ! fixup A - offset: 0, value: %lo(4294967295), kind: fixup_sparc_lo10
setx (0xffff0000+0x0000ffff), %g1, %o1

! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: setx 0x0123456789abcdef, %g1, %o0
! V9: sethi %hi(81985529216486895), %o0 ! encoding: [0x11,0b00AAAAAA,A,A]
! V9: ! fixup A - offset: 0, value: %hi(81985529216486895), kind: fixup_sparc_hi22
! V9: or %o0, %lo(81985529216486895), %o0 ! encoding: [0x90,0x12,0b001000AA,A]
! V9: ! fixup A - offset: 0, value: %lo(81985529216486895), kind: fixup_sparc_lo10
! V9: sethi %hh(81985529216486895), %g1 ! encoding: [0x03,0b00AAAAAA,A,A]
! V9: ! fixup A - offset: 0, value: %hh(81985529216486895), kind: fixup_sparc_hh
! V9: or %g1, %hm(81985529216486895), %g1 ! encoding: [0x82,0x10,0b011000AA,A]
! V9: ! fixup A - offset: 0, value: %hm(81985529216486895), kind: fixup_sparc_hm
! V9: sllx %g1, 32, %g1 ! encoding: [0x83,0x28,0x70,0x20]
! V9: or %g1, %o0, %o0 ! encoding: [0x90,0x10,0x40,0x08]
setx 0x0123456789abcdef, %g1, %o0

! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: setx (0x0123456700000000+0x0000000089abcdef), %g1, %o0
! V9: sethi %hi(81985529216486895), %o0 ! encoding: [0x11,0b00AAAAAA,A,A]
! V9: ! fixup A - offset: 0, value: %hi(81985529216486895), kind: fixup_sparc_hi22
! V9: or %o0, %lo(81985529216486895), %o0 ! encoding: [0x90,0x12,0b001000AA,A]
! V9: ! fixup A - offset: 0, value: %lo(81985529216486895), kind: fixup_sparc_lo10
! V9: sethi %hh(81985529216486895), %g1 ! encoding: [0x03,0b00AAAAAA,A,A]
! V9: ! fixup A - offset: 0, value: %hh(81985529216486895), kind: fixup_sparc_hh
! V9: or %g1, %hm(81985529216486895), %g1 ! encoding: [0x82,0x10,0b011000AA,A]
! V9: ! fixup A - offset: 0, value: %hm(81985529216486895), kind: fixup_sparc_hm
! V9: sllx %g1, 32, %g1 ! encoding: [0x83,0x28,0x70,0x20]
! V9: or %g1, %o0, %o0 ! encoding: [0x90,0x10,0x40,0x08]
setx (0x0123456700000000+0x0000000089abcdef), %g1, %o0

! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: setx (.BB1-.BB0), %g1, %o0
! V9: sethi %hi(.BB1-.BB0), %o0 ! encoding: [0x11,0b00AAAAAA,A,A]
! V9: ! fixup A - offset: 0, value: %hi(.BB1-.BB0), kind: fixup_sparc_hi22
! V9: or %o0, %lo(.BB1-.BB0), %o0 ! encoding: [0x90,0x12,0b001000AA,A]
! V9: ! fixup A - offset: 0, value: %lo(.BB1-.BB0), kind: fixup_sparc_lo10
! V9: sethi %hh(.BB1-.BB0), %g1 ! encoding: [0x03,0b00AAAAAA,A,A]
! V9: ! fixup A - offset: 0, value: %hh(.BB1-.BB0), kind: fixup_sparc_hh
! V9: or %g1, %hm(.BB1-.BB0), %g1 ! encoding: [0x82,0x10,0b011000AA,A]
! V9: ! fixup A - offset: 0, value: %hm(.BB1-.BB0), kind: fixup_sparc_hm
! V9: sllx %g1, 32, %g1 ! encoding: [0x83,0x28,0x70,0x20]
! V9: or %g1, %o0, %o0 ! encoding: [0x90,0x10,0x40,0x08]
setx (.BB1-.BB0), %g1, %o0

0 comments on commit c8c5f31

Please sign in to comment.