- host_arg2reg(arg0, 0);
- host_arg2reg(arg1, 1);
- host_arg2reg(arg2, 2);
-
-#if (DRC_DEBUG & 4)
- emith_move_r_r(arg1, CONTEXT_REG);
- emith_move_r_r(arg2, rcache_get_reg(SHR_SR, RC_GR_READ));
- emith_call(sh2_drc_announce_entry);
- rcache_invalidate();
-#endif
- emith_tst_r_r(arg0, arg0);
- EMITH_SJMP_START(DCOND_EQ);
- emith_jump_reg_c(DCOND_NE, arg0);
- EMITH_SJMP_END(DCOND_EQ);
-}
-
-static void REGPARM(3) *lookup_block(u32 pc, int is_slave, int *tcache_id)
-{
- block_desc *bd = NULL;
- void *block = NULL;
- *tcache_id = 0;
-
- // we have full block id tables for data_array and RAM
- // BIOS goes to data_array table too
- if ((pc & 0xe0000000) == 0xc0000000 || (pc & ~0xfff) == 0) {
- int blkid = Pico32xMem->drcblk_da[is_slave][(pc & 0xfff) >> SH2_DRCBLK_DA_SHIFT];
- *tcache_id = 1 + is_slave;
- if (blkid & 1) {
- bd = &block_tables[*tcache_id][blkid >> 1];
- block = bd->tcache_ptr;
- }
- }
- // RAM
- else if ((pc & 0xc6000000) == 0x06000000) {
- int blkid = Pico32xMem->drcblk_ram[(pc & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT];
- if (blkid & 1) {
- bd = &block_tables[0][blkid >> 1];
- block = bd->tcache_ptr;
- }
- }
- // ROM
- else if ((pc & 0xc6000000) == 0x02000000) {
- bd = HASH_FUNC(hash_table, pc);
-
- if (bd != NULL) {
- if (bd->addr == pc)
- block = bd->tcache_ptr;
- else
- block = dr_find_block(bd, pc);
- }
- }
-
-#if (DRC_DEBUG & 1)
- if (bd != NULL)
- bd->refcount++;
-#endif
- return block;
-}
-
-void dr_link_blocks(void *target, u32 pc, int tcache_id)
-{
- block_link *bl = block_links[tcache_id];
- int cnt = block_link_counts[tcache_id];
- int i;
-
- for (i = 0; i < cnt; i++) {
- if (bl[i].target_pc == pc) {
- dbg(1, "- link from %p", bl[i].jump);
- emith_jump_patch(bl[i].jump, target);
- // XXX: sync ARM caches (old jump should be fine)?
- }
- }
-}
-
-void *dr_prepare_ext_branch(u32 pc, SH2 *sh2, int tcache_id)
-{
- int target_tcache_id;
- void *target;
- int ret;
-
- target = lookup_block(pc, sh2->is_slave, &target_tcache_id);
- if (target_tcache_id == tcache_id) {
- // allow linking blocks only from local cache
- ret = dr_add_block_link(pc, tcache_ptr, tcache_id);
- if (ret < 0)
- return NULL;
- }
- if (target == NULL || target_tcache_id != tcache_id)
- target = sh2_drc_dispatcher;