diff --git a/generated/SCPH1001_dispatch.c b/generated/SCPH1001_dispatch.c index aea2c958..4434aaa2 100644 --- a/generated/SCPH1001_dispatch.c +++ b/generated/SCPH1001_dispatch.c @@ -12,6 +12,7 @@ extern void psx_unknown_dispatch(CPUState* cpu, uint32_t addr, uint32_t phys); extern void psx_check_interrupts(CPUState* cpu); extern void psx_restore_state_escape(void); +extern void gte_execute(CPUState* cpu, uint32_t cmd); extern uint32_t g_debug_current_func_addr; extern void debug_server_trace_dispatch(uint32_t func_addr); diff --git a/generated/SCPH1001_full.c b/generated/SCPH1001_full.c index 91744cc9..79ccdaf3 100644 --- a/generated/SCPH1001_full.c +++ b/generated/SCPH1001_full.c @@ -10,6 +10,7 @@ extern void psx_dispatch(CPUState* cpu, uint32_t addr); extern void psx_unknown_dispatch(CPUState* cpu, uint32_t addr, uint32_t phys); extern void psx_check_interrupts(CPUState* cpu); extern void psx_restore_state_escape(void); +extern void gte_execute(CPUState* cpu, uint32_t cmd); void func_1FC00000(CPUState* cpu); void func_1FC00180(CPUState* cpu); @@ -127738,6 +127739,63 @@ label_BFC336E4: return; } +void func_1FC336F0(CPUState* cpu) { +label_BFC336F0: + psx_check_interrupts(cpu); + /* 0xBFC336F0: 00000000 nop */ + /* nop */ + /* 0xBFC336F4: 40026000 mfc0 $v0, cop0[12] */ + cpu->gpr[2] = cpu->cop0[12]; + /* 0xBFC336F8: 3C034000 lui $v1, 0x4000 */ + cpu->gpr[3] = 0x40000000u; + /* 0xBFC336FC: 00431025 or $v0, $v0, $v1 */ + cpu->gpr[2] = cpu->gpr[2] | cpu->gpr[3]; + /* 0xBFC33700: 40826000 mtc0 $v0, cop0[12] */ + cpu->cop0[12] = cpu->gpr[2]; + /* 0xBFC33704: 00000000 nop */ + /* nop */ + /* 0xBFC33708: 24080155 addiu $t0, $zero, 341 */ + cpu->gpr[8] = (uint32_t)((int32_t)cpu->gpr[0] + (341)); + /* 0xBFC3370C: 48C8E800 ctc2 $t0, gte_ctrl[29] */ + cpu->gte_ctrl[29] = cpu->gpr[8]; + /* 0xBFC33710: 00000000 nop */ + /* nop */ + /* 0xBFC33714: 24080100 addiu $t0, $zero, 256 */ + cpu->gpr[8] = (uint32_t)((int32_t)cpu->gpr[0] + (256)); + /* 0xBFC33718: 48C8F000 ctc2 $t0, gte_ctrl[30] */ + cpu->gte_ctrl[30] = cpu->gpr[8]; + /* 0xBFC3371C: 00000000 nop */ + /* nop */ + /* 0xBFC33720: 240803E8 addiu $t0, $zero, 1000 */ + cpu->gpr[8] = (uint32_t)((int32_t)cpu->gpr[0] + (1000)); + /* 0xBFC33724: 48C8D000 ctc2 $t0, gte_ctrl[26] */ + cpu->gte_ctrl[26] = cpu->gpr[8]; + /* 0xBFC33728: 00000000 nop */ + /* nop */ + /* 0xBFC3372C: 2408EF9E addiu $t0, $zero, -4194 */ + cpu->gpr[8] = (uint32_t)((int32_t)cpu->gpr[0] + (-4194)); + /* 0xBFC33730: 48C8D800 ctc2 $t0, gte_ctrl[27] */ + cpu->gte_ctrl[27] = cpu->gpr[8]; + /* 0xBFC33734: 00000000 nop */ + /* nop */ + /* 0xBFC33738: 3C080140 lui $t0, 0x140 */ + cpu->gpr[8] = 0x01400000u; + /* 0xBFC3373C: 48C8E000 ctc2 $t0, gte_ctrl[28] */ + cpu->gte_ctrl[28] = cpu->gpr[8]; + /* 0xBFC33740: 00000000 nop */ + /* nop */ + /* 0xBFC33744: 48C0C000 ctc2 $zero, gte_ctrl[24] */ + cpu->gte_ctrl[24] = cpu->gpr[0]; + /* 0xBFC33748: 48C0C800 ctc2 $zero, gte_ctrl[25] */ + cpu->gte_ctrl[25] = cpu->gpr[0]; + /* 0xBFC3374C: 00000000 nop */ + /* nop */ + /* 0xBFC33750: 03E00008 jr $ra */ + /* 0xBFC33754: 00000000 nop */ + /* nop */ + return; +} + void func_1FC339F0(CPUState* cpu) { label_BFC339F0: psx_check_interrupts(cpu); @@ -127846,6 +127904,132 @@ label_BFC33A58: return; } +void func_1FC33C98(CPUState* cpu) { +label_BFC33C98: + psx_check_interrupts(cpu); + /* 0xBFC33C98: 4884F000 mtc2 $a0, gte_data[30] */ + cpu->gte_data[30] = cpu->gpr[4]; + /* 0xBFC33C9C: 00000000 nop */ + /* nop */ + /* 0xBFC33CA0: 00000000 nop */ + /* nop */ + /* 0xBFC33CA4: 4802F800 mfc2 $v0, gte_data[31] */ + cpu->gpr[2] = cpu->gte_data[31]; + /* 0xBFC33CA8: 24010020 addiu $at, $zero, 32 */ + cpu->gpr[1] = (uint32_t)((int32_t)cpu->gpr[0] + (32)); + /* 0xBFC33CAC: 1041001B beq $v0, $at, 0xBFC33D1C */ + uint32_t psx_brA_BFC33CAC = cpu->gpr[2]; uint32_t psx_brB_BFC33CAC = cpu->gpr[1]; + int psx_taken_BFC33CAC = (psx_brA_BFC33CAC == psx_brB_BFC33CAC); + /* 0xBFC33CB0: 00000000 nop */ + /* nop */ + if (psx_taken_BFC33CAC) { cpu->pc = 0xBFC33D1Cu; return; } +label_BFC33CB4: + psx_check_interrupts(cpu); + /* 0xBFC33CB4: 10400019 beq $v0, $zero, 0xBFC33D1C */ + uint32_t psx_brA_BFC33CB4 = cpu->gpr[2]; uint32_t psx_brB_BFC33CB4 = cpu->gpr[0]; + int psx_taken_BFC33CB4 = (psx_brA_BFC33CB4 == psx_brB_BFC33CB4); + /* 0xBFC33CB8: 00000000 nop */ + /* nop */ + if (psx_taken_BFC33CB4) { cpu->pc = 0xBFC33D1Cu; return; } +label_BFC33CBC: + psx_check_interrupts(cpu); + /* 0xBFC33CBC: 30480001 andi $t0, $v0, 0x1 */ + cpu->gpr[8] = cpu->gpr[2] & 0x1u; + cpu->pc = 0xBFC33CC0u; return; /* fallthrough */ +} + +void func_1FC33F00(CPUState* cpu) { +label_BFC33F00: + psx_check_interrupts(cpu); + /* 0xBFC33F00: 00042100 sll $a0, $a0, 4 */ + cpu->gpr[4] = cpu->gpr[4] << 4u; + /* 0xBFC33F04: 00052900 sll $a1, $a1, 4 */ + cpu->gpr[5] = cpu->gpr[5] << 4u; + /* 0xBFC33F08: 00063100 sll $a2, $a2, 4 */ + cpu->gpr[6] = cpu->gpr[6] << 4u; + /* 0xBFC33F0C: 48C46800 ctc2 $a0, gte_ctrl[13] */ + cpu->gte_ctrl[13] = cpu->gpr[4]; + /* 0xBFC33F10: 48C57000 ctc2 $a1, gte_ctrl[14] */ + cpu->gte_ctrl[14] = cpu->gpr[5]; + /* 0xBFC33F14: 48C67800 ctc2 $a2, gte_ctrl[15] */ + cpu->gte_ctrl[15] = cpu->gpr[6]; + /* 0xBFC33F18: 03E00008 jr $ra */ + /* 0xBFC33F1C: 00000000 nop */ + /* nop */ + return; +} + +void func_1FC33F20(CPUState* cpu) { +label_BFC33F20: + psx_check_interrupts(cpu); + /* 0xBFC33F20: 00042100 sll $a0, $a0, 4 */ + cpu->gpr[4] = cpu->gpr[4] << 4u; + /* 0xBFC33F24: 00052900 sll $a1, $a1, 4 */ + cpu->gpr[5] = cpu->gpr[5] << 4u; + /* 0xBFC33F28: 00063100 sll $a2, $a2, 4 */ + cpu->gpr[6] = cpu->gpr[6] << 4u; + /* 0xBFC33F2C: 48C4A800 ctc2 $a0, gte_ctrl[21] */ + cpu->gte_ctrl[21] = cpu->gpr[4]; + /* 0xBFC33F30: 48C5B000 ctc2 $a1, gte_ctrl[22] */ + cpu->gte_ctrl[22] = cpu->gpr[5]; + /* 0xBFC33F34: 48C6B800 ctc2 $a2, gte_ctrl[23] */ + cpu->gte_ctrl[23] = cpu->gpr[6]; + /* 0xBFC33F38: 03E00008 jr $ra */ + /* 0xBFC33F3C: 00000000 nop */ + /* nop */ + return; +} + +void func_1FC33FB4(CPUState* cpu) { +label_BFC33FB4: + psx_check_interrupts(cpu); + /* 0xBFC33FB4: 00042400 sll $a0, $a0, 16 */ + cpu->gpr[4] = cpu->gpr[4] << 16u; + /* 0xBFC33FB8: 00052C00 sll $a1, $a1, 16 */ + cpu->gpr[5] = cpu->gpr[5] << 16u; + /* 0xBFC33FBC: 48C4C000 ctc2 $a0, gte_ctrl[24] */ + cpu->gte_ctrl[24] = cpu->gpr[4]; + /* 0xBFC33FC0: 48C5C800 ctc2 $a1, gte_ctrl[25] */ + cpu->gte_ctrl[25] = cpu->gpr[5]; + /* 0xBFC33FC4: 03E00008 jr $ra */ + /* 0xBFC33FC8: 00000000 nop */ + /* nop */ + return; +} + +void func_1FC33FCC(CPUState* cpu) { +label_BFC33FCC: + psx_check_interrupts(cpu); + /* 0xBFC33FCC: 48C4D000 ctc2 $a0, gte_ctrl[26] */ + cpu->gte_ctrl[26] = cpu->gpr[4]; + /* 0xBFC33FD0: 03E00008 jr $ra */ + /* 0xBFC33FD4: 00000000 nop */ + /* nop */ + return; +} + +void func_1FC33FD8(CPUState* cpu) { +label_BFC33FD8: + psx_check_interrupts(cpu); + /* 0xBFC33FD8: 48C4D800 ctc2 $a0, gte_ctrl[27] */ + cpu->gte_ctrl[27] = cpu->gpr[4]; + /* 0xBFC33FDC: 03E00008 jr $ra */ + /* 0xBFC33FE0: 00000000 nop */ + /* nop */ + return; +} + +void func_1FC33FE4(CPUState* cpu) { +label_BFC33FE4: + psx_check_interrupts(cpu); + /* 0xBFC33FE4: 48C4E000 ctc2 $a0, gte_ctrl[28] */ + cpu->gte_ctrl[28] = cpu->gpr[4]; + /* 0xBFC33FE8: 03E00008 jr $ra */ + /* 0xBFC33FEC: 00000000 nop */ + /* nop */ + return; +} + void func_1FC34160(CPUState* cpu) { label_BFC34160: psx_check_interrupts(cpu); @@ -130027,6 +130211,281 @@ label_BFC359B4: return; } +void func_1FC35AD8(CPUState* cpu) { +label_BFC35AD8: + psx_check_interrupts(cpu); + /* 0xBFC35AD8: 8C880000 lw $t0, 0($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (0)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35AD8u); return; } cpu->gpr[8] = cpu->read_word(psx_addr); } + /* 0xBFC35ADC: 8C890004 lw $t1, 4($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (4)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35ADCu); return; } cpu->gpr[9] = cpu->read_word(psx_addr); } + /* 0xBFC35AE0: 8C8A0008 lw $t2, 8($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (8)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35AE0u); return; } cpu->gpr[10] = cpu->read_word(psx_addr); } + /* 0xBFC35AE4: 8C8B000C lw $t3, 12($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (12)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35AE4u); return; } cpu->gpr[11] = cpu->read_word(psx_addr); } + /* 0xBFC35AE8: 8C8C0010 lw $t4, 16($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (16)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35AE8u); return; } cpu->gpr[12] = cpu->read_word(psx_addr); } + /* 0xBFC35AEC: 48C80000 ctc2 $t0, gte_ctrl[0] */ + cpu->gte_ctrl[0] = cpu->gpr[8]; + /* 0xBFC35AF0: 48C90800 ctc2 $t1, gte_ctrl[1] */ + cpu->gte_ctrl[1] = cpu->gpr[9]; + /* 0xBFC35AF4: 48CA1000 ctc2 $t2, gte_ctrl[2] */ + cpu->gte_ctrl[2] = cpu->gpr[10]; + /* 0xBFC35AF8: 48CB1800 ctc2 $t3, gte_ctrl[3] */ + cpu->gte_ctrl[3] = cpu->gpr[11]; + /* 0xBFC35AFC: 48CC2000 ctc2 $t4, gte_ctrl[4] */ + cpu->gte_ctrl[4] = cpu->gpr[12]; + /* 0xBFC35B00: 03E00008 jr $ra */ + /* 0xBFC35B04: 00000000 nop */ + /* nop */ + return; +} + +void func_1FC35B08(CPUState* cpu) { +label_BFC35B08: + psx_check_interrupts(cpu); + /* 0xBFC35B08: 8C880000 lw $t0, 0($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (0)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B08u); return; } cpu->gpr[8] = cpu->read_word(psx_addr); } + /* 0xBFC35B0C: 8C890004 lw $t1, 4($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (4)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B0Cu); return; } cpu->gpr[9] = cpu->read_word(psx_addr); } + /* 0xBFC35B10: 8C8A0008 lw $t2, 8($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (8)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B10u); return; } cpu->gpr[10] = cpu->read_word(psx_addr); } + /* 0xBFC35B14: 8C8B000C lw $t3, 12($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (12)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B14u); return; } cpu->gpr[11] = cpu->read_word(psx_addr); } + /* 0xBFC35B18: 8C8C0010 lw $t4, 16($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (16)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B18u); return; } cpu->gpr[12] = cpu->read_word(psx_addr); } + /* 0xBFC35B1C: 48C84000 ctc2 $t0, gte_ctrl[8] */ + cpu->gte_ctrl[8] = cpu->gpr[8]; + /* 0xBFC35B20: 48C94800 ctc2 $t1, gte_ctrl[9] */ + cpu->gte_ctrl[9] = cpu->gpr[9]; + /* 0xBFC35B24: 48CA5000 ctc2 $t2, gte_ctrl[10] */ + cpu->gte_ctrl[10] = cpu->gpr[10]; + /* 0xBFC35B28: 48CB5800 ctc2 $t3, gte_ctrl[11] */ + cpu->gte_ctrl[11] = cpu->gpr[11]; + /* 0xBFC35B2C: 48CC6000 ctc2 $t4, gte_ctrl[12] */ + cpu->gte_ctrl[12] = cpu->gpr[12]; + /* 0xBFC35B30: 03E00008 jr $ra */ + /* 0xBFC35B34: 00000000 nop */ + /* nop */ + return; +} + +void func_1FC35B38(CPUState* cpu) { +label_BFC35B38: + psx_check_interrupts(cpu); + /* 0xBFC35B38: 8C880000 lw $t0, 0($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (0)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B38u); return; } cpu->gpr[8] = cpu->read_word(psx_addr); } + /* 0xBFC35B3C: 8C890004 lw $t1, 4($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (4)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B3Cu); return; } cpu->gpr[9] = cpu->read_word(psx_addr); } + /* 0xBFC35B40: 8C8A0008 lw $t2, 8($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (8)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B40u); return; } cpu->gpr[10] = cpu->read_word(psx_addr); } + /* 0xBFC35B44: 8C8B000C lw $t3, 12($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (12)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B44u); return; } cpu->gpr[11] = cpu->read_word(psx_addr); } + /* 0xBFC35B48: 8C8C0010 lw $t4, 16($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (16)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B48u); return; } cpu->gpr[12] = cpu->read_word(psx_addr); } + /* 0xBFC35B4C: 48C88000 ctc2 $t0, gte_ctrl[16] */ + cpu->gte_ctrl[16] = cpu->gpr[8]; + /* 0xBFC35B50: 48C98800 ctc2 $t1, gte_ctrl[17] */ + cpu->gte_ctrl[17] = cpu->gpr[9]; + /* 0xBFC35B54: 48CA9000 ctc2 $t2, gte_ctrl[18] */ + cpu->gte_ctrl[18] = cpu->gpr[10]; + /* 0xBFC35B58: 48CB9800 ctc2 $t3, gte_ctrl[19] */ + cpu->gte_ctrl[19] = cpu->gpr[11]; + /* 0xBFC35B5C: 48CCA000 ctc2 $t4, gte_ctrl[20] */ + cpu->gte_ctrl[20] = cpu->gpr[12]; + /* 0xBFC35B60: 03E00008 jr $ra */ + /* 0xBFC35B64: 00000000 nop */ + /* nop */ + return; +} + +void func_1FC35B68(CPUState* cpu) { +label_BFC35B68: + psx_check_interrupts(cpu); + /* 0xBFC35B68: 8C880014 lw $t0, 20($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (20)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B68u); return; } cpu->gpr[8] = cpu->read_word(psx_addr); } + /* 0xBFC35B6C: 8C890018 lw $t1, 24($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (24)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B6Cu); return; } cpu->gpr[9] = cpu->read_word(psx_addr); } + /* 0xBFC35B70: 8C8A001C lw $t2, 28($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (28)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC35B70u); return; } cpu->gpr[10] = cpu->read_word(psx_addr); } + /* 0xBFC35B74: 48C82800 ctc2 $t0, gte_ctrl[5] */ + cpu->gte_ctrl[5] = cpu->gpr[8]; + /* 0xBFC35B78: 48C93000 ctc2 $t1, gte_ctrl[6] */ + cpu->gte_ctrl[6] = cpu->gpr[9]; + /* 0xBFC35B7C: 48CA3800 ctc2 $t2, gte_ctrl[7] */ + cpu->gte_ctrl[7] = cpu->gpr[10]; + /* 0xBFC35B80: 03E00008 jr $ra */ + /* 0xBFC35B84: 00000000 nop */ + /* nop */ + return; +} + +void func_1FC36068(CPUState* cpu) { +label_BFC36068: + psx_check_interrupts(cpu); + /* 0xBFC36068: C8800000 lwc2 gte[0], 0($a0) */ + cpu->gte_data[0] = cpu->read_word(cpu->gpr[4]); + /* 0xBFC3606C: C8810004 lwc2 gte[1], 4($a0) */ + cpu->gte_data[1] = cpu->read_word((uint32_t)((int32_t)cpu->gpr[4] + (4))); + /* 0xBFC36070: C8A60000 lwc2 gte[6], 0($a1) */ + cpu->gte_data[6] = cpu->read_word(cpu->gpr[5]); + /* 0xBFC36074: 48864000 mtc2 $a2, gte_data[8] */ + cpu->gte_data[8] = cpu->gpr[6]; + /* 0xBFC36078: 00000000 nop */ + /* nop */ + /* 0xBFC3607C: 4AE80413 gte cmd 0x13 */ + gte_execute(cpu, 0x0E80413); + /* 0xBFC36080: E8F60000 swc2 gte[22], 0($a3) */ + cpu->write_word(cpu->gpr[7], cpu->gte_data[22]); + /* 0xBFC36084: E8F60000 swc2 gte[22], 0($a3) */ + cpu->write_word(cpu->gpr[7], cpu->gte_data[22]); + /* 0xBFC36088: 00000000 nop */ + /* nop */ + /* 0xBFC3608C: 03E00008 jr $ra */ + /* 0xBFC36090: 00000000 nop */ + /* nop */ + return; +} + +void func_1FC362D0(CPUState* cpu) { +label_BFC362D0: + psx_check_interrupts(cpu); + /* 0xBFC362D0: 484D0000 cfc2 $t5, gte_ctrl[0] */ + cpu->gpr[13] = cpu->gte_ctrl[0]; + /* 0xBFC362D4: 484E1000 cfc2 $t6, gte_ctrl[2] */ + cpu->gpr[14] = cpu->gte_ctrl[2]; + /* 0xBFC362D8: 484F2000 cfc2 $t7, gte_ctrl[4] */ + cpu->gpr[15] = cpu->gte_ctrl[4]; + /* 0xBFC362DC: 8C880000 lw $t0, 0($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (0)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC362DCu); return; } cpu->gpr[8] = cpu->read_word(psx_addr); } + /* 0xBFC362E0: 8C890004 lw $t1, 4($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (4)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC362E0u); return; } cpu->gpr[9] = cpu->read_word(psx_addr); } + /* 0xBFC362E4: 8C8A0008 lw $t2, 8($a0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[4] + (8)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC362E4u); return; } cpu->gpr[10] = cpu->read_word(psx_addr); } + /* 0xBFC362E8: 48C80000 ctc2 $t0, gte_ctrl[0] */ + cpu->gte_ctrl[0] = cpu->gpr[8]; + /* 0xBFC362EC: 48C91000 ctc2 $t1, gte_ctrl[2] */ + cpu->gte_ctrl[2] = cpu->gpr[9]; + /* 0xBFC362F0: 48CA2000 ctc2 $t2, gte_ctrl[4] */ + cpu->gte_ctrl[4] = cpu->gpr[10]; + /* 0xBFC362F4: C8AB0008 lwc2 gte[11], 8($a1) */ + cpu->gte_data[11] = cpu->read_word((uint32_t)((int32_t)cpu->gpr[5] + (8))); + /* 0xBFC362F8: C8A90000 lwc2 gte[9], 0($a1) */ + cpu->gte_data[9] = cpu->read_word(cpu->gpr[5]); + /* 0xBFC362FC: C8AA0004 lwc2 gte[10], 4($a1) */ + cpu->gte_data[10] = cpu->read_word((uint32_t)((int32_t)cpu->gpr[5] + (4))); + /* 0xBFC36300: 00000000 nop */ + /* nop */ + /* 0xBFC36304: 4B78000C gte cmd 0x0C */ + gte_execute(cpu, 0x178000C); + /* 0xBFC36308: E8D90000 swc2 gte[25], 0($a2) */ + cpu->write_word(cpu->gpr[6], cpu->gte_data[25]); + /* 0xBFC3630C: E8D90000 swc2 gte[25], 0($a2) */ + cpu->write_word(cpu->gpr[6], cpu->gte_data[25]); + /* 0xBFC36310: E8DA0004 swc2 gte[26], 4($a2) */ + cpu->write_word((uint32_t)((int32_t)cpu->gpr[6] + (4)), cpu->gte_data[26]); + /* 0xBFC36314: E8DB0008 swc2 gte[27], 8($a2) */ + cpu->write_word((uint32_t)((int32_t)cpu->gpr[6] + (8)), cpu->gte_data[27]); + /* 0xBFC36318: 48CD0000 ctc2 $t5, gte_ctrl[0] */ + cpu->gte_ctrl[0] = cpu->gpr[13]; + /* 0xBFC3631C: 48CE1000 ctc2 $t6, gte_ctrl[2] */ + cpu->gte_ctrl[2] = cpu->gpr[14]; + /* 0xBFC36320: 48CF2000 ctc2 $t7, gte_ctrl[4] */ + cpu->gte_ctrl[4] = cpu->gpr[15]; + /* 0xBFC36324: 03E00008 jr $ra */ + /* 0xBFC36328: 00000000 nop */ + /* nop */ + return; +} + +void func_1FC36740(CPUState* cpu) { +label_BFC36740: + psx_check_interrupts(cpu); + /* 0xBFC36740: C8800000 lwc2 gte[0], 0($a0) */ + cpu->gte_data[0] = cpu->read_word(cpu->gpr[4]); + /* 0xBFC36744: C8810004 lwc2 gte[1], 4($a0) */ + cpu->gte_data[1] = cpu->read_word((uint32_t)((int32_t)cpu->gpr[4] + (4))); + /* 0xBFC36748: C8A20000 lwc2 gte[2], 0($a1) */ + cpu->gte_data[2] = cpu->read_word(cpu->gpr[5]); + /* 0xBFC3674C: C8A30004 lwc2 gte[3], 4($a1) */ + cpu->gte_data[3] = cpu->read_word((uint32_t)((int32_t)cpu->gpr[5] + (4))); + /* 0xBFC36750: C8C40000 lwc2 gte[4], 0($a2) */ + cpu->gte_data[4] = cpu->read_word(cpu->gpr[6]); + /* 0xBFC36754: C8C50004 lwc2 gte[5], 4($a2) */ + cpu->gte_data[5] = cpu->read_word((uint32_t)((int32_t)cpu->gpr[6] + (4))); + /* 0xBFC36758: 00000000 nop */ + /* nop */ + /* 0xBFC3675C: 4A280030 gte cmd 0x30 */ + gte_execute(cpu, 0x0280030); + /* 0xBFC36760: 8FA80020 lw $t0, 32($sp) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[29] + (32)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC36760u); return; } cpu->gpr[8] = cpu->read_word(psx_addr); } + /* 0xBFC36764: 4849F800 cfc2 $t1, gte_ctrl[31] */ + cpu->gpr[9] = cpu->gte_ctrl[31]; + /* 0xBFC36768: 4849F800 cfc2 $t1, gte_ctrl[31] */ + cpu->gpr[9] = cpu->gte_ctrl[31]; + /* 0xBFC3676C: 00000000 nop */ + /* nop */ + /* 0xBFC36770: AD090000 sw $t1, 0($t0) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[8] + (0)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC36770u); return; } cpu->write_word(psx_addr, cpu->gpr[9]); } + /* 0xBFC36774: 4B400006 gte cmd 0x06 */ + gte_execute(cpu, 0x1400006); + /* 0xBFC36778: 8FA80010 lw $t0, 16($sp) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[29] + (16)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC36778u); return; } cpu->gpr[8] = cpu->read_word(psx_addr); } + /* 0xBFC3677C: 8FA90014 lw $t1, 20($sp) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[29] + (20)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC3677Cu); return; } cpu->gpr[9] = cpu->read_word(psx_addr); } + /* 0xBFC36780: 8FAA0018 lw $t2, 24($sp) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[29] + (24)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC36780u); return; } cpu->gpr[10] = cpu->read_word(psx_addr); } + /* 0xBFC36784: 4802C000 mfc2 $v0, gte_data[24] */ + cpu->gpr[2] = cpu->gte_data[24]; + /* 0xBFC36788: 4802C000 mfc2 $v0, gte_data[24] */ + cpu->gpr[2] = cpu->gte_data[24]; + /* 0xBFC3678C: 00000000 nop */ + /* nop */ + /* 0xBFC36790: 1C400003 bgtz $v0, 0xBFC367A0 */ + uint32_t psx_brA_BFC36790 = cpu->gpr[2]; + int psx_taken_BFC36790 = ((int32_t)psx_brA_BFC36790 > 0); + /* 0xBFC36794: 00000000 nop */ + /* nop */ + if (psx_taken_BFC36790) goto label_BFC367A0; +label_BFC36798: + psx_check_interrupts(cpu); + /* 0xBFC36798: 1000000C beq $zero, $zero, 0xBFC367CC */ + uint32_t psx_brA_BFC36798 = cpu->gpr[0]; uint32_t psx_brB_BFC36798 = cpu->gpr[0]; + int psx_taken_BFC36798 = (psx_brA_BFC36798 == psx_brB_BFC36798); + /* 0xBFC3679C: 00000000 nop */ + /* nop */ + if (psx_taken_BFC36798) goto label_BFC367CC; +label_BFC367A0: + psx_check_interrupts(cpu); + /* 0xBFC367A0: E8EC0000 swc2 gte[12], 0($a3) */ + cpu->write_word(cpu->gpr[7], cpu->gte_data[12]); + /* 0xBFC367A4: E90D0000 swc2 gte[13], 0($t0) */ + cpu->write_word(cpu->gpr[8], cpu->gte_data[13]); + /* 0xBFC367A8: E92E0000 swc2 gte[14], 0($t1) */ + cpu->write_word(cpu->gpr[9], cpu->gte_data[14]); + /* 0xBFC367AC: E9480000 swc2 gte[8], 0($t2) */ + cpu->write_word(cpu->gpr[10], cpu->gte_data[8]); + /* 0xBFC367B0: 00000000 nop */ + /* nop */ + /* 0xBFC367B4: 4B58002D gte cmd 0x2D */ + gte_execute(cpu, 0x158002D); + /* 0xBFC367B8: 8FA9001C lw $t1, 28($sp) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[29] + (28)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC367B8u); return; } cpu->gpr[9] = cpu->read_word(psx_addr); } + /* 0xBFC367BC: 48083800 mfc2 $t0, gte_data[7] */ + cpu->gpr[8] = cpu->gte_data[7]; + /* 0xBFC367C0: 48083800 mfc2 $t0, gte_data[7] */ + cpu->gpr[8] = cpu->gte_data[7]; + /* 0xBFC367C4: 00000000 nop */ + /* nop */ + /* 0xBFC367C8: AD280000 sw $t0, 0($t1) */ + { uint32_t psx_addr = (uint32_t)((int32_t)cpu->gpr[9] + (0)); if (psx_addr & 3u) { psx_unaligned_access(cpu, psx_addr, 0xBFC367C8u); return; } cpu->write_word(psx_addr, cpu->gpr[8]); } +label_BFC367CC: + psx_check_interrupts(cpu); + /* 0xBFC367CC: 03E00008 jr $ra */ + /* 0xBFC367D0: 00000000 nop */ + /* nop */ + return; +} + void func_1FC36CF0(CPUState* cpu) { label_BFC36CF0: psx_check_interrupts(cpu); @@ -161788,67 +162247,7 @@ void func_1FC02324(CPUState* cpu) { psx_unknown_dispatch(cpu, 0xBFC02324u, 0x1FC02324u); } -void func_1FC336F0(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC336F0u, 0x1FC336F0u); -} - -void func_1FC33C98(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC33C98u, 0x1FC33C98u); -} - void func_1FC33CC0(CPUState* cpu) { psx_unknown_dispatch(cpu, 0xBFC33CC0u, 0x1FC33CC0u); } -void func_1FC33F00(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC33F00u, 0x1FC33F00u); -} - -void func_1FC33F20(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC33F20u, 0x1FC33F20u); -} - -void func_1FC33FB4(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC33FB4u, 0x1FC33FB4u); -} - -void func_1FC33FCC(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC33FCCu, 0x1FC33FCCu); -} - -void func_1FC33FD8(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC33FD8u, 0x1FC33FD8u); -} - -void func_1FC33FE4(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC33FE4u, 0x1FC33FE4u); -} - -void func_1FC35AD8(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC35AD8u, 0x1FC35AD8u); -} - -void func_1FC35B08(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC35B08u, 0x1FC35B08u); -} - -void func_1FC35B38(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC35B38u, 0x1FC35B38u); -} - -void func_1FC35B68(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC35B68u, 0x1FC35B68u); -} - -void func_1FC36068(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC36068u, 0x1FC36068u); -} - -void func_1FC362D0(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC362D0u, 0x1FC362D0u); -} - -void func_1FC36740(CPUState* cpu) { - psx_unknown_dispatch(cpu, 0xBFC36740u, 0x1FC36740u); -} - diff --git a/recompiler/src/full_function_emitter.cpp b/recompiler/src/full_function_emitter.cpp index f35001da..d61f24e1 100644 --- a/recompiler/src/full_function_emitter.cpp +++ b/recompiler/src/full_function_emitter.cpp @@ -506,6 +506,7 @@ void FullFunctionEmitter::emit_dispatch( out += "extern void psx_unknown_dispatch(CPUState* cpu, uint32_t addr, uint32_t phys);\n"; out += "extern void psx_check_interrupts(CPUState* cpu);\n"; out += "extern void psx_restore_state_escape(void);\n"; + out += "extern void gte_execute(CPUState* cpu, uint32_t cmd);\n"; out += "extern uint32_t g_debug_current_func_addr;\n"; out += "extern void debug_server_trace_dispatch(uint32_t func_addr);\n\n"; @@ -628,7 +629,8 @@ EmitStats FullFunctionEmitter::emit( full_c += "extern void psx_dispatch(CPUState* cpu, uint32_t addr);\n"; full_c += "extern void psx_unknown_dispatch(CPUState* cpu, uint32_t addr, uint32_t phys);\n"; full_c += "extern void psx_check_interrupts(CPUState* cpu);\n"; - full_c += "extern void psx_restore_state_escape(void);\n\n"; + full_c += "extern void psx_restore_state_escape(void);\n"; + full_c += "extern void gte_execute(CPUState* cpu, uint32_t cmd);\n\n"; // Forward declare ALL functions so intra-file calls resolve. for (const auto& fn : dr.functions) { diff --git a/recompiler/src/strict_translator.cpp b/recompiler/src/strict_translator.cpp index a03c829c..0556e380 100644 --- a/recompiler/src/strict_translator.cpp +++ b/recompiler/src/strict_translator.cpp @@ -1201,6 +1201,96 @@ TranslateResult StrictTranslator::translate(const PSXRecomp::DecodedInstruction& fmt::format("COP0 rs 0x{:02X} not implemented (only MFC0/MTC0/RFE in Phase 1b)", rs)); } + // COP2 / GTE (opcode 0x12) + if (opcode == 0x12) { + const uint8_t cop_op = (d.raw >> 21) & 0x1F; + const uint8_t rt = (d.raw >> 16) & 0x1F; + const uint8_t rd = (d.raw >> 11) & 0x1F; + + if (cop_op == 0x00) { // MFC2 — move from COP2 data register + r.supported = true; + r.c_code = emit_gpr_write(rt, + fmt::format("cpu->gte_data[{}]", static_cast(rd))); + r.comment = fmt::format("mfc2 {}, gte_data[{}]", gpr_name(rt), rd); + return r; + } + if (cop_op == 0x02) { // CFC2 — move from COP2 control register + r.supported = true; + r.c_code = emit_gpr_write(rt, + fmt::format("cpu->gte_ctrl[{}]", static_cast(rd))); + r.comment = fmt::format("cfc2 {}, gte_ctrl[{}]", gpr_name(rt), rd); + return r; + } + if (cop_op == 0x04) { // MTC2 — move to COP2 data register + r.supported = true; + r.c_code = fmt::format( + "cpu->gte_data[{}] = cpu->gpr[{}];", + static_cast(rd), static_cast(rt)); + r.comment = fmt::format("mtc2 {}, gte_data[{}]", gpr_name(rt), rd); + return r; + } + if (cop_op == 0x06) { // CTC2 — move to COP2 control register + r.supported = true; + r.c_code = fmt::format( + "cpu->gte_ctrl[{}] = cpu->gpr[{}];", + static_cast(rd), static_cast(rt)); + r.comment = fmt::format("ctc2 {}, gte_ctrl[{}]", gpr_name(rt), rd); + return r; + } + if (cop_op & 0x10) { // GTE command (bit 25 set) + uint32_t gte_cmd = d.raw & 0x1FFFFFF; + r.supported = true; + r.c_code = fmt::format( + "gte_execute(cpu, 0x{:07X});", + gte_cmd); + r.comment = fmt::format("gte cmd 0x{:02X}", gte_cmd & 0x3F); + return r; + } + + return unsupported(d, + fmt::format("COP2 rs 0x{:02X} not implemented", cop_op)); + } + + // LWC2 (opcode 0x32) — load word to COP2 data register + if (opcode == 0x32) { + const uint8_t rs = (d.raw >> 21) & 0x1F; + const uint8_t rt = (d.raw >> 16) & 0x1F; + const int16_t offset = static_cast(d.raw & 0xFFFF); + r.supported = true; + if (offset == 0) { + r.c_code = fmt::format( + "cpu->gte_data[{}] = cpu->read_word(cpu->gpr[{}]);", + static_cast(rt), static_cast(rs)); + } else { + r.c_code = fmt::format( + "cpu->gte_data[{}] = cpu->read_word((uint32_t)((int32_t)cpu->gpr[{}] + ({})));", + static_cast(rt), static_cast(rs), static_cast(offset)); + } + r.comment = fmt::format("lwc2 gte[{}], {}({})", + rt, static_cast(offset), gpr_name(rs)); + return r; + } + + // SWC2 (opcode 0x3A) — store word from COP2 data register + if (opcode == 0x3A) { + const uint8_t rs = (d.raw >> 21) & 0x1F; + const uint8_t rt = (d.raw >> 16) & 0x1F; + const int16_t offset = static_cast(d.raw & 0xFFFF); + r.supported = true; + if (offset == 0) { + r.c_code = fmt::format( + "cpu->write_word(cpu->gpr[{}], cpu->gte_data[{}]);", + static_cast(rs), static_cast(rt)); + } else { + r.c_code = fmt::format( + "cpu->write_word((uint32_t)((int32_t)cpu->gpr[{}] + ({})), cpu->gte_data[{}]);", + static_cast(rs), static_cast(offset), static_cast(rt)); + } + r.comment = fmt::format("swc2 gte[{}], {}({})", + rt, static_cast(offset), gpr_name(rs)); + return r; + } + return unsupported(d, fmt::format("top-level opcode 0x{:02X} not implemented in Phase 1a", opcode)); }