Path: blob/master/libmupen64plus/mupen64plus-core/src/r4300/recomp.c
2 views
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *1* Mupen64plus - recomp.h *2* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *3* Copyright (C) 2002 Hacktarux *4* *5* This program is free software; you can redistribute it and/or modify *6* it under the terms of the GNU General Public License as published by *7* the Free Software Foundation; either version 2 of the License, or *8* (at your option) any later version. *9* *10* This program is distributed in the hope that it will be useful, *11* but WITHOUT ANY WARRANTY; without even the implied warranty of *12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *13* GNU General Public License for more details. *14* *15* You should have received a copy of the GNU General Public License *16* along with this program; if not, write to the *17* Free Software Foundation, Inc., *18* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *19* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */2021#include <stdlib.h>22#include <string.h>2324#if defined(__GNUC__)25#include <unistd.h>26#ifndef __MINGW32__27#include <sys/mman.h>28#endif29#endif3031#include "api/m64p_types.h"32#include "api/callbacks.h"33#include "memory/memory.h"3435#include "recomp.h"36#include "recomph.h" //include for function prototypes37#include "macros.h"38#include "r4300.h"39#include "ops.h"4041static void *malloc_exec(size_t size);42static void free_exec(void *ptr, size_t length);4344// global variables :45precomp_instr *dst; // destination structure for the recompiled instruction46int code_length; // current real recompiled code length47int max_code_length; // current recompiled code's buffer length48unsigned char **inst_pointer; // output buffer for recompiled code49precomp_block *dst_block; // the current block that we are recompiling50int src; // the current recompiled instruction51int fast_memory;5253static void (*recomp_func)(void); // pointer to the dynarec's generator54// function for the latest decoded opcode5556#if defined(PROFILE_R4300)57FILE *pfProfile;58#endif5960static int *SRC; // currently recompiled instruction in the input stream61static int check_nop; // next instruction is nop ?62static int delay_slot_compiled = 0;63646566static void RSV(void)67{68dst->ops = current_instruction_table.RESERVED;69recomp_func = genreserved;70}7172static void RFIN_BLOCK(void)73{74dst->ops = current_instruction_table.FIN_BLOCK;75recomp_func = genfin_block;76}7778static void RNOTCOMPILED(void)79{80dst->ops = current_instruction_table.NOTCOMPILED;81recomp_func = gennotcompiled;82}8384static void recompile_standard_i_type(void)85{86dst->f.i.rs = reg + ((src >> 21) & 0x1F);87dst->f.i.rt = reg + ((src >> 16) & 0x1F);88dst->f.i.immediate = src & 0xFFFF;89}9091static void recompile_standard_j_type(void)92{93dst->f.j.inst_index = src & 0x3FFFFFF;94}9596static void recompile_standard_r_type(void)97{98dst->f.r.rs = reg + ((src >> 21) & 0x1F);99dst->f.r.rt = reg + ((src >> 16) & 0x1F);100dst->f.r.rd = reg + ((src >> 11) & 0x1F);101dst->f.r.sa = (src >> 6) & 0x1F;102}103104static void recompile_standard_lf_type(void)105{106dst->f.lf.base = (src >> 21) & 0x1F;107dst->f.lf.ft = (src >> 16) & 0x1F;108dst->f.lf.offset = src & 0xFFFF;109}110111static void recompile_standard_cf_type(void)112{113dst->f.cf.ft = (src >> 16) & 0x1F;114dst->f.cf.fs = (src >> 11) & 0x1F;115dst->f.cf.fd = (src >> 6) & 0x1F;116}117118//-------------------------------------------------------------------------119// SPECIAL120//-------------------------------------------------------------------------121122static void RNOP(void)123{124dst->ops = current_instruction_table.NOP;125recomp_func = gennop;126}127128static void RSLL(void)129{130dst->ops = current_instruction_table.SLL;131recomp_func = gensll;132recompile_standard_r_type();133if (dst->f.r.rd == reg) RNOP();134}135136static void RSRL(void)137{138dst->ops = current_instruction_table.SRL;139recomp_func = gensrl;140recompile_standard_r_type();141if (dst->f.r.rd == reg) RNOP();142}143144static void RSRA(void)145{146dst->ops = current_instruction_table.SRA;147recomp_func = gensra;148recompile_standard_r_type();149if (dst->f.r.rd == reg) RNOP();150}151152static void RSLLV(void)153{154dst->ops = current_instruction_table.SLLV;155recomp_func = gensllv;156recompile_standard_r_type();157if (dst->f.r.rd == reg) RNOP();158}159160static void RSRLV(void)161{162dst->ops = current_instruction_table.SRLV;163recomp_func = gensrlv;164recompile_standard_r_type();165if (dst->f.r.rd == reg) RNOP();166}167168static void RSRAV(void)169{170dst->ops = current_instruction_table.SRAV;171recomp_func = gensrav;172recompile_standard_r_type();173if (dst->f.r.rd == reg) RNOP();174}175176static void RJR(void)177{178dst->ops = current_instruction_table.JR;179recomp_func = genjr;180recompile_standard_i_type();181}182183static void RJALR(void)184{185dst->ops = current_instruction_table.JALR;186recomp_func = genjalr;187recompile_standard_r_type();188}189190static void RSYSCALL(void)191{192dst->ops = current_instruction_table.SYSCALL;193recomp_func = gensyscall;194}195196static void RBREAK(void)197{198dst->ops = current_instruction_table.NI;199recomp_func = genni;200}201202static void RSYNC(void)203{204dst->ops = current_instruction_table.SYNC;205recomp_func = gensync;206}207208static void RMFHI(void)209{210dst->ops = current_instruction_table.MFHI;211recomp_func = genmfhi;212recompile_standard_r_type();213if (dst->f.r.rd == reg) RNOP();214}215216static void RMTHI(void)217{218dst->ops = current_instruction_table.MTHI;219recomp_func = genmthi;220recompile_standard_r_type();221}222223static void RMFLO(void)224{225dst->ops = current_instruction_table.MFLO;226recomp_func = genmflo;227recompile_standard_r_type();228if (dst->f.r.rd == reg) RNOP();229}230231static void RMTLO(void)232{233dst->ops = current_instruction_table.MTLO;234recomp_func = genmtlo;235recompile_standard_r_type();236}237238static void RDSLLV(void)239{240dst->ops = current_instruction_table.DSLLV;241recomp_func = gendsllv;242recompile_standard_r_type();243if (dst->f.r.rd == reg) RNOP();244}245246static void RDSRLV(void)247{248dst->ops = current_instruction_table.DSRLV;249recomp_func = gendsrlv;250recompile_standard_r_type();251if (dst->f.r.rd == reg) RNOP();252}253254static void RDSRAV(void)255{256dst->ops = current_instruction_table.DSRAV;257recomp_func = gendsrav;258recompile_standard_r_type();259if (dst->f.r.rd == reg) RNOP();260}261262static void RMULT(void)263{264dst->ops = current_instruction_table.MULT;265recomp_func = genmult;266recompile_standard_r_type();267}268269static void RMULTU(void)270{271dst->ops = current_instruction_table.MULTU;272recomp_func = genmultu;273recompile_standard_r_type();274}275276static void RDIV(void)277{278dst->ops = current_instruction_table.DIV;279recomp_func = gendiv;280recompile_standard_r_type();281}282283static void RDIVU(void)284{285dst->ops = current_instruction_table.DIVU;286recomp_func = gendivu;287recompile_standard_r_type();288}289290static void RDMULT(void)291{292dst->ops = current_instruction_table.DMULT;293recomp_func = gendmult;294recompile_standard_r_type();295}296297static void RDMULTU(void)298{299dst->ops = current_instruction_table.DMULTU;300recomp_func = gendmultu;301recompile_standard_r_type();302}303304static void RDDIV(void)305{306dst->ops = current_instruction_table.DDIV;307recomp_func = genddiv;308recompile_standard_r_type();309}310311static void RDDIVU(void)312{313dst->ops = current_instruction_table.DDIVU;314recomp_func = genddivu;315recompile_standard_r_type();316}317318static void RADD(void)319{320dst->ops = current_instruction_table.ADD;321recomp_func = genadd;322recompile_standard_r_type();323if (dst->f.r.rd == reg) RNOP();324}325326static void RADDU(void)327{328dst->ops = current_instruction_table.ADDU;329recomp_func = genaddu;330recompile_standard_r_type();331if (dst->f.r.rd == reg) RNOP();332}333334static void RSUB(void)335{336dst->ops = current_instruction_table.SUB;337recomp_func = gensub;338recompile_standard_r_type();339if (dst->f.r.rd == reg) RNOP();340}341342static void RSUBU(void)343{344dst->ops = current_instruction_table.SUBU;345recomp_func = gensubu;346recompile_standard_r_type();347if (dst->f.r.rd == reg) RNOP();348}349350static void RAND(void)351{352dst->ops = current_instruction_table.AND;353recomp_func = genand;354recompile_standard_r_type();355if(dst->f.r.rd == reg) RNOP();356}357358static void ROR(void)359{360dst->ops = current_instruction_table.OR;361recomp_func = genor;362recompile_standard_r_type();363if(dst->f.r.rd == reg) RNOP();364}365366static void RXOR(void)367{368dst->ops = current_instruction_table.XOR;369recomp_func = genxor;370recompile_standard_r_type();371if(dst->f.r.rd == reg) RNOP();372}373374static void RNOR(void)375{376dst->ops = current_instruction_table.NOR;377recomp_func = gennor;378recompile_standard_r_type();379if(dst->f.r.rd == reg) RNOP();380}381382static void RSLT(void)383{384dst->ops = current_instruction_table.SLT;385recomp_func = genslt;386recompile_standard_r_type();387if(dst->f.r.rd == reg) RNOP();388}389390static void RSLTU(void)391{392dst->ops = current_instruction_table.SLTU;393recomp_func = gensltu;394recompile_standard_r_type();395if(dst->f.r.rd == reg) RNOP();396}397398static void RDADD(void)399{400dst->ops = current_instruction_table.DADD;401recomp_func = gendadd;402recompile_standard_r_type();403if (dst->f.r.rd == reg) RNOP();404}405406static void RDADDU(void)407{408dst->ops = current_instruction_table.DADDU;409recomp_func = gendaddu;410recompile_standard_r_type();411if (dst->f.r.rd == reg) RNOP();412}413414static void RDSUB(void)415{416dst->ops = current_instruction_table.DSUB;417recomp_func = gendsub;418recompile_standard_r_type();419if (dst->f.r.rd == reg) RNOP();420}421422static void RDSUBU(void)423{424dst->ops = current_instruction_table.DSUBU;425recomp_func = gendsubu;426recompile_standard_r_type();427if (dst->f.r.rd == reg) RNOP();428}429430static void RTGE(void)431{432dst->ops = current_instruction_table.NI;433recomp_func = genni;434}435436static void RTGEU(void)437{438dst->ops = current_instruction_table.NI;439recomp_func = genni;440}441442static void RTLT(void)443{444dst->ops = current_instruction_table.NI;445recomp_func = genni;446}447448static void RTLTU(void)449{450dst->ops = current_instruction_table.NI;451recomp_func = genni;452}453454static void RTEQ(void)455{456dst->ops = current_instruction_table.TEQ;457recomp_func = genteq;458recompile_standard_r_type();459}460461static void RTNE(void)462{463dst->ops = current_instruction_table.NI;464recomp_func = genni;465}466467static void RDSLL(void)468{469dst->ops = current_instruction_table.DSLL;470recomp_func = gendsll;471recompile_standard_r_type();472if (dst->f.r.rd == reg) RNOP();473}474475static void RDSRL(void)476{477dst->ops = current_instruction_table.DSRL;478recomp_func = gendsrl;479recompile_standard_r_type();480if (dst->f.r.rd == reg) RNOP();481}482483static void RDSRA(void)484{485dst->ops = current_instruction_table.DSRA;486recomp_func = gendsra;487recompile_standard_r_type();488if (dst->f.r.rd == reg) RNOP();489}490491static void RDSLL32(void)492{493dst->ops = current_instruction_table.DSLL32;494recomp_func = gendsll32;495recompile_standard_r_type();496if (dst->f.r.rd == reg) RNOP();497}498499static void RDSRL32(void)500{501dst->ops = current_instruction_table.DSRL32;502recomp_func = gendsrl32;503recompile_standard_r_type();504if (dst->f.r.rd == reg) RNOP();505}506507static void RDSRA32(void)508{509dst->ops = current_instruction_table.DSRA32;510recomp_func = gendsra32;511recompile_standard_r_type();512if (dst->f.r.rd == reg) RNOP();513}514515static void (*recomp_special[64])(void) =516{517RSLL , RSV , RSRL , RSRA , RSLLV , RSV , RSRLV , RSRAV ,518RJR , RJALR , RSV , RSV , RSYSCALL, RBREAK , RSV , RSYNC ,519RMFHI, RMTHI , RMFLO, RMTLO, RDSLLV , RSV , RDSRLV , RDSRAV ,520RMULT, RMULTU, RDIV , RDIVU, RDMULT , RDMULTU, RDDIV , RDDIVU ,521RADD , RADDU , RSUB , RSUBU, RAND , ROR , RXOR , RNOR ,522RSV , RSV , RSLT , RSLTU, RDADD , RDADDU , RDSUB , RDSUBU ,523RTGE , RTGEU , RTLT , RTLTU, RTEQ , RSV , RTNE , RSV ,524RDSLL, RSV , RDSRL, RDSRA, RDSLL32 , RSV , RDSRL32, RDSRA32525};526527//-------------------------------------------------------------------------528// REGIMM529//-------------------------------------------------------------------------530531static void RBLTZ(void)532{533unsigned int target;534dst->ops = current_instruction_table.BLTZ;535recomp_func = genbltz;536recompile_standard_i_type();537target = dst->addr + dst->f.i.immediate*4 + 4;538if (target == dst->addr)539{540if (check_nop)541{542dst->ops = current_instruction_table.BLTZ_IDLE;543recomp_func = genbltz_idle;544}545}546else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))547{548dst->ops = current_instruction_table.BLTZ_OUT;549recomp_func = genbltz_out;550}551}552553static void RBGEZ(void)554{555unsigned int target;556dst->ops = current_instruction_table.BGEZ;557recomp_func = genbgez;558recompile_standard_i_type();559target = dst->addr + dst->f.i.immediate*4 + 4;560if (target == dst->addr)561{562if (check_nop)563{564dst->ops = current_instruction_table.BGEZ_IDLE;565recomp_func = genbgez_idle;566}567}568else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))569{570dst->ops = current_instruction_table.BGEZ_OUT;571recomp_func = genbgez_out;572}573}574575static void RBLTZL(void)576{577unsigned int target;578dst->ops = current_instruction_table.BLTZL;579recomp_func = genbltzl;580recompile_standard_i_type();581target = dst->addr + dst->f.i.immediate*4 + 4;582if (target == dst->addr)583{584if (check_nop)585{586dst->ops = current_instruction_table.BLTZL_IDLE;587recomp_func = genbltzl_idle;588}589}590else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))591{592dst->ops = current_instruction_table.BLTZL_OUT;593recomp_func = genbltzl_out;594}595}596597static void RBGEZL(void)598{599unsigned int target;600dst->ops = current_instruction_table.BGEZL;601recomp_func = genbgezl;602recompile_standard_i_type();603target = dst->addr + dst->f.i.immediate*4 + 4;604if (target == dst->addr)605{606if (check_nop)607{608dst->ops = current_instruction_table.BGEZL_IDLE;609recomp_func = genbgezl_idle;610}611}612else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))613{614dst->ops = current_instruction_table.BGEZL_OUT;615recomp_func = genbgezl_out;616}617}618619static void RTGEI(void)620{621dst->ops = current_instruction_table.NI;622recomp_func = genni;623}624625static void RTGEIU(void)626{627dst->ops = current_instruction_table.NI;628recomp_func = genni;629}630631static void RTLTI(void)632{633dst->ops = current_instruction_table.NI;634recomp_func = genni;635}636637static void RTLTIU(void)638{639dst->ops = current_instruction_table.NI;640recomp_func = genni;641}642643static void RTEQI(void)644{645dst->ops = current_instruction_table.NI;646recomp_func = genni;647}648649static void RTNEI(void)650{651dst->ops = current_instruction_table.NI;652recomp_func = genni;653}654655static void RBLTZAL(void)656{657unsigned int target;658dst->ops = current_instruction_table.BLTZAL;659recomp_func = genbltzal;660recompile_standard_i_type();661target = dst->addr + dst->f.i.immediate*4 + 4;662if (target == dst->addr)663{664if (check_nop)665{666dst->ops = current_instruction_table.BLTZAL_IDLE;667recomp_func = genbltzal_idle;668}669}670else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))671{672dst->ops = current_instruction_table.BLTZAL_OUT;673recomp_func = genbltzal_out;674}675}676677static void RBGEZAL(void)678{679unsigned int target;680dst->ops = current_instruction_table.BGEZAL;681recomp_func = genbgezal;682recompile_standard_i_type();683target = dst->addr + dst->f.i.immediate*4 + 4;684if (target == dst->addr)685{686if (check_nop)687{688dst->ops = current_instruction_table.BGEZAL_IDLE;689recomp_func = genbgezal_idle;690}691}692else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))693{694dst->ops = current_instruction_table.BGEZAL_OUT;695recomp_func = genbgezal_out;696}697}698699static void RBLTZALL(void)700{701unsigned int target;702dst->ops = current_instruction_table.BLTZALL;703recomp_func = genbltzall;704recompile_standard_i_type();705target = dst->addr + dst->f.i.immediate*4 + 4;706if (target == dst->addr)707{708if (check_nop)709{710dst->ops = current_instruction_table.BLTZALL_IDLE;711recomp_func = genbltzall_idle;712}713}714else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))715{716dst->ops = current_instruction_table.BLTZALL_OUT;717recomp_func = genbltzall_out;718}719}720721static void RBGEZALL(void)722{723unsigned int target;724dst->ops = current_instruction_table.BGEZALL;725recomp_func = genbgezall;726recompile_standard_i_type();727target = dst->addr + dst->f.i.immediate*4 + 4;728if (target == dst->addr)729{730if (check_nop)731{732dst->ops = current_instruction_table.BGEZALL_IDLE;733recomp_func = genbgezall_idle;734}735}736else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))737{738dst->ops = current_instruction_table.BGEZALL_OUT;739recomp_func = genbgezall_out;740}741}742743static void (*recomp_regimm[32])(void) =744{745RBLTZ , RBGEZ , RBLTZL , RBGEZL , RSV , RSV, RSV , RSV,746RTGEI , RTGEIU , RTLTI , RTLTIU , RTEQI, RSV, RTNEI, RSV,747RBLTZAL, RBGEZAL, RBLTZALL, RBGEZALL, RSV , RSV, RSV , RSV,748RSV , RSV , RSV , RSV , RSV , RSV, RSV , RSV749};750751//-------------------------------------------------------------------------752// TLB753//-------------------------------------------------------------------------754755static void RTLBR(void)756{757dst->ops = current_instruction_table.TLBR;758recomp_func = gentlbr;759}760761static void RTLBWI(void)762{763dst->ops = current_instruction_table.TLBWI;764recomp_func = gentlbwi;765}766767static void RTLBWR(void)768{769dst->ops = current_instruction_table.TLBWR;770recomp_func = gentlbwr;771}772773static void RTLBP(void)774{775dst->ops = current_instruction_table.TLBP;776recomp_func = gentlbp;777}778779static void RERET(void)780{781dst->ops = current_instruction_table.ERET;782recomp_func = generet;783}784785static void (*recomp_tlb[64])(void) =786{787RSV , RTLBR, RTLBWI, RSV, RSV, RSV, RTLBWR, RSV,788RTLBP, RSV , RSV , RSV, RSV, RSV, RSV , RSV,789RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV,790RERET, RSV , RSV , RSV, RSV, RSV, RSV , RSV,791RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV,792RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV,793RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV,794RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV795};796797//-------------------------------------------------------------------------798// COP0799//-------------------------------------------------------------------------800801static void RMFC0(void)802{803dst->ops = current_instruction_table.MFC0;804recomp_func = genmfc0;805recompile_standard_r_type();806dst->f.r.rd = (long long*)(reg_cop0 + ((src >> 11) & 0x1F));807dst->f.r.nrd = (src >> 11) & 0x1F;808if (dst->f.r.rt == reg) RNOP();809}810811static void RMTC0(void)812{813dst->ops = current_instruction_table.MTC0;814recomp_func = genmtc0;815recompile_standard_r_type();816dst->f.r.nrd = (src >> 11) & 0x1F;817}818819static void RTLB(void)820{821recomp_tlb[(src & 0x3F)]();822}823824static void (*recomp_cop0[32])(void) =825{826RMFC0, RSV, RSV, RSV, RMTC0, RSV, RSV, RSV,827RSV , RSV, RSV, RSV, RSV , RSV, RSV, RSV,828RTLB , RSV, RSV, RSV, RSV , RSV, RSV, RSV,829RSV , RSV, RSV, RSV, RSV , RSV, RSV, RSV830};831832//-------------------------------------------------------------------------833// BC834//-------------------------------------------------------------------------835836static void RBC1F(void)837{838unsigned int target;839dst->ops = current_instruction_table.BC1F;840recomp_func = genbc1f;841recompile_standard_i_type();842target = dst->addr + dst->f.i.immediate*4 + 4;843if (target == dst->addr)844{845if (check_nop)846{847dst->ops = current_instruction_table.BC1F_IDLE;848recomp_func = genbc1f_idle;849}850}851else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))852{853dst->ops = current_instruction_table.BC1F_OUT;854recomp_func = genbc1f_out;855}856}857858static void RBC1T(void)859{860unsigned int target;861dst->ops = current_instruction_table.BC1T;862recomp_func = genbc1t;863recompile_standard_i_type();864target = dst->addr + dst->f.i.immediate*4 + 4;865if (target == dst->addr)866{867if (check_nop)868{869dst->ops = current_instruction_table.BC1T_IDLE;870recomp_func = genbc1t_idle;871}872}873else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))874{875dst->ops = current_instruction_table.BC1T_OUT;876recomp_func = genbc1t_out;877}878}879880static void RBC1FL(void)881{882unsigned int target;883dst->ops = current_instruction_table.BC1FL;884recomp_func = genbc1fl;885recompile_standard_i_type();886target = dst->addr + dst->f.i.immediate*4 + 4;887if (target == dst->addr)888{889if (check_nop)890{891dst->ops = current_instruction_table.BC1FL_IDLE;892recomp_func = genbc1fl_idle;893}894}895else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))896{897dst->ops = current_instruction_table.BC1FL_OUT;898recomp_func = genbc1fl_out;899}900}901902static void RBC1TL(void)903{904unsigned int target;905dst->ops = current_instruction_table.BC1TL;906recomp_func = genbc1tl;907recompile_standard_i_type();908target = dst->addr + dst->f.i.immediate*4 + 4;909if (target == dst->addr)910{911if (check_nop)912{913dst->ops = current_instruction_table.BC1TL_IDLE;914recomp_func = genbc1tl_idle;915}916}917else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))918{919dst->ops = current_instruction_table.BC1TL_OUT;920recomp_func = genbc1tl_out;921}922}923924static void (*recomp_bc[4])(void) =925{926RBC1F , RBC1T ,927RBC1FL, RBC1TL928};929930//-------------------------------------------------------------------------931// S932//-------------------------------------------------------------------------933934static void RADD_S(void)935{936dst->ops = current_instruction_table.ADD_S;937recomp_func = genadd_s;938recompile_standard_cf_type();939}940941static void RSUB_S(void)942{943dst->ops = current_instruction_table.SUB_S;944recomp_func = gensub_s;945recompile_standard_cf_type();946}947948static void RMUL_S(void)949{950dst->ops = current_instruction_table.MUL_S;951recomp_func = genmul_s;952recompile_standard_cf_type();953}954955static void RDIV_S(void)956{957dst->ops = current_instruction_table.DIV_S;958recomp_func = gendiv_s;959recompile_standard_cf_type();960}961962static void RSQRT_S(void)963{964dst->ops = current_instruction_table.SQRT_S;965recomp_func = gensqrt_s;966recompile_standard_cf_type();967}968969static void RABS_S(void)970{971dst->ops = current_instruction_table.ABS_S;972recomp_func = genabs_s;973recompile_standard_cf_type();974}975976static void RMOV_S(void)977{978dst->ops = current_instruction_table.MOV_S;979recomp_func = genmov_s;980recompile_standard_cf_type();981}982983static void RNEG_S(void)984{985dst->ops = current_instruction_table.NEG_S;986recomp_func = genneg_s;987recompile_standard_cf_type();988}989990static void RROUND_L_S(void)991{992dst->ops = current_instruction_table.ROUND_L_S;993recomp_func = genround_l_s;994recompile_standard_cf_type();995}996997static void RTRUNC_L_S(void)998{999dst->ops = current_instruction_table.TRUNC_L_S;1000recomp_func = gentrunc_l_s;1001recompile_standard_cf_type();1002}10031004static void RCEIL_L_S(void)1005{1006dst->ops = current_instruction_table.CEIL_L_S;1007recomp_func = genceil_l_s;1008recompile_standard_cf_type();1009}10101011static void RFLOOR_L_S(void)1012{1013dst->ops = current_instruction_table.FLOOR_L_S;1014recomp_func = genfloor_l_s;1015recompile_standard_cf_type();1016}10171018static void RROUND_W_S(void)1019{1020dst->ops = current_instruction_table.ROUND_W_S;1021recomp_func = genround_w_s;1022recompile_standard_cf_type();1023}10241025static void RTRUNC_W_S(void)1026{1027dst->ops = current_instruction_table.TRUNC_W_S;1028recomp_func = gentrunc_w_s;1029recompile_standard_cf_type();1030}10311032static void RCEIL_W_S(void)1033{1034dst->ops = current_instruction_table.CEIL_W_S;1035recomp_func = genceil_w_s;1036recompile_standard_cf_type();1037}10381039static void RFLOOR_W_S(void)1040{1041dst->ops = current_instruction_table.FLOOR_W_S;1042recomp_func = genfloor_w_s;1043recompile_standard_cf_type();1044}10451046static void RCVT_D_S(void)1047{1048dst->ops = current_instruction_table.CVT_D_S;1049recomp_func = gencvt_d_s;1050recompile_standard_cf_type();1051}10521053static void RCVT_W_S(void)1054{1055dst->ops = current_instruction_table.CVT_W_S;1056recomp_func = gencvt_w_s;1057recompile_standard_cf_type();1058}10591060static void RCVT_L_S(void)1061{1062dst->ops = current_instruction_table.CVT_L_S;1063recomp_func = gencvt_l_s;1064recompile_standard_cf_type();1065}10661067static void RC_F_S(void)1068{1069dst->ops = current_instruction_table.C_F_S;1070recomp_func = genc_f_s;1071recompile_standard_cf_type();1072}10731074static void RC_UN_S(void)1075{1076dst->ops = current_instruction_table.C_UN_S;1077recomp_func = genc_un_s;1078recompile_standard_cf_type();1079}10801081static void RC_EQ_S(void)1082{1083dst->ops = current_instruction_table.C_EQ_S;1084recomp_func = genc_eq_s;1085recompile_standard_cf_type();1086}10871088static void RC_UEQ_S(void)1089{1090dst->ops = current_instruction_table.C_UEQ_S;1091recomp_func = genc_ueq_s;1092recompile_standard_cf_type();1093}10941095static void RC_OLT_S(void)1096{1097dst->ops = current_instruction_table.C_OLT_S;1098recomp_func = genc_olt_s;1099recompile_standard_cf_type();1100}11011102static void RC_ULT_S(void)1103{1104dst->ops = current_instruction_table.C_ULT_S;1105recomp_func = genc_ult_s;1106recompile_standard_cf_type();1107}11081109static void RC_OLE_S(void)1110{1111dst->ops = current_instruction_table.C_OLE_S;1112recomp_func = genc_ole_s;1113recompile_standard_cf_type();1114}11151116static void RC_ULE_S(void)1117{1118dst->ops = current_instruction_table.C_ULE_S;1119recomp_func = genc_ule_s;1120recompile_standard_cf_type();1121}11221123static void RC_SF_S(void)1124{1125dst->ops = current_instruction_table.C_SF_S;1126recomp_func = genc_sf_s;1127recompile_standard_cf_type();1128}11291130static void RC_NGLE_S(void)1131{1132dst->ops = current_instruction_table.C_NGLE_S;1133recomp_func = genc_ngle_s;1134recompile_standard_cf_type();1135}11361137static void RC_SEQ_S(void)1138{1139dst->ops = current_instruction_table.C_SEQ_S;1140recomp_func = genc_seq_s;1141recompile_standard_cf_type();1142}11431144static void RC_NGL_S(void)1145{1146dst->ops = current_instruction_table.C_NGL_S;1147recomp_func = genc_ngl_s;1148recompile_standard_cf_type();1149}11501151static void RC_LT_S(void)1152{1153dst->ops = current_instruction_table.C_LT_S;1154recomp_func = genc_lt_s;1155recompile_standard_cf_type();1156}11571158static void RC_NGE_S(void)1159{1160dst->ops = current_instruction_table.C_NGE_S;1161recomp_func = genc_nge_s;1162recompile_standard_cf_type();1163}11641165static void RC_LE_S(void)1166{1167dst->ops = current_instruction_table.C_LE_S;1168recomp_func = genc_le_s;1169recompile_standard_cf_type();1170}11711172static void RC_NGT_S(void)1173{1174dst->ops = current_instruction_table.C_NGT_S;1175recomp_func = genc_ngt_s;1176recompile_standard_cf_type();1177}11781179static void (*recomp_s[64])(void) =1180{1181RADD_S , RSUB_S , RMUL_S , RDIV_S , RSQRT_S , RABS_S , RMOV_S , RNEG_S ,1182RROUND_L_S, RTRUNC_L_S, RCEIL_L_S, RFLOOR_L_S, RROUND_W_S, RTRUNC_W_S, RCEIL_W_S, RFLOOR_W_S,1183RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV ,1184RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV ,1185RSV , RCVT_D_S , RSV , RSV , RCVT_W_S , RCVT_L_S , RSV , RSV ,1186RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV ,1187RC_F_S , RC_UN_S , RC_EQ_S , RC_UEQ_S , RC_OLT_S , RC_ULT_S , RC_OLE_S , RC_ULE_S ,1188RC_SF_S , RC_NGLE_S , RC_SEQ_S , RC_NGL_S , RC_LT_S , RC_NGE_S , RC_LE_S , RC_NGT_S1189};11901191//-------------------------------------------------------------------------1192// D1193//-------------------------------------------------------------------------11941195static void RADD_D(void)1196{1197dst->ops = current_instruction_table.ADD_D;1198recomp_func = genadd_d;1199recompile_standard_cf_type();1200}12011202static void RSUB_D(void)1203{1204dst->ops = current_instruction_table.SUB_D;1205recomp_func = gensub_d;1206recompile_standard_cf_type();1207}12081209static void RMUL_D(void)1210{1211dst->ops = current_instruction_table.MUL_D;1212recomp_func = genmul_d;1213recompile_standard_cf_type();1214}12151216static void RDIV_D(void)1217{1218dst->ops = current_instruction_table.DIV_D;1219recomp_func = gendiv_d;1220recompile_standard_cf_type();1221}12221223static void RSQRT_D(void)1224{1225dst->ops = current_instruction_table.SQRT_D;1226recomp_func = gensqrt_d;1227recompile_standard_cf_type();1228}12291230static void RABS_D(void)1231{1232dst->ops = current_instruction_table.ABS_D;1233recomp_func = genabs_d;1234recompile_standard_cf_type();1235}12361237static void RMOV_D(void)1238{1239dst->ops = current_instruction_table.MOV_D;1240recomp_func = genmov_d;1241recompile_standard_cf_type();1242}12431244static void RNEG_D(void)1245{1246dst->ops = current_instruction_table.NEG_D;1247recomp_func = genneg_d;1248recompile_standard_cf_type();1249}12501251static void RROUND_L_D(void)1252{1253dst->ops = current_instruction_table.ROUND_L_D;1254recomp_func = genround_l_d;1255recompile_standard_cf_type();1256}12571258static void RTRUNC_L_D(void)1259{1260dst->ops = current_instruction_table.TRUNC_L_D;1261recomp_func = gentrunc_l_d;1262recompile_standard_cf_type();1263}12641265static void RCEIL_L_D(void)1266{1267dst->ops = current_instruction_table.CEIL_L_D;1268recomp_func = genceil_l_d;1269recompile_standard_cf_type();1270}12711272static void RFLOOR_L_D(void)1273{1274dst->ops = current_instruction_table.FLOOR_L_D;1275recomp_func = genfloor_l_d;1276recompile_standard_cf_type();1277}12781279static void RROUND_W_D(void)1280{1281dst->ops = current_instruction_table.ROUND_W_D;1282recomp_func = genround_w_d;1283recompile_standard_cf_type();1284}12851286static void RTRUNC_W_D(void)1287{1288dst->ops = current_instruction_table.TRUNC_W_D;1289recomp_func = gentrunc_w_d;1290recompile_standard_cf_type();1291}12921293static void RCEIL_W_D(void)1294{1295dst->ops = current_instruction_table.CEIL_W_D;1296recomp_func = genceil_w_d;1297recompile_standard_cf_type();1298}12991300static void RFLOOR_W_D(void)1301{1302dst->ops = current_instruction_table.FLOOR_W_D;1303recomp_func = genfloor_w_d;1304recompile_standard_cf_type();1305}13061307static void RCVT_S_D(void)1308{1309dst->ops = current_instruction_table.CVT_S_D;1310recomp_func = gencvt_s_d;1311recompile_standard_cf_type();1312}13131314static void RCVT_W_D(void)1315{1316dst->ops = current_instruction_table.CVT_W_D;1317recomp_func = gencvt_w_d;1318recompile_standard_cf_type();1319}13201321static void RCVT_L_D(void)1322{1323dst->ops = current_instruction_table.CVT_L_D;1324recomp_func = gencvt_l_d;1325recompile_standard_cf_type();1326}13271328static void RC_F_D(void)1329{1330dst->ops = current_instruction_table.C_F_D;1331recomp_func = genc_f_d;1332recompile_standard_cf_type();1333}13341335static void RC_UN_D(void)1336{1337dst->ops = current_instruction_table.C_UN_D;1338recomp_func = genc_un_d;1339recompile_standard_cf_type();1340}13411342static void RC_EQ_D(void)1343{1344dst->ops = current_instruction_table.C_EQ_D;1345recomp_func = genc_eq_d;1346recompile_standard_cf_type();1347}13481349static void RC_UEQ_D(void)1350{1351dst->ops = current_instruction_table.C_UEQ_D;1352recomp_func = genc_ueq_d;1353recompile_standard_cf_type();1354}13551356static void RC_OLT_D(void)1357{1358dst->ops = current_instruction_table.C_OLT_D;1359recomp_func = genc_olt_d;1360recompile_standard_cf_type();1361}13621363static void RC_ULT_D(void)1364{1365dst->ops = current_instruction_table.C_ULT_D;1366recomp_func = genc_ult_d;1367recompile_standard_cf_type();1368}13691370static void RC_OLE_D(void)1371{1372dst->ops = current_instruction_table.C_OLE_D;1373recomp_func = genc_ole_d;1374recompile_standard_cf_type();1375}13761377static void RC_ULE_D(void)1378{1379dst->ops = current_instruction_table.C_ULE_D;1380recomp_func = genc_ule_d;1381recompile_standard_cf_type();1382}13831384static void RC_SF_D(void)1385{1386dst->ops = current_instruction_table.C_SF_D;1387recomp_func = genc_sf_d;1388recompile_standard_cf_type();1389}13901391static void RC_NGLE_D(void)1392{1393dst->ops = current_instruction_table.C_NGLE_D;1394recomp_func = genc_ngle_d;1395recompile_standard_cf_type();1396}13971398static void RC_SEQ_D(void)1399{1400dst->ops = current_instruction_table.C_SEQ_D;1401recomp_func = genc_seq_d;1402recompile_standard_cf_type();1403}14041405static void RC_NGL_D(void)1406{1407dst->ops = current_instruction_table.C_NGL_D;1408recomp_func = genc_ngl_d;1409recompile_standard_cf_type();1410}14111412static void RC_LT_D(void)1413{1414dst->ops = current_instruction_table.C_LT_D;1415recomp_func = genc_lt_d;1416recompile_standard_cf_type();1417}14181419static void RC_NGE_D(void)1420{1421dst->ops = current_instruction_table.C_NGE_D;1422recomp_func = genc_nge_d;1423recompile_standard_cf_type();1424}14251426static void RC_LE_D(void)1427{1428dst->ops = current_instruction_table.C_LE_D;1429recomp_func = genc_le_d;1430recompile_standard_cf_type();1431}14321433static void RC_NGT_D(void)1434{1435dst->ops = current_instruction_table.C_NGT_D;1436recomp_func = genc_ngt_d;1437recompile_standard_cf_type();1438}14391440static void (*recomp_d[64])(void) =1441{1442RADD_D , RSUB_D , RMUL_D , RDIV_D , RSQRT_D , RABS_D , RMOV_D , RNEG_D ,1443RROUND_L_D, RTRUNC_L_D, RCEIL_L_D, RFLOOR_L_D, RROUND_W_D, RTRUNC_W_D, RCEIL_W_D, RFLOOR_W_D,1444RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV ,1445RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV ,1446RCVT_S_D , RSV , RSV , RSV , RCVT_W_D , RCVT_L_D , RSV , RSV ,1447RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV ,1448RC_F_D , RC_UN_D , RC_EQ_D , RC_UEQ_D , RC_OLT_D , RC_ULT_D , RC_OLE_D , RC_ULE_D ,1449RC_SF_D , RC_NGLE_D , RC_SEQ_D , RC_NGL_D , RC_LT_D , RC_NGE_D , RC_LE_D , RC_NGT_D1450};14511452//-------------------------------------------------------------------------1453// W1454//-------------------------------------------------------------------------14551456static void RCVT_S_W(void)1457{1458dst->ops = current_instruction_table.CVT_S_W;1459recomp_func = gencvt_s_w;1460recompile_standard_cf_type();1461}14621463static void RCVT_D_W(void)1464{1465dst->ops = current_instruction_table.CVT_D_W;1466recomp_func = gencvt_d_w;1467recompile_standard_cf_type();1468}14691470static void (*recomp_w[64])(void) =1471{1472RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1473RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1474RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1475RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1476RCVT_S_W, RCVT_D_W, RSV, RSV, RSV, RSV, RSV, RSV,1477RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1478RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1479RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV1480};14811482//-------------------------------------------------------------------------1483// L1484//-------------------------------------------------------------------------14851486static void RCVT_S_L(void)1487{1488dst->ops = current_instruction_table.CVT_S_L;1489recomp_func = gencvt_s_l;1490recompile_standard_cf_type();1491}14921493static void RCVT_D_L(void)1494{1495dst->ops = current_instruction_table.CVT_D_L;1496recomp_func = gencvt_d_l;1497recompile_standard_cf_type();1498}14991500static void (*recomp_l[64])(void) =1501{1502RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1503RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1504RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1505RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1506RCVT_S_L, RCVT_D_L, RSV, RSV, RSV, RSV, RSV, RSV,1507RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1508RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1509RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,1510};15111512//-------------------------------------------------------------------------1513// COP11514//-------------------------------------------------------------------------15151516static void RMFC1(void)1517{1518dst->ops = current_instruction_table.MFC1;1519recomp_func = genmfc1;1520recompile_standard_r_type();1521dst->f.r.nrd = (src >> 11) & 0x1F;1522if (dst->f.r.rt == reg) RNOP();1523}15241525static void RDMFC1(void)1526{1527dst->ops = current_instruction_table.DMFC1;1528recomp_func = gendmfc1;1529recompile_standard_r_type();1530dst->f.r.nrd = (src >> 11) & 0x1F;1531if (dst->f.r.rt == reg) RNOP();1532}15331534static void RCFC1(void)1535{1536dst->ops = current_instruction_table.CFC1;1537recomp_func = gencfc1;1538recompile_standard_r_type();1539dst->f.r.nrd = (src >> 11) & 0x1F;1540if (dst->f.r.rt == reg) RNOP();1541}15421543static void RMTC1(void)1544{1545dst->ops = current_instruction_table.MTC1;1546recompile_standard_r_type();1547recomp_func = genmtc1;1548dst->f.r.nrd = (src >> 11) & 0x1F;1549}15501551static void RDMTC1(void)1552{1553dst->ops = current_instruction_table.DMTC1;1554recompile_standard_r_type();1555recomp_func = gendmtc1;1556dst->f.r.nrd = (src >> 11) & 0x1F;1557}15581559static void RCTC1(void)1560{1561dst->ops = current_instruction_table.CTC1;1562recompile_standard_r_type();1563recomp_func = genctc1;1564dst->f.r.nrd = (src >> 11) & 0x1F;1565}15661567static void RBC(void)1568{1569recomp_bc[((src >> 16) & 3)]();1570}15711572static void RS(void)1573{1574recomp_s[(src & 0x3F)]();1575}15761577static void RD(void)1578{1579recomp_d[(src & 0x3F)]();1580}15811582static void RW(void)1583{1584recomp_w[(src & 0x3F)]();1585}15861587static void RL(void)1588{1589recomp_l[(src & 0x3F)]();1590}15911592static void (*recomp_cop1[32])(void) =1593{1594RMFC1, RDMFC1, RCFC1, RSV, RMTC1, RDMTC1, RCTC1, RSV,1595RBC , RSV , RSV , RSV, RSV , RSV , RSV , RSV,1596RS , RD , RSV , RSV, RW , RL , RSV , RSV,1597RSV , RSV , RSV , RSV, RSV , RSV , RSV , RSV1598};15991600//-------------------------------------------------------------------------1601// R43001602//-------------------------------------------------------------------------16031604static void RSPECIAL(void)1605{1606recomp_special[(src & 0x3F)]();1607}16081609static void RREGIMM(void)1610{1611recomp_regimm[((src >> 16) & 0x1F)]();1612}16131614static void RJ(void)1615{1616unsigned int target;1617dst->ops = current_instruction_table.J;1618recomp_func = genj;1619recompile_standard_j_type();1620target = (dst->f.j.inst_index<<2) | (dst->addr & 0xF0000000);1621if (target == dst->addr)1622{1623if (check_nop)1624{1625dst->ops = current_instruction_table.J_IDLE;1626recomp_func = genj_idle;1627}1628}1629else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))1630{1631dst->ops = current_instruction_table.J_OUT;1632recomp_func = genj_out;1633}1634}16351636static void RJAL(void)1637{1638unsigned int target;1639dst->ops = current_instruction_table.JAL;1640recomp_func = genjal;1641recompile_standard_j_type();1642target = (dst->f.j.inst_index<<2) | (dst->addr & 0xF0000000);1643if (target == dst->addr)1644{1645if (check_nop)1646{1647dst->ops = current_instruction_table.JAL_IDLE;1648recomp_func = genjal_idle;1649}1650}1651else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))1652{1653dst->ops = current_instruction_table.JAL_OUT;1654recomp_func = genjal_out;1655}1656}16571658static void RBEQ(void)1659{1660unsigned int target;1661dst->ops = current_instruction_table.BEQ;1662recomp_func = genbeq;1663recompile_standard_i_type();1664target = dst->addr + dst->f.i.immediate*4 + 4;1665if (target == dst->addr)1666{1667if (check_nop)1668{1669dst->ops = current_instruction_table.BEQ_IDLE;1670recomp_func = genbeq_idle;1671}1672}1673else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))1674{1675dst->ops = current_instruction_table.BEQ_OUT;1676recomp_func = genbeq_out;1677}1678}16791680static void RBNE(void)1681{1682unsigned int target;1683dst->ops = current_instruction_table.BNE;1684recomp_func = genbne;1685recompile_standard_i_type();1686target = dst->addr + dst->f.i.immediate*4 + 4;1687if (target == dst->addr)1688{1689if (check_nop)1690{1691dst->ops = current_instruction_table.BNE_IDLE;1692recomp_func = genbne_idle;1693}1694}1695else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))1696{1697dst->ops = current_instruction_table.BNE_OUT;1698recomp_func = genbne_out;1699}1700}17011702static void RBLEZ(void)1703{1704unsigned int target;1705dst->ops = current_instruction_table.BLEZ;1706recomp_func = genblez;1707recompile_standard_i_type();1708target = dst->addr + dst->f.i.immediate*4 + 4;1709if (target == dst->addr)1710{1711if (check_nop)1712{1713dst->ops = current_instruction_table.BLEZ_IDLE;1714recomp_func = genblez_idle;1715}1716}1717else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))1718{1719dst->ops = current_instruction_table.BLEZ_OUT;1720recomp_func = genblez_out;1721}1722}17231724static void RBGTZ(void)1725{1726unsigned int target;1727dst->ops = current_instruction_table.BGTZ;1728recomp_func = genbgtz;1729recompile_standard_i_type();1730target = dst->addr + dst->f.i.immediate*4 + 4;1731if (target == dst->addr)1732{1733if (check_nop)1734{1735dst->ops = current_instruction_table.BGTZ_IDLE;1736recomp_func = genbgtz_idle;1737}1738}1739else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))1740{1741dst->ops = current_instruction_table.BGTZ_OUT;1742recomp_func = genbgtz_out;1743}1744}17451746static void RADDI(void)1747{1748dst->ops = current_instruction_table.ADDI;1749recomp_func = genaddi;1750recompile_standard_i_type();1751if(dst->f.i.rt == reg) RNOP();1752}17531754static void RADDIU(void)1755{1756dst->ops = current_instruction_table.ADDIU;1757recomp_func = genaddiu;1758recompile_standard_i_type();1759if(dst->f.i.rt == reg) RNOP();1760}17611762static void RSLTI(void)1763{1764dst->ops = current_instruction_table.SLTI;1765recomp_func = genslti;1766recompile_standard_i_type();1767if(dst->f.i.rt == reg) RNOP();1768}17691770static void RSLTIU(void)1771{1772dst->ops = current_instruction_table.SLTIU;1773recomp_func = gensltiu;1774recompile_standard_i_type();1775if(dst->f.i.rt == reg) RNOP();1776}17771778static void RANDI(void)1779{1780dst->ops = current_instruction_table.ANDI;1781recomp_func = genandi;1782recompile_standard_i_type();1783if(dst->f.i.rt == reg) RNOP();1784}17851786static void RORI(void)1787{1788dst->ops = current_instruction_table.ORI;1789recomp_func = genori;1790recompile_standard_i_type();1791if (dst->f.i.rt == reg) RNOP();1792}17931794static void RXORI(void)1795{1796dst->ops = current_instruction_table.XORI;1797recomp_func = genxori;1798recompile_standard_i_type();1799if (dst->f.i.rt == reg) RNOP();1800}18011802static void RLUI(void)1803{1804dst->ops = current_instruction_table.LUI;1805recomp_func = genlui;1806recompile_standard_i_type();1807if (dst->f.i.rt == reg) RNOP();1808}18091810static void RCOP0(void)1811{1812recomp_cop0[((src >> 21) & 0x1F)]();1813}18141815static void RCOP1(void)1816{1817recomp_cop1[((src >> 21) & 0x1F)]();1818}18191820static void RBEQL(void)1821{1822unsigned int target;1823dst->ops = current_instruction_table.BEQL;1824recomp_func = genbeql;1825recompile_standard_i_type();1826target = dst->addr + dst->f.i.immediate*4 + 4;1827if (target == dst->addr)1828{1829if (check_nop)1830{1831dst->ops = current_instruction_table.BEQL_IDLE;1832recomp_func = genbeql_idle;1833}1834}1835else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))1836{1837dst->ops = current_instruction_table.BEQL_OUT;1838recomp_func = genbeql_out;1839}1840}18411842static void RBNEL(void)1843{1844unsigned int target;1845dst->ops = current_instruction_table.BNEL;1846recomp_func = genbnel;1847recompile_standard_i_type();1848target = dst->addr + dst->f.i.immediate*4 + 4;1849if (target == dst->addr)1850{1851if (check_nop)1852{1853dst->ops = current_instruction_table.BNEL_IDLE;1854recomp_func = genbnel_idle;1855}1856}1857else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))1858{1859dst->ops = current_instruction_table.BNEL_OUT;1860recomp_func = genbnel_out;1861}1862}18631864static void RBLEZL(void)1865{1866unsigned int target;1867dst->ops = current_instruction_table.BLEZL;1868recomp_func = genblezl;1869recompile_standard_i_type();1870target = dst->addr + dst->f.i.immediate*4 + 4;1871if (target == dst->addr)1872{1873if (check_nop)1874{1875dst->ops = current_instruction_table.BLEZL_IDLE;1876recomp_func = genblezl_idle;1877}1878}1879else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))1880{1881dst->ops = current_instruction_table.BLEZL_OUT;1882recomp_func = genblezl_out;1883}1884}18851886static void RBGTZL(void)1887{1888unsigned int target;1889dst->ops = current_instruction_table.BGTZL;1890recomp_func = genbgtzl;1891recompile_standard_i_type();1892target = dst->addr + dst->f.i.immediate*4 + 4;1893if (target == dst->addr)1894{1895if (check_nop)1896{1897dst->ops = current_instruction_table.BGTZL_IDLE;1898recomp_func = genbgtzl_idle;1899}1900}1901else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))1902{1903dst->ops = current_instruction_table.BGTZL_OUT;1904recomp_func = genbgtzl_out;1905}1906}19071908static void RDADDI(void)1909{1910dst->ops = current_instruction_table.DADDI;1911recomp_func = gendaddi;1912recompile_standard_i_type();1913if(dst->f.i.rt == reg) RNOP();1914}19151916static void RDADDIU(void)1917{1918dst->ops = current_instruction_table.DADDIU;1919recomp_func = gendaddiu;1920recompile_standard_i_type();1921if(dst->f.i.rt == reg) RNOP();1922}19231924static void RLDL(void)1925{1926dst->ops = current_instruction_table.LDL;1927recomp_func = genldl;1928recompile_standard_i_type();1929if(dst->f.i.rt == reg) RNOP();1930}19311932static void RLDR(void)1933{1934dst->ops = current_instruction_table.LDR;1935recomp_func = genldr;1936recompile_standard_i_type();1937if(dst->f.i.rt == reg) RNOP();1938}19391940static void RLB(void)1941{1942dst->ops = current_instruction_table.LB;1943recomp_func = genlb;1944recompile_standard_i_type();1945if (dst->f.i.rt == reg) RNOP();1946}19471948static void RLH(void)1949{1950dst->ops = current_instruction_table.LH;1951recomp_func = genlh;1952recompile_standard_i_type();1953if (dst->f.i.rt == reg) RNOP();1954}19551956static void RLWL(void)1957{1958dst->ops = current_instruction_table.LWL;1959recomp_func = genlwl;1960recompile_standard_i_type();1961if (dst->f.i.rt == reg) RNOP();1962}19631964static void RLW(void)1965{1966dst->ops = current_instruction_table.LW;1967recomp_func = genlw;1968recompile_standard_i_type();1969if (dst->f.i.rt == reg) RNOP();1970}19711972static void RLBU(void)1973{1974dst->ops = current_instruction_table.LBU;1975recomp_func = genlbu;1976recompile_standard_i_type();1977if(dst->f.i.rt == reg) RNOP();1978}19791980static void RLHU(void)1981{1982dst->ops = current_instruction_table.LHU;1983recomp_func = genlhu;1984recompile_standard_i_type();1985if(dst->f.i.rt == reg) RNOP();1986}19871988static void RLWR(void)1989{1990dst->ops = current_instruction_table.LWR;1991recomp_func = genlwr;1992recompile_standard_i_type();1993if(dst->f.i.rt == reg) RNOP();1994}19951996static void RLWU(void)1997{1998dst->ops = current_instruction_table.LWU;1999recomp_func = genlwu;2000recompile_standard_i_type();2001if(dst->f.i.rt == reg) RNOP();2002}20032004static void RSB(void)2005{2006dst->ops = current_instruction_table.SB;2007recomp_func = gensb;2008recompile_standard_i_type();2009}20102011static void RSH(void)2012{2013dst->ops = current_instruction_table.SH;2014recomp_func = gensh;2015recompile_standard_i_type();2016}20172018static void RSWL(void)2019{2020dst->ops = current_instruction_table.SWL;2021recomp_func = genswl;2022recompile_standard_i_type();2023}20242025static void RSW(void)2026{2027dst->ops = current_instruction_table.SW;2028recomp_func = gensw;2029recompile_standard_i_type();2030}20312032static void RSDL(void)2033{2034dst->ops = current_instruction_table.SDL;2035recomp_func = gensdl;2036recompile_standard_i_type();2037}20382039static void RSDR(void)2040{2041dst->ops = current_instruction_table.SDR;2042recomp_func = gensdr;2043recompile_standard_i_type();2044}20452046static void RSWR(void)2047{2048dst->ops = current_instruction_table.SWR;2049recomp_func = genswr;2050recompile_standard_i_type();2051}20522053static void RCACHE(void)2054{2055recomp_func = gencache;2056dst->ops = current_instruction_table.CACHE;2057}20582059static void RLL(void)2060{2061recomp_func = genll;2062dst->ops = current_instruction_table.LL;2063recompile_standard_i_type();2064if(dst->f.i.rt == reg) RNOP();2065}20662067static void RLWC1(void)2068{2069dst->ops = current_instruction_table.LWC1;2070recomp_func = genlwc1;2071recompile_standard_lf_type();2072}20732074static void RLLD(void)2075{2076dst->ops = current_instruction_table.NI;2077recomp_func = genni;2078recompile_standard_i_type();2079}20802081static void RLDC1(void)2082{2083dst->ops = current_instruction_table.LDC1;2084recomp_func = genldc1;2085recompile_standard_lf_type();2086}20872088static void RLD(void)2089{2090dst->ops = current_instruction_table.LD;2091recomp_func = genld;2092recompile_standard_i_type();2093if (dst->f.i.rt == reg) RNOP();2094}20952096static void RSC(void)2097{2098dst->ops = current_instruction_table.SC;2099recomp_func = gensc;2100recompile_standard_i_type();2101if (dst->f.i.rt == reg) RNOP();2102}21032104static void RSWC1(void)2105{2106dst->ops = current_instruction_table.SWC1;2107recomp_func = genswc1;2108recompile_standard_lf_type();2109}21102111static void RSCD(void)2112{2113dst->ops = current_instruction_table.NI;2114recomp_func = genni;2115recompile_standard_i_type();2116}21172118static void RSDC1(void)2119{2120dst->ops = current_instruction_table.SDC1;2121recomp_func = gensdc1;2122recompile_standard_lf_type();2123}21242125static void RSD(void)2126{2127dst->ops = current_instruction_table.SD;2128recomp_func = gensd;2129recompile_standard_i_type();2130}21312132static void (*recomp_ops[64])(void) =2133{2134RSPECIAL, RREGIMM, RJ , RJAL , RBEQ , RBNE , RBLEZ , RBGTZ ,2135RADDI , RADDIU , RSLTI, RSLTIU, RANDI, RORI , RXORI , RLUI ,2136RCOP0 , RCOP1 , RSV , RSV , RBEQL, RBNEL, RBLEZL, RBGTZL,2137RDADDI , RDADDIU, RLDL , RLDR , RSV , RSV , RSV , RSV ,2138RLB , RLH , RLWL , RLW , RLBU , RLHU , RLWR , RLWU ,2139RSB , RSH , RSWL , RSW , RSDL , RSDR , RSWR , RCACHE,2140RLL , RLWC1 , RSV , RSV , RLLD , RLDC1, RSV , RLD ,2141RSC , RSWC1 , RSV , RSV , RSCD , RSDC1, RSV , RSD2142};21432144static int get_block_length(const precomp_block *block)2145{2146return (block->end-block->start)/4;2147}21482149static size_t get_block_memsize(const precomp_block *block)2150{2151int length = get_block_length(block);2152return ((length+1)+(length>>2)) * sizeof(precomp_instr);2153}21542155/**********************************************************************2156******************** initialize an empty block ***********************2157**********************************************************************/2158void init_block(precomp_block *block)2159{2160int i, length, already_exist = 1;2161static int init_length;2162start_section(COMPILER_SECTION);2163#ifdef CORE_DBG2164DebugMessage(M64MSG_INFO, "init block %x - %x", (int) block->start, (int) block->end);2165#endif21662167length = get_block_length(block);21682169if (!block->block)2170{2171size_t memsize = get_block_memsize(block);2172if (r4300emu == CORE_DYNAREC) {2173block->block = (precomp_instr *) malloc_exec(memsize);2174if (!block->block) {2175DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate executable memory for dynamic recompiler. Try to use an interpreter mode.");2176return;2177}2178}2179else {2180block->block = (precomp_instr *) malloc(memsize);2181if (!block->block) {2182DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate memory for cached interpreter.");2183return;2184}2185}21862187memset(block->block, 0, memsize);2188already_exist = 0;2189}21902191if (r4300emu == CORE_DYNAREC)2192{2193if (!block->code)2194{2195#if defined(PROFILE_R4300)2196max_code_length = 524288; /* allocate so much code space that we'll never have to realloc(), because this may */2197/* cause instruction locations to move, and break our profiling data */2198#else2199max_code_length = 32768;2200#endif2201block->code = (unsigned char *) malloc_exec(max_code_length);2202}2203else2204{2205max_code_length = block->max_code_length;2206}2207code_length = 0;2208inst_pointer = &block->code;22092210if (block->jumps_table)2211{2212free(block->jumps_table);2213block->jumps_table = NULL;2214}2215if (block->riprel_table)2216{2217free(block->riprel_table);2218block->riprel_table = NULL;2219}2220init_assembler(NULL, 0, NULL, 0);2221init_cache(block->block);2222}22232224if (!already_exist)2225{2226#if defined(PROFILE_R4300)2227pfProfile = fopen("instructionaddrs.dat", "ab");2228long x86addr = (long) block->code;2229int mipsop = -2; /* -2 == NOTCOMPILED block at beginning of x86 code */2230if (fwrite(&mipsop, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode2231fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction2232DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data");2233#endif22342235for (i=0; i<length; i++)2236{2237dst = block->block + i;2238dst->addr = block->start + i*4;2239dst->reg_cache_infos.need_map = 0;2240dst->local_addr = code_length;2241#ifdef COMPARE_CORE2242if (r4300emu == CORE_DYNAREC) gendebug();2243#endif2244RNOTCOMPILED();2245if (r4300emu == CORE_DYNAREC) recomp_func();2246}2247#if defined(PROFILE_R4300)2248fclose(pfProfile);2249pfProfile = NULL;2250#endif2251init_length = code_length;2252}2253else2254{2255#if defined(PROFILE_R4300)2256code_length = block->code_length; /* leave old instructions in their place */2257#else2258code_length = init_length; /* recompile everything, overwrite old recompiled instructions */2259#endif2260for (i=0; i<length; i++)2261{2262dst = block->block + i;2263dst->reg_cache_infos.need_map = 0;2264dst->local_addr = i * (init_length / length);2265dst->ops = current_instruction_table.NOTCOMPILED;2266}2267}22682269if (r4300emu == CORE_DYNAREC)2270{2271free_all_registers();2272/* calling pass2 of the assembler is not necessary here because all of the code emitted by2273gennotcompiled() and gendebug() is position-independent and contains no jumps . */2274block->code_length = code_length;2275block->max_code_length = max_code_length;2276free_assembler(&block->jumps_table, &block->jumps_number, &block->riprel_table, &block->riprel_number);2277}22782279/* here we're marking the block as a valid code even if it's not compiled2280* yet as the game should have already set up the code correctly.2281*/2282invalid_code[block->start>>12] = 0;2283if (block->end < 0x80000000 || block->start >= 0xc0000000)2284{2285unsigned int paddr;22862287paddr = virtual_to_physical_address(block->start, 2);2288invalid_code[paddr>>12] = 0;2289if (!blocks[paddr>>12])2290{2291blocks[paddr>>12] = (precomp_block *) malloc(sizeof(precomp_block));2292blocks[paddr>>12]->code = NULL;2293blocks[paddr>>12]->block = NULL;2294blocks[paddr>>12]->jumps_table = NULL;2295blocks[paddr>>12]->riprel_table = NULL;2296blocks[paddr>>12]->start = paddr & ~0xFFF;2297blocks[paddr>>12]->end = (paddr & ~0xFFF) + 0x1000;2298}2299init_block(blocks[paddr>>12]);23002301paddr += block->end - block->start - 4;2302invalid_code[paddr>>12] = 0;2303if (!blocks[paddr>>12])2304{2305blocks[paddr>>12] = (precomp_block *) malloc(sizeof(precomp_block));2306blocks[paddr>>12]->code = NULL;2307blocks[paddr>>12]->block = NULL;2308blocks[paddr>>12]->jumps_table = NULL;2309blocks[paddr>>12]->riprel_table = NULL;2310blocks[paddr>>12]->start = paddr & ~0xFFF;2311blocks[paddr>>12]->end = (paddr & ~0xFFF) + 0x1000;2312}2313init_block(blocks[paddr>>12]);2314}2315else2316{2317if (block->start >= 0x80000000 && block->end < 0xa0000000 && invalid_code[(block->start+0x20000000)>>12])2318{2319if (!blocks[(block->start+0x20000000)>>12])2320{2321blocks[(block->start+0x20000000)>>12] = (precomp_block *) malloc(sizeof(precomp_block));2322blocks[(block->start+0x20000000)>>12]->code = NULL;2323blocks[(block->start+0x20000000)>>12]->block = NULL;2324blocks[(block->start+0x20000000)>>12]->jumps_table = NULL;2325blocks[(block->start+0x20000000)>>12]->riprel_table = NULL;2326blocks[(block->start+0x20000000)>>12]->start = (block->start+0x20000000) & ~0xFFF;2327blocks[(block->start+0x20000000)>>12]->end = ((block->start+0x20000000) & ~0xFFF) + 0x1000;2328}2329init_block(blocks[(block->start+0x20000000)>>12]);2330}2331if (block->start >= 0xa0000000 && block->end < 0xc0000000 && invalid_code[(block->start-0x20000000)>>12])2332{2333if (!blocks[(block->start-0x20000000)>>12])2334{2335blocks[(block->start-0x20000000)>>12] = (precomp_block *) malloc(sizeof(precomp_block));2336blocks[(block->start-0x20000000)>>12]->code = NULL;2337blocks[(block->start-0x20000000)>>12]->block = NULL;2338blocks[(block->start-0x20000000)>>12]->jumps_table = NULL;2339blocks[(block->start-0x20000000)>>12]->riprel_table = NULL;2340blocks[(block->start-0x20000000)>>12]->start = (block->start-0x20000000) & ~0xFFF;2341blocks[(block->start-0x20000000)>>12]->end = ((block->start-0x20000000) & ~0xFFF) + 0x1000;2342}2343init_block(blocks[(block->start-0x20000000)>>12]);2344}2345}2346end_section(COMPILER_SECTION);2347}23482349void free_block(precomp_block *block)2350{2351size_t memsize = get_block_memsize(block);23522353if (block->block) {2354if (r4300emu == CORE_DYNAREC)2355free_exec(block->block, memsize);2356else2357free(block->block);2358block->block = NULL;2359}2360if (block->code) { free_exec(block->code, block->max_code_length); block->code = NULL; }2361if (block->jumps_table) { free(block->jumps_table); block->jumps_table = NULL; }2362if (block->riprel_table) { free(block->riprel_table); block->riprel_table = NULL; }2363}23642365/**********************************************************************2366********************* recompile a block of code **********************2367**********************************************************************/2368void recompile_block(int *source, precomp_block *block, unsigned int func)2369{2370int i, length, finished=0;2371start_section(COMPILER_SECTION);2372length = (block->end-block->start)/4;2373dst_block = block;23742375//for (i=0; i<16; i++) block->md5[i] = 0;2376block->adler32 = 0;23772378if (r4300emu == CORE_DYNAREC)2379{2380code_length = block->code_length;2381max_code_length = block->max_code_length;2382inst_pointer = &block->code;2383init_assembler(block->jumps_table, block->jumps_number, block->riprel_table, block->riprel_number);2384init_cache(block->block + (func & 0xFFF) / 4);2385}23862387#if defined(PROFILE_R4300)2388pfProfile = fopen("instructionaddrs.dat", "ab");2389#endif23902391for (i = (func & 0xFFF) / 4; finished != 2; i++)2392{2393if(block->start < 0x80000000 || block->start >= 0xc0000000)2394{2395unsigned int address2 =2396virtual_to_physical_address(block->start + i*4, 0);2397if(blocks[address2>>12]->block[(address2&0xFFF)/4].ops == current_instruction_table.NOTCOMPILED)2398blocks[address2>>12]->block[(address2&0xFFF)/4].ops = current_instruction_table.NOTCOMPILED2;2399}24002401SRC = source + i;2402src = source[i];2403check_nop = source[i+1] == 0;2404dst = block->block + i;2405dst->addr = block->start + i*4;2406dst->reg_cache_infos.need_map = 0;2407dst->local_addr = code_length;2408#ifdef COMPARE_CORE2409if (r4300emu == CORE_DYNAREC) gendebug();2410#endif2411#if defined(PROFILE_R4300)2412long x86addr = (long) (block->code + block->block[i].local_addr);2413if (fwrite(source + i, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode2414fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction2415DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data");2416#endif2417recomp_func = NULL;2418recomp_ops[((src >> 26) & 0x3F)]();2419if (r4300emu == CORE_DYNAREC) recomp_func();2420dst = block->block + i;24212422/*if ((dst+1)->ops != NOTCOMPILED && !delay_slot_compiled &&2423i < length)2424{2425if (r4300emu == CORE_DYNAREC) genlink_subblock();2426finished = 2;2427}*/2428if (delay_slot_compiled)2429{2430delay_slot_compiled--;2431free_all_registers();2432}24332434if (i >= length-2+(length>>2)) finished = 2;2435if (i >= (length-1) && (block->start == 0xa4000000 ||2436block->start >= 0xc0000000 ||2437block->end < 0x80000000)) finished = 2;2438if (dst->ops == current_instruction_table.ERET || finished == 1) finished = 2;2439if (/*i >= length &&*/2440(dst->ops == current_instruction_table.J ||2441dst->ops == current_instruction_table.J_OUT ||2442dst->ops == current_instruction_table.JR) &&2443!(i >= (length-1) && (block->start >= 0xc0000000 ||2444block->end < 0x80000000)))2445finished = 1;2446}24472448#if defined(PROFILE_R4300)2449long x86addr = (long) (block->code + code_length);2450int mipsop = -3; /* -3 == block-postfix */2451if (fwrite(&mipsop, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode2452fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction2453DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data");2454#endif24552456if (i >= length)2457{2458dst = block->block + i;2459dst->addr = block->start + i*4;2460dst->reg_cache_infos.need_map = 0;2461dst->local_addr = code_length;2462#ifdef COMPARE_CORE2463if (r4300emu == CORE_DYNAREC) gendebug();2464#endif2465RFIN_BLOCK();2466if (r4300emu == CORE_DYNAREC) recomp_func();2467i++;2468if (i < length-1+(length>>2)) // useful when last opcode is a jump2469{2470dst = block->block + i;2471dst->addr = block->start + i*4;2472dst->reg_cache_infos.need_map = 0;2473dst->local_addr = code_length;2474#ifdef COMPARE_CORE2475if (r4300emu == CORE_DYNAREC) gendebug();2476#endif2477RFIN_BLOCK();2478if (r4300emu == CORE_DYNAREC) recomp_func();2479i++;2480}2481}2482else if (r4300emu == CORE_DYNAREC) genlink_subblock();24832484if (r4300emu == CORE_DYNAREC)2485{2486free_all_registers();2487passe2(block->block, (func&0xFFF)/4, i, block);2488block->code_length = code_length;2489block->max_code_length = max_code_length;2490free_assembler(&block->jumps_table, &block->jumps_number, &block->riprel_table, &block->riprel_number);2491}2492#ifdef CORE_DBG2493DebugMessage(M64MSG_INFO, "block recompiled (%x-%x)", (int)func, (int)(block->start+i*4));2494#endif2495#if defined(PROFILE_R4300)2496fclose(pfProfile);2497pfProfile = NULL;2498#endif2499end_section(COMPILER_SECTION);2500}25012502static int is_jump(void)2503{2504recomp_ops[((src >> 26) & 0x3F)]();2505return2506(dst->ops == current_instruction_table.J ||2507dst->ops == current_instruction_table.J_OUT ||2508dst->ops == current_instruction_table.J_IDLE ||2509dst->ops == current_instruction_table.JAL ||2510dst->ops == current_instruction_table.JAL_OUT ||2511dst->ops == current_instruction_table.JAL_IDLE ||2512dst->ops == current_instruction_table.BEQ ||2513dst->ops == current_instruction_table.BEQ_OUT ||2514dst->ops == current_instruction_table.BEQ_IDLE ||2515dst->ops == current_instruction_table.BNE ||2516dst->ops == current_instruction_table.BNE_OUT ||2517dst->ops == current_instruction_table.BNE_IDLE ||2518dst->ops == current_instruction_table.BLEZ ||2519dst->ops == current_instruction_table.BLEZ_OUT ||2520dst->ops == current_instruction_table.BLEZ_IDLE ||2521dst->ops == current_instruction_table.BGTZ ||2522dst->ops == current_instruction_table.BGTZ_OUT ||2523dst->ops == current_instruction_table.BGTZ_IDLE ||2524dst->ops == current_instruction_table.BEQL ||2525dst->ops == current_instruction_table.BEQL_OUT ||2526dst->ops == current_instruction_table.BEQL_IDLE ||2527dst->ops == current_instruction_table.BNEL ||2528dst->ops == current_instruction_table.BNEL_OUT ||2529dst->ops == current_instruction_table.BNEL_IDLE ||2530dst->ops == current_instruction_table.BLEZL ||2531dst->ops == current_instruction_table.BLEZL_OUT ||2532dst->ops == current_instruction_table.BLEZL_IDLE ||2533dst->ops == current_instruction_table.BGTZL ||2534dst->ops == current_instruction_table.BGTZL_OUT ||2535dst->ops == current_instruction_table.BGTZL_IDLE ||2536dst->ops == current_instruction_table.JR ||2537dst->ops == current_instruction_table.JALR ||2538dst->ops == current_instruction_table.BLTZ ||2539dst->ops == current_instruction_table.BLTZ_OUT ||2540dst->ops == current_instruction_table.BLTZ_IDLE ||2541dst->ops == current_instruction_table.BGEZ ||2542dst->ops == current_instruction_table.BGEZ_OUT ||2543dst->ops == current_instruction_table.BGEZ_IDLE ||2544dst->ops == current_instruction_table.BLTZL ||2545dst->ops == current_instruction_table.BLTZL_OUT ||2546dst->ops == current_instruction_table.BLTZL_IDLE ||2547dst->ops == current_instruction_table.BGEZL ||2548dst->ops == current_instruction_table.BGEZL_OUT ||2549dst->ops == current_instruction_table.BGEZL_IDLE ||2550dst->ops == current_instruction_table.BLTZAL ||2551dst->ops == current_instruction_table.BLTZAL_OUT ||2552dst->ops == current_instruction_table.BLTZAL_IDLE ||2553dst->ops == current_instruction_table.BGEZAL ||2554dst->ops == current_instruction_table.BGEZAL_OUT ||2555dst->ops == current_instruction_table.BGEZAL_IDLE ||2556dst->ops == current_instruction_table.BLTZALL ||2557dst->ops == current_instruction_table.BLTZALL_OUT ||2558dst->ops == current_instruction_table.BLTZALL_IDLE ||2559dst->ops == current_instruction_table.BGEZALL ||2560dst->ops == current_instruction_table.BGEZALL_OUT ||2561dst->ops == current_instruction_table.BGEZALL_IDLE ||2562dst->ops == current_instruction_table.BC1F ||2563dst->ops == current_instruction_table.BC1F_OUT ||2564dst->ops == current_instruction_table.BC1F_IDLE ||2565dst->ops == current_instruction_table.BC1T ||2566dst->ops == current_instruction_table.BC1T_OUT ||2567dst->ops == current_instruction_table.BC1T_IDLE ||2568dst->ops == current_instruction_table.BC1FL ||2569dst->ops == current_instruction_table.BC1FL_OUT ||2570dst->ops == current_instruction_table.BC1FL_IDLE ||2571dst->ops == current_instruction_table.BC1TL ||2572dst->ops == current_instruction_table.BC1TL_OUT ||2573dst->ops == current_instruction_table.BC1TL_IDLE);2574}25752576/**********************************************************************2577************ recompile only one opcode (use for delay slot) **********2578**********************************************************************/2579void recompile_opcode(void)2580{2581SRC++;2582src = *SRC;2583dst++;2584dst->addr = (dst-1)->addr + 4;2585dst->reg_cache_infos.need_map = 0;2586if(!is_jump())2587{2588#if defined(PROFILE_R4300)2589long x86addr = (long) ((*inst_pointer) + code_length);2590if (fwrite(&src, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode2591fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction2592DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data");2593#endif2594recomp_func = NULL;2595recomp_ops[((src >> 26) & 0x3F)]();2596if (r4300emu == CORE_DYNAREC) recomp_func();2597}2598else2599{2600RNOP();2601if (r4300emu == CORE_DYNAREC) recomp_func();2602}2603delay_slot_compiled = 2;2604}26052606/**********************************************************************2607************** decode one opcode (for the interpreter) ***************2608**********************************************************************/2609void prefetch_opcode(unsigned int op, unsigned int nextop)2610{2611dst = PC;2612src = op;2613check_nop = nextop == 0;2614recomp_ops[((src >> 26) & 0x3F)]();2615}26162617/**********************************************************************2618************** allocate memory with executable bit set ***************2619**********************************************************************/2620static void *malloc_exec(size_t size)2621{2622#if defined(WIN32)2623return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);2624#elif defined(__GNUC__)26252626#ifndef MAP_ANONYMOUS2627#ifdef MAP_ANON2628#define MAP_ANONYMOUS MAP_ANON2629#endif2630#endif26312632void *block = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);2633if (block == MAP_FAILED)2634{ DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate %zi byte block of aligned RWX memory.", size); return NULL; }26352636return block;2637#else2638return malloc(size);2639#endif2640}26412642/**********************************************************************2643************* reallocate memory with executable bit set **************2644**********************************************************************/2645void *realloc_exec(void *ptr, size_t oldsize, size_t newsize)2646{2647void* block = malloc_exec(newsize);2648if (block != NULL)2649{2650size_t copysize;2651if (oldsize < newsize)2652copysize = oldsize;2653else2654copysize = newsize;2655memcpy(block, ptr, copysize);2656}2657free_exec(ptr, oldsize);2658return block;2659}26602661/**********************************************************************2662**************** frees memory with executable bit set ****************2663**********************************************************************/2664static void free_exec(void *ptr, size_t length)2665{2666#if defined(WIN32)2667VirtualFree(ptr, 0, MEM_RELEASE);2668#elif defined(__GNUC__)2669munmap(ptr, length);2670#else2671free(ptr);2672#endif2673}267426752676