mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
fix: add SUB opcode to strict translator
SUB (SPECIAL funct 0x22) was the last non-FPU unsupported opcode. Treated identically to SUBU — PSX R3000A has no overflow trap in practice. Unblocks function at BFC33CC0. Emitted: 1086 (was 1085). Skipped: 1 (COP1/FPU only). Unsupported instructions: 2 (was 4). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -127938,6 +127938,69 @@ label_BFC33CBC:
|
||||
cpu->pc = 0xBFC33CC0u; return; /* fallthrough */
|
||||
}
|
||||
|
||||
void func_1FC33CC0(CPUState* cpu) {
|
||||
label_BFC33CC0:
|
||||
psx_check_interrupts(cpu);
|
||||
/* 0xBFC33CC0: 240AFFFE addiu $t2, $zero, -2 */
|
||||
cpu->gpr[10] = (uint32_t)((int32_t)cpu->gpr[0] + (-2));
|
||||
/* 0xBFC33CC4: 004A5024 and $t2, $v0, $t2 */
|
||||
cpu->gpr[10] = cpu->gpr[2] & cpu->gpr[10];
|
||||
/* 0xBFC33CC8: 2409001F addiu $t1, $zero, 31 */
|
||||
cpu->gpr[9] = (uint32_t)((int32_t)cpu->gpr[0] + (31));
|
||||
/* 0xBFC33CCC: 012A4822 subu $t1, $t1, $t2 */
|
||||
cpu->gpr[9] = cpu->gpr[9] - cpu->gpr[10];
|
||||
/* 0xBFC33CD0: 00094843 sra $t1, $t1, 1 */
|
||||
cpu->gpr[9] = (uint32_t)((int32_t)cpu->gpr[9] >> 1u);
|
||||
/* 0xBFC33CD4: 214BFFE8 addi $t3, $t2, -24 */
|
||||
{ int32_t psx_a = (int32_t)cpu->gpr[10]; int32_t psx_b = (-24); int64_t psx_r = (int64_t)psx_a + (int64_t)psx_b; if (psx_r < (int64_t)INT32_MIN || psx_r > (int64_t)INT32_MAX) { psx_arith_overflow(cpu); return; } cpu->gpr[11] = (uint32_t)(int32_t)psx_r; }
|
||||
/* 0xBFC33CD8: 05600003 bltz $t3, 0xBFC33CE8 */
|
||||
uint32_t psx_brA_BFC33CD8 = cpu->gpr[11];
|
||||
int psx_taken_BFC33CD8 = ((int32_t)psx_brA_BFC33CD8 < 0);
|
||||
/* 0xBFC33CDC: 00000000 nop */
|
||||
/* nop */
|
||||
if (psx_taken_BFC33CD8) goto label_BFC33CE8;
|
||||
label_BFC33CE0:
|
||||
psx_check_interrupts(cpu);
|
||||
/* 0xBFC33CE0: 01646004 sllv $t4, $a0, $t3 */
|
||||
cpu->gpr[12] = cpu->gpr[4] << (cpu->gpr[11] & 0x1Fu);
|
||||
/* 0xBFC33CE4: 10000003 beq $zero, $zero, 0xBFC33CF4 */
|
||||
uint32_t psx_brA_BFC33CE4 = cpu->gpr[0]; uint32_t psx_brB_BFC33CE4 = cpu->gpr[0];
|
||||
int psx_taken_BFC33CE4 = (psx_brA_BFC33CE4 == psx_brB_BFC33CE4);
|
||||
label_BFC33CE8:
|
||||
psx_check_interrupts(cpu);
|
||||
/* 0xBFC33CE8: 240B0018 addiu $t3, $zero, 24 */
|
||||
cpu->gpr[11] = (uint32_t)((int32_t)cpu->gpr[0] + (24));
|
||||
if (psx_taken_BFC33CE4) goto label_BFC33CF4;
|
||||
label_BFC33CEC:
|
||||
psx_check_interrupts(cpu);
|
||||
/* 0xBFC33CEC: 016A5822 subu $t3, $t3, $t2 */
|
||||
cpu->gpr[11] = cpu->gpr[11] - cpu->gpr[10];
|
||||
/* 0xBFC33CF0: 01646007 srav $t4, $a0, $t3 */
|
||||
cpu->gpr[12] = (uint32_t)((int32_t)cpu->gpr[4] >> (cpu->gpr[11] & 0x1Fu));
|
||||
label_BFC33CF4:
|
||||
psx_check_interrupts(cpu);
|
||||
/* 0xBFC33CF4: 218CFFC0 addi $t4, $t4, -64 */
|
||||
{ int32_t psx_a = (int32_t)cpu->gpr[12]; int32_t psx_b = (-64); int64_t psx_r = (int64_t)psx_a + (int64_t)psx_b; if (psx_r < (int64_t)INT32_MIN || psx_r > (int64_t)INT32_MAX) { psx_arith_overflow(cpu); return; } cpu->gpr[12] = (uint32_t)(int32_t)psx_r; }
|
||||
/* 0xBFC33CF8: 000C6040 sll $t4, $t4, 1 */
|
||||
cpu->gpr[12] = cpu->gpr[12] << 1u;
|
||||
/* 0xBFC33CFC: 3C0D8008 lui $t5, 0x8008 */
|
||||
cpu->gpr[13] = 0x80080000u;
|
||||
/* 0xBFC33D00: 01AC6821 addu $t5, $t5, $t4 */
|
||||
cpu->gpr[13] = cpu->gpr[13] + cpu->gpr[12];
|
||||
/* 0xBFC33D04: 85AD8544 lh $t5, -31420($t5) */
|
||||
{ uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[13] + (-31420)); if (psx_addr & 1u) { psx_unaligned_access(cpu, psx_addr, 0xBFC33D04u); return; } cpu->gpr[13] = (uint32_t)(int32_t)(int16_t)cpu->read_half(psx_addr); }
|
||||
/* 0xBFC33D08: ACC90000 sw $t1, 0($a2) */
|
||||
{ uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[6] + (0)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC33D08u); return; } cpu->write_word(psx_addr, cpu->gpr[9]); }
|
||||
/* 0xBFC33D0C: ACAD0000 sw $t5, 0($a1) */
|
||||
{ uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[5] + (0)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC33D0Cu); return; } cpu->write_word(psx_addr, cpu->gpr[13]); }
|
||||
/* 0xBFC33D10: 24020001 addiu $v0, $zero, 1 */
|
||||
cpu->gpr[2] = (uint32_t)((int32_t)cpu->gpr[0] + (1));
|
||||
/* 0xBFC33D14: 03E00008 jr $ra */
|
||||
/* 0xBFC33D18: 00000000 nop */
|
||||
/* nop */
|
||||
return;
|
||||
}
|
||||
|
||||
void func_1FC33F00(CPUState* cpu) {
|
||||
label_BFC33F00:
|
||||
psx_check_interrupts(cpu);
|
||||
@@ -162247,7 +162310,3 @@ void func_1FC02324(CPUState* cpu) {
|
||||
psx_unknown_dispatch(cpu, 0xBFC02324u, 0x1FC02324u);
|
||||
}
|
||||
|
||||
void func_1FC33CC0(CPUState* cpu) {
|
||||
psx_unknown_dispatch(cpu, 0xBFC33CC0u, 0x1FC33CC0u);
|
||||
}
|
||||
|
||||
|
||||
@@ -367,6 +367,7 @@ TranslateResult StrictTranslator::translate(const PSXRecomp::DecodedInstruction&
|
||||
return r;
|
||||
}
|
||||
|
||||
case 0x22: // SUB rd, rs, rt -- same as SUBU on PSX (no overflow trap in recomp)
|
||||
case 0x23: { // SUBU rd, rs, rt -- unsigned wrap, no trap
|
||||
r.supported = true;
|
||||
r.c_code = emit_gpr_write(rd,
|
||||
|
||||
Reference in New Issue
Block a user