コード例 #1
0
/*
 * 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);
	}
}
コード例 #2
0
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)