?? prim_ops.c
字號:
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); set_parity_flag(mod); 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); set_parity_flag(mod); M.x86.R_EAX = (u32)div; M.x86.R_EDX = (u32)mod;}/****************************************************************************REMARKS:Implements the DIV instruction and side effects.****************************************************************************/void div_byte(u8 s){ u32 dvd, div, mod; dvd = M.x86.R_AX; if (s == 0) { x86emu_intr_raise(0); return; } div = dvd / (u8)s; mod = dvd % (u8)s; if (abs(div) > 0xff) { x86emu_intr_raise(0); return; } M.x86.R_AL = (u8)div; M.x86.R_AH = (u8)mod;}/****************************************************************************REMARKS:Implements the DIV instruction and side effects.****************************************************************************/void div_word(u16 s){ u32 dvd, div, mod; dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX; if (s == 0) { x86emu_intr_raise(0); return; } div = dvd / (u16)s; mod = dvd % (u16)s; if (abs(div) > 0xffff) { x86emu_intr_raise(0); return; } CLEAR_FLAG(F_CF); CLEAR_FLAG(F_SF); CONDITIONAL_SET_FLAG(div == 0, F_ZF); set_parity_flag(mod); M.x86.R_AX = (u16)div; M.x86.R_DX = (u16)mod;}/****************************************************************************REMARKS:Implements the DIV instruction and side effects.****************************************************************************/void div_long(u32 s){#ifdef __HAS_LONG_LONG__ u64 dvd, div, mod; dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX; if (s == 0) { x86emu_intr_raise(0); return; } div = dvd / (u32)s; mod = dvd % (u32)s; if (abs(div) > 0xffffffff) { 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 h_s = s; u32 l_s = 0; int counter = 32; int carry; if (s == 0) { x86emu_intr_raise(0); return; } do { div <<= 1; carry = (l_dvd >= l_s) ? 0 : 1; if (h_dvd < (h_s + carry)) { h_s >>= 1; l_s = s << (--counter); continue; } else { h_dvd -= (h_s + carry); l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1) : (l_dvd - l_s); h_s >>= 1; l_s = s << (--counter); div |= 1; continue; } } while (counter > -1); /* overflow */ if (h_dvd || (l_dvd > s)) { x86emu_intr_raise(0); return; } mod = l_dvd;#endif CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF); SET_FLAG(F_ZF); set_parity_flag(mod); M.x86.R_EAX = (u32)div; M.x86.R_EDX = (u32)mod;}/****************************************************************************REMARKS:Implements the IN string instruction and side effects.****************************************************************************/static void single_in(int size){ if(size == 1) store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inb)(M.x86.R_DX)); else if (size == 2) store_data_word_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inw)(M.x86.R_DX)); else store_data_long_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inl)(M.x86.R_DX));}void ins(int size){ int inc = size; if (ACCESS_FLAG(F_DF)) { inc = -size; } if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { /* dont care whether REPE or REPNE */ /* in until CX is ZERO. */ u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ? M.x86.R_ECX : M.x86.R_CX); while (count--) { single_in(size); M.x86.R_DI += inc; } M.x86.R_CX = 0; if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ECX = 0; } M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); } else { single_in(size); M.x86.R_DI += inc; }}/****************************************************************************REMARKS:Implements the OUT string instruction and side effects.****************************************************************************/static void single_out(int size){ if(size == 1) (*sys_outb)(M.x86.R_DX,fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI)); else if (size == 2) (*sys_outw)(M.x86.R_DX,fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI)); else (*sys_outl)(M.x86.R_DX,fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));}void outs(int size){ int inc = size; if (ACCESS_FLAG(F_DF)) { inc = -size; } if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { /* dont care whether REPE or REPNE */ /* out until CX is ZERO. */ u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ? M.x86.R_ECX : M.x86.R_CX); while (count--) { single_out(size); M.x86.R_SI += inc; } M.x86.R_CX = 0; if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ECX = 0; } M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); } else { single_out(size); M.x86.R_SI += inc; }}/****************************************************************************PARAMETERS:addr - Address to fetch word fromREMARKS:Fetches a word from emulator memory using an absolute address.****************************************************************************/u16 mem_access_word(int addr){DB( if (CHECK_MEM_ACCESS()) x86emu_check_mem_access(addr);) return (*sys_rdw)(addr);}/****************************************************************************REMARKS:Pushes a word onto the stack.NOTE: Do not inline this, as (*sys_wrX) is already inline!****************************************************************************/void push_word(u16 w){DB( if (CHECK_SP_ACCESS()) x86emu_check_sp_access();) M.x86.R_SP -= 2; (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);}/****************************************************************************REMARKS:Pushes a long onto the stack.NOTE: Do not inline this, as (*sys_wrX) is already inline!****************************************************************************/void push_long(u32 w){DB( if (CHECK_SP_ACCESS()) x86emu_check_sp_access();) M.x86.R_SP -= 4; (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);}/****************************************************************************REMARKS:Pops a word from the stack.NOTE: Do not inline this, as (*sys_rdX) is already inline!****************************************************************************/u16 pop_word(void){ u16 res;DB( if (CHECK_SP_ACCESS()) x86emu_check_sp_access();) res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP); M.x86.R_SP += 2; return res;}/****************************************************************************REMARKS:Pops a long from the stack.NOTE: Do not inline this, as (*sys_rdX) is already inline!****************************************************************************/u32 pop_long(void){ u32 res;DB( if (CHECK_SP_ACCESS()) x86emu_check_sp_access();) res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP); M.x86.R_SP += 4; return res;}#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -