1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 18:53:28 +01:00

Merge pull request #879 from gopalsr83/master

PPU: Implemented some instructions and fixed some bugs in the recompiler. Also fixed some issues in the interpreter.
This commit is contained in:
B1ackDaemon 2014-12-02 03:19:35 +02:00
commit b942da3f68
5 changed files with 1653 additions and 743 deletions

View File

@ -155,7 +155,8 @@ private:
case 0x106:
case 0x107: return CPU.USPRG[n - 0x100];
case 0x10C: return get_time();
case 0x10C: CPU.TB = get_time(); return CPU.TB;
case 0x10D: CPU.TB = get_time(); return CPU.TBH;
case 0x110:
case 0x111:
@ -190,6 +191,7 @@ private:
case 0x107: CPU.USPRG[n - 0x100] = value; return;
case 0x10C: UNK("WriteSPR: Write to time-based SPR. Report this to a developer!"); return;
case 0x10D: UNK("WriteSPR: Write to time-based SPR upper. Report this to a developer!"); return;
case 0x110:
case 0x111:
@ -832,45 +834,57 @@ private:
}
void VCTSXS(u32 vd, u32 uimm5, u32 vb)
{
int nScale = 1 << uimm5;
u32 nScale = 1 << uimm5;
for (uint w = 0; w < 4; w++)
{
float result = CPU.VPR[vb]._f[w] * nScale;
{
double result = (double)CPU.VPR[vb]._f[w] * nScale;
if (result > 0x7fffffff)
{
CPU.VPR[vd]._s32[w] = (int)0x7fffffff;
CPU.VSCR.SAT = 1;
}
else if (result < -pow(2, 31))
{
CPU.VPR[vd]._s32[w] = (int)0x80000000;
CPU.VSCR.SAT = 1;
}
else // C rounding = Round towards 0
CPU.VPR[vd]._s32[w] = (int)result;
}
}
void VCTUXS(u32 vd, u32 uimm5, u32 vb)
{
int nScale = 1 << uimm5;
u32 nScale = 1 << uimm5;
for (uint w = 0; w < 4; w++)
{
// C rounding = Round towards 0
s64 result = (s64)(CPU.VPR[vb]._f[w] * nScale);
double result = (double)CPU.VPR[vb]._f[w] * nScale;
if (result > 0xffffffffu)
{
CPU.VPR[vd]._u32[w] = 0xffffffffu;
CPU.VSCR.SAT = 1;
}
else if (result < 0)
{
CPU.VPR[vd]._u32[w] = 0;
CPU.VSCR.SAT = 1;
}
else
CPU.VPR[vd]._u32[w] = (u32)result;
}
}
void VEXPTEFP(u32 vd, u32 vb)
{
// vd = exp(vb * log(2))
// vd = 2^x
// ISA : Note that the value placed into the element of vD may vary between implementations
// and between different executions on the same implementation.
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._f[w] = exp(CPU.VPR[vb]._f[w] * log(2.0f));
CPU.VPR[vd]._f[w] = powf(2.0f, CPU.VPR[vb]._f[w]);
}
}
void VLOGEFP(u32 vd, u32 vb)
@ -879,7 +893,7 @@ private:
// and between different executions on the same implementation.
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._f[w] = log(CPU.VPR[vb]._f[w]) / log(2.0f);
CPU.VPR[vd]._f[w] = log2f(CPU.VPR[vb]._f[w]);
}
}
void VMADDFP(u32 vd, u32 va, u32 vc, u32 vb)
@ -938,7 +952,8 @@ private:
{
for (uint h = 0; h < 8; h++)
{
s32 result = (s32)CPU.VPR[va]._s16[h] * (s32)CPU.VPR[vb]._s16[h] + (s32)CPU.VPR[vc]._s16[h];
s32 result = (s32)CPU.VPR[va]._s16[h] * (s32)CPU.VPR[vb]._s16[h];
result = (result >> 15) + (s32)CPU.VPR[vc]._s16[h];
if (result > INT16_MAX)
{
@ -958,7 +973,8 @@ private:
{
for (uint h = 0; h < 8; h++)
{
s32 result = (s32)CPU.VPR[va]._s16[h] * (s32)CPU.VPR[vb]._s16[h] + (s32)CPU.VPR[vc]._s16[h] + 0x4000;
s32 result = ((s32)CPU.VPR[va]._s16[h] * (s32)CPU.VPR[vb]._s16[h]) + 0x4000;
result = (result >> 15) + (s32)CPU.VPR[vc]._s16[h];
if (result > INT16_MAX)
{
@ -1062,26 +1078,32 @@ private:
}
void VMRGLB(u32 vd, u32 va, u32 vb)
{
u128 VA = CPU.VPR[va];
u128 VB = CPU.VPR[vb];
for (uint h = 0; h < 8; h++)
{
CPU.VPR[vd]._u8[15 - h*2] = CPU.VPR[va]._u8[7 - h];
CPU.VPR[vd]._u8[15 - h*2 - 1] = CPU.VPR[vb]._u8[7 - h];
CPU.VPR[vd]._u8[15 - h*2] = VA._u8[7 - h];
CPU.VPR[vd]._u8[15 - h*2 - 1] = VB._u8[7 - h];
}
}
void VMRGLH(u32 vd, u32 va, u32 vb)
{
u128 VA = CPU.VPR[va];
u128 VB = CPU.VPR[vb];
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._u16[7 - w*2] = CPU.VPR[va]._u16[3 - w];
CPU.VPR[vd]._u16[7 - w*2 - 1] = CPU.VPR[vb]._u16[3 - w];
CPU.VPR[vd]._u16[7 - w*2] = VA._u16[3 - w];
CPU.VPR[vd]._u16[7 - w*2 - 1] = VB._u16[3 - w];
}
}
void VMRGLW(u32 vd, u32 va, u32 vb)
{
u128 VA = CPU.VPR[va];
u128 VB = CPU.VPR[vb];
for (uint d = 0; d < 2; d++)
{
CPU.VPR[vd]._u32[3 - d*2] = CPU.VPR[va]._u32[1 - d];
CPU.VPR[vd]._u32[3 - d*2 - 1] = CPU.VPR[vb]._u32[1 - d];
CPU.VPR[vd]._u32[3 - d*2] = VA._u32[1 - d];
CPU.VPR[vd]._u32[3 - d*2 - 1] = VB._u32[1 - d];
}
}
void VMSUMMBM(u32 vd, u32 va, u32 vb, u32 vc) //nf
@ -1152,7 +1174,7 @@ private:
for (uint b = 0; b < 4; b++)
{
result += CPU.VPR[va]._u8[w*4 + b] * CPU.VPR[vb]._u8[w*4 + b];
result += (u32)CPU.VPR[va]._u8[w*4 + b] * (u32)CPU.VPR[vb]._u8[w*4 + b];
}
result += CPU.VPR[vc]._u32[w];
@ -1167,7 +1189,7 @@ private:
for (uint h = 0; h < 2; h++)
{
result += CPU.VPR[va]._u16[w*2 + h] * CPU.VPR[vb]._u16[w*2 + h];
result += (u32)CPU.VPR[va]._u16[w*2 + h] * (u32)CPU.VPR[vb]._u16[w*2 + h];
}
result += CPU.VPR[vc]._u32[w];
@ -1183,7 +1205,7 @@ private:
for (uint h = 0; h < 2; h++)
{
result += CPU.VPR[va]._u16[w*2 + h] * CPU.VPR[vb]._u16[w*2 + h];
result += (u64)CPU.VPR[va]._u16[w*2 + h] * (u64)CPU.VPR[vb]._u16[w*2 + h];
}
result += CPU.VPR[vc]._u32[w];
@ -1291,16 +1313,18 @@ private:
}
void VPKPX(u32 vd, u32 va, u32 vb)
{
u128 VA = CPU.VPR[va];
u128 VB = CPU.VPR[vb];
for (uint h = 0; h < 4; h++)
{
u16 bb7 = CPU.VPR[vb]._u8[15 - (h*4 + 0)] & 0x1;
u16 bb8 = CPU.VPR[vb]._u8[15 - (h*4 + 1)] >> 3;
u16 bb16 = CPU.VPR[vb]._u8[15 - (h*4 + 2)] >> 3;
u16 bb24 = CPU.VPR[vb]._u8[15 - (h*4 + 3)] >> 3;
u16 ab7 = CPU.VPR[va]._u8[15 - (h*4 + 0)] & 0x1;
u16 ab8 = CPU.VPR[va]._u8[15 - (h*4 + 1)] >> 3;
u16 ab16 = CPU.VPR[va]._u8[15 - (h*4 + 2)] >> 3;
u16 ab24 = CPU.VPR[va]._u8[15 - (h*4 + 3)] >> 3;
u16 bb7 = VB._u8[15 - (h*4 + 0)] & 0x1;
u16 bb8 = VB._u8[15 - (h*4 + 1)] >> 3;
u16 bb16 = VB._u8[15 - (h*4 + 2)] >> 3;
u16 bb24 = VB._u8[15 - (h*4 + 3)] >> 3;
u16 ab7 = VA._u8[15 - (h*4 + 0)] & 0x1;
u16 ab8 = VA._u8[15 - (h*4 + 1)] >> 3;
u16 ab16 = VA._u8[15 - (h*4 + 2)] >> 3;
u16 ab24 = VA._u8[15 - (h*4 + 3)] >> 3;
CPU.VPR[vd]._u16[3 - h] = (bb7 << 15) | (bb8 << 10) | (bb16 << 5) | bb24;
CPU.VPR[vd]._u16[4 + (3 - h)] = (ab7 << 15) | (ab8 << 10) | (ab16 << 5) | ab24;
@ -1308,9 +1332,11 @@ private:
}
void VPKSHSS(u32 vd, u32 va, u32 vb) //nf
{
u128 VA = CPU.VPR[va];
u128 VB = CPU.VPR[vb];
for (uint b = 0; b < 8; b++)
{
s16 result = CPU.VPR[va]._s16[b];
s16 result = VA._s16[b];
if (result > INT8_MAX)
{
@ -1325,7 +1351,7 @@ private:
CPU.VPR[vd]._s8[b+8] = (s8)result;
result = CPU.VPR[vb]._s16[b];
result = VB._s16[b];
if (result > INT8_MAX)
{
@ -1343,9 +1369,11 @@ private:
}
void VPKSHUS(u32 vd, u32 va, u32 vb)
{
u128 VA = CPU.VPR[va];
u128 VB = CPU.VPR[vb];
for (uint b = 0; b < 8; b++)
{
s16 result = CPU.VPR[va]._s16[b];
s16 result = VA._s16[b];
if (result > UINT8_MAX)
{
@ -1360,7 +1388,7 @@ private:
CPU.VPR[vd]._u8[b+8] = (u8)result;
result = CPU.VPR[vb]._s16[b];
result = VB._s16[b];
if (result > UINT8_MAX)
{
@ -1378,9 +1406,11 @@ private:
}
void VPKSWSS(u32 vd, u32 va, u32 vb)
{
u128 VA = CPU.VPR[va];
u128 VB = CPU.VPR[vb];
for (uint h = 0; h < 4; h++)
{
s32 result = CPU.VPR[va]._s32[h];
s32 result = VA._s32[h];
if (result > INT16_MAX)
{
@ -1395,7 +1425,7 @@ private:
CPU.VPR[vd]._s16[h+4] = result;
result = CPU.VPR[vb]._s32[h];
result = VB._s32[h];
if (result > INT16_MAX)
{
@ -1413,9 +1443,11 @@ private:
}
void VPKSWUS(u32 vd, u32 va, u32 vb) //nf
{
u128 VA = CPU.VPR[va];
u128 VB = CPU.VPR[vb];
for (uint h = 0; h < 4; h++)
{
s32 result = CPU.VPR[va]._s32[h];
s32 result = VA._s32[h];
if (result > UINT16_MAX)
{
@ -1430,7 +1462,7 @@ private:
CPU.VPR[vd]._u16[h+4] = result;
result = CPU.VPR[vb]._s32[h];
result = VB._s32[h];
if (result > UINT16_MAX)
{
@ -1448,17 +1480,21 @@ private:
}
void VPKUHUM(u32 vd, u32 va, u32 vb) //nf
{
u128 VA = CPU.VPR[va];
u128 VB = CPU.VPR[vb];
for (uint b = 0; b < 8; b++)
{
CPU.VPR[vd]._u8[b+8] = CPU.VPR[va]._u8[b*2];
CPU.VPR[vd]._u8[b ] = CPU.VPR[vb]._u8[b*2];
CPU.VPR[vd]._u8[b+8] = VA._u8[b*2];
CPU.VPR[vd]._u8[b ] = VB._u8[b*2];
}
}
void VPKUHUS(u32 vd, u32 va, u32 vb)
{
u128 VA = CPU.VPR[va];
u128 VB = CPU.VPR[vb];
for (uint b = 0; b < 8; b++)
{
u16 result = CPU.VPR[va]._u16[b];
u16 result = VA._u16[b];
if (result > UINT8_MAX)
{
@ -1468,7 +1504,7 @@ private:
CPU.VPR[vd]._u8[b+8] = (u8)result;
result = CPU.VPR[vb]._u16[b];
result = VB._u16[b];
if (result > UINT8_MAX)
{
@ -1481,17 +1517,21 @@ private:
}
void VPKUWUM(u32 vd, u32 va, u32 vb)
{
u128 VA = CPU.VPR[va];
u128 VB = CPU.VPR[vb];
for (uint h = 0; h < 4; h++)
{
CPU.VPR[vd]._u16[h+4] = CPU.VPR[va]._u16[h*2];
CPU.VPR[vd]._u16[h ] = CPU.VPR[vb]._u16[h*2];
CPU.VPR[vd]._u16[h+4] = VA._u16[h*2];
CPU.VPR[vd]._u16[h ] = VB._u16[h*2];
}
}
void VPKUWUS(u32 vd, u32 va, u32 vb) //nf
{
u128 VA = CPU.VPR[va];
u128 VB = CPU.VPR[vb];
for (uint h = 0; h < 4; h++)
{
u32 result = CPU.VPR[va]._u32[h];
u32 result = VA._u32[h];
if (result > UINT16_MAX)
{
@ -1501,7 +1541,7 @@ private:
CPU.VPR[vd]._u16[h+4] = result;
result = CPU.VPR[vb]._u32[h];
result = VB._u32[h];
if (result > UINT16_MAX)
{
@ -1523,30 +1563,28 @@ private:
{
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._f[w] = floor(CPU.VPR[vb]._f[w]);
CPU.VPR[vd]._f[w] = floorf(CPU.VPR[vb]._f[w]);
}
}
void VRFIN(u32 vd, u32 vb)
{
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._f[w] = floor(CPU.VPR[vb]._f[w] + 0.5f);
CPU.VPR[vd]._f[w] = nearbyintf(CPU.VPR[vb]._f[w]);
}
}
void VRFIP(u32 vd, u32 vb)
{
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._f[w] = ceil(CPU.VPR[vb]._f[w]);
CPU.VPR[vd]._f[w] = ceilf(CPU.VPR[vb]._f[w]);
}
}
void VRFIZ(u32 vd, u32 vb)
{
for (uint w = 0; w < 4; w++)
{
float f;
modff(CPU.VPR[vb]._f[w], &f);
CPU.VPR[vd]._f[w] = f;
CPU.VPR[vd]._f[w] = truncf(CPU.VPR[vb]._f[w]);
}
}
void VRLB(u32 vd, u32 va, u32 vb) //nf
@ -1589,12 +1627,13 @@ private:
}
void VSL(u32 vd, u32 va, u32 vb) //nf
{
u128 VA = CPU.VPR[va];
u8 sh = CPU.VPR[vb]._u8[0] & 0x7;
CPU.VPR[vd]._u8[0] = CPU.VPR[va]._u8[0] << sh;
CPU.VPR[vd]._u8[0] = VA._u8[0] << sh;
for (uint b = 1; b < 16; b++)
{
CPU.VPR[vd]._u8[b] = (CPU.VPR[va]._u8[b] << sh) | (CPU.VPR[va]._u8[b-1] >> (8 - sh));
CPU.VPR[vd]._u8[b] = (VA._u8[b] << sh) | (VA._u8[b-1] >> (8 - sh));
}
}
void VSLB(u32 vd, u32 va, u32 vb)
@ -1619,18 +1658,19 @@ private:
{
for (uint h = 0; h < 8; h++)
{
CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] << (CPU.VPR[vb]._u8[h*2] & 0xf);
CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] << (CPU.VPR[vb]._u16[h] & 0xf);
}
}
void VSLO(u32 vd, u32 va, u32 vb)
{
u128 VA = CPU.VPR[va];
u8 nShift = (CPU.VPR[vb]._u8[0] >> 3) & 0xf;
CPU.VPR[vd].clear();
for (u8 b = 0; b < 16 - nShift; b++)
{
CPU.VPR[vd]._u8[15 - b] = CPU.VPR[va]._u8[15 - (b + nShift)];
CPU.VPR[vd]._u8[15 - b] = VA._u8[15 - (b + nShift)];
}
}
void VSLW(u32 vd, u32 va, u32 vb)
@ -1694,12 +1734,13 @@ private:
}
void VSR(u32 vd, u32 va, u32 vb) //nf
{
u128 VA = CPU.VPR[va];
u8 sh = CPU.VPR[vb]._u8[0] & 0x7;
CPU.VPR[vd]._u8[15] = CPU.VPR[va]._u8[15] >> sh;
CPU.VPR[vd]._u8[15] = VA._u8[15] >> sh;
for (uint b = 14; ~b; b--)
{
CPU.VPR[vd]._u8[b] = (CPU.VPR[va]._u8[b] >> sh) | (CPU.VPR[va]._u8[b+1] << (8 - sh));
CPU.VPR[vd]._u8[b] = (VA._u8[b] >> sh) | (VA._u8[b+1] << (8 - sh));
}
}
void VSRAB(u32 vd, u32 va, u32 vb) //nf
@ -1713,14 +1754,14 @@ private:
{
for (uint h = 0; h < 8; h++)
{
CPU.VPR[vd]._s16[h] = CPU.VPR[va]._s16[h] >> (CPU.VPR[vb]._u8[h*2] & 0xf);
CPU.VPR[vd]._s16[h] = CPU.VPR[va]._s16[h] >> (CPU.VPR[vb]._u16[h] & 0xf);
}
}
void VSRAW(u32 vd, u32 va, u32 vb)
{
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._s32[w] = CPU.VPR[va]._s32[w] >> (CPU.VPR[vb]._u8[w*4] & 0x1f);
CPU.VPR[vd]._s32[w] = CPU.VPR[va]._s32[w] >> (CPU.VPR[vb]._u32[w] & 0x1f);
}
}
void VSRB(u32 vd, u32 va, u32 vb)
@ -1734,25 +1775,26 @@ private:
{
for (uint h = 0; h < 8; h++)
{
CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] >> (CPU.VPR[vb]._u8[h*2] & 0xf);
CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] >> (CPU.VPR[vb]._u16[h] & 0xf);
}
}
void VSRO(u32 vd, u32 va, u32 vb)
{
u128 VA = CPU.VPR[va];
u8 nShift = (CPU.VPR[vb]._u8[0] >> 3) & 0xf;
CPU.VPR[vd].clear();
for (u8 b = 0; b < 16 - nShift; b++)
{
CPU.VPR[vd]._u8[b] = CPU.VPR[va]._u8[b + nShift];
CPU.VPR[vd]._u8[b] = VA._u8[b + nShift];
}
}
void VSRW(u32 vd, u32 va, u32 vb)
{
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] >> (CPU.VPR[vb]._u8[w*4] & 0x1f);
CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] >> (CPU.VPR[vb]._u32[w] & 0x1f);
}
}
void VSUBCUW(u32 vd, u32 va, u32 vb) //nf
@ -2013,50 +2055,56 @@ private:
}
void VUPKHPX(u32 vd, u32 vb)
{
u128 VB = CPU.VPR[vb];
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._s8[(3 - w)*4 + 3] = CPU.VPR[vb]._s8[w*2 + 0] >> 7; // signed shift sign extends
CPU.VPR[vd]._u8[(3 - w)*4 + 2] = (CPU.VPR[vb]._u8[w*2 + 0] >> 2) & 0x1f;
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[(3 - w)*4 + 0] = CPU.VPR[vb]._u8[w*2 + 1] & 0x1f;
CPU.VPR[vd]._s8[w*4 + 3] = VB._s8[8 + w*2 + 1] >> 7; // signed shift sign extends
CPU.VPR[vd]._u8[w*4 + 2] = (VB._u8[8 + w*2 + 1] >> 2) & 0x1f;
CPU.VPR[vd]._u8[w*4 + 1] = ((VB._u8[8 + w*2 + 1] & 0x3) << 3) | ((VB._u8[8 + w*2 + 0] >> 5) & 0x7);
CPU.VPR[vd]._u8[w*4 + 0] = VB._u8[8 + w*2 + 0] & 0x1f;
}
}
void VUPKHSB(u32 vd, u32 vb)
{
u128 VB = CPU.VPR[vb];
for (uint h = 0; h < 8; h++)
{
CPU.VPR[vd]._s16[h] = CPU.VPR[vb]._s8[h];
CPU.VPR[vd]._s16[h] = VB._s8[8 + h];
}
}
void VUPKHSH(u32 vd, u32 vb)
{
u128 VB = CPU.VPR[vb];
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._s32[w] = CPU.VPR[vb]._s16[w];
CPU.VPR[vd]._s32[w] = VB._s16[4 + w];
}
}
void VUPKLPX(u32 vd, u32 vb)
{
u128 VB = CPU.VPR[vb];
for (uint w = 0; w < 4; w++)
{
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[(3 - w)*4 + 2] = (CPU.VPR[vb]._u8[8 + w*2 + 0] >> 2) & 0x1f;
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[(3 - w)*4 + 0] = CPU.VPR[vb]._u8[8 + w*2 + 1] & 0x1f;
CPU.VPR[vd]._s8[w*4 + 3] = VB._s8[w*2 + 1] >> 7; // signed shift sign extends
CPU.VPR[vd]._u8[w*4 + 2] = (VB._u8[w*2 + 1] >> 2) & 0x1f;
CPU.VPR[vd]._u8[w*4 + 1] = ((VB._u8[w*2 + 1] & 0x3) << 3) | ((VB._u8[w*2 + 0] >> 5) & 0x7);
CPU.VPR[vd]._u8[w*4 + 0] = VB._u8[w*2 + 0] & 0x1f;
}
}
void VUPKLSB(u32 vd, u32 vb) //nf
{
u128 VB = CPU.VPR[vb];
for (uint h = 0; h < 8; h++)
{
CPU.VPR[vd]._s16[h] = CPU.VPR[vb]._s8[8 + h];
CPU.VPR[vd]._s16[h] = VB._s8[h];
}
}
void VUPKLSH(u32 vd, u32 vb)
{
u128 VB = CPU.VPR[vb];
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._s32[w] = CPU.VPR[vb]._s16[4 + w];
CPU.VPR[vd]._s32[w] = VB._s16[w];
}
}
void VXOR(u32 vd, u32 va, u32 vb)
@ -4064,7 +4112,7 @@ private:
}
void MTFSB1(u32 crbd, bool rc)
{
u64 mask = (1ULL << crbd);
u64 mask = (1ULL << (31 - crbd));
if ((crbd == 29) && !CPU.FPSCR.NI) LOG_WARNING(PPU, "Non-IEEE mode enabled");
CPU.FPSCR.FPSCR |= mask;
@ -4072,13 +4120,32 @@ private:
}
void MCRFS(u32 crbd, u32 crbs)
{
u64 mask = (1ULL << crbd);
CPU.CR.CR &= ~mask;
CPU.CR.CR |= CPU.FPSCR.FPSCR & mask;
CPU.SetCR(crbd, (CPU.FPSCR.FPSCR >> ((7 - crbs) * 4)) & 0xf);
switch (crbs)
{
case 0:
CPU.FPSCR.FX = CPU.FPSCR.OX = 0;
break;
case 1:
CPU.FPSCR.UX = CPU.FPSCR.ZX = CPU.FPSCR.XX = CPU.FPSCR.VXSNAN = 0;
break;
case 2:
CPU.FPSCR.VXISI = CPU.FPSCR.VXIDI = CPU.FPSCR.VXZDZ = CPU.FPSCR.VXIMZ = 0;
break;
case 3:
CPU.FPSCR.VXVC = 0;
break;
case 5:
CPU.FPSCR.VXSOFT = CPU.FPSCR.VXSQRT = CPU.FPSCR.VXCVI = 0;
break;
default:
break;
}
}
void MTFSB0(u32 crbd, bool rc)
{
u64 mask = (1ULL << crbd);
u64 mask = (1ULL << (31 - crbd));
if ((crbd == 29) && !CPU.FPSCR.NI) LOG_WARNING(PPU, "Non-IEEE mode disabled");
CPU.FPSCR.FPSCR &= ~mask;
@ -4086,17 +4153,18 @@ private:
}
void MTFSFI(u32 crfd, u32 i, bool rc)
{
u64 mask = (0x1ULL << crfd);
u32 mask = 0xF0000000 >> (crfd * 4);
u32 val = (i & 0xF) << ((7 - crfd) * 4);
if(i)
const u32 oldNI = CPU.FPSCR.NI;
CPU.FPSCR.FPSCR &= ~mask;
CPU.FPSCR.FPSCR |= val;
if (CPU.FPSCR.NI != oldNI)
{
if ((crfd == 29) && !CPU.FPSCR.NI) LOG_WARNING(PPU, "Non-IEEE mode enabled");
CPU.FPSCR.FPSCR |= mask;
}
else
{
if ((crfd == 29) && CPU.FPSCR.NI) LOG_WARNING(PPU, "Non-IEEE mode disabled");
CPU.FPSCR.FPSCR &= ~mask;
if (oldNI)
LOG_WARNING(PPU, "Non-IEEE mode disabled");
else
LOG_WARNING(PPU, "Non-IEEE mode enabled");
}
if(rc) UNIMPLEMENTED();
@ -4210,9 +4278,7 @@ private:
}
}
(u64&)CPU.FPR[frd] = 0xfff8000000000000ull | r;
if(r == 0 && ( (u64&)b & DOUBLE_SIGN )) (u64&)CPU.FPR[frd] |= 0x100000000ull;
(u64&)CPU.FPR[frd] = r;
if(rc) UNK("fctiw.");
}
void FCTIWZ(u32 frd, u32 frb, bool rc)
@ -4250,10 +4316,7 @@ private:
value = (u32)i;
}
(u64&)CPU.FPR[frd] = 0xfff8000000000000ull | value;
if (value == 0 && ( (u64&)b & DOUBLE_SIGN ))
(u64&)CPU.FPR[frd] |= 0x100000000ull;
(u64&)CPU.FPR[frd] = (u64)value;
if(rc) UNK("fctiwz.");
}
void FDIV(u32 frd, u32 fra, u32 frb, bool rc)
@ -4351,7 +4414,7 @@ private:
{
CPU.SetFPSCRException(FPSCR_ZX);
}
CPU.FPR[frd] = static_cast<float>(1.0 / sqrt(CPU.FPR[frb]));
CPU.FPR[frd] = 1.0 / sqrt(CPU.FPR[frb]);
if(rc) UNK("frsqrte.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
@ -4476,9 +4539,7 @@ private:
}
}
(u64&)CPU.FPR[frd] = 0xfff8000000000000ull | r;
if(r == 0 && ( (u64&)b & DOUBLE_SIGN )) (u64&)CPU.FPR[frd] |= 0x100000000ull;
(u64&)CPU.FPR[frd] = r;
if(rc) UNK("fctid.");
}
void FCTIDZ(u32 frd, u32 frb, bool rc)
@ -4516,9 +4577,7 @@ private:
r = (u64)i;
}
(u64&)CPU.FPR[frd] = 0xfff8000000000000ull | r;
if(r == 0 && ( (u64&)b & DOUBLE_SIGN )) (u64&)CPU.FPR[frd] |= 0x100000000ull;
(u64&)CPU.FPR[frd] = r;
if(rc) UNK("fctidz.");
}
void FCFID(u32 frd, u32 frb, bool rc)

