/*
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
*/






#include "bx_bochs.h"


/* MOVSB ES:[EDI], DS:[ESI]   DS may be overridden
 *   mov string from DS:[ESI] into ES:[EDI]
 */

  void
bx_MOVSB_XbYb()
{
  bx_segment_reg_t *seg;
  Bit8u temp8;

  if (bx_segment_override) {
    seg = bx_segment_override;
    }
  else {
    seg = &bx_cpu.ds;
    }

  if (bx_32bit_addrsize) {
    Bit32u esi, edi, ecx;

    esi = ESI;
    edi = EDI;

    ecx = 1;
    if (bx_rep_prefix) {
      ecx = ECX;
      }

    for (;ecx != 0; ecx--) {
      bx_access_virtual(seg, esi, 1, BX_READ, &temp8);
      bx_access_virtual(&bx_cpu.es, edi, 1, BX_WRITE, &temp8);
      if (bx_cpu.eflags.df) {
	/* decrement ESI, EDI */
	esi--;
	edi--;
	}
      else {
	/* increment ESI, EDI */
	esi++;
	edi++;
	}
      }

    if (bx_rep_prefix) {
      ECX = 0;
      }

    ESI = esi;
    EDI = edi;
    }

  else { /* 16 bit address mode */
    Bit16u si, di, cx;

    si = SI;
    di = DI;

    cx = 1;
    if (bx_rep_prefix) {
      cx = CX;
      }

    for (;cx != 0; cx--) {
      bx_access_virtual(seg, si, 1, BX_READ, &temp8);
      bx_access_virtual(&bx_cpu.es, di, 1, BX_WRITE, &temp8);
      if (bx_cpu.eflags.df) {
	/* decrement SI, DI */
	si--;
	di--;
	}
      else {
	/* increment SI, DI */
	si++;
	di++;
	}
      }

    if (bx_rep_prefix) {
      CX = 0;
      }

    SI = si;
    DI = di;
    }
}

  void
bx_MOVSW_XvYv()
{
  bx_segment_reg_t *seg;
  Bit16u  temp16;
  Bit32u  temp32;

  if (bx_segment_override) {
    seg = bx_segment_override;
    }
  else {
    seg = &bx_cpu.ds;
    }

  if (bx_32bit_addrsize) {
    Bit32u esi, edi, ecx;

    esi = ESI;
    edi = EDI;

    ecx = 1;
    if (bx_rep_prefix) {
      ecx = ECX;
      }

    if (bx_32bit_opsize) {
      for (;ecx != 0; ecx--) {
	bx_access_virtual(seg, esi, 4, BX_READ, &temp32);
	bx_access_virtual(&bx_cpu.es, edi, 4, BX_WRITE, &temp32);

	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  esi -= 4;
	  edi -= 4;
	  }
	else {
	  /* increment ESI */
	  esi += 4;
	  edi += 4;
	  }
	}
      } /* if (bx_32bit_opsize) ... */
    else { /* 16 bit opsize mode */
      for (;ecx != 0; ecx--) {
	bx_access_virtual(seg, esi, 2, BX_READ, &temp16);
	bx_access_virtual(&bx_cpu.es, edi, 2, BX_WRITE, &temp16);

	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  esi -= 2;
	  edi -= 2;
	  }
	else {
	  /* increment ESI */
	  esi += 2;
	  edi += 2;
	  }
	}
      }


    if (bx_rep_prefix) {
      ECX = 0;
      }

    ESI = esi;
    EDI = edi;
    }

  else { /* 16bit address mode */
    Bit16u si, di, cx;

    si = SI;
    di = DI;

    cx = 1;
    if (bx_rep_prefix) {
      cx = CX;
      }

    if (bx_32bit_opsize) {
      for (;cx != 0; cx--) {
	bx_access_virtual(seg, si, 4, BX_READ, &temp32);
	bx_access_virtual(&bx_cpu.es, di, 4, BX_WRITE, &temp32);

	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  si -= 4;
	  di -= 4;
	  }
	else {
	  /* increment ESI */
	  si += 4;
	  di += 4;
	  }
	}
      } /* if (bx_32bit_opsize) ... */
    else { /* 16 bit opsize mode */
      for (;cx != 0; cx--) {
	bx_access_virtual(seg, si, 2, BX_READ, &temp16);
	bx_access_virtual(&bx_cpu.es, di, 2, BX_WRITE, &temp16);

	if (bx_cpu.eflags.df) {
	  /* decrement SI, DI */
	  si -= 2;
	  di -= 2;
	  }
	else {
	  /* increment SI, DI */
	  si += 2;
	  di += 2;
	  }
	}
      }


    if (bx_rep_prefix) {
      CX = 0;
      }

    SI = si;
    DI = di;
    }
}

  void
bx_CMPSB_XbYb()
{
  bx_segment_reg_t *seg;
  Bit8u src8, dst8, src_b7, dst_b7, diff_8, diff_b7;


  if (bx_segment_override) {
    seg = bx_segment_override;
    }
  else {
    seg = &bx_cpu.ds;
    }

  if (bx_32bit_addrsize) {
    Bit32u esi, edi, ecx;

    esi = ESI;
    edi = EDI;

    ecx = 1;
    if (bx_rep_prefix || bx_repne_prefix) {
      ecx = ECX;
      }

    for (;ecx != 0;) {
      ecx--;
      bx_access_virtual(seg, esi, 1, BX_READ, &src8);
      bx_access_virtual(&bx_cpu.es, edi, 1, BX_READ, &dst8);

      diff_8 = src8 - dst8;

      /* set eflags:
       * CMPSB affects the following flags: O,S,Z,A,P,C
       */
      dst_b7  = dst8  & 0x80;
      src_b7  = src8  & 0x80;
      diff_b7 = diff_8 & 0x80;

      bx_cpu.eflags.of =  (dst_b7 != src_b7) && (diff_b7 != src_b7);
      bx_cpu.eflags.sf = (diff_b7 != 0);
      bx_cpu.eflags.zf = (diff_8 == 0);
      bx_cpu.eflags.af = ((src8 & 0x0F) < (dst8 & 0x0F));
      bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
      bx_cpu.eflags.cf = (src8 < dst8);


      if (bx_cpu.eflags.df) {
	/* decrement ESI */
	esi--;
	edi--;
	}
      else {
	/* increment ESI */
	esi++;
	edi++;
	}

      if (bx_rep_prefix && bx_cpu.eflags.zf==0) break;
      if (bx_repne_prefix && bx_cpu.eflags.zf!=0) break;
      }

    if (bx_rep_prefix || bx_repne_prefix) {
      ECX = ecx;
      }

    EDI = edi;
    ESI = esi;
    }

  else { /* 16bit address mode */
    Bit16u si, di, cx;

    si = SI;
    di = DI;

    cx = 1;
    if (bx_rep_prefix || bx_repne_prefix) {
      cx = CX;
      }

    for (;cx != 0;) {
      cx--;
      bx_access_virtual(seg, si, 1, BX_READ, &src8);
      bx_access_virtual(&bx_cpu.es, di, 1, BX_READ, &dst8);

      diff_8 = src8 - dst8;

      /* set eflags:
       * CMPSB affects the following flags: O,S,Z,A,P,C
       */
      dst_b7  = dst8  & 0x80;
      src_b7  = src8  & 0x80;
      diff_b7 = diff_8 & 0x80;

      bx_cpu.eflags.of =  (dst_b7 != src_b7) && (diff_b7 != src_b7);
      bx_cpu.eflags.sf = (diff_b7 != 0);
      bx_cpu.eflags.zf = (diff_8 == 0);
      bx_cpu.eflags.af = ((src8 & 0x0F) < (dst8 & 0x0F));
      bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
      bx_cpu.eflags.cf = (src8 < dst8);


      if (bx_cpu.eflags.df) {
	/* decrement ESI */
	si--;
	di--;
	}
      else {
	/* increment ESI */
	si++;
	di++;
	}

      if (bx_rep_prefix && bx_cpu.eflags.zf==0) break;
      if (bx_repne_prefix && bx_cpu.eflags.zf!=0) break;
      }

    if (bx_rep_prefix || bx_repne_prefix) {
      CX = cx;
      }

    DI = di;
    SI = si;
    }
}

  void
bx_CMPSW_XvYv()
{
  bx_segment_reg_t *seg;
  Bit32u src32, dst32, src_b31, dst_b31, diff_32, diff_b31;
  Bit16u src16, dst16, src_b15, dst_b15, diff_16, diff_b15;


  if (bx_segment_override) {
    seg = bx_segment_override;
    }
  else {
    seg = &bx_cpu.ds;
    }

  if (bx_32bit_addrsize) {
    Bit32u esi, edi, ecx;

    esi = ESI;
    edi = EDI;

    ecx = 1;
    if (bx_rep_prefix || bx_repne_prefix) {
      ecx = ECX;
      }

    for (;ecx != 0;) {
      ecx--;

      if (bx_32bit_opsize) {
	bx_access_virtual(seg, esi, 4, BX_READ, &src32);
	bx_access_virtual(&bx_cpu.es, edi, 4, BX_READ, &dst32);

	diff_32 = src32 - dst32;

	/* set eflags:
	 * CMPSB affects the following flags: O,S,Z,A,P,C
	 */
	dst_b31  = dst32  & 0x80000000;
	src_b31  = src32  & 0x80000000;
	diff_b31 = diff_32 & 0x80000000;

	bx_cpu.eflags.of =  (dst_b31 != src_b31) && (diff_b31 != src_b31);
	bx_cpu.eflags.sf = (diff_b31 != 0);
	bx_cpu.eflags.zf = (diff_32 == 0);
	bx_cpu.eflags.af = ((src32 & 0x0F) < (dst32 & 0x0F));
	bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
	bx_cpu.eflags.cf = (src32 < dst32);
	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  esi -= 4;
	  edi -= 4;
	  }
	else {
	  /* increment ESI */
	  esi += 4;
	  edi += 4;
	  }
	}
      else { /* 16 bit opsize */
	bx_access_virtual(seg, esi, 2, BX_READ, &src16);
	bx_access_virtual(&bx_cpu.es, edi, 2, BX_READ, &dst16);

	diff_16 = src16 - dst16;

	/* set eflags:
	 * CMPSB affects the following flags: O,S,Z,A,P,C
	 */
	dst_b15  = dst16  & 0x8000;
	src_b15  = src16  & 0x8000;
	diff_b15 = diff_16 & 0x8000;

	bx_cpu.eflags.of =  (dst_b15 != src_b15) && (diff_b15 != src_b15);
	bx_cpu.eflags.sf = (diff_b15 != 0);
	bx_cpu.eflags.zf = (diff_16 == 0);
	bx_cpu.eflags.af = ((src16 & 0x0F) < (dst16 & 0x0F));
	bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
	bx_cpu.eflags.cf = (src16 < dst16);
	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  esi -= 2;
	  edi -= 2;
	  }
	else {
	  /* increment ESI */
	  esi += 2;
	  edi += 2;
	  }
	}


      if (bx_rep_prefix && bx_cpu.eflags.zf==0) break;
      if (bx_repne_prefix && bx_cpu.eflags.zf!=0) break;
      }

    if (bx_rep_prefix || bx_repne_prefix) {
      ECX = ecx;
      }

    EDI = edi;
    ESI = esi;
    }

  else { /* 16 bit address mode */
    Bit16u si, di, cx;

    si = SI;
    di = DI;

    cx = 1;
    if (bx_rep_prefix || bx_repne_prefix) {
      cx = CX;
      }

    for (;cx != 0;) {
      cx--;

      if (bx_32bit_opsize) {
	bx_access_virtual(seg, si, 4, BX_READ, &src32);
	bx_access_virtual(&bx_cpu.es, di, 4, BX_READ, &dst32);

	diff_32 = src32 - dst32;

	/* set eflags:
	 * CMPSB affects the following flags: O,S,Z,A,P,C
	 */
	dst_b31  = dst32  & 0x80000000;
	src_b31  = src32  & 0x80000000;
	diff_b31 = diff_32 & 0x80000000;

	bx_cpu.eflags.of =  (dst_b31 != src_b31) && (diff_b31 != src_b31);
	bx_cpu.eflags.sf = (diff_b31 != 0);
	bx_cpu.eflags.zf = (diff_32 == 0);
	bx_cpu.eflags.af = ((src32 & 0x0F) < (dst32 & 0x0F));
	bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
	bx_cpu.eflags.cf = (src32 < dst32);
	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  si -= 4;
	  di -= 4;
	  }
	else {
	  /* increment ESI */
	  si += 4;
	  di += 4;
	  }
	}
      else { /* 16 bit opsize */
	bx_access_virtual(seg, si, 2, BX_READ, &src16);
	bx_access_virtual(&bx_cpu.es, di, 2, BX_READ, &dst16);

	diff_16 = src16 - dst16;

	/* set eflags:
	 * CMPSB affects the following flags: O,S,Z,A,P,C
	 */
	dst_b15  = dst16  & 0x8000;
	src_b15  = src16  & 0x8000;
	diff_b15 = diff_16 & 0x8000;

	bx_cpu.eflags.of =  (dst_b15 != src_b15) && (diff_b15 != src_b15);
	bx_cpu.eflags.sf = (diff_b15 != 0);
	bx_cpu.eflags.zf = (diff_16 == 0);
	bx_cpu.eflags.af = ((src16 & 0x0F) < (dst16 & 0x0F));
	bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
	bx_cpu.eflags.cf = (src16 < dst16);
	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  si -= 2;
	  di -= 2;
	  }
	else {
	  /* increment ESI */
	  si += 2;
	  di += 2;
	  }
	}


      if (bx_rep_prefix && bx_cpu.eflags.zf==0) break;
      if (bx_repne_prefix && bx_cpu.eflags.zf!=0) break;
      }

    if (bx_rep_prefix || bx_repne_prefix) {
      CX = cx;
      }

    DI = di;
    SI = si;
    }

}

  void
bx_SCASB_ALXb()
{
  Bit8u al, dst8, src_b7, dst_b7, diff_8, diff_b7;


  if (bx_32bit_addrsize) {
    Bit32u edi, ecx;

    edi = EDI;

    ecx = 1;
    if (bx_rep_prefix || bx_repne_prefix) {
      ecx = ECX;
      }

    al = AL;

    for (;ecx != 0;) {
      ecx--;
      bx_access_virtual(&bx_cpu.es, edi, 1, BX_READ, &dst8);

      diff_8 = al - dst8;

      /* set eflags:
       * CMPSB affects the following flags: O,S,Z,A,P,C
       */
      dst_b7  = dst8  & 0x80;
      src_b7  = al  & 0x80;
      diff_b7 = diff_8 & 0x80;

      bx_cpu.eflags.of =  (dst_b7 != src_b7) && (diff_b7 != src_b7);
      bx_cpu.eflags.sf = (diff_b7 != 0);
      bx_cpu.eflags.zf = (diff_8 == 0);
      bx_cpu.eflags.af = ((al & 0x0F) < (dst8 & 0x0F));
      bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
      bx_cpu.eflags.cf = (al < dst8);


      if (bx_cpu.eflags.df) {
	/* decrement ESI */
	edi--;
	}
      else {
	/* increment ESI */
	edi++;
	}

      if (bx_rep_prefix && bx_cpu.eflags.zf==0) break;
      if (bx_repne_prefix && bx_cpu.eflags.zf!=0) break;
      }

    if (bx_rep_prefix || bx_repne_prefix) {
      ECX = ecx;
      }

    EDI = edi;
    }

  else { /* 16bit address mode */
    Bit16u di, cx;

    di = DI;

    cx = 1;
    if (bx_rep_prefix || bx_repne_prefix) {
      cx = CX;
      }

    al = AL;

    for (;cx != 0;) {
      cx--;
      bx_access_virtual(&bx_cpu.es, di, 1, BX_READ, &dst8);

      diff_8 = al - dst8;

      /* set eflags:
       * CMPSB affects the following flags: O,S,Z,A,P,C
       */
      dst_b7  = dst8  & 0x80;
      src_b7  = al  & 0x80;
      diff_b7 = diff_8 & 0x80;

      bx_cpu.eflags.of =  (dst_b7 != src_b7) && (diff_b7 != src_b7);
      bx_cpu.eflags.sf = (diff_b7 != 0);
      bx_cpu.eflags.zf = (diff_8 == 0);
      bx_cpu.eflags.af = ((al & 0x0F) < (dst8 & 0x0F));
      bx_cpu.eflags.pf = bx_parity_lookup[diff_8];
      bx_cpu.eflags.cf = (al < dst8);


      if (bx_cpu.eflags.df) {
	/* decrement ESI */
	di--;
	}
      else {
	/* increment ESI */
	di++;
	}

      if (bx_rep_prefix && bx_cpu.eflags.zf==0) break;
      if (bx_repne_prefix && bx_cpu.eflags.zf!=0) break;
      }

    if (bx_rep_prefix || bx_repne_prefix) {
      CX = cx;
      }

    DI = di;
    }
}

  void
bx_SCASW_eAXXv()
{

  Bit32u src32, dst32, src_b31, dst_b31, diff_32, diff_b31;
  Bit16u src16, dst16, src_b15, dst_b15, diff_16, diff_b15;


  if (bx_32bit_addrsize) {
    Bit32u edi, ecx;

    edi = EDI;

    ecx = 1;
    if (bx_rep_prefix || bx_repne_prefix) {
      ecx = ECX;
      }
    if (bx_32bit_opsize) {
      src32 = EAX;
      }
    else /* 16 bit opsize mode */
      src16 = AX;

    for (;ecx != 0;) {
      ecx--;

      if (bx_32bit_opsize) {
	bx_access_virtual(&bx_cpu.es, edi, 4, BX_READ, &dst32);

	diff_32 = src32 - dst32;

	/* set eflags:
	 * CMPSB affects the following flags: O,S,Z,A,P,C
	 */
	dst_b31  = dst32  & 0x80000000;
	src_b31  = src32  & 0x80000000;
	diff_b31 = diff_32 & 0x80000000;

	bx_cpu.eflags.of =  (dst_b31 != src_b31) && (diff_b31 != src_b31);
	bx_cpu.eflags.sf = (diff_b31 != 0);
	bx_cpu.eflags.zf = (diff_32 == 0);
	bx_cpu.eflags.af = ((src32 & 0x0F) < (dst32 & 0x0F));
	bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
	bx_cpu.eflags.cf = (src32 < dst32);

	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  edi -= 4;
	  }
	else {
	  /* increment ESI */
	  edi += 4;
	  }
	}
      else { /* 16 bit opsize */
	bx_access_virtual(&bx_cpu.es, edi, 2, BX_READ, &dst16);

	diff_16 = src16 - dst16;

	/* set eflags:
	 * CMPSB affects the following flags: O,S,Z,A,P,C
	 */
	dst_b15  = dst16  & 0x8000;
	src_b15  = src16  & 0x8000;
	diff_b15 = diff_16 & 0x8000;

	bx_cpu.eflags.of =  (dst_b15 != src_b15) && (diff_b15 != src_b15);
	bx_cpu.eflags.sf = (diff_b15 != 0);
	bx_cpu.eflags.zf = (diff_16 == 0);
	bx_cpu.eflags.af = ((src16 & 0x0F) < (dst16 & 0x0F));
	bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
	bx_cpu.eflags.cf = (src16 < dst16);

	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  edi -= 2;
	  }
	else {
	  /* increment ESI */
	  edi += 2;
	  }
	}

      if (bx_rep_prefix && bx_cpu.eflags.zf==0) break;
      if (bx_repne_prefix && bx_cpu.eflags.zf!=0) break;
      }

    if (bx_rep_prefix || bx_repne_prefix) {
      ECX = ecx;
      }

    EDI = edi;
    }

  else { /* 16bit address mode */
    Bit16u di, cx;

    di = DI;

    cx = 1;
    if (bx_rep_prefix || bx_repne_prefix) {
      cx = CX;
      }
    if (bx_32bit_opsize) {
      src32 = EAX;
      }
    else /* 16 bit opsize mode */
      src16 = AX;

    for (;cx != 0;) {
      cx--;

      if (bx_32bit_opsize) {
	bx_access_virtual(&bx_cpu.es, di, 4, BX_READ, &dst32);

	diff_32 = src32 - dst32;

	/* set eflags:
	 * CMPSB affects the following flags: O,S,Z,A,P,C
	 */
	dst_b31  = dst32  & 0x80000000;
	src_b31  = src32  & 0x80000000;
	diff_b31 = diff_32 & 0x80000000;

	bx_cpu.eflags.of =  (dst_b31 != src_b31) && (diff_b31 != src_b31);
	bx_cpu.eflags.sf = (diff_b31 != 0);
	bx_cpu.eflags.zf = (diff_32 == 0);
	bx_cpu.eflags.af = ((src32 & 0x0F) < (dst32 & 0x0F));
	bx_cpu.eflags.pf = bx_parity_lookup[diff_32 & 0xFF];
	bx_cpu.eflags.cf = (src32 < dst32);

	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  di -= 4;
	  }
	else {
	  /* increment ESI */
	  di += 4;
	  }
	}
      else { /* 16 bit opsize */
	bx_access_virtual(&bx_cpu.es, di, 2, BX_READ, &dst16);

	diff_16 = src16 - dst16;

	/* set eflags:
	 * CMPSB affects the following flags: O,S,Z,A,P,C
	 */
	dst_b15  = dst16  & 0x8000;
	src_b15  = src16  & 0x8000;
	diff_b15 = diff_16 & 0x8000;

	bx_cpu.eflags.of =  (dst_b15 != src_b15) && (diff_b15 != src_b15);
	bx_cpu.eflags.sf = (diff_b15 != 0);
	bx_cpu.eflags.zf = (diff_16 == 0);
	bx_cpu.eflags.af = ((src16 & 0x0F) < (dst16 & 0x0F));
	bx_cpu.eflags.pf = bx_parity_lookup[diff_16 & 0xFF];
	bx_cpu.eflags.cf = (src16 < dst16);

	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  di -= 2;
	  }
	else {
	  /* increment ESI */
	  di += 2;
	  }
	}

      if (bx_rep_prefix && bx_cpu.eflags.zf==0) break;
      if (bx_repne_prefix && bx_cpu.eflags.zf!=0) break;
      }

    if (bx_rep_prefix || bx_repne_prefix) {
      CX = cx;
      }

    DI = di;
    }
}

  void
bx_STOSB_YbAL()
{
  Bit8u al;

  if (bx_32bit_addrsize) {
    Bit32u edi, ecx;

    edi = EDI;

    ecx = 1;
    if (bx_rep_prefix) {
      ecx = ECX;
      }
/*  bx_printf(0, "edi = %08x, ecx = %08x\n", (int) edi, (int) ecx); */

    for (;ecx != 0; ecx--) {
      al = AL;
      bx_access_virtual(&bx_cpu.es, edi, 1, BX_WRITE, &al);

      if (bx_cpu.eflags.df) {
	/* decrement EDI */
	edi--;
	}
      else {
	/* increment EDI */
	edi++;
	}
      }

    if (bx_rep_prefix) {
      ECX = 0;
      }

    EDI = edi;
    }

  else { /* 16bit address size */
    Bit16u di, cx;

    di = DI;

    cx = 1;
    if (bx_rep_prefix) {
      cx = CX;
      }
/*  bx_printf(0, "di = %08x, ecx = %08x\n", (int) di, (int) cx); */

    for (;cx != 0; cx--) {
      al = AL;
      bx_access_virtual(&bx_cpu.es, di, 1, BX_WRITE, &al);

      if (bx_cpu.eflags.df) {
	/* decrement EDI */
	di--;
	}
      else {
	/* increment EDI */
	di++;
	}
      }

    if (bx_rep_prefix) {
      CX = 0;
      }

    DI = di;
    }
}

  void
bx_STOSW_YveAX()
{
  Bit16u ax;
  Bit32u eax;


  if (bx_32bit_addrsize) {
    Bit32u edi, ecx;
    edi = EDI;

    ecx = 1;
    if (bx_rep_prefix) {
      ecx = ECX;
      }

    if (bx_32bit_opsize) {
      for (;ecx != 0; ecx--) {
	eax = EAX;
	bx_access_virtual(&bx_cpu.es, edi, 4, BX_WRITE, &eax);
	if (bx_cpu.eflags.df) {
	  /* decrement EDI */
	  edi -= 4;
	  }
	else {
	  /* increment EDI */
	  edi += 4;
	  }
	}
      } /* if (bx_32bit_opsize) ... */
    else { /* 16 bit opsize mode */
      for (;ecx != 0; ecx--) {
	ax = AX;
	bx_access_virtual(&bx_cpu.es, edi, 2, BX_WRITE, &ax);
	if (bx_cpu.eflags.df) {
	  /* decrement EDI */
	  edi -= 2;
	  }
	else {
	  /* increment EDI */
	  edi += 2;
	  }
	}
      }


    if (bx_rep_prefix) {
      ECX = 0;
      }

    EDI = edi;
    }

  else { /* 16bit address size */
    Bit16u di, cx;

    di = DI;

    cx = 1;
    if (bx_rep_prefix) {
      cx = CX;
      }

    if (bx_32bit_opsize) {
      for (;cx != 0; cx--) {
	eax = EAX;
	bx_access_virtual(&bx_cpu.es, di, 4, BX_WRITE, &eax);
	if (bx_cpu.eflags.df) {
	  /* decrement EDI */
	  di -= 4;
	  }
	else {
	  /* increment EDI */
	  di += 4;
	  }
	}
      } /* if (bx_32bit_opsize) ... */
    else { /* 16 bit opsize mode */
      for (;cx != 0; cx--) {
	ax = AX;
	bx_access_virtual(&bx_cpu.es, di, 2, BX_WRITE, &ax);
	if (bx_cpu.eflags.df) {
	  /* decrement EDI */
	  di -= 2;
	  }
	else {
	  /* increment EDI */
	  di += 2;
	  }
	}
      }


    if (bx_rep_prefix) {
      CX = 0;
      }

    DI = di;
    }
}


  void
