?? prim_ops.c
字號:
/****************************************************************************** Realmode X86 Emulator Library** Copyright (C) 1991-2004 SciTech Software, Inc.* Copyright (C) David Mosberger-Tang* Copyright (C) 1999 Egbert Eich** ========================================================================** Permission to use, copy, modify, distribute, and sell this software and* its documentation for any purpose is hereby granted without fee,* provided that the above copyright notice appear in all copies and that* both that copyright notice and this permission notice appear in* supporting documentation, and that the name of the authors not be used* in advertising or publicity pertaining to distribution of the software* without specific, written prior permission. The authors makes no* representations about the suitability of this software for any purpose.* It is provided "as is" without express or implied warranty.** THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR* PERFORMANCE OF THIS SOFTWARE.** ========================================================================** Language: ANSI C* Environment: Any* Developer: Kendall Bennett** Description: This file contains the code to implement the primitive* machine operations used by the emulation code in ops.c** Carry Chain Calculation** This represents a somewhat expensive calculation which is* apparently required to emulate the setting of the OF343364 and AF flag.* The latter is not so important, but the former is. The overflow* flag is the XOR of the top two bits of the carry chain for an* addition (similar for subtraction). Since we do not want to* simulate the addition in a bitwise manner, we try to calculate the* carry chain given the two operands and the result.** So, given the following table, which represents the addition of two* bits, we can derive a formula for the carry chain.** a b cin r cout* 0 0 0 0 0* 0 0 1 1 0* 0 1 0 1 0* 0 1 1 0 1* 1 0 0 1 0* 1 0 1 0 1* 1 1 0 0 1* 1 1 1 1 1** Construction of table for cout:** ab* r \ 00 01 11 10* |------------------* 0 | 0 1 1 1* 1 | 0 0 1 0** By inspection, one gets: cc = ab + r'(a + b)** That represents alot of operations, but NO CHOICE....** Borrow Chain Calculation.** The following table represents the subtraction of two bits, from* which we can derive a formula for the borrow chain.** a b bin r bout* 0 0 0 0 0* 0 0 1 1 1* 0 1 0 1 1* 0 1 1 0 1* 1 0 0 1 0* 1 0 1 0 0* 1 1 0 0 0* 1 1 1 1 1** Construction of table for cout:** ab* r \ 00 01 11 10* |------------------* 0 | 0 1 0 0* 1 | 1 1 1 0** By inspection, one gets: bc = a'b + r(a' + b)*****************************************************************************/#include <common.h>#define PRIM_OPS_NO_REDEFINE_ASM#if defined(CONFIG_BIOSEMU)#include "x86emu/x86emui.h"/*------------------------- Global Variables ------------------------------*/static u32 x86emu_parity_tab[8] ={ 0x96696996, 0x69969669, 0x69969669, 0x96696996, 0x69969669, 0x96696996, 0x96696996, 0x69969669,};#define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)/*----------------------------- Implementation ----------------------------*/int abs(int v){ return (v>0)?v:-v;}/*----------------------------- Implementation ----------------------------*//*--------- Side effects helper functions -------*//****************************************************************************REMARKS:implements side efects for byte operations that don't overflow****************************************************************************/static void set_parity_flag(u32 res){ CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);}static void set_szp_flags_8(u8 res){ CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); set_parity_flag(res);}static void set_szp_flags_16(u16 res){ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); set_parity_flag(res);}static void set_szp_flags_32(u32 res){ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); set_parity_flag(res);}static void no_carry_byte_side_eff(u8 res){ CLEAR_FLAG(F_OF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); set_szp_flags_8(res);}static void no_carry_word_side_eff(u16 res){ CLEAR_FLAG(F_OF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); set_szp_flags_16(res);}static void no_carry_long_side_eff(u32 res){ CLEAR_FLAG(F_OF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); set_szp_flags_32(res);}static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry){ u32 cc; cc = (s & d) | ((~res) & (s | d)); CONDITIONAL_SET_FLAG(XOR2(cc >> (bits - 2)), F_OF); CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); if (set_carry) { CONDITIONAL_SET_FLAG(res & (1 << bits), F_CF); }}static void calc_borrow_chain(int bits, u32 d, u32 s, u32 res, int set_carry){ u32 bc; bc = (res & (~d | s)) | (~d & s); CONDITIONAL_SET_FLAG(XOR2(bc >> (bits - 2)), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); if (set_carry) { CONDITIONAL_SET_FLAG(bc & (1 << (bits - 1)), F_CF); }}/****************************************************************************REMARKS:Implements the AAA instruction and side effects.****************************************************************************/u16 aaa_word(u16 d){ u16 res; if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { d += 0x6; d += 0x100; SET_FLAG(F_AF); SET_FLAG(F_CF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); } res = (u16)(d & 0xFF0F); set_szp_flags_16(res); return res;}/****************************************************************************REMARKS:Implements the AAA instruction and side effects.****************************************************************************/u16 aas_word(u16 d){ u16 res; if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { d -= 0x6; d -= 0x100; SET_FLAG(F_AF); SET_FLAG(F_CF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); } res = (u16)(d & 0xFF0F); set_szp_flags_16(res); return res;}/****************************************************************************REMARKS:Implements the AAD instruction and side effects.****************************************************************************/u16 aad_word(u16 d){ u16 l; u8 hb, lb; hb = (u8)((d >> 8) & 0xff); lb = (u8)((d & 0xff)); l = (u16)((lb + 10 * hb) & 0xFF); no_carry_byte_side_eff(l & 0xFF); return l;}/****************************************************************************REMARKS:Implements the AAM instruction and side effects.****************************************************************************/u16 aam_word(u8 d){ u16 h, l; h = (u16)(d / 10); l = (u16)(d % 10); l |= (u16)(h << 8); no_carry_byte_side_eff(l & 0xFF); return l;}/****************************************************************************REMARKS:Implements the ADC instruction and side effects.****************************************************************************/u8 adc_byte(u8 d, u8 s){ u32 res; /* all operands in native machine order */ res = d + s; if (ACCESS_FLAG(F_CF)) res++; set_szp_flags_8(res); calc_carry_chain(8,s,d,res,1); return (u8)res;}/****************************************************************************REMARKS:Implements the ADC instruction and side effects.****************************************************************************/u16 adc_word(u16 d, u16 s){ u32 res; /* all operands in native machine order */ res = d + s; if (ACCESS_FLAG(F_CF)) res++; set_szp_flags_16((u16)res); calc_carry_chain(16,s,d,res,1); return (u16)res;}/****************************************************************************REMARKS:Implements the ADC instruction and side effects.****************************************************************************/u32 adc_long(u32 d, u32 s){ u32 lo; /* all operands in native machine order */ u32 hi; u32 res; lo = (d & 0xFFFF) + (s & 0xFFFF); res = d + s; if (ACCESS_FLAG(F_CF)) { lo++; res++; } hi = (lo >> 16) + (d >> 16) + (s >> 16); set_szp_flags_32(res); calc_carry_chain(32,s,d,res,0); CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); return res;}/****************************************************************************REMARKS:Implements the ADD instruction and side effects.****************************************************************************/u8 add_byte(u8 d, u8 s){ u32 res; /* all operands in native machine order */ res = d + s; set_szp_flags_8((u8)res); calc_carry_chain(8,s,d,res,1); return (u8)res;}/****************************************************************************REMARKS:Implements the ADD instruction and side effects.****************************************************************************/u16 add_word(u16 d, u16 s){ u32 res; /* all operands in native machine order */ res = d + s; set_szp_flags_16((u16)res); calc_carry_chain(16,s,d,res,1); return (u16)res;}/****************************************************************************REMARKS:Implements the ADD instruction and side effects.****************************************************************************/u32 add_long(u32 d, u32 s){ u32 res; res = d + s; set_szp_flags_32(res); calc_carry_chain(32,s,d,res,0); CONDITIONAL_SET_FLAG(res < d || res < s, F_CF); return res;}/****************************************************************************REMARKS:Implements the AND instruction and side effects.****************************************************************************/u8 and_byte(u8 d, u8 s){ u8 res; /* all operands in native machine order */ res = d & s; no_carry_byte_side_eff(res); return res;}/****************************************************************************REMARKS:Implements the AND instruction and side effects.****************************************************************************/u16 and_word(u16 d, u16 s){ u16 res; /* all operands in native machine order */ res = d & s; no_carry_word_side_eff(res); return res;}/****************************************************************************REMARKS:Implements the AND instruction and side effects.****************************************************************************/u32 and_long(u32 d, u32 s){ u32 res; /* all operands in native machine order */ res = d & s; no_carry_long_side_eff(res); return res;}/****************************************************************************REMARKS:Implements the CMP instruction and side effects.****************************************************************************/u8 cmp_byte(u8 d, u8 s){ u32 res; /* all operands in native machine order */ res = d - s; set_szp_flags_8((u8)res); calc_borrow_chain(8, d, s, res, 1); return d;}/****************************************************************************REMARKS:Implements the CMP instruction and side effects.****************************************************************************/u16 cmp_word(u16 d, u16 s){ u32 res; /* all operands in native machine order */ res = d - s; set_szp_flags_16((u16)res); calc_borrow_chain(16, d, s, res, 1); return d;}/****************************************************************************REMARKS:Implements the CMP instruction and side effects.****************************************************************************/u32 cmp_long(u32 d, u32 s){ u32 res; /* all operands in native machine order */ res = d - s; set_szp_flags_32(res); calc_borrow_chain(32, d, s, res, 1); return d;}/****************************************************************************REMARKS:Implements the DAA instruction and side effects.****************************************************************************/u8 daa_byte(u8 d){ u32 res = d;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -