void passe2(precomp_instr *dest, int start, int end, precomp_block *block) { unsigned int i, real_code_length, addr_dest; build_wrappers(dest, start, end, block); real_code_length = code_length; for (i=0; i<jumps_number; i++) { code_length = jumps_table[i].pc_addr; if (dest[(jumps_table[i].mi_addr - dest[0].addr)/4].reg_cache_infos.need_map) { addr_dest = (unsigned int)dest[(jumps_table[i].mi_addr - dest[0].addr)/4].reg_cache_infos.jump_wrapper; put32(addr_dest-((unsigned int)block->code+code_length)-4); } else { addr_dest = dest[(jumps_table[i].mi_addr - dest[0].addr)/4].local_addr; put32(addr_dest-code_length-4); } } code_length = real_code_length; }
void passe2(struct precomp_instr *dest, int start, int end, struct precomp_block *block) { unsigned int i; build_wrappers(dest, start, end, block); /* First, fix up all the jumps. This involves a table lookup to find the offset into the block of x86_64 code for * for start of a recompiled r4300i instruction corresponding to the given jump destination address in the N64 * address space. Next, the relative offset between this destination and the location of the jump instruction is * computed and stored in memory, so that the jump will branch to the right place in the recompiled code. */ for (i = 0; i < g_dev.r4300.jumps_number; i++) { struct precomp_instr *jump_instr = dest + ((g_dev.r4300.jumps_table[i].mi_addr - dest[0].addr) / 4); unsigned int jmp_offset_loc = g_dev.r4300.jumps_table[i].pc_addr; unsigned char *addr_dest = NULL; /* calculate the destination address to jump to */ if (jump_instr->reg_cache_infos.need_map) { addr_dest = jump_instr->reg_cache_infos.jump_wrapper; } else { addr_dest = block->code + jump_instr->local_addr; } /* write either a 32-bit IP-relative offset or a 64-bit absolute address */ if (g_dev.r4300.jumps_table[i].absolute64) { *((unsigned long long *) (block->code + jmp_offset_loc)) = (unsigned long long) addr_dest; } else { long jump_rel_offset = (long) (addr_dest - (block->code + jmp_offset_loc + 4)); *((int *) (block->code + jmp_offset_loc)) = (int) jump_rel_offset; if (jump_rel_offset >= 0x7fffffffLL || jump_rel_offset < -0x80000000LL) { DebugMessage(M64MSG_ERROR, "assembler pass2 error: offset too big for relative jump from %p to %p", (block->code + jmp_offset_loc + 4), addr_dest); OSAL_BREAKPOINT_INTERRUPT; } } } /* Next, fix up all of the RIP-relative memory accesses. This is unique to the x86_64 architecture, because * the 32-bit absolute displacement addressing mode is not available (and there's no 64-bit absolute displacement * mode either). */ for (i = 0; i < g_dev.r4300.riprel_number; i++) { unsigned char *rel_offset_ptr = block->code + g_dev.r4300.riprel_table[i].pc_addr; long rip_rel_offset = (long) (g_dev.r4300.riprel_table[i].global_dst - (rel_offset_ptr + 4 + g_dev.r4300.riprel_table[i].extra_bytes)); if (rip_rel_offset >= 0x7fffffffLL || rip_rel_offset < -0x80000000LL) { DebugMessage(M64MSG_ERROR, "assembler pass2 error: offset too big between mem target: %p and code position: %p", g_dev.r4300.riprel_table[i].global_dst, rel_offset_ptr); OSAL_BREAKPOINT_INTERRUPT; } *((int *) rel_offset_ptr) = (int) rip_rel_offset; } }