bx_LODSB_ALXb()
{
  bx_segment_reg_t *seg;
  Bit8u al;

  if (bx_segment_override) {
    seg = bx_segment_override;
    }
  else {
    seg = &bx_cpu.ds;
    }

  if (bx_32bit_addrsize) {
    Bit32u esi, ecx;

    esi = ESI;

    ecx = 1;
    if (bx_rep_prefix) {
      ecx = ECX;
      }

    for (;ecx != 0; ecx--) {
      bx_access_virtual(seg, esi, 1, BX_READ, &al);
      AL = al;
      if (bx_cpu.eflags.df) {
	/* decrement ESI */
	esi--;
	}
      else {
	/* increment ESI */
	esi++;
	}
      }

    if (bx_rep_prefix) {
      ECX = 0;
      }

    ESI = esi;
    }

  else { /* 16bit address mode */
    Bit16u si, cx;

    si = SI;

    cx = 1;
    if (bx_rep_prefix) {
      cx = CX;
      }

    for (;cx != 0; cx--) {
      bx_access_virtual(seg, si, 1, BX_READ, &al);
      AL = al;
      if (bx_cpu.eflags.df) {
	/* decrement ESI */
	si--;
	}
      else {
	/* increment ESI */
	si++;
	}
      }

    if (bx_rep_prefix) {
      CX = 0;
      }

    SI = si;
    }
}

  void
bx_LODSW_eAXXv()
{
  bx_segment_reg_t *seg;
  Bit16u ax;
  Bit32u eax;


  if (bx_segment_override) {
    seg = bx_segment_override;
    }
  else {
    seg = &bx_cpu.ds;
    }

  if (bx_32bit_addrsize) {
    Bit32u esi, ecx;

    esi = ESI;

    ecx = 1;
    if (bx_rep_prefix) {
      ecx = ECX;
      }

    if (bx_32bit_opsize) {
      for (;ecx != 0; ecx--) {
	bx_access_virtual(seg, esi, 4, BX_READ, &eax);
	EAX = eax;
	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  esi -= 4;
	  }
	else {
	  /* increment ESI */
	  esi += 4;
	  }
	}
      } /* if (bx_32bit_opsize) ... */
    else { /* 16 bit opsize mode */
      for (;ecx != 0; ecx--) {
	bx_access_virtual(seg, esi, 2, BX_READ, &ax);
	AX = ax;
	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  esi -= 2;
	  }
	else {
	  /* increment ESI */
	  esi += 2;
	  }
	}
      }


    if (bx_rep_prefix) {
      ECX = 0;
      }

    ESI = esi;
    }

  else { /* 16bit address mode */
    Bit16u si, cx;

    si = SI;

    cx = 1;
    if (bx_rep_prefix) {
      cx = CX;
      }

    if (bx_32bit_opsize) {
      for (;cx != 0; cx--) {
	bx_access_virtual(seg, si, 4, BX_READ, &eax);
	EAX = eax;
	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  si -= 4;
	  }
	else {
	  /* increment ESI */
	  si += 4;
	  }
	}
      } /* if (bx_32bit_opsize) ... */
    else { /* 16 bit opsize mode */
      for (;cx != 0; cx--) {
	bx_access_virtual(seg, si, 2, BX_READ, &ax);
	AX = ax;
	if (bx_cpu.eflags.df) {
	  /* decrement ESI */
	  si -= 2;
	  }
	else {
	  /* increment ESI */
	  si += 2;
	  }
	}
      }


    if (bx_rep_prefix) {
      CX = 0;
      }

    SI = si;
    }
}
