prim_ops.c

来自「适合KS8695X」· C语言 代码 · 共 2,262 行 · 第 1/5 页

C
2,262
字号
	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
	return (u8)res;
}

/****************************************************************************
REMARKS:
Implements the SBB instruction and side effects.
****************************************************************************/
u16 sbb_word(u16 d, u16 s)
{
    register u32 res;   /* all operands in native machine order */
    register u32 bc;

	if (ACCESS_FLAG(F_CF))
	res = d - s - 1;
    else
	res = d - s;
	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);

	/* calculate the borrow chain.  See note at top */
	bc = (res & (~d | s)) | (~d & s);
	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
	return (u16)res;
}

/****************************************************************************
REMARKS:
Implements the SBB instruction and side effects.
****************************************************************************/
u32 sbb_long(u32 d, u32 s)
{
	register u32 res;   /* all operands in native machine order */
	register u32 bc;

	if (ACCESS_FLAG(F_CF))
	res = d - s - 1;
    else
	res = d - s;
	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);

	/* calculate the borrow chain.  See note at top */
	bc = (res & (~d | s)) | (~d & s);
	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
	return res;
}

/****************************************************************************
REMARKS:
Implements the SUB instruction and side effects.
****************************************************************************/
u8 sub_byte(u8 d, u8 s)
{
	register u32 res;   /* all operands in native machine order */
	register u32 bc;

	res = d - s;
	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);

	/* calculate the borrow chain.  See note at top */
	bc = (res & (~d | s)) | (~d & s);
	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
	return (u8)res;
}

/****************************************************************************
REMARKS:
Implements the SUB instruction and side effects.
****************************************************************************/
u16 sub_word(u16 d, u16 s)
{
    register u32 res;   /* all operands in native machine order */
    register u32 bc;

    res = d - s;
	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);

	/* calculate the borrow chain.  See note at top */
	bc = (res & (~d | s)) | (~d & s);
	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
	return (u16)res;
}

/****************************************************************************
REMARKS:
Implements the SUB instruction and side effects.
****************************************************************************/
u32 sub_long(u32 d, u32 s)
{
	register u32 res;   /* all operands in native machine order */
	register u32 bc;

	res = d - s;
	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);

	/* calculate the borrow chain.  See note at top */
	bc = (res & (~d | s)) | (~d & s);
	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
	return res;
}

/****************************************************************************
REMARKS:
Implements the TEST instruction and side effects.
****************************************************************************/
void test_byte(u8 d, u8 s)
{
    register u32 res;   /* all operands in native machine order */

    res = d & s;

	CLEAR_FLAG(F_OF);
	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
    /* AF == dont care */
	CLEAR_FLAG(F_CF);
}

/****************************************************************************
REMARKS:
Implements the TEST instruction and side effects.
****************************************************************************/
void test_word(u16 d, u16 s)
{
	register u32 res;   /* all operands in native machine order */

	res = d & s;

	CLEAR_FLAG(F_OF);
	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
	/* AF == dont care */
	CLEAR_FLAG(F_CF);
}

/****************************************************************************
REMARKS:
Implements the TEST instruction and side effects.
****************************************************************************/
void test_long(u32 d, u32 s)
{
	register u32 res;   /* all operands in native machine order */

	res = d & s;

	CLEAR_FLAG(F_OF);
	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
	/* AF == dont care */
	CLEAR_FLAG(F_CF);
}

/****************************************************************************
REMARKS:
Implements the XOR instruction and side effects.
****************************************************************************/
u8 xor_byte(u8 d, u8 s)
{
	register u8 res;    /* all operands in native machine order */

	res = d ^ s;
	CLEAR_FLAG(F_OF);
	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
	CLEAR_FLAG(F_CF);
	CLEAR_FLAG(F_AF);
	return res;
}

/****************************************************************************
REMARKS:
Implements the XOR instruction and side effects.
****************************************************************************/
u16 xor_word(u16 d, u16 s)
{
	register u16 res;   /* all operands in native machine order */

	res = d ^ s;
	CLEAR_FLAG(F_OF);
	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
	CLEAR_FLAG(F_CF);
	CLEAR_FLAG(F_AF);
	return res;
}

/****************************************************************************
REMARKS:
Implements the XOR instruction and side effects.
****************************************************************************/
u32 xor_long(u32 d, u32 s)
{
	register u32 res;   /* all operands in native machine order */

	res = d ^ s;
	CLEAR_FLAG(F_OF);
	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
	CLEAR_FLAG(F_CF);
	CLEAR_FLAG(F_AF);
	return res;
}

