1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

SPU Fixes 3

Almost all implemented instructions are fixed. Partialy tested. Some
instructions are still unimplemented.
This commit is contained in:
Nekotekina 2013-12-01 21:30:40 +04:00
parent ae39d3802f
commit 1cfcc742d8

View File

@ -301,7 +301,7 @@ private:
} }
void STQX(u32 rt, u32 ra, u32 rb) void STQX(u32 rt, u32 ra, u32 rb)
{ {
u32 lsa = (CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) & 0xFFFFFFF0; u32 lsa = (CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) & 0x3fff0;
if(!CPU.IsGoodLSA(lsa)) if(!CPU.IsGoodLSA(lsa))
{ {
ConLog.Error("STQX: bad lsa (0x%x)", lsa); ConLog.Error("STQX: bad lsa (0x%x)", lsa);
@ -317,9 +317,10 @@ private:
} }
void BISL(u32 rt, u32 ra) void BISL(u32 rt, u32 ra)
{ {
CPU.SetBranch(branchTarget(CPU.GPR[ra]._u32[3], 0)); const u32 NewPC = CPU.GPR[ra]._u32[3];
CPU.GPR[rt].Reset(); CPU.GPR[rt].Reset();
CPU.GPR[rt]._u32[3] = CPU.PC + 4; CPU.GPR[rt]._u32[3] = CPU.PC + 4;
CPU.SetBranch(branchTarget(NewPC, 0));
} }
void IRET(u32 ra) void IRET(u32 ra)
{ {
@ -335,40 +336,48 @@ private:
} }
void GB(u32 rt, u32 ra) void GB(u32 rt, u32 ra)
{ {
CPU.GPR[rt].Reset();
CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[0] & 1) | CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[0] & 1) |
((CPU.GPR[ra]._u32[1] & 1) << 1) | ((CPU.GPR[ra]._u32[1] & 1) << 1) |
((CPU.GPR[ra]._u32[2] & 1) << 2) | ((CPU.GPR[ra]._u32[2] & 1) << 2) |
((CPU.GPR[ra]._u32[3] & 1) << 3); ((CPU.GPR[ra]._u32[3] & 1) << 3);
CPU.GPR[rt]._u32[2] = 0;
CPU.GPR[rt]._u64[0] = 0;
} }
void GBH(u32 rt, u32 ra) void GBH(u32 rt, u32 ra)
{ {
CPU.GPR[rt].Reset(); u32 temp = 0;
for (int h = 0; h < 8; h++) for (int h = 0; h < 8; h++)
CPU.GPR[rt]._u32[3] |= (CPU.GPR[ra]._u16[h] & 1) << h; temp |= (CPU.GPR[ra]._u16[h] & 1) << h;
CPU.GPR[rt]._u32[3] = temp;
CPU.GPR[rt]._u32[2] = 0;
CPU.GPR[rt]._u64[0] = 0;
} }
void GBB(u32 rt, u32 ra) void GBB(u32 rt, u32 ra)
{ {
CPU.GPR[rt].Reset(); u32 temp;
for (int b = 0; b < 16; b++) for (int b = 0; b < 16; b++)
CPU.GPR[rt]._u32[3] |= (CPU.GPR[ra]._u8[b] & 1) << b; temp |= (CPU.GPR[ra]._u8[b] & 1) << b;
CPU.GPR[rt]._u32[3] = temp;
CPU.GPR[rt]._u32[2] = 0;
CPU.GPR[rt]._u64[0] = 0;
} }
void FSM(u32 rt, u32 ra) void FSM(u32 rt, u32 ra)
{ {
const u32 pref = CPU.GPR[ra]._u32[3];
for (int w = 0; w < 4; w++) for (int w = 0; w < 4; w++)
CPU.GPR[rt]._u32[w] = (CPU.GPR[ra]._u32[3] & (1 << w)) ? ~0 : 0; CPU.GPR[rt]._u32[w] = (pref & (1 << w)) ? ~0 : 0;
} }
void FSMH(u32 rt, u32 ra) void FSMH(u32 rt, u32 ra)
{ {
const u32 pref = CPU.GPR[ra]._u32[3];
for (int h = 0; h < 8; h++) for (int h = 0; h < 8; h++)
CPU.GPR[rt]._u16[h] = (CPU.GPR[ra]._u32[3] & (1 << h)) ? ~0 : 0; CPU.GPR[rt]._u16[h] = (pref & (1 << h)) ? ~0 : 0;
} }
void FSMB(u32 rt, u32 ra) void FSMB(u32 rt, u32 ra)
{ {
const u32 pref = CPU.GPR[ra]._u32[3];
for (int b = 0; b < 16; b++) for (int b = 0; b < 16; b++)
CPU.GPR[rt]._u8[b] = (CPU.GPR[ra]._u32[3] & (1 << b)) ? ~0 : 0; CPU.GPR[rt]._u8[b] = (pref & (1 << b)) ? ~0 : 0;
} }
void FREST(u32 rt, u32 ra) void FREST(u32 rt, u32 ra)
{ {
@ -386,7 +395,7 @@ private:
} }
void LQX(u32 rt, u32 ra, u32 rb) void LQX(u32 rt, u32 ra, u32 rb)
{ {
u32 lsa = (CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) & 0xFFFFFFF0; u32 lsa = (CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) & 0x3fff0;
if(!CPU.IsGoodLSA(lsa)) if(!CPU.IsGoodLSA(lsa))
{ {
ConLog.Error("LQX: bad lsa (0x%x)", lsa); ConLog.Error("LQX: bad lsa (0x%x)", lsa);
@ -399,25 +408,25 @@ private:
void ROTQBYBI(u32 rt, u32 ra, u32 rb) void ROTQBYBI(u32 rt, u32 ra, u32 rb)
{ {
const int s = (CPU.GPR[rb]._u32[3] >> 3) & 0xf; const int s = (CPU.GPR[rb]._u32[3] >> 3) & 0xf;
const SPU_GPR_hdr temp = CPU.GPR[ra];
for (int b = 0; b < 16; b++) for (int b = 0; b < 16; b++)
CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[(b - s) & 0xf]; CPU.GPR[rt]._u8[b] = temp._u8[(b - s) & 0xf];
} }
void ROTQMBYBI(u32 rt, u32 ra, u32 rb) void ROTQMBYBI(u32 rt, u32 ra, u32 rb)
{ {
const int s = (0 - (CPU.GPR[rb]._u32[3] >> 3)) & 0x1f; const int s = (0 - (CPU.GPR[rb]._u32[3] >> 3)) & 0x1f;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt].Reset(); CPU.GPR[rt].Reset();
for (int b = 0; b < 16 - s; b++) for (int b = 0; b < 16 - s; b++)
CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + s]; CPU.GPR[rt]._u8[b] = temp._u8[b + s];
} }
void SHLQBYBI(u32 rt, u32 ra, u32 rb) void SHLQBYBI(u32 rt, u32 ra, u32 rb)
{ {
const int s = (CPU.GPR[rb]._u32[3] >> 3) & 0x1f; const int s = (CPU.GPR[rb]._u32[3] >> 3) & 0x1f;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt].Reset(); CPU.GPR[rt].Reset();
for (int b = s; b < 16; b++) for (int b = s; b < 16; b++)
CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b - s]; CPU.GPR[rt]._u8[b] = temp._u8[b - s];
} }
void CBX(u32 rt, u32 ra, u32 rb) void CBX(u32 rt, u32 ra, u32 rb)
{ {
@ -454,57 +463,58 @@ private:
void ROTQBI(u32 rt, u32 ra, u32 rb) void ROTQBI(u32 rt, u32 ra, u32 rb)
{ {
const int t = CPU.GPR[rb]._u32[3] & 0x7; const int t = CPU.GPR[rb]._u32[3] & 0x7;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << t) | (CPU.GPR[ra]._u32[3] >> (32 - t)); CPU.GPR[rt]._u32[0] = (temp._u32[0] << t) | (temp._u32[3] >> (32 - t));
CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << t) | (CPU.GPR[ra]._u32[0] >> (32 - t)); CPU.GPR[rt]._u32[1] = (temp._u32[1] << t) | (temp._u32[0] >> (32 - t));
CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << t) | (CPU.GPR[ra]._u32[1] >> (32 - t)); CPU.GPR[rt]._u32[2] = (temp._u32[2] << t) | (temp._u32[1] >> (32 - t));
CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] << t) | (CPU.GPR[ra]._u32[2] >> (32 - t)); CPU.GPR[rt]._u32[3] = (temp._u32[3] << t) | (temp._u32[2] >> (32 - t));
} }
void ROTQMBI(u32 rt, u32 ra, u32 rb) void ROTQMBI(u32 rt, u32 ra, u32 rb)
{ {
const int t = (0 - CPU.GPR[rb]._u32[3]) & 0x7; const int t = (0 - CPU.GPR[rb]._u32[3]) & 0x7;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] >> t) | (CPU.GPR[ra]._u32[1] << (32 - t)); CPU.GPR[rt]._u32[0] = (temp._u32[0] >> t) | (temp._u32[1] << (32 - t));
CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] >> t) | (CPU.GPR[ra]._u32[2] << (32 - t)); CPU.GPR[rt]._u32[1] = (temp._u32[1] >> t) | (temp._u32[2] << (32 - t));
CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] >> t) | (CPU.GPR[ra]._u32[3] << (32 - t)); CPU.GPR[rt]._u32[2] = (temp._u32[2] >> t) | (temp._u32[3] << (32 - t));
CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] >> t); CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] >> t);
} }
void SHLQBI(u32 rt, u32 ra, u32 rb) void SHLQBI(u32 rt, u32 ra, u32 rb)
{ {
const int t = CPU.GPR[rb]._u32[3] & 0x7; const int t = CPU.GPR[rb]._u32[3] & 0x7;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << t); CPU.GPR[rt]._u32[0] = (temp._u32[0] << t);
CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << t) | (CPU.GPR[ra]._u32[0] >> (32 - t)); CPU.GPR[rt]._u32[1] = (temp._u32[1] << t) | (temp._u32[0] >> (32 - t));
CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << t) | (CPU.GPR[ra]._u32[1] >> (32 - t)); CPU.GPR[rt]._u32[2] = (temp._u32[2] << t) | (temp._u32[1] >> (32 - t));
CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] << t) | (CPU.GPR[ra]._u32[2] >> (32 - t)); CPU.GPR[rt]._u32[3] = (temp._u32[3] << t) | (temp._u32[2] >> (32 - t));
} }
void ROTQBY(u32 rt, u32 ra, u32 rb) void ROTQBY(u32 rt, u32 ra, u32 rb)
{ {
const int s = CPU.GPR[rb]._u32[3] & 0xf; const int s = CPU.GPR[rb]._u32[3] & 0xf;
const SPU_GPR_hdr temp = CPU.GPR[ra];
for (int b = 0; b < 16; ++b) for (int b = 0; b < 16; ++b)
CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[(b - s) & 0xf]; CPU.GPR[rt]._u8[b] = temp._u8[(b - s) & 0xf];
} }
void ROTQMBY(u32 rt, u32 ra, u32 rb) void ROTQMBY(u32 rt, u32 ra, u32 rb)
{ {
const int s = (0 - CPU.GPR[rb]._u32[3]) & 0x1f; const int s = (0 - CPU.GPR[rb]._u32[3]) & 0x1f;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt].Reset(); CPU.GPR[rt].Reset();
for (int b = 0; b < 16 - s; b++) for (int b = 0; b < 16 - s; b++)
CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + s]; CPU.GPR[rt]._u8[b] = temp._u8[b + s];
} }
void SHLQBY(u32 rt, u32 ra, u32 rb) void SHLQBY(u32 rt, u32 ra, u32 rb)
{ {
const int s = CPU.GPR[rb]._u32[3] & 0x1f; const int s = CPU.GPR[rb]._u32[3] & 0x1f;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt].Reset(); CPU.GPR[rt].Reset();
for (int b = s; b < 16; b++) for (int b = s; b < 16; b++)
CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b - s]; CPU.GPR[rt]._u8[b] = temp._u8[b - s];
} }
void ORX(u32 rt, u32 ra) void ORX(u32 rt, u32 ra)
{ {
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt].Reset(); CPU.GPR[rt].Reset();
CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._u32[0] | CPU.GPR[ra]._u32[1] | CPU.GPR[ra]._u32[2] | CPU.GPR[ra]._u32[3]; CPU.GPR[rt]._u32[3] = temp._u32[0] | temp._u32[1] | temp._u32[2] | temp._u32[3];
} }
void CBD(u32 rt, u32 ra, s32 i7) void CBD(u32 rt, u32 ra, s32 i7)
{ {
@ -541,52 +551,52 @@ private:
void ROTQBII(u32 rt, u32 ra, s32 i7) void ROTQBII(u32 rt, u32 ra, s32 i7)
{ {
const int s = i7 & 0x7; const int s = i7 & 0x7;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << s) | (CPU.GPR[ra]._u32[3] >> (32 - s)); CPU.GPR[rt]._u32[0] = (temp._u32[0] << s) | (temp._u32[3] >> (32 - s));
CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << s) | (CPU.GPR[ra]._u32[0] >> (32 - s)); CPU.GPR[rt]._u32[1] = (temp._u32[1] << s) | (temp._u32[0] >> (32 - s));
CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << s) | (CPU.GPR[ra]._u32[1] >> (32 - s)); CPU.GPR[rt]._u32[2] = (temp._u32[2] << s) | (temp._u32[1] >> (32 - s));
CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] << s) | (CPU.GPR[ra]._u32[2] >> (32 - s)); CPU.GPR[rt]._u32[3] = (temp._u32[3] << s) | (temp._u32[2] >> (32 - s));
} }
void ROTQMBII(u32 rt, u32 ra, s32 i7) void ROTQMBII(u32 rt, u32 ra, s32 i7)
{ {
const int s = (0 - i7) & 0x7; const int s = (0 - i7) & 0x7;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] >> s) | (CPU.GPR[ra]._u32[1] << (32 - s)); CPU.GPR[rt]._u32[0] = (temp._u32[0] >> s) | (temp._u32[1] << (32 - s));
CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] >> s) | (CPU.GPR[ra]._u32[2] << (32 - s)); CPU.GPR[rt]._u32[1] = (temp._u32[1] >> s) | (temp._u32[2] << (32 - s));
CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] >> s) | (CPU.GPR[ra]._u32[3] << (32 - s)); CPU.GPR[rt]._u32[2] = (temp._u32[2] >> s) | (temp._u32[3] << (32 - s));
CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] >> s); CPU.GPR[rt]._u32[3] = (temp._u32[3] >> s);
} }
void SHLQBII(u32 rt, u32 ra, s32 i7) void SHLQBII(u32 rt, u32 ra, s32 i7)
{ {
const int s = i7 & 0x7; const int s = i7 & 0x7;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << s); CPU.GPR[rt]._u32[0] = (temp._u32[0] << s);
CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << s) | (CPU.GPR[ra]._u32[0] >> (32 - s)); CPU.GPR[rt]._u32[1] = (temp._u32[1] << s) | (temp._u32[0] >> (32 - s));
CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << s) | (CPU.GPR[ra]._u32[1] >> (32 - s)); CPU.GPR[rt]._u32[2] = (temp._u32[2] << s) | (temp._u32[1] >> (32 - s));
CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] << s) | (CPU.GPR[ra]._u32[2] >> (32 - s)); CPU.GPR[rt]._u32[3] = (temp._u32[3] << s) | (temp._u32[2] >> (32 - s));
} }
void ROTQBYI(u32 rt, u32 ra, s32 i7) void ROTQBYI(u32 rt, u32 ra, s32 i7)
{ {
const int s = i7 & 0xf; const int s = i7 & 0xf;
const SPU_GPR_hdr temp = CPU.GPR[ra];
for (int b = 0; b < 16; b++) for (int b = 0; b < 16; b++)
CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[(b - s) & 0xf]; CPU.GPR[rt]._u8[b] = temp._u8[(b - s) & 0xf];
} }
void ROTQMBYI(u32 rt, u32 ra, s32 i7) void ROTQMBYI(u32 rt, u32 ra, s32 i7)
{ {
const int s = (0 - i7) & 0x1f; const int s = (0 - i7) & 0x1f;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt].Reset(); CPU.GPR[rt].Reset();
for (int b = 0; b < 16 - s; b++) for (int b = 0; b < 16 - s; b++)
CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + s]; CPU.GPR[rt]._u8[b] = temp._u8[b + s];
} }
void SHLQBYI(u32 rt, u32 ra, s32 i7) void SHLQBYI(u32 rt, u32 ra, s32 i7)
{ {
const int s = i7 & 0x1f; const int s = i7 & 0x1f;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt].Reset(); CPU.GPR[rt].Reset();
for (int b = s; b < 16; b++) for (int b = s; b < 16; b++)
CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b - s]; CPU.GPR[rt]._u8[b] = temp._u8[b - s];
} }
void NOP(u32 rt) void NOP(u32 rt)
{ {
@ -618,10 +628,12 @@ private:
} }
void SUMB(u32 rt, u32 ra, u32 rb) void SUMB(u32 rt, u32 ra, u32 rb)
{ {
const SPU_GPR_hdr _a = CPU.GPR[ra];
const SPU_GPR_hdr _b = CPU.GPR[rb];
for (int w = 0; w < 4; w++) for (int w = 0; w < 4; w++)
{ {
CPU.GPR[rt]._u16[w*2] = CPU.GPR[ra]._u8[w*4] + CPU.GPR[ra]._u8[w*4 + 1] + CPU.GPR[ra]._u8[w*4 + 2] + CPU.GPR[ra]._u8[w*4 + 3]; CPU.GPR[rt]._u16[w*2] = _a._u8[w*4] + _a._u8[w*4 + 1] + _a._u8[w*4 + 2] + _a._u8[w*4 + 3];
CPU.GPR[rt]._u16[w*2 + 1] = CPU.GPR[rb]._u8[w*4] + CPU.GPR[rb]._u8[w*4 + 1] + CPU.GPR[rb]._u8[w*4 + 2] + CPU.GPR[rb]._u8[w*4 + 3]; CPU.GPR[rt]._u16[w*2 + 1] = _b._u8[w*4] + _b._u8[w*4 + 1] + _b._u8[w*4 + 2] + _b._u8[w*4 + 3];
} }
} }
//HGT uses signed values. HLGT uses unsigned values //HGT uses signed values. HLGT uses unsigned values
@ -654,11 +666,11 @@ private:
} }
void CNTB(u32 rt, u32 ra) void CNTB(u32 rt, u32 ra)
{ {
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt].Reset(); CPU.GPR[rt].Reset();
for (int b = 0; b < 16; b++) for (int b = 0; b < 16; b++)
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
CPU.GPR[rt]._u8[b] += (CPU.GPR[ra]._u8[b] & (1 << i)) ? 1 : 0; CPU.GPR[rt]._u8[b] += (temp._u8[b] & (1 << i)) ? 1 : 0;
} }
void XSBH(u32 rt, u32 ra) void XSBH(u32 rt, u32 ra)
{ {
@ -851,50 +863,51 @@ private:
const u64 DoubleExpMask = 0x7ff0000000000000; const u64 DoubleExpMask = 0x7ff0000000000000;
const u64 DoubleFracMask = 0x000fffffffffffff; const u64 DoubleFracMask = 0x000fffffffffffff;
const u64 DoubleSignMask = 0x8000000000000000; const u64 DoubleSignMask = 0x8000000000000000;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt].Reset(); CPU.GPR[rt].Reset();
if (i7 & 1) //Negative Denorm Check (-, exp is zero, frac is non-zero) if (i7 & 1) //Negative Denorm Check (-, exp is zero, frac is non-zero)
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
if (CPU.GPR[ra]._u64[i] & DoubleFracMask) if (temp._u64[i] & DoubleFracMask)
if (CPU.GPR[ra]._u64[i] & DoubleSignMask & DoubleExpMask == DoubleSignMask) if (temp._u64[i] & DoubleSignMask & DoubleExpMask == DoubleSignMask)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
} }
if (i7 & 2) //Positive Denorm Check (+, exp is zero, frac is non-zero) if (i7 & 2) //Positive Denorm Check (+, exp is zero, frac is non-zero)
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
if (CPU.GPR[ra]._u64[i] & DoubleFracMask) if (temp._u64[i] & DoubleFracMask)
if (CPU.GPR[ra]._u64[i] & DoubleSignMask & DoubleExpMask == 0) if (temp._u64[i] & DoubleSignMask & DoubleExpMask == 0)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
} }
if (i7 & 4) //Negative Zero Check (-, exp is zero, frac is zero) if (i7 & 4) //Negative Zero Check (-, exp is zero, frac is zero)
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
if (CPU.GPR[ra]._u64[i] == DoubleSignMask) if (temp._u64[i] == DoubleSignMask)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
} }
if (i7 & 8) //Positive Zero Check (+, exp is zero, frac is zero) if (i7 & 8) //Positive Zero Check (+, exp is zero, frac is zero)
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
if (CPU.GPR[ra]._u64[i] == 0) if (temp._u64[i] == 0)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
} }
if (i7 & 16) //Negative Infinity Check (-, exp is 0x7ff, frac is zero) if (i7 & 16) //Negative Infinity Check (-, exp is 0x7ff, frac is zero)
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
if (CPU.GPR[ra]._u64[i] == DoubleSignMask & DoubleExpMask) if (temp._u64[i] == DoubleSignMask & DoubleExpMask)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
} }
if (i7 & 32) //Positive Infinity Check (+, exp is 0x7ff, frac is zero) if (i7 & 32) //Positive Infinity Check (+, exp is 0x7ff, frac is zero)
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
if (CPU.GPR[ra]._u64[i] == DoubleExpMask) if (temp._u64[i] == DoubleExpMask)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
} }
if (i7 & 64) //Not-a-Number Check (any sign, exp is 0x7ff, frac is non-zero) if (i7 & 64) //Not-a-Number Check (any sign, exp is 0x7ff, frac is non-zero)
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
if (CPU.GPR[ra]._u64[i] & DoubleFracMask) if (temp._u64[i] & DoubleFracMask)
if (CPU.GPR[ra]._u64[i] & DoubleExpMask == DoubleExpMask) if (temp._u64[i] & DoubleExpMask == DoubleExpMask)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
} }
} }
@ -992,7 +1005,7 @@ private:
} }
void STQA(u32 rt, s32 i16) void STQA(u32 rt, s32 i16)
{ {
u32 lsa = (i16 << 2) & 0xFFFFFFF0; u32 lsa = (i16 << 2) & 0x3fff0;
if(!CPU.IsGoodLSA(lsa)) if(!CPU.IsGoodLSA(lsa))
{ {
ConLog.Error("STQA: bad lsa (0x%x)", lsa); ConLog.Error("STQA: bad lsa (0x%x)", lsa);
@ -1019,7 +1032,7 @@ private:
} }
void STQR(u32 rt, s32 i16) void STQR(u32 rt, s32 i16)
{ {
u32 lsa = branchTarget(CPU.PC, (i16 << 2) & 0xFFFFFFF0); u32 lsa = branchTarget(CPU.PC, i16) & 0xFFFFFFF0;
if(!CPU.IsGoodLSA(lsa)) if(!CPU.IsGoodLSA(lsa))
{ {
ConLog.Error("STQR: bad lsa (0x%x)", lsa); ConLog.Error("STQR: bad lsa (0x%x)", lsa);
@ -1035,7 +1048,7 @@ private:
} }
void LQA(u32 rt, s32 i16) void LQA(u32 rt, s32 i16)
{ {
u32 lsa = (i16 << 2) & 0xFFFFFFF0; u32 lsa = (i16 << 2) & 0x3fff0;
if(!CPU.IsGoodLSA(lsa)) if(!CPU.IsGoodLSA(lsa))
{ {
ConLog.Error("LQA: bad lsa (0x%x)", lsa); ConLog.Error("LQA: bad lsa (0x%x)", lsa);
@ -1047,9 +1060,9 @@ private:
} }
void BRASL(u32 rt, s32 i16) void BRASL(u32 rt, s32 i16)
{ {
CPU.SetBranch(branchTarget(0, i16));
CPU.GPR[rt].Reset(); CPU.GPR[rt].Reset();
CPU.GPR[rt]._u32[3] = CPU.PC + 4; CPU.GPR[rt]._u32[3] = CPU.PC + 4;
CPU.SetBranch(branchTarget(0, i16));
} }
void BR(s32 i16) void BR(s32 i16)
{ {
@ -1073,13 +1086,13 @@ private:
} }
void BRSL(u32 rt, s32 i16) void BRSL(u32 rt, s32 i16)
{ {
CPU.SetBranch(branchTarget(CPU.PC, i16));
CPU.GPR[rt].Reset(); CPU.GPR[rt].Reset();
CPU.GPR[rt]._u32[3] = CPU.PC + 4; CPU.GPR[rt]._u32[3] = CPU.PC + 4;
CPU.SetBranch(branchTarget(CPU.PC, i16));
} }
void LQR(u32 rt, s32 i16) void LQR(u32 rt, s32 i16)
{ {
u32 lsa = branchTarget(CPU.PC, i16); u32 lsa = branchTarget(CPU.PC, i16) & 0xFFFFFFF0;
if(!CPU.IsGoodLSA(lsa)) if(!CPU.IsGoodLSA(lsa))
{ {
ConLog.Error("LQR: bad lsa (0x%x)", lsa); ConLog.Error("LQR: bad lsa (0x%x)", lsa);
@ -1164,9 +1177,9 @@ private:
for(u32 h = 0; h < 8; ++h) for(u32 h = 0; h < 8; ++h)
CPU.GPR[rt]._i16[h] = CPU.GPR[ra]._i16[h] + i10; CPU.GPR[rt]._i16[h] = CPU.GPR[ra]._i16[h] + i10;
} }
void STQD(u32 rt, s32 i10, u32 ra) //hello_world addr=0x178, value won't be saved void STQD(u32 rt, s32 i10, u32 ra) //i10 is shifted left by 4 while decoding
{ {
const u32 lsa = (CPU.GPR[ra]._u32[3] + (i10 << 4)) & 0xFFFFFFF0; const u32 lsa = (CPU.GPR[ra]._i32[3] + i10) & 0x3fff0;
if(!CPU.IsGoodLSA(lsa)) if(!CPU.IsGoodLSA(lsa))
{ {
ConLog.Error("STQD: bad lsa (0x%x)", lsa); ConLog.Error("STQD: bad lsa (0x%x)", lsa);
@ -1175,9 +1188,9 @@ private:
} }
CPU.WriteLS128(lsa, CPU.GPR[rt]._u128); CPU.WriteLS128(lsa, CPU.GPR[rt]._u128);
} }
void LQD(u32 rt, s32 i10, u32 ra) void LQD(u32 rt, s32 i10, u32 ra) //i10 is shifted left by 4 while decoding
{ {
const u32 lsa = (CPU.GPR[ra]._u32[3] + (i10 << 4)) & 0xFFFFFFF0; const u32 lsa = (CPU.GPR[ra]._i32[3] + i10) & 0x3fff0;
if(!CPU.IsGoodLSA(lsa)) if(!CPU.IsGoodLSA(lsa))
{ {
ConLog.Error("LQD: bad lsa (0x%x)", lsa); ConLog.Error("LQD: bad lsa (0x%x)", lsa);
@ -1277,7 +1290,7 @@ private:
//0 - 6 //0 - 6
void HBRA(s32 ro, s32 i16) void HBRA(s32 ro, s32 i16)
{ { //i16 is shifted left by 2 while decoding
} }
void HBRR(s32 ro, s32 i16) void HBRR(s32 ro, s32 i16)
{ {
@ -1293,15 +1306,17 @@ private:
//0 - 3 //0 - 3
void SELB(u32 rt, u32 ra, u32 rb, u32 rc) void SELB(u32 rt, u32 ra, u32 rb, u32 rc)
{ {
for(u32 i = 0; i < 4; ++i) for(u64 i = 0; i < 2; ++i)
{ {
CPU.GPR[rt]._u32[i] = CPU.GPR[rt]._u64[i] =
( CPU.GPR[rc]._u32[i] & CPU.GPR[rb]._u32[i]) | ( CPU.GPR[rc]._u64[i] & CPU.GPR[rb]._u64[i]) |
(~CPU.GPR[rc]._u32[i] & CPU.GPR[ra]._u32[i]); (~CPU.GPR[rc]._u64[i] & CPU.GPR[ra]._u64[i]);
} }
} }
void SHUFB(u32 rt, u32 ra, u32 rb, u32 rc) void SHUFB(u32 rt, u32 ra, u32 rb, u32 rc)
{ {
const SPU_GPR_hdr _a = CPU.GPR[ra];
const SPU_GPR_hdr _b = CPU.GPR[rb];
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
u8 b = CPU.GPR[rc]._u8[i]; u8 b = CPU.GPR[rc]._u8[i];
@ -1315,9 +1330,9 @@ private:
CPU.GPR[rt]._u8[i] = 0x00; CPU.GPR[rt]._u8[i] = 0x00;
} else { } else {
if(b & 0x10) if(b & 0x10)
CPU.GPR[rt]._u8[i] = CPU.GPR[rb]._u8[15 - (b & 0x0F)]; CPU.GPR[rt]._u8[i] = _b._u8[15 - (b & 0x0F)];
else else
CPU.GPR[rt]._u8[i] = CPU.GPR[ra]._u8[15 - (b & 0x0F)]; CPU.GPR[rt]._u8[i] = _a._u8[15 - (b & 0x0F)];
} }
} }
} }