text: /* $XFree86: xc/extras/x86emu/src/x86emu/prim_ops.c,v 1.4 2008/10/15 20:59:11 tsi Exp $ */
  /****************************************************************************
  *
  *						Realmode X86 Emulator Library
  *
  *            	Copyright (C) 1996-1999 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 OF 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)
  *
  ****************************************************************************/
  
  #define	PRIM_OPS_NO_REDEFINE_ASM
  #include "x86emu/x86emui.h"
  
  /*------------------------- Global Variables ------------------------------*/
  
  #ifndef	__HAVE_INLINE_ASSEMBLER__
  
  static u32 x86emu_parity_tab[8] =
  {
  	0x96696996,
  	0x69969669,
  	0x69969669,
  	0x96696996,
  	0x69969669,
  	0x96696996,
  	0x96696996,
  	0x69969669,
  };
  
  #endif
  
  #define PARITY(x)   (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
  #define XOR2(x) 	(((x) ^ ((x)>>1)) & 0x1)
  
  /*----------------------------- Implementation ----------------------------*/
  
  #ifndef	__HAVE_INLINE_ASSEMBLER__
  
  /****************************************************************************
  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);
  	CLEAR_FLAG(F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  	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);
  	CLEAR_FLAG(F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  	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);
  
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_AF);
  	CLEAR_FLAG(F_OF);
  	CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG(l == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
  	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);
  
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_AF);
  	CLEAR_FLAG(F_OF);
  	CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG(l == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
      return l;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the ADC instruction and side effects.
  ****************************************************************************/
  u8 adc_byte(u8 d, u8 s)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 cc;
  
  	if (ACCESS_FLAG(F_CF))
  		res = 1 + d + s;
  	else
  		res = d + s;
  
  	CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
  	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the carry chain  SEE NOTE AT TOP. */
  	cc = (s & d) | ((~res) & (s | d));
  	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
  	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
  	return (u8)res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the ADC instruction and side effects.
  ****************************************************************************/
  u16 adc_word(u16 d, u16 s)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 cc;
  
  	if (ACCESS_FLAG(F_CF))
  		res = 1 + d + s;
  	else
  		res = d + s;
  
  	CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
  	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the carry chain  SEE NOTE AT TOP. */
  	cc = (s & d) | ((~res) & (s | d));
  	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
  	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
  	return (u16)res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the ADC instruction and side effects.
  ****************************************************************************/
  u32 adc_long(u32 d, u32 s)
  {
  	register u32 lo;	/* all operands in native machine order */
  	register u32 hi;
  	register u32 res;
  	register u32 cc;
  
  	if (ACCESS_FLAG(F_CF)) {
  		lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
  		res = 1 + d + s;
  		}
  	else {
  		lo = (d & 0xFFFF) + (s & 0xFFFF);
  		res = d + s;
  		}
  	hi = (lo >> 16) + (d >> 16) + (s >> 16);
  
  	CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
  	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the carry chain  SEE NOTE AT TOP. */
  	cc = (s & d) | ((~res) & (s | d));
  	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
  	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the ADD instruction and side effects.
  ****************************************************************************/
  u8 add_byte(u8 d, u8 s)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 cc;
  
  	res = d + s;
  	CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
  	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the carry chain  SEE NOTE AT TOP. */
  	cc = (s & d) | ((~res) & (s | d));
  	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
  	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
  	return (u8)res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the ADD instruction and side effects.
  ****************************************************************************/
  u16 add_word(u16 d, u16 s)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 cc;
  
  	res = d + s;
  	CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
  	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the carry chain  SEE NOTE AT TOP. */
  	cc = (s & d) | ((~res) & (s | d));
  	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
  	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
  	return (u16)res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the ADD instruction and side effects.
  ****************************************************************************/
  u32 add_long(u32 d, u32 s)
  {
  	register u32 lo;	/* all operands in native machine order */
  	register u32 hi;
  	register u32 res;
  	register u32 cc;
  
  	lo = (d & 0xFFFF) + (s & 0xFFFF);
  	res = d + s;
  	hi = (lo >> 16) + (d >> 16) + (s >> 16);
  
  	CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
  	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
      /* calculate the carry chain  SEE NOTE AT TOP. */
      cc = (s & d) | ((~res) & (s | d));
  	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
  	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
  
      return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the AND instruction and side effects.
  ****************************************************************************/
  u8 and_byte(u8 d, u8 s)
  {
  	register u8 res;    /* all operands in native machine order */
  
  	res = d & s;
  
  	/* set the flags  */
  	CLEAR_FLAG(F_OF);
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_AF);
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the AND instruction and side effects.
  ****************************************************************************/
  u16 and_word(u16 d, u16 s)
  {
      register u16 res;   /* all operands in native machine order */
  
      res = d & s;
  
      /* set the flags  */
  	CLEAR_FLAG(F_OF);
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_AF);
  	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
      return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the AND instruction and side effects.
  ****************************************************************************/
  u32 and_long(u32 d, u32 s)
  {
  	register u32 res;   /* all operands in native machine order */
  
  	res = d & s;
  
  	/* set the flags  */
  	CLEAR_FLAG(F_OF);
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_AF);
  	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the CMP instruction and side effects.
  ****************************************************************************/
  u8 cmp_byte(u8 d, u8 s)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 bc;
  
  	res = d - s;
  	CLEAR_FLAG(F_CF);
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the borrow chain.  See note at top */
  	bc = (res & (~d | s)) | (~d & s);
  	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return d;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the CMP instruction and side effects.
  ****************************************************************************/
  u16 cmp_word(u16 d, u16 s)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 bc;
  
  	res = d - s;
  	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the borrow chain.  See note at top */
      bc = (res & (~d | s)) | (~d & s);
  	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return d;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the CMP instruction and side effects.
  ****************************************************************************/
  u32 cmp_long(u32 d, u32 s)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 bc;
  
  	res = d - s;
  	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the borrow chain.  See note at top */
  	bc = (res & (~d | s)) | (~d & s);
  	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return 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);
  	}
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  	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);
  	}
  	CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG(d == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
  	return d;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the DEC instruction and side effects.
  ****************************************************************************/
  u8 dec_byte(u8 d)
  {
      register u32 res;   /* all operands in native machine order */
      register u32 bc;
  
      res = d - 1;
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the borrow chain.  See note at top */
  	/* based on sub_byte, uses s==1.  */
  	bc = (res & (~d | 1)) | (~d & 1);
  	/* carry flag unchanged */
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return (u8)res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the DEC instruction and side effects.
  ****************************************************************************/
  u16 dec_word(u16 d)
  {
      register u32 res;   /* all operands in native machine order */
      register u32 bc;
  
      res = d - 1;
  	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
      /* calculate the borrow chain.  See note at top */
      /* based on the sub_byte routine, with s==1 */
      bc = (res & (~d | 1)) | (~d & 1);
      /* carry flag unchanged */
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return (u16)res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the DEC instruction and side effects.
  ****************************************************************************/
  u32 dec_long(u32 d)
  {
      register u32 res;   /* all operands in native machine order */
      register u32 bc;
  
      res = d - 1;
  
  	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
      /* calculate the borrow chain.  See note at top */
  	bc = (res & (~d | 1)) | (~d & 1);
  	/* carry flag unchanged */
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the INC instruction and side effects.
  ****************************************************************************/
  u8 inc_byte(u8 d)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 cc;
  
  	res = d + 1;
  	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the carry chain  SEE NOTE AT TOP. */
  	cc = ((1 & d) | (~res)) & (1 | d);
  	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
  	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
  	return (u8)res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the INC instruction and side effects.
  ****************************************************************************/
  u16 inc_word(u16 d)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 cc;
  
  	res = d + 1;
  	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the carry chain  SEE NOTE AT TOP. */
  	cc = (1 & d) | ((~res) & (1 | d));
  	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
  	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
  	return (u16)res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the INC instruction and side effects.
  ****************************************************************************/
  u32 inc_long(u32 d)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 cc;
  
  	res = d + 1;
  	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the carry chain  SEE NOTE AT TOP. */
  	cc = (1 & d) | ((~res) & (1 | d));
  	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
  	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the OR instruction and side effects.
  ****************************************************************************/
  u8 or_byte(u8 d, u8 s)
  {
  	register u8 res;    /* all operands in native machine order */
  
  	res = d | s;
  	CLEAR_FLAG(F_OF);
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_AF);
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the OR instruction and side effects.
  ****************************************************************************/
  u16 or_word(u16 d, u16 s)
  {
  	register u16 res;   /* all operands in native machine order */
  
  	res = d | s;
  	/* set the carry flag to be bit 8 */
  	CLEAR_FLAG(F_OF);
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_AF);
  	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the OR instruction and side effects.
  ****************************************************************************/
  u32 or_long(u32 d, u32 s)
  {
  	register u32 res;   /* all operands in native machine order */
  
  	res = d | s;
  
  	/* set the carry flag to be bit 8 */
  	CLEAR_FLAG(F_OF);
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_AF);
  	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the OR instruction and side effects.
  ****************************************************************************/
  u8 neg_byte(u8 s)
  {
      register u8 res;
      register u8 bc;
  
  	CONDITIONAL_SET_FLAG(s != 0, F_CF);
  	res = (u8)-s;
  	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
  	/* calculate the borrow chain --- modified such that d=0.
  	   substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
  	   (the one used for sub) and simplifying, since ~d=0xff...,
  	   ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
  	   ~d&s == s.  So the simplified result is: */
  	bc = res | s;
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the OR instruction and side effects.
  ****************************************************************************/
  u16 neg_word(u16 s)
  {
  	register u16 res;
  	register u16 bc;
  
  	CONDITIONAL_SET_FLAG(s != 0, F_CF);
  	res = (u16)-s;
  	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the borrow chain --- modified such that d=0.
  	   substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
  	   (the one used for sub) and simplifying, since ~d=0xff...,
  	   ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
  	   ~d&s == s.  So the simplified result is: */
  	bc = res | s;
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the OR instruction and side effects.
  ****************************************************************************/
  u32 neg_long(u32 s)
  {
  	register u32 res;
  	register u32 bc;
  
  	CONDITIONAL_SET_FLAG(s != 0, F_CF);
  	res = (u32)-s;
  	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the borrow chain --- modified such that d=0.
  	   substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
  	   (the one used for sub) and simplifying, since ~d=0xff...,
  	   ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
  	   ~d&s == s.  So the simplified result is: */
  	bc = res | s;
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	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)
  {
      register 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)
  {
  	register 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)
  {
  	register 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)
  {
      register 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)
  {
      register 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)
  {
      register 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)
  {
      register 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)
  {
      register 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)
  {
  	register 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);
  			CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
  			CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  		} 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);
  			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  		} 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);
  			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  		} 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);
  			CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
  			CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  		} 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);
  			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  		} 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);
  			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
          } 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;
  		}
  		CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
  		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  		CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
      } 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;
          }
  		CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  		CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
      } 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;
          }
  		CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  		CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
      } 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 < 32) {
  		cnt = s % 32;
  		if (cnt > 0) {
  			if (cnt > 15) {
  				res = (unsigned int)fill << (cnt - 16);
  				if (cnt == 16)
  					cf = d & 0x1;
  				else
  					cf = res & 0x10000;
  			}
  			else {
  				res = (d << cnt) | (fill >> (16-cnt));
  				cf = d & (1 << (16 - cnt));
  			}
  			CONDITIONAL_SET_FLAG(cf, F_CF);
  			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  		} 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);
  			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  		} 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 < 32) {
  		cnt = s % 32;
  		if (cnt > 0) {
  			if (cnt > 15) {
  				if (cnt == 16)
  					cf = d & 0x8000;
  				else
  					cf = fill & (1 << (cnt - 17));
  				res = fill >> (cnt - 16);
  			} else {
  				cf = d & (1 << (cnt - 1));
  				res = (d >> cnt) | (fill << (16 - cnt));
  			}
  			CONDITIONAL_SET_FLAG(cf, F_CF);
  			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  		} 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);
  			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  		} 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)
  {
      register u32 res;   /* all operands in native machine order */
      register u32 bc;
  
  	if (ACCESS_FLAG(F_CF))
  		res = d - s - 1;
  	else
  		res = d - s;
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the borrow chain.  See note at top */
  	bc = (res & (~d | s)) | (~d & s);
  	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return (u8)res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the SBB instruction and side effects.
  ****************************************************************************/
  u16 sbb_word(u16 d, u16 s)
  {
      register u32 res;   /* all operands in native machine order */
      register u32 bc;
  
  	if (ACCESS_FLAG(F_CF))
          res = d - s - 1;
      else
          res = d - s;
  	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the borrow chain.  See note at top */
  	bc = (res & (~d | s)) | (~d & s);
  	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return (u16)res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the SBB instruction and side effects.
  ****************************************************************************/
  u32 sbb_long(u32 d, u32 s)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 bc;
  
  	if (ACCESS_FLAG(F_CF))
          res = d - s - 1;
      else
          res = d - s;
  	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the borrow chain.  See note at top */
  	bc = (res & (~d | s)) | (~d & s);
  	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the SUB instruction and side effects.
  ****************************************************************************/
  u8 sub_byte(u8 d, u8 s)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 bc;
  
  	res = d - s;
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the borrow chain.  See note at top */
  	bc = (res & (~d | s)) | (~d & s);
  	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return (u8)res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the SUB instruction and side effects.
  ****************************************************************************/
  u16 sub_word(u16 d, u16 s)
  {
      register u32 res;   /* all operands in native machine order */
      register u32 bc;
  
      res = d - s;
  	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the borrow chain.  See note at top */
  	bc = (res & (~d | s)) | (~d & s);
  	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return (u16)res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the SUB instruction and side effects.
  ****************************************************************************/
  u32 sub_long(u32 d, u32 s)
  {
  	register u32 res;   /* all operands in native machine order */
  	register u32 bc;
  
  	res = d - s;
  	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  
  	/* calculate the borrow chain.  See note at top */
  	bc = (res & (~d | s)) | (~d & s);
  	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
  	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
  	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the TEST instruction and side effects.
  ****************************************************************************/
  void test_byte(u8 d, u8 s)
  {
      register u32 res;   /* all operands in native machine order */
  
      res = d & s;
  
  	CLEAR_FLAG(F_OF);
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
      /* AF == dont care */
  	CLEAR_FLAG(F_CF);
  }
  
  /****************************************************************************
  REMARKS:
  Implements the TEST instruction and side effects.
  ****************************************************************************/
  void test_word(u16 d, u16 s)
  {
  	register u32 res;   /* all operands in native machine order */
  
  	res = d & s;
  
  	CLEAR_FLAG(F_OF);
  	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  	/* AF == dont care */
  	CLEAR_FLAG(F_CF);
  }
  
  /****************************************************************************
  REMARKS:
  Implements the TEST instruction and side effects.
  ****************************************************************************/
  void test_long(u32 d, u32 s)
  {
  	register u32 res;   /* all operands in native machine order */
  
  	res = d & s;
  
  	CLEAR_FLAG(F_OF);
  	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  	/* AF == dont care */
  	CLEAR_FLAG(F_CF);
  }
  
  /****************************************************************************
  REMARKS:
  Implements the XOR instruction and side effects.
  ****************************************************************************/
  u8 xor_byte(u8 d, u8 s)
  {
  	register u8 res;    /* all operands in native machine order */
  
  	res = d ^ s;
  	CLEAR_FLAG(F_OF);
  	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_AF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the XOR instruction and side effects.
  ****************************************************************************/
  u16 xor_word(u16 d, u16 s)
  {
  	register u16 res;   /* all operands in native machine order */
  
  	res = d ^ s;
  	CLEAR_FLAG(F_OF);
  	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_AF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the XOR instruction and side effects.
  ****************************************************************************/
  u32 xor_long(u32 d, u32 s)
  {
  	register u32 res;   /* all operands in native machine order */
  
  	res = d ^ s;
  	CLEAR_FLAG(F_OF);
  	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_AF);
  	return res;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the IMUL instruction and side effects.
  ****************************************************************************/
  void imul_byte(u8 s)
  {
  	s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
  
  	M.x86.R_AX = res;
  	if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
  		((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
  		CLEAR_FLAG(F_CF);
  		CLEAR_FLAG(F_OF);
  	} else {
  		SET_FLAG(F_CF);
  		SET_FLAG(F_OF);
  	}
  }
  
  /****************************************************************************
  REMARKS:
  Implements the IMUL instruction and side effects.
  ****************************************************************************/
  void imul_word(u16 s)
  {
  	s32 res = (s16)M.x86.R_AX * (s16)s;
  
  	M.x86.R_AX = (u16)res;
  	M.x86.R_DX = (u16)(res >> 16);
  	if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) ||
  		((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) {
  		CLEAR_FLAG(F_CF);
  		CLEAR_FLAG(F_OF);
  	} else {
  		SET_FLAG(F_CF);
  		SET_FLAG(F_OF);
  	}
  }
  
  /****************************************************************************
  REMARKS:
  Implements the IMUL instruction and side effects.
  ****************************************************************************/
  void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
  {
  #ifdef	__HAS_LONG_LONG__
  	s64 res = (s64)(s32)d * (s32)s;
  
  	*res_lo = (u32)res;
  	*res_hi = (u32)(res >> 32);
  #else
  	u32	d_lo,d_hi,d_sign;
  	u32	s_lo,s_hi,s_sign;
  	u32	rlo_lo,rlo_hi,rhi_lo;
  
  	if ((d_sign = d & 0x80000000) != 0)
  		d = -d;
  	d_lo = d & 0xFFFF;
  	d_hi = d >> 16;
  	if ((s_sign = s & 0x80000000) != 0)
  		s = -s;
  	s_lo = s & 0xFFFF;
  	s_hi = s >> 16;
  	rlo_lo = d_lo * s_lo;
  	rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
  	rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
  	*res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
  	*res_hi = rhi_lo;
  	if (d_sign != s_sign) {
  		d = ~*res_lo;
  		s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
  		*res_lo = ~*res_lo+1;
  		*res_hi = ~*res_hi+(s >> 16);
  		}
  #endif
  }
  
  /****************************************************************************
  REMARKS:
  Implements the IMUL instruction and side effects.
  ****************************************************************************/
  void imul_long(u32 s)
  {
  	imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
  	if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) ||
  		((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) {
  		CLEAR_FLAG(F_CF);
  		CLEAR_FLAG(F_OF);
  	} else {
  		SET_FLAG(F_CF);
  		SET_FLAG(F_OF);
  	}
  }
  
  /****************************************************************************
  REMARKS:
  Implements the MUL instruction and side effects.
  ****************************************************************************/
  void mul_byte(u8 s)
  {
  	u16 res = (u16)(M.x86.R_AL * s);
  
  	M.x86.R_AX = res;
  	if (M.x86.R_AH == 0) {
  		CLEAR_FLAG(F_CF);
  		CLEAR_FLAG(F_OF);
  	} else {
  		SET_FLAG(F_CF);
  		SET_FLAG(F_OF);
  	}
  }
  
  /****************************************************************************
  REMARKS:
  Implements the MUL instruction and side effects.
  ****************************************************************************/
  void mul_word(u16 s)
  {
  	u32 res = M.x86.R_AX * s;
  
  	M.x86.R_AX = (u16)res;
  	M.x86.R_DX = (u16)(res >> 16);
  	if (M.x86.R_DX == 0) {
  		CLEAR_FLAG(F_CF);
  		CLEAR_FLAG(F_OF);
      } else {
  		SET_FLAG(F_CF);
  		SET_FLAG(F_OF);
      }
  }
  
  /****************************************************************************
  REMARKS:
  Implements the MUL instruction and side effects.
  ****************************************************************************/
  void mul_long(u32 s)
  {
  #ifdef	__HAS_LONG_LONG__
  	u64 res = (u64)M.x86.R_EAX * s;
  
  	M.x86.R_EAX = (u32)res;
  	M.x86.R_EDX = (u32)(res >> 32);
  #else
  	u32	a,a_lo,a_hi;
  	u32	s_lo,s_hi;
  	u32	rlo_lo,rlo_hi,rhi_lo;
  
  	a = M.x86.R_EAX;
  	a_lo = a & 0xFFFF;
  	a_hi = a >> 16;
  	s_lo = s & 0xFFFF;
  	s_hi = s >> 16;
  	rlo_lo = a_lo * s_lo;
  	rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
  	rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
  	M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
  	M.x86.R_EDX = rhi_lo;
  #endif
  
  	if (M.x86.R_EDX == 0) {
  		CLEAR_FLAG(F_CF);
  		CLEAR_FLAG(F_OF);
  	} else {
  		SET_FLAG(F_CF);
  		SET_FLAG(F_OF);
      }
  }
  
  /****************************************************************************
  REMARKS:
  Implements the IDIV instruction and side effects.
  ****************************************************************************/
  void idiv_byte(u8 s)
  {
      s32 dvd, div, mod;
  
  	dvd = (s16)M.x86.R_AX;
  	if (s == 0) {
  		x86emu_intr_raise(0);
          return;
  	}
  	div = dvd / (s8)s;
  	mod = dvd % (s8)s;
  	if (abs(div) > 0x7f) {
  		x86emu_intr_raise(0);
  		return;
  	}
  	M.x86.R_AL = (s8) div;
  	M.x86.R_AH = (s8) mod;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the IDIV instruction and side effects.
  ****************************************************************************/
  void idiv_word(u16 s)
  {
  	s32 dvd, div, mod;
  
  	dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
  	if (s == 0) {
  		x86emu_intr_raise(0);
  		return;
  	}
  	div = dvd / (s16)s;
  	mod = dvd % (s16)s;
  	if (abs(div) > 0x7fff) {
  		x86emu_intr_raise(0);
  		return;
  	}
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_SF);
  	CONDITIONAL_SET_FLAG(div == 0, F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
  
  	M.x86.R_AX = (u16)div;
  	M.x86.R_DX = (u16)mod;
  }
  
  /****************************************************************************
  REMARKS:
  Implements the IDIV instruction and side effects.
  ****************************************************************************/
  void idiv_long(u32 s)
  {
  #ifdef	__HAS_LONG_LONG__
  	s64 dvd, div, mod;
  
  	dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
  	if (s == 0) {
  		x86emu_intr_raise(0);
  		return;
  	}
  	div = dvd / (s32)s;
  	mod = dvd % (s32)s;
  	if (abs(div) > 0x7fffffff) {
  		x86emu_intr_raise(0);
  		return;
  	}
  #else
  	s32 div = 0, mod;
  	s32 h_dvd = M.x86.R_EDX;
  	u32 l_dvd = M.x86.R_EAX;
  	u32 abs_s = s & 0x7FFFFFFF;
  	u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
  	u32 h_s = abs_s >> 1;
  	u32 l_s = abs_s << 31;
  	int counter = 31;
  	int carry;
  
  	if (s == 0) {
  		x86emu_intr_raise(0);
  		return;
  	}
  	do {
  		div <<= 1;
  		carry = (l_dvd >= l_s) ? 0 : 1;
  		
  		if (abs_h_dvd < (h_s + carry)) {
  			h_s >>= 1;
  			l_s = abs_s << (--counter);
  			continue;
  		} else {
  			abs_h_dvd -= (h_s + carry);
  			l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
  				: (l_dvd - l_s);
  			h_s >>= 1;
  			l_s = abs_s << (--counter);
  			div |= 1;
  			continue;
  		}
  		
  	} while (counter > -1);
  	/* overflow */
  	if (abs_h_dvd || (l_dvd > abs_s)) {
  		x86emu_intr_raise(0);
  		return;
  	}
  	/* sign */
  	div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
  	mod = l_dvd;
  
  #endif
  	CLEAR_FLAG(F_CF);
  	CLEAR_FLAG(F_AF);
  	CLEAR_FLAG(F_SF);
  	SET_FLAG(F_ZF);
  	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
  
  	M.x86.R_EAX = (u32)div;
  	M.x86.R_EDX = (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);
  	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
  
  	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);
  	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
  
  	M.x86.R_EAX = (u32)div;
  	M.x86.R_EDX = (u32)mod;
  }
  
  #endif	/* __HAVE_INLINE_ASSEMBLER__ */
  
  /****************************************************************************
  REMARKS:
  Implements the IN string instruction and side effects.
  ****************************************************************************/
  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);
          switch (size) {
            case 1:
              while (count--) {
  				store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
  									(*sys_inb)(M.x86.R_DX));
  				M.x86.R_DI += inc;
              }
              break;
  
            case 2:
              while (count--) {
  				store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
  									(*sys_inw)(M.x86.R_DX));
  				M.x86.R_DI += inc;
              }
              break;
            case 4:
              while (count--) {
  				store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
  									(*sys_inl)(M.x86.R_DX));
  				M.x86.R_DI += inc;
                  break;
              }
          }
  		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 {
          switch (size) {
            case 1:
  			store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
  								(*sys_inb)(M.x86.R_DX));
              break;
            case 2:
  			store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
  								(*sys_inw)(M.x86.R_DX));
              break;
            case 4:
  			store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
  								(*sys_inl)(M.x86.R_DX));
              break;
          }
  		M.x86.R_DI += inc;
      }
  }
  
  /****************************************************************************
  REMARKS:
  Implements the OUT string instruction and side effects.
  ****************************************************************************/
  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);
          switch (size) {
            case 1:
              while (count--) {
  				(*sys_outb)(M.x86.R_DX,
  						 fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
  				M.x86.R_SI += inc;
              }
              break;
  
            case 2:
              while (count--) {
  				(*sys_outw)(M.x86.R_DX,
  						 fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
  				M.x86.R_SI += inc;
              }
              break;
            case 4:
              while (count--) {
  				(*sys_outl)(M.x86.R_DX,
  						 fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
  				M.x86.R_SI += inc;
                  break;
              }
          }
  		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 {
          switch (size) {
            case 1:
  			(*sys_outb)(M.x86.R_DX,
  					 fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
              break;
            case 2:
  			(*sys_outw)(M.x86.R_DX,
  					 fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
              break;
            case 4:
  			(*sys_outl)(M.x86.R_DX,
  					 fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
              break;
          }
  		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)
  {
  	register 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)
  {
      register 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;
  }
  
  #ifdef	__HAVE_INLINE_ASSEMBLER__
  
  u16 aaa_word (u16 d)
  { return aaa_word_asm(&M.x86.R_EFLG,d); }
  
  u16 aas_word (u16 d)
  { return aas_word_asm(&M.x86.R_EFLG,d); }
  
  u16 aad_word (u16 d)
  { return aad_word_asm(&M.x86.R_EFLG,d); }
  
  u16 aam_word (u8 d)
  { return aam_word_asm(&M.x86.R_EFLG,d); }
  
  u8 adc_byte (u8 d, u8 s)
  { return adc_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 adc_word (u16 d, u16 s)
  { return adc_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 adc_long (u32 d, u32 s)
  { return adc_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 add_byte (u8 d, u8 s)
  { return add_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 add_word (u16 d, u16 s)
  { return add_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 add_long (u32 d, u32 s)
  { return add_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 and_byte (u8 d, u8 s)
  { return and_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 and_word (u16 d, u16 s)
  { return and_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 and_long (u32 d, u32 s)
  { return and_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 cmp_byte (u8 d, u8 s)
  { return cmp_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 cmp_word (u16 d, u16 s)
  { return cmp_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 cmp_long (u32 d, u32 s)
  { return cmp_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 daa_byte (u8 d)
  { return daa_byte_asm(&M.x86.R_EFLG,d); }
  
  u8 das_byte (u8 d)
  { return das_byte_asm(&M.x86.R_EFLG,d); }
  
  u8 dec_byte (u8 d)
  { return dec_byte_asm(&M.x86.R_EFLG,d); }
  
  u16 dec_word (u16 d)
  { return dec_word_asm(&M.x86.R_EFLG,d); }
  
  u32 dec_long (u32 d)
  { return dec_long_asm(&M.x86.R_EFLG,d); }
  
  u8 inc_byte (u8 d)
  { return inc_byte_asm(&M.x86.R_EFLG,d); }
  
  u16 inc_word (u16 d)
  { return inc_word_asm(&M.x86.R_EFLG,d); }
  
  u32 inc_long (u32 d)
  { return inc_long_asm(&M.x86.R_EFLG,d); }
  
  u8 or_byte (u8 d, u8 s)
  { return or_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 or_word (u16 d, u16 s)
  { return or_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 or_long (u32 d, u32 s)
  { return or_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 neg_byte (u8 s)
  { return neg_byte_asm(&M.x86.R_EFLG,s); }
  
  u16 neg_word (u16 s)
  { return neg_word_asm(&M.x86.R_EFLG,s); }
  
  u32 neg_long (u32 s)
  { return neg_long_asm(&M.x86.R_EFLG,s); }
  
  u8 not_byte (u8 s)
  { return not_byte_asm(&M.x86.R_EFLG,s); }
  
  u16 not_word (u16 s)
  { return not_word_asm(&M.x86.R_EFLG,s); }
  
  u32 not_long (u32 s)
  { return not_long_asm(&M.x86.R_EFLG,s); }
  
  u8 rcl_byte (u8 d, u8 s)
  { return rcl_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 rcl_word (u16 d, u8 s)
  { return rcl_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 rcl_long (u32 d, u8 s)
  { return rcl_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 rcr_byte (u8 d, u8 s)
  { return rcr_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 rcr_word (u16 d, u8 s)
  { return rcr_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 rcr_long (u32 d, u8 s)
  { return rcr_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 rol_byte (u8 d, u8 s)
  { return rol_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 rol_word (u16 d, u8 s)
  { return rol_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 rol_long (u32 d, u8 s)
  { return rol_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 ror_byte (u8 d, u8 s)
  { return ror_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 ror_word (u16 d, u8 s)
  { return ror_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 ror_long (u32 d, u8 s)
  { return ror_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 shl_byte (u8 d, u8 s)
  { return shl_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 shl_word (u16 d, u8 s)
  { return shl_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 shl_long (u32 d, u8 s)
  { return shl_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 shr_byte (u8 d, u8 s)
  { return shr_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 shr_word (u16 d, u8 s)
  { return shr_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 shr_long (u32 d, u8 s)
  { return shr_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 sar_byte (u8 d, u8 s)
  { return sar_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 sar_word (u16 d, u8 s)
  { return sar_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 sar_long (u32 d, u8 s)
  { return sar_long_asm(&M.x86.R_EFLG,d,s); }
  
  u16 shld_word (u16 d, u16 fill, u8 s)
  { return shld_word_asm(&M.x86.R_EFLG,d,fill,s); }
  
  u32 shld_long (u32 d, u32 fill, u8 s)
  { return shld_long_asm(&M.x86.R_EFLG,d,fill,s); }
  
  u16 shrd_word (u16 d, u16 fill, u8 s)
  { return shrd_word_asm(&M.x86.R_EFLG,d,fill,s); }
  
  u32 shrd_long (u32 d, u32 fill, u8 s)
  { return shrd_long_asm(&M.x86.R_EFLG,d,fill,s); }
  
  u8 sbb_byte (u8 d, u8 s)
  { return sbb_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 sbb_word (u16 d, u16 s)
  { return sbb_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 sbb_long (u32 d, u32 s)
  { return sbb_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 sub_byte (u8 d, u8 s)
  { return sub_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 sub_word (u16 d, u16 s)
  { return sub_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 sub_long (u32 d, u32 s)
  { return sub_long_asm(&M.x86.R_EFLG,d,s); }
  
  void test_byte (u8 d, u8 s)
  { test_byte_asm(&M.x86.R_EFLG,d,s); }
  
  void test_word (u16 d, u16 s)
  { test_word_asm(&M.x86.R_EFLG,d,s); }
  
  void test_long (u32 d, u32 s)
  { test_long_asm(&M.x86.R_EFLG,d,s); }
  
  u8 xor_byte (u8 d, u8 s)
  { return xor_byte_asm(&M.x86.R_EFLG,d,s); }
  
  u16 xor_word (u16 d, u16 s)
  { return xor_word_asm(&M.x86.R_EFLG,d,s); }
  
  u32 xor_long (u32 d, u32 s)
  { return xor_long_asm(&M.x86.R_EFLG,d,s); }
  
  void imul_byte (u8 s)
  { imul_byte_asm(&M.x86.R_EFLG,&M.x86.R_AX,M.x86.R_AL,s); }
  
  void imul_word (u16 s)
  { imul_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,s); }
  
  void imul_long (u32 s)
  { imul_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s); }
  
  void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
  { imul_long_asm(&M.x86.R_EFLG,res_lo,res_hi,d,s); }
  
  void mul_byte (u8 s)
  { mul_byte_asm(&M.x86.R_EFLG,&M.x86.R_AX,M.x86.R_AL,s); }
  
  void mul_word (u16 s)
  { mul_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,s); }
  
  void mul_long (u32 s)
  { mul_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s); }
  
  void idiv_byte (u8 s)
  { idiv_byte_asm(&M.x86.R_EFLG,&M.x86.R_AL,&M.x86.R_AH,M.x86.R_AX,s); }
  
  void idiv_word (u16 s)
  { idiv_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,M.x86.R_DX,s); }
  
  void idiv_long (u32 s)
  { idiv_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,M.x86.R_EDX,s); }
  
  void div_byte (u8 s)
  { div_byte_asm(&M.x86.R_EFLG,&M.x86.R_AL,&M.x86.R_AH,M.x86.R_AX,s); }
  
  void div_word (u16 s)
  { div_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,M.x86.R_DX,s); }
  
  void div_long (u32 s)
  { div_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,M.x86.R_EDX,s); }
  
  #endif
  
  /*
   * CPUID emulation.  For now, only levels 0 and 1 are supported.  If the host
   * architecture supports CPUID, pass that implementation's results to the
   * emulation.  If running on a 386 or 486 that does not support CPUID, provide
   * a reasonable simulation (instead of SIGILL'ing).  On all other host
   * architectures, the emulator will report itself as a 486DX4.
   *
   * Note that, in level 0's case, the "GenuineIntel" string is in EBX:EDX:ECX,
   * not in EBX:ECX:EDX as one might have expected.
   */
  
  #if defined(__i386__) || defined(__amd64__) || defined(__x86_64__)
  /* No need to worry about PIC on x86_64 */
  #if defined(__PIC__) && !defined(__amd64__) && !defined(__x86_64__)
  #define CPUID()                 \
      __asm__ __volatile__        \
      (                           \
          "pushl %%ebx\n\t"       \
          "cpuid\n\t"             \
          "movl %%ebx, %1\n\t"    \
          "popl %%ebx"            \
          : "=a" (M.x86.R_EAX),   \
            "=r" (M.x86.R_EBX),   \
            "=c" (M.x86.R_ECX),   \
            "=d" (M.x86.R_EDX)    \
          : "a"  (M.x86.R_EAX),   \
            "c"  (M.x86.R_ECX)    \
          : "cc"                  \
      )
  #else
  #define CPUID()                 \
      __asm__ __volatile__        \
      (                           \
          "cpuid"                 \
          : "=a" (M.x86.R_EAX),   \
            "=b" (M.x86.R_EBX),   \
            "=c" (M.x86.R_ECX),   \
            "=d" (M.x86.R_EDX)    \
          : "a"  (M.x86.R_EAX),   \
            "c"  (M.x86.R_ECX)    \
          : "cc"                  \
      )
  #endif
  #endif
  
  void
  cpuid(void)
  {
      if (M.x86.R_EAX > 1) {
          M.x86.R_EAX = M.x86.R_EBX = M.x86.R_ECX = M.x86.R_EDX = 0;
      } else {
  
  #if defined(__amd64__) || defined(__x86_64__)
  
          u32 level = M.x86.R_EAX;
  
          CPUID();
          if (level == 0) {
              /* Upto level one supported */
              if (M.x86.R_EAX > 1)
                  M.x86.R_EAX = 1;
          } else {
              /* Only TSC and VME */
              M.x86.R_EDX &= 0x00000012;
          }
  
  #else /* !x86_64 */
  
  #if defined(__i386__)
  
          u32 level = M.x86.R_EAX;
          u32 ecx, eflags;
  
          /*
           * Determine if the AC & ID bits in EFLAGS can be modified.  Might as
           * well use EBX as the needed work register and not care about PIC.
           */
          __asm__ __volatile__
          (
              "pushl %%ebx\n\t"           /* Save work register */
              "pushfl\n\t"                /* Get EFLAGS */
              "popl %%eax\n\t"
              "movl %%eax,%%ebx\n\t"      /* Save original */
              "xorl $0x240000,%%eax\n\t"  /* Toggle AC & ID bits */
              "pushl %%eax\n\t"           /* Copy to EFLAGS */
              "popfl\n\t"
              "pushfl\n\t"                /* Get new EFLAGS */
              "popl %%eax\n\t"
              "xorl %%ebx,%%eax\n\t"      /* Logical difference */
              "pushl %%ebx\n\t"           /* Restore original EFLAGS */
              "popfl\n\t"
              "popl %%ebx"                /* Restore work register */
              : "=a" (eflags)
          );
  
          if ((eflags & 0x240000) != 0x240000) {
              /* 386 or pre-DX4 486;  Simulate CPUID */
              if (level == 0) {
                  M.x86.R_EAX = 0;        /* No level supported */
                  /* "GenuineIntel" byte-swapped (but not really...) */
                  M.x86.R_EBX = 0x756e6547;       /* "uneG" */
                  M.x86.R_EDX = 0x49656e69;       /* "Ieni" */
                  M.x86.R_ECX = 0x6c65746e;       /* "letn" */
              } else {
                  if (!(eflags & 0x040000))
                      M.x86.R_EAX = 0x00000300;
                  else
                      M.x86.R_EAX = 0x00000400;
                  M.x86.R_EBX = M.x86.R_ECX = M.x86.R_EDX = 0;
              }
          } else {
              /* 486DX4 or later */
              ecx = M.x86.R_ECX;
              M.x86.R_EAX = 0;
              CPUID();
              if (level == 0) {
                  /* Upto level one supported */
                  if (M.x86.R_EAX > 1)
                      M.x86.R_EAX = 1;
              } else {
                  if (M.x86.R_EAX == 0) {
                      /* Level one not supported;  Simulate it */
                      M.x86.R_EAX = 0x00000400;
                      M.x86.R_EBX = M.x86.R_ECX = M.x86.R_EDX = 0;
                  } else {
                      M.x86.R_EAX = 1;
                      M.x86.R_ECX = ecx;
                      CPUID();
                      /* Only TSC and VME */
                      M.x86.R_EDX &= 0x00000012;
                  }
              }
          }
  
  #else /* !amd64 && !i386 */
  
          /* Emulate a 486DX4 */
          if (M.x86.R_EAX == 0) {
              M.x86.R_EAX = 1;            /* Upto one level supported */
              /* "GenuineIntel" byte-swapped (but not really...) */
              M.x86.R_EBX = 0x756e6547;   /* "uneG" */
              M.x86.R_EDX = 0x49656e69;   /* "Ieni" */
              M.x86.R_ECX = 0x6c65746e;   /* "letn" */
          } else {
              M.x86.R_EAX = 0x00000480;
              M.x86.R_EBX = 0x00000000;
              M.x86.R_ECX = 0x00000000;
              M.x86.R_EDX = 0x00000002;   /* VME only */
          }
  
  #endif
  
  #endif
  
      }
  
  }
  