diff --git a/asm/non_matchings/virtual_console/cpu/cpuExecuteOpcode.s b/asm/non_matchings/virtual_console/cpu/cpuExecuteOpcode.s index b34f9be..96fbf73 100644 --- a/asm/non_matchings/virtual_console/cpu/cpuExecuteOpcode.s +++ b/asm/non_matchings/virtual_console/cpu/cpuExecuteOpcode.s @@ -3045,7 +3045,7 @@ lbl_8003854C: /* 80038670 00033C30 7C 9A 02 14 */ add r4, r26, r0 /* 80038674 00033C34 80 64 01 48 */ lwz r3, 0x148(r4) /* 80038678 00033C38 80 84 01 4C */ lwz r4, 0x14c(r4) -/* 8003867C 00033C3C 48 11 AC C5 */ bl func_80153340 +/* 8003867C 00033C3C 48 11 AC C5 */ bl __cvt_sll_dbl /* 80038680 00033C40 48 12 C9 11 */ bl sqrt /* 80038684 00033C44 48 11 AE 21 */ bl __cvt_dbl_usll /* 80038688 00033C48 56 C0 EE 38 */ rlwinm r0, r22, 0x1d, 0x18, 0x1c @@ -3057,7 +3057,7 @@ lbl_8003854C: /* 800386A0 00033C60 7C 9A 02 14 */ add r4, r26, r0 /* 800386A4 00033C64 80 64 01 48 */ lwz r3, 0x148(r4) /* 800386A8 00033C68 80 84 01 4C */ lwz r4, 0x14c(r4) -/* 800386AC 00033C6C 48 11 AC 95 */ bl func_80153340 +/* 800386AC 00033C6C 48 11 AC 95 */ bl __cvt_sll_dbl /* 800386B0 00033C70 FC 20 0A 10 */ fabs f1, f1 /* 800386B4 00033C74 48 11 AD F1 */ bl __cvt_dbl_usll /* 800386B8 00033C78 56 C0 EE 38 */ rlwinm r0, r22, 0x1d, 0x18, 0x1c @@ -3107,7 +3107,7 @@ lbl_8003854C: /* 80038768 00033D28 7C 9A 02 14 */ add r4, r26, r0 /* 8003876C 00033D2C 80 64 01 48 */ lwz r3, 0x148(r4) /* 80038770 00033D30 80 84 01 4C */ lwz r4, 0x14c(r4) -/* 80038774 00033D34 48 11 AB CD */ bl func_80153340 +/* 80038774 00033D34 48 11 AB CD */ bl __cvt_sll_dbl /* 80038778 00033D38 48 12 BE E5 */ bl ceil /* 8003877C 00033D3C 48 11 AD 29 */ bl __cvt_dbl_usll /* 80038780 00033D40 56 C0 EE 38 */ rlwinm r0, r22, 0x1d, 0x18, 0x1c @@ -3119,7 +3119,7 @@ lbl_8003854C: /* 80038798 00033D58 7C 9A 02 14 */ add r4, r26, r0 /* 8003879C 00033D5C 80 64 01 48 */ lwz r3, 0x148(r4) /* 800387A0 00033D60 80 84 01 4C */ lwz r4, 0x14c(r4) -/* 800387A4 00033D64 48 11 AB 9D */ bl func_80153340 +/* 800387A4 00033D64 48 11 AB 9D */ bl __cvt_sll_dbl /* 800387A8 00033D68 48 12 C0 F5 */ bl floor /* 800387AC 00033D6C 48 11 AC F9 */ bl __cvt_dbl_usll /* 800387B0 00033D70 56 C0 EE 38 */ rlwinm r0, r22, 0x1d, 0x18, 0x1c @@ -3145,7 +3145,7 @@ lbl_8003854C: /* 80038800 00033DC0 7C 9A 02 14 */ add r4, r26, r0 /* 80038804 00033DC4 80 64 01 48 */ lwz r3, 0x148(r4) /* 80038808 00033DC8 80 84 01 4C */ lwz r4, 0x14c(r4) -/* 8003880C 00033DCC 48 11 AB 35 */ bl func_80153340 +/* 8003880C 00033DCC 48 11 AB 35 */ bl __cvt_sll_dbl /* 80038810 00033DD0 48 12 BE 4D */ bl ceil /* 80038814 00033DD4 FC 00 08 1E */ fctiwz f0, f1 /* 80038818 00033DD8 56 C0 EE 38 */ rlwinm r0, r22, 0x1d, 0x18, 0x1c @@ -3158,7 +3158,7 @@ lbl_8003854C: /* 80038834 00033DF4 7C 9A 02 14 */ add r4, r26, r0 /* 80038838 00033DF8 80 64 01 48 */ lwz r3, 0x148(r4) /* 8003883C 00033DFC 80 84 01 4C */ lwz r4, 0x14c(r4) -/* 80038840 00033E00 48 11 AB 01 */ bl func_80153340 +/* 80038840 00033E00 48 11 AB 01 */ bl __cvt_sll_dbl /* 80038844 00033E04 48 12 C0 59 */ bl floor /* 80038848 00033E08 FC 00 08 1E */ fctiwz f0, f1 /* 8003884C 00033E0C 56 C0 EE 38 */ rlwinm r0, r22, 0x1d, 0x18, 0x1c @@ -3171,7 +3171,7 @@ lbl_8003854C: /* 80038868 00033E28 7C 9A 02 14 */ add r4, r26, r0 /* 8003886C 00033E2C 80 64 01 48 */ lwz r3, 0x148(r4) /* 80038870 00033E30 80 84 01 4C */ lwz r4, 0x14c(r4) -/* 80038874 00033E34 48 11 AB 7D */ bl func_801533F0 +/* 80038874 00033E34 48 11 AB 7D */ bl __cvt_sll_flt /* 80038878 00033E38 56 C0 EE 38 */ rlwinm r0, r22, 0x1d, 0x18, 0x1c /* 8003887C 00033E3C 7C 7A 02 14 */ add r3, r26, r0 /* 80038880 00033E40 D0 23 01 4C */ stfs f1, 0x14c(r3) @@ -3180,7 +3180,7 @@ lbl_8003854C: /* 8003888C 00033E4C 7C 9A 02 14 */ add r4, r26, r0 /* 80038890 00033E50 80 64 01 48 */ lwz r3, 0x148(r4) /* 80038894 00033E54 80 84 01 4C */ lwz r4, 0x14c(r4) -/* 80038898 00033E58 48 11 AA A9 */ bl func_80153340 +/* 80038898 00033E58 48 11 AA A9 */ bl __cvt_sll_dbl /* 8003889C 00033E5C 56 C0 EE 38 */ rlwinm r0, r22, 0x1d, 0x18, 0x1c /* 800388A0 00033E60 7C 7A 02 14 */ add r3, r26, r0 /* 800388A4 00033E64 D8 23 01 48 */ stfd f1, 0x148(r3) diff --git a/asm/virtual_console/code_800825B0.s b/asm/virtual_console/code_800825B0.s index 7a59026..bdd939b 100644 --- a/asm/virtual_console/code_800825B0.s +++ b/asm/virtual_console/code_800825B0.s @@ -237381,7 +237381,7 @@ lbl_80153338: /* 80153338 0014E8F8 7C 63 2E 30 */ sraw r3, r3, r5 /* 8015333C 0014E8FC 4E 80 00 20 */ blr -glabel func_80153340 +glabel __cvt_sll_dbl /* 80153340 0014E900 94 21 FF F0 */ stwu r1, -0x10(r1) /* 80153344 0014E904 54 65 00 01 */ rlwinm. r5, r3, 0, 0, 0 /* 80153348 0014E908 41 82 00 0C */ beq lbl_80153354 @@ -237431,7 +237431,7 @@ lbl_801533DC: /* 801533E8 0014E9A8 38 21 00 10 */ addi r1, r1, 0x10 /* 801533EC 0014E9AC 4E 80 00 20 */ blr -glabel func_801533F0 +glabel __cvt_sll_flt /* 801533F0 0014E9B0 94 21 FF F0 */ stwu r1, -0x10(r1) /* 801533F4 0014E9B4 54 65 00 01 */ rlwinm. r5, r3, 0, 0, 0 /* 801533F8 0014E9B8 41 82 00 0C */ beq lbl_80153404 diff --git a/include/cpu.h b/include/cpu.h index 9b4c43b..8f85dfb 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -3,19 +3,19 @@ #include "tree.h" -typedef s32 (*lb_func_t)(void* obj, u32 addr, s8* dst); -typedef s32 (*lh_func_t)(void* obj, u32 addr, s16* dst); -typedef s32 (*lw_func_t)(void* obj, u32 addr, s32* dst); -typedef s32 (*ld_func_t)(void* obj, u32 addr, s64* dst); -typedef s32 (*sb_func_t)(void* obj, u32 addr, s8* src); -typedef s32 (*sh_func_t)(void* obj, u32 addr, s16* src); -typedef s32 (*sw_func_t)(void* obj, u32 addr, s32* src); -typedef s32 (*sd_func_t)(void* obj, u32 addr, s64* src); +typedef s32 (*lb_func_t)(void* obj, s32 addr, s8* dst); +typedef s32 (*lh_func_t)(void* obj, s32 addr, s16* dst); +typedef s32 (*lw_func_t)(void* obj, s32 addr, s32* dst); +typedef s32 (*ld_func_t)(void* obj, s32 addr, s64* dst); +typedef s32 (*sb_func_t)(void* obj, s32 addr, s8* src); +typedef s32 (*sh_func_t)(void* obj, s32 addr, s16* src); +typedef s32 (*sw_func_t)(void* obj, s32 addr, s32* src); +typedef s32 (*sd_func_t)(void* obj, s32 addr, s64* src); typedef struct { /* 0x0000 */ u32 unk_0; /* 0x0004 */ void *unk_4; - /* 0x0008 */ u32 unk_8; + /* 0x0008 */ s32 unk_8; /* 0x000C */ lb_func_t lb; /* 0x0010 */ lh_func_t lh; /* 0x0014 */ lw_func_t lw; diff --git a/include/mips.h b/include/mips.h new file mode 100644 index 0000000..8db56e4 --- /dev/null +++ b/include/mips.h @@ -0,0 +1,124 @@ +#ifndef _MIPS_H +#define _MIPS_H + +#define MIPS_OP(inst) ((inst >> 0x1A) & 0x3F) + +#define OPC_SPECIAL 0 +#define OPC_REGIMM 1 +#define OPC_J 2 +#define OPC_JAL 3 +#define OPC_BEQ 4 +#define OPC_BNE 5 +#define OPC_BLEZ 6 +#define OPC_BGTZ 7 +#define OPC_ADDI 8 +#define OPC_ADDIU 9 +#define OPC_SLTI 10 +#define OPC_SLTIU 11 +#define OPC_ANDI 12 +#define OPC_ORI 13 +#define OPC_XORI 14 +#define OPC_LUI 15 +#define OPC_CP0 16 +#define OPC_CP1 17 + +#define SPEC_FUNCT(inst) ((inst >> 0) & 0x3F) +#define SPEC_SLL 0 +#define SPEC_SRL 2 +#define SPEC_SRA 3 +#define SPEC_SLLV 4 +#define SPEC_SRLV 6 +#define SPEC_SRAV 7 +#define SPEC_JR 8 +#define SPEC_JALR 9 +#define SPEC_SYSCALL 12 +#define SPEC_BREAK 13 +#define SPEC_MFHI 16 +#define SPEC_MTHI 17 +#define SPEC_MFLO 18 +#define SPEC_MTLO 19 +#define SPEC_DSLLV 20 +#define SPEC_DSRLV 22 +#define SPEC_DSRAV 23 +#define SPEC_MULT 24 +#define SPEC_MULTU 25 +#define SPEC_DIV 26 +#define SPEC_DIVU 27 +#define SPEC_DMULT 28 +#define SPEC_DMULTU 29 +#define SPEC_DDIV 30 +#define SPEC_DDIVU 31 +#define SPEC_ADD 32 +#define SPEC_ADDU 33 +#define SPEC_SUB 34 +#define SPEC_SUBU 35 +#define SPEC_AND 36 +#define SPEC_OR 37 +#define SPEC_XOR 38 +#define SPEC_NOR 39 +#define SPEC_SLT 42 +#define SPEC_SLTU 43 +#define SPEC_DADD 44 +#define SPEC_DADDU 45 +#define SPEC_DSUB 46 +#define SPEC_DSUBU 47 +#define SPEC_TGE 48 +#define SPEC_TGEU 49 +#define SPEC_TLT 50 +#define SPEC_TLTU 51 +#define SPEC_TEQ 52 +#define SPEC_TNE 54 +#define SPEC_DSLL 56 +#define SPEC_DSRL 58 +#define SPEC_DSRA 59 +#define SPEC_DSLL32 60 +#define SPEC_DSRL32 62 +#define SPEC_DSRA32 63 + +#define REGIMM_SUB(inst) ((inst >> 16) & 0x1F) +#define REGIMM_BLTZ 0 +#define REGIMM_BGEZ 1 +#define REGIMM_BLTZL 2 +#define REGIMM_BGEZL 3 +#define REGIMM_TGEI 8 +#define REGIMM_TGEIU 9 +#define REGIMM_TLTI 10 +#define REGIMM_TLTIU 11 +#define REGIMM_TEQI 12 +#define REGIMM_TNEI 14 +#define REGIMM_BLTZAL 16 +#define REGIMM_BGEZAL 17 +#define REGIMM_BLTZALL 18 +#define REGIMM_BGEZALL 19 + +#define MIPS_RD(inst) ((inst >> 0xB) & 0x1F) +#define MIPS_RT(inst) ((inst >> 0x10) & 0x1F) +#define MIPS_RS(inst) ((inst >> 0x15) & 0x1F) + +#define MIPS_FDT(inst) ((inst >> 0) & 0x7FF) +#define MIPS_FR(inst) ((inst >> 0x15) & 0x1F) +#define MIPS_FT(inst) ((inst >> 0x10) & 0x1F) +#define MIPS_FS(inst) ((inst >> 0xB) & 0x1F) +#define MIPS_FD(inst) ((inst >> 6) & 0x1F) +#define MIPS_FSUB(inst) ((inst >> 0x15) & 0x1F) +#define MIPS_FFMT(inst) ((inst >> 0x15) & 0x1F) +#define MIPS_FFUNC(inst) ((inst >> 0x0) & 0x3F) +#define MIPS_FCC(inst) ((inst >> 8) & 7) +#define MIPS_FFMT3(inst) ((inst >> 0) & 7) +#define MIPS_FOP4(inst) ((inst >> 3) & 7) + +#define MIPS_FMT_SINGLE 16 +#define MIPS_FMT_DOUBLE 17 +#define MIPS_FMT_WORD 20 +#define MIPS_FMT_DBLWORD 21 + +#define MIPS_FSUB_MFC 0 +#define MIPS_FSUB_DMFC 1 +#define MIPS_FSUB_CFC 2 +#define MIPS_FSUB_MTC 4 +#define MIPS_FSUB_DMTC 5 +#define MIPS_FSUB_CTC 6 + +#define MIPS_IMM(inst) ((s16)(inst & 0xFFFF)) +#define MIPS_SA(inst ) ((inst >> 6) & 0x1F) +#endif \ No newline at end of file diff --git a/src/virtual_console/cpu.c b/src/virtual_console/cpu.c index fb3db51..7e1e677 100644 --- a/src/virtual_console/cpu.c +++ b/src/virtual_console/cpu.c @@ -1,4 +1,5 @@ #include "cpu.h" +#include "mips.h" #include "rom.h" #include "xlHeap.h" #include "system.h" @@ -514,11 +515,55 @@ inline s32 checkRetrace() { return 1; } + +inline unkFrameSet(u32 rom_id, u32 *frame, u32 addr) { + if(rom_id == 'NKTJ') { + if(addr == 0x802A4118) { + frame[0x11] = 0; + } + if(addr == 0x80072D94) { + frame[0x11] = 1; + } + } else if(rom_id == 'NKTP') { + if(addr == 0x802A4160) { + frame[0x11] = 0; + } + if(addr == 0x80072E34) { + frame[0x11] = 1; + } + } else if(rom_id == 'NKTE') { + if(addr == 0x802A4160) { + frame[0x11] = 0; + } + if(addr == 0x80072E54) { + frame[0x11] = 1; + } + } +} + + + +inline cpu_dev_t *get_dev(cpu_dev_t **devs, u8 *idxs, u32 addr) { + return devs[idxs[(addr >> 0x10)]]; +} + +inline s32 calc_ea(cpu_class_t *cpu, s32 reg, s32 imm) { + return cpu->gpr[reg].w[1] + (u32)imm; +} + void *cpuExecuteOpcode(cpu_class_t *cpu, s32 arg1, u32 addr, u32 *ret) { + s32 save_ra = 0; u32 tick = OSGetTick(); u32 *code_buf; u32 inst; - reg64_t prev_ra; + u64 prev_ra; + u8 *dev_idx; + cpu_dev_t *dev; + cpu_dev_t **devs; + reg64_t tmp; + s32 i; + s32 val; + u32 ea; if(cpu->unk_0x24 != 0) { cpu->unk_0x00 |= 8; @@ -526,28 +571,10 @@ void *cpuExecuteOpcode(cpu_class_t *cpu, s32 arg1, u32 addr, u32 *ret) { cpu->unk_0x00 &= ~8; } - if(gSystem->rom_id == 'NKTJ') { - if(addr == 0x802A4118) { - gSystem->frame[0x11] = 0; - } - if(addr == 0x80072D94) { - gSystem->frame[0x11] = 1; - } - } else if(gSystem->rom_id == 'NKTP') { - if(addr == 0x802A4160) { - gSystem->frame[0x11] = 0; - } - if(addr == 0x80072E34) { - gSystem->frame[0x11] = 1; - } - } else if(gSystem->rom_id == 'NKTE') { - if(addr == 0x802A4160) { - gSystem->frame[0x11] = 0; - } - if(addr == 0x80072E54) { - gSystem->frame[0x11] = 1; - } - } + unkFrameSet(gSystem->rom_id, gSystem->frame, addr); + + dev_idx = cpu->mem_hi_map; + devs = cpu->devices; if(!cpuGetAddressBuffer(cpu, (void**)&code_buf, addr)) { return NULL; @@ -556,344 +583,320 @@ void *cpuExecuteOpcode(cpu_class_t *cpu, s32 arg1, u32 addr, u32 *ret) { inst = *code_buf; cpu->pc = addr + 4; if(inst == 0xACBF011C) { - prev_ra = cpu->gpr[0x1F]; + prev_ra = cpu->gpr[0x1F].d; cpu->gpr[0x1F].w[1] = cpu->unk_0x30; + save_ra = 1; } - switch(inst >> 0x1A) { - case 0: - switch(inst & 0x3F) { - case 0: // SLL - cpu->gpr[(inst >> 0xB) & 0x1F].w[1] = cpu->gpr[(inst >> 0x10) & 0x1F].w[1] << ((inst >> 6) & 0x1F); + switch(MIPS_OP(inst)) { + case OPC_SPECIAL: + switch(SPEC_FUNCT(inst)) { + case SPEC_SLL: // SLL + cpu->gpr[MIPS_RD(inst)].w[1] = cpu->gpr[MIPS_RT(inst)].w[1] << MIPS_SA(inst); break; - case 2: // SRL - cpu->gpr[(inst >> 0xB) & 0x1F].w[1] = cpu->gpr[(inst >> 0x10) & 0x1F].w[1] >> ((inst >> 6) & 0x1F); + case SPEC_SRL: // SRL + cpu->gpr[MIPS_RD(inst)].w[1] = cpu->gpr[MIPS_RT(inst)].w[1] >> MIPS_SA(inst); break; - case 3: // SRA - cpu->gpr[(inst >> 0xB) & 0x1F].sw[1] = cpu->gpr[(inst >> 0x10) & 0x1F].sw[1] >> ((inst >> 6) & 0x1F); + case SPEC_SRA: // SRA + cpu->gpr[MIPS_RD(inst)].sw[1] = cpu->gpr[MIPS_RT(inst)].sw[1] >> MIPS_SA(inst); break; - case 4: // SLLV - cpu->gpr[(inst >> 0xB) & 0x1F].w[1] = cpu->gpr[(inst >> 0x10) & 0x1F].w[1] << (cpu->gpr[(inst >> 0x15) & 0x1F].w[1] & 0x1F); + case SPEC_SLLV: // SLLV + cpu->gpr[MIPS_RD(inst)].w[1] = + cpu->gpr[MIPS_RT(inst)].w[1] << (cpu->gpr[MIPS_RS(inst)].w[1] & 0x1F); break; - case 6: // SRLV - cpu->gpr[(inst >> 0xB) & 0x1F].w[1] = cpu->gpr[(inst >> 0x10) & 0x1F].w[1] >> (cpu->gpr[(inst >> 0x15) & 0x1F].w[1] & 0x1F); + case SPEC_SRLV: // SRLV + cpu->gpr[MIPS_RD(inst)].w[1] = + cpu->gpr[MIPS_RT(inst)].w[1] >> (cpu->gpr[MIPS_RS(inst)].w[1] & 0x1F); break; - case 7: // SRAV - cpu->gpr[(inst >> 0xB) & 0x1F].sw[1] = cpu->gpr[(inst >> 0x10) & 0x1F].sw[1] >> (cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] & 0x1F); + case SPEC_SRAV: // SRAV + cpu->gpr[MIPS_RD(inst)].sw[1] = + cpu->gpr[MIPS_RT(inst)].sw[1] >> (cpu->gpr[MIPS_RS(inst)].sw[1] & 0x1F); break; - case 8: // JR - cpu->unk_0x24 = cpu->gpr[(inst >> 0x15) & 0x1F].w[1]; + case SPEC_JR: // JR + cpu->unk_0x24 = cpu->gpr[MIPS_RS(inst)].w[1]; break; - case 9: // JALR - cpu->unk_0x24 = cpu->gpr[(inst >> 0x15) & 0x1F].w[1]; - cpu->gpr[(inst >> 0xB) & 0x1F].d = cpu->pc + 4; + case SPEC_JALR: // JALR + cpu->unk_0x24 = cpu->gpr[MIPS_RS(inst)].w[1]; + cpu->gpr[MIPS_RD(inst)].d = cpu->pc + 4; break; - case 10: - case 11: - break; - case 12: // SYSCALL + case SPEC_SYSCALL: // SYSCALL cpuException(cpu, 8, 0); break; - case 13: // BREAk + case SPEC_BREAK: // BREAk cpuException(cpu, 9, 0); break; - case 14: - case 15: + case SPEC_MFHI: // MFHI + cpu->gpr[MIPS_RD(inst)].d = cpu->hi.d; break; - case 16: // MFHI - cpu->gpr[(inst >> 0xB) & 0x1F].d = cpu->hi.d; + case SPEC_MTHI: // MTHI + cpu->hi.d = cpu->gpr[MIPS_RS(inst)].d; break; - case 17: // MTHI - cpu->hi.d = cpu->gpr[(inst >> 0x15) & 0x1F].d; + case SPEC_MFLO: // MFLO + cpu->gpr[MIPS_RD(inst)].d = cpu->lo.d; break; - case 18: // MFLO - cpu->gpr[(inst >> 0xB) & 0x1F].d = cpu->lo.d; + case SPEC_MTLO: // MTLO + cpu->lo.d = cpu->gpr[MIPS_RD(inst)].d; break; - case 19: // MTLO - cpu->lo.d = cpu->gpr[(inst >> 0xB) & 0x1F].d; + case SPEC_DSLLV: // DSLLV + cpu->gpr[MIPS_RD(inst)].d = cpu->gpr[MIPS_RT(inst)].d << (cpu->gpr[MIPS_RS(inst)].d & 0x1F); break; - case 20: // DSLLV - cpu->gpr[(inst >> 0xB) & 0x1F].d = cpu->gpr[(inst >> 0x10) & 0x1F].d << (cpu->gpr[(inst >> 0x15) & 0x1F].d & 0x1F); + case SPEC_DSRLV: // DSRLV + cpu->gpr[MIPS_RD(inst)].d = cpu->gpr[MIPS_RT(inst)].d >> (cpu->gpr[MIPS_RS(inst)].d & 0x1F); break; - case 21: + case SPEC_DSRAV: // DRAV + cpu->gpr[MIPS_RD(inst)].sd = cpu->gpr[MIPS_RT(inst)].sd >> (cpu->gpr[MIPS_RS(inst)].sd & 0x1F); break; - case 22: // DSRLV - cpu->gpr[(inst >> 0xB) & 0x1F].d = cpu->gpr[(inst >> 0x10) & 0x1F].d >> (cpu->gpr[(inst >> 0x15) & 0x1F].d & 0x1F); - break; - case 23: // DRAV - cpu->gpr[(inst >> 0xB) & 0x1F].sd = cpu->gpr[(inst >> 0x10) & 0x1F].sd >> (cpu->gpr[(inst >> 0x15) & 0x1F].sd & 0x1F); - break; - case 24: // MULT + case SPEC_MULT: // MULT { - reg64_t r; - r.sd = (s64)(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] * cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]); - cpu->lo.sd = r.w[0]; - cpu->hi.sd = r.w[1]; + s64 rs = cpu->gpr[MIPS_RS(inst)].sw[1]; + s64 rt = cpu->gpr[MIPS_RT(inst)].sw[1]; + tmp.sd = (s64)(rs * rt); + cpu->lo.sd = (s32)(tmp.sd & 0xFFFFFFFF); + cpu->hi.sd = (s32)(tmp.sd >> 32); } break; - case 25: // MULTU + case SPEC_MULTU: // MULTU { - reg64_t r; - u64 rs = cpu->gpr[(inst >> 0x15) & 0x1F].w[1]; - u64 rt = cpu->gpr[(inst >> 0x10) & 0x1F].w[1]; - r.sd = rs * rt; - cpu->lo.sd = r.d & 0xFFFFFFFF; - cpu->hi.d = r.w[1] >> 32; + u64 rs = cpu->gpr[MIPS_RS(inst)].w[1]; + u64 rt = cpu->gpr[MIPS_RT(inst)].w[1]; + tmp.d = (s64)(rs * rt); + cpu->lo.sd = (s32)(tmp.sd & 0xFFFFFFFF); + cpu->hi.sd = (s32)(tmp.sd >> 32); } break; - case 26: // DIV + case SPEC_DIV: // DIV { - u32 res; - if(cpu->gpr[(inst >> 0x10) & 0x1F].w[1] == 0) { + if(cpu->gpr[MIPS_RT(inst)].w[1] == 0) { break; } - res = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] / cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]; - cpu->lo.d = res; + cpu->lo.sd = cpu->gpr[MIPS_RS(inst)].sw[1] / cpu->gpr[MIPS_RT(inst)].sw[1]; - res = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] % cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]; - cpu->hi.d = res; + cpu->hi.sd = cpu->gpr[MIPS_RS(inst)].sw[1] % cpu->gpr[MIPS_RT(inst)].sw[1]; } break; - case 27: // DIVU + case SPEC_DIVU: // DIVU { - u64 res; - if(cpu->gpr[(inst >> 0x10) & 0x1F].w[1] == 0) { + if(cpu->gpr[MIPS_RT(inst)].w[1] == 0) { break; } - cpu->lo.d = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] / cpu->gpr[(inst >> 0x10) & 0x1F].w[1]; - cpu->hi.d = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] % cpu->gpr[(inst >> 0x10) & 0x1F].w[1]; + cpu->lo.sd = (s32)(cpu->gpr[MIPS_RS(inst)].w[1] / cpu->gpr[MIPS_RT(inst)].w[1]); + cpu->hi.sd = (s32)(cpu->gpr[MIPS_RS(inst)].w[1] % cpu->gpr[MIPS_RT(inst)].w[1]); } break; - case 28: // DMULT - { - s64 prod = cpu->gpr[(inst >> 0x15) & 0x1F].sd * cpu->gpr[(inst >> 0x10) & 0x1F].sd; - cpu->lo.sd = prod; - cpu->hi.sd = prod >> 32; - } - break; - case 29: // DMULTU - { - u64 prod = cpu->gpr[(inst >> 0x15) & 0x1F].d * cpu->gpr[(inst >> 0x10) & 0x1F].d; - cpu->lo.d = prod; - cpu->hi.d = prod >> 32; - } - break; - case 30: // DDIV - if(cpu->gpr[(inst >> 0x10) & 0x1F].w[1] == 0) { + case SPEC_DMULT: // DMULT + { + + reg64_t *rs = &cpu->gpr[MIPS_RS(inst)]; + reg64_t *rt = &cpu->gpr[MIPS_RT(inst)]; + + cpu->lo.w[1] = rs->w[1] * rt->w[1]; + cpu->lo.w[0] = (u32)(((u64)rs->w[1] * (u64)rt->w[1]) >> 32) + (rs->w[0] * rt->w[1]); + cpu->hi.sd = -((cpu->lo.w[0] ^ 0x80000000) < 0x80000000); + } + break; + case SPEC_DMULTU: // DMULTU + { + tmp.d = cpu->gpr[MIPS_RS(inst)].d * cpu->gpr[MIPS_RT(inst)].d; + cpu->lo.d = tmp.d; + cpu->hi.d = tmp.d >> 32; + } + break; + case SPEC_DDIV: // DDIV + if(cpu->gpr[MIPS_RT(inst)].d == 0) { break; } - cpu->lo.sd = cpu->gpr[(inst >> 0x15) & 0x1F].sd / cpu->gpr[(inst >> 0x10) & 0x1F].sd; - cpu->hi.sd = cpu->gpr[(inst >> 0x15) & 0x1F].sd % cpu->gpr[(inst >> 0x10) & 0x1F].sd; + cpu->lo.sd = cpu->gpr[MIPS_RS(inst)].sd / cpu->gpr[MIPS_RT(inst)].sd; + cpu->hi.sd = cpu->gpr[MIPS_RS(inst)].sd % cpu->gpr[MIPS_RT(inst)].sd; break; - case 31: // DDIVU - if(cpu->gpr[(inst >> 0x10) & 0x1F].w[1] == 0) { + case SPEC_DDIVU: // DDIVU + if(cpu->gpr[MIPS_RT(inst)].d == 0) { break; } - cpu->lo.d = cpu->gpr[(inst >> 0x15) & 0x1F].d / cpu->gpr[(inst >> 0x10) & 0x1F].d; - cpu->hi.d = cpu->gpr[(inst >> 0x15) & 0x1F].d % cpu->gpr[(inst >> 0x10) & 0x1F].d; + cpu->lo.d = cpu->gpr[MIPS_RS(inst)].d / cpu->gpr[MIPS_RT(inst)].d; + cpu->hi.d = cpu->gpr[MIPS_RS(inst)].d % cpu->gpr[MIPS_RT(inst)].d; break; - case 32: // ADD - cpu->gpr[(inst >> 0xB) & 0x1F].sw[1] = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] + cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]; + case SPEC_ADD: // ADD + cpu->gpr[MIPS_RD(inst)].sw[1] = cpu->gpr[MIPS_RS(inst)].sw[1] + cpu->gpr[MIPS_RT(inst)].sw[1]; break; - case 33: // ADDU - cpu->gpr[(inst >> 0xB) & 0x1F].w[1] = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + cpu->gpr[(inst >> 0x10) & 0x1F].w[1]; + case SPEC_ADDU: // ADDU + cpu->gpr[MIPS_RD(inst)].w[1] = cpu->gpr[MIPS_RS(inst)].w[1] + cpu->gpr[MIPS_RT(inst)].w[1]; break; - case 34: // SUB - cpu->gpr[(inst >> 0xB) & 0x1F].sw[1] = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] - cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]; + case SPEC_SUB: // SUB + cpu->gpr[MIPS_RD(inst)].sw[1] = cpu->gpr[MIPS_RS(inst)].sw[1] - cpu->gpr[MIPS_RT(inst)].sw[1]; break; - case 35: // SUBU - cpu->gpr[(inst >> 0xB) & 0x1F].sw[1] = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] - cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]; + case SPEC_SUBU: // SUBU + cpu->gpr[MIPS_RD(inst)].sw[1] = cpu->gpr[MIPS_RS(inst)].sw[1] - cpu->gpr[MIPS_RT(inst)].sw[1]; break; - case 36: // AND - cpu->gpr[(inst >> 0xB) & 0x1F].w[1] = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] & cpu->gpr[(inst >> 0x10) & 0x1F].w[1]; + case SPEC_AND: // AND + cpu->gpr[MIPS_RD(inst)].w[1] = cpu->gpr[MIPS_RS(inst)].w[1] & cpu->gpr[MIPS_RT(inst)].w[1]; break; - case 37: // AND - cpu->gpr[(inst >> 0xB) & 0x1F].w[1] = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] | cpu->gpr[(inst >> 0x10) & 0x1F].w[1]; + case SPEC_OR: // OR + cpu->gpr[MIPS_RD(inst)].w[1] = cpu->gpr[MIPS_RS(inst)].w[1] | cpu->gpr[MIPS_RT(inst)].w[1]; break; - case 38: // XOR - cpu->gpr[(inst >> 0xB) & 0x1F].w[1] = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] ^ cpu->gpr[(inst >> 0x10) & 0x1F].w[1]; + case SPEC_XOR: // XOR + cpu->gpr[MIPS_RD(inst)].w[1] = cpu->gpr[MIPS_RS(inst)].w[1] ^ cpu->gpr[MIPS_RT(inst)].w[1]; break; - case 39: // NOR - cpu->gpr[(inst >> 0xB) & 0x1F].w[1] = ~(cpu->gpr[(inst >> 0x15) & 0x1F].w[1] | cpu->gpr[(inst >> 0x10) & 0x1F].w[1]); + case SPEC_NOR: // NOR + cpu->gpr[MIPS_RD(inst)].w[1] = ~(cpu->gpr[MIPS_RS(inst)].w[1] | cpu->gpr[MIPS_RT(inst)].w[1]); break; - case 40: - case 41: + case SPEC_SLT: // SLT + cpu->gpr[MIPS_RD(inst)].sw[1] = !!(cpu->gpr[MIPS_RS(inst)].sw[1] < cpu->gpr[MIPS_RT(inst)].sw[1]); break; - case 42: // SLT - cpu->gpr[(inst >> 0xB) & 0x1F].sw[1] = !!(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] < cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]); + case SPEC_SLTU: // SLTU + cpu->gpr[MIPS_RD(inst)].w[1] = !!(cpu->gpr[MIPS_RS(inst)].w[1] < cpu->gpr[MIPS_RT(inst)].w[1]); break; - case 43: // SLTU - cpu->gpr[(inst >> 0xB) & 0x1F].w[1] = !!(cpu->gpr[(inst >> 0x15) & 0x1F].w[1] < cpu->gpr[(inst >> 0x10) & 0x1F].w[1]); + case SPEC_DADD: // DADD + cpu->gpr[MIPS_RD(inst)].sd = cpu->gpr[MIPS_RS(inst)].sd + cpu->gpr[MIPS_RT(inst)].sd; break; - case 44: // DADD - cpu->gpr[(inst >> 0xB) & 0x1F].sd = cpu->gpr[(inst >> 0x15) & 0x1F].sd + cpu->gpr[(inst >> 0x10) & 0x1F].sd; + case SPEC_DADDU: // DADDU + cpu->gpr[MIPS_RD(inst)].d = cpu->gpr[MIPS_RS(inst)].d + cpu->gpr[MIPS_RT(inst)].d; break; - case 45: // DADDU - cpu->gpr[(inst >> 0xB) & 0x1F].d = cpu->gpr[(inst >> 0x15) & 0x1F].d + cpu->gpr[(inst >> 0x10) & 0x1F].d; + case SPEC_DSUB: // DSUB + cpu->gpr[MIPS_RD(inst)].sd = cpu->gpr[MIPS_RS(inst)].sd - cpu->gpr[MIPS_RT(inst)].sd; break; - case 46: // DSUB - cpu->gpr[(inst >> 0xB) & 0x1F].sd = cpu->gpr[(inst >> 0x15) & 0x1F].sd - cpu->gpr[(inst >> 0x10) & 0x1F].sd; + case SPEC_DSUBU: // DSUBU + cpu->gpr[MIPS_RD(inst)].sd = cpu->gpr[MIPS_RS(inst)].sd - cpu->gpr[MIPS_RT(inst)].sd; break; - case 47: // DSUBU - cpu->gpr[(inst >> 0xB) & 0x1F].sd = cpu->gpr[(inst >> 0x15) & 0x1F].sd - cpu->gpr[(inst >> 0x10) & 0x1F].sd; - break; - case 48: // TGE - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] >= cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]) { + case SPEC_TGE: // TGE + if(cpu->gpr[MIPS_RS(inst)].sw[1] >= cpu->gpr[MIPS_RT(inst)].sw[1]) { cpuException(cpu, 0xD, 0); } break; - case 49: // TGEU - if(cpu->gpr[(inst >> 0x15) & 0x1F].w[1] >= cpu->gpr[(inst >> 0x10) & 0x1F].w[1]) { + case SPEC_TGEU: // TGEU + if(cpu->gpr[MIPS_RS(inst)].w[1] >= cpu->gpr[MIPS_RT(inst)].w[1]) { cpuException(cpu, 0xD, 0); } break; - case 50: // TGE - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] < cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]) { + case SPEC_TLT: // TGE + if(cpu->gpr[MIPS_RS(inst)].sw[1] < cpu->gpr[MIPS_RT(inst)].sw[1]) { cpuException(cpu, 0xD, 0); } break; - case 51: // TGEU - if(cpu->gpr[(inst >> 0x15) & 0x1F].w[1] < cpu->gpr[(inst >> 0x10) & 0x1F].w[1]) { + case SPEC_TLTU: // TGEU + if(cpu->gpr[MIPS_RS(inst)].w[1] < cpu->gpr[MIPS_RT(inst)].w[1]) { cpuException(cpu, 0xD, 0); } break; - case 52: // TEQ - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] == cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]) { + case SPEC_TEQ: // TEQ + if(cpu->gpr[MIPS_RS(inst)].sw[1] == cpu->gpr[MIPS_RT(inst)].sw[1]) { cpuException(cpu, 0xD, 0); } break; - case 53: - break; - case 54: // TNE - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] != cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]) { + case SPEC_TNE: // TNE + if(cpu->gpr[MIPS_RS(inst)].sw[1] != cpu->gpr[MIPS_RT(inst)].sw[1]) { cpuException(cpu, 0xD, 0); } break; - case 55: + case SPEC_DSLL: // DSLL + cpu->gpr[MIPS_RD(inst)].d = cpu->gpr[MIPS_RT(inst)].d << MIPS_SA(inst); break; - case 56: // DSLL - cpu->gpr[(inst >> 0xB) & 0x1F].d = cpu->gpr[(inst >> 0x10) & 0x1F].d << ((inst >> 6) & 0x1F); + case SPEC_DSRL: // DSRL + cpu->gpr[MIPS_RD(inst)].d = cpu->gpr[MIPS_RT(inst)].d >> MIPS_SA(inst); break; - case 57: + case SPEC_DSRA: // DSRA + cpu->gpr[MIPS_RD(inst)].sd = cpu->gpr[MIPS_RT(inst)].sd >> MIPS_SA(inst); break; - case 58: // DSRL - cpu->gpr[(inst >> 0xB) & 0x1F].d = cpu->gpr[(inst >> 0x10) & 0x1F].d >> ((inst >> 6) & 0x1F); + case SPEC_DSLL32: // DSLL32 + cpu->gpr[MIPS_RD(inst)].d = cpu->gpr[MIPS_RT(inst)].d << (MIPS_SA(inst) + 32); break; - case 59: // DSRA - cpu->gpr[(inst >> 0xB) & 0x1F].sd = cpu->gpr[(inst >> 0x10) & 0x1F].sd >> ((inst >> 6) & 0x1F); + case SPEC_DSRL32: // DSRL32 + cpu->gpr[MIPS_RD(inst)].d = cpu->gpr[MIPS_RT(inst)].d >> (MIPS_SA(inst) + 32); break; - case 60: // DSLL32 - cpu->gpr[(inst >> 0xB) & 0x1F].d = cpu->gpr[(inst >> 0x10) & 0x1F].d << (((inst >> 6) & 0x1F) + 32); - break; - case 61: - break; - case 62: // DSRL32 - cpu->gpr[(inst >> 0xB) & 0x1F].d = cpu->gpr[(inst >> 0x10) & 0x1F].d >> (((inst >> 6) & 0x1F) + 32); - break; - case 63: // DSRA32 - cpu->gpr[(inst >> 0xB) & 0x1F].sd = cpu->gpr[(inst >> 0x10) & 0x1F].sd >> (((inst >> 6) & 0x1F) + 32); + case SPEC_DSRA32: // DSRA32 + cpu->gpr[MIPS_RD(inst)].sd = cpu->gpr[MIPS_RT(inst)].sd >> (MIPS_SA(inst) + 32); break; } break; - case 1: - switch((inst >> 0x10) & 0x1F) { - case 0: // BLTZ - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] < 0) { - cpu->unk_0x24 = cpu->pc + ((s16)(inst & 0xFFFF) * 4); + case OPC_REGIMM: + switch(REGIMM_SUB(inst)) { + case REGIMM_BLTZ: // BLTZ + if(cpu->gpr[MIPS_RS(inst)].sw[1] < 0) { + cpu->unk_0x24 = cpu->pc + (MIPS_IMM(inst) * 4); } break; - case 1: // BGEZ - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] >= 0) { - cpu->unk_0x24 = cpu->pc + ((s16)(inst & 0xFFFF) * 4); + case REGIMM_BGEZ: // BGEZ + if(cpu->gpr[MIPS_RS(inst)].sw[1] >= 0) { + cpu->unk_0x24 = cpu->pc + (MIPS_IMM(inst) * 4); } break; - case 2: // BLTZL - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] < 0) { - cpu->unk_0x24 = cpu->pc + ((s16)(inst & 0xFFFF) * 4); + case REGIMM_BLTZL: // BLTZL + if(cpu->gpr[MIPS_RS(inst)].sw[1] < 0) { + cpu->unk_0x24 = cpu->pc + (MIPS_IMM(inst) * 4); } else { cpu->unk_0x00 |= 4; cpu->pc += 4; } break; - case 3: // BGEZL - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] >= 0) { - cpu->unk_0x24 = cpu->pc + ((s16)(inst & 0xFFFF) * 4); + case REGIMM_BGEZL: // BGEZL + if(cpu->gpr[MIPS_RS(inst)].sw[1] >= 0) { + cpu->unk_0x24 = cpu->pc + (MIPS_IMM(inst) * 4); } else { cpu->unk_0x00 |= 4; cpu->pc += 4; } break; - case 4: - case 5: - case 6: - case 7: - break; - case 8: // TGEI - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] >= (s16)(inst & 0xFFFF)) { + case REGIMM_TGEI: // TGEI + if(cpu->gpr[MIPS_RS(inst)].sw[1] >= MIPS_IMM(inst) ) { cpuException(cpu, 0xD, 0); } break; - case 9: // TGEIU - if(cpu->gpr[(inst >> 0x15) & 0x1F].w[1] >= (s16)(inst & 0xFFFF)) { + case REGIMM_TGEIU: // TGEIU + if(cpu->gpr[MIPS_RS(inst)].w[1] >= MIPS_IMM(inst) ) { cpuException(cpu, 0xD, 0); } break; - case 10: // TLTI - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] < (s16)(inst & 0xFFFF)) { + case REGIMM_TLTI: // TLTI + if(cpu->gpr[MIPS_RS(inst)].sw[1] < MIPS_IMM(inst) ) { cpuException(cpu, 0xD, 0); } break; - case 11: // TLTIU - if(cpu->gpr[(inst >> 0x15) & 0x1F].w[1] < (s16)(inst & 0xFFFF)) { + case REGIMM_TLTIU: // TLTIU + if(cpu->gpr[MIPS_RS(inst)].w[1] < MIPS_IMM(inst) ) { cpuException(cpu, 0xD, 0); } break; - case 12: // TEQI - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] == (s16)(inst & 0xFFFF)) { + case REGIMM_TEQI: // TEQI + if(cpu->gpr[MIPS_RS(inst)].sw[1] == MIPS_IMM(inst) ) { cpuException(cpu, 0xD, 0); } break; - case 13: - break; - case 14: // TNEI - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] != (s16)(inst & 0xFFFF)) { + case REGIMM_TNEI: // TNEI + if(cpu->gpr[MIPS_RS(inst)].sw[1] != MIPS_IMM(inst) ) { cpuException(cpu, 0xD, 0); } break; - case 15: - break; - case 16: // BLTZAL + case REGIMM_BLTZAL: // BLTZAL cpu->gpr[0x1F].w[1] = cpu->pc + 4; - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] < 0) { - cpu->unk_0x24 = cpu->unk_0x28 = cpu->pc + ((s16)(inst & 0xFFFF) * 4); + if(cpu->gpr[MIPS_RS(inst)].sw[1] < 0) { + cpu->unk_0x24 = cpu->unk_0x28 = cpu->pc + (MIPS_IMM(inst) * 4); } break; - case 17: // BGEZAL + case REGIMM_BGEZAL: // BGEZAL cpu->gpr[0x1F].w[1] = cpu->pc + 4; - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] >= 0) { - cpu->unk_0x24 = cpu->unk_0x28 = cpu->pc + ((s16)(inst & 0xFFFF) * 4); + if(cpu->gpr[MIPS_RS(inst)].sw[1] >= 0) { + cpu->unk_0x24 = cpu->unk_0x28 = cpu->pc + (MIPS_IMM(inst) * 4); } break; - case 18: // BLTZALL - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] < 0) { + case REGIMM_BLTZALL: // BLTZALL + if(cpu->gpr[MIPS_RS(inst)].sw[1] < 0) { cpu->gpr[0x1F].sw[1] = cpu->pc + 4; - cpu->unk_0x24 = cpu->pc + ((s16)(inst & 0xFFFF) * 4); + cpu->unk_0x24 = cpu->pc + (MIPS_IMM(inst) * 4); } else { cpu->unk_0x00 |= 4; cpu->pc += 4; } break; - case 19: // BGEZALL - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] >= 0) { + case REGIMM_BGEZALL: // BGEZALL + if(cpu->gpr[MIPS_RS(inst)].sw[1] >= 0) { cpu->gpr[0x1F].sw[1] = cpu->pc + 4; - cpu->unk_0x24 = cpu->pc + ((s16)(inst & 0xFFFF) * 4); + cpu->unk_0x24 = cpu->pc + (MIPS_IMM(inst) * 4); } else { cpu->unk_0x00 |= 4; cpu->pc += 4; @@ -901,7 +904,7 @@ void *cpuExecuteOpcode(cpu_class_t *cpu, s32 arg1, u32 addr, u32 *ret) { break; } break; - case 2: // J + case OPC_J: // J { cpu->unk_0x24 = (cpu->pc & 0xF0000000) | ((inst & 0x3FFFFFF) << 2); if(cpu->unk_0x24 != cpu->pc - 4) { @@ -913,7 +916,7 @@ void *cpuExecuteOpcode(cpu_class_t *cpu, s32 arg1, u32 addr, u32 *ret) { } } break; - case 3: //JAL + case OPC_JAL: //JAL { recomp_node_t *node; @@ -922,9 +925,9 @@ void *cpuExecuteOpcode(cpu_class_t *cpu, s32 arg1, u32 addr, u32 *ret) { cpuFindFunction(cpu, cpu->unk_0x24, &node); } break; - case 4: // BEQ - if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] == cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]) { - cpu->unk_0x24 = cpu->pc + (s16)(inst & 0xFFFF) * 4; + case OPC_BEQ: // BEQ + if(cpu->gpr[MIPS_RS(inst)].sw[1] == cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->unk_0x24 = cpu->pc + MIPS_IMM(inst) * 4; } if(cpu->unk_0x24 != cpu->pc - 4) { @@ -935,46 +938,47 @@ void *cpuExecuteOpcode(cpu_class_t *cpu, s32 arg1, u32 addr, u32 *ret) { return NULL; } break; - case 5: // BNE + case OPC_BNE: // BNE if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] != cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]) { - cpu->unk_0x24 = cpu->pc + (s16)(inst & 0xFFFF) * 4; + cpu->unk_0x24 = cpu->pc + MIPS_IMM(inst) * 4; } break; - case 6: // BLEZ + case OPC_BLEZ: // BLEZ if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] <= 0) { - cpu->unk_0x24 = cpu->pc + (s16)(inst & 0xFFFF) * 4; + cpu->unk_0x24 = cpu->pc + MIPS_IMM(inst) * 4; } break; - case 7: // BGTZ + case OPC_BGTZ: // BGTZ if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] > 0) { - cpu->unk_0x24 = cpu->pc + (s16)(inst & 0xFFFF) * 4; + cpu->unk_0x24 = cpu->pc + MIPS_IMM(inst) * 4; } break; - case 8: // ADDI - cpu->gpr[(inst >> 0x10) & 0x1F].sw[1] = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] + (s16)(inst & 0xFFFF); + case OPC_ADDI: // ADDI + cpu->gpr[(inst >> 0x10) & 0x1F].sw[1] = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] + MIPS_IMM(inst) ; break; - case 9: // ADDIU - cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + (s16)(inst & 0xFFFF); + case OPC_ADDIU: // ADDIU + cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst) ; break; - case 10: // SLTI - cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = !!(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] < (s16)(inst & 0xFFFF)); + case OPC_SLTI: // SLTI + cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = !!(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] < MIPS_IMM(inst) ); break; - case 11: // SLTIU - cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = !!(cpu->gpr[(inst >> 0x15) & 0x1F].w[1] < (s16)(inst & 0xFFFF)); + case OPC_SLTIU: // SLTIU + cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = !!(cpu->gpr[(inst >> 0x15) & 0x1F].w[1] < MIPS_IMM(inst) ); break; - case 12: // ANDI + case OPC_ANDI: // ANDI cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] & (inst & 0xFFFF); break; - case 13: // ORI + case OPC_ORI: // ORI cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] | (inst & 0xFFFF); break; - case 14: // XORI + case OPC_XORI: // XORI cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] ^ (inst & 0xFFFF); break; - case 15: // LUI + case OPC_LUI: // LUI cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = (inst & 0xFFFF) << 0x10; + break; - case 16: // CP0 + case OPC_CP0: // CP0 switch(inst & 0x3F) { case 1: // TLBR cpu->cp0[2].d = cpu->unk_0x248[cpu->cp0[0].w[1] & 0x3F].unk_0x00.d; @@ -987,9 +991,6 @@ void *cpuExecuteOpcode(cpu_class_t *cpu, s32 arg1, u32 addr, u32 *ret) { break; case 5: // TLBWR { - s32 i; - s32 val; - for(i = 0; i < 0x30; i++) { if(!(cpu->unk_0x248[i].unk_0x10.w[1] & 2)) { val++; @@ -1002,9 +1003,6 @@ void *cpuExecuteOpcode(cpu_class_t *cpu, s32 arg1, u32 addr, u32 *ret) { break; case 8: // TLBP { - s32 i; - s32 val; - cpu->cp0[0].d |= 0x80000000; for(i = 0; i < 0x30; i++) { @@ -1027,125 +1025,116 @@ void *cpuExecuteOpcode(cpu_class_t *cpu, s32 arg1, u32 addr, u32 *ret) { } cpu->unk_0x00 |= 0x24; break; - case 0: // SUB - case 3: - case 4: - case 6: - case 7: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - case 17: - case 18: - case 19: - case 20: - case 21: - case 22: - case 23: + case 0: + default: switch((inst >> 0x15) & 0x1F) { case 0: // MFC0 { - u32 res; - - if(!func_8000E2B0(cpu, (inst >> 0xB) & 0x1F, &res)) { + if(!func_8000E2B0(cpu, (inst >> 0xB) & 0x1F, &tmp.w[1])) { break; } - cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = res; + cpu->gpr[(inst >> 0x10) & 0x1F].d = tmp.d & 0xFFFFFFFFUL; } break; case 1: // DMFC0 { - u32 res[2]; - if(!func_8000E2B0(cpu, (inst >> 0xB) & 0x1F, res)) { + if(!func_8000E2B0(cpu, (inst >> 0xB) & 0x1F, &tmp.w[0])) { break; } - cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = res[1]; - cpu->gpr[(inst >> 0x10) & 0x1F].w[0] = res[0]; + cpu->gpr[(inst >> 0x10) & 0x1F].d = tmp.d; } break; + case 2: + break; case 4: // MTC0 func_8000E0E8(cpu, (inst >> 0xB) & 0x1F, 0, cpu->gpr[(inst >> 0x10) & 0x1F].w[1]); break; case 5: // DMTC0 func_8000E0E8(cpu, (inst >> 0xB) & 0x1F, cpu->gpr[(inst >> 0x10) & 0x1F].w[0], cpu->gpr[(inst >> 0x10) & 0x1F].w[1]); break; + case 6: + break; } break; - - } break; - case 17: // CP1 - if((inst & 0x7FF) == 0) { - switch((inst >> 0x15) & 0x1F) { - case 0: // MFC1 - if((inst >> 0x10) & 1) { - cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = cpu->fpr[(inst >> 0xB) & 0x1F].w[0]; - } else { - cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = cpu->fpr[(inst >> 0xB) & 0x1F].w[1]; - } - break; - case 1: // DMFC1 - cpu->gpr[(inst >> 0x10) & 0x1F].d = cpu->fpr[(inst >> 0xB) & 0x1F].d; - break; - case 2: // CFC1 - cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = cpu->fscr[(inst >> 0xB) & 0x1F]; - break; - case 4: - if((inst >> 0xB) & 1) { - cpu->fpr[(inst >> 0xB) & 0x1F].w[0] = cpu->gpr[(inst >> 0x10) & 0x1F].w[1]; - } else { - cpu->fpr[(inst >> 0xB) & 0x1F].w[1] = cpu->gpr[(inst >> 0x10) & 0x1F].w[1]; - } - break; - case 5: - cpu->fpr[(inst >> 0xB) & 0x1F].d = cpu->fpr[(inst >> 0xB) & 0x1F].d; - break; + case OPC_CP1: + if(MIPS_FDT(inst) == 0) { + if(MIPS_FSUB(inst) >= 0x10) { + break; + } + switch(MIPS_FSUB(inst)) { + case MIPS_FSUB_MFC: + if(MIPS_FS(inst) & 1) { + cpu->gpr[MIPS_RT(inst)].w[1] = cpu->fpr[MIPS_FS(inst) - 1].w[0]; + } else { + cpu->gpr[MIPS_RT(inst)].w[1] = cpu->fpr[MIPS_FS(inst)].w[1]; + } + break; + case MIPS_FSUB_DMFC: + cpu->gpr[MIPS_RT(inst)].d = cpu->fpr[MIPS_FS(inst)].d; + break; + case MIPS_FSUB_CFC: + cpu->gpr[MIPS_RT(inst)].w[1] = cpu->fscr[MIPS_FS(inst)]; + break; + case MIPS_FSUB_MTC: + if(MIPS_FS(inst) & 1) { + cpu->fpr[MIPS_FS(inst) - 1].d = cpu->fpr[MIPS_FS(inst) - 1].d & 0xFFFFFFFFUL; + cpu->fpr[MIPS_FS(inst) - 1].d |= ((u64)cpu->gpr[MIPS_RT(inst)].w[1] << 32); + + } else { + cpu->fpr[MIPS_FS(inst)].w[1] = cpu->gpr[MIPS_RT(inst)].w[1]; + } + break; + case MIPS_FSUB_DMTC: + cpu->fpr[MIPS_FS(inst)].d = cpu->gpr[MIPS_RT(inst)].d; + break; + case MIPS_FSUB_CTC: + cpu->fscr[MIPS_FS(inst)] = cpu->gpr[MIPS_RT(inst)].w[1]; + break; + } + break; + } + + // Condition Code + if(MIPS_FFMT(inst) == 8) { + switch((inst >> 0x10) & 0x1F) { + case 0: // BC1F + if(!(cpu->fscr[0x1F] & 0x800000)) { + cpu->unk_0x24 = cpu->pc + MIPS_IMM(inst) * 4; + } + break; + case 1: // BC1T + if(cpu->fscr[0x1F] & 0x800000) { + cpu->unk_0x24 = cpu->pc + MIPS_IMM(inst) * 4; + } + break; + case 2: // BC1FL + if(!(cpu->fscr[0x1F] & 0x800000)) { + cpu->unk_0x24 = cpu->pc + MIPS_IMM(inst) * 4; + } else { + cpu->unk_0x00 |= 4; + cpu->pc += 4; + } + break; + case 3: // BC1TL + if(cpu->fscr[0x1F] & 0x800000) { + cpu->unk_0x24 = cpu->pc + MIPS_IMM(inst) * 4; + } else { + cpu->unk_0x00 |= 4; + cpu->pc += 4; + } + break; } break; } - switch((inst >> 0x15) & 0x1F) { - case 8: - switch((inst >> 0x10) & 0x1F) { - case 0: // BC1F - if(!(cpu->fscr[0x1F] & 0x800000)) { - cpu->unk_0x24 = cpu->pc + (s16)(inst & 0xFFFF) * 4; - } - break; - case 1: // BC1T - if(cpu->fscr[0x1F] & 0x800000) { - cpu->unk_0x24 = cpu->pc + (s16)(inst & 0xFFFF) * 4; - } - break; - case 2: // BC1FL - if(!(cpu->fscr[0x1F] & 0x800000)) { - cpu->unk_0x24 = cpu->pc + (s16)(inst & 0xFFFF) * 4; - } else { - cpu->unk_0x00 |= 4; - cpu->pc += 4; - } - break; - case 3: // BC1TL - if(cpu->fscr[0x1F] & 0x800000) { - cpu->unk_0x24 = cpu->pc + (s16)(inst & 0xFFFF) * 4; - } else { - cpu->unk_0x00 |= 4; - cpu->pc += 4; - } - break; - } - break; - case 0x10: // SINGLE - switch(inst & 0x3F) { + switch(MIPS_FFMT(inst)) { + case MIPS_FMT_SINGLE: + switch(MIPS_FFUNC(inst)) { case 0: // ADD.S cpu->fpr[(inst >> 6) & 0x1F].f[1] = cpu->fpr[(inst >> 0xB) & 0x1F].f[1] + cpu->fpr[(inst >> 0x10) & 0x1F].f[1]; break; @@ -1191,7 +1180,7 @@ void *cpuExecuteOpcode(cpu_class_t *cpu, s32 arg1, u32 addr, u32 *ret) { case 14: // CEIL.W.S cpu->fpr[(inst >> 6) & 0x1F].sw[1] = ceil(cpu->fpr[(inst >> 0xB) & 0x1F].f[1]); break; - case 15: // FLOOR.L.S + case 15: // FLOOR.W.S cpu->fpr[(inst >> 6) & 0x1F].sw[1] = floor(cpu->fpr[(inst >> 0xB) & 0x1F].f[1]); break; case 16: @@ -1250,26 +1239,1078 @@ void *cpuExecuteOpcode(cpu_class_t *cpu, s32 arg1, u32 addr, u32 *ret) { cpu->fscr[0x1F] &= ~0x00800000; } break; - - + case 52: // C.UEQ.S + if(cpu->fpr[(inst >> 0xB) & 0x1F].f[1] == cpu->fpr[(inst >> 0x10) & 0x1F].f[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 53: // C.OLT.S + if(cpu->fpr[(inst >> 0xB) & 0x1F].f[1] < cpu->fpr[(inst >> 0x10) & 0x1F].f[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 54: // C.ULT.S + if(cpu->fpr[(inst >> 0xB) & 0x1F].f[1] < cpu->fpr[(inst >> 0x10) & 0x1F].f[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 55: // C.OLE.S + if(cpu->fpr[(inst >> 0xB) & 0x1F].f[1] <= cpu->fpr[(inst >> 0x10) & 0x1F].f[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 56: // C.ULE.S + if(cpu->fpr[(inst >> 0xB) & 0x1F].f[1] <= cpu->fpr[(inst >> 0x10) & 0x1F].f[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 57: // C.SF.S + cpu->fscr[0x1F] &= ~0x00800000; + break; + case 58: // C.NGLE.S + if(cpu->fpr[(inst >> 0xB) & 0x1F].f[1] <= cpu->fpr[(inst >> 0x10) & 0x1F].f[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 59: // C.SEQ.S + if(cpu->fpr[(inst >> 0xB) & 0x1F].f[1] == cpu->fpr[(inst >> 0x10) & 0x1F].f[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 60: // C.NGL.S + if(cpu->fpr[(inst >> 0xB) & 0x1F].f[1] == cpu->fpr[(inst >> 0x10) & 0x1F].f[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 61: // C.LT.S + if(cpu->fpr[(inst >> 0xB) & 0x1F].f[1] < cpu->fpr[(inst >> 0x10) & 0x1F].f[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 62: // C.NGE.S + if(cpu->fpr[(inst >> 0xB) & 0x1F].f[1] < cpu->fpr[(inst >> 0x10) & 0x1F].f[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 63: // C.LE.S + if(cpu->fpr[(inst >> 0xB) & 0x1F].f[1] <= cpu->fpr[(inst >> 0x10) & 0x1F].f[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 64: // C.NGT.S + if(cpu->fpr[(inst >> 0xB) & 0x1F].f[1] <= cpu->fpr[(inst >> 0x10) & 0x1F].f[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; } break; - case 0x11: // DOUBLE - case 0x14: // LONG - case 0x15: // WORD + case MIPS_FMT_DOUBLE: + switch(MIPS_FFUNC(inst)) { + case 0: // ADD.D + cpu->fpr[(inst >> 6) & 0x1F].fd = cpu->fpr[(inst >> 0xB) & 0x1F].fd + cpu->fpr[(inst >> 0x10) & 0x1F].fd; + break; + case 1: // SUB.D + cpu->fpr[(inst >> 6) & 0x1F].fd = cpu->fpr[(inst >> 0xB) & 0x1F].fd - cpu->fpr[(inst >> 0x10) & 0x1F].fd; + break; + case 3: // MUL.D + cpu->fpr[(inst >> 6) & 0x1F].fd = cpu->fpr[(inst >> 0xB) & 0x1F].fd * cpu->fpr[(inst >> 0x10) & 0x1F].fd; + break; + case 4: // DIV.D + cpu->fpr[(inst >> 6) & 0x1F].fd = cpu->fpr[(inst >> 0xB) & 0x1F].fd / cpu->fpr[(inst >> 0x10) & 0x1F].fd; + break; + case 5: // SQRT.D + cpu->fpr[(inst >> 6) & 0x1F].fd = sqrt(cpu->fpr[(inst >> 0xB) & 0x1F].fd); + break; + case 6: // ABS.D + cpu->fpr[(inst >> 6) & 0x1F].fd = __fabs(cpu->fpr[(inst >> 0xB) & 0x1F].fd); + break; + case 7: // MOV.D + cpu->fpr[(inst >> 6) & 0x1F].fd = cpu->fpr[(inst >> 0xB) & 0x1F].fd; + break; + case 8: // NEG.D + cpu->fpr[(inst >> 6) & 0x1F].fd = -cpu->fpr[(inst >> 0xB) & 0x1F].fd; + break; + case 9: // ROUND.L.D + cpu->fpr[(inst >> 6) & 0x1F].sd = 0.5 + cpu->fpr[(inst >> 0xB) & 0x1F].fd; + break; + case 10: // TRUNC.L.D + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].fd; + break; + case 11: // CEIL.L.D + cpu->fpr[(inst >> 6) & 0x1F].sd = ceil(cpu->fpr[(inst >> 0xB) & 0x1F].fd); + break; + case 12: // FLOOR.L.D + cpu->fpr[(inst >> 6) & 0x1F].sd = floor(cpu->fpr[(inst >> 0xB) & 0x1F].fd); + break; + case 13: // ROUND.W.D + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = 0.5 + cpu->fpr[(inst >> 0xB) & 0x1F].fd; + break; + case 14: // TRUNC.W.D + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].fd; + break; + case 15: // CEIL.W.D + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = ceil(cpu->fpr[(inst >> 0xB) & 0x1F].fd); + break; + case 16: // FLOOR.W.D + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = floor(cpu->fpr[(inst >> 0xB) & 0x1F].fd); + break; + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + break; + case 33: // CVT.S.D + cpu->fpr[(inst >> 6) & 0x1F].f[1] = cpu->fpr[(inst >> 0xB) & 0x1F].fd; + break; + case 34: // CVT.D.D + cpu->fpr[(inst >> 6) & 0x1F].fd = cpu->fpr[(inst >> 0xB) & 0x1F].fd; + break; + case 35: + case 36: + break; + case 37: // CVT.W.D + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].fd; + break; + case 38: // CVT.L.D + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].fd; + break; + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + break; + case 49: // C.F.D + cpu->fscr[0x1F] &= ~0x00800000; + break; + case 50: // C.UN.D + cpu->fscr[0x1F] &= ~0x00800000; + break; + case 51: // C.EQ.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd == cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 52: // C.UEQ.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd == cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 53: // C.OLT.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd < cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 54: // C.ULT.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd < cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 55: // C.OLE.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd <= cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 56: // C.ULE.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd <= cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 57: // C.SF.D + cpu->fscr[0x1F] &= ~0x00800000; + break; + case 58: // C.NGLE.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd <= cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 59: // C.SEQ.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd == cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 60: // C.NGL.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd == cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 61: // C.LT.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd < cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 62: // C.NGE.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd < cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 63: // C.LE.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd <= cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 64: // C.NGT.D + if(cpu->fpr[(inst >> 0xB) & 0x1F].fd <= cpu->fpr[(inst >> 0x10) & 0x1F].fd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + } + break; + case MIPS_FMT_WORD: + switch(MIPS_FFUNC(inst)) { + case 0: // ADD.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] + cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]; + break; + case 1: // SUB.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] - cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]; + break; + case 2: // MUL.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] * cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]; + break; + case 3: // DIV.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] / cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]; + break; + case 4: // SQRT.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = sqrt(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]); + break; + case 5: // ABS.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = __fabs(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]); + break; + case 6: // MOV.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]; + break; + case 7: // NEG.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = -cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]; + break; + case 8: // ROUND.L.W + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]; + break; + case 9: // TRUNC.L.W + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]; + break; + case 10: // CEIL.L.W + cpu->fpr[(inst >> 6) & 0x1F].sd = ceil(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]); + break; + case 11: // FLOOR.L.W + cpu->fpr[(inst >> 6) & 0x1F].sd = floor(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]); + break; + case 12: // ROUND.W.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]; + break; + case 13: // TRUNC.W.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]; + break; + case 14: // CEIL.W.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = ceil(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]); + break; + case 15: // FLOOR.W.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = floor(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]); + break; + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + break; + case 32: // CVT.S.W + cpu->fpr[(inst >> 6) & 0x1F].f[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]; + break; + case 33: // CVT.D.W + cpu->fpr[(inst >> 6) & 0x1F].fd = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]; + break; + case 34: + case 35: + break; + case 37: // CVT.W.W + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]; + break; + case 38: // CVT.L.W + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].sw[1]; + break; + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + break; + case 49: // C.F.W + cpu->fscr[0x1F] &= ~0x00800000; + break; + case 50: // C.UN.W + cpu->fscr[0x1F] &= ~0x00800000; + break; + case 51: // C.EQ.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] == cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 52: // C.UEQ.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] == cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 53: // C.OLT.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] < cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 54: // C.ULT.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] < cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 55: // C.OLE.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] <= cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 56: // C.ULE.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] <= cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 57: // C.SF.W + cpu->fscr[0x1F] &= ~0x00800000; + break; + case 58: // C.NGLE.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] <= cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 59: // C.SEQ.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] == cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 60: // C.NGL.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] == cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 61: // C.LT.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] < cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 62: // C.NGE.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] < cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 63: // C.LE.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] <= cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 64: // C.NGT.W + if(cpu->fpr[(inst >> 0xB) & 0x1F].sw[1] <= cpu->fpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + } + break; + case MIPS_FMT_DBLWORD: + switch(MIPS_FFUNC(inst)) { + case 0: // ADD.L + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].sd + cpu->fpr[(inst >> 0x10) & 0x1F].sd; + break; + case 1: // SUB.L + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].sd - cpu->fpr[(inst >> 0x10) & 0x1F].sd; + break; + case 2: // MUL.L + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].sd * cpu->fpr[(inst >> 0x10) & 0x1F].sd; + break; + case 3: // DIV.L + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].sd / cpu->fpr[(inst >> 0x10) & 0x1F].sd; + break; + case 4: // SQRT.L + cpu->fpr[(inst >> 6) & 0x1F].sd = sqrt(cpu->fpr[(inst >> 0xB) & 0x1F].sd); + break; + case 5: // ABS.L + cpu->fpr[(inst >> 6) & 0x1F].sd = __fabs(cpu->fpr[(inst >> 0xB) & 0x1F].sd); + break; + case 6: // MOV.L + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].sd; + break; + case 7: // NEG.L + cpu->fpr[(inst >> 6) & 0x1F].sd = -cpu->fpr[(inst >> 0xB) & 0x1F].sd; + break; + case 8: // ROUND.L.L + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].sd; + break; + case 9: // TRUNC.L.L + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].sd; + break; + case 10: // CEIL.L.L + cpu->fpr[(inst >> 6) & 0x1F].sd = ceil(cpu->fpr[(inst >> 0xB) & 0x1F].sd); + break; + case 11: // FLOOR.L.L + cpu->fpr[(inst >> 6) & 0x1F].sd = floor(cpu->fpr[(inst >> 0xB) & 0x1F].sd); + break; + case 12: // ROUND.W.L + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sd; + break; + case 13: // TRUNC.W.L + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sd; + break; + case 14: // CEIL.W.L + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = ceil(cpu->fpr[(inst >> 0xB) & 0x1F].sd); + break; + case 15: // FLOOR.W.L + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = floor(cpu->fpr[(inst >> 0xB) & 0x1F].sd); + break; + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + break; + case 32: // CVT.S.L + cpu->fpr[(inst >> 6) & 0x1F].f[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sd; + break; + case 33: // CVT.D.L + cpu->fpr[(inst >> 6) & 0x1F].fd = cpu->fpr[(inst >> 0xB) & 0x1F].sd; + break; + case 34: + case 35: + break; + case 37: // CVT.W.L + cpu->fpr[(inst >> 6) & 0x1F].sw[1] = cpu->fpr[(inst >> 0xB) & 0x1F].sd; + break; + case 38: // CVT.L.L + cpu->fpr[(inst >> 6) & 0x1F].sd = cpu->fpr[(inst >> 0xB) & 0x1F].sd; + break; + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + break; + case 49: // C.F.L + cpu->fscr[0x1F] &= ~0x00800000; + break; + case 50: // C.UN.L + cpu->fscr[0x1F] &= ~0x00800000; + break; + case 51: // C.EQ.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd == cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 52: // C.UEQ.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd == cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 53: // C.OLT.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd < cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 54: // C.ULT.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd < cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 55: // C.OLE.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd <= cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 56: // C.ULE.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd <= cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 57: // C.SF.L + cpu->fscr[0x1F] &= ~0x00800000; + break; + case 58: // C.NGLE.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd <= cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 59: // C.SEQ.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd == cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 60: // C.NGL.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd == cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 61: // C.LT.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd < cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 62: // C.NGE.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd < cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 63: // C.LE.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd <= cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + case 64: // C.NGT.L + if(cpu->fpr[(inst >> 0xB) & 0x1F].sd <= cpu->fpr[(inst >> 0x10) & 0x1F].sd) { + cpu->fscr[0x1F] |= 0x00800000; + } else { + cpu->fscr[0x1F] &= ~0x00800000; + } + break; + } break; - } + break; + case 20: // BEQL + if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] == cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->unk_0x24 = cpu->pc + MIPS_IMM(inst) * 4; + } else { + cpu->unk_0x00 |= 4; + cpu->pc += 4; + } + break; + case 21: // BNEL + if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] != cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]) { + cpu->unk_0x24 = cpu->pc + MIPS_IMM(inst) * 4; + } else { + cpu->unk_0x00 |= 4; + cpu->pc += 4; + } + break; + case 22: // BLEZL + if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] <= 0) { + cpu->unk_0x24 = cpu->pc + MIPS_IMM(inst) * 4; + } else { + cpu->unk_0x00 |= 4; + cpu->pc += 4; + } + break; + case 23: // BGTZL + if(cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] > 0) { + cpu->unk_0x24 = cpu->pc + MIPS_IMM(inst) * 4; + } else { + cpu->unk_0x00 |= 4; + cpu->pc += 4; + } + break; + case 24: // DADDI + cpu->gpr[(inst >> 0x10) & 0x1F].sd = cpu->gpr[(inst >> 0x15) & 0x1F].sd + MIPS_IMM(inst) ; + break; + case 25: // DADDIU + cpu->gpr[(inst >> 0x10) & 0x1F].d = cpu->gpr[(inst >> 0x15) & 0x1F].sd + MIPS_IMM(inst) ; + break; + case 31: // precompiled function. + if(!func_8005D614(gSystem->unk_0x0058, cpu, MIPS_IMM(inst) )) { + return NULL; + } + break; + case 26: // LDL + { + s32 sh = 0x38; + u8 buf; + ea = MIPS_IMM(inst) + cpu->gpr[MIPS_RS(inst)].sw[1]; + + do { + dev = devs[dev_idx[ea >> 0x10]]; + + if(dev->lb(dev->unk_4, ea + dev->unk_8, (s8*)&buf)) { + tmp.d = (u64)buf << sh; + cpu->gpr[(inst >> 0x10) & 0x1F].d = tmp.d | (cpu->gpr[(inst >> 0x10) & 0x1F].d & ~((u64)0xFF << sh)); + } + + ea++; + sh -= 8; + + } while((ea - 1) & 7); + } + break; + case 27: // LDR + { + s32 sh = 0; + u8 buf; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] + MIPS_IMM(inst) ; + + do { + if(devs[dev_idx[ea >> 0x10]]->lb(devs[dev_idx[ea >> 0x10]]->unk_4, ea + devs[dev_idx[ea >> 0x10]]->unk_8, (s8*)&buf)) { + tmp.d = (u64)buf << sh; + cpu->gpr[(inst >> 0x10) & 0x1F].d = tmp.d | (cpu->gpr[(inst >> 0x10) & 0x1F].d & ~((u64)0xFF << sh)); + } + ea--; + sh += 8; + } while((ea + 1) & 7); + } + break; + case 39: // LWU + { + u32 dst; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + if(dev->lw(dev->unk_4, ea + dev->unk_8, (s32*)&dst)) { + cpu->gpr[(inst >> 0x10) & 0x1F].d = dst; + } + } + break; + case 32: // LB + { + s8 dst; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + if(dev->lb(dev->unk_4, ea + dev->unk_8, &dst)) { + cpu->gpr[(inst >> 0x10) & 0x1F].sw[1] = dst; + } + } + break; + case 33: // LH + { + s16 dst; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + if(dev->lh(dev->unk_4, ea + dev->unk_8, &dst)) { + cpu->gpr[(inst >> 0x10) & 0x1F].sw[1] = dst; + } + } + break; + case 34: // LWL + { + u8 buf; + s32 sh = 0x18; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] + MIPS_IMM(inst); + + do { + dev = devs[dev_idx[ea >> 0x10]]; + if(dev->lb(dev->unk_4, ea + dev->unk_8, (s8*)&buf)) { + tmp.w[1] = (u32)buf << sh; + cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = tmp.w[1] | (cpu->gpr[(inst >> 0x10) & 0x1F].w[1] & ~((u32)0xFF << sh)); + } + ea++; + sh -= 8; + } while((ea - 1) & 3); + } + break; + case 35: // LW + { + s32 dst; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + if(dev->lw(dev->unk_4, ea + dev->unk_8, &dst)) { + cpu->gpr[(inst >> 0x10) & 0x1F].sw[1] = dst; + } + } + break; + case 36: // LBU + { + u8 dst; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + if(dev->lb(dev->unk_4, ea + dev->unk_8, (s8*)&dst)) { + cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = dst; + } + } + break; + case 37: // LHU + { + u16 dst; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + + if(func_80052D68(gSystem->frame, &dst, ea)) { + cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = dst; + break; + } + dev = devs[dev_idx[ea >> 0x10]]; + + if(dev->lh(dev->unk_4, ea + dev->unk_8, (s16*)&dst)) { + cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = dst; + } + } + break; + case 38: // LWR + { + u8 buf; + s32 sh = 0; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] + MIPS_IMM(inst); + + do { + dev = devs[dev_idx[ea >> 0x10]]; + if(dev->lb(dev->unk_4, ea + dev->unk_8, (s8*)&buf)) { + tmp.w[1] = (u32)buf << sh; + cpu->gpr[(inst >> 0x10) & 0x1F].w[1] = tmp.w[1] | (cpu->gpr[(inst >> 0x10) & 0x1F].w[1] & ~((u32)0xFF << sh)); + } + ea--; + sh += 8; + } while((ea + 1) & 3); + } + break; + case 40: // SB + { + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + dev->sb(dev->unk_4, ea + dev->unk_8, (s8*)&cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]); + } + break; + case 41: // SH + { + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + dev->sh(dev->unk_4, ea + dev->unk_8, (s16*)&cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]); + } + break; + case 42: // SWL + { + s8 buf; + s32 sh = 0x18; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] + MIPS_IMM(inst); + + do { + buf = cpu->gpr[(inst >> 0x10) & 0x1F].w[1] >> sh; + dev = devs[dev_idx[ea >> 0x10]]; + dev->sb(dev->unk_4, ea + dev->unk_8, &buf); + ea++; + sh -= 8; + } while((ea - 1) & 3); + } + break; + case 43: // SW + { + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + dev->sw(dev->unk_4, ea + dev->unk_8, &cpu->gpr[(inst >> 0x10) & 0x1F].sw[1]); + } + break; + case 44: // SDL + { + s8 buf; + s32 sh = 0x38; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] + MIPS_IMM(inst); + + do { + buf = cpu->gpr[(inst >> 0x10) & 0x1F].d >> sh; + dev = devs[dev_idx[ea >> 0x10]]; + dev->sb(dev->unk_4, ea + dev->unk_8, &buf); + ea++; + sh -= 8; + } while((ea - 1) & 7); + } + break; + case 45: // SDR + { + s8 buf; + s32 sh = 0; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] + MIPS_IMM(inst); + + do { + buf = cpu->gpr[(inst >> 0x10) & 0x1F].d >> sh; + dev = devs[dev_idx[ea >> 0x10]]; + dev->sb(dev->unk_4, ea + dev->unk_8, &buf); + ea--; + sh += 8; + } while((ea + 1) & 7); + } + break; + break; + case 46: // SWR + { + s8 buf; + s32 sh = 0; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].sw[1] + MIPS_IMM(inst); + + do { + buf = cpu->gpr[(inst >> 0x10) & 0x1F].w[1] >> sh; + dev = devs[dev_idx[ea >> 0x10]]; + dev->sb(dev->unk_4, ea + dev->unk_8, &buf); + ea--; + sh += 8; + } while((ea + 1) & 3); + } + break; + case 48: // LL + { + s32 dst; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + if(dev->lw(dev->unk_4, ea + dev->unk_8, &dst)) { + cpu->gpr[(inst >> 0x10) & 0x1F].sw[1] = dst; + } + } + break; + case 49: // LWC1 + { + s32 dst; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + if(dev->lw(dev->unk_4, ea + dev->unk_8, &dst)) { + if((inst >> 0x10) & 1) { + cpu->fpr[MIPS_FS(inst) - 1].d = cpu->fpr[MIPS_FS(inst) - 1].d & 0xFFFFFFFFUL; + cpu->fpr[MIPS_FS(inst) - 1].d |= ((u64)cpu->gpr[MIPS_RT(inst)].w[1] << 32); + } else { + cpu->fpr[(inst >> 0x10) & 0x1F].sw[1] = dst; + } + } + } + break; + case 52: // LLD + { + s64 dst; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + if(dev->ld(dev->unk_4, ea + dev->unk_8, &dst)) { + cpu->gpr[(inst >> 0x10) & 0x1F].d = dst; + } + } + break; + case 53: // LDC1 + { + s64 dst; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + if(dev->ld(dev->unk_4, ea + dev->unk_8, &dst)) { + cpu->fpr[(inst >> 0x10) & 0x1F].d = dst; + } + } + break; + case 55: // LD + { + s64 dst; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + if(dev->ld(dev->unk_4, ea + dev->unk_8, &dst)) { + cpu->gpr[(inst >> 0x10) & 0x1F].d = dst; + } + } + break; + case 56: // SC + { + ea = cpu->gpr[(inst >> 0x10) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + cpu->gpr[(inst >> 0x10) & 0x1F].sw[1] = !!dev->sw(dev->unk_4, ea + dev->unk_8, &cpu->gpr[(inst >> 0x15) & 0x1F].sw[1]); + } + break; + case 57: // SWC1 + { + u32 buf; + + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + if((inst >> 0x10) & 1) { + buf = cpu->fpr[(inst >> 0x10) & 0x1F].w[0]; + } else { + buf = cpu->fpr[(inst >> 0x10) & 0x1F].w[1]; + } + + dev->sw(dev->unk_4, ea + dev->unk_8, (s32*)&buf); + } + break; + case 60: // SCD + { + ea = cpu->gpr[(inst >> 0x10) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + cpu->gpr[(inst >> 0x10) & 0x1F].sw[1] = !!dev->sd(dev->unk_4, ea + dev->unk_8, &cpu->gpr[(inst >> 0x15) & 0x1F].sd); + } + break; + case 61: // SDC1 + { + u64 buf = cpu->fpr[(inst >> 0x10) & 0x1F].d; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + dev->sd(dev->unk_4, ea + dev->unk_8, (s64*)&buf); + } + break; + case 63: + { + u64 buf = cpu->gpr[(inst >> 0x10) & 0x1F].d; + ea = cpu->gpr[(inst >> 0x15) & 0x1F].w[1] + MIPS_IMM(inst); + dev = devs[dev_idx[ea >> 0x10]]; + + dev->sd(dev->unk_4, ea + dev->unk_8, (s64*)&buf); + } + break; + } if(!cpuExecuteUpdate(cpu, &ret, tick + 1)) { return NULL; } - if(inst == 0xACBF011C) { - cpu->gpr[0x1F] = prev_ra; + if(save_ra) { + cpu->gpr[0x1F].d = prev_ra; } + + cpu->unk_0x24 = -1; + cpu->unk_0x38 = OSGetTick(); + + return ret; } + //#pragma GLOBAL_ASM("asm/non_matchings/virtual_console/cpu/cpuExecuteOpcode.s") s32 videoForceRetrace(void *);