2453 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			2453 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			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;
 | 
						|
    if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
 | 
						|
	res += 6;
 | 
						|
	SET_FLAG(F_AF);
 | 
						|
    }
 | 
						|
    if (res > 0x9F || ACCESS_FLAG(F_CF)) {
 | 
						|
	res += 0x60;
 | 
						|
	SET_FLAG(F_CF);
 | 
						|
    }
 | 
						|
    set_szp_flags_8((u8)res);
 | 
						|
    return (u8)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the DAS instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 das_byte(u8 d)
 | 
						|
{
 | 
						|
    if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
 | 
						|
	d -= 6;
 | 
						|
	SET_FLAG(F_AF);
 | 
						|
    }
 | 
						|
    if (d > 0x9F || ACCESS_FLAG(F_CF)) {
 | 
						|
	d -= 0x60;
 | 
						|
	SET_FLAG(F_CF);
 | 
						|
    }
 | 
						|
    set_szp_flags_8(d);
 | 
						|
    return d;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the DEC instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 dec_byte(u8 d)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
 | 
						|
    res = d - 1;
 | 
						|
    set_szp_flags_8((u8)res);
 | 
						|
    calc_borrow_chain(8, d, 1, res, 0);
 | 
						|
 | 
						|
    return (u8)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the DEC instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 dec_word(u16 d)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
 | 
						|
    res = d - 1;
 | 
						|
    set_szp_flags_16((u16)res);
 | 
						|
    calc_borrow_chain(16, d, 1, res, 0);
 | 
						|
 | 
						|
    return (u16)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the DEC instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 dec_long(u32 d)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
 | 
						|
    res = d - 1;
 | 
						|
 | 
						|
    set_szp_flags_32(res);
 | 
						|
    calc_borrow_chain(32, d, 1, res, 0);
 | 
						|
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the INC instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 inc_byte(u8 d)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
 | 
						|
    res = d + 1;
 | 
						|
    set_szp_flags_8((u8)res);
 | 
						|
    calc_carry_chain(8, d, 1, res, 0);
 | 
						|
 | 
						|
    return (u8)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the INC instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 inc_word(u16 d)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
 | 
						|
    res = d + 1;
 | 
						|
    set_szp_flags_16((u16)res);
 | 
						|
    calc_carry_chain(16, d, 1, res, 0);
 | 
						|
 | 
						|
    return (u16)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the INC instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 inc_long(u32 d)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
 | 
						|
    res = d + 1;
 | 
						|
    set_szp_flags_32(res);
 | 
						|
    calc_carry_chain(32, d, 1, res, 0);
 | 
						|
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the OR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 or_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 OR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 or_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 OR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 or_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 OR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 neg_byte(u8 s)
 | 
						|
{
 | 
						|
    u8 res;
 | 
						|
 | 
						|
    CONDITIONAL_SET_FLAG(s != 0, F_CF);
 | 
						|
    res = (u8)-s;
 | 
						|
    set_szp_flags_8(res);
 | 
						|
    calc_borrow_chain(8, 0, s, res, 0);
 | 
						|
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the OR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 neg_word(u16 s)
 | 
						|
{
 | 
						|
    u16 res;
 | 
						|
 | 
						|
    CONDITIONAL_SET_FLAG(s != 0, F_CF);
 | 
						|
    res = (u16)-s;
 | 
						|
    set_szp_flags_16((u16)res);
 | 
						|
    calc_borrow_chain(16, 0, s, res, 0);
 | 
						|
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the OR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 neg_long(u32 s)
 | 
						|
{
 | 
						|
    u32 res;
 | 
						|
 | 
						|
    CONDITIONAL_SET_FLAG(s != 0, F_CF);
 | 
						|
    res = (u32)-s;
 | 
						|
    set_szp_flags_32(res);
 | 
						|
    calc_borrow_chain(32, 0, s, res, 0);
 | 
						|
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the NOT instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 not_byte(u8 s)
 | 
						|
{
 | 
						|
    return ~s;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the NOT instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 not_word(u16 s)
 | 
						|
{
 | 
						|
    return ~s;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the NOT instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 not_long(u32 s)
 | 
						|
{
 | 
						|
    return ~s;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the RCL instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 rcl_byte(u8 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int res, cnt, mask, cf;
 | 
						|
 | 
						|
    /* s is the rotate distance.  It varies from 0 - 8. */
 | 
						|
    /* have
 | 
						|
 | 
						|
       CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
 | 
						|
 | 
						|
       want to rotate through the carry by "s" bits.  We could
 | 
						|
       loop, but that's inefficient.  So the width is 9,
 | 
						|
       and we split into three parts:
 | 
						|
 | 
						|
       The new carry flag   (was B_n)
 | 
						|
       the stuff in B_n-1 .. B_0
 | 
						|
       the stuff in B_7 .. B_n+1
 | 
						|
 | 
						|
       The new rotate is done mod 9, and given this,
 | 
						|
       for a rotation of n bits (mod 9) the new carry flag is
 | 
						|
       then located n bits from the MSB.  The low part is
 | 
						|
       then shifted up cnt bits, and the high part is or'd
 | 
						|
       in.  Using CAPS for new values, and lowercase for the
 | 
						|
       original values, this can be expressed as:
 | 
						|
 | 
						|
       IF n > 0
 | 
						|
       1) CF <-	 b_(8-n)
 | 
						|
       2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
 | 
						|
       3) B_(n-1) <- cf
 | 
						|
       4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
 | 
						|
     */
 | 
						|
    res = d;
 | 
						|
    if ((cnt = s % 9) != 0) {
 | 
						|
	/* extract the new CARRY FLAG. */
 | 
						|
	/* CF <-  b_(8-n)	      */
 | 
						|
	cf = (d >> (8 - cnt)) & 0x1;
 | 
						|
 | 
						|
	/* get the low stuff which rotated
 | 
						|
	   into the range B_7 .. B_cnt */
 | 
						|
	/* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0  */
 | 
						|
	/* note that the right hand side done by the mask */
 | 
						|
	res = (d << cnt) & 0xff;
 | 
						|
 | 
						|
	/* now the high stuff which rotated around
 | 
						|
	   into the positions B_cnt-2 .. B_0 */
 | 
						|
	/* B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1)) */
 | 
						|
	/* shift it downward, 7-(n-2) = 9-n positions.
 | 
						|
	   and mask off the result before or'ing in.
 | 
						|
	 */
 | 
						|
	mask = (1 << (cnt - 1)) - 1;
 | 
						|
	res |= (d >> (9 - cnt)) & mask;
 | 
						|
 | 
						|
	/* if the carry flag was set, or it in.	 */
 | 
						|
	if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
 | 
						|
	    /*	B_(n-1) <- cf */
 | 
						|
	    res |= 1 << (cnt - 1);
 | 
						|
	}
 | 
						|
	/* set the new carry flag, based on the variable "cf" */
 | 
						|
	CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	/* OVERFLOW is set *IFF* cnt==1, then it is the
 | 
						|
	   xor of CF and the most significant bit.  Blecck. */
 | 
						|
	/* parenthesized this expression since it appears to
 | 
						|
	   be causing OF to be misset */
 | 
						|
	CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
 | 
						|
			     F_OF);
 | 
						|
 | 
						|
    }
 | 
						|
    return (u8)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the RCL instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 rcl_word(u16 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int res, cnt, mask, cf;
 | 
						|
 | 
						|
    res = d;
 | 
						|
    if ((cnt = s % 17) != 0) {
 | 
						|
	cf = (d >> (16 - cnt)) & 0x1;
 | 
						|
	res = (d << cnt) & 0xffff;
 | 
						|
	mask = (1 << (cnt - 1)) - 1;
 | 
						|
	res |= (d >> (17 - cnt)) & mask;
 | 
						|
	if (ACCESS_FLAG(F_CF)) {
 | 
						|
	    res |= 1 << (cnt - 1);
 | 
						|
	}
 | 
						|
	CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
 | 
						|
			     F_OF);
 | 
						|
    }
 | 
						|
    return (u16)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the RCL instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 rcl_long(u32 d, u8 s)
 | 
						|
{
 | 
						|
    u32 res, cnt, mask, cf;
 | 
						|
 | 
						|
    res = d;
 | 
						|
    if ((cnt = s % 33) != 0) {
 | 
						|
	cf = (d >> (32 - cnt)) & 0x1;
 | 
						|
	res = (d << cnt) & 0xffffffff;
 | 
						|
	mask = (1 << (cnt - 1)) - 1;
 | 
						|
	res |= (d >> (33 - cnt)) & mask;
 | 
						|
	if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
 | 
						|
	    res |= 1 << (cnt - 1);
 | 
						|
	}
 | 
						|
	CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
 | 
						|
			     F_OF);
 | 
						|
    }
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the RCR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 rcr_byte(u8 d, u8 s)
 | 
						|
{
 | 
						|
    u32 res, cnt;
 | 
						|
    u32 mask, cf, ocf = 0;
 | 
						|
 | 
						|
    /* rotate right through carry */
 | 
						|
    /*
 | 
						|
       s is the rotate distance.  It varies from 0 - 8.
 | 
						|
       d is the byte object rotated.
 | 
						|
 | 
						|
       have
 | 
						|
 | 
						|
       CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
 | 
						|
 | 
						|
       The new rotate is done mod 9, and given this,
 | 
						|
       for a rotation of n bits (mod 9) the new carry flag is
 | 
						|
       then located n bits from the LSB.  The low part is
 | 
						|
       then shifted up cnt bits, and the high part is or'd
 | 
						|
       in.  Using CAPS for new values, and lowercase for the
 | 
						|
       original values, this can be expressed as:
 | 
						|
 | 
						|
       IF n > 0
 | 
						|
       1) CF <-	 b_(n-1)
 | 
						|
       2) B_(8-(n+1)) .. B_(0)	<-  b_(7) .. b_(n)
 | 
						|
       3) B_(8-n) <- cf
 | 
						|
       4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
 | 
						|
     */
 | 
						|
    res = d;
 | 
						|
    if ((cnt = s % 9) != 0) {
 | 
						|
	/* extract the new CARRY FLAG. */
 | 
						|
	/* CF <-  b_(n-1)	       */
 | 
						|
	if (cnt == 1) {
 | 
						|
	    cf = d & 0x1;
 | 
						|
	    /* note hackery here.  Access_flag(..) evaluates to either
 | 
						|
	       0 if flag not set
 | 
						|
	       non-zero if flag is set.
 | 
						|
	       doing access_flag(..) != 0 casts that into either
 | 
						|
	       0..1 in any representation of the flags register
 | 
						|
	       (i.e. packed bit array or unpacked.)
 | 
						|
	     */
 | 
						|
	    ocf = ACCESS_FLAG(F_CF) != 0;
 | 
						|
	} else
 | 
						|
	    cf = (d >> (cnt - 1)) & 0x1;
 | 
						|
 | 
						|
	/* B_(8-(n+1)) .. B_(0)	 <-  b_(7) .. b_n  */
 | 
						|
	/* note that the right hand side done by the mask
 | 
						|
	   This is effectively done by shifting the
 | 
						|
	   object to the right.	 The result must be masked,
 | 
						|
	   in case the object came in and was treated
 | 
						|
	   as a negative number.  Needed??? */
 | 
						|
 | 
						|
	mask = (1 << (8 - cnt)) - 1;
 | 
						|
	res = (d >> cnt) & mask;
 | 
						|
 | 
						|
	/* now the high stuff which rotated around
 | 
						|
	   into the positions B_cnt-2 .. B_0 */
 | 
						|
	/* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
 | 
						|
	/* shift it downward, 7-(n-2) = 9-n positions.
 | 
						|
	   and mask off the result before or'ing in.
 | 
						|
	 */
 | 
						|
	res |= (d << (9 - cnt));
 | 
						|
 | 
						|
	/* if the carry flag was set, or it in.	 */
 | 
						|
	if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
 | 
						|
	    /*	B_(8-n) <- cf */
 | 
						|
	    res |= 1 << (8 - cnt);
 | 
						|
	}
 | 
						|
	/* set the new carry flag, based on the variable "cf" */
 | 
						|
	CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	/* OVERFLOW is set *IFF* cnt==1, then it is the
 | 
						|
	   xor of CF and the most significant bit.  Blecck. */
 | 
						|
	/* parenthesized... */
 | 
						|
	if (cnt == 1) {
 | 
						|
	    CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
 | 
						|
				 F_OF);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return (u8)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the RCR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 rcr_word(u16 d, u8 s)
 | 
						|
{
 | 
						|
    u32 res, cnt;
 | 
						|
    u32 mask, cf, ocf = 0;
 | 
						|
 | 
						|
    /* rotate right through carry */
 | 
						|
    res = d;
 | 
						|
    if ((cnt = s % 17) != 0) {
 | 
						|
	if (cnt == 1) {
 | 
						|
	    cf = d & 0x1;
 | 
						|
	    ocf = ACCESS_FLAG(F_CF) != 0;
 | 
						|
	} else
 | 
						|
	    cf = (d >> (cnt - 1)) & 0x1;
 | 
						|
	mask = (1 << (16 - cnt)) - 1;
 | 
						|
	res = (d >> cnt) & mask;
 | 
						|
	res |= (d << (17 - cnt));
 | 
						|
	if (ACCESS_FLAG(F_CF)) {
 | 
						|
	    res |= 1 << (16 - cnt);
 | 
						|
	}
 | 
						|
	CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	if (cnt == 1) {
 | 
						|
	    CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
 | 
						|
				 F_OF);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return (u16)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the RCR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 rcr_long(u32 d, u8 s)
 | 
						|
{
 | 
						|
    u32 res, cnt;
 | 
						|
    u32 mask, cf, ocf = 0;
 | 
						|
 | 
						|
    /* rotate right through carry */
 | 
						|
    res = d;
 | 
						|
    if ((cnt = s % 33) != 0) {
 | 
						|
	if (cnt == 1) {
 | 
						|
	    cf = d & 0x1;
 | 
						|
	    ocf = ACCESS_FLAG(F_CF) != 0;
 | 
						|
	} else
 | 
						|
	    cf = (d >> (cnt - 1)) & 0x1;
 | 
						|
	mask = (1 << (32 - cnt)) - 1;
 | 
						|
	res = (d >> cnt) & mask;
 | 
						|
	if (cnt != 1)
 | 
						|
	    res |= (d << (33 - cnt));
 | 
						|
	if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
 | 
						|
	    res |= 1 << (32 - cnt);
 | 
						|
	}
 | 
						|
	CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	if (cnt == 1) {
 | 
						|
	    CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
 | 
						|
				 F_OF);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the ROL instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 rol_byte(u8 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int res, cnt, mask;
 | 
						|
 | 
						|
    /* rotate left */
 | 
						|
    /*
 | 
						|
       s is the rotate distance.  It varies from 0 - 8.
 | 
						|
       d is the byte object rotated.
 | 
						|
 | 
						|
       have
 | 
						|
 | 
						|
       CF  B_7 ... B_0
 | 
						|
 | 
						|
       The new rotate is done mod 8.
 | 
						|
       Much simpler than the "rcl" or "rcr" operations.
 | 
						|
 | 
						|
       IF n > 0
 | 
						|
       1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0)
 | 
						|
       2) B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n)
 | 
						|
     */
 | 
						|
    res = d;
 | 
						|
    if ((cnt = s % 8) != 0) {
 | 
						|
	/* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
 | 
						|
	res = (d << cnt);
 | 
						|
 | 
						|
	/* B_(n-1) .. B_(0) <-	b_(7) .. b_(8-n) */
 | 
						|
	mask = (1 << cnt) - 1;
 | 
						|
	res |= (d >> (8 - cnt)) & mask;
 | 
						|
 | 
						|
	/* set the new carry flag, Note that it is the low order
 | 
						|
	   bit of the result!!!				      */
 | 
						|
	CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
 | 
						|
	/* OVERFLOW is set *IFF* s==1, then it is the
 | 
						|
	   xor of CF and the most significant bit.  Blecck. */
 | 
						|
	CONDITIONAL_SET_FLAG(s == 1 &&
 | 
						|
			     XOR2((res & 0x1) + ((res >> 6) & 0x2)),
 | 
						|
			     F_OF);
 | 
						|
    } if (s != 0) {
 | 
						|
	/* set the new carry flag, Note that it is the low order
 | 
						|
	   bit of the result!!!				      */
 | 
						|
	CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
 | 
						|
    }
 | 
						|
    return (u8)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the ROL instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 rol_word(u16 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int res, cnt, mask;
 | 
						|
 | 
						|
    res = d;
 | 
						|
    if ((cnt = s % 16) != 0) {
 | 
						|
	res = (d << cnt);
 | 
						|
	mask = (1 << cnt) - 1;
 | 
						|
	res |= (d >> (16 - cnt)) & mask;
 | 
						|
	CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
 | 
						|
	CONDITIONAL_SET_FLAG(s == 1 &&
 | 
						|
			     XOR2((res & 0x1) + ((res >> 14) & 0x2)),
 | 
						|
			     F_OF);
 | 
						|
    } if (s != 0) {
 | 
						|
	/* set the new carry flag, Note that it is the low order
 | 
						|
	   bit of the result!!!				      */
 | 
						|
	CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
 | 
						|
    }
 | 
						|
    return (u16)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the ROL instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 rol_long(u32 d, u8 s)
 | 
						|
{
 | 
						|
    u32 res, cnt, mask;
 | 
						|
 | 
						|
    res = d;
 | 
						|
    if ((cnt = s % 32) != 0) {
 | 
						|
	res = (d << cnt);
 | 
						|
	mask = (1 << cnt) - 1;
 | 
						|
	res |= (d >> (32 - cnt)) & mask;
 | 
						|
	CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
 | 
						|
	CONDITIONAL_SET_FLAG(s == 1 &&
 | 
						|
			     XOR2((res & 0x1) + ((res >> 30) & 0x2)),
 | 
						|
			     F_OF);
 | 
						|
    } if (s != 0) {
 | 
						|
	/* set the new carry flag, Note that it is the low order
 | 
						|
	   bit of the result!!!				      */
 | 
						|
	CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
 | 
						|
    }
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the ROR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 ror_byte(u8 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int res, cnt, mask;
 | 
						|
 | 
						|
    /* rotate right */
 | 
						|
    /*
 | 
						|
       s is the rotate distance.  It varies from 0 - 8.
 | 
						|
       d is the byte object rotated.
 | 
						|
 | 
						|
       have
 | 
						|
 | 
						|
       B_7 ... B_0
 | 
						|
 | 
						|
       The rotate is done mod 8.
 | 
						|
 | 
						|
       IF n > 0
 | 
						|
       1) B_(8-(n+1)) .. B_(0)	<-  b_(7) .. b_(n)
 | 
						|
       2) B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0)
 | 
						|
     */
 | 
						|
    res = d;
 | 
						|
    if ((cnt = s % 8) != 0) {		/* not a typo, do nada if cnt==0 */
 | 
						|
	/* B_(7) .. B_(8-n) <-	b_(n-1) .. b_(0) */
 | 
						|
	res = (d << (8 - cnt));
 | 
						|
 | 
						|
	/* B_(8-(n+1)) .. B_(0)	 <-  b_(7) .. b_(n) */
 | 
						|
	mask = (1 << (8 - cnt)) - 1;
 | 
						|
	res |= (d >> (cnt)) & mask;
 | 
						|
 | 
						|
	/* set the new carry flag, Note that it is the low order
 | 
						|
	   bit of the result!!!				      */
 | 
						|
	CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
 | 
						|
	/* OVERFLOW is set *IFF* s==1, then it is the
 | 
						|
	   xor of the two most significant bits.  Blecck. */
 | 
						|
	CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
 | 
						|
    } else if (s != 0) {
 | 
						|
	/* set the new carry flag, Note that it is the low order
 | 
						|
	   bit of the result!!!				      */
 | 
						|
	CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
 | 
						|
    }
 | 
						|
    return (u8)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the ROR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 ror_word(u16 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int res, cnt, mask;
 | 
						|
 | 
						|
    res = d;
 | 
						|
    if ((cnt = s % 16) != 0) {
 | 
						|
	res = (d << (16 - cnt));
 | 
						|
	mask = (1 << (16 - cnt)) - 1;
 | 
						|
	res |= (d >> (cnt)) & mask;
 | 
						|
	CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
 | 
						|
	CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
 | 
						|
    } else if (s != 0) {
 | 
						|
	/* set the new carry flag, Note that it is the low order
 | 
						|
	   bit of the result!!!				      */
 | 
						|
	CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
 | 
						|
    }
 | 
						|
    return (u16)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the ROR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 ror_long(u32 d, u8 s)
 | 
						|
{
 | 
						|
    u32 res, cnt, mask;
 | 
						|
 | 
						|
    res = d;
 | 
						|
    if ((cnt = s % 32) != 0) {
 | 
						|
	res = (d << (32 - cnt));
 | 
						|
	mask = (1 << (32 - cnt)) - 1;
 | 
						|
	res |= (d >> (cnt)) & mask;
 | 
						|
	CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
 | 
						|
	CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
 | 
						|
    } else if (s != 0) {
 | 
						|
	/* set the new carry flag, Note that it is the low order
 | 
						|
	   bit of the result!!!				      */
 | 
						|
	CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
 | 
						|
    }
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SHL instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 shl_byte(u8 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int cnt, res, cf;
 | 
						|
 | 
						|
    if (s < 8) {
 | 
						|
	cnt = s % 8;
 | 
						|
 | 
						|
	/* last bit shifted out goes into carry flag */
 | 
						|
	if (cnt > 0) {
 | 
						|
	    res = d << cnt;
 | 
						|
	    cf = d & (1 << (8 - cnt));
 | 
						|
	    CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	    set_szp_flags_8((u8)res);
 | 
						|
	} else {
 | 
						|
	    res = (u8) d;
 | 
						|
	}
 | 
						|
 | 
						|
	if (cnt == 1) {
 | 
						|
	    /* Needs simplification. */
 | 
						|
	    CONDITIONAL_SET_FLAG(
 | 
						|
				    (((res & 0x80) == 0x80) ^
 | 
						|
				     (ACCESS_FLAG(F_CF) != 0)),
 | 
						|
	    /* was (M.x86.R_FLG&F_CF)==F_CF)), */
 | 
						|
				    F_OF);
 | 
						|
	} else {
 | 
						|
	    CLEAR_FLAG(F_OF);
 | 
						|
	}
 | 
						|
    } else {
 | 
						|
	res = 0;
 | 
						|
	CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
 | 
						|
	CLEAR_FLAG(F_OF);
 | 
						|
	CLEAR_FLAG(F_SF);
 | 
						|
	SET_FLAG(F_PF);
 | 
						|
	SET_FLAG(F_ZF);
 | 
						|
    }
 | 
						|
    return (u8)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SHL instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 shl_word(u16 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int cnt, res, cf;
 | 
						|
 | 
						|
    if (s < 16) {
 | 
						|
	cnt = s % 16;
 | 
						|
	if (cnt > 0) {
 | 
						|
	    res = d << cnt;
 | 
						|
	    cf = d & (1 << (16 - cnt));
 | 
						|
	    CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	    set_szp_flags_16((u16)res);
 | 
						|
	} else {
 | 
						|
	    res = (u16) d;
 | 
						|
	}
 | 
						|
 | 
						|
	if (cnt == 1) {
 | 
						|
	    CONDITIONAL_SET_FLAG(
 | 
						|
				    (((res & 0x8000) == 0x8000) ^
 | 
						|
				     (ACCESS_FLAG(F_CF) != 0)),
 | 
						|
				    F_OF);
 | 
						|
	} else {
 | 
						|
	    CLEAR_FLAG(F_OF);
 | 
						|
	}
 | 
						|
    } else {
 | 
						|
	res = 0;
 | 
						|
	CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
 | 
						|
	CLEAR_FLAG(F_OF);
 | 
						|
	CLEAR_FLAG(F_SF);
 | 
						|
	SET_FLAG(F_PF);
 | 
						|
	SET_FLAG(F_ZF);
 | 
						|
    }
 | 
						|
    return (u16)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SHL instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 shl_long(u32 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int cnt, res, cf;
 | 
						|
 | 
						|
    if (s < 32) {
 | 
						|
	cnt = s % 32;
 | 
						|
	if (cnt > 0) {
 | 
						|
	    res = d << cnt;
 | 
						|
	    cf = d & (1 << (32 - cnt));
 | 
						|
	    CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	    set_szp_flags_32((u32)res);
 | 
						|
	} else {
 | 
						|
	    res = d;
 | 
						|
	}
 | 
						|
	if (cnt == 1) {
 | 
						|
	    CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
 | 
						|
				  (ACCESS_FLAG(F_CF) != 0)), F_OF);
 | 
						|
	} else {
 | 
						|
	    CLEAR_FLAG(F_OF);
 | 
						|
	}
 | 
						|
    } else {
 | 
						|
	res = 0;
 | 
						|
	CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
 | 
						|
	CLEAR_FLAG(F_OF);
 | 
						|
	CLEAR_FLAG(F_SF);
 | 
						|
	SET_FLAG(F_PF);
 | 
						|
	SET_FLAG(F_ZF);
 | 
						|
    }
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SHR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 shr_byte(u8 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int cnt, res, cf;
 | 
						|
 | 
						|
    if (s < 8) {
 | 
						|
	cnt = s % 8;
 | 
						|
	if (cnt > 0) {
 | 
						|
	    cf = d & (1 << (cnt - 1));
 | 
						|
	    res = d >> cnt;
 | 
						|
	    CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	    set_szp_flags_8((u8)res);
 | 
						|
	} else {
 | 
						|
	    res = (u8) d;
 | 
						|
	}
 | 
						|
 | 
						|
	if (cnt == 1) {
 | 
						|
	    CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
 | 
						|
	} else {
 | 
						|
	    CLEAR_FLAG(F_OF);
 | 
						|
	}
 | 
						|
    } else {
 | 
						|
	res = 0;
 | 
						|
	CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
 | 
						|
	CLEAR_FLAG(F_OF);
 | 
						|
	CLEAR_FLAG(F_SF);
 | 
						|
	SET_FLAG(F_PF);
 | 
						|
	SET_FLAG(F_ZF);
 | 
						|
    }
 | 
						|
    return (u8)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SHR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 shr_word(u16 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int cnt, res, cf;
 | 
						|
 | 
						|
    if (s < 16) {
 | 
						|
	cnt = s % 16;
 | 
						|
	if (cnt > 0) {
 | 
						|
	    cf = d & (1 << (cnt - 1));
 | 
						|
	    res = d >> cnt;
 | 
						|
	    CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	    set_szp_flags_16((u16)res);
 | 
						|
	} else {
 | 
						|
	    res = d;
 | 
						|
	}
 | 
						|
 | 
						|
	if (cnt == 1) {
 | 
						|
	    CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
 | 
						|
	} else {
 | 
						|
	    CLEAR_FLAG(F_OF);
 | 
						|
	}
 | 
						|
    } else {
 | 
						|
	res = 0;
 | 
						|
	CLEAR_FLAG(F_CF);
 | 
						|
	CLEAR_FLAG(F_OF);
 | 
						|
	SET_FLAG(F_ZF);
 | 
						|
	CLEAR_FLAG(F_SF);
 | 
						|
	CLEAR_FLAG(F_PF);
 | 
						|
    }
 | 
						|
    return (u16)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SHR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 shr_long(u32 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int cnt, res, cf;
 | 
						|
 | 
						|
    if (s < 32) {
 | 
						|
	cnt = s % 32;
 | 
						|
	if (cnt > 0) {
 | 
						|
	    cf = d & (1 << (cnt - 1));
 | 
						|
	    res = d >> cnt;
 | 
						|
	    CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	    set_szp_flags_32((u32)res);
 | 
						|
	} else {
 | 
						|
	    res = d;
 | 
						|
	}
 | 
						|
	if (cnt == 1) {
 | 
						|
	    CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
 | 
						|
	} else {
 | 
						|
	    CLEAR_FLAG(F_OF);
 | 
						|
	}
 | 
						|
    } else {
 | 
						|
	res = 0;
 | 
						|
	CLEAR_FLAG(F_CF);
 | 
						|
	CLEAR_FLAG(F_OF);
 | 
						|
	SET_FLAG(F_ZF);
 | 
						|
	CLEAR_FLAG(F_SF);
 | 
						|
	CLEAR_FLAG(F_PF);
 | 
						|
    }
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SAR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 sar_byte(u8 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int cnt, res, cf, mask, sf;
 | 
						|
 | 
						|
    res = d;
 | 
						|
    sf = d & 0x80;
 | 
						|
    cnt = s % 8;
 | 
						|
    if (cnt > 0 && cnt < 8) {
 | 
						|
	mask = (1 << (8 - cnt)) - 1;
 | 
						|
	cf = d & (1 << (cnt - 1));
 | 
						|
	res = (d >> cnt) & mask;
 | 
						|
	CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	if (sf) {
 | 
						|
	    res |= ~mask;
 | 
						|
	}
 | 
						|
	set_szp_flags_8((u8)res);
 | 
						|
    } else if (cnt >= 8) {
 | 
						|
	if (sf) {
 | 
						|
	    res = 0xff;
 | 
						|
	    SET_FLAG(F_CF);
 | 
						|
	    CLEAR_FLAG(F_ZF);
 | 
						|
	    SET_FLAG(F_SF);
 | 
						|
	    SET_FLAG(F_PF);
 | 
						|
	} else {
 | 
						|
	    res = 0;
 | 
						|
	    CLEAR_FLAG(F_CF);
 | 
						|
	    SET_FLAG(F_ZF);
 | 
						|
	    CLEAR_FLAG(F_SF);
 | 
						|
	    CLEAR_FLAG(F_PF);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return (u8)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SAR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 sar_word(u16 d, u8 s)
 | 
						|
{
 | 
						|
    unsigned int cnt, res, cf, mask, sf;
 | 
						|
 | 
						|
    sf = d & 0x8000;
 | 
						|
    cnt = s % 16;
 | 
						|
    res = d;
 | 
						|
    if (cnt > 0 && cnt < 16) {
 | 
						|
	mask = (1 << (16 - cnt)) - 1;
 | 
						|
	cf = d & (1 << (cnt - 1));
 | 
						|
	res = (d >> cnt) & mask;
 | 
						|
	CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	if (sf) {
 | 
						|
	    res |= ~mask;
 | 
						|
	}
 | 
						|
	set_szp_flags_16((u16)res);
 | 
						|
    } else if (cnt >= 16) {
 | 
						|
	if (sf) {
 | 
						|
	    res = 0xffff;
 | 
						|
	    SET_FLAG(F_CF);
 | 
						|
	    CLEAR_FLAG(F_ZF);
 | 
						|
	    SET_FLAG(F_SF);
 | 
						|
	    SET_FLAG(F_PF);
 | 
						|
	} else {
 | 
						|
	    res = 0;
 | 
						|
	    CLEAR_FLAG(F_CF);
 | 
						|
	    SET_FLAG(F_ZF);
 | 
						|
	    CLEAR_FLAG(F_SF);
 | 
						|
	    CLEAR_FLAG(F_PF);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return (u16)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SAR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 sar_long(u32 d, u8 s)
 | 
						|
{
 | 
						|
    u32 cnt, res, cf, mask, sf;
 | 
						|
 | 
						|
    sf = d & 0x80000000;
 | 
						|
    cnt = s % 32;
 | 
						|
    res = d;
 | 
						|
    if (cnt > 0 && cnt < 32) {
 | 
						|
	mask = (1 << (32 - cnt)) - 1;
 | 
						|
	cf = d & (1 << (cnt - 1));
 | 
						|
	res = (d >> cnt) & mask;
 | 
						|
	CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	if (sf) {
 | 
						|
	    res |= ~mask;
 | 
						|
	}
 | 
						|
	set_szp_flags_32(res);
 | 
						|
    } else if (cnt >= 32) {
 | 
						|
	if (sf) {
 | 
						|
	    res = 0xffffffff;
 | 
						|
	    SET_FLAG(F_CF);
 | 
						|
	    CLEAR_FLAG(F_ZF);
 | 
						|
	    SET_FLAG(F_SF);
 | 
						|
	    SET_FLAG(F_PF);
 | 
						|
	} else {
 | 
						|
	    res = 0;
 | 
						|
	    CLEAR_FLAG(F_CF);
 | 
						|
	    SET_FLAG(F_ZF);
 | 
						|
	    CLEAR_FLAG(F_SF);
 | 
						|
	    CLEAR_FLAG(F_PF);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SHLD instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 shld_word (u16 d, u16 fill, u8 s)
 | 
						|
{
 | 
						|
    unsigned int cnt, res, cf;
 | 
						|
 | 
						|
    if (s < 16) {
 | 
						|
	cnt = s % 16;
 | 
						|
	if (cnt > 0) {
 | 
						|
	    res = (d << cnt) | (fill >> (16-cnt));
 | 
						|
	    cf = d & (1 << (16 - cnt));
 | 
						|
	    CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	    set_szp_flags_16((u16)res);
 | 
						|
	} else {
 | 
						|
	    res = d;
 | 
						|
	}
 | 
						|
	if (cnt == 1) {
 | 
						|
	    CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
 | 
						|
				  (ACCESS_FLAG(F_CF) != 0)), F_OF);
 | 
						|
	} else {
 | 
						|
	    CLEAR_FLAG(F_OF);
 | 
						|
	}
 | 
						|
    } else {
 | 
						|
	res = 0;
 | 
						|
	CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
 | 
						|
	CLEAR_FLAG(F_OF);
 | 
						|
	CLEAR_FLAG(F_SF);
 | 
						|
	SET_FLAG(F_PF);
 | 
						|
	SET_FLAG(F_ZF);
 | 
						|
    }
 | 
						|
    return (u16)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SHLD instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 shld_long (u32 d, u32 fill, u8 s)
 | 
						|
{
 | 
						|
    unsigned int cnt, res, cf;
 | 
						|
 | 
						|
    if (s < 32) {
 | 
						|
	cnt = s % 32;
 | 
						|
	if (cnt > 0) {
 | 
						|
	    res = (d << cnt) | (fill >> (32-cnt));
 | 
						|
	    cf = d & (1 << (32 - cnt));
 | 
						|
	    CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	    set_szp_flags_32((u32)res);
 | 
						|
	} else {
 | 
						|
	    res = d;
 | 
						|
	}
 | 
						|
	if (cnt == 1) {
 | 
						|
	    CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
 | 
						|
				  (ACCESS_FLAG(F_CF) != 0)), F_OF);
 | 
						|
	} else {
 | 
						|
	    CLEAR_FLAG(F_OF);
 | 
						|
	}
 | 
						|
    } else {
 | 
						|
	res = 0;
 | 
						|
	CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
 | 
						|
	CLEAR_FLAG(F_OF);
 | 
						|
	CLEAR_FLAG(F_SF);
 | 
						|
	SET_FLAG(F_PF);
 | 
						|
	SET_FLAG(F_ZF);
 | 
						|
    }
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SHRD instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 shrd_word (u16 d, u16 fill, u8 s)
 | 
						|
{
 | 
						|
    unsigned int cnt, res, cf;
 | 
						|
 | 
						|
    if (s < 16) {
 | 
						|
	cnt = s % 16;
 | 
						|
	if (cnt > 0) {
 | 
						|
	    cf = d & (1 << (cnt - 1));
 | 
						|
	    res = (d >> cnt) | (fill << (16 - cnt));
 | 
						|
	    CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	    set_szp_flags_16((u16)res);
 | 
						|
	} else {
 | 
						|
	    res = d;
 | 
						|
	}
 | 
						|
 | 
						|
	if (cnt == 1) {
 | 
						|
	    CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
 | 
						|
	} else {
 | 
						|
	    CLEAR_FLAG(F_OF);
 | 
						|
	}
 | 
						|
    } else {
 | 
						|
	res = 0;
 | 
						|
	CLEAR_FLAG(F_CF);
 | 
						|
	CLEAR_FLAG(F_OF);
 | 
						|
	SET_FLAG(F_ZF);
 | 
						|
	CLEAR_FLAG(F_SF);
 | 
						|
	CLEAR_FLAG(F_PF);
 | 
						|
    }
 | 
						|
    return (u16)res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SHRD instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 shrd_long (u32 d, u32 fill, u8 s)
 | 
						|
{
 | 
						|
    unsigned int cnt, res, cf;
 | 
						|
 | 
						|
    if (s < 32) {
 | 
						|
	cnt = s % 32;
 | 
						|
	if (cnt > 0) {
 | 
						|
	    cf = d & (1 << (cnt - 1));
 | 
						|
	    res = (d >> cnt) | (fill << (32 - cnt));
 | 
						|
	    CONDITIONAL_SET_FLAG(cf, F_CF);
 | 
						|
	    set_szp_flags_32((u32)res);
 | 
						|
	} else {
 | 
						|
	    res = d;
 | 
						|
	}
 | 
						|
	if (cnt == 1) {
 | 
						|
	    CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
 | 
						|
	} else {
 | 
						|
	    CLEAR_FLAG(F_OF);
 | 
						|
	}
 | 
						|
    } else {
 | 
						|
	res = 0;
 | 
						|
	CLEAR_FLAG(F_CF);
 | 
						|
	CLEAR_FLAG(F_OF);
 | 
						|
	SET_FLAG(F_ZF);
 | 
						|
	CLEAR_FLAG(F_SF);
 | 
						|
	CLEAR_FLAG(F_PF);
 | 
						|
    }
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the SBB instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 sbb_byte(u8 d, u8 s)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
    u32 bc;
 | 
						|
 | 
						|
    if (ACCESS_FLAG(F_CF))
 | 
						|
	res = d - s - 1;
 | 
						|
    else
 | 
						|
	res = d - s;
 | 
						|
    set_szp_flags_8((u8)res);
 | 
						|
 | 
						|
    /* 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 SBB instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 sbb_word(u16 d, u16 s)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
    u32 bc;
 | 
						|
 | 
						|
    if (ACCESS_FLAG(F_CF))
 | 
						|
	res = d - s - 1;
 | 
						|
    else
 | 
						|
	res = d - s;
 | 
						|
    set_szp_flags_16((u16)res);
 | 
						|
 | 
						|
    /* 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)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
    u32 bc;
 | 
						|
 | 
						|
    if (ACCESS_FLAG(F_CF))
 | 
						|
	res = d - s - 1;
 | 
						|
    else
 | 
						|
	res = d - s;
 | 
						|
 | 
						|
    set_szp_flags_32(res);
 | 
						|
 | 
						|
    /* 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)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
    u32 bc;
 | 
						|
 | 
						|
    res = d - s;
 | 
						|
    set_szp_flags_8((u8)res);
 | 
						|
 | 
						|
    /* 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)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
    u32 bc;
 | 
						|
 | 
						|
    res = d - s;
 | 
						|
    set_szp_flags_16((u16)res);
 | 
						|
 | 
						|
    /* 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)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
    u32 bc;
 | 
						|
 | 
						|
    res = d - s;
 | 
						|
    set_szp_flags_32(res);
 | 
						|
 | 
						|
    /* 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)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
 | 
						|
    res = d & s;
 | 
						|
 | 
						|
    CLEAR_FLAG(F_OF);
 | 
						|
    set_szp_flags_8((u8)res);
 | 
						|
    /* AF == dont care */
 | 
						|
    CLEAR_FLAG(F_CF);
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the TEST instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
void test_word(u16 d, u16 s)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
 | 
						|
    res = d & s;
 | 
						|
 | 
						|
    CLEAR_FLAG(F_OF);
 | 
						|
    set_szp_flags_16((u16)res);
 | 
						|
    /* AF == dont care */
 | 
						|
    CLEAR_FLAG(F_CF);
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the TEST instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
void test_long(u32 d, u32 s)
 | 
						|
{
 | 
						|
    u32 res;   /* all operands in native machine order */
 | 
						|
 | 
						|
    res = d & s;
 | 
						|
 | 
						|
    CLEAR_FLAG(F_OF);
 | 
						|
    set_szp_flags_32(res);
 | 
						|
    /* AF == dont care */
 | 
						|
    CLEAR_FLAG(F_CF);
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
REMARKS:
 | 
						|
Implements the XOR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u8 xor_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 XOR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u16 xor_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 XOR instruction and side effects.
 | 
						|
****************************************************************************/
 | 
						|
u32 xor_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 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 == 0x0000) ||
 | 
						|
	((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFFFF)) {
 | 
						|
	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 == 0x00000000) ||
 | 
						|
	((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFFFFFFFF)) {
 | 
						|
	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);
 | 
						|
    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 from
 | 
						|
 | 
						|
REMARKS:
 | 
						|
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
 |