mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-12 17:19:28 +01:00
Merge pull request #22908 from hrydgard/ir-vsrt-vf2h
IR: Compile vsrt1-4 and vf2h instead of interpreting them
This commit is contained in:
9 files changed
+104
-5
No files matched your search
@@ -1503,6 +1503,35 @@ namespace MIPSComp {
|
||||
ApplyPrefixD(dregs, outsize, _VD);
|
||||
}
|
||||
|
||||
void IRFrontend::Comp_Vf2h(MIPSOpcode op) {
|
||||
CONDITIONAL_DISABLE(VFPU_VEC);
|
||||
// The prefixes act oddly here (the S swizzle applies to all four lanes), so leave those to the interpreter.
|
||||
if (!js.HasNoPrefix()) {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
// Vector pack float to half
|
||||
// d[N] = half(s[N*2]) | half(s[N*2+1]) << 16
|
||||
VectorSize sz = GetVecSize(op);
|
||||
if (sz != V_Pair && sz != V_Quad) {
|
||||
DISABLE;
|
||||
}
|
||||
VectorSize outsize = sz == V_Pair ? V_Single : V_Pair;
|
||||
int nOut = GetNumVectorElements(outsize);
|
||||
|
||||
u8 sregs[4], dregs[2];
|
||||
GetVectorRegs(sregs, sz, _VS);
|
||||
GetVectorRegs(dregs, outsize, _VD);
|
||||
|
||||
// Through temps, since d may overlap s.
|
||||
for (int i = 0; i < nOut; i++) {
|
||||
ir.Write(IROp::FFloatToHalf2, IRVTEMP_0 + i, sregs[i * 2], sregs[i * 2 + 1]);
|
||||
}
|
||||
for (int i = 0; i < nOut; i++) {
|
||||
ir.Write(IROp::FMov, dregs[i], IRVTEMP_0 + i);
|
||||
}
|
||||
}
|
||||
|
||||
void IRFrontend::Comp_Vf2i(MIPSOpcode op) {
|
||||
CONDITIONAL_DISABLE(VFPU_VEC);
|
||||
if (js.HasUnknownPrefix() || !IsPrefixWithinSize(js.prefixS, op) || (js.prefixD & 0xFF) != 0) {
|
||||
@@ -2743,6 +2772,60 @@ namespace MIPSComp {
|
||||
ApplyPrefixD(dregs, outsize, _VD);
|
||||
}
|
||||
|
||||
void IRFrontend::Comp_Vsrt(MIPSOpcode op) {
|
||||
CONDITIONAL_DISABLE(VFPU_VEC);
|
||||
// T is S re-swizzled, with the T prefix rewritten around that, so S and T prefixes go to the interpreter.
|
||||
// The D prefix applies normally (Colin McRae masks off half the lanes).
|
||||
if (js.HasUnknownPrefix() || js.HasSPrefix() || js.HasTPrefix() || GetVecSize(op) != V_Quad) {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
// Sorts pairs of lanes with vmin/vmax, which keep the second operand on a tie, in the
|
||||
// same operand order as Int_Vsrt1-4, so the same lane wins a tie.
|
||||
// vsrt1: (x, y) (z, w) ascending. vsrt2: (x, w) (y, z) ascending.
|
||||
// vsrt3: (x, y) (z, w) descending. vsrt4: (x, w) (y, z) descending.
|
||||
u8 s[4], dregs[4];
|
||||
GetVectorRegs(s, V_Quad, _VS);
|
||||
GetVectorRegsPrefixD(dregs, V_Quad, _VD);
|
||||
|
||||
u8 tmp[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
tmp[i] = IRVTEMP_0 + i;
|
||||
}
|
||||
switch ((op >> 16) & 0x1F) {
|
||||
case 0: // vsrt1, t = yxwz
|
||||
ir.Write(IROp::FMin, tmp[0], s[1], s[0]);
|
||||
ir.Write(IROp::FMax, tmp[1], s[1], s[0]);
|
||||
ir.Write(IROp::FMin, tmp[2], s[3], s[2]);
|
||||
ir.Write(IROp::FMax, tmp[3], s[3], s[2]);
|
||||
break;
|
||||
case 1: // vsrt2, t = wzyx
|
||||
ir.Write(IROp::FMin, tmp[0], s[3], s[0]);
|
||||
ir.Write(IROp::FMin, tmp[1], s[2], s[1]);
|
||||
ir.Write(IROp::FMax, tmp[2], s[2], s[1]);
|
||||
ir.Write(IROp::FMax, tmp[3], s[3], s[0]);
|
||||
break;
|
||||
case 8: // vsrt3, t = yxwz
|
||||
ir.Write(IROp::FMax, tmp[0], s[0], s[1]);
|
||||
ir.Write(IROp::FMin, tmp[1], s[0], s[1]);
|
||||
ir.Write(IROp::FMax, tmp[2], s[2], s[3]);
|
||||
ir.Write(IROp::FMin, tmp[3], s[2], s[3]);
|
||||
break;
|
||||
case 9: // vsrt4, t = wzyx
|
||||
ir.Write(IROp::FMax, tmp[0], s[0], s[3]);
|
||||
ir.Write(IROp::FMax, tmp[1], s[1], s[2]);
|
||||
ir.Write(IROp::FMin, tmp[2], s[1], s[2]);
|
||||
ir.Write(IROp::FMin, tmp[3], s[0], s[3]);
|
||||
break;
|
||||
default:
|
||||
DISABLE;
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ir.Write(IROp::FMov, dregs[i], tmp[i]);
|
||||
}
|
||||
ApplyPrefixD(dregs, V_Quad, _VD);
|
||||
}
|
||||
|
||||
void IRFrontend::Comp_Vbfy(MIPSOpcode op) {
|
||||
CONDITIONAL_DISABLE(VFPU_VEC);
|
||||
if (js.HasUnknownPrefix() || !IsPrefixWithinSize(js.prefixS, op) || js.HasTPrefix() || (js.prefixS & VFPU_NEGATE(1, 1, 1, 1)) != 0) {
|
||||
|
||||
@@ -92,6 +92,8 @@ public:
|
||||
void Comp_Vocp(MIPSOpcode op) override;
|
||||
void Comp_ColorConv(MIPSOpcode op) override;
|
||||
void Comp_Vbfy(MIPSOpcode op) override;
|
||||
void Comp_Vsrt(MIPSOpcode op) override;
|
||||
void Comp_Vf2h(MIPSOpcode op) override;
|
||||
|
||||
int Replace_fabsf() override;
|
||||
// Returns true if a loaded state means blocks compiled before it can't run any more.
|
||||
|
||||
@@ -122,6 +122,7 @@ static const IRMeta irMeta[] = {
|
||||
{ IROp::FLog2, "FLog2", "FF" },
|
||||
{ IROp::FHalfToFloat, "FHalfToFloat", "FFI" },
|
||||
{ IROp::FSinCos, "FSinCos", "2F" },
|
||||
{ IROp::FFloatToHalf2, "FFloatToHalf2", "FFF" },
|
||||
{ IROp::FNeg, "FNeg", "FF" },
|
||||
{ IROp::FSign, "FSign", "FF" },
|
||||
{ IROp::FAbs, "FAbs", "FF" },
|
||||
|
||||
@@ -231,6 +231,7 @@ enum class IROp : uint8_t {
|
||||
FLog2, // vlog2, bit-exact with the PSP
|
||||
FHalfToFloat, // vh2f of the lower (src2 = 0) or upper (src2 = 1) half of src1
|
||||
FSinCos, // dest = sin(src1), dest + 1 = cos(src1), from one argument reduction
|
||||
FFloatToHalf2, // vf2h of a pair: dest = half(src1) | half(src2) << 16, bit-exact with the PSP
|
||||
|
||||
// Fake/System instructions
|
||||
Interpret,
|
||||
|
||||
@@ -272,6 +272,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, const IRInst *chainArena) {
|
||||
dispatch[(int)IROp::FExp2] = &&L_FExp2;
|
||||
dispatch[(int)IROp::FLog2] = &&L_FLog2;
|
||||
dispatch[(int)IROp::FSinCos] = &&L_FSinCos;
|
||||
dispatch[(int)IROp::FFloatToHalf2] = &&L_FFloatToHalf2;
|
||||
dispatch[(int)IROp::FHalfToFloat] = &&L_FHalfToFloat;
|
||||
dispatch[(int)IROp::ShlImm] = &&L_ShlImm;
|
||||
dispatch[(int)IROp::ShrImm] = &&L_ShrImm;
|
||||
@@ -992,6 +993,9 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, const IRInst *chainArena) {
|
||||
mips->f[inst->dest + 1] = c;
|
||||
IR_NEXT;
|
||||
}
|
||||
IR_CASE(FFloatToHalf2)
|
||||
mips->fi[inst->dest] = vfpu_f2h(mips->fi[inst->src1]) | ((u32)vfpu_f2h(mips->fi[inst->src2]) << 16);
|
||||
IR_NEXT;
|
||||
IR_CASE(FHalfToFloat)
|
||||
mips->fi[inst->dest] = vfpu_h2f((u16)(inst->src2 ? mips->fi[inst->src1] >> 16 : mips->fi[inst->src1] & 0xFFFF));
|
||||
IR_NEXT;
|
||||
|
||||
@@ -459,6 +459,11 @@ void IRNativeBackend::CompileIRInst(IRInst inst) {
|
||||
CompIR_FSpecial(inst);
|
||||
break;
|
||||
|
||||
case IROp::FFloatToHalf2:
|
||||
// Rare enough that the backends just call the IR interpreter's version.
|
||||
CompIR_Generic(inst);
|
||||
break;
|
||||
|
||||
case IROp::Interpret:
|
||||
CompIR_Interpret(inst);
|
||||
break;
|
||||
|
||||
@@ -809,6 +809,7 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts
|
||||
case IROp::FLog2:
|
||||
case IROp::FHalfToFloat:
|
||||
case IROp::FSinCos:
|
||||
case IROp::FFloatToHalf2:
|
||||
case IROp::FMin:
|
||||
case IROp::FMax:
|
||||
case IROp::FSign:
|
||||
|
||||
@@ -109,6 +109,8 @@ namespace MIPSComp {
|
||||
virtual void Comp_Vocp(MIPSOpcode op) = 0;
|
||||
virtual void Comp_ColorConv(MIPSOpcode op) = 0;
|
||||
virtual void Comp_Vbfy(MIPSOpcode op) = 0;
|
||||
virtual void Comp_Vsrt(MIPSOpcode op) = 0;
|
||||
virtual void Comp_Vf2h(MIPSOpcode op) = 0;
|
||||
virtual void Comp_DoNothing(MIPSOpcode op) = 0;
|
||||
|
||||
virtual int Replace_fabsf() = 0;
|
||||
|
||||
@@ -613,7 +613,7 @@ static const MIPSInstruction tableVFPU7[32] = // 110100 00001 xxxxx . ....... .
|
||||
//16
|
||||
INVALID,
|
||||
INVALID,
|
||||
INSTR("vf2h", JITFUNC(Comp_Generic), Dis_Vf2h, Int_Vf2h, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vf2h", JITFUNC(Comp_Vf2h), Dis_Vf2h, Int_Vf2h, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vh2f", JITFUNC(Comp_Vh2f), Dis_Vh2f, Int_Vh2f, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
|
||||
INVALID,
|
||||
@@ -738,8 +738,8 @@ static const MIPSInstruction tableVFPUMatrixSet1[16] = // 111100 11100 .xxxx . .
|
||||
|
||||
static const MIPSInstruction tableVFPU9[32] = // 110100 00010 xxxxx . ....... . .......
|
||||
{
|
||||
INSTR("vsrt1", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsrt1, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsrt2", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsrt2, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsrt1", JITFUNC(Comp_Vsrt), Dis_Vbfy, Int_Vsrt1, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsrt2", JITFUNC(Comp_Vsrt), Dis_Vbfy, Int_Vsrt2, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vbfy1", JITFUNC(Comp_Vbfy), Dis_Vbfy, Int_Vbfy, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vbfy2", JITFUNC(Comp_Vbfy), Dis_Vbfy, Int_Vbfy, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
//4
|
||||
@@ -748,8 +748,8 @@ static const MIPSInstruction tableVFPU9[32] = // 110100 00010 xxxxx . ....... .
|
||||
INSTR("vfad", JITFUNC(Comp_Vhoriz), Dis_Vfad, Int_Vfad, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vavg", JITFUNC(Comp_Vhoriz), Dis_Vfad, Int_Vavg, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
//8
|
||||
INSTR("vsrt3", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsrt3, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsrt4", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsrt4, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsrt3", JITFUNC(Comp_Vsrt), Dis_Vbfy, Int_Vsrt3, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsrt4", JITFUNC(Comp_Vsrt), Dis_Vbfy, Int_Vsrt4, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsgn", JITFUNC(Comp_Vsgn), Dis_Vbfy, Int_Vsgn, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INVALID,
|
||||
//12
|
||||
|
||||
Reference in new issue
Block a user