/*
Copyright Notice
================
BOCHS is Copyright 1994 by Kevin P. Lawton.

BOCHS is shareware for PERSONAL USE only.

For more information, read the file 'LICENSE' included in the bochs
distribution.  If you don't have access to this file, or have questions
regarding the licensing policy, the author may be contacted via:

    US Mail:  Kevin Lawton
              528 Lexington St.
              Waltham, MA 02154

    EMail:    bochs@tiac.net
*/



#define BX_ARITH_C 1

#include <stdio.h>
#include <assert.h>
#include "bx_bochs.h"

    

  void
bx_ADD_EbGb()
{
  Bit8u op2, op1, sum;
  Bit32u op2_addr, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u op2_b7, op1_b7, sum_b7, op2_b3, op1_b3, sum_b3;\


  bx_decode_exgx(&op2_addr, &op1_addr, &op1_type, &op1_seg_reg);

  /* op2 is a register, op2_addr is an index of a register */
  BX_READ_8BIT_REG(op2, op2_addr);

  /* op1 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1);

  sum = op1 + op2;

  /* set eflags:
   * ADD affects the following flags: O,S,Z,A,P,C
   */
  op2_b7 = op2 & 0x80;
  op1_b7 = op1 & 0x80;
  sum_b7 = sum & 0x80;
  op2_b3 = op2 & 0x08;
  op1_b3 = op1 & 0x08;
  sum_b3 = sum & 0x08;

  bx_cpu.eflags.of =  (op2_b7 == op1_b7) && (sum_b7 != op2_b7);
  bx_cpu.eflags.sf = (sum_b7 != 0);
  bx_cpu.eflags.zf = (sum == 0);
  bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
  bx_cpu.eflags.pf = bx_parity_lookup[sum];
  bx_cpu.eflags.cf = (op2_b7 || op1_b7) && !sum_b7;

  /* now write sum back to destination */
  if (op1_type == BX_REGISTER_REF) {
    BX_WRITE_8BIT_REG(op1_addr, sum);
    }
  else
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_WRITE, &sum);
}


  void
bx_ADD_EvGv()
{
  Bit32u op2_addr, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, sum_b31;
  Bit32u op2_32, op1_32, sum_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, sum_16;
  Bit16u op2_b15, op1_b15, sum_b15;

  /* for either mode */
  Bit8u op2_b3, op1_b3, sum_b3;


  bx_decode_exgx(&op2_addr, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op2_32 is a register, op2_addr is an index of a register */
    BX_READ_32BIT_REG(op2_32, op2_addr);

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    sum_32 = op1_32 + op2_32;

    /* set eflags:
     * ADD affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    sum_b31 = sum_32 & 0x80000000;
    op2_b3  = op2_32 & 0x00000008;
    op1_b3  = op1_32 & 0x00000008;
    sum_b3  = sum_32 & 0x00000008;

    bx_cpu.eflags.of = (op2_b31 == op1_b31) && (sum_b31 != op2_b31);
    bx_cpu.eflags.sf = (sum_b31 != 0);
    bx_cpu.eflags.zf = (sum_32 == 0);
    bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_32 & 0xFF];
    bx_cpu.eflags.cf = (op2_b31 || op1_b31) && !sum_b31;

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, sum_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &sum_32);
    }
  else { /* 16 bit operand size mode */

    /* op2_16 is a register, op2_addr is an index of a register */
    BX_READ_16BIT_REG(op2_16, op2_addr);

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    sum_16 = op1_16 + op2_16;

    /* set eflags:
     * ADD affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    sum_b15 = sum_16 & 0x8000;
    op2_b3  = op2_16 & 0x0008;
    op1_b3  = op1_16 & 0x0008;
    sum_b3  = sum_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 == op1_b15) && (sum_b15 != op2_b15);
    bx_cpu.eflags.sf = (sum_b15 != 0);
    bx_cpu.eflags.zf = (sum_16 == 0);
    bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_16 & 0xFF];
    bx_cpu.eflags.cf = (op2_b15 || op1_b15) && !sum_b15;

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, sum_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &sum_16);
    }
}


  void
bx_ADD_GbEb()
{
  Bit8u op1, op2, sum;
  Bit32u op1_addr, op2_addr;
  int op2_type;
  bx_segment_reg_t *op2_seg_reg;
  Bit8u op1_b7, op2_b7, sum_b7, op1_b3, op2_b3, sum_b3;\


  bx_decode_exgx(&op1_addr, &op2_addr, &op2_type, &op2_seg_reg);

  /* op1 is a register, op1_addr is an index of a register */
  BX_READ_8BIT_REG(op1, op1_addr);

  /* op2 is a register or memory reference */
  if (op2_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op2, op2_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op2_seg_reg, op2_addr, 1, BX_READ, &op2);

  sum = op1 + op2;

  /* set eflags:
   * ADD affects the following flags: O,S,Z,A,P,C
   */
  op1_b7 = op1 & 0x80;
  op2_b7 = op2 & 0x80;
  sum_b7 = sum & 0x80;
  op1_b3 = op1 & 0x08;
  op2_b3 = op2 & 0x08;
  sum_b3 = sum & 0x08;

  bx_cpu.eflags.of = (op1_b7 == op2_b7) && (sum_b7 != op1_b7);
  bx_cpu.eflags.sf = (sum_b7 != 0);
  bx_cpu.eflags.zf = (sum == 0);
  bx_cpu.eflags.af = (op1_b3 || op2_b3) && !sum_b3;
  bx_cpu.eflags.pf = bx_parity_lookup[sum];
  bx_cpu.eflags.cf = (op1_b7 || op2_b7) && !sum_b7;

  /* now write sum back to destination, which is a register */
  BX_WRITE_8BIT_REG(op1_addr, sum);
}

  void
bx_ADD_GvEv()
{
  Bit32u op1_addr, op2_addr;
  int op2_type;
  bx_segment_reg_t *op2_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op1_b31, op2_b31, sum_b31;
  Bit32u op1_32, op2_32, sum_32;

  /* for 16 bit operand size mode */
  Bit16u op1_16, op2_16, sum_16;
  Bit16u op1_b15, op2_b15, sum_b15;

  /* for either mode */
  Bit8u op1_b3, op2_b3, sum_b3;


  bx_decode_exgx(&op1_addr, &op2_addr, &op2_type, &op2_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op1_32 is a register, op1_addr is an index of a register */
    BX_READ_32BIT_REG(op1_32, op1_addr);

    /* op2_32 is a register or memory reference */
    if (op2_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op2_32, op2_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op2_seg_reg, op2_addr, 4, BX_READ, &op2_32);

    sum_32 = op1_32 + op2_32;

    /* set eflags:
     * ADD affects the following flags: O,S,Z,A,P,C
     */
    op1_b31 = op1_32 & 0x80000000;
    op2_b31 = op2_32 & 0x80000000;
    sum_b31 = sum_32 & 0x80000000;
    op1_b3  = op1_32 & 0x00000008;
    op2_b3  = op2_32 & 0x00000008;
    sum_b3  = sum_32 & 0x00000008;

    bx_cpu.eflags.of = (op1_b31 == op2_b31) && (sum_b31 != op1_b31);
    bx_cpu.eflags.sf = (sum_b31 != 0);
    bx_cpu.eflags.zf = (sum_32 == 0);
    bx_cpu.eflags.af = (op1_b3 || op2_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_b31 || op2_b31) && !sum_b31;

    /* now write sum back to destination */

    BX_WRITE_32BIT_REG(op1_addr, sum_32);
    }
  else { /* 16 bit operand size mode */

    /* op1_16 is a register, op1_addr is an index of a register */
    BX_READ_16BIT_REG(op1_16, op1_addr);

    /* op2_16 is a register or memory reference */
    if (op2_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op2_16, op2_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op2_seg_reg, op2_addr, 2, BX_READ, &op2_16);

    sum_16 = op1_16 + op2_16;

    /* set eflags:
     * ADD affects the following flags: O,S,Z,A,P,C
     */
    op1_b15 = op1_16 & 0x8000;
    op2_b15 = op2_16 & 0x8000;
    sum_b15 = sum_16 & 0x8000;
    op1_b3  = op1_16 & 0x0008;
    op2_b3  = op2_16 & 0x0008;
    sum_b3  = sum_16 & 0x0008;

    bx_cpu.eflags.of = (op1_b15 == op2_b15) && (sum_b15 != op1_b15);
    bx_cpu.eflags.sf = (sum_b15 != 0);
    bx_cpu.eflags.zf = (sum_16 == 0);
    bx_cpu.eflags.af = (op1_b3 || op2_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_b15 || op2_b15) && !sum_b15;

    /* now write sum back to destination */

    BX_WRITE_16BIT_REG(op1_addr, sum_16);
    }
}

  void
bx_ADD_ALIb()
{
  Bit8u op1, op2, sum;
  Bit8u op1_b7, op2_b7, sum_b7, op1_b3, op2_b3, sum_b3;


  op1 = AL;

  bx_fetch_next_byte1(op2);

  sum = op1 + op2;

  /* set eflags:
   * ADD affects the following flags: O,S,Z,A,P,C
   */
  op1_b7 = op1 & 0x80;
  op2_b7 = op2 & 0x80;
  sum_b7 = sum & 0x80;
  op1_b3 = op1 & 0x08;
  op2_b3 = op2 & 0x08;
  sum_b3 = sum & 0x08;

  bx_cpu.eflags.of = (op1_b7 == op2_b7) && (sum_b7 != op1_b7);
  bx_cpu.eflags.sf = (sum_b7 != 0);
  bx_cpu.eflags.zf = (sum == 0);
  bx_cpu.eflags.af = (op1_b3 || op2_b3) && !sum_b3;
  bx_cpu.eflags.pf = bx_parity_lookup[sum];
  bx_cpu.eflags.cf = (op1_b7 || op2_b7) && !sum_b7;

  /* now write sum back to destination, which is a register */
  AL = sum;
}

  void
bx_ADD_eAXIv()
{
  /* for 32 bit operand size mode */
  Bit32u op1_b31, op2_b31, sum_b31;
  Bit32u op1_32, op2_32, sum_32;

  /* for 16 bit operand size mode */
  Bit16u op1_16, op2_16, sum_16;
  Bit16u op1_b15, op2_b15, sum_b15;

  /* for either mode */
  Bit8u op1_b3, op2_b3, sum_b3;


  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op1_32 = EAX;

    op2_32 = bx_fetch_next_dword();

    sum_32 = op1_32 + op2_32;

    /* set eflags:
     * ADD affects the following flags: O,S,Z,A,P,C
     */
    op1_b31 = op1_32 & 0x80000000;
    op2_b31 = op2_32 & 0x80000000;
    sum_b31 = sum_32 & 0x80000000;
    op1_b3  = op1_32 & 0x00000008;
    op2_b3  = op2_32 & 0x00000008;
    sum_b3  = sum_32 & 0x00000008;

    bx_cpu.eflags.of = (op1_b31 == op2_b31) && (sum_b31 != op1_b31);
    bx_cpu.eflags.sf = (sum_b31 != 0);
    bx_cpu.eflags.zf = (sum_32 == 0);
    bx_cpu.eflags.af = (op1_b3 || op2_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_b31 || op2_b31) && !sum_b31;

    /* now write sum back to destination */

    EAX = sum_32;
    }
  else { /* 16 bit operand size mode */
    op1_16 = AX;

    bx_fetch_next_word1(op2_16);

    sum_16 = op1_16 + op2_16;

    /* set eflags:
     * ADD affects the following flags: O,S,Z,A,P,C
     */
    op1_b15 = op1_16 & 0x8000;
    op2_b15 = op2_16 & 0x8000;
    sum_b15 = sum_16 & 0x8000;
    op1_b3  = op1_16 & 0x0008;
    op2_b3  = op2_16 & 0x0008;
    sum_b3  = sum_16 & 0x0008;

    bx_cpu.eflags.of = (op1_b15 == op2_b15) && (sum_b15 != op1_b15);
    bx_cpu.eflags.sf = (sum_b15 != 0);
    bx_cpu.eflags.zf = (sum_16 == 0);
    bx_cpu.eflags.af = (op1_b3 || op2_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_b15 || op2_b15) && !sum_b15;

    /* now write sum back to destination */

    AX = sum_16;
    }
}

  void
