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