Beispiel #1
0
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;
}
Beispiel #2
0
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;
  }

}