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 + -
显示快捷键?