void gendmultu(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[76]); #endif #ifdef INTERPRET_DMULTU gencallinterp((unsigned long long)cached_interpreter_table.DMULTU, 0); #else free_registers_move_start(); mov_xreg64_m64rel(RAX, (unsigned long long *) dst->f.r.rs); mov_xreg64_m64rel(RDX, (unsigned long long *) dst->f.r.rt); mul_reg64(RDX); mov_m64rel_xreg64((unsigned long long *) &lo, RAX); mov_m64rel_xreg64((unsigned long long *) &hi, RDX); #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; }
void genjalr(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[62]); #endif #ifdef INTERPRET_JALR gencallinterp((unsigned long long)cached_interpreter_table.JALR, 0); #else static unsigned int precomp_instr_size = sizeof(precomp_instr); unsigned int diff = (unsigned int) offsetof(precomp_instr, local_addr); unsigned int diff_need = (unsigned int) offsetof(precomp_instr, reg_cache_infos.need_map); unsigned int diff_wrap = (unsigned int) offsetof(precomp_instr, reg_cache_infos.jump_wrapper); if (((dst->addr & 0xFFF) == 0xFFC && (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump) { gencallinterp((unsigned long long)cached_interpreter_table.JALR, 1); return; } free_registers_move_start(); mov_xreg32_m32rel(EAX, (unsigned int *)dst->f.r.rs); mov_m32rel_xreg32((unsigned int *)&local_rs, EAX); gendelayslot(); mov_m32rel_imm32((unsigned int *)(dst-1)->f.r.rd, dst->addr+4); if ((dst->addr+4) & 0x80000000) mov_m32rel_imm32(((unsigned int *)(dst-1)->f.r.rd)+1, 0xFFFFFFFF); else mov_m32rel_imm32(((unsigned int *)(dst-1)->f.r.rd)+1, 0); mov_xreg32_m32rel(EAX, (unsigned int *)&local_rs); mov_m32rel_xreg32((unsigned int *)&last_addr, EAX); gencheck_interupt_reg(); mov_xreg32_m32rel(EAX, (unsigned int *)&local_rs); mov_reg32_reg32(EBX, EAX); and_eax_imm32(0xFFFFF000); cmp_eax_imm32(dst_block->start & 0xFFFFF000); je_near_rj(0); jump_start_rel32(); mov_m32rel_xreg32(&jump_to_address, EBX); mov_reg64_imm64(RAX, (unsigned long long) (dst+1)); mov_m64rel_xreg64((unsigned long long *)(&PC), RAX); mov_reg64_imm64(RAX, (unsigned long long) jump_to_func); call_reg64(RAX); /* will never return from call */ jump_end_rel32(); mov_reg64_imm64(RSI, (unsigned long long) dst_block->block); mov_reg32_reg32(EAX, EBX); sub_eax_imm32(dst_block->start); shr_reg32_imm8(EAX, 2); mul_m32rel((unsigned int *)(&precomp_instr_size)); mov_reg32_preg64preg64pimm32(EBX, RAX, RSI, diff_need); cmp_reg32_imm32(EBX, 1); jne_rj(11); add_reg32_imm32(EAX, diff_wrap); // 6 add_reg64_reg64(RAX, RSI); // 3 jmp_reg64(RAX); // 2 mov_reg32_preg64preg64pimm32(EBX, RAX, RSI, diff); mov_rax_memoffs64((unsigned long long *) &dst_block->code); add_reg64_reg64(RAX, RBX); jmp_reg64(RAX); #endif }