{
if (rs != 0)
emit_mov(rs, 0);
+ emit_readptr(&hash_table_ptr, 1);
emit_far_call(ndrc_get_addr_ht);
emit_jmpreg(0);
}
enum blockExecCaller block_caller)
{
void *drc_local = (char *)regs - LO_psxRegs;
+ struct ht_entry *hash_table =
+ *(void **)((char *)drc_local + LO_hash_table_ptr);
void *target;
if (likely(!ndrc_g.thread.busy)) {
ndrc_g.thread.addr = 0;
- target = ndrc_get_addr_ht_param(regs->pc, ndrc_cm_no_compile);
+ target = ndrc_get_addr_ht_param(hash_table, regs->pc,
+ ndrc_cm_no_compile);
if (target) {
clear_local_cache();
new_dyna_start_at(drc_local, target);
static void ari64_compile_thread(void *unused)
{
+ struct ht_entry *hash_table =
+ *(void **)((char *)dynarec_local + LO_hash_table_ptr);
void *target;
u32 addr;
if (!ndrc_g.thread.busy || !addr || ndrc_g.thread.exit)
continue;
- target = ndrc_get_addr_ht_param(addr, ndrc_cm_compile_in_thread);
+ target = ndrc_get_addr_ht_param(hash_table, addr,
+ ndrc_cm_compile_in_thread);
//printf("c %08x -> %p\n", addr, target);
ndrc_g.thread.busy = 0;
}
static int ari64_init()
{
- static u32 scratch_buf[8*8*2] __attribute__((aligned(64)));
size_t i;
new_dynarec_init();
#endif
psxH_ptr = psxH;
zeromem_ptr = zero_mem;
- scratch_buf_ptr = scratch_buf;
ari64_thread_init();
#else // if DRC_DISABLE
struct ndrc_globals ndrc_g; // dummy
-void *psxH_ptr;
-void *zeromem_ptr;
-u32 zero_mem[0x1000/4];
-void *mem_rtab;
-void *scratch_buf_ptr;
void new_dynarec_init() {}
void new_dyna_start(void *context) {}
void new_dynarec_cleanup() {}
DRC_VAR(psxH_ptr, 4)
DRC_VAR(zeromem_ptr, 4)
DRC_VAR(invc_ptr, 4)
-DRC_VAR(scratch_buf_ptr, 4)
+DRC_VAR(hash_table_ptr, 4)
DRC_VAR(ram_offset, 4)
DRC_VAR(mini_ht, 256)
mov r5, r1
lsl r6, r6, #8
/* must not compile - that might expire the caller block */
- mov r1, #0 /* ndrc_compile_mode */
+ ldr r0, [fp, #LO_hash_table_ptr]
+ mov r1, r4
+ mov r2, #0 /* ndrc_compile_mode=ndrc_cm_no_compile */
bl ndrc_get_addr_ht_param
movs r8, r0
#else
/* XXX: should be able to do better than this... */
#endif
+ ldr r1, [fp, #LO_hash_table_ptr]
bl ndrc_get_addr_ht
mov pc, r0
.size dyna_linker, .-dyna_linker
add r0, r7, #0
.size jump_vaddr_r7, .-jump_vaddr_r7
FUNCTION(jump_vaddr_r0):
+ ldr r1, [fp, #LO_hash_table_ptr]
bl ndrc_get_addr_ht
mov pc, r0
.size jump_vaddr_r0, .-jump_vaddr_r0
ldmfdne sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
cmp r0, r9
moveq pc, lr
+ ldr r1, [fp, #LO_hash_table_ptr]
bl ndrc_get_addr_ht
mov pc, r0
.size cc_interrupt, .-cc_interrupt
str r1, [fp, #LO_last_count]
sub r10, r10, r1
bne new_dyna_leave
+ ldr r1, [fp, #LO_hash_table_ptr]
bl ndrc_get_addr_ht
mov pc, r0
.size jump_to_new_pc, .-jump_to_new_pc
stmfd sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
mov fp, r0 /* dynarec_local */
ldr r0, [fp, #LO_pcaddr]
+ ldr r1, [fp, #LO_hash_table_ptr]
bl ndrc_get_addr_ht
new_dyna_start_at_e:
ldr r1, [fp, #LO_next_interupt]
DRC_VAR(psxH_ptr, 8)
DRC_VAR(invc_ptr, 8)
DRC_VAR(zeromem_ptr, 8)
-DRC_VAR(scratch_buf_ptr, 8)
+DRC_VAR(hash_table_ptr, 8)
DRC_VAR(ram_offset, 8)
DRC_VAR(mini_ht, 256)
FUNCTION(dyna_linker):
/* r0 = virtual target address */
/* r1 = instruction to patch */
+ ldr x1, [rFP, #LO_hash_table_ptr]
bl ndrc_get_addr_ht
br x0
ESIZE(dyna_linker, .-dyna_linker)
bne 2f
ret
2:
+ ldr x1, [rFP, #LO_hash_table_ptr]
bl ndrc_get_addr_ht
br x0
ESIZE(cc_interrupt, .-cc_interrupt)
sub rCC, rCC, w1
str w1, [rFP, #LO_last_count]
cbnz w2, new_dyna_leave
+ ldr x1, [rFP, #LO_hash_table_ptr]
bl ndrc_get_addr_ht
br x0
ESIZE(jump_to_new_pc, .-jump_to_new_pc)
stp x29, x30, [sp, #-SSP_ALL]!
mov rFP, x0
ldr w0, [rFP, #LO_pcaddr]
+ ldr x1, [rFP, #LO_hash_table_ptr]
bl ndrc_get_addr_ht
- mov x1, x0
+ mov x1, x0
new_dyna_start_at_e:
ldr w3, [rFP, #LO_next_interupt]
ldr w2, [rFP, #LO_cycle]
#define LO_psxH_ptr (LO_mem_wtab + PTRSZ)
#define LO_zeromem_ptr (LO_psxH_ptr + PTRSZ)
#define LO_invc_ptr (LO_zeromem_ptr + PTRSZ)
-#define LO_scratch_buf_ptr (LO_invc_ptr + PTRSZ)
-#define LO_saved_lr (LO_scratch_buf_ptr + PTRSZ)
+#define LO_hash_table_ptr (LO_invc_ptr + PTRSZ)
+#define LO_saved_lr (LO_hash_table_ptr + PTRSZ)
#define LO_ram_offset (LO_saved_lr + PTRSZ)
#define LO_mini_ht (LO_ram_offset + PTRSZ)
#define LO_dynarec_local_size (LO_mini_ht + PTRSZ*32*2)
extern int reg_cop2d[], reg_cop2c[];
+extern void *hash_table_ptr;
extern uintptr_t ram_offset;
extern uintptr_t mini_ht[32][2];
void call_gteStall();
void new_dyna_leave();
-void *ndrc_get_addr_ht(u_int vaddr);
+void *ndrc_get_addr_ht(u_int vaddr, struct ht_entry *ht);
void ndrc_add_jump_out(u_int vaddr, void *src);
void ndrc_write_invalidate_one(u_int addr);
static void ndrc_write_invalidate_many(u_int addr, u_int end);
return page;
}
+static struct ht_entry *hash_table_get_p(struct ht_entry *ht, u_int vaddr)
+{
+ return &ht[((vaddr >> 16) ^ vaddr) & 0xFFFF];
+}
+
static struct ht_entry *hash_table_get(u_int vaddr)
{
- return &hash_table[((vaddr>>16)^vaddr)&0xFFFF];
+ return hash_table_get_p(hash_table, vaddr);
}
#define HASH_TABLE_BAD 0xbac
// Get address from virtual address
// This is called from the recompiled JR/JALR instructions
-static void noinline *get_addr(const u_int vaddr, enum ndrc_compile_mode compile_mode)
+static void noinline *get_addr(struct ht_entry *ht, const u_int vaddr,
+ enum ndrc_compile_mode compile_mode)
{
u_int start_page = get_page_prev(vaddr);
u_int i, page, end_page = get_page(vaddr);
int r = new_recompile_block(vaddr);
if (likely(r == 0))
- return ndrc_get_addr_ht(vaddr);
+ return ndrc_get_addr_ht(vaddr, ht);
if (compile_mode == ndrc_cm_compile_live)
- return ndrc_get_addr_ht(generate_exception(vaddr));
+ return ndrc_get_addr_ht(generate_exception(vaddr), ht);
return NULL;
}
// Look up address in hash table first
-void *ndrc_get_addr_ht_param(unsigned int vaddr, enum ndrc_compile_mode compile_mode)
+void *ndrc_get_addr_ht_param(struct ht_entry *ht, unsigned int vaddr,
+ enum ndrc_compile_mode compile_mode)
{
//check_for_block_changes(vaddr, vaddr + MAXBLOCK);
- const struct ht_entry *ht_bin = hash_table_get(vaddr);
+ const struct ht_entry *ht_bin = hash_table_get_p(ht, vaddr);
u_int vaddr_a = vaddr & ~3;
stat_inc(stat_ht_lookups);
if (ht_bin->vaddr[0] == vaddr_a) return ht_bin->tcaddr[0];
if (ht_bin->vaddr[1] == vaddr_a) return ht_bin->tcaddr[1];
- return get_addr(vaddr, compile_mode);
+ return get_addr(ht, vaddr, compile_mode);
}
// "usual" addr lookup for indirect branches, etc
// to be used by currently running code only
-void *ndrc_get_addr_ht(u_int vaddr)
+void *ndrc_get_addr_ht(u_int vaddr, struct ht_entry *ht)
{
- return ndrc_get_addr_ht_param(vaddr, ndrc_cm_compile_live);
+ return ndrc_get_addr_ht_param(ht, vaddr, ndrc_cm_compile_live);
}
static void clear_all_regs(signed char regmap[])
ofscase(psxH_ptr);
ofscase(invc_ptr);
ofscase(ram_offset);
+ ofscase(hash_table_ptr);
#undef ofscase
}
buf[0] = 0;
if(i_regs->regmap==regs[i].regmap) {
load_all_consts(regs[i].regmap_entry,regs[i].wasdirty,i);
wb_dirtys(regs[i].regmap_entry,regs[i].wasdirty);
- emit_movimm(start+i*4+4,0);
- emit_writeword(0,&psxRegs.pc);
- emit_addimm(HOST_CCREG,2,HOST_CCREG);
+ emit_readptr(&hash_table_ptr, 1);
+ emit_movimm(start+i*4+4, 0);
+ emit_writeword(0, &psxRegs.pc);
+ emit_addimm(HOST_CCREG, 2, HOST_CCREG);
emit_far_call(ndrc_get_addr_ht);
emit_jmpreg(0);
}
emit_cmp(HOST_TEMPREG, 0);
void *jaddr = out;
emit_jeq(0);
+ emit_readptr(&hash_table_ptr, 1);
emit_far_call(ndrc_get_addr_ht);
emit_jmpreg(0);
set_jump_target(jaddr, out);
#endif
out = ndrc->translation_cache;
new_dynarec_clear_full();
+ hash_table_ptr = hash_table;
#ifdef HOST_IMM8
// Copy this into local area so we don't have to put it in every literal pool
invc_ptr=invalid_code;
psxRegs.GPR.r[i] = 0x1f800000;
}
- ndrc_get_addr_ht_param(sblocks[b].addr, ndrc_cm_compile_offline);
+ ndrc_get_addr_ht_param(hash_table, sblocks[b].addr, ndrc_cm_compile_offline);
for (f = sblocks[b].regflags, i = 0; f; f >>= 1, i++) {
if (f & 1)
emit_addimm(0, 0x18, 0);
emit_adds_ptr(1, 1, 1);
emit_ldr_dualindexed(1, 0, 0);
+ emit_readptr(&hash_table_ptr, 1);
emit_writeword(0, &psxRegs.GPR.r[26]); // lw k0, 0x18(sp)
emit_far_call(ndrc_get_addr_ht);
emit_jmpreg(0); // jr k0
void new_dyna_start(void *context);
void new_dyna_start_at(void *context, void *compiled_code);
+struct ht_entry;
enum ndrc_compile_mode {
ndrc_cm_no_compile = 0,
ndrc_cm_compile_live, // from executing code, vaddr is the current pc
ndrc_cm_compile_offline,
ndrc_cm_compile_in_thread,
};
-void *ndrc_get_addr_ht_param(unsigned int vaddr, enum ndrc_compile_mode compile_mode);
+void *ndrc_get_addr_ht_param(struct ht_entry *ht, unsigned int vaddr,
+ enum ndrc_compile_mode compile_mode);
extern unsigned int ndrc_smrv_regs[32];