bx_ADC_EbGb()
{
  Bit8u op2, op1, sum;
  Bit32u op2_addr, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u op2_b7, op1_b7, sum_b7, op2_b3, op1_b3, sum_b3;\


  bx_decode_exgx(&op2_addr, &op1_addr, &op1_type, &op1_seg_reg);

  /* op2 is a register, op2_addr is an index of a register */
  BX_READ_8BIT_REG(op2, op2_addr);

  /* op1 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1);

  sum = op1 + op2 + (bx_cpu.eflags.cf?1:0);

  /* set eflags:
   * ADC affects the following flags: O,S,Z,A,P,C
   */
  op2_b7 = op2 & 0x80;
  op1_b7 = op1 & 0x80;
  sum_b7 = sum & 0x80;
  op2_b3 = op2 & 0x08;
  op1_b3 = op1 & 0x08;
  sum_b3 = sum & 0x08;

  bx_cpu.eflags.of =  (op2_b7 == op1_b7) && (sum_b7 != op2_b7);
  bx_cpu.eflags.sf = (sum_b7 != 0);
  bx_cpu.eflags.zf = (sum == 0);
  bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
  bx_cpu.eflags.pf = bx_parity_lookup[sum];
  bx_cpu.eflags.cf = (op2_b7 || op1_b7) && !sum_b7;

  /* now write sum back to destination */
  if (op1_type == BX_REGISTER_REF) {
    BX_WRITE_8BIT_REG(op1_addr, sum);
    }
  else
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_WRITE, &sum);
}

  void
bx_ADC_EvGv()
{
  Bit32u op2_addr, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, sum_b31;
  Bit32u op2_32, op1_32, sum_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, sum_16;
  Bit16u op2_b15, op1_b15, sum_b15;

  /* for either mode */
  Bit8u op2_b3, op1_b3, sum_b3;


  bx_decode_exgx(&op2_addr, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op2_32 is a register, op2_addr is an index of a register */
    BX_READ_32BIT_REG(op2_32, op2_addr);

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    sum_32 = op1_32 + op2_32 + (bx_cpu.eflags.cf?1:0);

    /* set eflags:
     * ADC affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    sum_b31 = sum_32 & 0x80000000;
    op2_b3  = op2_32 & 0x00000008;
    op1_b3  = op1_32 & 0x00000008;
    sum_b3  = sum_32 & 0x00000008;

    bx_cpu.eflags.of = (op2_b31 == op1_b31) && (sum_b31 != op2_b31);
    bx_cpu.eflags.sf = (sum_b31 != 0);
    bx_cpu.eflags.zf = (sum_32 == 0);
    bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_32 & 0xFF];
    bx_cpu.eflags.cf = (op2_b31 || op1_b31) && !sum_b31;

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, sum_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &sum_32);
    }
  else { /* 16 bit operand size mode */

    /* op2_16 is a register, op2_addr is an index of a register */
    BX_READ_16BIT_REG(op2_16, op2_addr);

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    sum_16 = op1_16 + op2_16 + (bx_cpu.eflags.cf?1:0);

    /* set eflags:
     * ADC affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    sum_b15 = sum_16 & 0x8000;
    op2_b3  = op2_16 & 0x0008;
    op1_b3  = op1_16 & 0x0008;
    sum_b3  = sum_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 == op1_b15) && (sum_b15 != op2_b15);
    bx_cpu.eflags.sf = (sum_b15 != 0);
    bx_cpu.eflags.zf = (sum_16 == 0);
    bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_16 & 0xFF];
    bx_cpu.eflags.cf = (op2_b15 || op1_b15) && !sum_b15;

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, sum_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &sum_16);
    }
}

  void
bx_ADC_GbEb()
{
  Bit8u op1, op2, sum;
  Bit32u op1_addr, op2_addr;
  int op2_type;
  bx_segment_reg_t *op2_seg_reg;
  Bit8u op1_b7, op2_b7, sum_b7, op1_b3, op2_b3, sum_b3;\


  bx_decode_exgx(&op1_addr, &op2_addr, &op2_type, &op2_seg_reg);

  /* op1 is a register, op1_addr is an index of a register */
  BX_READ_8BIT_REG(op1, op1_addr);

  /* op2 is a register or memory reference */
  if (op2_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op2, op2_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op2_seg_reg, op2_addr, 1, BX_READ, &op2);

  sum = op1 + op2 + (bx_cpu.eflags.cf?1:0);

  /* set eflags:
   * ADC affects the following flags: O,S,Z,A,P,C
   */
  op1_b7 = op1 & 0x80;
  op2_b7 = op2 & 0x80;
  sum_b7 = sum & 0x80;
  op1_b3 = op1 & 0x08;
  op2_b3 = op2 & 0x08;
  sum_b3 = sum & 0x08;

  bx_cpu.eflags.of = (op1_b7 == op2_b7) && (sum_b7 != op1_b7);
  bx_cpu.eflags.sf = (sum_b7 != 0);
  bx_cpu.eflags.zf = (sum == 0);
  bx_cpu.eflags.af = (op1_b3 || op2_b3) && !sum_b3;
  bx_cpu.eflags.pf = bx_parity_lookup[sum];
  bx_cpu.eflags.cf = (op1_b7 || op2_b7) && !sum_b7;

  /* now write sum back to destination, which is a register */
  BX_WRITE_8BIT_REG(op1_addr, sum);
}

  void
bx_ADC_GvEv()
{
  Bit32u op1_addr, op2_addr;
  int op2_type;
  bx_segment_reg_t *op2_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op1_b31, op2_b31, sum_b31;
  Bit32u op1_32, op2_32, sum_32;

  /* for 16 bit operand size mode */
  Bit16u op1_16, op2_16, sum_16;
  Bit16u op1_b15, op2_b15, sum_b15;

  /* for either mode */
  Bit8u op1_b3, op2_b3, sum_b3;


  bx_decode_exgx(&op1_addr, &op2_addr, &op2_type, &op2_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op1_32 is a register, op1_addr is an index of a register */
    BX_READ_32BIT_REG(op1_32, op1_addr);

    /* op2_32 is a register or memory reference */
    if (op2_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op2_32, op2_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op2_seg_reg, op2_addr, 4, BX_READ, &op2_32);

    sum_32 = op1_32 + op2_32 + (bx_cpu.eflags.cf?1:0);

    /* set eflags:
     * ADC affects the following flags: O,S,Z,A,P,C
     */
    op1_b31 = op1_32 & 0x80000000;
    op2_b31 = op2_32 & 0x80000000;
    sum_b31 = sum_32 & 0x80000000;
    op1_b3  = op1_32 & 0x00000008;
    op2_b3  = op2_32 & 0x00000008;
    sum_b3  = sum_32 & 0x00000008;

    bx_cpu.eflags.of = (op1_b31 == op2_b31) && (sum_b31 != op1_b31);
    bx_cpu.eflags.sf = (sum_b31 != 0);
    bx_cpu.eflags.zf = (sum_32 == 0);
    bx_cpu.eflags.af = (op1_b3 || op2_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_b31 || op2_b31) && !sum_b31;

    /* now write sum back to destination */

    BX_WRITE_32BIT_REG(op1_addr, sum_32);
    }
  else { /* 16 bit operand size mode */

    /* op1_16 is a register, op1_addr is an index of a register */
    BX_READ_16BIT_REG(op1_16, op1_addr);

    /* op2_16 is a register or memory reference */
    if (op2_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op2_16, op2_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op2_seg_reg, op2_addr, 2, BX_READ, &op2_16);

    sum_16 = op1_16 + op2_16 + (bx_cpu.eflags.cf?1:0);

    /* set eflags:
     * ADC affects the following flags: O,S,Z,A,P,C
     */
    op1_b15 = op1_16 & 0x8000;
    op2_b15 = op2_16 & 0x8000;
    sum_b15 = sum_16 & 0x8000;
    op1_b3  = op1_16 & 0x0008;
    op2_b3  = op2_16 & 0x0008;
    sum_b3  = sum_16 & 0x0008;

    bx_cpu.eflags.of = (op1_b15 == op2_b15) && (sum_b15 != op1_b15);
    bx_cpu.eflags.sf = (sum_b15 != 0);
    bx_cpu.eflags.zf = (sum_16 == 0);
    bx_cpu.eflags.af = (op1_b3 || op2_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_b15 || op2_b15) && !sum_b15;

    /* now write sum back to destination */

    BX_WRITE_16BIT_REG(op1_addr, sum_16);
    }
}

  void
bx_ADC_ALIb()
{
  Bit8u op1, op2, sum;
  Bit8u op1_b7, op2_b7, sum_b7, op1_b3, op2_b3, sum_b3;


  op1 = AL;

  bx_fetch_next_byte1(op2);

  sum = op1 + op2 + (bx_cpu.eflags.cf?1:0);

  /* set eflags:
   * ADC affects the following flags: O,S,Z,A,P,C
   */
  op1_b7 = op1 & 0x80;
  op2_b7 = op2 & 0x80;
  sum_b7 = sum & 0x80;
  op1_b3 = op1 & 0x08;
  op2_b3 = op2 & 0x08;
  sum_b3 = sum & 0x08;

  bx_cpu.eflags.of = (op1_b7 == op2_b7) && (sum_b7 != op1_b7);
  bx_cpu.eflags.sf = (sum_b7 != 0);
  bx_cpu.eflags.zf = (sum == 0);
  bx_cpu.eflags.af = (op1_b3 || op2_b3) && !sum_b3;
  bx_cpu.eflags.pf = bx_parity_lookup[sum];
  bx_cpu.eflags.cf = (op1_b7 || op2_b7) && !sum_b7;

  /* now write sum back to destination, which is a register */
  AL = sum;
}

  void
bx_ADC_eAXIv()
{
  /* for 32 bit operand size mode */
  Bit32u op1_b31, op2_b31, sum_b31;
  Bit32u op1_32, op2_32, sum_32;

  /* for 16 bit operand size mode */
  Bit16u op1_16, op2_16, sum_16;
  Bit16u op1_b15, op2_b15, sum_b15;

  /* for either mode */
  Bit8u op1_b3, op2_b3, sum_b3;


  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op1_32 = EAX;

    op2_32 = bx_fetch_next_dword();

    sum_32 = op1_32 + op2_32 + (bx_cpu.eflags.cf?1:0);

    /* set eflags:
     * ADC affects the following flags: O,S,Z,A,P,C
     */
    op1_b31 = op1_32 & 0x80000000;
    op2_b31 = op2_32 & 0x80000000;
    sum_b31 = sum_32 & 0x80000000;
    op1_b3  = op1_32 & 0x00000008;
    op2_b3  = op2_32 & 0x00000008;
    sum_b3  = sum_32 & 0x00000008;

    bx_cpu.eflags.of = (op1_b31 == op2_b31) && (sum_b31 != op1_b31);
    bx_cpu.eflags.sf = (sum_b31 != 0);
    bx_cpu.eflags.zf = (sum_32 == 0);
    bx_cpu.eflags.af = (op1_b3 || op2_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_b31 || op2_b31) && !sum_b31;

    /* now write sum back to destination */

    EAX = sum_32;
    }
  else { /* 16 bit operand size mode */
    op1_16 = AX;

    bx_fetch_next_word1(op2_16);

    sum_16 = op1_16 + op2_16 + (bx_cpu.eflags.cf?1:0);

    /* set eflags:
     * ADC affects the following flags: O,S,Z,A,P,C
     */
    op1_b15 = op1_16 & 0x8000;
    op2_b15 = op2_16 & 0x8000;
    sum_b15 = sum_16 & 0x8000;
    op1_b3  = op1_16 & 0x0008;
    op2_b3  = op2_16 & 0x0008;
    sum_b3  = sum_16 & 0x0008;

    bx_cpu.eflags.of = (op1_b15 == op2_b15) && (sum_b15 != op1_b15);
    bx_cpu.eflags.sf = (sum_b15 != 0);
    bx_cpu.eflags.zf = (sum_16 == 0);
    bx_cpu.eflags.af = (op1_b3 || op2_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_b15 || op2_b15) && !sum_b15;

    /* now write sum back to destination */

    AX = sum_16;
    }
}

  void
bx_SBB_EbGb()
{
  Bit8u op2_8, op1_8, diff_8;
  Bit32u op2_addr, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u op2_b7, op1_b7, diff_b7, op2_b3, op1_b3, diff_b3;\


  bx_decode_exgx(&op2_addr, &op1_addr, &op1_type, &op1_seg_reg);

  /* op2 is a register, op2_addr is an index of a register */
  BX_READ_8BIT_REG(op2_8, op2_addr);

  /* op1_8 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1_8, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1_8);

  diff_8 = op1_8 - (op2_8 + (bx_cpu.eflags.cf?1:0));

  /* set eflags:
   * SBB affects the following flags: O,S,Z,A,P,C
   */
  op2_b7  = op2_8  & 0x80;
  op1_b7  = op1_8  & 0x80;
  diff_b7 = diff_8 & 0x80;
  op2_b3  = op2_8  & 0x08;
  op1_b3  = op1_8  & 0x08;
  diff_b3 = diff_8 & 0x08;

  bx_cpu.eflags.of =  (op2_b7 != op1_b7) && (diff_b7 != op1_b7);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = ((op1_8 & 0x0F) < ((op2_8 + (bx_cpu.eflags.cf?1:0)) & 0x0F));
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 < (op2_8 + (bx_cpu.eflags.cf?1:0)));

  /* now write diff back to destination */
  if (op1_type == BX_REGISTER_REF) {
    BX_WRITE_8BIT_REG(op1_addr, diff_8);
    }
  else
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_WRITE, &diff_8);
}

  void
bx_SBB_EvGv()
{
  Bit32u op2_addr, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, diff_b31;
  Bit32u op2_32, op1_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, diff_16;
  Bit16u op2_b15, op1_b15, diff_b15;

  /* for either mode */
  Bit8u op2_b3, op1_b3, diff_b3;


  bx_decode_exgx(&op2_addr, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op2_32 is a register, op2_addr is an index of a register */
    BX_READ_32BIT_REG(op2_32, op2_addr);

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    diff_32 = op1_32 - (op2_32 + (bx_cpu.eflags.cf?1:0));

    /* set eflags:
     * SBB affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;
    op2_b3  = op2_32 & 0x00000008;
    op1_b3  = op1_32 & 0x00000008;
    diff_b3  = diff_32 & 0x00000008;

    bx_cpu.eflags.of = (op2_b31 != op1_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < ((op2_32+(bx_cpu.eflags.cf?1:0)) & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < (op2_32 + (bx_cpu.eflags.cf?1:0)));

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, diff_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &diff_32);
    }
  else { /* 16 bit operand size mode */

    /* op2_16 is a register, op2_addr is an index of a register */
    BX_READ_16BIT_REG(op2_16, op2_addr);

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    diff_16 = op1_16 - (op2_16 + (bx_cpu.eflags.cf?1:0));

    /* set eflags:
     * SBB affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;
    op2_b3  = op2_16 & 0x0008;
    op1_b3  = op1_16 & 0x0008;
    diff_b3  = diff_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 != op1_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < ((op2_16+(bx_cpu.eflags.cf?1:0)) & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < (op2_16 + (bx_cpu.eflags.cf?1:0)));

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, diff_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &diff_16);
    }
}

  void
bx_SBB_GbEb()
{
  Bit8u op1_8, op2_8, diff_8;
  Bit32u op1_addr, op2_addr;
  int op2_type;
  bx_segment_reg_t *op2_seg_reg;
  Bit8u op1_b7, op2_b7, diff_b7, op1_b3, op2_b3, diff_b3;\


  bx_decode_exgx(&op1_addr, &op2_addr, &op2_type, &op2_seg_reg);

  /* op1 is a register, op1_addr is an index of a register */
  BX_READ_8BIT_REG(op1_8, op1_addr);

  /* op2 is a register or memory reference */
  if (op2_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op2_8, op2_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op2_seg_reg, op2_addr, 1, BX_READ, &op2_8);

  diff_8 = op1_8 - (op2_8 + (bx_cpu.eflags.cf?1:0));

  /* set eflags:
   * SBB affects the following flags: O,S,Z,A,P,C
   */
  op1_b7 = op1_8 & 0x80;
  op2_b7 = op2_8 & 0x80;
  diff_b7 = diff_8 & 0x80;
  op1_b3 = op1_8 & 0x08;
  op2_b3 = op2_8 & 0x08;
  diff_b3 = diff_8 & 0x08;

  bx_cpu.eflags.of = (op1_b7 != op2_b7) && (diff_b7 != op1_b7);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = ((op1_8 & 0x0F) < ((op2_8 + (bx_cpu.eflags.cf?1:0)) & 0x0F));
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 < (op2_8 + (bx_cpu.eflags.cf?1:0)));


  /* now write diff back to destination, which is a register */
  BX_WRITE_8BIT_REG(op1_addr, diff_8);
}

  void
bx_SBB_GvEv()
{
  Bit32u op1_addr, op2_addr;
  int op2_type;
  bx_segment_reg_t *op2_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op1_b31, op2_b31, diff_b31;
  Bit32u op1_32, op2_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op1_16, op2_16, diff_16;
  Bit16u op1_b15, op2_b15, diff_b15;

  /* for either mode */
  Bit8u op1_b3, op2_b3, diff_b3;


  bx_decode_exgx(&op1_addr, &op2_addr, &op2_type, &op2_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op1_32 is a register, op1_addr is an index of a register */
    BX_READ_32BIT_REG(op1_32, op1_addr);

    /* op2_32 is a register or memory reference */
    if (op2_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op2_32, op2_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op2_seg_reg, op2_addr, 4, BX_READ, &op2_32);

    diff_32 = op1_32 - (op2_32 + (bx_cpu.eflags.cf?1:0));

    /* set eflags:
     * SBB affects the following flags: O,S,Z,A,P,C
     */
    op1_b31 = op1_32 & 0x80000000;
    op2_b31 = op2_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;
    op1_b3  = op1_32 & 0x00000008;
    op2_b3  = op2_32 & 0x00000008;
    diff_b3  = diff_32 & 0x00000008;

    bx_cpu.eflags.of = (op1_b31 != op2_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < ((op2_32+(bx_cpu.eflags.cf?1:0)) & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < (op2_32 + (bx_cpu.eflags.cf?1:0)));


    /* now write diff back to destination */

    BX_WRITE_32BIT_REG(op1_addr, diff_32);
    }
  else { /* 16 bit operand size mode */

    /* op1_16 is a register, op1_addr is an index of a register */
    BX_READ_16BIT_REG(op1_16, op1_addr);

    /* op2_16 is a register or memory reference */
    if (op2_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op2_16, op2_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op2_seg_reg, op2_addr, 2, BX_READ, &op2_16);

    diff_16 = op1_16 - (op2_16 + (bx_cpu.eflags.cf?1:0));

    /* set eflags:
     * SBB affects the following flags: O,S,Z,A,P,C
     */
    op1_b15 = op1_16 & 0x8000;
    op2_b15 = op2_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;
    op1_b3  = op1_16 & 0x0008;
    op2_b3  = op2_16 & 0x0008;
    diff_b3  = diff_16 & 0x0008;

    bx_cpu.eflags.of = (op1_b15 != op2_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < ((op2_16+(bx_cpu.eflags.cf?1:0)) & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < (op2_16 + (bx_cpu.eflags.cf?1:0)));


    /* now write diff back to destination */

    BX_WRITE_16BIT_REG(op1_addr, diff_16);
    }
}

  void
bx_SBB_ALIb()
{
  Bit8u op1_8, op2_8, diff_8;
  Bit8u op1_b7, op2_b7, diff_b7, op1_b3, op2_b3, diff_b3;


  op1_8 = AL;

  bx_fetch_next_byte1(op2_8);

  diff_8 = op1_8 - (op2_8 + (bx_cpu.eflags.cf?1:0));

  /* set eflags:
   * SBB affects the following flags: O,S,Z,A,P,C
   */
  op1_b7 = op1_8 & 0x80;
  op2_b7 = op2_8 & 0x80;
  diff_b7 = diff_8 & 0x80;
  op1_b3 = op1_8 & 0x08;
  op2_b3 = op2_8 & 0x08;
  diff_b3 = diff_8 & 0x08;

  bx_cpu.eflags.of = (op1_b7 != op2_b7) && (diff_b7 != op1_b7);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = ((op1_8 & 0x0F) < ((op2_8 + (bx_cpu.eflags.cf?1:0)) & 0x0F));
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 < (op2_8 + (bx_cpu.eflags.cf?1:0)));


  /* now write diff back to destination, which is a register */
  AL = diff_8;
}

  void
bx_SBB_eAXIv()
{
  /* for 32 bit operand size mode */
  Bit32u op1_b31, op2_b31, diff_b31;
  Bit32u op1_32, op2_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op1_16, op2_16, diff_16;
  Bit16u op1_b15, op2_b15, diff_b15;

  /* for either mode */
  Bit8u op1_b3, op2_b3, diff_b3;


  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op1_32 = EAX;

    op2_32 = bx_fetch_next_dword();

    diff_32 = op1_32 - (op2_32 + (bx_cpu.eflags.cf?1:0));

    /* set eflags:
     * SBB affects the following flags: O,S,Z,A,P,C
     */
    op1_b31 = op1_32 & 0x80000000;
    op2_b31 = op2_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;
    op1_b3  = op1_32 & 0x00000008;
    op2_b3  = op2_32 & 0x00000008;
    diff_b3  = diff_32 & 0x00000008;

    bx_cpu.eflags.of = (op1_b31 != op2_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < ((op2_32+(bx_cpu.eflags.cf?1:0)) & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < (op2_32 + (bx_cpu.eflags.cf?1:0)));


    /* now write diff back to destination */

    EAX = diff_32;
    }
  else { /* 16 bit operand size mode */
    op1_16 = AX;

    bx_fetch_next_word1(op2_16);

    diff_16 = op1_16 - (op2_16 + (bx_cpu.eflags.cf?1:0));

    /* set eflags:
     * SBB affects the following flags: O,S,Z,A,P,C
     */
    op1_b15 = op1_16 & 0x8000;
    op2_b15 = op2_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;
    op1_b3  = op1_16 & 0x0008;
    op2_b3  = op2_16 & 0x0008;
    diff_b3  = diff_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 != op1_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < ((op2_16+(bx_cpu.eflags.cf?1:0)) & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < (op2_16 + (bx_cpu.eflags.cf?1:0)));



    /* now write diff back to destination */

    AX = diff_16;
    }
}


  void
bx_SUB_EbGb()
{
  Bit8u op2_8, op1_8, diff_8;
  Bit32u op2_addr, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u op2_b7, op1_b7, diff_b7;


  bx_decode_exgx(&op2_addr, &op1_addr, &op1_type, &op1_seg_reg);

  /* op2 is a register, op2_addr is an index of a register */
  BX_READ_8BIT_REG(op2_8, op2_addr);

  /* op1_8 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1_8, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1_8);

  diff_8 = op1_8 - op2_8;

  /* set eflags:
   * SUB affects the following flags: O,S,Z,A,P,C
   */
  op2_b7  = op2_8  & 0x80;
  op1_b7  = op1_8  & 0x80;
  diff_b7 = diff_8 & 0x80;

  bx_cpu.eflags.of =  (op2_b7 != op1_b7) && (diff_b7 != op1_b7);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = ((op1_8 & 0x0F) < (op2_8 & 0x0F));
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 < op2_8);

  /* now write diff back to destination */
  if (op1_type == BX_REGISTER_REF) {
    BX_WRITE_8BIT_REG(op1_addr, diff_8);
    }
  else
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_WRITE, &diff_8);
}

  void
bx_SUB_EvGv()
{
  Bit32u op2_addr, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, diff_b31;
  Bit32u op2_32, op1_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, diff_16;
  Bit16u op2_b15, op1_b15, diff_b15;


  bx_decode_exgx(&op2_addr, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op2_32 is a register, op2_addr is an index of a register */
    BX_READ_32BIT_REG(op2_32, op2_addr);

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    diff_32 = op1_32 - op2_32;

    /* set eflags:
     * SUB affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;

    bx_cpu.eflags.of = (op2_b31 != op1_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < (op2_32 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < op2_32);

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, diff_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &diff_32);
    }
  else { /* 16 bit operand size mode */

    /* op2_16 is a register, op2_addr is an index of a register */
    BX_READ_16BIT_REG(op2_16, op2_addr);

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    diff_16 = op1_16 - op2_16;

    /* set eflags:
     * SUB affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;


    bx_cpu.eflags.of = (op2_b15 != op1_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < (op2_16 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < op2_16);

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, diff_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &diff_16);
    }
}

  void
bx_SUB_GbEb()
{
  Bit8u op1_8, op2_8, diff_8;
  Bit32u op1_addr, op2_addr;
  int op2_type;
  bx_segment_reg_t *op2_seg_reg;
  Bit8u op1_b7, op2_b7, diff_b7;


  bx_decode_exgx(&op1_addr, &op2_addr, &op2_type, &op2_seg_reg);

  /* op1 is a register, op1_addr is an index of a register */
  BX_READ_8BIT_REG(op1_8, op1_addr);

  /* op2 is a register or memory reference */
  if (op2_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op2_8, op2_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op2_seg_reg, op2_addr, 1, BX_READ, &op2_8);

  diff_8 = op1_8 - op2_8;

  /* set eflags:
   * SUB affects the following flags: O,S,Z,A,P,C
   */
  op1_b7 = op1_8 & 0x80;
  op2_b7 = op2_8 & 0x80;
  diff_b7 = diff_8 & 0x80;


  bx_cpu.eflags.of = (op1_b7 != op2_b7) && (diff_b7 != op1_b7);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = ((op1_8 & 0x0F) < (op2_8 & 0x0F));
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 < op2_8);

  /* now write diff back to destination, which is a register */
  BX_WRITE_8BIT_REG(op1_addr, diff_8);
}

  void
bx_SUB_GvEv()
{
  Bit32u op1_addr, op2_addr;
  int op2_type;
  bx_segment_reg_t *op2_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op1_b31, op2_b31, diff_b31;
  Bit32u op1_32, op2_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op1_16, op2_16, diff_16;
  Bit16u op1_b15, op2_b15, diff_b15;


  bx_decode_exgx(&op1_addr, &op2_addr, &op2_type, &op2_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op1_32 is a register, op1_addr is an index of a register */
    BX_READ_32BIT_REG(op1_32, op1_addr);

    /* op2_32 is a register or memory reference */
    if (op2_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op2_32, op2_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op2_seg_reg, op2_addr, 4, BX_READ, &op2_32);

    diff_32 = op1_32 - op2_32;

    /* set eflags:
     * SUB affects the following flags: O,S,Z,A,P,C
     */
    op1_b31 = op1_32 & 0x80000000;
    op2_b31 = op2_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;


    bx_cpu.eflags.of = (op1_b31 != op2_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < (op2_32 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < op2_32);

    /* now write diff back to destination */

    BX_WRITE_32BIT_REG(op1_addr, diff_32);
    }
  else { /* 16 bit operand size mode */

    /* op1_16 is a register, op1_addr is an index of a register */
    BX_READ_16BIT_REG(op1_16, op1_addr);

    /* op2_16 is a register or memory reference */
    if (op2_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op2_16, op2_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op2_seg_reg, op2_addr, 2, BX_READ, &op2_16);

    diff_16 = op1_16 - op2_16;

    /* set eflags:
     * SUB affects the following flags: O,S,Z,A,P,C
     */
    op1_b15 = op1_16 & 0x8000;
    op2_b15 = op2_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;

    bx_cpu.eflags.of = (op1_b15 != op2_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < (op2_16 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < op2_16);

    /* now write diff back to destination */

    BX_WRITE_16BIT_REG(op1_addr, diff_16);
    }
}

  void
bx_SUB_ALIb()
{
  Bit8u op1_8, op2_8, diff_8;
  Bit8u op1_b7, op2_b7, diff_b7;


  op1_8 = AL;

  bx_fetch_next_byte1(op2_8);

  diff_8 = op1_8 - op2_8;

  /* set eflags:
   * SUB affects the following flags: O,S,Z,A,P,C
   */
  op1_b7 = op1_8 & 0x80;
  op2_b7 = op2_8 & 0x80;
  diff_b7 = diff_8 & 0x80;


  bx_cpu.eflags.of = (op1_b7 != op2_b7) && (diff_b7 != op1_b7);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = ((op1_8 & 0x0F) < (op2_8 & 0x0F));
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 < op2_8);

  /* now write diff back to destination, which is a register */
  AL = diff_8;
}

  void
bx_SUB_eAXIv()
{
  /* for 32 bit operand size mode */
  Bit32u op1_b31, op2_b31, diff_b31;
  Bit32u op1_32, op2_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op1_16, op2_16, diff_16;
  Bit16u op1_b15, op2_b15, diff_b15;


  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op1_32 = EAX;

    op2_32 = bx_fetch_next_dword();

    diff_32 = op1_32 - op2_32;

    /* set eflags:
     * SUB affects the following flags: O,S,Z,A,P,C
     */
    op1_b31 = op1_32 & 0x80000000;
    op2_b31 = op2_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;


    bx_cpu.eflags.of = (op1_b31 != op2_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < (op2_32 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < op2_32);

    /* now write diff back to destination */

    EAX = diff_32;
    }
  else { /* 16 bit operand size mode */
    op1_16 = AX;

    bx_fetch_next_word1(op2_16);

    diff_16 = op1_16 - op2_16;

    /* set eflags:
     * SUB affects the following flags: O,S,Z,A,P,C
     */
    op1_b15 = op1_16 & 0x8000;
    op2_b15 = op2_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;

    bx_cpu.eflags.of = (op2_b15 != op1_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < (op2_16 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < op2_16);


    /* now write diff back to destination */

    AX = diff_16;
    }
}

  void
bx_DAS()
{
  Bit8u al;

  al = AL;

  /* DAS effect the following flags: A,C,S,Z,P */

  if (((al & 0x0F) > 0x09) || bx_cpu.eflags.af) {
    al = al - 0x06;
    bx_cpu.eflags.af = 1;
    }
  if ((al > 0x9F) || bx_cpu.eflags.cf) {
    al = al - 0x60;
    bx_cpu.eflags.cf = 1;
    }

  AL = al;

  bx_cpu.eflags.sf = ((al & 0x80) > 0);
  bx_cpu.eflags.zf = (al==0);
  bx_cpu.eflags.pf = bx_parity_lookup[al];
}

  void
bx_AAA()
{
  Bit8u ah, al;

  ah = AH;
  al = AL;

  /* AAA effects the following flags: A,C */

  if ( ((al & 0x0F) > 0x09) || bx_cpu.eflags.af ) {
    al = (al + 6) & 0x0F;
    ah = ah + 1;
    bx_cpu.eflags.af = 1;
    bx_cpu.eflags.cf = 1;
    }
  else {
    bx_cpu.eflags.af = 0;
    bx_cpu.eflags.cf = 0;
    }

  AH = ah;
  AL = al;
}

  void
bx_CMP_EbGb()
{
  Bit8u op2_8, op1_8, diff_8;
  Bit32u op2_addr, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u op2_b7, op1_b7, diff_b7, op2_b3, op1_b3, diff_b3;\


  bx_decode_exgx(&op2_addr, &op1_addr, &op1_type, &op1_seg_reg);

  /* op2 is a register, op2_addr is an index of a register */
  BX_READ_8BIT_REG(op2_8, op2_addr);

  /* op1_8 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1_8, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1_8);

  diff_8 = op1_8 - op2_8;

  /* set eflags:
   * CMP affects the following flags: O,S,Z,A,P,C
   */
  op2_b7  = op2_8  & 0x80;
  op1_b7  = op1_8  & 0x80;
  diff_b7 = diff_8 & 0x80;
  op2_b3  = op2_8  & 0x08;
  op1_b3  = op1_8  & 0x08;
  diff_b3 = diff_8 & 0x08;

  bx_cpu.eflags.of =  (op2_b7 != op1_b7) && (diff_b7 != op1_b7);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = ((op1_8 & 0x0F) < (op2_8 & 0x0F));
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 < op2_8);
}

  void
bx_CMP_EvGv()
{
  Bit32u op2_addr, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, diff_b31;
  Bit32u op2_32, op1_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, diff_16;
  Bit16u op2_b15, op1_b15, diff_b15;

  /* for either mode */
  Bit8u op2_b3, op1_b3, diff_b3;


  bx_decode_exgx(&op2_addr, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op2_32 is a register, op2_addr is an index of a register */
    BX_READ_32BIT_REG(op2_32, op2_addr);

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    diff_32 = op1_32 - op2_32;

    /* set eflags:
     * CMP affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;
    op2_b3  = op2_32 & 0x00000008;
    op1_b3  = op1_32 & 0x00000008;
    diff_b3  = diff_32 & 0x00000008;

    bx_cpu.eflags.of = (op2_b31 != op1_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < (op2_32 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < op2_32);
    }
  else { /* 16 bit operand size mode */

    /* op2_16 is a register, op2_addr is an index of a register */
    BX_READ_16BIT_REG(op2_16, op2_addr);

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    diff_16 = op1_16 - op2_16;

    /* set eflags:
     * CMP affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;
    op2_b3  = op2_16 & 0x0008;
    op1_b3  = op1_16 & 0x0008;
    diff_b3  = diff_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 != op1_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < (op2_16 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < op2_16);
    }
}

  void
bx_CMP_GbEb()
{
  Bit8u op1_8, op2_8, diff_8;
  Bit32u op1_addr, op2_addr;
  int op2_type;
  bx_segment_reg_t *op2_seg_reg;
  Bit8u op1_b7, op2_b7, diff_b7, op1_b3, op2_b3, diff_b3;\


  bx_decode_exgx(&op1_addr, &op2_addr, &op2_type, &op2_seg_reg);

  /* op1 is a register, op1_addr is an index of a register */
  BX_READ_8BIT_REG(op1_8, op1_addr);

  /* op2 is a register or memory reference */
  if (op2_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op2_8, op2_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op2_seg_reg, op2_addr, 1, BX_READ, &op2_8);

  diff_8 = op1_8 - op2_8;

  /* set eflags:
   * CMP affects the following flags: O,S,Z,A,P,C
   */
  op1_b7 = op1_8 & 0x80;
  op2_b7 = op2_8 & 0x80;
  diff_b7 = diff_8 & 0x80;
  op1_b3 = op1_8 & 0x08;
  op2_b3 = op2_8 & 0x08;
  diff_b3 = diff_8 & 0x08;

  bx_cpu.eflags.of = (op1_b7 != op2_b7) && (diff_b7 != op1_b7);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = ((op1_8 & 0x0F) < (op2_8 & 0x0F));
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 < op2_8);
}

  void
bx_CMP_GvEv()
{
  Bit32u op1_addr, op2_addr;
  int op2_type;
  bx_segment_reg_t *op2_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op1_b31, op2_b31, diff_b31;
  Bit32u op1_32, op2_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op1_16, op2_16, diff_16;
  Bit16u op1_b15, op2_b15, diff_b15;

  /* for either mode */
  Bit8u op1_b3, op2_b3, diff_b3;


  bx_decode_exgx(&op1_addr, &op2_addr, &op2_type, &op2_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op1_32 is a register, op1_addr is an index of a register */
    BX_READ_32BIT_REG(op1_32, op1_addr);

    /* op2_32 is a register or memory reference */
    if (op2_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op2_32, op2_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op2_seg_reg, op2_addr, 4, BX_READ, &op2_32);

    diff_32 = op1_32 - op2_32;

    /* set eflags:
     * CMP affects the following flags: O,S,Z,A,P,C
     */
    op1_b31 = op1_32 & 0x80000000;
    op2_b31 = op2_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;
    op1_b3  = op1_32 & 0x00000008;
    op2_b3  = op2_32 & 0x00000008;
    diff_b3  = diff_32 & 0x00000008;

    bx_cpu.eflags.of = (op1_b31 != op2_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < (op2_32 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < op2_32);
    }
  else { /* 16 bit operand size mode */

    /* op1_16 is a register, op1_addr is an index of a register */
    BX_READ_16BIT_REG(op1_16, op1_addr);

    /* op2_16 is a register or memory reference */
    if (op2_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op2_16, op2_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op2_seg_reg, op2_addr, 2, BX_READ, &op2_16);

    diff_16 = op1_16 - op2_16;

    /* set eflags:
     * CMP affects the following flags: O,S,Z,A,P,C
     */
    op1_b15 = op1_16 & 0x8000;
    op2_b15 = op2_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;
    op1_b3  = op1_16 & 0x0008;
    op2_b3  = op2_16 & 0x0008;
    diff_b3  = diff_16 & 0x0008;

    bx_cpu.eflags.of = (op1_b15 != op2_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < (op2_16 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < op2_16);
    }
}

  void
bx_CMP_ALIb()
{
  Bit8u op1_8, op2_8, diff_8;
  Bit8u op1_b7, op2_b7, diff_b7, op1_b3, op2_b3, diff_b3;


  op1_8 = AL;

  bx_fetch_next_byte1(op2_8);

  diff_8 = op1_8 - op2_8;

  /* set eflags:
   * CMP affects the following flags: O,S,Z,A,P,C
   */
  op1_b7 = op1_8 & 0x80;
  op2_b7 = op2_8 & 0x80;
  diff_b7 = diff_8 & 0x80;
  op1_b3 = op1_8 & 0x08;
  op2_b3 = op2_8 & 0x08;
  diff_b3 = diff_8 & 0x08;

  bx_cpu.eflags.of = (op1_b7 != op2_b7) && (diff_b7 != op1_b7);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = ((op1_8 & 0x0F) < (op2_8 & 0x0F));
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 < op2_8);
}

  void
bx_CMP_eAXIv()
{
  /* for 32 bit operand size mode */
  Bit32u op1_b31, op2_b31, diff_b31;
  Bit32u op1_32, op2_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op1_16, op2_16, diff_16;
  Bit16u op1_b15, op2_b15, diff_b15;

  /* for either mode */
  Bit8u op1_b3, op2_b3, diff_b3;


  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op1_32 = EAX;

    op2_32 = bx_fetch_next_dword();

    diff_32 = op1_32 - op2_32;

    /* set eflags:
     * CMP affects the following flags: O,S,Z,A,P,C
     */
    op1_b31 = op1_32 & 0x80000000;
    op2_b31 = op2_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;
    op1_b3  = op1_32 & 0x00000008;
    op2_b3  = op2_32 & 0x00000008;
    diff_b3  = diff_32 & 0x00000008;

    bx_cpu.eflags.of = (op1_b31 != op2_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < (op2_32 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < op2_32);
    }
  else { /* 16 bit operand size mode */
    op1_16 = AX;

    bx_fetch_next_word1(op2_16);

    diff_16 = op1_16 - op2_16;

    /* set eflags:
     * CMP affects the following flags: O,S,Z,A,P,C
     */
    op1_b15 = op1_16 & 0x8000;
    op2_b15 = op2_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;
    op1_b3  = op1_16 & 0x0008;
    op2_b3  = op2_16 & 0x0008;
    diff_b3  = diff_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 != op1_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < (op2_16 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < op2_16);
    }
}

  void
bx_AAS()
{
  Bit8u ah, al;

  /* AAS effect the following flags: A,C */

  ah = AH;
  al = AL;

  if ( ((al & 0x0F) > 0x09) || bx_cpu.eflags.af ) {
    al = (al - 6) & 0x0F;
    ah = ah - 1;
    bx_cpu.eflags.af = 1;
    bx_cpu.eflags.cf = 1;
    }
  else {
    bx_cpu.eflags.af = 0;
    bx_cpu.eflags.cf = 0;
    }

  AH = ah;
  AL = al;
}


  void
bx_INC_eAX()
{
  Bit16u ax;
  Bit32u eax;
  Bit8u  ax_b3, eax_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    eax = EAX;

    eax_b3 = eax & 0x08;
    eax++;
    result_b3  = eax & 0x08;
    result_b31 = eax & 0x80000000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (eax == 0x80000000);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (eax == 0);
    bx_cpu.eflags.af = eax_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[eax & 0xFF];

    EAX = eax;
    }
  else {
    ax = AX;

    ax_b3 = ax & 0x08;
    ax++;
    result_b3  = ax & 0x08;
    result_b15 = ax & 0x8000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (ax == 0x8000);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (ax == 0);
    bx_cpu.eflags.af = ax_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[ax & 0xFF];

    AX = ax;
    }
}

  void
bx_INC_eCX()
{
  Bit16u cx;
  Bit32u ecx;
  Bit8u  cx_b3, ecx_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    ecx = ECX;

    ecx_b3 = ecx & 0x08;
    ecx++;
    result_b3  = ecx & 0x08;
    result_b31 = ecx & 0x80000000;


    /* INC effects the following flags: O,S,Z,A,P */
    bx_cpu.eflags.of = (ecx == 0x80000000);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (ecx == 0);
    bx_cpu.eflags.af = ecx_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[ecx & 0xFF];

    ECX = ecx;
    }
  else {
    cx = CX;

    cx_b3 = cx & 0x08;
    cx++;
    result_b3  = cx & 0x08;
    result_b15 = cx & 0x8000;


    /* INC effects the following flags: O,S,Z,A,P */
    bx_cpu.eflags.of = (cx == 0x8000);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (cx == 0);
    bx_cpu.eflags.af = cx_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[cx & 0xFF];

    CX = cx;
    }
}

  void
