Fix VFPU bugs thanks to new tests.

This commit is contained in:
Henrik Rydgard 2012-11-11 18:44:20 +01:00
parent 7fd96a0c27
commit 8aa072161c
5 changed files with 94 additions and 34 deletions

View File

@ -468,7 +468,9 @@ namespace MIPSInt
case 21: d[i] = logf(s[i])/log(2.0f); break;
case 22: d[i] = sqrtf(s[i]); break; //vsqrt
case 23: d[i] = asinf(s[i] * (float)M_2_PI); break; //vasin
// case 24: vnrcp
// case 26: vnsin
case 28: d[i] = 1.0f / expf(s[i] * (float)M_LOG2E); break; // vrexp2
default:
_dbg_assert_msg_(CPU,0,"Trying to interpret VV2Op instruction that can't be interpreted");
break;
@ -516,24 +518,6 @@ namespace MIPSInt
EatPrefixes();
}
void Int_VRexp2(u32 op)
{
float s[4], d[4];
int vd = _VD;
int vs = _VS;
VectorSize sz = GetVecSize(op);
ReadVector(s, sz, vs);
ApplySwizzleS(s, sz);
for (int i = 0; i < GetNumVectorElements(sz); i++)
{
d[i] = 1.0f / expf(s[i] * (float)M_LOG2E);
}
ApplyPrefixD(d, sz);
WriteVector(d, sz, vd);
PC += 4;
EatPrefixes();
}
void Int_Vf2i(u32 op)
{
float s[4];
@ -609,6 +593,70 @@ namespace MIPSInt
EatPrefixes();
}
u32 replicate3(u32 low) {
low &= 0xFF;
return low | (low << 8) | (low << 16);
}
void Int_Vx2i(u32 op)
{
int s[4];
u32 d[4] = {0};
int vd = _VD;
int vs = _VS;
VectorSize sz = GetVecSize(op);
VectorSize oz = sz;
ReadVector((float*)s, sz, vs);
// ForbidVPFXS
switch ((op >> 16) & 3) {
case 0: // vuc2i
// Quad is the only option
{
_dbg_assert_msg_(CPU,0,"Trying to interpret instruction that can't be interpreted");
// this op appears to be bugged and most likely useless, and this stuff is wrong. I've disabled this op in the vfpu_convert test
u32 value = s[0];
u32 value2 = value / 2;
for (int i = 0; i < 4; i++) {
d[i] = ((value & 0xFF) << 24) | replicate3(value2);
value >>= 8;
value2 >>= 8;
}
}
break;
case 1: // vc2i
// Quad is the only option
{
u32 value = s[0];
d[0] = (value & 0xFF) << 24;
d[1] = (value & 0xFF00) << 16;
d[2] = (value & 0xFF0000) << 8;
d[3] = (value & 0xFF000000);
}
break;
case 2: // vus2i
// Actually identical to vs2i, the sign doesn't matter I think.
case 3: // vs2i
for (int i = 0; i < GetNumVectorElements(sz); i++) {
u32 value = s[i];
d[i * 2] = (value & 0xFFFF) << 16;
d[i * 2 + 1] = value & 0xFFFF0000;
}
oz = V_Pair;
if (sz == V_Pair) oz = V_Quad;
break;
default:
_dbg_assert_msg_(CPU,0,"Trying to interpret instruction that can't be interpreted");
break;
}
ApplyPrefixD((float*)d,oz); // Only write mask should be valid
WriteVector((float*)d,oz,vd);
PC += 4;
EatPrefixes();
}
void Int_Vi2x(u32 op)
{
int s[4];
@ -694,7 +742,7 @@ namespace MIPSInt
u16 colors[4];
for (int i = 0; i < 4; i++)
{
u32 in = colors[i];
u32 in = s[i];
u16 col = 0;
switch ((op >> 16) & 3)
{
@ -709,10 +757,10 @@ namespace MIPSInt
}
case 2: // 5551
{
int a = ((in >> 24) & 0xFF) >> 4;
int b = ((in >> 16) & 0xFF) >> 4;
int g = ((in >> 8) & 0xFF) >> 4;
int r = ((in) & 0xFF) >> 4;
int a = ((in >> 24) & 0xFF) >> 7;
int b = ((in >> 16) & 0xFF) >> 3;
int g = ((in >> 8) & 0xFF) >> 3;
int r = ((in) & 0xFF) >> 3;
col = (a << 15) | (b << 10) | (g << 5) | (r);
break;
}

View File

@ -57,11 +57,11 @@ namespace MIPSInt
void Int_Vf2i(u32 op);
void Int_Vi2f(u32 op);
void Int_Vi2x(u32 op);
void Int_Vx2i(u32 op);
void Int_VBranch(u32 op);
void Int_Vrnds(u32 op);
void Int_VrndX(u32 op);
void Int_ColorConv(u32 op);
void Int_Vh2f2h(u32 op);
void Int_VRexp2(u32 op);
}

View File

@ -241,7 +241,11 @@ const MIPSInstruction tableSpecial[64] = /// 000000 ...... ...... .......... xxx
{-2},
//56
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
{-2}, {-2}, {-2}, {-2}, {-2},
{-2},
{-2},
{-2},
};
const MIPSInstruction tableSpecial2[64] =
@ -566,10 +570,10 @@ MIPSInstruction tableVFPU7[32] =
{-2},
INSTR("vlgb", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU),
//24
INSTR("vrexp2", &Jit::Comp_Generic, Dis_Generic, Int_VRexp2, IS_VFPU), // vrexp2 Seen in BraveStory, initialization 110100 00001110000 000 0001 0000 0000
{-2},
INSTR("vus2i", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU),
INSTR("vs2i", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU),
INSTR("vuc2i", &Jit::Comp_Generic, Dis_Generic, Int_Vx2i, IS_VFPU), // Seen in BraveStory, initialization 110100 00001110000 000 0001 0000 0000
INSTR("vc2i", &Jit::Comp_Generic, Dis_Generic, Int_Vx2i, IS_VFPU),
INSTR("vus2i", &Jit::Comp_Generic, Dis_Generic, Int_Vx2i, IS_VFPU),
INSTR("vs2i", &Jit::Comp_Generic, Dis_Generic, Int_Vx2i, IS_VFPU),
INSTR("vi2uc", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU),
INSTR("vi2c", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU),

