diff options
| author | iCatButler <i.am.catbutler@gmail.com> | 2016-06-11 10:40:03 +0100 |
|---|---|---|
| committer | iCatButler <i.am.catbutler@gmail.com> | 2016-06-11 10:40:03 +0100 |
| commit | cfa7b3ad119aed09b12aa44521f70d12df234414 (patch) | |
| tree | a4e81f674b9dae53a8cf634133cdd67d55b454af /libpcsxcore/pgxp_cpu.c | |
| parent | f70082329d751ee8a358437feb34134e283b27d8 (diff) | |
| download | pcsxr-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.c | 77 |
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); } |
