X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=source%2Fmupen64plus-core%2Fsrc%2Fr4300%2Frecomp.c;fp=source%2Fmupen64plus-core%2Fsrc%2Fr4300%2Frecomp.c;h=dfca49aa6cb764acef1e01266486dd6ad8fc62cc;hb=451ab91e3827a6384981b3300e2a7000d2eaba58;hp=0000000000000000000000000000000000000000;hpb=a2ab25365b5b0dddbee476d695d8a31151407581;p=mupen64plus-pandora.git diff --git a/source/mupen64plus-core/src/r4300/recomp.c b/source/mupen64plus-core/src/r4300/recomp.c new file mode 100644 index 0000000..dfca49a --- /dev/null +++ b/source/mupen64plus-core/src/r4300/recomp.c @@ -0,0 +1,2674 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - recomp.h * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2002 Hacktarux * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include +#include + +#if defined(__GNUC__) +#include +#ifndef __MINGW32__ +#include +#endif +#endif + +#include "api/m64p_types.h" +#include "api/callbacks.h" +#include "memory/memory.h" + +#include "recomp.h" +#include "recomph.h" //include for function prototypes +#include "macros.h" +#include "r4300.h" +#include "ops.h" + +static void *malloc_exec(size_t size); +static void free_exec(void *ptr, size_t length); + +// global variables : +precomp_instr *dst; // destination structure for the recompiled instruction +int code_length; // current real recompiled code length +int max_code_length; // current recompiled code's buffer length +unsigned char **inst_pointer; // output buffer for recompiled code +precomp_block *dst_block; // the current block that we are recompiling +int src; // the current recompiled instruction +int fast_memory; + +static void (*recomp_func)(void); // pointer to the dynarec's generator + // function for the latest decoded opcode + +#if defined(PROFILE_R4300) +FILE *pfProfile; +#endif + +static int *SRC; // currently recompiled instruction in the input stream +static int check_nop; // next instruction is nop ? +static int delay_slot_compiled = 0; + + + +static void RSV(void) +{ + dst->ops = current_instruction_table.RESERVED; + recomp_func = genreserved; +} + +static void RFIN_BLOCK(void) +{ + dst->ops = current_instruction_table.FIN_BLOCK; + recomp_func = genfin_block; +} + +static void RNOTCOMPILED(void) +{ + dst->ops = current_instruction_table.NOTCOMPILED; + recomp_func = gennotcompiled; +} + +static void recompile_standard_i_type(void) +{ + dst->f.i.rs = reg + ((src >> 21) & 0x1F); + dst->f.i.rt = reg + ((src >> 16) & 0x1F); + dst->f.i.immediate = src & 0xFFFF; +} + +static void recompile_standard_j_type(void) +{ + dst->f.j.inst_index = src & 0x3FFFFFF; +} + +static void recompile_standard_r_type(void) +{ + dst->f.r.rs = reg + ((src >> 21) & 0x1F); + dst->f.r.rt = reg + ((src >> 16) & 0x1F); + dst->f.r.rd = reg + ((src >> 11) & 0x1F); + dst->f.r.sa = (src >> 6) & 0x1F; +} + +static void recompile_standard_lf_type(void) +{ + dst->f.lf.base = (src >> 21) & 0x1F; + dst->f.lf.ft = (src >> 16) & 0x1F; + dst->f.lf.offset = src & 0xFFFF; +} + +static void recompile_standard_cf_type(void) +{ + dst->f.cf.ft = (src >> 16) & 0x1F; + dst->f.cf.fs = (src >> 11) & 0x1F; + dst->f.cf.fd = (src >> 6) & 0x1F; +} + +//------------------------------------------------------------------------- +// SPECIAL +//------------------------------------------------------------------------- + +static void RNOP(void) +{ + dst->ops = current_instruction_table.NOP; + recomp_func = gennop; +} + +static void RSLL(void) +{ + dst->ops = current_instruction_table.SLL; + recomp_func = gensll; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RSRL(void) +{ + dst->ops = current_instruction_table.SRL; + recomp_func = gensrl; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RSRA(void) +{ + dst->ops = current_instruction_table.SRA; + recomp_func = gensra; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RSLLV(void) +{ + dst->ops = current_instruction_table.SLLV; + recomp_func = gensllv; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RSRLV(void) +{ + dst->ops = current_instruction_table.SRLV; + recomp_func = gensrlv; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RSRAV(void) +{ + dst->ops = current_instruction_table.SRAV; + recomp_func = gensrav; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RJR(void) +{ + dst->ops = current_instruction_table.JR; + recomp_func = genjr; + recompile_standard_i_type(); +} + +static void RJALR(void) +{ + dst->ops = current_instruction_table.JALR; + recomp_func = genjalr; + recompile_standard_r_type(); +} + +static void RSYSCALL(void) +{ + dst->ops = current_instruction_table.SYSCALL; + recomp_func = gensyscall; +} + +static void RBREAK(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; +} + +static void RSYNC(void) +{ + dst->ops = current_instruction_table.SYNC; + recomp_func = gensync; +} + +static void RMFHI(void) +{ + dst->ops = current_instruction_table.MFHI; + recomp_func = genmfhi; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RMTHI(void) +{ + dst->ops = current_instruction_table.MTHI; + recomp_func = genmthi; + recompile_standard_r_type(); +} + +static void RMFLO(void) +{ + dst->ops = current_instruction_table.MFLO; + recomp_func = genmflo; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RMTLO(void) +{ + dst->ops = current_instruction_table.MTLO; + recomp_func = genmtlo; + recompile_standard_r_type(); +} + +static void RDSLLV(void) +{ + dst->ops = current_instruction_table.DSLLV; + recomp_func = gendsllv; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RDSRLV(void) +{ + dst->ops = current_instruction_table.DSRLV; + recomp_func = gendsrlv; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RDSRAV(void) +{ + dst->ops = current_instruction_table.DSRAV; + recomp_func = gendsrav; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RMULT(void) +{ + dst->ops = current_instruction_table.MULT; + recomp_func = genmult; + recompile_standard_r_type(); +} + +static void RMULTU(void) +{ + dst->ops = current_instruction_table.MULTU; + recomp_func = genmultu; + recompile_standard_r_type(); +} + +static void RDIV(void) +{ + dst->ops = current_instruction_table.DIV; + recomp_func = gendiv; + recompile_standard_r_type(); +} + +static void RDIVU(void) +{ + dst->ops = current_instruction_table.DIVU; + recomp_func = gendivu; + recompile_standard_r_type(); +} + +static void RDMULT(void) +{ + dst->ops = current_instruction_table.DMULT; + recomp_func = gendmult; + recompile_standard_r_type(); +} + +static void RDMULTU(void) +{ + dst->ops = current_instruction_table.DMULTU; + recomp_func = gendmultu; + recompile_standard_r_type(); +} + +static void RDDIV(void) +{ + dst->ops = current_instruction_table.DDIV; + recomp_func = genddiv; + recompile_standard_r_type(); +} + +static void RDDIVU(void) +{ + dst->ops = current_instruction_table.DDIVU; + recomp_func = genddivu; + recompile_standard_r_type(); +} + +static void RADD(void) +{ + dst->ops = current_instruction_table.ADD; + recomp_func = genadd; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RADDU(void) +{ + dst->ops = current_instruction_table.ADDU; + recomp_func = genaddu; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RSUB(void) +{ + dst->ops = current_instruction_table.SUB; + recomp_func = gensub; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RSUBU(void) +{ + dst->ops = current_instruction_table.SUBU; + recomp_func = gensubu; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RAND(void) +{ + dst->ops = current_instruction_table.AND; + recomp_func = genand; + recompile_standard_r_type(); + if(dst->f.r.rd == reg) RNOP(); +} + +static void ROR(void) +{ + dst->ops = current_instruction_table.OR; + recomp_func = genor; + recompile_standard_r_type(); + if(dst->f.r.rd == reg) RNOP(); +} + +static void RXOR(void) +{ + dst->ops = current_instruction_table.XOR; + recomp_func = genxor; + recompile_standard_r_type(); + if(dst->f.r.rd == reg) RNOP(); +} + +static void RNOR(void) +{ + dst->ops = current_instruction_table.NOR; + recomp_func = gennor; + recompile_standard_r_type(); + if(dst->f.r.rd == reg) RNOP(); +} + +static void RSLT(void) +{ + dst->ops = current_instruction_table.SLT; + recomp_func = genslt; + recompile_standard_r_type(); + if(dst->f.r.rd == reg) RNOP(); +} + +static void RSLTU(void) +{ + dst->ops = current_instruction_table.SLTU; + recomp_func = gensltu; + recompile_standard_r_type(); + if(dst->f.r.rd == reg) RNOP(); +} + +static void RDADD(void) +{ + dst->ops = current_instruction_table.DADD; + recomp_func = gendadd; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RDADDU(void) +{ + dst->ops = current_instruction_table.DADDU; + recomp_func = gendaddu; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RDSUB(void) +{ + dst->ops = current_instruction_table.DSUB; + recomp_func = gendsub; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RDSUBU(void) +{ + dst->ops = current_instruction_table.DSUBU; + recomp_func = gendsubu; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RTGE(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; +} + +static void RTGEU(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; +} + +static void RTLT(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; +} + +static void RTLTU(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; +} + +static void RTEQ(void) +{ + dst->ops = current_instruction_table.TEQ; + recomp_func = genteq; + recompile_standard_r_type(); +} + +static void RTNE(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; +} + +static void RDSLL(void) +{ + dst->ops = current_instruction_table.DSLL; + recomp_func = gendsll; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RDSRL(void) +{ + dst->ops = current_instruction_table.DSRL; + recomp_func = gendsrl; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RDSRA(void) +{ + dst->ops = current_instruction_table.DSRA; + recomp_func = gendsra; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RDSLL32(void) +{ + dst->ops = current_instruction_table.DSLL32; + recomp_func = gendsll32; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RDSRL32(void) +{ + dst->ops = current_instruction_table.DSRL32; + recomp_func = gendsrl32; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void RDSRA32(void) +{ + dst->ops = current_instruction_table.DSRA32; + recomp_func = gendsra32; + recompile_standard_r_type(); + if (dst->f.r.rd == reg) RNOP(); +} + +static void (*recomp_special[64])(void) = +{ + RSLL , RSV , RSRL , RSRA , RSLLV , RSV , RSRLV , RSRAV , + RJR , RJALR , RSV , RSV , RSYSCALL, RBREAK , RSV , RSYNC , + RMFHI, RMTHI , RMFLO, RMTLO, RDSLLV , RSV , RDSRLV , RDSRAV , + RMULT, RMULTU, RDIV , RDIVU, RDMULT , RDMULTU, RDDIV , RDDIVU , + RADD , RADDU , RSUB , RSUBU, RAND , ROR , RXOR , RNOR , + RSV , RSV , RSLT , RSLTU, RDADD , RDADDU , RDSUB , RDSUBU , + RTGE , RTGEU , RTLT , RTLTU, RTEQ , RSV , RTNE , RSV , + RDSLL, RSV , RDSRL, RDSRA, RDSLL32 , RSV , RDSRL32, RDSRA32 +}; + +//------------------------------------------------------------------------- +// REGIMM +//------------------------------------------------------------------------- + +static void RBLTZ(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BLTZ; + recomp_func = genbltz; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BLTZ_IDLE; + recomp_func = genbltz_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BLTZ_OUT; + recomp_func = genbltz_out; + } +} + +static void RBGEZ(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BGEZ; + recomp_func = genbgez; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BGEZ_IDLE; + recomp_func = genbgez_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BGEZ_OUT; + recomp_func = genbgez_out; + } +} + +static void RBLTZL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BLTZL; + recomp_func = genbltzl; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BLTZL_IDLE; + recomp_func = genbltzl_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BLTZL_OUT; + recomp_func = genbltzl_out; + } +} + +static void RBGEZL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BGEZL; + recomp_func = genbgezl; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BGEZL_IDLE; + recomp_func = genbgezl_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BGEZL_OUT; + recomp_func = genbgezl_out; + } +} + +static void RTGEI(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; +} + +static void RTGEIU(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; +} + +static void RTLTI(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; +} + +static void RTLTIU(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; +} + +static void RTEQI(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; +} + +static void RTNEI(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; +} + +static void RBLTZAL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BLTZAL; + recomp_func = genbltzal; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BLTZAL_IDLE; + recomp_func = genbltzal_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BLTZAL_OUT; + recomp_func = genbltzal_out; + } +} + +static void RBGEZAL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BGEZAL; + recomp_func = genbgezal; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BGEZAL_IDLE; + recomp_func = genbgezal_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BGEZAL_OUT; + recomp_func = genbgezal_out; + } +} + +static void RBLTZALL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BLTZALL; + recomp_func = genbltzall; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BLTZALL_IDLE; + recomp_func = genbltzall_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BLTZALL_OUT; + recomp_func = genbltzall_out; + } +} + +static void RBGEZALL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BGEZALL; + recomp_func = genbgezall; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BGEZALL_IDLE; + recomp_func = genbgezall_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BGEZALL_OUT; + recomp_func = genbgezall_out; + } +} + +static void (*recomp_regimm[32])(void) = +{ + RBLTZ , RBGEZ , RBLTZL , RBGEZL , RSV , RSV, RSV , RSV, + RTGEI , RTGEIU , RTLTI , RTLTIU , RTEQI, RSV, RTNEI, RSV, + RBLTZAL, RBGEZAL, RBLTZALL, RBGEZALL, RSV , RSV, RSV , RSV, + RSV , RSV , RSV , RSV , RSV , RSV, RSV , RSV +}; + +//------------------------------------------------------------------------- +// TLB +//------------------------------------------------------------------------- + +static void RTLBR(void) +{ + dst->ops = current_instruction_table.TLBR; + recomp_func = gentlbr; +} + +static void RTLBWI(void) +{ + dst->ops = current_instruction_table.TLBWI; + recomp_func = gentlbwi; +} + +static void RTLBWR(void) +{ + dst->ops = current_instruction_table.TLBWR; + recomp_func = gentlbwr; +} + +static void RTLBP(void) +{ + dst->ops = current_instruction_table.TLBP; + recomp_func = gentlbp; +} + +static void RERET(void) +{ + dst->ops = current_instruction_table.ERET; + recomp_func = generet; +} + +static void (*recomp_tlb[64])(void) = +{ + RSV , RTLBR, RTLBWI, RSV, RSV, RSV, RTLBWR, RSV, + RTLBP, RSV , RSV , RSV, RSV, RSV, RSV , RSV, + RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV, + RERET, RSV , RSV , RSV, RSV, RSV, RSV , RSV, + RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV, + RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV, + RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV, + RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV +}; + +//------------------------------------------------------------------------- +// COP0 +//------------------------------------------------------------------------- + +static void RMFC0(void) +{ + dst->ops = current_instruction_table.MFC0; + recomp_func = genmfc0; + recompile_standard_r_type(); + dst->f.r.rd = (long long*)(reg_cop0 + ((src >> 11) & 0x1F)); + dst->f.r.nrd = (src >> 11) & 0x1F; + if (dst->f.r.rt == reg) RNOP(); +} + +static void RMTC0(void) +{ + dst->ops = current_instruction_table.MTC0; + recomp_func = genmtc0; + recompile_standard_r_type(); + dst->f.r.nrd = (src >> 11) & 0x1F; +} + +static void RTLB(void) +{ + recomp_tlb[(src & 0x3F)](); +} + +static void (*recomp_cop0[32])(void) = +{ + RMFC0, RSV, RSV, RSV, RMTC0, RSV, RSV, RSV, + RSV , RSV, RSV, RSV, RSV , RSV, RSV, RSV, + RTLB , RSV, RSV, RSV, RSV , RSV, RSV, RSV, + RSV , RSV, RSV, RSV, RSV , RSV, RSV, RSV +}; + +//------------------------------------------------------------------------- +// BC +//------------------------------------------------------------------------- + +static void RBC1F(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BC1F; + recomp_func = genbc1f; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BC1F_IDLE; + recomp_func = genbc1f_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BC1F_OUT; + recomp_func = genbc1f_out; + } +} + +static void RBC1T(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BC1T; + recomp_func = genbc1t; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BC1T_IDLE; + recomp_func = genbc1t_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BC1T_OUT; + recomp_func = genbc1t_out; + } +} + +static void RBC1FL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BC1FL; + recomp_func = genbc1fl; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BC1FL_IDLE; + recomp_func = genbc1fl_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BC1FL_OUT; + recomp_func = genbc1fl_out; + } +} + +static void RBC1TL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BC1TL; + recomp_func = genbc1tl; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BC1TL_IDLE; + recomp_func = genbc1tl_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BC1TL_OUT; + recomp_func = genbc1tl_out; + } +} + +static void (*recomp_bc[4])(void) = +{ + RBC1F , RBC1T , + RBC1FL, RBC1TL +}; + +//------------------------------------------------------------------------- +// S +//------------------------------------------------------------------------- + +static void RADD_S(void) +{ + dst->ops = current_instruction_table.ADD_S; + recomp_func = genadd_s; + recompile_standard_cf_type(); +} + +static void RSUB_S(void) +{ + dst->ops = current_instruction_table.SUB_S; + recomp_func = gensub_s; + recompile_standard_cf_type(); +} + +static void RMUL_S(void) +{ + dst->ops = current_instruction_table.MUL_S; + recomp_func = genmul_s; + recompile_standard_cf_type(); +} + +static void RDIV_S(void) +{ + dst->ops = current_instruction_table.DIV_S; + recomp_func = gendiv_s; + recompile_standard_cf_type(); +} + +static void RSQRT_S(void) +{ + dst->ops = current_instruction_table.SQRT_S; + recomp_func = gensqrt_s; + recompile_standard_cf_type(); +} + +static void RABS_S(void) +{ + dst->ops = current_instruction_table.ABS_S; + recomp_func = genabs_s; + recompile_standard_cf_type(); +} + +static void RMOV_S(void) +{ + dst->ops = current_instruction_table.MOV_S; + recomp_func = genmov_s; + recompile_standard_cf_type(); +} + +static void RNEG_S(void) +{ + dst->ops = current_instruction_table.NEG_S; + recomp_func = genneg_s; + recompile_standard_cf_type(); +} + +static void RROUND_L_S(void) +{ + dst->ops = current_instruction_table.ROUND_L_S; + recomp_func = genround_l_s; + recompile_standard_cf_type(); +} + +static void RTRUNC_L_S(void) +{ + dst->ops = current_instruction_table.TRUNC_L_S; + recomp_func = gentrunc_l_s; + recompile_standard_cf_type(); +} + +static void RCEIL_L_S(void) +{ + dst->ops = current_instruction_table.CEIL_L_S; + recomp_func = genceil_l_s; + recompile_standard_cf_type(); +} + +static void RFLOOR_L_S(void) +{ + dst->ops = current_instruction_table.FLOOR_L_S; + recomp_func = genfloor_l_s; + recompile_standard_cf_type(); +} + +static void RROUND_W_S(void) +{ + dst->ops = current_instruction_table.ROUND_W_S; + recomp_func = genround_w_s; + recompile_standard_cf_type(); +} + +static void RTRUNC_W_S(void) +{ + dst->ops = current_instruction_table.TRUNC_W_S; + recomp_func = gentrunc_w_s; + recompile_standard_cf_type(); +} + +static void RCEIL_W_S(void) +{ + dst->ops = current_instruction_table.CEIL_W_S; + recomp_func = genceil_w_s; + recompile_standard_cf_type(); +} + +static void RFLOOR_W_S(void) +{ + dst->ops = current_instruction_table.FLOOR_W_S; + recomp_func = genfloor_w_s; + recompile_standard_cf_type(); +} + +static void RCVT_D_S(void) +{ + dst->ops = current_instruction_table.CVT_D_S; + recomp_func = gencvt_d_s; + recompile_standard_cf_type(); +} + +static void RCVT_W_S(void) +{ + dst->ops = current_instruction_table.CVT_W_S; + recomp_func = gencvt_w_s; + recompile_standard_cf_type(); +} + +static void RCVT_L_S(void) +{ + dst->ops = current_instruction_table.CVT_L_S; + recomp_func = gencvt_l_s; + recompile_standard_cf_type(); +} + +static void RC_F_S(void) +{ + dst->ops = current_instruction_table.C_F_S; + recomp_func = genc_f_s; + recompile_standard_cf_type(); +} + +static void RC_UN_S(void) +{ + dst->ops = current_instruction_table.C_UN_S; + recomp_func = genc_un_s; + recompile_standard_cf_type(); +} + +static void RC_EQ_S(void) +{ + dst->ops = current_instruction_table.C_EQ_S; + recomp_func = genc_eq_s; + recompile_standard_cf_type(); +} + +static void RC_UEQ_S(void) +{ + dst->ops = current_instruction_table.C_UEQ_S; + recomp_func = genc_ueq_s; + recompile_standard_cf_type(); +} + +static void RC_OLT_S(void) +{ + dst->ops = current_instruction_table.C_OLT_S; + recomp_func = genc_olt_s; + recompile_standard_cf_type(); +} + +static void RC_ULT_S(void) +{ + dst->ops = current_instruction_table.C_ULT_S; + recomp_func = genc_ult_s; + recompile_standard_cf_type(); +} + +static void RC_OLE_S(void) +{ + dst->ops = current_instruction_table.C_OLE_S; + recomp_func = genc_ole_s; + recompile_standard_cf_type(); +} + +static void RC_ULE_S(void) +{ + dst->ops = current_instruction_table.C_ULE_S; + recomp_func = genc_ule_s; + recompile_standard_cf_type(); +} + +static void RC_SF_S(void) +{ + dst->ops = current_instruction_table.C_SF_S; + recomp_func = genc_sf_s; + recompile_standard_cf_type(); +} + +static void RC_NGLE_S(void) +{ + dst->ops = current_instruction_table.C_NGLE_S; + recomp_func = genc_ngle_s; + recompile_standard_cf_type(); +} + +static void RC_SEQ_S(void) +{ + dst->ops = current_instruction_table.C_SEQ_S; + recomp_func = genc_seq_s; + recompile_standard_cf_type(); +} + +static void RC_NGL_S(void) +{ + dst->ops = current_instruction_table.C_NGL_S; + recomp_func = genc_ngl_s; + recompile_standard_cf_type(); +} + +static void RC_LT_S(void) +{ + dst->ops = current_instruction_table.C_LT_S; + recomp_func = genc_lt_s; + recompile_standard_cf_type(); +} + +static void RC_NGE_S(void) +{ + dst->ops = current_instruction_table.C_NGE_S; + recomp_func = genc_nge_s; + recompile_standard_cf_type(); +} + +static void RC_LE_S(void) +{ + dst->ops = current_instruction_table.C_LE_S; + recomp_func = genc_le_s; + recompile_standard_cf_type(); +} + +static void RC_NGT_S(void) +{ + dst->ops = current_instruction_table.C_NGT_S; + recomp_func = genc_ngt_s; + recompile_standard_cf_type(); +} + +static void (*recomp_s[64])(void) = +{ + RADD_S , RSUB_S , RMUL_S , RDIV_S , RSQRT_S , RABS_S , RMOV_S , RNEG_S , + RROUND_L_S, RTRUNC_L_S, RCEIL_L_S, RFLOOR_L_S, RROUND_W_S, RTRUNC_W_S, RCEIL_W_S, RFLOOR_W_S, + RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV , + RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV , + RSV , RCVT_D_S , RSV , RSV , RCVT_W_S , RCVT_L_S , RSV , RSV , + RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV , + RC_F_S , RC_UN_S , RC_EQ_S , RC_UEQ_S , RC_OLT_S , RC_ULT_S , RC_OLE_S , RC_ULE_S , + RC_SF_S , RC_NGLE_S , RC_SEQ_S , RC_NGL_S , RC_LT_S , RC_NGE_S , RC_LE_S , RC_NGT_S +}; + +//------------------------------------------------------------------------- +// D +//------------------------------------------------------------------------- + +static void RADD_D(void) +{ + dst->ops = current_instruction_table.ADD_D; + recomp_func = genadd_d; + recompile_standard_cf_type(); +} + +static void RSUB_D(void) +{ + dst->ops = current_instruction_table.SUB_D; + recomp_func = gensub_d; + recompile_standard_cf_type(); +} + +static void RMUL_D(void) +{ + dst->ops = current_instruction_table.MUL_D; + recomp_func = genmul_d; + recompile_standard_cf_type(); +} + +static void RDIV_D(void) +{ + dst->ops = current_instruction_table.DIV_D; + recomp_func = gendiv_d; + recompile_standard_cf_type(); +} + +static void RSQRT_D(void) +{ + dst->ops = current_instruction_table.SQRT_D; + recomp_func = gensqrt_d; + recompile_standard_cf_type(); +} + +static void RABS_D(void) +{ + dst->ops = current_instruction_table.ABS_D; + recomp_func = genabs_d; + recompile_standard_cf_type(); +} + +static void RMOV_D(void) +{ + dst->ops = current_instruction_table.MOV_D; + recomp_func = genmov_d; + recompile_standard_cf_type(); +} + +static void RNEG_D(void) +{ + dst->ops = current_instruction_table.NEG_D; + recomp_func = genneg_d; + recompile_standard_cf_type(); +} + +static void RROUND_L_D(void) +{ + dst->ops = current_instruction_table.ROUND_L_D; + recomp_func = genround_l_d; + recompile_standard_cf_type(); +} + +static void RTRUNC_L_D(void) +{ + dst->ops = current_instruction_table.TRUNC_L_D; + recomp_func = gentrunc_l_d; + recompile_standard_cf_type(); +} + +static void RCEIL_L_D(void) +{ + dst->ops = current_instruction_table.CEIL_L_D; + recomp_func = genceil_l_d; + recompile_standard_cf_type(); +} + +static void RFLOOR_L_D(void) +{ + dst->ops = current_instruction_table.FLOOR_L_D; + recomp_func = genfloor_l_d; + recompile_standard_cf_type(); +} + +static void RROUND_W_D(void) +{ + dst->ops = current_instruction_table.ROUND_W_D; + recomp_func = genround_w_d; + recompile_standard_cf_type(); +} + +static void RTRUNC_W_D(void) +{ + dst->ops = current_instruction_table.TRUNC_W_D; + recomp_func = gentrunc_w_d; + recompile_standard_cf_type(); +} + +static void RCEIL_W_D(void) +{ + dst->ops = current_instruction_table.CEIL_W_D; + recomp_func = genceil_w_d; + recompile_standard_cf_type(); +} + +static void RFLOOR_W_D(void) +{ + dst->ops = current_instruction_table.FLOOR_W_D; + recomp_func = genfloor_w_d; + recompile_standard_cf_type(); +} + +static void RCVT_S_D(void) +{ + dst->ops = current_instruction_table.CVT_S_D; + recomp_func = gencvt_s_d; + recompile_standard_cf_type(); +} + +static void RCVT_W_D(void) +{ + dst->ops = current_instruction_table.CVT_W_D; + recomp_func = gencvt_w_d; + recompile_standard_cf_type(); +} + +static void RCVT_L_D(void) +{ + dst->ops = current_instruction_table.CVT_L_D; + recomp_func = gencvt_l_d; + recompile_standard_cf_type(); +} + +static void RC_F_D(void) +{ + dst->ops = current_instruction_table.C_F_D; + recomp_func = genc_f_d; + recompile_standard_cf_type(); +} + +static void RC_UN_D(void) +{ + dst->ops = current_instruction_table.C_UN_D; + recomp_func = genc_un_d; + recompile_standard_cf_type(); +} + +static void RC_EQ_D(void) +{ + dst->ops = current_instruction_table.C_EQ_D; + recomp_func = genc_eq_d; + recompile_standard_cf_type(); +} + +static void RC_UEQ_D(void) +{ + dst->ops = current_instruction_table.C_UEQ_D; + recomp_func = genc_ueq_d; + recompile_standard_cf_type(); +} + +static void RC_OLT_D(void) +{ + dst->ops = current_instruction_table.C_OLT_D; + recomp_func = genc_olt_d; + recompile_standard_cf_type(); +} + +static void RC_ULT_D(void) +{ + dst->ops = current_instruction_table.C_ULT_D; + recomp_func = genc_ult_d; + recompile_standard_cf_type(); +} + +static void RC_OLE_D(void) +{ + dst->ops = current_instruction_table.C_OLE_D; + recomp_func = genc_ole_d; + recompile_standard_cf_type(); +} + +static void RC_ULE_D(void) +{ + dst->ops = current_instruction_table.C_ULE_D; + recomp_func = genc_ule_d; + recompile_standard_cf_type(); +} + +static void RC_SF_D(void) +{ + dst->ops = current_instruction_table.C_SF_D; + recomp_func = genc_sf_d; + recompile_standard_cf_type(); +} + +static void RC_NGLE_D(void) +{ + dst->ops = current_instruction_table.C_NGLE_D; + recomp_func = genc_ngle_d; + recompile_standard_cf_type(); +} + +static void RC_SEQ_D(void) +{ + dst->ops = current_instruction_table.C_SEQ_D; + recomp_func = genc_seq_d; + recompile_standard_cf_type(); +} + +static void RC_NGL_D(void) +{ + dst->ops = current_instruction_table.C_NGL_D; + recomp_func = genc_ngl_d; + recompile_standard_cf_type(); +} + +static void RC_LT_D(void) +{ + dst->ops = current_instruction_table.C_LT_D; + recomp_func = genc_lt_d; + recompile_standard_cf_type(); +} + +static void RC_NGE_D(void) +{ + dst->ops = current_instruction_table.C_NGE_D; + recomp_func = genc_nge_d; + recompile_standard_cf_type(); +} + +static void RC_LE_D(void) +{ + dst->ops = current_instruction_table.C_LE_D; + recomp_func = genc_le_d; + recompile_standard_cf_type(); +} + +static void RC_NGT_D(void) +{ + dst->ops = current_instruction_table.C_NGT_D; + recomp_func = genc_ngt_d; + recompile_standard_cf_type(); +} + +static void (*recomp_d[64])(void) = +{ + RADD_D , RSUB_D , RMUL_D , RDIV_D , RSQRT_D , RABS_D , RMOV_D , RNEG_D , + RROUND_L_D, RTRUNC_L_D, RCEIL_L_D, RFLOOR_L_D, RROUND_W_D, RTRUNC_W_D, RCEIL_W_D, RFLOOR_W_D, + RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV , + RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV , + RCVT_S_D , RSV , RSV , RSV , RCVT_W_D , RCVT_L_D , RSV , RSV , + RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV , + RC_F_D , RC_UN_D , RC_EQ_D , RC_UEQ_D , RC_OLT_D , RC_ULT_D , RC_OLE_D , RC_ULE_D , + RC_SF_D , RC_NGLE_D , RC_SEQ_D , RC_NGL_D , RC_LT_D , RC_NGE_D , RC_LE_D , RC_NGT_D +}; + +//------------------------------------------------------------------------- +// W +//------------------------------------------------------------------------- + +static void RCVT_S_W(void) +{ + dst->ops = current_instruction_table.CVT_S_W; + recomp_func = gencvt_s_w; + recompile_standard_cf_type(); +} + +static void RCVT_D_W(void) +{ + dst->ops = current_instruction_table.CVT_D_W; + recomp_func = gencvt_d_w; + recompile_standard_cf_type(); +} + +static void (*recomp_w[64])(void) = +{ + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, + RCVT_S_W, RCVT_D_W, RSV, RSV, RSV, RSV, RSV, RSV, + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV +}; + +//------------------------------------------------------------------------- +// L +//------------------------------------------------------------------------- + +static void RCVT_S_L(void) +{ + dst->ops = current_instruction_table.CVT_S_L; + recomp_func = gencvt_s_l; + recompile_standard_cf_type(); +} + +static void RCVT_D_L(void) +{ + dst->ops = current_instruction_table.CVT_D_L; + recomp_func = gencvt_d_l; + recompile_standard_cf_type(); +} + +static void (*recomp_l[64])(void) = +{ + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, + RCVT_S_L, RCVT_D_L, RSV, RSV, RSV, RSV, RSV, RSV, + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, + RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV, +}; + +//------------------------------------------------------------------------- +// COP1 +//------------------------------------------------------------------------- + +static void RMFC1(void) +{ + dst->ops = current_instruction_table.MFC1; + recomp_func = genmfc1; + recompile_standard_r_type(); + dst->f.r.nrd = (src >> 11) & 0x1F; + if (dst->f.r.rt == reg) RNOP(); +} + +static void RDMFC1(void) +{ + dst->ops = current_instruction_table.DMFC1; + recomp_func = gendmfc1; + recompile_standard_r_type(); + dst->f.r.nrd = (src >> 11) & 0x1F; + if (dst->f.r.rt == reg) RNOP(); +} + +static void RCFC1(void) +{ + dst->ops = current_instruction_table.CFC1; + recomp_func = gencfc1; + recompile_standard_r_type(); + dst->f.r.nrd = (src >> 11) & 0x1F; + if (dst->f.r.rt == reg) RNOP(); +} + +static void RMTC1(void) +{ + dst->ops = current_instruction_table.MTC1; + recompile_standard_r_type(); + recomp_func = genmtc1; + dst->f.r.nrd = (src >> 11) & 0x1F; +} + +static void RDMTC1(void) +{ + dst->ops = current_instruction_table.DMTC1; + recompile_standard_r_type(); + recomp_func = gendmtc1; + dst->f.r.nrd = (src >> 11) & 0x1F; +} + +static void RCTC1(void) +{ + dst->ops = current_instruction_table.CTC1; + recompile_standard_r_type(); + recomp_func = genctc1; + dst->f.r.nrd = (src >> 11) & 0x1F; +} + +static void RBC(void) +{ + recomp_bc[((src >> 16) & 3)](); +} + +static void RS(void) +{ + recomp_s[(src & 0x3F)](); +} + +static void RD(void) +{ + recomp_d[(src & 0x3F)](); +} + +static void RW(void) +{ + recomp_w[(src & 0x3F)](); +} + +static void RL(void) +{ + recomp_l[(src & 0x3F)](); +} + +static void (*recomp_cop1[32])(void) = +{ + RMFC1, RDMFC1, RCFC1, RSV, RMTC1, RDMTC1, RCTC1, RSV, + RBC , RSV , RSV , RSV, RSV , RSV , RSV , RSV, + RS , RD , RSV , RSV, RW , RL , RSV , RSV, + RSV , RSV , RSV , RSV, RSV , RSV , RSV , RSV +}; + +//------------------------------------------------------------------------- +// R4300 +//------------------------------------------------------------------------- + +static void RSPECIAL(void) +{ + recomp_special[(src & 0x3F)](); +} + +static void RREGIMM(void) +{ + recomp_regimm[((src >> 16) & 0x1F)](); +} + +static void RJ(void) +{ + unsigned int target; + dst->ops = current_instruction_table.J; + recomp_func = genj; + recompile_standard_j_type(); + target = (dst->f.j.inst_index<<2) | (dst->addr & 0xF0000000); + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.J_IDLE; + recomp_func = genj_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.J_OUT; + recomp_func = genj_out; + } +} + +static void RJAL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.JAL; + recomp_func = genjal; + recompile_standard_j_type(); + target = (dst->f.j.inst_index<<2) | (dst->addr & 0xF0000000); + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.JAL_IDLE; + recomp_func = genjal_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.JAL_OUT; + recomp_func = genjal_out; + } +} + +static void RBEQ(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BEQ; + recomp_func = genbeq; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BEQ_IDLE; + recomp_func = genbeq_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BEQ_OUT; + recomp_func = genbeq_out; + } +} + +static void RBNE(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BNE; + recomp_func = genbne; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BNE_IDLE; + recomp_func = genbne_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BNE_OUT; + recomp_func = genbne_out; + } +} + +static void RBLEZ(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BLEZ; + recomp_func = genblez; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BLEZ_IDLE; + recomp_func = genblez_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BLEZ_OUT; + recomp_func = genblez_out; + } +} + +static void RBGTZ(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BGTZ; + recomp_func = genbgtz; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BGTZ_IDLE; + recomp_func = genbgtz_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BGTZ_OUT; + recomp_func = genbgtz_out; + } +} + +static void RADDI(void) +{ + dst->ops = current_instruction_table.ADDI; + recomp_func = genaddi; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RADDIU(void) +{ + dst->ops = current_instruction_table.ADDIU; + recomp_func = genaddiu; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RSLTI(void) +{ + dst->ops = current_instruction_table.SLTI; + recomp_func = genslti; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RSLTIU(void) +{ + dst->ops = current_instruction_table.SLTIU; + recomp_func = gensltiu; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RANDI(void) +{ + dst->ops = current_instruction_table.ANDI; + recomp_func = genandi; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RORI(void) +{ + dst->ops = current_instruction_table.ORI; + recomp_func = genori; + recompile_standard_i_type(); + if (dst->f.i.rt == reg) RNOP(); +} + +static void RXORI(void) +{ + dst->ops = current_instruction_table.XORI; + recomp_func = genxori; + recompile_standard_i_type(); + if (dst->f.i.rt == reg) RNOP(); +} + +static void RLUI(void) +{ + dst->ops = current_instruction_table.LUI; + recomp_func = genlui; + recompile_standard_i_type(); + if (dst->f.i.rt == reg) RNOP(); +} + +static void RCOP0(void) +{ + recomp_cop0[((src >> 21) & 0x1F)](); +} + +static void RCOP1(void) +{ + recomp_cop1[((src >> 21) & 0x1F)](); +} + +static void RBEQL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BEQL; + recomp_func = genbeql; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BEQL_IDLE; + recomp_func = genbeql_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BEQL_OUT; + recomp_func = genbeql_out; + } +} + +static void RBNEL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BNEL; + recomp_func = genbnel; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BNEL_IDLE; + recomp_func = genbnel_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BNEL_OUT; + recomp_func = genbnel_out; + } +} + +static void RBLEZL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BLEZL; + recomp_func = genblezl; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BLEZL_IDLE; + recomp_func = genblezl_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BLEZL_OUT; + recomp_func = genblezl_out; + } +} + +static void RBGTZL(void) +{ + unsigned int target; + dst->ops = current_instruction_table.BGTZL; + recomp_func = genbgtzl; + recompile_standard_i_type(); + target = dst->addr + dst->f.i.immediate*4 + 4; + if (target == dst->addr) + { + if (check_nop) + { + dst->ops = current_instruction_table.BGTZL_IDLE; + recomp_func = genbgtzl_idle; + } + } + else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4))) + { + dst->ops = current_instruction_table.BGTZL_OUT; + recomp_func = genbgtzl_out; + } +} + +static void RDADDI(void) +{ + dst->ops = current_instruction_table.DADDI; + recomp_func = gendaddi; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RDADDIU(void) +{ + dst->ops = current_instruction_table.DADDIU; + recomp_func = gendaddiu; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RLDL(void) +{ + dst->ops = current_instruction_table.LDL; + recomp_func = genldl; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RLDR(void) +{ + dst->ops = current_instruction_table.LDR; + recomp_func = genldr; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RLB(void) +{ + dst->ops = current_instruction_table.LB; + recomp_func = genlb; + recompile_standard_i_type(); + if (dst->f.i.rt == reg) RNOP(); +} + +static void RLH(void) +{ + dst->ops = current_instruction_table.LH; + recomp_func = genlh; + recompile_standard_i_type(); + if (dst->f.i.rt == reg) RNOP(); +} + +static void RLWL(void) +{ + dst->ops = current_instruction_table.LWL; + recomp_func = genlwl; + recompile_standard_i_type(); + if (dst->f.i.rt == reg) RNOP(); +} + +static void RLW(void) +{ + dst->ops = current_instruction_table.LW; + recomp_func = genlw; + recompile_standard_i_type(); + if (dst->f.i.rt == reg) RNOP(); +} + +static void RLBU(void) +{ + dst->ops = current_instruction_table.LBU; + recomp_func = genlbu; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RLHU(void) +{ + dst->ops = current_instruction_table.LHU; + recomp_func = genlhu; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RLWR(void) +{ + dst->ops = current_instruction_table.LWR; + recomp_func = genlwr; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RLWU(void) +{ + dst->ops = current_instruction_table.LWU; + recomp_func = genlwu; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RSB(void) +{ + dst->ops = current_instruction_table.SB; + recomp_func = gensb; + recompile_standard_i_type(); +} + +static void RSH(void) +{ + dst->ops = current_instruction_table.SH; + recomp_func = gensh; + recompile_standard_i_type(); +} + +static void RSWL(void) +{ + dst->ops = current_instruction_table.SWL; + recomp_func = genswl; + recompile_standard_i_type(); +} + +static void RSW(void) +{ + dst->ops = current_instruction_table.SW; + recomp_func = gensw; + recompile_standard_i_type(); +} + +static void RSDL(void) +{ + dst->ops = current_instruction_table.SDL; + recomp_func = gensdl; + recompile_standard_i_type(); +} + +static void RSDR(void) +{ + dst->ops = current_instruction_table.SDR; + recomp_func = gensdr; + recompile_standard_i_type(); +} + +static void RSWR(void) +{ + dst->ops = current_instruction_table.SWR; + recomp_func = genswr; + recompile_standard_i_type(); +} + +static void RCACHE(void) +{ + recomp_func = gencache; + dst->ops = current_instruction_table.CACHE; +} + +static void RLL(void) +{ + recomp_func = genll; + dst->ops = current_instruction_table.LL; + recompile_standard_i_type(); + if(dst->f.i.rt == reg) RNOP(); +} + +static void RLWC1(void) +{ + dst->ops = current_instruction_table.LWC1; + recomp_func = genlwc1; + recompile_standard_lf_type(); +} + +static void RLLD(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; + recompile_standard_i_type(); +} + +static void RLDC1(void) +{ + dst->ops = current_instruction_table.LDC1; + recomp_func = genldc1; + recompile_standard_lf_type(); +} + +static void RLD(void) +{ + dst->ops = current_instruction_table.LD; + recomp_func = genld; + recompile_standard_i_type(); + if (dst->f.i.rt == reg) RNOP(); +} + +static void RSC(void) +{ + dst->ops = current_instruction_table.SC; + recomp_func = gensc; + recompile_standard_i_type(); + if (dst->f.i.rt == reg) RNOP(); +} + +static void RSWC1(void) +{ + dst->ops = current_instruction_table.SWC1; + recomp_func = genswc1; + recompile_standard_lf_type(); +} + +static void RSCD(void) +{ + dst->ops = current_instruction_table.NI; + recomp_func = genni; + recompile_standard_i_type(); +} + +static void RSDC1(void) +{ + dst->ops = current_instruction_table.SDC1; + recomp_func = gensdc1; + recompile_standard_lf_type(); +} + +static void RSD(void) +{ + dst->ops = current_instruction_table.SD; + recomp_func = gensd; + recompile_standard_i_type(); +} + +static void (*recomp_ops[64])(void) = +{ + RSPECIAL, RREGIMM, RJ , RJAL , RBEQ , RBNE , RBLEZ , RBGTZ , + RADDI , RADDIU , RSLTI, RSLTIU, RANDI, RORI , RXORI , RLUI , + RCOP0 , RCOP1 , RSV , RSV , RBEQL, RBNEL, RBLEZL, RBGTZL, + RDADDI , RDADDIU, RLDL , RLDR , RSV , RSV , RSV , RSV , + RLB , RLH , RLWL , RLW , RLBU , RLHU , RLWR , RLWU , + RSB , RSH , RSWL , RSW , RSDL , RSDR , RSWR , RCACHE, + RLL , RLWC1 , RSV , RSV , RLLD , RLDC1, RSV , RLD , + RSC , RSWC1 , RSV , RSV , RSCD , RSDC1, RSV , RSD +}; + +static int get_block_length(const precomp_block *block) +{ + return (block->end-block->start)/4; +} + +static size_t get_block_memsize(const precomp_block *block) +{ + int length = get_block_length(block); + return ((length+1)+(length>>2)) * sizeof(precomp_instr); +} + +/********************************************************************** + ******************** initialize an empty block *********************** + **********************************************************************/ +void init_block(precomp_block *block) +{ + int i, length, already_exist = 1; + static int init_length; + start_section(COMPILER_SECTION); +#ifdef CORE_DBG + DebugMessage(M64MSG_INFO, "init block %x - %x", (int) block->start, (int) block->end); +#endif + + length = get_block_length(block); + + if (!block->block) + { + size_t memsize = get_block_memsize(block); + if (r4300emu == CORE_DYNAREC) { + block->block = (precomp_instr *) malloc_exec(memsize); + if (!block->block) { + DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate executable memory for dynamic recompiler. Try to use an interpreter mode."); + return; + } + } + else { + block->block = (precomp_instr *) malloc(memsize); + if (!block->block) { + DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate memory for cached interpreter."); + return; + } + } + + memset(block->block, 0, memsize); + already_exist = 0; + } + + if (r4300emu == CORE_DYNAREC) + { + if (!block->code) + { +#if defined(PROFILE_R4300) + max_code_length = 524288; /* allocate so much code space that we'll never have to realloc(), because this may */ + /* cause instruction locations to move, and break our profiling data */ +#else + max_code_length = 32768; +#endif + block->code = (unsigned char *) malloc_exec(max_code_length); + } + else + { + max_code_length = block->max_code_length; + } + code_length = 0; + inst_pointer = &block->code; + + if (block->jumps_table) + { + free(block->jumps_table); + block->jumps_table = NULL; + } + if (block->riprel_table) + { + free(block->riprel_table); + block->riprel_table = NULL; + } + init_assembler(NULL, 0, NULL, 0); + init_cache(block->block); + } + + if (!already_exist) + { +#if defined(PROFILE_R4300) + pfProfile = fopen("instructionaddrs.dat", "ab"); + long x86addr = (long) block->code; + int mipsop = -2; /* -2 == NOTCOMPILED block at beginning of x86 code */ + if (fwrite(&mipsop, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode + fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction + DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data"); +#endif + + for (i=0; iblock + i; + dst->addr = block->start + i*4; + dst->reg_cache_infos.need_map = 0; + dst->local_addr = code_length; +#ifdef COMPARE_CORE + if (r4300emu == CORE_DYNAREC) gendebug(); +#endif + RNOTCOMPILED(); + if (r4300emu == CORE_DYNAREC) recomp_func(); + } +#if defined(PROFILE_R4300) + fclose(pfProfile); + pfProfile = NULL; +#endif + init_length = code_length; + } + else + { +#if defined(PROFILE_R4300) + code_length = block->code_length; /* leave old instructions in their place */ +#else + code_length = init_length; /* recompile everything, overwrite old recompiled instructions */ +#endif + for (i=0; iblock + i; + dst->reg_cache_infos.need_map = 0; + dst->local_addr = i * (init_length / length); + dst->ops = current_instruction_table.NOTCOMPILED; + } + } + + if (r4300emu == CORE_DYNAREC) + { + free_all_registers(); + /* calling pass2 of the assembler is not necessary here because all of the code emitted by + gennotcompiled() and gendebug() is position-independent and contains no jumps . */ + block->code_length = code_length; + block->max_code_length = max_code_length; + free_assembler(&block->jumps_table, &block->jumps_number, &block->riprel_table, &block->riprel_number); + } + + /* here we're marking the block as a valid code even if it's not compiled + * yet as the game should have already set up the code correctly. + */ + invalid_code[block->start>>12] = 0; + if (block->end < 0x80000000 || block->start >= 0xc0000000) + { + unsigned int paddr; + + paddr = virtual_to_physical_address(block->start, 2); + invalid_code[paddr>>12] = 0; + if (!blocks[paddr>>12]) + { + blocks[paddr>>12] = (precomp_block *) malloc(sizeof(precomp_block)); + blocks[paddr>>12]->code = NULL; + blocks[paddr>>12]->block = NULL; + blocks[paddr>>12]->jumps_table = NULL; + blocks[paddr>>12]->riprel_table = NULL; + blocks[paddr>>12]->start = paddr & ~0xFFF; + blocks[paddr>>12]->end = (paddr & ~0xFFF) + 0x1000; + } + init_block(blocks[paddr>>12]); + + paddr += block->end - block->start - 4; + invalid_code[paddr>>12] = 0; + if (!blocks[paddr>>12]) + { + blocks[paddr>>12] = (precomp_block *) malloc(sizeof(precomp_block)); + blocks[paddr>>12]->code = NULL; + blocks[paddr>>12]->block = NULL; + blocks[paddr>>12]->jumps_table = NULL; + blocks[paddr>>12]->riprel_table = NULL; + blocks[paddr>>12]->start = paddr & ~0xFFF; + blocks[paddr>>12]->end = (paddr & ~0xFFF) + 0x1000; + } + init_block(blocks[paddr>>12]); + } + else + { + if (block->start >= 0x80000000 && block->end < 0xa0000000 && invalid_code[(block->start+0x20000000)>>12]) + { + if (!blocks[(block->start+0x20000000)>>12]) + { + blocks[(block->start+0x20000000)>>12] = (precomp_block *) malloc(sizeof(precomp_block)); + blocks[(block->start+0x20000000)>>12]->code = NULL; + blocks[(block->start+0x20000000)>>12]->block = NULL; + blocks[(block->start+0x20000000)>>12]->jumps_table = NULL; + blocks[(block->start+0x20000000)>>12]->riprel_table = NULL; + blocks[(block->start+0x20000000)>>12]->start = (block->start+0x20000000) & ~0xFFF; + blocks[(block->start+0x20000000)>>12]->end = ((block->start+0x20000000) & ~0xFFF) + 0x1000; + } + init_block(blocks[(block->start+0x20000000)>>12]); + } + if (block->start >= 0xa0000000 && block->end < 0xc0000000 && invalid_code[(block->start-0x20000000)>>12]) + { + if (!blocks[(block->start-0x20000000)>>12]) + { + blocks[(block->start-0x20000000)>>12] = (precomp_block *) malloc(sizeof(precomp_block)); + blocks[(block->start-0x20000000)>>12]->code = NULL; + blocks[(block->start-0x20000000)>>12]->block = NULL; + blocks[(block->start-0x20000000)>>12]->jumps_table = NULL; + blocks[(block->start-0x20000000)>>12]->riprel_table = NULL; + blocks[(block->start-0x20000000)>>12]->start = (block->start-0x20000000) & ~0xFFF; + blocks[(block->start-0x20000000)>>12]->end = ((block->start-0x20000000) & ~0xFFF) + 0x1000; + } + init_block(blocks[(block->start-0x20000000)>>12]); + } + } + end_section(COMPILER_SECTION); +} + +void free_block(precomp_block *block) +{ + size_t memsize = get_block_memsize(block); + + if (block->block) { + if (r4300emu == CORE_DYNAREC) + free_exec(block->block, memsize); + else + free(block->block); + block->block = NULL; + } + if (block->code) { free_exec(block->code, block->max_code_length); block->code = NULL; } + if (block->jumps_table) { free(block->jumps_table); block->jumps_table = NULL; } + if (block->riprel_table) { free(block->riprel_table); block->riprel_table = NULL; } +} + +/********************************************************************** + ********************* recompile a block of code ********************** + **********************************************************************/ +void recompile_block(int *source, precomp_block *block, unsigned int func) +{ + int i, length, finished=0; + start_section(COMPILER_SECTION); + length = (block->end-block->start)/4; + dst_block = block; + + //for (i=0; i<16; i++) block->md5[i] = 0; + block->adler32 = 0; + + if (r4300emu == CORE_DYNAREC) + { + code_length = block->code_length; + max_code_length = block->max_code_length; + inst_pointer = &block->code; + init_assembler(block->jumps_table, block->jumps_number, block->riprel_table, block->riprel_number); + init_cache(block->block + (func & 0xFFF) / 4); + } + +#if defined(PROFILE_R4300) + pfProfile = fopen("instructionaddrs.dat", "ab"); +#endif + + for (i = (func & 0xFFF) / 4; finished != 2; i++) + { + if(block->start < 0x80000000 || block->start >= 0xc0000000) + { + unsigned int address2 = + virtual_to_physical_address(block->start + i*4, 0); + if(blocks[address2>>12]->block[(address2&0xFFF)/4].ops == current_instruction_table.NOTCOMPILED) + blocks[address2>>12]->block[(address2&0xFFF)/4].ops = current_instruction_table.NOTCOMPILED2; + } + + SRC = source + i; + src = source[i]; + check_nop = source[i+1] == 0; + dst = block->block + i; + dst->addr = block->start + i*4; + dst->reg_cache_infos.need_map = 0; + dst->local_addr = code_length; +#ifdef COMPARE_CORE + if (r4300emu == CORE_DYNAREC) gendebug(); +#endif +#if defined(PROFILE_R4300) + long x86addr = (long) (block->code + block->block[i].local_addr); + if (fwrite(source + i, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode + fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction + DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data"); +#endif + recomp_func = NULL; + recomp_ops[((src >> 26) & 0x3F)](); + if (r4300emu == CORE_DYNAREC) recomp_func(); + dst = block->block + i; + + /*if ((dst+1)->ops != NOTCOMPILED && !delay_slot_compiled && + i < length) + { + if (r4300emu == CORE_DYNAREC) genlink_subblock(); + finished = 2; + }*/ + if (delay_slot_compiled) + { + delay_slot_compiled--; + free_all_registers(); + } + + if (i >= length-2+(length>>2)) finished = 2; + if (i >= (length-1) && (block->start == 0xa4000000 || + block->start >= 0xc0000000 || + block->end < 0x80000000)) finished = 2; + if (dst->ops == current_instruction_table.ERET || finished == 1) finished = 2; + if (/*i >= length &&*/ + (dst->ops == current_instruction_table.J || + dst->ops == current_instruction_table.J_OUT || + dst->ops == current_instruction_table.JR) && + !(i >= (length-1) && (block->start >= 0xc0000000 || + block->end < 0x80000000))) + finished = 1; + } + +#if defined(PROFILE_R4300) + long x86addr = (long) (block->code + code_length); + int mipsop = -3; /* -3 == block-postfix */ + if (fwrite(&mipsop, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode + fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction + DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data"); +#endif + + if (i >= length) + { + dst = block->block + i; + dst->addr = block->start + i*4; + dst->reg_cache_infos.need_map = 0; + dst->local_addr = code_length; +#ifdef COMPARE_CORE + if (r4300emu == CORE_DYNAREC) gendebug(); +#endif + RFIN_BLOCK(); + if (r4300emu == CORE_DYNAREC) recomp_func(); + i++; + if (i < length-1+(length>>2)) // useful when last opcode is a jump + { + dst = block->block + i; + dst->addr = block->start + i*4; + dst->reg_cache_infos.need_map = 0; + dst->local_addr = code_length; +#ifdef COMPARE_CORE + if (r4300emu == CORE_DYNAREC) gendebug(); +#endif + RFIN_BLOCK(); + if (r4300emu == CORE_DYNAREC) recomp_func(); + i++; + } + } + else if (r4300emu == CORE_DYNAREC) genlink_subblock(); + + if (r4300emu == CORE_DYNAREC) + { + free_all_registers(); + passe2(block->block, (func&0xFFF)/4, i, block); + block->code_length = code_length; + block->max_code_length = max_code_length; + free_assembler(&block->jumps_table, &block->jumps_number, &block->riprel_table, &block->riprel_number); + } +#ifdef CORE_DBG + DebugMessage(M64MSG_INFO, "block recompiled (%x-%x)", (int)func, (int)(block->start+i*4)); +#endif +#if defined(PROFILE_R4300) + fclose(pfProfile); + pfProfile = NULL; +#endif + end_section(COMPILER_SECTION); +} + +static int is_jump(void) +{ + recomp_ops[((src >> 26) & 0x3F)](); + return + (dst->ops == current_instruction_table.J || + dst->ops == current_instruction_table.J_OUT || + dst->ops == current_instruction_table.J_IDLE || + dst->ops == current_instruction_table.JAL || + dst->ops == current_instruction_table.JAL_OUT || + dst->ops == current_instruction_table.JAL_IDLE || + dst->ops == current_instruction_table.BEQ || + dst->ops == current_instruction_table.BEQ_OUT || + dst->ops == current_instruction_table.BEQ_IDLE || + dst->ops == current_instruction_table.BNE || + dst->ops == current_instruction_table.BNE_OUT || + dst->ops == current_instruction_table.BNE_IDLE || + dst->ops == current_instruction_table.BLEZ || + dst->ops == current_instruction_table.BLEZ_OUT || + dst->ops == current_instruction_table.BLEZ_IDLE || + dst->ops == current_instruction_table.BGTZ || + dst->ops == current_instruction_table.BGTZ_OUT || + dst->ops == current_instruction_table.BGTZ_IDLE || + dst->ops == current_instruction_table.BEQL || + dst->ops == current_instruction_table.BEQL_OUT || + dst->ops == current_instruction_table.BEQL_IDLE || + dst->ops == current_instruction_table.BNEL || + dst->ops == current_instruction_table.BNEL_OUT || + dst->ops == current_instruction_table.BNEL_IDLE || + dst->ops == current_instruction_table.BLEZL || + dst->ops == current_instruction_table.BLEZL_OUT || + dst->ops == current_instruction_table.BLEZL_IDLE || + dst->ops == current_instruction_table.BGTZL || + dst->ops == current_instruction_table.BGTZL_OUT || + dst->ops == current_instruction_table.BGTZL_IDLE || + dst->ops == current_instruction_table.JR || + dst->ops == current_instruction_table.JALR || + dst->ops == current_instruction_table.BLTZ || + dst->ops == current_instruction_table.BLTZ_OUT || + dst->ops == current_instruction_table.BLTZ_IDLE || + dst->ops == current_instruction_table.BGEZ || + dst->ops == current_instruction_table.BGEZ_OUT || + dst->ops == current_instruction_table.BGEZ_IDLE || + dst->ops == current_instruction_table.BLTZL || + dst->ops == current_instruction_table.BLTZL_OUT || + dst->ops == current_instruction_table.BLTZL_IDLE || + dst->ops == current_instruction_table.BGEZL || + dst->ops == current_instruction_table.BGEZL_OUT || + dst->ops == current_instruction_table.BGEZL_IDLE || + dst->ops == current_instruction_table.BLTZAL || + dst->ops == current_instruction_table.BLTZAL_OUT || + dst->ops == current_instruction_table.BLTZAL_IDLE || + dst->ops == current_instruction_table.BGEZAL || + dst->ops == current_instruction_table.BGEZAL_OUT || + dst->ops == current_instruction_table.BGEZAL_IDLE || + dst->ops == current_instruction_table.BLTZALL || + dst->ops == current_instruction_table.BLTZALL_OUT || + dst->ops == current_instruction_table.BLTZALL_IDLE || + dst->ops == current_instruction_table.BGEZALL || + dst->ops == current_instruction_table.BGEZALL_OUT || + dst->ops == current_instruction_table.BGEZALL_IDLE || + dst->ops == current_instruction_table.BC1F || + dst->ops == current_instruction_table.BC1F_OUT || + dst->ops == current_instruction_table.BC1F_IDLE || + dst->ops == current_instruction_table.BC1T || + dst->ops == current_instruction_table.BC1T_OUT || + dst->ops == current_instruction_table.BC1T_IDLE || + dst->ops == current_instruction_table.BC1FL || + dst->ops == current_instruction_table.BC1FL_OUT || + dst->ops == current_instruction_table.BC1FL_IDLE || + dst->ops == current_instruction_table.BC1TL || + dst->ops == current_instruction_table.BC1TL_OUT || + dst->ops == current_instruction_table.BC1TL_IDLE); +} + +/********************************************************************** + ************ recompile only one opcode (use for delay slot) ********** + **********************************************************************/ +void recompile_opcode(void) +{ + SRC++; + src = *SRC; + dst++; + dst->addr = (dst-1)->addr + 4; + dst->reg_cache_infos.need_map = 0; + if(!is_jump()) + { +#if defined(PROFILE_R4300) + long x86addr = (long) ((*inst_pointer) + code_length); + if (fwrite(&src, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode + fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction + DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data"); +#endif + recomp_func = NULL; + recomp_ops[((src >> 26) & 0x3F)](); + if (r4300emu == CORE_DYNAREC) recomp_func(); + } + else + { + RNOP(); + if (r4300emu == CORE_DYNAREC) recomp_func(); + } + delay_slot_compiled = 2; +} + +/********************************************************************** + ************** decode one opcode (for the interpreter) *************** + **********************************************************************/ +void prefetch_opcode(unsigned int op, unsigned int nextop) +{ + dst = PC; + src = op; + check_nop = nextop == 0; + recomp_ops[((src >> 26) & 0x3F)](); +} + +/********************************************************************** + ************** allocate memory with executable bit set *************** + **********************************************************************/ +static void *malloc_exec(size_t size) +{ +#if defined(WIN32) + return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); +#elif defined(__GNUC__) + + #ifndef MAP_ANONYMOUS + #ifdef MAP_ANON + #define MAP_ANONYMOUS MAP_ANON + #endif + #endif + + void *block = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (block == MAP_FAILED) + { DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate %zi byte block of aligned RWX memory.", size); return NULL; } + + return block; +#else + return malloc(size); +#endif +} + +/********************************************************************** + ************* reallocate memory with executable bit set ************** + **********************************************************************/ +void *realloc_exec(void *ptr, size_t oldsize, size_t newsize) +{ + void* block = malloc_exec(newsize); + if (block != NULL) + { + size_t copysize; + if (oldsize < newsize) + copysize = oldsize; + else + copysize = newsize; + memcpy(block, ptr, copysize); + } + free_exec(ptr, oldsize); + return block; +} + +/********************************************************************** + **************** frees memory with executable bit set **************** + **********************************************************************/ +static void free_exec(void *ptr, size_t length) +{ +#if defined(WIN32) + VirtualFree(ptr, 0, MEM_RELEASE); +#elif defined(__GNUC__) + munmap(ptr, length); +#else + free(ptr); +#endif +}