summaryrefslogtreecommitdiff
path: root/libpcsxcore/pgxp_cpu.c
diff options
context:
space:
mode:
authoriCatButler <i.am.catbutler@gmail.com>2016-06-11 10:40:03 +0100
committeriCatButler <i.am.catbutler@gmail.com>2016-06-11 10:40:03 +0100
commitcfa7b3ad119aed09b12aa44521f70d12df234414 (patch)
treea4e81f674b9dae53a8cf634133cdd67d55b454af /libpcsxcore/pgxp_cpu.c
parentf70082329d751ee8a358437feb34134e283b27d8 (diff)
downloadpcsxr-cfa7b3ad119aed09b12aa44521f70d12df234414.tar.gz
CPU op fixes
- SH: Use appropriate masking when validating 16-bit values before storing - Shift operations: on shifts larger than 16bits, first shift elements along, then apply arithmetic for remainder
Diffstat (limited to 'libpcsxcore/pgxp_cpu.c')
-rw-r--r--libpcsxcore/pgxp_cpu.c77
1 files changed, 42 insertions, 35 deletions
diff --git a/libpcsxcore/pgxp_cpu.c b/libpcsxcore/pgxp_cpu.c
index 60e623e5..99c507be 100644
--- a/libpcsxcore/pgxp_cpu.c
+++ b/libpcsxcore/pgxp_cpu.c
@@ -455,15 +455,18 @@ void PGXP_CPU_DIV(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal)
Validate(&CPU_reg[rs(instr)], rsVal);
Validate(&CPU_reg[rt(instr)], rtVal);
- // iCB: Only require one valid input
+ //// iCB: Only require one valid input
//if (!(CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid) && (CPU_reg[rs(instr)].valid || CPU_reg[rt(instr)].valid))
//{
// MakeValid(&CPU_reg[rs(instr)], rsVal);
// MakeValid(&CPU_reg[rt(instr)], rtVal);
//}
- CPU_Lo.x = CPU_reg[rs(instr)].x / CPU_reg[rt(instr)].x;
- CPU_Hi.x = fmod(CPU_reg[rs(instr)].x, CPU_reg[rt(instr)].x);
+ float vs = CPU_reg[rs(instr)].y + (CPU_reg[rs(instr)].x / (float)(1 << 16));
+ float vt = CPU_reg[rt(instr)].y + (CPU_reg[rt(instr)].x / (float)(1 << 16));
+
+ CPU_Lo.x = vs / vt;
+ CPU_Hi.x = fmod(vs, vt);
CPU_Lo.x -= CPU_Hi.x;
CPU_Lo.valid = CPU_Hi.valid = CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid;
@@ -479,15 +482,18 @@ void PGXP_CPU_DIVU(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal)
Validate(&CPU_reg[rs(instr)], rsVal);
Validate(&CPU_reg[rt(instr)], rtVal);
- // iCB: Only require one valid input
+ //// iCB: Only require one valid input
//if (!(CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid) && (CPU_reg[rs(instr)].valid || CPU_reg[rt(instr)].valid))
//{
// MakeValid(&CPU_reg[rs(instr)], rsVal);
// MakeValid(&CPU_reg[rt(instr)], rtVal);
//}
- CPU_Lo.x = fabs(CPU_reg[rs(instr)].x) / fabs(CPU_reg[rt(instr)].x);
- CPU_Hi.x = fmod(fabs(CPU_reg[rs(instr)].x), fabs(CPU_reg[rt(instr)].x));
+ float vs = CPU_reg[rs(instr)].y + (CPU_reg[rs(instr)].x / (float)(1 << 16));
+ float vt = CPU_reg[rt(instr)].y + (CPU_reg[rt(instr)].x / (float)(1 << 16));
+
+ CPU_Lo.x = fabs(vs) / fabs(vt);
+ CPU_Hi.x = fmod(fabs(vs), fabs(vt));
CPU_Lo.x -= CPU_Hi.x;
CPU_Lo.valid = CPU_Hi.valid = CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid;
@@ -502,23 +508,23 @@ void PGXP_CPU_DIVU(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal)
void PGXP_CPU_SLL(u32 instr, u32 rdVal, u32 rtVal)
{
// Rd = Rt << Sa
+ u32 sh = sa(instr);
Validate(&CPU_reg[rt(instr)], rtVal);
CPU_reg[rd(instr)] = CPU_reg[rt(instr)];
// Shift y into x?
- if (sa(instr) == 16)
+ if (sh >= 16)
{
CPU_reg[rd(instr)].y = CPU_reg[rd(instr)].x;
CPU_reg[rd(instr)].x = 0;
CPU_reg[rd(instr)].hFlags = CPU_reg[rd(instr)].lFlags;
CPU_reg[rd(instr)].lFlags = 0;
+ sh -= 16;
}
- else
- {
- // assume multiply with no overflow
- CPU_reg[rd(instr)].x *= (float)(1 << sa(instr));
- CPU_reg[rd(instr)].y *= (float)(1 << sa(instr));
- }
+
+ // assume multiply with no overflow
+ CPU_reg[rd(instr)].x *= (float)(1 << sh);
+ CPU_reg[rd(instr)].y *= (float)(1 << sh);
CPU_reg[rd(instr)].value = rdVal;
}
@@ -526,23 +532,23 @@ void PGXP_CPU_SLL(u32 instr, u32 rdVal, u32 rtVal)
void PGXP_CPU_SRL(u32 instr, u32 rdVal, u32 rtVal)
{
// Rd = Rt >> Sa
+ u32 sh = sa(instr);
Validate(&CPU_reg[rt(instr)], rtVal);
CPU_reg[rd(instr)] = CPU_reg[rt(instr)];
// Shift x into y?
- if (sa(instr) == 16)
+ if (sh >= 16)
{
CPU_reg[rd(instr)].x = CPU_reg[rd(instr)].y;
CPU_reg[rd(instr)].y = 0;
CPU_reg[rd(instr)].lFlags = CPU_reg[rd(instr)].hFlags;
CPU_reg[rd(instr)].hFlags = 0;
+ sh -= 16;
}
- else
- {
- // assume divide with no overflow
- CPU_reg[rd(instr)].x /= (float)(1 << sa(instr));
- CPU_reg[rd(instr)].y /= (float)(1 << sa(instr));
- }
+
+ // assume divide with no overflow
+ CPU_reg[rd(instr)].x /= (float)(1 << sh);
+ CPU_reg[rd(instr)].y /= (float)(1 << sh);
CPU_reg[rd(instr)].value = rdVal;
}
@@ -559,25 +565,25 @@ void PGXP_CPU_SRA(u32 instr, u32 rdVal, u32 rtVal)
void PGXP_CPU_SLLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal)
{
// Rd = Rt << Rs
+ u32 sh = rsVal & 0x1F;
Validate(&CPU_reg[rt(instr)], rtVal);
Validate(&CPU_reg[rs(instr)], rsVal);
CPU_reg[rd(instr)] = CPU_reg[rt(instr)];
// Shift y into x?
- if ((rsVal & 0x1F) == 16)
+ if (sh >= 16)
{
CPU_reg[rd(instr)].y = CPU_reg[rd(instr)].x;
CPU_reg[rd(instr)].x = 0;
CPU_reg[rd(instr)].hFlags = CPU_reg[rd(instr)].lFlags;
CPU_reg[rd(instr)].lFlags = 0;
+ sh -= 16;
}
- else
- {
- // assume multiply with no overflow
- CPU_reg[rd(instr)].x *= (float)(1 << (rsVal & 0x1F));
- CPU_reg[rd(instr)].y *= (float)(1 << (rsVal & 0x1F));
- }
+
+ // assume multiply with no overflow
+ CPU_reg[rd(instr)].x *= (float)(1 << sh);
+ CPU_reg[rd(instr)].y *= (float)(1 << sh);
CPU_reg[rd(instr)].value = rdVal;
}
@@ -585,26 +591,26 @@ void PGXP_CPU_SLLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal)
void PGXP_CPU_SRLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal)
{
// Rd = Rt >> Sa
+ u32 sh = rsVal & 0x1F;
Validate(&CPU_reg[rt(instr)], rtVal);
Validate(&CPU_reg[rs(instr)], rsVal);
CPU_reg[rd(instr)] = CPU_reg[rt(instr)];
// Shift x into y?
- if ((rsVal & 0x1F) == 16)
+ if (sh >= 16)
{
CPU_reg[rd(instr)].x = CPU_reg[rd(instr)].y;
CPU_reg[rd(instr)].y = 0;
CPU_reg[rd(instr)].lFlags = CPU_reg[rd(instr)].hFlags;
CPU_reg[rd(instr)].hFlags = 0;
- }
- else
- {
- // assume divide with no overflow
- CPU_reg[rd(instr)].x /= (float)(1 << (rsVal & 0x1F));
- CPU_reg[rd(instr)].y /= (float)(1 << (rsVal & 0x1F));
+ sh -= 16;
}
+ // assume divide with no overflow
+ CPU_reg[rd(instr)].x /= (float)(1 << sh);
+ CPU_reg[rd(instr)].y /= (float)(1 << sh);
+
CPU_reg[rd(instr)].value = rdVal;
}
@@ -725,7 +731,8 @@ void PGXP_CPU_SWR(u32 instr, u32 rtVal, u32 addr)
// Store 16-bit
void PGXP_CPU_SH(u32 instr, u16 rtVal, u32 addr)
{
- Validate(&CPU_reg[rt(instr)], rtVal);
+ // validate and copy half value
+ MaskValidate(&CPU_reg[rt(instr)], rtVal, 0xFFFF);
WriteMem16(&CPU_reg[rt(instr)], addr);
}