Example #1
0
void genxor(void)
{
#ifdef INTERPRET_XOR
   gencallinterp((unsigned int)cached_interpreter_table.XOR, 0);
#else
   int rs1 = allocate_64_register1((unsigned int *)g_dev.r4300.recomp.dst->f.r.rs);
   int rs2 = allocate_64_register2((unsigned int *)g_dev.r4300.recomp.dst->f.r.rs);
   int rt1 = allocate_64_register1((unsigned int *)g_dev.r4300.recomp.dst->f.r.rt);
   int rt2 = allocate_64_register2((unsigned int *)g_dev.r4300.recomp.dst->f.r.rt);
   int rd1 = allocate_64_register1_w((unsigned int *)g_dev.r4300.recomp.dst->f.r.rd);
   int rd2 = allocate_64_register2_w((unsigned int *)g_dev.r4300.recomp.dst->f.r.rd);
   
   if (rt1 != rd1 && rs1 != rd1)
     {
    mov_reg32_reg32(rd1, rs1);
    mov_reg32_reg32(rd2, rs2);
    xor_reg32_reg32(rd1, rt1);
    xor_reg32_reg32(rd2, rt2);
     }
   else
     {
    int temp = lru_register();
    free_register(temp);
    mov_reg32_reg32(temp, rs1);
    xor_reg32_reg32(temp, rt1);
    mov_reg32_reg32(rd1, temp);
    mov_reg32_reg32(temp, rs2);
    xor_reg32_reg32(temp, rt2);
    mov_reg32_reg32(rd2, temp);
     }
#endif
}
Example #2
0
void gensllv(void)
{
#ifdef INTERPRET_SLLV
   gencallinterp((unsigned int)cached_interpreter_table.SLLV, 0);
#else
   int rt, rd;
   allocate_register_manually(ECX, (unsigned int *)g_dev.r4300.recomp.dst->f.r.rs);
   
   rt = allocate_register((unsigned int *)g_dev.r4300.recomp.dst->f.r.rt);
   rd = allocate_register_w((unsigned int *)g_dev.r4300.recomp.dst->f.r.rd);
   
   if (rd != ECX)
     {
    mov_reg32_reg32(rd, rt);
    shl_reg32_cl(rd);
     }
   else
     {
    int temp = lru_register();
    free_register(temp);
    mov_reg32_reg32(temp, rt);
    shl_reg32_cl(temp);
    mov_reg32_reg32(rd, temp);
     }
#endif
}
Example #3
0
void gendsrav()
{
#ifdef INTERPRET_DSRAV
   gencallinterp((unsigned long)DSRAV, 0);
#else
   int rt1, rt2, rd1, rd2;
   allocate_register_manually(ECX, (unsigned long *)dst->f.r.rs);
   
   rt1 = allocate_64_register1((unsigned long *)dst->f.r.rt);
   rt2 = allocate_64_register2((unsigned long *)dst->f.r.rt);
   rd1 = allocate_64_register1_w((unsigned long *)dst->f.r.rd);
   rd2 = allocate_64_register2_w((unsigned long *)dst->f.r.rd);
   
   if (rd1 != ECX && rd2 != ECX)
     {
	mov_reg32_reg32(rd1, rt1);
	mov_reg32_reg32(rd2, rt2);
	shrd_reg32_reg32_cl(rd1,rd2);
	sar_reg32_cl(rd2);
	test_reg32_imm32(ECX, 0x20);
	je_rj(5);
	mov_reg32_reg32(rd1, rd2); // 2
	sar_reg32_imm8(rd2, 31); // 3
     }
   else
     {
	int temp1, temp2;
	force_32(ECX);
	temp1 = lru_register();
	temp2 = lru_register_exc1(temp1);
	free_register(temp1);
	free_register(temp2);
	
	mov_reg32_reg32(temp1, rt1);
	mov_reg32_reg32(temp2, rt2);
	shrd_reg32_reg32_cl(temp1, temp2);
	sar_reg32_cl(temp2);
	test_reg32_imm32(ECX, 0x20);
	je_rj(5);
	mov_reg32_reg32(temp1, temp2); // 2
	sar_reg32_imm8(temp2, 31); // 3
	
	mov_reg32_reg32(rd1, temp1);
	mov_reg32_reg32(rd2, temp2);
     }
#endif
}
Example #4
0
void gendsrav(usf_state_t * state)
{
#ifdef INTERPRET_DSRAV
   gencallinterp(state, (unsigned int)state->current_instruction_table.DSRAV, 0);
#else
   int rt1, rt2, rd1, rd2;
   allocate_register_manually(state, ECX, (unsigned int *)state->dst->f.r.rs);
   
   rt1 = allocate_64_register1(state, (unsigned int *)state->dst->f.r.rt);
   rt2 = allocate_64_register2(state, (unsigned int *)state->dst->f.r.rt);
   rd1 = allocate_64_register1_w(state, (unsigned int *)state->dst->f.r.rd);
   rd2 = allocate_64_register2_w(state, (unsigned int *)state->dst->f.r.rd);
   
   if (rd1 != ECX && rd2 != ECX)
     {
    mov_reg32_reg32(state, rd1, rt1);
    mov_reg32_reg32(state, rd2, rt2);
    shrd_reg32_reg32_cl(state, rd1,rd2);
    sar_reg32_cl(state, rd2);
    test_reg32_imm32(state, ECX, 0x20);
    je_rj(state, 5);
    mov_reg32_reg32(state, rd1, rd2); // 2
    sar_reg32_imm8(state, rd2, 31); // 3
     }
   else
     {
    int temp1, temp2;
    force_32(state, ECX);
    temp1 = lru_register(state);
    temp2 = lru_register_exc1(state, temp1);
    free_register(state, temp1);
    free_register(state, temp2);
    
    mov_reg32_reg32(state, temp1, rt1);
    mov_reg32_reg32(state, temp2, rt2);
    shrd_reg32_reg32_cl(state, temp1, temp2);
    sar_reg32_cl(state, temp2);
    test_reg32_imm32(state, ECX, 0x20);
    je_rj(state, 5);
    mov_reg32_reg32(state, temp1, temp2); // 2
    sar_reg32_imm8(state, temp2, 31); // 3
    
    mov_reg32_reg32(state, rd1, temp1);
    mov_reg32_reg32(state, rd2, temp2);
     }
#endif
}
Example #5
0
void gendsrlv(void)
{
#ifdef INTERPRET_DSRLV
    gencallinterp((unsigned int)cached_interpreter_table.DSRLV, 0);
#else
    int rt1, rt2, rd1, rd2;
    allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);

    rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
    rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
    rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
    rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);

    if (rd1 != ECX && rd2 != ECX)
    {
        mov_reg32_reg32(rd1, rt1);
        mov_reg32_reg32(rd2, rt2);
        shrd_reg32_reg32_cl(rd1,rd2);
        shr_reg32_cl(rd2);
        test_reg32_imm32(ECX, 0x20);
        je_rj(4);
        mov_reg32_reg32(rd1, rd2); // 2
        xor_reg32_reg32(rd2, rd2); // 2
    }
    else
    {
        int temp1, temp2;
        force_32(ECX);
        temp1 = lru_register();
        temp2 = lru_register_exc1(temp1);
        free_register(temp1);
        free_register(temp2);

        mov_reg32_reg32(temp1, rt1);
        mov_reg32_reg32(temp2, rt2);
        shrd_reg32_reg32_cl(temp1, temp2);
        shr_reg32_cl(temp2);
        test_reg32_imm32(ECX, 0x20);
        je_rj(4);
        mov_reg32_reg32(temp1, temp2); // 2
        xor_reg32_reg32(temp2, temp2); // 2

        mov_reg32_reg32(rd1, temp1);
        mov_reg32_reg32(rd2, temp2);
    }
