📄 prim_ops.c
字号:
/****************************************************************************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;}/****************************************************************************REMARKS:Implements the IDIV instruction and side effects.****************************************************************************/void idiv_long(u32 s){#ifdef __HAS_LONG_LONG__ s64 dvd, div, mod; dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX; if (s == 0) { x86emu_intr_raise(0); return; } div = dvd / (s32)s; mod = dvd % (s32)s; if (abs(div) > 0x7fffffff) { x86emu_intr_raise(0); return; }#else s32 div = 0, mod; s32 h_dvd = M.x86.R_EDX; u32 l_dvd = M.x86.R_EAX; u32 abs_s = s & 0x7FFFFFFF; u32 abs_h_dvd = h_dvd & 0x7FFFFFFF; u32 h_s = abs_s >> 1; u32 l_s = abs_s << 31; int counter = 31; int carry; if (s == 0) { x86emu_intr_raise(0); return; } do { div <<= 1; carry = (l_dvd >= l_s) ? 0 : 1; if (abs_h_dvd < (h_s + carry)) { h_s >>= 1; l_s = abs_s << (--counter); continue; } else { abs_h_dvd -= (h_s + carry); l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1) : (l_dvd - l_s); h_s >>= 1; l_s = abs_s << (--counter); div |= 1; continue; } } while (counter > -1); /* overflow */ if (abs_h_dvd || (l_dvd > abs_s)) { x86emu_intr_raise(0); return; } /* sign */ div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000)); mod = l_dvd;#endif CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF); SET_FLAG(F_ZF); CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); M.x86.R_EAX = (u32)div; M.x86.R_EDX =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -