mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-09-30 13:56:16 +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 ("sync" : : : "memory");
|
||||||
asm volatile ("isync" : : : "memory");
|
asm volatile ("isync" : : : "memory");
|
||||||
#endif
|
#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
|
#endif
|
||||||
|
|
||||||
|
@ -787,6 +787,18 @@ void gen_code(const char *name, const char *demangled_name,
|
|||||||
if (rel->r_offset >= start_offset &&
|
if (rel->r_offset >= start_offset &&
|
||||||
rel->r_offset < start_offset + copy_size) {
|
rel->r_offset < start_offset + copy_size) {
|
||||||
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
|
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)) {
|
if (strstart(sym_name, "__op_param", &p)) {
|
||||||
snprintf(name, sizeof(name), "param%s", p);
|
snprintf(name, sizeof(name), "param%s", p);
|
||||||
} else if (strstart(sym_name, "__op_cpuparam", &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 &&
|
if (rel->r_offset >= start_offset &&
|
||||||
rel->r_offset < start_offset + copy_size) {
|
rel->r_offset < start_offset + copy_size) {
|
||||||
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
|
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))
|
if (strstart(sym_name, "__op_param", &p))
|
||||||
snprintf(name, sizeof(name), "param%s", p);
|
snprintf(name, sizeof(name), "param%s", p);
|
||||||
else if (strstart(sym_name, ".LC", NULL))
|
else if (strstart(sym_name, ".LC", NULL))
|
||||||
|
@ -44,7 +44,8 @@ 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_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
|
||||||
#endif
|
#endif
|
||||||
uintptr min_pc, max_pc;
|
uintptr min_pc, max_pc;
|
||||||
|
@ -440,7 +440,7 @@ 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 = pc();
|
const uint32 tpc = sbi->jmp_pc[n];
|
||||||
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);
|
||||||
|
@ -684,6 +684,17 @@ DEFINE_OP(branch_if_not_T0);
|
|||||||
#undef DEFINE_OP
|
#undef DEFINE_OP
|
||||||
#undef DEFINE_OP_CTR
|
#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 >
|
template< int bo, bool chain >
|
||||||
static inline void do_execute_branch_bo(uint32 tpc, uint32 npc)
|
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)) {
|
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))
|
if (BO_BRANCH_IF_CTR_ZERO(bo))
|
||||||
ctr_ok = ctr == 0;
|
ctr_ok = T1 == 0;
|
||||||
else
|
else
|
||||||
ctr_ok = ctr != 0;
|
ctr_ok = T1 != 0;
|
||||||
powerpc_dyngen_helper::set_ctr(ctr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctr_ok && cond_ok) {
|
|
||||||
powerpc_dyngen_helper::set_pc(tpc);
|
|
||||||
#ifdef DYNGEN_FAST_DISPATCH
|
#ifdef DYNGEN_FAST_DISPATCH
|
||||||
if (chain && powerpc_dyngen_helper::spcflags().empty())
|
if (chain) {
|
||||||
DYNGEN_FAST_DISPATCH(__op_jmp0);
|
T1 = powerpc_dyngen_helper::spcflags().get();
|
||||||
#endif
|
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 {
|
else
|
||||||
powerpc_dyngen_helper::set_pc(npc);
|
|
||||||
#ifdef DYNGEN_FAST_DISPATCH
|
|
||||||
if (chain && powerpc_dyngen_helper::spcflags().empty())
|
|
||||||
DYNGEN_FAST_DISPATCH(__op_jmp1);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
|
T0 = (ctr_ok && cond_ok) ? tpc : npc;
|
||||||
|
powerpc_dyngen_helper::set_pc(T0);
|
||||||
dyngen_barrier();
|
dyngen_barrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,8 +448,11 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
|||||||
#if DYNGEN_DIRECT_BLOCK_CHAINING
|
#if DYNGEN_DIRECT_BLOCK_CHAINING
|
||||||
// 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
|
||||||
const uint32 npc = dpc + 4;
|
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;
|
use_direct_block_chaining = true;
|
||||||
|
bi->jmp_pc[0] = tpc;
|
||||||
|
bi->jmp_pc[1] = npc;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
dg.gen_mov_32_A0_im(tpc);
|
dg.gen_mov_32_A0_im(tpc);
|
||||||
goto do_branch;
|
goto do_branch;
|
||||||
|
@ -52,6 +52,9 @@ public:
|
|||||||
void init(uint32 v)
|
void init(uint32 v)
|
||||||
{ mask = v; }
|
{ mask = v; }
|
||||||
|
|
||||||
|
uint32 get() const
|
||||||
|
{ return mask; }
|
||||||
|
|
||||||
void set(uint32 v)
|
void set(uint32 v)
|
||||||
{ mask |= v; }
|
{ mask |= v; }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user