@ -1 +1 @@
Subproject commit 696aad4df5ff0e4cd26dd46b705ca1c2fe57ccfd
Subproject commit 1a817700d4ae2b2c1fd20e68b4351d3a9014ee96

14
test.py
View File

@ -14,6 +14,10 @@ TEST_ROOT = "pspautotests/tests/"
# These have worked and should keep working always - regression tests.
tests_good = [
"cpu/cpu/cpu",
"cpu/vfpu/vfpu",
"cpu/vfpu/convert/vfpu_convert",
"cpu/vfpu/prefixes/vfpu_prefixes",
"cpu/vfpu/colors/vfpu_colors",
"cpu/icache/icache",
"cpu/lsu/lsu",
"cpu/fpu/fpu",
@ -31,7 +35,6 @@ tests_good = [
# These are the next tests up for fixing.
tests_next = [
"cpu/vfpu/vfpu",
"ctrl/ctrl",
"gpu/simple/simple",
"gpu/triangle/triangle",
@ -42,10 +45,8 @@ tests_next = [
"io/io/io",
"io/iodrv/iodrv",
"malloc/malloc",
"mstick/mstick",
"modules/loadexec/loader",
"power/power",
"sysmem/sysmem",
"threads/events/events",
"threads/fpl/fpl",
"threads/msgpipe/msgpipe",
@ -64,6 +65,13 @@ tests_next = [
"video/pmf_simple",
]
# These don't even run (or run correctly) on the real PSP
test_broken = [
"sysmem/sysmem",
"mstick/mstick",
]
# These are the tests we ignore (not important, or impossible to run)
tests_ignored = [
"kirk/kirk",