/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
void imul_byte(u8 s)
{
	s16 res = (s16)((s8)M.x86.R_AL * (s8)s);

	M.x86.R_AX = res;
	if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
		((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
		CLEAR_FLAG(F_CF);
		CLEAR_FLAG(F_OF);
	} else {
		SET_FLAG(F_CF);
		SET_FLAG(F_OF);
	}
}

/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
void imul_word(u16 s)
{
	s32 res = (s16)M.x86.R_AX * (s16)s;

	M.x86.R_AX = (u16)res;
	M.x86.R_DX = (u16)(res >> 16);
	if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) ||
		((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) {
		CLEAR_FLAG(F_CF);
		CLEAR_FLAG(F_OF);
	} else {
		SET_FLAG(F_CF);
		SET_FLAG(F_OF);
	}
}

/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
{
#ifdef	__HAS_LONG_LONG__
	s64 res = (s32)d * (s32)s;

	*res_lo = (u32)res;
	*res_hi = (u32)(res >> 32);
#else
	u32	d_lo,d_hi,d_sign;
	u32	s_lo,s_hi,s_sign;
	u32	rlo_lo,rlo_hi,rhi_lo;

	if ((d_sign = d & 0x80000000) != 0)
		d = -d;
	d_lo = d & 0xFFFF;
	d_hi = d >> 16;
	if ((s_sign = s & 0x80000000) != 0)
		s = -s;
	s_lo = s & 0xFFFF;
	s_hi = s >> 16;
	rlo_lo = d_lo * s_lo;
	rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
	rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
	*res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
	*res_hi = rhi_lo;
	if (d_sign != s_sign) {
		d = ~*res_lo;
		s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
		*res_lo = ~*res_lo+1;
		*res_hi = ~*res_hi+(s >> 16);
		}
#endif
}

/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
void imul_long(u32 s)
{
	imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
	if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) ||
		((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) {
		CLEAR_FLAG(F_CF);
		CLEAR_FLAG(F_OF);
	} else {
		SET_FLAG(F_CF);
		SET_FLAG(F_OF);
	}
}

/****************************************************************************
REMARKS:
Implements the MUL instruction and side effects.
****************************************************************************/
void mul_byte(u8 s)
{
	u16 res = (u16)(M.x86.R_AL * s);

	M.x86.R_AX = res;
	if (M.x86.R_AH == 0) {
		CLEAR_FLAG(F_CF);
		CLEAR_FLAG(F_OF);
	} else {
		SET_FLAG(F_CF);
		SET_FLAG(F_OF);
	}
}

/****************************************************************************
REMARKS:
Implements the MUL instruction and side effects.
****************************************************************************/
void mul_word(u16 s)
{
	u32 res = M.x86.R_AX * s;

	M.x86.R_AX = (u16)res;
	M.x86.R_DX = (u16)(res >> 16);
	if (M.x86.R_DX == 0) {
		CLEAR_FLAG(F_CF);
		CLEAR_FLAG(F_OF);
    } else {
		SET_FLAG(F_CF);
		SET_FLAG(F_OF);
    }
}

/****************************************************************************
REMARKS:
Implements the MUL instruction and side effects.
****************************************************************************/
void mul_long(u32 s)
{
#ifdef	__HAS_LONG_LONG__
	u64 res = (u32)M.x86.R_EAX * (u32)s;

	M.x86.R_EAX = (u32)res;
	M.x86.R_EDX = (u32)(res >> 32);
#else
	u32	a,a_lo,a_hi;
	u32	s_lo,s_hi;
	u32	rlo_lo,rlo_hi,rhi_lo;

	a = M.x86.R_EAX;
	a_lo = a & 0xFFFF;
	a_hi = a >> 16;
	s_lo = s & 0xFFFF;
	s_hi = s >> 16;
	rlo_lo = a_lo * s_lo;
	rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
	rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
	M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
	M.x86.R_EDX = rhi_lo;
#endif

	if (M.x86.R_EDX == 0) {
		CLEAR_FLAG(F_CF);
		CLEAR_FLAG(F_OF);
	} else {
		SET_FLAG(F_CF);
		SET_FLAG(F_OF);
    }
}

/****************************************************************************
REMARKS:
Implements the IDIV instruction and side effects.
****************************************************************************/
void idiv_byte(u8 s)
{
    s32 dvd, div, mod;

	dvd = (s16)M.x86.R_AX;
	if (s == 0) {
		x86emu_intr_raise(0);
	return;
	}
	div = dvd / (s8)s;
	mod = dvd % (s8)s;
	if (abs(div) > 0x7f) {
		x86emu_intr_raise(0);
		return;
	}
	M.x86.R_AL = (s8) div;
	M.x86.R_AH = (s8) mod;
}

/****************************************************************************
REMARKS:
Implements the IDIV instruction and side effects.
****************************************************************************/
void idiv_word(u16 s)
{
	s32 dvd, div, mod;

	dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
	if (s == 0) {
		x86emu_intr_raise(0);
		return;
	}
	div = dvd / (s16)s;
	mod = dvd % (s16)s;
	if (abs(div) > 0x7fff) {
		x86emu_intr_raise(0);
		return;
	}
	CLEAR_FLAG(F_CF);
	CLEAR_FLAG(F_SF);
	CONDITIONAL_SET_FLAG(div == 0, F_ZF);
	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);

	M.x86.R_AX = (u16)div;
	M.x86.R_DX = (u16)mod;
}

/******

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?