From 57e8694a3fd34c900203c7a2b329e2c97f3d36a3 Mon Sep 17 00:00:00 2001 From: Ville Linde Date: Mon, 17 Jul 2006 11:17:01 +0000 Subject: [PATCH] Fixed VF3 and Scud Race --- ppc_drc/genx86.c | 46 +++++++++++++++++++++ ppc_drc/genx86.h | 6 +++ ppc_drc/ppc_drc.c | 16 ++++++-- ppc_drc/ppc_drc_ops.c | 96 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 3 deletions(-) diff --git a/ppc_drc/genx86.c b/ppc_drc/genx86.c index 7e75cfc..f8c8346 100644 --- a/ppc_drc/genx86.c +++ b/ppc_drc/genx86.c @@ -356,6 +356,52 @@ void gen(GENX86_OPCODE opcode, INT32 dst_param, INT32 src_param) break; } + case FABS: + { + emit_byte(0xd9); + emit_byte(0xe1); + break; + } + + case FCHS: + { + emit_byte(0xd9); + emit_byte(0xe0); + break; + } + + case FADDM64: + { + emit_byte(0xdc); + emit_byte(0x05); + emit_dword(dst_param); + break; + } + + case FDIVM64: + { + emit_byte(0xdc); + emit_byte(0x35); + emit_dword(dst_param); + break; + } + + case FLDM64: + { + emit_byte(0xdd); + emit_byte(0x05); + emit_dword(dst_param); + break; + } + + case FSTPM64: + { + emit_byte(0xdd); + emit_byte(0x1d); + emit_dword(dst_param); + break; + } + case IDIV: { emit_byte(0xf7); diff --git a/ppc_drc/genx86.h b/ppc_drc/genx86.h index 581b7c8..d4818f9 100644 --- a/ppc_drc/genx86.h +++ b/ppc_drc/genx86.h @@ -89,6 +89,12 @@ typedef enum CMPMR, CVTSD2SS, CVTSS2SD, + FABS, + FCHS, + FADDM64, + FDIVM64, + FLDM64, + FSTPM64, IDIV, IMUL, JA, diff --git a/ppc_drc/ppc_drc.c b/ppc_drc/ppc_drc.c index 2ccc198..988976c 100644 --- a/ppc_drc/ppc_drc.c +++ b/ppc_drc/ppc_drc.c @@ -8,6 +8,7 @@ #define DISABLE_UNTESTED_OPS 0 #define ENABLE_FASTRAM_PATH 1 #define ENABLE_FASTRAM_PATH_FPU 1 +#define COMPILE_FPU_OPS 1 #define DONT_COMPILE_ADD 0 #define DONT_COMPILE_ADDC 0 @@ -289,7 +290,7 @@ static PPC_REGS ppc; static UINT32 ppc_rotate_mask[32][32]; -#define TB_DIVIDER 5 +#define TB_DIVIDER 4 INLINE int CYCLES_TO_DEC(int cycles) { @@ -526,6 +527,12 @@ INLINE void ppc_set_spr(int spr, UINT32 value) { /* trigger interrupt */ //ppc.interrupt_pending |= 0x2; + ppc.interrupt_pending |= 0x2; + if (ppc.msr & MSR_EE) + { + ppc_stolen_cycles += ppc_icount; + ppc_icount = 0; + } } write_decrementer(value); return; @@ -1072,8 +1079,11 @@ void ppc_set_irq_line(int irqline) { ppc.interrupt_pending |= 0x1; - ppc_stolen_cycles += ppc_icount; - ppc_icount = 0; + if (ppc.msr & MSR_EE) + { + ppc_stolen_cycles += ppc_icount; + ppc_icount = 0; + } } UINT32 ppc_get_pc(void) diff --git a/ppc_drc/ppc_drc_ops.c b/ppc_drc/ppc_drc_ops.c index 05091ce..91a2f95 100644 --- a/ppc_drc/ppc_drc_ops.c +++ b/ppc_drc/ppc_drc_ops.c @@ -4,6 +4,7 @@ static UINT32 drc_invalid_area(void) } #define PPCREG(x) ((UINT32)&ppc.r[x]) +#define FPRREG(x) ((UINT32)&ppc.fpr[x].fd) static int block_cycle_count; static UINT32 block_start_pc; @@ -36,6 +37,9 @@ static UINT32 drc_recompile_block(void) gen(SUBIM, (UINT32)&ppc_icount, 1); op = READ32(drc_pc); + + if (op == 0) break; // VF3 will hit this + switch (op >> 26) { case 19: res = drc_op_table19[(op >> 1) & 0x3ff](op); break; @@ -68,6 +72,13 @@ static void insert_set_cr0(int reg) gen(MOVR8M8, (UINT32)&ppc.cr[0], REG_AL); } +static void insert_set_cr1(void) +{ + gen(MOVMR, REG_EBX, (UINT32)&ppc.fpscr); + gen(SHRI, REG_EBX, 28); + gen(MOVR8M8, (UINT32)&ppc.cr[1], REG_BL); +} + static UINT32 drc_add(UINT32 op) @@ -3801,19 +3812,48 @@ static UINT32 drc_ecowx(UINT32 op) static UINT32 drc_fabs(UINT32 op) { +#if !COMPILE_FPU_OPS || DONT_COMPILE_FABS + gen(PUSHI, op, 0); gen(CALLI, (UINT32)(ppc_fabsx), 0); gen(ADDI, REG_ESP, 4); +#else + + gen(FLDM64, FPRREG(RB), 0); + gen(FABS, 0, 0); + gen(FSTPM64, FPRREG(RD), 0); + if (RCBIT) + { + insert_set_cr1(); + } + +#endif return 0; } static UINT32 drc_fadd(UINT32 op) { +#if !COMPILE_FPU_OPS || DONT_COMPILE_FADD + gen(PUSHI, op, 0); gen(CALLI, (UINT32)(ppc_faddx), 0); gen(ADDI, REG_ESP, 4); +#else + + gen(FLDM64, FPRREG(RA), 0); + gen(FADDM64, FPRREG(RB), 0); + gen(FSTPM64, FPRREG(RD), 0); + + // TODO: FPSCR/FPRF + + if (RCBIT) + { + insert_set_cr1(); + } + +#endif return 0; } @@ -3855,37 +3895,93 @@ static UINT32 drc_fctiwz(UINT32 op) static UINT32 drc_fdiv(UINT32 op) { +#if !COMPILE_FPU_OPS || DONT_COMPILE_FDIV + gen(PUSHI, op, 0); gen(CALLI, (UINT32)(ppc_fdivx), 0); gen(ADDI, REG_ESP, 4); +#else + + gen(FLDM64, FPRREG(RA), 0); + gen(FDIVM64, FPRREG(RB), 0); + gen(FSTPM64, FPRREG(RD), 0); + + // TODO: FPSCR/FPRF + + if (RCBIT) + { + insert_set_cr1(); + } + +#endif return 0; } static UINT32 drc_fmr(UINT32 op) { +#if !COMPILE_FPU_OPS || DONT_COMPILE_FMR + gen(PUSHI, op, 0); gen(CALLI, (UINT32)(ppc_fmrx), 0); gen(ADDI, REG_ESP, 4); +#else + + gen(FLDM64, FPRREG(RB), 0); + gen(FSTPM64, FPRREG(RD), 0); + if (RCBIT) + { + insert_set_cr1(); + } + +#endif return 0; } +// NOTE: not tested! static UINT32 drc_fnabs(UINT32 op) { +#if !COMPILE_FPU_OPS || DONT_COMPILE_FNABS || DISABLE_UNTESTED_OPS + gen(PUSHI, op, 0); gen(CALLI, (UINT32)(ppc_fnabsx), 0); gen(ADDI, REG_ESP, 4); +#else + + gen(FLDM64, FPRREG(RB), 0); + gen(FABS, 0, 0); + gen(FCHS, 0, 0); + gen(FSTPM64, FPRREG(RD), 0); + if (RCBIT) + { + insert_set_cr1(); + } + +#endif return 0; } static UINT32 drc_fneg(UINT32 op) { +#if !COMPILE_FPU_OPS || DONT_COMPILE_FNEG + gen(PUSHI, op, 0); gen(CALLI, (UINT32)(ppc_fnegx), 0); gen(ADDI, REG_ESP, 4); +#else + + gen(FLDM64, FPRREG(RB), 0); + gen(FCHS, 0, 0); + gen(FSTPM64, FPRREG(RD), 0); + if (RCBIT) + { + insert_set_cr1(); + } + +#endif return 0; }