mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-11-07 07:06:46 +00:00
Direct block chaining on x86 and amd64 too. Optimize do_execute_branch_bo<>
No need to update Program Counter if we have direct linked blocks. TODO: remove obsolete PC-related generators
This commit is contained in:
parent
15a0779328
commit
81ae2fee40
@ -233,6 +233,11 @@ basic_dyngen::set_jmp_target(uint8 *jmp_addr, uint8 *addr)
|
||||
asm volatile ("sync" : : : "memory");
|
||||
asm volatile ("isync" : : : "memory");
|
||||
#endif
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
// patch the branch destination
|
||||
*(uint32 *)jmp_addr = addr - (jmp_addr + 4);
|
||||
// no need to flush icache explicitly
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -787,6 +787,18 @@ void gen_code(const char *name, const char *demangled_name,
|
||||
if (rel->r_offset >= start_offset &&
|
||||
rel->r_offset < start_offset + copy_size) {
|
||||
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
|
||||
if (strstart(sym_name, "__op_jmp", &p)) {
|
||||
int n;
|
||||
n = strtol(p, NULL, 10);
|
||||
/* __op_jmp relocations are done at
|
||||
runtime to do translated block
|
||||
chaining: the offset of the instruction
|
||||
needs to be stored */
|
||||
fprintf(outfile, " jmp_addr[%d] = code_ptr() + %d;\n",
|
||||
n, rel->r_offset - start_offset);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strstart(sym_name, "__op_param", &p)) {
|
||||
snprintf(name, sizeof(name), "param%s", p);
|
||||
} else if (strstart(sym_name, "__op_cpuparam", &p)) {
|
||||
@ -820,6 +832,18 @@ void gen_code(const char *name, const char *demangled_name,
|
||||
if (rel->r_offset >= start_offset &&
|
||||
rel->r_offset < start_offset + copy_size) {
|
||||
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
|
||||
if (strstart(sym_name, "__op_jmp", &p)) {
|
||||
int n;
|
||||
n = strtol(p, NULL, 10);
|
||||
/* __op_jmp relocations are done at
|
||||
runtime to do translated block
|
||||
chaining: the offset of the instruction
|
||||
needs to be stored */
|
||||
fprintf(outfile, " jmp_addr[%d] = code_ptr() + %d;\n",
|
||||
n, rel->r_offset - start_offset);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strstart(sym_name, "__op_param", &p))
|
||||
snprintf(name, sizeof(name), "param%s", p);
|
||||
else if (strstart(sym_name, ".LC", NULL))
|
||||
|
@ -44,7 +44,8 @@ struct powerpc_block_info
|
||||
#if PPC_ENABLE_JIT
|
||||
uint8 * entry_point;
|
||||
#if DYNGEN_DIRECT_BLOCK_CHAINING
|
||||
uint8 * jmp_addr[2]; // Jump addresses for direct chaining
|
||||
uint8 * jmp_addr[2]; // Address of target native branch offset to patch
|
||||
uint32 jmp_pc[2]; // Target jump addresses in emulated address space
|
||||
#endif
|
||||
#endif
|
||||
uintptr min_pc, max_pc;
|
||||
|
@ -440,7 +440,7 @@ void *powerpc_cpu::compile_chain_block(block_info *sbi)
|
||||
sbi = (block_info *)(((uintptr)sbi) & ~3L);
|
||||
const uint32 bpc = sbi->pc;
|
||||
|
||||
const uint32 tpc = pc();
|
||||
const uint32 tpc = sbi->jmp_pc[n];
|
||||
block_info *tbi = block_cache.find(tpc);
|
||||
if (tbi == NULL)
|
||||
tbi = compile_block(tpc);
|
||||
|
@ -684,6 +684,17 @@ DEFINE_OP(branch_if_not_T0);
|
||||
#undef DEFINE_OP
|
||||
#undef DEFINE_OP_CTR
|
||||
|
||||
#ifdef DYNGEN_FAST_DISPATCH
|
||||
#if defined(__x86_64__)
|
||||
#define FAST_COMPARE_SPECFLAGS_DISPATCH(SPCFLAGS, TARGET) \
|
||||
asm volatile ("test %0,%0 ; jz " #TARGET : "+r" (SPCFLAGS))
|
||||
#endif
|
||||
#ifndef FAST_COMPARE_SPECFLAGS_DISPATCH
|
||||
#define FAST_COMPARE_SPECFLAGS_DISPATCH(SPCFLAGS, TARGET) \
|
||||
if (SPCFLAGS == 0) DYNGEN_FAST_DISPATCH(TARGET)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template< int bo, bool chain >
|
||||
static inline void do_execute_branch_bo(uint32 tpc, uint32 npc)
|
||||
{
|
||||
@ -698,29 +709,31 @@ static inline void do_execute_branch_bo(uint32 tpc, uint32 npc)
|
||||
}
|
||||
|
||||
if (BO_DECREMENT_CTR(bo)) {
|
||||
uint32 ctr = powerpc_dyngen_helper::get_ctr() - 1;
|
||||
T1 = powerpc_dyngen_helper::get_ctr() - 1;
|
||||
powerpc_dyngen_helper::set_ctr(T1);
|
||||
if (BO_BRANCH_IF_CTR_ZERO(bo))
|
||||
ctr_ok = ctr == 0;
|
||||
ctr_ok = T1 == 0;
|
||||
else
|
||||
ctr_ok = ctr != 0;
|
||||
powerpc_dyngen_helper::set_ctr(ctr);
|
||||
ctr_ok = T1 != 0;
|
||||
}
|
||||
|
||||
if (ctr_ok && cond_ok) {
|
||||
powerpc_dyngen_helper::set_pc(tpc);
|
||||
#ifdef DYNGEN_FAST_DISPATCH
|
||||
if (chain && powerpc_dyngen_helper::spcflags().empty())
|
||||
DYNGEN_FAST_DISPATCH(__op_jmp0);
|
||||
#endif
|
||||
if (chain) {
|
||||
T1 = powerpc_dyngen_helper::spcflags().get();
|
||||
if (ctr_ok && cond_ok) {
|
||||
FAST_COMPARE_SPECFLAGS_DISPATCH(T1, __op_jmp0);
|
||||
T0 = tpc;
|
||||
}
|
||||
else {
|
||||
FAST_COMPARE_SPECFLAGS_DISPATCH(T1, __op_jmp1);
|
||||
T0 = npc;
|
||||
}
|
||||
}
|
||||
else {
|
||||
powerpc_dyngen_helper::set_pc(npc);
|
||||
#ifdef DYNGEN_FAST_DISPATCH
|
||||
if (chain && powerpc_dyngen_helper::spcflags().empty())
|
||||
DYNGEN_FAST_DISPATCH(__op_jmp1);
|
||||
else
|
||||
#endif
|
||||
}
|
||||
|
||||
T0 = (ctr_ok && cond_ok) ? tpc : npc;
|
||||
powerpc_dyngen_helper::set_pc(T0);
|
||||
dyngen_barrier();
|
||||
}
|
||||
|
||||
|
@ -448,8 +448,11 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
||||
#if DYNGEN_DIRECT_BLOCK_CHAINING
|
||||
// Use direct block chaining for in-page jumps or jumps to ROM area
|
||||
const uint32 npc = dpc + 4;
|
||||
if (((tpc & -4096) == (npc & -4096)) || is_read_only_memory(tpc))
|
||||
if (((tpc & -4096) == (npc & -4096)) || is_read_only_memory(tpc)) {
|
||||
use_direct_block_chaining = true;
|
||||
bi->jmp_pc[0] = tpc;
|
||||
bi->jmp_pc[1] = npc;
|
||||
}
|
||||
#endif
|
||||
dg.gen_mov_32_A0_im(tpc);
|
||||
goto do_branch;
|
||||
|
@ -52,6 +52,9 @@ public:
|
||||
void init(uint32 v)
|
||||
{ mask = v; }
|
||||
|
||||
uint32 get() const
|
||||
{ return mask; }
|
||||
|
||||
void set(uint32 v)
|
||||
{ mask |= v; }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user