PPU Interpreter: Fixed all VPR instructions.

This commit is contained in:
DH 2013-07-03 16:02:46 +03:00
parent 4486cbb855
commit 8ba26db020

View file

@ -1526,10 +1526,10 @@ private:
else else
{ {
//undefined //undefined
CPU.VPR[vd]._u32[0] = ((rand() % 0x100) << 24) | ((rand() % 0x100) << 16) | ((rand() % 0x100) << 8) | (rand() % 0x100); CPU.VPR[vd]._u32[0] = 0xCDCDCDCD;
CPU.VPR[vd]._u32[1] = ((rand() % 0x100) << 24) | ((rand() % 0x100) << 16) | ((rand() % 0x100) << 8) | (rand() % 0x100); CPU.VPR[vd]._u32[1] = 0xCDCDCDCD;
CPU.VPR[vd]._u32[2] = ((rand() % 0x100) << 24) | ((rand() % 0x100) << 16) | ((rand() % 0x100) << 8) | (rand() % 0x100); CPU.VPR[vd]._u32[2] = 0xCDCDCDCD;
CPU.VPR[vd]._u32[3] = ((rand() % 0x100) << 24) | ((rand() % 0x100) << 16) | ((rand() % 0x100) << 8) | (rand() % 0x100); CPU.VPR[vd]._u32[3] = 0xCDCDCDCD;
} }
} }
void VSLB(OP_REG vd, OP_REG va, OP_REG vb) void VSLB(OP_REG vd, OP_REG va, OP_REG vb)
@ -1629,13 +1629,30 @@ private:
} }
void VSR(OP_REG vd, OP_REG va, OP_REG vb) void VSR(OP_REG vd, OP_REG va, OP_REG vb)
{ {
u8 sh = CPU.VPR[vb]._u8[15] & 0x7; u8 sh = CPU.VPR[vb]._u8[0] & 0x7;
u32 t = 1;
CPU.VPR[vd]._u32[0] = CPU.VPR[va]._u32[0] >> sh; for (uint b = 0; b < 16; b++)
for (uint w = 1; w < 4; w++)
{ {
CPU.VPR[vd]._u32[w] = (CPU.VPR[va]._u32[w] >> sh) | (CPU.VPR[va]._u32[w - 1] << (32 - sh)); t &= (CPU.VPR[vb]._u8[b] & 0x7) == sh;
}
if(t)
{
CPU.VPR[vd]._u8[15] = CPU.VPR[va]._u8[15] >> sh;
for (uint b = 14; b >= 0; b--)
{
CPU.VPR[vd]._u8[b] = (CPU.VPR[va]._u8[b] >> sh) | (CPU.VPR[va]._u8[b+1] << (8 - sh));
}
}
else
{
//undefined
CPU.VPR[vd]._u32[0] = 0xCDCDCDCD;
CPU.VPR[vd]._u32[1] = 0xCDCDCDCD;
CPU.VPR[vd]._u32[2] = 0xCDCDCDCD;
CPU.VPR[vd]._u32[3] = 0xCDCDCDCD;
} }
} }
void VSRAB(OP_REG vd, OP_REG va, OP_REG vb) void VSRAB(OP_REG vd, OP_REG va, OP_REG vb)
@ -1649,14 +1666,14 @@ private:
{ {
for (uint h = 0; h < 8; h++) for (uint h = 0; h < 8; h++)
{ {
CPU.VPR[vd]._s16[h] = CPU.VPR[va]._s16[h] >> (CPU.VPR[vb]._u8[h*2 + 1] & 0xf); CPU.VPR[vd]._s16[h] = CPU.VPR[va]._s16[h] >> (CPU.VPR[vb]._u8[h*2] & 0xf);
} }
} }
void VSRAW(OP_REG vd, OP_REG va, OP_REG vb) void VSRAW(OP_REG vd, OP_REG va, OP_REG vb)
{ {
for (uint w = 0; w < 4; w++) for (uint w = 0; w < 4; w++)
{ {
CPU.VPR[vd]._s32[w] = CPU.VPR[va]._s32[w] >> (CPU.VPR[vb]._u8[w*4 + 3] & 0x1f); CPU.VPR[vd]._s32[w] = CPU.VPR[va]._s32[w] >> (CPU.VPR[vb]._u8[w*4] & 0x1f);
} }
} }
void VSRB(OP_REG vd, OP_REG va, OP_REG vb) void VSRB(OP_REG vd, OP_REG va, OP_REG vb)
@ -1670,25 +1687,25 @@ private:
{ {
for (uint h = 0; h < 8; h++) for (uint h = 0; h < 8; h++)
{ {
CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] >> (CPU.VPR[vb]._u8[h*2 + 1] & 0xf); CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] >> (CPU.VPR[vb]._u8[h*2] & 0xf);
} }
} }
void VSRO(OP_REG vd, OP_REG va, OP_REG vb) void VSRO(OP_REG vd, OP_REG va, OP_REG vb)
{ {
u8 nShift = (CPU.VPR[vb]._u8[15] >> 3) & 0xf; u8 nShift = (CPU.VPR[vb]._u8[0] >> 3) & 0xf;
CPU.VPR[vd].Clear(); CPU.VPR[vd].Clear();
for (u8 b = nShift; b < 16; b++) for (u8 b = 0; b < 16 - nShift; b++)
{ {
CPU.VPR[vd]._u8[b] = CPU.VPR[va]._u8[b - nShift]; CPU.VPR[vd]._u8[b] = CPU.VPR[va]._u8[b + nShift];
} }
} }
void VSRW(OP_REG vd, OP_REG va, OP_REG vb) void VSRW(OP_REG vd, OP_REG va, OP_REG vb)
{ {
for (uint w = 0; w < 4; w++) for (uint w = 0; w < 4; w++)
{ {
CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] >> (CPU.VPR[vb]._u8[w*4 + 3] & 0x1f); CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] >> (CPU.VPR[vb]._u8[w*4] & 0x1f);
} }
} }
void VSUBCUW(OP_REG vd, OP_REG va, OP_REG vb) void VSUBCUW(OP_REG vd, OP_REG va, OP_REG vb)
@ -1844,16 +1861,16 @@ private:
if (sum > INT32_MAX) if (sum > INT32_MAX)
{ {
CPU.VPR[vd]._s32[3] = (s32)INT32_MAX; CPU.VPR[vd]._s32[0] = (s32)INT32_MAX;
CPU.VSCR.SAT = 1; CPU.VSCR.SAT = 1;
} }
else if (sum < INT32_MIN) else if (sum < INT32_MIN)
{ {
CPU.VPR[vd]._s32[3] = (s32)INT32_MIN; CPU.VPR[vd]._s32[0] = (s32)INT32_MIN;
CPU.VSCR.SAT = 1; CPU.VSCR.SAT = 1;
} }
else else
CPU.VPR[vd]._s32[3] = (s32)sum; CPU.VPR[vd]._s32[0] = (s32)sum;
} }
void VSUM2SWS(OP_REG vd, OP_REG va, OP_REG vb) void VSUM2SWS(OP_REG vd, OP_REG va, OP_REG vb)
{ {
@ -1861,25 +1878,20 @@ private:
for (uint n = 0; n < 2; n++) for (uint n = 0; n < 2; n++)
{ {
s64 sum = CPU.VPR[vb]._s32[n*2 + 1]; s64 sum = (s64)CPU.VPR[va]._s32[n*2] + CPU.VPR[va]._s32[n*2 + 1] + CPU.VPR[vb]._s32[n*2];
for (uint w = 0; w < 2; w++)
{
sum += CPU.VPR[va]._s32[n*2 + w];
}
if (sum > INT32_MAX) if (sum > INT32_MAX)
{ {
CPU.VPR[vd]._s32[n*2 + 1] = (s32)INT32_MAX; CPU.VPR[vd]._s32[n*2] = (s32)INT32_MAX;
CPU.VSCR.SAT = 1; CPU.VSCR.SAT = 1;
} }
else if (sum < INT32_MIN) else if (sum < INT32_MIN)
{ {
CPU.VPR[vd]._s32[n*2 + 1] = (s32)INT32_MIN; CPU.VPR[vd]._s32[n*2] = (s32)INT32_MIN;
CPU.VSCR.SAT = 1; CPU.VSCR.SAT = 1;
} }
else else
CPU.VPR[vd]._s32[n*2 + 1] = (s32)sum; CPU.VPR[vd]._s32[n*2] = (s32)sum;
} }
} }
void VSUM4SBS(OP_REG vd, OP_REG va, OP_REG vb) void VSUM4SBS(OP_REG vd, OP_REG va, OP_REG vb)
@ -1956,10 +1968,10 @@ private:
{ {
for (uint w = 0; w < 4; w++) for (uint w = 0; w < 4; w++)
{ {
CPU.VPR[vd]._s8[w*4 + 0] = CPU.VPR[vb]._s8[w*2 + 0] >> 7; // signed shift sign extends CPU.VPR[vd]._s8[(3 - w)*4 + 3] = CPU.VPR[vb]._s8[w*2 + 0] >> 7; // signed shift sign extends
CPU.VPR[vd]._u8[w*4 + 1] = (CPU.VPR[vb]._u8[w*2 + 0] >> 2) & 0x1f; CPU.VPR[vd]._u8[(3 - w)*4 + 2] = (CPU.VPR[vb]._u8[w*2 + 0] >> 2) & 0x1f;
CPU.VPR[vd]._u8[w*4 + 2] = ((CPU.VPR[vb]._u8[w*2 + 0] & 0x3) << 3) | ((CPU.VPR[vb]._u8[w*2 + 1] >> 5) & 0x7); CPU.VPR[vd]._u8[(3 - w)*4 + 1] = ((CPU.VPR[vb]._u8[w*2 + 0] & 0x3) << 3) | ((CPU.VPR[vb]._u8[w*2 + 1] >> 5) & 0x7);
CPU.VPR[vd]._u8[w*4 + 3] = CPU.VPR[vb]._u8[w*2 + 1] & 0x1f; CPU.VPR[vd]._u8[(3 - w)*4 + 0] = CPU.VPR[vb]._u8[w*2 + 1] & 0x1f;
} }
} }
void VUPKHSB(OP_REG vd, OP_REG vb) void VUPKHSB(OP_REG vd, OP_REG vb)
@ -1980,10 +1992,10 @@ private:
{ {
for (uint w = 0; w < 4; w++) for (uint w = 0; w < 4; w++)
{ {
CPU.VPR[vd]._s8[w*4 + 0] = CPU.VPR[vb]._s8[8 + w*2 + 0] >> 7; // signed shift sign extends CPU.VPR[vd]._s8[(3 - w)*4 + 3] = CPU.VPR[vb]._s8[8 + w*2 + 0] >> 7; // signed shift sign extends
CPU.VPR[vd]._u8[w*4 + 1] = (CPU.VPR[vb]._u8[8 + w*2 + 0] >> 2) & 0x1f; CPU.VPR[vd]._u8[(3 - w)*4 + 2] = (CPU.VPR[vb]._u8[8 + w*2 + 0] >> 2) & 0x1f;
CPU.VPR[vd]._u8[w*4 + 2] = ((CPU.VPR[vb]._u8[8 + w*2 + 0] & 0x3) << 3) | ((CPU.VPR[vb]._u8[8 + w*2 + 1] >> 5) & 0x7); CPU.VPR[vd]._u8[(3 - w)*4 + 1] = ((CPU.VPR[vb]._u8[8 + w*2 + 0] & 0x3) << 3) | ((CPU.VPR[vb]._u8[8 + w*2 + 1] >> 5) & 0x7);
CPU.VPR[vd]._u8[w*4 + 3] = CPU.VPR[vb]._u8[8 + w*2 + 1] & 0x1f; CPU.VPR[vd]._u8[(3 - w)*4 + 0] = CPU.VPR[vb]._u8[8 + w*2 + 1] & 0x1f;
} }
} }
void VUPKLSB(OP_REG vd, OP_REG vb) void VUPKLSB(OP_REG vd, OP_REG vb)
@ -2224,25 +2236,28 @@ private:
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
switch(addr & 0xf) static const u64 lvsl_values[0x10][2] =
{ {
case 0x0: CPU.VPR[vd]._u64[1] = 0x0001020304050607; CPU.VPR[vd]._u64[0] = 0x08090A0B0C0D0E0F; break; {0x08090A0B0C0D0E0F, 0x0001020304050607},
case 0x1: CPU.VPR[vd]._u64[1] = 0x0102030405060708; CPU.VPR[vd]._u64[0] = 0x090A0B0C0D0E0F10; break; {0x090A0B0C0D0E0F10, 0x0102030405060708},
case 0x2: CPU.VPR[vd]._u64[1] = 0x0203040506070809; CPU.VPR[vd]._u64[0] = 0x0A0B0C0D0E0F1011; break; {0x0A0B0C0D0E0F1011, 0x0203040506070809},
case 0x3: CPU.VPR[vd]._u64[1] = 0x030405060708090A; CPU.VPR[vd]._u64[0] = 0x0B0C0D0E0F101112; break; {0x0B0C0D0E0F101112, 0x030405060708090A},
case 0x4: CPU.VPR[vd]._u64[1] = 0x0405060708090A0B; CPU.VPR[vd]._u64[0] = 0x0C0D0E0F10111213; break; {0x0C0D0E0F10111213, 0x0405060708090A0B},
case 0x5: CPU.VPR[vd]._u64[1] = 0x05060708090A0B0C; CPU.VPR[vd]._u64[0] = 0x0D0E0F1011121314; break; {0x0D0E0F1011121314, 0x05060708090A0B0C},
case 0x6: CPU.VPR[vd]._u64[1] = 0x060708090A0B0C0D; CPU.VPR[vd]._u64[0] = 0x0E0F101112131415; break; {0x0E0F101112131415, 0x060708090A0B0C0D},
case 0x7: CPU.VPR[vd]._u64[1] = 0x0708090A0B0C0D0E; CPU.VPR[vd]._u64[0] = 0x0F10111213141516; break; {0x0F10111213141516, 0x0708090A0B0C0D0E},
case 0x8: CPU.VPR[vd]._u64[1] = 0x08090A0B0C0D0E0F; CPU.VPR[vd]._u64[0] = 0x1011121314151617; break; {0x1011121314151617, 0x08090A0B0C0D0E0F},
case 0x9: CPU.VPR[vd]._u64[1] = 0x090A0B0C0D0E0F10; CPU.VPR[vd]._u64[0] = 0x1112131415161718; break; {0x1112131415161718, 0x090A0B0C0D0E0F10},
case 0xa: CPU.VPR[vd]._u64[1] = 0x0A0B0C0D0E0F1011; CPU.VPR[vd]._u64[0] = 0x1213141516171819; break; {0x1213141516171819, 0x0A0B0C0D0E0F1011},
case 0xb: CPU.VPR[vd]._u64[1] = 0x0B0C0D0E0F101112; CPU.VPR[vd]._u64[0] = 0x131415161718191A; break; {0x131415161718191A, 0x0B0C0D0E0F101112},
case 0xc: CPU.VPR[vd]._u64[1] = 0x0C0D0E0F10111213; CPU.VPR[vd]._u64[0] = 0x1415161718191A1B; break; {0x1415161718191A1B, 0x0C0D0E0F10111213},
case 0xd: CPU.VPR[vd]._u64[1] = 0x0D0E0F1011121314; CPU.VPR[vd]._u64[0] = 0x15161718191A1B1C; break; {0x15161718191A1B1C, 0x0D0E0F1011121314},
case 0xe: CPU.VPR[vd]._u64[1] = 0x0E0F101112131415; CPU.VPR[vd]._u64[0] = 0x161718191A1B1C1D; break; {0x161718191A1B1C1D, 0x0E0F101112131415},
case 0xf: CPU.VPR[vd]._u64[1] = 0x0F10111213141516; CPU.VPR[vd]._u64[0] = 0x1718191A1B1C1D1E; break; {0x1718191A1B1C1D1E, 0x0F10111213141516},
} };
CPU.VPR[vd]._u64[0] = lvsl_values[addr & 0xf][0];
CPU.VPR[vd]._u64[1] = lvsl_values[addr & 0xf][1];
} }
void LVEBX(OP_REG vd, OP_REG ra, OP_REG rb) void LVEBX(OP_REG vd, OP_REG ra, OP_REG rb)
{ {
@ -2381,25 +2396,28 @@ private:
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
switch(addr & 0xf) static const u64 lvsr_values[0x10][2] =
{ {
case 0x0: CPU.VPR[vd]._u64[1] = 0x1011121314151617; CPU.VPR[vd]._u64[0] = 0x18191A1B1C1D1E1F; break; {0x18191A1B1C1D1E1F, 0x1011121314151617},
case 0x1: CPU.VPR[vd]._u64[1] = 0x0F10111213141516; CPU.VPR[vd]._u64[0] = 0x1718191A1B1C1D1E; break; {0x1718191A1B1C1D1E, 0x0F10111213141516},
case 0x2: CPU.VPR[vd]._u64[1] = 0x0E0F101112131415; CPU.VPR[vd]._u64[0] = 0x161718191A1B1C1D; break; {0x161718191A1B1C1D, 0x0E0F101112131415},
case 0x3: CPU.VPR[vd]._u64[1] = 0x0D0E0F1011121314; CPU.VPR[vd]._u64[0] = 0x15161718191A1B1C; break; {0x15161718191A1B1C, 0x0D0E0F1011121314},
case 0x4: CPU.VPR[vd]._u64[1] = 0x0C0D0E0F10111213; CPU.VPR[vd]._u64[0] = 0x1415161718191A1B; break; {0x1415161718191A1B, 0x0C0D0E0F10111213},
case 0x5: CPU.VPR[vd]._u64[1] = 0x0B0C0D0E0F101112; CPU.VPR[vd]._u64[0] = 0x131415161718191A; break; {0x131415161718191A, 0x0B0C0D0E0F101112},
case 0x6: CPU.VPR[vd]._u64[1] = 0x0A0B0C0D0E0F1011; CPU.VPR[vd]._u64[0] = 0x1213141516171819; break; {0x1213141516171819, 0x0A0B0C0D0E0F1011},
case 0x7: CPU.VPR[vd]._u64[1] = 0x090A0B0C0D0E0F10; CPU.VPR[vd]._u64[0] = 0x1112131415161718; break; {0x1112131415161718, 0x090A0B0C0D0E0F10},
case 0x8: CPU.VPR[vd]._u64[1] = 0x08090A0B0C0D0E0F; CPU.VPR[vd]._u64[0] = 0x1011121314151617; break; {0x1011121314151617, 0x08090A0B0C0D0E0F},
case 0x9: CPU.VPR[vd]._u64[1] = 0x0708090A0B0C0D0E; CPU.VPR[vd]._u64[0] = 0x0F10111213141516; break; {0x0F10111213141516, 0x0708090A0B0C0D0E},
case 0xa: CPU.VPR[vd]._u64[1] = 0x060708090A0B0C0D; CPU.VPR[vd]._u64[0] = 0x0E0F101112131415; break; {0x0E0F101112131415, 0x060708090A0B0C0D},
case 0xb: CPU.VPR[vd]._u64[1] = 0x05060708090A0B0C; CPU.VPR[vd]._u64[0] = 0x0D0E0F1011121314; break; {0x0D0E0F1011121314, 0x05060708090A0B0C},
case 0xc: CPU.VPR[vd]._u64[1] = 0x0405060708090A0B; CPU.VPR[vd]._u64[0] = 0x0C0D0E0F10111213; break; {0x0C0D0E0F10111213, 0x0405060708090A0B},
case 0xd: CPU.VPR[vd]._u64[1] = 0x030405060708090A; CPU.VPR[vd]._u64[0] = 0x0B0C0D0E0F101112; break; {0x0B0C0D0E0F101112, 0x030405060708090A},
case 0xe: CPU.VPR[vd]._u64[1] = 0x0203040506070809; CPU.VPR[vd]._u64[0] = 0x0A0B0C0D0E0F1011; break; {0x0A0B0C0D0E0F1011, 0x0203040506070809},
case 0xf: CPU.VPR[vd]._u64[1] = 0x0102030405060708; CPU.VPR[vd]._u64[0] = 0x090A0B0C0D0E0F10; break; {0x090A0B0C0D0E0F10, 0x0102030405060708},
} };
CPU.VPR[vd]._u64[0] = lvsr_values[addr & 0xf][0];
CPU.VPR[vd]._u64[1] = lvsr_values[addr & 0xf][1];
} }
void LVEHX(OP_REG vd, OP_REG ra, OP_REG rb) void LVEHX(OP_REG vd, OP_REG ra, OP_REG rb)
{ {