mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
feat: COP2/GTE instruction support in strict translator
The strict translator rejected opcode 0x12 (COP2) as "not implemented", causing all GTE functions to be skipped during emission. The code generator already handled COP2 — only the strict translator was missing. Added to strict_translator.cpp: - MFC2/CFC2: move from GTE data/control registers - MTC2/CTC2: move to GTE data/control registers - GTE commands (bit 25 set): route through gte_execute() - LWC2 (opcode 0x32): load word to GTE data register - SWC2 (opcode 0x3A): store word from GTE data register Added gte_execute extern declaration to full_function_emitter.cpp for both dispatch and full file headers. Result: 0 dispatch misses (was 5 COP2/GTE + cascading CARD driver). Emitted functions: 1085 (was 1056). Unsupported instructions: 4 (was 34). Only 2 skipped functions remain (COP1/FPU + SUB opcode). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
+459
-60
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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<int>(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<int>(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<int>(rd), static_cast<int>(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<int>(rd), static_cast<int>(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<int16_t>(d.raw & 0xFFFF);
|
||||
r.supported = true;
|
||||
if (offset == 0) {
|
||||
r.c_code = fmt::format(
|
||||
"cpu->gte_data[{}] = cpu->read_word(cpu->gpr[{}]);",
|
||||
static_cast<int>(rt), static_cast<int>(rs));
|
||||
} else {
|
||||
r.c_code = fmt::format(
|
||||
"cpu->gte_data[{}] = cpu->read_word((uint32_t)((int32_t)cpu->gpr[{}] + ({})));",
|
||||
static_cast<int>(rt), static_cast<int>(rs), static_cast<int>(offset));
|
||||
}
|
||||
r.comment = fmt::format("lwc2 gte[{}], {}({})",
|
||||
rt, static_cast<int>(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<int16_t>(d.raw & 0xFFFF);
|
||||
r.supported = true;
|
||||
if (offset == 0) {
|
||||
r.c_code = fmt::format(
|
||||
"cpu->write_word(cpu->gpr[{}], cpu->gte_data[{}]);",
|
||||
static_cast<int>(rs), static_cast<int>(rt));
|
||||
} else {
|
||||
r.c_code = fmt::format(
|
||||
"cpu->write_word((uint32_t)((int32_t)cpu->gpr[{}] + ({})), cpu->gte_data[{}]);",
|
||||
static_cast<int>(rs), static_cast<int>(offset), static_cast<int>(rt));
|
||||
}
|
||||
r.comment = fmt::format("swc2 gte[{}], {}({})",
|
||||
rt, static_cast<int>(offset), gpr_name(rs));
|
||||
return r;
|
||||
}
|
||||
|
||||
return unsupported(d, fmt::format("top-level opcode 0x{:02X} not implemented in Phase 1a", opcode));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user