bx_INC_eDX()
{
  Bit16u dx;
  Bit32u edx;
  Bit8u  dx_b3, edx_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    edx = EDX;

    edx_b3 = edx & 0x08;
    edx++;
    result_b3  = edx & 0x08;
    result_b31 = edx & 0x80000000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (edx == 0x80000000);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (edx == 0);
    bx_cpu.eflags.af = edx_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[edx & 0xFF];

    EDX = edx;
    }
  else {
    dx = DX;

    dx_b3 = dx & 0x08;
    dx++;
    result_b3  = dx & 0x08;
    result_b15 = dx & 0x8000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (dx == 0x8000);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (dx == 0);
    bx_cpu.eflags.af = dx_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[dx & 0xFF];

    DX = dx;
    }
}

  void
bx_INC_eBX()
{
  Bit16u bx;
  Bit32u ebx;
  Bit8u  bx_b3, ebx_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    ebx = EBX;

    ebx_b3 = ebx & 0x08;
    ebx++;
    result_b3  = ebx & 0x08;
    result_b31 = ebx & 0x80000000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (ebx == 0x80000000);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (ebx == 0);
    bx_cpu.eflags.af = ebx_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[ebx & 0xFF];

    EBX = ebx;
    }
  else {
    bx = BX;

    bx_b3 = bx & 0x08;
    bx++;
    result_b3  = bx & 0x08;
    result_b15 = bx & 0x8000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (bx == 0x8000);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (bx == 0);
    bx_cpu.eflags.af = bx_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[bx & 0xFF];

    BX = bx;
    }
}

  void
bx_INC_eSP()
{
  Bit16u sp;
  Bit32u esp;
  Bit8u  sp_b3, esp_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    esp = ESP;

    esp_b3 = esp & 0x08;
    esp++;
    result_b3  = esp & 0x08;
    result_b31 = esp & 0x80000000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (esp == 0x80000000);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (esp == 0);
    bx_cpu.eflags.af = esp_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[esp & 0xFF];

    ESP = esp;
    }
  else {
    sp = SP;

    sp_b3 = sp & 0x08;
    sp++;
    result_b3  = sp & 0x08;
    result_b15 = sp & 0x8000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (sp == 0x8000);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (sp == 0);
    bx_cpu.eflags.af = sp_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sp & 0xFF];

    SP = sp;
    }
}

  void
bx_INC_eBP()
{
  Bit16u bp;
  Bit32u ebp;
  Bit8u  bp_b3, ebp_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    ebp = EBP;

    ebp_b3 = ebp & 0x08;
    ebp++;
    result_b3  = ebp & 0x08;
    result_b31 = ebp & 0x80000000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (ebp == 0x80000000);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (ebp == 0);
    bx_cpu.eflags.af = ebp_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[ebp & 0xFF];

    EBP = ebp;
    }
  else {
    bp = BP;

    bp_b3 = bp & 0x08;
    bp++;
    result_b3  = bp & 0x08;
    result_b15 = bp & 0x8000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (bp == 0x8000);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (bp == 0);
    bx_cpu.eflags.af = bp_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[bp & 0xFF];

    BP = bp;
    }
}

  void
bx_INC_eSI()
{
  Bit16u si;
  Bit32u esi;
  Bit8u  si_b3, esi_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    esi = ESI;

    esi_b3 = esi & 0x08;
    esi++;
    result_b3  = esi & 0x08;
    result_b31 = esi & 0x80000000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (esi == 0x80000000);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (esi == 0);
    bx_cpu.eflags.af = esi_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[esi & 0xFF];

    ESI = esi;
    }
  else {
    si = SI;

    si_b3 = si & 0x08;
    si++;
    result_b3  = si & 0x08;
    result_b15 = si & 0x8000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (si == 0x8000);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (si == 0);
    bx_cpu.eflags.af = si_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[si & 0xFF];

    SI = si;
    }
}

  void
bx_INC_eDI()
{
  Bit16u di;
  Bit32u edi;
  Bit8u  di_b3, edi_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    edi = EDI;

    edi_b3 = edi & 0x08;
    edi++;
    result_b3  = edi & 0x08;
    result_b31 = edi & 0x80000000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (edi == 0x80000000);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (edi == 0);
    bx_cpu.eflags.af = edi_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[edi & 0xFF];

    EDI = edi;
    }
  else {
    di = DI;

    di_b3 = di & 0x08;
    di++;
    result_b3  = di & 0x08;
    result_b15 = di & 0x8000;


    /* INC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (di == 0x8000);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (di == 0);
    bx_cpu.eflags.af = di_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[di & 0xFF];

    DI = di;
    }
}

  void
bx_DEC_eAX()
{
  Bit16u ax;
  Bit32u eax;
  Bit8u  ax_b3, eax_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    eax = EAX;

    eax_b3 = eax & 0x08;
    eax--;
    result_b3  = eax & 0x08;
    result_b31 = eax & 0x80000000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (eax == 0x7FFFFFFF);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (eax == 0);
    bx_cpu.eflags.af = !eax_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[eax & 0xFF];

    EAX = eax;
    }
  else {
    ax = AX;

    ax_b3 = ax & 0x08;
    ax--;
    result_b3  = ax & 0x08;
    result_b15 = ax & 0x8000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (ax == 0x7FFF);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (ax == 0);
    bx_cpu.eflags.af = (!ax_b3) && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[ax & 0xFF];

    AX = ax;
    }
}

  void
bx_DEC_eCX()
{
  Bit16u cx;
  Bit32u ecx;
  Bit8u  cx_b3, ecx_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    ecx = ECX;

    ecx_b3 = ecx & 0x08;
    ecx--;
    result_b3  = ecx & 0x08;
    result_b31 = ecx & 0x80000000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (ecx == 0x7FFFFFFF);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (ecx == 0);
    bx_cpu.eflags.af = !ecx_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[ecx & 0xFF];

    ECX = ecx;
    }
  else {
    cx = CX;

    cx_b3 = cx & 0x08;
    cx--;
    result_b3  = cx & 0x08;
    result_b15 = cx & 0x8000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (cx == 0x7FFF);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (cx == 0);
    bx_cpu.eflags.af = (!cx_b3) && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[cx & 0xFF];

    CX = cx;
    }
}

  void
bx_DEC_eDX()
{
  Bit16u dx;
  Bit32u edx;
  Bit8u  dx_b3, edx_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    edx = EDX;

    edx_b3 = edx & 0x08;
    edx--;
    result_b3  = edx & 0x08;
    result_b31 = edx & 0x80000000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (edx == 0x7FFFFFFF);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (edx == 0);
    bx_cpu.eflags.af = !edx_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[edx & 0xFF];

    EDX = edx;
    }
  else {
    dx = DX;

    dx_b3 = dx & 0x08;
    dx--;
    result_b3  = dx & 0x08;
    result_b15 = dx & 0x8000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (dx == 0x7FFF);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (dx == 0);
    bx_cpu.eflags.af = !dx_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[dx & 0xFF];

    DX = dx;
    }
}

  void
bx_DEC_eBX()
{
  Bit16u bx;
  Bit32u ebx;
  Bit8u  bx_b3, ebx_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    ebx = EBX;

    ebx_b3 = ebx & 0x08;
    ebx--;
    result_b3  = ebx & 0x08;
    result_b31 = ebx & 0x80000000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (ebx == 0x7FFFFFFF);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (ebx == 0);
    bx_cpu.eflags.af = !ebx_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[ebx & 0xFF];

    EBX = ebx;
    }
  else {
    bx = BX;

    bx_b3 = bx & 0x08;
    bx--;
    result_b3  = bx & 0x08;
    result_b15 = bx & 0x8000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (bx == 0x7FFF);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (bx == 0);
    bx_cpu.eflags.af = !bx_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[bx & 0xFF];

    BX = bx;
    }
}

  void
bx_DEC_eSP()
{
  Bit16u sp;
  Bit32u esp;
  Bit8u  sp_b3, esp_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    esp = ESP;

    esp_b3 = esp & 0x08;
    esp--;
    result_b3  = esp & 0x08;
    result_b31 = esp & 0x80000000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (esp == 0x7FFFFFFF);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (esp == 0);
    bx_cpu.eflags.af = !esp_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[esp & 0xFF];

    ESP = esp;
    }
  else {
    sp = SP;

    sp_b3 = sp & 0x08;
    sp--;
    result_b3  = sp & 0x08;
    result_b15 = sp & 0x8000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (sp == 0x7FFF);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (sp == 0);
    bx_cpu.eflags.af = !sp_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sp & 0xFF];

    SP = sp;
    }
}

  void
bx_DEC_eBP()
{
  Bit16u bp;
  Bit32u ebp;
  Bit8u  bp_b3, ebp_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    ebp = EBP;

    ebp_b3 = ebp & 0x08;
    ebp--;
    result_b3  = ebp & 0x08;
    result_b31 = ebp & 0x80000000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (ebp == 0x7FFFFFFF);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (ebp == 0);
    bx_cpu.eflags.af = !ebp_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[ebp & 0xFF];

    EBP = ebp;
    }
  else {
    bp = BP;

    bp_b3 = bp & 0x08;
    bp--;
    result_b3  = bp & 0x08;
    result_b15 = bp & 0x8000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (bp == 0x7FFF);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (bp == 0);
    bx_cpu.eflags.af = !bp_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[bp & 0xFF];

    BP = bp;
    }
}

  void
bx_DEC_eSI()
{
  Bit16u si;
  Bit32u esi;
  Bit8u  si_b3, esi_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    esi = ESI;

    esi_b3 = esi & 0x08;
    esi--;
    result_b3  = esi & 0x08;
    result_b31 = esi & 0x80000000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (esi == 0x7FFFFFFF);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (esi == 0);
    bx_cpu.eflags.af = !esi_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[esi & 0xFF];

    ESI = esi;
    }
  else {
    si = SI;

    si_b3 = si & 0x08;
    si--;
    result_b3  = si & 0x08;
    result_b15 = si & 0x8000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (si == 0x7FFF);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (si == 0);
    bx_cpu.eflags.af = !si_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[si & 0xFF];

    SI = si;
    }
}

  void
bx_DEC_eDI()
{
  Bit16u di;
  Bit32u edi;
  Bit8u  di_b3, edi_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    edi = EDI;

    edi_b3 = edi & 0x08;
    edi--;
    result_b3  = edi & 0x08;
    result_b31 = edi & 0x80000000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (edi == 0x7FFFFFFF);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (edi == 0);
    bx_cpu.eflags.af = !edi_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[edi & 0xFF];

    EDI = edi;
    }
  else {
    di = DI;

    di_b3 = di & 0x08;
    di--;
    result_b3  = di & 0x08;
    result_b15 = di & 0x8000;


    /* DEC effects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (di == 0x7FFF);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (di == 0);
    bx_cpu.eflags.af = !di_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[di & 0xFF];

    DI = di;
    }
}



  void
bx_TEST_EbGb()
{
  Bit8u op2, op1, result;
  Bit32u op2_addr, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u result_b7;


  bx_decode_exgx(&op2_addr, &op1_addr, &op1_type, &op1_seg_reg);

  /* op2 is a register, op2_addr is an index of a register */
  BX_READ_8BIT_REG(op2, op2_addr);

  /* op1 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1);

  result = op1 & op2;

  /* set eflags:
   * TEST affects the following flags: O,S,Z,P,C
   */
  result_b7 = result & 0x80;

  bx_cpu.eflags.of = 0;
  bx_cpu.eflags.cf = 0;
  bx_cpu.eflags.sf = result_b7 != 0;
  bx_cpu.eflags.zf = (result == 0);
  bx_cpu.eflags.pf = bx_parity_lookup[result];
}

  void
bx_TEST_EvGv()
{
  Bit32u op2_addr, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, result_b31;
  Bit32u op2_32, op1_32, result_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, result_16;
  Bit16u op2_b15, op1_b15, result_b15;



  bx_decode_exgx(&op2_addr, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op2_32 is a register, op2_addr is an index of a register */
    BX_READ_32BIT_REG(op2_32, op2_addr);

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    result_32 = op1_32 & op2_32;

    /* set eflags:
     * TEST affects the following flags: O,S,Z,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    result_b31 = result_32 & 0x80000000;

    bx_cpu.eflags.of = 0;
    bx_cpu.eflags.cf = 0;
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (result_32 == 0);
    bx_cpu.eflags.pf = bx_parity_lookup[result_32 & 0xFF];
    }
  else { /* 16 bit operand size mode */

    /* op2_16 is a register, op2_addr is an index of a register */
    BX_READ_16BIT_REG(op2_16, op2_addr);

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    result_16 = op1_16 & op2_16;

    /* set eflags:
     * TEST affects the following flags: O,S,Z,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    result_b15 = result_16 & 0x8000;

    bx_cpu.eflags.of = 0;
    bx_cpu.eflags.cf = 0;
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (result_16 == 0);
    bx_cpu.eflags.pf = bx_parity_lookup[result_16 & 0xFF];
    }
}


  void
bx_TEST_ALIb()
{
  Bit8u op2, op1, result;
  Bit8u result_b7;

  /* op1 is the AL register */
  op1 = AL;

  /* op2 is imm8 */
  bx_fetch_next_byte1(op2);

  result = op1 & op2;

  /* set eflags:
   * TEST affects the following flags: O,S,Z,P,C
   */
  result_b7 = result & 0x80;

  bx_cpu.eflags.of = 0;
  bx_cpu.eflags.cf = 0;
  bx_cpu.eflags.sf = result_b7 != 0;
  bx_cpu.eflags.zf = (result == 0);
  bx_cpu.eflags.pf = bx_parity_lookup[result];
}

  void
bx_TEST_eAXIv()
{
  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, result_b31;
  Bit32u op2_32, op1_32, result_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, result_16;
  Bit16u op2_b15, op1_b15, result_b15;


  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op1 is EAX register */
    op1_32 = EAX;

    /* op2 is imm32 */
    op2_32 = bx_fetch_next_dword();

    result_32 = op1_32 & op2_32;

    /* set eflags:
     * TEST affects the following flags: O,S,Z,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    result_b31 = result_32 & 0x80000000;

    bx_cpu.eflags.of = 0;
    bx_cpu.eflags.cf = 0;
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (result_32 == 0);
    bx_cpu.eflags.pf = bx_parity_lookup[result_32 & 0xFF];
    }
  else { /* 16 bit operand size mode */

    op1_16 = AX;

    /* op2_16 is imm16 */
    bx_fetch_next_word1(op2_16);

    result_16 = op1_16 & op2_16;

    /* set eflags:
     * TEST affects the following flags: O,S,Z,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    result_b15 = result_16 & 0x8000;

    bx_cpu.eflags.of = 0;
    bx_cpu.eflags.cf = 0;
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (result_16 == 0);
    bx_cpu.eflags.pf = bx_parity_lookup[result_16 & 0xFF];
    }
}


  void
bx_CBW()
{
  /* CBW: no flags are effected */

  if (bx_32bit_opsize) { /* CWDE opcode */
    EAX = (Bit16s) AX;
    }
  else { /* CBW opcode */
    AX = (Bit8s) AL;
    }
}

  void
bx_CWD()
{
  Bit32u eax;
  Bit16u ax;

  /* CWD: no flags are affected */

  if (bx_32bit_opsize) { /* CDQ opcode */
    eax = EAX;
    if (eax & 0x80000000) {
      EDX = 0xFFFFFFFF;
      }
    else {
      EDX = 0x00000000;
      }
    }
  else { /* CWD opcode */
    ax = AX;
    if (ax & 0x8000) {
      DX = 0xFFFF;
      }
    else {
      DX = 0x0000;
      }
    }
}

  void
bx_AAM()
{
  Bit8u ah, al, imm8;

  bx_fetch_next_byte1(imm8);
  ah = AH;
  al = AL;
  ah = al / imm8;
  al = al % imm8;
  AH = ah;
  AL = al;

  /* AAM affectes the following flags: S,Z,P */

  bx_cpu.eflags.sf = ((ah & 0x80) > 0);
  bx_cpu.eflags.zf = (ah==0 && al==0);
  bx_cpu.eflags.pf = bx_parity_lookup[al];
}

  void
bx_AAD()
{
  Bit8u ah, al, imm8;

  bx_fetch_next_byte1(imm8);
  ah = AH;
  al = AL;

  al = (ah * imm8 + al) & 0xFF;
  AH = 0;
  AL = al;

  /* AAD effects the following flags: S,Z,P */

  bx_cpu.eflags.sf = ((al & 0x80) > 0);
  bx_cpu.eflags.zf = (al==0);
  bx_cpu.eflags.pf = bx_parity_lookup[al];
}


void bx_CMPXCHG_XBTS() {bx_invalid_instruction();}
void bx_CMPXCHG_IBTS() {bx_invalid_instruction();}
void bx_XADD_EbGb() {bx_invalid_instruction();}
void bx_XADD_EvGv() {bx_invalid_instruction();}

  void
bx_ADD_EbIb()
{
  Bit8u op2, op1, sum;
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u op2_b7, op1_b7, sum_b7, op2_b3, op1_b3, sum_b3;


  /* op1 is mod+r/m, op2 is an 8bit immediate */
  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  bx_fetch_next_byte1(op2);

  /* op1 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1);

  sum = op1 + op2;

  /* set eflags:
   * ADD affects the following flags: O,S,Z,A,P,C
   */
  op2_b7 = op2 & 0x80;
  op1_b7 = op1 & 0x80;
  sum_b7 = sum & 0x80;
  op2_b3 = op2 & 0x08;
  op1_b3 = op1 & 0x08;
  sum_b3 = sum & 0x08;

  bx_cpu.eflags.of =  (op2_b7 == op1_b7) && (sum_b7 != op2_b7);
  bx_cpu.eflags.sf = (sum_b7 != 0);
  bx_cpu.eflags.zf = (sum == 0);
  bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
  bx_cpu.eflags.pf = bx_parity_lookup[sum];
  bx_cpu.eflags.cf = (op2_b7 || op1_b7) && !sum_b7;

  /* now write sum back to destination */
  if (op1_type == BX_REGISTER_REF) {
    BX_WRITE_8BIT_REG(op1_addr, sum);
    }
  else
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_WRITE, &sum);
}

  void
bx_ADC_EbIb()
{
  Bit8u op2, op1, sum;
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u op2_b7, op1_b7, sum_b7, op2_b3, op1_b3, sum_b3;\


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  bx_fetch_next_byte1(op2);

  /* op1 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1);

  sum = op1 + op2 + (bx_cpu.eflags.cf?1:0);

  /* set eflags:
   * ADC affects the following flags: O,S,Z,A,P,C
   */
  op2_b7 = op2 & 0x80;
  op1_b7 = op1 & 0x80;
  sum_b7 = sum & 0x80;
  op2_b3 = op2 & 0x08;
  op1_b3 = op1 & 0x08;
  sum_b3 = sum & 0x08;

  bx_cpu.eflags.of =  (op2_b7 == op1_b7) && (sum_b7 != op2_b7);
  bx_cpu.eflags.sf = (sum_b7 != 0);
  bx_cpu.eflags.zf = (sum == 0);
  bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
  bx_cpu.eflags.pf = bx_parity_lookup[sum];
  bx_cpu.eflags.cf = (op2_b7 || op1_b7) && !sum_b7;

  /* now write sum back to destination */
  if (op1_type == BX_REGISTER_REF) {
    BX_WRITE_8BIT_REG(op1_addr, sum);
    }
  else
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_WRITE, &sum);
}

  void
bx_SBB_EbIb()
{
  Bit8u op2_8, op1_8, diff_8;
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u op2_b7, op1_b7, diff_b7, op2_b3, op1_b3, diff_b3;\


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  bx_fetch_next_byte1(op2_8);

  /* op1_8 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1_8, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1_8);

  diff_8 = op1_8 - (op2_8 + (bx_cpu.eflags.cf?1:0));

  /* set eflags:
   * SBB affects the following flags: O,S,Z,A,P,C
   */
  op2_b7  = op2_8  & 0x80;
  op1_b7  = op1_8  & 0x80;
  diff_b7 = diff_8 & 0x80;
  op2_b3  = op2_8  & 0x08;
  op1_b3  = op1_8  & 0x08;
  diff_b3 = diff_8 & 0x08;

  bx_cpu.eflags.of =  (op2_b7 != op1_b7) && (diff_b7 != op1_b7);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = ((op1_8 & 0x0F) < ((op2_8 + (bx_cpu.eflags.cf?1:0)) & 0x0F));
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 < (op2_8 + (bx_cpu.eflags.cf?1:0)));

  /* now write diff back to destination */
  if (op1_type == BX_REGISTER_REF) {
    BX_WRITE_8BIT_REG(op1_addr, diff_8);
    }
  else
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_WRITE, &diff_8);
}

  void
bx_SUB_EbIb()
{
  Bit8u op2_8, op1_8, diff_8;
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u op2_b7, op1_b7, diff_b7;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  bx_fetch_next_byte1(op2_8);

  /* op1_8 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1_8, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1_8);

  diff_8 = op1_8 - op2_8;

  /* set eflags:
   * SUB affects the following flags: O,S,Z,A,P,C
   */
  op2_b7  = op2_8  & 0x80;
  op1_b7  = op1_8  & 0x80;
  diff_b7 = diff_8 & 0x80;


  bx_cpu.eflags.of =  (op2_b7 != op1_b7) && (diff_b7 != op1_b7);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = ((op1_8 & 0x0F) < (op2_8 & 0x0F));
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 < op2_8);

  /* now write diff back to destination */
  if (op1_type == BX_REGISTER_REF) {
    BX_WRITE_8BIT_REG(op1_addr, diff_8);
    }
  else
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_WRITE, &diff_8);
}

  void
bx_CMP_EbIb()
{
  Bit8u op2_8, op1_8, diff_8;
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u op2_b7, op1_b7, diff_b7, op2_b3, op1_b3, diff_b3;\


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  bx_fetch_next_byte1(op2_8);

  /* op1_8 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1_8, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1_8);

  diff_8 = op1_8 - op2_8;

  /* set eflags:
   * CMP affects the following flags: O,S,Z,A,P,C
   */
  op2_b7  = op2_8  & 0x80;
  op1_b7  = op1_8  & 0x80;
  diff_b7 = diff_8 & 0x80;
  op2_b3  = op2_8  & 0x08;
  op1_b3  = op1_8  & 0x08;
  diff_b3 = diff_8 & 0x08;

  bx_cpu.eflags.of =  (op2_b7 != op1_b7) && (diff_b7 != op1_b7);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = ((op1_8 & 0x0F) < (op2_8 & 0x0F));
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 < op2_8);
}


  void
bx_ADD_EvIv()
{
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, sum_b31;
  Bit32u op2_32, op1_32, sum_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, sum_16;
  Bit16u op2_b15, op1_b15, sum_b15;

  /* for either mode */
  Bit8u op2_b3, op1_b3, sum_b3;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op2_32 = bx_fetch_next_dword();

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    sum_32 = op1_32 + op2_32;

    /* set eflags:
     * ADD affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    sum_b31 = sum_32 & 0x80000000;
    op2_b3  = op2_32 & 0x00000008;
    op1_b3  = op1_32 & 0x00000008;
    sum_b3  = sum_32 & 0x00000008;

    bx_cpu.eflags.of = (op2_b31 == op1_b31) && (sum_b31 != op2_b31);
    bx_cpu.eflags.sf = (sum_b31 != 0);
    bx_cpu.eflags.zf = (sum_32 == 0);
    bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_32 & 0xFF];
    bx_cpu.eflags.cf = (op2_b31 || op1_b31) && !sum_b31;

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, sum_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &sum_32);
    }
  else { /* 16 bit operand size mode */

    bx_fetch_next_word1(op2_16);

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    sum_16 = op1_16 + op2_16;

    /* set eflags:
     * ADD affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    sum_b15 = sum_16 & 0x8000;
    op2_b3  = op2_16 & 0x0008;
    op1_b3  = op1_16 & 0x0008;
    sum_b3  = sum_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 == op1_b15) && (sum_b15 != op2_b15);
    bx_cpu.eflags.sf = (sum_b15 != 0);
    bx_cpu.eflags.zf = (sum_16 == 0);
    bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_16 & 0xFF];
    bx_cpu.eflags.cf = (op2_b15 || op1_b15) && !sum_b15;

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, sum_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &sum_16);
    }
}

  void
bx_ADC_EvIv()
{
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, sum_b31;
  Bit32u op2_32, op1_32, sum_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, sum_16;
  Bit16u op2_b15, op1_b15, sum_b15;

  /* for either mode */
  Bit8u op2_b3, op1_b3, sum_b3;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op2_32 = bx_fetch_next_dword();

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    sum_32 = op1_32 + op2_32 + (bx_cpu.eflags.cf?1:0);

    /* set eflags:
     * ADC affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    sum_b31 = sum_32 & 0x80000000;
    op2_b3  = op2_32 & 0x00000008;
    op1_b3  = op1_32 & 0x00000008;
    sum_b3  = sum_32 & 0x00000008;

    bx_cpu.eflags.of = (op2_b31 == op1_b31) && (sum_b31 != op2_b31);
    bx_cpu.eflags.sf = (sum_b31 != 0);
    bx_cpu.eflags.zf = (sum_32 == 0);
    bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_32 & 0xFF];
    bx_cpu.eflags.cf = (op2_b31 || op1_b31) && !sum_b31;

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, sum_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &sum_32);
    }
  else { /* 16 bit operand size mode */

    bx_fetch_next_word1(op2_16);

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    sum_16 = op1_16 + op2_16 + (bx_cpu.eflags.cf?1:0);

    /* set eflags:
     * ADC affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    sum_b15 = sum_16 & 0x8000;
    op2_b3  = op2_16 & 0x0008;
    op1_b3  = op1_16 & 0x0008;
    sum_b3  = sum_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 == op1_b15) && (sum_b15 != op2_b15);
    bx_cpu.eflags.sf = (sum_b15 != 0);
    bx_cpu.eflags.zf = (sum_16 == 0);
    bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_16 & 0xFF];
    bx_cpu.eflags.cf = (op2_b15 || op1_b15) && !sum_b15;

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, sum_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &sum_16);
    }
}

  void
bx_SBB_EvIv()
{
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, diff_b31;
  Bit32u op2_32, op1_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, diff_16;
  Bit16u op2_b15, op1_b15, diff_b15;

  /* for either mode */
  Bit8u op2_b3, op1_b3, diff_b3;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op2_32 = bx_fetch_next_dword();

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    diff_32 = op1_32 - (op2_32 + (bx_cpu.eflags.cf?1:0));

    /* set eflags:
     * SBB affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;
    op2_b3  = op2_32 & 0x00000008;
    op1_b3  = op1_32 & 0x00000008;
    diff_b3  = diff_32 & 0x00000008;

    bx_cpu.eflags.of = (op2_b31 != op1_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < ((op2_32+(bx_cpu.eflags.cf?1:0)) & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < (op2_32 + (bx_cpu.eflags.cf?1:0)));

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, diff_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &diff_32);
    }
  else { /* 16 bit operand size mode */

    bx_fetch_next_word1(op2_16);

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    diff_16 = op1_16 - (op2_16 + (bx_cpu.eflags.cf?1:0));

    /* set eflags:
     * SBB affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;
    op2_b3  = op2_16 & 0x0008;
    op1_b3  = op1_16 & 0x0008;
    diff_b3  = diff_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 != op1_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < ((op2_16+(bx_cpu.eflags.cf?1:0)) & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < (op2_16 + (bx_cpu.eflags.cf?1:0)));

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, diff_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &diff_16);
    }
}

  void
bx_SUB_EvIv()
{
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, diff_b31;
  Bit32u op2_32, op1_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, diff_16;
  Bit16u op2_b15, op1_b15, diff_b15;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op2_32 = bx_fetch_next_dword();

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    diff_32 = op1_32 - op2_32;

    /* set eflags:
     * SUB affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;


    bx_cpu.eflags.of = (op2_b31 != op1_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < (op2_32 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < op2_32);

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, diff_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &diff_32);
    }
  else { /* 16 bit operand size mode */

    bx_fetch_next_word1(op2_16);

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    diff_16 = op1_16 - op2_16;

    /* set eflags:
     * SUB affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;


    bx_cpu.eflags.of = (op2_b15 != op1_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < (op2_16 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < op2_16);

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, diff_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &diff_16);
    }
}

  void
bx_CMP_EvIv()
{
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, diff_b31;
  Bit32u op2_32, op1_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, diff_16;
  Bit16u op2_b15, op1_b15, diff_b15;

  /* for either mode */
  Bit8u op2_b3, op1_b3, diff_b3;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op2_32 = bx_fetch_next_dword();

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    diff_32 = op1_32 - op2_32;

    /* set eflags:
     * CMP affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;
    op2_b3  = op2_32 & 0x00000008;
    op1_b3  = op1_32 & 0x00000008;
    diff_b3  = diff_32 & 0x00000008;

    bx_cpu.eflags.of = (op2_b31 != op1_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < (op2_32 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < op2_32);
    }
  else { /* 16 bit operand size mode */

    bx_fetch_next_word1(op2_16);

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    diff_16 = op1_16 - op2_16;

    /* set eflags:
     * CMP affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;
    op2_b3  = op2_16 & 0x0008;
    op1_b3  = op1_16 & 0x0008;
    diff_b3  = diff_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 != op1_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < (op2_16 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < op2_16);
    }
}

  void
bx_ADD_EvIb()
{
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, sum_b31;
  Bit32u op2_32, op1_32, sum_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, sum_16;
  Bit16u op2_b15, op1_b15, sum_b15;

  /* for either mode */
  Bit8u op2_b3, op1_b3, sum_b3;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op2_32 = (Bit8s) bx_fetch_next_byte();

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    sum_32 = op1_32 + op2_32;

    /* set eflags:
     * ADD affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    sum_b31 = sum_32 & 0x80000000;
    op2_b3  = op2_32 & 0x00000008;
    op1_b3  = op1_32 & 0x00000008;
    sum_b3  = sum_32 & 0x00000008;

    bx_cpu.eflags.of = (op2_b31 == op1_b31) && (sum_b31 != op2_b31);
    bx_cpu.eflags.sf = (sum_b31 != 0);
    bx_cpu.eflags.zf = (sum_32 == 0);
    bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_32 & 0xFF];
    bx_cpu.eflags.cf = (op2_b31 || op1_b31) && !sum_b31;

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, sum_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &sum_32);
    }
  else { /* 16 bit operand size mode */

    op2_16 = (Bit8s) bx_fetch_next_byte();

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    sum_16 = op1_16 + op2_16;

    /* set eflags:
     * ADD affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    sum_b15 = sum_16 & 0x8000;
    op2_b3  = op2_16 & 0x0008;
    op1_b3  = op1_16 & 0x0008;
    sum_b3  = sum_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 == op1_b15) && (sum_b15 != op2_b15);
    bx_cpu.eflags.sf = (sum_b15 != 0);
    bx_cpu.eflags.zf = (sum_16 == 0);
    bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_16 & 0xFF];
    bx_cpu.eflags.cf = (op2_b15 || op1_b15) && !sum_b15;

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, sum_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &sum_16);
    }
}

  void
bx_ADC_EvIb()
{
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, sum_b31;
  Bit32u op2_32, op1_32, sum_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, sum_16;
  Bit16u op2_b15, op1_b15, sum_b15;

  /* for either mode */
  Bit8u op2_b3, op1_b3, sum_b3;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op2_32 = (Bit8s) bx_fetch_next_byte();

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    sum_32 = op1_32 + op2_32 + (bx_cpu.eflags.cf?1:0);

    /* set eflags:
     * ADC affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    sum_b31 = sum_32 & 0x80000000;
    op2_b3  = op2_32 & 0x00000008;
    op1_b3  = op1_32 & 0x00000008;
    sum_b3  = sum_32 & 0x00000008;

    bx_cpu.eflags.of = (op2_b31 == op1_b31) && (sum_b31 != op2_b31);
    bx_cpu.eflags.sf = (sum_b31 != 0);
    bx_cpu.eflags.zf = (sum_32 == 0);
    bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_32 & 0xFF];
    bx_cpu.eflags.cf = (op2_b31 || op1_b31) && !sum_b31;

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, sum_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &sum_32);
    }
  else { /* 16 bit operand size mode */

    op2_16 = (Bit8s) bx_fetch_next_byte();

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    sum_16 = op1_16 + op2_16 + (bx_cpu.eflags.cf?1:0);

    /* set eflags:
     * ADC affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    sum_b15 = sum_16 & 0x8000;
    op2_b3  = op2_16 & 0x0008;
    op1_b3  = op1_16 & 0x0008;
    sum_b3  = sum_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 == op1_b15) && (sum_b15 != op2_b15);
    bx_cpu.eflags.sf = (sum_b15 != 0);
    bx_cpu.eflags.zf = (sum_16 == 0);
    bx_cpu.eflags.af = (op2_b3 || op1_b3) && !sum_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[sum_16 & 0xFF];
    bx_cpu.eflags.cf = (op2_b15 || op1_b15) && !sum_b15;

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, sum_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &sum_16);
    }
}

  void
bx_SBB_EvIb()
{
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, diff_b31;
  Bit32u op2_32, op1_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, diff_16;
  Bit16u op2_b15, op1_b15, diff_b15;

  /* for either mode */
  Bit8u op2_b3, op1_b3, diff_b3;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op2_32 = (Bit8s) bx_fetch_next_byte();

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    diff_32 = op1_32 - (op2_32 + (bx_cpu.eflags.cf?1:0));

    /* set eflags:
     * SBB affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;
    op2_b3  = op2_32 & 0x00000008;
    op1_b3  = op1_32 & 0x00000008;
    diff_b3  = diff_32 & 0x00000008;

    bx_cpu.eflags.of = (op2_b31 != op1_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < ((op2_32+(bx_cpu.eflags.cf?1:0)) & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < (op2_32 + (bx_cpu.eflags.cf?1:0)));

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, diff_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &diff_32);
    }
  else { /* 16 bit operand size mode */

    op2_16 = (Bit8s) bx_fetch_next_byte();

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    diff_16 = op1_16 - (op2_16 + (bx_cpu.eflags.cf?1:0));

    /* set eflags:
     * SBB affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;
    op2_b3  = op2_16 & 0x0008;
    op1_b3  = op1_16 & 0x0008;
    diff_b3  = diff_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 != op1_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < ((op2_16+(bx_cpu.eflags.cf?1:0)) & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < (op2_16 + (bx_cpu.eflags.cf?1:0)));

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, diff_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &diff_16);
    }
}

  void
bx_SUB_EvIb()
{
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, diff_b31;
  Bit32u op2_32, op1_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, diff_16;
  Bit16u op2_b15, op1_b15, diff_b15;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op2_32 = (Bit8s) bx_fetch_next_byte();

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    diff_32 = op1_32 - op2_32;

    /* set eflags:
     * SUB affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;

    bx_cpu.eflags.of = (op2_b31 != op1_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < (op2_32 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < op2_32);

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, diff_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &diff_32);
    }
  else { /* 16 bit operand size mode */

    op2_16 = (Bit8s) bx_fetch_next_byte();

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    diff_16 = op1_16 - op2_16;

    /* set eflags:
     * SUB affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;


    bx_cpu.eflags.of = (op2_b15 != op1_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < (op2_16 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < op2_16);

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, diff_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &diff_16);
    }
}

  void
bx_CMP_EvIb()
{
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, diff_b31;
  Bit32u op2_32, op1_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, diff_16;
  Bit16u op2_b15, op1_b15, diff_b15;

  /* for either mode */
  Bit8u op2_b3, op1_b3, diff_b3;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    op2_32 = (Bit8s) bx_fetch_next_byte();

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    diff_32 = op1_32 - op2_32;

    /* set eflags:
     * CMP affects the following flags: O,S,Z,A,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    diff_b31 = diff_32 & 0x80000000;
    op2_b3  = op2_32 & 0x00000008;
    op1_b3  = op1_32 & 0x00000008;
    diff_b3  = diff_32 & 0x00000008;

    bx_cpu.eflags.of = (op2_b31 != op1_b31) && (diff_b31 != op1_b31);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = ((op1_32 & 0x0F) < (op2_32 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 < op2_32);
    }
  else { /* 16 bit operand size mode */

    op2_16 = (Bit8s) bx_fetch_next_byte();

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    diff_16 = op1_16 - op2_16;

    /* set eflags:
     * CMP affects the following flags: O,S,Z,A,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    diff_b15 = diff_16 & 0x8000;
    op2_b3  = op2_16 & 0x0008;
    op1_b3  = op1_16 & 0x0008;
    diff_b3  = diff_16 & 0x0008;

    bx_cpu.eflags.of = (op2_b15 != op1_b15) && (diff_b15 != op1_b15);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = ((op1_16 & 0x0F) < (op2_16 & 0x0F));
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 < op2_16);
    }
}

  void
bx_TEST_EbIb()
{
  Bit8u op2, op1, result;
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u result_b7;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  bx_fetch_next_byte1(op2);

  /* op1 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1);

  result = op1 & op2;

  /* set eflags:
   * TEST affects the following flags: O,S,Z,P,C
   */
  result_b7 = result & 0x80;

  bx_cpu.eflags.of = 0;
  bx_cpu.eflags.cf = 0;
  bx_cpu.eflags.sf = (result_b7 != 0);
  bx_cpu.eflags.zf = (result == 0);
  bx_cpu.eflags.pf = bx_parity_lookup[result];
}

  void
bx_TEST_EvIv()
{
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u op2_b31, op1_b31, result_b31;
  Bit32u op2_32, op1_32, result_32;

  /* for 16 bit operand size mode */
  Bit16u op2_16, op1_16, result_16;
  Bit16u op2_b15, op1_b15, result_b15;



  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op2 is imm32 */
    op2_32 = bx_fetch_next_dword();

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    result_32 = op1_32 & op2_32;

    /* set eflags:
     * TEST affects the following flags: O,S,Z,P,C
     */
    op2_b31 = op2_32 & 0x80000000;
    op1_b31 = op1_32 & 0x80000000;
    result_b31 = result_32 & 0x80000000;

    bx_cpu.eflags.of = 0;
    bx_cpu.eflags.cf = 0;
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (result_32 == 0);
    bx_cpu.eflags.pf = bx_parity_lookup[result_32 & 0xFF];
    }
  else { /* 16 bit operand size mode */

    /* op2_16 is imm16 */
    bx_fetch_next_word1(op2_16);

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    result_16 = op1_16 & op2_16;

    /* set eflags:
     * TEST affects the following flags: O,S,Z,P,C
     */
    op2_b15 = op2_16 & 0x8000;
    op1_b15 = op1_16 & 0x8000;
    result_b15 = result_16 & 0x8000;

    bx_cpu.eflags.of = 0;
    bx_cpu.eflags.cf = 0;
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (result_16 == 0);
    bx_cpu.eflags.pf = bx_parity_lookup[result_16 & 0xFF];
    }
}

  void
bx_NEG_Eb()
{
  Bit8u op1_8, diff_8;
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;
  Bit8u diff_b7;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  /* op1_8 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1_8, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1_8);

  diff_8 = 0 - op1_8;

  /* set eflags:
   * NEG affects the following flags: O,S,Z,A,P,C
   */

  diff_b7 = diff_8 & 0x80;


  bx_cpu.eflags.of = (op1_8 == 0x80);
  bx_cpu.eflags.sf = (diff_b7 != 0);
  bx_cpu.eflags.zf = (diff_8 == 0);
  bx_cpu.eflags.af = 0;
  bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
  bx_cpu.eflags.cf = (op1_8 != 0);

  /* now write diff back to destination */
  if (op1_type == BX_REGISTER_REF) {
    BX_WRITE_8BIT_REG(op1_addr, diff_8);
    }
  else
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_WRITE, &diff_8);
}

  void
bx_NEG_Ev()
{
  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;

  /* for 32 bit operand size mode */
  Bit32u diff_b31;
  Bit32u op1_32, diff_32;

  /* for 16 bit operand size mode */
  Bit16u op1_16, diff_16;
  Bit16u diff_b15;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    diff_32 = 0 - op1_32;

    /* set eflags:
     * NEG affects the following flags: O,S,Z,A,P,C
     */

    diff_b31 = diff_32 & 0x80000000;

    bx_cpu.eflags.of = (op1_32 == 0x80000000);
    bx_cpu.eflags.sf = (diff_b31 != 0);
    bx_cpu.eflags.zf = (diff_32 == 0);
    bx_cpu.eflags.af = 0;
    bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
    bx_cpu.eflags.cf = (op1_32 != 0);

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, diff_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &diff_32);
    }
  else { /* 16 bit operand size mode */

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    diff_16 = 0 - op1_16;

    /* set eflags:
     * NEG affects the following flags: O,S,Z,A,P,C
     */

    diff_b15 = diff_16 & 0x8000;

    bx_cpu.eflags.of = (op1_16 == 0x8000);
    bx_cpu.eflags.sf = (diff_b15 != 0);
    bx_cpu.eflags.zf = (diff_16 == 0);
    bx_cpu.eflags.af = 0;
    bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
    bx_cpu.eflags.cf = (op1_16 != 0);

    /* now write diff back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, diff_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &diff_16);
    }
}


  void
bx_INC_Eb()
{
  Bit8u  op1;
  Bit8u  op1_b3, result_b3;
  Bit16u result_b7;

  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  /* op1 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1);


  op1_b3 = op1 & 0x08;
  op1++;
  result_b3  = op1 & 0x08;
  result_b7 = op1 & 0x80;


  /* INC affect the following flags: O,S,Z,A,P */

  bx_cpu.eflags.of = (op1 == 0x80);
  bx_cpu.eflags.sf = (result_b7 != 0);
  bx_cpu.eflags.zf = (op1 == 0);
  bx_cpu.eflags.af = op1_b3 && !result_b3;
  bx_cpu.eflags.pf = bx_parity_lookup[op1 & 0xFF];

  /* now write sum back to destination */
  if (op1_type == BX_REGISTER_REF) {
    BX_WRITE_8BIT_REG(op1_addr, op1);
    }
  else
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_WRITE, &op1);
}

  void
bx_INC_Ev()
{
  Bit16u op1_16;
  Bit32u op1_32;
  Bit8u  op1_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */

    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    op1_b3 = op1_32 & 0x08;
    op1_32++;
    result_b3  = op1_32 & 0x08;
    result_b31 = op1_32 & 0x80000000;


    /* INC affect the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (op1_32 == 0x80000000);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (op1_32 == 0);
    bx_cpu.eflags.af = op1_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[op1_32 & 0xFF];

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, op1_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &op1_32);
    }
  else {

    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    op1_b3 = op1_16 & 0x08;
    op1_16++;
    result_b3  = op1_16 & 0x08;
    result_b15 = op1_16 & 0x8000;


    /* INC affect the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (op1_16 == 0x8000);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (op1_16 == 0);
    bx_cpu.eflags.af = op1_b3 && !result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[op1_16 & 0xFF];


    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, op1_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &op1_16);
    }
}

  void
bx_DEC_Eb()
{
  Bit16u op1_8;
  Bit8u  op1_b3, result_b3;
  Bit16u result_b7;

  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  /* op1_8 is a register or memory reference */
  if (op1_type == BX_REGISTER_REF) {
    BX_READ_8BIT_REG(op1_8, op1_addr);
    }
  else
    /* pointer, segment address pair */
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_READ, &op1_8);

  op1_b3 = op1_8 & 0x08;
  op1_8--;
  result_b3 = op1_8 & 0x08;
  result_b7 = op1_8 & 0x80;


  /* DEC affects the following flags: O,S,Z,A,P */

  bx_cpu.eflags.of = (op1_8 == 0x7F);
  bx_cpu.eflags.sf = (result_b7 != 0);
  bx_cpu.eflags.zf = (op1_8 == 0);
  bx_cpu.eflags.af = !op1_b3 && result_b3;
  bx_cpu.eflags.pf = bx_parity_lookup[op1_8 & 0xFF];

  /* now write sum back to destination */
  if (op1_type == BX_REGISTER_REF) {
    BX_WRITE_8BIT_REG(op1_addr, op1_8);
    }
  else
    bx_access_virtual(op1_seg_reg, op1_addr, 1, BX_WRITE, &op1_8);
}

  void
bx_DEC_Ev()
{
  Bit16u op1_16;
  Bit32u op1_32;
  Bit8u  op1_b3, result_b3;
  Bit16u result_b15;
  Bit32u result_b31;

  Bit32u unused, op1_addr;
  int op1_type;
  bx_segment_reg_t *op1_seg_reg;


  bx_decode_exgx(&unused, &op1_addr, &op1_type, &op1_seg_reg);

  if (bx_32bit_opsize) { /* 32 bit operand size mode */
    /* op1_32 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_32BIT_REG(op1_32, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_READ, &op1_32);

    op1_b3 = op1_32 & 0x08;
    op1_32--;
    result_b3  = op1_32 & 0x08;
    result_b31 = op1_32 & 0x80000000;


    /* DEC affects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (op1_32 == 0x7FFFFFFF);
    bx_cpu.eflags.sf = (result_b31 != 0);
    bx_cpu.eflags.zf = (op1_32 == 0);
    bx_cpu.eflags.af = !op1_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[op1_32 & 0xFF];

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_32BIT_REG(op1_addr, op1_32);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 4, BX_WRITE, &op1_32);
    }
  else {
    /* op1_16 is a register or memory reference */
    if (op1_type == BX_REGISTER_REF) {
      BX_READ_16BIT_REG(op1_16, op1_addr);
      }
    else
      /* pointer, segment address pair */
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_READ, &op1_16);

    op1_b3 = op1_16 & 0x08;
    op1_16--;
    result_b3  = op1_16 & 0x08;
    result_b15 = op1_16 & 0x8000;


    /* DEC affects the following flags: O,S,Z,A,P */

    bx_cpu.eflags.of = (op1_16 == 0x7FFF);
    bx_cpu.eflags.sf = (result_b15 != 0);
    bx_cpu.eflags.zf = (op1_16 == 0);

    bx_cpu.eflags.af = !op1_b3 && result_b3;
    bx_cpu.eflags.pf = bx_parity_lookup[op1_16 & 0xFF];

    /* now write sum back to destination */
    if (op1_type == BX_REGISTER_REF) {
      BX_WRITE_16BIT_REG(op1_addr, op1_16);
      }
    else
      bx_access_virtual(op1_seg_reg, op1_addr, 2, BX_WRITE, &op1_16);
    }
}

void bx_CMPXCHG_EbGb() {bx_invalid_instruction();}
void bx_CMPXCHG_EvGv() {bx_invalid_instruction();}

  void
bx_DAA()
{
  Bit8u al;

  al = AL;

  /* DAA affects the following flags: S,Z,A,P,C */

  if (((al & 0x0F) > 0x09) || bx_cpu.eflags.af) {
    al = al + 0x06;
    bx_cpu.eflags.af = 1;
    }
  if ((al > 0x9F) || bx_cpu.eflags.cf) {
    al = al + 0x60;
    bx_cpu.eflags.cf = 1;
    }

  AL = al;

  bx_cpu.eflags.sf = ((al & 0x80) > 0);
  bx_cpu.eflags.zf = (al==0);
  bx_cpu.eflags.pf = bx_parity_lookup[al];
}
