mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-01-12 16:30:44 +00:00
Stop forced compilation when entering a new JIT execution level.
This commit is contained in:
parent
aeab320c3f
commit
72b26d7ff7
@ -82,6 +82,9 @@ public:
|
||||
dyngen_cpu_base cpu() const
|
||||
{ return parent_cpu; }
|
||||
|
||||
// Align on ALIGN byte boundaries, ALIGN must be a power of 2
|
||||
uint8 *gen_align(int align = 16);
|
||||
|
||||
// Start code generation of a new block
|
||||
// Align on 16-byte boundaries
|
||||
// Returns pointer to entry point
|
||||
@ -231,7 +234,8 @@ public:
|
||||
#undef DEFINE_ALIAS_RAW
|
||||
|
||||
// Address of jump offset to patch for direct chaining
|
||||
uint8 *jmp_addr[2];
|
||||
static const int MAX_JUMPS = 2;
|
||||
uint8 *jmp_addr[MAX_JUMPS];
|
||||
};
|
||||
|
||||
inline bool
|
||||
@ -294,12 +298,20 @@ basic_dyngen::direct_call_possible(uintptr target) const
|
||||
return false;
|
||||
}
|
||||
|
||||
inline uint8 *
|
||||
basic_dyngen::gen_align(int align)
|
||||
{
|
||||
while ((uintptr)code_ptr() & (align - 1))
|
||||
inc_code_ptr(1);
|
||||
return code_ptr();
|
||||
}
|
||||
|
||||
inline uint8 *
|
||||
basic_dyngen::gen_start()
|
||||
{
|
||||
while ((uintptr)code_ptr() & 15)
|
||||
inc_code_ptr(1);
|
||||
gen_code_start = code_ptr();
|
||||
for (int i = 0; i < MAX_JUMPS; i++)
|
||||
jmp_addr[i] = NULL;
|
||||
gen_code_start = gen_align();
|
||||
return gen_code_start;
|
||||
}
|
||||
|
||||
|
@ -44,18 +44,37 @@ struct powerpc_block_info
|
||||
#if PPC_ENABLE_JIT
|
||||
uint8 * entry_point;
|
||||
#if DYNGEN_DIRECT_BLOCK_CHAINING
|
||||
uint8 * jmp_resolve_addr[2]; // Address of default code to resolve target addr
|
||||
uint8 * jmp_addr[2]; // Address of target native branch offset to patch
|
||||
uint32 jmp_pc[2]; // Target jump addresses in emulated address space
|
||||
struct link_info {
|
||||
uint8 * jmp_resolve_addr; // Address of default code to resolve target addr
|
||||
uint8 * jmp_addr; // Address of target native branch offset to patch
|
||||
uint32 jmp_pc; // Target jump addresses in emulated address space
|
||||
};
|
||||
static const uint32 INVALID_PC = 0xffffffff; // An invalid PC address to mark jmp_pc[] as stale
|
||||
link_info li[MAX_TARGETS];
|
||||
#endif
|
||||
#endif
|
||||
uintptr min_pc, max_pc;
|
||||
|
||||
void init(uintptr start_pc);
|
||||
bool intersect(uintptr start, uintptr end);
|
||||
void invalidate();
|
||||
};
|
||||
|
||||
inline void
|
||||
powerpc_block_info::init(uintptr start_pc)
|
||||
{
|
||||
basic_block_info::init(start_pc);
|
||||
#if PPC_DECODE_CACHE
|
||||
di = NULL;
|
||||
#endif
|
||||
#if PPC_ENABLE_JIT
|
||||
#if DYNGEN_DIRECT_BLOCK_CHAINING
|
||||
for (int i = 0; i < MAX_TARGETS; i++)
|
||||
li[i].jmp_pc = INVALID_PC;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
powerpc_block_info::intersect(uintptr start, uintptr end)
|
||||
{
|
||||
|
@ -440,13 +440,13 @@ void *powerpc_cpu::compile_chain_block(block_info *sbi)
|
||||
sbi = (block_info *)(((uintptr)sbi) & ~3L);
|
||||
const uint32 bpc = sbi->pc;
|
||||
|
||||
const uint32 tpc = sbi->jmp_pc[n];
|
||||
const uint32 tpc = sbi->li[n].jmp_pc;
|
||||
block_info *tbi = block_cache.find(tpc);
|
||||
if (tbi == NULL)
|
||||
tbi = compile_block(tpc);
|
||||
assert(tbi && tbi->pc == tpc);
|
||||
|
||||
dg_set_jmp_target(sbi->jmp_addr[n], tbi->entry_point);
|
||||
dg_set_jmp_target(sbi->li[n].jmp_addr, tbi->entry_point);
|
||||
return tbi->entry_point;
|
||||
}
|
||||
#endif
|
||||
@ -462,9 +462,10 @@ void powerpc_cpu::execute(uint32 entry)
|
||||
if (execute_depth == 1 || PPC_REENTRANT_JIT) {
|
||||
#if PPC_ENABLE_JIT
|
||||
if (use_jit) {
|
||||
block_info *bi = block_cache.find(pc());
|
||||
if (bi == NULL)
|
||||
bi = compile_block(pc());
|
||||
for (;;) {
|
||||
block_info *bi = compile_block(pc());
|
||||
|
||||
// Execute all cached blocks
|
||||
for (;;) {
|
||||
codegen.execute(bi->entry_point);
|
||||
@ -486,23 +487,33 @@ void powerpc_cpu::execute(uint32 entry)
|
||||
if ((bi = block_cache.find(pc())) == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
// Compile new block
|
||||
bi = compile_block(pc());
|
||||
}
|
||||
goto return_site;
|
||||
}
|
||||
#endif
|
||||
#if PPC_DECODE_CACHE
|
||||
block_info *bi = block_cache.find(pc());
|
||||
if (bi != NULL)
|
||||
goto pdi_execute;
|
||||
for (;;) {
|
||||
pdi_compile:
|
||||
#if PPC_PROFILE_COMPILE_TIME
|
||||
compile_count++;
|
||||
clock_t start_time = clock();
|
||||
#endif
|
||||
block_info *bi = block_cache.new_blockinfo();
|
||||
bi = block_cache.new_blockinfo();
|
||||
bi->init(pc());
|
||||
|
||||
// Predecode a new block
|
||||
block_info::decode_info *di = bi->di = decode_cache_p;
|
||||
pdi_decode:
|
||||
block_info::decode_info *di;
|
||||
const instr_info_t *ii;
|
||||
uint32 dpc = pc() - 4;
|
||||
uint32 dpc;
|
||||
di = bi->di = decode_cache_p;
|
||||
dpc = pc() - 4;
|
||||
do {
|
||||
uint32 opcode = vm_read_memory_4(dpc += 4);
|
||||
ii = decode(opcode);
|
||||
@ -551,6 +562,7 @@ void powerpc_cpu::execute(uint32 entry)
|
||||
#endif
|
||||
|
||||
// Execute all cached blocks
|
||||
pdi_execute:
|
||||
for (;;) {
|
||||
const int r = bi->size % 4;
|
||||
di = bi->di + r;
|
||||
@ -647,6 +659,7 @@ void powerpc_cpu::kill_decode_cache()
|
||||
|
||||
void powerpc_cpu::invalidate_cache()
|
||||
{
|
||||
D(bug("Invalidate all cache blocks\n"));
|
||||
#if PPC_DECODE_CACHE || PPC_ENABLE_JIT
|
||||
block_cache.clear();
|
||||
block_cache.initialize();
|
||||
@ -662,13 +675,19 @@ void powerpc_cpu::invalidate_cache()
|
||||
|
||||
inline void powerpc_block_info::invalidate()
|
||||
{
|
||||
#if PPC_DECODE_CACHE
|
||||
// Don't do anything if this is a predecoded block
|
||||
if (di)
|
||||
return;
|
||||
#endif
|
||||
#if DYNGEN_DIRECT_BLOCK_CHAINING
|
||||
for (int i = 0; i < 2; i++) {
|
||||
uint32 tpc = jmp_pc[i];
|
||||
for (int i = 0; i < MAX_TARGETS; i++) {
|
||||
link_info * const tli = &li[i];
|
||||
uint32 tpc = tli->jmp_pc;
|
||||
// For any jump within page boundaries, reset the jump address
|
||||
// to the target block resolver (trampoline)
|
||||
if (tpc != INVALID_PC && ((tpc ^ pc) >> 12) == 0)
|
||||
dg_set_jmp_target(jmp_addr[i], jmp_resolve_addr[i]);
|
||||
dg_set_jmp_target(tli->jmp_addr, tli->jmp_resolve_addr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -682,6 +701,7 @@ void powerpc_cpu::invalidate_cache_range(uintptr start, uintptr end)
|
||||
// Invalidate on page boundaries
|
||||
start &= -4096;
|
||||
end = (end + 4095) & -4096;
|
||||
D(bug(" at page boundaries [%08x - %08x]\n", start, end));
|
||||
}
|
||||
#endif
|
||||
block_cache.clear_range(start, end);
|
||||
|
@ -138,12 +138,6 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
||||
block_info *bi = block_cache.new_blockinfo();
|
||||
bi->init(entry_point);
|
||||
bi->entry_point = dg.gen_start();
|
||||
#if DYNGEN_DIRECT_BLOCK_CHAINING
|
||||
for (int i = 0; i < 2; i++) {
|
||||
dg.jmp_addr[i] = NULL;
|
||||
bi->jmp_pc[i] = block_info::INVALID_PC;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Direct block chaining support variables
|
||||
bool use_direct_block_chaining = false;
|
||||
@ -484,10 +478,10 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
||||
// Use direct block chaining for in-page jumps or jumps to ROM area
|
||||
if (direct_chaining_possible(bi->pc, tpc)) {
|
||||
use_direct_block_chaining = true;
|
||||
bi->jmp_pc[0] = tpc;
|
||||
bi->li[0].jmp_pc = tpc;
|
||||
// Make sure it's a conditional branch
|
||||
if (BO_CONDITIONAL_BRANCH(bo) || BO_DECREMENT_CTR(bo))
|
||||
bi->jmp_pc[1] = npc;
|
||||
bi->li[1].jmp_pc = npc;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -547,7 +541,7 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
||||
// Use direct block chaining, addresses will be resolved at execution
|
||||
if (direct_chaining_possible(bi->pc, tpc)) {
|
||||
use_direct_block_chaining = true;
|
||||
bi->jmp_pc[0] = tpc;
|
||||
bi->li[0].jmp_pc = tpc;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1507,7 +1501,6 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
||||
}
|
||||
dg.gen_exec_return();
|
||||
}
|
||||
dg.gen_end();
|
||||
bi->end_pc = dpc;
|
||||
if (dpc < min_pc)
|
||||
min_pc = dpc;
|
||||
@ -1524,22 +1517,22 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
||||
if (use_direct_block_chaining) {
|
||||
typedef void *(*func_t)(dyngen_cpu_base);
|
||||
func_t func = (func_t)nv_mem_fun(&powerpc_cpu::compile_chain_block).ptr();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (bi->jmp_pc[i] != block_info::INVALID_PC) {
|
||||
uint8 *p = dg.gen_start();
|
||||
for (int i = 0; i < block_info::MAX_TARGETS; i++) {
|
||||
if (bi->li[i].jmp_pc != block_info::INVALID_PC) {
|
||||
uint8 *p = dg.gen_align(16);
|
||||
dg.gen_mov_ad_T0_im(((uintptr)bi) | i);
|
||||
dg.gen_invoke_CPU_T0_ret_A0(func);
|
||||
dg.gen_jmp_A0();
|
||||
dg.gen_end();
|
||||
assert(dg.jmp_addr[i] != NULL);
|
||||
bi->jmp_addr[i] = dg.jmp_addr[i];
|
||||
bi->jmp_resolve_addr[i] = p;
|
||||
dg_set_jmp_target(bi->jmp_addr[i], bi->jmp_resolve_addr[i]);
|
||||
bi->li[i].jmp_addr = dg.jmp_addr[i];
|
||||
bi->li[i].jmp_resolve_addr = p;
|
||||
dg_set_jmp_target(bi->li[i].jmp_addr, bi->li[i].jmp_resolve_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
dg.gen_end();
|
||||
block_cache.add_to_cl_list(bi);
|
||||
if (is_read_only_memory(bi->pc))
|
||||
block_cache.add_to_dormant_list(bi);
|
||||
|
Loading…
x
Reference in New Issue
Block a user