Don't pull in x86emu from a foreign directory anymore. This
produced numerous problems in the past, including the fact that
x86emu doesn't work in v3 anymore even though it lives in the v3
repository.

Since this is a cross-repository move, keeping the history in the v2 tree 
would make life hard for everone. So check the v3 repository for x86emu history
since the merger. The his commit is based on an svn export of r1175 of the
coreboot-v3 repository.

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Patrick Georgi <patrick.georgi@coresystems.de>



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4532 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
diff --git a/util/x86emu/Config.lb b/util/x86emu/Config.lb
new file mode 100644
index 0000000..e5b4b3a
--- /dev/null
+++ b/util/x86emu/Config.lb
@@ -0,0 +1,18 @@
+uses CONFIG_PCI_OPTION_ROM_RUN_YABEL
+uses CONFIG_PCI_OPTION_ROM_RUN_REALMODE
+
+if CONFIG_PCI_OPTION_ROM_RUN_YABEL
+  dir yabel
+  dir x86emu
+else
+  if CONFIG_PCI_OPTION_ROM_RUN_REALMODE
+    object x86.o
+    object x86_interrupts.o
+    object x86_asm.S
+  else
+    object biosemu.o
+    dir pcbios
+    dir x86emu
+  end
+end
+
diff --git a/util/x86emu/Makefile b/util/x86emu/Makefile
new file mode 100644
index 0000000..2c915d4
--- /dev/null
+++ b/util/x86emu/Makefile
@@ -0,0 +1,72 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007 coresystems GmbH
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+##
+
+#X86EMU_INCLUDE = -I $(src)/util/x86emu/include  
+
+X86EMU_SRC  = debug.c decode.c fpu.c ops.c ops2.c prim_ops.c sys.c
+ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_X86EMU),y)
+BIOSEMU_SRC = biosemu.c pcbios/pcibios.c
+endif
+
+ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_YABEL),y)
+BIOSEMU_SRC  = biosemu.c debug.c device.c mem.c io.c interrupt.c 
+#TODO: add vbe.c, currently not needed...
+#BIOSEMU_SRC +=vbe.c
+BIOSEMU_SRC +=pmm.c
+#PH: TODO: remove the compat files??
+BIOSEMU_SRC  += compat/functions.c
+X86EMU_INCLUDE += -I $(src)/util/x86emu/yabel
+X86EMU_INCLUDE += -I $(src)/util/x86emu
+#TODO: remove these, these are .h files from slof, to make the merge easier...
+X86EMU_INCLUDE += -I $(src)/util/x86emu/yabel/compat
+endif
+REALMODE_SRC    = x86.c x86_asm.S
+
+ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_X86EMU),y)
+LIBX86EMU_SRC=$(patsubst %,x86emu/%,$(X86EMU_SRC)) $(BIOSEMU_SRC)
+endif
+
+ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_YABEL),y)
+LIBX86EMU_SRC=$(patsubst %,x86emu/%,$(X86EMU_SRC)) $(patsubst %,yabel/%,$(BIOSEMU_SRC))
+endif
+
+ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_REALMODE),y)
+LIBX86EMU_SRC=$(REALMODE_SRC)
+endif
+
+LIBX86EMU_OBJS = $(patsubst %.c,$(obj)/util/x86emu/%.o,$(LIBX86EMU_SRC))
+# needed for kscope
+PCIROM_SRC += $(patsubst %,$(src)/util/x86emu/%,$(LIBX86EMU_SRC)) 
+
+
+$(obj)/util/x86emu/libx86emu.a: $(LIBX86EMU_OBJS) $(src)/.config
+	$(Q)printf "  AR      $(subst $(shell pwd)/,,$(@))\n"
+	$(Q)rm -f $@ # otherwise we always add to the archive
+	$(Q)$(AR) qcs $@ $(LIBX86EMU_OBJS)
+
+#
+# This rule is also valid for all subdirectories
+#
+
+$(obj)/util/x86emu/%.o: $(src)/util/x86emu/%.c
+	$(Q)mkdir -p $(dir $@)
+	$(Q)printf "  CC      $(subst $(shell pwd)/,,$(@))\n"
+	$(Q)$(CC) -Werror $(INITCFLAGS) $(X86EMU_INCLUDE) -I$(src)/util/x86emu/include -c $< -o $@
+
diff --git a/util/x86emu/biosemu.c b/util/x86emu/biosemu.c
new file mode 100644
index 0000000..e913436
--- /dev/null
+++ b/util/x86emu/biosemu.c
@@ -0,0 +1,399 @@
+/*
+ * This software and ancillary information (herein called SOFTWARE )
+ * called LinuxBIOS          is made available under the terms described
+ * here.  The SOFTWARE has been approved for release with associated
+ * LA-CC Number 00-34   .  Unless otherwise indicated, this SOFTWARE has
+ * been authored by an employee or employees of the University of
+ * California, operator of the Los Alamos National Laboratory under
+ * Contract No. W-7405-ENG-36 with the U.S. Department of Energy.  The
+ * U.S. Government has rights to use, reproduce, and distribute this
+ * SOFTWARE.  The public may copy, distribute, prepare derivative works
+ * and publicly display this SOFTWARE without charge, provided that this
+ * Notice and any statement of authorship are reproduced on all copies.
+ * Neither the Government nor the University makes any warranty, express
+ * or implied, or assumes any liability or responsibility for the use of
+ * this SOFTWARE.  If SOFTWARE is modified to produce derivative works,
+ * such modified SOFTWARE should be clearly marked, so as not to confuse
+ * it with the version available from LANL.
+ */
+ /*
+ * This file is part of the coreboot project.
+ *
+ *  (c) Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
+ *  Copyright (C) 2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by 
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+#ifdef CONFIG_COREBOOT_V2
+#include <arch/io.h>
+#include <console/console.h>
+#else
+#include <io.h>
+#include <console.h>
+#endif
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+
+#include <x86emu/x86emu.h>
+
+#include "pcbios/pcibios.h"
+
+#define MEM_WB(where, what) wrb(where, what)
+#define MEM_WW(where, what) wrw(where, what)
+#define MEM_WL(where, what) wrl(where, what)
+
+#define MEM_RB(where) rdb(where)
+#define MEM_RW(where) rdw(where)
+#define MEM_RL(where) rdl(where)
+
+u8 x_inb(u16 port);
+u16 x_inw(u16 port);
+void x_outb(u16 port, u8 val);
+void x_outw(u16 port, u16 val);
+u32 x_inl(u16 port);
+void x_outl(u16 port, u32 val);
+
+//
+void X86EMU_setMemBase(void *base, size_t size);
+
+/* general software interrupt handler */
+u32 getIntVect(int num)
+{
+	return MEM_RW(num << 2) + (MEM_RW((num << 2) + 2) << 4);
+}
+
+/* FIXME: There is already a push_word() in the emulator */
+void pushw(u16 val)
+{
+	X86_ESP -= 2;
+	MEM_WW(((u32) X86_SS << 4) + X86_SP, val);
+}
+
+int run_bios_int(int num)
+{
+	u32 eflags;
+
+	eflags = X86_EFLAGS;
+	pushw(eflags);
+	pushw(X86_CS);
+	pushw(X86_IP);
+	X86_CS = MEM_RW((num << 2) + 2);
+	X86_IP = MEM_RW(num << 2);
+
+	return 1;
+}
+
+u8 x_inb(u16 port)
+{
+	u8 val;
+
+	val = inb(port);
+#ifdef CONFIG_DEBUG
+	if (port != 0x40)
+	    printk("inb(0x%04x) = 0x%02x\n", port, val);
+#endif
+
+	return val;
+}
+
+u16 x_inw(u16 port)
+{
+	u16 val;
+
+	val = inw(port);
+
+#ifdef CONFIG_DEBUG
+	printk("inw(0x%04x) = 0x%04x\n", port, val);
+#endif
+	return val;
+}
+
+u32 x_inl(u16 port)
+{
+	u32 val;
+
+	val = inl(port);
+
+#ifdef CONFIG_DEBUG
+	printk("inl(0x%04x) = 0x%08x\n", port, val);
+#endif
+	return val;
+}
+
+void x_outb(u16 port, u8 val)
+{
+#ifdef CONFIG_DEBUG
+	if (port != 0x43)
+		printk("outb(0x%02x, 0x%04x)\n", val, port);
+#endif
+	outb(val, port);
+}
+
+void x_outw(u16 port, u16 val)
+{
+#ifdef CONFIG_DEBUG
+	printk("outw(0x%04x, 0x%04x)\n", val, port);
+#endif
+	outw(val, port);
+}
+
+void x_outl(u16 port, u32 val)
+{
+#ifdef CONFIG_DEBUG
+	printk("outl(0x%08x, 0x%04x)\n", val, port);
+#endif
+	outl(val, port);
+}
+
+X86EMU_pioFuncs myfuncs = {
+	x_inb, x_inw, x_inl,
+	x_outb, x_outw, x_outl
+};
+
+
+
+/* Interrupt multiplexer */
+
+void do_int(int num)
+{
+	int ret = 0;
+
+	printk("int%x vector at %x\n", num, getIntVect(num));
+
+	switch (num) {
+#ifndef _PC
+	case 0x10:
+	case 0x42:
+	case 0x6D:
+		if (getIntVect(num) == 0x0000) {
+			printk("uninitialized interrupt vector\n");
+			ret = 1;
+		}
+		if (getIntVect(num) == 0xFF065) {
+			//ret = int42_handler();
+			ret = 1;
+		}
+		break;
+#endif
+	case 0x15:
+		//ret = int15_handler();
+		ret = 1;
+		break;
+	case 0x16:
+		//ret = int16_handler();
+		ret = 0;
+		break;
+	case 0x1A:
+		ret = pcibios_handler();
+		ret = 1;
+		break;
+	case 0xe6:
+		//ret = intE6_handler();
+		ret = 0;
+		break;
+	default:
+		break;
+	}
+
+	if (!ret)
+		ret = run_bios_int(num);
+
+}
+
+#if 0
+#define SYS_BIOS 0xf0000
+/*
+ * here we are really paranoid about faking a "real"
+ * BIOS. Most of this information was pulled from
+ * dosemu.
+ */
+#if 0
+void setup_int_vect(void)
+{
+	int i;
+
+	/* let the int vects point to the SYS_BIOS seg */
+	for (i = 0; i < 0x80; i++) {
+		MEM_WW(i << 2, 0);
+		MEM_WW((i << 2) + 2, SYS_BIOS >> 4);
+	}
+
+	reset_int_vect();
+
+	/* font tables default location (int 1F) */
+	MEM_WW(0x1f << 2, 0xfa6e);
+	/* int 11 default location (Get Equipment Configuration) */
+	MEM_WW(0x11 << 2, 0xf84d);
+	/* int 12 default location (Get Conventional Memory Size) */
+	MEM_WW(0x12 << 2, 0xf841);
+	/* int 15 default location (I/O System Extensions) */
+	MEM_WW(0x15 << 2, 0xf859);
+	/* int 1A default location (RTC, PCI and others) */
+	MEM_WW(0x1a << 2, 0xff6e);
+	/* int 05 default location (Bound Exceeded) */
+	MEM_WW(0x05 << 2, 0xff54);
+	/* int 08 default location (Double Fault) */
+	MEM_WW(0x08 << 2, 0xfea5);
+	/* int 13 default location (Disk) */
+	MEM_WW(0x13 << 2, 0xec59);
+	/* int 0E default location (Page Fault) */
+	MEM_WW(0x0e << 2, 0xef57);
+	/* int 17 default location (Parallel Port) */
+	MEM_WW(0x17 << 2, 0xefd2);
+	/* fdd table default location (int 1e) */
+	MEM_WW(0x1e << 2, 0xefc7);
+
+	/* Set Equipment flag to VGA */
+	i = MEM_RB(0x0410) & 0xCF;
+	MEM_WB(0x0410, i);
+	/* XXX Perhaps setup more of the BDA here.  See also int42(0x00). */
+}
+
+int setup_system_bios(void *base_addr)
+{
+	char *base = (char *) base_addr;
+
+	/*
+	 * we trap the "industry standard entry points" to the BIOS
+	 * and all other locations by filling them with "hlt"
+	 * TODO: implement hlt-handler for these
+	 */
+	memset(base, 0xf4, 0x10000);
+
+	/* set bios date */
+	//strcpy(base + 0x0FFF5, "06/11/99");
+	/* set up eisa ident string */
+	//strcpy(base + 0x0FFD9, "PCI_ISA");
+	/* write system model id for IBM-AT */
+	//*((unsigned char *) (base + 0x0FFFE)) = 0xfc;
+
+	return 1;
+}
+#endif
+
+void reset_int_vect(void)
+{
+	/*
+	 * This table is normally located at 0xF000:0xF0A4.  However, int 0x42,
+	 * function 0 (Mode Set) expects it (or a copy) somewhere in the bottom
+	 * 64kB.  Note that because this data doesn't survive POST, int 0x42 should
+	 * only be used during EGA/VGA BIOS initialisation.
+	 */
+	static const u8 VideoParms[] = {
+		/* Timing for modes 0x00 & 0x01 */
+		0x38, 0x28, 0x2d, 0x0a, 0x1f, 0x06, 0x19, 0x1c,
+		0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
+		/* Timing for modes 0x02 & 0x03 */
+		0x71, 0x50, 0x5a, 0x0a, 0x1f, 0x06, 0x19, 0x1c,
+		0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
+		/* Timing for modes 0x04, 0x05 & 0x06 */
+		0x38, 0x28, 0x2d, 0x0a, 0x7f, 0x06, 0x64, 0x70,
+		0x02, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
+		/* Timing for mode 0x07 */
+		0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19,
+		0x02, 0x0d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
+		/* Display page lengths in little endian order */
+		0x00, 0x08,	/* Modes 0x00 and 0x01 */
+		0x00, 0x10,	/* Modes 0x02 and 0x03 */
+		0x00, 0x40,	/* Modes 0x04 and 0x05 */
+		0x00, 0x40,	/* Modes 0x06 and 0x07 */
+		/* Number of columns for each mode */
+		40, 40, 80, 80, 40, 40, 80, 80,
+		/* CGA Mode register value for each mode */
+		0x2c, 0x28, 0x2d, 0x29, 0x2a, 0x2e, 0x1e, 0x29,
+		/* Padding */
+		0x00, 0x00, 0x00, 0x00
+	};
+	int i;
+
+	for (i = 0; i < sizeof(VideoParms); i++)
+		MEM_WB(i + (0x1000 - sizeof(VideoParms)), VideoParms[i]);
+	MEM_WW(0x1d << 2, 0x1000 - sizeof(VideoParms));
+	MEM_WW((0x1d << 2) + 2, 0);
+
+	printk(BIOS_DEBUG,"SETUP INT\n");
+	MEM_WW(0x10 << 2, 0xf065);
+	MEM_WW((0x10 << 2) + 2, SYS_BIOS >> 4);
+	MEM_WW(0x42 << 2, 0xf065);
+	MEM_WW((0x42 << 2) + 2, SYS_BIOS >> 4);
+	MEM_WW(0x6D << 2, 0xf065);
+	MEM_WW((0x6D << 2) + 2, SYS_BIOS >> 4);
+}
+#endif
+
+void run_bios(struct device * dev, unsigned long addr)
+{
+#if 1
+	int i;
+	unsigned short initialcs = (addr & 0xF0000) >> 4;
+	unsigned short initialip = (addr + 3) & 0xFFFF;
+	unsigned short devfn = dev->bus->secondary << 8 | dev->path.pci.devfn;
+
+	X86EMU_intrFuncs intFuncs[256];
+
+	X86EMU_setMemBase(0, 0x100000);
+	X86EMU_setupPioFuncs(&myfuncs);
+	for (i = 0; i < 256; i++)
+		intFuncs[i] = do_int;
+	X86EMU_setupIntrFuncs(intFuncs);
+
+	{
+		char *date = "01/01/99";
+		for (i = 0; date[i]; i++)
+			wrb(0xffff5 + i, date[i]);
+		wrb(0xffff7, '/');
+		wrb(0xffffa, '/');
+	}
+
+	{
+	    /* FixME: move PIT init to its own file */
+	    outb(0x36, 0x43);
+	    outb(0x00, 0x40);
+	    outb(0x00, 0x40);
+	}
+	//setup_int_vect();
+
+	/* cpu setup */
+	X86_AX = devfn ? devfn : 0xff;
+	X86_DX = 0x80;
+	X86_EIP = initialip;
+	X86_CS = initialcs;
+
+	/* Initialize stack and data segment */
+	X86_SS = initialcs;
+	X86_SP = 0xfffe;
+	X86_DS = 0x0040;
+	X86_ES = 0x0000;
+
+	/* We need a sane way to return from bios
+	 * execution. A hlt instruction and a pointer
+	 * to it, both kept on the stack, will do.
+	 */
+	pushw(0xf4f4);		/* hlt; hlt */
+	pushw(X86_SS);
+	pushw(X86_SP + 2);
+
+#ifdef CONFIG_DEBUG
+	//X86EMU_trace_on();
+#endif
+
+	printk("entering emulator\n");
+	X86EMU_exec();
+	printk("exited emulator\n");
+
+#endif
+}
diff --git a/util/x86emu/include/x86emu/fpu_regs.h b/util/x86emu/include/x86emu/fpu_regs.h
new file mode 100644
index 0000000..efc13ef
--- /dev/null
+++ b/util/x86emu/include/x86emu/fpu_regs.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+*
+*						Realmode X86 Emulator Library
+*
+*            	Copyright (C) 1996-1999 SciTech Software, Inc.
+* 				     Copyright (C) David Mosberger-Tang
+* 					   Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:		ANSI C
+* Environment:	Any
+* Developer:    Kendall Bennett
+*
+* Description:  Header file for FPU register definitions.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_FPU_REGS_H
+#define __X86EMU_FPU_REGS_H
+
+#ifdef X86_FPU_SUPPORT
+
+#pragma	pack(1)
+
+/* Basic 8087 register can hold any of the following values: */
+
+union x86_fpu_reg_u {
+    s8                  tenbytes[10];
+    double              dval;
+    float               fval;
+    s16                 sval;
+    s32                 lval;
+	};
+
+struct x86_fpu_reg {
+	union x86_fpu_reg_u reg;
+	char                tag;
+	};
+
+/*
+ * Since we are not going to worry about the problems of aliasing
+ * registers, every time a register is modified, its result type is
+ * set in the tag fields for that register.  If some operation
+ * attempts to access the type in a way inconsistent with its current
+ * storage format, then we flag the operation.  If common, we'll
+ * attempt the conversion.
+ */
+
+#define  X86_FPU_VALID          0x80
+#define  X86_FPU_REGTYP(r)      ((r) & 0x7F)
+
+#define  X86_FPU_WORD           0x0
+#define  X86_FPU_SHORT          0x1
+#define  X86_FPU_LONG           0x2
+#define  X86_FPU_FLOAT          0x3
+#define  X86_FPU_DOUBLE         0x4
+#define  X86_FPU_LDBL           0x5
+#define  X86_FPU_BSD            0x6
+
+#define  X86_FPU_STKTOP  0
+
+struct x86_fpu_registers {
+    struct x86_fpu_reg  x86_fpu_stack[8];
+    int                 x86_fpu_flags;
+    int                 x86_fpu_config;         /* rounding modes, etc. */
+    short               x86_fpu_tos, x86_fpu_bos;
+	};
+
+#pragma	pack()
+
+/*
+ * There are two versions of the following macro.
+ *
+ * One version is for opcode D9, for which there are more than 32
+ * instructions encoded in the second byte of the opcode.
+ *
+ * The other version, deals with all the other 7 i87 opcodes, for
+ * which there are only 32 strings needed to describe the
+ * instructions.
+ */
+
+#endif /* X86_FPU_SUPPORT */
+
+#ifdef CONFIG_DEBUG
+# define DECODE_PRINTINSTR32(t,mod,rh,rl)     	\
+	DECODE_PRINTF(t[(mod<<3)+(rh)]);
+# define DECODE_PRINTINSTR256(t,mod,rh,rl)    	\
+	DECODE_PRINTF(t[(mod<<6)+(rh<<3)+(rl)]);
+#else
+# define DECODE_PRINTINSTR32(t,mod,rh,rl)
+# define DECODE_PRINTINSTR256(t,mod,rh,rl)
+#endif
+
+#endif /* __X86EMU_FPU_REGS_H */
diff --git a/util/x86emu/include/x86emu/regs.h b/util/x86emu/include/x86emu/regs.h
new file mode 100644
index 0000000..4b368e4
--- /dev/null
+++ b/util/x86emu/include/x86emu/regs.h
@@ -0,0 +1,379 @@
+/****************************************************************************
+*
+*						Realmode X86 Emulator Library
+*
+*            	Copyright (C) 1996-1999 SciTech Software, Inc.
+* 				     Copyright (C) David Mosberger-Tang
+* 					   Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:		ANSI C
+* Environment:	Any
+* Developer:    Kendall Bennett
+*
+* Description:  Header file for x86 register definitions.
+*
+****************************************************************************/
+/* $XFree86: xc/extras/x86emu/include/x86emu/regs.h,v 1.3 2001/10/28 03:32:25 tsi Exp $ */
+
+#ifndef __X86EMU_REGS_H
+#define __X86EMU_REGS_H
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#pragma pack(1)
+
+/*
+ * General EAX, EBX, ECX, EDX type registers.  Note that for
+ * portability, and speed, the issue of byte swapping is not addressed
+ * in the registers.  All registers are stored in the default format
+ * available on the host machine.  The only critical issue is that the
+ * registers should line up EXACTLY in the same manner as they do in
+ * the 386.  That is:
+ *
+ * EAX & 0xff  === AL
+ * EAX & 0xffff == AX
+ *
+ * etc.  The result is that alot of the calculations can then be
+ * done using the native instruction set fully.
+ */
+
+#ifdef	__BIG_ENDIAN__
+
+typedef struct {
+    u32 e_reg;
+	} I32_reg_t;
+
+typedef struct {
+	u16 filler0, x_reg;
+	} I16_reg_t;
+
+typedef struct {
+	u8 filler0, filler1, h_reg, l_reg;
+	} I8_reg_t;
+
+#else /* !__BIG_ENDIAN__ */
+
+typedef struct {
+    u32 e_reg;
+	} I32_reg_t;
+
+typedef struct {
+	u16 x_reg;
+	} I16_reg_t;
+
+typedef struct {
+	u8 l_reg, h_reg;
+	} I8_reg_t;
+
+#endif /* BIG_ENDIAN */
+
+typedef union {
+	I32_reg_t   I32_reg;
+	I16_reg_t   I16_reg;
+	I8_reg_t    I8_reg;
+	} i386_general_register;
+
+struct i386_general_regs {
+	i386_general_register A, B, C, D;
+	};
+
+typedef struct i386_general_regs Gen_reg_t;
+
+struct i386_special_regs {
+	i386_general_register SP, BP, SI, DI, IP;
+	u32 FLAGS;
+	};
+
+/*  
+ * Segment registers here represent the 16 bit quantities
+ * CS, DS, ES, SS.
+ */
+
+struct i386_segment_regs {
+    u16 CS, DS, SS, ES, FS, GS;
+	};
+
+/* 8 bit registers */
+#define R_AH  gen.A.I8_reg.h_reg
+#define R_AL  gen.A.I8_reg.l_reg
+#define R_BH  gen.B.I8_reg.h_reg
+#define R_BL  gen.B.I8_reg.l_reg
+#define R_CH  gen.C.I8_reg.h_reg
+#define R_CL  gen.C.I8_reg.l_reg
+#define R_DH  gen.D.I8_reg.h_reg
+#define R_DL  gen.D.I8_reg.l_reg
+
+/* 16 bit registers */
+#define R_AX  gen.A.I16_reg.x_reg
+#define R_BX  gen.B.I16_reg.x_reg
+#define R_CX  gen.C.I16_reg.x_reg
+#define R_DX  gen.D.I16_reg.x_reg
+
+/* 32 bit extended registers */
+#define R_EAX  gen.A.I32_reg.e_reg
+#define R_EBX  gen.B.I32_reg.e_reg
+#define R_ECX  gen.C.I32_reg.e_reg
+#define R_EDX  gen.D.I32_reg.e_reg
+
+/* special registers */
+#define R_SP  spc.SP.I16_reg.x_reg
+#define R_BP  spc.BP.I16_reg.x_reg
+#define R_SI  spc.SI.I16_reg.x_reg
+#define R_DI  spc.DI.I16_reg.x_reg
+#define R_IP  spc.IP.I16_reg.x_reg
+#define R_FLG spc.FLAGS
+
+/* special registers */
+#define R_SP  spc.SP.I16_reg.x_reg
+#define R_BP  spc.BP.I16_reg.x_reg
+#define R_SI  spc.SI.I16_reg.x_reg
+#define R_DI  spc.DI.I16_reg.x_reg
+#define R_IP  spc.IP.I16_reg.x_reg
+#define R_FLG spc.FLAGS
+
+/* special registers */
+#define R_ESP  spc.SP.I32_reg.e_reg
+#define R_EBP  spc.BP.I32_reg.e_reg
+#define R_ESI  spc.SI.I32_reg.e_reg
+#define R_EDI  spc.DI.I32_reg.e_reg
+#define R_EIP  spc.IP.I32_reg.e_reg
+#define R_EFLG spc.FLAGS
+
+/* segment registers */
+#define R_CS  seg.CS
+#define R_DS  seg.DS
+#define R_SS  seg.SS
+#define R_ES  seg.ES
+#define R_FS  seg.FS
+#define R_GS  seg.GS
+
+/* flag conditions   */
+#define FB_CF 0x0001            /* CARRY flag  */
+#define FB_PF 0x0004            /* PARITY flag */
+#define FB_AF 0x0010            /* AUX  flag   */
+#define FB_ZF 0x0040            /* ZERO flag   */
+#define FB_SF 0x0080            /* SIGN flag   */
+#define FB_TF 0x0100            /* TRAP flag   */
+#define FB_IF 0x0200            /* INTERRUPT ENABLE flag */
+#define FB_DF 0x0400            /* DIR flag    */
+#define FB_OF 0x0800            /* OVERFLOW flag */
+
+/* 80286 and above always have bit#1 set */
+#define F_ALWAYS_ON  (0x0002)   /* flag bits always on */
+
+/*
+ * Define a mask for only those flag bits we will ever pass back 
+ * (via PUSHF) 
+ */
+#define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF)
+
+/* following bits masked in to a 16bit quantity */
+
+#define F_CF 0x0001             /* CARRY flag  */
+#define F_PF 0x0004             /* PARITY flag */
+#define F_AF 0x0010             /* AUX  flag   */
+#define F_ZF 0x0040             /* ZERO flag   */
+#define F_SF 0x0080             /* SIGN flag   */
+#define F_TF 0x0100             /* TRAP flag   */
+#define F_IF 0x0200             /* INTERRUPT ENABLE flag */
+#define F_DF 0x0400             /* DIR flag    */
+#define F_OF 0x0800             /* OVERFLOW flag */
+
+#define TOGGLE_FLAG(flag)     	(M.x86.R_FLG ^= (flag))
+#define SET_FLAG(flag)        	(M.x86.R_FLG |= (flag))
+#define CLEAR_FLAG(flag)      	(M.x86.R_FLG &= ~(flag))
+#define ACCESS_FLAG(flag)     	(M.x86.R_FLG & (flag))
+#define CLEARALL_FLAG(m)    	(M.x86.R_FLG = 0)
+
+#define CONDITIONAL_SET_FLAG(COND,FLAG) \
+  if (COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG)
+
+#define F_PF_CALC 0x010000      /* PARITY flag has been calced    */
+#define F_ZF_CALC 0x020000      /* ZERO flag has been calced      */
+#define F_SF_CALC 0x040000      /* SIGN flag has been calced      */
+
+#define F_ALL_CALC      0xff0000        /* All have been calced   */
+
+/*
+ * Emulator machine state.
+ * Segment usage control.
+ */
+#define SYSMODE_SEG_DS_SS       0x00000001
+#define SYSMODE_SEGOVR_CS       0x00000002
+#define SYSMODE_SEGOVR_DS       0x00000004
+#define SYSMODE_SEGOVR_ES       0x00000008
+#define SYSMODE_SEGOVR_FS       0x00000010
+#define SYSMODE_SEGOVR_GS       0x00000020
+#define SYSMODE_SEGOVR_SS       0x00000040
+#define SYSMODE_PREFIX_REPE     0x00000080
+#define SYSMODE_PREFIX_REPNE    0x00000100
+#define SYSMODE_PREFIX_DATA     0x00000200
+#define SYSMODE_PREFIX_ADDR     0x00000400
+//phueper: for REP(E|NE) Instructions, we need to decide wether it should be using
+//the 32bit ECX register as or the 16bit CX register as count register
+#define SYSMODE_32BIT_REP       0x00000800
+#define SYSMODE_INTR_PENDING    0x10000000
+#define SYSMODE_EXTRN_INTR      0x20000000
+#define SYSMODE_HALTED          0x40000000
+
+#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS      | \
+						 SYSMODE_SEGOVR_CS      | \
+						 SYSMODE_SEGOVR_DS      | \
+						 SYSMODE_SEGOVR_ES      | \
+						 SYSMODE_SEGOVR_FS      | \
+						 SYSMODE_SEGOVR_GS      | \
+						 SYSMODE_SEGOVR_SS)
+#define SYSMODE_CLRMASK (SYSMODE_SEG_DS_SS      | \
+						 SYSMODE_SEGOVR_CS      | \
+						 SYSMODE_SEGOVR_DS      | \
+						 SYSMODE_SEGOVR_ES      | \
+						 SYSMODE_SEGOVR_FS      | \
+						 SYSMODE_SEGOVR_GS      | \
+						 SYSMODE_SEGOVR_SS      | \
+						 SYSMODE_PREFIX_DATA    | \
+						 SYSMODE_PREFIX_ADDR    | \
+						 SYSMODE_32BIT_REP)
+
+#define  INTR_SYNCH           0x1
+#define  INTR_ASYNCH          0x2
+#define  INTR_HALTED          0x4
+
+typedef struct {
+    struct i386_general_regs    gen;
+    struct i386_special_regs    spc;
+    struct i386_segment_regs    seg;
+    /*
+     * MODE contains information on:
+     *  REPE prefix             2 bits  repe,repne
+     *  SEGMENT overrides       5 bits  normal,DS,SS,CS,ES
+     *  Delayed flag set        3 bits  (zero, signed, parity)
+     *  reserved                6 bits
+     *  interrupt #             8 bits  instruction raised interrupt
+     *  BIOS video segregs      4 bits  
+     *  Interrupt Pending       1 bits  
+     *  Extern interrupt        1 bits
+     *  Halted                  1 bits
+     */
+    u32                         mode;
+    volatile int                intr;   /* mask of pending interrupts */
+    volatile int                         debug;
+#ifdef CONFIG_DEBUG
+    int                         check;
+    u16                         saved_ip;
+    u16                         saved_cs;
+    int                         enc_pos;
+    int                         enc_str_pos;
+    char                        decode_buf[32]; /* encoded byte stream  */
+    char                        decoded_buf[256]; /* disassembled strings */
+#endif
+    u8                          intno;
+    u8                          __pad[3];
+	} X86EMU_regs;
+
+/****************************************************************************
+REMARKS:
+Structure maintaining the emulator machine state.
+
+MEMBERS:
+mem_base		- Base real mode memory for the emulator
+abseg			- Base for the absegment
+mem_size		- Size of the real mode memory block for the emulator
+private			- private data pointer
+x86			- X86 registers
+****************************************************************************/
+typedef struct {
+	unsigned long	mem_base;
+	unsigned long	mem_size;
+	unsigned long	abseg;
+	void*        	private;
+	X86EMU_regs		x86;
+	} X86EMU_sysEnv;
+
+#pragma pack()
+
+/*----------------------------- Global Variables --------------------------*/
+
+#ifdef  __cplusplus
+extern "C" {            			/* Use "C" linkage when in C++ mode */
+#endif
+
+/* Global emulator machine state.
+ *
+ * We keep it global to avoid pointer dereferences in the code for speed.
+ */
+
+extern    X86EMU_sysEnv	_X86EMU_env;
+#define   M             _X86EMU_env
+
+#define X86_EAX M.x86.R_EAX
+#define X86_EBX M.x86.R_EBX
+#define X86_ECX M.x86.R_ECX
+#define X86_EDX M.x86.R_EDX
+#define X86_ESI M.x86.R_ESI
+#define X86_EDI M.x86.R_EDI
+#define X86_EBP M.x86.R_EBP
+#define X86_EIP M.x86.R_EIP
+#define X86_ESP M.x86.R_ESP
+#define X86_EFLAGS M.x86.R_EFLG
+
+#define X86_FLAGS M.x86.R_FLG
+#define X86_AX M.x86.R_AX
+#define X86_BX M.x86.R_BX
+#define X86_CX M.x86.R_CX
+#define X86_DX M.x86.R_DX
+#define X86_SI M.x86.R_SI
+#define X86_DI M.x86.R_DI
+#define X86_BP M.x86.R_BP
+#define X86_IP M.x86.R_IP
+#define X86_SP M.x86.R_SP
+#define X86_CS M.x86.R_CS
+#define X86_DS M.x86.R_DS
+#define X86_ES M.x86.R_ES
+#define X86_SS M.x86.R_SS
+#define X86_FS M.x86.R_FS
+#define X86_GS M.x86.R_GS
+
+#define X86_AL M.x86.R_AL
+#define X86_BL M.x86.R_BL
+#define X86_CL M.x86.R_CL
+#define X86_DL M.x86.R_DL
+
+#define X86_AH M.x86.R_AH
+#define X86_BH M.x86.R_BH
+#define X86_CH M.x86.R_CH
+#define X86_DH M.x86.R_DH
+
+		
+/*-------------------------- Function Prototypes --------------------------*/
+
+/* Function to log information at runtime */
+
+//void	printk(const char *fmt, ...);
+
+#ifdef  __cplusplus
+}                       			/* End of "C" linkage for C++   	*/
+#endif
+
+#endif /* __X86EMU_REGS_H */
diff --git a/util/x86emu/include/x86emu/types.h b/util/x86emu/include/x86emu/types.h
new file mode 100644
index 0000000..5485eea
--- /dev/null
+++ b/util/x86emu/include/x86emu/types.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+*
+*						Realmode X86 Emulator Library
+*
+*            	Copyright (C) 1996-1999 SciTech Software, Inc.
+* 				     Copyright (C) David Mosberger-Tang
+* 					   Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:		ANSI C
+* Environment:	Any
+* Developer:    Kendall Bennett
+*
+* Description:  Header file for x86 emulator type definitions.
+*
+****************************************************************************/
+
+/* $XFree86: xc/extras/x86emu/include/x86emu/types.h,v 1.4 2000/09/26 15:56:44 tsi Exp $ */
+
+#ifndef __X86EMU_TYPES_H
+#define __X86EMU_TYPES_H
+
+//#ifndef IN_MODULE
+//#include <sys/types.h>
+//#endif
+
+/*
+ * The following kludge is an attempt to work around typedef conflicts with
+ * <sys/types.h>.
+ */
+#define u8   x86emuu8
+#define u16  x86emuu16
+#define u32  x86emuu32
+#define u64  x86emuu64
+#define s8   x86emus8
+#define s16  x86emus16
+#define s32  x86emus32
+#define s64  x86emus64
+#define uint x86emuuint
+#define sint x86emusint
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+/* Currently only for Linux/32bit */
+#if defined(__GNUC__) && !defined(NO_LONG_LONG)
+#define __HAS_LONG_LONG__
+#endif
+
+typedef unsigned char 		u8;
+typedef unsigned short 		u16;
+typedef unsigned int 		u32;
+#ifdef __HAS_LONG_LONG__
+typedef unsigned long long 	u64;
+#endif
+
+typedef signed char 		s8;
+typedef signed short 		s16;
+typedef signed int 		s32;
+#ifdef __HAS_LONG_LONG__
+typedef signed long long 	s64;
+#endif
+
+typedef unsigned int		uint;
+typedef signed int 		sint;
+
+typedef u16 X86EMU_pioAddr;
+
+#endif	/* __X86EMU_TYPES_H */
diff --git a/util/x86emu/include/x86emu/x86emu.h b/util/x86emu/include/x86emu/x86emu.h
new file mode 100644
index 0000000..6101e57
--- /dev/null
+++ b/util/x86emu/include/x86emu/x86emu.h
@@ -0,0 +1,206 @@
+/****************************************************************************
+*
+*						Realmode X86 Emulator Library
+*
+*            	Copyright (C) 1996-1999 SciTech Software, Inc.
+* 				     Copyright (C) David Mosberger-Tang
+* 					   Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:		ANSI C
+* Environment:	Any
+* Developer:    Kendall Bennett
+*
+* Description:  Header file for public specific functions.
+*               Any application linking against us should only
+*               include this header
+*
+****************************************************************************/
+/* $XFree86: xc/extras/x86emu/include/x86emu.h,v 1.2 2000/11/21 23:10:25 tsi Exp $ */
+
+#ifndef __X86EMU_X86EMU_H
+#define __X86EMU_X86EMU_H
+
+/* FIXME: undefine printk for the moment */
+#if 1 /* Coreboot needs to map prinkf to printk. */
+#include <console.h>
+#define printk(x...) printk(BIOS_DEBUG, x)
+#else
+#define printk printf
+#endif 
+
+#ifdef SCITECH
+#include "scitech.h"
+#define	X86API	_ASMAPI
+#define	X86APIP	_ASMAPIP
+typedef int X86EMU_pioAddr;
+#else
+#include "types.h"
+#define	X86API
+#define	X86APIP	*
+#endif
+#include "regs.h"
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#pragma	pack(1)
+
+/****************************************************************************
+REMARKS:
+Data structure containing ponters to programmed I/O functions used by the
+emulator. This is used so that the user program can hook all programmed
+I/O for the emulator to handled as necessary by the user program. By
+default the emulator contains simple functions that do not do access the
+hardware in any way. To allow the emualtor access the hardware, you will
+need to override the programmed I/O functions using the X86EMU_setupPioFuncs
+function.
+
+HEADER:
+x86emu.h
+
+MEMBERS:
+inb		- Function to read a byte from an I/O port
+inw		- Function to read a word from an I/O port
+inl     - Function to read a dword from an I/O port
+outb	- Function to write a byte to an I/O port
+outw    - Function to write a word to an I/O port
+outl    - Function to write a dword to an I/O port
+****************************************************************************/
+typedef struct {
+	u8  	(X86APIP inb)(X86EMU_pioAddr addr);
+	u16 	(X86APIP inw)(X86EMU_pioAddr addr);
+	u32 	(X86APIP inl)(X86EMU_pioAddr addr);
+	void 	(X86APIP outb)(X86EMU_pioAddr addr, u8 val);
+	void 	(X86APIP outw)(X86EMU_pioAddr addr, u16 val);
+	void 	(X86APIP outl)(X86EMU_pioAddr addr, u32 val);
+	} X86EMU_pioFuncs;
+
+/****************************************************************************
+REMARKS:
+Data structure containing ponters to memory access functions used by the
+emulator. This is used so that the user program can hook all memory
+access functions as necessary for the emulator. By default the emulator
+contains simple functions that only access the internal memory of the
+emulator. If you need specialised functions to handle access to different
+types of memory (ie: hardware framebuffer accesses and BIOS memory access
+etc), you will need to override this using the X86EMU_setupMemFuncs
+function.
+
+HEADER:
+x86emu.h
+
+MEMBERS:
+rdb		- Function to read a byte from an address
+rdw		- Function to read a word from an address
+rdl     - Function to read a dword from an address
+wrb		- Function to write a byte to an address
+wrw    	- Function to write a word to an address
+wrl    	- Function to write a dword to an address
+****************************************************************************/
+typedef struct {
+	u8  	(X86APIP rdb)(u32 addr);
+	u16 	(X86APIP rdw)(u32 addr);
+	u32 	(X86APIP rdl)(u32 addr);
+	void 	(X86APIP wrb)(u32 addr, u8 val);
+	void 	(X86APIP wrw)(u32 addr, u16 val);
+	void	(X86APIP wrl)(u32 addr, u32 val);
+	} X86EMU_memFuncs;
+
+/****************************************************************************
+  Here are the default memory read and write
+  function in case they are needed as fallbacks.
+***************************************************************************/
+extern u8 X86API rdb(u32 addr);
+extern u16 X86API rdw(u32 addr);
+extern u32 X86API rdl(u32 addr);
+extern void X86API wrb(u32 addr, u8 val);
+extern void X86API wrw(u32 addr, u16 val);
+extern void X86API wrl(u32 addr, u32 val);
+ 
+#pragma	pack()
+
+/*--------------------- type definitions -----------------------------------*/
+
+typedef void (X86APIP X86EMU_intrFuncs)(int num);
+extern X86EMU_intrFuncs _X86EMU_intrTab[256];
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+#ifdef  __cplusplus
+extern "C" {            			/* Use "C" linkage when in C++ mode */
+#endif
+
+void 	X86EMU_setupMemFuncs(X86EMU_memFuncs *funcs);
+void 	X86EMU_setupPioFuncs(X86EMU_pioFuncs *funcs);
+void 	X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]);
+void 	X86EMU_prepareForInt(int num);
+
+//void X86EMU_setMemBase(void *base, size_t size);
+
+/* decode.c */
+
+void 	X86EMU_exec(void);
+void 	X86EMU_halt_sys(void);
+
+#ifdef	CONFIG_DEBUG
+#define	HALT_SYS()	\
+    	printk("halt_sys: file %s, line %d\n", __FILE__, __LINE__);	\
+	X86EMU_halt_sys();
+#else
+#define	HALT_SYS()	X86EMU_halt_sys()
+#endif
+
+/* Debug options */
+
+#define DEBUG_DECODE_F          0x000001 /* print decoded instruction  */
+#define DEBUG_TRACE_F           0x000002 /* dump regs before/after execution */
+#define DEBUG_STEP_F            0x000004
+#define DEBUG_DISASSEMBLE_F     0x000008
+#define DEBUG_BREAK_F           0x000010
+#define DEBUG_SVC_F             0x000020
+#define DEBUG_FS_F              0x000080
+#define DEBUG_PROC_F            0x000100
+#define DEBUG_SYSINT_F          0x000200 /* bios system interrupts. */
+#define DEBUG_TRACECALL_F       0x000400
+#define DEBUG_INSTRUMENT_F      0x000800
+#define DEBUG_MEM_TRACE_F       0x001000 
+#define DEBUG_IO_TRACE_F        0x002000 
+#define DEBUG_TRACECALL_REGS_F  0x004000
+#define DEBUG_DECODE_NOPRINT_F  0x008000 
+#define DEBUG_SAVE_IP_CS_F      0x010000
+#define DEBUG_TRACEJMP_F        0x020000
+#define DEBUG_TRACEJMP_REGS_F   0x040000
+#define DEBUG_SYS_F             (DEBUG_SVC_F|DEBUG_FS_F|DEBUG_PROC_F)
+
+void 	X86EMU_trace_regs(void);
+void 	X86EMU_trace_xregs(void);
+void 	X86EMU_dump_memory(u16 seg, u16 off, u32 amt);
+int 	X86EMU_trace_on(void);
+int 	X86EMU_trace_off(void);
+
+#ifdef  __cplusplus
+}                       			/* End of "C" linkage for C++   	*/
+#endif
+
+#endif /* __X86EMU_X86EMU_H */
diff --git a/util/x86emu/pcbios/Config.lb b/util/x86emu/pcbios/Config.lb
new file mode 100644
index 0000000..231b662
--- /dev/null
+++ b/util/x86emu/pcbios/Config.lb
@@ -0,0 +1 @@
+object pcibios.o
\ No newline at end of file
diff --git a/util/x86emu/pcbios/pcibios.c b/util/x86emu/pcbios/pcibios.c
new file mode 100644
index 0000000..506aad0
--- /dev/null
+++ b/util/x86emu/pcbios/pcibios.c
@@ -0,0 +1,185 @@
+/*
+ * This software and ancillary information (herein called SOFTWARE )
+ * called LinuxBIOS          is made available under the terms described
+ * here.  The SOFTWARE has been approved for release with associated
+ * LA-CC Number 00-34   .  Unless otherwise indicated, this SOFTWARE has
+ * been authored by an employee or employees of the University of
+ * California, operator of the Los Alamos National Laboratory under
+ * Contract No. W-7405-ENG-36 with the U.S. Department of Energy.  The
+ * U.S. Government has rights to use, reproduce, and distribute this
+ * SOFTWARE.  The public may copy, distribute, prepare derivative works
+ * and publicly display this SOFTWARE without charge, provided that this
+ * Notice and any statement of authorship are reproduced on all copies.
+ * Neither the Government nor the University makes any warranty, express
+ * or implied, or assumes any liability or responsibility for the use of
+ * this SOFTWARE.  If SOFTWARE is modified to produce derivative works,
+ * such modified SOFTWARE should be clearly marked, so as not to confuse
+ * it with the version available from LANL.
+ */
+ /*
+ * This file is part of the coreboot project.
+ *
+ *  (c) Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by 
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+#ifdef CONFIG_COREBOOT_V2
+#include <console/console.h>
+#else
+#include <console.h>
+#endif
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <x86emu/x86emu.h>
+
+#include "pcibios.h"
+
+int pcibios_handler(void)
+{
+	int ret = 0;
+	struct device *dev = 0;
+
+	switch (X86_AX) {
+	case PCI_BIOS_PRESENT:
+		X86_AH	= 0x00;		/* no config space/special cycle support */
+		X86_AL	= 0x01;		/* config mechanism 1 */
+		X86_EDX = 'P' | 'C' << 8 | 'I' << 16 | ' ' << 24;
+		X86_EBX = 0x0210;	/* Version 2.10 */
+		X86_ECX = 0xFF00;	/* FixME: Max bus number */
+		X86_EFLAGS &= ~FB_CF;	/* clear carry flag */
+		ret = 1;
+		break;
+	case FIND_PCI_DEVICE:
+		/* FixME: support SI != 0 */
+#ifdef CONFIG_COREBOOT_V2
+		dev = dev_find_device(X86_DX, X86_CX, dev);
+#else
+		dev = dev_find_pci_device(X86_DX, X86_CX, dev);
+#endif
+		if (dev != 0) {
+			X86_BH = dev->bus->secondary;
+			X86_BL = dev->path.pci.devfn;
+			X86_AH = SUCCESSFUL;
+			X86_EFLAGS &= ~FB_CF;	/* clear carry flag */
+			ret = 1;
+		} else {
+			X86_AH = DEVICE_NOT_FOUND;
+			X86_EFLAGS |= FB_CF;	/* set carry flag */
+			ret = 0;
+		}
+		break;
+	case FIND_PCI_CLASS_CODE:
+		/* FixME: support SI != 0 */
+		dev = dev_find_class(X86_ECX, dev);
+		if (dev != 0) {
+			X86_BH = dev->bus->secondary;
+			X86_BL = dev->path.pci.devfn;
+			X86_AH = SUCCESSFUL;
+			X86_EFLAGS &= ~FB_CF;	/* clear carry flag */
+			ret = 1;
+		} else {
+			X86_AH = DEVICE_NOT_FOUND;
+			X86_EFLAGS |= FB_CF;	/* set carry flag */
+			ret = 0;
+		}
+		break;
+	case READ_CONFIG_BYTE:
+		dev = dev_find_slot(X86_BH, X86_BL);
+		if (dev != 0) {
+			X86_CL = pci_read_config8(dev, X86_DI);
+			X86_AH = SUCCESSFUL;
+			X86_EFLAGS &= ~FB_CF;	/* clear carry flag */
+			ret = 1;
+		} else {
+			X86_AH = DEVICE_NOT_FOUND;
+			X86_EFLAGS |= FB_CF;	/* set carry flag */	
+			ret = 0;
+		}
+		break;
+	case READ_CONFIG_WORD:
+		dev = dev_find_slot(X86_BH, X86_BL);
+		if (dev != 0) {
+			X86_CX = pci_read_config16(dev, X86_DI);
+			X86_AH = SUCCESSFUL;
+			X86_EFLAGS &= ~FB_CF;	/* clear carry flag */
+			ret = 1;
+		} else {
+			X86_AH = DEVICE_NOT_FOUND;
+			X86_EFLAGS |= FB_CF;	/* set carry flag */	
+			ret = 0;
+		}
+		break;
+	case READ_CONFIG_DWORD:
+		dev = dev_find_slot(X86_BH, X86_BL);
+		if (dev != 0) {
+			X86_ECX = pci_read_config32(dev, X86_DI);
+			X86_AH = SUCCESSFUL;
+			X86_EFLAGS &= ~FB_CF;	/* clear carry flag */
+			ret = 1;
+		} else {
+			X86_AH = DEVICE_NOT_FOUND;
+			X86_EFLAGS |= FB_CF;	/* set carry flag */	
+			ret = 0;
+		}
+		break;
+	case WRITE_CONFIG_BYTE:
+		dev = dev_find_slot(X86_BH, X86_BL);
+		if (dev != 0) {
+			pci_write_config8(dev, X86_DI, X86_CL);
+			X86_AH = SUCCESSFUL;
+			X86_EFLAGS &= ~FB_CF;	/* clear carry flag */
+			ret = 1;
+		} else {
+			X86_AH = DEVICE_NOT_FOUND;
+			X86_EFLAGS |= FB_CF;	/* set carry flag */	
+			ret = 0;
+		}
+		break;
+	case WRITE_CONFIG_WORD:
+		dev = dev_find_slot(X86_BH, X86_BL);
+		if (dev != 0) {
+			pci_write_config16(dev, X86_DI, X86_CX);
+			X86_AH = SUCCESSFUL;
+			X86_EFLAGS &= ~FB_CF;	/* clear carry flag */
+			ret = 1;
+		} else {
+			X86_AH = DEVICE_NOT_FOUND;
+			X86_EFLAGS |= FB_CF;	/* set carry flag */	
+			ret = 0;
+		}
+		break;
+	case WRITE_CONFIG_DWORD:
+		dev = dev_find_slot(X86_BH, X86_BL);
+		if (dev != 0) {
+			pci_write_config16(dev, X86_DI, X86_ECX);
+			X86_AH = SUCCESSFUL;
+			X86_EFLAGS &= ~FB_CF;	/* clear carry flag */
+			ret = 1;
+		} else {
+			X86_AH = DEVICE_NOT_FOUND;
+			X86_EFLAGS |= FB_CF;	/* set carry flag */	
+			ret = 0;
+		}
+		break;
+	default:
+		X86_AH = FUNC_NOT_SUPPORTED;
+		X86_EFLAGS |= FB_CF; 
+		break;
+	}
+
+	return ret;
+}
diff --git a/util/x86emu/pcbios/pcibios.h b/util/x86emu/pcbios/pcibios.h
new file mode 100644
index 0000000..0ee1911
--- /dev/null
+++ b/util/x86emu/pcbios/pcibios.h
@@ -0,0 +1,70 @@
+/*
+ * This software and ancillary information (herein called SOFTWARE )
+ * called LinuxBIOS          is made available under the terms described
+ * here.  The SOFTWARE has been approved for release with associated
+ * LA-CC Number 00-34   .  Unless otherwise indicated, this SOFTWARE has
+ * been authored by an employee or employees of the University of
+ * California, operator of the Los Alamos National Laboratory under
+ * Contract No. W-7405-ENG-36 with the U.S. Department of Energy.  The
+ * U.S. Government has rights to use, reproduce, and distribute this
+ * SOFTWARE.  The public may copy, distribute, prepare derivative works
+ * and publicly display this SOFTWARE without charge, provided that this
+ * Notice and any statement of authorship are reproduced on all copies.
+ * Neither the Government nor the University makes any warranty, express
+ * or implied, or assumes any liability or responsibility for the use of
+ * this SOFTWARE.  If SOFTWARE is modified to produce derivative works,
+ * such modified SOFTWARE should be clearly marked, so as not to confuse
+ * it with the version available from LANL.
+ */
+ /*
+ * This file is part of the coreboot project.
+ *
+ *  (c) Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by 
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#ifndef PCI_BIOS_H
+#define PCI_BIOS_H
+
+enum {
+	PCI_BIOS_PRESENT	= 0xB101,
+	FIND_PCI_DEVICE		= 0xB102,
+	FIND_PCI_CLASS_CODE	= 0xB103,
+	GENERATE_SPECIAL_CYCLE	= 0xB106,
+	READ_CONFIG_BYTE	= 0xB108,
+	READ_CONFIG_WORD	= 0xB109,
+	READ_CONFIG_DWORD	= 0xB10A,
+	WRITE_CONFIG_BYTE	= 0xB10B,
+	WRITE_CONFIG_WORD	= 0xB10C,
+	WRITE_CONFIG_DWORD	= 0xB10D,
+	GET_IRQ_ROUTING_OPTIONS	= 0xB10E,
+	SET_PCI_IRQ		= 0xB10F
+};
+
+enum {
+	SUCCESSFUL		= 0x00,
+	FUNC_NOT_SUPPORTED	= 0x81,
+	BAD_VENDOR_ID		= 0x83,
+	DEVICE_NOT_FOUND	= 0x86,
+	BAD_REGISTER_NUMBER	= 0x87,
+	SET_FAILED		= 0x88,
+	BUFFER_TOO_SMALL	= 0x89
+};
+
+int pcibios_handler(void);
+
+#endif /* PCI_BIOS_H */
+
diff --git a/util/x86emu/x86.c b/util/x86emu/x86.c
new file mode 100644
index 0000000..8509df3
--- /dev/null
+++ b/util/x86emu/x86.c
@@ -0,0 +1,230 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <device/pci.h>
+#include <string.h>
+
+#ifdef CONFIG_COREBOOT_V2
+#include <arch/io.h>
+#include <console/console.h>
+#define printk(x...) do_printk(x)
+#else
+#include <console.h>
+#endif
+
+#define REALMODE_BASE ((void *)0x500)
+
+struct realmode_idt {
+	u16 offset, cs;
+};
+
+struct eregs {
+	uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi;
+	uint32_t vector;
+	uint32_t error_code;
+	uint32_t eip;
+	uint32_t cs;
+	uint32_t eflags;
+};
+
+void x86_exception(struct eregs *info);
+
+extern unsigned char __idt_handler, __idt_handler_size;
+extern unsigned char __realmode_code, __realmode_code_size;
+extern unsigned char __run_optionrom, __run_interrupt;
+
+void (*run_optionrom)(u32 devfn) = (void *)&__run_optionrom;
+void (*vga_enable_console)(void) = (void *)&__run_interrupt;
+
+int (*intXX_handler[256])(struct eregs *regs) = { NULL };
+
+static int intXX_exception_handler(struct eregs *regs)
+{
+	printk(BIOS_INFO, "Oops, exception %d while executing option rom\n", 
+			regs->vector);
+	x86_exception(regs);	// Call coreboot exception handler 
+
+	return 0;		// Never returns?
+}
+
+static int intXX_unknown_handler(struct eregs *regs)
+{
+	printk(BIOS_INFO, "Unsupported software interrupt #0x%x\n", 
+			regs->vector);
+
+	return -1;
+}
+
+int int12_handler(struct eregs *regs);
+int int15_handler(struct eregs *regs);
+int int1a_handler(struct eregs *regs);
+
+static void setup_interrupt_handlers(void)
+{
+	int i;
+
+	/* The first 16 intXX functions are not BIOS services, 
+	 * but the CPU-generated exceptions ("hardware interrupts")
+	 */
+	for (i = 0; i < 0x10; i++)
+		intXX_handler[i] = &intXX_exception_handler;
+	
+	/* Mark all other intXX calls as unknown first */
+	for (i = 0x10; i < 0x100; i++)
+		intXX_handler[i] = &intXX_unknown_handler;
+
+	/* Now set the default functions that are actually
+	 * needed to initialize the option roms. This is very
+	 * slick, as it allows us to implement mainboard specific
+	 * interrupt handlers, such as the int15
+	 */
+	intXX_handler[0x12] = &int12_handler;
+	intXX_handler[0x15] = &int15_handler;
+	intXX_handler[0x1a] = &int1a_handler;
+}
+
+static void write_idt_stub(void *target, u8 intnum)
+{
+	unsigned char *codeptr;
+	codeptr = (unsigned char *) target;
+	memcpy(codeptr, &__idt_handler, (size_t)&__idt_handler_size);
+	codeptr[3] = intnum; /* modify int# in the code stub. */
+}
+
+static void setup_realmode_idt(void)
+{
+	struct realmode_idt *idts = (struct realmode_idt *) 0;
+	int i;
+
+	/* Copy IDT stub code for each interrupt. This might seem wasteful
+	 * but it is really simple
+	 */
+	 for (i = 0; i < 256; i++) {
+		idts[i].cs = 0;
+		idts[i].offset = 0x1000 + (i * (u32)&__idt_handler_size);
+		write_idt_stub((void *)((u32 )idts[i].offset), i);
+	}
+
+	/* Many option ROMs use the hard coded interrupt entry points in the
+	 * system bios. So install them at the known locations. 
+	 * Only need int10 so far.
+	 */
+	
+	/* int42 is the relocated int10 */
+	write_idt_stub((void *)0xff065, 0x42); 
+}
+
+void run_bios(struct device *dev, unsigned long addr)
+{
+	int i;
+
+	/* clear vga bios data area */
+	for (i = 0x400; i < 0x500; i++) {
+		*(unsigned char *) i = 0;
+	}
+	
+	/* Set up C interrupt handlers */
+	setup_interrupt_handlers();
+
+	/* Setting up realmode IDT */
+	setup_realmode_idt();
+
+	memcpy(REALMODE_BASE, &__realmode_code, (size_t)&__realmode_code_size);
+	printk(BIOS_SPEW, "Real mode stub @%p: %d bytes\n", REALMODE_BASE,
+			(u32)&__realmode_code_size);
+
+	printk(BIOS_DEBUG, "Calling Option ROM...\n");
+	run_optionrom((dev->bus->secondary << 8) | dev->path.pci.devfn);
+	printk(BIOS_DEBUG, "... Option ROM returned.\n");
+}
+
+int __attribute__((regparm(0))) interrupt_handler(u32 intnumber,
+	    u32 gsfs, u32 dses,
+	    u32 edi, u32 esi,
+	    u32 ebp, u32 esp,
+	    u32 ebx, u32 edx,
+	    u32 ecx, u32 eax,
+	    u32 cs_ip, u16 stackflags)
+{
+	u32 ip;
+	u32 cs;
+	u32 flags;
+	int ret = -1;
+	struct eregs reg_info;
+
+	ip = cs_ip & 0xffff;
+	cs = cs_ip >> 16;
+	flags = stackflags;
+
+	printk(BIOS_DEBUG, "oprom: INT# 0x%x\n", intnumber);
+	printk(BIOS_DEBUG, "oprom: eax: %08x ebx: %08x ecx: %08x edx: %08x\n",
+		      eax, ebx, ecx, edx);
+	printk(BIOS_DEBUG, "oprom: ebp: %08x esp: %08x edi: %08x esi: %08x\n",
+		     ebp, esp, edi, esi);
+	printk(BIOS_DEBUG, "oprom:  ip: %04x      cs: %04x   flags: %08x\n",
+		     ip, cs, flags);
+
+	// Fetch arguments from the stack and put them into
+	// a structure that we want to pass on to our sub interrupt
+	// handlers.
+	reg_info = (struct eregs) {
+		.eax=eax,
+		.ecx=ecx,
+		.edx=edx,
+		.ebx=ebx,
+		.esp=esp,
+		.ebp=ebp,
+		.esi=esi,
+		.edi=edi,
+		.vector=intnumber,
+		.error_code=0, // ??
+		.eip=ip,
+		.cs=cs,
+		.eflags=flags // ??
+	};
+
+	// Call the interrupt handler for this int#
+	ret = intXX_handler[intnumber](&reg_info);
+
+	// Put registers back on the stack. The assembler code
+	// will later pop them.
+	// What happens here is that we force (volatile!) changing
+	// the values of the parameters of this function. We do this
+	// because we know that they stay alive on the stack after 
+	// we leave this function. Don't say this is bollocks.
+	*(volatile u32 *)&eax = reg_info.eax;
+	*(volatile u32 *)&ecx = reg_info.ecx;
+	*(volatile u32 *)&edx = reg_info.edx;
+	*(volatile u32 *)&ebx = reg_info.ebx;
+	*(volatile u32 *)&esi = reg_info.esi;
+	*(volatile u32 *)&edi = reg_info.edi;
+	flags = reg_info.eflags;
+
+	/* Pass errors back to our caller via the CARRY flag */
+	if (ret) {
+		printk(BIOS_DEBUG,"error!\n");
+		flags |= 1;  // error: set carry
+	}else{
+		flags &= ~1; // no error: clear carry
+	}
+	*(volatile u16 *)&stackflags = flags;
+
+	return ret;
+}
+
diff --git a/util/x86emu/x86_asm.S b/util/x86emu/x86_asm.S
new file mode 100644
index 0000000..988b596
--- /dev/null
+++ b/util/x86emu/x86_asm.S
@@ -0,0 +1,345 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define REALMODE_BASE		0x500
+#define RELOCATED(x)	(x - __realmode_code + REALMODE_BASE)
+
+/* CR0 bits */
+#define PE		(1 << 0)
+
+/* This is the intXX interrupt handler stub code. It gets copied
+ * to the IDT and to some fixed addresses in the F segment. Before
+ * the code can used, it gets patched up by the C function copying 
+ * it: byte 3 (the $0 in movb $0, %al) is overwritten with the int#.
+ */
+
+	.code16
+	.globl __idt_handler
+__idt_handler:
+	pushal
+	movb 	$0, %al /* This instruction gets modified */
+	ljmp 	$0, $__interrupt_handler_16bit
+	.globl __idt_handler_size
+__idt_handler_size = ( . - __idt_handler)
+
+
+/* In order to be independent of coreboot's position in RAM
+ * we relocate a part of the code to the low megabyte, so the
+ * CPU can use it in real-mode. This code lives at __realmode_code.
+ */
+	.globl __realmode_code
+__realmode_code:
+
+/* Realmode IDT pointer structure. */
+	.globl __realmode_idt
+__realmode_idt = RELOCATED(.)
+	.word 1023	/* 16-bit limit */
+	.long 0		/* 24-bit base */
+	.word 0
+
+/* Preserve old stack */
+__stack = RELOCATED(.)
+	.long 0
+
+	.code32
+	.globl __run_optionrom
+__run_optionrom = RELOCATED(.)
+	/* save all registers to the stack */
+	pushal
+
+	/* Move the protected mode stack to a safe place */
+	mov 	%esp, __stack
+
+	/* Get devfn into %ecx */
+	movl    %esp, %ebp
+	// FIXME: Should this function be called with regparm=0?
+	movl    8(%ebp), %ecx
+
+	/* Activate the right segment descriptor real mode. */
+	ljmp	$0x28, $RELOCATED(1f)
+1:
+.code16
+	/* 16 bit code from here on... */
+
+	/* Load the segment registers w/ properly configured
+	 * segment descriptors. They will retain these
+	 * configurations (limits, writability, etc.) once
+	 * protected mode is turned off.
+	 */
+	mov	$0x30, %ax
+	mov	%ax, %ds       
+	mov	%ax, %es       
+	mov	%ax, %fs       
+	mov	%ax, %gs       
+	mov	%ax, %ss       
+
+	/* Turn off protection */
+	movl	%cr0, %eax
+	andl	$~PE, %eax
+	movl	%eax, %cr0
+
+	/* Now really going into real mode */
+	ljmp	$0, $RELOCATED(1f)
+1:
+	/* Setup a stack: Put the stack at the end of page zero.
+	 * That way we can easily share it between real and
+	 * protected, since the 16-bit ESP at segment 0 will
+	 * work for any case. */
+	mov	$0x0, %ax
+	mov	%ax, %ss
+	movl	$0x1000, %eax
+	movl	%eax, %esp
+
+	/* Load our 16 bit idt */
+	xor	%ax, %ax
+	mov	%ax, %ds
+	lidt	__realmode_idt
+
+	/* Set all segments to 0x0000, ds to 0x0040 */
+	mov	%ax, %es       
+	mov	%ax, %fs       
+	mov	%ax, %gs       
+	mov	$0x40, %ax
+	mov	%ax, %ds
+	mov	%cx, %ax	// restore ax
+
+	/* ************************************ */
+	// TODO this will not work for non-VGA option ROMs
+	/* run VGA BIOS at 0xc000:0003 */
+	lcall	$0xc000, $0x0003
+	/* ************************************ */
+
+	/* If we got here, just about done.
+	 * Need to get back to protected mode
+	 */
+	movl	%cr0, %eax
+	orl	$PE, %eax
+	movl	%eax, %cr0
+
+	/* Now that we are in protected mode
+	 * jump to a 32 bit code segment.
+	 */
+	data32	ljmp	$0x10, $RELOCATED(1f)
+1:
+	.code32
+	movw	$0x18, %ax     
+	mov	%ax, %ds       
+	mov	%ax, %es
+	mov	%ax, %fs
+	mov	%ax, %gs
+	mov	%ax, %ss
+
+	/* restore proper idt */
+	lidt	idtarg
+
+	/* and exit */
+	mov	__stack, %esp
+	popal
+	ret
+
+	.globl __run_interrupt
+__run_interrupt = RELOCATED(.)
+
+	/* paranoia -- does ecx get saved? not sure. This is
+	 * the easiest safe thing to do. */
+	pushal
+	/* save the stack */
+	mov	%esp, __stack
+
+
+	/*  This configures CS properly for real mode. */
+	ljmp 	$0x28, $RELOCATED(1f)
+1:
+	.code16 /* 16 bit code from here on... */
+
+	// CONFIG_DEBUG
+	movb    $0xec, %al
+	outb    %al, $0x80
+
+	/* Load the segment registers w/ properly configured segment
+	 * descriptors.  They will retain these configurations (limits,
+	 * writability, etc.) once protected mode is turned off.
+	 */
+	mov	$0x30, %ax     
+	mov	%ax, %ds       
+	mov	%ax, %es       
+	mov	%ax, %fs       
+	mov	%ax, %gs       
+	mov	%ax, %ss       
+
+	/* Turn off protected mode */
+	movl	%cr0, %eax     
+	andl	$~PE, %eax
+	movl	%eax, %cr0     
+
+	/* Now really going into real mode */
+	data32 ljmp	$0, $RELOCATED(1f)
+1:
+
+	/* put the stack at the end of page zero.
+	 * that way we can easily share it between real and protected,
+	 * since the 16-bit ESP at segment 0 will work for any case.
+	 */
+	/* setup a stack */
+	mov	$0x0, %ax
+	mov	%ax, %ss
+	movl	$0x1000, %eax
+	movl	%eax, %esp
+
+	/* Load 16-bit intXX IDT */
+	xor	%ax, %ax       
+	mov	%ax, %ds
+	lidt	__realmode_idt
+
+	/* Set all segments to 0x0000 */
+	mov	%ax, %ds
+	mov	%ax, %es
+	mov	%ax, %fs
+	mov	%ax, %gs
+
+	/* Call VGA BIOS int10 function 0x4f14 to enable main console
+	 * Epia-M does not always autosence the main console so forcing
+	 * it on is good.
+	 */
+
+	/* Ask VGA option rom to enable main console */
+	movw	$0x4f14,%ax
+	movw	$0x8003,%bx
+	movw	$1, %cx
+	movw	$0, %dx
+	movw	$0, %di
+	int	$0x10
+
+	/* Ok, the job is done, now go back to protected mode coreboot */
+	movl	%cr0, %eax
+	orl	$PE, %eax
+	movl	%eax, %cr0
+
+	/* Now that we are in protected mode jump to a 32-bit code segment. */
+	data32	ljmp	$0x10, $RELOCATED(1f)
+1:
+	.code32
+	movw	$0x18, %ax
+	mov	%ax, %ds
+	mov	%ax, %es
+	mov	%ax, %fs
+	mov	%ax, %gs
+	mov	%ax, %ss
+
+	/* restore coreboot's 32-bit IDT */
+	lidt	idtarg
+
+	/* Exit */
+	mov	__stack, %esp
+	popal
+	ret
+
+/* This is the 16-bit interrupt entry point called by the IDT stub code.
+ * Before this code code is called, %eax is pushed to the stack, and the
+ * interrupt number is loaded into %al
+ */
+	.code16
+__interrupt_handler_16bit = RELOCATED(.)
+	push	%ds
+	push	%es
+	push	%fs
+	push	%gs
+
+	/* Clean up the interrupt number. We could have done this in the stub,
+	 * but it would have cost 2 more bytes per stub entry.
+	 */
+	andl	$0xff, %eax
+	pushl	%eax		/* ... and make it the first parameter */
+
+	/* Switch to protected mode */
+	movl    %cr0, %eax
+	orl	$PE, %eax
+	movl	%eax, %cr0
+
+	/* ... and jump to a 32 bit code segment. */
+	data32 ljmp    $0x10, $RELOCATED(1f)
+1:
+	.code32
+	movw	$0x18, %ax
+	mov	%ax, %ds
+	mov	%ax, %es
+	mov	%ax, %fs
+	mov	%ax, %gs
+	mov	%ax, %ss
+
+	lidt	idtarg
+
+	/* Call the C interrupt handler */
+	movl	$interrupt_handler, %eax
+	call	*%eax
+
+	/* Now return to real mode ... */
+	ljmp	$0x28, $RELOCATED(1f)
+1:
+	.code16
+	/* Load the segment registers with properly configured segment
+	 * descriptors.  They will retain these configurations (limits,
+	 * writability, etc.) once protected mode is turned off.
+	 */
+	mov	$0x30, %ax
+	mov	%ax, %ds
+	mov	%ax, %es
+	mov	%ax, %fs
+	mov	%ax, %gs
+	mov	%ax, %ss
+
+	/* Disable Protected Mode */
+	movl	%cr0, %eax
+	andl	$~PE, %eax
+	movl	%eax, %cr0
+
+	/* Now really going into real mode */
+	ljmp $0,  $RELOCATED(1f)
+1:
+	/* Restore real-mode stack segment */
+	mov	$0x0, %ax
+	mov	%ax, %ss
+
+	/* Restore 16-bit IDT */
+	xor	%ax, %ax
+	mov	%ax, %ds
+	lidt	__realmode_idt
+
+	/* Set up our segment registers to segment 0x0000 */
+	mov	%ax, %es
+	mov	%ax, %fs
+	mov	%ax, %gs
+	mov	$0x40, %ax
+	mov	%ax, %ds
+
+	/* Restore all registers, including those
+	 * manipulated by the C handler
+	 */
+	popl	%eax
+	pop	%gs
+	pop	%fs
+	pop	%es
+	pop	%ds
+	popal
+	iret
+
+	.globl __realmode_code_size
+__realmode_code_size = (. - __realmode_code)
+
+	.code32
diff --git a/util/x86emu/x86_interrupts.c b/util/x86emu/x86_interrupts.c
new file mode 100644
index 0000000..c20c017
--- /dev/null
+++ b/util/x86emu/x86_interrupts.c
@@ -0,0 +1,244 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2001 Ronald G. Minnich
+ * Copyright (C) 2005 Nick.Barker9@btinternet.com
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <string.h>
+#ifdef CONFIG_COREBOOT_V2
+#include <console/console.h>
+#include <arch/io.h>
+#define printk(x...) do_printk(x)
+#else
+#include <console.h>
+#include <io.h>
+#endif
+
+struct eregs {
+	uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi;
+	uint32_t vector;
+	uint32_t error_code;
+	uint32_t eip;
+	uint32_t cs;
+	uint32_t eflags;
+};
+
+enum {
+	CHECK = 0xb001,
+	FINDDEV = 0xb102,
+	READCONFBYTE = 0xb108,
+	READCONFWORD = 0xb109,
+	READCONFDWORD = 0xb10a,
+	WRITECONFBYTE = 0xb10b,
+	WRITECONFWORD = 0xb10c,
+	WRITECONFDWORD = 0xb10d
+};
+
+// errors go in AH. Just set these up so that word assigns
+// will work. KISS.
+enum {
+	PCIBIOS_NODEV = 0x8600,
+	PCIBIOS_BADREG = 0x8700
+};
+
+int int12_handler(struct eregs *regs)
+{
+	regs->eax = 64 * 1024;
+	return 0;
+}
+
+int int1a_handler(struct eregs *regs)
+{
+	unsigned short func = (unsigned short) regs->eax;
+	int retval = 0;
+	unsigned short devid, vendorid, devfn;
+	/* Use short to get rid of gabage in upper half of 32-bit register */
+	short devindex;
+	unsigned char bus;
+	struct device *dev;
+
+	switch(func) {
+	case  CHECK:
+		regs->edx = 0x4350;
+		regs->ecx = 0x2049;
+		retval = 0;
+		break;
+	case FINDDEV:
+	{
+		devid = regs->ecx;
+		vendorid = regs->edx;
+		devindex = regs->esi;
+		dev = 0;
+#ifdef CONFIG_COREBOOT_V2
+		while ((dev = dev_find_device(vendorid, devid, dev))) {
+#else
+		while ((dev = dev_find_pci_device(vendorid, devid, dev))) {
+#endif
+			if (devindex <= 0)
+				break;
+			devindex--;
+		}
+		if (dev) {
+			unsigned short busdevfn;
+			regs->eax = 0;
+			// busnum is an unsigned char;
+			// devfn is an int, so we mask it off.
+			busdevfn = (dev->bus->secondary << 8)
+				| (dev->path.pci.devfn & 0xff);
+			printk(BIOS_DEBUG, "0x%x: return 0x%x\n", func, busdevfn);
+			regs->ebx = busdevfn;
+			retval = 0;
+		} else {
+			regs->eax = PCIBIOS_NODEV;
+			retval = -1;
+		}
+	}
+	break;
+	case READCONFDWORD:
+	case READCONFWORD:
+	case READCONFBYTE:
+	case WRITECONFDWORD:
+	case WRITECONFWORD:
+	case WRITECONFBYTE:
+	{
+		unsigned long dword;
+		unsigned short word;
+		unsigned char byte;
+		unsigned char reg;
+
+		devfn = regs->ebx & 0xff;
+		bus = regs->ebx >> 8;
+		reg = regs->edi;
+		dev = dev_find_slot(bus, devfn);
+		if (! dev) {
+			printk(BIOS_DEBUG, "0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn);
+			// idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
+			regs->eax = PCIBIOS_BADREG;
+			retval = -1;
+		}
+		switch(func) {
+		case READCONFBYTE:
+			byte = pci_read_config8(dev, reg);
+			regs->ecx = byte;
+			break;
+		case READCONFWORD:
+			word = pci_read_config16(dev, reg);
+			regs->ecx = word;
+			break;
+		case READCONFDWORD:
+			dword = pci_read_config32(dev, reg);
+			regs->ecx = dword;
+			break;
+		case WRITECONFBYTE:
+			byte = regs->ecx;
+			pci_write_config8(dev, reg, byte);
+			break;
+		case WRITECONFWORD:
+			word = regs->ecx;
+			pci_write_config16(dev, reg, word);
+			break;
+		case WRITECONFDWORD:
+			dword = regs->ecx;
+			pci_write_config32(dev, reg, dword);
+			break;
+		}
+
+		if (retval)
+			retval = PCIBIOS_BADREG;
+		printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n",
+			     func, bus, devfn, reg, regs->ecx);
+		regs->eax = 0;
+		retval = 0;
+	}
+	break;
+	default:
+		printk(BIOS_ERR, "UNSUPPORTED PCIBIOS FUNCTION 0x%x\n",  func);
+		break;
+	}
+
+	return retval;
+}
+
+int int15_handler(struct eregs *regs)
+{
+	int res = -1;
+
+	/* This int15 handler is VIA Tech. specific. Other chipsets need other
+	 * handlers. The right way to do this is to move this handler code into
+	 * the mainboard or northbridge code.
+	 */
+	switch (regs->eax & 0xffff) {
+	case 0x5f19:
+		break;
+	case 0x5f18:
+		regs->eax = 0x5f;
+		// MCLK = 133, 32M frame buffer, 256 M main memory
+		regs->ebx = 0x545;
+		regs->ecx = 0x060;
+		res = 0;
+		break;
+	case 0x5f00:
+		regs->eax = 0x8600;
+		break;
+	case 0x5f01:
+		regs->eax = 0x5f;
+		regs->ecx = (regs->ecx & 0xffffff00 ) | 2; // panel type =  2 = 1024 * 768
+		res = 0;
+		break;
+	case 0x5f02:
+		regs->eax = 0x5f;
+		regs->ebx = (regs->ebx & 0xffff0000) | 2;
+		regs->ecx = (regs->ecx & 0xffff0000) | 0x401;  // PAL + crt only
+		regs->edx = (regs->edx & 0xffff0000) | 0;  // TV Layout - default
+		res = 0;
+		break;
+	case 0x5f0f:
+		regs->eax = 0x860f;
+		break;
+	/* And now Intel IGD code */
+#define BOOT_DISPLAY_CRT        (1 << 0)
+#define BOOT_DISPLAY_TV         (1 << 1)
+#define BOOT_DISPLAY_EFP        (1 << 2)
+#define BOOT_DISPLAY_LCD        (1 << 3)
+#define BOOT_DISPLAY_CRT2       (1 << 4)
+#define BOOT_DISPLAY_TV2        (1 << 5)
+#define BOOT_DISPLAY_EFP2       (1 << 6)
+#define BOOT_DISPLAY_LCD2       (1 << 7)
+
+	case 0x5f35:
+		regs->eax = 0x5f;
+		regs->ecx = BOOT_DISPLAY_LCD|BOOT_DISPLAY_CRT;
+		res = 0;
+		break;
+	case 0x5f40:
+		regs->eax = 0x5f;
+		regs->ecx = 3; // This is mainboard specific
+		printk(BIOS_DEBUG, "DISPLAY=%x\n", regs->ecx);
+		res = 0;
+		break;
+	default:
+		printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", 
+				regs->eax & 0xffff);
+	}
+
+	return res;
+}
+
diff --git a/util/x86emu/x86emu/Config.lb b/util/x86emu/x86emu/Config.lb
new file mode 100644
index 0000000..20e8072
--- /dev/null
+++ b/util/x86emu/x86emu/Config.lb
@@ -0,0 +1,7 @@
+object debug.o
+object decode.o
+object fpu.o
+object ops.o
+object ops2.o
+object prim_ops.o
+object sys.o
diff --git a/util/x86emu/x86emu/LICENSE b/util/x86emu/x86emu/LICENSE
new file mode 100644
index 0000000..a3ede4a
--- /dev/null
+++ b/util/x86emu/x86emu/LICENSE
@@ -0,0 +1,17 @@
+                         License information
+                         -------------------
+
+The x86emu library is under a BSD style license, comaptible
+with the XFree86 and X licenses used by XFree86. The
+original x86emu libraries were under the GNU General Public
+License. Due to license incompatibilities between the GPL
+and the XFree86 license, the original authors of the code
+decided to allow a license change. If you have submitted
+code to the original x86emu project, and you don't agree
+with the license change, please contact us and let you
+know. Your code will be removed to comply with your wishes.
+
+If you have any questions about this, please send email to
+x86emu@linuxlabs.com or KendallB@scitechsoft.com for
+clarification.
+
diff --git a/util/x86emu/x86emu/debug.c b/util/x86emu/x86emu/debug.c
new file mode 100644
index 0000000..c884462
--- /dev/null
+++ b/util/x86emu/x86emu/debug.c
@@ -0,0 +1,435 @@
+/****************************************************************************
+*
+*                       Realmode X86 Emulator Library
+*
+*               Copyright (C) 1991-2004 SciTech Software, Inc.
+*                    Copyright (C) David Mosberger-Tang
+*                      Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:     ANSI C
+* Environment:  Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file contains the code to handle debugging of the
+*               emulator.
+*
+****************************************************************************/
+
+#include "x86emui.h"
+// #include <stdarg.h>
+
+/*----------------------------- Implementation ----------------------------*/
+
+#ifdef CONFIG_DEBUG
+
+static void     print_encoded_bytes (u16 s, u16 o);
+static void     print_decoded_instruction (void);
+int      parse_line (char *s, int *ps, int *n);
+
+/* should look something like debug's output. */
+void X86EMU_trace_regs (void)
+{
+    if (DEBUG_TRACE()) {
+	if (M.x86.mode & (SYSMODE_PREFIX_DATA | SYSMODE_PREFIX_ADDR)) {
+	        x86emu_dump_xregs();
+	} else {
+	        x86emu_dump_regs();
+	}
+    }
+    if (DEBUG_DECODE() && ! DEBUG_DECODE_NOPRINT()) {
+        printk("%04x:%04x ",M.x86.saved_cs, M.x86.saved_ip);
+        print_encoded_bytes( M.x86.saved_cs, M.x86.saved_ip);
+        print_decoded_instruction();
+    }
+}
+
+void X86EMU_trace_xregs (void)
+{
+    if (DEBUG_TRACE()) {
+        x86emu_dump_xregs();
+    }
+}
+
+void x86emu_just_disassemble (void)
+{
+    /*
+     * This routine called if the flag DEBUG_DISASSEMBLE is set kind
+     * of a hack!
+     */
+    printk("%04x:%04x ",M.x86.saved_cs, M.x86.saved_ip);
+    print_encoded_bytes( M.x86.saved_cs, M.x86.saved_ip);
+    print_decoded_instruction();
+}
+
+void disassemble_forward (u16 seg, u16 off, int n)
+{
+    X86EMU_sysEnv tregs;
+    int i;
+    u8 op1;
+    /*
+     * hack, hack, hack.  What we do is use the exact machinery set up
+     * for execution, except that now there is an additional state
+     * flag associated with the "execution", and we are using a copy
+     * of the register struct.  All the major opcodes, once fully
+     * decoded, have the following two steps: TRACE_REGS(r,m);
+     * SINGLE_STEP(r,m); which disappear if CONFIG_DEBUG is not defined to
+     * the preprocessor.  The TRACE_REGS macro expands to:
+     *
+     * if (debug&DEBUG_DISASSEMBLE)
+     *     {just_disassemble(); goto EndOfInstruction;}
+     *     if (debug&DEBUG_TRACE) trace_regs(r,m);
+     *
+     * ......  and at the last line of the routine.
+     *
+     * EndOfInstruction: end_instr();
+     *
+     * Up to the point where TRACE_REG is expanded, NO modifications
+     * are done to any register EXCEPT the IP register, for fetch and
+     * decoding purposes.
+     *
+     * This was done for an entirely different reason, but makes a
+     * nice way to get the system to help debug codes.
+     */
+    tregs = M;
+    tregs.x86.R_IP = off;
+    tregs.x86.R_CS = seg;
+
+    /* reset the decoding buffers */
+    tregs.x86.enc_str_pos = 0;
+    tregs.x86.enc_pos = 0;
+
+    /* turn on the "disassemble only, no execute" flag */
+    tregs.x86.debug |= DEBUG_DISASSEMBLE_F;
+
+    /* DUMP NEXT n instructions to screen in straight_line fashion */
+    /*
+     * This looks like the regular instruction fetch stream, except
+     * that when this occurs, each fetched opcode, upon seeing the
+     * DEBUG_DISASSEMBLE flag set, exits immediately after decoding
+     * the instruction.  XXX --- CHECK THAT MEM IS NOT AFFECTED!!!
+     * Note the use of a copy of the register structure...
+     */
+    for (i=0; i<n; i++) {
+        op1 = (*sys_rdb)(((u32)M.x86.R_CS<<4) + (M.x86.R_IP++));
+        (x86emu_optab[op1])(op1);
+    }
+    /* end major hack mode. */
+}
+
+void x86emu_check_ip_access (void)
+{
+    /* NULL as of now */
+}
+
+void x86emu_check_sp_access (void)
+{
+}
+
+void x86emu_check_mem_access (u32 dummy)
+{
+    /*  check bounds, etc */
+}
+
+void x86emu_check_data_access (uint dummy1, uint dummy2)
+{
+    /*  check bounds, etc */
+}
+
+void x86emu_inc_decoded_inst_len (int x)
+{
+    M.x86.enc_pos += x;
+}
+
+void x86emu_decode_printf (char *x)
+{
+    sprintf(M.x86.decoded_buf+M.x86.enc_str_pos,"%s",x);
+    M.x86.enc_str_pos += strlen(x);
+}
+
+void x86emu_decode_printf2 (char *x, int y)
+{
+    char temp[100];
+    sprintf(temp,x,y);
+    sprintf(M.x86.decoded_buf+M.x86.enc_str_pos,"%s",temp);
+    M.x86.enc_str_pos += strlen(temp);
+}
+
+void x86emu_end_instr (void)
+{
+    M.x86.enc_str_pos = 0;
+    M.x86.enc_pos = 0;
+}
+
+static void print_encoded_bytes (u16 s, u16 o)
+{
+    int i;
+    char buf1[64];
+    for (i=0; i< M.x86.enc_pos; i++) {
+        sprintf(buf1+2*i,"%02x", fetch_data_byte_abs(s,o+i));
+    }
+    printk("%-20s ",buf1);
+}
+
+static void print_decoded_instruction (void)
+{
+    printk("%s", M.x86.decoded_buf);
+}
+
+void x86emu_print_int_vect (u16 iv)
+{
+    u16 seg,off;
+
+    if (iv > 256) return;
+    seg   = fetch_data_word_abs(0,iv*4);
+    off   = fetch_data_word_abs(0,iv*4+2);
+    printk("%04x:%04x ", seg, off);
+}
+
+void X86EMU_dump_memory (u16 seg, u16 off, u32 amt)
+{
+    u32 start = off & 0xfffffff0;
+    u32 end  = (off+16) & 0xfffffff0;
+    u32 i;
+    u32 current;
+
+    current = start;
+    while (end <= off + amt) {
+        printk("%04x:%04x ", seg, start);
+        for (i=start; i< off; i++)
+          printk("   ");
+        for (       ; i< end; i++)
+          printk("%02x ", fetch_data_byte_abs(seg,i));
+        printk("\n");
+        start = end;
+        end = start + 16;
+    }
+}
+
+void x86emu_single_step (void)
+{
+#if 0
+    char s[1024];
+    int ps[10];
+    int ntok;
+    int cmd;
+    int done;
+        int segment;
+    int offset;
+    static int breakpoint;
+    static int noDecode = 1;
+
+    char *p;
+
+        if (DEBUG_BREAK()) {
+                if (M.x86.saved_ip != breakpoint) {
+                        return;
+                } else {
+              M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
+                        M.x86.debug |= DEBUG_TRACE_F;
+                        M.x86.debug &= ~DEBUG_BREAK_F;
+                        print_decoded_instruction ();
+                        X86EMU_trace_regs();
+                }
+        }
+    done=0;
+    offset = M.x86.saved_ip;
+    while (!done) {
+        printk("-");
+        p = fgets(s, 1023, stdin);
+        cmd = parse_line(s, ps, &ntok);
+        switch(cmd) {
+          case 'u':
+            disassemble_forward(M.x86.saved_cs,(u16)offset,10);
+            break;
+          case 'd':
+                            if (ntok == 2) {
+                                    segment = M.x86.saved_cs;
+                                    offset = ps[1];
+                                    X86EMU_dump_memory(segment,(u16)offset,16);
+                                    offset += 16;
+                            } else if (ntok == 3) {
+                                    segment = ps[1];
+                                    offset = ps[2];
+                                    X86EMU_dump_memory(segment,(u16)offset,16);
+                                    offset += 16;
+                            } else {
+                                    segment = M.x86.saved_cs;
+                                    X86EMU_dump_memory(segment,(u16)offset,16);
+                                    offset += 16;
+                            }
+            break;
+          case 'c':
+            M.x86.debug ^= DEBUG_TRACECALL_F;
+            break;
+          case 's':
+            M.x86.debug ^= DEBUG_SVC_F | DEBUG_SYS_F | DEBUG_SYSINT_F;
+            break;
+          case 'r':
+            X86EMU_trace_regs();
+            break;
+          case 'x':
+            X86EMU_trace_xregs();
+            break;
+          case 'g':
+            if (ntok == 2) {
+                breakpoint = ps[1];
+        if (noDecode) {
+                        M.x86.debug |= DEBUG_DECODE_NOPRINT_F;
+        } else {
+                        M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
+        }
+        M.x86.debug &= ~DEBUG_TRACE_F;
+        M.x86.debug |= DEBUG_BREAK_F;
+        done = 1;
+            }
+            break;
+          case 'q':
+          M.x86.debug |= DEBUG_EXIT;
+          return;
+      case 'P':
+          noDecode = (noDecode)?0:1;
+          printk("Toggled decoding to %s\n",(noDecode)?"FALSE":"TRUE");
+          break;
+          case 't':
+      case 0:
+            done = 1;
+            break;
+        }
+    }
+#endif
+}
+
+int X86EMU_trace_on(void)
+{
+    return M.x86.debug |= DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F;
+}
+
+int X86EMU_trace_off(void)
+{
+    return M.x86.debug &= ~(DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F);
+}
+
+int parse_line (char *s, int *ps, int *n)
+{
+#if 0
+    int cmd;
+
+    *n = 0;
+    while(*s == ' ' || *s == '\t') s++;
+    ps[*n] = *s;
+    switch (*s) {
+      case '\n':
+        *n += 1;
+        return 0;
+      default:
+        cmd = *s;
+        *n += 1;
+    }
+
+    while (1) {
+        while (*s != ' ' && *s != '\t' && *s != '\n')  s++;
+
+        if (*s == '\n')
+            return cmd;
+
+        while(*s == ' ' || *s == '\t') s++;
+
+        sscanf(s,"%x",&ps[*n]);
+        *n += 1;
+    }
+#else
+    return 0;
+#endif
+}
+
+#endif /* CONFIG_DEBUG */
+
+void x86emu_dump_regs (void)
+{
+    printk("\tAX=%04x  ", M.x86.R_AX );
+    printk("BX=%04x  ", M.x86.R_BX );
+    printk("CX=%04x  ", M.x86.R_CX );
+    printk("DX=%04x  ", M.x86.R_DX );
+    printk("SP=%04x  ", M.x86.R_SP );
+    printk("BP=%04x  ", M.x86.R_BP );
+    printk("SI=%04x  ", M.x86.R_SI );
+    printk("DI=%04x\n", M.x86.R_DI );
+    printk("\tDS=%04x  ", M.x86.R_DS );
+    printk("ES=%04x  ", M.x86.R_ES );
+    printk("SS=%04x  ", M.x86.R_SS );
+    printk("CS=%04x  ", M.x86.R_CS );
+    printk("IP=%04x   ", M.x86.R_IP );
+    if (ACCESS_FLAG(F_OF))    printk("OV ");     /* CHECKED... */
+    else                        printk("NV ");
+    if (ACCESS_FLAG(F_DF))    printk("DN ");
+    else                        printk("UP ");
+    if (ACCESS_FLAG(F_IF))    printk("EI ");
+    else                        printk("DI ");
+    if (ACCESS_FLAG(F_SF))    printk("NG ");
+    else                        printk("PL ");
+    if (ACCESS_FLAG(F_ZF))    printk("ZR ");
+    else                        printk("NZ ");
+    if (ACCESS_FLAG(F_AF))    printk("AC ");
+    else                        printk("NA ");
+    if (ACCESS_FLAG(F_PF))    printk("PE ");
+    else                        printk("PO ");
+    if (ACCESS_FLAG(F_CF))    printk("CY ");
+    else                        printk("NC ");
+    printk("\n");
+}
+
+void x86emu_dump_xregs (void)
+{
+    printk("\tEAX=%08x  ", M.x86.R_EAX );
+    printk("EBX=%08x  ", M.x86.R_EBX );
+    printk("ECX=%08x  ", M.x86.R_ECX );
+    printk("EDX=%08x  \n", M.x86.R_EDX );
+    printk("\tESP=%08x  ", M.x86.R_ESP );
+    printk("EBP=%08x  ", M.x86.R_EBP );
+    printk("ESI=%08x  ", M.x86.R_ESI );
+    printk("EDI=%08x\n", M.x86.R_EDI );
+    printk("\tDS=%04x  ", M.x86.R_DS );
+    printk("ES=%04x  ", M.x86.R_ES );
+    printk("SS=%04x  ", M.x86.R_SS );
+    printk("CS=%04x  ", M.x86.R_CS );
+    printk("EIP=%08x\n\t", M.x86.R_EIP );
+    if (ACCESS_FLAG(F_OF))    printk("OV ");     /* CHECKED... */
+    else                        printk("NV ");
+    if (ACCESS_FLAG(F_DF))    printk("DN ");
+    else                        printk("UP ");
+    if (ACCESS_FLAG(F_IF))    printk("EI ");
+    else                        printk("DI ");
+    if (ACCESS_FLAG(F_SF))    printk("NG ");
+    else                        printk("PL ");
+    if (ACCESS_FLAG(F_ZF))    printk("ZR ");
+    else                        printk("NZ ");
+    if (ACCESS_FLAG(F_AF))    printk("AC ");
+    else                        printk("NA ");
+    if (ACCESS_FLAG(F_PF))    printk("PE ");
+    else                        printk("PO ");
+    if (ACCESS_FLAG(F_CF))    printk("CY ");
+    else                        printk("NC ");
+    printk("\n");
+}
diff --git a/util/x86emu/x86emu/debug.h b/util/x86emu/x86emu/debug.h
new file mode 100644
index 0000000..4e95e34
--- /dev/null
+++ b/util/x86emu/x86emu/debug.h
@@ -0,0 +1,223 @@
+/****************************************************************************
+*
+*						Realmode X86 Emulator Library
+*
+*            	Copyright (C) 1996-1999 SciTech Software, Inc.
+* 				     Copyright (C) David Mosberger-Tang
+* 					   Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:		ANSI C
+* Environment:	Any
+* Developer:    Kendall Bennett
+*
+* Description:  Header file for debug definitions.
+*
+****************************************************************************/
+/* $XFree86: xc/extras/x86emu/src/x86emu/x86emu/debug.h,v 1.4 2000/11/21 23:10:27 tsi Exp $ */
+
+#ifndef __X86EMU_DEBUG_H
+#define __X86EMU_DEBUG_H
+
+//#define CONFIG_DEBUG 0
+//#undef CONFIG_DEBUG
+/*---------------------- Macros and type definitions ----------------------*/
+
+/* checks to be enabled for "runtime" */
+
+#define CHECK_IP_FETCH_F                0x1
+#define CHECK_SP_ACCESS_F               0x2
+#define CHECK_MEM_ACCESS_F              0x4 /*using regular linear pointer */
+#define CHECK_DATA_ACCESS_F             0x8 /*using segment:offset*/
+
+#ifdef CONFIG_DEBUG
+# define CHECK_IP_FETCH()              	(M.x86.check & CHECK_IP_FETCH_F)
+# define CHECK_SP_ACCESS()             	(M.x86.check & CHECK_SP_ACCESS_F)
+# define CHECK_MEM_ACCESS()            	(M.x86.check & CHECK_MEM_ACCESS_F)
+# define CHECK_DATA_ACCESS()           	(M.x86.check & CHECK_DATA_ACCESS_F)
+#else
+# define CHECK_IP_FETCH()
+# define CHECK_SP_ACCESS()
+# define CHECK_MEM_ACCESS()
+# define CHECK_DATA_ACCESS()
+#endif
+
+#ifdef CONFIG_DEBUG
+# define DEBUG_INSTRUMENT()    	(M.x86.debug & DEBUG_INSTRUMENT_F)
+# define DEBUG_DECODE()        	(M.x86.debug & DEBUG_DECODE_F)
+# define DEBUG_TRACE()         	(M.x86.debug & DEBUG_TRACE_F)
+# define DEBUG_STEP()          	(M.x86.debug & DEBUG_STEP_F)
+# define DEBUG_DISASSEMBLE()   	(M.x86.debug & DEBUG_DISASSEMBLE_F)
+# define DEBUG_BREAK()         	(M.x86.debug & DEBUG_BREAK_F)
+# define DEBUG_SVC()           	(M.x86.debug & DEBUG_SVC_F)
+# define DEBUG_SAVE_IP_CS()     (M.x86.debug & DEBUG_SAVE_IP_CS_F)
+
+# define DEBUG_FS()            	(M.x86.debug & DEBUG_FS_F)
+# define DEBUG_PROC()          	(M.x86.debug & DEBUG_PROC_F)
+# define DEBUG_SYSINT()        	(M.x86.debug & DEBUG_SYSINT_F)
+# define DEBUG_TRACECALL()     	(M.x86.debug & DEBUG_TRACECALL_F)
+# define DEBUG_TRACECALLREGS() 	(M.x86.debug & DEBUG_TRACECALL_REGS_F)
+# define DEBUG_TRACEJMP()       (M.x86.debug & DEBUG_TRACEJMP_F)
+# define DEBUG_TRACEJMPREGS()   (M.x86.debug & DEBUG_TRACEJMP_REGS_F)
+# define DEBUG_SYS()           	(M.x86.debug & DEBUG_SYS_F)
+# define DEBUG_MEM_TRACE()     	(M.x86.debug & DEBUG_MEM_TRACE_F)
+# define DEBUG_IO_TRACE()      	(M.x86.debug & DEBUG_IO_TRACE_F)
+# define DEBUG_DECODE_NOPRINT() (M.x86.debug & DEBUG_DECODE_NOPRINT_F)
+#else
+# define DEBUG_INSTRUMENT()    	0
+# define DEBUG_DECODE()        	0
+# define DEBUG_TRACE()         	0
+# define DEBUG_STEP()          	0
+# define DEBUG_DISASSEMBLE()   	0
+# define DEBUG_BREAK()         	0
+# define DEBUG_SVC()           	0
+# define DEBUG_SAVE_IP_CS()     0
+# define DEBUG_FS()            	0
+# define DEBUG_PROC()          	0
+# define DEBUG_SYSINT()        	0
+# define DEBUG_TRACECALL()     	0
+# define DEBUG_TRACECALLREGS() 	0
+# define DEBUG_TRACEJMP()       0
+# define DEBUG_TRACEJMPREGS()   0
+# define DEBUG_SYS()           	0
+# define DEBUG_MEM_TRACE()     	0
+# define DEBUG_IO_TRACE()      	0
+# define DEBUG_DECODE_NOPRINT() 0
+#endif
+
+#ifdef CONFIG_DEBUG
+
+# define DECODE_PRINTF(x)     	if (DEBUG_DECODE()) \
+									x86emu_decode_printf(x)
+# define DECODE_PRINTF2(x,y)  	if (DEBUG_DECODE()) \
+									x86emu_decode_printf2(x,y)
+
+/*
+ * The following allow us to look at the bytes of an instruction.  The
+ * first INCR_INSTRN_LEN, is called everytime bytes are consumed in
+ * the decoding process.  The SAVE_IP_CS is called initially when the
+ * major opcode of the instruction is accessed.
+ */
+#define INC_DECODED_INST_LEN(x)                    	\
+	if (DEBUG_DECODE())  	                       	\
+		x86emu_inc_decoded_inst_len(x)
+
+#define SAVE_IP_CS(x,y)                               			\
+	if (DEBUG_DECODE() | DEBUG_TRACECALL() | DEBUG_BREAK() \
+              | DEBUG_IO_TRACE() | DEBUG_SAVE_IP_CS()) { \
+		M.x86.saved_cs = x;                          			\
+		M.x86.saved_ip = y;                          			\
+	}
+#else
+# define INC_DECODED_INST_LEN(x)
+# define DECODE_PRINTF(x)
+# define DECODE_PRINTF2(x,y)
+# define SAVE_IP_CS(x,y)
+#endif
+
+#ifdef CONFIG_DEBUG
+#define TRACE_REGS()                                   		\
+	if (DEBUG_DISASSEMBLE()) {                         		\
+		x86emu_just_disassemble();                        	\
+		goto EndOfTheInstructionProcedure;             		\
+	}                                                   	\
+	if (DEBUG_TRACE() || DEBUG_DECODE()) X86EMU_trace_regs()
+#else
+# define TRACE_REGS()
+#endif
+
+#ifdef CONFIG_DEBUG
+# define SINGLE_STEP()		if (DEBUG_STEP()) x86emu_single_step()
+#else
+# define SINGLE_STEP()
+#endif
+
+#define TRACE_AND_STEP()	\
+	TRACE_REGS();			\
+	SINGLE_STEP()
+
+#ifdef CONFIG_DEBUG
+# define START_OF_INSTR()
+# define END_OF_INSTR()		EndOfTheInstructionProcedure: x86emu_end_instr();
+# define END_OF_INSTR_NO_TRACE()	x86emu_end_instr();
+#else
+# define START_OF_INSTR()
+# define END_OF_INSTR()
+# define END_OF_INSTR_NO_TRACE()
+#endif
+
+#ifdef CONFIG_DEBUG
+# define  CALL_TRACE(u,v,w,x,s)                                 \
+	if (DEBUG_TRACECALLREGS())									\
+		x86emu_dump_regs();                                     \
+	if (DEBUG_TRACECALL())                                     	\
+		printk("%04x:%04x: CALL %s%04x:%04x\n", u , v, s, w, x);
+# define RETURN_TRACE(u,v,w,x,s)                                    \
+	if (DEBUG_TRACECALLREGS())									\
+		x86emu_dump_regs();                                     \
+	if (DEBUG_TRACECALL())                                     	\
+		printk("%04x:%04x: RET %s %04x:%04x\n",u,v,s,w,x);
+# define  JMP_TRACE(u,v,w,x,s)                                 \
+   if (DEBUG_TRACEJMPREGS()) \
+      x86emu_dump_regs(); \
+   if (DEBUG_TRACEJMP()) \
+      printk("%04x:%04x: JMP %s%04x:%04x\n", u , v, s, w, x);
+#else
+# define CALL_TRACE(u,v,w,x,s)
+# define RETURN_TRACE(u,v,w,x,s)
+# define  JMP_TRACE(u,v,w,x,s)
+#endif
+
+#ifdef CONFIG_DEBUG
+#define	DB(x)	x
+#else
+#define	DB(x)
+#endif
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+#ifdef  __cplusplus
+extern "C" {            			/* Use "C" linkage when in C++ mode */
+#endif
+
+extern void x86emu_inc_decoded_inst_len (int x);
+extern void x86emu_decode_printf (char *x);
+extern void x86emu_decode_printf2 (char *x, int y);
+extern void x86emu_just_disassemble (void);
+extern void x86emu_single_step (void);
+extern void x86emu_end_instr (void);
+extern void x86emu_dump_regs (void);
+extern void x86emu_dump_xregs (void);
+extern void x86emu_print_int_vect (u16 iv);
+extern void x86emu_instrument_instruction (void);
+extern void x86emu_check_ip_access (void);
+extern void x86emu_check_sp_access (void);
+extern void x86emu_check_mem_access (u32 p);
+extern void x86emu_check_data_access (uint s, uint o);
+
+#ifdef  __cplusplus
+}                       			/* End of "C" linkage for C++   	*/
+#endif
+
+#endif /* __X86EMU_DEBUG_H */
diff --git a/util/x86emu/x86emu/decode.c b/util/x86emu/x86emu/decode.c
new file mode 100644
index 0000000..8e42e5d
--- /dev/null
+++ b/util/x86emu/x86emu/decode.c
@@ -0,0 +1,1149 @@
+/****************************************************************************
+*
+*                       Realmode X86 Emulator Library
+*
+*               Copyright (C) 1991-2004 SciTech Software, Inc.
+*                    Copyright (C) David Mosberger-Tang
+*                      Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:     ANSI C
+* Environment:  Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file includes subroutines which are related to
+*               instruction decoding and accessess of immediate data via IP.  etc.
+*
+****************************************************************************/
+
+#include "x86emui.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+REMARKS:
+Handles any pending asychronous interrupts.
+****************************************************************************/
+static void x86emu_intr_handle(void)
+{
+    u8  intno;
+
+    if (M.x86.intr & INTR_SYNCH) {
+        intno = M.x86.intno;
+        if (_X86EMU_intrTab[intno]) {
+            (*_X86EMU_intrTab[intno])(intno);
+        } else {
+            push_word((u16)M.x86.R_FLG);
+            CLEAR_FLAG(F_IF);
+            CLEAR_FLAG(F_TF);
+            push_word(M.x86.R_CS);
+            M.x86.R_CS = mem_access_word(intno * 4 + 2);
+            push_word(M.x86.R_IP);
+            M.x86.R_IP = mem_access_word(intno * 4);
+            M.x86.intr = 0;
+        }
+    }
+}
+
+/****************************************************************************
+PARAMETERS:
+intrnum - Interrupt number to raise
+
+REMARKS:
+Raise the specified interrupt to be handled before the execution of the
+next instruction.
+****************************************************************************/
+void x86emu_intr_raise(
+    u8 intrnum)
+{
+    printk("%s, rasing execption %x\n", __func__, intrnum);
+    x86emu_dump_regs();
+    M.x86.intno = intrnum;
+    M.x86.intr |= INTR_SYNCH;
+}
+
+/****************************************************************************
+REMARKS:
+Main execution loop for the emulator. We return from here when the system
+halts, which is normally caused by a stack fault when we return from the
+original real mode call.
+****************************************************************************/
+void X86EMU_exec(void)
+{
+    u8 op1;
+
+    M.x86.intr = 0;
+    DB(x86emu_end_instr();)
+
+    for (;;) {
+DB(     if (CHECK_IP_FETCH())
+            x86emu_check_ip_access();)
+        /* If debugging, save the IP and CS values. */
+        SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
+        INC_DECODED_INST_LEN(1);
+        if (M.x86.intr) {
+            if (M.x86.intr & INTR_HALTED) {
+DB(             if (M.x86.R_SP != 0) {
+                    printk("halted\n");
+                    X86EMU_trace_regs();
+                    }
+                else {
+                    if (M.x86.debug)
+                        printk("Service completed successfully\n");
+                    })
+                return;
+            }
+            if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) ||
+                !ACCESS_FLAG(F_IF)) {
+                x86emu_intr_handle();
+            }
+        }
+        op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+        (*x86emu_optab[op1])(op1);
+        //if (M.x86.debug & DEBUG_EXIT) {
+        //    M.x86.debug &= ~DEBUG_EXIT;
+        //    return;
+        //}
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Halts the system by setting the halted system flag.
+****************************************************************************/
+void X86EMU_halt_sys(void)
+{
+    M.x86.intr |= INTR_HALTED;
+}
+
+/****************************************************************************
+PARAMETERS:
+mod     - Mod value from decoded byte
+regh    - Reg h value from decoded byte
+regl    - Reg l value from decoded byte
+
+REMARKS:
+Raise the specified interrupt to be handled before the execution of the
+next instruction.
+
+NOTE: Do not inline this function, as (*sys_rdb) is already inline!
+****************************************************************************/
+void fetch_decode_modrm(
+    int *mod,
+    int *regh,
+    int *regl)
+{
+    int fetched;
+
+DB( if (CHECK_IP_FETCH())
+        x86emu_check_ip_access();)
+    fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+    INC_DECODED_INST_LEN(1);
+    *mod  = (fetched >> 6) & 0x03;
+    *regh = (fetched >> 3) & 0x07;
+    *regl = (fetched >> 0) & 0x07;
+}
+
+/****************************************************************************
+RETURNS:
+Immediate byte value read from instruction queue
+
+REMARKS:
+This function returns the immediate byte from the instruction queue, and
+moves the instruction pointer to the next value.
+
+NOTE: Do not inline this function, as (*sys_rdb) is already inline!
+****************************************************************************/
+u8 fetch_byte_imm(void)
+{
+    u8 fetched;
+
+DB( if (CHECK_IP_FETCH())
+        x86emu_check_ip_access();)
+    fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+    INC_DECODED_INST_LEN(1);
+    return fetched;
+}
+
+/****************************************************************************
+RETURNS:
+Immediate word value read from instruction queue
+
+REMARKS:
+This function returns the immediate byte from the instruction queue, and
+moves the instruction pointer to the next value.
+
+NOTE: Do not inline this function, as (*sys_rdw) is already inline!
+****************************************************************************/
+u16 fetch_word_imm(void)
+{
+    u16 fetched;
+
+DB( if (CHECK_IP_FETCH())
+        x86emu_check_ip_access();)
+    fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
+    M.x86.R_IP += 2;
+    INC_DECODED_INST_LEN(2);
+    return fetched;
+}
+
+/****************************************************************************
+RETURNS:
+Immediate lone value read from instruction queue
+
+REMARKS:
+This function returns the immediate byte from the instruction queue, and
+moves the instruction pointer to the next value.
+
+NOTE: Do not inline this function, as (*sys_rdw) is already inline!
+****************************************************************************/
+u32 fetch_long_imm(void)
+{
+    u32 fetched;
+
+DB( if (CHECK_IP_FETCH())
+        x86emu_check_ip_access();)
+    fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
+    M.x86.R_IP += 4;
+    INC_DECODED_INST_LEN(4);
+    return fetched;
+}
+
+/****************************************************************************
+RETURNS:
+Value of the default data segment
+
+REMARKS:
+Inline function that returns the default data segment for the current
+instruction.
+
+On the x86 processor, the default segment is not always DS if there is
+no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
+addresses relative to SS (ie: on the stack). So, at the minimum, all
+decodings of addressing modes would have to set/clear a bit describing
+whether the access is relative to DS or SS.  That is the function of the
+cpu-state-varible M.x86.mode. There are several potential states:
+
+    repe prefix seen  (handled elsewhere)
+    repne prefix seen  (ditto)
+
+    cs segment override
+    ds segment override
+    es segment override
+    fs segment override
+    gs segment override
+    ss segment override
+
+    ds/ss select (in absense of override)
+
+Each of the above 7 items are handled with a bit in the mode field.
+****************************************************************************/
+_INLINE u32 get_data_segment(void)
+{
+#define GET_SEGMENT(segment)
+    switch (M.x86.mode & SYSMODE_SEGMASK) {
+      case 0:                   /* default case: use ds register */
+      case SYSMODE_SEGOVR_DS:
+      case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
+        return  M.x86.R_DS;
+      case SYSMODE_SEG_DS_SS:   /* non-overridden, use ss register */
+        return  M.x86.R_SS;
+      case SYSMODE_SEGOVR_CS:
+      case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
+        return  M.x86.R_CS;
+      case SYSMODE_SEGOVR_ES:
+      case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
+        return  M.x86.R_ES;
+      case SYSMODE_SEGOVR_FS:
+      case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
+        return  M.x86.R_FS;
+      case SYSMODE_SEGOVR_GS:
+      case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
+        return  M.x86.R_GS;
+      case SYSMODE_SEGOVR_SS:
+      case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
+        return  M.x86.R_SS;
+      default:
+#ifdef  CONFIG_DEBUG
+        printk("error: should not happen:  multiple overrides.\n");
+#endif
+        HALT_SYS();
+        return 0;
+    }
+}
+
+/****************************************************************************
+PARAMETERS:
+offset  - Offset to load data from
+
+RETURNS:
+Byte value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u8 fetch_data_byte(
+    uint offset)
+{
+#ifdef CONFIG_DEBUG
+    if (CHECK_DATA_ACCESS())
+        x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+    return (*sys_rdb)((get_data_segment() << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset  - Offset to load data from
+
+RETURNS:
+Word value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u16 fetch_data_word(
+    uint offset)
+{
+#ifdef CONFIG_DEBUG
+    if (CHECK_DATA_ACCESS())
+        x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+    return (*sys_rdw)((get_data_segment() << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset  - Offset to load data from
+
+RETURNS:
+Long value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u32 fetch_data_long(
+    uint offset)
+{
+#ifdef CONFIG_DEBUG
+    if (CHECK_DATA_ACCESS())
+        x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+    return (*sys_rdl)((get_data_segment() << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to load data from
+offset  - Offset to load data from
+
+RETURNS:
+Byte value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u8 fetch_data_byte_abs(
+    uint segment,
+    uint offset)
+{
+#ifdef CONFIG_DEBUG
+    if (CHECK_DATA_ACCESS())
+        x86emu_check_data_access(segment, offset);
+#endif
+    return (*sys_rdb)(((u32)segment << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to load data from
+offset  - Offset to load data from
+
+RETURNS:
+Word value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u16 fetch_data_word_abs(
+    uint segment,
+    uint offset)
+{
+#ifdef CONFIG_DEBUG
+    if (CHECK_DATA_ACCESS())
+        x86emu_check_data_access(segment, offset);
+#endif
+    return (*sys_rdw)(((u32)segment << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to load data from
+offset  - Offset to load data from
+
+RETURNS:
+Long value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u32 fetch_data_long_abs(
+    uint segment,
+    uint offset)
+{
+#ifdef CONFIG_DEBUG
+    if (CHECK_DATA_ACCESS())
+        x86emu_check_data_access(segment, offset);
+#endif
+    return (*sys_rdl)(((u32)segment << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset  - Offset to store data at
+val     - Value to store
+
+REMARKS:
+Writes a word value to an segmented memory location. The segment used is
+the current 'default' segment, which may have been overridden.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_byte(
+    uint offset,
+    u8 val)
+{
+#ifdef CONFIG_DEBUG
+    if (CHECK_DATA_ACCESS())
+        x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+    (*sys_wrb)((get_data_segment() << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset  - Offset to store data at
+val     - Value to store
+
+REMARKS:
+Writes a word value to an segmented memory location. The segment used is
+the current 'default' segment, which may have been overridden.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_word(
+    uint offset,
+    u16 val)
+{
+#ifdef CONFIG_DEBUG
+    if (CHECK_DATA_ACCESS())
+        x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+    (*sys_wrw)((get_data_segment() << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset  - Offset to store data at
+val     - Value to store
+
+REMARKS:
+Writes a long value to an segmented memory location. The segment used is
+the current 'default' segment, which may have been overridden.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_long(
+    uint offset,
+    u32 val)
+{
+#ifdef CONFIG_DEBUG
+    if (CHECK_DATA_ACCESS())
+        x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+    (*sys_wrl)((get_data_segment() << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to store data at
+offset  - Offset to store data at
+val     - Value to store
+
+REMARKS:
+Writes a byte value to an absolute memory location.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_byte_abs(
+    uint segment,
+    uint offset,
+    u8 val)
+{
+#ifdef CONFIG_DEBUG
+    if (CHECK_DATA_ACCESS())
+        x86emu_check_data_access(segment, offset);
+#endif
+    (*sys_wrb)(((u32)segment << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to store data at
+offset  - Offset to store data at
+val     - Value to store
+
+REMARKS:
+Writes a word value to an absolute memory location.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_word_abs(
+    uint segment,
+    uint offset,
+    u16 val)
+{
+#ifdef CONFIG_DEBUG
+    if (CHECK_DATA_ACCESS())
+        x86emu_check_data_access(segment, offset);
+#endif
+    (*sys_wrw)(((u32)segment << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to store data at
+offset  - Offset to store data at
+val     - Value to store
+
+REMARKS:
+Writes a long value to an absolute memory location.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_long_abs(
+    uint segment,
+    uint offset,
+    u32 val)
+{
+#ifdef CONFIG_DEBUG
+    if (CHECK_DATA_ACCESS())
+        x86emu_check_data_access(segment, offset);
+#endif
+    (*sys_wrl)(((u32)segment << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+reg - Register to decode
+
+RETURNS:
+Pointer to the appropriate register
+
+REMARKS:
+Return a pointer to the register given by the R/RM field of the
+modrm byte, for byte operands. Also enables the decoding of instructions.
+****************************************************************************/
+u8* decode_rm_byte_register(
+    int reg)
+{
+    switch (reg) {
+      case 0:
+        DECODE_PRINTF("AL");
+        return &M.x86.R_AL;
+      case 1:
+        DECODE_PRINTF("CL");
+        return &M.x86.R_CL;
+      case 2:
+        DECODE_PRINTF("DL");
+        return &M.x86.R_DL;
+      case 3:
+        DECODE_PRINTF("BL");
+        return &M.x86.R_BL;
+      case 4:
+        DECODE_PRINTF("AH");
+        return &M.x86.R_AH;
+      case 5:
+        DECODE_PRINTF("CH");
+        return &M.x86.R_CH;
+      case 6:
+        DECODE_PRINTF("DH");
+        return &M.x86.R_DH;
+      case 7:
+        DECODE_PRINTF("BH");
+        return &M.x86.R_BH;
+    }
+    HALT_SYS();
+    return NULL;                /* NOT REACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+reg - Register to decode
+
+RETURNS:
+Pointer to the appropriate register
+
+REMARKS:
+Return a pointer to the register given by the R/RM field of the
+modrm byte, for word operands.  Also enables the decoding of instructions.
+****************************************************************************/
+u16* decode_rm_word_register(
+    int reg)
+{
+    switch (reg) {
+      case 0:
+        DECODE_PRINTF("AX");
+        return &M.x86.R_AX;
+      case 1:
+        DECODE_PRINTF("CX");
+        return &M.x86.R_CX;
+      case 2:
+        DECODE_PRINTF("DX");
+        return &M.x86.R_DX;
+      case 3:
+        DECODE_PRINTF("BX");
+        return &M.x86.R_BX;
+      case 4:
+        DECODE_PRINTF("SP");
+        return &M.x86.R_SP;
+      case 5:
+        DECODE_PRINTF("BP");
+        return &M.x86.R_BP;
+      case 6:
+        DECODE_PRINTF("SI");
+        return &M.x86.R_SI;
+      case 7:
+        DECODE_PRINTF("DI");
+        return &M.x86.R_DI;
+    }
+    HALT_SYS();
+    return NULL;                /* NOTREACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+reg - Register to decode
+
+RETURNS:
+Pointer to the appropriate register
+
+REMARKS:
+Return a pointer to the register given by the R/RM field of the
+modrm byte, for dword operands.  Also enables the decoding of instructions.
+****************************************************************************/
+u32* decode_rm_long_register(
+    int reg)
+{
+    switch (reg) {
+      case 0:
+        DECODE_PRINTF("EAX");
+        return &M.x86.R_EAX;
+      case 1:
+        DECODE_PRINTF("ECX");
+        return &M.x86.R_ECX;
+      case 2:
+        DECODE_PRINTF("EDX");
+        return &M.x86.R_EDX;
+      case 3:
+        DECODE_PRINTF("EBX");
+        return &M.x86.R_EBX;
+      case 4:
+        DECODE_PRINTF("ESP");
+        return &M.x86.R_ESP;
+      case 5:
+        DECODE_PRINTF("EBP");
+        return &M.x86.R_EBP;
+      case 6:
+        DECODE_PRINTF("ESI");
+        return &M.x86.R_ESI;
+      case 7:
+        DECODE_PRINTF("EDI");
+        return &M.x86.R_EDI;
+    }
+    HALT_SYS();
+    return NULL;                /* NOTREACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+reg - Register to decode
+
+RETURNS:
+Pointer to the appropriate register
+
+REMARKS:
+Return a pointer to the register given by the R/RM field of the
+modrm byte, for word operands, modified from above for the weirdo
+special case of segreg operands.  Also enables the decoding of instructions.
+****************************************************************************/
+u16* decode_rm_seg_register(
+    int reg)
+{
+    switch (reg) {
+      case 0:
+        DECODE_PRINTF("ES");
+        return &M.x86.R_ES;
+      case 1:
+        DECODE_PRINTF("CS");
+        return &M.x86.R_CS;
+      case 2:
+        DECODE_PRINTF("SS");
+        return &M.x86.R_SS;
+      case 3:
+        DECODE_PRINTF("DS");
+        return &M.x86.R_DS;
+      case 4:
+        DECODE_PRINTF("FS");
+        return &M.x86.R_FS;
+      case 5:
+        DECODE_PRINTF("GS");
+        return &M.x86.R_GS;
+      case 6:
+      case 7:
+        DECODE_PRINTF("ILLEGAL SEGREG");
+        break;
+    }
+    HALT_SYS();
+    return NULL;                /* NOT REACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+scale - scale value of SIB byte
+index - index value of SIB byte
+
+RETURNS:
+Value of scale * index
+
+REMARKS:
+Decodes scale/index of SIB byte and returns relevant offset part of 
+effective address.
+****************************************************************************/
+unsigned decode_sib_si(
+    int scale,
+    int index)
+{
+    scale = 1 << scale;
+    if (scale > 1) {
+        DECODE_PRINTF2("[%d*", scale);
+    } else {
+        DECODE_PRINTF("[");
+    }
+    switch (index) {
+      case 0:
+        DECODE_PRINTF("EAX]");
+        return M.x86.R_EAX * index;
+      case 1:
+        DECODE_PRINTF("ECX]");
+        return M.x86.R_ECX * index;
+      case 2:
+        DECODE_PRINTF("EDX]");
+        return M.x86.R_EDX * index;
+      case 3:
+        DECODE_PRINTF("EBX]");
+        return M.x86.R_EBX * index;
+      case 4:
+        DECODE_PRINTF("0]");
+        return 0;
+      case 5:
+        DECODE_PRINTF("EBP]");
+        return M.x86.R_EBP * index;
+      case 6:
+        DECODE_PRINTF("ESI]");
+        return M.x86.R_ESI * index;
+      case 7:
+        DECODE_PRINTF("EDI]");
+        return M.x86.R_EDI * index;
+    }
+    HALT_SYS();
+    return 0;                   /* NOT REACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+mod - MOD value of preceding ModR/M byte
+
+RETURNS:
+Offset in memory for the address decoding
+
+REMARKS:
+Decodes SIB addressing byte and returns calculated effective address.
+****************************************************************************/
+unsigned decode_sib_address(
+    int mod)
+{
+    int sib   = fetch_byte_imm();
+    int ss    = (sib >> 6) & 0x03;
+    int index = (sib >> 3) & 0x07;
+    int base  = sib & 0x07;
+    int offset = 0;
+    int displacement;
+
+    switch (base) {
+      case 0:
+        DECODE_PRINTF("[EAX]");
+        offset = M.x86.R_EAX;
+        break;
+      case 1:
+        DECODE_PRINTF("[ECX]");
+        offset = M.x86.R_ECX;
+        break;
+      case 2:
+        DECODE_PRINTF("[EDX]");
+        offset = M.x86.R_EDX;
+        break;
+      case 3:
+        DECODE_PRINTF("[EBX]");
+        offset = M.x86.R_EBX;
+        break;
+      case 4:
+        DECODE_PRINTF("[ESP]");
+        offset = M.x86.R_ESP;
+        break;
+      case 5:
+        switch (mod) {
+          case 0:
+            displacement = (s32)fetch_long_imm();
+            DECODE_PRINTF2("[%d]", displacement);
+            offset = displacement;
+            break;
+          case 1:
+            displacement = (s8)fetch_byte_imm();
+            DECODE_PRINTF2("[%d][EBP]", displacement);
+            offset = M.x86.R_EBP + displacement;
+            break;
+          case 2:
+            displacement = (s32)fetch_long_imm();
+            DECODE_PRINTF2("[%d][EBP]", displacement);
+            offset = M.x86.R_EBP + displacement;
+            break;
+          default:
+            HALT_SYS();
+        }
+        DECODE_PRINTF("[EAX]");
+        offset = M.x86.R_EAX;
+        break;
+      case 6:
+        DECODE_PRINTF("[ESI]");
+        offset = M.x86.R_ESI;
+        break;
+      case 7:
+        DECODE_PRINTF("[EDI]");
+        offset = M.x86.R_EDI;
+        break;
+      default:
+        HALT_SYS();
+    }
+    offset += decode_sib_si(ss, index);
+    return offset;
+}
+
+/****************************************************************************
+PARAMETERS:
+rm  - RM value to decode
+
+RETURNS:
+Offset in memory for the address decoding
+
+REMARKS:
+Return the offset given by mod=00 addressing.  Also enables the
+decoding of instructions.
+
+NOTE:   The code which specifies the corresponding segment (ds vs ss)
+        below in the case of [BP+..].  The assumption here is that at the
+        point that this subroutine is called, the bit corresponding to
+        SYSMODE_SEG_DS_SS will be zero.  After every instruction
+        except the segment override instructions, this bit (as well
+        as any bits indicating segment overrides) will be clear.  So
+        if a SS access is needed, set this bit.  Otherwise, DS access
+        occurs (unless any of the segment override bits are set).
+****************************************************************************/
+unsigned decode_rm00_address(
+    int rm)
+{
+    unsigned offset;
+
+    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+        /* 32-bit addressing */
+        switch (rm) {
+          case 0:
+            DECODE_PRINTF("[EAX]");
+            return M.x86.R_EAX;
+          case 1:
+            DECODE_PRINTF("[ECX]");
+            return M.x86.R_ECX;
+          case 2:
+            DECODE_PRINTF("[EDX]");
+            return M.x86.R_EDX;
+          case 3:
+            DECODE_PRINTF("[EBX]");
+            return M.x86.R_EBX;
+          case 4:
+            return decode_sib_address(0);
+          case 5:
+            offset = fetch_long_imm();
+            DECODE_PRINTF2("[%08x]", offset);
+            return offset;
+          case 6:
+            DECODE_PRINTF("[ESI]");
+            return M.x86.R_ESI;
+          case 7:
+            DECODE_PRINTF("[EDI]");
+            return M.x86.R_EDI;
+        }
+    } else {
+        /* 16-bit addressing */
+        switch (rm) {
+          case 0:
+            DECODE_PRINTF("[BX+SI]");
+            return (M.x86.R_BX + M.x86.R_SI) & 0xffff;
+          case 1:
+            DECODE_PRINTF("[BX+DI]");
+            return (M.x86.R_BX + M.x86.R_DI) & 0xffff;
+          case 2:
+            DECODE_PRINTF("[BP+SI]");
+            M.x86.mode |= SYSMODE_SEG_DS_SS;
+            return (M.x86.R_BP + M.x86.R_SI) & 0xffff;
+          case 3:
+            DECODE_PRINTF("[BP+DI]");
+            M.x86.mode |= SYSMODE_SEG_DS_SS;
+            return (M.x86.R_BP + M.x86.R_DI) & 0xffff;
+          case 4:
+            DECODE_PRINTF("[SI]");
+            return M.x86.R_SI;
+          case 5:
+            DECODE_PRINTF("[DI]");
+            return M.x86.R_DI;
+          case 6:
+            offset = fetch_word_imm();
+            DECODE_PRINTF2("[%04x]", offset);
+            return offset;
+          case 7:
+            DECODE_PRINTF("[BX]");
+            return M.x86.R_BX;
+        }
+    }
+    HALT_SYS();
+    return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+rm  - RM value to decode
+
+RETURNS:
+Offset in memory for the address decoding
+
+REMARKS:
+Return the offset given by mod=01 addressing.  Also enables the
+decoding of instructions.
+****************************************************************************/
+unsigned decode_rm01_address(
+    int rm)
+{
+    int displacement;
+
+    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+        /* 32-bit addressing */
+        if (rm != 4)
+            displacement = (s8)fetch_byte_imm();
+        else
+            displacement = 0;
+
+        switch (rm) {
+          case 0:
+            DECODE_PRINTF2("%d[EAX]", displacement);
+            return M.x86.R_EAX + displacement;
+          case 1:
+            DECODE_PRINTF2("%d[ECX]", displacement);
+            return M.x86.R_ECX + displacement;
+          case 2:
+            DECODE_PRINTF2("%d[EDX]", displacement);
+            return M.x86.R_EDX + displacement;
+          case 3:
+            DECODE_PRINTF2("%d[EBX]", displacement);
+            return M.x86.R_EBX + displacement;
+          case 4: {
+            int offset = decode_sib_address(1);
+            displacement = (s8)fetch_byte_imm();
+            DECODE_PRINTF2("[%d]", displacement);
+            return offset + displacement;
+          }
+          case 5:
+            DECODE_PRINTF2("%d[EBP]", displacement);
+            return M.x86.R_EBP + displacement;
+          case 6:
+            DECODE_PRINTF2("%d[ESI]", displacement);
+            return M.x86.R_ESI + displacement;
+          case 7:
+            DECODE_PRINTF2("%d[EDI]", displacement);
+            return M.x86.R_EDI + displacement;
+        }
+    } else {
+        /* 16-bit addressing */
+        displacement = (s8)fetch_byte_imm();
+        switch (rm) {
+          case 0:
+            DECODE_PRINTF2("%d[BX+SI]", displacement);
+            return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
+          case 1:
+            DECODE_PRINTF2("%d[BX+DI]", displacement);
+            return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
+          case 2:
+            DECODE_PRINTF2("%d[BP+SI]", displacement);
+            M.x86.mode |= SYSMODE_SEG_DS_SS;
+            return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
+          case 3:
+            DECODE_PRINTF2("%d[BP+DI]", displacement);
+            M.x86.mode |= SYSMODE_SEG_DS_SS;
+            return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
+          case 4:
+            DECODE_PRINTF2("%d[SI]", displacement);
+            return (M.x86.R_SI + displacement) & 0xffff;
+          case 5:
+            DECODE_PRINTF2("%d[DI]", displacement);
+            return (M.x86.R_DI + displacement) & 0xffff;
+          case 6:
+            DECODE_PRINTF2("%d[BP]", displacement);
+            M.x86.mode |= SYSMODE_SEG_DS_SS;
+            return (M.x86.R_BP + displacement) & 0xffff;
+          case 7:
+            DECODE_PRINTF2("%d[BX]", displacement);
+            return (M.x86.R_BX + displacement) & 0xffff;
+        }
+    }
+    HALT_SYS();
+    return 0;                   /* SHOULD NOT HAPPEN */
+}
+
+/****************************************************************************
+PARAMETERS:
+rm  - RM value to decode
+
+RETURNS:
+Offset in memory for the address decoding
+
+REMARKS:
+Return the offset given by mod=10 addressing.  Also enables the
+decoding of instructions.
+****************************************************************************/
+unsigned decode_rm10_address(
+    int rm)
+{
+    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+        int displacement;
+
+        /* 32-bit addressing */
+        if (rm != 4)
+            displacement = (s32)fetch_long_imm();
+        else
+            displacement = 0;
+
+        switch (rm) {
+          case 0:
+            DECODE_PRINTF2("%d[EAX]", displacement);
+            return M.x86.R_EAX + displacement;
+          case 1:
+            DECODE_PRINTF2("%d[ECX]", displacement);
+            return M.x86.R_ECX + displacement;
+          case 2:
+            DECODE_PRINTF2("%d[EDX]", displacement);
+            return M.x86.R_EDX + displacement;
+          case 3:
+            DECODE_PRINTF2("%d[EBX]", displacement);
+            return M.x86.R_EBX + displacement;
+          case 4: {
+            int offset = decode_sib_address(2);
+            displacement = (s32)fetch_long_imm();
+            DECODE_PRINTF2("[%d]", displacement);
+            return offset + displacement;
+          }
+          case 5:
+            DECODE_PRINTF2("%d[EBP]", displacement);
+            return M.x86.R_EBP + displacement;
+          case 6:
+            DECODE_PRINTF2("%d[ESI]", displacement);
+            return M.x86.R_ESI + displacement;
+          case 7:
+            DECODE_PRINTF2("%d[EDI]", displacement);
+            return M.x86.R_EDI + displacement;
+        }
+    } else {
+        int displacement = (s16)fetch_word_imm();
+
+        /* 16-bit addressing */
+        switch (rm) {
+          case 0:
+            DECODE_PRINTF2("%d[BX+SI]", displacement);
+            return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
+          case 1:
+            DECODE_PRINTF2("%d[BX+DI]", displacement);
+            return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
+          case 2:
+            DECODE_PRINTF2("%d[BP+SI]", displacement);
+            M.x86.mode |= SYSMODE_SEG_DS_SS;
+            return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
+          case 3:
+            DECODE_PRINTF2("%d[BP+DI]", displacement);
+            M.x86.mode |= SYSMODE_SEG_DS_SS;
+            return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
+          case 4:
+            DECODE_PRINTF2("%d[SI]", displacement);
+            return (M.x86.R_SI + displacement) & 0xffff;
+          case 5:
+            DECODE_PRINTF2("%d[DI]", displacement);
+            return (M.x86.R_DI + displacement) & 0xffff;
+          case 6:
+            DECODE_PRINTF2("%d[BP]", displacement);
+            M.x86.mode |= SYSMODE_SEG_DS_SS;
+            return (M.x86.R_BP + displacement) & 0xffff;
+          case 7:
+            DECODE_PRINTF2("%d[BX]", displacement);
+            return (M.x86.R_BX + displacement) & 0xffff;
+        }
+    }
+    HALT_SYS();
+    return 0;                   /* SHOULD NOT HAPPEN */
+}
+
+
+/****************************************************************************
+PARAMETERS:
+mod - modifier
+rm  - RM value to decode
+
+RETURNS:
+Offset in memory for the address decoding, multiplexing calls to
+the decode_rmXX_address functions
+
+REMARKS:
+Return the offset given by "mod" addressing.
+****************************************************************************/
+
+unsigned decode_rmXX_address(int mod, int rm)
+{
+  if(mod == 0)
+    return decode_rm00_address(rm);
+  if(mod == 1)
+    return decode_rm01_address(rm);
+  return decode_rm10_address(rm);
+}
+
+
+
diff --git a/util/x86emu/x86emu/decode.h b/util/x86emu/x86emu/decode.h
new file mode 100644
index 0000000..99ed7f6
--- /dev/null
+++ b/util/x86emu/x86emu/decode.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+*
+*						Realmode X86 Emulator Library
+*
+*            	Copyright (C) 1996-1999 SciTech Software, Inc.
+* 				     Copyright (C) David Mosberger-Tang
+* 					   Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:		ANSI C
+* Environment:	Any
+* Developer:    Kendall Bennett
+*
+* Description:  Header file for instruction decoding logic.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_DECODE_H
+#define __X86EMU_DECODE_H
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+/* Instruction Decoding Stuff */
+
+#define FETCH_DECODE_MODRM(mod,rh,rl) 	fetch_decode_modrm(&mod,&rh,&rl)
+#define DECODE_RM_BYTE_REGISTER(r)    	decode_rm_byte_register(r)
+#define DECODE_RM_WORD_REGISTER(r)    	decode_rm_word_register(r)
+#define DECODE_RM_LONG_REGISTER(r)    	decode_rm_long_register(r)
+#define DECODE_CLEAR_SEGOVR()         	M.x86.mode &= ~SYSMODE_CLRMASK
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+#ifdef  __cplusplus
+extern "C" {            			/* Use "C" linkage when in C++ mode */
+#endif
+
+void 	x86emu_intr_raise (u8 type);
+void    fetch_decode_modrm (int *mod,int *regh,int *regl);
+u8      fetch_byte_imm (void);
+u16     fetch_word_imm (void);
+u32     fetch_long_imm (void);
+u8      fetch_data_byte (uint offset);
+u8      fetch_data_byte_abs (uint segment, uint offset);
+u16     fetch_data_word (uint offset);
+u16     fetch_data_word_abs (uint segment, uint offset);
+u32     fetch_data_long (uint offset);
+u32     fetch_data_long_abs (uint segment, uint offset);
+void    store_data_byte (uint offset, u8 val);
+void    store_data_byte_abs (uint segment, uint offset, u8 val);
+void    store_data_word (uint offset, u16 val);
+void    store_data_word_abs (uint segment, uint offset, u16 val);
+void    store_data_long (uint offset, u32 val);
+void    store_data_long_abs (uint segment, uint offset, u32 val);
+u8* 	decode_rm_byte_register(int reg);
+u16* 	decode_rm_word_register(int reg);
+u32* 	decode_rm_long_register(int reg);
+u16* 	decode_rm_seg_register(int reg);
+unsigned decode_rm00_address(int rm);
+unsigned decode_rm01_address(int rm);
+unsigned decode_rm10_address(int rm);
+unsigned decode_rmXX_address(int mod, int rm);
+
+#ifdef  __cplusplus
+}                       			/* End of "C" linkage for C++   	*/
+#endif
+
+#endif /* __X86EMU_DECODE_H */
diff --git a/util/x86emu/x86emu/fpu.c b/util/x86emu/x86emu/fpu.c
new file mode 100644
index 0000000..86be6e9
--- /dev/null
+++ b/util/x86emu/x86emu/fpu.c
@@ -0,0 +1,945 @@
+/****************************************************************************
+*
+*                       Realmode X86 Emulator Library
+*
+*               Copyright (C) 1991-2004 SciTech Software, Inc.
+*                    Copyright (C) David Mosberger-Tang
+*                      Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:     ANSI C
+* Environment:  Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file contains the code to implement the decoding and
+*               emulation of the FPU instructions.
+*
+****************************************************************************/
+
+#include "x86emui.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/* opcode=0xd8 */
+void x86emuOp_esc_coprocess_d8(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("ESC D8\n");
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef CONFIG_DEBUG
+
+static char *x86emu_fpu_op_d9_tab[] = {
+    "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
+    "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
+
+    "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
+    "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
+
+    "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
+    "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
+};
+
+static char *x86emu_fpu_op_d9_tab1[] = {
+    "FLD\t", "FLD\t", "FLD\t", "FLD\t",
+    "FLD\t", "FLD\t", "FLD\t", "FLD\t",
+
+    "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
+    "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
+
+    "FNOP", "ESC_D9", "ESC_D9", "ESC_D9",
+    "ESC_D9", "ESC_D9", "ESC_D9", "ESC_D9",
+
+    "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
+    "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
+
+    "FCHS", "FABS", "ESC_D9", "ESC_D9",
+    "FTST", "FXAM", "ESC_D9", "ESC_D9",
+
+    "FLD1", "FLDL2T", "FLDL2E", "FLDPI",
+    "FLDLG2", "FLDLN2", "FLDZ", "ESC_D9",
+
+    "F2XM1", "FYL2X", "FPTAN", "FPATAN",
+    "FXTRACT", "ESC_D9", "FDECSTP", "FINCSTP",
+
+    "FPREM", "FYL2XP1", "FSQRT", "ESC_D9",
+    "FRNDINT", "FSCALE", "ESC_D9", "ESC_D9",
+};
+
+#endif /* CONFIG_DEBUG */
+
+/* opcode=0xd9 */
+void x86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 stkelem;
+
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (mod != 3) {
+        DECODE_PRINTINSTR32(x86emu_fpu_op_d9_tab, mod, rh, rl);
+    } else {
+        DECODE_PRINTF(x86emu_fpu_op_d9_tab1[(rh << 3) + rl]);
+    }
+#endif
+    switch (mod) {
+      case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 3:                   /* register to register */
+        stkelem = (u8)rl;
+        if (rh < 4) {
+                DECODE_PRINTF2("ST(%d)\n", stkelem);
+        } else {
+                DECODE_PRINTF("\n");
+        }
+        break;
+    }
+#ifdef X86EMU_FPU_PRESENT
+    /* execute */
+    switch (mod) {
+      case 3:
+        switch (rh) {
+          case 0:
+            x86emu_fpu_R_fld(X86EMU_FPU_STKTOP, stkelem);
+            break;
+          case 1:
+            x86emu_fpu_R_fxch(X86EMU_FPU_STKTOP, stkelem);
+            break;
+          case 2:
+            switch (rl) {
+              case 0:
+                x86emu_fpu_R_nop();
+                break;
+              default:
+                x86emu_fpu_illegal();
+                break;
+            }
+          case 3:
+            x86emu_fpu_R_fstp(X86EMU_FPU_STKTOP, stkelem);
+            break;
+          case 4:
+            switch (rl) {
+            case 0:
+                x86emu_fpu_R_fchs(X86EMU_FPU_STKTOP);
+                break;
+            case 1:
+                x86emu_fpu_R_fabs(X86EMU_FPU_STKTOP);
+                break;
+            case 4:
+                x86emu_fpu_R_ftst(X86EMU_FPU_STKTOP);
+                break;
+            case 5:
+                x86emu_fpu_R_fxam(X86EMU_FPU_STKTOP);
+                break;
+            default:
+                /* 2,3,6,7 */
+                x86emu_fpu_illegal();
+                break;
+            }
+            break;
+
+          case 5:
+            switch (rl) {
+              case 0:
+                x86emu_fpu_R_fld1(X86EMU_FPU_STKTOP);
+                break;
+              case 1:
+                x86emu_fpu_R_fldl2t(X86EMU_FPU_STKTOP);
+                break;
+              case 2:
+                x86emu_fpu_R_fldl2e(X86EMU_FPU_STKTOP);
+                break;
+              case 3:
+                x86emu_fpu_R_fldpi(X86EMU_FPU_STKTOP);
+                break;
+              case 4:
+                x86emu_fpu_R_fldlg2(X86EMU_FPU_STKTOP);
+                break;
+              case 5:
+                x86emu_fpu_R_fldln2(X86EMU_FPU_STKTOP);
+                break;
+              case 6:
+                x86emu_fpu_R_fldz(X86EMU_FPU_STKTOP);
+                break;
+              default:
+                /* 7 */
+                x86emu_fpu_illegal();
+                break;
+            }
+            break;
+
+          case 6:
+            switch (rl) {
+              case 0:
+                x86emu_fpu_R_f2xm1(X86EMU_FPU_STKTOP);
+                break;
+              case 1:
+                x86emu_fpu_R_fyl2x(X86EMU_FPU_STKTOP);
+                break;
+              case 2:
+                x86emu_fpu_R_fptan(X86EMU_FPU_STKTOP);
+                break;
+              case 3:
+                x86emu_fpu_R_fpatan(X86EMU_FPU_STKTOP);
+                break;
+              case 4:
+                x86emu_fpu_R_fxtract(X86EMU_FPU_STKTOP);
+                break;
+              case 5:
+                x86emu_fpu_illegal();
+                break;
+              case 6:
+                x86emu_fpu_R_decstp();
+                break;
+              case 7:
+                x86emu_fpu_R_incstp();
+                break;
+            }
+            break;
+
+          case 7:
+            switch (rl) {
+              case 0:
+                x86emu_fpu_R_fprem(X86EMU_FPU_STKTOP);
+                break;
+              case 1:
+                x86emu_fpu_R_fyl2xp1(X86EMU_FPU_STKTOP);
+                break;
+              case 2:
+                x86emu_fpu_R_fsqrt(X86EMU_FPU_STKTOP);
+                break;
+              case 3:
+                x86emu_fpu_illegal();
+                break;
+              case 4:
+                x86emu_fpu_R_frndint(X86EMU_FPU_STKTOP);
+                break;
+              case 5:
+                x86emu_fpu_R_fscale(X86EMU_FPU_STKTOP);
+                break;
+              case 6:
+              case 7:
+              default:
+                x86emu_fpu_illegal();
+                break;
+            }
+            break;
+
+          default:
+            switch (rh) {
+              case 0:
+                x86emu_fpu_M_fld(X86EMU_FPU_FLOAT, destoffset);
+                break;
+              case 1:
+                x86emu_fpu_illegal();
+                break;
+              case 2:
+                x86emu_fpu_M_fst(X86EMU_FPU_FLOAT, destoffset);
+                break;
+              case 3:
+                x86emu_fpu_M_fstp(X86EMU_FPU_FLOAT, destoffset);
+                break;
+              case 4:
+                x86emu_fpu_M_fldenv(X86EMU_FPU_WORD, destoffset);
+                break;
+              case 5:
+                x86emu_fpu_M_fldcw(X86EMU_FPU_WORD, destoffset);
+                break;
+              case 6:
+                x86emu_fpu_M_fstenv(X86EMU_FPU_WORD, destoffset);
+                break;
+              case 7:
+                x86emu_fpu_M_fstcw(X86EMU_FPU_WORD, destoffset);
+                break;
+            }
+        }
+    }
+#endif /* X86EMU_FPU_PRESENT */
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef CONFIG_DEBUG
+
+char *x86emu_fpu_op_da_tab[] = {
+    "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
+    "FICOMP\tDWORD PTR ",
+    "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
+    "FIDIVR\tDWORD PTR ",
+
+    "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
+    "FICOMP\tDWORD PTR ",
+    "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
+    "FIDIVR\tDWORD PTR ",
+
+    "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
+    "FICOMP\tDWORD PTR ",
+    "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
+    "FIDIVR\tDWORD PTR ",
+
+    "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ",
+    "ESC_DA     ", "ESC_DA ", "ESC_DA   ", "ESC_DA ",
+};
+
+#endif /* CONFIG_DEBUG */
+
+/* opcode=0xda */
+void x86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 stkelem;
+
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    DECODE_PRINTINSTR32(x86emu_fpu_op_da_tab, mod, rh, rl);
+    switch (mod) {
+      case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 3:           /* register to register */
+        stkelem = (u8)rl;
+        DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
+        break;
+    }
+#ifdef X86EMU_FPU_PRESENT
+    switch (mod) {
+      case 3:
+        x86emu_fpu_illegal();
+        break;
+      default:
+        switch (rh) {
+          case 0:
+            x86emu_fpu_M_iadd(X86EMU_FPU_SHORT, destoffset);
+            break;
+          case 1:
+            x86emu_fpu_M_imul(X86EMU_FPU_SHORT, destoffset);
+            break;
+          case 2:
+            x86emu_fpu_M_icom(X86EMU_FPU_SHORT, destoffset);
+            break;
+          case 3:
+            x86emu_fpu_M_icomp(X86EMU_FPU_SHORT, destoffset);
+            break;
+          case 4:
+            x86emu_fpu_M_isub(X86EMU_FPU_SHORT, destoffset);
+            break;
+          case 5:
+            x86emu_fpu_M_isubr(X86EMU_FPU_SHORT, destoffset);
+            break;
+          case 6:
+            x86emu_fpu_M_idiv(X86EMU_FPU_SHORT, destoffset);
+            break;
+          case 7:
+            x86emu_fpu_M_idivr(X86EMU_FPU_SHORT, destoffset);
+            break;
+        }
+    }
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef CONFIG_DEBUG
+
+char *x86emu_fpu_op_db_tab[] = {
+    "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
+    "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
+
+    "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
+    "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
+
+    "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
+    "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
+};
+
+#endif /* CONFIG_DEBUG */
+
+/* opcode=0xdb */
+void x86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (mod != 3) {
+        DECODE_PRINTINSTR32(x86emu_fpu_op_db_tab, mod, rh, rl);
+    } else if (rh == 4) {       /* === 11 10 0 nnn */
+        switch (rl) {
+          case 0:
+            DECODE_PRINTF("FENI\n");
+            break;
+          case 1:
+            DECODE_PRINTF("FDISI\n");
+            break;
+          case 2:
+            DECODE_PRINTF("FCLEX\n");
+            break;
+          case 3:
+            DECODE_PRINTF("FINIT\n");
+            break;
+        }
+    } else {
+        DECODE_PRINTF2("ESC_DB %0x\n", (mod << 6) + (rh << 3) + (rl));
+    }
+#endif /* CONFIG_DEBUG */
+    switch (mod) {
+      case 0:
+        destoffset = decode_rm00_address(rl);
+        break;
+      case 1:
+        destoffset = decode_rm01_address(rl);
+        break;
+      case 2:
+        destoffset = decode_rm10_address(rl);
+        break;
+      case 3:                   /* register to register */
+        break;
+    }
+#ifdef X86EMU_FPU_PRESENT
+    /* execute */
+    switch (mod) {
+      case 3:
+        switch (rh) {
+          case 4:
+            switch (rl) {
+              case 0:
+                x86emu_fpu_R_feni();
+                break;
+              case 1:
+                x86emu_fpu_R_fdisi();
+                break;
+              case 2:
+                x86emu_fpu_R_fclex();
+                break;
+              case 3:
+                x86emu_fpu_R_finit();
+                break;
+              default:
+                x86emu_fpu_illegal();
+                break;
+            }
+            break;
+          default:
+            x86emu_fpu_illegal();
+            break;
+        }
+        break;
+      default:
+        switch (rh) {
+          case 0:
+            x86emu_fpu_M_fild(X86EMU_FPU_SHORT, destoffset);
+            break;
+          case 1:
+            x86emu_fpu_illegal();
+            break;
+          case 2:
+            x86emu_fpu_M_fist(X86EMU_FPU_SHORT, destoffset);
+            break;
+          case 3:
+            x86emu_fpu_M_fistp(X86EMU_FPU_SHORT, destoffset);
+            break;
+          case 4:
+            x86emu_fpu_illegal();
+            break;
+          case 5:
+            x86emu_fpu_M_fld(X86EMU_FPU_LDBL, destoffset);
+            break;
+                      case 6:
+            x86emu_fpu_illegal();
+            break;
+          case 7:
+            x86emu_fpu_M_fstp(X86EMU_FPU_LDBL, destoffset);
+            break;
+        }
+    }
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef CONFIG_DEBUG
+char *x86emu_fpu_op_dc_tab[] = {
+    "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
+    "FCOMP\tQWORD PTR ",
+    "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
+    "FDIVR\tQWORD PTR ",
+
+    "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
+    "FCOMP\tQWORD PTR ",
+    "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
+    "FDIVR\tQWORD PTR ",
+
+    "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
+    "FCOMP\tQWORD PTR ",
+    "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
+    "FDIVR\tQWORD PTR ",
+
+    "FADD\t", "FMUL\t", "FCOM\t", "FCOMP\t",
+    "FSUBR\t", "FSUB\t", "FDIVR\t", "FDIV\t",
+};
+#endif /* CONFIG_DEBUG */
+
+/* opcode=0xdc */
+void x86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 stkelem;
+
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    DECODE_PRINTINSTR32(x86emu_fpu_op_dc_tab, mod, rh, rl);
+    switch (mod) {
+      case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 3:                   /* register to register */
+        stkelem = (u8)rl;
+        DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
+        break;
+    }
+#ifdef X86EMU_FPU_PRESENT
+    /* execute */
+    switch (mod) {
+      case 3:
+        switch (rh) {
+          case 0:
+            x86emu_fpu_R_fadd(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 1:
+            x86emu_fpu_R_fmul(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 2:
+            x86emu_fpu_R_fcom(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 3:
+            x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 4:
+            x86emu_fpu_R_fsubr(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 5:
+            x86emu_fpu_R_fsub(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 6:
+            x86emu_fpu_R_fdivr(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 7:
+            x86emu_fpu_R_fdiv(stkelem, X86EMU_FPU_STKTOP);
+            break;
+        }
+        break;
+      default:
+        switch (rh) {
+          case 0:
+            x86emu_fpu_M_fadd(X86EMU_FPU_DOUBLE, destoffset);
+            break;
+          case 1:
+            x86emu_fpu_M_fmul(X86EMU_FPU_DOUBLE, destoffset);
+            break;
+          case 2:
+            x86emu_fpu_M_fcom(X86EMU_FPU_DOUBLE, destoffset);
+            break;
+          case 3:
+            x86emu_fpu_M_fcomp(X86EMU_FPU_DOUBLE, destoffset);
+            break;
+          case 4:
+            x86emu_fpu_M_fsub(X86EMU_FPU_DOUBLE, destoffset);
+            break;
+          case 5:
+            x86emu_fpu_M_fsubr(X86EMU_FPU_DOUBLE, destoffset);
+            break;
+          case 6:
+            x86emu_fpu_M_fdiv(X86EMU_FPU_DOUBLE, destoffset);
+            break;
+          case 7:
+            x86emu_fpu_M_fdivr(X86EMU_FPU_DOUBLE, destoffset);
+            break;
+        }
+    }
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef CONFIG_DEBUG
+
+static char *x86emu_fpu_op_dd_tab[] = {
+    "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
+    "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
+
+    "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
+    "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
+
+    "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
+    "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
+
+    "FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
+    "ESC_DD\t2C,", "ESC_DD\t2D,", "ESC_DD\t2E,", "ESC_DD\t2F,",
+};
+
+#endif /* CONFIG_DEBUG */
+
+/* opcode=0xdd */
+void x86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 stkelem;
+
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    DECODE_PRINTINSTR32(x86emu_fpu_op_dd_tab, mod, rh, rl);
+    switch (mod) {
+      case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 3:                   /* register to register */
+        stkelem = (u8)rl;
+        DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
+        break;
+    }
+#ifdef X86EMU_FPU_PRESENT
+    switch (mod) {
+      case 3:
+        switch (rh) {
+          case 0:
+            x86emu_fpu_R_ffree(stkelem);
+            break;
+          case 1:
+            x86emu_fpu_R_fxch(stkelem);
+            break;
+          case 2:
+            x86emu_fpu_R_fst(stkelem);  /* register version */
+            break;
+          case 3:
+            x86emu_fpu_R_fstp(stkelem); /* register version */
+            break;
+          default:
+            x86emu_fpu_illegal();
+            break;
+        }
+        break;
+      default:
+        switch (rh) {
+          case 0:
+            x86emu_fpu_M_fld(X86EMU_FPU_DOUBLE, destoffset);
+            break;
+          case 1:
+            x86emu_fpu_illegal();
+            break;
+          case 2:
+            x86emu_fpu_M_fst(X86EMU_FPU_DOUBLE, destoffset);
+            break;
+          case 3:
+            x86emu_fpu_M_fstp(X86EMU_FPU_DOUBLE, destoffset);
+            break;
+          case 4:
+            x86emu_fpu_M_frstor(X86EMU_FPU_WORD, destoffset);
+            break;
+          case 5:
+            x86emu_fpu_illegal();
+            break;
+          case 6:
+            x86emu_fpu_M_fsave(X86EMU_FPU_WORD, destoffset);
+            break;
+          case 7:
+            x86emu_fpu_M_fstsw(X86EMU_FPU_WORD, destoffset);
+            break;
+        }
+    }
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef CONFIG_DEBUG
+
+static char *x86emu_fpu_op_de_tab[] =
+{
+    "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
+    "FICOMP\tWORD PTR ",
+    "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
+    "FIDIVR\tWORD PTR ",
+
+    "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
+    "FICOMP\tWORD PTR ",
+    "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
+    "FIDIVR\tWORD PTR ",
+
+    "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
+    "FICOMP\tWORD PTR ",
+    "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
+    "FIDIVR\tWORD PTR ",
+
+    "FADDP\t", "FMULP\t", "FCOMP\t", "FCOMPP\t",
+    "FSUBRP\t", "FSUBP\t", "FDIVRP\t", "FDIVP\t",
+};
+
+#endif /* CONFIG_DEBUG */
+
+/* opcode=0xde */
+void x86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 stkelem;
+
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    DECODE_PRINTINSTR32(x86emu_fpu_op_de_tab, mod, rh, rl);
+    switch (mod) {
+      case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 3:                   /* register to register */
+        stkelem = (u8)rl;
+        DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
+        break;
+    }
+#ifdef X86EMU_FPU_PRESENT
+    switch (mod) {
+      case 3:
+        switch (rh) {
+          case 0:
+            x86emu_fpu_R_faddp(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 1:
+            x86emu_fpu_R_fmulp(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 2:
+            x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 3:
+            if (stkelem == 1)
+              x86emu_fpu_R_fcompp(stkelem, X86EMU_FPU_STKTOP);
+            else
+              x86emu_fpu_illegal();
+            break;
+          case 4:
+            x86emu_fpu_R_fsubrp(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 5:
+            x86emu_fpu_R_fsubp(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 6:
+            x86emu_fpu_R_fdivrp(stkelem, X86EMU_FPU_STKTOP);
+            break;
+          case 7:
+            x86emu_fpu_R_fdivp(stkelem, X86EMU_FPU_STKTOP);
+            break;
+        }
+        break;
+      default:
+        switch (rh) {
+          case 0:
+            x86emu_fpu_M_fiadd(X86EMU_FPU_WORD, destoffset);
+            break;
+          case 1:
+            x86emu_fpu_M_fimul(X86EMU_FPU_WORD, destoffset);
+            break;
+          case 2:
+            x86emu_fpu_M_ficom(X86EMU_FPU_WORD, destoffset);
+            break;
+          case 3:
+            x86emu_fpu_M_ficomp(X86EMU_FPU_WORD, destoffset);
+            break;
+          case 4:
+            x86emu_fpu_M_fisub(X86EMU_FPU_WORD, destoffset);
+            break;
+          case 5:
+            x86emu_fpu_M_fisubr(X86EMU_FPU_WORD, destoffset);
+            break;
+          case 6:
+            x86emu_fpu_M_fidiv(X86EMU_FPU_WORD, destoffset);
+            break;
+          case 7:
+            x86emu_fpu_M_fidivr(X86EMU_FPU_WORD, destoffset);
+            break;
+        }
+    }
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef CONFIG_DEBUG
+
+static char *x86emu_fpu_op_df_tab[] = {
+    /* mod == 00 */
+    "FILD\tWORD PTR ", "ESC_DF\t39\n", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
+    "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
+    "FISTP\tQWORD PTR ",
+
+    /* mod == 01 */
+    "FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
+    "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
+    "FISTP\tQWORD PTR ",
+
+    /* mod == 10 */
+    "FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
+    "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
+    "FISTP\tQWORD PTR ",
+
+    /* mod == 11 */
+    "FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
+    "ESC_DF\t3C,", "ESC_DF\t3D,", "ESC_DF\t3E,", "ESC_DF\t3F,"
+};
+
+#endif /* CONFIG_DEBUG */
+
+/* opcode=0xdf */
+void x86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 stkelem;
+
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    DECODE_PRINTINSTR32(x86emu_fpu_op_df_tab, mod, rh, rl);
+    switch (mod) {
+      case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        break;
+      case 3:                   /* register to register */
+        stkelem = (u8)rl;
+        DECODE_PRINTF2("\tST(%d)\n", stkelem);
+        break;
+    }
+#ifdef X86EMU_FPU_PRESENT
+    switch (mod) {
+      case 3:
+        switch (rh) {
+          case 0:
+            x86emu_fpu_R_ffree(stkelem);
+            break;
+          case 1:
+            x86emu_fpu_R_fxch(stkelem);
+            break;
+          case 2:
+            x86emu_fpu_R_fst(stkelem);  /* register version */
+            break;
+          case 3:
+            x86emu_fpu_R_fstp(stkelem); /* register version */
+            break;
+          default:
+            x86emu_fpu_illegal();
+            break;
+        }
+        break;
+      default:
+        switch (rh) {
+          case 0:
+            x86emu_fpu_M_fild(X86EMU_FPU_WORD, destoffset);
+            break;
+          case 1:
+            x86emu_fpu_illegal();
+            break;
+          case 2:
+            x86emu_fpu_M_fist(X86EMU_FPU_WORD, destoffset);
+            break;
+          case 3:
+            x86emu_fpu_M_fistp(X86EMU_FPU_WORD, destoffset);
+            break;
+          case 4:
+            x86emu_fpu_M_fbld(X86EMU_FPU_BSD, destoffset);
+            break;
+          case 5:
+            x86emu_fpu_M_fild(X86EMU_FPU_LONG, destoffset);
+            break;
+          case 6:
+            x86emu_fpu_M_fbstp(X86EMU_FPU_BSD, destoffset);
+            break;
+          case 7:
+            x86emu_fpu_M_fistp(X86EMU_FPU_LONG, destoffset);
+            break;
+        }
+    }
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
diff --git a/util/x86emu/x86emu/fpu.h b/util/x86emu/x86emu/fpu.h
new file mode 100644
index 0000000..5fb2714
--- /dev/null
+++ b/util/x86emu/x86emu/fpu.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+*
+*						Realmode X86 Emulator Library
+*
+*            	Copyright (C) 1996-1999 SciTech Software, Inc.
+* 				     Copyright (C) David Mosberger-Tang
+* 					   Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:		ANSI C
+* Environment:	Any
+* Developer:    Kendall Bennett
+*
+* Description:  Header file for FPU instruction decoding.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_FPU_H
+#define __X86EMU_FPU_H
+
+#ifdef  __cplusplus
+extern "C" {            			/* Use "C" linkage when in C++ mode */
+#endif
+
+/* these have to be defined, whether 8087 support compiled in or not. */
+
+extern void x86emuOp_esc_coprocess_d8 (u8 op1);
+extern void x86emuOp_esc_coprocess_d9 (u8 op1);
+extern void x86emuOp_esc_coprocess_da (u8 op1);
+extern void x86emuOp_esc_coprocess_db (u8 op1);
+extern void x86emuOp_esc_coprocess_dc (u8 op1);
+extern void x86emuOp_esc_coprocess_dd (u8 op1);
+extern void x86emuOp_esc_coprocess_de (u8 op1);
+extern void x86emuOp_esc_coprocess_df (u8 op1);
+
+#ifdef  __cplusplus
+}                       			/* End of "C" linkage for C++   	*/
+#endif
+
+#endif /* __X86EMU_FPU_H */
diff --git a/util/x86emu/x86emu/ops.c b/util/x86emu/x86emu/ops.c
new file mode 100644
index 0000000..a22faf9
--- /dev/null
+++ b/util/x86emu/x86emu/ops.c
@@ -0,0 +1,5474 @@
+/****************************************************************************
+*
+*						Realmode X86 Emulator Library
+*
+*            	Copyright (C) 1991-2004 SciTech Software, Inc.
+* 				     Copyright (C) David Mosberger-Tang
+* 					   Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:		ANSI C
+* Environment:	Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file includes subroutines to implement the decoding
+*               and emulation of all the x86 processor instructions.
+*
+* There are approximately 250 subroutines in here, which correspond
+* to the 256 byte-"opcodes" found on the 8086.  The table which
+* dispatches this is found in the files optab.[ch].
+*
+* Each opcode proc has a comment preceeding it which gives it's table
+* address.  Several opcodes are missing (undefined) in the table.
+*
+* Each proc includes information for decoding (DECODE_PRINTF and
+* DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
+* functions (START_OF_INSTR, END_OF_INSTR).
+*
+* Many of the procedures are *VERY* similar in coding.  This has
+* allowed for a very large amount of code to be generated in a fairly
+* short amount of time (i.e. cut, paste, and modify).  The result is
+* that much of the code below could have been folded into subroutines
+* for a large reduction in size of this file.  The downside would be
+* that there would be a penalty in execution speed.  The file could
+* also have been *MUCH* larger by inlining certain functions which
+* were called.  This could have resulted even faster execution.  The
+* prime directive I used to decide whether to inline the code or to
+* modularize it, was basically: 1) no unnecessary subroutine calls,
+* 2) no routines more than about 200 lines in size, and 3) modularize
+* any code that I might not get right the first time.  The fetch_*
+* subroutines fall into the latter category.  The The decode_* fall
+* into the second category.  The coding of the "switch(mod){ .... }"
+* in many of the subroutines below falls into the first category.
+* Especially, the coding of {add,and,or,sub,...}_{byte,word}
+* subroutines are an especially glaring case of the third guideline.
+* Since so much of the code is cloned from other modules (compare
+* opcode #00 to opcode #01), making the basic operations subroutine
+* calls is especially important; otherwise mistakes in coding an
+* "add" would represent a nightmare in maintenance.
+*
+****************************************************************************/
+
+#include "x86emui.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/* constant arrays to do several instructions in just one function */
+
+#ifdef CONFIG_DEBUG
+static char *x86emu_GenOpName[8] = {
+    "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
+#endif
+
+/* used by several opcodes  */
+static u8 (*genop_byte_operation[])(u8 d, u8 s) =
+{
+    add_byte,           /* 00 */
+    or_byte,            /* 01 */
+    adc_byte,           /* 02 */
+    sbb_byte,           /* 03 */
+    and_byte,           /* 04 */
+    sub_byte,           /* 05 */
+    xor_byte,           /* 06 */
+    cmp_byte,           /* 07 */
+};
+
+static u16 (*genop_word_operation[])(u16 d, u16 s) =
+{
+    add_word,           /*00 */
+    or_word,            /*01 */
+    adc_word,           /*02 */
+    sbb_word,           /*03 */
+    and_word,           /*04 */
+    sub_word,           /*05 */
+    xor_word,           /*06 */
+    cmp_word,           /*07 */
+};
+
+static u32 (*genop_long_operation[])(u32 d, u32 s) =
+{
+    add_long,           /*00 */
+    or_long,            /*01 */
+    adc_long,           /*02 */
+    sbb_long,           /*03 */
+    and_long,           /*04 */
+    sub_long,           /*05 */
+    xor_long,           /*06 */
+    cmp_long,           /*07 */
+};
+
+/* used by opcodes 80, c0, d0, and d2. */
+static u8(*opcD0_byte_operation[])(u8 d, u8 s) =
+{
+    rol_byte,
+    ror_byte,
+    rcl_byte,
+    rcr_byte,
+    shl_byte,
+    shr_byte,
+    shl_byte,           /* sal_byte === shl_byte  by definition */
+    sar_byte,
+};
+
+/* used by opcodes c1, d1, and d3. */
+static u16(*opcD1_word_operation[])(u16 s, u8 d) =
+{
+    rol_word,
+    ror_word,
+    rcl_word,
+    rcr_word,
+    shl_word,
+    shr_word,
+    shl_word,           /* sal_byte === shl_byte  by definition */
+    sar_word,
+};
+
+/* used by opcodes c1, d1, and d3. */
+static u32 (*opcD1_long_operation[])(u32 s, u8 d) =
+{
+    rol_long,
+    ror_long,
+    rcl_long,
+    rcr_long,
+    shl_long,
+    shr_long,
+    shl_long,           /* sal_byte === shl_byte  by definition */
+    sar_long,
+};
+
+#ifdef CONFIG_DEBUG
+
+static char *opF6_names[8] =
+  { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
+
+#endif
+
+/****************************************************************************
+PARAMETERS:
+op1 - Instruction op code
+
+REMARKS:
+Handles illegal opcodes.
+****************************************************************************/
+void x86emuOp_illegal_op(
+    u8 op1)
+{
+    START_OF_INSTR();
+    if (M.x86.R_SP != 0) {
+        DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
+        TRACE_REGS();
+        DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
+            M.x86.R_CS, M.x86.R_IP-1,op1));
+        HALT_SYS();
+        }
+    else {
+        /* If we get here, it means the stack pointer is back to zero
+         * so we are just returning from an emulator service call
+         * so therte is no need to display an error message. We trap
+         * the emulator with an 0xF1 opcode to finish the service
+         * call.
+         */
+        X86EMU_halt_sys();
+        }
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
+****************************************************************************/
+void x86emuOp_genop_byte_RM_R(u8 op1)
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 *destreg, *srcreg;
+    u8 destval;
+
+    op1 = (op1 >> 3) & 0x7;
+
+    START_OF_INSTR();
+    DECODE_PRINTF(x86emu_GenOpName[op1]);
+    DECODE_PRINTF("\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if(mod<3)
+        { destoffset = decode_rmXX_address(mod,rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = genop_byte_operation[op1](destval, *srcreg);
+        if (op1 != 7)
+            store_data_byte(destoffset, destval);
+        }
+    else
+        {                       /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = genop_byte_operation[op1](*destreg, *srcreg);
+        }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
+****************************************************************************/
+void x86emuOp_genop_word_RM_R(u8 op1)
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    op1 = (op1 >> 3) & 0x7;
+
+    START_OF_INSTR();
+    DECODE_PRINTF(x86emu_GenOpName[op1]);
+    DECODE_PRINTF("\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+
+    if(mod<3) {
+        destoffset = decode_rmXX_address(mod,rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = genop_long_operation[op1](destval, *srcreg);
+            if (op1 != 7)
+                store_data_long(destoffset, destval);
+        } else {
+            u16 destval;
+            u16 *srcreg;
+
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = genop_word_operation[op1](destval, *srcreg);
+            if (op1 != 7)
+                store_data_word(destoffset, destval);
+        }
+    } else {                    /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg, *srcreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = genop_long_operation[op1](*destreg, *srcreg);
+        } else {
+            u16 *destreg, *srcreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = genop_word_operation[op1](*destreg, *srcreg);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
+****************************************************************************/
+void x86emuOp_genop_byte_R_RM(u8 op1)
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint srcoffset;
+    u8 srcval;
+
+    op1 = (op1 >> 3) & 0x7;
+
+    START_OF_INSTR();
+    DECODE_PRINTF(x86emu_GenOpName[op1]);
+    DECODE_PRINTF("\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rmXX_address(mod,rl);
+        srcval = fetch_data_byte(srcoffset);
+    } else {     /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rl);
+        srcval = *srcreg;
+    }
+    DECODE_PRINTF("\n");
+    TRACE_AND_STEP();
+    *destreg = genop_byte_operation[op1](*destreg, srcval);
+
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
+****************************************************************************/
+void x86emuOp_genop_word_R_RM(u8 op1)
+{
+    int mod, rl, rh;
+    uint srcoffset;
+    u32 *destreg32, srcval;
+    u16 *destreg;
+
+    op1 = (op1 >> 3) & 0x7;
+
+    START_OF_INSTR();
+    DECODE_PRINTF(x86emu_GenOpName[op1]);
+    DECODE_PRINTF("\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        srcoffset = decode_rmXX_address(mod,rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            destreg32 = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg32 = genop_long_operation[op1](*destreg32, srcval);
+        } else {
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = genop_word_operation[op1](*destreg, srcval);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg;
+            destreg32 = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
+        } else {
+            u16 *srcreg;
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = genop_word_operation[op1](*destreg, *srcreg);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
+****************************************************************************/
+void x86emuOp_genop_byte_AL_IMM(u8 op1)
+{
+    u8 srcval;
+
+    op1 = (op1 >> 3) & 0x7;
+
+    START_OF_INSTR();
+    DECODE_PRINTF(x86emu_GenOpName[op1]);
+    DECODE_PRINTF("\tAL,");
+    srcval = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
+****************************************************************************/
+void x86emuOp_genop_word_AX_IMM(u8 op1)
+{
+    u32 srcval;
+
+    op1 = (op1 >> 3) & 0x7;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF(x86emu_GenOpName[op1]);
+        DECODE_PRINTF("\tEAX,");
+        srcval = fetch_long_imm();
+    } else {
+        DECODE_PRINTF(x86emu_GenOpName[op1]);
+        DECODE_PRINTF("\tAX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
+    } else {
+        M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x06
+****************************************************************************/
+void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("PUSH\tES\n");
+    TRACE_AND_STEP();
+    push_word(M.x86.R_ES);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x07
+****************************************************************************/
+void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("POP\tES\n");
+    TRACE_AND_STEP();
+    M.x86.R_ES = pop_word();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0e
+****************************************************************************/
+void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("PUSH\tCS\n");
+    TRACE_AND_STEP();
+    push_word(M.x86.R_CS);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
+****************************************************************************/
+void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
+{
+    u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+    INC_DECODED_INST_LEN(1);
+    (*x86emu_optab2[op2])(op2);
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x16
+****************************************************************************/
+void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("PUSH\tSS\n");
+    TRACE_AND_STEP();
+    push_word(M.x86.R_SS);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x17
+****************************************************************************/
+void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("POP\tSS\n");
+    TRACE_AND_STEP();
+    M.x86.R_SS = pop_word();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1e
+****************************************************************************/
+void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("PUSH\tDS\n");
+    TRACE_AND_STEP();
+    push_word(M.x86.R_DS);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1f
+****************************************************************************/
+void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("POP\tDS\n");
+    TRACE_AND_STEP();
+    M.x86.R_DS = pop_word();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x26
+****************************************************************************/
+void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("ES:\n");
+    TRACE_AND_STEP();
+    M.x86.mode |= SYSMODE_SEGOVR_ES;
+    /*
+     * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
+     * opcode subroutines we do not want to do this.
+     */
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x27
+****************************************************************************/
+void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("DAA\n");
+    TRACE_AND_STEP();
+    M.x86.R_AL = daa_byte(M.x86.R_AL);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2e
+****************************************************************************/
+void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("CS:\n");
+    TRACE_AND_STEP();
+    M.x86.mode |= SYSMODE_SEGOVR_CS;
+    /* note no DECODE_CLEAR_SEGOVR here. */
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2f
+****************************************************************************/
+void x86emuOp_das(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("DAS\n");
+    TRACE_AND_STEP();
+    M.x86.R_AL = das_byte(M.x86.R_AL);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x36
+****************************************************************************/
+void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("SS:\n");
+    TRACE_AND_STEP();
+    M.x86.mode |= SYSMODE_SEGOVR_SS;
+    /* no DECODE_CLEAR_SEGOVR ! */
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x37
+****************************************************************************/
+void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("AAA\n");
+    TRACE_AND_STEP();
+    M.x86.R_AX = aaa_word(M.x86.R_AX);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3e
+****************************************************************************/
+void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("DS:\n");
+    TRACE_AND_STEP();
+    M.x86.mode |= SYSMODE_SEGOVR_DS;
+    /* NO DECODE_CLEAR_SEGOVR! */
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3f
+****************************************************************************/
+void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("AAS\n");
+    TRACE_AND_STEP();
+    M.x86.R_AX = aas_word(M.x86.R_AX);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x40 - 0x47
+****************************************************************************/
+void x86emuOp_inc_register(u8 op1)
+{
+    START_OF_INSTR();
+    op1 &= 0x7;
+    DECODE_PRINTF("INC\t");
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        u32 *reg;
+        reg = DECODE_RM_LONG_REGISTER(op1);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *reg = inc_long(*reg);
+    } else {
+        u16 *reg;
+        reg = DECODE_RM_WORD_REGISTER(op1);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *reg = inc_word(*reg);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x48 - 0x4F
+****************************************************************************/
+void x86emuOp_dec_register(u8 op1)
+{
+    START_OF_INSTR();
+    op1 &= 0x7;
+    DECODE_PRINTF("DEC\t");
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        u32 *reg;
+        reg = DECODE_RM_LONG_REGISTER(op1);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *reg = dec_long(*reg);
+    } else {
+        u16 *reg;
+        reg = DECODE_RM_WORD_REGISTER(op1);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *reg = dec_word(*reg);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x50 - 0x57
+****************************************************************************/
+void x86emuOp_push_register(u8 op1)
+{
+    START_OF_INSTR();
+    op1 &= 0x7;
+    DECODE_PRINTF("PUSH\t");
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        u32 *reg;
+        reg = DECODE_RM_LONG_REGISTER(op1);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        push_long(*reg);
+    } else {
+        u16 *reg;
+        reg = DECODE_RM_WORD_REGISTER(op1);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        push_word(*reg);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x58 - 0x5F
+****************************************************************************/
+void x86emuOp_pop_register(u8 op1)
+{
+    START_OF_INSTR();
+    op1 &= 0x7;
+    DECODE_PRINTF("POP\t");
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        u32 *reg;
+        reg = DECODE_RM_LONG_REGISTER(op1);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *reg = pop_long();
+    } else {
+        u16 *reg;
+        reg = DECODE_RM_WORD_REGISTER(op1);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *reg = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x60
+****************************************************************************/
+void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("PUSHAD\n");
+    } else {
+        DECODE_PRINTF("PUSHA\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        u32 old_sp = M.x86.R_ESP;
+
+        push_long(M.x86.R_EAX);
+        push_long(M.x86.R_ECX);
+        push_long(M.x86.R_EDX);
+        push_long(M.x86.R_EBX);
+        push_long(old_sp);
+        push_long(M.x86.R_EBP);
+        push_long(M.x86.R_ESI);
+        push_long(M.x86.R_EDI);
+    } else {
+        u16 old_sp = M.x86.R_SP;
+
+        push_word(M.x86.R_AX);
+        push_word(M.x86.R_CX);
+        push_word(M.x86.R_DX);
+        push_word(M.x86.R_BX);
+        push_word(old_sp);
+        push_word(M.x86.R_BP);
+        push_word(M.x86.R_SI);
+        push_word(M.x86.R_DI);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x61
+****************************************************************************/
+void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("POPAD\n");
+    } else {
+        DECODE_PRINTF("POPA\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EDI = pop_long();
+        M.x86.R_ESI = pop_long();
+        M.x86.R_EBP = pop_long();
+        M.x86.R_ESP += 4;              /* skip ESP */
+        M.x86.R_EBX = pop_long();
+        M.x86.R_EDX = pop_long();
+        M.x86.R_ECX = pop_long();
+        M.x86.R_EAX = pop_long();
+    } else {
+        M.x86.R_DI = pop_word();
+        M.x86.R_SI = pop_word();
+        M.x86.R_BP = pop_word();
+        M.x86.R_SP += 2;               /* skip SP */
+        M.x86.R_BX = pop_word();
+        M.x86.R_DX = pop_word();
+        M.x86.R_CX = pop_word();
+        M.x86.R_AX = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/*opcode 0x62   ILLEGAL OP, calls x86emuOp_illegal_op() */
+/*opcode 0x63   ILLEGAL OP, calls x86emuOp_illegal_op() */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x64
+****************************************************************************/
+void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("FS:\n");
+    TRACE_AND_STEP();
+    M.x86.mode |= SYSMODE_SEGOVR_FS;
+    /*
+     * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
+     * opcode subroutines we do not want to do this.
+     */
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x65
+****************************************************************************/
+void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("GS:\n");
+    TRACE_AND_STEP();
+    M.x86.mode |= SYSMODE_SEGOVR_GS;
+    /*
+     * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
+     * opcode subroutines we do not want to do this.
+     */
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x66 - prefix for 32-bit register
+****************************************************************************/
+void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("DATA:\n");
+    TRACE_AND_STEP();
+    M.x86.mode |= SYSMODE_PREFIX_DATA;
+    /* note no DECODE_CLEAR_SEGOVR here. */
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x67 - prefix for 32-bit address
+****************************************************************************/
+void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("ADDR:\n");
+    TRACE_AND_STEP();
+    M.x86.mode |= SYSMODE_PREFIX_ADDR;
+    /* note no DECODE_CLEAR_SEGOVR here. */
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x68
+****************************************************************************/
+void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 imm;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        imm = fetch_long_imm();
+    } else {
+        imm = fetch_word_imm();
+    }
+    DECODE_PRINTF2("PUSH\t%x\n", imm);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(imm);
+    } else {
+        push_word((u16)imm);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x69
+****************************************************************************/
+void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("IMUL\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        srcoffset = decode_rmXX_address(mod, rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+            u32 res_lo,res_hi;
+            s32 imm;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcval = fetch_data_long(srcoffset);
+            imm = fetch_long_imm();
+            DECODE_PRINTF2(",%d\n", (s32)imm);
+            TRACE_AND_STEP();
+            imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+            if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
+                (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            *destreg = (u32)res_lo;
+        } else {
+            u16 *destreg;
+            u16 srcval;
+            u32 res;
+            s16 imm;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcval = fetch_data_word(srcoffset);
+            imm = fetch_word_imm();
+            DECODE_PRINTF2(",%d\n", (s32)imm);
+            TRACE_AND_STEP();
+            res = (s16)srcval * (s16)imm;
+            if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
+                (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            *destreg = (u16)res;
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg,*srcreg;
+            u32 res_lo,res_hi;
+            s32 imm;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            imm = fetch_long_imm();
+            DECODE_PRINTF2(",%d\n", (s32)imm);
+            TRACE_AND_STEP();
+            imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
+            if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
+                (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            *destreg = (u32)res_lo;
+        } else {
+            u16 *destreg,*srcreg;
+            u32 res;
+            s16 imm;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            imm = fetch_word_imm();
+            DECODE_PRINTF2(",%d\n", (s32)imm);
+            res = (s16)*srcreg * (s16)imm;
+            if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
+                (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            *destreg = (u16)res;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6a
+****************************************************************************/
+void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
+{
+    s16 imm;
+
+    START_OF_INSTR();
+    imm = (s8)fetch_byte_imm();
+    DECODE_PRINTF2("PUSH\t%d\n", imm);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(imm);
+    } else {
+        push_word(imm);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6b
+****************************************************************************/
+void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+    s8  imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("IMUL\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        srcoffset = decode_rmXX_address(mod, rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+            u32 res_lo,res_hi;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcval = fetch_data_long(srcoffset);
+            imm = fetch_byte_imm();
+            DECODE_PRINTF2(",%d\n", (s32)imm);
+            TRACE_AND_STEP();
+            imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+            if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
+                (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            *destreg = (u32)res_lo;
+        } else {
+            u16 *destreg;
+            u16 srcval;
+            u32 res;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcval = fetch_data_word(srcoffset);
+            imm = fetch_byte_imm();
+            DECODE_PRINTF2(",%d\n", (s32)imm);
+            TRACE_AND_STEP();
+            res = (s16)srcval * (s16)imm;
+            if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
+                (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            *destreg = (u16)res;
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg,*srcreg;
+            u32 res_lo,res_hi;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            imm = fetch_byte_imm();
+            DECODE_PRINTF2(",%d\n", (s32)imm);
+            TRACE_AND_STEP();
+            imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
+            if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
+                (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            *destreg = (u32)res_lo;
+        } else {
+            u16 *destreg,*srcreg;
+            u32 res;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            imm = fetch_byte_imm();
+            DECODE_PRINTF2(",%d\n", (s32)imm);
+            TRACE_AND_STEP();
+            res = (s16)*srcreg * (s16)imm;
+            if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
+                (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            *destreg = (u16)res;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6c
+****************************************************************************/
+void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("INSB\n");
+    ins(1);
+    TRACE_AND_STEP();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6d
+****************************************************************************/
+void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("INSD\n");
+        ins(4);
+    } else {
+        DECODE_PRINTF("INSW\n");
+        ins(2);
+    }
+    TRACE_AND_STEP();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6e
+****************************************************************************/
+void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("OUTSB\n");
+    outs(1);
+    TRACE_AND_STEP();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6f
+****************************************************************************/
+void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("OUTSD\n");
+        outs(4);
+    } else {
+        DECODE_PRINTF("OUTSW\n");
+        outs(2);
+    }
+    TRACE_AND_STEP();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x70 - 0x7F
+****************************************************************************/
+int x86emu_check_jump_condition(u8 op);
+
+void x86emuOp_jump_near_cond(u8 op1)
+{
+    s8 offset;
+    u16 target;
+    int cond;
+
+    /* jump to byte offset if overflow flag is set */
+    START_OF_INSTR();
+    cond = x86emu_check_jump_condition(op1 & 0xF);
+    offset = (s8)fetch_byte_imm();
+    target = (u16)(M.x86.R_IP + (s16)offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (cond) {
+        M.x86.R_IP = target;
+	JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " NEAR COND ");
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x80
+****************************************************************************/
+void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg;
+    uint destoffset;
+    u8 imm;
+    u8 destval;
+
+    /*
+     * Weirdo special case instruction format.  Part of the opcode
+     * held below in "RH".  Doubly nested case would result, except
+     * that the decoded instruction
+     */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (DEBUG_DECODE()) {
+        /* XXX DECODE_PRINTF may be changed to something more
+           general, so that it is important to leave the strings
+           in the same format, even though the result is that the
+           above test is done twice. */
+
+        switch (rh) {
+        case 0:
+            DECODE_PRINTF("ADD\t");
+            break;
+        case 1:
+            DECODE_PRINTF("OR\t");
+            break;
+        case 2:
+            DECODE_PRINTF("ADC\t");
+            break;
+        case 3:
+            DECODE_PRINTF("SBB\t");
+            break;
+        case 4:
+            DECODE_PRINTF("AND\t");
+            break;
+        case 5:
+            DECODE_PRINTF("SUB\t");
+            break;
+        case 6:
+            DECODE_PRINTF("XOR\t");
+            break;
+        case 7:
+            DECODE_PRINTF("CMP\t");
+            break;
+        }
+    }
+#endif
+    /* know operation, decode the mod byte to find the addressing
+       mode. */
+    if (mod < 3) {
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2("%x\n", imm);
+        TRACE_AND_STEP();
+        destval = (*genop_byte_operation[rh]) (destval, imm);
+        if (rh != 7)
+            store_data_byte(destoffset, destval);
+    } else {                     /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2("%x\n", imm);
+        TRACE_AND_STEP();
+        *destreg = (*genop_byte_operation[rh]) (*destreg, imm);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x81
+****************************************************************************/
+void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    /*
+     * Weirdo special case instruction format.  Part of the opcode
+     * held below in "RH".  Doubly nested case would result, except
+     * that the decoded instruction
+     */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (DEBUG_DECODE()) {
+        /* XXX DECODE_PRINTF may be changed to something more
+           general, so that it is important to leave the strings
+           in the same format, even though the result is that the
+           above test is done twice. */
+
+        switch (rh) {
+        case 0:
+            DECODE_PRINTF("ADD\t");
+            break;
+        case 1:
+            DECODE_PRINTF("OR\t");
+            break;
+        case 2:
+            DECODE_PRINTF("ADC\t");
+            break;
+        case 3:
+            DECODE_PRINTF("SBB\t");
+            break;
+        case 4:
+            DECODE_PRINTF("AND\t");
+            break;
+        case 5:
+            DECODE_PRINTF("SUB\t");
+            break;
+        case 6:
+            DECODE_PRINTF("XOR\t");
+            break;
+        case 7:
+            DECODE_PRINTF("CMP\t");
+            break;
+        }
+    }
+#endif
+    /*
+     * Know operation, decode the mod byte to find the addressing
+     * mode.
+     */
+    if (mod < 3) {
+        DECODE_PRINTF("DWORD PTR ");
+        destoffset = decode_rmXX_address(mod, rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval,imm;
+
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            imm = fetch_long_imm();
+            DECODE_PRINTF2("%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*genop_long_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_long(destoffset, destval);
+        } else {
+            u16 destval,imm;
+
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            imm = fetch_word_imm();
+            DECODE_PRINTF2("%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*genop_word_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_word(destoffset, destval);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg, imm;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            imm = fetch_long_imm();
+            DECODE_PRINTF2("%x\n", imm);
+            TRACE_AND_STEP();
+            *destreg = (*genop_long_operation[rh]) (*destreg, imm);
+        } else {
+            u16 *destreg, imm;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            imm = fetch_word_imm();
+            DECODE_PRINTF2("%x\n", imm);
+            TRACE_AND_STEP();
+            *destreg = (*genop_word_operation[rh]) (*destreg, imm);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x82
+****************************************************************************/
+void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg;
+    uint destoffset;
+    u8 imm;
+    u8 destval;
+
+    /*
+     * Weirdo special case instruction format.  Part of the opcode
+     * held below in "RH".  Doubly nested case would result, except
+     * that the decoded instruction Similar to opcode 81, except that
+     * the immediate byte is sign extended to a word length.
+     */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (DEBUG_DECODE()) {
+        /* XXX DECODE_PRINTF may be changed to something more
+           general, so that it is important to leave the strings
+           in the same format, even though the result is that the
+           above test is done twice. */
+        switch (rh) {
+        case 0:
+            DECODE_PRINTF("ADD\t");
+            break;
+        case 1:
+            DECODE_PRINTF("OR\t");
+            break;
+        case 2:
+            DECODE_PRINTF("ADC\t");
+            break;
+        case 3:
+            DECODE_PRINTF("SBB\t");
+            break;
+        case 4:
+            DECODE_PRINTF("AND\t");
+            break;
+        case 5:
+            DECODE_PRINTF("SUB\t");
+            break;
+        case 6:
+            DECODE_PRINTF("XOR\t");
+            break;
+        case 7:
+            DECODE_PRINTF("CMP\t");
+            break;
+        }
+    }
+#endif
+    /* know operation, decode the mod byte to find the addressing
+       mode. */
+    if (mod < 3) {
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rmXX_address(mod, rl);
+        destval = fetch_data_byte(destoffset);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2(",%x\n", imm);
+        TRACE_AND_STEP();
+        destval = (*genop_byte_operation[rh]) (destval, imm);
+        if (rh != 7)
+            store_data_byte(destoffset, destval);
+    } else {                     /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2(",%x\n", imm);
+        TRACE_AND_STEP();
+        *destreg = (*genop_byte_operation[rh]) (*destreg, imm);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x83
+****************************************************************************/
+void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    /*
+     * Weirdo special case instruction format.  Part of the opcode
+     * held below in "RH".  Doubly nested case would result, except
+     * that the decoded instruction Similar to opcode 81, except that
+     * the immediate byte is sign extended to a word length.
+     */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (DEBUG_DECODE()) {
+        /* XXX DECODE_PRINTF may be changed to something more
+           general, so that it is important to leave the strings
+           in the same format, even though the result is that the
+           above test is done twice. */
+       switch (rh) {
+        case 0:
+            DECODE_PRINTF("ADD\t");
+            break;
+        case 1:
+            DECODE_PRINTF("OR\t");
+            break;
+        case 2:
+            DECODE_PRINTF("ADC\t");
+            break;
+        case 3:
+            DECODE_PRINTF("SBB\t");
+            break;
+        case 4:
+            DECODE_PRINTF("AND\t");
+            break;
+        case 5:
+            DECODE_PRINTF("SUB\t");
+            break;
+        case 6:
+            DECODE_PRINTF("XOR\t");
+            break;
+        case 7:
+            DECODE_PRINTF("CMP\t");
+            break;
+        }
+    }
+#endif
+    /* know operation, decode the mod byte to find the addressing
+       mode. */
+    if (mod < 3) {
+        DECODE_PRINTF("DWORD PTR ");
+        destoffset = decode_rmXX_address(mod,rl);
+
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval,imm;
+
+            destval = fetch_data_long(destoffset);
+            imm = (s8) fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*genop_long_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_long(destoffset, destval);
+        } else {
+            u16 destval,imm;
+
+            destval = fetch_data_word(destoffset);
+            imm = (s8) fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*genop_word_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_word(destoffset, destval);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg, imm;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            imm = (s8) fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            *destreg = (*genop_long_operation[rh]) (*destreg, imm);
+        } else {
+            u16 *destreg, imm;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            imm = (s8) fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            *destreg = (*genop_word_operation[rh]) (*destreg, imm);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x84
+****************************************************************************/
+void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint destoffset;
+    u8 destval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("TEST\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        test_byte(destval, *srcreg);
+    } else {                     /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        test_byte(*destreg, *srcreg);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x85
+****************************************************************************/
+void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("TEST\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            test_long(destval, *srcreg);
+        } else {
+            u16 destval;
+            u16 *srcreg;
+
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            test_word(destval, *srcreg);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg,*srcreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            test_long(*destreg, *srcreg);
+        } else {
+            u16 *destreg,*srcreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            test_word(*destreg, *srcreg);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x86
+****************************************************************************/
+void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint destoffset;
+    u8 destval;
+    u8 tmp;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("XCHG\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        tmp = *srcreg;
+        *srcreg = destval;
+        destval = tmp;
+        store_data_byte(destoffset, destval);
+    } else {                     /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        tmp = *srcreg;
+        *srcreg = *destreg;
+        *destreg = tmp;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x87
+****************************************************************************/
+void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("XCHG\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",");
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg;
+            u32 destval,tmp;
+
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            tmp = *srcreg;
+            *srcreg = destval;
+            destval = tmp;
+            store_data_long(destoffset, destval);
+        } else {
+            u16 *srcreg;
+            u16 destval,tmp;
+
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            tmp = *srcreg;
+            *srcreg = destval;
+            destval = tmp;
+            store_data_word(destoffset, destval);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg,*srcreg;
+            u32 tmp;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            tmp = *srcreg;
+            *srcreg = *destreg;
+            *destreg = tmp;
+        } else {
+            u16 *destreg,*srcreg;
+            u16 tmp;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            tmp = *srcreg;
+            *srcreg = *destreg;
+            *destreg = tmp;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x88
+****************************************************************************/
+void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        store_data_byte(destoffset, *srcreg);
+    } else {                     /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = *srcreg;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x89
+****************************************************************************/
+void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg;
+
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            store_data_long(destoffset, *srcreg);
+        } else {
+            u16 *srcreg;
+
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            store_data_word(destoffset, *srcreg);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg,*srcreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = *srcreg;
+        } else {
+            u16 *destreg,*srcreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = *srcreg;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8a
+****************************************************************************/
+void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint srcoffset;
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rmXX_address(mod, rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+    } else {                     /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = *srcreg;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8b
+****************************************************************************/
+void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rmXX_address(mod, rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        } else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rmXX_address(mod, rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg, *srcreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = *srcreg;
+        } else {
+            u16 *destreg, *srcreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = *srcreg;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8c
+****************************************************************************/
+void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u16 *destreg, *srcreg;
+    uint destoffset;
+    u16 destval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",");
+        srcreg = decode_rm_seg_register(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = *srcreg;
+        store_data_word(destoffset, destval);
+    } else {                     /* register to register */
+        destreg = DECODE_RM_WORD_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = decode_rm_seg_register(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = *srcreg;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8d
+****************************************************************************/
+void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u16 *srcreg;
+    uint destoffset;
+
+/*
+ * TODO: Need to handle address size prefix!
+ *
+ * lea  eax,[eax+ebx*2] ??
+ */
+
+    START_OF_INSTR();
+    DECODE_PRINTF("LEA\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        srcreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        destoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *srcreg = (u16)destoffset;
+        }
+    /* } else { undefined.  Do nothing. } */
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8e
+****************************************************************************/
+void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u16 *destreg, *srcreg;
+    uint srcoffset;
+    u16 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destreg = decode_rm_seg_register(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rmXX_address(mod, rl);
+        srcval = fetch_data_word(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+    } else {                     /* register to register */
+        destreg = decode_rm_seg_register(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_WORD_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = *srcreg;
+    }
+    /*
+     * Clean up, and reset all the R_xSP pointers to the correct
+     * locations.  This is about 3x too much overhead (doing all the
+     * segreg ptrs when only one is needed, but this instruction
+     * *cannot* be that common, and this isn't too much work anyway.
+     */
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8f
+****************************************************************************/
+void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("POP\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (rh != 0) {
+        DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
+        HALT_SYS();
+    }
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = pop_long();
+            store_data_long(destoffset, destval);
+        } else {
+            u16 destval;
+
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = pop_word();
+            store_data_word(destoffset, destval);
+        }
+    } else {                    /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = pop_long();
+        } else {
+            u16 *destreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = pop_word();
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x90
+****************************************************************************/
+void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("NOP\n");
+    TRACE_AND_STEP();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x91-0x97
+****************************************************************************/
+void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
+{
+    u32 tmp;
+
+    op1 &= 0x7;
+
+    START_OF_INSTR();
+
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        u32 *reg32;
+        DECODE_PRINTF("XCHG\tEAX,");
+        reg32 = DECODE_RM_LONG_REGISTER(op1);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        tmp = M.x86.R_EAX;
+        M.x86.R_EAX = *reg32;
+        *reg32 = tmp;
+    } else {
+        u16 *reg16;
+        DECODE_PRINTF("XCHG\tAX,");
+        reg16 = DECODE_RM_WORD_REGISTER(op1);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        tmp = M.x86.R_AX;
+        M.x86.R_AX = *reg16;
+        *reg16 = (u16)tmp;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x98
+****************************************************************************/
+void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("CWDE\n");
+    } else {
+        DECODE_PRINTF("CBW\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        if (M.x86.R_AX & 0x8000) {
+            M.x86.R_EAX |= 0xffff0000;
+        } else {
+            M.x86.R_EAX &= 0x0000ffff;
+        }
+    } else {
+        if (M.x86.R_AL & 0x80) {
+            M.x86.R_AH = 0xff;
+        } else {
+            M.x86.R_AH = 0x0;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x99
+****************************************************************************/
+void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("CDQ\n");
+    } else {
+        DECODE_PRINTF("CWD\n");
+    }
+    DECODE_PRINTF("CWD\n");
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        if (M.x86.R_EAX & 0x80000000) {
+            M.x86.R_EDX = 0xffffffff;
+        } else {
+            M.x86.R_EDX = 0x0;
+        }
+    } else {
+        if (M.x86.R_AX & 0x8000) {
+            M.x86.R_DX = 0xffff;
+        } else {
+            M.x86.R_DX = 0x0;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9a
+****************************************************************************/
+void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u16 farseg, faroff;
+
+    START_OF_INSTR();
+	DECODE_PRINTF("CALL\t");
+	faroff = fetch_word_imm();
+	farseg = fetch_word_imm();
+	DECODE_PRINTF2("%04x:", farseg);
+	DECODE_PRINTF2("%04x\n", faroff);
+	CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
+
+    /* XXX
+     *
+     * Hooked interrupt vectors calling into our "BIOS" will cause
+     * problems unless all intersegment stuff is checked for BIOS
+     * access.  Check needed here.  For moment, let it alone.
+     */
+    TRACE_AND_STEP();
+    push_word(M.x86.R_CS);
+    M.x86.R_CS = farseg;
+    push_word(M.x86.R_IP);
+    M.x86.R_IP = faroff;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9b
+****************************************************************************/
+void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("WAIT");
+    TRACE_AND_STEP();
+    /* NADA.  */
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9c
+****************************************************************************/
+void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
+{
+    u32 flags;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("PUSHFD\n");
+    } else {
+        DECODE_PRINTF("PUSHF\n");
+    }
+    TRACE_AND_STEP();
+
+    /* clear out *all* bits not representing flags, and turn on real bits */
+    flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(flags);
+    } else {
+        push_word((u16)flags);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9d
+****************************************************************************/
+void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("POPFD\n");
+    } else {
+        DECODE_PRINTF("POPF\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EFLG = pop_long();
+    } else {
+        M.x86.R_FLG = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9e
+****************************************************************************/
+void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("SAHF\n");
+    TRACE_AND_STEP();
+    /* clear the lower bits of the flag register */
+    M.x86.R_FLG &= 0xffffff00;
+    /* or in the AH register into the flags register */
+    M.x86.R_FLG |= M.x86.R_AH;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9f
+****************************************************************************/
+void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("LAHF\n");
+    TRACE_AND_STEP();
+	M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
+    /*undocumented TC++ behavior??? Nope.  It's documented, but
+       you have too look real hard to notice it. */
+    M.x86.R_AH |= 0x2;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa0
+****************************************************************************/
+void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u16 offset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\tAL,");
+    offset = fetch_word_imm();
+    DECODE_PRINTF2("[%04x]\n", offset);
+    TRACE_AND_STEP();
+    M.x86.R_AL = fetch_data_byte(offset);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa1
+****************************************************************************/
+void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u16 offset;
+
+    START_OF_INSTR();
+    offset = fetch_word_imm();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
+    } else {
+        DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = fetch_data_long(offset);
+    } else {
+        M.x86.R_AX = fetch_data_word(offset);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa2
+****************************************************************************/
+void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u16 offset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\t");
+    offset = fetch_word_imm();
+    DECODE_PRINTF2("[%04x],AL\n", offset);
+    TRACE_AND_STEP();
+    store_data_byte(offset, M.x86.R_AL);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa3
+****************************************************************************/
+void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u16 offset;
+
+    START_OF_INSTR();
+    offset = fetch_word_imm();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
+    } else {
+        DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        store_data_long(offset, M.x86.R_EAX);
+    } else {
+        store_data_word(offset, M.x86.R_AX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa4
+****************************************************************************/
+void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
+{
+    u8  val;
+    u32 count;
+    int inc;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOVS\tBYTE\n");
+    if (ACCESS_FLAG(F_DF))   /* down */
+        inc = -1;
+    else
+        inc = 1;
+    TRACE_AND_STEP();
+    count = 1;
+    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+        /* dont care whether REPE or REPNE */
+        /* move them until (E)CX is ZERO. */
+        count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
+        M.x86.R_CX = 0;
+	if (M.x86.mode & SYSMODE_32BIT_REP)
+            M.x86.R_ECX = 0;
+        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+    }
+    while (count--) {
+        val = fetch_data_byte(M.x86.R_SI);
+        store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
+        M.x86.R_SI += inc;
+        M.x86.R_DI += inc;
+        if (M.x86.intr & INTR_HALTED)
+            break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa5
+****************************************************************************/
+void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
+{
+    u32 val;
+    int inc;
+    u32 count;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("MOVS\tDWORD\n");
+        if (ACCESS_FLAG(F_DF))      /* down */
+            inc = -4;
+        else
+            inc = 4;
+    } else {
+        DECODE_PRINTF("MOVS\tWORD\n");
+        if (ACCESS_FLAG(F_DF))      /* down */
+            inc = -2;
+        else
+            inc = 2;
+    }
+    TRACE_AND_STEP();
+    count = 1;
+    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+        /* dont care whether REPE or REPNE */
+        /* move them until (E)CX is ZERO. */
+        count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
+        M.x86.R_CX = 0;
+	if (M.x86.mode & SYSMODE_32BIT_REP)
+            M.x86.R_ECX = 0;
+        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+    }
+    while (count--) {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            val = fetch_data_long(M.x86.R_SI);
+            store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
+        } else {
+            val = fetch_data_word(M.x86.R_SI);
+            store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
+        }
+        M.x86.R_SI += inc;
+        M.x86.R_DI += inc;
+        if (M.x86.intr & INTR_HALTED)
+            break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa6
+****************************************************************************/
+void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
+{
+    s8 val1, val2;
+    int inc;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("CMPS\tBYTE\n");
+    TRACE_AND_STEP();
+    if (ACCESS_FLAG(F_DF))   /* down */
+        inc = -1;
+    else
+        inc = 1;
+
+    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+        /* REPE  */
+        /* move them until (E)CX is ZERO. */
+        while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
+            val1 = fetch_data_byte(M.x86.R_SI);
+            val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+                     cmp_byte(val1, val2);
+            if (M.x86.mode & SYSMODE_32BIT_REP)
+                M.x86.R_ECX -= 1;
+            else
+                M.x86.R_CX -= 1;
+            M.x86.R_SI += inc;
+            M.x86.R_DI += inc;
+            if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
+            if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
+            if (M.x86.intr & INTR_HALTED)
+                break;
+        }
+        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+    } else {
+        val1 = fetch_data_byte(M.x86.R_SI);
+        val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+        cmp_byte(val1, val2);
+        M.x86.R_SI += inc;
+        M.x86.R_DI += inc;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa7
+****************************************************************************/
+void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
+{
+    u32 val1,val2;
+    int inc;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("CMPS\tDWORD\n");
+        inc = 4;
+    } else {
+        DECODE_PRINTF("CMPS\tWORD\n");
+        inc = 2;
+    }
+    if (ACCESS_FLAG(F_DF))   /* down */
+        inc = -inc;
+
+    TRACE_AND_STEP();
+    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+        /* REPE  */
+        /* move them until (E)CX is ZERO. */
+        while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                val1 = fetch_data_long(M.x86.R_SI);
+                val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+                cmp_long(val1, val2);
+            } else {
+                val1 = fetch_data_word(M.x86.R_SI);
+                val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+                cmp_word((u16)val1, (u16)val2);
+            }
+            if (M.x86.mode & SYSMODE_32BIT_REP)
+                M.x86.R_ECX -= 1;
+            else
+                M.x86.R_CX -= 1;
+            M.x86.R_SI += inc;
+            M.x86.R_DI += inc;
+            if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
+            if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
+            if (M.x86.intr & INTR_HALTED)
+                break;
+        }
+        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+    } else {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            val1 = fetch_data_long(M.x86.R_SI);
+            val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+            cmp_long(val1, val2);
+        } else {
+            val1 = fetch_data_word(M.x86.R_SI);
+            val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+            cmp_word((u16)val1, (u16)val2);
+        }
+        M.x86.R_SI += inc;
+        M.x86.R_DI += inc;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa8
+****************************************************************************/
+void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    int imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("TEST\tAL,");
+    imm = fetch_byte_imm();
+    DECODE_PRINTF2("%04x\n", imm);
+    TRACE_AND_STEP();
+	test_byte(M.x86.R_AL, (u8)imm);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa9
+****************************************************************************/
+void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("TEST\tEAX,");
+        srcval = fetch_long_imm();
+    } else {
+        DECODE_PRINTF("TEST\tAX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        test_long(M.x86.R_EAX, srcval);
+    } else {
+        test_word(M.x86.R_AX, (u16)srcval);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xaa
+****************************************************************************/
+void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
+{
+    int inc;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("STOS\tBYTE\n");
+    if (ACCESS_FLAG(F_DF))   /* down */
+        inc = -1;
+    else
+        inc = 1;
+    TRACE_AND_STEP();
+    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+        /* dont care whether REPE or REPNE */
+        /* move them until (E)CX is ZERO. */
+        while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
+            store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
+            if (M.x86.mode & SYSMODE_32BIT_REP)
+                M.x86.R_ECX -= 1;
+            else
+                M.x86.R_CX -= 1;
+            M.x86.R_DI += inc;
+            if (M.x86.intr & INTR_HALTED)
+                break;
+        }
+        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+    } else {
+        store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
+        M.x86.R_DI += inc;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xab
+****************************************************************************/
+void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
+{
+    int inc;
+    u32 count;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("STOS\tDWORD\n");
+        if (ACCESS_FLAG(F_DF))   /* down */
+            inc = -4;
+        else
+            inc = 4;
+    } else {
+        DECODE_PRINTF("STOS\tWORD\n");
+        if (ACCESS_FLAG(F_DF))   /* down */
+            inc = -2;
+        else
+            inc = 2;
+    }
+    TRACE_AND_STEP();
+    count = 1;
+    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+        /* dont care whether REPE or REPNE */
+        /* move them until (E)CX is ZERO. */
+        count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
+        M.x86.R_CX = 0;
+	if (M.x86.mode & SYSMODE_32BIT_REP)
+            M.x86.R_ECX = 0;
+        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+    }
+    while (count--) {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
+        } else {
+            store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
+        }
+        M.x86.R_DI += inc;
+        if (M.x86.intr & INTR_HALTED)
+            break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xac
+****************************************************************************/
+void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
+{
+    int inc;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("LODS\tBYTE\n");
+    TRACE_AND_STEP();
+    if (ACCESS_FLAG(F_DF))   /* down */
+        inc = -1;
+    else
+        inc = 1;
+    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+        /* dont care whether REPE or REPNE */
+        /* move them until (E)CX is ZERO. */
+        while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
+            M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
+            if (M.x86.mode & SYSMODE_32BIT_REP)
+                M.x86.R_ECX -= 1;
+            else
+                M.x86.R_CX -= 1;
+            M.x86.R_SI += inc;
+            if (M.x86.intr & INTR_HALTED)
+                break;
+        }
+        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+    } else {
+        M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
+        M.x86.R_SI += inc;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xad
+****************************************************************************/
+void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
+{
+    int inc;
+    u32 count;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("LODS\tDWORD\n");
+        if (ACCESS_FLAG(F_DF))   /* down */
+            inc = -4;
+        else
+            inc = 4;
+    } else {
+        DECODE_PRINTF("LODS\tWORD\n");
+        if (ACCESS_FLAG(F_DF))   /* down */
+            inc = -2;
+        else
+            inc = 2;
+    }
+    TRACE_AND_STEP();
+    count = 1;
+    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+        /* dont care whether REPE or REPNE */
+        /* move them until (E)CX is ZERO. */
+        count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
+        M.x86.R_CX = 0;
+	if (M.x86.mode & SYSMODE_32BIT_REP)
+            M.x86.R_ECX = 0;
+        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+    }
+    while (count--) {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
+        } else {
+            M.x86.R_AX = fetch_data_word(M.x86.R_SI);
+        }
+        M.x86.R_SI += inc;
+        if (M.x86.intr & INTR_HALTED)
+            break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xae
+****************************************************************************/
+void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
+{
+    s8 val2;
+    int inc;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SCAS\tBYTE\n");
+    TRACE_AND_STEP();
+    if (ACCESS_FLAG(F_DF))   /* down */
+        inc = -1;
+    else
+        inc = 1;
+    if (M.x86.mode & SYSMODE_PREFIX_REPE) {
+        /* REPE  */
+        /* move them until (E)CX is ZERO. */
+        while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
+            val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+            cmp_byte(M.x86.R_AL, val2);
+            if (M.x86.mode & SYSMODE_32BIT_REP)
+                M.x86.R_ECX -= 1;
+            else
+                M.x86.R_CX -= 1;
+            M.x86.R_DI += inc;
+            if (ACCESS_FLAG(F_ZF) == 0)
+                break;
+            if (M.x86.intr & INTR_HALTED)
+                break;
+        }
+        M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+    } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+        /* REPNE  */
+        /* move them until (E)CX is ZERO. */
+        while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
+            val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+            cmp_byte(M.x86.R_AL, val2);
+            if (M.x86.mode & SYSMODE_32BIT_REP)
+                M.x86.R_ECX -= 1;
+            else
+                M.x86.R_CX -= 1;
+            M.x86.R_DI += inc;
+            if (ACCESS_FLAG(F_ZF))
+                break;          /* zero flag set means equal */
+            if (M.x86.intr & INTR_HALTED)
+                break;
+        }
+        M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
+    } else {
+        val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+        cmp_byte(M.x86.R_AL, val2);
+        M.x86.R_DI += inc;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xaf
+****************************************************************************/
+void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
+{
+    int inc;
+    u32 val;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("SCAS\tDWORD\n");
+        if (ACCESS_FLAG(F_DF))   /* down */
+            inc = -4;
+        else
+            inc = 4;
+    } else {
+        DECODE_PRINTF("SCAS\tWORD\n");
+        if (ACCESS_FLAG(F_DF))   /* down */
+            inc = -2;
+        else
+            inc = 2;
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_REPE) {
+        /* REPE  */
+        /* move them until (E)CX is ZERO. */
+        while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+                cmp_long(M.x86.R_EAX, val);
+            } else {
+                val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+                cmp_word(M.x86.R_AX, (u16)val);
+            }
+            if (M.x86.mode & SYSMODE_32BIT_REP)
+                M.x86.R_ECX -= 1;
+            else
+                M.x86.R_CX -= 1;
+            M.x86.R_DI += inc;
+            if (ACCESS_FLAG(F_ZF) == 0)
+                break;
+            if (M.x86.intr & INTR_HALTED)
+                break;
+        }
+        M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+    } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+        /* REPNE  */
+        /* move them until (E)CX is ZERO. */
+        while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+                cmp_long(M.x86.R_EAX, val);
+            } else {
+                val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+                cmp_word(M.x86.R_AX, (u16)val);
+            }
+            if (M.x86.mode & SYSMODE_32BIT_REP)
+                M.x86.R_ECX -= 1;
+            else
+                M.x86.R_CX -= 1;
+            M.x86.R_DI += inc;
+            if (ACCESS_FLAG(F_ZF))
+                break;          /* zero flag set means equal */
+            if (M.x86.intr & INTR_HALTED)
+                break;
+        }
+        M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
+    } else {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+            cmp_long(M.x86.R_EAX, val);
+        } else {
+            val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+            cmp_word(M.x86.R_AX, (u16)val);
+        }
+        M.x86.R_DI += inc;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb0 - 0xb7
+****************************************************************************/
+void x86emuOp_mov_byte_register_IMM(u8 op1)
+{
+    u8 imm, *ptr;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\t");
+    ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
+    DECODE_PRINTF(",");
+    imm = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", imm);
+    TRACE_AND_STEP();
+    *ptr = imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb8 - 0xbf
+****************************************************************************/
+void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    op1 &= 0x7;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\t");
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        u32 *reg32;
+        reg32 = DECODE_RM_LONG_REGISTER(op1);
+        srcval = fetch_long_imm();
+        DECODE_PRINTF2(",%x\n", srcval);
+        TRACE_AND_STEP();
+        *reg32 = srcval;
+    } else {
+        u16 *reg16;
+        reg16 = DECODE_RM_WORD_REGISTER(op1);
+        srcval = fetch_word_imm();
+        DECODE_PRINTF2(",%x\n", srcval);
+        TRACE_AND_STEP();
+        *reg16 = (u16)srcval;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc0
+****************************************************************************/
+void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg;
+    uint destoffset;
+    u8 destval;
+    u8 amt;
+
+    /*
+     * Yet another weirdo special case instruction format.  Part of
+     * the opcode held below in "RH".  Doubly nested case would
+     * result, except that the decoded instruction
+     */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (DEBUG_DECODE()) {
+        /* XXX DECODE_PRINTF may be changed to something more
+           general, so that it is important to leave the strings
+           in the same format, even though the result is that the
+           above test is done twice. */
+
+        switch (rh) {
+        case 0:
+            DECODE_PRINTF("ROL\t");
+            break;
+        case 1:
+            DECODE_PRINTF("ROR\t");
+            break;
+        case 2:
+            DECODE_PRINTF("RCL\t");
+            break;
+        case 3:
+            DECODE_PRINTF("RCR\t");
+            break;
+        case 4:
+            DECODE_PRINTF("SHL\t");
+            break;
+        case 5:
+            DECODE_PRINTF("SHR\t");
+            break;
+        case 6:
+            DECODE_PRINTF("SAL\t");
+            break;
+        case 7:
+            DECODE_PRINTF("SAR\t");
+            break;
+        }
+    }
+#endif
+    /* know operation, decode the mod byte to find the addressing
+       mode. */
+    if (mod < 3) {
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rmXX_address(mod, rl);
+        amt = fetch_byte_imm();
+        DECODE_PRINTF2(",%x\n", amt);
+        destval = fetch_data_byte(destoffset);
+        TRACE_AND_STEP();
+        destval = (*opcD0_byte_operation[rh]) (destval, amt);
+        store_data_byte(destoffset, destval);
+    } else {                     /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        amt = fetch_byte_imm();
+        DECODE_PRINTF2(",%x\n", amt);
+        TRACE_AND_STEP();
+        destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
+        *destreg = destval;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc1
+****************************************************************************/
+void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 amt;
+
+    /*
+     * Yet another weirdo special case instruction format.  Part of
+     * the opcode held below in "RH".  Doubly nested case would
+     * result, except that the decoded instruction
+     */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (DEBUG_DECODE()) {
+        /* XXX DECODE_PRINTF may be changed to something more
+           general, so that it is important to leave the strings
+           in the same format, even though the result is that the
+           above test is done twice. */
+
+        switch (rh) {
+        case 0:
+            DECODE_PRINTF("ROL\t");
+            break;
+        case 1:
+            DECODE_PRINTF("ROR\t");
+            break;
+        case 2:
+            DECODE_PRINTF("RCL\t");
+            break;
+        case 3:
+            DECODE_PRINTF("RCR\t");
+            break;
+        case 4:
+            DECODE_PRINTF("SHL\t");
+            break;
+        case 5:
+            DECODE_PRINTF("SHR\t");
+            break;
+        case 6:
+            DECODE_PRINTF("SAL\t");
+            break;
+        case 7:
+            DECODE_PRINTF("SAR\t");
+            break;
+        }
+    }
+#endif
+    /* know operation, decode the mod byte to find the addressing
+       mode. */
+    if (mod < 3) {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rmXX_address(mod, rl);
+            amt = fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", amt);
+            destval = fetch_data_long(destoffset);
+            TRACE_AND_STEP();
+            destval = (*opcD1_long_operation[rh]) (destval, amt);
+            store_data_long(destoffset, destval);
+        } else {
+            u16 destval;
+
+            DECODE_PRINTF("WORD PTR ");
+            destoffset = decode_rmXX_address(mod, rl);
+            amt = fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", amt);
+            destval = fetch_data_word(destoffset);
+            TRACE_AND_STEP();
+            destval = (*opcD1_word_operation[rh]) (destval, amt);
+            store_data_word(destoffset, destval);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            amt = fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", amt);
+            TRACE_AND_STEP();
+            *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
+        } else {
+            u16 *destreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            amt = fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", amt);
+            TRACE_AND_STEP();
+            *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc2
+****************************************************************************/
+void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u16 imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("RET\t");
+    imm = fetch_word_imm();
+    DECODE_PRINTF2("%x\n", imm);
+	TRACE_AND_STEP();
+    M.x86.R_IP = pop_word();
+	RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "NEAR");
+    M.x86.R_SP += imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc3
+****************************************************************************/
+void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("RET\n");
+	TRACE_AND_STEP();
+    M.x86.R_IP = pop_word();
+	RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "NEAR");
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc4
+****************************************************************************/
+void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rh, rl;
+    u16 *dstreg;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("LES\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_ES = fetch_data_word(srcoffset + 2);
+    }
+    /* else UNDEFINED!                   register to register */
+
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc5
+****************************************************************************/
+void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rh, rl;
+    u16 *dstreg;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("LDS\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_DS = fetch_data_word(srcoffset + 2);
+    }
+    /* else UNDEFINED! */
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc6
+****************************************************************************/
+void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg;
+    uint destoffset;
+    u8 imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (rh != 0) {
+        DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
+        HALT_SYS();
+    }
+    if (mod < 3) {
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rmXX_address(mod, rl);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2(",%2x\n", imm);
+        TRACE_AND_STEP();
+        store_data_byte(destoffset, imm);
+    } else {                     /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2(",%2x\n", imm);
+        TRACE_AND_STEP();
+        *destreg = imm;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc7
+****************************************************************************/
+void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (rh != 0) {
+        DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
+        HALT_SYS();
+    }
+    if (mod < 3) {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 imm;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rmXX_address(mod, rl);
+            imm = fetch_long_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            store_data_long(destoffset, imm);
+        } else {
+            u16 imm;
+
+            DECODE_PRINTF("WORD PTR ");
+            destoffset = decode_rmXX_address(mod, rl);
+            imm = fetch_word_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            store_data_word(destoffset, imm);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+			u32 *destreg;
+			u32 imm;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            imm = fetch_long_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            *destreg = imm;
+        } else {
+			u16 *destreg;
+			u16 imm;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            imm = fetch_word_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            *destreg = imm;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc8
+****************************************************************************/
+void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
+{
+    u16 local,frame_pointer;
+    u8  nesting;
+    int i;
+
+    START_OF_INSTR();
+    local = fetch_word_imm();
+    nesting = fetch_byte_imm();
+    DECODE_PRINTF2("ENTER %x\n", local);
+    DECODE_PRINTF2(",%x\n", nesting);
+    TRACE_AND_STEP();
+    push_word(M.x86.R_BP);
+    frame_pointer = M.x86.R_SP;
+    if (nesting > 0) {
+        for (i = 1; i < nesting; i++) {
+            M.x86.R_BP -= 2;
+            push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
+            }
+        push_word(frame_pointer);
+        }
+    M.x86.R_BP = frame_pointer;
+    M.x86.R_SP = (u16)(M.x86.R_SP - local);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc9
+****************************************************************************/
+void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("LEAVE\n");
+    TRACE_AND_STEP();
+    M.x86.R_SP = M.x86.R_BP;
+    M.x86.R_BP = pop_word();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xca
+****************************************************************************/
+void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u16 imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("RETF\t");
+    imm = fetch_word_imm();
+    DECODE_PRINTF2("%x\n", imm);
+	TRACE_AND_STEP();
+    M.x86.R_IP = pop_word();
+    M.x86.R_CS = pop_word();
+	RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "FAR");
+    M.x86.R_SP += imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcb
+****************************************************************************/
+void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("RETF\n");
+	TRACE_AND_STEP();
+    M.x86.R_IP = pop_word();
+    M.x86.R_CS = pop_word();
+	RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "FAR");
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcc
+****************************************************************************/
+void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
+{
+    u16 tmp;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("INT 3\n");
+    tmp = (u16) mem_access_word(3 * 4 + 2);
+    /* access the segment register */
+    TRACE_AND_STEP();
+	if (_X86EMU_intrTab[3]) {
+		(*_X86EMU_intrTab[3])(3);
+    } else {
+        push_word((u16)M.x86.R_FLG);
+        CLEAR_FLAG(F_IF);
+        CLEAR_FLAG(F_TF);
+        push_word(M.x86.R_CS);
+        M.x86.R_CS = mem_access_word(3 * 4 + 2);
+        push_word(M.x86.R_IP);
+        M.x86.R_IP = mem_access_word(3 * 4);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcd
+****************************************************************************/
+void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u16 tmp;
+    u8 intnum;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("INT\t");
+    intnum = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", intnum);
+    tmp = mem_access_word(intnum * 4 + 2);
+    TRACE_AND_STEP();
+	if (_X86EMU_intrTab[intnum]) {
+		(*_X86EMU_intrTab[intnum])(intnum);
+    } else {
+        push_word((u16)M.x86.R_FLG);
+        CLEAR_FLAG(F_IF);
+        CLEAR_FLAG(F_TF);
+        push_word(M.x86.R_CS);
+        M.x86.R_CS = mem_access_word(intnum * 4 + 2);
+        push_word(M.x86.R_IP);
+        M.x86.R_IP = mem_access_word(intnum * 4);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xce
+****************************************************************************/
+void x86emuOp_into(u8 X86EMU_UNUSED(op1))
+{
+    u16 tmp;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("INTO\n");
+    TRACE_AND_STEP();
+    if (ACCESS_FLAG(F_OF)) {
+        tmp = mem_access_word(4 * 4 + 2);
+		if (_X86EMU_intrTab[4]) {
+			(*_X86EMU_intrTab[4])(4);
+        } else {
+            push_word((u16)M.x86.R_FLG);
+            CLEAR_FLAG(F_IF);
+            CLEAR_FLAG(F_TF);
+            push_word(M.x86.R_CS);
+            M.x86.R_CS = mem_access_word(4 * 4 + 2);
+            push_word(M.x86.R_IP);
+            M.x86.R_IP = mem_access_word(4 * 4);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcf
+****************************************************************************/
+void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("IRET\n");
+
+    TRACE_AND_STEP();
+
+    M.x86.R_IP = pop_word();
+    M.x86.R_CS = pop_word();
+    M.x86.R_FLG = pop_word();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd0
+****************************************************************************/
+void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg;
+    uint destoffset;
+    u8 destval;
+
+    /*
+     * Yet another weirdo special case instruction format.  Part of
+     * the opcode held below in "RH".  Doubly nested case would
+     * result, except that the decoded instruction
+     */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (DEBUG_DECODE()) {
+        /* XXX DECODE_PRINTF may be changed to something more
+           general, so that it is important to leave the strings
+           in the same format, even though the result is that the
+           above test is done twice. */
+        switch (rh) {
+        case 0:
+            DECODE_PRINTF("ROL\t");
+            break;
+        case 1:
+            DECODE_PRINTF("ROR\t");
+            break;
+        case 2:
+            DECODE_PRINTF("RCL\t");
+            break;
+        case 3:
+            DECODE_PRINTF("RCR\t");
+            break;
+        case 4:
+            DECODE_PRINTF("SHL\t");
+            break;
+        case 5:
+            DECODE_PRINTF("SHR\t");
+            break;
+        case 6:
+            DECODE_PRINTF("SAL\t");
+            break;
+        case 7:
+            DECODE_PRINTF("SAR\t");
+            break;
+        }
+    }
+#endif
+    /* know operation, decode the mod byte to find the addressing
+       mode. */
+    if (mod < 3) {
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",1\n");
+        destval = fetch_data_byte(destoffset);
+        TRACE_AND_STEP();
+        destval = (*opcD0_byte_operation[rh]) (destval, 1);
+        store_data_byte(destoffset, destval);
+    } else {                     /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",1\n");
+        TRACE_AND_STEP();
+        destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
+        *destreg = destval;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd1
+****************************************************************************/
+void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    /*
+     * Yet another weirdo special case instruction format.  Part of
+     * the opcode held below in "RH".  Doubly nested case would
+     * result, except that the decoded instruction
+     */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (DEBUG_DECODE()) {
+        /* XXX DECODE_PRINTF may be changed to something more
+           general, so that it is important to leave the strings
+           in the same format, even though the result is that the
+           above test is done twice. */
+        switch (rh) {
+        case 0:
+            DECODE_PRINTF("ROL\t");
+            break;
+        case 1:
+            DECODE_PRINTF("ROR\t");
+            break;
+        case 2:
+            DECODE_PRINTF("RCL\t");
+            break;
+        case 3:
+            DECODE_PRINTF("RCR\t");
+            break;
+        case 4:
+            DECODE_PRINTF("SHL\t");
+            break;
+        case 5:
+            DECODE_PRINTF("SHR\t");
+            break;
+        case 6:
+            DECODE_PRINTF("SAL\t");
+            break;
+        case 7:
+            DECODE_PRINTF("SAR\t");
+            break;
+        }
+    }
+#endif
+    /* know operation, decode the mod byte to find the addressing
+       mode. */
+    if (mod < 3) {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rmXX_address(mod, rl);
+            DECODE_PRINTF(",1\n");
+            destval = fetch_data_long(destoffset);
+            TRACE_AND_STEP();
+            destval = (*opcD1_long_operation[rh]) (destval, 1);
+            store_data_long(destoffset, destval);
+        } else {
+            u16 destval;
+
+            DECODE_PRINTF("WORD PTR ");
+            destoffset = decode_rmXX_address(mod, rl);
+            DECODE_PRINTF(",1\n");
+            destval = fetch_data_word(destoffset);
+            TRACE_AND_STEP();
+            destval = (*opcD1_word_operation[rh]) (destval, 1);
+            store_data_word(destoffset, destval);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+			u32 destval;
+			u32 *destreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",1\n");
+            TRACE_AND_STEP();
+            destval = (*opcD1_long_operation[rh]) (*destreg, 1);
+            *destreg = destval;
+        } else {
+			u16 destval;
+			u16 *destreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",1\n");
+            TRACE_AND_STEP();
+            destval = (*opcD1_word_operation[rh]) (*destreg, 1);
+            *destreg = destval;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd2
+****************************************************************************/
+void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg;
+    uint destoffset;
+    u8 destval;
+    u8 amt;
+
+    /*
+     * Yet another weirdo special case instruction format.  Part of
+     * the opcode held below in "RH".  Doubly nested case would
+     * result, except that the decoded instruction
+     */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (DEBUG_DECODE()) {
+        /* XXX DECODE_PRINTF may be changed to something more
+           general, so that it is important to leave the strings
+           in the same format, even though the result is that the
+           above test is done twice. */
+        switch (rh) {
+        case 0:
+            DECODE_PRINTF("ROL\t");
+            break;
+        case 1:
+            DECODE_PRINTF("ROR\t");
+            break;
+        case 2:
+            DECODE_PRINTF("RCL\t");
+            break;
+        case 3:
+            DECODE_PRINTF("RCR\t");
+            break;
+        case 4:
+            DECODE_PRINTF("SHL\t");
+            break;
+        case 5:
+            DECODE_PRINTF("SHR\t");
+            break;
+        case 6:
+            DECODE_PRINTF("SAL\t");
+            break;
+        case 7:
+            DECODE_PRINTF("SAR\t");
+            break;
+        }
+    }
+#endif
+    /* know operation, decode the mod byte to find the addressing
+       mode. */
+    amt = M.x86.R_CL;
+    if (mod < 3) {
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",CL\n");
+        destval = fetch_data_byte(destoffset);
+        TRACE_AND_STEP();
+        destval = (*opcD0_byte_operation[rh]) (destval, amt);
+        store_data_byte(destoffset, destval);
+    } else {                     /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",CL\n");
+        TRACE_AND_STEP();
+        destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
+        *destreg = destval;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd3
+****************************************************************************/
+void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 amt;
+
+    /*
+     * Yet another weirdo special case instruction format.  Part of
+     * the opcode held below in "RH".  Doubly nested case would
+     * result, except that the decoded instruction
+     */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (DEBUG_DECODE()) {
+        /* XXX DECODE_PRINTF may be changed to something more
+           general, so that it is important to leave the strings
+           in the same format, even though the result is that the
+           above test is done twice. */
+        switch (rh) {
+        case 0:
+            DECODE_PRINTF("ROL\t");
+            break;
+        case 1:
+            DECODE_PRINTF("ROR\t");
+            break;
+        case 2:
+            DECODE_PRINTF("RCL\t");
+            break;
+        case 3:
+            DECODE_PRINTF("RCR\t");
+            break;
+        case 4:
+            DECODE_PRINTF("SHL\t");
+            break;
+        case 5:
+            DECODE_PRINTF("SHR\t");
+            break;
+        case 6:
+            DECODE_PRINTF("SAL\t");
+            break;
+        case 7:
+            DECODE_PRINTF("SAR\t");
+            break;
+        }
+    }
+#endif
+    /* know operation, decode the mod byte to find the addressing
+       mode. */
+    amt = M.x86.R_CL;
+    if (mod < 3) {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rmXX_address(mod, rl);
+            DECODE_PRINTF(",CL\n");
+            destval = fetch_data_long(destoffset);
+            TRACE_AND_STEP();
+            destval = (*opcD1_long_operation[rh]) (destval, amt);
+            store_data_long(destoffset, destval);
+        } else {
+            u16 destval;
+
+            DECODE_PRINTF("WORD PTR ");
+            destoffset = decode_rmXX_address(mod, rl);
+            DECODE_PRINTF(",CL\n");
+            destval = fetch_data_word(destoffset);
+            TRACE_AND_STEP();
+            destval = (*opcD1_word_operation[rh]) (destval, amt);
+            store_data_word(destoffset, destval);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",CL\n");
+            TRACE_AND_STEP();
+            *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
+        } else {
+            u16 *destreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",CL\n");
+            TRACE_AND_STEP();
+            *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd4
+****************************************************************************/
+void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
+{
+    u8 a;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("AAM\n");
+    a = fetch_byte_imm();      /* this is a stupid encoding. */
+    if (a != 10) {
+        DECODE_PRINTF("ERROR DECODING AAM\n");
+        TRACE_REGS();
+        HALT_SYS();
+    }
+    TRACE_AND_STEP();
+    /* note the type change here --- returning AL and AH in AX. */
+    M.x86.R_AX = aam_word(M.x86.R_AL);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd5
+****************************************************************************/
+void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
+{
+    u8 a;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("AAD\n");
+    a = fetch_byte_imm();
+    TRACE_AND_STEP();
+    M.x86.R_AX = aad_word(M.x86.R_AX);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/* opcode 0xd6 ILLEGAL OPCODE */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd7
+****************************************************************************/
+void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
+{
+    u16 addr;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("XLAT\n");
+    TRACE_AND_STEP();
+	addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
+    M.x86.R_AL = fetch_data_byte(addr);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/* instuctions  D8 .. DF are in i87_ops.c */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe0
+****************************************************************************/
+void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
+{
+    s16 ip;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("LOOPNE\t");
+    ip = (s8) fetch_byte_imm();
+    ip += (s16) M.x86.R_IP;
+    DECODE_PRINTF2("%04x\n", ip);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_ADDR)
+        M.x86.R_ECX -= 1;
+    else
+        M.x86.R_CX -= 1;
+    if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0 && !ACCESS_FLAG(F_ZF))      /* (E)CX != 0 and !ZF */
+        M.x86.R_IP = ip;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe1
+****************************************************************************/
+void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
+{
+    s16 ip;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("LOOPE\t");
+    ip = (s8) fetch_byte_imm();
+    ip += (s16) M.x86.R_IP;
+    DECODE_PRINTF2("%04x\n", ip);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_ADDR)
+        M.x86.R_ECX -= 1;
+    else
+        M.x86.R_CX -= 1;
+    if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0 && ACCESS_FLAG(F_ZF))      /* (E)CX != 0 and ZF */
+        M.x86.R_IP = ip;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe2
+****************************************************************************/
+void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
+{
+    s16 ip;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("LOOP\t");
+    ip = (s8) fetch_byte_imm();
+    ip += (s16) M.x86.R_IP;
+    DECODE_PRINTF2("%04x\n", ip);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_ADDR)
+        M.x86.R_ECX -= 1;
+    else
+        M.x86.R_CX -= 1;
+    if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0)      /* (E)CX != 0 */
+        M.x86.R_IP = ip;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe3
+****************************************************************************/
+void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
+{
+    u16 target;
+    s8  offset;
+
+    /* jump to byte offset if overflow flag is set */
+    START_OF_INSTR();
+    DECODE_PRINTF("JCXZ\t");
+    offset = (s8)fetch_byte_imm();
+    target = (u16)(M.x86.R_IP + offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (M.x86.R_CX == 0) {
+        M.x86.R_IP = target;
+	JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " CXZ ");
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe4
+****************************************************************************/
+void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 port;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("IN\t");
+	port = (u8) fetch_byte_imm();
+    DECODE_PRINTF2("%x,AL\n", port);
+    TRACE_AND_STEP();
+    M.x86.R_AL = (*sys_inb)(port);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe5
+****************************************************************************/
+void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 port;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("IN\t");
+	port = (u8) fetch_byte_imm();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF2("EAX,%x\n", port);
+    } else {
+        DECODE_PRINTF2("AX,%x\n", port);
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = (*sys_inl)(port);
+    } else {
+        M.x86.R_AX = (*sys_inw)(port);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe6
+****************************************************************************/
+void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
+{
+    u8 port;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("OUT\t");
+	port = (u8) fetch_byte_imm();
+    DECODE_PRINTF2("%x,AL\n", port);
+    TRACE_AND_STEP();
+    (*sys_outb)(port, M.x86.R_AL);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe7
+****************************************************************************/
+void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
+{
+    u8 port;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("OUT\t");
+	port = (u8) fetch_byte_imm();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF2("%x,EAX\n", port);
+    } else {
+        DECODE_PRINTF2("%x,AX\n", port);
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        (*sys_outl)(port, M.x86.R_EAX);
+    } else {
+        (*sys_outw)(port, M.x86.R_AX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe8
+****************************************************************************/
+void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+    s16 ip;
+
+    START_OF_INSTR();
+	DECODE_PRINTF("CALL\t");
+	ip = (s16) fetch_word_imm();
+	ip += (s16) M.x86.R_IP;    /* CHECK SIGN */
+	DECODE_PRINTF2("%04x\n", ip);
+	CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
+    TRACE_AND_STEP();
+    push_word(M.x86.R_IP);
+    M.x86.R_IP = ip;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe9
+****************************************************************************/
+void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+    int ip;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("JMP\t");
+    ip = (s16)fetch_word_imm();
+    ip += (s16)M.x86.R_IP;
+    DECODE_PRINTF2("%04x\n", ip);
+    JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, " NEAR ");
+    TRACE_AND_STEP();
+    M.x86.R_IP = (u16)ip;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xea
+****************************************************************************/
+void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u16 cs, ip;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("JMP\tFAR ");
+    ip = fetch_word_imm();
+    cs = fetch_word_imm();
+    DECODE_PRINTF2("%04x:", cs);
+    DECODE_PRINTF2("%04x\n", ip);
+    JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, cs, ip, " FAR ");
+    TRACE_AND_STEP();
+    M.x86.R_IP = ip;
+    M.x86.R_CS = cs;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xeb
+****************************************************************************/
+void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u16 target;
+    s8 offset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("JMP\t");
+    offset = (s8)fetch_byte_imm();
+    target = (u16)(M.x86.R_IP + offset);
+    DECODE_PRINTF2("%x\n", target);
+    JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, target, " BYTE ");
+    TRACE_AND_STEP();
+    M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xec
+****************************************************************************/
+void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("IN\tAL,DX\n");
+    TRACE_AND_STEP();
+    M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xed
+****************************************************************************/
+void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("IN\tEAX,DX\n");
+    } else {
+        DECODE_PRINTF("IN\tAX,DX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
+    } else {
+        M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xee
+****************************************************************************/
+void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("OUT\tDX,AL\n");
+    TRACE_AND_STEP();
+    (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xef
+****************************************************************************/
+void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("OUT\tDX,EAX\n");
+    } else {
+        DECODE_PRINTF("OUT\tDX,AX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
+    } else {
+        (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf0
+****************************************************************************/
+void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("LOCK:\n");
+    TRACE_AND_STEP();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/*opcode 0xf1 ILLEGAL OPERATION */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf2
+****************************************************************************/
+void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("REPNE\n");
+    TRACE_AND_STEP();
+    M.x86.mode |= SYSMODE_PREFIX_REPNE;
+    if (M.x86.mode & SYSMODE_PREFIX_ADDR)
+        M.x86.mode |= SYSMODE_32BIT_REP;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf3
+****************************************************************************/
+void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("REPE\n");
+    TRACE_AND_STEP();
+    M.x86.mode |= SYSMODE_PREFIX_REPE;
+    if (M.x86.mode & SYSMODE_PREFIX_ADDR)
+        M.x86.mode |= SYSMODE_32BIT_REP;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf4
+****************************************************************************/
+void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("HALT\n");
+    TRACE_AND_STEP();
+    HALT_SYS();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf5
+****************************************************************************/
+void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
+{
+    /* complement the carry flag. */
+    START_OF_INSTR();
+    DECODE_PRINTF("CMC\n");
+    TRACE_AND_STEP();
+    TOGGLE_FLAG(F_CF);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf6
+****************************************************************************/
+void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg;
+    uint destoffset;
+    u8 destval, srcval;
+
+    /* long, drawn out code follows.  Double switch for a total
+       of 32 cases.  */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    DECODE_PRINTF(opF6_names[rh]);
+    if (mod < 3) {
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rmXX_address(mod, rl);
+        destval = fetch_data_byte(destoffset);
+
+        switch (rh) {
+        case 0:         /* test byte imm */
+            DECODE_PRINTF(",");
+            srcval = fetch_byte_imm();
+            DECODE_PRINTF2("%02x\n", srcval);
+            TRACE_AND_STEP();
+            test_byte(destval, srcval);
+            break;
+        case 1:
+            DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+            HALT_SYS();
+            break;
+        case 2:
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = not_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        case 3:
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = neg_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        case 4:
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            mul_byte(destval);
+            break;
+        case 5:
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            imul_byte(destval);
+            break;
+        case 6:
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            div_byte(destval);
+            break;
+        default:
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            idiv_byte(destval);
+            break;
+        }
+    } else {                     /* mod=11 */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        switch (rh) {
+        case 0:         /* test byte imm */
+            DECODE_PRINTF(",");
+            srcval = fetch_byte_imm();
+            DECODE_PRINTF2("%02x\n", srcval);
+            TRACE_AND_STEP();
+            test_byte(*destreg, srcval);
+            break;
+        case 1:
+            DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+            HALT_SYS();
+            break;
+        case 2:
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = not_byte(*destreg);
+            break;
+        case 3:
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = neg_byte(*destreg);
+            break;
+        case 4:
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            mul_byte(*destreg);      /*!!!  */
+            break;
+        case 5:
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            imul_byte(*destreg);
+            break;
+        case 6:
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            div_byte(*destreg);
+            break;
+        default:
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            idiv_byte(*destreg);
+            break;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf7
+****************************************************************************/
+void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    DECODE_PRINTF(opF6_names[rh]);
+    if (mod < 3) {
+
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval, srcval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rmXX_address(mod, rl);
+            destval = fetch_data_long(destoffset);
+
+            switch (rh) {
+            case 0:
+                DECODE_PRINTF(",");
+                srcval = fetch_long_imm();
+                DECODE_PRINTF2("%x\n", srcval);
+                TRACE_AND_STEP();
+                test_long(destval, srcval);
+                break;
+            case 1:
+                DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
+                HALT_SYS();
+                break;
+            case 2:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                destval = not_long(destval);
+                store_data_long(destoffset, destval);
+                break;
+            case 3:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                destval = neg_long(destval);
+                store_data_long(destoffset, destval);
+                break;
+            case 4:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                mul_long(destval);
+                break;
+            case 5:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                imul_long(destval);
+                break;
+            case 6:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                div_long(destval);
+                break;
+            case 7:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                idiv_long(destval);
+                break;
+            }
+        } else {
+            u16 destval, srcval;
+
+            DECODE_PRINTF("WORD PTR ");
+            destoffset = decode_rmXX_address(mod, rl);
+            destval = fetch_data_word(destoffset);
+
+            switch (rh) {
+            case 0:         /* test word imm */
+                DECODE_PRINTF(",");
+                srcval = fetch_word_imm();
+                DECODE_PRINTF2("%x\n", srcval);
+                TRACE_AND_STEP();
+                test_word(destval, srcval);
+                break;
+            case 1:
+                DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
+                HALT_SYS();
+                break;
+            case 2:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                destval = not_word(destval);
+                store_data_word(destoffset, destval);
+                break;
+            case 3:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                destval = neg_word(destval);
+                store_data_word(destoffset, destval);
+                break;
+            case 4:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                mul_word(destval);
+                break;
+            case 5:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                imul_word(destval);
+                break;
+            case 6:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                div_word(destval);
+                break;
+            case 7:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                idiv_word(destval);
+                break;
+            }
+        }
+
+    } else {                     /* mod=11 */
+
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+
+            switch (rh) {
+            case 0:         /* test word imm */
+                DECODE_PRINTF(",");
+                srcval = fetch_long_imm();
+                DECODE_PRINTF2("%x\n", srcval);
+                TRACE_AND_STEP();
+                test_long(*destreg, srcval);
+                break;
+            case 1:
+                DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+                HALT_SYS();
+                break;
+            case 2:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg = not_long(*destreg);
+                break;
+            case 3:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg = neg_long(*destreg);
+                break;
+            case 4:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                mul_long(*destreg);      /*!!!  */
+                break;
+            case 5:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                imul_long(*destreg);
+                break;
+            case 6:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                div_long(*destreg);
+                break;
+            case 7:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                idiv_long(*destreg);
+                break;
+            }
+        } else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+
+            switch (rh) {
+            case 0:         /* test word imm */
+                DECODE_PRINTF(",");
+                srcval = fetch_word_imm();
+                DECODE_PRINTF2("%x\n", srcval);
+                TRACE_AND_STEP();
+                test_word(*destreg, srcval);
+                break;
+            case 1:
+                DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+                HALT_SYS();
+                break;
+            case 2:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg = not_word(*destreg);
+                break;
+            case 3:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg = neg_word(*destreg);
+                break;
+            case 4:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                mul_word(*destreg);      /*!!!  */
+                break;
+            case 5:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                imul_word(*destreg);
+                break;
+            case 6:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                div_word(*destreg);
+                break;
+            case 7:
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                idiv_word(*destreg);
+                break;
+            }
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf8
+****************************************************************************/
+void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
+{
+    /* clear the carry flag. */
+    START_OF_INSTR();
+    DECODE_PRINTF("CLC\n");
+    TRACE_AND_STEP();
+    CLEAR_FLAG(F_CF);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf9
+****************************************************************************/
+void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
+{
+    /* set the carry flag. */
+    START_OF_INSTR();
+    DECODE_PRINTF("STC\n");
+    TRACE_AND_STEP();
+    SET_FLAG(F_CF);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfa
+****************************************************************************/
+void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
+{
+    /* clear interrupts. */
+    START_OF_INSTR();
+    DECODE_PRINTF("CLI\n");
+    TRACE_AND_STEP();
+    CLEAR_FLAG(F_IF);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfb
+****************************************************************************/
+void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
+{
+    /* enable  interrupts. */
+    START_OF_INSTR();
+    DECODE_PRINTF("STI\n");
+    TRACE_AND_STEP();
+    SET_FLAG(F_IF);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfc
+****************************************************************************/
+void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
+{
+    /* clear interrupts. */
+    START_OF_INSTR();
+    DECODE_PRINTF("CLD\n");
+    TRACE_AND_STEP();
+    CLEAR_FLAG(F_DF);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfd
+****************************************************************************/
+void x86emuOp_std(u8 X86EMU_UNUSED(op1))
+{
+    /* clear interrupts. */
+    START_OF_INSTR();
+    DECODE_PRINTF("STD\n");
+    TRACE_AND_STEP();
+    SET_FLAG(F_DF);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfe
+****************************************************************************/
+void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rh, rl;
+    u8 destval;
+    uint destoffset;
+    u8 *destreg;
+
+    /* Yet another special case instruction. */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (DEBUG_DECODE()) {
+        /* XXX DECODE_PRINTF may be changed to something more
+           general, so that it is important to leave the strings
+           in the same format, even though the result is that the
+           above test is done twice. */
+
+        switch (rh) {
+        case 0:
+            DECODE_PRINTF("INC\t");
+            break;
+        case 1:
+            DECODE_PRINTF("DEC\t");
+            break;
+        case 2:
+        case 3:
+        case 4:
+        case 5:
+        case 6:
+        case 7:
+            DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
+            HALT_SYS();
+            break;
+        }
+    }
+#endif
+    if (mod < 3) {
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF("\n");
+        destval = fetch_data_byte(destoffset);
+        TRACE_AND_STEP();
+        if (rh == 0)
+          destval = inc_byte(destval);
+        else
+          destval = dec_byte(destval);
+        store_data_byte(destoffset, destval);
+    } else {
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        if (rh == 0)
+          *destreg = inc_byte(*destreg);
+        else
+          *destreg = dec_byte(*destreg);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xff
+****************************************************************************/
+void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rh, rl;
+    uint destoffset = 0;
+	u16 *destreg;
+	u32 *destreg32;
+	u16 destval,destval2;
+	u32 destval32;
+
+    /* Yet another special case instruction. */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef CONFIG_DEBUG
+    if (DEBUG_DECODE()) {
+        /* XXX DECODE_PRINTF may be changed to something more
+           general, so that it is important to leave the strings
+           in the same format, even though the result is that the
+           above test is done twice. */
+
+        switch (rh) {
+        case 0:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                DECODE_PRINTF("INC\tDWORD PTR ");
+            } else {
+                DECODE_PRINTF("INC\tWORD PTR ");
+            }
+            break;
+        case 1:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                DECODE_PRINTF("DEC\tDWORD PTR ");
+            } else {
+                DECODE_PRINTF("DEC\tWORD PTR ");
+            }
+            break;
+        case 2:
+            DECODE_PRINTF("CALL\t ");
+            break;
+        case 3:
+            DECODE_PRINTF("CALL\tFAR ");
+            break;
+        case 4:
+            DECODE_PRINTF("JMP\t");
+            break;
+        case 5:
+            DECODE_PRINTF("JMP\tFAR ");
+            break;
+        case 6:
+            DECODE_PRINTF("PUSH\t");
+            break;
+        case 7:
+            DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
+            HALT_SYS();
+            break;
+        }
+    }
+#endif
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF("\n");
+        switch (rh) {
+        case 0:         /* inc word ptr ... */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destval32 = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval32 = inc_long(destval32);
+                store_data_long(destoffset, destval32);
+            } else {
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval = inc_word(destval);
+                store_data_word(destoffset, destval);
+            }
+            break;
+        case 1:         /* dec word ptr ... */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destval32 = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval32 = dec_long(destval32);
+                store_data_long(destoffset, destval32);
+            } else {
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval = dec_word(destval);
+                store_data_word(destoffset, destval);
+            }
+            break;
+        case 2:         /* call word ptr ... */
+            destval = fetch_data_word(destoffset);
+            TRACE_AND_STEP();
+            push_word(M.x86.R_IP);
+            M.x86.R_IP = destval;
+            break;
+        case 3:         /* call far ptr ... */
+            destval = fetch_data_word(destoffset);
+            destval2 = fetch_data_word(destoffset + 2);
+            TRACE_AND_STEP();
+            push_word(M.x86.R_CS);
+            M.x86.R_CS = destval2;
+            push_word(M.x86.R_IP);
+            M.x86.R_IP = destval;
+            break;
+        case 4:         /* jmp word ptr ... */
+            destval = fetch_data_word(destoffset);
+            JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, destval, " WORD ");
+            TRACE_AND_STEP();
+            M.x86.R_IP = destval;
+            break;
+        case 5:         /* jmp far ptr ... */
+            destval = fetch_data_word(destoffset);
+            destval2 = fetch_data_word(destoffset + 2);
+            JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, destval2, destval, " FAR ");
+            TRACE_AND_STEP();
+            M.x86.R_IP = destval;
+            M.x86.R_CS = destval2;
+            break;
+        case 6:         /*  push word ptr ... */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destval32 = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                push_long(destval32);
+            } else {
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                push_word(destval);
+            }
+            break;
+        }
+    } else {
+        switch (rh) {
+        case 0:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destreg32 = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg32 = inc_long(*destreg32);
+            } else {
+                destreg = DECODE_RM_WORD_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg = inc_word(*destreg);
+            }
+            break;
+        case 1:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destreg32 = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg32 = dec_long(*destreg32);
+            } else {
+                destreg = DECODE_RM_WORD_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg = dec_word(*destreg);
+            }
+            break;
+        case 2:         /* call word ptr ... */
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            push_word(M.x86.R_IP);
+            M.x86.R_IP = *destreg;
+            break;
+        case 3:         /* jmp far ptr ... */
+            DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
+            TRACE_AND_STEP();
+            HALT_SYS();
+            break;
+
+        case 4:         /* jmp  ... */
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            M.x86.R_IP = (u16) (*destreg);
+            break;
+        case 5:         /* jmp far ptr ... */
+            DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
+            TRACE_AND_STEP();
+            HALT_SYS();
+            break;
+        case 6:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destreg32 = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                push_long(*destreg32);
+            } else {
+                destreg = DECODE_RM_WORD_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                push_word(*destreg);
+            }
+            break;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/***************************************************************************
+ * Single byte operation code table:
+ **************************************************************************/
+void (*x86emu_optab[256])(u8) =
+{
+/*  0x00 */ x86emuOp_genop_byte_RM_R,
+/*  0x01 */ x86emuOp_genop_word_RM_R,
+/*  0x02 */ x86emuOp_genop_byte_R_RM,
+/*  0x03 */ x86emuOp_genop_word_R_RM,
+/*  0x04 */ x86emuOp_genop_byte_AL_IMM,
+/*  0x05 */ x86emuOp_genop_word_AX_IMM,
+/*  0x06 */ x86emuOp_push_ES,
+/*  0x07 */ x86emuOp_pop_ES,
+
+/*  0x08 */ x86emuOp_genop_byte_RM_R,
+/*  0x09 */ x86emuOp_genop_word_RM_R,
+/*  0x0a */ x86emuOp_genop_byte_R_RM,
+/*  0x0b */ x86emuOp_genop_word_R_RM,
+/*  0x0c */ x86emuOp_genop_byte_AL_IMM,
+/*  0x0d */ x86emuOp_genop_word_AX_IMM,
+/*  0x0e */ x86emuOp_push_CS,
+/*  0x0f */ x86emuOp_two_byte,
+
+/*  0x10 */ x86emuOp_genop_byte_RM_R,
+/*  0x11 */ x86emuOp_genop_word_RM_R,
+/*  0x12 */ x86emuOp_genop_byte_R_RM,
+/*  0x13 */ x86emuOp_genop_word_R_RM,
+/*  0x14 */ x86emuOp_genop_byte_AL_IMM,
+/*  0x15 */ x86emuOp_genop_word_AX_IMM,
+/*  0x16 */ x86emuOp_push_SS,
+/*  0x17 */ x86emuOp_pop_SS,
+
+/*  0x18 */ x86emuOp_genop_byte_RM_R,
+/*  0x19 */ x86emuOp_genop_word_RM_R,
+/*  0x1a */ x86emuOp_genop_byte_R_RM,
+/*  0x1b */ x86emuOp_genop_word_R_RM,
+/*  0x1c */ x86emuOp_genop_byte_AL_IMM,
+/*  0x1d */ x86emuOp_genop_word_AX_IMM,
+/*  0x1e */ x86emuOp_push_DS,
+/*  0x1f */ x86emuOp_pop_DS,
+
+/*  0x20 */ x86emuOp_genop_byte_RM_R,
+/*  0x21 */ x86emuOp_genop_word_RM_R,
+/*  0x22 */ x86emuOp_genop_byte_R_RM,
+/*  0x23 */ x86emuOp_genop_word_R_RM,
+/*  0x24 */ x86emuOp_genop_byte_AL_IMM,
+/*  0x25 */ x86emuOp_genop_word_AX_IMM,
+/*  0x26 */ x86emuOp_segovr_ES,
+/*  0x27 */ x86emuOp_daa,
+
+/*  0x28 */ x86emuOp_genop_byte_RM_R,
+/*  0x29 */ x86emuOp_genop_word_RM_R,
+/*  0x2a */ x86emuOp_genop_byte_R_RM,
+/*  0x2b */ x86emuOp_genop_word_R_RM,
+/*  0x2c */ x86emuOp_genop_byte_AL_IMM,
+/*  0x2d */ x86emuOp_genop_word_AX_IMM,
+/*  0x2e */ x86emuOp_segovr_CS,
+/*  0x2f */ x86emuOp_das,
+
+/*  0x30 */ x86emuOp_genop_byte_RM_R,
+/*  0x31 */ x86emuOp_genop_word_RM_R,
+/*  0x32 */ x86emuOp_genop_byte_R_RM,
+/*  0x33 */ x86emuOp_genop_word_R_RM,
+/*  0x34 */ x86emuOp_genop_byte_AL_IMM,
+/*  0x35 */ x86emuOp_genop_word_AX_IMM,
+/*  0x36 */ x86emuOp_segovr_SS,
+/*  0x37 */ x86emuOp_aaa,
+
+/*  0x38 */ x86emuOp_genop_byte_RM_R,
+/*  0x39 */ x86emuOp_genop_word_RM_R,
+/*  0x3a */ x86emuOp_genop_byte_R_RM,
+/*  0x3b */ x86emuOp_genop_word_R_RM,
+/*  0x3c */ x86emuOp_genop_byte_AL_IMM,
+/*  0x3d */ x86emuOp_genop_word_AX_IMM,
+/*  0x3e */ x86emuOp_segovr_DS,
+/*  0x3f */ x86emuOp_aas,
+
+/*  0x40 */ x86emuOp_inc_register,
+/*  0x41 */ x86emuOp_inc_register,
+/*  0x42 */ x86emuOp_inc_register,
+/*  0x43 */ x86emuOp_inc_register,
+/*  0x44 */ x86emuOp_inc_register,
+/*  0x45 */ x86emuOp_inc_register,
+/*  0x46 */ x86emuOp_inc_register,
+/*  0x47 */ x86emuOp_inc_register,
+
+/*  0x48 */ x86emuOp_dec_register,
+/*  0x49 */ x86emuOp_dec_register,
+/*  0x4a */ x86emuOp_dec_register,
+/*  0x4b */ x86emuOp_dec_register,
+/*  0x4c */ x86emuOp_dec_register,
+/*  0x4d */ x86emuOp_dec_register,
+/*  0x4e */ x86emuOp_dec_register,
+/*  0x4f */ x86emuOp_dec_register,
+
+/*  0x50 */ x86emuOp_push_register,
+/*  0x51 */ x86emuOp_push_register,
+/*  0x52 */ x86emuOp_push_register,
+/*  0x53 */ x86emuOp_push_register,
+/*  0x54 */ x86emuOp_push_register,
+/*  0x55 */ x86emuOp_push_register,
+/*  0x56 */ x86emuOp_push_register,
+/*  0x57 */ x86emuOp_push_register,
+
+/*  0x58 */ x86emuOp_pop_register,
+/*  0x59 */ x86emuOp_pop_register,
+/*  0x5a */ x86emuOp_pop_register,
+/*  0x5b */ x86emuOp_pop_register,
+/*  0x5c */ x86emuOp_pop_register,
+/*  0x5d */ x86emuOp_pop_register,
+/*  0x5e */ x86emuOp_pop_register,
+/*  0x5f */ x86emuOp_pop_register,
+
+/*  0x60 */ x86emuOp_push_all,
+/*  0x61 */ x86emuOp_pop_all,
+/*  0x62 */ x86emuOp_illegal_op,   /* bound */
+/*  0x63 */ x86emuOp_illegal_op,   /* arpl */
+/*  0x64 */ x86emuOp_segovr_FS,
+/*  0x65 */ x86emuOp_segovr_GS,
+/*  0x66 */ x86emuOp_prefix_data,
+/*  0x67 */ x86emuOp_prefix_addr,
+
+/*  0x68 */ x86emuOp_push_word_IMM,
+/*  0x69 */ x86emuOp_imul_word_IMM,
+/*  0x6a */ x86emuOp_push_byte_IMM,
+/*  0x6b */ x86emuOp_imul_byte_IMM,
+/*  0x6c */ x86emuOp_ins_byte,
+/*  0x6d */ x86emuOp_ins_word,
+/*  0x6e */ x86emuOp_outs_byte,
+/*  0x6f */ x86emuOp_outs_word,
+
+/*  0x70 */ x86emuOp_jump_near_cond,
+/*  0x71 */ x86emuOp_jump_near_cond,
+/*  0x72 */ x86emuOp_jump_near_cond,
+/*  0x73 */ x86emuOp_jump_near_cond,
+/*  0x74 */ x86emuOp_jump_near_cond,
+/*  0x75 */ x86emuOp_jump_near_cond,
+/*  0x76 */ x86emuOp_jump_near_cond,
+/*  0x77 */ x86emuOp_jump_near_cond,
+
+/*  0x78 */ x86emuOp_jump_near_cond,
+/*  0x79 */ x86emuOp_jump_near_cond,
+/*  0x7a */ x86emuOp_jump_near_cond,
+/*  0x7b */ x86emuOp_jump_near_cond,
+/*  0x7c */ x86emuOp_jump_near_cond,
+/*  0x7d */ x86emuOp_jump_near_cond,
+/*  0x7e */ x86emuOp_jump_near_cond,
+/*  0x7f */ x86emuOp_jump_near_cond,
+
+/*  0x80 */ x86emuOp_opc80_byte_RM_IMM,
+/*  0x81 */ x86emuOp_opc81_word_RM_IMM,
+/*  0x82 */ x86emuOp_opc82_byte_RM_IMM,
+/*  0x83 */ x86emuOp_opc83_word_RM_IMM,
+/*  0x84 */ x86emuOp_test_byte_RM_R,
+/*  0x85 */ x86emuOp_test_word_RM_R,
+/*  0x86 */ x86emuOp_xchg_byte_RM_R,
+/*  0x87 */ x86emuOp_xchg_word_RM_R,
+
+/*  0x88 */ x86emuOp_mov_byte_RM_R,
+/*  0x89 */ x86emuOp_mov_word_RM_R,
+/*  0x8a */ x86emuOp_mov_byte_R_RM,
+/*  0x8b */ x86emuOp_mov_word_R_RM,
+/*  0x8c */ x86emuOp_mov_word_RM_SR,
+/*  0x8d */ x86emuOp_lea_word_R_M,
+/*  0x8e */ x86emuOp_mov_word_SR_RM,
+/*  0x8f */ x86emuOp_pop_RM,
+
+/*  0x90 */ x86emuOp_nop,
+/*  0x91 */ x86emuOp_xchg_word_AX_register,
+/*  0x92 */ x86emuOp_xchg_word_AX_register,
+/*  0x93 */ x86emuOp_xchg_word_AX_register,
+/*  0x94 */ x86emuOp_xchg_word_AX_register,
+/*  0x95 */ x86emuOp_xchg_word_AX_register,
+/*  0x96 */ x86emuOp_xchg_word_AX_register,
+/*  0x97 */ x86emuOp_xchg_word_AX_register,
+
+/*  0x98 */ x86emuOp_cbw,
+/*  0x99 */ x86emuOp_cwd,
+/*  0x9a */ x86emuOp_call_far_IMM,
+/*  0x9b */ x86emuOp_wait,
+/*  0x9c */ x86emuOp_pushf_word,
+/*  0x9d */ x86emuOp_popf_word,
+/*  0x9e */ x86emuOp_sahf,
+/*  0x9f */ x86emuOp_lahf,
+
+/*  0xa0 */ x86emuOp_mov_AL_M_IMM,
+/*  0xa1 */ x86emuOp_mov_AX_M_IMM,
+/*  0xa2 */ x86emuOp_mov_M_AL_IMM,
+/*  0xa3 */ x86emuOp_mov_M_AX_IMM,
+/*  0xa4 */ x86emuOp_movs_byte,
+/*  0xa5 */ x86emuOp_movs_word,
+/*  0xa6 */ x86emuOp_cmps_byte,
+/*  0xa7 */ x86emuOp_cmps_word,
+/*  0xa8 */ x86emuOp_test_AL_IMM,
+/*  0xa9 */ x86emuOp_test_AX_IMM,
+/*  0xaa */ x86emuOp_stos_byte,
+/*  0xab */ x86emuOp_stos_word,
+/*  0xac */ x86emuOp_lods_byte,
+/*  0xad */ x86emuOp_lods_word,
+/*  0xac */ x86emuOp_scas_byte,
+/*  0xad */ x86emuOp_scas_word,
+
+/*  0xb0 */ x86emuOp_mov_byte_register_IMM,
+/*  0xb1 */ x86emuOp_mov_byte_register_IMM,
+/*  0xb2 */ x86emuOp_mov_byte_register_IMM,
+/*  0xb3 */ x86emuOp_mov_byte_register_IMM,
+/*  0xb4 */ x86emuOp_mov_byte_register_IMM,
+/*  0xb5 */ x86emuOp_mov_byte_register_IMM,
+/*  0xb6 */ x86emuOp_mov_byte_register_IMM,
+/*  0xb7 */ x86emuOp_mov_byte_register_IMM,
+
+/*  0xb8 */ x86emuOp_mov_word_register_IMM,
+/*  0xb9 */ x86emuOp_mov_word_register_IMM,
+/*  0xba */ x86emuOp_mov_word_register_IMM,
+/*  0xbb */ x86emuOp_mov_word_register_IMM,
+/*  0xbc */ x86emuOp_mov_word_register_IMM,
+/*  0xbd */ x86emuOp_mov_word_register_IMM,
+/*  0xbe */ x86emuOp_mov_word_register_IMM,
+/*  0xbf */ x86emuOp_mov_word_register_IMM,
+
+/*  0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
+/*  0xc1 */ x86emuOp_opcC1_word_RM_MEM,
+/*  0xc2 */ x86emuOp_ret_near_IMM,
+/*  0xc3 */ x86emuOp_ret_near,
+/*  0xc4 */ x86emuOp_les_R_IMM,
+/*  0xc5 */ x86emuOp_lds_R_IMM,
+/*  0xc6 */ x86emuOp_mov_byte_RM_IMM,
+/*  0xc7 */ x86emuOp_mov_word_RM_IMM,
+/*  0xc8 */ x86emuOp_enter,
+/*  0xc9 */ x86emuOp_leave,
+/*  0xca */ x86emuOp_ret_far_IMM,
+/*  0xcb */ x86emuOp_ret_far,
+/*  0xcc */ x86emuOp_int3,
+/*  0xcd */ x86emuOp_int_IMM,
+/*  0xce */ x86emuOp_into,
+/*  0xcf */ x86emuOp_iret,
+
+/*  0xd0 */ x86emuOp_opcD0_byte_RM_1,
+/*  0xd1 */ x86emuOp_opcD1_word_RM_1,
+/*  0xd2 */ x86emuOp_opcD2_byte_RM_CL,
+/*  0xd3 */ x86emuOp_opcD3_word_RM_CL,
+/*  0xd4 */ x86emuOp_aam,
+/*  0xd5 */ x86emuOp_aad,
+/*  0xd6 */ x86emuOp_illegal_op,   /* Undocumented SETALC instruction */
+/*  0xd7 */ x86emuOp_xlat,
+/*  0xd8 */ x86emuOp_esc_coprocess_d8,
+/*  0xd9 */ x86emuOp_esc_coprocess_d9,
+/*  0xda */ x86emuOp_esc_coprocess_da,
+/*  0xdb */ x86emuOp_esc_coprocess_db,
+/*  0xdc */ x86emuOp_esc_coprocess_dc,
+/*  0xdd */ x86emuOp_esc_coprocess_dd,
+/*  0xde */ x86emuOp_esc_coprocess_de,
+/*  0xdf */ x86emuOp_esc_coprocess_df,
+
+/*  0xe0 */ x86emuOp_loopne,
+/*  0xe1 */ x86emuOp_loope,
+/*  0xe2 */ x86emuOp_loop,
+/*  0xe3 */ x86emuOp_jcxz,
+/*  0xe4 */ x86emuOp_in_byte_AL_IMM,
+/*  0xe5 */ x86emuOp_in_word_AX_IMM,
+/*  0xe6 */ x86emuOp_out_byte_IMM_AL,
+/*  0xe7 */ x86emuOp_out_word_IMM_AX,
+
+/*  0xe8 */ x86emuOp_call_near_IMM,
+/*  0xe9 */ x86emuOp_jump_near_IMM,
+/*  0xea */ x86emuOp_jump_far_IMM,
+/*  0xeb */ x86emuOp_jump_byte_IMM,
+/*  0xec */ x86emuOp_in_byte_AL_DX,
+/*  0xed */ x86emuOp_in_word_AX_DX,
+/*  0xee */ x86emuOp_out_byte_DX_AL,
+/*  0xef */ x86emuOp_out_word_DX_AX,
+
+/*  0xf0 */ x86emuOp_lock,
+/*  0xf1 */ x86emuOp_illegal_op,
+/*  0xf2 */ x86emuOp_repne,
+/*  0xf3 */ x86emuOp_repe,
+/*  0xf4 */ x86emuOp_halt,
+/*  0xf5 */ x86emuOp_cmc,
+/*  0xf6 */ x86emuOp_opcF6_byte_RM,
+/*  0xf7 */ x86emuOp_opcF7_word_RM,
+
+/*  0xf8 */ x86emuOp_clc,
+/*  0xf9 */ x86emuOp_stc,
+/*  0xfa */ x86emuOp_cli,
+/*  0xfb */ x86emuOp_sti,
+/*  0xfc */ x86emuOp_cld,
+/*  0xfd */ x86emuOp_std,
+/*  0xfe */ x86emuOp_opcFE_byte_RM,
+/*  0xff */ x86emuOp_opcFF_word_RM,
+};
diff --git a/util/x86emu/x86emu/ops.h b/util/x86emu/x86emu/ops.h
new file mode 100644
index 0000000..65ea676
--- /dev/null
+++ b/util/x86emu/x86emu/ops.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+*
+*						Realmode X86 Emulator Library
+*
+*            	Copyright (C) 1996-1999 SciTech Software, Inc.
+* 				     Copyright (C) David Mosberger-Tang
+* 					   Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:		ANSI C
+* Environment:	Any
+* Developer:    Kendall Bennett
+*
+* Description:  Header file for operand decoding functions.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_OPS_H
+#define __X86EMU_OPS_H
+
+extern void (*x86emu_optab[0x100])(u8 op1);
+extern void (*x86emu_optab2[0x100])(u8 op2);
+
+#endif /* __X86EMU_OPS_H */
diff --git a/util/x86emu/x86emu/ops2.c b/util/x86emu/x86emu/ops2.c
new file mode 100644
index 0000000..53a7776
--- /dev/null
+++ b/util/x86emu/x86emu/ops2.c
@@ -0,0 +1,1825 @@
+/****************************************************************************
+*
+*                       Realmode X86 Emulator Library
+*
+*               Copyright (C) 1991-2004 SciTech Software, Inc.
+*                    Copyright (C) David Mosberger-Tang
+*                      Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:     ANSI C
+* Environment:  Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file includes subroutines to implement the decoding
+*               and emulation of all the x86 extended two-byte processor
+*               instructions.
+*
+****************************************************************************/
+
+#include "x86emui.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+op1 - Instruction op code
+
+REMARKS:
+Handles illegal opcodes.
+****************************************************************************/
+void x86emuOp2_illegal_op(
+    u8 op2)
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
+    TRACE_REGS();
+    printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
+        M.x86.R_CS, M.x86.R_IP-2,op2);
+    HALT_SYS();
+    END_OF_INSTR();
+}
+
+#define xorl(a,b)   (((a) && !(b)) || (!(a) && (b)))
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0x80-0x8F
+****************************************************************************/
+int x86emu_check_jump_condition(u8 op)
+{
+    switch (op) {
+      case 0x0:
+        DECODE_PRINTF("JO\t");
+        return ACCESS_FLAG(F_OF);
+      case 0x1:
+        DECODE_PRINTF("JNO\t");
+        return !ACCESS_FLAG(F_OF);
+        break;
+      case 0x2:
+        DECODE_PRINTF("JB\t");
+        return ACCESS_FLAG(F_CF);
+        break;
+      case 0x3:
+        DECODE_PRINTF("JNB\t");
+        return !ACCESS_FLAG(F_CF);
+        break;
+      case 0x4:
+        DECODE_PRINTF("JZ\t");
+        return ACCESS_FLAG(F_ZF);
+        break;
+      case 0x5:
+        DECODE_PRINTF("JNZ\t");
+        return !ACCESS_FLAG(F_ZF);
+        break;
+      case 0x6:
+        DECODE_PRINTF("JBE\t");
+        return ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
+        break;
+      case 0x7:
+        DECODE_PRINTF("JNBE\t");
+        return !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
+        break;
+      case 0x8:
+        DECODE_PRINTF("JS\t");
+        return ACCESS_FLAG(F_SF);
+        break;
+      case 0x9:
+        DECODE_PRINTF("JNS\t");
+        return !ACCESS_FLAG(F_SF);
+        break;
+      case 0xa:
+        DECODE_PRINTF("JP\t");
+        return ACCESS_FLAG(F_PF);
+        break;
+      case 0xb:
+        DECODE_PRINTF("JNP\t");
+        return !ACCESS_FLAG(F_PF);
+        break;
+      case 0xc:
+        DECODE_PRINTF("JL\t");
+        return xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+        break;
+      case 0xd:
+        DECODE_PRINTF("JNL\t");
+        return !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+        break;
+      case 0xe:
+        DECODE_PRINTF("JLE\t");
+        return (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+                ACCESS_FLAG(F_ZF));
+        break;
+      default:
+        DECODE_PRINTF("JNLE\t");
+        return !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+                 ACCESS_FLAG(F_ZF));
+    }
+}
+
+void x86emuOp2_long_jump(u8 op2)
+{
+    s32 target;
+    int cond;
+
+    /* conditional jump to word offset. */
+    START_OF_INSTR();
+    cond = x86emu_check_jump_condition(op2 & 0xF);
+    target = (s16) fetch_word_imm();
+    target += (s16) M.x86.R_IP;
+    DECODE_PRINTF2("%04x\n", target);
+    TRACE_AND_STEP();
+    if (cond) {
+        M.x86.R_IP = (u16)target;
+	JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " LONG COND ");
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xC8-0xCF
+****************************************************************************/
+s32 x86emu_bswap(s32 reg)
+{
+   // perform the byte swap
+   s32 temp = reg;
+   reg = (temp & 0xFF000000) >> 24;
+   reg |= (temp & 0xFF0000) >> 8;
+   reg |= (temp & 0xFF00) << 8;
+   reg |= (temp & 0xFF) << 24;
+   return reg;
+}
+
+void x86emuOp2_bswap(u8 op2)
+{
+    /* byte swap 32 bit register */
+    START_OF_INSTR();
+    DECODE_PRINTF("BSWAP\t");
+    switch (op2) {
+      case 0xc8:
+        DECODE_PRINTF("EAX\n");
+        M.x86.R_EAX = x86emu_bswap(M.x86.R_EAX);
+        break;
+      case 0xc9:
+        DECODE_PRINTF("ECX\n");
+        M.x86.R_ECX = x86emu_bswap(M.x86.R_ECX);
+        break;
+      case 0xca:
+        DECODE_PRINTF("EDX\n");
+        M.x86.R_EDX = x86emu_bswap(M.x86.R_EDX);
+        break;
+      case 0xcb:
+        DECODE_PRINTF("EBX\n");
+        M.x86.R_EBX = x86emu_bswap(M.x86.R_EBX);
+        break;
+      case 0xcc:
+        DECODE_PRINTF("ESP\n");
+        M.x86.R_ESP = x86emu_bswap(M.x86.R_ESP);
+        break;
+      case 0xcd:
+        DECODE_PRINTF("EBP\n");
+        M.x86.R_EBP = x86emu_bswap(M.x86.R_EBP);
+        break;
+      case 0xce:
+        DECODE_PRINTF("ESI\n");
+        M.x86.R_ESI = x86emu_bswap(M.x86.R_ESI);
+        break;
+      case 0xcf:
+        DECODE_PRINTF("EDI\n");
+        M.x86.R_EDI = x86emu_bswap(M.x86.R_EDI);
+        break;
+    }
+    TRACE_AND_STEP();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0x90-0x9F
+****************************************************************************/
+void x86emuOp2_set_byte(u8 op2)
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8  *destreg;
+    char *name = 0;
+    int cond = 0;
+
+    START_OF_INSTR();
+    switch (op2) {
+      case 0x90:
+        name = "SETO\t";
+        cond =  ACCESS_FLAG(F_OF);
+        break;
+      case 0x91:
+        name = "SETNO\t";
+        cond = !ACCESS_FLAG(F_OF);
+        break;
+      case 0x92:
+        name = "SETB\t";
+        cond = ACCESS_FLAG(F_CF);
+        break;
+      case 0x93:
+        name = "SETNB\t";
+        cond = !ACCESS_FLAG(F_CF);
+        break;
+      case 0x94:
+        name = "SETZ\t";
+        cond = ACCESS_FLAG(F_ZF);
+        break;
+      case 0x95:
+        name = "SETNZ\t";
+        cond = !ACCESS_FLAG(F_ZF);
+        break;
+      case 0x96:
+        name = "SETBE\t";
+        cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
+        break;
+      case 0x97:
+        name = "SETNBE\t";
+        cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
+        break;
+      case 0x98:
+        name = "SETS\t";
+        cond = ACCESS_FLAG(F_SF);
+        break;
+      case 0x99:
+        name = "SETNS\t";
+        cond = !ACCESS_FLAG(F_SF);
+        break;
+      case 0x9a:
+        name = "SETP\t";
+        cond = ACCESS_FLAG(F_PF);
+        break;
+      case 0x9b:
+        name = "SETNP\t";
+        cond = !ACCESS_FLAG(F_PF);
+        break;
+      case 0x9c:
+        name = "SETL\t";
+        cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+        break;
+      case 0x9d:
+        name = "SETNL\t";
+        cond = !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+        break;
+      case 0x9e:
+        name = "SETLE\t";
+        cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+                ACCESS_FLAG(F_ZF));
+        break;
+      case 0x9f:
+        name = "SETNLE\t";
+        cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+                 ACCESS_FLAG(F_ZF));
+        break;
+    }
+    DECODE_PRINTF(name);
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        TRACE_AND_STEP();
+        store_data_byte(destoffset, cond ? 0x01 : 0x00);
+    } else {                     /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        TRACE_AND_STEP();
+        *destreg = cond ? 0x01 : 0x00;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa0
+****************************************************************************/
+void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("PUSH\tFS\n");
+    TRACE_AND_STEP();
+    push_word(M.x86.R_FS);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa1
+****************************************************************************/
+void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("POP\tFS\n");
+    TRACE_AND_STEP();
+    M.x86.R_FS = pop_word();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa3
+****************************************************************************/
+void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+    int bit,disp;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("BT\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        srcoffset = decode_rmXX_address(mod, rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval;
+            u32 *shiftreg;
+
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0x1F;
+            disp = (s16)*shiftreg >> 5;
+            srcval = fetch_data_long(srcoffset+disp);
+            CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
+        } else {
+            u16 srcval;
+            u16 *shiftreg;
+
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0xF;
+            disp = (s16)*shiftreg >> 4;
+            srcval = fetch_data_word(srcoffset+disp);
+            CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg,*shiftreg;
+
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0x1F;
+            CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
+        } else {
+            u16 *srcreg,*shiftreg;
+
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0xF;
+            CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa4
+****************************************************************************/
+void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 shift;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SHLD\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            DECODE_PRINTF2("%d\n", shift);
+            TRACE_AND_STEP();
+            destval = fetch_data_long(destoffset);
+            destval = shld_long(destval,*shiftreg,shift);
+            store_data_long(destoffset, destval);
+        } else {
+            u16 destval;
+            u16 *shiftreg;
+
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            DECODE_PRINTF2("%d\n", shift);
+            TRACE_AND_STEP();
+            destval = fetch_data_word(destoffset);
+            destval = shld_word(destval,*shiftreg,shift);
+            store_data_word(destoffset, destval);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg,*shiftreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            DECODE_PRINTF2("%d\n", shift);
+            TRACE_AND_STEP();
+            *destreg = shld_long(*destreg,*shiftreg,shift);
+        } else {
+            u16 *destreg,*shiftreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            DECODE_PRINTF2("%d\n", shift);
+            TRACE_AND_STEP();
+            *destreg = shld_word(*destreg,*shiftreg,shift);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa5
+****************************************************************************/
+void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SHLD\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",CL\n");
+            TRACE_AND_STEP();
+            destval = fetch_data_long(destoffset);
+            destval = shld_long(destval,*shiftreg,M.x86.R_CL);
+            store_data_long(destoffset, destval);
+        } else {
+            u16 destval;
+            u16 *shiftreg;
+
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",CL\n");
+            TRACE_AND_STEP();
+            destval = fetch_data_word(destoffset);
+            destval = shld_word(destval,*shiftreg,M.x86.R_CL);
+            store_data_word(destoffset, destval);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg,*shiftreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",CL\n");
+            TRACE_AND_STEP();
+            *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL);
+        } else {
+            u16 *destreg,*shiftreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",CL\n");
+            TRACE_AND_STEP();
+            *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa8
+****************************************************************************/
+void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("PUSH\tGS\n");
+    TRACE_AND_STEP();
+    push_word(M.x86.R_GS);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa9
+****************************************************************************/
+void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("POP\tGS\n");
+    TRACE_AND_STEP();
+    M.x86.R_GS = pop_word();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xaa
+****************************************************************************/
+void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+    int bit,disp;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("BTS\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        srcoffset = decode_rmXX_address(mod, rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval,mask;
+            u32 *shiftreg;
+
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0x1F;
+            disp = (s16)*shiftreg >> 5;
+            srcval = fetch_data_long(srcoffset+disp);
+            mask = (0x1 << bit);
+            CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+            store_data_long(srcoffset+disp, srcval | mask);
+        } else {
+            u16 srcval,mask;
+            u16 *shiftreg;
+
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0xF;
+            disp = (s16)*shiftreg >> 4;
+            srcval = fetch_data_word(srcoffset+disp);
+            mask = (u16)(0x1 << bit);
+            CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+            store_data_word(srcoffset+disp, srcval | mask);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg,*shiftreg;
+            u32 mask;
+
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0x1F;
+            mask = (0x1 << bit);
+            CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+            *srcreg |= mask;
+        } else {
+            u16 *srcreg,*shiftreg;
+            u16 mask;
+
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0xF;
+            mask = (u16)(0x1 << bit);
+            CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+            *srcreg |= mask;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xac
+****************************************************************************/
+void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 shift;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SHLD\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            DECODE_PRINTF2("%d\n", shift);
+            TRACE_AND_STEP();
+            destval = fetch_data_long(destoffset);
+            destval = shrd_long(destval,*shiftreg,shift);
+            store_data_long(destoffset, destval);
+        } else {
+            u16 destval;
+            u16 *shiftreg;
+
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            DECODE_PRINTF2("%d\n", shift);
+            TRACE_AND_STEP();
+            destval = fetch_data_word(destoffset);
+            destval = shrd_word(destval,*shiftreg,shift);
+            store_data_word(destoffset, destval);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg,*shiftreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            DECODE_PRINTF2("%d\n", shift);
+            TRACE_AND_STEP();
+            *destreg = shrd_long(*destreg,*shiftreg,shift);
+        } else {
+            u16 *destreg,*shiftreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            DECODE_PRINTF2("%d\n", shift);
+            TRACE_AND_STEP();
+            *destreg = shrd_word(*destreg,*shiftreg,shift);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xad
+****************************************************************************/
+void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SHLD\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",");
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",CL\n");
+            TRACE_AND_STEP();
+            destval = fetch_data_long(destoffset);
+            destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
+            store_data_long(destoffset, destval);
+        } else {
+            u16 destval;
+            u16 *shiftreg;
+
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",CL\n");
+            TRACE_AND_STEP();
+            destval = fetch_data_word(destoffset);
+            destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
+            store_data_word(destoffset, destval);
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg,*shiftreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",CL\n");
+            TRACE_AND_STEP();
+            *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL);
+        } else {
+            u16 *destreg,*shiftreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",CL\n");
+            TRACE_AND_STEP();
+            *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xaf
+****************************************************************************/
+void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("IMUL\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+            u32 res_lo,res_hi;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rmXX_address(mod, rl);
+            srcval = fetch_data_long(srcoffset);
+            TRACE_AND_STEP();
+            imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
+            if (res_hi != 0) {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            } else {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            }
+            *destreg = (u32)res_lo;
+        } else {
+            u16 *destreg;
+            u16 srcval;
+            u32 res;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rmXX_address(mod, rl);
+            srcval = fetch_data_word(srcoffset);
+            TRACE_AND_STEP();
+            res = (s16)*destreg * (s16)srcval;
+            if (res > 0xFFFF) {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            } else {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            }
+            *destreg = (u16)res;
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg,*srcreg;
+            u32 res_lo,res_hi;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            TRACE_AND_STEP();
+            imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg);
+            if (res_hi != 0) {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            } else {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            }
+            *destreg = (u32)res_lo;
+        } else {
+            u16 *destreg,*srcreg;
+            u32 res;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            res = (s16)*destreg * (s16)*srcreg;
+            if (res > 0xFFFF) {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            } else {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            }
+            *destreg = (u16)res;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb2
+****************************************************************************/
+void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rh, rl;
+    u16 *dstreg;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("LSS\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_SS = fetch_data_word(srcoffset + 2);
+    } else {                     /* register to register */
+        /* UNDEFINED! */
+        TRACE_AND_STEP();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb3
+****************************************************************************/
+void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+    int bit,disp;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("BTR\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        srcoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",");
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval,mask;
+            u32 *shiftreg;
+
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0x1F;
+            disp = (s16)*shiftreg >> 5;
+            srcval = fetch_data_long(srcoffset+disp);
+            mask = (0x1 << bit);
+            CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+            store_data_long(srcoffset+disp, srcval & ~mask);
+        } else {
+            u16 srcval,mask;
+            u16 *shiftreg;
+
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0xF;
+            disp = (s16)*shiftreg >> 4;
+            srcval = fetch_data_word(srcoffset+disp);
+            mask = (u16)(0x1 << bit);
+            CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+            store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg,*shiftreg;
+            u32 mask;
+
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0x1F;
+            mask = (0x1 << bit);
+            CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+            *srcreg &= ~mask;
+        } else {
+            u16 *srcreg,*shiftreg;
+            u16 mask;
+
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0xF;
+            mask = (u16)(0x1 << bit);
+            CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+            *srcreg &= ~mask;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb4
+****************************************************************************/
+void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rh, rl;
+    u16 *dstreg;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("LFS\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_FS = fetch_data_word(srcoffset + 2);
+    } else {                     /* register to register */
+        /* UNDEFINED! */
+        TRACE_AND_STEP();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb5
+****************************************************************************/
+void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rh, rl;
+    u16 *dstreg;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("LGS\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_GS = fetch_data_word(srcoffset + 2);
+    } else {                     /* register to register */
+        /* UNDEFINED! */
+        TRACE_AND_STEP();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb6
+****************************************************************************/
+void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOVZX\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rmXX_address(mod, rl);
+            srcval = fetch_data_byte(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        } else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rmXX_address(mod, rl);
+            srcval = fetch_data_byte(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u8  *srcreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_BYTE_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = *srcreg;
+        } else {
+            u16 *destreg;
+            u8  *srcreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_BYTE_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = *srcreg;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb7
+****************************************************************************/
+void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+    u32 *destreg;
+    u32 srcval;
+    u16 *srcreg;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOVZX\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destreg = DECODE_RM_LONG_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rmXX_address(mod, rl);
+        srcval = fetch_data_word(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+    } else {                     /* register to register */
+        destreg = DECODE_RM_LONG_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_WORD_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = *srcreg;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xba
+****************************************************************************/
+void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+    u8 shift;
+    int bit;
+
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (rh) {
+    case 4:
+        DECODE_PRINTF("BT\t");
+        break;
+    case 5:
+        DECODE_PRINTF("BTS\t");
+        break;
+    case 6:
+        DECODE_PRINTF("BTR\t");
+        break;
+    case 7:
+        DECODE_PRINTF("BTC\t");
+        break;
+    default:
+        DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
+        TRACE_REGS();
+        printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
+                M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl);
+        HALT_SYS();
+    }
+    if (mod < 3) {
+
+        srcoffset = decode_rmXX_address(mod, rl);
+        shift = fetch_byte_imm();
+        DECODE_PRINTF2(",%d\n", shift);
+        TRACE_AND_STEP();
+
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+
+            bit = shift & 0x1F;
+            srcval = fetch_data_long(srcoffset);
+            mask = (0x1 << bit);
+            CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+            switch (rh) {
+            case 5:
+                store_data_long(srcoffset, srcval | mask);
+                break;
+            case 6:
+                store_data_long(srcoffset, srcval & ~mask);
+                break;
+            case 7:
+                store_data_long(srcoffset, srcval ^ mask);
+                break;
+            default:
+                break;
+            }
+        } else {
+            u16 srcval, mask;
+
+            bit = shift & 0xF;
+            srcval = fetch_data_word(srcoffset);
+            mask = (0x1 << bit);
+            CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+            switch (rh) {
+            case 5:
+                store_data_word(srcoffset, srcval | mask);
+                break;
+            case 6:
+                store_data_word(srcoffset, srcval & ~mask);
+                break;
+            case 7:
+                store_data_word(srcoffset, srcval ^ mask);
+                break;
+            default:
+                break;
+            }
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg;
+            u32 mask;
+
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            shift = fetch_byte_imm();
+            DECODE_PRINTF2(",%d\n", shift);
+            TRACE_AND_STEP();
+            bit = shift & 0x1F;
+            mask = (0x1 << bit);
+            CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+            switch (rh) {
+            case 5:
+                *srcreg |= mask;
+                break;
+            case 6:
+                *srcreg &= ~mask;
+                break;
+            case 7:
+                *srcreg ^= mask;
+                break;
+            default:
+                break;
+            }
+        } else {
+            u16 *srcreg;
+            u16 mask;
+
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            shift = fetch_byte_imm();
+            DECODE_PRINTF2(",%d\n", shift);
+            TRACE_AND_STEP();
+            bit = shift & 0xF;
+            mask = (0x1 << bit);
+            CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+            switch (rh) {
+            case 5:
+                *srcreg |= mask;
+                break;
+            case 6:
+                *srcreg &= ~mask;
+                break;
+            case 7:
+                *srcreg ^= mask;
+                break;
+            default:
+                break;
+            }
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbb
+****************************************************************************/
+void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+    int bit,disp;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("BTC\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        srcoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",");
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval,mask;
+            u32 *shiftreg;
+
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0x1F;
+            disp = (s16)*shiftreg >> 5;
+            srcval = fetch_data_long(srcoffset+disp);
+            mask = (0x1 << bit);
+            CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+            store_data_long(srcoffset+disp, srcval ^ mask);
+        } else {
+            u16 srcval,mask;
+            u16 *shiftreg;
+
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0xF;
+            disp = (s16)*shiftreg >> 4;
+            srcval = fetch_data_word(srcoffset+disp);
+            mask = (u16)(0x1 << bit);
+            CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+            store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg,*shiftreg;
+            u32 mask;
+
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0x1F;
+            mask = (0x1 << bit);
+            CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+            *srcreg ^= mask;
+        } else {
+            u16 *srcreg,*shiftreg;
+            u16 mask;
+
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shiftreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            bit = *shiftreg & 0xF;
+            mask = (u16)(0x1 << bit);
+            CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+            *srcreg ^= mask;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbc
+****************************************************************************/
+void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("BSF\n");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        srcoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",");
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, *dstreg;
+
+            dstreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            srcval = fetch_data_long(srcoffset);
+            CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+            for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
+                if ((srcval >> *dstreg) & 1) break;
+        } else {
+            u16 srcval, *dstreg;
+
+            dstreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            srcval = fetch_data_word(srcoffset);
+            CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+            for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
+                if ((srcval >> *dstreg) & 1) break;
+        }
+    } else {             /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg, *dstreg;
+
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            dstreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
+            for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
+                if ((*srcreg >> *dstreg) & 1) break;
+        } else {
+            u16 *srcreg, *dstreg;
+
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            dstreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
+            for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
+                if ((*srcreg >> *dstreg) & 1) break;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbd
+****************************************************************************/
+void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("BSF\n");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        srcoffset = decode_rmXX_address(mod, rl);
+        DECODE_PRINTF(",");
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, *dstreg;
+
+            dstreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            srcval = fetch_data_long(srcoffset);
+            CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+            for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
+                if ((srcval >> *dstreg) & 1) break;
+        } else {
+            u16 srcval, *dstreg;
+
+            dstreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            srcval = fetch_data_word(srcoffset);
+            CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+            for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
+                if ((srcval >> *dstreg) & 1) break;
+        }
+    } else {             /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg, *dstreg;
+
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            dstreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
+            for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
+                if ((*srcreg >> *dstreg) & 1) break;
+        } else {
+            u16 *srcreg, *dstreg;
+
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            dstreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
+            for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
+                if ((*srcreg >> *dstreg) & 1) break;
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbe
+****************************************************************************/
+void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOVSX\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rmXX_address(mod, rl);
+            srcval = (s32)((s8)fetch_data_byte(srcoffset));
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        } else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rmXX_address(mod, rl);
+            srcval = (s16)((s8)fetch_data_byte(srcoffset));
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        }
+    } else {                     /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u8  *srcreg;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_BYTE_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = (s32)((s8)*srcreg);
+        } else {
+            u16 *destreg;
+            u8  *srcreg;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_BYTE_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = (s16)((s8)*srcreg);
+        }
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbf
+****************************************************************************/
+void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+    u32 *destreg;
+    u32 srcval;
+    u16 *srcreg;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOVSX\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    if (mod < 3) {
+        destreg = DECODE_RM_LONG_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rmXX_address(mod, rl);
+        srcval = (s32)((s16)fetch_data_word(srcoffset));
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+    } else {                     /* register to register */
+        destreg = DECODE_RM_LONG_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_WORD_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = (s32)((s16)*srcreg);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/***************************************************************************
+ * Double byte operation code table:
+ **************************************************************************/
+void (*x86emu_optab2[256])(u8) =
+{
+/*  0x00 */ x86emuOp2_illegal_op,  /* Group F (ring 0 PM)      */
+/*  0x01 */ x86emuOp2_illegal_op,  /* Group G (ring 0 PM)      */
+/*  0x02 */ x86emuOp2_illegal_op,  /* lar (ring 0 PM)          */
+/*  0x03 */ x86emuOp2_illegal_op,  /* lsl (ring 0 PM)          */
+/*  0x04 */ x86emuOp2_illegal_op,
+/*  0x05 */ x86emuOp2_illegal_op,  /* loadall (undocumented)   */
+/*  0x06 */ x86emuOp2_illegal_op,  /* clts (ring 0 PM)         */
+/*  0x07 */ x86emuOp2_illegal_op,  /* loadall (undocumented)   */
+/*  0x08 */ x86emuOp2_illegal_op,  /* invd (ring 0 PM)         */
+/*  0x09 */ x86emuOp2_illegal_op,  /* wbinvd (ring 0 PM)       */
+/*  0x0a */ x86emuOp2_illegal_op,
+/*  0x0b */ x86emuOp2_illegal_op,
+/*  0x0c */ x86emuOp2_illegal_op,
+/*  0x0d */ x86emuOp2_illegal_op,
+/*  0x0e */ x86emuOp2_illegal_op,
+/*  0x0f */ x86emuOp2_illegal_op,
+
+/*  0x10 */ x86emuOp2_illegal_op,
+/*  0x11 */ x86emuOp2_illegal_op,
+/*  0x12 */ x86emuOp2_illegal_op,
+/*  0x13 */ x86emuOp2_illegal_op,
+/*  0x14 */ x86emuOp2_illegal_op,
+/*  0x15 */ x86emuOp2_illegal_op,
+/*  0x16 */ x86emuOp2_illegal_op,
+/*  0x17 */ x86emuOp2_illegal_op,
+/*  0x18 */ x86emuOp2_illegal_op,
+/*  0x19 */ x86emuOp2_illegal_op,
+/*  0x1a */ x86emuOp2_illegal_op,
+/*  0x1b */ x86emuOp2_illegal_op,
+/*  0x1c */ x86emuOp2_illegal_op,
+/*  0x1d */ x86emuOp2_illegal_op,
+/*  0x1e */ x86emuOp2_illegal_op,
+/*  0x1f */ x86emuOp2_illegal_op,
+
+/*  0x20 */ x86emuOp2_illegal_op,  /* mov reg32,creg (ring 0 PM) */
+/*  0x21 */ x86emuOp2_illegal_op,  /* mov reg32,dreg (ring 0 PM) */
+/*  0x22 */ x86emuOp2_illegal_op,  /* mov creg,reg32 (ring 0 PM) */
+/*  0x23 */ x86emuOp2_illegal_op,  /* mov dreg,reg32 (ring 0 PM) */
+/*  0x24 */ x86emuOp2_illegal_op,  /* mov reg32,treg (ring 0 PM) */
+/*  0x25 */ x86emuOp2_illegal_op,
+/*  0x26 */ x86emuOp2_illegal_op,  /* mov treg,reg32 (ring 0 PM) */
+/*  0x27 */ x86emuOp2_illegal_op,
+/*  0x28 */ x86emuOp2_illegal_op,
+/*  0x29 */ x86emuOp2_illegal_op,
+/*  0x2a */ x86emuOp2_illegal_op,
+/*  0x2b */ x86emuOp2_illegal_op,
+/*  0x2c */ x86emuOp2_illegal_op,
+/*  0x2d */ x86emuOp2_illegal_op,
+/*  0x2e */ x86emuOp2_illegal_op,
+/*  0x2f */ x86emuOp2_illegal_op,
+
+/*  0x30 */ x86emuOp2_illegal_op,
+/*  0x31 */ x86emuOp2_illegal_op,
+/*  0x32 */ x86emuOp2_illegal_op,
+/*  0x33 */ x86emuOp2_illegal_op,
+/*  0x34 */ x86emuOp2_illegal_op,
+/*  0x35 */ x86emuOp2_illegal_op,
+/*  0x36 */ x86emuOp2_illegal_op,
+/*  0x37 */ x86emuOp2_illegal_op,
+/*  0x38 */ x86emuOp2_illegal_op,
+/*  0x39 */ x86emuOp2_illegal_op,
+/*  0x3a */ x86emuOp2_illegal_op,
+/*  0x3b */ x86emuOp2_illegal_op,
+/*  0x3c */ x86emuOp2_illegal_op,
+/*  0x3d */ x86emuOp2_illegal_op,
+/*  0x3e */ x86emuOp2_illegal_op,
+/*  0x3f */ x86emuOp2_illegal_op,
+
+/*  0x40 */ x86emuOp2_illegal_op,
+/*  0x41 */ x86emuOp2_illegal_op,
+/*  0x42 */ x86emuOp2_illegal_op,
+/*  0x43 */ x86emuOp2_illegal_op,
+/*  0x44 */ x86emuOp2_illegal_op,
+/*  0x45 */ x86emuOp2_illegal_op,
+/*  0x46 */ x86emuOp2_illegal_op,
+/*  0x47 */ x86emuOp2_illegal_op,
+/*  0x48 */ x86emuOp2_illegal_op,
+/*  0x49 */ x86emuOp2_illegal_op,
+/*  0x4a */ x86emuOp2_illegal_op,
+/*  0x4b */ x86emuOp2_illegal_op,
+/*  0x4c */ x86emuOp2_illegal_op,
+/*  0x4d */ x86emuOp2_illegal_op,
+/*  0x4e */ x86emuOp2_illegal_op,
+/*  0x4f */ x86emuOp2_illegal_op,
+
+/*  0x50 */ x86emuOp2_illegal_op,
+/*  0x51 */ x86emuOp2_illegal_op,
+/*  0x52 */ x86emuOp2_illegal_op,
+/*  0x53 */ x86emuOp2_illegal_op,
+/*  0x54 */ x86emuOp2_illegal_op,
+/*  0x55 */ x86emuOp2_illegal_op,
+/*  0x56 */ x86emuOp2_illegal_op,
+/*  0x57 */ x86emuOp2_illegal_op,
+/*  0x58 */ x86emuOp2_illegal_op,
+/*  0x59 */ x86emuOp2_illegal_op,
+/*  0x5a */ x86emuOp2_illegal_op,
+/*  0x5b */ x86emuOp2_illegal_op,
+/*  0x5c */ x86emuOp2_illegal_op,
+/*  0x5d */ x86emuOp2_illegal_op,
+/*  0x5e */ x86emuOp2_illegal_op,
+/*  0x5f */ x86emuOp2_illegal_op,
+
+/*  0x60 */ x86emuOp2_illegal_op,
+/*  0x61 */ x86emuOp2_illegal_op,
+/*  0x62 */ x86emuOp2_illegal_op,
+/*  0x63 */ x86emuOp2_illegal_op,
+/*  0x64 */ x86emuOp2_illegal_op,
+/*  0x65 */ x86emuOp2_illegal_op,
+/*  0x66 */ x86emuOp2_illegal_op,
+/*  0x67 */ x86emuOp2_illegal_op,
+/*  0x68 */ x86emuOp2_illegal_op,
+/*  0x69 */ x86emuOp2_illegal_op,
+/*  0x6a */ x86emuOp2_illegal_op,
+/*  0x6b */ x86emuOp2_illegal_op,
+/*  0x6c */ x86emuOp2_illegal_op,
+/*  0x6d */ x86emuOp2_illegal_op,
+/*  0x6e */ x86emuOp2_illegal_op,
+/*  0x6f */ x86emuOp2_illegal_op,
+
+/*  0x70 */ x86emuOp2_illegal_op,
+/*  0x71 */ x86emuOp2_illegal_op,
+/*  0x72 */ x86emuOp2_illegal_op,
+/*  0x73 */ x86emuOp2_illegal_op,
+/*  0x74 */ x86emuOp2_illegal_op,
+/*  0x75 */ x86emuOp2_illegal_op,
+/*  0x76 */ x86emuOp2_illegal_op,
+/*  0x77 */ x86emuOp2_illegal_op,
+/*  0x78 */ x86emuOp2_illegal_op,
+/*  0x79 */ x86emuOp2_illegal_op,
+/*  0x7a */ x86emuOp2_illegal_op,
+/*  0x7b */ x86emuOp2_illegal_op,
+/*  0x7c */ x86emuOp2_illegal_op,
+/*  0x7d */ x86emuOp2_illegal_op,
+/*  0x7e */ x86emuOp2_illegal_op,
+/*  0x7f */ x86emuOp2_illegal_op,
+
+/*  0x80 */ x86emuOp2_long_jump,
+/*  0x81 */ x86emuOp2_long_jump,
+/*  0x82 */ x86emuOp2_long_jump,
+/*  0x83 */ x86emuOp2_long_jump,
+/*  0x84 */ x86emuOp2_long_jump,
+/*  0x85 */ x86emuOp2_long_jump,
+/*  0x86 */ x86emuOp2_long_jump,
+/*  0x87 */ x86emuOp2_long_jump,
+/*  0x88 */ x86emuOp2_long_jump,
+/*  0x89 */ x86emuOp2_long_jump,
+/*  0x8a */ x86emuOp2_long_jump,
+/*  0x8b */ x86emuOp2_long_jump,
+/*  0x8c */ x86emuOp2_long_jump,
+/*  0x8d */ x86emuOp2_long_jump,
+/*  0x8e */ x86emuOp2_long_jump,
+/*  0x8f */ x86emuOp2_long_jump,
+
+/*  0x90 */ x86emuOp2_set_byte,
+/*  0x91 */ x86emuOp2_set_byte,
+/*  0x92 */ x86emuOp2_set_byte,
+/*  0x93 */ x86emuOp2_set_byte,
+/*  0x94 */ x86emuOp2_set_byte,
+/*  0x95 */ x86emuOp2_set_byte,
+/*  0x96 */ x86emuOp2_set_byte,
+/*  0x97 */ x86emuOp2_set_byte,
+/*  0x98 */ x86emuOp2_set_byte,
+/*  0x99 */ x86emuOp2_set_byte,
+/*  0x9a */ x86emuOp2_set_byte,
+/*  0x9b */ x86emuOp2_set_byte,
+/*  0x9c */ x86emuOp2_set_byte,
+/*  0x9d */ x86emuOp2_set_byte,
+/*  0x9e */ x86emuOp2_set_byte,
+/*  0x9f */ x86emuOp2_set_byte,
+
+/*  0xa0 */ x86emuOp2_push_FS,
+/*  0xa1 */ x86emuOp2_pop_FS,
+/*  0xa2 */ x86emuOp2_illegal_op,
+/*  0xa3 */ x86emuOp2_bt_R,
+/*  0xa4 */ x86emuOp2_shld_IMM,
+/*  0xa5 */ x86emuOp2_shld_CL,
+/*  0xa6 */ x86emuOp2_illegal_op,
+/*  0xa7 */ x86emuOp2_illegal_op,
+/*  0xa8 */ x86emuOp2_push_GS,
+/*  0xa9 */ x86emuOp2_pop_GS,
+/*  0xaa */ x86emuOp2_illegal_op,
+/*  0xab */ x86emuOp2_bt_R,
+/*  0xac */ x86emuOp2_shrd_IMM,
+/*  0xad */ x86emuOp2_shrd_CL,
+/*  0xae */ x86emuOp2_illegal_op,
+/*  0xaf */ x86emuOp2_imul_R_RM,
+
+/*  0xb0 */ x86emuOp2_illegal_op,  /* TODO: cmpxchg */
+/*  0xb1 */ x86emuOp2_illegal_op,  /* TODO: cmpxchg */
+/*  0xb2 */ x86emuOp2_lss_R_IMM,
+/*  0xb3 */ x86emuOp2_btr_R,
+/*  0xb4 */ x86emuOp2_lfs_R_IMM,
+/*  0xb5 */ x86emuOp2_lgs_R_IMM,
+/*  0xb6 */ x86emuOp2_movzx_byte_R_RM,
+/*  0xb7 */ x86emuOp2_movzx_word_R_RM,
+/*  0xb8 */ x86emuOp2_illegal_op,
+/*  0xb9 */ x86emuOp2_illegal_op,
+/*  0xba */ x86emuOp2_btX_I,
+/*  0xbb */ x86emuOp2_btc_R,
+/*  0xbc */ x86emuOp2_bsf,
+/*  0xbd */ x86emuOp2_bsr,
+/*  0xbe */ x86emuOp2_movsx_byte_R_RM,
+/*  0xbf */ x86emuOp2_movsx_word_R_RM,
+
+/*  0xc0 */ x86emuOp2_illegal_op,  /* TODO: xadd */
+/*  0xc1 */ x86emuOp2_illegal_op,  /* TODO: xadd */
+/*  0xc2 */ x86emuOp2_illegal_op,
+/*  0xc3 */ x86emuOp2_illegal_op,
+/*  0xc4 */ x86emuOp2_illegal_op,
+/*  0xc5 */ x86emuOp2_illegal_op,
+/*  0xc6 */ x86emuOp2_illegal_op,
+/*  0xc7 */ x86emuOp2_illegal_op,
+/*  0xc8 */ x86emuOp2_bswap,
+/*  0xc9 */ x86emuOp2_bswap,
+/*  0xca */ x86emuOp2_bswap,
+/*  0xcb */ x86emuOp2_bswap,
+/*  0xcc */ x86emuOp2_bswap,
+/*  0xcd */ x86emuOp2_bswap,
+/*  0xce */ x86emuOp2_bswap,
+/*  0xcf */ x86emuOp2_bswap,
+
+/*  0xd0 */ x86emuOp2_illegal_op,
+/*  0xd1 */ x86emuOp2_illegal_op,
+/*  0xd2 */ x86emuOp2_illegal_op,
+/*  0xd3 */ x86emuOp2_illegal_op,
+/*  0xd4 */ x86emuOp2_illegal_op,
+/*  0xd5 */ x86emuOp2_illegal_op,
+/*  0xd6 */ x86emuOp2_illegal_op,
+/*  0xd7 */ x86emuOp2_illegal_op,
+/*  0xd8 */ x86emuOp2_illegal_op,
+/*  0xd9 */ x86emuOp2_illegal_op,
+/*  0xda */ x86emuOp2_illegal_op,
+/*  0xdb */ x86emuOp2_illegal_op,
+/*  0xdc */ x86emuOp2_illegal_op,
+/*  0xdd */ x86emuOp2_illegal_op,
+/*  0xde */ x86emuOp2_illegal_op,
+/*  0xdf */ x86emuOp2_illegal_op,
+
+/*  0xe0 */ x86emuOp2_illegal_op,
+/*  0xe1 */ x86emuOp2_illegal_op,
+/*  0xe2 */ x86emuOp2_illegal_op,
+/*  0xe3 */ x86emuOp2_illegal_op,
+/*  0xe4 */ x86emuOp2_illegal_op,
+/*  0xe5 */ x86emuOp2_illegal_op,
+/*  0xe6 */ x86emuOp2_illegal_op,
+/*  0xe7 */ x86emuOp2_illegal_op,
+/*  0xe8 */ x86emuOp2_illegal_op,
+/*  0xe9 */ x86emuOp2_illegal_op,
+/*  0xea */ x86emuOp2_illegal_op,
+/*  0xeb */ x86emuOp2_illegal_op,
+/*  0xec */ x86emuOp2_illegal_op,
+/*  0xed */ x86emuOp2_illegal_op,
+/*  0xee */ x86emuOp2_illegal_op,
+/*  0xef */ x86emuOp2_illegal_op,
+
+/*  0xf0 */ x86emuOp2_illegal_op,
+/*  0xf1 */ x86emuOp2_illegal_op,
+/*  0xf2 */ x86emuOp2_illegal_op,
+/*  0xf3 */ x86emuOp2_illegal_op,
+/*  0xf4 */ x86emuOp2_illegal_op,
+/*  0xf5 */ x86emuOp2_illegal_op,
+/*  0xf6 */ x86emuOp2_illegal_op,
+/*  0xf7 */ x86emuOp2_illegal_op,
+/*  0xf8 */ x86emuOp2_illegal_op,
+/*  0xf9 */ x86emuOp2_illegal_op,
+/*  0xfa */ x86emuOp2_illegal_op,
+/*  0xfb */ x86emuOp2_illegal_op,
+/*  0xfc */ x86emuOp2_illegal_op,
+/*  0xfd */ x86emuOp2_illegal_op,
+/*  0xfe */ x86emuOp2_illegal_op,
+/*  0xff */ x86emuOp2_illegal_op,
+};
diff --git a/util/x86emu/x86emu/prim_asm.h b/util/x86emu/x86emu/prim_asm.h
new file mode 100644
index 0000000..4fa8d55
--- /dev/null
+++ b/util/x86emu/x86emu/prim_asm.h
@@ -0,0 +1,971 @@
+/****************************************************************************
+*
+*						Realmode X86 Emulator Library
+*
+*            	Copyright (C) 1996-1999 SciTech Software, Inc.
+* 				     Copyright (C) David Mosberger-Tang
+* 					   Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:		Watcom C++ 10.6 or later
+* Environment:	Any
+* Developer:    Kendall Bennett
+*
+* Description:  Inline assembler versions of the primitive operand
+*				functions for faster performance. At the moment this is
+*				x86 inline assembler, but these functions could be replaced
+*				with native inline assembler for each supported processor
+*				platform.
+*
+****************************************************************************/
+/* $XFree86: xc/extras/x86emu/src/x86emu/x86emu/prim_asm.h,v 1.3 2000/04/19 15:48:15 tsi Exp $ */
+
+#ifndef	__X86EMU_PRIM_ASM_H
+#define	__X86EMU_PRIM_ASM_H
+
+#ifdef	__WATCOMC__
+
+#ifndef	VALIDATE
+#define	__HAVE_INLINE_ASSEMBLER__
+#endif
+
+u32		get_flags_asm(void);
+#pragma aux get_flags_asm =			\
+	"pushf"                         \
+	"pop	eax"                  	\
+	value [eax]                     \
+	modify exact [eax];
+
+u16     aaa_word_asm(u32 *flags,u16 d);
+#pragma aux aaa_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"aaa"                  			\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] 				\
+	value [ax]                      \
+	modify exact [ax];
+
+u16     aas_word_asm(u32 *flags,u16 d);
+#pragma aux aas_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"aas"                  			\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] 				\
+	value [ax]                      \
+	modify exact [ax];
+
+u16     aad_word_asm(u32 *flags,u16 d);
+#pragma aux aad_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"aad"                  			\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] 				\
+	value [ax]                      \
+	modify exact [ax];
+
+u16     aam_word_asm(u32 *flags,u8 d);
+#pragma aux aam_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"aam"                  			\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] 				\
+	value [ax]                      \
+	modify exact [ax];
+
+u8      adc_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux adc_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"adc	al,bl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [bl]            \
+	value [al]                      \
+	modify exact [al bl];
+
+u16     adc_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux adc_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"adc	ax,bx"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [bx]            \
+	value [ax]                      \
+	modify exact [ax bx];
+
+u32     adc_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux adc_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"adc	eax,ebx"                \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [ebx]          \
+	value [eax]                     \
+	modify exact [eax ebx];
+
+u8      add_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux add_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"add	al,bl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [bl]            \
+	value [al]                      \
+	modify exact [al bl];
+
+u16     add_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux add_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"add	ax,bx"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [bx]            \
+	value [ax]                      \
+	modify exact [ax bx];
+
+u32     add_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux add_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"add	eax,ebx"                \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [ebx]          \
+	value [eax]                     \
+	modify exact [eax ebx];
+
+u8      and_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux and_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"and	al,bl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [bl]            \
+	value [al]                      \
+	modify exact [al bl];
+
+u16     and_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux and_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"and	ax,bx"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [bx]            \
+	value [ax]                      \
+	modify exact [ax bx];
+
+u32     and_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux and_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"and	eax,ebx"                \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [ebx]          \
+	value [eax]                     \
+	modify exact [eax ebx];
+
+u8      cmp_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux cmp_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"cmp	al,bl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [bl]            \
+	value [al]                      \
+	modify exact [al bl];
+
+u16     cmp_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux cmp_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"cmp	ax,bx"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [bx]            \
+	value [ax]                      \
+	modify exact [ax bx];
+
+u32     cmp_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux cmp_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"cmp	eax,ebx"                \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [ebx]          \
+	value [eax]                     \
+	modify exact [eax ebx];
+
+u8      daa_byte_asm(u32 *flags,u8 d);
+#pragma aux daa_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"daa"                  			\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al]            		\
+	value [al]                      \
+	modify exact [al];
+
+u8      das_byte_asm(u32 *flags,u8 d);
+#pragma aux das_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"das"                  			\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al]            		\
+	value [al]                      \
+	modify exact [al];
+
+u8      dec_byte_asm(u32 *flags,u8 d);
+#pragma aux dec_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"dec	al"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al]            		\
+	value [al]                      \
+	modify exact [al];
+
+u16     dec_word_asm(u32 *flags,u16 d);
+#pragma aux dec_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"dec	ax"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax]            		\
+	value [ax]                      \
+	modify exact [ax];
+
+u32     dec_long_asm(u32 *flags,u32 d);
+#pragma aux dec_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"dec	eax"                	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax]          		\
+	value [eax]                     \
+	modify exact [eax];
+
+u8      inc_byte_asm(u32 *flags,u8 d);
+#pragma aux inc_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"inc	al"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al]            		\
+	value [al]                      \
+	modify exact [al];
+
+u16     inc_word_asm(u32 *flags,u16 d);
+#pragma aux inc_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"inc	ax"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax]            		\
+	value [ax]                      \
+	modify exact [ax];
+
+u32     inc_long_asm(u32 *flags,u32 d);
+#pragma aux inc_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"inc	eax"                	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax]          		\
+	value [eax]                     \
+	modify exact [eax];
+
+u8      or_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux or_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"or	al,bl"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [bl]            \
+	value [al]                      \
+	modify exact [al bl];
+
+u16     or_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux or_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"or	ax,bx"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [bx]            \
+	value [ax]                      \
+	modify exact [ax bx];
+
+u32     or_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux or_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"or	eax,ebx"                	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [ebx]          \
+	value [eax]                     \
+	modify exact [eax ebx];
+
+u8      neg_byte_asm(u32 *flags,u8 d);
+#pragma aux neg_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"neg	al"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al]            		\
+	value [al]                      \
+	modify exact [al];
+
+u16     neg_word_asm(u32 *flags,u16 d);
+#pragma aux neg_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"neg	ax"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax]            		\
+	value [ax]                      \
+	modify exact [ax];
+
+u32     neg_long_asm(u32 *flags,u32 d);
+#pragma aux neg_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"neg	eax"                	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax]          		\
+	value [eax]                     \
+	modify exact [eax];
+
+u8      not_byte_asm(u32 *flags,u8 d);
+#pragma aux not_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"not	al"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al]            		\
+	value [al]                      \
+	modify exact [al];
+
+u16     not_word_asm(u32 *flags,u16 d);
+#pragma aux not_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"not	ax"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax]            		\
+	value [ax]                      \
+	modify exact [ax];
+
+u32     not_long_asm(u32 *flags,u32 d);
+#pragma aux not_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"not	eax"                	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax]          		\
+	value [eax]                     \
+	modify exact [eax];
+
+u8      rcl_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux rcl_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"rcl	al,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [cl]            \
+	value [al]                      \
+	modify exact [al cl];
+
+u16     rcl_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux rcl_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"rcl	ax,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [cl]            \
+	value [ax]                      \
+	modify exact [ax cl];
+
+u32     rcl_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux rcl_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"rcl	eax,cl"                	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [cl]          	\
+	value [eax]                     \
+	modify exact [eax cl];
+
+u8      rcr_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux rcr_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"rcr	al,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [cl]            \
+	value [al]                      \
+	modify exact [al cl];
+
+u16     rcr_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux rcr_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"rcr	ax,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [cl]            \
+	value [ax]                      \
+	modify exact [ax cl];
+
+u32     rcr_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux rcr_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"rcr	eax,cl"                	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [cl]          	\
+	value [eax]                     \
+	modify exact [eax cl];
+
+u8      rol_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux rol_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"rol	al,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [cl]            \
+	value [al]                      \
+	modify exact [al cl];
+
+u16     rol_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux rol_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"rol	ax,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [cl]            \
+	value [ax]                      \
+	modify exact [ax cl];
+
+u32     rol_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux rol_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"rol	eax,cl"                	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [cl]          	\
+	value [eax]                     \
+	modify exact [eax cl];
+
+u8      ror_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux ror_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"ror	al,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [cl]            \
+	value [al]                      \
+	modify exact [al cl];
+
+u16     ror_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux ror_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"ror	ax,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [cl]            \
+	value [ax]                      \
+	modify exact [ax cl];
+
+u32     ror_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux ror_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"ror	eax,cl"                	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [cl]          	\
+	value [eax]                     \
+	modify exact [eax cl];
+
+u8      shl_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux shl_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"shl	al,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [cl]            \
+	value [al]                      \
+	modify exact [al cl];
+
+u16     shl_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux shl_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"shl	ax,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [cl]            \
+	value [ax]                      \
+	modify exact [ax cl];
+
+u32     shl_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux shl_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"shl	eax,cl"                	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [cl]          	\
+	value [eax]                     \
+	modify exact [eax cl];
+
+u8      shr_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux shr_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"shr	al,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [cl]            \
+	value [al]                      \
+	modify exact [al cl];
+
+u16     shr_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux shr_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"shr	ax,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [cl]            \
+	value [ax]                      \
+	modify exact [ax cl];
+
+u32     shr_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux shr_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"shr	eax,cl"                	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [cl]          	\
+	value [eax]                     \
+	modify exact [eax cl];
+
+u8      sar_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux sar_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"sar	al,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [cl]            \
+	value [al]                      \
+	modify exact [al cl];
+
+u16     sar_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux sar_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"sar	ax,cl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [cl]            \
+	value [ax]                      \
+	modify exact [ax cl];
+
+u32     sar_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux sar_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"sar	eax,cl"                	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [cl]          	\
+	value [eax]                     \
+	modify exact [eax cl];
+
+u16		shld_word_asm(u32 *flags,u16 d, u16 fill, u8 s);
+#pragma aux shld_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"shld	ax,dx,cl"               \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [dx] [cl]       \
+	value [ax]                      \
+	modify exact [ax dx cl];
+
+u32     shld_long_asm(u32 *flags,u32 d, u32 fill, u8 s);
+#pragma aux shld_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"shld	eax,edx,cl"             \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [edx] [cl]     \
+	value [eax]                     \
+	modify exact [eax edx cl];
+
+u16		shrd_word_asm(u32 *flags,u16 d, u16 fill, u8 s);
+#pragma aux shrd_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"shrd	ax,dx,cl"               \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [dx] [cl]       \
+	value [ax]                      \
+	modify exact [ax dx cl];
+
+u32     shrd_long_asm(u32 *flags,u32 d, u32 fill, u8 s);
+#pragma aux shrd_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"shrd	eax,edx,cl"             \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [edx] [cl]     \
+	value [eax]                     \
+	modify exact [eax edx cl];
+
+u8      sbb_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux sbb_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"sbb	al,bl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [bl]            \
+	value [al]                      \
+	modify exact [al bl];
+
+u16     sbb_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux sbb_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"sbb	ax,bx"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [bx]            \
+	value [ax]                      \
+	modify exact [ax bx];
+
+u32     sbb_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux sbb_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"sbb	eax,ebx"                \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [ebx]          \
+	value [eax]                     \
+	modify exact [eax ebx];
+
+u8      sub_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux sub_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"sub	al,bl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [bl]            \
+	value [al]                      \
+	modify exact [al bl];
+
+u16     sub_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux sub_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"sub	ax,bx"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [bx]            \
+	value [ax]                      \
+	modify exact [ax bx];
+
+u32     sub_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux sub_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"sub	eax,ebx"                \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [ebx]          \
+	value [eax]                     \
+	modify exact [eax ebx];
+
+void	test_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux test_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"test	al,bl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [bl]            \
+	modify exact [al bl];
+
+void	test_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux test_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"test	ax,bx"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [bx]            \
+	modify exact [ax bx];
+
+void	test_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux test_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"test	eax,ebx"                \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [ebx]          \
+	modify exact [eax ebx];
+
+u8      xor_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux xor_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"xor	al,bl"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [al] [bl]            \
+	value [al]                      \
+	modify exact [al bl];
+
+u16     xor_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux xor_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"xor	ax,bx"                  \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [ax] [bx]            \
+	value [ax]                      \
+	modify exact [ax bx];
+
+u32     xor_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux xor_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"xor	eax,ebx"                \
+	"pushf"                         \
+	"pop	[edi]"            		\
+	parm [edi] [eax] [ebx]          \
+	value [eax]                     \
+	modify exact [eax ebx];
+
+void    imul_byte_asm(u32 *flags,u16 *ax,u8 d,u8 s);
+#pragma aux imul_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"imul	bl"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	"mov	[esi],ax"				\
+	parm [edi] [esi] [al] [bl]      \
+	modify exact [esi ax bl];
+
+void    imul_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 d,u16 s);
+#pragma aux imul_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"imul	bx"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	"mov	[esi],ax"				\
+	"mov	[ecx],dx"				\
+	parm [edi] [esi] [ecx] [ax] [bx]\
+	modify exact [esi edi ax bx dx];
+
+void    imul_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 d,u32 s);
+#pragma aux imul_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"imul	ebx"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	"mov	[esi],eax"				\
+	"mov	[ecx],edx"				\
+	parm [edi] [esi] [ecx] [eax] [ebx] \
+	modify exact [esi edi eax ebx edx];
+
+void    mul_byte_asm(u32 *flags,u16 *ax,u8 d,u8 s);
+#pragma aux mul_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"mul	bl"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	"mov	[esi],ax"				\
+	parm [edi] [esi] [al] [bl]      \
+	modify exact [esi ax bl];
+
+void    mul_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 d,u16 s);
+#pragma aux mul_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"mul	bx"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	"mov	[esi],ax"				\
+	"mov	[ecx],dx"				\
+	parm [edi] [esi] [ecx] [ax] [bx]\
+	modify exact [esi edi ax bx dx];
+
+void    mul_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 d,u32 s);
+#pragma aux mul_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"mul	ebx"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	"mov	[esi],eax"				\
+	"mov	[ecx],edx"				\
+	parm [edi] [esi] [ecx] [eax] [ebx] \
+	modify exact [esi edi eax ebx edx];
+
+void	idiv_byte_asm(u32 *flags,u8 *al,u8 *ah,u16 d,u8 s);
+#pragma aux idiv_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"idiv	bl"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	"mov	[esi],al"				\
+	"mov	[ecx],ah"				\
+	parm [edi] [esi] [ecx] [ax] [bl]\
+	modify exact [esi edi ax bl];
+
+void	idiv_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 dlo,u16 dhi,u16 s);
+#pragma aux idiv_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"idiv	bx"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	"mov	[esi],ax"				\
+	"mov	[ecx],dx"				\
+	parm [edi] [esi] [ecx] [ax] [dx] [bx]\
+	modify exact [esi edi ax dx bx];
+
+void	idiv_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 dlo,u32 dhi,u32 s);
+#pragma aux idiv_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"idiv	ebx"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	"mov	[esi],eax"				\
+	"mov	[ecx],edx"				\
+	parm [edi] [esi] [ecx] [eax] [edx] [ebx]\
+	modify exact [esi edi eax edx ebx];
+
+void	div_byte_asm(u32 *flags,u8 *al,u8 *ah,u16 d,u8 s);
+#pragma aux div_byte_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"div	bl"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	"mov	[esi],al"				\
+	"mov	[ecx],ah"				\
+	parm [edi] [esi] [ecx] [ax] [bl]\
+	modify exact [esi edi ax bl];
+
+void	div_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 dlo,u16 dhi,u16 s);
+#pragma aux div_word_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"div	bx"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	"mov	[esi],ax"				\
+	"mov	[ecx],dx"				\
+	parm [edi] [esi] [ecx] [ax] [dx] [bx]\
+	modify exact [esi edi ax dx bx];
+
+void	div_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 dlo,u32 dhi,u32 s);
+#pragma aux div_long_asm =			\
+	"push	[edi]"            		\
+	"popf"                         	\
+	"div	ebx"                  	\
+	"pushf"                         \
+	"pop	[edi]"            		\
+	"mov	[esi],eax"				\
+	"mov	[ecx],edx"				\
+	parm [edi] [esi] [ecx] [eax] [edx] [ebx]\
+	modify exact [esi edi eax edx ebx];
+
+#endif
+
+#endif /* __X86EMU_PRIM_ASM_H */
diff --git a/util/x86emu/x86emu/prim_ops.c b/util/x86emu/x86emu/prim_ops.c
new file mode 100644
index 0000000..a4a46a2
--- /dev/null
+++ b/util/x86emu/x86emu/prim_ops.c
@@ -0,0 +1,2450 @@
+/****************************************************************************
+*
+*                       Realmode X86 Emulator Library
+*
+*               Copyright (C) 1991-2004 SciTech Software, Inc.
+*                    Copyright (C) David Mosberger-Tang
+*                      Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:     ANSI C
+* Environment:  Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file contains the code to implement the primitive
+*               machine operations used by the emulation code in ops.c
+*
+* Carry Chain Calculation
+*
+* This represents a somewhat expensive calculation which is
+* apparently required to emulate the setting of the OF and AF flag.
+* The latter is not so important, but the former is.  The overflow
+* flag is the XOR of the top two bits of the carry chain for an
+* addition (similar for subtraction).  Since we do not want to
+* simulate the addition in a bitwise manner, we try to calculate the
+* carry chain given the two operands and the result.
+*
+* So, given the following table, which represents the addition of two
+* bits, we can derive a formula for the carry chain.
+*
+* a   b   cin   r     cout
+* 0   0   0     0     0
+* 0   0   1     1     0
+* 0   1   0     1     0
+* 0   1   1     0     1
+* 1   0   0     1     0
+* 1   0   1     0     1
+* 1   1   0     0     1
+* 1   1   1     1     1
+*
+* Construction of table for cout:
+*
+* ab
+* r  \  00   01   11  10
+* |------------------
+* 0  |   0    1    1   1
+* 1  |   0    0    1   0
+*
+* By inspection, one gets:  cc = ab +  r'(a + b)
+*
+* That represents alot of operations, but NO CHOICE....
+*
+* Borrow Chain Calculation.
+*
+* The following table represents the subtraction of two bits, from
+* which we can derive a formula for the borrow chain.
+*
+* a   b   bin   r     bout
+* 0   0   0     0     0
+* 0   0   1     1     1
+* 0   1   0     1     1
+* 0   1   1     0     1
+* 1   0   0     1     0
+* 1   0   1     0     0
+* 1   1   0     0     0
+* 1   1   1     1     1
+*
+* Construction of table for cout:
+*
+* ab
+* r  \  00   01   11  10
+* |------------------
+* 0  |   0    1    0   0
+* 1  |   1    1    1   0
+*
+* By inspection, one gets:  bc = a'b +  r(a' + b)
+*
+****************************************************************************/
+
+#define PRIM_OPS_NO_REDEFINE_ASM
+#include "x86emui.h"
+
+#define abs(x) ({                               \
+                int __x = (x);                  \
+                (__x < 0) ? -__x : __x;         \
+        })
+
+#define labs(x) ({                              \
+                long __x = (x);                 \
+                (__x < 0) ? -__x : __x;         \
+        })
+
+/*------------------------- Global Variables ------------------------------*/
+
+static u32 x86emu_parity_tab[8] =
+{
+    0x96696996,
+    0x69969669,
+    0x69969669,
+    0x96696996,
+    0x69969669,
+    0x96696996,
+    0x96696996,
+    0x69969669,
+};
+
+#define PARITY(x)   (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
+#define XOR2(x)     (((x) ^ ((x)>>1)) & 0x1)
+
+/*----------------------------- Implementation ----------------------------*/
+
+
+/*--------- Side effects helper functions -------*/
+
+/****************************************************************************
+REMARKS:
+implements side efects for byte operations that don't overflow
+****************************************************************************/
+
+static void set_parity_flag(u32 res)
+{
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);
+}
+
+static void set_szp_flags_8(u8 res)
+{
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    set_parity_flag(res);
+}
+
+static void set_szp_flags_16(u16 res)
+{
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    set_parity_flag(res);
+}
+
+static void set_szp_flags_32(u32 res)
+{
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    set_parity_flag(res);
+}
+
+static void no_carry_byte_side_eff(u8 res)
+{
+    CLEAR_FLAG(F_OF);
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    set_szp_flags_8(res);
+}
+
+static void no_carry_word_side_eff(u16 res)
+{
+    CLEAR_FLAG(F_OF);
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    set_szp_flags_16(res);
+}
+
+static void no_carry_long_side_eff(u32 res)
+{
+    CLEAR_FLAG(F_OF);
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    set_szp_flags_32(res);
+}
+
+static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
+{
+    u32 cc;
+
+    cc = (s & d) | ((~res) & (s | d));
+    CONDITIONAL_SET_FLAG(XOR2(cc >> (bits - 2)), F_OF);
+    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+    if (set_carry) {
+        CONDITIONAL_SET_FLAG(res & (1 << bits), F_CF);
+    }
+}
+
+static void calc_borrow_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
+{
+    u32 bc;
+
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> (bits - 2)), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    if (set_carry) {
+        CONDITIONAL_SET_FLAG(bc & (1 << (bits - 1)), F_CF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAA instruction and side effects.
+****************************************************************************/
+u16 aaa_word(u16 d)
+{
+    u16 res;
+    if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
+        d += 0x6;
+        d += 0x100;
+        SET_FLAG(F_AF);
+        SET_FLAG(F_CF);
+    } else {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_AF);
+    }
+    res = (u16)(d & 0xFF0F);
+    set_szp_flags_16(res);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAA instruction and side effects.
+****************************************************************************/
+u16 aas_word(u16 d)
+{
+    u16 res;
+    if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
+        d -= 0x6;
+        d -= 0x100;
+        SET_FLAG(F_AF);
+        SET_FLAG(F_CF);
+    } else {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_AF);
+    }
+    res = (u16)(d & 0xFF0F);
+    set_szp_flags_16(res);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAD instruction and side effects.
+****************************************************************************/
+u16 aad_word(u16 d)
+{
+    u16 l;
+    u8 hb, lb;
+
+    hb = (u8)((d >> 8) & 0xff);
+    lb = (u8)((d & 0xff));
+    l = (u16)((lb + 10 * hb) & 0xFF);
+
+    no_carry_byte_side_eff(l & 0xFF);
+    return l;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAM instruction and side effects.
+****************************************************************************/
+u16 aam_word(u8 d)
+{
+    u16 h, l;
+
+    h = (u16)(d / 10);
+    l = (u16)(d % 10);
+    l |= (u16)(h << 8);
+
+    no_carry_byte_side_eff(l & 0xFF);
+    return l;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADC instruction and side effects.
+****************************************************************************/
+u8 adc_byte(u8 d, u8 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d + s;
+    if (ACCESS_FLAG(F_CF)) res++;
+
+    set_szp_flags_8(res);
+    calc_carry_chain(8,s,d,res,1);
+
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADC instruction and side effects.
+****************************************************************************/
+u16 adc_word(u16 d, u16 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d + s;
+    if (ACCESS_FLAG(F_CF))
+        res++;
+
+    set_szp_flags_16((u16)res);
+    calc_carry_chain(16,s,d,res,1);
+
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADC instruction and side effects.
+****************************************************************************/
+u32 adc_long(u32 d, u32 s)
+{
+    u32 lo;    /* all operands in native machine order */
+    u32 hi;
+    u32 res;
+
+    lo = (d & 0xFFFF) + (s & 0xFFFF);
+    res = d + s;
+
+    if (ACCESS_FLAG(F_CF)) {
+        lo++;
+        res++;
+    }
+
+    hi = (lo >> 16) + (d >> 16) + (s >> 16);
+
+    set_szp_flags_32(res);
+    calc_carry_chain(32,s,d,res,0);
+
+    CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
+
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADD instruction and side effects.
+****************************************************************************/
+u8 add_byte(u8 d, u8 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d + s;
+    set_szp_flags_8((u8)res);
+    calc_carry_chain(8,s,d,res,1);
+
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADD instruction and side effects.
+****************************************************************************/
+u16 add_word(u16 d, u16 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d + s;
+    set_szp_flags_16((u16)res);
+    calc_carry_chain(16,s,d,res,1);
+
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADD instruction and side effects.
+****************************************************************************/
+u32 add_long(u32 d, u32 s)
+{
+    u32 res;
+
+    res = d + s;
+    set_szp_flags_32(res);
+    calc_carry_chain(32,s,d,res,0);
+
+    CONDITIONAL_SET_FLAG(res < d || res < s, F_CF);
+
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AND instruction and side effects.
+****************************************************************************/
+u8 and_byte(u8 d, u8 s)
+{
+    u8 res;    /* all operands in native machine order */
+
+    res = d & s;
+
+    no_carry_byte_side_eff(res);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AND instruction and side effects.
+****************************************************************************/
+u16 and_word(u16 d, u16 s)
+{
+    u16 res;   /* all operands in native machine order */
+
+    res = d & s;
+
+    no_carry_word_side_eff(res);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AND instruction and side effects.
+****************************************************************************/
+u32 and_long(u32 d, u32 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d & s;
+    no_carry_long_side_eff(res);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the CMP instruction and side effects.
+****************************************************************************/
+u8 cmp_byte(u8 d, u8 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d - s;
+    set_szp_flags_8((u8)res);
+    calc_borrow_chain(8, d, s, res, 1);
+
+    return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the CMP instruction and side effects.
+****************************************************************************/
+u16 cmp_word(u16 d, u16 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d - s;
+    set_szp_flags_16((u16)res);
+    calc_borrow_chain(16, d, s, res, 1);
+
+    return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the CMP instruction and side effects.
+****************************************************************************/
+u32 cmp_long(u32 d, u32 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d - s;
+    set_szp_flags_32(res);
+    calc_borrow_chain(32, d, s, res, 1);
+
+    return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DAA instruction and side effects.
+****************************************************************************/
+u8 daa_byte(u8 d)
+{
+    u32 res = d;
+    if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
+        res += 6;
+        SET_FLAG(F_AF);
+    }
+    if (res > 0x9F || ACCESS_FLAG(F_CF)) {
+        res += 0x60;
+        SET_FLAG(F_CF);
+    }
+    set_szp_flags_8((u8)res);
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DAS instruction and side effects.
+****************************************************************************/
+u8 das_byte(u8 d)
+{
+    if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
+        d -= 6;
+        SET_FLAG(F_AF);
+    }
+    if (d > 0x9F || ACCESS_FLAG(F_CF)) {
+        d -= 0x60;
+        SET_FLAG(F_CF);
+    }
+    set_szp_flags_8(d);
+    return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DEC instruction and side effects.
+****************************************************************************/
+u8 dec_byte(u8 d)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d - 1;
+    set_szp_flags_8((u8)res);
+    calc_borrow_chain(8, d, 1, res, 0);
+
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DEC instruction and side effects.
+****************************************************************************/
+u16 dec_word(u16 d)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d - 1;
+    set_szp_flags_16((u16)res);
+    calc_borrow_chain(16, d, 1, res, 0);
+
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DEC instruction and side effects.
+****************************************************************************/
+u32 dec_long(u32 d)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d - 1;
+
+    set_szp_flags_32(res);
+    calc_borrow_chain(32, d, 1, res, 0);
+
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the INC instruction and side effects.
+****************************************************************************/
+u8 inc_byte(u8 d)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d + 1;
+    set_szp_flags_8((u8)res);
+    calc_carry_chain(8, d, 1, res, 0);
+
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the INC instruction and side effects.
+****************************************************************************/
+u16 inc_word(u16 d)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d + 1;
+    set_szp_flags_16((u16)res);
+    calc_carry_chain(16, d, 1, res, 0);
+
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the INC instruction and side effects.
+****************************************************************************/
+u32 inc_long(u32 d)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d + 1;
+    set_szp_flags_32(res);
+    calc_carry_chain(32, d, 1, res, 0);
+
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u8 or_byte(u8 d, u8 s)
+{
+    u8 res;    /* all operands in native machine order */
+
+    res = d | s;
+    no_carry_byte_side_eff(res);
+
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u16 or_word(u16 d, u16 s)
+{
+    u16 res;   /* all operands in native machine order */
+
+    res = d | s;
+    no_carry_word_side_eff(res);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u32 or_long(u32 d, u32 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d | s;
+    no_carry_long_side_eff(res);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u8 neg_byte(u8 s)
+{
+    u8 res;
+
+    CONDITIONAL_SET_FLAG(s != 0, F_CF);
+    res = (u8)-s;
+    set_szp_flags_8(res);
+    calc_borrow_chain(8, 0, s, res, 0);
+
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u16 neg_word(u16 s)
+{
+    u16 res;
+
+    CONDITIONAL_SET_FLAG(s != 0, F_CF);
+    res = (u16)-s;
+    set_szp_flags_16((u16)res);
+    calc_borrow_chain(16, 0, s, res, 0);
+
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u32 neg_long(u32 s)
+{
+    u32 res;
+
+    CONDITIONAL_SET_FLAG(s != 0, F_CF);
+    res = (u32)-s;
+    set_szp_flags_32(res);
+    calc_borrow_chain(32, 0, s, res, 0);
+
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the NOT instruction and side effects.
+****************************************************************************/
+u8 not_byte(u8 s)
+{
+    return ~s;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the NOT instruction and side effects.
+****************************************************************************/
+u16 not_word(u16 s)
+{
+    return ~s;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the NOT instruction and side effects.
+****************************************************************************/
+u32 not_long(u32 s)
+{
+    return ~s;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCL instruction and side effects.
+****************************************************************************/
+u8 rcl_byte(u8 d, u8 s)
+{
+    unsigned int res, cnt, mask, cf;
+
+    /* s is the rotate distance.  It varies from 0 - 8. */
+    /* have
+
+       CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
+
+       want to rotate through the carry by "s" bits.  We could
+       loop, but that's inefficient.  So the width is 9,
+       and we split into three parts:
+
+       The new carry flag   (was B_n)
+       the stuff in B_n-1 .. B_0
+       the stuff in B_7 .. B_n+1
+
+       The new rotate is done mod 9, and given this,
+       for a rotation of n bits (mod 9) the new carry flag is
+       then located n bits from the MSB.  The low part is
+       then shifted up cnt bits, and the high part is or'd
+       in.  Using CAPS for new values, and lowercase for the
+       original values, this can be expressed as:
+
+       IF n > 0
+       1) CF <-  b_(8-n)
+       2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
+       3) B_(n-1) <- cf
+       4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
+     */
+    res = d;
+    if ((cnt = s % 9) != 0) {
+        /* extract the new CARRY FLAG. */
+        /* CF <-  b_(8-n)             */
+        cf = (d >> (8 - cnt)) & 0x1;
+
+        /* get the low stuff which rotated
+           into the range B_7 .. B_cnt */
+        /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0  */
+        /* note that the right hand side done by the mask */
+        res = (d << cnt) & 0xff;
+
+        /* now the high stuff which rotated around
+           into the positions B_cnt-2 .. B_0 */
+        /* B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1)) */
+        /* shift it downward, 7-(n-2) = 9-n positions.
+           and mask off the result before or'ing in.
+         */
+        mask = (1 << (cnt - 1)) - 1;
+        res |= (d >> (9 - cnt)) & mask;
+
+        /* if the carry flag was set, or it in.  */
+        if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
+            /*  B_(n-1) <- cf */
+            res |= 1 << (cnt - 1);
+        }
+        /* set the new carry flag, based on the variable "cf" */
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        /* OVERFLOW is set *IFF* cnt==1, then it is the
+           xor of CF and the most significant bit.  Blecck. */
+        /* parenthesized this expression since it appears to
+           be causing OF to be misset */
+        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
+                             F_OF);
+
+    }
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCL instruction and side effects.
+****************************************************************************/
+u16 rcl_word(u16 d, u8 s)
+{
+    unsigned int res, cnt, mask, cf;
+
+    res = d;
+    if ((cnt = s % 17) != 0) {
+        cf = (d >> (16 - cnt)) & 0x1;
+        res = (d << cnt) & 0xffff;
+        mask = (1 << (cnt - 1)) - 1;
+        res |= (d >> (17 - cnt)) & mask;
+        if (ACCESS_FLAG(F_CF)) {
+            res |= 1 << (cnt - 1);
+        }
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
+                             F_OF);
+    }
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCL instruction and side effects.
+****************************************************************************/
+u32 rcl_long(u32 d, u8 s)
+{
+    u32 res, cnt, mask, cf;
+
+    res = d;
+    if ((cnt = s % 33) != 0) {
+        cf = (d >> (32 - cnt)) & 0x1;
+        res = (d << cnt) & 0xffffffff;
+        mask = (1 << (cnt - 1)) - 1;
+        res |= (d >> (33 - cnt)) & mask;
+        if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
+            res |= 1 << (cnt - 1);
+        }
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
+                             F_OF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCR instruction and side effects.
+****************************************************************************/
+u8 rcr_byte(u8 d, u8 s)
+{
+    u32 res, cnt;
+    u32 mask, cf, ocf = 0;
+
+    /* rotate right through carry */
+    /*
+       s is the rotate distance.  It varies from 0 - 8.
+       d is the byte object rotated.
+
+       have
+
+       CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
+
+       The new rotate is done mod 9, and given this,
+       for a rotation of n bits (mod 9) the new carry flag is
+       then located n bits from the LSB.  The low part is
+       then shifted up cnt bits, and the high part is or'd
+       in.  Using CAPS for new values, and lowercase for the
+       original values, this can be expressed as:
+
+       IF n > 0
+       1) CF <-  b_(n-1)
+       2) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
+       3) B_(8-n) <- cf
+       4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
+     */
+    res = d;
+    if ((cnt = s % 9) != 0) {
+        /* extract the new CARRY FLAG. */
+        /* CF <-  b_(n-1)              */
+        if (cnt == 1) {
+            cf = d & 0x1;
+            /* note hackery here.  Access_flag(..) evaluates to either
+               0 if flag not set
+               non-zero if flag is set.
+               doing access_flag(..) != 0 casts that into either
+               0..1 in any representation of the flags register
+               (i.e. packed bit array or unpacked.)
+             */
+            ocf = ACCESS_FLAG(F_CF) != 0;
+        } else
+            cf = (d >> (cnt - 1)) & 0x1;
+
+        /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_n  */
+        /* note that the right hand side done by the mask
+           This is effectively done by shifting the
+           object to the right.  The result must be masked,
+           in case the object came in and was treated
+           as a negative number.  Needed??? */
+
+        mask = (1 << (8 - cnt)) - 1;
+        res = (d >> cnt) & mask;
+
+        /* now the high stuff which rotated around
+           into the positions B_cnt-2 .. B_0 */
+        /* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
+        /* shift it downward, 7-(n-2) = 9-n positions.
+           and mask off the result before or'ing in.
+         */
+        res |= (d << (9 - cnt));
+
+        /* if the carry flag was set, or it in.  */
+        if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
+            /*  B_(8-n) <- cf */
+            res |= 1 << (8 - cnt);
+        }
+        /* set the new carry flag, based on the variable "cf" */
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        /* OVERFLOW is set *IFF* cnt==1, then it is the
+           xor of CF and the most significant bit.  Blecck. */
+        /* parenthesized... */
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
+                                 F_OF);
+        }
+    }
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCR instruction and side effects.
+****************************************************************************/
+u16 rcr_word(u16 d, u8 s)
+{
+    u32 res, cnt;
+    u32 mask, cf, ocf = 0;
+
+    /* rotate right through carry */
+    res = d;
+    if ((cnt = s % 17) != 0) {
+        if (cnt == 1) {
+            cf = d & 0x1;
+            ocf = ACCESS_FLAG(F_CF) != 0;
+        } else
+            cf = (d >> (cnt - 1)) & 0x1;
+        mask = (1 << (16 - cnt)) - 1;
+        res = (d >> cnt) & mask;
+        res |= (d << (17 - cnt));
+        if (ACCESS_FLAG(F_CF)) {
+            res |= 1 << (16 - cnt);
+        }
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
+                                 F_OF);
+        }
+    }
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCR instruction and side effects.
+****************************************************************************/
+u32 rcr_long(u32 d, u8 s)
+{
+    u32 res, cnt;
+    u32 mask, cf, ocf = 0;
+
+    /* rotate right through carry */
+    res = d;
+    if ((cnt = s % 33) != 0) {
+        if (cnt == 1) {
+            cf = d & 0x1;
+            ocf = ACCESS_FLAG(F_CF) != 0;
+        } else
+            cf = (d >> (cnt - 1)) & 0x1;
+        mask = (1 << (32 - cnt)) - 1;
+        res = (d >> cnt) & mask;
+        if (cnt != 1)
+            res |= (d << (33 - cnt));
+        if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
+            res |= 1 << (32 - cnt);
+        }
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
+                                 F_OF);
+        }
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROL instruction and side effects.
+****************************************************************************/
+u8 rol_byte(u8 d, u8 s)
+{
+    unsigned int res, cnt, mask;
+
+    /* rotate left */
+    /*
+       s is the rotate distance.  It varies from 0 - 8.
+       d is the byte object rotated.
+
+       have
+
+       CF  B_7 ... B_0
+
+       The new rotate is done mod 8.
+       Much simpler than the "rcl" or "rcr" operations.
+
+       IF n > 0
+       1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0)
+       2) B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n)
+     */
+    res = d;
+    if ((cnt = s % 8) != 0) {
+        /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
+        res = (d << cnt);
+
+        /* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
+        mask = (1 << cnt) - 1;
+        res |= (d >> (8 - cnt)) & mask;
+
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+        /* OVERFLOW is set *IFF* s==1, then it is the
+           xor of CF and the most significant bit.  Blecck. */
+        CONDITIONAL_SET_FLAG(s == 1 &&
+                             XOR2((res & 0x1) + ((res >> 6) & 0x2)),
+                             F_OF);
+    } if (s != 0) {
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+    }
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROL instruction and side effects.
+****************************************************************************/
+u16 rol_word(u16 d, u8 s)
+{
+    unsigned int res, cnt, mask;
+
+    res = d;
+    if ((cnt = s % 16) != 0) {
+        res = (d << cnt);
+        mask = (1 << cnt) - 1;
+        res |= (d >> (16 - cnt)) & mask;
+        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+        CONDITIONAL_SET_FLAG(s == 1 &&
+                             XOR2((res & 0x1) + ((res >> 14) & 0x2)),
+                             F_OF);
+    } if (s != 0) {
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+    }
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROL instruction and side effects.
+****************************************************************************/
+u32 rol_long(u32 d, u8 s)
+{
+    u32 res, cnt, mask;
+
+    res = d;
+    if ((cnt = s % 32) != 0) {
+        res = (d << cnt);
+        mask = (1 << cnt) - 1;
+        res |= (d >> (32 - cnt)) & mask;
+        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+        CONDITIONAL_SET_FLAG(s == 1 &&
+                             XOR2((res & 0x1) + ((res >> 30) & 0x2)),
+                             F_OF);
+    } if (s != 0) {
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROR instruction and side effects.
+****************************************************************************/
+u8 ror_byte(u8 d, u8 s)
+{
+    unsigned int res, cnt, mask;
+
+    /* rotate right */
+    /*
+       s is the rotate distance.  It varies from 0 - 8.
+       d is the byte object rotated.
+
+       have
+
+       B_7 ... B_0
+
+       The rotate is done mod 8.
+
+       IF n > 0
+       1) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
+       2) B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0)
+     */
+    res = d;
+    if ((cnt = s % 8) != 0) {           /* not a typo, do nada if cnt==0 */
+        /* B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0) */
+        res = (d << (8 - cnt));
+
+        /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
+        mask = (1 << (8 - cnt)) - 1;
+        res |= (d >> (cnt)) & mask;
+
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
+        /* OVERFLOW is set *IFF* s==1, then it is the
+           xor of the two most significant bits.  Blecck. */
+        CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
+    } else if (s != 0) {
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
+    }
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROR instruction and side effects.
+****************************************************************************/
+u16 ror_word(u16 d, u8 s)
+{
+    unsigned int res, cnt, mask;
+
+    res = d;
+    if ((cnt = s % 16) != 0) {
+        res = (d << (16 - cnt));
+        mask = (1 << (16 - cnt)) - 1;
+        res |= (d >> (cnt)) & mask;
+        CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
+        CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
+    } else if (s != 0) {
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
+    }
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROR instruction and side effects.
+****************************************************************************/
+u32 ror_long(u32 d, u8 s)
+{
+    u32 res, cnt, mask;
+
+    res = d;
+    if ((cnt = s % 32) != 0) {
+        res = (d << (32 - cnt));
+        mask = (1 << (32 - cnt)) - 1;
+        res |= (d >> (cnt)) & mask;
+        CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
+        CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
+    } else if (s != 0) {
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHL instruction and side effects.
+****************************************************************************/
+u8 shl_byte(u8 d, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 8) {
+        cnt = s % 8;
+
+        /* last bit shifted out goes into carry flag */
+        if (cnt > 0) {
+            res = d << cnt;
+            cf = d & (1 << (8 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            set_szp_flags_8((u8)res);
+        } else {
+            res = (u8) d;
+        }
+
+        if (cnt == 1) {
+            /* Needs simplification. */
+            CONDITIONAL_SET_FLAG(
+                                    (((res & 0x80) == 0x80) ^
+                                     (ACCESS_FLAG(F_CF) != 0)),
+            /* was (M.x86.R_FLG&F_CF)==F_CF)), */
+                                    F_OF);
+        } else {
+            CLEAR_FLAG(F_OF);
+        }
+    } else {
+        res = 0;
+        CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
+        CLEAR_FLAG(F_OF);
+        CLEAR_FLAG(F_SF);
+        SET_FLAG(F_PF);
+        SET_FLAG(F_ZF);
+    }
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHL instruction and side effects.
+****************************************************************************/
+u16 shl_word(u16 d, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 16) {
+        cnt = s % 16;
+        if (cnt > 0) {
+            res = d << cnt;
+            cf = d & (1 << (16 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            set_szp_flags_16((u16)res);
+        } else {
+            res = (u16) d;
+        }
+
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(
+                                    (((res & 0x8000) == 0x8000) ^
+                                     (ACCESS_FLAG(F_CF) != 0)),
+                                    F_OF);
+        } else {
+            CLEAR_FLAG(F_OF);
+        }
+    } else {
+        res = 0;
+        CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
+        CLEAR_FLAG(F_OF);
+        CLEAR_FLAG(F_SF);
+        SET_FLAG(F_PF);
+        SET_FLAG(F_ZF);
+    }
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHL instruction and side effects.
+****************************************************************************/
+u32 shl_long(u32 d, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 32) {
+        cnt = s % 32;
+        if (cnt > 0) {
+            res = d << cnt;
+            cf = d & (1 << (32 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            set_szp_flags_32((u32)res);
+        } else {
+            res = d;
+        }
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
+                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
+        } else {
+            CLEAR_FLAG(F_OF);
+        }
+    } else {
+        res = 0;
+        CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
+        CLEAR_FLAG(F_OF);
+        CLEAR_FLAG(F_SF);
+        SET_FLAG(F_PF);
+        SET_FLAG(F_ZF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHR instruction and side effects.
+****************************************************************************/
+u8 shr_byte(u8 d, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 8) {
+        cnt = s % 8;
+        if (cnt > 0) {
+            cf = d & (1 << (cnt - 1));
+            res = d >> cnt;
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            set_szp_flags_8((u8)res);
+        } else {
+            res = (u8) d;
+        }
+
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
+        } else {
+            CLEAR_FLAG(F_OF);
+        }
+    } else {
+        res = 0;
+        CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
+        CLEAR_FLAG(F_OF);
+        CLEAR_FLAG(F_SF);
+        SET_FLAG(F_PF);
+        SET_FLAG(F_ZF);
+    }
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHR instruction and side effects.
+****************************************************************************/
+u16 shr_word(u16 d, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 16) {
+        cnt = s % 16;
+        if (cnt > 0) {
+            cf = d & (1 << (cnt - 1));
+            res = d >> cnt;
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            set_szp_flags_16((u16)res);
+        } else {
+            res = d;
+        }
+
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
+        } else {
+            CLEAR_FLAG(F_OF);
+        }
+    } else {
+        res = 0;
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+        SET_FLAG(F_ZF);
+        CLEAR_FLAG(F_SF);
+        CLEAR_FLAG(F_PF);
+    }
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHR instruction and side effects.
+****************************************************************************/
+u32 shr_long(u32 d, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 32) {
+        cnt = s % 32;
+        if (cnt > 0) {
+            cf = d & (1 << (cnt - 1));
+            res = d >> cnt;
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            set_szp_flags_32((u32)res);
+        } else {
+            res = d;
+        }
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
+        } else {
+            CLEAR_FLAG(F_OF);
+        }
+    } else {
+        res = 0;
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+        SET_FLAG(F_ZF);
+        CLEAR_FLAG(F_SF);
+        CLEAR_FLAG(F_PF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SAR instruction and side effects.
+****************************************************************************/
+u8 sar_byte(u8 d, u8 s)
+{
+    unsigned int cnt, res, cf, mask, sf;
+
+    res = d;
+    sf = d & 0x80;
+    cnt = s % 8;
+    if (cnt > 0 && cnt < 8) {
+        mask = (1 << (8 - cnt)) - 1;
+        cf = d & (1 << (cnt - 1));
+        res = (d >> cnt) & mask;
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        if (sf) {
+            res |= ~mask;
+        }
+        set_szp_flags_8((u8)res);
+    } else if (cnt >= 8) {
+        if (sf) {
+            res = 0xff;
+            SET_FLAG(F_CF);
+            CLEAR_FLAG(F_ZF);
+            SET_FLAG(F_SF);
+            SET_FLAG(F_PF);
+        } else {
+            res = 0;
+            CLEAR_FLAG(F_CF);
+            SET_FLAG(F_ZF);
+            CLEAR_FLAG(F_SF);
+            CLEAR_FLAG(F_PF);
+        }
+    }
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SAR instruction and side effects.
+****************************************************************************/
+u16 sar_word(u16 d, u8 s)
+{
+    unsigned int cnt, res, cf, mask, sf;
+
+    sf = d & 0x8000;
+    cnt = s % 16;
+    res = d;
+    if (cnt > 0 && cnt < 16) {
+        mask = (1 << (16 - cnt)) - 1;
+        cf = d & (1 << (cnt - 1));
+        res = (d >> cnt) & mask;
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        if (sf) {
+            res |= ~mask;
+        }
+        set_szp_flags_16((u16)res);
+    } else if (cnt >= 16) {
+        if (sf) {
+            res = 0xffff;
+            SET_FLAG(F_CF);
+            CLEAR_FLAG(F_ZF);
+            SET_FLAG(F_SF);
+            SET_FLAG(F_PF);
+        } else {
+            res = 0;
+            CLEAR_FLAG(F_CF);
+            SET_FLAG(F_ZF);
+            CLEAR_FLAG(F_SF);
+            CLEAR_FLAG(F_PF);
+        }
+    }
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SAR instruction and side effects.
+****************************************************************************/
+u32 sar_long(u32 d, u8 s)
+{
+    u32 cnt, res, cf, mask, sf;
+
+    sf = d & 0x80000000;
+    cnt = s % 32;
+    res = d;
+    if (cnt > 0 && cnt < 32) {
+        mask = (1 << (32 - cnt)) - 1;
+        cf = d & (1 << (cnt - 1));
+        res = (d >> cnt) & mask;
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        if (sf) {
+            res |= ~mask;
+        }
+        set_szp_flags_32(res);
+    } else if (cnt >= 32) {
+        if (sf) {
+            res = 0xffffffff;
+            SET_FLAG(F_CF);
+            CLEAR_FLAG(F_ZF);
+            SET_FLAG(F_SF);
+            SET_FLAG(F_PF);
+        } else {
+            res = 0;
+            CLEAR_FLAG(F_CF);
+            SET_FLAG(F_ZF);
+            CLEAR_FLAG(F_SF);
+            CLEAR_FLAG(F_PF);
+        }
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHLD instruction and side effects.
+****************************************************************************/
+u16 shld_word (u16 d, u16 fill, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 16) {
+        cnt = s % 16;
+        if (cnt > 0) {
+            res = (d << cnt) | (fill >> (16-cnt));
+            cf = d & (1 << (16 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            set_szp_flags_16((u16)res);
+        } else {
+            res = d;
+        }
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
+                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
+        } else {
+            CLEAR_FLAG(F_OF);
+        }
+    } else {
+        res = 0;
+        CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
+        CLEAR_FLAG(F_OF);
+        CLEAR_FLAG(F_SF);
+        SET_FLAG(F_PF);
+        SET_FLAG(F_ZF);
+    }
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHLD instruction and side effects.
+****************************************************************************/
+u32 shld_long (u32 d, u32 fill, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 32) {
+        cnt = s % 32;
+        if (cnt > 0) {
+            res = (d << cnt) | (fill >> (32-cnt));
+            cf = d & (1 << (32 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            set_szp_flags_32((u32)res);
+        } else {
+            res = d;
+        }
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
+                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
+        } else {
+            CLEAR_FLAG(F_OF);
+        }
+    } else {
+        res = 0;
+        CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
+        CLEAR_FLAG(F_OF);
+        CLEAR_FLAG(F_SF);
+        SET_FLAG(F_PF);
+        SET_FLAG(F_ZF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHRD instruction and side effects.
+****************************************************************************/
+u16 shrd_word (u16 d, u16 fill, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 16) {
+        cnt = s % 16;
+        if (cnt > 0) {
+            cf = d & (1 << (cnt - 1));
+            res = (d >> cnt) | (fill << (16 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            set_szp_flags_16((u16)res);
+        } else {
+            res = d;
+        }
+
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
+        } else {
+            CLEAR_FLAG(F_OF);
+        }
+    } else {
+        res = 0;
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+        SET_FLAG(F_ZF);
+        CLEAR_FLAG(F_SF);
+        CLEAR_FLAG(F_PF);
+    }
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHRD instruction and side effects.
+****************************************************************************/
+u32 shrd_long (u32 d, u32 fill, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 32) {
+        cnt = s % 32;
+        if (cnt > 0) {
+            cf = d & (1 << (cnt - 1));
+            res = (d >> cnt) | (fill << (32 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            set_szp_flags_32((u32)res);
+        } else {
+            res = d;
+        }
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
+        } else {
+            CLEAR_FLAG(F_OF);
+        }
+    } else {
+        res = 0;
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+        SET_FLAG(F_ZF);
+        CLEAR_FLAG(F_SF);
+        CLEAR_FLAG(F_PF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SBB instruction and side effects.
+****************************************************************************/
+u8 sbb_byte(u8 d, u8 s)
+{
+    u32 res;   /* all operands in native machine order */
+    u32 bc;
+
+    if (ACCESS_FLAG(F_CF))
+        res = d - s - 1;
+    else
+        res = d - s;
+    set_szp_flags_8((u8)res);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SBB instruction and side effects.
+****************************************************************************/
+u16 sbb_word(u16 d, u16 s)
+{
+    u32 res;   /* all operands in native machine order */
+    u32 bc;
+
+    if (ACCESS_FLAG(F_CF))
+        res = d - s - 1;
+    else
+        res = d - s;
+    set_szp_flags_16((u16)res);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SBB instruction and side effects.
+****************************************************************************/
+u32 sbb_long(u32 d, u32 s)
+{
+    u32 res;   /* all operands in native machine order */
+    u32 bc;
+
+    if (ACCESS_FLAG(F_CF))
+        res = d - s - 1;
+    else
+        res = d - s;
+
+    set_szp_flags_32(res);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SUB instruction and side effects.
+****************************************************************************/
+u8 sub_byte(u8 d, u8 s)
+{
+    u32 res;   /* all operands in native machine order */
+    u32 bc;
+
+    res = d - s;
+    set_szp_flags_8((u8)res);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SUB instruction and side effects.
+****************************************************************************/
+u16 sub_word(u16 d, u16 s)
+{
+    u32 res;   /* all operands in native machine order */
+    u32 bc;
+
+    res = d - s;
+    set_szp_flags_16((u16)res);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SUB instruction and side effects.
+****************************************************************************/
+u32 sub_long(u32 d, u32 s)
+{
+    u32 res;   /* all operands in native machine order */
+    u32 bc;
+
+    res = d - s;
+    set_szp_flags_32(res);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the TEST instruction and side effects.
+****************************************************************************/
+void test_byte(u8 d, u8 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d & s;
+
+    CLEAR_FLAG(F_OF);
+    set_szp_flags_8((u8)res);
+    /* AF == dont care */
+    CLEAR_FLAG(F_CF);
+}
+
+/****************************************************************************
+REMARKS:
+Implements the TEST instruction and side effects.
+****************************************************************************/
+void test_word(u16 d, u16 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d & s;
+
+    CLEAR_FLAG(F_OF);
+    set_szp_flags_16((u16)res);
+    /* AF == dont care */
+    CLEAR_FLAG(F_CF);
+}
+
+/****************************************************************************
+REMARKS:
+Implements the TEST instruction and side effects.
+****************************************************************************/
+void test_long(u32 d, u32 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d & s;
+
+    CLEAR_FLAG(F_OF);
+    set_szp_flags_32(res);
+    /* AF == dont care */
+    CLEAR_FLAG(F_CF);
+}
+
+/****************************************************************************
+REMARKS:
+Implements the XOR instruction and side effects.
+****************************************************************************/
+u8 xor_byte(u8 d, u8 s)
+{
+    u8 res;    /* all operands in native machine order */
+
+    res = d ^ s;
+    no_carry_byte_side_eff(res);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the XOR instruction and side effects.
+****************************************************************************/
+u16 xor_word(u16 d, u16 s)
+{
+    u16 res;   /* all operands in native machine order */
+
+    res = d ^ s;
+    no_carry_word_side_eff(res);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the XOR instruction and side effects.
+****************************************************************************/
+u32 xor_long(u32 d, u32 s)
+{
+    u32 res;   /* all operands in native machine order */
+
+    res = d ^ s;
+    no_carry_long_side_eff(res);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void imul_byte(u8 s)
+{
+    s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
+
+    M.x86.R_AX = res;
+    if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
+        ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+    } else {
+        SET_FLAG(F_CF);
+        SET_FLAG(F_OF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void imul_word(u16 s)
+{
+    s32 res = (s16)M.x86.R_AX * (s16)s;
+
+    M.x86.R_AX = (u16)res;
+    M.x86.R_DX = (u16)(res >> 16);
+    if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x0000) ||
+        ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFFFF)) {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+    } else {
+        SET_FLAG(F_CF);
+        SET_FLAG(F_OF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
+{
+#ifdef  __HAS_LONG_LONG__
+    s64 res = (s64)(s32)d * (s64)(s32)s;
+
+    *res_lo = (u32)res;
+    *res_hi = (u32)(res >> 32);
+#else
+    u32 d_lo,d_hi,d_sign;
+    u32 s_lo,s_hi,s_sign;
+    u32 rlo_lo,rlo_hi,rhi_lo;
+
+    if ((d_sign = d & 0x80000000) != 0)
+        d = -d;
+    d_lo = d & 0xFFFF;
+    d_hi = d >> 16;
+    if ((s_sign = s & 0x80000000) != 0)
+        s = -s;
+    s_lo = s & 0xFFFF;
+    s_hi = s >> 16;
+    rlo_lo = d_lo * s_lo;
+    rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
+    rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
+    *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
+    *res_hi = rhi_lo;
+    if (d_sign != s_sign) {
+        d = ~*res_lo;
+        s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
+        *res_lo = ~*res_lo+1;
+        *res_hi = ~*res_hi+(s >> 16);
+        }
+#endif
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void imul_long(u32 s)
+{
+    imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
+    if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00000000) ||
+        ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFFFFFFFF)) {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+    } else {
+        SET_FLAG(F_CF);
+        SET_FLAG(F_OF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the MUL instruction and side effects.
+****************************************************************************/
+void mul_byte(u8 s)
+{
+    u16 res = (u16)(M.x86.R_AL * s);
+
+    M.x86.R_AX = res;
+    if (M.x86.R_AH == 0) {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+    } else {
+        SET_FLAG(F_CF);
+        SET_FLAG(F_OF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the MUL instruction and side effects.
+****************************************************************************/
+void mul_word(u16 s)
+{
+    u32 res = M.x86.R_AX * s;
+
+    M.x86.R_AX = (u16)res;
+    M.x86.R_DX = (u16)(res >> 16);
+    if (M.x86.R_DX == 0) {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+    } else {
+        SET_FLAG(F_CF);
+        SET_FLAG(F_OF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the MUL instruction and side effects.
+****************************************************************************/
+void mul_long(u32 s)
+{
+#ifdef  __HAS_LONG_LONG__
+    u64 res = (u64)M.x86.R_EAX * s;
+
+    M.x86.R_EAX = (u32)res;
+    M.x86.R_EDX = (u32)(res >> 32);
+#else
+    u32 a,a_lo,a_hi;
+    u32 s_lo,s_hi;
+    u32 rlo_lo,rlo_hi,rhi_lo;
+
+    a = M.x86.R_EAX;
+    a_lo = a & 0xFFFF;
+    a_hi = a >> 16;
+    s_lo = s & 0xFFFF;
+    s_hi = s >> 16;
+    rlo_lo = a_lo * s_lo;
+    rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
+    rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
+    M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
+    M.x86.R_EDX = rhi_lo;
+#endif
+    if (M.x86.R_EDX == 0) {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+    } else {
+        SET_FLAG(F_CF);
+        SET_FLAG(F_OF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IDIV instruction and side effects.
+****************************************************************************/
+void idiv_byte(u8 s)
+{
+    s32 dvd, div, mod;
+
+    dvd = (s16)M.x86.R_AX;
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    div = dvd / (s8)s;
+    mod = dvd % (s8)s;
+    if (abs(div) > 0x7f) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    M.x86.R_AL = (s8) div;
+    M.x86.R_AH = (s8) mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IDIV instruction and side effects.
+****************************************************************************/
+void idiv_word(u16 s)
+{
+    s32 dvd, div, mod;
+
+    dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    div = dvd / (s16)s;
+    mod = dvd % (s16)s;
+    if (abs(div) > 0x7fff) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_SF);
+    CONDITIONAL_SET_FLAG(div == 0, F_ZF);
+    set_parity_flag(mod);
+
+    M.x86.R_AX = (u16)div;
+    M.x86.R_DX = (u16)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IDIV instruction and side effects.
+****************************************************************************/
+void idiv_long(u32 s)
+{
+#ifdef  __HAS_LONG_LONG__
+    s64 dvd, div, mod;
+
+    dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    div = dvd / (s32)s;
+    mod = dvd % (s32)s;
+    if (abs(div) > 0x7fffffff) {
+        x86emu_intr_raise(0);
+        return;
+    }
+#else
+    s32 div = 0, mod;
+    s32 h_dvd = M.x86.R_EDX;
+    u32 l_dvd = M.x86.R_EAX;
+    u32 abs_s = s & 0x7FFFFFFF;
+    u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
+    u32 h_s = abs_s >> 1;
+    u32 l_s = abs_s << 31;
+    int counter = 31;
+    int carry;
+
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    do {
+        div <<= 1;
+        carry = (l_dvd >= l_s) ? 0 : 1;
+
+        if (abs_h_dvd < (h_s + carry)) {
+            h_s >>= 1;
+            l_s = abs_s << (--counter);
+            continue;
+        } else {
+            abs_h_dvd -= (h_s + carry);
+            l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
+                : (l_dvd - l_s);
+            h_s >>= 1;
+            l_s = abs_s << (--counter);
+            div |= 1;
+            continue;
+        }
+
+    } while (counter > -1);
+    /* overflow */
+    if (abs_h_dvd || (l_dvd > abs_s)) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    /* sign */
+    div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
+    mod = l_dvd;
+
+#endif
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    CLEAR_FLAG(F_SF);
+    SET_FLAG(F_ZF);
+    set_parity_flag(mod);
+
+    M.x86.R_EAX = (u32)div;
+    M.x86.R_EDX = (u32)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DIV instruction and side effects.
+****************************************************************************/
+void div_byte(u8 s)
+{
+    u32 dvd, div, mod;
+
+    dvd = M.x86.R_AX;
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    div = dvd / (u8)s;
+    mod = dvd % (u8)s;
+    if (abs(div) > 0xff) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    M.x86.R_AL = (u8)div;
+    M.x86.R_AH = (u8)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DIV instruction and side effects.
+****************************************************************************/
+void div_word(u16 s)
+{
+    u32 dvd, div, mod;
+
+    dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    div = dvd / (u16)s;
+    mod = dvd % (u16)s;
+    if (abs(div) > 0xffff) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_SF);
+    CONDITIONAL_SET_FLAG(div == 0, F_ZF);
+    set_parity_flag(mod);
+
+    M.x86.R_AX = (u16)div;
+    M.x86.R_DX = (u16)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DIV instruction and side effects.
+****************************************************************************/
+void div_long(u32 s)
+{
+#ifdef  __HAS_LONG_LONG__
+    u64 dvd, div, mod;
+
+    dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    div = dvd / (u32)s;
+    mod = dvd % (u32)s;
+    if (abs(div) > 0xffffffff) {
+        x86emu_intr_raise(0);
+        return;
+    }
+#else
+    s32 div = 0, mod;
+    s32 h_dvd = M.x86.R_EDX;
+    u32 l_dvd = M.x86.R_EAX;
+
+    u32 h_s = s;
+    u32 l_s = 0;
+    i