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:
gbeauche 2004-05-12 10:44:04 +00:00
parent 15a0779328
commit 81ae2fee40
7 changed files with 67 additions and 18 deletions

View File

@ -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

View File

@ -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))

View File

@ -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;

View File

@ -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);

View File

@ -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();
}

View File

@ -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;

View File

@ -52,6 +52,9 @@ public:
void init(uint32 v)
{ mask = v; }
uint32 get() const
{ return mask; }
void set(uint32 v)
{ mask |= v; }