static void genbranchlink(void) { int r31_64bit = is64((unsigned int*)®[31]); if (r31_64bit == 0) { int r31 = allocate_register_32_w((unsigned int *)®[31]); mov_reg32_imm32(r31, dst->addr+8); } else if (r31_64bit == -1) { mov_m32rel_imm32((unsigned int *)®[31], dst->addr + 8); if (dst->addr & 0x80000000) mov_m32rel_imm32(((unsigned int *)®[31])+1, 0xFFFFFFFF); else mov_m32rel_imm32(((unsigned int *)®[31])+1, 0); } else { int r31 = allocate_register_64_w((unsigned long long *)®[31]); mov_reg32_imm32(r31, dst->addr+8); movsxd_reg64_reg32(r31, r31); } }
// 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; }
// 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; }
static void genbranchlink(void) { int r31_64bit = is64((unsigned int*)®[31]); if (r31_64bit == 0) { #ifdef __x86_64__ int r31 = allocate_register_32_w((unsigned int *)®[31]); mov_reg32_imm32(r31, dst->addr+8); #else int r31 = allocate_register_w((unsigned int *)®[31]); mov_reg32_imm32(r31, dst->addr+8); #endif } else if (r31_64bit == -1) { #ifdef __x86_64__ mov_m32rel_imm32((unsigned int *)®[31], dst->addr + 8); if (dst->addr & 0x80000000) mov_m32rel_imm32(((unsigned int *)®[31])+1, 0xFFFFFFFF); else mov_m32rel_imm32(((unsigned int *)®[31])+1, 0); #else mov_m32_imm32((unsigned int *)®[31], dst->addr + 8); if (dst->addr & 0x80000000) mov_m32_imm32(((unsigned int *)®[31])+1, 0xFFFFFFFF); else mov_m32_imm32(((unsigned int *)®[31])+1, 0); #endif } else { #ifdef __x86_64__ int r31 = allocate_register_64_w((uint64_t*)®[31]); mov_reg32_imm32(r31, dst->addr+8); movsxd_reg64_reg32(r31, r31); #else int r311 = allocate_64_register1_w((unsigned int *)®[31]); int r312 = allocate_64_register2_w((unsigned int *)®[31]); mov_reg32_imm32(r311, dst->addr+8); if (dst->addr & 0x80000000) mov_reg32_imm32(r312, 0xFFFFFFFF); else mov_reg32_imm32(r312, 0); #endif } }
// this function frees a specific X86 GPR void free_register(usf_state_t * state, int reg) { precomp_instr *last; if (state->last_access[reg] == (precomp_instr *) 0xFFFFFFFFFFFFFFFFULL) unlock_register(state, reg); 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; last++; } if (state->last_access[reg] == NULL) { state->free_since[reg] = state->dst+1; return; } if (state->dirty[reg]) { if (state->is64bits[reg]) { mov_m64rel_xreg64(state, (unsigned long long *) state->reg_content[reg], reg); } else { movsxd_reg64_reg32(state, reg, reg); mov_m64rel_xreg64(state, (unsigned long long *) state->reg_content[reg], reg); } } state->last_access[reg] = NULL; state->free_since[reg] = state->dst+1; }
// this function frees a specific X86 GPR void free_register(int reg) { precomp_instr *last; 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; last++; } if (last_access[reg] == NULL) { free_since[reg] = dst+1; return; } if (dirty[reg]) { if (is64bits[reg]) { mov_m64rel_xreg64((unsigned long long *) reg_content[reg], reg); } else { movsxd_reg64_reg32(reg, reg); mov_m64rel_xreg64((unsigned long long *) reg_content[reg], reg); } } last_access[reg] = NULL; free_since[reg] = dst+1; }