#endif
}
Example #6
0
void allocate_register_32_manually_w(int reg, unsigned int *addr)
{
  int i;

  /* check if we just happen to already have this r4300 reg cached in the requested x86 reg */
  if (last_access[reg] != NULL && reg_content[reg] == (unsigned long long *) addr)
  {
    precomp_instr *last = last_access[reg]+1;
    while (last <= dst)
    {
      last->reg_cache_infos.needed_registers[reg] = NULL;
      last++;
    }
    last_access[reg] = dst;
    is64bits[reg] = 0;
    dirty[reg] = 1;
    return;
  }
   
  /* otherwise free up the requested x86 register */
  if (last_access[reg])
    free_register(reg);
  else
  {
    while (free_since[reg] <= dst)
    {
      free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
      free_since[reg]++;
    }
  }

  /* if the r4300 register is already cached in a different x86 register, then free it and bind to the requested x86 register */
  for (i = 0; i < 8; i++)
  {
    if (last_access[i] != NULL && reg_content[i] == (unsigned long long *) addr)
    {
      precomp_instr *last = last_access[i] + 1;
      while (last <= dst)
      {
        last->reg_cache_infos.needed_registers[i] = NULL;
        last++;
      }
      last_access[reg] = dst;
      reg_content[reg] = reg_content[i];
      dirty[reg] = 1;
      is64bits[reg] = 0;
      /* free the previous x86 register used to cache this r4300 register */
      free_since[i] = dst+1;
      last_access[i] = NULL;
      return;
    }
  }
   
  /* otherwise just set up the requested register as 32-bit */
  last_access[reg] = dst;
  reg_content[reg] = (unsigned long long *) addr;
  dirty[reg] = 1;
  is64bits[reg] = 0;
}
Example #7
0
// this function is similar to allocate_register except it loads
// a 64 bits value, and return the register number of the LSB part
int allocate_register_64(usf_state_t * state, unsigned long long *addr)
{
  int reg, i;

  // is it already cached?
  if (addr != NULL)
  {
    for (i = 0; i < 8; i++)
    {
      if (state->last_access[i] != NULL && state->reg_content[i] == addr)
      {
        precomp_instr *last = state->last_access[i]+1;

        while (last <= state->dst)
        {
          last->reg_cache_infos.needed_registers[i] = state->reg_content[i];
          last++;
        }
        state->last_access[i] = state->dst;
        if (state->is64bits[i] == 0)
        {
          movsxd_reg64_reg32(state, i, i);
          state->is64bits[i] = 1;
        }
        return i;
      }
    }
  }

  // it's not cached, so take the least recently used register
  reg = lru_register(state);
   
  if (state->last_access[reg])
    free_register(state, reg);
  else
  {
    while (state->free_since[reg] <= state->dst)
    {
      state->free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
      state->free_since[reg]++;
    }
  }
   
  state->last_access[reg] = state->dst;
  state->reg_content[reg] = addr;
  state->dirty[reg] = 0;
  state->is64bits[reg] = 1;
   
  if (addr != NULL)
  {
    if (addr == state->r0)
      xor_reg64_reg64(state, reg, reg);
    else
      mov_xreg64_m64rel(state, reg, addr);
  }

  return reg;
}
Example #8
0
// this function is similar to allocate_register except it loads
// a 64 bits value, and return the register number of the LSB part
int allocate_register_64(unsigned long long *addr)
{
  int reg, i;

  // is it already cached?
  if (addr != NULL)
  {
    for (i = 0; i < 8; i++)
    {
      if (last_access[i] != NULL && reg_content[i] == addr)
      {
        precomp_instr *last = last_access[i]+1;

        while (last <= dst)
        {
          last->reg_cache_infos.needed_registers[i] = reg_content[i];
          last++;
        }
        last_access[i] = dst;
        if (is64bits[i] == 0)
        {
          movsxd_reg64_reg32(i, i);
          is64bits[i] = 1;
        }
        return i;
      }
    }
  }

  // it's not cached, so take the least recently used register
  reg = lru_register();
   
  if (last_access[reg])
    free_register(reg);
  else
  {
    while (free_since[reg] <= dst)
    {
      free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
      free_since[reg]++;
    }
  }
   
  last_access[reg] = dst;
  reg_content[reg] = addr;
  dirty[reg] = 0;
  is64bits[reg] = 1;
   
  if (addr != NULL)
  {
    if (addr == r0)
      xor_reg64_reg64(reg, reg);
    else
      mov_xreg64_m64rel(reg, addr);
  }

  return reg;
}
Example #9
0
// this function frees a specific X86 GPR
void free_register(int reg)
{
   precomp_instr *last;
   
   if (last_access[reg] != NULL &&
       r64[reg] != -1 && (int)reg_content[reg] != (int)reg_content[r64[reg]]-4)
     {
    free_register(r64[reg]);
    return;
     }
   
   if (last_access[reg] != NULL) last = last_access[reg]+1;
   else last = free_since[reg];
   
   while (last <= dst)
     {
    if (last_access[reg] != NULL && dirty[reg])
      last->reg_cache_infos.needed_registers[reg] = reg_content[reg];
    else
      last->reg_cache_infos.needed_registers[reg] = NULL;
    
    if (last_access[reg] != NULL && r64[reg] != -1)
      {
         if (dirty[r64[reg]])
           last->reg_cache_infos.needed_registers[r64[reg]] = reg_content[r64[reg]];
         else
           last->reg_cache_infos.needed_registers[r64[reg]] = NULL;
      }
    
    last++;
     }
   if (last_access[reg] == NULL) 
     {
    free_since[reg] = dst+1;
    return;
     }
   
   if (dirty[reg]) 
     {
    mov_m32_reg32(reg_content[reg], reg);
    if (r64[reg] == -1)
      {
         sar_reg32_imm8(reg, 31);
         mov_m32_reg32((unsigned int*)reg_content[reg]+1, reg);
      }
    else mov_m32_reg32(reg_content[r64[reg]], r64[reg]);
     }
   last_access[reg] = NULL;
   free_since[reg] = dst+1;
   if (r64[reg] != -1)
     {
    last_access[r64[reg]] = NULL;
    free_since[r64[reg]] = dst+1;
     }
}
Example #10
0
// this function frees a specific X86 GPR
void free_register(int reg)
{
   struct precomp_instr *last;
   
   if (g_dev.r4300.regcache_state.last_access[reg] != NULL &&
       g_dev.r4300.regcache_state.r64[reg] != -1 && (int)g_dev.r4300.regcache_state.reg_content[reg] != (int)g_dev.r4300.regcache_state.reg_content[g_dev.r4300.regcache_state.r64[reg]]-4)
     {
    free_register(g_dev.r4300.regcache_state.r64[reg]);
    return;
     }
   
   if (g_dev.r4300.regcache_state.last_access[reg] != NULL) last = g_dev.r4300.regcache_state.last_access[reg]+1;
   else last = g_dev.r4300.regcache_state.free_since[reg];
   
   while (last <= g_dev.r4300.recomp.dst)
     {
    if (g_dev.r4300.regcache_state.last_access[reg] != NULL && g_dev.r4300.regcache_state.dirty[reg])
      last->reg_cache_infos.needed_registers[reg] = g_dev.r4300.regcache_state.reg_content[reg];
    else
      last->reg_cache_infos.needed_registers[reg] = NULL;
    
    if (g_dev.r4300.regcache_state.last_access[reg] != NULL && g_dev.r4300.regcache_state.r64[reg] != -1)
      {
         if (g_dev.r4300.regcache_state.dirty[g_dev.r4300.regcache_state.r64[reg]])
           last->reg_cache_infos.needed_registers[g_dev.r4300.regcache_state.r64[reg]] = g_dev.r4300.regcache_state.reg_content[g_dev.r4300.regcache_state.r64[reg]];
         else
           last->reg_cache_infos.needed_registers[g_dev.r4300.regcache_state.r64[reg]] = NULL;
      }
    
    last++;
     }
   if (g_dev.r4300.regcache_state.last_access[reg] == NULL) 
     {
    g_dev.r4300.regcache_state.free_since[reg] = g_dev.r4300.recomp.dst+1;
    return;
     }
   
   if (g_dev.r4300.regcache_state.dirty[reg]) 
     {
    mov_m32_reg32(g_dev.r4300.regcache_state.reg_content[reg], reg);
    if (g_dev.r4300.regcache_state.r64[reg] == -1)
      {
         sar_reg32_imm8(reg, 31);
         mov_m32_reg32((unsigned int*)g_dev.r4300.regcache_state.reg_content[reg]+1, reg);
      }
    else mov_m32_reg32(g_dev.r4300.regcache_state.reg_content[g_dev.r4300.regcache_state.r64[reg]], g_dev.r4300.regcache_state.r64[reg]);
     }
   g_dev.r4300.regcache_state.last_access[reg] = NULL;
   g_dev.r4300.regcache_state.free_since[reg] = g_dev.r4300.recomp.dst+1;
   if (g_dev.r4300.regcache_state.r64[reg] != -1)
     {
    g_dev.r4300.regcache_state.last_access[g_dev.r4300.regcache_state.r64[reg]] = NULL;
    g_dev.r4300.regcache_state.free_since[g_dev.r4300.regcache_state.r64[reg]] = g_dev.r4300.recomp.dst+1;
     }
}
Example #11
0
// this function frees a specific X86 GPR
void free_register(usf_state_t * state, int reg)
{
   precomp_instr *last;
   
   if (state->last_access[reg] != NULL &&
       state->r64[reg] != -1 && (int)state->reg_content[reg] != (int)state->reg_content[state->r64[reg]]-4)
     {
    free_register(state, state->r64[reg]);
    return;
     }
   
   if (state->last_access[reg] != NULL) last = state->last_access[reg]+1;
   else last = state->free_since[reg];
   
   while (last <= state->dst)
     {
    if (state->last_access[reg] != NULL && state->dirty[reg])
      last->reg_cache_infos.needed_registers[reg] = state->reg_content[reg];
    else
      last->reg_cache_infos.needed_registers[reg] = NULL;
    
    if (state->last_access[reg] != NULL && state->r64[reg] != -1)
      {
         if (state->dirty[state->r64[reg]])
           last->reg_cache_infos.needed_registers[state->r64[reg]] = state->reg_content[state->r64[reg]];
         else
           last->reg_cache_infos.needed_registers[state->r64[reg]] = NULL;
      }
    
    last++;
     }
   if (state->last_access[reg] == NULL)
     {
    state->free_since[reg] = state->dst+1;
    return;
     }
   
   if (state->dirty[reg])
     {
    mov_m32_reg32(state, state->reg_content[reg], reg);
    if (state->r64[reg] == -1)
      {
         sar_reg32_imm8(state, reg, 31);
         mov_m32_reg32(state, (unsigned int*)state->reg_content[reg]+1, reg);
      }
    else mov_m32_reg32(state, state->reg_content[state->r64[reg]], state->r64[reg]);
     }
   state->last_access[reg] = NULL;
   state->free_since[reg] = state->dst+1;
   if (state->r64[reg] != -1)
     {
    state->last_access[state->r64[reg]] = NULL;
    state->free_since[state->r64[reg]] = state->dst+1;
     }
}
Example #12
0
int generate_code(mdk_context_t *ctx)
{
	int i, r1, r2;
	char *inst;

	if (ctx == NULL)
		return EINVAL;

	for (i = 0; ctx->tkn[i].token; i++) {
		if (ctx->tkn[i].type != MDK_TOKEN_VALUE) {
			switch (ctx->tkn[i].type) {
			case MDK_TOKEN_ADD: inst = "ADD"; break;
			case MDK_TOKEN_SUB: inst = "SUB"; break;
			case MDK_TOKEN_MUL: inst = "MUL"; break;
			case MDK_TOKEN_DIV: inst = "DIV"; break;
			default:
				/* error */
				break;
			}

			r1 = capt_register(ctx);
			r2 = capt_register(ctx);

			printf("POP	QB%d\n", r1);
			printf("POP	QB%d\n", r2);
			printf("%s	QB%d,QB%d\n", inst, r1, r2);
			printf("PUSH	QB%d\n", r1);

			free_register(ctx, r1);
			free_register(ctx, r2);
		} else
			printf("PUSH	%s\n", ctx->tkn[i].token);

		printf(";\n");
	}
	r1 = capt_register(ctx);
	printf("POP	QB%d\n", r1);
	free_register(ctx, r1);

	return 0;
}
Example #13
0
void free_all_registers(usf_state_t * state)
{
   int i;
   for (i=0; i<8; i++)
     {
    if (state->last_access[i]) free_register(state, i);
    else
      {
         while (state->free_since[i] <= state->dst)
           {
          state->free_since[i]->reg_cache_infos.needed_registers[i] = NULL;
          state->free_since[i]++;
           }
      }
     }
}
Example #14
0
int allocate_register_64_w(usf_state_t *state, unsigned long long *addr)
{
  int reg, i;

  // is it already cached?
  for (i = 0; i < 8; i++)
  {
    if (state->last_access[i] != NULL && state->reg_content[i] == addr)
    {
      precomp_instr *last = state->last_access[i] + 1;

      while (last <= state->dst)
      {
        last->reg_cache_infos.needed_registers[i] = NULL;
        last++;
      }
      state->last_access[i] = state->dst;
      state->is64bits[i] = 1;
      state->dirty[i] = 1;
      return i;
    }
  }

  // it's not cached, so take the least recently used register
  reg = lru_register(state);
   
  if (state->last_access[reg])
    free_register(state, reg);
  else
  {
    while (state->free_since[reg] <= state->dst)
    {
      state->free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
      state->free_since[reg]++;
    }
  }
   
  state->last_access[reg] = state->dst;
  state->reg_content[reg] = addr;
  state->dirty[reg] = 1;
  state->is64bits[reg] = 1;

  return reg;
}
Example #15
0
int allocate_register_64_w(unsigned long long *addr)
{
  int reg, i;

  // is it already cached?
  for (i = 0; i < 8; i++)
  {
    if (last_access[i] != NULL && reg_content[i] == addr)
    {
      precomp_instr *last = last_access[i] + 1;

      while (last <= dst)
      {
        last->reg_cache_infos.needed_registers[i] = NULL;
        last++;
      }
      last_access[i] = dst;
      is64bits[i] = 1;
      dirty[i] = 1;
      return i;
    }
  }

  // it's not cached, so take the least recently used register
  reg = lru_register();
   
  if (last_access[reg])
    free_register(reg);
  else
  {
    while (free_since[reg] <= dst)
    {
      free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
      free_since[reg]++;
    }
  }
   
  last_access[reg] = dst;
  reg_content[reg] = addr;
  dirty[reg] = 1;
  is64bits[reg] = 1;

  return reg;
}
Example #16
0
void free_all_registers(void)
{
#if defined(PROFILE_R4300)
  int freestart = code_length;
  int flushed = 0;
#endif

  int i;
  for (i=0; i<8; i++)
  {
#if defined(PROFILE_R4300)
    if (last_access[i] && dirty[i]) flushed = 1;
#endif
    if (last_access[i])
    {
      free_register(i);
    }
    else
    {
      while (free_since[i] <= dst)
      {
        free_since[i]->reg_cache_infos.needed_registers[i] = NULL;
        free_since[i]++;
      }
    }
  }

#if defined(PROFILE_R4300)
  if (flushed == 1)
  {
    long long x86addr = (long long) ((*inst_pointer) + freestart);
    int mipsop = -5;
    if (fwrite(&mipsop, 1, 4, pfProfile) != 4 || /* -5 = regcache flushing */
        fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to start of register cache flushing instructions
        DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data");
    x86addr = (long long) ((*inst_pointer) + code_length);
    if (fwrite(&src, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode for current instruction
        fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction
        DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data");
  }
#endif
}
Example #17
0
void free_all_registers(void)
{
#if defined(PROFILE_R4300)
  int freestart = g_dev.r4300.recomp.code_length;
  int flushed = 0;
#endif

   int i;
   for (i=0; i<8; i++)
     {
#if defined(PROFILE_R4300)
    if (g_dev.r4300.regcache_state.last_access[i] && g_dev.r4300.regcache_state.dirty[i]) flushed = 1;
#endif
    if (g_dev.r4300.regcache_state.last_access[i]) free_register(i);
    else
      {
         while (g_dev.r4300.regcache_state.free_since[i] <= g_dev.r4300.recomp.dst)
           {
          g_dev.r4300.regcache_state.free_since[i]->reg_cache_infos.needed_registers[i] = NULL;
          g_dev.r4300.regcache_state.free_since[i]++;
           }
      }
     }

#if defined(PROFILE_R4300)
  if (flushed == 1)
  {
    long x86addr = (long) ((*g_dev.r4300.recomp.inst_pointer) + freestart);
    int mipsop = -5;
    fwrite(&mipsop, 1, 4, g_dev.r4300.recomp.pfProfile); /* -5 = regcache flushing */
    fwrite(&x86addr, 1, sizeof(char *), g_dev.r4300.recomp.pfProfile); // write pointer to start of register cache flushing instructions
    x86addr = (long) ((*g_dev.r4300.recomp.inst_pointer) + g_dev.r4300.recomp.code_length);
    fwrite(&g_dev.r4300.recomp.src, 1, 4, g_dev.r4300.recomp.pfProfile); // write 4-byte MIPS opcode for current instruction
    fwrite(&x86addr, 1, sizeof(char *), g_dev.r4300.recomp.pfProfile); // write pointer to dynamically generated x86 code for this MIPS instruction
  }
#endif
}
Example #18
0
void genaddu(void)
{
#ifdef INTERPRET_ADDU
   gencallinterp((unsigned int)cached_interpreter_table.ADDU, 0);
#else
   int rs = allocate_register((unsigned int *)g_dev.r4300.recomp.dst->f.r.rs);
   int rt = allocate_register((unsigned int *)g_dev.r4300.recomp.dst->f.r.rt);
   int rd = allocate_register_w((unsigned int *)g_dev.r4300.recomp.dst->f.r.rd);
   
   if (rt != rd && rs != rd)
     {
    mov_reg32_reg32(rd, rs);
    add_reg32_reg32(rd, rt);
     }
   else
     {
    int temp = lru_register();
    free_register(temp);
    mov_reg32_reg32(temp, rs);
    add_reg32_reg32(temp, rt);
    mov_reg32_reg32(rd, temp);
     }
#endif
}
Example #19
0
void gennor()
{
#ifdef INTERPRET_NOR
   gencallinterp((unsigned long)NOR, 0);
#else
   int rs1 = allocate_64_register1((unsigned long *)dst->f.r.rs);
   int rs2 = allocate_64_register2((unsigned long *)dst->f.r.rs);
   int rt1 = allocate_64_register1((unsigned long *)dst->f.r.rt);
   int rt2 = allocate_64_register2((unsigned long *)dst->f.r.rt);
   int rd1 = allocate_64_register1_w((unsigned long *)dst->f.r.rd);
   int rd2 = allocate_64_register2_w((unsigned long *)dst->f.r.rd);
   
   if (rt1 != rd1 && rs1 != rd1)
     {
	mov_reg32_reg32(rd1, rs1);
	mov_reg32_reg32(rd2, rs2);
	or_reg32_reg32(rd1, rt1);
	or_reg32_reg32(rd2, rt2);
	not_reg32(rd1);
	not_reg32(rd2);
     }
   else
     {
	int temp = lru_register();
	free_register(temp);
	mov_reg32_reg32(temp, rs1);
	or_reg32_reg32(temp, rt1);
	mov_reg32_reg32(rd1, temp);
	mov_reg32_reg32(temp, rs2);
	or_reg32_reg32(temp, rt2);
	mov_reg32_reg32(rd2, temp);
	not_reg32(rd1);
	not_reg32(rd2);
     }
#endif
}
Example #20
0
void gensubu(usf_state_t * state)
{
#ifdef INTERPRET_SUBU
   gencallinterp(state, (unsigned int)state->current_instruction_table.SUBU, 0);
#else
   int rs = allocate_register(state, (unsigned int *)state->dst->f.r.rs);
   int rt = allocate_register(state, (unsigned int *)state->dst->f.r.rt);
   int rd = allocate_register_w(state, (unsigned int *)state->dst->f.r.rd);
   
   if (rt != rd && rs != rd)
     {
    mov_reg32_reg32(state, rd, rs);
    sub_reg32_reg32(state, rd, rt);
     }
   else
     {
    int temp = lru_register(state);
    free_register(state, temp);
    mov_reg32_reg32(state, temp, rs);
    sub_reg32_reg32(state, temp, rt);
    mov_reg32_reg32(state, rd, temp);
     }
#endif
}
Example #21
0
void gensubu()
{
#ifdef INTERPRET_SUBU
   gencallinterp((unsigned long)SUBU, 0);
#else
   int rs = allocate_register((unsigned long *)dst->f.r.rs);
   int rt = allocate_register((unsigned long *)dst->f.r.rt);
   int rd = allocate_register_w((unsigned long *)dst->f.r.rd);
   
   if (rt != rd && rs != rd)
     {
	mov_reg32_reg32(rd, rs);
	sub_reg32_reg32(rd, rt);
     }
   else
     {
	int temp = lru_register();
	free_register(temp);
	mov_reg32_reg32(temp, rs);
	sub_reg32_reg32(temp, rt);
	mov_reg32_reg32(rd, temp);
     }
#endif
}
Example #22
0
void gennor(usf_state_t * state)
{
#ifdef INTERPRET_NOR
   gencallinterp(state, (unsigned int)state->current_instruction_table.NOR, 0);
#else
   int rs1 = allocate_64_register1(state, (unsigned int *)state->dst->f.r.rs);
   int rs2 = allocate_64_register2(state, (unsigned int *)state->dst->f.r.rs);
   int rt1 = allocate_64_register1(state, (unsigned int *)state->dst->f.r.rt);
   int rt2 = allocate_64_register2(state, (unsigned int *)state->dst->f.r.rt);
   int rd1 = allocate_64_register1_w(state, (unsigned int *)state->dst->f.r.rd);
   int rd2 = allocate_64_register2_w(state, (unsigned int *)state->dst->f.r.rd);
   
   if (rt1 != rd1 && rs1 != rd1)
     {
    mov_reg32_reg32(state, rd1, rs1);
    mov_reg32_reg32(state, rd2, rs2);
    or_reg32_reg32(state, rd1, rt1);
    or_reg32_reg32(state, rd2, rt2);
    not_reg32(state, rd1);
    not_reg32(state, rd2);
     }
   else
     {
    int temp = lru_register(state);
    free_register(state, temp);
    mov_reg32_reg32(state, temp, rs1);
    or_reg32_reg32(state, temp, rt1);
    mov_reg32_reg32(state, rd1, temp);
    mov_reg32_reg32(state, temp, rs2);
    or_reg32_reg32(state, temp, rt2);
    mov_reg32_reg32(state, rd2, temp);
    not_reg32(state, rd1);
    not_reg32(state, rd2);
     }
#endif
}
Example #23
0
void gensub(void)
{
#ifdef INTERPRET_SUB
    gencallinterp((unsigned int)cached_interpreter_table.SUB, 0);
#else
    int rs = allocate_register((unsigned int *)dst->f.r.rs);
    int rt = allocate_register((unsigned int *)dst->f.r.rt);
    int rd = allocate_register_w((unsigned int *)dst->f.r.rd);

    if (rt != rd && rs != rd)
    {
        mov_reg32_reg32(rd, rs);
        sub_reg32_reg32(rd, rt);
    }
    else
    {
        int temp = lru_register();
        free_register(temp);
        mov_reg32_reg32(temp, rs);
        sub_reg32_reg32(temp, rt);
        mov_reg32_reg32(rd, temp);
    }
#endif
}
Example #24
0
void allocate_register_32_manually(int reg, unsigned int *addr)
{
  int i;

  /* check if we just happen to already have this r4300 reg cached in the requested x86 reg */
  if (last_access[reg] != NULL && reg_content[reg] == (unsigned long long *) addr)
  {
    precomp_instr *last = last_access[reg] + 1;
    while (last <= dst)
    {
      last->reg_cache_infos.needed_registers[reg] = reg_content[reg];
      last++;
    }
    last_access[reg] = dst;
    /* we won't touch is64bits or dirty; the register returned is "read-only" */
    return;
  }

  /* otherwise free up the requested x86 register */
  if (last_access[reg])
    free_register(reg);
  else
  {
    while (free_since[reg] <= dst)
    {
      free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
      free_since[reg]++;
    }
  }

  /* if the r4300 register is already cached in a different x86 register, then copy it to the requested x86 register */
  for (i=0; i<8; i++)
  {
    if (last_access[i] != NULL && reg_content[i] == (unsigned long long *) addr)
    {
      precomp_instr *last = last_access[i]+1;
      while (last <= dst)
      {
        last->reg_cache_infos.needed_registers[i] = reg_content[i];
        last++;
      }
      last_access[i] = dst;
      if (is64bits[i])
        mov_reg64_reg64(reg, i);
      else
        mov_reg32_reg32(reg, i);
      last_access[reg] = dst;
      is64bits[reg] = is64bits[i];
      dirty[reg] = dirty[i];
      reg_content[reg] = reg_content[i];
      /* free the previous x86 register used to cache this r4300 register */
      free_since[i] = dst + 1;
      last_access[i] = NULL;
      return;
    }
  }

  /* otherwise just load the 32-bit value into the requested register */
  last_access[reg] = dst;
  reg_content[reg] = (unsigned long long *) addr;
  dirty[reg] = 0;
  is64bits[reg] = 0;
   
  if ((unsigned long long *) addr == r0)
    xor_reg32_reg32(reg, reg);
  else
    mov_xreg32_m32rel(reg, addr);
}
Example #25
0
int allocate_64_register2_w(unsigned int *addr)
{
   int reg1, reg2, i;
   
   // is it already cached as a 32 bits value ?
   for (i=0; i<8; i++)
     {
    if (g_dev.r4300.regcache_state.last_access[i] != NULL && g_dev.r4300.regcache_state.reg_content[i] == addr)
      {
         if (g_dev.r4300.regcache_state.r64[i] == -1)
           {
          allocate_register_w(addr);
          reg2 = lru_register();
          if (g_dev.r4300.regcache_state.last_access[reg2]) free_register(reg2);
          else
          {
            while (g_dev.r4300.regcache_state.free_since[reg2] <= g_dev.r4300.recomp.dst)
            {
              g_dev.r4300.regcache_state.free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL;
              g_dev.r4300.regcache_state.free_since[reg2]++;
            }
          }
          g_dev.r4300.regcache_state.r64[i] = reg2;
          g_dev.r4300.regcache_state.r64[reg2] = i;
          g_dev.r4300.regcache_state.last_access[reg2] = g_dev.r4300.recomp.dst;
          
          g_dev.r4300.regcache_state.reg_content[reg2] = addr+1;
          g_dev.r4300.regcache_state.dirty[reg2] = 1;
          mov_reg32_reg32(reg2, i);
          sar_reg32_imm8(reg2, 31);
          
          return reg2;
           }
         else
           {
          g_dev.r4300.regcache_state.last_access[i] = g_dev.r4300.recomp.dst;
          g_dev.r4300.regcache_state.last_access[g_dev.r4300.regcache_state.r64[i]] = g_dev.r4300.recomp.dst;
          g_dev.r4300.regcache_state.dirty[i] = g_dev.r4300.regcache_state.dirty[g_dev.r4300.regcache_state.r64[i]] = 1;
          return g_dev.r4300.regcache_state.r64[i];
           }
      }
     }
   
   reg1 = allocate_register_w(addr);
   reg2 = lru_register();
   if (g_dev.r4300.regcache_state.last_access[reg2]) free_register(reg2);
   else
     {
    while (g_dev.r4300.regcache_state.free_since[reg2] <= g_dev.r4300.recomp.dst)
      {
         g_dev.r4300.regcache_state.free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL;
         g_dev.r4300.regcache_state.free_since[reg2]++;
      }
     }
   g_dev.r4300.regcache_state.r64[reg1] = reg2;
   g_dev.r4300.regcache_state.r64[reg2] = reg1;
   g_dev.r4300.regcache_state.last_access[reg2] = g_dev.r4300.recomp.dst;
   g_dev.r4300.regcache_state.reg_content[reg2] = addr+1;
   g_dev.r4300.regcache_state.dirty[reg2] = 1;
   
   return reg2;
}
Example #26
0
void allocate_register_manually_w(int reg, unsigned int *addr, int load)
{
   int i;
   
   if (g_dev.r4300.regcache_state.last_access[reg] != NULL && g_dev.r4300.regcache_state.reg_content[reg] == addr)
     {
    struct precomp_instr *last = g_dev.r4300.regcache_state.last_access[reg]+1;
         
    while (last <= g_dev.r4300.recomp.dst)
      {
         last->reg_cache_infos.needed_registers[reg] = g_dev.r4300.regcache_state.reg_content[reg];
         last++;
      }
    g_dev.r4300.regcache_state.last_access[reg] = g_dev.r4300.recomp.dst;
    
    if (g_dev.r4300.regcache_state.r64[reg] != -1) 
      {
         last = g_dev.r4300.regcache_state.last_access[g_dev.r4300.regcache_state.r64[reg]]+1;
         
         while (last <= g_dev.r4300.recomp.dst)
           {
          last->reg_cache_infos.needed_registers[g_dev.r4300.regcache_state.r64[reg]] = g_dev.r4300.regcache_state.reg_content[g_dev.r4300.regcache_state.r64[reg]];
          last++;
           }
         g_dev.r4300.regcache_state.last_access[g_dev.r4300.regcache_state.r64[reg]] = NULL;
         g_dev.r4300.regcache_state.free_since[g_dev.r4300.regcache_state.r64[reg]] = g_dev.r4300.recomp.dst+1;
         g_dev.r4300.regcache_state.r64[reg] = -1;
      }
    g_dev.r4300.regcache_state.dirty[reg] = 1;
    return;
     }
   
   if (g_dev.r4300.regcache_state.last_access[reg]) free_register(reg);
   else
     {
    while (g_dev.r4300.regcache_state.free_since[reg] <= g_dev.r4300.recomp.dst)
      {
         g_dev.r4300.regcache_state.free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
         g_dev.r4300.regcache_state.free_since[reg]++;
      }
     }
   
   // is it already cached ?
   for (i=0; i<8; i++)
     {
    if (g_dev.r4300.regcache_state.last_access[i] != NULL && g_dev.r4300.regcache_state.reg_content[i] == addr)
      {
         struct precomp_instr *last = g_dev.r4300.regcache_state.last_access[i]+1;
         
         while (last <= g_dev.r4300.recomp.dst)
           {
          last->reg_cache_infos.needed_registers[i] = g_dev.r4300.regcache_state.reg_content[i];
          last++;
           }
         g_dev.r4300.regcache_state.last_access[i] = g_dev.r4300.recomp.dst;
         if (g_dev.r4300.regcache_state.r64[i] != -1)
           {
          last = g_dev.r4300.regcache_state.last_access[g_dev.r4300.regcache_state.r64[i]]+1;
          while (last <= g_dev.r4300.recomp.dst)
            {
               last->reg_cache_infos.needed_registers[g_dev.r4300.regcache_state.r64[i]] = NULL;
               last++;
            }
          g_dev.r4300.regcache_state.free_since[g_dev.r4300.regcache_state.r64[i]] = g_dev.r4300.recomp.dst+1;
          g_dev.r4300.regcache_state.last_access[g_dev.r4300.regcache_state.r64[i]] = NULL;
          g_dev.r4300.regcache_state.r64[i] = -1;
           }
         
         if (load)
           mov_reg32_reg32(reg, i);
         g_dev.r4300.regcache_state.last_access[reg] = g_dev.r4300.recomp.dst;
         g_dev.r4300.regcache_state.dirty[reg] = 1;
         g_dev.r4300.regcache_state.r64[reg] = -1;
         g_dev.r4300.regcache_state.reg_content[reg] = g_dev.r4300.regcache_state.reg_content[i];
         g_dev.r4300.regcache_state.free_since[i] = g_dev.r4300.recomp.dst+1;
         g_dev.r4300.regcache_state.last_access[i] = NULL;
         
         return;
      }
     }
   
   g_dev.r4300.regcache_state.last_access[reg] = g_dev.r4300.recomp.dst;
   g_dev.r4300.regcache_state.reg_content[reg] = addr;
   g_dev.r4300.regcache_state.dirty[reg] = 1;
   g_dev.r4300.regcache_state.r64[reg] = -1;
   
   if (addr != NULL && load)
     {
    if (addr == g_dev.r4300.regcache_state.r0 || addr == g_dev.r4300.regcache_state.r0+1)
      xor_reg32_reg32(reg, reg);
    else
      mov_reg32_m32(reg, addr);
     }
}
Example #27
0
void allocate_register_manually_w(int reg, unsigned int *addr, int load)
{
   int i;
   
   if (last_access[reg] != NULL && reg_content[reg] == addr)
     {
    precomp_instr *last = last_access[reg]+1;
         
    while (last <= dst)
      {
         last->reg_cache_infos.needed_registers[reg] = reg_content[reg];
         last++;
      }
    last_access[reg] = dst;
    
    if (r64[reg] != -1) 
      {
         last = last_access[r64[reg]]+1;
         
         while (last <= dst)
           {
          last->reg_cache_infos.needed_registers[r64[reg]] = reg_content[r64[reg]];
          last++;
           }
         last_access[r64[reg]] = NULL;
         free_since[r64[reg]] = dst+1;
         r64[reg] = -1;
      }
    dirty[reg] = 1;
    return;
     }
   
   if (last_access[reg]) free_register(reg);
   else
     {
    while (free_since[reg] <= dst)
      {
         free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
         free_since[reg]++;
      }
     }
   
   // is it already cached ?
   for (i=0; i<8; i++)
     {
    if (last_access[i] != NULL && reg_content[i] == addr)
      {
         precomp_instr *last = last_access[i]+1;
         
         while (last <= dst)
           {
          last->reg_cache_infos.needed_registers[i] = reg_content[i];
          last++;
           }
         last_access[i] = dst;
         if (r64[i] != -1)
           {
          last = last_access[r64[i]]+1;
          while (last <= dst)
            {
               last->reg_cache_infos.needed_registers[r64[i]] = NULL;
               last++;
            }
          free_since[r64[i]] = dst+1;
          last_access[r64[i]] = NULL;
          r64[i] = -1;
           }
         
         if (load)
           mov_reg32_reg32(reg, i);
         last_access[reg] = dst;
         dirty[reg] = 1;
         r64[reg] = -1;
         reg_content[reg] = reg_content[i];
         free_since[i] = dst+1;
         last_access[i] = NULL;
         
         return;
      }
     }
   
   last_access[reg] = dst;
   reg_content[reg] = addr;
   dirty[reg] = 1;
   r64[reg] = -1;
   
   if (addr != NULL && load)
     {
    if (addr == r0 || addr == r0+1)
      xor_reg32_reg32(reg, reg);
    else
      mov_reg32_m32(reg, addr);
     }
}
Example #28
0
void lock_register(int reg)
{
   free_register(reg);
   last_access[reg] = (precomp_instr *)0xFFFFFFFF;
   reg_content[reg] = NULL;
}
Example #29
0
int allocate_64_register2_w(unsigned int *addr)
{
   int reg1, reg2, i;
   
   // is it already cached as a 32 bits value ?
   for (i=0; i<8; i++)
     {
    if (last_access[i] != NULL && reg_content[i] == addr)
      {
         if (r64[i] == -1)
           {
          allocate_register_w(addr);
          reg2 = lru_register();
          if (last_access[reg2]) free_register(reg2);
          else
          {
            while (free_since[reg2] <= dst)
            {
              free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL;
              free_since[reg2]++;
            }
          }
          r64[i] = reg2;
          r64[reg2] = i;
          last_access[reg2] = dst;
          
          reg_content[reg2] = addr+1;
          dirty[reg2] = 1;
          mov_reg32_reg32(reg2, i);
          sar_reg32_imm8(reg2, 31);
          
          return reg2;
           }
         else
           {
          last_access[i] = dst;
          last_access[r64[i]] = dst;
          dirty[i] = dirty[r64[i]] = 1;
          return r64[i];
           }
      }
     }
   
   reg1 = allocate_register_w(addr);
   reg2 = lru_register();
   if (last_access[reg2]) free_register(reg2);
   else
     {
    while (free_since[reg2] <= dst)
      {
         free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL;
         free_since[reg2]++;
      }
     }
   r64[reg1] = reg2;
   r64[reg2] = reg1;
   last_access[reg2] = dst;
   reg_content[reg2] = addr+1;
   dirty[reg2] = 1;
   
   return reg2;
}
Example #30
0
int allocate_register_w(unsigned int *addr)
{
   unsigned int oldest_access = 0xFFFFFFFF;
   int reg = 0, i;
   
   // is it already cached ?
   for (i=0; i<8; i++)
     {
    if (last_access[i] != NULL && reg_content[i] == addr)
      {
         precomp_instr *last = last_access[i]+1;
         
         while (last <= dst)
           {
          last->reg_cache_infos.needed_registers[i] = NULL;
          last++;
           }
         last_access[i] = dst;
         dirty[i] = 1;
         if (r64[i] != -1)
           {
          last = last_access[r64[i]]+1;
          while (last <= dst)
            {
               last->reg_cache_infos.needed_registers[r64[i]] = NULL;
               last++;
            }
          free_since[r64[i]] = dst+1;
          last_access[r64[i]] = NULL;
          r64[i] = -1;
           }
         
         return i;
      }
     }
   
   // if it's not cached, we take the least recently used register
   for (i=0; i<8; i++)
     {
    if (i != ESP && (unsigned int)last_access[i] < oldest_access)
      {
         oldest_access = (int)last_access[i];
         reg = i;
      }
     }
   
   if (last_access[reg]) free_register(reg);
   else
     {
    while (free_since[reg] <= dst)
      {
         free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
         free_since[reg]++;
      }
     }
   
   last_access[reg] = dst;
   reg_content[reg] = addr;
   dirty[reg] = 1;
   r64[reg] = -1;
   
   return reg;
}