Path: blob/master/libmupen64plus/mupen64plus-core/src/r4300/r4300.c
2 views
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *1* Mupen64plus - r4300.c *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#include "api/m64p_types.h"25#include "api/callbacks.h"26#include "api/debugger.h"27#include "memory/memory.h"28#include "main/main.h"29#include "main/rom.h"3031#include "r4300.h"32#include "ops.h"33#include "exception.h"34#include "interupt.h"35#include "macros.h"36#include "recomp.h"37#include "recomph.h"38#include "new_dynarec/new_dynarec.h"3940#ifdef DBG41#include "debugger/dbg_types.h"42#include "debugger/debugger.h"43#endif4445unsigned int r4300emu = 0;46int no_compiled_jump = 0;47int llbit; //, rompause;48HANDLE rompausesem;49#if NEW_DYNAREC != NEW_DYNAREC_ARM50int stop;51long long int reg[32], hi, lo;52unsigned int reg_cop0[32];53float *reg_cop1_simple[32];54double *reg_cop1_double[32];55int FCR0, FCR31;56unsigned int next_interupt;57precomp_instr *PC;58#endif59long long int local_rs;60long long int reg_cop1_fgr_64[32];61tlb tlb_e[32];62unsigned int delay_slot, skip_jump = 0, dyna_interp = 0, last_addr;63unsigned long long int debug_count = 0;64unsigned int CIC_Chip;65char invalid_code[0x100000];6667precomp_block *blocks[0x100000], *actual;68int rounding_mode = 0x33F, trunc_mode = 0xF3F, round_mode = 0x33F,69ceil_mode = 0xB3F, floor_mode = 0x73F;7071// -----------------------------------------------------------72// Cached interpreter functions (and fallback for dynarec).73// -----------------------------------------------------------74#ifdef DBG75#define UPDATE_DEBUGGER() if (g_DebuggerActive) update_debugger(PC->addr, -1)76#else77#define UPDATE_DEBUGGER() do { } while(0)78#endif7980#define PCADDR PC->addr81#define ADD_TO_PC(x) PC += x;82#define DECLARE_INSTRUCTION(name) static void name(void)8384#define DECLARE_JUMP(name, destination, condition, link, likely, cop1) \85static void name(void) \86{ \87const int take_jump = (condition); \88const unsigned int jump_target = (destination); \89long long int *link_register = (link); \90if (cop1 && check_cop1_unusable()) return; \91if (!likely || take_jump) \92{ \93PC++; \94delay_slot=1; \95UPDATE_DEBUGGER(); \96PC->ops(); \97update_count(); \98delay_slot=0; \99if (take_jump && !skip_jump) \100{ \101if (link_register != ®[0]) \102{ \103*link_register=PC->addr; \104sign_extended(*link_register); \105} \106PC=actual->block+((jump_target-actual->start)>>2); \107} \108} \109else \110{ \111PC += 2; \112update_count(); \113} \114last_addr = PC->addr; \115if (next_interupt <= Count) gen_interupt(); \116} \117static void name##_OUT(void) \118{ \119const int take_jump = (condition); \120const unsigned int jump_target = (destination); \121long long int *link_register = (link); \122if (cop1 && check_cop1_unusable()) return; \123if (!likely || take_jump) \124{ \125PC++; \126delay_slot=1; \127UPDATE_DEBUGGER(); \128PC->ops(); \129update_count(); \130delay_slot=0; \131if (take_jump && !skip_jump) \132{ \133if (link_register != ®[0]) \134{ \135*link_register=PC->addr; \136sign_extended(*link_register); \137} \138jump_to(jump_target); \139} \140} \141else \142{ \143PC += 2; \144update_count(); \145} \146last_addr = PC->addr; \147if (next_interupt <= Count) gen_interupt(); \148} \149static void name##_IDLE(void) \150{ \151const int take_jump = (condition); \152int skip; \153if (cop1 && check_cop1_unusable()) return; \154if (take_jump) \155{ \156update_count(); \157skip = next_interupt - Count; \158if (skip > 3) Count += (skip & 0xFFFFFFFC); \159else name(); \160} \161else name(); \162}163164#define CHECK_MEMORY() \165if (!invalid_code[address>>12]) \166if (blocks[address>>12]->block[(address&0xFFF)/4].ops != \167current_instruction_table.NOTCOMPILED) \168invalid_code[address>>12] = 1;169170#include "interpreter.def"171172// two functions are defined from the macros above but never used173// these prototype declarations will prevent a warning174#if defined(__GNUC__)175void JR_IDLE(void) __attribute__((used));176void JALR_IDLE(void) __attribute__((used));177#endif178179// -----------------------------------------------------------180// Flow control 'fake' instructions181// -----------------------------------------------------------182static void FIN_BLOCK(void)183{184if (!delay_slot)185{186jump_to((PC-1)->addr+4);187/*#ifdef DBG188if (g_DebuggerActive) update_debugger(PC->addr);189#endif190Used by dynarec only, check should be unnecessary191*/192PC->ops();193if (r4300emu == CORE_DYNAREC) dyna_jump();194}195else196{197precomp_block *blk = actual;198precomp_instr *inst = PC;199jump_to((PC-1)->addr+4);200201/*#ifdef DBG202if (g_DebuggerActive) update_debugger(PC->addr);203#endif204Used by dynarec only, check should be unnecessary205*/206if (!skip_jump)207{208PC->ops();209actual = blk;210PC = inst+1;211}212else213PC->ops();214215if (r4300emu == CORE_DYNAREC) dyna_jump();216}217}218219static void NOTCOMPILED(void)220{221unsigned int *mem = fast_mem_access(blocks[PC->addr>>12]->start);222#ifdef CORE_DBG223DebugMessage(M64MSG_INFO, "NOTCOMPILED: addr = %x ops = %lx", PC->addr, (long) PC->ops);224#endif225226if (mem != NULL)227recompile_block((int *)mem, blocks[PC->addr >> 12], PC->addr);228else229DebugMessage(M64MSG_ERROR, "not compiled exception");230231/*#ifdef DBG232if (g_DebuggerActive) update_debugger(PC->addr);233#endif234The preceeding update_debugger SHOULD be unnecessary since it should have been235called before NOTCOMPILED would have been executed236*/237PC->ops();238if (r4300emu == CORE_DYNAREC)239dyna_jump();240}241242static void NOTCOMPILED2(void)243{244NOTCOMPILED();245}246247// -----------------------------------------------------------248// Cached interpreter instruction table249// -----------------------------------------------------------250const cpu_instruction_table cached_interpreter_table = {251LB,252LBU,253LH,254LHU,255LW,256LWL,257LWR,258SB,259SH,260SW,261SWL,262SWR,263264LD,265LDL,266LDR,267LL,268LWU,269SC,270SD,271SDL,272SDR,273SYNC,274275ADDI,276ADDIU,277SLTI,278SLTIU,279ANDI,280ORI,281XORI,282LUI,283284DADDI,285DADDIU,286287ADD,288ADDU,289SUB,290SUBU,291SLT,292SLTU,293AND,294OR,295XOR,296NOR,297298DADD,299DADDU,300DSUB,301DSUBU,302303MULT,304MULTU,305DIV,306DIVU,307MFHI,308MTHI,309MFLO,310MTLO,311312DMULT,313DMULTU,314DDIV,315DDIVU,316317J,318J_OUT,319J_IDLE,320JAL,321JAL_OUT,322JAL_IDLE,323// Use the _OUT versions of JR and JALR, since we don't know324// until runtime if they're going to jump inside or outside the block325JR_OUT,326JALR_OUT,327BEQ,328BEQ_OUT,329BEQ_IDLE,330BNE,331BNE_OUT,332BNE_IDLE,333BLEZ,334BLEZ_OUT,335BLEZ_IDLE,336BGTZ,337BGTZ_OUT,338BGTZ_IDLE,339BLTZ,340BLTZ_OUT,341BLTZ_IDLE,342BGEZ,343BGEZ_OUT,344BGEZ_IDLE,345BLTZAL,346BLTZAL_OUT,347BLTZAL_IDLE,348BGEZAL,349BGEZAL_OUT,350BGEZAL_IDLE,351352BEQL,353BEQL_OUT,354BEQL_IDLE,355BNEL,356BNEL_OUT,357BNEL_IDLE,358BLEZL,359BLEZL_OUT,360BLEZL_IDLE,361BGTZL,362BGTZL_OUT,363BGTZL_IDLE,364BLTZL,365BLTZL_OUT,366BLTZL_IDLE,367BGEZL,368BGEZL_OUT,369BGEZL_IDLE,370BLTZALL,371BLTZALL_OUT,372BLTZALL_IDLE,373BGEZALL,374BGEZALL_OUT,375BGEZALL_IDLE,376BC1TL,377BC1TL_OUT,378BC1TL_IDLE,379BC1FL,380BC1FL_OUT,381BC1FL_IDLE,382383SLL,384SRL,385SRA,386SLLV,387SRLV,388SRAV,389390DSLL,391DSRL,392DSRA,393DSLLV,394DSRLV,395DSRAV,396DSLL32,397DSRL32,398DSRA32,399400MTC0,401MFC0,402403TLBR,404TLBWI,405TLBWR,406TLBP,407CACHE,408ERET,409410LWC1,411SWC1,412MTC1,413MFC1,414CTC1,415CFC1,416BC1T,417BC1T_OUT,418BC1T_IDLE,419BC1F,420BC1F_OUT,421BC1F_IDLE,422423DMFC1,424DMTC1,425LDC1,426SDC1,427428CVT_S_D,429CVT_S_W,430CVT_S_L,431CVT_D_S,432CVT_D_W,433CVT_D_L,434CVT_W_S,435CVT_W_D,436CVT_L_S,437CVT_L_D,438439ROUND_W_S,440ROUND_W_D,441ROUND_L_S,442ROUND_L_D,443444TRUNC_W_S,445TRUNC_W_D,446TRUNC_L_S,447TRUNC_L_D,448449CEIL_W_S,450CEIL_W_D,451CEIL_L_S,452CEIL_L_D,453454FLOOR_W_S,455FLOOR_W_D,456FLOOR_L_S,457FLOOR_L_D,458459ADD_S,460ADD_D,461462SUB_S,463SUB_D,464465MUL_S,466MUL_D,467468DIV_S,469DIV_D,470471ABS_S,472ABS_D,473474MOV_S,475MOV_D,476477NEG_S,478NEG_D,479480SQRT_S,481SQRT_D,482483C_F_S,484C_F_D,485C_UN_S,486C_UN_D,487C_EQ_S,488C_EQ_D,489C_UEQ_S,490C_UEQ_D,491C_OLT_S,492C_OLT_D,493C_ULT_S,494C_ULT_D,495C_OLE_S,496C_OLE_D,497C_ULE_S,498C_ULE_D,499C_SF_S,500C_SF_D,501C_NGLE_S,502C_NGLE_D,503C_SEQ_S,504C_SEQ_D,505C_NGL_S,506C_NGL_D,507C_LT_S,508C_LT_D,509C_NGE_S,510C_NGE_D,511C_LE_S,512C_LE_D,513C_NGT_S,514C_NGT_D,515516SYSCALL,517518TEQ,519520NOP,521RESERVED,522NI,523524FIN_BLOCK,525NOTCOMPILED,526NOTCOMPILED2527};528529cpu_instruction_table current_instruction_table;530531static unsigned int update_invalid_addr(unsigned int addr)532{533if (addr >= 0x80000000 && addr < 0xa0000000)534{535if (invalid_code[addr>>12]) invalid_code[(addr+0x20000000)>>12] = 1;536if (invalid_code[(addr+0x20000000)>>12]) invalid_code[addr>>12] = 1;537return addr;538}539else if (addr >= 0xa0000000 && addr < 0xc0000000)540{541if (invalid_code[addr>>12]) invalid_code[(addr-0x20000000)>>12] = 1;542if (invalid_code[(addr-0x20000000)>>12]) invalid_code[addr>>12] = 1;543return addr;544}545else546{547unsigned int paddr = virtual_to_physical_address(addr, 2);548if (paddr)549{550unsigned int beg_paddr = paddr - (addr - (addr&~0xFFF));551update_invalid_addr(paddr);552if (invalid_code[(beg_paddr+0x000)>>12]) invalid_code[addr>>12] = 1;553if (invalid_code[(beg_paddr+0xFFC)>>12]) invalid_code[addr>>12] = 1;554if (invalid_code[addr>>12]) invalid_code[(beg_paddr+0x000)>>12] = 1;555if (invalid_code[addr>>12]) invalid_code[(beg_paddr+0xFFC)>>12] = 1;556}557return paddr;558}559}560561#define addr jump_to_address562unsigned int jump_to_address;563void jump_to_func(void)564{565unsigned int paddr;566if (skip_jump) return;567paddr = update_invalid_addr(addr);568if (!paddr) return;569actual = blocks[addr>>12];570if (invalid_code[addr>>12])571{572if (!blocks[addr>>12])573{574blocks[addr>>12] = (precomp_block *) malloc(sizeof(precomp_block));575actual = blocks[addr>>12];576blocks[addr>>12]->code = NULL;577blocks[addr>>12]->block = NULL;578blocks[addr>>12]->jumps_table = NULL;579blocks[addr>>12]->riprel_table = NULL;580}581blocks[addr>>12]->start = addr & ~0xFFF;582blocks[addr>>12]->end = (addr & ~0xFFF) + 0x1000;583init_block(blocks[addr>>12]);584}585PC=actual->block+((addr-actual->start)>>2);586587if (r4300emu == CORE_DYNAREC) dyna_jump();588}589#undef addr590591void generic_jump_to(unsigned int address)592{593if (r4300emu == CORE_PURE_INTERPRETER)594PC->addr = address;595else {596#ifdef NEW_DYNAREC597if (r4300emu == CORE_DYNAREC)598last_addr = pcaddr;599else600jump_to(address);601#else602jump_to(address);603#endif604}605}606607/* Refer to Figure 6-2 on page 155 and explanation on page B-11608of MIPS R4000 Microprocessor User's Manual (Second Edition)609by Joe Heinrich.610*/611void shuffle_fpr_data(int oldStatus, int newStatus)612{613#if defined(M64P_BIG_ENDIAN)614const int isBigEndian = 1;615#else616const int isBigEndian = 0;617#endif618619if ((newStatus & 0x04000000) != (oldStatus & 0x04000000))620{621int i;622int temp_fgr_32[32];623624// pack or unpack the FGR register data625if (newStatus & 0x04000000)626{ // switching into 64-bit mode627// retrieve 32 FPR values from packed 32-bit FGR registers628for (i = 0; i < 32; i++)629{630temp_fgr_32[i] = *((int *) ®_cop1_fgr_64[i>>1] + ((i & 1) ^ isBigEndian));631}632// unpack them into 32 64-bit registers, taking the high 32-bits from their temporary place in the upper 16 FGRs633for (i = 0; i < 32; i++)634{635int high32 = *((int *) ®_cop1_fgr_64[(i>>1)+16] + (i & 1));636*((int *) ®_cop1_fgr_64[i] + isBigEndian) = temp_fgr_32[i];637*((int *) ®_cop1_fgr_64[i] + (isBigEndian^1)) = high32;638}639}640else641{ // switching into 32-bit mode642// retrieve the high 32 bits from each 64-bit FGR register and store in temp array643for (i = 0; i < 32; i++)644{645temp_fgr_32[i] = *((int *) ®_cop1_fgr_64[i] + (isBigEndian^1));646}647// take the low 32 bits from each register and pack them together into 64-bit pairs648for (i = 0; i < 16; i++)649{650unsigned int least32 = *((unsigned int *) ®_cop1_fgr_64[i*2] + isBigEndian);651unsigned int most32 = *((unsigned int *) ®_cop1_fgr_64[i*2+1] + isBigEndian);652reg_cop1_fgr_64[i] = ((unsigned long long) most32 << 32) | (unsigned long long) least32;653}654// store the high bits in the upper 16 FGRs, which wont be accessible in 32-bit mode655for (i = 0; i < 32; i++)656{657*((int *) ®_cop1_fgr_64[(i>>1)+16] + (i & 1)) = temp_fgr_32[i];658}659}660}661}662663void set_fpr_pointers(int newStatus)664{665int i;666#if defined(M64P_BIG_ENDIAN)667const int isBigEndian = 1;668#else669const int isBigEndian = 0;670#endif671672// update the FPR register pointers673if (newStatus & 0x04000000)674{675for (i = 0; i < 32; i++)676{677reg_cop1_double[i] = (double*) ®_cop1_fgr_64[i];678reg_cop1_simple[i] = ((float*) ®_cop1_fgr_64[i]) + isBigEndian;679}680}681else682{683for (i = 0; i < 32; i++)684{685reg_cop1_double[i] = (double*) ®_cop1_fgr_64[i>>1];686reg_cop1_simple[i] = ((float*) ®_cop1_fgr_64[i>>1]) + ((i & 1) ^ isBigEndian);687}688}689}690691int check_cop1_unusable(void)692{693if (!(Status & 0x20000000))694{695Cause = (11 << 2) | 0x10000000;696exception_general();697return 1;698}699return 0;700}701702void update_count(void)703{704#ifdef NEW_DYNAREC705if (r4300emu != CORE_DYNAREC)706{707#endif708Count = Count + (PC->addr - last_addr)/2;709last_addr = PC->addr;710#ifdef NEW_DYNAREC711}712#endif713714#ifdef COMPARE_CORE715if (delay_slot)716CoreCompareCallback();717#endif718/*#ifdef DBG719if (g_DebuggerActive && !delay_slot) update_debugger(PC->addr);720#endif721*/722}723724void init_blocks(void)725{726int i;727for (i=0; i<0x100000; i++)728{729invalid_code[i] = 1;730blocks[i] = NULL;731}732}733734void free_blocks(void)735{736int i;737for (i=0; i<0x100000; i++)738{739if (blocks[i])740{741free_block(blocks[i]);742free(blocks[i]);743blocks[i] = NULL;744}745}746}747748/* this hard reset function simulates the boot-up state of the R4300 CPU */749void r4300_reset_hard(void)750{751unsigned int i;752753// clear r4300 registers and TLB entries754for (i = 0; i < 32; i++)755{756reg[i]=0;757reg_cop0[i]=0;758reg_cop1_fgr_64[i]=0;759760// --------------tlb------------------------761tlb_e[i].mask=0;762tlb_e[i].vpn2=0;763tlb_e[i].g=0;764tlb_e[i].asid=0;765tlb_e[i].pfn_even=0;766tlb_e[i].c_even=0;767tlb_e[i].d_even=0;768tlb_e[i].v_even=0;769tlb_e[i].pfn_odd=0;770tlb_e[i].c_odd=0;771tlb_e[i].d_odd=0;772tlb_e[i].v_odd=0;773tlb_e[i].r=0;774//tlb_e[i].check_parity_mask=0x1000;775776tlb_e[i].start_even=0;777tlb_e[i].end_even=0;778tlb_e[i].phys_even=0;779tlb_e[i].start_odd=0;780tlb_e[i].end_odd=0;781tlb_e[i].phys_odd=0;782}783for (i=0; i<0x100000; i++)784{785tlb_LUT_r[i] = 0;786tlb_LUT_w[i] = 0;787}788llbit=0;789hi=0;790lo=0;791FCR0=0x511;792FCR31=0;793794// set COP0 registers795Random = 31;796Status= 0x34000000;797set_fpr_pointers(Status);798Config= 0x6e463;799PRevID = 0xb00;800Count = 0x5000;801Cause = 0x5C;802Context = 0x7FFFF0;803EPC = 0xFFFFFFFF;804BadVAddr = 0xFFFFFFFF;805ErrorEPC = 0xFFFFFFFF;806807rounding_mode = 0x33F;808}809810/* this soft reset function simulates the actions of the PIF ROM, which may vary by region811* TODO: accurately simulate the effects of the PIF ROM in the case of a soft reset812* (e.g. Goldeneye crashes) */813void r4300_reset_soft(void)814{815long long CRC = 0;816unsigned int i;817818// copy boot code from ROM to SP_DMEM819memcpy((char *)SP_DMEM+0x40, rom+0x40, 0xFC0);820821// the following values are extracted from the pj64 source code822// thanks to Zilmar and Jabo823824reg[6] = 0xFFFFFFFFA4001F0CLL;825reg[7] = 0xFFFFFFFFA4001F08LL;826reg[8] = 0x00000000000000C0LL;827reg[10]= 0x0000000000000040LL;828reg[11]= 0xFFFFFFFFA4000040LL;829reg[29]= 0xFFFFFFFFA4001FF0LL;830831// figure out which ROM type is loaded832for (i = 0x40/4; i < (0x1000/4); i++)833CRC += SP_DMEM[i];834switch(CRC) {835case 0x000000D0027FDF31LL:836case 0x000000CFFB631223LL:837CIC_Chip = 1;838break;839case 0x000000D057C85244LL:840CIC_Chip = 2;841break;842case 0x000000D6497E414BLL:843CIC_Chip = 3;844break;845case 0x0000011A49F60E96LL:846CIC_Chip = 5;847break;848case 0x000000D6D5BE5580LL:849CIC_Chip = 6;850break;851default:852CIC_Chip = 2;853}854855switch(ROM_PARAMS.systemtype)856{857case SYSTEM_PAL:858switch (CIC_Chip) {859case 2:860reg[5] = 0xFFFFFFFFC0F1D859LL;861reg[14]= 0x000000002DE108EALL;862break;863case 3:864reg[5] = 0xFFFFFFFFD4646273LL;865reg[14]= 0x000000001AF99984LL;866break;867case 5:868SP_IMEM[1] = 0xBDA807FC;869reg[5] = 0xFFFFFFFFDECAAAD1LL;870reg[14]= 0x000000000CF85C13LL;871reg[24]= 0x0000000000000002LL;872break;873case 6:874reg[5] = 0xFFFFFFFFB04DC903LL;875reg[14]= 0x000000001AF99984LL;876reg[24]= 0x0000000000000002LL;877break;878}879reg[23]= 0x0000000000000006LL;880reg[31]= 0xFFFFFFFFA4001554LL;881break;882case SYSTEM_NTSC:883default:884switch (CIC_Chip) {885case 2:886reg[5] = 0xFFFFFFFFC95973D5LL;887reg[14]= 0x000000002449A366LL;888break;889case 3:890reg[5] = 0xFFFFFFFF95315A28LL;891reg[14]= 0x000000005BACA1DFLL;892break;893case 5:894SP_IMEM[1] = 0x8DA807FC;895reg[5] = 0x000000005493FB9ALL;896reg[14]= 0xFFFFFFFFC2C20384LL;897break;898case 6:899reg[5] = 0xFFFFFFFFE067221FLL;900reg[14]= 0x000000005CD2B70FLL;901break;902}903reg[20]= 0x0000000000000001LL;904reg[24]= 0x0000000000000003LL;905reg[31]= 0xFFFFFFFFA4001550LL;906}907switch (CIC_Chip) {908case 1:909reg[22]= 0x000000000000003FLL;910break;911case 2:912reg[1] = 0x0000000000000001LL;913reg[2] = 0x000000000EBDA536LL;914reg[3] = 0x000000000EBDA536LL;915reg[4] = 0x000000000000A536LL;916reg[12]= 0xFFFFFFFFED10D0B3LL;917reg[13]= 0x000000001402A4CCLL;918reg[15]= 0x000000003103E121LL;919reg[22]= 0x000000000000003FLL;920reg[25]= 0xFFFFFFFF9DEBB54FLL;921break;922case 3:923reg[1] = 0x0000000000000001LL;924reg[2] = 0x0000000049A5EE96LL;925reg[3] = 0x0000000049A5EE96LL;926reg[4] = 0x000000000000EE96LL;927reg[12]= 0xFFFFFFFFCE9DFBF7LL;928reg[13]= 0xFFFFFFFFCE9DFBF7LL;929reg[15]= 0x0000000018B63D28LL;930reg[22]= 0x0000000000000078LL;931reg[25]= 0xFFFFFFFF825B21C9LL;932break;933case 5:934SP_IMEM[0] = 0x3C0DBFC0;935SP_IMEM[2] = 0x25AD07C0;936SP_IMEM[3] = 0x31080080;937SP_IMEM[4] = 0x5500FFFC;938SP_IMEM[5] = 0x3C0DBFC0;939SP_IMEM[6] = 0x8DA80024;940SP_IMEM[7] = 0x3C0BB000;941reg[2] = 0xFFFFFFFFF58B0FBFLL;942reg[3] = 0xFFFFFFFFF58B0FBFLL;943reg[4] = 0x0000000000000FBFLL;944reg[12]= 0xFFFFFFFF9651F81ELL;945reg[13]= 0x000000002D42AAC5LL;946reg[15]= 0x0000000056584D60LL;947reg[22]= 0x0000000000000091LL;948reg[25]= 0xFFFFFFFFCDCE565FLL;949break;950case 6:951reg[2] = 0xFFFFFFFFA95930A4LL;952reg[3] = 0xFFFFFFFFA95930A4LL;953reg[4] = 0x00000000000030A4LL;954reg[12]= 0xFFFFFFFFBCB59510LL;955reg[13]= 0xFFFFFFFFBCB59510LL;956reg[15]= 0x000000007A3C07F4LL;957reg[22]= 0x0000000000000085LL;958reg[25]= 0x00000000465E3F72LL;959break;960}961962}963964#if !defined(NO_ASM)965static void dynarec_setup_code(void)966{967// The dynarec jumps here after we call dyna_start and it prepares968// Here we need to prepare the initial code block and jump to it969jump_to(0xa4000040);970971// Prevent segfault on failed jump_to972if (!actual->block || !actual->code)973dyna_stop();974}975#endif976977void r4300_execute(void (*startcb)(void))978{979#if defined(COUNT_INSTR) || (defined(DYNAREC) && defined(PROFILE_R4300))980unsigned int i;981#endif982983current_instruction_table = cached_interpreter_table;984985debug_count = 0;986delay_slot=0;987stop = 0;988//rompause = 1;989rompausesem = CreateSemaphore(NULL, 0, 1, NULL);990991/* clear instruction counters */992#if defined(COUNT_INSTR)993for (i = 0; i < 131; i++)994instr_count[i] = 0;995#endif996997last_addr = 0xa4000040;998next_interupt = 624999;999init_interupt();10001001if (startcb)1002startcb();10031004// now that everything has been set up, we stop here to wait for the first frame1005WaitForSingleObject(rompausesem, INFINITE);10061007if (r4300emu == CORE_PURE_INTERPRETER)1008{1009DebugMessage(M64MSG_INFO, "Starting R4300 emulator: Pure Interpreter");1010r4300emu = CORE_PURE_INTERPRETER;1011pure_interpreter();1012}1013#if defined(DYNAREC)1014else if (r4300emu >= 2)1015{1016DebugMessage(M64MSG_INFO, "Starting R4300 emulator: Dynamic Recompiler");1017r4300emu = CORE_DYNAREC;1018init_blocks();10191020#ifdef NEW_DYNAREC1021new_dynarec_init();1022new_dyna_start();1023new_dynarec_cleanup();1024#else1025dyna_start(dynarec_setup_code);1026PC++;1027#endif1028#if defined(PROFILE_R4300)1029pfProfile = fopen("instructionaddrs.dat", "ab");1030for (i=0; i<0x100000; i++)1031if (invalid_code[i] == 0 && blocks[i] != NULL && blocks[i]->code != NULL && blocks[i]->block != NULL)1032{1033unsigned char *x86addr;1034int mipsop;1035// store final code length for this block1036mipsop = -1; /* -1 == end of x86 code block */1037x86addr = blocks[i]->code + blocks[i]->code_length;1038if (fwrite(&mipsop, 1, 4, pfProfile) != 4 ||1039fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *))1040DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data");1041}1042fclose(pfProfile);1043pfProfile = NULL;1044#endif1045free_blocks();1046}1047#endif1048else /* if (r4300emu == CORE_INTERPRETER) */1049{1050DebugMessage(M64MSG_INFO, "Starting R4300 emulator: Cached Interpreter");1051r4300emu = CORE_INTERPRETER;1052init_blocks();1053jump_to(0xa4000040);10541055/* Prevent segfault on failed jump_to */1056if (!actual->block)1057return;10581059last_addr = PC->addr;1060while (!stop)1061{1062#ifdef COMPARE_CORE1063if (PC->ops == FIN_BLOCK && (PC->addr < 0x80000000 || PC->addr >= 0xc0000000))1064virtual_to_physical_address(PC->addr, 2);1065CoreCompareCallback();1066#endif1067#ifdef DBG1068if (g_DebuggerActive) update_debugger(PC->addr, -1);1069#endif1070TRACECB();1071PC->ops();1072}10731074free_blocks();1075}10761077debug_count+= Count;1078DebugMessage(M64MSG_INFO, "R4300 emulator finished.");10791080/* print instruction counts */1081#if defined(COUNT_INSTR)1082if (r4300emu == CORE_DYNAREC)1083{1084unsigned int iTypeCount[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};1085unsigned int iTotal = 0;1086char line[128], param[24];1087DebugMessage(M64MSG_INFO, "Instruction counters:");1088line[0] = 0;1089for (i = 0; i < 131; i++)1090{1091sprintf(param, "%8s: %08i ", instr_name[i], instr_count[i]);1092strcat(line, param);1093if (i % 5 == 4)1094{1095DebugMessage(M64MSG_INFO, "%s", line);1096line[0] = 0;1097}1098iTypeCount[instr_type[i]] += instr_count[i];1099iTotal += instr_count[i];1100}1101DebugMessage(M64MSG_INFO, "Instruction type summary (total instructions = %i)", iTotal);1102for (i = 0; i < 11; i++)1103{1104DebugMessage(M64MSG_INFO, "%20s: %04.1f%% (%i)", instr_typename[i], (float) iTypeCount[i] * 100.0 / iTotal, iTypeCount[i]);1105}1106}1107#endif1108}11091110EXPORT void CALL GetRegisters(unsigned char * dest)1111{1112memcpy(dest, reg, 8 * 32);1113dest += 8 * 32;11141115if (PC != NULL)1116{1117memcpy(dest, &(PC->addr), 4);1118}1119else1120{1121char stupid[] = "0000";1122memcpy(dest, stupid, 4);1123}11241125dest += 4;11261127memcpy(dest, &llbit, 4);1128dest += 4;1129memcpy(dest, &lo, 8);1130dest += 8;1131memcpy(dest, &hi, 8);1132dest += 8;1133memcpy(dest, &FCR0, 4);1134dest += 4;1135memcpy(dest, &FCR31, 4);1136dest += 4;11371138memcpy(dest, reg_cop0, 4 * 32);1139dest += 4 * 32;11401141memcpy(dest, reg_cop1_fgr_64, 8 * 32);1142dest += 8 * 32;11431144}11451146