2013-12-19 17:10:14 +00:00
|
|
|
#include "types.h"
|
2019-04-19 09:45:05 +00:00
|
|
|
#include <unordered_set>
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-09-30 17:14:46 +00:00
|
|
|
#include "deps/xxhash/xxhash.h"
|
2013-12-19 17:10:14 +00:00
|
|
|
#include "../sh4_interpreter.h"
|
|
|
|
#include "../sh4_opcode_list.h"
|
|
|
|
#include "../sh4_core.h"
|
|
|
|
#include "../sh4_if.h"
|
|
|
|
#include "hw/sh4/sh4_interrupts.h"
|
|
|
|
|
2019-05-12 17:47:11 +00:00
|
|
|
#include "hw/mem/_vmem.h"
|
2013-12-19 17:10:14 +00:00
|
|
|
#include "hw/sh4/sh4_mem.h"
|
2019-03-25 10:53:13 +00:00
|
|
|
#include "hw/sh4/modules/mmu.h"
|
2013-12-19 17:10:14 +00:00
|
|
|
#include "hw/pvr/pvr_mem.h"
|
|
|
|
#include "hw/aica/aica_if.h"
|
|
|
|
#include "hw/gdrom/gdrom_if.h"
|
|
|
|
|
2019-09-07 12:37:39 +00:00
|
|
|
#include <ctime>
|
|
|
|
#include <cfloat>
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
#include "blockmanager.h"
|
|
|
|
#include "ngen.h"
|
|
|
|
#include "decoder.h"
|
|
|
|
|
2015-07-25 06:39:35 +00:00
|
|
|
#if FEAT_SHREC != DYNAREC_NONE
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-04-19 09:45:05 +00:00
|
|
|
u8 SH4_TCB[CODE_SIZE + TEMP_CODE_SIZE + 4096]
|
2019-08-25 17:29:56 +00:00
|
|
|
#if defined(_WIN32) || FEAT_SHREC != DYNAREC_JIT
|
2015-07-28 16:10:31 +00:00
|
|
|
;
|
2013-12-19 17:10:14 +00:00
|
|
|
#elif HOST_OS == OS_LINUX
|
2015-07-28 16:10:31 +00:00
|
|
|
__attribute__((section(".text")));
|
2015-05-16 05:12:19 +00:00
|
|
|
#elif HOST_OS==OS_DARWIN
|
2015-07-28 16:10:31 +00:00
|
|
|
__attribute__((section("__TEXT,.text")));
|
Partially working dyna for iOS. Very few games working atm.
This works, but is extremelly hacky. Must be started without attached debugger, lldb doesn't want to let go of EXC_BAD_ADDRESS, but reicast really depends on it getting delivered as SIGSEGV/SIGBUS. Also xcode has a really bad day upon seeing the jit code. Oh well.
There's some dynarec bug that causes color corruption on bios logo/boot triagles, TA crash on ikaruga and infinitive loop on crazy taxi. I'd guess some fp-memory-write thingy, abi, or smth. Too bad.
- Force code to compile in arm mode (arm jit -> thumb mem functions is complicated)
- SIGILL, SIGBUS. Works w/o Mach exceptions and EXC_BAD_ADDRESS
- Code buffers move to __TEXT, munmapped && memmapped to actually work
- Primitive input. Button + start, or left (works to get out of bios date screen)
- Fixup emitter for thumb2/interworking (didn't work though, reverted to arm cc)
- Block Manager: Disable mem saving / page fault alloc-on-demand logic
- Move cycle counter to r11, r9 is not clean on iOS. Remove r11 from reg alloc list
- Cache flushes for iOS
- log to log.txt
- load game.chd
2015-01-19 07:52:12 +00:00
|
|
|
#else
|
2015-05-16 05:12:19 +00:00
|
|
|
#error SH4_TCB ALLOC
|
2013-12-19 17:10:14 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
u8* CodeCache;
|
2019-04-19 09:45:05 +00:00
|
|
|
u8* TempCodeCache;
|
2019-05-12 20:02:57 +00:00
|
|
|
uintptr_t cc_rx_offset;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
u32 LastAddr;
|
|
|
|
u32 LastAddr_min;
|
2019-04-19 09:45:05 +00:00
|
|
|
u32 TempLastAddr;
|
2013-12-19 17:10:14 +00:00
|
|
|
u32* emit_ptr=0;
|
2019-04-19 09:45:05 +00:00
|
|
|
u32* emit_ptr_limit;
|
|
|
|
|
|
|
|
std::unordered_set<u32> smc_hotspots;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
void* emit_GetCCPtr() { return emit_ptr==0?(void*)&CodeCache[LastAddr]:(void*)emit_ptr; }
|
|
|
|
void emit_SetBaseAddr() { LastAddr_min = LastAddr; }
|
|
|
|
void emit_WriteCodeCache()
|
|
|
|
{
|
|
|
|
wchar path[512];
|
2015-08-17 11:59:39 +00:00
|
|
|
sprintf(path,"/code_cache_%8p.bin",CodeCache);
|
2015-08-28 23:28:51 +00:00
|
|
|
string pt2=get_writable_data_path(path);
|
2019-07-01 10:17:51 +00:00
|
|
|
INFO_LOG(DYNAREC, "Writing code cache to %s",pt2.c_str());
|
2013-12-19 17:10:14 +00:00
|
|
|
FILE*f=fopen(pt2.c_str(),"wb");
|
|
|
|
if (f)
|
|
|
|
{
|
|
|
|
fwrite(CodeCache,LastAddr,1,f);
|
|
|
|
fclose(f);
|
2019-07-01 10:17:51 +00:00
|
|
|
INFO_LOG(DYNAREC, "Written!");
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bm_WriteBlockMap(pt2+".map");
|
|
|
|
}
|
|
|
|
|
2019-04-19 09:45:05 +00:00
|
|
|
void clear_temp_cache(bool full)
|
|
|
|
{
|
|
|
|
//printf("recSh4:Temp Code Cache clear at %08X\n", curr_pc);
|
|
|
|
TempLastAddr = 0;
|
|
|
|
bm_ResetTempCache(full);
|
|
|
|
}
|
|
|
|
|
2019-08-30 21:35:10 +00:00
|
|
|
static void recSh4_ClearCache()
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-07-01 10:17:51 +00:00
|
|
|
INFO_LOG(DYNAREC, "recSh4:Dynarec Cache clear at %08X free space %d", next_pc, emit_FreeSpace());
|
2013-12-19 17:10:14 +00:00
|
|
|
LastAddr=LastAddr_min;
|
2019-06-19 09:01:33 +00:00
|
|
|
bm_ResetCache();
|
2019-04-19 09:45:05 +00:00
|
|
|
smc_hotspots.clear();
|
|
|
|
clear_temp_cache(true);
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2019-08-30 21:35:10 +00:00
|
|
|
static void recSh4_Run()
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
sh4_int_bCpuRun=true;
|
|
|
|
|
|
|
|
sh4_dyna_rcb=(u8*)&Sh4cntx + sizeof(Sh4cntx);
|
2019-07-01 10:17:51 +00:00
|
|
|
INFO_LOG(DYNAREC, "cntx // fpcb offset: %td // pc offset: %td // pc %08X", (u8*)&sh4rcb.fpcb - sh4_dyna_rcb, (u8*)&sh4rcb.cntx.pc - sh4_dyna_rcb, sh4rcb.cntx.pc);
|
2019-03-30 05:33:52 +00:00
|
|
|
|
2019-03-29 18:23:37 +00:00
|
|
|
if (!settings.dynarec.safemode)
|
2019-07-01 10:17:51 +00:00
|
|
|
NOTICE_LOG(DYNAREC, "Warning: Dynarec safe mode is off");
|
2019-03-30 05:33:52 +00:00
|
|
|
|
2019-03-29 18:23:37 +00:00
|
|
|
if (settings.dynarec.unstable_opt)
|
2019-07-01 10:17:51 +00:00
|
|
|
NOTICE_LOG(DYNAREC, "Warning: Unstable optimizations is on");
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
verify(rcb_noffs(&next_pc)==-184);
|
|
|
|
ngen_mainloop(sh4_dyna_rcb);
|
|
|
|
|
2019-07-28 15:37:04 +00:00
|
|
|
sh4_int_bCpuRun = false;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void emit_Write32(u32 data)
|
|
|
|
{
|
|
|
|
if (emit_ptr)
|
|
|
|
{
|
|
|
|
*emit_ptr=data;
|
|
|
|
emit_ptr++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*(u32*)&CodeCache[LastAddr]=data;
|
|
|
|
LastAddr+=4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void emit_Skip(u32 sz)
|
|
|
|
{
|
2019-04-19 09:45:05 +00:00
|
|
|
if (emit_ptr)
|
|
|
|
emit_ptr = (u32*)((u8*)emit_ptr + sz);
|
|
|
|
else
|
2019-05-23 09:40:33 +00:00
|
|
|
LastAddr += sz;
|
2019-04-19 09:45:05 +00:00
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
u32 emit_FreeSpace()
|
|
|
|
{
|
2019-04-19 09:45:05 +00:00
|
|
|
if (emit_ptr)
|
|
|
|
return (emit_ptr_limit - emit_ptr) * sizeof(u32);
|
|
|
|
else
|
2019-05-23 09:40:33 +00:00
|
|
|
return CODE_SIZE - LastAddr;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AnalyseBlock(RuntimeBlockInfo* blk);
|
|
|
|
|
2019-09-29 21:14:38 +00:00
|
|
|
static char block_hash[1024];
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-09-29 21:14:38 +00:00
|
|
|
const char* RuntimeBlockInfo::hash()
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-09-29 21:14:38 +00:00
|
|
|
XXH32_hash_t hash = 0;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-06-19 09:01:33 +00:00
|
|
|
u8* ptr = GetMemPtr(this->addr, this->sh4_code_size);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
if (ptr)
|
|
|
|
{
|
2019-09-29 21:14:38 +00:00
|
|
|
XXH32_state_t *state = XXH32_createState();
|
|
|
|
XXH32_reset(state, 7);
|
|
|
|
for (u32 i = 0; i < this->guest_opcodes; i++)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-09-29 21:14:38 +00:00
|
|
|
u16 data = ptr[i];
|
|
|
|
//Do not count PC relative loads (relocated code)
|
|
|
|
if ((ptr[i] >> 12) == 0xD)
|
|
|
|
data = 0xD000;
|
|
|
|
|
|
|
|
XXH32_update(state, &data, 2);
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
2019-09-29 21:14:38 +00:00
|
|
|
hash = XXH32_digest(state);
|
|
|
|
XXH32_freeState(state);
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2019-09-29 21:14:38 +00:00
|
|
|
sprintf(block_hash, ">:1:%02X:%08X", this->guest_opcodes, hash);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
return block_hash;
|
|
|
|
}
|
|
|
|
|
2019-04-15 16:02:34 +00:00
|
|
|
bool RuntimeBlockInfo::Setup(u32 rpc,fpscr_t rfpu_cfg)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
staging_runs=addr=lookups=runs=host_code_size=0;
|
|
|
|
guest_cycles=guest_opcodes=host_opcodes=0;
|
2019-06-19 20:55:47 +00:00
|
|
|
sh4_code_size = 0;
|
2013-12-19 17:10:14 +00:00
|
|
|
pBranchBlock=pNextBlock=0;
|
|
|
|
code=0;
|
|
|
|
has_jcond=false;
|
|
|
|
BranchBlock=NextBlock=csc_RetCache=0xFFFFFFFF;
|
|
|
|
BlockType=BET_SCL_Intr;
|
2019-03-25 10:53:13 +00:00
|
|
|
has_fpu_op = false;
|
2019-04-19 09:45:05 +00:00
|
|
|
temp_block = false;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-03-25 10:53:13 +00:00
|
|
|
vaddr = rpc;
|
|
|
|
if (mmu_enabled())
|
|
|
|
{
|
2019-05-26 11:30:05 +00:00
|
|
|
u32 rv = mmu_instruction_translation(vaddr, addr);
|
2019-04-15 16:02:34 +00:00
|
|
|
if (rv != MMU_ERROR_NONE)
|
|
|
|
{
|
|
|
|
DoMMUException(vaddr, rv, MMU_TT_IREAD);
|
|
|
|
return false;
|
|
|
|
}
|
2019-03-25 10:53:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
addr = vaddr;
|
2013-12-19 17:10:14 +00:00
|
|
|
fpu_cfg=rfpu_cfg;
|
|
|
|
|
|
|
|
oplist.clear();
|
|
|
|
|
2019-06-13 16:36:08 +00:00
|
|
|
#if !defined(NO_MMU)
|
|
|
|
try {
|
|
|
|
#endif
|
|
|
|
if (!dec_DecodeBlock(this, SH4_TIMESLICE / 2))
|
|
|
|
return false;
|
|
|
|
#if !defined(NO_MMU)
|
|
|
|
}
|
|
|
|
catch (SH4ThrownException& ex) {
|
|
|
|
Do_Exception(rpc, ex.expEvn, ex.callVect);
|
2019-04-15 16:02:34 +00:00
|
|
|
return false;
|
2019-06-13 16:36:08 +00:00
|
|
|
}
|
|
|
|
#endif
|
2019-06-19 09:01:33 +00:00
|
|
|
SetProtectedFlags();
|
2019-04-15 16:02:34 +00:00
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
AnalyseBlock(this);
|
2019-04-15 16:02:34 +00:00
|
|
|
|
|
|
|
return true;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2019-04-19 09:45:05 +00:00
|
|
|
DynarecCodeEntryPtr rdv_CompilePC(u32 blockcheck_failures)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
u32 pc=next_pc;
|
|
|
|
|
2015-02-25 18:30:08 +00:00
|
|
|
if (emit_FreeSpace()<16*1024 || pc==0x8c0000e0 || pc==0xac010000 || pc==0xac008300)
|
2013-12-19 17:10:14 +00:00
|
|
|
recSh4_ClearCache();
|
|
|
|
|
2019-03-25 10:53:13 +00:00
|
|
|
RuntimeBlockInfo* rbi = ngen_AllocateBlock();
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-04-15 16:02:34 +00:00
|
|
|
if (!rbi->Setup(pc,fpscr))
|
|
|
|
{
|
2019-03-25 10:53:13 +00:00
|
|
|
delete rbi;
|
2019-04-15 16:02:34 +00:00
|
|
|
return NULL;
|
2019-03-25 10:53:13 +00:00
|
|
|
}
|
2019-04-19 09:45:05 +00:00
|
|
|
rbi->blockcheck_failures = blockcheck_failures;
|
|
|
|
if (smc_hotspots.find(rbi->addr) != smc_hotspots.end())
|
|
|
|
{
|
|
|
|
if (TEMP_CODE_SIZE - TempLastAddr < 16 * 1024)
|
|
|
|
clear_temp_cache(false);
|
|
|
|
emit_ptr = (u32 *)(TempCodeCache + TempLastAddr);
|
|
|
|
emit_ptr_limit = (u32 *)(TempCodeCache + TEMP_CODE_SIZE);
|
|
|
|
rbi->temp_block = true;
|
2019-06-19 09:01:33 +00:00
|
|
|
if (rbi->read_only)
|
2019-07-01 10:17:51 +00:00
|
|
|
INFO_LOG(DYNAREC, "WARNING: temp block %x (%x) is protected!", rbi->vaddr, rbi->addr);
|
2019-04-19 09:45:05 +00:00
|
|
|
}
|
2019-05-23 09:40:33 +00:00
|
|
|
bool do_opts = !rbi->temp_block;
|
2019-04-15 16:02:34 +00:00
|
|
|
rbi->staging_runs=do_opts?100:-100;
|
2019-09-29 16:18:46 +00:00
|
|
|
bool block_check = !rbi->read_only;
|
2019-06-19 09:01:33 +00:00
|
|
|
ngen_Compile(rbi, block_check, (pc & 0xFFFFFF) == 0x08300 || (pc & 0xFFFFFF) == 0x10000, false, do_opts);
|
2019-04-15 16:02:34 +00:00
|
|
|
verify(rbi->code!=0);
|
|
|
|
|
|
|
|
bm_AddBlock(rbi);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-04-19 09:45:05 +00:00
|
|
|
if (emit_ptr != NULL)
|
|
|
|
{
|
|
|
|
TempLastAddr = (u8*)emit_ptr - TempCodeCache;
|
|
|
|
emit_ptr = NULL;
|
|
|
|
emit_ptr_limit = NULL;
|
|
|
|
}
|
|
|
|
|
2019-03-25 10:53:13 +00:00
|
|
|
return rbi->code;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2019-04-15 16:02:34 +00:00
|
|
|
DynarecCodeEntryPtr DYNACALL rdv_FailedToFindBlock_pc()
|
|
|
|
{
|
|
|
|
return rdv_FailedToFindBlock(next_pc);
|
|
|
|
}
|
|
|
|
|
2015-05-08 16:59:20 +00:00
|
|
|
DynarecCodeEntryPtr DYNACALL rdv_FailedToFindBlock(u32 pc)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
//printf("rdv_FailedToFindBlock ~ %08X\n",pc);
|
2019-04-15 16:02:34 +00:00
|
|
|
next_pc=pc;
|
2019-04-19 09:45:05 +00:00
|
|
|
DynarecCodeEntryPtr code = rdv_CompilePC(0);
|
2019-04-15 16:02:34 +00:00
|
|
|
if (code == NULL)
|
|
|
|
code = bm_GetCodeByVAddr(next_pc);
|
2019-05-22 12:13:00 +00:00
|
|
|
else
|
|
|
|
code = (DynarecCodeEntryPtr)CC_RW2RX(code);
|
2019-04-15 16:02:34 +00:00
|
|
|
return code;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2019-01-11 22:52:20 +00:00
|
|
|
static void ngen_FailedToFindBlock_internal() {
|
|
|
|
rdv_FailedToFindBlock(Sh4cntx.pc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void (*ngen_FailedToFindBlock)() = &ngen_FailedToFindBlock_internal;
|
|
|
|
|
2015-07-13 21:56:42 +00:00
|
|
|
u32 DYNACALL rdv_DoInterrupts_pc(u32 pc) {
|
|
|
|
next_pc = pc;
|
2013-12-19 17:10:14 +00:00
|
|
|
UpdateINTC();
|
|
|
|
|
|
|
|
return next_pc;
|
|
|
|
}
|
|
|
|
|
2015-07-13 21:56:42 +00:00
|
|
|
u32 DYNACALL rdv_DoInterrupts(void* block_cpde)
|
|
|
|
{
|
2019-06-19 09:01:33 +00:00
|
|
|
RuntimeBlockInfoPtr rbi = bm_GetBlock(block_cpde);
|
2019-03-25 10:53:13 +00:00
|
|
|
return rdv_DoInterrupts_pc(rbi->vaddr);
|
2015-07-13 21:56:42 +00:00
|
|
|
}
|
|
|
|
|
2019-03-25 10:53:13 +00:00
|
|
|
// addr must be the physical address of the start of the block
|
|
|
|
DynarecCodeEntryPtr DYNACALL rdv_BlockCheckFail(u32 addr)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-04-19 09:45:05 +00:00
|
|
|
u32 blockcheck_failures = 0;
|
2019-04-15 16:02:34 +00:00
|
|
|
if (mmu_enabled())
|
|
|
|
{
|
2019-06-19 09:01:33 +00:00
|
|
|
RuntimeBlockInfoPtr block = bm_GetBlock(addr);
|
2019-04-19 09:45:05 +00:00
|
|
|
blockcheck_failures = block->blockcheck_failures + 1;
|
|
|
|
if (blockcheck_failures > 5)
|
|
|
|
{
|
|
|
|
bool inserted = smc_hotspots.insert(addr).second;
|
2019-07-01 10:17:51 +00:00
|
|
|
if (inserted)
|
|
|
|
DEBUG_LOG(DYNAREC, "rdv_BlockCheckFail SMC hotspot @ %08x fails %d", addr, blockcheck_failures);
|
2019-04-19 09:45:05 +00:00
|
|
|
}
|
2019-06-19 09:01:33 +00:00
|
|
|
bm_DiscardBlock(block.get());
|
2019-04-15 16:02:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
next_pc = addr;
|
|
|
|
recSh4_ClearCache();
|
|
|
|
}
|
2019-05-22 12:13:00 +00:00
|
|
|
return (DynarecCodeEntryPtr)CC_RW2RX(rdv_CompilePC(blockcheck_failures));
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2015-05-08 16:59:20 +00:00
|
|
|
DynarecCodeEntryPtr rdv_FindOrCompile()
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-05-22 12:13:00 +00:00
|
|
|
DynarecCodeEntryPtr rv = bm_GetCodeByVAddr(next_pc); // Returns exec addr
|
2019-05-12 20:02:57 +00:00
|
|
|
if (rv == ngen_FailedToFindBlock)
|
2019-05-22 12:13:00 +00:00
|
|
|
rv = (DynarecCodeEntryPtr)CC_RW2RX(rdv_CompilePC(0)); // Returns rw addr
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* DYNACALL rdv_LinkBlock(u8* code,u32 dpc)
|
|
|
|
{
|
2019-05-12 20:02:57 +00:00
|
|
|
// code is the RX addr to return after, however bm_GetBlock returns RW
|
2019-06-19 09:01:33 +00:00
|
|
|
RuntimeBlockInfoPtr rbi = bm_GetBlock(code);
|
|
|
|
bool stale_block = false;
|
2013-12-19 17:10:14 +00:00
|
|
|
if (!rbi)
|
|
|
|
{
|
2019-06-19 09:01:33 +00:00
|
|
|
stale_block = true;
|
2019-05-12 20:02:57 +00:00
|
|
|
rbi = bm_GetStaleBlock(code);
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2015-07-31 18:37:39 +00:00
|
|
|
verify(rbi != NULL);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-06-19 09:01:33 +00:00
|
|
|
u32 bcls = BET_GET_CLS(rbi->BlockType);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-06-19 09:01:33 +00:00
|
|
|
if (bcls == BET_CLS_Static)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-06-19 09:01:33 +00:00
|
|
|
if (rbi->BlockType == BET_StaticIntr)
|
|
|
|
next_pc = rbi->NextBlock;
|
|
|
|
else
|
|
|
|
next_pc = rbi->BranchBlock;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
2019-06-19 09:01:33 +00:00
|
|
|
else if (bcls == BET_CLS_Dynamic)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-06-19 09:01:33 +00:00
|
|
|
next_pc = dpc;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
2019-06-19 09:01:33 +00:00
|
|
|
else if (bcls == BET_CLS_COND)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
if (dpc)
|
2019-06-19 09:01:33 +00:00
|
|
|
next_pc = rbi->BranchBlock;
|
2013-12-19 17:10:14 +00:00
|
|
|
else
|
2019-06-19 09:01:33 +00:00
|
|
|
next_pc = rbi->NextBlock;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2019-05-12 20:02:57 +00:00
|
|
|
DynarecCodeEntryPtr rv = rdv_FindOrCompile(); // Returns rx ptr
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-06-19 09:01:33 +00:00
|
|
|
if (!mmu_enabled() && !stale_block)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-06-19 09:01:33 +00:00
|
|
|
if (bcls == BET_CLS_Dynamic)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-06-19 09:01:33 +00:00
|
|
|
verify(rbi->relink_data == 0 || rbi->pBranchBlock == NULL);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-06-19 09:01:33 +00:00
|
|
|
if (rbi->pBranchBlock != NULL)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
rbi->pBranchBlock->RemRef(rbi);
|
2019-06-19 09:01:33 +00:00
|
|
|
rbi->pBranchBlock = NULL;
|
|
|
|
rbi->relink_data = 1;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
2019-06-19 09:01:33 +00:00
|
|
|
else if (rbi->relink_data == 0)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-06-19 09:01:33 +00:00
|
|
|
rbi->pBranchBlock = bm_GetBlock(next_pc).get();
|
2013-12-19 17:10:14 +00:00
|
|
|
rbi->pBranchBlock->AddRef(rbi);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-06-19 09:01:33 +00:00
|
|
|
RuntimeBlockInfo* nxt = bm_GetBlock(next_pc).get();
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-06-19 09:01:33 +00:00
|
|
|
if (rbi->BranchBlock == next_pc)
|
|
|
|
rbi->pBranchBlock = nxt;
|
|
|
|
if (rbi->NextBlock == next_pc)
|
|
|
|
rbi->pNextBlock = nxt;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
nxt->AddRef(rbi);
|
|
|
|
}
|
2019-06-19 09:01:33 +00:00
|
|
|
u32 ncs = rbi->relink_offset + rbi->Relink();
|
|
|
|
verify(rbi->host_code_size >= ncs);
|
|
|
|
rbi->host_code_size = ncs;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-07-01 10:17:51 +00:00
|
|
|
INFO_LOG(DYNAREC, "null RBI: from %08X to %08X -- unlinked stale block -- code %p next %p", rbi->vaddr, next_pc, code, rv);
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (void*)rv;
|
|
|
|
}
|
2019-08-30 21:35:10 +00:00
|
|
|
static void recSh4_Stop()
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
Sh4_int_Stop();
|
|
|
|
}
|
|
|
|
|
2019-08-30 21:35:10 +00:00
|
|
|
static void recSh4_Start()
|
2018-09-02 13:49:23 +00:00
|
|
|
{
|
|
|
|
Sh4_int_Start();
|
|
|
|
}
|
|
|
|
|
2019-08-30 21:35:10 +00:00
|
|
|
static void recSh4_Step()
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
Sh4_int_Step();
|
|
|
|
}
|
|
|
|
|
2019-08-30 21:35:10 +00:00
|
|
|
static void recSh4_Skip()
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
Sh4_int_Skip();
|
|
|
|
}
|
|
|
|
|
2019-08-30 21:35:10 +00:00
|
|
|
static void recSh4_Reset(bool hard)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-07-10 15:25:11 +00:00
|
|
|
Sh4_int_Reset(hard);
|
2019-05-25 16:03:18 +00:00
|
|
|
recSh4_ClearCache();
|
2019-06-19 09:01:33 +00:00
|
|
|
bm_Reset();
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2019-08-30 21:35:10 +00:00
|
|
|
static void recSh4_Init()
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-07-01 10:17:51 +00:00
|
|
|
INFO_LOG(DYNAREC, "recSh4 Init");
|
2013-12-19 17:10:14 +00:00
|
|
|
Sh4_int_Init();
|
|
|
|
bm_Init();
|
|
|
|
|
2015-08-11 17:07:23 +00:00
|
|
|
verify(rcb_noffs(p_sh4rcb->fpcb) == FPCB_OFFSET);
|
2015-07-13 21:56:42 +00:00
|
|
|
|
|
|
|
verify(rcb_noffs(p_sh4rcb->sq_buffer) == -512);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2015-07-13 21:56:42 +00:00
|
|
|
verify(rcb_noffs(&p_sh4rcb->cntx.sh4_sched_next) == -152);
|
|
|
|
verify(rcb_noffs(&p_sh4rcb->cntx.interrupt_pend) == -148);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-08-30 21:35:10 +00:00
|
|
|
if (_nvmem_enabled())
|
|
|
|
{
|
2019-05-23 09:40:33 +00:00
|
|
|
if (!_nvmem_4gb_space())
|
|
|
|
{
|
|
|
|
verify(mem_b.data==((u8*)p_sh4rcb->sq_buffer+512+0x0C000000));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
verify(mem_b.data==((u8*)p_sh4rcb->sq_buffer+512+0x8C000000));
|
|
|
|
}
|
2015-08-11 22:58:50 +00:00
|
|
|
}
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-05-12 17:47:11 +00:00
|
|
|
// Prepare some pointer to the pre-allocated code cache:
|
|
|
|
void *candidate_ptr = (void*)(((unat)SH4_TCB + 4095) & ~4095);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-05-12 17:47:11 +00:00
|
|
|
// Call the platform-specific magic to make the pages RWX
|
|
|
|
CodeCache = NULL;
|
2019-05-12 20:02:57 +00:00
|
|
|
#ifdef FEAT_NO_RWX_PAGES
|
2019-05-22 12:13:00 +00:00
|
|
|
verify(vmem_platform_prepare_jit_block(candidate_ptr, CODE_SIZE + TEMP_CODE_SIZE, (void**)&CodeCache, &cc_rx_offset));
|
2019-05-12 20:02:57 +00:00
|
|
|
#else
|
2019-05-22 12:13:00 +00:00
|
|
|
verify(vmem_platform_prepare_jit_block(candidate_ptr, CODE_SIZE + TEMP_CODE_SIZE, (void**)&CodeCache));
|
2015-07-28 15:28:53 +00:00
|
|
|
#endif
|
2019-05-12 17:47:11 +00:00
|
|
|
// Ensure the pointer returned is non-null
|
2018-09-25 10:27:37 +00:00
|
|
|
verify(CodeCache != NULL);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-05-22 12:13:00 +00:00
|
|
|
memset(CodeCache, 0xFF, CODE_SIZE + TEMP_CODE_SIZE);
|
2019-04-19 09:45:05 +00:00
|
|
|
TempCodeCache = CodeCache + CODE_SIZE;
|
2013-12-19 17:10:14 +00:00
|
|
|
ngen_init();
|
2019-06-19 09:01:33 +00:00
|
|
|
bm_ResetCache();
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2019-08-30 21:35:10 +00:00
|
|
|
static void recSh4_Term()
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-07-01 10:17:51 +00:00
|
|
|
INFO_LOG(DYNAREC, "recSh4 Term");
|
2013-12-19 17:10:14 +00:00
|
|
|
bm_Term();
|
|
|
|
Sh4_int_Term();
|
|
|
|
}
|
|
|
|
|
2019-08-30 21:35:10 +00:00
|
|
|
static bool recSh4_IsCpuRunning()
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
return Sh4_int_IsCpuRunning();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Get_Sh4Recompiler(sh4_if* rv)
|
|
|
|
{
|
2015-07-25 06:39:35 +00:00
|
|
|
rv->Run = recSh4_Run;
|
|
|
|
rv->Stop = recSh4_Stop;
|
2018-09-02 13:49:23 +00:00
|
|
|
rv->Start = recSh4_Start;
|
2015-07-25 06:39:35 +00:00
|
|
|
rv->Step = recSh4_Step;
|
|
|
|
rv->Skip = recSh4_Skip;
|
|
|
|
rv->Reset = recSh4_Reset;
|
|
|
|
rv->Init = recSh4_Init;
|
|
|
|
rv->Term = recSh4_Term;
|
|
|
|
rv->IsCpuRunning = recSh4_IsCpuRunning;
|
|
|
|
rv->ResetCache = recSh4_ClearCache;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
2019-05-12 17:47:11 +00:00
|
|
|
|
|
|
|
#endif // FEAT_SHREC != DYNAREC_NONE
|