/* * Perform an integer division or remainder. */ static void Divide(MDUnroll *unroll, int isSigned, int wantRemainder, unsigned char *pc, unsigned char *label) { #if !defined(IL_USE_INTERRUPT_BASED_INT_DIVIDE_BY_ZERO_CHECKS) #define IL_NEED_DIVIDE_REEXECUTE 1 unsigned char *patch1; #endif #if !defined(IL_USE_INTERRUPT_BASED_INT_OVERFLOW_CHECKS) #define IL_NEED_DIVIDE_REEXECUTE 1 unsigned char *patch2, *patch3; #endif /* Get the arguments into EAX and ECX so we know where they are */ if(unroll->pseudoStackSize != 2 || unroll->pseudoStack[0] != X86_EAX || unroll->pseudoStack[1] != X86_ECX) { FlushRegisterStack(unroll); unroll->stackHeight -= 8; x86_mov_reg_membase(unroll->out, X86_EAX, MD_REG_STACK, unroll->stackHeight, 4); x86_mov_reg_membase(unroll->out, X86_ECX, MD_REG_STACK, unroll->stackHeight + 4, 4); unroll->pseudoStack[0] = X86_EAX; unroll->pseudoStack[1] = X86_ECX; unroll->pseudoStackSize = 2; unroll->regsUsed |= ((1 << X86_EAX) | (1 << X86_ECX)); } /* Check for conditions that may cause an exception */ #if !defined(IL_USE_INTERRUPT_BASED_INT_DIVIDE_BY_ZERO_CHECKS) x86_alu_reg_imm(unroll->out, X86_CMP, X86_ECX, 0); patch1 = unroll->out; x86_branch8(unroll->out, X86_CC_EQ, 0, 0); #endif #if !defined(IL_USE_INTERRUPT_BASED_INT_OVERFLOW_CHECKS) x86_alu_reg_imm(unroll->out, X86_CMP, X86_ECX, -1); patch2 = unroll->out; x86_branch32(unroll->out, X86_CC_NE, 0, 0); x86_alu_reg_imm(unroll->out, X86_CMP, X86_EAX, (int)0x80000000); patch3 = unroll->out; x86_branch32(unroll->out, X86_CC_NE, 0, 0); #endif #if !defined(IL_USE_INTERRUPT_BASED_INT_DIVIDE_BY_ZERO_CHECKS) x86_patch(patch1, unroll->out); #endif #if defined(IL_NEED_DIVIDE_REEXECUTE) /* Re-execute the division instruction to throw the exception */ ReExecute(unroll, pc, label); #endif #if !defined(IL_USE_INTERRUPT_BASED_INT_OVERFLOW_CHECKS) x86_patch(patch2, unroll->out); x86_patch(patch3, unroll->out); #endif /* Perform the division */ if(isSigned) { x86_cdq(unroll->out); } else { x86_clear_reg(unroll->out, X86_EDX); } x86_div_reg(unroll->out, X86_ECX, isSigned); /* Pop ECX from the pseudo stack */ FreeTopRegister(unroll, -1); /* If we want the remainder, then replace EAX with EDX on the stack */ if(wantRemainder) { unroll->pseudoStack[0] = X86_EDX; unroll->regsUsed = (1 << X86_EDX); } }
void _jit_gen_load_value(jit_gencode_t gen, int reg, int other_reg, jit_value_t value) { jit_type_t type; int src_reg, other_src_reg; void *ptr; int offset; /* Make sure that we have sufficient space */ jit_cache_setup_output(16); type = jit_type_normalize(value->type); /* Load zero */ if(value->is_constant) { switch(type->kind) { case JIT_TYPE_SBYTE: case JIT_TYPE_UBYTE: case JIT_TYPE_SHORT: case JIT_TYPE_USHORT: case JIT_TYPE_INT: case JIT_TYPE_UINT: { if((jit_nint)(value->address) == 0) { x86_clear_reg(inst, _jit_reg_info[reg].cpu_reg); } else { x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, (jit_nint)(value->address)); } } break; case JIT_TYPE_LONG: case JIT_TYPE_ULONG: { jit_long long_value; long_value = jit_value_get_long_constant(value); if(long_value == 0) { #ifdef JIT_NATIVE_INT64 x86_clear_reg(inst, _jit_reg_info[reg].cpu_reg); #else x86_clear_reg(inst, _jit_reg_info[reg].cpu_reg); x86_clear_reg(inst, _jit_reg_info[other_reg].cpu_reg); #endif } else { #ifdef JIT_NATIVE_INT64 x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, (jit_nint)long_value); #else x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, (jit_int)long_value); x86_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg, (jit_int)(long_value >> 32)); #endif } } break; case JIT_TYPE_FLOAT32: { jit_float32 float32_value; float32_value = jit_value_get_float32_constant(value); if(IS_WORD_REG(reg)) { union { jit_float32 float32_value; jit_int int_value; } un; un.float32_value = float32_value; x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, un.int_value); } else { if(float32_value == (jit_float32) 0.0) { x86_fldz(inst); } else if(float32_value == (jit_float32) 1.0) { x86_fld1(inst); } else { ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float32)); jit_memcpy(ptr, &float32_value, sizeof(float32_value)); x86_fld(inst, ptr, 0); } } } break; case JIT_TYPE_FLOAT64: { jit_float64 float64_value; float64_value = jit_value_get_float64_constant(value); if(IS_WORD_REG(reg)) { union { jit_float64 float64_value; jit_int int_value[2]; } un; un.float64_value = float64_value; x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, un.int_value[0]); x86_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg, un.int_value[1]); } else { if(float64_value == (jit_float64) 0.0) { x86_fldz(inst); } else if(float64_value == (jit_float64) 1.0) { x86_fld1(inst); } else { ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float64)); jit_memcpy(ptr, &float64_value, sizeof(float64_value)); x86_fld(inst, ptr, 1); } } } break; case JIT_TYPE_NFLOAT: { jit_nfloat nfloat_value; nfloat_value = jit_value_get_nfloat_constant(value); if(IS_WORD_REG(reg) && sizeof(jit_nfloat) == sizeof(jit_float64)) { union { jit_nfloat nfloat_value; jit_int int_value[2]; } un; un.nfloat_value = nfloat_value; x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, un.int_value[0]); x86_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg, un.int_value[1]); } else { if(nfloat_value == (jit_nfloat) 0.0) { x86_fldz(inst); } else if(nfloat_value == (jit_nfloat) 1.0) { x86_fld1(inst); } else { ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_nfloat)); jit_memcpy(ptr, &nfloat_value, sizeof(nfloat_value)); if(sizeof(jit_nfloat) == sizeof(jit_float64)) { x86_fld(inst, ptr, 1); } else { x86_fld80_mem(inst, ptr); } } } } break; } } else if(value->in_register || value->in_global_register)