File diff suppressed because it is too large Load Diff

View File

@ -214,7 +214,7 @@ namespace ppu_recompiler_llvm {
}
std::string ToString() const {
auto s = fmt::Format("0x%08X (0x%08X):", start_address, function_address);
auto s = fmt::Format("0x%08X (0x%08X): Size=%u ->", start_address, function_address, GetSize());
for (auto i = instruction_addresses.begin(); i != instruction_addresses.end(); i++) {
s += fmt::Format(" 0x%08X", *i);
}
@ -237,6 +237,12 @@ namespace ppu_recompiler_llvm {
return s;
}
/// Get the size of the CFG. The size is a score of how large the CFG is and increases everytime
/// a node or an edge is added to the CFG.
size_t GetSize() const {
return instruction_addresses.size() + branches.size() + calls.size();
}
};
enum class BranchType {
@ -247,7 +253,7 @@ namespace ppu_recompiler_llvm {
};
/// Pointer to an executable
typedef u32(*Executable)(PPUThread * ppu_state, PPUInterpreter * interpreter, u64 context);
typedef u32(*Executable)(PPUThread * ppu_state, u64 context);
/// PPU compiler that uses LLVM for code generation and optimization
class Compiler : protected PPUOpcodes, protected PPCDecoder {
@ -264,9 +270,6 @@ namespace ppu_recompiler_llvm {
/// Total time
std::chrono::nanoseconds total_time;
/// Contains the number of times interpreter fallback was used
std::map<std::string, u64> interpreter_fallback_stats;
};
Compiler(RecompilationEngine & recompilation_engine, const Executable execute_unknown_function, const Executable execute_unknown_block);
@ -289,7 +292,7 @@ namespace ppu_recompiler_llvm {
Stats GetStats();
/// Execute all tests
void RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter);
void RunAllTests();
protected:
void Decode(const u32 code) override;
@ -699,7 +702,6 @@ namespace ppu_recompiler_llvm {
struct CompileTaskState {
enum Args {
State,
Interpreter,
Context,
MaxArgs,
};
@ -863,6 +865,12 @@ namespace ppu_recompiler_llvm {
/// Set USPRG0
void SetUsprg0(llvm::Value * val_x64);
/// Load FPSCR
llvm::Value * GetFpscr();
/// Set FPSCR
void SetFpscr(llvm::Value * val_x32);
/// Get FPR
llvm::Value * GetFpr(u32 r, u32 bits = 64, bool as_int = false);
@ -902,10 +910,6 @@ namespace ppu_recompiler_llvm {
/// Write to memory
void WriteMemory(llvm::Value * addr_i64, llvm::Value * val_ix, u32 alignment = 0, bool bswap = true, bool could_be_mmio = true);
/// Call an interpreter function
template<class Func, class... Args>
llvm::Value * InterpreterCall(const char * name, Func function, Args... args);
/// Convert a C++ type to an LLVM type
template<class T>
llvm::Type * CppToLlvmType();
@ -924,6 +928,9 @@ namespace ppu_recompiler_llvm {
/// Excute a test
void RunTest(const char * name, std::function<void()> test_case, std::function<void()> input, std::function<bool(std::string & msg)> check_result);
/// Handle compilation errors
void CompilationError(const std::string & error);
/// A mask used in rotate instructions
static u64 s_rotate_mask[64][64];
@ -970,6 +977,9 @@ namespace ppu_recompiler_llvm {
/// The current revision number of this function
u32 revision;
/// Size of the CFG when it was last compiled
size_t last_compiled_cfg_size;
/// The CFG for this block
ControlFlowGraph cfg;
@ -979,13 +989,14 @@ namespace ppu_recompiler_llvm {
BlockEntry(u32 start_address, u32 function_address)
: num_hits(0)
, revision(0)
, last_compiled_cfg_size(0)
, is_compiled(false)
, cfg(start_address, function_address) {
}
std::string ToString() const {
return fmt::Format("0x%08X (0x%08X): NumHits=%u, Revision=%u, IsCompiled=%c",
cfg.start_address, cfg.function_address, num_hits, revision, is_compiled ? 'Y' : 'N');
return fmt::Format("0x%08X (0x%08X): NumHits=%u, Revision=%u, LastCompiledCfgSize=%u, IsCompiled=%c",
cfg.start_address, cfg.function_address, num_hits, revision, last_compiled_cfg_size, is_compiled ? 'Y' : 'N');
}
bool operator == (const BlockEntry & other) const {
@ -1009,54 +1020,8 @@ namespace ppu_recompiler_llvm {
};
};
/// An entry in the function table
struct FunctionEntry {
/// Address of the function
u32 address;
/// Number of compiled fragments
u32 num_compiled_fragments;
/// Blocks in the function
std::list<BlockEntry *> blocks;
FunctionEntry(u32 address)
: address(address)
, num_compiled_fragments(0) {
}
void AddBlock(BlockEntry * block_entry) {
auto i = std::find(blocks.begin(), blocks.end(), block_entry);
if (i == blocks.end()) {
if (block_entry->IsFunction()) {
// The first block must be the starting block of the function
blocks.push_front(block_entry);
} else {
blocks.push_back(block_entry);
}
}
}
std::string ToString() const {
return fmt::Format("0x%08X: NumCompiledFragments=%u, NumBlocks=%u", address, num_compiled_fragments, blocks.size());
}
bool operator == (const FunctionEntry & other) const {
return address == other.address;
}
struct hash {
size_t operator()(const FunctionEntry * f) const {
return f->address;
}
};
struct equal_to {
bool operator()(const FunctionEntry * lhs, const FunctionEntry * rhs) const {
return *lhs == *rhs;
}
};
};
/// Log
llvm::raw_fd_ostream * m_log;
/// Lock for accessing m_pending_execution_traces. TODO: Eliminate this and use a lock-free queue.
std::mutex m_pending_execution_traces_lock;
@ -1067,9 +1032,6 @@ namespace ppu_recompiler_llvm {
/// Block table
std::unordered_set<BlockEntry *, BlockEntry::hash, BlockEntry::equal_to> m_block_table;
/// Function table
std::unordered_set<FunctionEntry *, FunctionEntry::hash, FunctionEntry::equal_to> m_function_table;
/// Execution traces that have been already encountered. Data is the list of all blocks that this trace includes.
std::unordered_map<ExecutionTrace::Id, std::vector<BlockEntry *>> m_processed_execution_traces;
@ -1086,9 +1048,6 @@ namespace ppu_recompiler_llvm {
/// PPU Compiler
Compiler m_compiler;
/// Log
llvm::raw_fd_ostream * m_log;
/// Executable lookup table
Executable m_executable_lookup[10000]; // TODO: Adjust size
@ -1107,7 +1066,7 @@ namespace ppu_recompiler_llvm {
void UpdateControlFlowGraph(ControlFlowGraph & cfg, const ExecutionTraceEntry & this_entry, const ExecutionTraceEntry * next_entry);
/// Compile a block
void CompileBlock(FunctionEntry & function_entry, BlockEntry & block_entry);
void CompileBlock(BlockEntry & block_entry);
/// Mutex used to prevent multiple creation
static std::mutex s_mutex;
@ -1199,10 +1158,10 @@ namespace ppu_recompiler_llvm {
Executable GetExecutable(u32 address, Executable default_executable) const;
/// Execute a function
static u32 ExecuteFunction(PPUThread * ppu_state, PPUInterpreter * interpreter, u64 context);
static u32 ExecuteFunction(PPUThread * ppu_state, u64 context);
/// Execute till the current function returns
static u32 ExecuteTillReturn(PPUThread * ppu_state, PPUInterpreter * interpreter, u64 context);
static u32 ExecuteTillReturn(PPUThread * ppu_state, u64 context);
};
/// Get the branch type from a branch instruction

View File

@ -63,7 +63,7 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp
u64 R_ADDR;
u64 R_VALUE;
/// Mmeory block
/// Memory block
u32 address;
u64 mem_block[64];
@ -130,9 +130,9 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp
FPR[i] = (double)rng();
GPR[i] = rng();
VPR[i]._f[0] = (float)rng();
VPR[i]._f[1] = (float)rng();
VPR[i]._f[2] = (float)rng();
VPR[i]._f[3] = (float)rng();
VPR[i]._f[1] = (float)(rng() & 0x7FFFFFFF);
VPR[i]._f[2] = -(float)(rng() & 0x7FFFFFFF);
VPR[i]._f[3] = -(float)rng();
if (i < 8) {
SPRG[i] = rng();
@ -164,7 +164,7 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp
std::string ret;
for (int i = 0; i < 32; i++) {
ret += fmt::Format("GPR[%02d] = 0x%016llx FPR[%02d] = %16g VPR[%02d] = 0x%s [%s]\n", i, GPR[i], i, FPR[i]._double, i, VPR[i].to_hex().c_str(), VPR[i].to_xyzw().c_str());
ret += fmt::Format("GPR[%02d] = 0x%016llx FPR[%02d] = %16g (0x%016llx) VPR[%02d] = 0x%s [%s]\n", i, GPR[i], i, FPR[i]._double, FPR[i]._u64, i, VPR[i].to_hex().c_str(), VPR[i].to_xyzw().c_str());
}
for (int i = 0; i < 8; i++) {
@ -222,8 +222,8 @@ void Compiler::VerifyInstructionAgainstInterpreter(const char * name, CompilerFn
if (interp_output_state.ToString() != recomp_output_state.ToString()) {
msg = std::string("Input state:\n") + input_state.ToString() +
std::string("\nOutput state:\n") + recomp_output_state.ToString() +
std::string("\nInterpreter output state:\n") + interp_output_state.ToString();
std::string("\nOutput state:\n") + recomp_output_state.ToString() +
std::string("\nInterpreter output state:\n") + interp_output_state.ToString();
return false;
}
@ -235,58 +235,59 @@ void Compiler::VerifyInstructionAgainstInterpreter(const char * name, CompilerFn
void Compiler::RunTest(const char * name, std::function<void()> test_case, std::function<void()> input, std::function<bool(std::string & msg)> check_result) {
#ifdef PPU_LLVM_RECOMPILER_UNIT_TESTS
// Create the unit test function
m_current_function = (Function *)m_module->getOrInsertFunction(name, m_ir_builder->getVoidTy(),
m_ir_builder->getInt8PtrTy() /*ppu_state*/,
m_ir_builder->getInt64Ty() /*base_addres*/,
m_ir_builder->getInt8PtrTy() /*interpreter*/, nullptr);
m_current_function->setCallingConv(CallingConv::X86_64_Win64);
auto arg_i = m_current_function->arg_begin();
arg_i->setName("ppu_state");
(++arg_i)->setName("base_address");
(++arg_i)->setName("interpreter");
m_recompilation_engine.Log() << "Running test " << name << '\n';
auto block = BasicBlock::Create(*m_llvm_context, "start", m_current_function);
// Create the function
m_state.function = (Function *)m_module->getOrInsertFunction(name, m_compiled_function_type);
m_state.function->setCallingConv(CallingConv::X86_64_Win64);
auto arg_i = m_state.function->arg_begin();
arg_i->setName("ppu_state");
m_state.args[CompileTaskState::Args::State] = arg_i;
(++arg_i)->setName("context");
m_state.args[CompileTaskState::Args::Context] = arg_i;
m_state.current_instruction_address = s_ppu_state->PC;
auto block = BasicBlock::Create(*m_llvm_context, "start", m_state.function);
m_ir_builder->SetInsertPoint(block);
test_case();
m_ir_builder->CreateRetVoid();
m_ir_builder->CreateRet(m_ir_builder->getInt32(0));
// Print the IR
std::string ir;
raw_string_ostream ir_ostream(ir);
m_current_function->print(ir_ostream);
LOG_NOTICE(PPU, "[UT %s] LLVM IR:%s", name, ir.c_str());
m_state.function->print(ir_ostream);
m_recompilation_engine.Log() << "LLVM IR:" << ir;
std::string verify;
raw_string_ostream verify_ostream(verify);
if (verifyFunction(*m_current_function, &verify_ostream)) {
LOG_ERROR(PPU, "[UT %s] Verification Failed:%s", name, verify.c_str());
std::string verify_results;
raw_string_ostream verify_results_ostream(verify_results);
if (verifyFunction(*m_state.function, &verify_results_ostream)) {
m_recompilation_engine.Log() << "Verification Failed:\n" << verify_results << '\n';
return;
}
// Optimize
m_fpm->run(*m_current_function);
m_fpm->run(*m_state.function);
// Print the optimized IR
ir = "";
m_current_function->print(ir_ostream);
LOG_NOTICE(PPU, "[UT %s] Optimized LLVM IR:%s", name, ir.c_str());
m_state.function->print(ir_ostream);
m_recompilation_engine.Log() << "Optimized LLVM IR:" << ir;
// Generate the function
MachineCodeInfo mci;
m_execution_engine->runJITOnFunction(m_current_function, &mci);
m_execution_engine->runJITOnFunction(m_state.function, &mci);
// Disassemble the generated function
auto disassembler = LLVMCreateDisasm(sys::getProcessTriple().c_str(), nullptr, 0, nullptr, nullptr);
LOG_NOTICE(PPU, "[UT %s] Disassembly:", name);
m_recompilation_engine.Log() << "Disassembly:\n";
for (uint64_t pc = 0; pc < mci.size();) {
char str[1024];
auto size = LLVMDisasmInstruction(disassembler, (uint8_t *)mci.address() + pc, mci.size() - pc, (uint64_t)((uint8_t *)mci.address() + pc), str, sizeof(str));
LOG_NOTICE(PPU, "[UT %s] %p: %s.", name, (uint8_t *)mci.address() + pc, str);
m_recompilation_engine.Log() << ((uint8_t *)mci.address() + pc) << ':' << str << '\n';
pc += size;
}
@ -294,33 +295,31 @@ void Compiler::RunTest(const char * name, std::function<void()> test_case, std::
// Run the test
input();
std::vector<GenericValue> args;
args.push_back(GenericValue(s_ppu_state));
args.push_back(GenericValue(s_interpreter));
m_execution_engine->runFunction(m_current_function, args);
auto executable = (Executable)m_execution_engine->getPointerToFunction(m_state.function);
executable(s_ppu_state, 0);
// Verify results
std::string msg;
bool pass = check_result(msg);
if (pass) {
LOG_NOTICE(PPU, "[UT %s] Test passed. %s", name, msg.c_str());
m_recompilation_engine.Log() << "Test " << name << " passed\n" << msg << "\n";
} else {
LOG_ERROR(PPU, "[UT %s] Test failed. %s", name, msg.c_str());
m_recompilation_engine.Log() << "Test " << name << " failed\n" << msg << "\n";
}
m_execution_engine->freeMachineCodeForFunction(m_current_function);
m_execution_engine->freeMachineCodeForFunction(m_state.function);
#endif // PPU_LLVM_RECOMPILER_UNIT_TESTS
}
void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter) {
void Compiler::RunAllTests() {
#ifdef PPU_LLVM_RECOMPILER_UNIT_TESTS
s_ppu_state = ppu_state;
s_interpreter = interpreter;
PPUThread ppu_state;
PPUInterpreter interpreter(ppu_state);
PPUState initial_state;
initial_state.Load(*ppu_state, 0x10000);
s_ppu_state = &ppu_state;
s_interpreter = &interpreter;
LOG_NOTICE(PPU, "Running Unit Tests");
m_recompilation_engine.Log() << "Starting Unit Tests\n";
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MFVSCR, 0, 5, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTVSCR, 0, 5, 1);
@ -399,6 +398,12 @@ void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter)
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUW, 5, 5, 0, 1, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUW_, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUW_, 5, 5, 0, 1, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCTSXS, 0, 5, 0, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCTSXS, 5, 5, 0, 3, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCTUXS, 0, 5, 0, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCTUXS, 5, 5, 0, 3, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VEXPTEFP, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VLOGEFP, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMADDFP, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMAXFP, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMAXSB, 0, 5, 0, 1, 2);
@ -407,6 +412,8 @@ void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter)
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMAXUB, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMAXUH, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMAXUW, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMHADDSHS, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMHRADDSHS, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINFP, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINSB, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINSH, 0, 5, 0, 1, 2);
@ -414,6 +421,7 @@ void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter)
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINUB, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINUH, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINUW, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMLADDUHM, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMRGHB, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMRGHH, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMRGHW, 0, 5, 0, 1, 2);
@ -422,13 +430,40 @@ void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter)
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMRGLW, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMSUMMBM, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMSUMSHM, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMSUMSHS, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMSUMUBM, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMSUMUHM, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMSUMUHS, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMULESB, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMULESH, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMULEUB, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMULEUH, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMULOSB, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMULOSH, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMULOUB, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMULOUH, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VNMSUBFP, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VNOR, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VOR, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VPERM, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VPKPX, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VPKSHSS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VPKSHUS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VPKSWSS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VPKSWUS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VPKUHUM, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VPKUHUS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VPKUWUM, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VPKUWUS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VREFP, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VRFIM, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VRFIN, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VRFIP, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VRFIZ, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VRLB, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VRLH, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VRLW, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VRSQRTEFP, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSEL, 0, 5, 0, 1, 2, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSL, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSLB, 0, 5, 0, 1, 2);
@ -460,6 +495,17 @@ void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter)
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBUHS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBUWM, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBUWS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUMSWS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUM2SWS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUM4SBS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUM4SHS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUM4UBS, 0, 5, 0, 1, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VUPKHPX, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VUPKHSB, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VUPKHSH, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VUPKLPX, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VUPKLSB, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VUPKLSH, 0, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VXOR, 0, 5, 0, 1, 2);
// TODO: Rest of the vector instructions
@ -483,7 +529,7 @@ void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter)
// TODO: BCLR
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRNOR, 0, 5, 0, 7, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRANDC, 0, 5, 5, 6, 7);
// TODO: ISYNC
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ISYNC, 0, 5);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRXOR, 0, 5, 7, 7, 7);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRNAND, 0, 5, 3, 4, 5);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRAND, 0, 5, 1, 2, 3);
@ -513,115 +559,174 @@ void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter)
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDIMI, 5, 5, 21, 22, 23, 43, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDC_LR, 0, 5, 7, 8, 9, 12, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDC_LR, 5, 5, 21, 22, 23, 43, 1, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADD, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADD, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBF, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBF, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(NEG, 0, 5, 7, 8, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(NEG, 5, 5, 21, 22, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMP, 0, 5, 3, 0, 9, 31);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMP, 5, 5, 6, 1, 23, 14);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFC, 0, 5, 0, 1, 2, 0, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFC, 5, 5, 0, 1, 2, 0, true);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDC, 0, 5, 0, 1, 2, 0, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDC, 5, 5, 0, 1, 2, 0, true);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHDU, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHDU, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHWU, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHWU, 5, 5, 21, 22, 23, 1);
// TODO: MFOCRF
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SLW, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SLW, 5, 5, 5, 6, 7, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CNTLZW, 0, 5, 5, 6, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CNTLZW, 5, 5, 5, 6, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SLD, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SLD, 5, 5, 5, 6, 7, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(AND, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(AND, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPL, 0, 5, 3, 0, 9, 31);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPL, 5, 5, 6, 1, 23, 14);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBF, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBF, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CNTLZD, 0, 5, 5, 6, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CNTLZD, 5, 5, 5, 6, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ANDC, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ANDC, 5, 5, 5, 6, 7, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHD, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHD, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHW, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHW, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLD, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLD, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLW, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLW, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVD, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVD, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVDU, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVDU, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVW, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVW, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVWU, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVWU, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(AND, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(AND, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(OR, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(OR, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(XOR, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(XOR, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(NEG, 0, 5, 7, 8, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(NEG, 5, 5, 21, 22, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(NOR, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(NOR, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMP, 0, 5, 3, 0, 9, 31);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMP, 5, 5, 6, 1, 23, 14);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPL, 0, 5, 3, 0, 9, 31);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPL, 5, 5, 6, 1, 23, 14);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDC, 0, 5, 0, 1, 2, 0, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDC, 5, 5, 0, 1, 2, 0, true);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFC, 0, 5, 0, 1, 2, 0, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFC, 5, 5, 0, 1, 2, 0, true);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSB, 0, 5, 3, 5, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSB, 5, 5, 3, 5, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSH, 0, 5, 6, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSH, 5, 5, 6, 9, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSW, 0, 5, 25, 29, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSW, 5, 5, 25, 29, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTSPR, 0, 5, 0x20, 5);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTSPR, 5, 5, 0x100, 5);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTSPR, 10, 5, 0x120, 5);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTSPR, 15, 5, 0x8, 5);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFE, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFE, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDE, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDE, 5, 5, 21, 22, 23, 0, 1);
// TODO: MTOCRF
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDZE, 0, 5, 7, 8, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDZE, 5, 5, 21, 22, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFZE, 0, 5, 7, 8, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFZE, 5, 5, 21, 22, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFME, 0, 5, 7, 8, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFME, 5, 5, 21, 22, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLD, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLD, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDME, 0, 5, 7, 8, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDME, 5, 5, 21, 22, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLW, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLW, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADD, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADD, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EQV, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EQV, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(XOR, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(XOR, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MFSPR, 0, 5, 5, 0x20);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MFSPR, 5, 5, 5, 0x100);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MFSPR, 10, 5, 5, 0x120);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MFSPR, 15, 5, 5, 0x8);
// TODO: MFTB
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ORC, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ORC, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(OR, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(OR, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVDU, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVDU, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVWU, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVWU, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTSPR, 0, 5, 0x20, 5);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTSPR, 5, 5, 0x100, 5);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTSPR, 10, 5, 0x120, 5);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTSPR, 15, 5, 0x8, 5);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(NAND, 0, 5, 7, 8, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(NAND, 5, 5, 21, 22, 23, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVD, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVD, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVW, 0, 5, 7, 8, 9, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVW, 5, 5, 21, 22, 23, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRW, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRW, 5, 5, 5, 6, 7, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRD, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRD, 5, 5, 5, 6, 7, 1);
// TODO: SYNC
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAW, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAW, 5, 5, 5, 6, 7, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAD, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAD, 5, 5, 5, 6, 7, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAWI, 0, 5, 5, 6, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAWI, 5, 5, 5, 6, 12, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAWI, 10, 5, 5, 6, 22, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAWI, 15, 5, 5, 6, 31, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAW, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAW, 5, 5, 5, 6, 7, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRADI1, 0, 5, 5, 6, 0, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRADI1, 5, 5, 5, 6, 12, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRADI1, 10, 5, 5, 6, 48, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRADI1, 15, 5, 5, 6, 63, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAD, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAD, 5, 5, 5, 6, 7, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SLW, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SLW, 5, 5, 5, 6, 7, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRW, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRW, 5, 5, 5, 6, 7, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SLD, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SLD, 5, 5, 5, 6, 7, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRD, 0, 5, 5, 6, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRD, 5, 5, 5, 6, 7, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CNTLZW, 0, 5, 5, 6, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CNTLZW, 5, 5, 5, 6, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CNTLZD, 0, 5, 5, 6, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CNTLZD, 5, 5, 5, 6, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ISYNC, 0, 5);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EIEIO, 0, 5);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSH, 0, 5, 6, 9, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSH, 5, 5, 6, 9, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSB, 0, 5, 3, 5, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSB, 5, 5, 3, 5, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSW, 0, 5, 25, 29, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSW, 5, 5, 25, 29, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FSQRT, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FDIVS, 0, 5, 0, 1, 2, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FSUBS, 0, 5, 0, 1, 2, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FADDS, 0, 5, 0, 1, 2, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FSQRTS, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FRES, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMULS, 0, 5, 0, 1, 2, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMADDS, 0, 5, 0, 1, 2, 3, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMSUBS, 0, 5, 0, 1, 2, 3, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNMSUBS, 0, 5, 0, 1, 2, 3, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNMADDS, 0, 5, 0, 1, 2, 3, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSB1, 0, 5, 0, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSB1, 5, 5, 3, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSB1, 10, 5, 25, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSB1, 15, 5, 31, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MCRFS, 0, 5, 0, 7);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MCRFS, 5, 5, 7, 0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MCRFS, 10, 5, 5, 2);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MCRFS, 15, 5, 5, 3);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSB0, 0, 5, 0, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSB0, 5, 5, 3, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSB0, 10, 5, 25, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSB0, 15, 5, 31, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSFI, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSFI, 5, 5, 2, 6, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSFI, 10, 5, 5, 11, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSFI, 15, 5, 7, 14, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MFFS, 0, 5, 0, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSF, 0, 5, 0, 0, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSF, 5, 5, 2, 0, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSF, 10, 5, 5, 0, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTFSF, 15, 5, 7, 0, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCMPU, 0, 5, 5, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FRSP, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCTIW, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCTIWZ, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FDIV, 0, 5, 0, 1, 2, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FSUB, 0, 5, 0, 1, 2, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FADD, 0, 5, 0, 1, 2, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FSQRT, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FSEL, 0, 5, 0, 1, 2, 3, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMUL, 0, 5, 0, 1, 2, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FRSQRTE, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMSUB, 0, 5, 0, 1, 2, 3, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMADD, 0, 5, 0, 1, 2, 3, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNMSUB, 0, 5, 0, 1, 2, 3, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNMADD, 0, 5, 0, 1, 2, 3, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCMPO, 0, 5, 3, 0, 1);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNEG, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMR, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNABS, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FABS, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCFID, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCTID, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCTIW, 0, 5, 0, 1, false);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCFID, 0, 5, 0, 1, false);
PPUState input;
input.SetRandom(0x10000);
input.GPR[14] = 10;
input.GPR[21] = 15;
input.GPR[23] = 0x10000;
input.GPR[14] = 10;
input.GPR[21] = 15;
input.GPR[23] = 0x10000;
input.R_ADDR = 0x10000;
input.R_VALUE = 0x1122334455667788;
input.mem_block[0] = 0x8877665544332211;
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZ, 0, input, 5, 0, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZ, 1, input, 5, 14, 0x10000);
@ -634,6 +739,8 @@ void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter)
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZU, 0, input, 5, 14, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 0, input, 5, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 1, input, 5, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 0, input, 5, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 1, input, 5, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZUX, 0, input, 5, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 0, input, 5, 0, 0x100F0);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 1, input, 5, 14, 0x100F0);
@ -712,6 +819,8 @@ void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter)
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STB, 0, input, 3, 0, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STB, 1, input, 3, 14, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBU, 0, input, 3, 14, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 0, input, 3, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 1, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBX, 0, input, 3, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBX, 1, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBUX, 0, input, 3, 14, 23);
@ -720,6 +829,8 @@ void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter)
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHU, 0, input, 3, 14, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 0, input, 3, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 1, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 0, input, 3, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 1, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHUX, 0, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHBRX, 0, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STW, 0, input, 3, 0, 0x10000);
@ -728,18 +839,26 @@ void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter)
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWX, 0, input, 3, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWX, 1, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWUX, 0, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVLX, 0, input, 0, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVLX, 1, input, 0, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVLX, 2, input, 0, 21, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWBRX, 0, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STD, 0, input, 3, 0, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STD, 1, input, 3, 14, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDU, 0, input, 3, 14, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDX, 0, input, 3, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDX, 1, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 0, input, 3, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 1, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDUX, 0, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFS, 0, input, 3, 0, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFS, 1, input, 3, 14, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFSU, 0, input, 3, 14, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFSX, 0, input, 3, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFSX, 1, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVRX, 0, input, 0, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVRX, 1, input, 0, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVRX, 2, input, 0, 21, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFSUX, 0, input, 3, 14, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFD, 0, input, 3, 0, 0x10000);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFD, 1, input, 3, 14, 0x10000);
@ -767,6 +886,6 @@ void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter)
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(DCBZ, 0, input, 0, 23);
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(DCBZ, 1, input, 14, 23);
initial_state.Store(*ppu_state);
m_recompilation_engine.Log() << "Finished Unit Tests\n";
#endif // PPU_LLVM_RECOMPILER_UNIT_TESTS
}

View File

@ -767,7 +767,7 @@
</Link>
<Lib>
<AdditionalLibraryDirectories>..\llvm_build\Release\lib</AdditionalLibraryDirectories>
<AdditionalDependencies>LLVMJIT.lib;LLVMVectorize.lib;LLVMX86CodeGen.lib;LLVMX86Disassembler.lib;LLVMExecutionEngine.lib;LLVMAsmPrinter.lib;LLVMSelectionDAG.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMTarget.lib;LLVMX86Desc.lib;LLVMX86AsmPrinter.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMCore.lib;LLVMX86Utils.lib;LLVMMC.lib;LLVMX86Info.lib;LLVMSupport.lib</AdditionalDependencies>
<AdditionalDependencies>LLVMJIT.lib;LLVMVectorize.lib;LLVMX86CodeGen.lib;LLVMX86Disassembler.lib;LLVMExecutionEngine.lib;LLVMAsmPrinter.lib;LLVMSelectionDAG.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMTarget.lib;LLVMX86Desc.lib;LLVMX86AsmPrinter.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMCore.lib;LLVMX86Utils.lib;LLVMMC.lib;LLVMX86Info.lib;LLVMSupport.lib;LLVMMCDisassembler.lib</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />