Add a clean copy of the x86emu library.
authorDavid Given <dg@cowlark.com>
Sun, 3 Jun 2018 15:06:23 +0000 (08:06 -0700)
committerDavid Given <dg@cowlark.com>
Sun, 3 Jun 2018 15:06:23 +0000 (08:06 -0700)
25 files changed:
plat/pc86/emu/README.md [new file with mode: 0644]
plat/pc86/emu/x86emu/COPYING [new file with mode: 0644]
plat/pc86/emu/x86emu/Makefile.am [new file with mode: 0644]
plat/pc86/emu/x86emu/debug.c [new file with mode: 0644]
plat/pc86/emu/x86emu/decode.c [new file with mode: 0644]
plat/pc86/emu/x86emu/fpu.c [new file with mode: 0644]
plat/pc86/emu/x86emu/meson.build [new file with mode: 0644]
plat/pc86/emu/x86emu/ops.c [new file with mode: 0644]
plat/pc86/emu/x86emu/ops.o [new file with mode: 0644]
plat/pc86/emu/x86emu/ops2.c [new file with mode: 0644]
plat/pc86/emu/x86emu/prim_ops.c [new file with mode: 0644]
plat/pc86/emu/x86emu/sys.c [new file with mode: 0644]
plat/pc86/emu/x86emu/validate.c [new file with mode: 0644]
plat/pc86/emu/x86emu/x86emu.h [new file with mode: 0644]
plat/pc86/emu/x86emu/x86emu/debug.h [new file with mode: 0644]
plat/pc86/emu/x86emu/x86emu/decode.h [new file with mode: 0644]
plat/pc86/emu/x86emu/x86emu/fpu.h [new file with mode: 0644]
plat/pc86/emu/x86emu/x86emu/fpu_regs.h [new file with mode: 0644]
plat/pc86/emu/x86emu/x86emu/ops.h [new file with mode: 0644]
plat/pc86/emu/x86emu/x86emu/prim_asm.h [new file with mode: 0644]
plat/pc86/emu/x86emu/x86emu/prim_ops.h [new file with mode: 0644]
plat/pc86/emu/x86emu/x86emu/prim_x86_gcc.h [new file with mode: 0644]
plat/pc86/emu/x86emu/x86emu/regs.h [new file with mode: 0644]
plat/pc86/emu/x86emu/x86emu/types.h [new file with mode: 0644]
plat/pc86/emu/x86emu/x86emu/x86emui.h [new file with mode: 0644]

diff --git a/plat/pc86/emu/README.md b/plat/pc86/emu/README.md
new file mode 100644 (file)
index 0000000..85ffd05
--- /dev/null
@@ -0,0 +1 @@
+The x86emu directory contains a copy of the xorg 8086 emulation library from\rthe X server. It's distributable under the MIT/X11 license, and so is\rcompatible with the ACK.\r\r
\ No newline at end of file
diff --git a/plat/pc86/emu/x86emu/COPYING b/plat/pc86/emu/x86emu/COPYING
new file mode 100644 (file)
index 0000000..abf13c2
--- /dev/null
@@ -0,0 +1,1847 @@
+The following is the 'standard copyright' agreed upon by most contributors,
+and is currently the canonical license preferred by the X.Org Foundation.
+This is a slight variant of the common MIT license form published by the
+Open Source Initiative at http://www.opensource.org/licenses/mit-license.php
+
+Copyright holders of new code should use this license statement where
+possible, and insert their name to this list.  Please sort by surname
+for people, and by the full name for other entities (e.g.  Juliusz
+Chroboczek sorts before Intel Corporation sorts before Daniel Stone).
+
+Copyright © 2011 Dave Airlie
+Copyright © 2000-2001 Juliusz Chroboczek
+Copyright © 1998 Egbert Eich
+Copyright © 2006-2007 Intel Corporation
+Copyright © 2006 Nokia Corporation
+Copyright © 2006-2008 Peter Hutterer
+Copyright © 2006 Adam Jackson
+Copyright © 2009-2010 NVIDIA Corporation
+Copyright © 1987, 2003-2006, 2008-2010 Oracle and/or its affiliates.
+Copyright © 1999 Keith Packard
+Copyright © 2007-2009 Red Hat, Inc.
+Copyright © 2005-2008 Daniel Stone
+Copyright © 2006-2009 Simon Thum
+Copyright © 2003-2008, 2013 Geert Uytterhoeven
+Copyright © 2006 Luc Verhaegen
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+
+
+
+The following licenses are 'legacy': usually MIT/X11 licenses with the name
+of the copyright holder(s) in the license statement, but also some BSD-like
+licenses.
+
+
+Copyright (C) 1994-2003 The XFree86 Project, Inc.  All Rights Reserved.
+Copyright (C) Colin Harrison 2005-2008
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+
+
+Copyright 1997 by The XFree86 Project, Inc.
+
+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 XFree86 Project, Inc.
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission.  The Xfree86
+Project, Inc. makes no representations about the suitability of this
+software for any purpose.  It is provided "as is" without express or
+implied warranty.
+
+THE XFREE86 PROJECT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT 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.
+
+
+Copyright 1985-1998, 2001  The Open Group
+Copyright 2002 Red Hat Inc., Durham, North Carolina.
+
+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.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright (c) 1987, 1989-1990, 1992-1995  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+
+Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Copyright © 1999-2000 SuSE, Inc.
+Copyright © 2007 Red Hat, Inc.
+
+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 SuSE not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission.  SuSE makes no representations about the
+suitability of this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+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.
+
+
+Copyright 1987-1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts.
+Copyright 1991 Massachusetts Institute of Technology, Cambridge, Massachusetts.
+Copyright 1991, 1993 Olivetti Research Limited, Cambridge, England.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
+Copyright 1994 Quarterdeck Office Systems.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 names of Digital and
+Quarterdeck not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL DIGITAL 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.
+
+
+Copyright 1997 Digital Equipment Corporation.
+All rights reserved.
+
+This software is furnished under license and may be used and copied only in
+accordance with the following terms and conditions.  Subject to these
+conditions, you may download, copy, install, use, modify and distribute
+this software in source and/or binary form. No title or ownership is
+transferred hereby.
+
+1) Any source code used, modified or distributed must reproduce and retain
+   this copyright notice and list of conditions as they appear in the
+   source file.
+
+2) No right is granted to use any trade name, trademark, or logo of Digital
+   Equipment Corporation. Neither the "Digital Equipment Corporation"
+   name nor any trademark or logo of Digital Equipment Corporation may be
+   used to endorse or promote products derived from this software without
+   the prior written permission of Digital Equipment Corporation.
+
+3) This software is provided "AS-IS" and any express or implied warranties,
+   including but not limited to, any implied warranties of merchantability,
+   fitness for a particular purpose, or non-infringement are disclaimed.
+   In no event shall DIGITAL be liable for any damages whatsoever, and in
+   particular, DIGITAL shall not be liable for special, indirect,
+   consequential, or incidental damages or damages for lost profits, loss
+   of revenue or loss of use, whether such damages arise in contract,
+   negligence, tort, under statute, in equity, at law or otherwise, even
+   if advised of the possibility of such damage.
+
+
+Copyright (c) 1991, 1996-1997 Digital Equipment Corporation, Maynard, Massachusetts.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+
+SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice including the dates of first publication and
+either this permission notice or a reference to
+http://oss.sgi.com/projects/FreeB/
+shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+Copyright (c) 1994, 1995  Hewlett-Packard Company
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the Hewlett-Packard
+Company shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the Hewlett-Packard Company.
+
+
+Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Hewlett-Packard not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+HEWLETT-PACKARD 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.
+
+
+Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
+Copyright (c) 2003 by the XFree86 Project, Inc.
+Copyright 2004-2005 Red Hat Inc., Raleigh, North Carolina.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation on the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+Copyright © 2008 Red Hat, Inc.
+Partly based on code Copyright © 2000 SuSE, Inc.
+
+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 Red Hat
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.  Red
+Hat makes no representations about the suitability of this software
+for any purpose.  It is provided "as is" without express or implied
+warranty.
+
+Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+NO EVENT SHALL Red Hat 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.
+
+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 SuSE not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission.  SuSE makes no representations about the
+suitability of this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+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.
+
+
+Copyright © 2006  Red Hat, Inc.
+(C) Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sub license,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+RED HAT, INC, OR PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Copyright (c) 1995  X Consortium
+Copyright 2004 Red Hat Inc., Durham, North Carolina.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation on the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT, THE X CONSORTIUM,
+AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in this Software without prior written
+authorization from the X Consortium.
+
+
+Copyright 1998-2000 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+Copyright (c) 2002, 2008, 2009 Apple Computer, Inc.
+Copyright (c) 2003-2004 Torrey T. Lyons.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+(C) Copyright IBM Corporation 2003
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+(C) Copyright IBM Corporation 2004-2005
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sub license,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+IBM,
+AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+Copyright (c) 1997  Metro Link Incorporated
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the Metro Link shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from Metro Link.
+
+
+Copyright 1995-1998 by Metro Link, Inc.
+Copyright (c) 1997 Matthieu Herrb
+
+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 Metro Link, Inc. not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  Metro Link, Inc. makes no
+representations about the suitability of this software for any purpose.
+ It is provided "as is" without express or implied warranty.
+
+METRO LINK, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL METRO LINK, INC. 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.
+
+
+Copyright 1998 by Metro Link Incorporated
+
+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 Metro Link
+Incorporated not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.  Metro Link Incorporated makes no representations
+about the suitability of this software for any purpose.  It is
+provided "as is" without express or implied warranty.
+
+METRO LINK INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL METRO LINK INCORPORATED 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.
+
+
+Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of Conectiva Linux shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from
+Conectiva Linux.
+
+
+Copyright (c) 2001, Andy Ritger  aritger@nvidia.com
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+o Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+o Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer
+  in the documentation and/or other materials provided with the
+  distribution.
+o Neither the name of NVIDIA nor the names of its contributors
+  may be used to endorse or promote products derived from this
+  software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
+NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+Copyright 1992 Vrije Universiteit, The Netherlands
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, 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 Vrije Universiteit not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  The Vrije Universiteit makes no
+representations about the suitability of this software for any purpose.
+It is provided "as is" without express or implied warranty.
+
+The Vrije Universiteit DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL The Vrije Universiteit 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.
+
+
+Copyright 1998 by Concurrent Computer Corporation
+
+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 Concurrent Computer
+Corporation not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.  Concurrent Computer Corporation makes no representations
+about the suitability of this software for any purpose.  It is
+provided "as is" without express or implied warranty.
+
+CONCURRENT COMPUTER CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL CONCURRENT COMPUTER CORPORATION 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.
+
+
+Copyright © 2004 Nokia
+
+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 Nokia not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Nokia makes no
+representations about the suitability of this software for any purpose.  It
+is provided "as is" without express or implied warranty.
+
+NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL NOKIA 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.
+
+
+(c)Copyright 1988,1991 Adobe Systems Incorporated.
+All rights reserved.
+
+Permission to use, copy, modify, distribute, and sublicense this software and its
+documentation for any purpose and without fee is hereby granted, provided that
+the above copyright notices appear in all copies and that both those copyright
+notices and this permission notice appear in supporting documentation and that
+the name of Adobe Systems Incorporated not be used in advertising or publicity
+pertaining to distribution of the software without specific, written prior
+permission.  No trademark license to use the Adobe trademarks is hereby
+granted.  If the Adobe trademark "Display PostScript"(tm) is used to describe
+this software, its functionality or for any other purpose, such use shall be
+limited to a statement that this software works in conjunction with the Display
+PostScript system.  Proper trademark attribution to reflect Adobe's ownership
+of the trademark shall be given whenever any such reference to the Display
+PostScript system is made.
+
+ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY
+PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.  ADOBE
+DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
+INFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO EVENT SHALL ADOBE BE LIABLE TO YOU
+OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT
+LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.  ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER
+SUPPORT FOR THE SOFTWARE.
+
+Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+Incorporated which may be registered in certain jurisdictions.
+
+
+Copyright 1989 Network Computing Devices, Inc., Mountain View, California.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, 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 N.C.D. not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission.  N.C.D. makes no representations about the
+suitability of this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+
+Copyright (c) 1987 by the Regents of the University of California
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies.  The University of California
+makes no representations about the suitability of this
+software for any purpose.  It is provided "as is" without
+express or implied warranty.
+
+
+Copyright 1992, 1993 Data General Corporation;
+Copyright 1992, 1993 OMRON Corporation
+
+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
+neither the name OMRON or DATA GENERAL be used in advertising or publicity
+pertaining to distribution of the software without specific, written prior
+permission of the party whose name is to be used.  Neither OMRON or
+DATA GENERAL make any representation about the suitability of this software
+for any purpose.  It is provided "as is" without express or implied warranty.
+
+OMRON AND DATA GENERAL EACH DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL OMRON OR DATA GENERAL 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.
+
+
+Copyright © 1998-2004, 2006 Keith Packard
+Copyright © 2000-2002 Keith Packard, member of The XFree86 Project, Inc.
+Copyright (c) 2002 Apple Computer, Inc.
+Copyright (c) 2003 Torrey T. Lyons.
+All Rights Reserved.
+
+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 Keith Packard not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  Keith Packard makes no
+representations about the suitability of this software for any purpose.  It
+is provided "as is" without express or implied warranty.
+
+KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL KEITH PACKARD 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.
+
+
+Copyright © 1999 Keith Packard
+Copyright © 2000 Compaq Computer Corporation
+Copyright © 2002 MontaVista Software Inc.
+Copyright © 2005 OpenedHand Ltd.
+Copyright © 2006 Nokia Corporation
+
+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 and/or copyright holders
+not be used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.  The authors and/or
+copyright holders make no representations about the suitability of this
+software for any purpose.  It is provided "as is" without express or
+implied warranty.
+
+THE AUTHORS AND/OR COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE AUTHORS AND/OR COPYRIGHT HOLDERS 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.
+
+
+Copyright 1993 by Davor Matic
+
+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.  Davor Matic makes no representations about
+the suitability of this software for any purpose.  It is provided "as
+is" without express or implied warranty.
+
+
+Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved.
+Copyright (C) Colin Harrison 2005-2008
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Harold L Hunt II
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+from Harold L Hunt II.
+
+
+Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+
+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 Thomas Roell not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  Thomas Roell makes no representations
+about the suitability of this software for any purpose.  It is provided
+"as is" without express or implied warranty.
+
+THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL THOMAS ROELL 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.
+
+
+Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
+Copyright 1993 by David Wexelblat <dwex@goblin.org>
+
+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 names of Thomas Roell and David Wexelblat
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission.  Thomas Roell and
+David Wexelblat makes no representations about the suitability of this
+software for any purpose.  It is provided "as is" without express or
+implied warranty.
+
+THOMAS ROELL AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THOMAS ROELL OR DAVID WEXELBLAT 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.
+
+
+Copyright 1990,91,92,93 by Thomas Roell, Germany.
+Copyright 1991,92,93    by SGCS (Snitily Graphics Consulting Services), USA.
+
+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 Thomas Roell nor
+SGCS be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+Thomas Roell nor SGCS makes no representations about the suitability
+of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+
+THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS 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.
+
+
+Copyright 1998 by Alan Hourihane, Wigan, England.
+Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales.
+
+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 Alan Hourihane not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  Alan Hourihane makes no representations
+about the suitability of this software for any purpose.  It is provided
+"as is" without express or implied warranty.
+
+ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL ALAN HOURIHANE 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.
+
+
+Copyright 1995  Kaleb S. KEITHLEY
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES
+OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Kaleb S. KEITHLEY
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+from Kaleb S. KEITHLEY
+
+
+Copyright (c) 1997 Matthieu Herrb
+
+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 Matthieu Herrb not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  Matthieu Herrb makes no
+representations about the suitability of this software for any purpose.
+ It is provided "as is" without express or implied warranty.
+
+MATTHIEU HERRB DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL MATTHIEU HERRB 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.
+
+
+Copyright 2004, Egbert Eich
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+EGBERT EICH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
+NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Egbert Eich shall not
+be used in advertising or otherwise to promote the sale, use or other deal-
+ings in this Software without prior written authorization from Egbert Eich.
+
+
+Copyright 1993 by David Wexelblat <dwex@goblin.org>
+Copyright 2005 by Kean Johnston <jkj@sco.com>
+Copyright 1993 by David McCullough <davidm@stallion.oz.au>
+
+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 David Wexelblat not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  David Wexelblat makes no representations
+about the suitability of this software for any purpose.  It is provided
+"as is" without express or implied warranty.
+
+DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL DAVID WEXELBLAT 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.
+
+
+Copyright 1992 by Orest Zborowski <obz@Kodak.com>
+Copyright 1993 by David Wexelblat <dwex@goblin.org>
+
+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 names of Orest Zborowski and David Wexelblat
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission.  Orest Zborowski
+and David Wexelblat make no representations about the suitability of this
+software for any purpose.  It is provided "as is" without express or
+implied warranty.
+
+OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT 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.
+
+
+Copyright 1992 by Orest Zborowski <obz@Kodak.com>
+Copyright 1993 by David Dawes <dawes@xfree86.org>
+
+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 names of Orest Zborowski and David Dawes
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission.  Orest Zborowski
+and David Dawes make no representations about the suitability of this
+software for any purpose.  It is provided "as is" without express or
+implied warranty.
+
+OREST ZBOROWSKI AND DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID DAWES 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.
+
+
+Copyright 1995-1999 by Frederic Lepied, France. <fred@sugix.frmug.fr.net>
+
+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  Frederic   Lepied not  be  used  in
+advertising or publicity pertaining to distribution of the software without
+specific,  written      prior  permission.     Frederic  Lepied   makes  no
+representations about the suitability of this software for any purpose.  It
+is provided "as is" without express or implied warranty.
+
+FREDERIC  LEPIED DISCLAIMS ALL   WARRANTIES WITH REGARD  TO  THIS SOFTWARE,
+INCLUDING ALL IMPLIED   WARRANTIES OF MERCHANTABILITY  AND   FITNESS, IN NO
+EVENT  SHALL FREDERIC  LEPIED 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.
+
+
+Copyright 1992 by Rich Murphey <Rich@Rice.edu>
+Copyright 1993 by David Wexelblat <dwex@goblin.org>
+
+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 names of Rich Murphey and David Wexelblat
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission.  Rich Murphey and
+David Wexelblat make no representations about the suitability of this
+software for any purpose.  It is provided "as is" without express or
+implied warranty.
+
+RICH MURPHEY AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID WEXELBLAT 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.
+
+
+Copyright 1992 by Rich Murphey <Rich@Rice.edu>
+Copyright 1993 by David Dawes <dawes@xfree86.org>
+
+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 names of Rich Murphey and David Dawes
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission.  Rich Murphey and
+David Dawes make no representations about the suitability of this
+software for any purpose.  It is provided "as is" without express or
+implied warranty.
+
+RICH MURPHEY AND DAVID DAWES DISCLAIM ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID DAWES 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.
+
+
+Copyright © 2003-2004 Anders Carlsson
+
+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 Anders Carlsson not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  Anders Carlsson makes no
+representations about the suitability of this software for any purpose.  It
+is provided "as is" without express or implied warranty.
+
+ANDERS CARLSSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL ANDERS CARLSSON 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.
+
+
+Copyright (C) 2003 Anders Carlsson
+Copyright © 2003-2004 Eric Anholt
+Copyright © 2004 Keith Packard
+
+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 Eric Anholt not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  Eric Anholt makes no
+representations about the suitability of this software for any purpose.  It
+is provided "as is" without express or implied warranty.
+
+ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL ERIC ANHOLT 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.
+
+
+Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+FOR ANY SPECIAL, DIRECT, 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.
+
+
+Copyright © 2003-2004 Philip Blundell
+
+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 Philip Blundell not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  Philip Blundell makes no
+representations about the suitability of this software for any purpose.  It
+is provided "as is" without express or implied warranty.
+
+PHILIP BLUNDELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL PHILIP BLUNDELL 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.
+
+
+
+Copyright (c) 1994-2003 by The XFree86 Project, Inc.
+Copyright 1997 by Metro Link, Inc.
+Copyright 2003 by David H. Dawes.
+Copyright 2003 by X-Oz Technologies.
+Copyright (c) 2004, X.Org Foundation
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder(s)
+and author(s) shall not be used in advertising or otherwise to promote
+the sale, use or other dealings in this Software without prior written
+authorization from the copyright holder(s) and author(s).
+
+
+Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
+Copyright 1993 by David Wexelblat <dwex@goblin.org>
+Copyright 1999 by David Holland <davidh@iquest.net>
+Copyright © 2000 Compaq Computer Corporation
+Copyright © 2002 Hewlett-Packard Company
+Copyright © 2004, 2005 Red Hat, Inc.
+Copyright © 2004 Nicholas Miell
+Copyright © 2005 Trolltech AS
+Copyright © 2006 Intel Corporation
+Copyright © 2006-2007 Keith Packard
+Copyright © 2008 Red Hat, Inc
+Copyright © 2008 George Sapountzis <gsap7@yahoo.gr>
+
+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 copyright holders not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission.  The copyright holders make no representations
+about the suitability of this software for any purpose.  It is provided "as
+is" without express or implied warranty.
+
+THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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.
+
+
+Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+            2005 Lars Knoll & Zack Rusin, Trolltech
+
+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 Keith Packard not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  Keith Packard makes no
+representations about the suitability of this software for any purpose.  It
+is provided "as is" without express or implied warranty.
+
+THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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.
+
+
+Copyright 1987, 1998  The Open Group
+Copyright © 1998-1999, 2001 The XFree86 Project, Inc.
+Copyright © 2000 VA Linux Systems, Inc.
+Copyright (c) 2000, 2001 Nokia Home Communications
+Copyright © 2007, 2008 Red Hat, Inc.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+
+Copyright 1996 by Thomas E. Dickey <dickey@clark.net>
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 above listed
+copyright holder(s) not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) 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.
+
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright (c) 2001 Andreas Monitzer.
+Copyright (c) 2001-2004 Greg Parker.
+Copyright (c) 2001-2004 Torrey T. Lyons
+Copyright (c) 2002-2003 Apple Computer, Inc.
+Copyright (c) 2004-2005 Alexander Gottwald
+Copyright (c) 2002-2009 Apple Inc.
+Copyright (c) 2007 Jeremy Huddleston
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright
+holders shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in this Software without prior written authorization.
+
+
+Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
+Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+  3. The name of the author may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Copyright (C) 2005 Bogdan D. bogdand@users.sourceforge.net
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall not be used in
+advertising or otherwise to promote the sale, use or other dealings in this
+Software without prior written authorization from the author.
+
+
+Copyright © 2002 David Dawes
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the author(s) shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from
+the author(s).
+
+
+Copyright (C) 1996-1999 SciTech Software, Inc.
+Copyright (C) David Mosberger-Tang
+Copyright (C) 1999 Egbert Eich
+Copyright (C) 2008 Bart Trojanowski, Symbio Technologies, LLC
+
+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.
+
+
+Copyright 2005-2006 Luc Verhaegen.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+Copyright 1995 by Robin Cutshaw <robin@XFree86.Org>
+Copyright 2000 by Egbert Eich
+Copyright 2002 by David Dawes
+
+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 names of the above listed copyright holder(s)
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission.  The above listed
+copyright holder(s) make(s) no representations about the suitability of this
+software for any purpose.  It is provided "as is" without express or
+implied warranty.
+
+THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) 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.
+
+
+Copyright 1997-2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+
+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 Marc Aurele La France not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission.  Marc Aurele La France makes no representations
+about the suitability of this software for any purpose.  It is provided
+"as-is" without express or implied warranty.
+
+MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
+EVENT SHALL MARC AURELE LA FRANCE 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.
+
+
+Copyright 1990, 1991 by Thomas Roell, Dinkelscherben, Germany
+Copyright 1992 by David Dawes <dawes@XFree86.org>
+Copyright 1992 by Jim Tsillas <jtsilla@damon.ccs.northeastern.edu>
+Copyright 1992 by Rich Murphey <Rich@Rice.edu>
+Copyright 1992 by Robert Baron <Robert.Baron@ernst.mach.cs.cmu.edu>
+Copyright 1992 by Orest Zborowski <obz@eskimo.com>
+Copyright 1993 by Vrije Universiteit, The Netherlands
+Copyright 1993 by David Wexelblat <dwex@XFree86.org>
+Copyright 1994, 1996 by Holger Veit <Holger.Veit@gmd.de>
+Copyright 1997 by Takis Psarogiannakopoulos <takis@dpmms.cam.ac.uk>
+Copyright 1994-2003 by The XFree86 Project, Inc
+
+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 names of the above listed copyright holders
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission.  The above listed
+copyright holders make no representations about the suitability of this
+software for any purpose.  It is provided "as is" without express or
+implied warranty.
+
+THE ABOVE LISTED COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDERS 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.
+
+
+Copyright 2001-2005 by J. Kean Johnston <jkj@sco.com>
+
+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 J. Kean Johnston not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  J. Kean Johnston makes no
+representations about the suitability of this software for any purpose.
+It is provided "as is" without express or implied warranty.
+
+J. KEAN JOHNSTON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL J. KEAN JOHNSTON 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.
+
+
+Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Copyright 1997,1998 by UCHIYAMA Yasushi
+
+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 UCHIYAMA Yasushi not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  UCHIYAMA Yasushi makes no representations
+about the suitability of this software for any purpose.  It is provided
+"as is" without express or implied warranty.
+
+UCHIYAMA YASUSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL UCHIYAMA YASUSHI 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.
+
+
+Copyright (C) 2000 Keith Packard
+              2004 Eric Anholt
+              2005 Zack Rusin
+
+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 copyright holders not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Copyright holders make no
+representations about the suitability of this software for any purpose.  It
+is provided "as is" without express or implied warranty.
+
+THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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.
+
+
+(C) Copyright IBM Corporation 2002-2007
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+this permission notice appear in supporting documentation.  This permission
+notice shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Copyright © 2007 OpenedHand Ltd
+
+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 OpenedHand Ltd not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. OpenedHand Ltd makes no
+representations about the suitability of this software for any purpose.  It
+is provided "as is" without express or implied warranty.
+
+OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL OpenedHand Ltd 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.
+
+
+Copyright (c) 1987, 1990, 1993
+     The Regents of the University of California.  All rights reserved.
+
+This code is derived from software contributed to Berkeley by
+Chris Torek.
+
+This code is derived from software contributed to Berkeley by
+Michael Rendell of Memorial University of Newfoundland.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 4. Neither the name of the University nor the names of its contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/plat/pc86/emu/x86emu/Makefile.am b/plat/pc86/emu/x86emu/Makefile.am
new file mode 100644 (file)
index 0000000..2a55d63
--- /dev/null
@@ -0,0 +1,29 @@
+if INT10_X86EMU
+noinst_LTLIBRARIES = libx86emu.la
+endif
+
+libx86emu_la_SOURCES = debug.c \
+                      decode.c \
+                      fpu.c \
+                      ops2.c \
+                      ops.c \
+                      prim_ops.c \
+                      sys.c \
+                      x86emu.h
+
+AM_CPPFLAGS = 
+
+AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS)
+
+EXTRA_DIST = validate.c \
+             x86emu/debug.h \
+             x86emu/decode.h \
+             x86emu/fpu.h \
+             x86emu/fpu_regs.h \
+             x86emu/ops.h \
+             x86emu/prim_asm.h \
+             x86emu/prim_ops.h \
+            x86emu/prim_x86_gcc.h \
+             x86emu/regs.h \
+             x86emu/types.h \
+             x86emu/x86emui.h
diff --git a/plat/pc86/emu/x86emu/debug.c b/plat/pc86/emu/x86emu/debug.c
new file mode 100644 (file)
index 0000000..576ace5
--- /dev/null
@@ -0,0 +1,487 @@
+/****************************************************************************
+*
+*                                              Realmode X86 Emulator Library
+*
+*              Copyright (C) 1996-1999 SciTech Software, Inc.
+*                                   Copyright (C) David Mosberger-Tang
+*                                         Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:            ANSI C
+* Environment: Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file contains the code to handle debugging of the
+*                              emulator.
+*
+****************************************************************************/
+
+#include "x86emu/x86emui.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#ifndef NO_SYS_HEADERS
+#include <stdlib.h>
+#endif
+
+/*----------------------------- Implementation ----------------------------*/
+
+#ifdef DEBUG
+
+static void print_encoded_bytes(u16 s, u16 o);
+static void print_decoded_instruction(void);
+static int parse_line(char *s, int *ps, int *n);
+
+/* should look something like debug's output. */
+void
+X86EMU_trace_regs(void)
+{
+    if (DEBUG_TRACE()) {
+        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();
+}
+
+static 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 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(const char *x, ...)
+{
+    va_list ap;
+    char temp[100];
+
+    va_start(ap, x);
+    vsnprintf(temp, sizeof(temp), x, ap);
+    va_end(ap);
+    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;
+
+    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)
+{
+    char s[1024];
+    int ps[10];
+    int ntok;
+    int cmd;
+    int done;
+    int segment;
+    int offset;
+    static int breakpoint;
+    static int noDecode = 1;
+
+    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("-");
+        (void)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;
+        }
+    }
+}
+
+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);
+}
+
+static int
+parse_line(char *s, int *ps, int *n)
+{
+    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;
+    }
+}
+
+#endif                          /* 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/plat/pc86/emu/x86emu/decode.c b/plat/pc86/emu/x86emu/decode.c
new file mode 100644 (file)
index 0000000..08a07b1
--- /dev/null
@@ -0,0 +1,1102 @@
+/****************************************************************************
+*
+*                                              Realmode X86 Emulator Library
+*
+*              Copyright (C) 1996-1999 SciTech Software, Inc.
+*                                   Copyright (C) David Mosberger-Tang
+*                                         Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:            ANSI C
+* Environment: Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file includes subroutines which are related to
+*                              instruction decoding and accessess of immediate data via IP.  etc.
+*
+****************************************************************************/
+
+#include <stdlib.h>
+
+#if defined(__sun) && defined(CS) /* avoid conflicts with Solaris sys/regset.h */
+# undef CS
+# undef DS
+# undef SS
+# undef ES
+# undef FS
+# undef GS
+#endif
+
+#include "x86emu/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)
+{
+    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 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 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 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 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 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 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 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 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 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 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 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 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 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 */
+}
+
+/*
+ *
+ * return offset from the SIB Byte
+ */
+u32
+decode_sib_address(int sib, int mod)
+{
+    u32 base = 0, i = 0, scale = 1;
+
+    switch (sib & 0x07) {
+    case 0:
+        DECODE_PRINTF("[EAX]");
+        base = M.x86.R_EAX;
+        break;
+    case 1:
+        DECODE_PRINTF("[ECX]");
+        base = M.x86.R_ECX;
+        break;
+    case 2:
+        DECODE_PRINTF("[EDX]");
+        base = M.x86.R_EDX;
+        break;
+    case 3:
+        DECODE_PRINTF("[EBX]");
+        base = M.x86.R_EBX;
+        break;
+    case 4:
+        DECODE_PRINTF("[ESP]");
+        base = M.x86.R_ESP;
+        M.x86.mode |= SYSMODE_SEG_DS_SS;
+        break;
+    case 5:
+        if (mod == 0) {
+            base = fetch_long_imm();
+            DECODE_PRINTF2("%08x", base);
+        }
+        else {
+            DECODE_PRINTF("[EBP]");
+            base = M.x86.R_ESP;
+            M.x86.mode |= SYSMODE_SEG_DS_SS;
+        }
+        break;
+    case 6:
+        DECODE_PRINTF("[ESI]");
+        base = M.x86.R_ESI;
+        break;
+    case 7:
+        DECODE_PRINTF("[EDI]");
+        base = M.x86.R_EDI;
+        break;
+    }
+    switch ((sib >> 3) & 0x07) {
+    case 0:
+        DECODE_PRINTF("[EAX");
+        i = M.x86.R_EAX;
+        break;
+    case 1:
+        DECODE_PRINTF("[ECX");
+        i = M.x86.R_ECX;
+        break;
+    case 2:
+        DECODE_PRINTF("[EDX");
+        i = M.x86.R_EDX;
+        break;
+    case 3:
+        DECODE_PRINTF("[EBX");
+        i = M.x86.R_EBX;
+        break;
+    case 4:
+        i = 0;
+        break;
+    case 5:
+        DECODE_PRINTF("[EBP");
+        i = M.x86.R_EBP;
+        break;
+    case 6:
+        DECODE_PRINTF("[ESI");
+        i = M.x86.R_ESI;
+        break;
+    case 7:
+        DECODE_PRINTF("[EDI");
+        i = M.x86.R_EDI;
+        break;
+    }
+    scale = 1 << ((sib >> 6) & 0x03);
+    if (((sib >> 3) & 0x07) != 4) {
+        if (scale == 1) {
+            DECODE_PRINTF("]");
+        }
+        else {
+            DECODE_PRINTF2("*%d]", scale);
+        }
+    }
+    return base + (i * scale);
+}
+
+/****************************************************************************
+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).
+****************************************************************************/
+u32
+decode_rm00_address(int rm)
+{
+    u32 offset;
+    int sib;
+
+    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:
+            sib = fetch_byte_imm();
+            return decode_sib_address(sib, 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;
+        }
+        HALT_SYS();
+    }
+    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.
+****************************************************************************/
+u32
+decode_rm01_address(int rm)
+{
+    int displacement = 0;
+    int sib;
+
+    /* Fetch disp8 if no SIB byte */
+    if (!((M.x86.mode & SYSMODE_PREFIX_ADDR) && (rm == 4)))
+        displacement = (s8) fetch_byte_imm();
+
+    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+        /* 32-bit addressing */
+        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:
+            sib = fetch_byte_imm();
+            displacement = (s8) fetch_byte_imm();
+            DECODE_PRINTF2("%d", displacement);
+            return decode_sib_address(sib, 1) + 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;
+        }
+        HALT_SYS();
+    }
+    else {
+        /* 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:
+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.
+****************************************************************************/
+u32
+decode_rm10_address(int rm)
+{
+    u32 displacement = 0;
+    int sib;
+
+    /* Fetch disp16 if 16-bit addr mode */
+    if (!(M.x86.mode & SYSMODE_PREFIX_ADDR))
+        displacement = (u16) fetch_word_imm();
+    else {
+        /* Fetch disp32 if no SIB byte */
+        if (rm != 4)
+            displacement = (u32) fetch_long_imm();
+    }
+
+    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+        /* 32-bit addressing */
+        switch (rm) {
+        case 0:
+            DECODE_PRINTF2("%08x[EAX]", displacement);
+            return M.x86.R_EAX + displacement;
+        case 1:
+            DECODE_PRINTF2("%08x[ECX]", displacement);
+            return M.x86.R_ECX + displacement;
+        case 2:
+            DECODE_PRINTF2("%08x[EDX]", displacement);
+            M.x86.mode |= SYSMODE_SEG_DS_SS;
+            return M.x86.R_EDX + displacement;
+        case 3:
+            DECODE_PRINTF2("%08x[EBX]", displacement);
+            return M.x86.R_EBX + displacement;
+        case 4:
+            sib = fetch_byte_imm();
+            displacement = (u32) fetch_long_imm();
+            DECODE_PRINTF2("%08x", displacement);
+            return decode_sib_address(sib, 2) + displacement;
+            break;
+        case 5:
+            DECODE_PRINTF2("%08x[EBP]", displacement);
+            return M.x86.R_EBP + displacement;
+        case 6:
+            DECODE_PRINTF2("%08x[ESI]", displacement);
+            return M.x86.R_ESI + displacement;
+        case 7:
+            DECODE_PRINTF2("%08x[EDI]", displacement);
+            return M.x86.R_EDI + displacement;
+        }
+        HALT_SYS();
+    }
+    else {
+        /* 16-bit addressing */
+        switch (rm) {
+        case 0:
+            DECODE_PRINTF2("%04x[BX+SI]", displacement);
+            return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
+        case 1:
+            DECODE_PRINTF2("%04x[BX+DI]", displacement);
+            return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
+        case 2:
+            DECODE_PRINTF2("%04x[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("%04x[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("%04x[SI]", displacement);
+            return (M.x86.R_SI + displacement) & 0xffff;
+        case 5:
+            DECODE_PRINTF2("%04x[DI]", displacement);
+            return (M.x86.R_DI + displacement) & 0xffff;
+        case 6:
+            DECODE_PRINTF2("%04x[BP]", displacement);
+            M.x86.mode |= SYSMODE_SEG_DS_SS;
+            return (M.x86.R_BP + displacement) & 0xffff;
+        case 7:
+            DECODE_PRINTF2("%04x[BX]", displacement);
+            return (M.x86.R_BX + displacement) & 0xffff;
+        }
+        HALT_SYS();
+    }
+    return 0;
+    /*NOTREACHED */
+}
diff --git a/plat/pc86/emu/x86emu/fpu.c b/plat/pc86/emu/x86emu/fpu.c
new file mode 100644 (file)
index 0000000..0dab05c
--- /dev/null
@@ -0,0 +1,976 @@
+/****************************************************************************
+*
+*                                              Realmode X86 Emulator Library
+*
+*              Copyright (C) 1996-1999 SciTech Software, Inc.
+*                                   Copyright (C) David Mosberger-Tang
+*                                         Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:            ANSI C
+* Environment: Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file contains the code to implement the decoding and
+*               emulation of the FPU instructions.
+*
+****************************************************************************/
+
+#include "x86emu/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 DEBUG
+
+static const 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 const 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                          /* DEBUG */
+
+/* opcode=0xd9 */
+void
+x86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset = 0;
+    u8 stkelem = 0;
+
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef 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;
+            }
+        }
+    }
+#else
+    (void) destoffset;
+    (void) stkelem;
+#endif                          /* X86EMU_FPU_PRESENT */
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+
+static const 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                          /* DEBUG */
+
+/* opcode=0xda */
+void
+x86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset = 0;
+    u8 stkelem = 0;
+
+    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;
+        }
+    }
+#else
+    (void) destoffset;
+    (void) stkelem;
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+
+static const 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                          /* DEBUG */
+
+/* opcode=0xdb */
+void
+x86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset = 0;
+
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef 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                          /* 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;
+        }
+    }
+#else
+    (void) destoffset;
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+static const 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                          /* DEBUG */
+
+/* opcode=0xdc */
+void
+x86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset = 0;
+    u8 stkelem = 0;
+
+    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;
+        }
+    }
+#else
+    (void) destoffset;
+    (void) stkelem;
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+
+static const 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                          /* DEBUG */
+
+/* opcode=0xdd */
+void
+x86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset = 0;
+    u8 stkelem = 0;
+
+    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;
+        }
+    }
+#else
+    (void) destoffset;
+    (void) stkelem;
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+
+static const 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                          /* DEBUG */
+
+/* opcode=0xde */
+void
+x86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset = 0;
+    u8 stkelem = 0;
+
+    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;
+        }
+    }
+#else
+    (void) destoffset;
+    (void) stkelem;
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+
+static const 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                          /* DEBUG */
+
+/* opcode=0xdf */
+void
+x86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset = 0;
+    u8 stkelem = 0;
+
+    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;
+        }
+    }
+#else
+    (void) destoffset;
+    (void) stkelem;
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR_NO_TRACE();
+}
diff --git a/plat/pc86/emu/x86emu/meson.build b/plat/pc86/emu/x86emu/meson.build
new file mode 100644 (file)
index 0000000..4846da9
--- /dev/null
@@ -0,0 +1,15 @@
+srcs_xorg_x86emu = [
+    'debug.c',
+    'decode.c',
+    'fpu.c',
+    'ops2.c',
+    'ops.c',
+    'prim_ops.c',
+    'sys.c',
+]
+
+xorg_x86emu = static_library('x86emu',
+    srcs_xorg_x86emu,
+    include_directories: [inc, xorg_inc],
+    dependencies: common_dep,
+)
diff --git a/plat/pc86/emu/x86emu/ops.c b/plat/pc86/emu/x86emu/ops.c
new file mode 100644 (file)
index 0000000..210f8ce
--- /dev/null
@@ -0,0 +1,12399 @@
+/****************************************************************************
+*
+*                                              Realmode X86 Emulator Library
+*
+*              Copyright (C) 1996-1999 SciTech Software, Inc.
+*                                   Copyright (C) David Mosberger-Tang
+*                                         Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:            ANSI C
+* Environment: Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file 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 "x86emu/x86emui.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+op1 - Instruction op code
+
+REMARKS:
+Handles illegal opcodes.
+****************************************************************************/
+static 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 opcode 0x00
+****************************************************************************/
+static void
+x86emuOp_add_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 *destreg, *srcreg;
+    u8 destval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("ADD\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = add_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = add_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = add_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = add_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x01
+****************************************************************************/
+static void
+x86emuOp_add_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("ADD\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = add_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = add_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = add_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = add_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = add_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = add_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 3:                    /* 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 = add_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();
+            *destreg = add_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x02
+****************************************************************************/
+static void
+x86emuOp_add_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint srcoffset;
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("ADD\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = add_byte(*destreg, srcval);
+        break;
+    case 1:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = add_byte(*destreg, srcval);
+        break;
+    case 2:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = add_byte(*destreg, srcval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = add_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x03
+****************************************************************************/
+static void
+x86emuOp_add_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("ADD\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = add_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = add_word(*destreg, srcval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = add_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = add_word(*destreg, srcval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = add_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = add_word(*destreg, srcval);
+        }
+        break;
+    case 3:                    /* 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 = add_long(*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 = add_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x04
+****************************************************************************/
+static void
+x86emuOp_add_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("ADD\tAL,");
+    srcval = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    M.x86.R_AL = add_byte(M.x86.R_AL, srcval);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x05
+****************************************************************************/
+static void
+x86emuOp_add_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("ADD\tEAX,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("ADD\tAX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = add_long(M.x86.R_EAX, srcval);
+    }
+    else {
+        M.x86.R_AX = add_word(M.x86.R_AX, (u16) srcval);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x06
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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 0x08
+****************************************************************************/
+static void
+x86emuOp_or_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint destoffset;
+    u8 destval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("OR\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = or_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = or_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = or_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = or_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x09
+****************************************************************************/
+static void
+x86emuOp_or_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("OR\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = or_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = or_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = or_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = or_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = or_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = or_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 3:                    /* 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 = or_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();
+            *destreg = or_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0a
+****************************************************************************/
+static void
+x86emuOp_or_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint srcoffset;
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("OR\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = or_byte(*destreg, srcval);
+        break;
+    case 1:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = or_byte(*destreg, srcval);
+        break;
+    case 2:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = or_byte(*destreg, srcval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = or_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0b
+****************************************************************************/
+static void
+x86emuOp_or_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("OR\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = or_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = or_word(*destreg, srcval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = or_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = or_word(*destreg, srcval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = or_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = or_word(*destreg, srcval);
+        }
+        break;
+    case 3:                    /* 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 = or_long(*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 = or_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0c
+****************************************************************************/
+static void
+x86emuOp_or_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("OR\tAL,");
+    srcval = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    M.x86.R_AL = or_byte(M.x86.R_AL, srcval);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0d
+****************************************************************************/
+static void
+x86emuOp_or_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("OR\tEAX,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("OR\tAX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = or_long(M.x86.R_EAX, srcval);
+    }
+    else {
+        M.x86.R_AX = or_word(M.x86.R_AX, (u16) srcval);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0e
+****************************************************************************/
+static 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)
+****************************************************************************/
+static 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 0x10
+****************************************************************************/
+static void
+x86emuOp_adc_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint destoffset;
+    u8 destval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("ADC\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = adc_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = adc_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = adc_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = adc_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x11
+****************************************************************************/
+static void
+x86emuOp_adc_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("ADC\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = adc_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = adc_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = adc_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = adc_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = adc_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = adc_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 3:                    /* 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 = adc_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();
+            *destreg = adc_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x12
+****************************************************************************/
+static void
+x86emuOp_adc_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint srcoffset;
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("ADC\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = adc_byte(*destreg, srcval);
+        break;
+    case 1:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = adc_byte(*destreg, srcval);
+        break;
+    case 2:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = adc_byte(*destreg, srcval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = adc_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x13
+****************************************************************************/
+static void
+x86emuOp_adc_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("ADC\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = adc_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = adc_word(*destreg, srcval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = adc_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = adc_word(*destreg, srcval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = adc_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = adc_word(*destreg, srcval);
+        }
+        break;
+    case 3:                    /* 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 = adc_long(*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 = adc_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x14
+****************************************************************************/
+static void
+x86emuOp_adc_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("ADC\tAL,");
+    srcval = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    M.x86.R_AL = adc_byte(M.x86.R_AL, srcval);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x15
+****************************************************************************/
+static void
+x86emuOp_adc_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("ADC\tEAX,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("ADC\tAX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = adc_long(M.x86.R_EAX, srcval);
+    }
+    else {
+        M.x86.R_AX = adc_word(M.x86.R_AX, (u16) srcval);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x16
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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 0x18
+****************************************************************************/
+static void
+x86emuOp_sbb_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint destoffset;
+    u8 destval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SBB\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = sbb_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = sbb_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = sbb_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = sbb_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x19
+****************************************************************************/
+static void
+x86emuOp_sbb_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SBB\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = sbb_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = sbb_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = sbb_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = sbb_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = sbb_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = sbb_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 3:                    /* 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 = sbb_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();
+            *destreg = sbb_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1a
+****************************************************************************/
+static void
+x86emuOp_sbb_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint srcoffset;
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SBB\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = sbb_byte(*destreg, srcval);
+        break;
+    case 1:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = sbb_byte(*destreg, srcval);
+        break;
+    case 2:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = sbb_byte(*destreg, srcval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = sbb_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1b
+****************************************************************************/
+static void
+x86emuOp_sbb_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SBB\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = sbb_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = sbb_word(*destreg, srcval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = sbb_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = sbb_word(*destreg, srcval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = sbb_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = sbb_word(*destreg, srcval);
+        }
+        break;
+    case 3:                    /* 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 = sbb_long(*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 = sbb_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1c
+****************************************************************************/
+static void
+x86emuOp_sbb_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SBB\tAL,");
+    srcval = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    M.x86.R_AL = sbb_byte(M.x86.R_AL, srcval);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1d
+****************************************************************************/
+static void
+x86emuOp_sbb_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("SBB\tEAX,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("SBB\tAX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = sbb_long(M.x86.R_EAX, srcval);
+    }
+    else {
+        M.x86.R_AX = sbb_word(M.x86.R_AX, (u16) srcval);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1e
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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 0x20
+****************************************************************************/
+static void
+x86emuOp_and_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint destoffset;
+    u8 destval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("AND\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = and_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = and_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = and_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = and_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x21
+****************************************************************************/
+static void
+x86emuOp_and_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("AND\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = and_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = and_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = and_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = and_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = and_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = and_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 3:                    /* 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 = and_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();
+            *destreg = and_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x22
+****************************************************************************/
+static void
+x86emuOp_and_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint srcoffset;
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("AND\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = and_byte(*destreg, srcval);
+        break;
+    case 1:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = and_byte(*destreg, srcval);
+        break;
+    case 2:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = and_byte(*destreg, srcval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = and_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x23
+****************************************************************************/
+static void
+x86emuOp_and_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("AND\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = and_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = and_word(*destreg, srcval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = and_long(*destreg, srcval);
+            break;
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = and_word(*destreg, srcval);
+            break;
+        }
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = and_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = and_word(*destreg, srcval);
+        }
+        break;
+    case 3:                    /* 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 = and_long(*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 = and_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x24
+****************************************************************************/
+static void
+x86emuOp_and_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("AND\tAL,");
+    srcval = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    M.x86.R_AL = and_byte(M.x86.R_AL, srcval);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x25
+****************************************************************************/
+static void
+x86emuOp_and_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("AND\tEAX,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("AND\tAX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = and_long(M.x86.R_EAX, srcval);
+    }
+    else {
+        M.x86.R_AX = and_word(M.x86.R_AX, (u16) srcval);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x26
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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 0x28
+****************************************************************************/
+static void
+x86emuOp_sub_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint destoffset;
+    u8 destval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SUB\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = sub_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = sub_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = sub_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = sub_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x29
+****************************************************************************/
+static void
+x86emuOp_sub_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SUB\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = sub_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = sub_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = sub_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = sub_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = sub_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = sub_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 3:                    /* 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 = sub_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();
+            *destreg = sub_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2a
+****************************************************************************/
+static void
+x86emuOp_sub_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint srcoffset;
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SUB\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = sub_byte(*destreg, srcval);
+        break;
+    case 1:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = sub_byte(*destreg, srcval);
+        break;
+    case 2:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = sub_byte(*destreg, srcval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = sub_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2b
+****************************************************************************/
+static void
+x86emuOp_sub_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SUB\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = sub_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = sub_word(*destreg, srcval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = sub_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = sub_word(*destreg, srcval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = sub_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = sub_word(*destreg, srcval);
+        }
+        break;
+    case 3:                    /* 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 = sub_long(*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 = sub_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2c
+****************************************************************************/
+static void
+x86emuOp_sub_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("SUB\tAL,");
+    srcval = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    M.x86.R_AL = sub_byte(M.x86.R_AL, srcval);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2d
+****************************************************************************/
+static void
+x86emuOp_sub_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("SUB\tEAX,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("SUB\tAX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = sub_long(M.x86.R_EAX, srcval);
+    }
+    else {
+        M.x86.R_AX = sub_word(M.x86.R_AX, (u16) srcval);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2e
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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 0x30
+****************************************************************************/
+static void
+x86emuOp_xor_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint destoffset;
+    u8 destval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("XOR\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = xor_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = xor_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = xor_byte(destval, *srcreg);
+        store_data_byte(destoffset, destval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = xor_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x31
+****************************************************************************/
+static void
+x86emuOp_xor_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("XOR\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = xor_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = xor_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = xor_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = xor_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = xor_long(destval, *srcreg);
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = xor_word(destval, *srcreg);
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 3:                    /* 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 = xor_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();
+            *destreg = xor_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x32
+****************************************************************************/
+static void
+x86emuOp_xor_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint srcoffset;
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("XOR\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = xor_byte(*destreg, srcval);
+        break;
+    case 1:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = xor_byte(*destreg, srcval);
+        break;
+    case 2:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = xor_byte(*destreg, srcval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = xor_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x33
+****************************************************************************/
+static void
+x86emuOp_xor_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("XOR\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = xor_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = xor_word(*destreg, srcval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = xor_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = xor_word(*destreg, srcval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = xor_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = xor_word(*destreg, srcval);
+        }
+        break;
+    case 3:                    /* 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 = xor_long(*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 = xor_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x34
+****************************************************************************/
+static void
+x86emuOp_xor_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("XOR\tAL,");
+    srcval = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    M.x86.R_AL = xor_byte(M.x86.R_AL, srcval);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x35
+****************************************************************************/
+static void
+x86emuOp_xor_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("XOR\tEAX,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("XOR\tAX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = xor_long(M.x86.R_EAX, srcval);
+    }
+    else {
+        M.x86.R_AX = xor_word(M.x86.R_AX, (u16) srcval);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x36
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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 0x38
+****************************************************************************/
+static void
+x86emuOp_cmp_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 *destreg, *srcreg;
+    u8 destval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("CMP\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        cmp_byte(destval, *srcreg);
+        break;
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        cmp_byte(destval, *srcreg);
+        break;
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        cmp_byte(destval, *srcreg);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        cmp_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x39
+****************************************************************************/
+static void
+x86emuOp_cmp_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("CMP\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            cmp_long(destval, *srcreg);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            cmp_word(destval, *srcreg);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            cmp_long(destval, *srcreg);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            cmp_word(destval, *srcreg);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            cmp_long(destval, *srcreg);
+        }
+        else {
+            u16 destval;
+            u16 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            cmp_word(destval, *srcreg);
+        }
+        break;
+    case 3:                    /* 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();
+            cmp_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();
+            cmp_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3a
+****************************************************************************/
+static void
+x86emuOp_cmp_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u8 *destreg, *srcreg;
+    uint srcoffset;
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("CMP\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        cmp_byte(*destreg, srcval);
+        break;
+    case 1:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        cmp_byte(*destreg, srcval);
+        break;
+    case 2:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        cmp_byte(*destreg, srcval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        cmp_byte(*destreg, *srcreg);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3b
+****************************************************************************/
+static void
+x86emuOp_cmp_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("CMP\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            cmp_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            cmp_word(*destreg, srcval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            cmp_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            cmp_word(*destreg, srcval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_long(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            cmp_long(*destreg, srcval);
+        }
+        else {
+            u16 *destreg;
+            u16 srcval;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            cmp_word(*destreg, srcval);
+        }
+        break;
+    case 3:                    /* 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();
+            cmp_long(*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();
+            cmp_word(*destreg, *srcreg);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3c
+****************************************************************************/
+static void
+x86emuOp_cmp_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 srcval;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("CMP\tAL,");
+    srcval = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    cmp_byte(M.x86.R_AL, srcval);
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3d
+****************************************************************************/
+static void
+x86emuOp_cmp_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("CMP\tEAX,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("CMP\tAX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        cmp_long(M.x86.R_EAX, srcval);
+    }
+    else {
+        cmp_word(M.x86.R_AX, (u16) srcval);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3e
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static void
+x86emuOp_inc_AX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("INC\tEAX\n");
+    }
+    else {
+        DECODE_PRINTF("INC\tAX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = inc_long(M.x86.R_EAX);
+    }
+    else {
+        M.x86.R_AX = inc_word(M.x86.R_AX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x41
+****************************************************************************/
+static void
+x86emuOp_inc_CX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("INC\tECX\n");
+    }
+    else {
+        DECODE_PRINTF("INC\tCX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_ECX = inc_long(M.x86.R_ECX);
+    }
+    else {
+        M.x86.R_CX = inc_word(M.x86.R_CX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x42
+****************************************************************************/
+static void
+x86emuOp_inc_DX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("INC\tEDX\n");
+    }
+    else {
+        DECODE_PRINTF("INC\tDX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EDX = inc_long(M.x86.R_EDX);
+    }
+    else {
+        M.x86.R_DX = inc_word(M.x86.R_DX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x43
+****************************************************************************/
+static void
+x86emuOp_inc_BX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("INC\tEBX\n");
+    }
+    else {
+        DECODE_PRINTF("INC\tBX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EBX = inc_long(M.x86.R_EBX);
+    }
+    else {
+        M.x86.R_BX = inc_word(M.x86.R_BX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x44
+****************************************************************************/
+static void
+x86emuOp_inc_SP(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("INC\tESP\n");
+    }
+    else {
+        DECODE_PRINTF("INC\tSP\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_ESP = inc_long(M.x86.R_ESP);
+    }
+    else {
+        M.x86.R_SP = inc_word(M.x86.R_SP);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x45
+****************************************************************************/
+static void
+x86emuOp_inc_BP(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("INC\tEBP\n");
+    }
+    else {
+        DECODE_PRINTF("INC\tBP\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EBP = inc_long(M.x86.R_EBP);
+    }
+    else {
+        M.x86.R_BP = inc_word(M.x86.R_BP);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x46
+****************************************************************************/
+static void
+x86emuOp_inc_SI(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("INC\tESI\n");
+    }
+    else {
+        DECODE_PRINTF("INC\tSI\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_ESI = inc_long(M.x86.R_ESI);
+    }
+    else {
+        M.x86.R_SI = inc_word(M.x86.R_SI);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x47
+****************************************************************************/
+static void
+x86emuOp_inc_DI(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("INC\tEDI\n");
+    }
+    else {
+        DECODE_PRINTF("INC\tDI\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EDI = inc_long(M.x86.R_EDI);
+    }
+    else {
+        M.x86.R_DI = inc_word(M.x86.R_DI);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x48
+****************************************************************************/
+static void
+x86emuOp_dec_AX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("DEC\tEAX\n");
+    }
+    else {
+        DECODE_PRINTF("DEC\tAX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = dec_long(M.x86.R_EAX);
+    }
+    else {
+        M.x86.R_AX = dec_word(M.x86.R_AX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x49
+****************************************************************************/
+static void
+x86emuOp_dec_CX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("DEC\tECX\n");
+    }
+    else {
+        DECODE_PRINTF("DEC\tCX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_ECX = dec_long(M.x86.R_ECX);
+    }
+    else {
+        M.x86.R_CX = dec_word(M.x86.R_CX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4a
+****************************************************************************/
+static void
+x86emuOp_dec_DX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("DEC\tEDX\n");
+    }
+    else {
+        DECODE_PRINTF("DEC\tDX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EDX = dec_long(M.x86.R_EDX);
+    }
+    else {
+        M.x86.R_DX = dec_word(M.x86.R_DX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4b
+****************************************************************************/
+static void
+x86emuOp_dec_BX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("DEC\tEBX\n");
+    }
+    else {
+        DECODE_PRINTF("DEC\tBX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EBX = dec_long(M.x86.R_EBX);
+    }
+    else {
+        M.x86.R_BX = dec_word(M.x86.R_BX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4c
+****************************************************************************/
+static void
+x86emuOp_dec_SP(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("DEC\tESP\n");
+    }
+    else {
+        DECODE_PRINTF("DEC\tSP\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_ESP = dec_long(M.x86.R_ESP);
+    }
+    else {
+        M.x86.R_SP = dec_word(M.x86.R_SP);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4d
+****************************************************************************/
+static void
+x86emuOp_dec_BP(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("DEC\tEBP\n");
+    }
+    else {
+        DECODE_PRINTF("DEC\tBP\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EBP = dec_long(M.x86.R_EBP);
+    }
+    else {
+        M.x86.R_BP = dec_word(M.x86.R_BP);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4e
+****************************************************************************/
+static void
+x86emuOp_dec_SI(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("DEC\tESI\n");
+    }
+    else {
+        DECODE_PRINTF("DEC\tSI\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_ESI = dec_long(M.x86.R_ESI);
+    }
+    else {
+        M.x86.R_SI = dec_word(M.x86.R_SI);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4f
+****************************************************************************/
+static void
+x86emuOp_dec_DI(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("DEC\tEDI\n");
+    }
+    else {
+        DECODE_PRINTF("DEC\tDI\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EDI = dec_long(M.x86.R_EDI);
+    }
+    else {
+        M.x86.R_DI = dec_word(M.x86.R_DI);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x50
+****************************************************************************/
+static void
+x86emuOp_push_AX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("PUSH\tEAX\n");
+    }
+    else {
+        DECODE_PRINTF("PUSH\tAX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(M.x86.R_EAX);
+    }
+    else {
+        push_word(M.x86.R_AX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x51
+****************************************************************************/
+static void
+x86emuOp_push_CX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("PUSH\tECX\n");
+    }
+    else {
+        DECODE_PRINTF("PUSH\tCX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(M.x86.R_ECX);
+    }
+    else {
+        push_word(M.x86.R_CX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x52
+****************************************************************************/
+static void
+x86emuOp_push_DX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("PUSH\tEDX\n");
+    }
+    else {
+        DECODE_PRINTF("PUSH\tDX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(M.x86.R_EDX);
+    }
+    else {
+        push_word(M.x86.R_DX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x53
+****************************************************************************/
+static void
+x86emuOp_push_BX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("PUSH\tEBX\n");
+    }
+    else {
+        DECODE_PRINTF("PUSH\tBX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(M.x86.R_EBX);
+    }
+    else {
+        push_word(M.x86.R_BX);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x54
+****************************************************************************/
+static void
+x86emuOp_push_SP(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("PUSH\tESP\n");
+    }
+    else {
+        DECODE_PRINTF("PUSH\tSP\n");
+    }
+    TRACE_AND_STEP();
+    /* Always push (E)SP, since we are emulating an i386 and above
+     * processor. This is necessary as some BIOS'es use this to check
+     * what type of processor is in the system.
+     */
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(M.x86.R_ESP);
+    }
+    else {
+        push_word((u16) (M.x86.R_SP));
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x55
+****************************************************************************/
+static void
+x86emuOp_push_BP(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("PUSH\tEBP\n");
+    }
+    else {
+        DECODE_PRINTF("PUSH\tBP\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(M.x86.R_EBP);
+    }
+    else {
+        push_word(M.x86.R_BP);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x56
+****************************************************************************/
+static void
+x86emuOp_push_SI(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("PUSH\tESI\n");
+    }
+    else {
+        DECODE_PRINTF("PUSH\tSI\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(M.x86.R_ESI);
+    }
+    else {
+        push_word(M.x86.R_SI);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x57
+****************************************************************************/
+static void
+x86emuOp_push_DI(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("PUSH\tEDI\n");
+    }
+    else {
+        DECODE_PRINTF("PUSH\tDI\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(M.x86.R_EDI);
+    }
+    else {
+        push_word(M.x86.R_DI);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x58
+****************************************************************************/
+static void
+x86emuOp_pop_AX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("POP\tEAX\n");
+    }
+    else {
+        DECODE_PRINTF("POP\tAX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = pop_long();
+    }
+    else {
+        M.x86.R_AX = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x59
+****************************************************************************/
+static void
+x86emuOp_pop_CX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("POP\tECX\n");
+    }
+    else {
+        DECODE_PRINTF("POP\tCX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_ECX = pop_long();
+    }
+    else {
+        M.x86.R_CX = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5a
+****************************************************************************/
+static void
+x86emuOp_pop_DX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("POP\tEDX\n");
+    }
+    else {
+        DECODE_PRINTF("POP\tDX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EDX = pop_long();
+    }
+    else {
+        M.x86.R_DX = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5b
+****************************************************************************/
+static void
+x86emuOp_pop_BX(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("POP\tEBX\n");
+    }
+    else {
+        DECODE_PRINTF("POP\tBX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EBX = pop_long();
+    }
+    else {
+        M.x86.R_BX = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5c
+****************************************************************************/
+static void
+x86emuOp_pop_SP(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("POP\tESP\n");
+    }
+    else {
+        DECODE_PRINTF("POP\tSP\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_ESP = pop_long();
+    }
+    else {
+        M.x86.R_SP = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5d
+****************************************************************************/
+static void
+x86emuOp_pop_BP(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("POP\tEBP\n");
+    }
+    else {
+        DECODE_PRINTF("POP\tBP\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EBP = pop_long();
+    }
+    else {
+        M.x86.R_BP = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5e
+****************************************************************************/
+static void
+x86emuOp_pop_SI(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("POP\tESI\n");
+    }
+    else {
+        DECODE_PRINTF("POP\tSI\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_ESI = pop_long();
+    }
+    else {
+        M.x86.R_SI = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5f
+****************************************************************************/
+static void
+x86emuOp_pop_DI(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("POP\tEDI\n");
+    }
+    else {
+        DECODE_PRINTF("POP\tDI\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EDI = pop_long();
+    }
+    else {
+        M.x86.R_DI = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x60
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        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(",");
+            srcoffset = decode_rm00_address(rl);
+            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_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;
+            s16 imm;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(rl);
+            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 > 0xFFFF) {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            else {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            }
+            *destreg = (u16) res;
+        }
+        break;
+    case 1:
+        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(",");
+            srcoffset = decode_rm01_address(rl);
+            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_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;
+            s16 imm;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(rl);
+            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 > 0xFFFF) {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            else {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            }
+            *destreg = (u16) res;
+        }
+        break;
+    case 2:
+        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(",");
+            srcoffset = decode_rm10_address(rl);
+            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_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;
+            s16 imm;
+
+            destreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(rl);
+            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 > 0xFFFF) {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            else {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            }
+            *destreg = (u16) res;
+        }
+        break;
+    case 3:                    /* 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_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;
+            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 > 0xFFFF) {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            else {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            }
+            *destreg = (u16) res;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6a
+****************************************************************************/
+static 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((s32) imm);
+    }
+    else {
+        push_word(imm);
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6b
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        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_rm00_address(rl);
+            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_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_rm00_address(rl);
+            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 > 0xFFFF) {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            else {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            }
+            *destreg = (u16) res;
+        }
+        break;
+    case 1:
+        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_rm01_address(rl);
+            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_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_rm01_address(rl);
+            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 > 0xFFFF) {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            else {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            }
+            *destreg = (u16) res;
+        }
+        break;
+    case 2:
+        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_rm10_address(rl);
+            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_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_rm10_address(rl);
+            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 > 0xFFFF) {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            else {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            }
+            *destreg = (u16) res;
+        }
+        break;
+    case 3:                    /* 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_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);
+            imm = fetch_byte_imm();
+            DECODE_PRINTF2(",%d\n", (s32) imm);
+            res = (s16) * srcreg * (s16) imm;
+            if (res > 0xFFFF) {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            else {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            }
+            *destreg = (u16) res;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6c
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static void
+x86emuOp_jump_near_O(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+
+    /* jump to byte offset if overflow flag is set */
+    START_OF_INSTR();
+    DECODE_PRINTF("JO\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (ACCESS_FLAG(F_OF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x71
+****************************************************************************/
+static void
+x86emuOp_jump_near_NO(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+
+    /* jump to byte offset if overflow is not set */
+    START_OF_INSTR();
+    DECODE_PRINTF("JNO\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (!ACCESS_FLAG(F_OF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x72
+****************************************************************************/
+static void
+x86emuOp_jump_near_B(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+
+    /* jump to byte offset if carry flag is set. */
+    START_OF_INSTR();
+    DECODE_PRINTF("JB\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (ACCESS_FLAG(F_CF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x73
+****************************************************************************/
+static void
+x86emuOp_jump_near_NB(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+
+    /* jump to byte offset if carry flag is clear. */
+    START_OF_INSTR();
+    DECODE_PRINTF("JNB\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (!ACCESS_FLAG(F_CF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x74
+****************************************************************************/
+static void
+x86emuOp_jump_near_Z(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+
+    /* jump to byte offset if zero flag is set. */
+    START_OF_INSTR();
+    DECODE_PRINTF("JZ\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (ACCESS_FLAG(F_ZF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x75
+****************************************************************************/
+static void
+x86emuOp_jump_near_NZ(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+
+    /* jump to byte offset if zero flag is clear. */
+    START_OF_INSTR();
+    DECODE_PRINTF("JNZ\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (!ACCESS_FLAG(F_ZF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x76
+****************************************************************************/
+static void
+x86emuOp_jump_near_BE(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+
+    /* jump to byte offset if carry flag is set or if the zero
+       flag is set. */
+    START_OF_INSTR();
+    DECODE_PRINTF("JBE\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x77
+****************************************************************************/
+static void
+x86emuOp_jump_near_NBE(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+
+    /* jump to byte offset if carry flag is clear and if the zero
+       flag is clear */
+    START_OF_INSTR();
+    DECODE_PRINTF("JNBE\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (!(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x78
+****************************************************************************/
+static void
+x86emuOp_jump_near_S(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+
+    /* jump to byte offset if sign flag is set */
+    START_OF_INSTR();
+    DECODE_PRINTF("JS\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (ACCESS_FLAG(F_SF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x79
+****************************************************************************/
+static void
+x86emuOp_jump_near_NS(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+
+    /* jump to byte offset if sign flag is clear */
+    START_OF_INSTR();
+    DECODE_PRINTF("JNS\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (!ACCESS_FLAG(F_SF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7a
+****************************************************************************/
+static void
+x86emuOp_jump_near_P(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+
+    /* jump to byte offset if parity flag is set (even parity) */
+    START_OF_INSTR();
+    DECODE_PRINTF("JP\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (ACCESS_FLAG(F_PF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7b
+****************************************************************************/
+static void
+x86emuOp_jump_near_NP(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+
+    /* jump to byte offset if parity flag is clear (odd parity) */
+    START_OF_INSTR();
+    DECODE_PRINTF("JNP\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    if (!ACCESS_FLAG(F_PF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7c
+****************************************************************************/
+static void
+x86emuOp_jump_near_L(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+    int sf, of;
+
+    /* jump to byte offset if sign flag not equal to overflow flag. */
+    START_OF_INSTR();
+    DECODE_PRINTF("JL\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    sf = ACCESS_FLAG(F_SF) != 0;
+    of = ACCESS_FLAG(F_OF) != 0;
+    if (sf ^ of)
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7d
+****************************************************************************/
+static void
+x86emuOp_jump_near_NL(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+    int sf, of;
+
+    /* jump to byte offset if sign flag not equal to overflow flag. */
+    START_OF_INSTR();
+    DECODE_PRINTF("JNL\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    sf = ACCESS_FLAG(F_SF) != 0;
+    of = ACCESS_FLAG(F_OF) != 0;
+    /* note: inverse of above, but using == instead of xor. */
+    if (sf == of)
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7e
+****************************************************************************/
+static void
+x86emuOp_jump_near_LE(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+    int sf, of;
+
+    /* jump to byte offset if sign flag not equal to overflow flag
+       or the zero flag is set */
+    START_OF_INSTR();
+    DECODE_PRINTF("JLE\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    sf = ACCESS_FLAG(F_SF) != 0;
+    of = ACCESS_FLAG(F_OF) != 0;
+    if ((sf ^ of) || ACCESS_FLAG(F_ZF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7f
+****************************************************************************/
+static void
+x86emuOp_jump_near_NLE(u8 X86EMU_UNUSED(op1))
+{
+    s8 offset;
+    u16 target;
+    int sf, of;
+
+    /* jump to byte offset if sign flag equal to overflow flag.
+       and the zero flag is clear */
+    START_OF_INSTR();
+    DECODE_PRINTF("JNLE\t");
+    offset = (s8) fetch_byte_imm();
+    target = (u16) (M.x86.R_IP + (s16) offset);
+    DECODE_PRINTF2("%x\n", target);
+    TRACE_AND_STEP();
+    sf = ACCESS_FLAG(F_SF) != 0;
+    of = ACCESS_FLAG(F_OF) != 0;
+    if ((sf == of) && !ACCESS_FLAG(F_ZF))
+        M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+static u8(*opc80_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 */
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x80
+****************************************************************************/
+static 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 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. */
+    switch (mod) {
+    case 0:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2("%x\n", imm);
+        TRACE_AND_STEP();
+        destval = (*opc80_byte_operation[rh]) (destval, imm);
+        if (rh != 7)
+            store_data_byte(destoffset, destval);
+        break;
+    case 1:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2("%x\n", imm);
+        TRACE_AND_STEP();
+        destval = (*opc80_byte_operation[rh]) (destval, imm);
+        if (rh != 7)
+            store_data_byte(destoffset, destval);
+        break;
+    case 2:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2("%x\n", imm);
+        TRACE_AND_STEP();
+        destval = (*opc80_byte_operation[rh]) (destval, imm);
+        if (rh != 7)
+            store_data_byte(destoffset, destval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF(",");
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2("%x\n", imm);
+        TRACE_AND_STEP();
+        destval = (*opc80_byte_operation[rh]) (*destreg, imm);
+        if (rh != 7)
+            *destreg = destval;
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+static u16(*opc81_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(*opc81_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 */
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x81
+****************************************************************************/
+static 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 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.
+     */
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval, imm;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            imm = fetch_long_imm();
+            DECODE_PRINTF2("%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc81_long_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval, imm;
+
+            DECODE_PRINTF("WORD PTR ");
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            imm = fetch_word_imm();
+            DECODE_PRINTF2("%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc81_word_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_word(destoffset, destval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval, imm;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            imm = fetch_long_imm();
+            DECODE_PRINTF2("%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc81_long_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval, imm;
+
+            DECODE_PRINTF("WORD PTR ");
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            imm = fetch_word_imm();
+            DECODE_PRINTF2("%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc81_word_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_word(destoffset, destval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval, imm;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_long(destoffset);
+            imm = fetch_long_imm();
+            DECODE_PRINTF2("%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc81_long_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval, imm;
+
+            DECODE_PRINTF("WORD PTR ");
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            imm = fetch_word_imm();
+            DECODE_PRINTF2("%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc81_word_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_word(destoffset, destval);
+        }
+        break;
+    case 3:                    /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 destval, imm;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            imm = fetch_long_imm();
+            DECODE_PRINTF2("%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc81_long_operation[rh]) (*destreg, imm);
+            if (rh != 7)
+                *destreg = destval;
+        }
+        else {
+            u16 *destreg;
+            u16 destval, imm;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            imm = fetch_word_imm();
+            DECODE_PRINTF2("%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc81_word_operation[rh]) (*destreg, imm);
+            if (rh != 7)
+                *destreg = destval;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+static u8(*opc82_byte_operation[]) (u8 s, u8 d) = {
+    add_byte,                   /*00 */
+        or_byte,                /*01 *//*YYY UNUSED ???? */
+        adc_byte,               /*02 */
+        sbb_byte,               /*03 */
+        and_byte,               /*04 *//*YYY UNUSED ???? */
+        sub_byte,               /*05 */
+        xor_byte,               /*06 *//*YYY UNUSED ???? */
+        cmp_byte,               /*07 */
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x82
+****************************************************************************/
+static 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 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. */
+    switch (mod) {
+    case 0:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm00_address(rl);
+        destval = fetch_data_byte(destoffset);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2(",%x\n", imm);
+        TRACE_AND_STEP();
+        destval = (*opc82_byte_operation[rh]) (destval, imm);
+        if (rh != 7)
+            store_data_byte(destoffset, destval);
+        break;
+    case 1:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm01_address(rl);
+        destval = fetch_data_byte(destoffset);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2(",%x\n", imm);
+        TRACE_AND_STEP();
+        destval = (*opc82_byte_operation[rh]) (destval, imm);
+        if (rh != 7)
+            store_data_byte(destoffset, destval);
+        break;
+    case 2:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm10_address(rl);
+        destval = fetch_data_byte(destoffset);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2(",%x\n", imm);
+        TRACE_AND_STEP();
+        destval = (*opc82_byte_operation[rh]) (destval, imm);
+        if (rh != 7)
+            store_data_byte(destoffset, destval);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2(",%x\n", imm);
+        TRACE_AND_STEP();
+        destval = (*opc82_byte_operation[rh]) (*destreg, imm);
+        if (rh != 7)
+            *destreg = destval;
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+static u16(*opc83_word_operation[]) (u16 s, u16 d) = {
+    add_word,                   /*00 */
+        or_word,                /*01 *//*YYY UNUSED ???? */
+        adc_word,               /*02 */
+        sbb_word,               /*03 */
+        and_word,               /*04 *//*YYY UNUSED ???? */
+        sub_word,               /*05 */
+        xor_word,               /*06 *//*YYY UNUSED ???? */
+        cmp_word,               /*07 */
+};
+
+static u32(*opc83_long_operation[]) (u32 s, u32 d) = {
+    add_long,                   /*00 */
+        or_long,                /*01 *//*YYY UNUSED ???? */
+        adc_long,               /*02 */
+        sbb_long,               /*03 */
+        and_long,               /*04 *//*YYY UNUSED ???? */
+        sub_long,               /*05 */
+        xor_long,               /*06 *//*YYY UNUSED ???? */
+        cmp_long,               /*07 */
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x83
+****************************************************************************/
+static 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 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. */
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval, imm;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm00_address(rl);
+            destval = fetch_data_long(destoffset);
+            imm = (s8) fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc83_long_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval, imm;
+
+            DECODE_PRINTF("WORD PTR ");
+            destoffset = decode_rm00_address(rl);
+            destval = fetch_data_word(destoffset);
+            imm = (s8) fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc83_word_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_word(destoffset, destval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval, imm;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm01_address(rl);
+            destval = fetch_data_long(destoffset);
+            imm = (s8) fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc83_long_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval, imm;
+
+            DECODE_PRINTF("WORD PTR ");
+            destoffset = decode_rm01_address(rl);
+            destval = fetch_data_word(destoffset);
+            imm = (s8) fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc83_word_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_word(destoffset, destval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval, imm;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm10_address(rl);
+            destval = fetch_data_long(destoffset);
+            imm = (s8) fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc83_long_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval, imm;
+
+            DECODE_PRINTF("WORD PTR ");
+            destoffset = decode_rm10_address(rl);
+            destval = fetch_data_word(destoffset);
+            imm = (s8) fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc83_word_operation[rh]) (destval, imm);
+            if (rh != 7)
+                store_data_word(destoffset, destval);
+        }
+        break;
+    case 3:                    /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 destval, imm;
+
+            destreg = DECODE_RM_LONG_REGISTER(rl);
+            imm = (s8) fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc83_long_operation[rh]) (*destreg, imm);
+            if (rh != 7)
+                *destreg = destval;
+        }
+        else {
+            u16 *destreg;
+            u16 destval, imm;
+
+            destreg = DECODE_RM_WORD_REGISTER(rl);
+            imm = (s8) fetch_byte_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            destval = (*opc83_word_operation[rh]) (*destreg, imm);
+            if (rh != 7)
+                *destreg = destval;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x84
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        test_byte(destval, *srcreg);
+        break;
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        test_byte(destval, *srcreg);
+        break;
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF(",");
+        destval = fetch_data_byte(destoffset);
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        test_byte(destval, *srcreg);
+        break;
+    case 3:                    /* 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);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x85
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            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;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            test_word(destval, *srcreg);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            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;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            test_word(destval, *srcreg);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            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;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            destval = fetch_data_word(destoffset);
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            test_word(destval, *srcreg);
+        }
+        break;
+    case 3:                    /* 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);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x86
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(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);
+        break;
+    case 1:
+        destoffset = decode_rm01_address(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);
+        break;
+    case 2:
+        destoffset = decode_rm10_address(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);
+        break;
+    case 3:                    /* 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;
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x87
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg;
+            u32 destval, tmp;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            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;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            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);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg;
+            u32 destval, tmp;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            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;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            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);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg;
+            u32 destval, tmp;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            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;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            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);
+        }
+        break;
+    case 3:                    /* 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;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x88
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        store_data_byte(destoffset, *srcreg);
+        break;
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        store_data_byte(destoffset, *srcreg);
+        break;
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF(",");
+        srcreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        store_data_byte(destoffset, *srcreg);
+        break;
+    case 3:                    /* 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;
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x89
+****************************************************************************/
+static void
+x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    u32 destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            store_data_long(destoffset, *srcreg);
+        }
+        else {
+            u16 *srcreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            store_data_word(destoffset, *srcreg);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            store_data_long(destoffset, *srcreg);
+        }
+        else {
+            u16 *srcreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            store_data_word(destoffset, *srcreg);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            store_data_long(destoffset, *srcreg);
+        }
+        else {
+            u16 *srcreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            srcreg = DECODE_RM_WORD_REGISTER(rh);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            store_data_word(destoffset, *srcreg);
+        }
+        break;
+    case 3:                    /* 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;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8a
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+        break;
+    case 1:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+        break;
+    case 2:
+        destreg = DECODE_RM_BYTE_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        srcval = fetch_data_byte(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+        break;
+    case 3:                    /* 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;
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8b
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(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_rm00_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(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_rm01_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(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_rm10_address(rl);
+            srcval = fetch_data_word(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        }
+        break;
+    case 3:                    /* 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;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8c
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF(",");
+        srcreg = decode_rm_seg_register(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = *srcreg;
+        store_data_word(destoffset, destval);
+        break;
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF(",");
+        srcreg = decode_rm_seg_register(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = *srcreg;
+        store_data_word(destoffset, destval);
+        break;
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF(",");
+        srcreg = decode_rm_seg_register(rh);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        destval = *srcreg;
+        store_data_word(destoffset, destval);
+        break;
+    case 3:                    /* 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;
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8d
+****************************************************************************/
+static void
+x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("LEA\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+            u32 *srcreg = DECODE_RM_LONG_REGISTER(rh);
+
+            DECODE_PRINTF(",");
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *srcreg = (u32) destoffset;
+        }
+        else {
+            u16 *srcreg = DECODE_RM_WORD_REGISTER(rh);
+
+            DECODE_PRINTF(",");
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *srcreg = (u16) destoffset;
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+            u32 *srcreg = DECODE_RM_LONG_REGISTER(rh);
+
+            DECODE_PRINTF(",");
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *srcreg = (u32) destoffset;
+        }
+        else {
+            u16 *srcreg = DECODE_RM_WORD_REGISTER(rh);
+
+            DECODE_PRINTF(",");
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *srcreg = (u16) destoffset;
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+            u32 *srcreg = DECODE_RM_LONG_REGISTER(rh);
+
+            DECODE_PRINTF(",");
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *srcreg = (u32) destoffset;
+        }
+        else {
+            u16 *srcreg = DECODE_RM_WORD_REGISTER(rh);
+
+            DECODE_PRINTF(",");
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *srcreg = (u16) destoffset;
+        }
+        break;
+    case 3:                    /* register to register */
+        /* undefined.  Do nothing. */
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8e
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        destreg = decode_rm_seg_register(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        srcval = fetch_data_word(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+        break;
+    case 1:
+        destreg = decode_rm_seg_register(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        srcval = fetch_data_word(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+        break;
+    case 2:
+        destreg = decode_rm_seg_register(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        srcval = fetch_data_word(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+        break;
+    case 3:                    /* 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;
+        break;
+    }
+    /*
+     * 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
+****************************************************************************/
+static 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();
+    }
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = pop_long();
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = pop_word();
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = pop_long();
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = pop_word();
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = pop_long();
+            store_data_long(destoffset, destval);
+        }
+        else {
+            u16 destval;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            destval = pop_word();
+            store_data_word(destoffset, destval);
+        }
+        break;
+    case 3:                    /* 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();
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x90
+****************************************************************************/
+static 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
+****************************************************************************/
+static void
+x86emuOp_xchg_word_AX_CX(u8 X86EMU_UNUSED(op1))
+{
+    u32 tmp;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("XCHG\tEAX,ECX\n");
+    }
+    else {
+        DECODE_PRINTF("XCHG\tAX,CX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        tmp = M.x86.R_EAX;
+        M.x86.R_EAX = M.x86.R_ECX;
+        M.x86.R_ECX = tmp;
+    }
+    else {
+        tmp = M.x86.R_AX;
+        M.x86.R_AX = M.x86.R_CX;
+        M.x86.R_CX = (u16) tmp;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x92
+****************************************************************************/
+static void
+x86emuOp_xchg_word_AX_DX(u8 X86EMU_UNUSED(op1))
+{
+    u32 tmp;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("XCHG\tEAX,EDX\n");
+    }
+    else {
+        DECODE_PRINTF("XCHG\tAX,DX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        tmp = M.x86.R_EAX;
+        M.x86.R_EAX = M.x86.R_EDX;
+        M.x86.R_EDX = tmp;
+    }
+    else {
+        tmp = M.x86.R_AX;
+        M.x86.R_AX = M.x86.R_DX;
+        M.x86.R_DX = (u16) tmp;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x93
+****************************************************************************/
+static void
+x86emuOp_xchg_word_AX_BX(u8 X86EMU_UNUSED(op1))
+{
+    u32 tmp;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("XCHG\tEAX,EBX\n");
+    }
+    else {
+        DECODE_PRINTF("XCHG\tAX,BX\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        tmp = M.x86.R_EAX;
+        M.x86.R_EAX = M.x86.R_EBX;
+        M.x86.R_EBX = tmp;
+    }
+    else {
+        tmp = M.x86.R_AX;
+        M.x86.R_AX = M.x86.R_BX;
+        M.x86.R_BX = (u16) tmp;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x94
+****************************************************************************/
+static void
+x86emuOp_xchg_word_AX_SP(u8 X86EMU_UNUSED(op1))
+{
+    u32 tmp;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("XCHG\tEAX,ESP\n");
+    }
+    else {
+        DECODE_PRINTF("XCHG\tAX,SP\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        tmp = M.x86.R_EAX;
+        M.x86.R_EAX = M.x86.R_ESP;
+        M.x86.R_ESP = tmp;
+    }
+    else {
+        tmp = M.x86.R_AX;
+        M.x86.R_AX = M.x86.R_SP;
+        M.x86.R_SP = (u16) tmp;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x95
+****************************************************************************/
+static void
+x86emuOp_xchg_word_AX_BP(u8 X86EMU_UNUSED(op1))
+{
+    u32 tmp;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("XCHG\tEAX,EBP\n");
+    }
+    else {
+        DECODE_PRINTF("XCHG\tAX,BP\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        tmp = M.x86.R_EAX;
+        M.x86.R_EAX = M.x86.R_EBP;
+        M.x86.R_EBP = tmp;
+    }
+    else {
+        tmp = M.x86.R_AX;
+        M.x86.R_AX = M.x86.R_BP;
+        M.x86.R_BP = (u16) tmp;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x96
+****************************************************************************/
+static void
+x86emuOp_xchg_word_AX_SI(u8 X86EMU_UNUSED(op1))
+{
+    u32 tmp;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("XCHG\tEAX,ESI\n");
+    }
+    else {
+        DECODE_PRINTF("XCHG\tAX,SI\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        tmp = M.x86.R_EAX;
+        M.x86.R_EAX = M.x86.R_ESI;
+        M.x86.R_ESI = tmp;
+    }
+    else {
+        tmp = M.x86.R_AX;
+        M.x86.R_AX = M.x86.R_SI;
+        M.x86.R_SI = (u16) tmp;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x97
+****************************************************************************/
+static void
+x86emuOp_xchg_word_AX_DI(u8 X86EMU_UNUSED(op1))
+{
+    u32 tmp;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("XCHG\tEAX,EDI\n");
+    }
+    else {
+        DECODE_PRINTF("XCHG\tAX,DI\n");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        tmp = M.x86.R_EAX;
+        M.x86.R_EAX = M.x86.R_EDI;
+        M.x86.R_EDI = tmp;
+    }
+    else {
+        tmp = M.x86.R_AX;
+        M.x86.R_AX = M.x86.R_DI;
+        M.x86.R_DI = (u16) tmp;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x98
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static void
+x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 farseg, faroff;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("CALL\t");
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        faroff = fetch_long_imm();
+        farseg = fetch_word_imm();
+    }
+    else {
+        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;
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(M.x86.R_EIP);
+    }
+    else {
+        push_word(M.x86.R_IP);
+    }
+    M.x86.R_EIP = faroff & 0xffff;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9b
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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 CX is ZERO. */
+        count = M.x86.R_CX;
+        M.x86.R_CX = 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;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa5
+****************************************************************************/
+static 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 CX is ZERO. */
+        count = M.x86.R_CX;
+        M.x86.R_CX = 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;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa6
+****************************************************************************/
+static 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) {
+        /* REPE  */
+        /* move them until CX is ZERO. */
+        while (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);
+            M.x86.R_CX -= 1;
+            M.x86.R_SI += inc;
+            M.x86.R_DI += inc;
+            if (ACCESS_FLAG(F_ZF) == 0)
+                break;
+        }
+        M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+    }
+    else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+        /* REPNE  */
+        /* move them until CX is ZERO. */
+        while (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);
+            M.x86.R_CX -= 1;
+            M.x86.R_SI += inc;
+            M.x86.R_DI += inc;
+            if (ACCESS_FLAG(F_ZF))
+                break;          /* zero flag set means equal */
+        }
+        M.x86.mode &= ~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
+****************************************************************************/
+static 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");
+        if (ACCESS_FLAG(F_DF))  /* down */
+            inc = -4;
+        else
+            inc = 4;
+    }
+    else {
+        DECODE_PRINTF("CMPS\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 CX is ZERO. */
+        while (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);
+            }
+            M.x86.R_CX -= 1;
+            M.x86.R_SI += inc;
+            M.x86.R_DI += inc;
+            if (ACCESS_FLAG(F_ZF) == 0)
+                break;
+        }
+        M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+    }
+    else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+        /* REPNE  */
+        /* move them until CX is ZERO. */
+        while (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);
+            }
+            M.x86.R_CX -= 1;
+            M.x86.R_SI += inc;
+            M.x86.R_DI += inc;
+            if (ACCESS_FLAG(F_ZF))
+                break;          /* zero flag set means equal */
+        }
+        M.x86.mode &= ~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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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 CX is ZERO. */
+        while (M.x86.R_CX != 0) {
+            store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
+            M.x86.R_CX -= 1;
+            M.x86.R_DI += inc;
+        }
+        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
+****************************************************************************/
+static 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 CX is ZERO. */
+        count = M.x86.R_CX;
+        M.x86.R_CX = 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;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xac
+****************************************************************************/
+static 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 CX is ZERO. */
+        while (M.x86.R_CX != 0) {
+            M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
+            M.x86.R_CX -= 1;
+            M.x86.R_SI += inc;
+        }
+        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
+****************************************************************************/
+static 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 CX is ZERO. */
+        count = M.x86.R_CX;
+        M.x86.R_CX = 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;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xae
+****************************************************************************/
+static 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 CX is ZERO. */
+        while (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);
+            M.x86.R_CX -= 1;
+            M.x86.R_DI += inc;
+            if (ACCESS_FLAG(F_ZF) == 0)
+                break;
+        }
+        M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+    }
+    else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+        /* REPNE  */
+        /* move them until CX is ZERO. */
+        while (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);
+            M.x86.R_CX -= 1;
+            M.x86.R_DI += inc;
+            if (ACCESS_FLAG(F_ZF))
+                break;          /* zero flag set means equal */
+        }
+        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
+****************************************************************************/
+static 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 CX is ZERO. */
+        while (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);
+            }
+            M.x86.R_CX -= 1;
+            M.x86.R_DI += inc;
+            if (ACCESS_FLAG(F_ZF) == 0)
+                break;
+        }
+        M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+    }
+    else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+        /* REPNE  */
+        /* move them until CX is ZERO. */
+        while (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);
+            }
+            M.x86.R_CX -= 1;
+            M.x86.R_DI += inc;
+            if (ACCESS_FLAG(F_ZF))
+                break;          /* zero flag set means equal */
+        }
+        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
+****************************************************************************/
+static void
+x86emuOp_mov_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\tAL,");
+    imm = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", imm);
+    TRACE_AND_STEP();
+    M.x86.R_AL = imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb1
+****************************************************************************/
+static void
+x86emuOp_mov_byte_CL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\tCL,");
+    imm = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", imm);
+    TRACE_AND_STEP();
+    M.x86.R_CL = imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb2
+****************************************************************************/
+static void
+x86emuOp_mov_byte_DL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\tDL,");
+    imm = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", imm);
+    TRACE_AND_STEP();
+    M.x86.R_DL = imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb3
+****************************************************************************/
+static void
+x86emuOp_mov_byte_BL_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\tBL,");
+    imm = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", imm);
+    TRACE_AND_STEP();
+    M.x86.R_BL = imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb4
+****************************************************************************/
+static void
+x86emuOp_mov_byte_AH_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\tAH,");
+    imm = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", imm);
+    TRACE_AND_STEP();
+    M.x86.R_AH = imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb5
+****************************************************************************/
+static void
+x86emuOp_mov_byte_CH_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\tCH,");
+    imm = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", imm);
+    TRACE_AND_STEP();
+    M.x86.R_CH = imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb6
+****************************************************************************/
+static void
+x86emuOp_mov_byte_DH_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\tDH,");
+    imm = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", imm);
+    TRACE_AND_STEP();
+    M.x86.R_DH = imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb7
+****************************************************************************/
+static void
+x86emuOp_mov_byte_BH_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 imm;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("MOV\tBH,");
+    imm = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", imm);
+    TRACE_AND_STEP();
+    M.x86.R_BH = imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb8
+****************************************************************************/
+static void
+x86emuOp_mov_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("MOV\tEAX,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("MOV\tAX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EAX = srcval;
+    }
+    else {
+        M.x86.R_AX = (u16) srcval;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb9
+****************************************************************************/
+static void
+x86emuOp_mov_word_CX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("MOV\tECX,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("MOV\tCX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_ECX = srcval;
+    }
+    else {
+        M.x86.R_CX = (u16) srcval;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xba
+****************************************************************************/
+static void
+x86emuOp_mov_word_DX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("MOV\tEDX,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("MOV\tDX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EDX = srcval;
+    }
+    else {
+        M.x86.R_DX = (u16) srcval;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbb
+****************************************************************************/
+static void
+x86emuOp_mov_word_BX_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("MOV\tEBX,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("MOV\tBX,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EBX = srcval;
+    }
+    else {
+        M.x86.R_BX = (u16) srcval;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbc
+****************************************************************************/
+static void
+x86emuOp_mov_word_SP_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("MOV\tESP,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("MOV\tSP,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_ESP = srcval;
+    }
+    else {
+        M.x86.R_SP = (u16) srcval;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbd
+****************************************************************************/
+static void
+x86emuOp_mov_word_BP_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("MOV\tEBP,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("MOV\tBP,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EBP = srcval;
+    }
+    else {
+        M.x86.R_BP = (u16) srcval;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbe
+****************************************************************************/
+static void
+x86emuOp_mov_word_SI_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("MOV\tESI,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("MOV\tSI,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_ESI = srcval;
+    }
+    else {
+        M.x86.R_SI = (u16) srcval;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbf
+****************************************************************************/
+static void
+x86emuOp_mov_word_DI_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 srcval;
+
+    START_OF_INSTR();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        DECODE_PRINTF("MOV\tEDI,");
+        srcval = fetch_long_imm();
+    }
+    else {
+        DECODE_PRINTF("MOV\tDI,");
+        srcval = fetch_word_imm();
+    }
+    DECODE_PRINTF2("%x\n", srcval);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EDI = srcval;
+    }
+    else {
+        M.x86.R_DI = (u16) srcval;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/* used by opcodes 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,};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc0
+****************************************************************************/
+static 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 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. */
+    switch (mod) {
+    case 0:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm00_address(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);
+        break;
+    case 1:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm01_address(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);
+        break;
+    case 2:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm10_address(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);
+        break;
+    case 3:                    /* 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;
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/* 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,};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc1
+****************************************************************************/
+static 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 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. */
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm00_address(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_rm00_address(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);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm01_address(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_rm01_address(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);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm10_address(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_rm10_address(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);
+        }
+        break;
+    case 3:                    /* 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);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc2
+****************************************************************************/
+static 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);
+    RETURN_TRACE("RET", M.x86.saved_cs, M.x86.saved_ip);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EIP = pop_long();
+    } else {
+        M.x86.R_IP = pop_word();
+    }
+    M.x86.R_SP += imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc3
+****************************************************************************/
+static void
+x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("RET\n");
+    RETURN_TRACE("RET", M.x86.saved_cs, M.x86.saved_ip);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EIP = pop_long();
+    } else {
+        M.x86.R_IP = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc4
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_ES = fetch_data_word(srcoffset + 2);
+        break;
+    case 1:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_ES = fetch_data_word(srcoffset + 2);
+        break;
+    case 2:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_ES = fetch_data_word(srcoffset + 2);
+        break;
+    case 3:                    /* register to register */
+        /* UNDEFINED! */
+        TRACE_AND_STEP();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc5
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_DS = fetch_data_word(srcoffset + 2);
+        break;
+    case 1:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_DS = fetch_data_word(srcoffset + 2);
+        break;
+    case 2:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_DS = fetch_data_word(srcoffset + 2);
+        break;
+    case 3:                    /* register to register */
+        /* UNDEFINED! */
+        TRACE_AND_STEP();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc6
+****************************************************************************/
+static 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();
+    }
+    switch (mod) {
+    case 0:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm00_address(rl);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2(",%2x\n", imm);
+        TRACE_AND_STEP();
+        store_data_byte(destoffset, imm);
+        break;
+    case 1:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm01_address(rl);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2(",%2x\n", imm);
+        TRACE_AND_STEP();
+        store_data_byte(destoffset, imm);
+        break;
+    case 2:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm10_address(rl);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2(",%2x\n", imm);
+        TRACE_AND_STEP();
+        store_data_byte(destoffset, imm);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        imm = fetch_byte_imm();
+        DECODE_PRINTF2(",%2x\n", imm);
+        TRACE_AND_STEP();
+        *destreg = imm;
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc7
+****************************************************************************/
+static 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();
+    }
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 imm;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm00_address(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_rm00_address(rl);
+            imm = fetch_word_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            store_data_word(destoffset, imm);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 imm;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm01_address(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_rm01_address(rl);
+            imm = fetch_word_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            store_data_word(destoffset, imm);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 imm;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm10_address(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_rm10_address(rl);
+            imm = fetch_word_imm();
+            DECODE_PRINTF2(",%x\n", imm);
+            TRACE_AND_STEP();
+            store_data_word(destoffset, imm);
+        }
+        break;
+    case 3:                    /* 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;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc8
+****************************************************************************/
+static 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++) {
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                M.x86.R_BP -= 4;
+                push_long(fetch_data_long_abs(M.x86.R_SS, M.x86.R_BP));
+            } else {
+                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
+****************************************************************************/
+static 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;
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EBP = pop_long();
+    } else {
+        M.x86.R_BP = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xca
+****************************************************************************/
+static 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);
+    RETURN_TRACE("RETF", M.x86.saved_cs, M.x86.saved_ip);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EIP = pop_long();
+        M.x86.R_CS = pop_long() & 0xffff;
+    } else {
+        M.x86.R_IP = pop_word();
+        M.x86.R_CS = pop_word();
+    }
+    M.x86.R_SP += imm;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcb
+****************************************************************************/
+static void
+x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("RETF\n");
+    RETURN_TRACE("RETF", M.x86.saved_cs, M.x86.saved_ip);
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EIP = pop_long();
+        M.x86.R_CS = pop_long() & 0xffff;
+    } else {
+        M.x86.R_IP = pop_word();
+        M.x86.R_CS = pop_word();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcc
+****************************************************************************/
+static void
+x86emuOp_int3(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("INT 3\n");
+    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
+****************************************************************************/
+static void
+x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u8 intnum;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("INT\t");
+    intnum = fetch_byte_imm();
+    DECODE_PRINTF2("%x\n", intnum);
+    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
+****************************************************************************/
+static void
+x86emuOp_into(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("INTO\n");
+    TRACE_AND_STEP();
+    if (ACCESS_FLAG(F_OF)) {
+        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
+****************************************************************************/
+static void
+x86emuOp_iret(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("IRET\n");
+
+    TRACE_AND_STEP();
+
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        M.x86.R_EIP = pop_long();
+        M.x86.R_CS = pop_long() & 0xffff;
+        M.x86.R_EFLG = (pop_long() & 0x257FD5) | (M.x86.R_EFLG & 0x1A0000);
+    } else {
+        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
+****************************************************************************/
+static 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 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. */
+    switch (mod) {
+    case 0:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm00_address(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);
+        break;
+    case 1:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm01_address(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);
+        break;
+    case 2:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm10_address(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);
+        break;
+    case 3:                    /* 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;
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd1
+****************************************************************************/
+static 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 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. */
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm00_address(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_rm00_address(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);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm01_address(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_rm01_address(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);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm10_address(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("BYTE PTR ");
+            destoffset = decode_rm10_address(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);
+        }
+        break;
+    case 3:                    /* 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;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd2
+****************************************************************************/
+static 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 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;
+    switch (mod) {
+    case 0:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm00_address(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);
+        break;
+    case 1:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm01_address(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);
+        break;
+    case 2:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm10_address(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);
+        break;
+    case 3:                    /* 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;
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd3
+****************************************************************************/
+static 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 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;
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm00_address(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_rm00_address(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);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm01_address(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_rm01_address(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);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+
+            DECODE_PRINTF("DWORD PTR ");
+            destoffset = decode_rm10_address(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_rm10_address(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);
+        }
+        break;
+    case 3:                    /* 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);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd4
+****************************************************************************/
+static 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) {
+        /* fix: add base decoding
+           aam_word(u8 val, int base a) */
+        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
+****************************************************************************/
+static void
+x86emuOp_aad(u8 X86EMU_UNUSED(op1))
+{
+    u8 a;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("AAD\n");
+    a = fetch_byte_imm();
+    if (a != 10) {
+        /* fix: add base decoding
+           aad_word(u16 val, int base a) */
+        DECODE_PRINTF("ERROR DECODING AAM\n");
+        TRACE_REGS();
+        HALT_SYS();
+    }
+    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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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();
+    M.x86.R_CX -= 1;
+    if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF))  /* CX != 0 and !ZF */
+        M.x86.R_IP = ip;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe1
+****************************************************************************/
+static 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();
+    M.x86.R_CX -= 1;
+    if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF))   /* CX != 0 and ZF */
+        M.x86.R_IP = ip;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe2
+****************************************************************************/
+static 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();
+    M.x86.R_CX -= 1;
+    if (M.x86.R_CX != 0)
+        M.x86.R_IP = ip;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe3
+****************************************************************************/
+static 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;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe4
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static void
+x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+    s16 ip16 = 0;
+    s32 ip32 = 0;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("CALL\t");
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        ip32 = (s32) fetch_long_imm();
+        ip32 += (s16) M.x86.R_IP;       /* CHECK SIGN */
+        DECODE_PRINTF2("%04x\n", (u16) ip32);
+        CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip32, "");
+    }
+    else {
+        ip16 = (s16) fetch_word_imm();
+        ip16 += (s16) M.x86.R_IP;       /* CHECK SIGN */
+        DECODE_PRINTF2("%04x\n", (u16) ip16);
+        CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip16, "");
+    }
+    TRACE_AND_STEP();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        push_long(M.x86.R_EIP);
+        M.x86.R_EIP = ip32 & 0xffff;
+    }
+    else {
+        push_word(M.x86.R_IP);
+        M.x86.R_EIP = ip16;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe9
+****************************************************************************/
+static void
+x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u32 ip;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("JMP\t");
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        ip = (u32) fetch_long_imm();
+        ip += (u32) M.x86.R_EIP;
+        DECODE_PRINTF2("%08x\n", (u32) ip);
+        TRACE_AND_STEP();
+        M.x86.R_EIP = (u32) ip;
+    }
+    else {
+        ip = (s16) fetch_word_imm();
+        ip += (s16) M.x86.R_IP;
+        DECODE_PRINTF2("%04x\n", (u16) ip);
+        TRACE_AND_STEP();
+        M.x86.R_IP = (u16) ip;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xea
+****************************************************************************/
+static void
+x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+    u16 cs;
+    u32 ip;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("JMP\tFAR ");
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+        ip = fetch_long_imm();
+    }
+    else {
+        ip = fetch_word_imm();
+    }
+    cs = fetch_word_imm();
+    DECODE_PRINTF2("%04x:", cs);
+    DECODE_PRINTF2("%04x\n", ip);
+    TRACE_AND_STEP();
+    M.x86.R_EIP = ip & 0xffff;
+    M.x86.R_CS = cs;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xeb
+****************************************************************************/
+static 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);
+    TRACE_AND_STEP();
+    M.x86.R_IP = target;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xec
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static void
+x86emuOp_repne(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("REPNE\n");
+    TRACE_AND_STEP();
+    M.x86.mode |= SYSMODE_PREFIX_REPNE;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf3
+****************************************************************************/
+static void
+x86emuOp_repe(u8 X86EMU_UNUSED(op1))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("REPE\n");
+    TRACE_AND_STEP();
+    M.x86.mode |= SYSMODE_PREFIX_REPE;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf4
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:                    /* mod=00 */
+        switch (rh) {
+        case 0:                /* test byte imm */
+            DECODE_PRINTF("TEST\tBYTE PTR ");
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            srcval = fetch_byte_imm();
+            DECODE_PRINTF2("%02x\n", srcval);
+            destval = fetch_data_byte(destoffset);
+            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("NOT\tBYTE PTR ");
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            destval = not_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        case 3:
+            DECODE_PRINTF("NEG\tBYTE PTR ");
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            destval = neg_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        case 4:
+            DECODE_PRINTF("MUL\tBYTE PTR ");
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            mul_byte(destval);
+            break;
+        case 5:
+            DECODE_PRINTF("IMUL\tBYTE PTR ");
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            imul_byte(destval);
+            break;
+        case 6:
+            DECODE_PRINTF("DIV\tBYTE PTR ");
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            div_byte(destval);
+            break;
+        case 7:
+            DECODE_PRINTF("IDIV\tBYTE PTR ");
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            idiv_byte(destval);
+            break;
+        }
+        break;                  /* end mod==00 */
+    case 1:                    /* mod=01 */
+        switch (rh) {
+        case 0:                /* test byte imm */
+            DECODE_PRINTF("TEST\tBYTE PTR ");
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            srcval = fetch_byte_imm();
+            DECODE_PRINTF2("%02x\n", srcval);
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            test_byte(destval, srcval);
+            break;
+        case 1:
+            DECODE_PRINTF("ILLEGAL OP MOD=01 RH=01 OP=F6\n");
+            HALT_SYS();
+            break;
+        case 2:
+            DECODE_PRINTF("NOT\tBYTE PTR ");
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            destval = not_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        case 3:
+            DECODE_PRINTF("NEG\tBYTE PTR ");
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            destval = neg_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        case 4:
+            DECODE_PRINTF("MUL\tBYTE PTR ");
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            mul_byte(destval);
+            break;
+        case 5:
+            DECODE_PRINTF("IMUL\tBYTE PTR ");
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            imul_byte(destval);
+            break;
+        case 6:
+            DECODE_PRINTF("DIV\tBYTE PTR ");
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            div_byte(destval);
+            break;
+        case 7:
+            DECODE_PRINTF("IDIV\tBYTE PTR ");
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            idiv_byte(destval);
+            break;
+        }
+        break;                  /* end mod==01 */
+    case 2:                    /* mod=10 */
+        switch (rh) {
+        case 0:                /* test byte imm */
+            DECODE_PRINTF("TEST\tBYTE PTR ");
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            srcval = fetch_byte_imm();
+            DECODE_PRINTF2("%02x\n", srcval);
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            test_byte(destval, srcval);
+            break;
+        case 1:
+            DECODE_PRINTF("ILLEGAL OP MOD=10 RH=01 OP=F6\n");
+            HALT_SYS();
+            break;
+        case 2:
+            DECODE_PRINTF("NOT\tBYTE PTR ");
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            destval = not_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        case 3:
+            DECODE_PRINTF("NEG\tBYTE PTR ");
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            destval = neg_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        case 4:
+            DECODE_PRINTF("MUL\tBYTE PTR ");
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            mul_byte(destval);
+            break;
+        case 5:
+            DECODE_PRINTF("IMUL\tBYTE PTR ");
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            imul_byte(destval);
+            break;
+        case 6:
+            DECODE_PRINTF("DIV\tBYTE PTR ");
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            div_byte(destval);
+            break;
+        case 7:
+            DECODE_PRINTF("IDIV\tBYTE PTR ");
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF("\n");
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            idiv_byte(destval);
+            break;
+        }
+        break;                  /* end mod==10 */
+    case 3:                    /* mod=11 */
+        switch (rh) {
+        case 0:                /* test byte imm */
+            DECODE_PRINTF("TEST\t");
+            destreg = DECODE_RM_BYTE_REGISTER(rl);
+            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("NOT\t");
+            destreg = DECODE_RM_BYTE_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = not_byte(*destreg);
+            break;
+        case 3:
+            DECODE_PRINTF("NEG\t");
+            destreg = DECODE_RM_BYTE_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = neg_byte(*destreg);
+            break;
+        case 4:
+            DECODE_PRINTF("MUL\t");
+            destreg = DECODE_RM_BYTE_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            mul_byte(*destreg); /*!!!  */
+            break;
+        case 5:
+            DECODE_PRINTF("IMUL\t");
+            destreg = DECODE_RM_BYTE_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            imul_byte(*destreg);
+            break;
+        case 6:
+            DECODE_PRINTF("DIV\t");
+            destreg = DECODE_RM_BYTE_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            div_byte(*destreg);
+            break;
+        case 7:
+            DECODE_PRINTF("IDIV\t");
+            destreg = DECODE_RM_BYTE_REGISTER(rl);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            idiv_byte(*destreg);
+            break;
+        }
+        break;                  /* end mod==11 */
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf7
+****************************************************************************/
+static void
+x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rl, rh;
+    uint destoffset;
+
+    /* long, drawn out code follows.  Double switch for a total
+       of 32 cases.  */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:                    /* mod=00 */
+        switch (rh) {
+        case 0:                /* test word imm */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval, srcval;
+
+                DECODE_PRINTF("TEST\tDWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF(",");
+                srcval = fetch_long_imm();
+                DECODE_PRINTF2("%x\n", srcval);
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                test_long(destval, srcval);
+            }
+            else {
+                u16 destval, srcval;
+
+                DECODE_PRINTF("TEST\tWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF(",");
+                srcval = fetch_word_imm();
+                DECODE_PRINTF2("%x\n", srcval);
+                destval = fetch_data_word(destoffset);
+                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:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("NOT\tDWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval = not_long(destval);
+                store_data_long(destoffset, destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("NOT\tWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval = not_word(destval);
+                store_data_word(destoffset, destval);
+            }
+            break;
+        case 3:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("NEG\tDWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval = neg_long(destval);
+                store_data_long(destoffset, destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("NEG\tWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval = neg_word(destval);
+                store_data_word(destoffset, destval);
+            }
+            break;
+        case 4:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("MUL\tDWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                mul_long(destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("MUL\tWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                mul_word(destval);
+            }
+            break;
+        case 5:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("IMUL\tDWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                imul_long(destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("IMUL\tWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                imul_word(destval);
+            }
+            break;
+        case 6:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("DIV\tDWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                div_long(destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("DIV\tWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                div_word(destval);
+            }
+            break;
+        case 7:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("IDIV\tDWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                idiv_long(destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("IDIV\tWORD PTR ");
+                destoffset = decode_rm00_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                idiv_word(destval);
+            }
+            break;
+        }
+        break;                  /* end mod==00 */
+    case 1:                    /* mod=01 */
+        switch (rh) {
+        case 0:                /* test word imm */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval, srcval;
+
+                DECODE_PRINTF("TEST\tDWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF(",");
+                srcval = fetch_long_imm();
+                DECODE_PRINTF2("%x\n", srcval);
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                test_long(destval, srcval);
+            }
+            else {
+                u16 destval, srcval;
+
+                DECODE_PRINTF("TEST\tWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF(",");
+                srcval = fetch_word_imm();
+                DECODE_PRINTF2("%x\n", srcval);
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                test_word(destval, srcval);
+            }
+            break;
+        case 1:
+            DECODE_PRINTF("ILLEGAL OP MOD=01 RH=01 OP=F6\n");
+            HALT_SYS();
+            break;
+        case 2:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("NOT\tDWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval = not_long(destval);
+                store_data_long(destoffset, destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("NOT\tWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval = not_word(destval);
+                store_data_word(destoffset, destval);
+            }
+            break;
+        case 3:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("NEG\tDWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval = neg_long(destval);
+                store_data_long(destoffset, destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("NEG\tWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval = neg_word(destval);
+                store_data_word(destoffset, destval);
+            }
+            break;
+        case 4:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("MUL\tDWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                mul_long(destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("MUL\tWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                mul_word(destval);
+            }
+            break;
+        case 5:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("IMUL\tDWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                imul_long(destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("IMUL\tWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                imul_word(destval);
+            }
+            break;
+        case 6:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("DIV\tDWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                div_long(destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("DIV\tWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                div_word(destval);
+            }
+            break;
+        case 7:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("IDIV\tDWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                idiv_long(destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("IDIV\tWORD PTR ");
+                destoffset = decode_rm01_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                idiv_word(destval);
+            }
+            break;
+        }
+        break;                  /* end mod==01 */
+    case 2:                    /* mod=10 */
+        switch (rh) {
+        case 0:                /* test word imm */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval, srcval;
+
+                DECODE_PRINTF("TEST\tDWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF(",");
+                srcval = fetch_long_imm();
+                DECODE_PRINTF2("%x\n", srcval);
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                test_long(destval, srcval);
+            }
+            else {
+                u16 destval, srcval;
+
+                DECODE_PRINTF("TEST\tWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF(",");
+                srcval = fetch_word_imm();
+                DECODE_PRINTF2("%x\n", srcval);
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                test_word(destval, srcval);
+            }
+            break;
+        case 1:
+            DECODE_PRINTF("ILLEGAL OP MOD=10 RH=01 OP=F6\n");
+            HALT_SYS();
+            break;
+        case 2:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("NOT\tDWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval = not_long(destval);
+                store_data_long(destoffset, destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("NOT\tWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval = not_word(destval);
+                store_data_word(destoffset, destval);
+            }
+            break;
+        case 3:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("NEG\tDWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval = neg_long(destval);
+                store_data_long(destoffset, destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("NEG\tWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval = neg_word(destval);
+                store_data_word(destoffset, destval);
+            }
+            break;
+        case 4:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("MUL\tDWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                mul_long(destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("MUL\tWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                mul_word(destval);
+            }
+            break;
+        case 5:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("IMUL\tDWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                imul_long(destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("IMUL\tWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                imul_word(destval);
+            }
+            break;
+        case 6:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("DIV\tDWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                div_long(destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("DIV\tWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                div_word(destval);
+            }
+            break;
+        case 7:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval;
+
+                DECODE_PRINTF("IDIV\tDWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                idiv_long(destval);
+            }
+            else {
+                u16 destval;
+
+                DECODE_PRINTF("IDIV\tWORD PTR ");
+                destoffset = decode_rm10_address(rl);
+                DECODE_PRINTF("\n");
+                destval = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                idiv_word(destval);
+            }
+            break;
+        }
+        break;                  /* end mod==10 */
+    case 3:                    /* mod=11 */
+        switch (rh) {
+        case 0:                /* test word imm */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 *destreg;
+                u32 srcval;
+
+                DECODE_PRINTF("TEST\t");
+                destreg = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF(",");
+                srcval = fetch_long_imm();
+                DECODE_PRINTF2("%x\n", srcval);
+                TRACE_AND_STEP();
+                test_long(*destreg, srcval);
+            }
+            else {
+                u16 *destreg;
+                u16 srcval;
+
+                DECODE_PRINTF("TEST\t");
+                destreg = DECODE_RM_WORD_REGISTER(rl);
+                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:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 *destreg;
+
+                DECODE_PRINTF("NOT\t");
+                destreg = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg = not_long(*destreg);
+            }
+            else {
+                u16 *destreg;
+
+                DECODE_PRINTF("NOT\t");
+                destreg = DECODE_RM_WORD_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg = not_word(*destreg);
+            }
+            break;
+        case 3:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 *destreg;
+
+                DECODE_PRINTF("NEG\t");
+                destreg = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg = neg_long(*destreg);
+            }
+            else {
+                u16 *destreg;
+
+                DECODE_PRINTF("NEG\t");
+                destreg = DECODE_RM_WORD_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg = neg_word(*destreg);
+            }
+            break;
+        case 4:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 *destreg;
+
+                DECODE_PRINTF("MUL\t");
+                destreg = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                mul_long(*destreg);     /*!!!  */
+            }
+            else {
+                u16 *destreg;
+
+                DECODE_PRINTF("MUL\t");
+                destreg = DECODE_RM_WORD_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                mul_word(*destreg);     /*!!!  */
+            }
+            break;
+        case 5:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 *destreg;
+
+                DECODE_PRINTF("IMUL\t");
+                destreg = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                imul_long(*destreg);
+            }
+            else {
+                u16 *destreg;
+
+                DECODE_PRINTF("IMUL\t");
+                destreg = DECODE_RM_WORD_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                imul_word(*destreg);
+            }
+            break;
+        case 6:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 *destreg;
+
+                DECODE_PRINTF("DIV\t");
+                destreg = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                div_long(*destreg);
+            }
+            else {
+                u16 *destreg;
+
+                DECODE_PRINTF("DIV\t");
+                destreg = DECODE_RM_WORD_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                div_word(*destreg);
+            }
+            break;
+        case 7:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 *destreg;
+
+                DECODE_PRINTF("IDIV\t");
+                destreg = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                idiv_long(*destreg);
+            }
+            else {
+                u16 *destreg;
+
+                DECODE_PRINTF("IDIV\t");
+                destreg = DECODE_RM_WORD_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                idiv_word(*destreg);
+            }
+            break;
+        }
+        break;                  /* end mod==11 */
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf8
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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 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
+    switch (mod) {
+    case 0:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        switch (rh) {
+        case 0:                /* inc word ptr ... */
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            destval = inc_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        case 1:                /* dec word ptr ... */
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            destval = dec_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        }
+        break;
+    case 1:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        switch (rh) {
+        case 0:
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            destval = inc_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        case 1:
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            destval = dec_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        }
+        break;
+    case 2:
+        DECODE_PRINTF("BYTE PTR ");
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        switch (rh) {
+        case 0:
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            destval = inc_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        case 1:
+            destval = fetch_data_byte(destoffset);
+            TRACE_AND_STEP();
+            destval = dec_byte(destval);
+            store_data_byte(destoffset, destval);
+            break;
+        }
+        break;
+    case 3:
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        DECODE_PRINTF("\n");
+        switch (rh) {
+        case 0:
+            TRACE_AND_STEP();
+            *destreg = inc_byte(*destreg);
+            break;
+        case 1:
+            TRACE_AND_STEP();
+            *destreg = dec_byte(*destreg);
+            break;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xff
+****************************************************************************/
+static void
+x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
+{
+    int mod, rh, rl;
+    uint destoffset = 0;
+    u16 *destreg;
+    u16 destval, destval2;
+
+    /* Yet another special case instruction. */
+    START_OF_INSTR();
+    FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef 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
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        switch (rh) {
+        case 0:                /* inc word ptr ... */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval32;
+
+                destval32 = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval32 = inc_long(destval32);
+                store_data_long(destoffset, destval32);
+            }
+            else {
+                u16 destval16;
+
+                destval16 = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval16 = inc_word(destval16);
+                store_data_word(destoffset, destval16);
+            }
+            break;
+        case 1:                /* dec word ptr ... */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval32;
+
+                destval32 = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval32 = dec_long(destval32);
+                store_data_long(destoffset, destval32);
+            }
+            else {
+                u16 destval16;
+
+                destval16 = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval16 = dec_word(destval16);
+                store_data_word(destoffset, destval16);
+            }
+            break;
+        case 2:                /* call word ptr ... */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                push_long(M.x86.R_EIP);
+                M.x86.R_EIP = destval;
+            } else {
+                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 ... */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destval = fetch_data_long(destoffset);
+                destval2 = fetch_data_word(destoffset + 4);
+                TRACE_AND_STEP();
+                push_long(M.x86.R_CS);
+                M.x86.R_CS = destval2;
+                push_long(M.x86.R_EIP);
+                M.x86.R_EIP = destval;
+            } else {
+                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);
+            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);
+            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) {
+                u32 destval32;
+
+                destval32 = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                push_long(destval32);
+            }
+            else {
+                u16 destval16;
+
+                destval16 = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                push_word(destval16);
+            }
+            break;
+        }
+        break;
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        switch (rh) {
+        case 0:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval32;
+
+                destval32 = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval32 = inc_long(destval32);
+                store_data_long(destoffset, destval32);
+            }
+            else {
+                u16 destval16;
+
+                destval16 = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval16 = inc_word(destval16);
+                store_data_word(destoffset, destval16);
+            }
+            break;
+        case 1:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval32;
+
+                destval32 = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval32 = dec_long(destval32);
+                store_data_long(destoffset, destval32);
+            }
+            else {
+                u16 destval16;
+
+                destval16 = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval16 = dec_word(destval16);
+                store_data_word(destoffset, destval16);
+            }
+            break;
+        case 2:                /* call word ptr ... */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                push_long(M.x86.R_EIP);
+                M.x86.R_EIP = destval;
+            } else {
+                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 ... */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destval = fetch_data_long(destoffset);
+                destval2 = fetch_data_word(destoffset + 4);
+                TRACE_AND_STEP();
+                push_long(M.x86.R_CS);
+                M.x86.R_CS = destval2;
+                push_long(M.x86.R_EIP);
+                M.x86.R_EIP = destval;
+            } else {
+                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);
+            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);
+            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) {
+                u32 destval32;
+
+                destval32 = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                push_long(destval32);
+            }
+            else {
+                u16 destval16;
+
+                destval16 = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                push_word(destval16);
+            }
+            break;
+        }
+        break;
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        switch (rh) {
+        case 0:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval32;
+
+                destval32 = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval32 = inc_long(destval32);
+                store_data_long(destoffset, destval32);
+            }
+            else {
+                u16 destval16;
+
+                destval16 = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval16 = inc_word(destval16);
+                store_data_word(destoffset, destval16);
+            }
+            break;
+        case 1:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 destval32;
+
+                destval32 = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                destval32 = dec_long(destval32);
+                store_data_long(destoffset, destval32);
+            }
+            else {
+                u16 destval16;
+
+                destval16 = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                destval16 = dec_word(destval16);
+                store_data_word(destoffset, destval16);
+            }
+            break;
+        case 2:                /* call word ptr ... */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destval = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                push_long(M.x86.R_EIP);
+                M.x86.R_EIP = destval;
+            } else {
+                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 ... */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destval = fetch_data_long(destoffset);
+                destval2 = fetch_data_word(destoffset + 4);
+                TRACE_AND_STEP();
+                push_long(M.x86.R_CS);
+                M.x86.R_CS = destval2;
+                push_long(M.x86.R_EIP);
+                M.x86.R_EIP = destval;
+            } else {
+                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);
+            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);
+            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) {
+                u32 destval32;
+
+                destval32 = fetch_data_long(destoffset);
+                TRACE_AND_STEP();
+                push_long(destval32);
+            }
+            else {
+                u16 destval16;
+
+                destval16 = fetch_data_word(destoffset);
+                TRACE_AND_STEP();
+                push_word(destval16);
+            }
+            break;
+        }
+        break;
+    case 3:
+        switch (rh) {
+        case 0:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 *destreg32;
+
+                destreg32 = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg32 = inc_long(*destreg32);
+            }
+            else {
+                u16 *destreg16;
+
+                destreg16 = DECODE_RM_WORD_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg16 = inc_word(*destreg16);
+            }
+            break;
+        case 1:
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                u32 *destreg32;
+
+                destreg32 = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg32 = dec_long(*destreg32);
+            }
+            else {
+                u16 *destreg16;
+
+                destreg16 = DECODE_RM_WORD_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                *destreg16 = dec_word(*destreg16);
+            }
+            break;
+        case 2:                /* call word ptr ... */
+            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+                destreg = (u16 *)DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                push_long(M.x86.R_EIP);
+                M.x86.R_EIP = *destreg;
+            } else {
+                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) {
+                u32 *destreg32;
+
+                destreg32 = DECODE_RM_LONG_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                push_long(*destreg32);
+            }
+            else {
+                u16 *destreg16;
+
+                destreg16 = DECODE_RM_WORD_REGISTER(rl);
+                DECODE_PRINTF("\n");
+                TRACE_AND_STEP();
+                push_word(*destreg16);
+            }
+            break;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/***************************************************************************
+ * Single byte operation code table:
+ **************************************************************************/
+void (*x86emu_optab[256]) (u8) = {
+/*  0x00 */ x86emuOp_add_byte_RM_R,
+/*  0x01 */ x86emuOp_add_word_RM_R,
+/*  0x02 */ x86emuOp_add_byte_R_RM,
+/*  0x03 */ x86emuOp_add_word_R_RM,
+/*  0x04 */ x86emuOp_add_byte_AL_IMM,
+/*  0x05 */ x86emuOp_add_word_AX_IMM,
+/*  0x06 */ x86emuOp_push_ES,
+/*  0x07 */ x86emuOp_pop_ES,
+/*  0x08 */ x86emuOp_or_byte_RM_R,
+/*  0x09 */ x86emuOp_or_word_RM_R,
+/*  0x0a */ x86emuOp_or_byte_R_RM,
+/*  0x0b */ x86emuOp_or_word_R_RM,
+/*  0x0c */ x86emuOp_or_byte_AL_IMM,
+/*  0x0d */ x86emuOp_or_word_AX_IMM,
+/*  0x0e */ x86emuOp_push_CS,
+/*  0x0f */ x86emuOp_two_byte,
+/*  0x10 */ x86emuOp_adc_byte_RM_R,
+/*  0x11 */ x86emuOp_adc_word_RM_R,
+/*  0x12 */ x86emuOp_adc_byte_R_RM,
+/*  0x13 */ x86emuOp_adc_word_R_RM,
+/*  0x14 */ x86emuOp_adc_byte_AL_IMM,
+/*  0x15 */ x86emuOp_adc_word_AX_IMM,
+/*  0x16 */ x86emuOp_push_SS,
+/*  0x17 */ x86emuOp_pop_SS,
+/*  0x18 */ x86emuOp_sbb_byte_RM_R,
+/*  0x19 */ x86emuOp_sbb_word_RM_R,
+/*  0x1a */ x86emuOp_sbb_byte_R_RM,
+/*  0x1b */ x86emuOp_sbb_word_R_RM,
+/*  0x1c */ x86emuOp_sbb_byte_AL_IMM,
+/*  0x1d */ x86emuOp_sbb_word_AX_IMM,
+/*  0x1e */ x86emuOp_push_DS,
+/*  0x1f */ x86emuOp_pop_DS,
+/*  0x20 */ x86emuOp_and_byte_RM_R,
+/*  0x21 */ x86emuOp_and_word_RM_R,
+/*  0x22 */ x86emuOp_and_byte_R_RM,
+/*  0x23 */ x86emuOp_and_word_R_RM,
+/*  0x24 */ x86emuOp_and_byte_AL_IMM,
+/*  0x25 */ x86emuOp_and_word_AX_IMM,
+/*  0x26 */ x86emuOp_segovr_ES,
+/*  0x27 */ x86emuOp_daa,
+/*  0x28 */ x86emuOp_sub_byte_RM_R,
+/*  0x29 */ x86emuOp_sub_word_RM_R,
+/*  0x2a */ x86emuOp_sub_byte_R_RM,
+/*  0x2b */ x86emuOp_sub_word_R_RM,
+/*  0x2c */ x86emuOp_sub_byte_AL_IMM,
+/*  0x2d */ x86emuOp_sub_word_AX_IMM,
+/*  0x2e */ x86emuOp_segovr_CS,
+/*  0x2f */ x86emuOp_das,
+/*  0x30 */ x86emuOp_xor_byte_RM_R,
+/*  0x31 */ x86emuOp_xor_word_RM_R,
+/*  0x32 */ x86emuOp_xor_byte_R_RM,
+/*  0x33 */ x86emuOp_xor_word_R_RM,
+/*  0x34 */ x86emuOp_xor_byte_AL_IMM,
+/*  0x35 */ x86emuOp_xor_word_AX_IMM,
+/*  0x36 */ x86emuOp_segovr_SS,
+/*  0x37 */ x86emuOp_aaa,
+/*  0x38 */ x86emuOp_cmp_byte_RM_R,
+/*  0x39 */ x86emuOp_cmp_word_RM_R,
+/*  0x3a */ x86emuOp_cmp_byte_R_RM,
+/*  0x3b */ x86emuOp_cmp_word_R_RM,
+/*  0x3c */ x86emuOp_cmp_byte_AL_IMM,
+/*  0x3d */ x86emuOp_cmp_word_AX_IMM,
+/*  0x3e */ x86emuOp_segovr_DS,
+/*  0x3f */ x86emuOp_aas,
+/*  0x40 */ x86emuOp_inc_AX,
+/*  0x41 */ x86emuOp_inc_CX,
+/*  0x42 */ x86emuOp_inc_DX,
+/*  0x43 */ x86emuOp_inc_BX,
+/*  0x44 */ x86emuOp_inc_SP,
+/*  0x45 */ x86emuOp_inc_BP,
+/*  0x46 */ x86emuOp_inc_SI,
+/*  0x47 */ x86emuOp_inc_DI,
+/*  0x48 */ x86emuOp_dec_AX,
+/*  0x49 */ x86emuOp_dec_CX,
+/*  0x4a */ x86emuOp_dec_DX,
+/*  0x4b */ x86emuOp_dec_BX,
+/*  0x4c */ x86emuOp_dec_SP,
+/*  0x4d */ x86emuOp_dec_BP,
+/*  0x4e */ x86emuOp_dec_SI,
+/*  0x4f */ x86emuOp_dec_DI,
+/*  0x50 */ x86emuOp_push_AX,
+/*  0x51 */ x86emuOp_push_CX,
+/*  0x52 */ x86emuOp_push_DX,
+/*  0x53 */ x86emuOp_push_BX,
+/*  0x54 */ x86emuOp_push_SP,
+/*  0x55 */ x86emuOp_push_BP,
+/*  0x56 */ x86emuOp_push_SI,
+/*  0x57 */ x86emuOp_push_DI,
+/*  0x58 */ x86emuOp_pop_AX,
+/*  0x59 */ x86emuOp_pop_CX,
+/*  0x5a */ x86emuOp_pop_DX,
+/*  0x5b */ x86emuOp_pop_BX,
+/*  0x5c */ x86emuOp_pop_SP,
+/*  0x5d */ x86emuOp_pop_BP,
+/*  0x5e */ x86emuOp_pop_SI,
+/*  0x5f */ x86emuOp_pop_DI,
+/*  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_O,
+/*  0x71 */ x86emuOp_jump_near_NO,
+/*  0x72 */ x86emuOp_jump_near_B,
+/*  0x73 */ x86emuOp_jump_near_NB,
+/*  0x74 */ x86emuOp_jump_near_Z,
+/*  0x75 */ x86emuOp_jump_near_NZ,
+/*  0x76 */ x86emuOp_jump_near_BE,
+/*  0x77 */ x86emuOp_jump_near_NBE,
+/*  0x78 */ x86emuOp_jump_near_S,
+/*  0x79 */ x86emuOp_jump_near_NS,
+/*  0x7a */ x86emuOp_jump_near_P,
+/*  0x7b */ x86emuOp_jump_near_NP,
+/*  0x7c */ x86emuOp_jump_near_L,
+/*  0x7d */ x86emuOp_jump_near_NL,
+/*  0x7e */ x86emuOp_jump_near_LE,
+/*  0x7f */ x86emuOp_jump_near_NLE,
+/*  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_CX,
+/*  0x92 */ x86emuOp_xchg_word_AX_DX,
+/*  0x93 */ x86emuOp_xchg_word_AX_BX,
+/*  0x94 */ x86emuOp_xchg_word_AX_SP,
+/*  0x95 */ x86emuOp_xchg_word_AX_BP,
+/*  0x96 */ x86emuOp_xchg_word_AX_SI,
+/*  0x97 */ x86emuOp_xchg_word_AX_DI,
+/*  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_AL_IMM,
+/*  0xb1 */ x86emuOp_mov_byte_CL_IMM,
+/*  0xb2 */ x86emuOp_mov_byte_DL_IMM,
+/*  0xb3 */ x86emuOp_mov_byte_BL_IMM,
+/*  0xb4 */ x86emuOp_mov_byte_AH_IMM,
+/*  0xb5 */ x86emuOp_mov_byte_CH_IMM,
+/*  0xb6 */ x86emuOp_mov_byte_DH_IMM,
+/*  0xb7 */ x86emuOp_mov_byte_BH_IMM,
+/*  0xb8 */ x86emuOp_mov_word_AX_IMM,
+/*  0xb9 */ x86emuOp_mov_word_CX_IMM,
+/*  0xba */ x86emuOp_mov_word_DX_IMM,
+/*  0xbb */ x86emuOp_mov_word_BX_IMM,
+/*  0xbc */ x86emuOp_mov_word_SP_IMM,
+/*  0xbd */ x86emuOp_mov_word_BP_IMM,
+/*  0xbe */ x86emuOp_mov_word_SI_IMM,
+/*  0xbf */ x86emuOp_mov_word_DI_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/plat/pc86/emu/x86emu/ops.o b/plat/pc86/emu/x86emu/ops.o
new file mode 100644 (file)
index 0000000..ebd6e77
Binary files /dev/null and b/plat/pc86/emu/x86emu/ops.o differ
diff --git a/plat/pc86/emu/x86emu/ops2.c b/plat/pc86/emu/x86emu/ops2.c
new file mode 100644 (file)
index 0000000..5ed2bf6
--- /dev/null
@@ -0,0 +1,3008 @@
+/****************************************************************************
+*
+*                                              Realmode X86 Emulator Library
+*
+*              Copyright (C) 1996-1999 SciTech Software, Inc.
+*                                   Copyright (C) David Mosberger-Tang
+*                                         Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:            ANSI C
+* Environment: Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file includes subroutines to implement the decoding
+*               and emulation of all the x86 extended two-byte processor
+*               instructions.
+*
+****************************************************************************/
+
+#include "x86emu/x86emui.h"
+
+#undef bswap_32
+#define bswap_32(x) (((x & 0xff000000) >> 24) | \
+                    ((x & 0x00ff0000) >> 8) | \
+                    ((x & 0x0000ff00) << 8) | \
+                    ((x & 0x000000ff) << 24))
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+op1 - Instruction op code
+
+REMARKS:
+Handles illegal opcodes.
+****************************************************************************/
+static 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,0x31
+****************************************************************************/
+static void
+x86emuOp2_rdtsc(u8 X86EMU_UNUSED(op2))
+{
+#ifdef __HAS_LONG_LONG__
+    static u64 counter = 0;
+#else
+    static u32 counter = 0;
+#endif
+
+    counter += 0x10000;
+
+    /* read timestamp counter */
+    /*
+     * Note that instead of actually trying to accurately measure this, we just
+     * increase the counter by a fixed amount every time we hit one of these
+     * instructions.  Feel free to come up with a better method.
+     */
+    START_OF_INSTR();
+    DECODE_PRINTF("RDTSC\n");
+    TRACE_AND_STEP();
+#ifdef __HAS_LONG_LONG__
+    M.x86.R_EAX = counter & 0xffffffff;
+    M.x86.R_EDX = counter >> 32;
+#else
+    M.x86.R_EAX = counter;
+    M.x86.R_EDX = 0;
+#endif
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0x80-0x8F
+****************************************************************************/
+static void
+x86emuOp2_long_jump(u8 op2)
+{
+    s32 target;
+    const char *name = NULL;
+    int cond = 0;
+
+    /* conditional jump to word offset. */
+    START_OF_INSTR();
+    switch (op2) {
+    case 0x80:
+        name = "JO\t";
+        cond = ACCESS_FLAG(F_OF);
+        break;
+    case 0x81:
+        name = "JNO\t";
+        cond = !ACCESS_FLAG(F_OF);
+        break;
+    case 0x82:
+        name = "JB\t";
+        cond = ACCESS_FLAG(F_CF);
+        break;
+    case 0x83:
+        name = "JNB\t";
+        cond = !ACCESS_FLAG(F_CF);
+        break;
+    case 0x84:
+        name = "JZ\t";
+        cond = ACCESS_FLAG(F_ZF);
+        break;
+    case 0x85:
+        name = "JNZ\t";
+        cond = !ACCESS_FLAG(F_ZF);
+        break;
+    case 0x86:
+        name = "JBE\t";
+        cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
+        break;
+    case 0x87:
+        name = "JNBE\t";
+        cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
+        break;
+    case 0x88:
+        name = "JS\t";
+        cond = ACCESS_FLAG(F_SF);
+        break;
+    case 0x89:
+        name = "JNS\t";
+        cond = !ACCESS_FLAG(F_SF);
+        break;
+    case 0x8a:
+        name = "JP\t";
+        cond = ACCESS_FLAG(F_PF);
+        break;
+    case 0x8b:
+        name = "JNP\t";
+        cond = !ACCESS_FLAG(F_PF);
+        break;
+    case 0x8c:
+        name = "JL\t";
+        cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+        break;
+    case 0x8d:
+        name = "JNL\t";
+        cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
+        break;
+    case 0x8e:
+        name = "JLE\t";
+        cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+                ACCESS_FLAG(F_ZF));
+        break;
+    case 0x8f:
+        name = "JNLE\t";
+        cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+                 ACCESS_FLAG(F_ZF));
+        break;
+    }
+    DECODE_PRINTF(name);
+    (void) name;
+    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;
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0x90-0x9F
+****************************************************************************/
+static void
+x86emuOp2_set_byte(u8 op2)
+{
+    int mod, rl, rh;
+    uint destoffset;
+    u8 *destreg;
+    const char *name = NULL;
+    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);
+    (void) name;
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        destoffset = decode_rm00_address(rl);
+        TRACE_AND_STEP();
+        store_data_byte(destoffset, cond ? 0x01 : 0x00);
+        break;
+    case 1:
+        destoffset = decode_rm01_address(rl);
+        TRACE_AND_STEP();
+        store_data_byte(destoffset, cond ? 0x01 : 0x00);
+        break;
+    case 2:
+        destoffset = decode_rm10_address(rl);
+        TRACE_AND_STEP();
+        store_data_byte(destoffset, cond ? 0x01 : 0x00);
+        break;
+    case 3:                    /* register to register */
+        destreg = DECODE_RM_BYTE_REGISTER(rl);
+        TRACE_AND_STEP();
+        *destreg = cond ? 0x01 : 0x00;
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa0
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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: CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
+Handles opcode 0x0f,0xa2
+****************************************************************************/
+static void
+x86emuOp2_cpuid(u8 X86EMU_UNUSED(op2))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("CPUID\n");
+    TRACE_AND_STEP();
+    cpuid();
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa3
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval;
+            u32 *shiftreg;
+
+            srcoffset = decode_rm00_address(rl);
+            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;
+
+            srcoffset = decode_rm00_address(rl);
+            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);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval;
+            u32 *shiftreg;
+
+            srcoffset = decode_rm01_address(rl);
+            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;
+
+            srcoffset = decode_rm01_address(rl);
+            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);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval;
+            u32 *shiftreg;
+
+            srcoffset = decode_rm10_address(rl);
+            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;
+
+            srcoffset = decode_rm10_address(rl);
+            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);
+        }
+        break;
+    case 3:                    /* 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);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa4
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            destoffset = decode_rm00_address(rl);
+            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;
+
+            destoffset = decode_rm00_address(rl);
+            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);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            destoffset = decode_rm01_address(rl);
+            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;
+
+            destoffset = decode_rm01_address(rl);
+            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);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            destoffset = decode_rm10_address(rl);
+            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;
+
+            destoffset = decode_rm10_address(rl);
+            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);
+        }
+        break;
+    case 3:                    /* 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);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa5
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            destoffset = decode_rm00_address(rl);
+            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;
+
+            destoffset = decode_rm00_address(rl);
+            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);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            destoffset = decode_rm01_address(rl);
+            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;
+
+            destoffset = decode_rm01_address(rl);
+            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);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            destoffset = decode_rm10_address(rl);
+            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;
+
+            destoffset = decode_rm10_address(rl);
+            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);
+        }
+        break;
+    case 3:                    /* 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);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa8
+****************************************************************************/
+static 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
+****************************************************************************/
+static 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,0xab
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+            u32 *shiftreg;
+
+            srcoffset = decode_rm00_address(rl);
+            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;
+
+            srcoffset = decode_rm00_address(rl);
+            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);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+            u32 *shiftreg;
+
+            srcoffset = decode_rm01_address(rl);
+            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;
+
+            srcoffset = decode_rm01_address(rl);
+            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);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+            u32 *shiftreg;
+
+            srcoffset = decode_rm10_address(rl);
+            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;
+
+            srcoffset = decode_rm10_address(rl);
+            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);
+        }
+        break;
+    case 3:                    /* 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;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xac
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            destoffset = decode_rm00_address(rl);
+            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;
+
+            destoffset = decode_rm00_address(rl);
+            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);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            destoffset = decode_rm01_address(rl);
+            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;
+
+            destoffset = decode_rm01_address(rl);
+            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);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            destoffset = decode_rm10_address(rl);
+            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;
+
+            destoffset = decode_rm10_address(rl);
+            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);
+        }
+        break;
+    case 3:                    /* 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);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xad
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            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;
+
+            destoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            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);
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            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;
+
+            destoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            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);
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 destval;
+            u32 *shiftreg;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            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;
+
+            destoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            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);
+        }
+        break;
+    case 3:                    /* 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);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xaf
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        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_rm00_address(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_rm00_address(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;
+        }
+        break;
+    case 1:
+        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_rm01_address(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_rm01_address(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;
+        }
+        break;
+    case 2:
+        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_rm10_address(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_rm10_address(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;
+        }
+        break;
+    case 3:                    /* 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;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb2
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_SS = fetch_data_word(srcoffset + 2);
+        break;
+    case 1:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_SS = fetch_data_word(srcoffset + 2);
+        break;
+    case 2:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_SS = fetch_data_word(srcoffset + 2);
+        break;
+    case 3:                    /* register to register */
+        /* UNDEFINED! */
+        TRACE_AND_STEP();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb3
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+            u32 *shiftreg;
+
+            srcoffset = decode_rm00_address(rl);
+            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;
+
+            srcoffset = decode_rm00_address(rl);
+            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, (u16) (srcval & ~mask));
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+            u32 *shiftreg;
+
+            srcoffset = decode_rm01_address(rl);
+            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;
+
+            srcoffset = decode_rm01_address(rl);
+            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, (u16) (srcval & ~mask));
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+            u32 *shiftreg;
+
+            srcoffset = decode_rm10_address(rl);
+            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;
+
+            srcoffset = decode_rm10_address(rl);
+            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, (u16) (srcval & ~mask));
+        }
+        break;
+    case 3:                    /* 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;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb4
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_FS = fetch_data_word(srcoffset + 2);
+        break;
+    case 1:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_FS = fetch_data_word(srcoffset + 2);
+        break;
+    case 2:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_FS = fetch_data_word(srcoffset + 2);
+        break;
+    case 3:                    /* register to register */
+        /* UNDEFINED! */
+        TRACE_AND_STEP();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb5
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_GS = fetch_data_word(srcoffset + 2);
+        break;
+    case 1:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_GS = fetch_data_word(srcoffset + 2);
+        break;
+    case 2:
+        dstreg = DECODE_RM_WORD_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *dstreg = fetch_data_word(srcoffset);
+        M.x86.R_GS = fetch_data_word(srcoffset + 2);
+        break;
+    case 3:                    /* register to register */
+        /* UNDEFINED! */
+        TRACE_AND_STEP();
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb6
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(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_rm00_address(rl);
+            srcval = fetch_data_byte(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(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_rm01_address(rl);
+            srcval = fetch_data_byte(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(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_rm10_address(rl);
+            srcval = fetch_data_byte(srcoffset);
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        }
+        break;
+    case 3:                    /* 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;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb7
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        destreg = DECODE_RM_LONG_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        srcval = fetch_data_word(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+        break;
+    case 1:
+        destreg = DECODE_RM_LONG_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        srcval = fetch_data_word(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+        break;
+    case 2:
+        destreg = DECODE_RM_LONG_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        srcval = fetch_data_word(srcoffset);
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+        break;
+    case 3:                    /* 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;
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xba
+****************************************************************************/
+static void
+x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+    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();
+    }
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+            u8 shift;
+
+            srcoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            TRACE_AND_STEP();
+            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;
+            u8 shift;
+
+            srcoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            TRACE_AND_STEP();
+            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;
+            }
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+            u8 shift;
+
+            srcoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            TRACE_AND_STEP();
+            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;
+            u8 shift;
+
+            srcoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            TRACE_AND_STEP();
+            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;
+            }
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+            u8 shift;
+
+            srcoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            TRACE_AND_STEP();
+            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;
+            u8 shift;
+
+            srcoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            TRACE_AND_STEP();
+            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;
+            }
+        }
+        break;
+    case 3:                    /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *srcreg;
+            u32 mask;
+            u8 shift;
+
+            srcreg = DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            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;
+            u8 shift;
+
+            srcreg = DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            shift = fetch_byte_imm();
+            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;
+            }
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbb
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+            u32 *shiftreg;
+
+            srcoffset = decode_rm00_address(rl);
+            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;
+
+            srcoffset = decode_rm00_address(rl);
+            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, (u16) (srcval ^ mask));
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+            u32 *shiftreg;
+
+            srcoffset = decode_rm01_address(rl);
+            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;
+
+            srcoffset = decode_rm01_address(rl);
+            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, (u16) (srcval ^ mask));
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, mask;
+            u32 *shiftreg;
+
+            srcoffset = decode_rm10_address(rl);
+            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;
+
+            srcoffset = decode_rm10_address(rl);
+            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, (u16) (srcval ^ mask));
+        }
+        break;
+    case 3:                    /* 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;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbc
+****************************************************************************/
+static void
+x86emuOp2_bsf(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("BSF\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, *dstreg;
+
+            srcoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            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;
+
+            srcoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            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;
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, *dstreg;
+
+            srcoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            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;
+
+            srcoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            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;
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, *dstreg;
+
+            srcoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            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;
+
+            srcoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            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;
+        }
+        break;
+    case 3:                    /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, *dstreg;
+
+            srcval = *DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            dstreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+            for (*dstreg = 0; *dstreg < 32; (*dstreg)++)
+                if ((srcval >> *dstreg) & 1)
+                    break;
+        }
+        else {
+            u16 srcval, *dstreg;
+
+            srcval = *DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            dstreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+            for (*dstreg = 0; *dstreg < 16; (*dstreg)++)
+                if ((srcval >> *dstreg) & 1)
+                    break;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbd
+****************************************************************************/
+static void
+x86emuOp2_bsr(u8 X86EMU_UNUSED(op2))
+{
+    int mod, rl, rh;
+    uint srcoffset;
+
+    START_OF_INSTR();
+    DECODE_PRINTF("BSR\t");
+    FETCH_DECODE_MODRM(mod, rh, rl);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, *dstreg;
+
+            srcoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            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;
+
+            srcoffset = decode_rm00_address(rl);
+            DECODE_PRINTF(",");
+            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;
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, *dstreg;
+
+            srcoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            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;
+
+            srcoffset = decode_rm01_address(rl);
+            DECODE_PRINTF(",");
+            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;
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, *dstreg;
+
+            srcoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            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;
+
+            srcoffset = decode_rm10_address(rl);
+            DECODE_PRINTF(",");
+            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;
+        }
+        break;
+    case 3:                    /* register to register */
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 srcval, *dstreg;
+
+            srcval = *DECODE_RM_LONG_REGISTER(rl);
+            DECODE_PRINTF(",");
+            dstreg = DECODE_RM_LONG_REGISTER(rh);
+            TRACE_AND_STEP();
+            CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+            for (*dstreg = 31; *dstreg > 0; (*dstreg)--)
+                if ((srcval >> *dstreg) & 1)
+                    break;
+        }
+        else {
+            u16 srcval, *dstreg;
+
+            srcval = *DECODE_RM_WORD_REGISTER(rl);
+            DECODE_PRINTF(",");
+            dstreg = DECODE_RM_WORD_REGISTER(rh);
+            TRACE_AND_STEP();
+            CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+            for (*dstreg = 15; *dstreg > 0; (*dstreg)--)
+                if ((srcval >> *dstreg) & 1)
+                    break;
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbe
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm00_address(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_rm00_address(rl);
+            srcval = (s16) ((s8) fetch_data_byte(srcoffset));
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        }
+        break;
+    case 1:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm01_address(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_rm01_address(rl);
+            srcval = (s16) ((s8) fetch_data_byte(srcoffset));
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        }
+        break;
+    case 2:
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            u32 *destreg;
+            u32 srcval;
+
+            destreg = DECODE_RM_LONG_REGISTER(rh);
+            DECODE_PRINTF(",");
+            srcoffset = decode_rm10_address(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_rm10_address(rl);
+            srcval = (s16) ((s8) fetch_data_byte(srcoffset));
+            DECODE_PRINTF("\n");
+            TRACE_AND_STEP();
+            *destreg = srcval;
+        }
+        break;
+    case 3:                    /* 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);
+        }
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbf
+****************************************************************************/
+static 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);
+    switch (mod) {
+    case 0:
+        destreg = DECODE_RM_LONG_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm00_address(rl);
+        srcval = (s32) ((s16) fetch_data_word(srcoffset));
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+        break;
+    case 1:
+        destreg = DECODE_RM_LONG_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm01_address(rl);
+        srcval = (s32) ((s16) fetch_data_word(srcoffset));
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+        break;
+    case 2:
+        destreg = DECODE_RM_LONG_REGISTER(rh);
+        DECODE_PRINTF(",");
+        srcoffset = decode_rm10_address(rl);
+        srcval = (s32) ((s16) fetch_data_word(srcoffset));
+        DECODE_PRINTF("\n");
+        TRACE_AND_STEP();
+        *destreg = srcval;
+        break;
+    case 3:                    /* 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);
+        break;
+    }
+    DECODE_CLEAR_SEGOVR();
+    END_OF_INSTR();
+}
+
+/* Handles opcodes 0xc8-0xcf */
+static void
+x86emuOp2_bswap(u8 X86EMU_UNUSED(op2))
+{
+    START_OF_INSTR();
+    DECODE_PRINTF("BSWAP\n");
+    TRACE_AND_STEP();
+
+    switch (op2) {
+    case 0xc8:
+        M.x86.R_EAX = bswap_32(M.x86.R_EAX);
+        break;
+    case 0xc9:
+        M.x86.R_ECX = bswap_32(M.x86.R_ECX);
+        break;
+    case 0xca:
+        M.x86.R_EDX = bswap_32(M.x86.R_EDX);
+        break;
+    case 0xcb:
+        M.x86.R_EBX = bswap_32(M.x86.R_EBX);
+        break;
+    case 0xcc:
+        M.x86.R_ESP = bswap_32(M.x86.R_ESP);
+        break;
+    case 0xcd:
+        M.x86.R_EBP = bswap_32(M.x86.R_EBP);
+        break;
+    case 0xce:
+        M.x86.R_ESI = bswap_32(M.x86.R_ESI);
+        break;
+    case 0xcf:
+        M.x86.R_EDI = bswap_32(M.x86.R_EDI);
+        break;
+    default:
+        /* can't happen */
+        break;
+    }
+
+    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_rdtsc,
+/*  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_cpuid,
+/*  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_bts_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/plat/pc86/emu/x86emu/prim_ops.c b/plat/pc86/emu/x86emu/prim_ops.c
new file mode 100644 (file)
index 0000000..5604c7e
--- /dev/null
@@ -0,0 +1,2859 @@
+/****************************************************************************
+*
+*                                              Realmode X86 Emulator Library
+*
+*              Copyright (C) 1996-1999 SciTech Software, Inc.
+*                                   Copyright (C) David Mosberger-Tang
+*                                         Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:            ANSI C
+* Environment: Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file contains the code to implement the primitive
+*                              machine operations used by the emulation code in ops.c
+*
+* Carry Chain Calculation
+*
+* This represents a somewhat expensive calculation which is
+* apparently required to emulate the setting of the OF and AF flag.
+* The latter is not so important, but the former is.  The overflow
+* flag is the XOR of the top two bits of the carry chain for an
+* addition (similar for subtraction).  Since we do not want to
+* simulate the addition in a bitwise manner, we try to calculate the
+* carry chain given the two operands and the result.
+*
+* So, given the following table, which represents the addition of two
+* bits, we can derive a formula for the carry chain.
+*
+* a   b   cin   r     cout
+* 0   0   0     0     0
+* 0   0   1     1     0
+* 0   1   0     1     0
+* 0   1   1     0     1
+* 1   0   0     1     0
+* 1   0   1     0     1
+* 1   1   0     0     1
+* 1   1   1     1     1
+*
+* Construction of table for cout:
+*
+* ab
+* r  \  00   01   11  10
+* |------------------
+* 0  |   0    1    1   1
+* 1  |   0    0    1   0
+*
+* By inspection, one gets:  cc = ab +  r'(a + b)
+*
+* That represents alot of operations, but NO CHOICE....
+*
+* Borrow Chain Calculation.
+*
+* The following table represents the subtraction of two bits, from
+* which we can derive a formula for the borrow chain.
+*
+* a   b   bin   r     bout
+* 0   0   0     0     0
+* 0   0   1     1     1
+* 0   1   0     1     1
+* 0   1   1     0     1
+* 1   0   0     1     0
+* 1   0   1     0     0
+* 1   1   0     0     0
+* 1   1   1     1     1
+*
+* Construction of table for cout:
+*
+* ab
+* r  \  00   01   11  10
+* |------------------
+* 0  |   0    1    0   0
+* 1  |   1    1    1   0
+*
+* By inspection, one gets:  bc = a'b +  r(a' + b)
+*
+****************************************************************************/
+
+#include <stdlib.h>
+
+#define        PRIM_OPS_NO_REDEFINE_ASM
+#include "x86emu/x86emui.h"
+
+#if defined(__GNUC__)
+#if defined (__i386__) || defined(__i386) || defined(__AMD64__) || defined(__amd64__)
+#include "x86emu/prim_x86_gcc.h"
+#endif
+#endif
+
+/*------------------------- 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 ----------------------------*/
+
+/****************************************************************************
+REMARKS:
+Implements the AAA instruction and side effects.
+****************************************************************************/
+u16
+aaa_word(u16 d)
+{
+    u16 res;
+
+    if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
+        d += 0x6;
+        d += 0x100;
+        SET_FLAG(F_AF);
+        SET_FLAG(F_CF);
+    }
+    else {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_AF);
+    }
+    res = (u16) (d & 0xFF0F);
+    CLEAR_FLAG(F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAA instruction and side effects.
+****************************************************************************/
+u16
+aas_word(u16 d)
+{
+    u16 res;
+
+    if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
+        d -= 0x6;
+        d -= 0x100;
+        SET_FLAG(F_AF);
+        SET_FLAG(F_CF);
+    }
+    else {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_AF);
+    }
+    res = (u16) (d & 0xFF0F);
+    CLEAR_FLAG(F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAD instruction and side effects.
+****************************************************************************/
+u16
+aad_word(u16 d)
+{
+    u16 l;
+    u8 hb, lb;
+
+    hb = (u8) ((d >> 8) & 0xff);
+    lb = (u8) ((d & 0xff));
+    l = (u16) ((lb + 10 * hb) & 0xFF);
+
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    CLEAR_FLAG(F_OF);
+    CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG(l == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
+    return l;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAM instruction and side effects.
+****************************************************************************/
+u16
+aam_word(u8 d)
+{
+    u16 h, l;
+
+    h = (u16) (d / 10);
+    l = (u16) (d % 10);
+    l |= (u16) (h << 8);
+
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    CLEAR_FLAG(F_OF);
+    CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG(l == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
+    return l;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADC instruction and side effects.
+****************************************************************************/
+u8
+adc_byte(u8 d, u8 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 cc;
+
+    if (ACCESS_FLAG(F_CF))
+        res = 1 + d + s;
+    else
+        res = d + s;
+
+    CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
+    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the carry chain  SEE NOTE AT TOP. */
+    cc = (s & d) | ((~res) & (s | d));
+    CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
+    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADC instruction and side effects.
+****************************************************************************/
+u16
+adc_word(u16 d, u16 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 cc;
+
+    if (ACCESS_FLAG(F_CF))
+        res = 1 + d + s;
+    else
+        res = d + s;
+
+    CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
+    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the carry chain  SEE NOTE AT TOP. */
+    cc = (s & d) | ((~res) & (s | d));
+    CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
+    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADC instruction and side effects.
+****************************************************************************/
+u32
+adc_long(u32 d, u32 s)
+{
+    register u32 lo;            /* all operands in native machine order */
+    register u32 hi;
+    register u32 res;
+    register u32 cc;
+
+    if (ACCESS_FLAG(F_CF)) {
+        lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
+        res = 1 + d + s;
+    }
+    else {
+        lo = (d & 0xFFFF) + (s & 0xFFFF);
+        res = d + s;
+    }
+    hi = (lo >> 16) + (d >> 16) + (s >> 16);
+
+    CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
+    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the carry chain  SEE NOTE AT TOP. */
+    cc = (s & d) | ((~res) & (s | d));
+    CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
+    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADD instruction and side effects.
+****************************************************************************/
+u8
+add_byte(u8 d, u8 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 cc;
+
+    res = d + s;
+    CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
+    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the carry chain  SEE NOTE AT TOP. */
+    cc = (s & d) | ((~res) & (s | d));
+    CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
+    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADD instruction and side effects.
+****************************************************************************/
+u16
+add_word(u16 d, u16 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 cc;
+
+    res = d + s;
+    CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
+    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the carry chain  SEE NOTE AT TOP. */
+    cc = (s & d) | ((~res) & (s | d));
+    CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
+    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADD instruction and side effects.
+****************************************************************************/
+u32
+add_long(u32 d, u32 s)
+{
+    register u32 lo;            /* all operands in native machine order */
+    register u32 hi;
+    register u32 res;
+    register u32 cc;
+
+    lo = (d & 0xFFFF) + (s & 0xFFFF);
+    res = d + s;
+    hi = (lo >> 16) + (d >> 16) + (s >> 16);
+
+    CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
+    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the carry chain  SEE NOTE AT TOP. */
+    cc = (s & d) | ((~res) & (s | d));
+    CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
+    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AND instruction and side effects.
+****************************************************************************/
+u8
+and_byte(u8 d, u8 s)
+{
+    register u8 res;            /* all operands in native machine order */
+
+    res = d & s;
+
+    /* set the flags  */
+    CLEAR_FLAG(F_OF);
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AND instruction and side effects.
+****************************************************************************/
+u16
+and_word(u16 d, u16 s)
+{
+    register u16 res;           /* all operands in native machine order */
+
+    res = d & s;
+
+    /* set the flags  */
+    CLEAR_FLAG(F_OF);
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AND instruction and side effects.
+****************************************************************************/
+u32
+and_long(u32 d, u32 s)
+{
+    register u32 res;           /* all operands in native machine order */
+
+    res = d & s;
+
+    /* set the flags  */
+    CLEAR_FLAG(F_OF);
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the CMP instruction and side effects.
+****************************************************************************/
+u8
+cmp_byte(u8 d, u8 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 bc;
+
+    res = d - s;
+    CLEAR_FLAG(F_CF);
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the CMP instruction and side effects.
+****************************************************************************/
+u16
+cmp_word(u16 d, u16 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 bc;
+
+    res = d - s;
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the CMP instruction and side effects.
+****************************************************************************/
+u32
+cmp_long(u32 d, u32 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 bc;
+
+    res = d - s;
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DAA instruction and side effects.
+****************************************************************************/
+u8
+daa_byte(u8 d)
+{
+    u32 res = d;
+
+    if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
+        res += 6;
+        SET_FLAG(F_AF);
+    }
+    if (res > 0x9F || ACCESS_FLAG(F_CF)) {
+        res += 0x60;
+        SET_FLAG(F_CF);
+    }
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DAS instruction and side effects.
+****************************************************************************/
+u8
+das_byte(u8 d)
+{
+    if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
+        d -= 6;
+        SET_FLAG(F_AF);
+    }
+    if (d > 0x9F || ACCESS_FLAG(F_CF)) {
+        d -= 0x60;
+        SET_FLAG(F_CF);
+    }
+    CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG(d == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
+    return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DEC instruction and side effects.
+****************************************************************************/
+u8
+dec_byte(u8 d)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 bc;
+
+    res = d - 1;
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain.  See note at top */
+    /* based on sub_byte, uses s==1.  */
+    bc = (res & (~d | 1)) | (~d & 1);
+    /* carry flag unchanged */
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DEC instruction and side effects.
+****************************************************************************/
+u16
+dec_word(u16 d)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 bc;
+
+    res = d - 1;
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain.  See note at top */
+    /* based on the sub_byte routine, with s==1 */
+    bc = (res & (~d | 1)) | (~d & 1);
+    /* carry flag unchanged */
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DEC instruction and side effects.
+****************************************************************************/
+u32
+dec_long(u32 d)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 bc;
+
+    res = d - 1;
+
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | 1)) | (~d & 1);
+    /* carry flag unchanged */
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the INC instruction and side effects.
+****************************************************************************/
+u8
+inc_byte(u8 d)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 cc;
+
+    res = d + 1;
+    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the carry chain  SEE NOTE AT TOP. */
+    cc = ((1 & d) | (~res)) & (1 | d);
+    CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
+    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the INC instruction and side effects.
+****************************************************************************/
+u16
+inc_word(u16 d)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 cc;
+
+    res = d + 1;
+    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the carry chain  SEE NOTE AT TOP. */
+    cc = (1 & d) | ((~res) & (1 | d));
+    CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
+    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the INC instruction and side effects.
+****************************************************************************/
+u32
+inc_long(u32 d)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 cc;
+
+    res = d + 1;
+    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the carry chain  SEE NOTE AT TOP. */
+    cc = (1 & d) | ((~res) & (1 | d));
+    CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
+    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u8
+or_byte(u8 d, u8 s)
+{
+    register u8 res;            /* all operands in native machine order */
+
+    res = d | s;
+    CLEAR_FLAG(F_OF);
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u16
+or_word(u16 d, u16 s)
+{
+    register u16 res;           /* all operands in native machine order */
+
+    res = d | s;
+    /* set the carry flag to be bit 8 */
+    CLEAR_FLAG(F_OF);
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u32
+or_long(u32 d, u32 s)
+{
+    register u32 res;           /* all operands in native machine order */
+
+    res = d | s;
+
+    /* set the carry flag to be bit 8 */
+    CLEAR_FLAG(F_OF);
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u8
+neg_byte(u8 s)
+{
+    register u8 res;
+    register u8 bc;
+
+    CONDITIONAL_SET_FLAG(s != 0, F_CF);
+    res = (u8) - s;
+    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
+    /* calculate the borrow chain --- modified such that d=0.
+       substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
+       (the one used for sub) and simplifying, since ~d=0xff...,
+       ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
+       ~d&s == s.  So the simplified result is: */
+    bc = res | s;
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u16
+neg_word(u16 s)
+{
+    register u16 res;
+    register u16 bc;
+
+    CONDITIONAL_SET_FLAG(s != 0, F_CF);
+    res = (u16) - s;
+    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain --- modified such that d=0.
+       substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
+       (the one used for sub) and simplifying, since ~d=0xff...,
+       ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
+       ~d&s == s.  So the simplified result is: */
+    bc = res | s;
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u32
+neg_long(u32 s)
+{
+    register u32 res;
+    register u32 bc;
+
+    CONDITIONAL_SET_FLAG(s != 0, F_CF);
+    res = (u32) - s;
+    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain --- modified such that d=0.
+       substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
+       (the one used for sub) and simplifying, since ~d=0xff...,
+       ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
+       ~d&s == s.  So the simplified result is: */
+    bc = res | s;
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the NOT instruction and side effects.
+****************************************************************************/
+u8
+not_byte(u8 s)
+{
+    return ~s;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the NOT instruction and side effects.
+****************************************************************************/
+u16
+not_word(u16 s)
+{
+    return ~s;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the NOT instruction and side effects.
+****************************************************************************/
+u32
+not_long(u32 s)
+{
+    return ~s;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCL instruction and side effects.
+****************************************************************************/
+u8
+rcl_byte(u8 d, u8 s)
+{
+    register unsigned int res, cnt, mask, cf;
+
+    /* s is the rotate distance.  It varies from 0 - 8. */
+    /* have
+
+       CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
+
+       want to rotate through the carry by "s" bits.  We could
+       loop, but that's inefficient.  So the width is 9,
+       and we split into three parts:
+
+       The new carry flag   (was B_n)
+       the stuff in B_n-1 .. B_0
+       the stuff in B_7 .. B_n+1
+
+       The new rotate is done mod 9, and given this,
+       for a rotation of n bits (mod 9) the new carry flag is
+       then located n bits from the MSB.  The low part is
+       then shifted up cnt bits, and the high part is or'd
+       in.  Using CAPS for new values, and lowercase for the
+       original values, this can be expressed as:
+
+       IF n > 0
+       1) CF <-  b_(8-n)
+       2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
+       3) B_(n-1) <- cf
+       4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
+     */
+    res = d;
+    if ((cnt = s % 9) != 0) {
+        /* extract the new CARRY FLAG. */
+        /* CF <-  b_(8-n)             */
+        cf = (d >> (8 - cnt)) & 0x1;
+
+        /* get the low stuff which rotated
+           into the range B_7 .. B_cnt */
+        /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0  */
+        /* note that the right hand side done by the mask */
+        res = (d << cnt) & 0xff;
+
+        /* now the high stuff which rotated around
+           into the positions B_cnt-2 .. B_0 */
+        /* B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1)) */
+        /* shift it downward, 7-(n-2) = 9-n positions.
+           and mask off the result before or'ing in.
+         */
+        mask = (1 << (cnt - 1)) - 1;
+        res |= (d >> (9 - cnt)) & mask;
+
+        /* if the carry flag was set, or it in.  */
+        if (ACCESS_FLAG(F_CF)) {        /* carry flag is set */
+            /*  B_(n-1) <- cf */
+            res |= 1 << (cnt - 1);
+        }
+        /* set the new carry flag, based on the variable "cf" */
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        /* OVERFLOW is set *IFF* cnt==1, then it is the
+           xor of CF and the most significant bit.  Blecck. */
+        /* parenthesized this expression since it appears to
+           be causing OF to be misset */
+        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)), F_OF);
+
+    }
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCL instruction and side effects.
+****************************************************************************/
+u16
+rcl_word(u16 d, u8 s)
+{
+    register unsigned int res, cnt, mask, cf;
+
+    res = d;
+    if ((cnt = s % 17) != 0) {
+        cf = (d >> (16 - cnt)) & 0x1;
+        res = (d << cnt) & 0xffff;
+        mask = (1 << (cnt - 1)) - 1;
+        res |= (d >> (17 - cnt)) & mask;
+        if (ACCESS_FLAG(F_CF)) {
+            res |= 1 << (cnt - 1);
+        }
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)), F_OF);
+    }
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCL instruction and side effects.
+****************************************************************************/
+u32
+rcl_long(u32 d, u8 s)
+{
+    register u32 res, cnt, mask, cf;
+
+    res = d;
+    if ((cnt = s % 33) != 0) {
+        cf = (d >> (32 - cnt)) & 0x1;
+        res = (d << cnt) & 0xffffffff;
+        mask = (1 << (cnt - 1)) - 1;
+        res |= (d >> (33 - cnt)) & mask;
+        if (ACCESS_FLAG(F_CF)) {        /* carry flag is set */
+            res |= 1 << (cnt - 1);
+        }
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)), F_OF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCR instruction and side effects.
+****************************************************************************/
+u8
+rcr_byte(u8 d, u8 s)
+{
+    u32 res, cnt;
+    u32 mask, cf, ocf = 0;
+
+    /* rotate right through carry */
+    /*
+       s is the rotate distance.  It varies from 0 - 8.
+       d is the byte object rotated.
+
+       have
+
+       CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
+
+       The new rotate is done mod 9, and given this,
+       for a rotation of n bits (mod 9) the new carry flag is
+       then located n bits from the LSB.  The low part is
+       then shifted up cnt bits, and the high part is or'd
+       in.  Using CAPS for new values, and lowercase for the
+       original values, this can be expressed as:
+
+       IF n > 0
+       1) CF <-  b_(n-1)
+       2) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
+       3) B_(8-n) <- cf
+       4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
+     */
+    res = d;
+    if ((cnt = s % 9) != 0) {
+        /* extract the new CARRY FLAG. */
+        /* CF <-  b_(n-1)              */
+        if (cnt == 1) {
+            cf = d & 0x1;
+            /* note hackery here.  Access_flag(..) evaluates to either
+               0 if flag not set
+               non-zero if flag is set.
+               doing access_flag(..) != 0 casts that into either
+               0..1 in any representation of the flags register
+               (i.e. packed bit array or unpacked.)
+             */
+            ocf = ACCESS_FLAG(F_CF) != 0;
+        }
+        else
+            cf = (d >> (cnt - 1)) & 0x1;
+
+        /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_n  */
+        /* note that the right hand side done by the mask
+           This is effectively done by shifting the
+           object to the right.  The result must be masked,
+           in case the object came in and was treated
+           as a negative number.  Needed??? */
+
+        mask = (1 << (8 - cnt)) - 1;
+        res = (d >> cnt) & mask;
+
+        /* now the high stuff which rotated around
+           into the positions B_cnt-2 .. B_0 */
+        /* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
+        /* shift it downward, 7-(n-2) = 9-n positions.
+           and mask off the result before or'ing in.
+         */
+        res |= (d << (9 - cnt));
+
+        /* if the carry flag was set, or it in.  */
+        if (ACCESS_FLAG(F_CF)) {        /* carry flag is set */
+            /*  B_(8-n) <- cf */
+            res |= 1 << (8 - cnt);
+        }
+        /* set the new carry flag, based on the variable "cf" */
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        /* OVERFLOW is set *IFF* cnt==1, then it is the
+           xor of CF and the most significant bit.  Blecck. */
+        /* parenthesized... */
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)), F_OF);
+        }
+    }
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCR instruction and side effects.
+****************************************************************************/
+u16
+rcr_word(u16 d, u8 s)
+{
+    u32 res, cnt;
+    u32 mask, cf, ocf = 0;
+
+    /* rotate right through carry */
+    res = d;
+    if ((cnt = s % 17) != 0) {
+        if (cnt == 1) {
+            cf = d & 0x1;
+            ocf = ACCESS_FLAG(F_CF) != 0;
+        }
+        else
+            cf = (d >> (cnt - 1)) & 0x1;
+        mask = (1 << (16 - cnt)) - 1;
+        res = (d >> cnt) & mask;
+        res |= (d << (17 - cnt));
+        if (ACCESS_FLAG(F_CF)) {
+            res |= 1 << (16 - cnt);
+        }
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)), F_OF);
+        }
+    }
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCR instruction and side effects.
+****************************************************************************/
+u32
+rcr_long(u32 d, u8 s)
+{
+    u32 res, cnt;
+    u32 mask, cf, ocf = 0;
+
+    /* rotate right through carry */
+    res = d;
+    if ((cnt = s % 33) != 0) {
+        if (cnt == 1) {
+            cf = d & 0x1;
+            ocf = ACCESS_FLAG(F_CF) != 0;
+        }
+        else
+            cf = (d >> (cnt - 1)) & 0x1;
+        mask = (1 << (32 - cnt)) - 1;
+        res = (d >> cnt) & mask;
+        if (cnt != 1)
+            res |= (d << (33 - cnt));
+        if (ACCESS_FLAG(F_CF)) {        /* carry flag is set */
+            res |= 1 << (32 - cnt);
+        }
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)), F_OF);
+        }
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROL instruction and side effects.
+****************************************************************************/
+u8
+rol_byte(u8 d, u8 s)
+{
+    register unsigned int res, cnt, mask;
+
+    /* rotate left */
+    /*
+       s is the rotate distance.  It varies from 0 - 8.
+       d is the byte object rotated.
+
+       have
+
+       CF  B_7 ... B_0
+
+       The new rotate is done mod 8.
+       Much simpler than the "rcl" or "rcr" operations.
+
+       IF n > 0
+       1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0)
+       2) B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n)
+     */
+    res = d;
+    if ((cnt = s % 8) != 0) {
+        /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
+        res = (d << cnt);
+
+        /* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
+        mask = (1 << cnt) - 1;
+        res |= (d >> (8 - cnt)) & mask;
+
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+        /* OVERFLOW is set *IFF* s==1, then it is the
+           xor of CF and the most significant bit.  Blecck. */
+        CONDITIONAL_SET_FLAG(s == 1 &&
+                             XOR2((res & 0x1) + ((res >> 6) & 0x2)), F_OF);
+    }
+    if (s != 0) {
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+    }
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROL instruction and side effects.
+****************************************************************************/
+u16
+rol_word(u16 d, u8 s)
+{
+    register unsigned int res, cnt, mask;
+
+    res = d;
+    if ((cnt = s % 16) != 0) {
+        res = (d << cnt);
+        mask = (1 << cnt) - 1;
+        res |= (d >> (16 - cnt)) & mask;
+        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+        CONDITIONAL_SET_FLAG(s == 1 &&
+                             XOR2((res & 0x1) + ((res >> 14) & 0x2)), F_OF);
+    }
+    if (s != 0) {
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+    }
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROL instruction and side effects.
+****************************************************************************/
+u32
+rol_long(u32 d, u8 s)
+{
+    register u32 res, cnt, mask;
+
+    res = d;
+    if ((cnt = s % 32) != 0) {
+        res = (d << cnt);
+        mask = (1 << cnt) - 1;
+        res |= (d >> (32 - cnt)) & mask;
+        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+        CONDITIONAL_SET_FLAG(s == 1 &&
+                             XOR2((res & 0x1) + ((res >> 30) & 0x2)), F_OF);
+    }
+    if (s != 0) {
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROR instruction and side effects.
+****************************************************************************/
+u8
+ror_byte(u8 d, u8 s)
+{
+    register unsigned int res, cnt, mask;
+
+    /* rotate right */
+    /*
+       s is the rotate distance.  It varies from 0 - 8.
+       d is the byte object rotated.
+
+       have
+
+       B_7 ... B_0
+
+       The rotate is done mod 8.
+
+       IF n > 0
+       1) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
+       2) B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0)
+     */
+    res = d;
+    if ((cnt = s % 8) != 0) {   /* not a typo, do nada if cnt==0 */
+        /* B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0) */
+        res = (d << (8 - cnt));
+
+        /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
+        mask = (1 << (8 - cnt)) - 1;
+        res |= (d >> (cnt)) & mask;
+
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
+        /* OVERFLOW is set *IFF* s==1, then it is the
+           xor of the two most significant bits.  Blecck. */
+        CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
+    }
+    else if (s != 0) {
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
+    }
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROR instruction and side effects.
+****************************************************************************/
+u16
+ror_word(u16 d, u8 s)
+{
+    register unsigned int res, cnt, mask;
+
+    res = d;
+    if ((cnt = s % 16) != 0) {
+        res = (d << (16 - cnt));
+        mask = (1 << (16 - cnt)) - 1;
+        res |= (d >> (cnt)) & mask;
+        CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
+        CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
+    }
+    else if (s != 0) {
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
+    }
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROR instruction and side effects.
+****************************************************************************/
+u32
+ror_long(u32 d, u8 s)
+{
+    register u32 res, cnt, mask;
+
+    res = d;
+    if ((cnt = s % 32) != 0) {
+        res = (d << (32 - cnt));
+        mask = (1 << (32 - cnt)) - 1;
+        res |= (d >> (cnt)) & mask;
+        CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
+        CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
+    }
+    else if (s != 0) {
+        /* set the new carry flag, Note that it is the low order
+           bit of the result!!!                               */
+        CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHL instruction and side effects.
+****************************************************************************/
+u8
+shl_byte(u8 d, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 8) {
+        cnt = s % 8;
+
+        /* last bit shifted out goes into carry flag */
+        if (cnt > 0) {
+            res = d << cnt;
+            cf = d & (1 << (8 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+        }
+        else {
+            res = (u8) d;
+        }
+
+        if (cnt == 1) {
+            /* Needs simplification. */
+            CONDITIONAL_SET_FLAG((((res & 0x80) == 0x80) ^
+                                  (ACCESS_FLAG(F_CF) != 0)),
+                                 /* was (M.x86.R_FLG&F_CF)==F_CF)), */
+                                 F_OF);
+        }
+        else {
+            CLEAR_FLAG(F_OF);
+        }
+    }
+    else {
+        res = 0;
+        CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
+        CLEAR_FLAG(F_OF);
+        CLEAR_FLAG(F_SF);
+        SET_FLAG(F_PF);
+        SET_FLAG(F_ZF);
+    }
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHL instruction and side effects.
+****************************************************************************/
+u16
+shl_word(u16 d, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 16) {
+        cnt = s % 16;
+        if (cnt > 0) {
+            res = d << cnt;
+            cf = d & (1 << (16 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+        }
+        else {
+            res = (u16) d;
+        }
+
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
+                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
+        }
+        else {
+            CLEAR_FLAG(F_OF);
+        }
+    }
+    else {
+        res = 0;
+        CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
+        CLEAR_FLAG(F_OF);
+        CLEAR_FLAG(F_SF);
+        SET_FLAG(F_PF);
+        SET_FLAG(F_ZF);
+    }
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHL instruction and side effects.
+****************************************************************************/
+u32
+shl_long(u32 d, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 32) {
+        cnt = s % 32;
+        if (cnt > 0) {
+            res = d << cnt;
+            cf = d & (1 << (32 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+        }
+        else {
+            res = d;
+        }
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
+                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
+        }
+        else {
+            CLEAR_FLAG(F_OF);
+        }
+    }
+    else {
+        res = 0;
+        CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
+        CLEAR_FLAG(F_OF);
+        CLEAR_FLAG(F_SF);
+        SET_FLAG(F_PF);
+        SET_FLAG(F_ZF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHR instruction and side effects.
+****************************************************************************/
+u8
+shr_byte(u8 d, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 8) {
+        cnt = s % 8;
+        if (cnt > 0) {
+            cf = d & (1 << (cnt - 1));
+            res = d >> cnt;
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+        }
+        else {
+            res = (u8) d;
+        }
+
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
+        }
+        else {
+            CLEAR_FLAG(F_OF);
+        }
+    }
+    else {
+        res = 0;
+        CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
+        CLEAR_FLAG(F_OF);
+        CLEAR_FLAG(F_SF);
+        SET_FLAG(F_PF);
+        SET_FLAG(F_ZF);
+    }
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHR instruction and side effects.
+****************************************************************************/
+u16
+shr_word(u16 d, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 16) {
+        cnt = s % 16;
+        if (cnt > 0) {
+            cf = d & (1 << (cnt - 1));
+            res = d >> cnt;
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+        }
+        else {
+            res = d;
+        }
+
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
+        }
+        else {
+            CLEAR_FLAG(F_OF);
+        }
+    }
+    else {
+        res = 0;
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+        SET_FLAG(F_ZF);
+        CLEAR_FLAG(F_SF);
+        CLEAR_FLAG(F_PF);
+    }
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHR instruction and side effects.
+****************************************************************************/
+u32
+shr_long(u32 d, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 32) {
+        cnt = s % 32;
+        if (cnt > 0) {
+            cf = d & (1 << (cnt - 1));
+            res = d >> cnt;
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+        }
+        else {
+            res = d;
+        }
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
+        }
+        else {
+            CLEAR_FLAG(F_OF);
+        }
+    }
+    else {
+        res = 0;
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+        SET_FLAG(F_ZF);
+        CLEAR_FLAG(F_SF);
+        CLEAR_FLAG(F_PF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SAR instruction and side effects.
+****************************************************************************/
+u8
+sar_byte(u8 d, u8 s)
+{
+    unsigned int cnt, res, cf, mask, sf;
+
+    res = d;
+    sf = d & 0x80;
+    cnt = s % 8;
+    if (cnt > 0 && cnt < 8) {
+        mask = (1 << (8 - cnt)) - 1;
+        cf = d & (1 << (cnt - 1));
+        res = (d >> cnt) & mask;
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        if (sf) {
+            res |= ~mask;
+        }
+        CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+        CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+        CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    }
+    else if (cnt >= 8) {
+        if (sf) {
+            res = 0xff;
+            SET_FLAG(F_CF);
+            CLEAR_FLAG(F_ZF);
+            SET_FLAG(F_SF);
+            SET_FLAG(F_PF);
+        }
+        else {
+            res = 0;
+            CLEAR_FLAG(F_CF);
+            SET_FLAG(F_ZF);
+            CLEAR_FLAG(F_SF);
+            CLEAR_FLAG(F_PF);
+        }
+    }
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SAR instruction and side effects.
+****************************************************************************/
+u16
+sar_word(u16 d, u8 s)
+{
+    unsigned int cnt, res, cf, mask, sf;
+
+    sf = d & 0x8000;
+    cnt = s % 16;
+    res = d;
+    if (cnt > 0 && cnt < 16) {
+        mask = (1 << (16 - cnt)) - 1;
+        cf = d & (1 << (cnt - 1));
+        res = (d >> cnt) & mask;
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        if (sf) {
+            res |= ~mask;
+        }
+        CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+        CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+        CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    }
+    else if (cnt >= 16) {
+        if (sf) {
+            res = 0xffff;
+            SET_FLAG(F_CF);
+            CLEAR_FLAG(F_ZF);
+            SET_FLAG(F_SF);
+            SET_FLAG(F_PF);
+        }
+        else {
+            res = 0;
+            CLEAR_FLAG(F_CF);
+            SET_FLAG(F_ZF);
+            CLEAR_FLAG(F_SF);
+            CLEAR_FLAG(F_PF);
+        }
+    }
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SAR instruction and side effects.
+****************************************************************************/
+u32
+sar_long(u32 d, u8 s)
+{
+    u32 cnt, res, cf, mask, sf;
+
+    sf = d & 0x80000000;
+    cnt = s % 32;
+    res = d;
+    if (cnt > 0 && cnt < 32) {
+        mask = (1 << (32 - cnt)) - 1;
+        cf = d & (1 << (cnt - 1));
+        res = (d >> cnt) & mask;
+        CONDITIONAL_SET_FLAG(cf, F_CF);
+        if (sf) {
+            res |= ~mask;
+        }
+        CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+        CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+        CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    }
+    else if (cnt >= 32) {
+        if (sf) {
+            res = 0xffffffff;
+            SET_FLAG(F_CF);
+            CLEAR_FLAG(F_ZF);
+            SET_FLAG(F_SF);
+            SET_FLAG(F_PF);
+        }
+        else {
+            res = 0;
+            CLEAR_FLAG(F_CF);
+            SET_FLAG(F_ZF);
+            CLEAR_FLAG(F_SF);
+            CLEAR_FLAG(F_PF);
+        }
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHLD instruction and side effects.
+****************************************************************************/
+u16
+shld_word(u16 d, u16 fill, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 16) {
+        cnt = s % 16;
+        if (cnt > 0) {
+            res = (d << cnt) | (fill >> (16 - cnt));
+            cf = d & (1 << (16 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+        }
+        else {
+            res = d;
+        }
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
+                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
+        }
+        else {
+            CLEAR_FLAG(F_OF);
+        }
+    }
+    else {
+        res = 0;
+        CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
+        CLEAR_FLAG(F_OF);
+        CLEAR_FLAG(F_SF);
+        SET_FLAG(F_PF);
+        SET_FLAG(F_ZF);
+    }
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHLD instruction and side effects.
+****************************************************************************/
+u32
+shld_long(u32 d, u32 fill, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 32) {
+        cnt = s % 32;
+        if (cnt > 0) {
+            res = (d << cnt) | (fill >> (32 - cnt));
+            cf = d & (1 << (32 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+        }
+        else {
+            res = d;
+        }
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
+                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
+        }
+        else {
+            CLEAR_FLAG(F_OF);
+        }
+    }
+    else {
+        res = 0;
+        CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
+        CLEAR_FLAG(F_OF);
+        CLEAR_FLAG(F_SF);
+        SET_FLAG(F_PF);
+        SET_FLAG(F_ZF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHRD instruction and side effects.
+****************************************************************************/
+u16
+shrd_word(u16 d, u16 fill, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 16) {
+        cnt = s % 16;
+        if (cnt > 0) {
+            cf = d & (1 << (cnt - 1));
+            res = (d >> cnt) | (fill << (16 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+        }
+        else {
+            res = d;
+        }
+
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
+        }
+        else {
+            CLEAR_FLAG(F_OF);
+        }
+    }
+    else {
+        res = 0;
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+        SET_FLAG(F_ZF);
+        CLEAR_FLAG(F_SF);
+        CLEAR_FLAG(F_PF);
+    }
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHRD instruction and side effects.
+****************************************************************************/
+u32
+shrd_long(u32 d, u32 fill, u8 s)
+{
+    unsigned int cnt, res, cf;
+
+    if (s < 32) {
+        cnt = s % 32;
+        if (cnt > 0) {
+            cf = d & (1 << (cnt - 1));
+            res = (d >> cnt) | (fill << (32 - cnt));
+            CONDITIONAL_SET_FLAG(cf, F_CF);
+            CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+        }
+        else {
+            res = d;
+        }
+        if (cnt == 1) {
+            CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
+        }
+        else {
+            CLEAR_FLAG(F_OF);
+        }
+    }
+    else {
+        res = 0;
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+        SET_FLAG(F_ZF);
+        CLEAR_FLAG(F_SF);
+        CLEAR_FLAG(F_PF);
+    }
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SBB instruction and side effects.
+****************************************************************************/
+u8
+sbb_byte(u8 d, u8 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 bc;
+
+    if (ACCESS_FLAG(F_CF))
+        res = d - s - 1;
+    else
+        res = d - s;
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SBB instruction and side effects.
+****************************************************************************/
+u16
+sbb_word(u16 d, u16 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 bc;
+
+    if (ACCESS_FLAG(F_CF))
+        res = d - s - 1;
+    else
+        res = d - s;
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SBB instruction and side effects.
+****************************************************************************/
+u32
+sbb_long(u32 d, u32 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 bc;
+
+    if (ACCESS_FLAG(F_CF))
+        res = d - s - 1;
+    else
+        res = d - s;
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SUB instruction and side effects.
+****************************************************************************/
+u8
+sub_byte(u8 d, u8 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 bc;
+
+    res = d - s;
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return (u8) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SUB instruction and side effects.
+****************************************************************************/
+u16
+sub_word(u16 d, u16 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 bc;
+
+    res = d - s;
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return (u16) res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SUB instruction and side effects.
+****************************************************************************/
+u32
+sub_long(u32 d, u32 s)
+{
+    register u32 res;           /* all operands in native machine order */
+    register u32 bc;
+
+    res = d - s;
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+    /* calculate the borrow chain.  See note at top */
+    bc = (res & (~d | s)) | (~d & s);
+    CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the TEST instruction and side effects.
+****************************************************************************/
+void
+test_byte(u8 d, u8 s)
+{
+    register u32 res;           /* all operands in native machine order */
+
+    res = d & s;
+
+    CLEAR_FLAG(F_OF);
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    /* AF == dont care */
+    CLEAR_FLAG(F_CF);
+}
+
+/****************************************************************************
+REMARKS:
+Implements the TEST instruction and side effects.
+****************************************************************************/
+void
+test_word(u16 d, u16 s)
+{
+    register u32 res;           /* all operands in native machine order */
+
+    res = d & s;
+
+    CLEAR_FLAG(F_OF);
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    /* AF == dont care */
+    CLEAR_FLAG(F_CF);
+}
+
+/****************************************************************************
+REMARKS:
+Implements the TEST instruction and side effects.
+****************************************************************************/
+void
+test_long(u32 d, u32 s)
+{
+    register u32 res;           /* all operands in native machine order */
+
+    res = d & s;
+
+    CLEAR_FLAG(F_OF);
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    /* AF == dont care */
+    CLEAR_FLAG(F_CF);
+}
+
+/****************************************************************************
+REMARKS:
+Implements the XOR instruction and side effects.
+****************************************************************************/
+u8
+xor_byte(u8 d, u8 s)
+{
+    register u8 res;            /* all operands in native machine order */
+
+    res = d ^ s;
+    CLEAR_FLAG(F_OF);
+    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the XOR instruction and side effects.
+****************************************************************************/
+u16
+xor_word(u16 d, u16 s)
+{
+    register u16 res;           /* all operands in native machine order */
+
+    res = d ^ s;
+    CLEAR_FLAG(F_OF);
+    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the XOR instruction and side effects.
+****************************************************************************/
+u32
+xor_long(u32 d, u32 s)
+{
+    register u32 res;           /* all operands in native machine order */
+
+    res = d ^ s;
+    CLEAR_FLAG(F_OF);
+    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void
+imul_byte(u8 s)
+{
+    s16 res = (s16) ((s8) M.x86.R_AL * (s8) s);
+
+    M.x86.R_AX = res;
+    if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
+        ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+    }
+    else {
+        SET_FLAG(F_CF);
+        SET_FLAG(F_OF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void
+imul_word(u16 s)
+{
+    s32 res = (s16) M.x86.R_AX * (s16) s;
+
+    M.x86.R_AX = (u16) res;
+    M.x86.R_DX = (u16) (res >> 16);
+    if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) ||
+        ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+    }
+    else {
+        SET_FLAG(F_CF);
+        SET_FLAG(F_OF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void
+imul_long_direct(u32 * res_lo, u32 * res_hi, u32 d, u32 s)
+{
+#ifdef __HAS_LONG_LONG__
+    s64 res = (s64) (s32) d * (s32) s;
+
+    *res_lo = (u32) res;
+    *res_hi = (u32) (res >> 32);
+#else
+    u32 d_lo, d_hi, d_sign;
+    u32 s_lo, s_hi, s_sign;
+    u32 rlo_lo, rlo_hi, rhi_lo;
+
+    if ((d_sign = d & 0x80000000) != 0)
+        d = -d;
+    d_lo = d & 0xFFFF;
+    d_hi = d >> 16;
+    if ((s_sign = s & 0x80000000) != 0)
+        s = -s;
+    s_lo = s & 0xFFFF;
+    s_hi = s >> 16;
+    rlo_lo = d_lo * s_lo;
+    rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
+    rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
+    *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
+    *res_hi = rhi_lo;
+    if (d_sign != s_sign) {
+        d = ~*res_lo;
+        s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
+        *res_lo = ~*res_lo + 1;
+        *res_hi = ~*res_hi + (s >> 16);
+    }
+#endif
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void
+imul_long(u32 s)
+{
+    imul_long_direct(&M.x86.R_EAX, &M.x86.R_EDX, M.x86.R_EAX, s);
+    if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) ||
+        ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+    }
+    else {
+        SET_FLAG(F_CF);
+        SET_FLAG(F_OF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the MUL instruction and side effects.
+****************************************************************************/
+void
+mul_byte(u8 s)
+{
+    u16 res = (u16) (M.x86.R_AL * s);
+
+    M.x86.R_AX = res;
+    if (M.x86.R_AH == 0) {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+    }
+    else {
+        SET_FLAG(F_CF);
+        SET_FLAG(F_OF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the MUL instruction and side effects.
+****************************************************************************/
+void
+mul_word(u16 s)
+{
+    u32 res = M.x86.R_AX * s;
+
+    M.x86.R_AX = (u16) res;
+    M.x86.R_DX = (u16) (res >> 16);
+    if (M.x86.R_DX == 0) {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+    }
+    else {
+        SET_FLAG(F_CF);
+        SET_FLAG(F_OF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the MUL instruction and side effects.
+****************************************************************************/
+void
+mul_long(u32 s)
+{
+#ifdef __HAS_LONG_LONG__
+    u64 res = (u64) M.x86.R_EAX * s;
+
+    M.x86.R_EAX = (u32) res;
+    M.x86.R_EDX = (u32) (res >> 32);
+#else
+    u32 a, a_lo, a_hi;
+    u32 s_lo, s_hi;
+    u32 rlo_lo, rlo_hi, rhi_lo;
+
+    a = M.x86.R_EAX;
+    a_lo = a & 0xFFFF;
+    a_hi = a >> 16;
+    s_lo = s & 0xFFFF;
+    s_hi = s >> 16;
+    rlo_lo = a_lo * s_lo;
+    rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
+    rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
+    M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
+    M.x86.R_EDX = rhi_lo;
+#endif
+
+    if (M.x86.R_EDX == 0) {
+        CLEAR_FLAG(F_CF);
+        CLEAR_FLAG(F_OF);
+    }
+    else {
+        SET_FLAG(F_CF);
+        SET_FLAG(F_OF);
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IDIV instruction and side effects.
+****************************************************************************/
+void
+idiv_byte(u8 s)
+{
+    s32 dvd, div, mod;
+
+    dvd = (s16) M.x86.R_AX;
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    div = dvd / (s8) s;
+    mod = dvd % (s8) s;
+    if (abs(div) > 0x7f) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    M.x86.R_AL = (s8) div;
+    M.x86.R_AH = (s8) mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IDIV instruction and side effects.
+****************************************************************************/
+void
+idiv_word(u16 s)
+{
+    s32 dvd, div, mod;
+
+    dvd = (((s32) M.x86.R_DX) << 16) | M.x86.R_AX;
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    div = dvd / (s16) s;
+    mod = dvd % (s16) s;
+    if (abs(div) > 0x7fff) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_SF);
+    CONDITIONAL_SET_FLAG(div == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
+
+    M.x86.R_AX = (u16) div;
+    M.x86.R_DX = (u16) mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IDIV instruction and side effects.
+****************************************************************************/
+void
+idiv_long(u32 s)
+{
+#ifdef __HAS_LONG_LONG__
+    s64 dvd, div, mod;
+
+    dvd = (((s64) M.x86.R_EDX) << 32) | M.x86.R_EAX;
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    div = dvd / (s32) s;
+    mod = dvd % (s32) s;
+    if (abs(div) > 0x7fffffff) {
+        x86emu_intr_raise(0);
+        return;
+    }
+#else
+    s32 div = 0, mod;
+    s32 h_dvd = M.x86.R_EDX;
+    u32 l_dvd = M.x86.R_EAX;
+    u32 abs_s = s & 0x7FFFFFFF;
+    u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
+    u32 h_s = abs_s >> 1;
+    u32 l_s = abs_s << 31;
+    int counter = 31;
+    int carry;
+
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    do {
+        div <<= 1;
+        carry = (l_dvd >= l_s) ? 0 : 1;
+
+        if (abs_h_dvd < (h_s + carry)) {
+            h_s >>= 1;
+            l_s = abs_s << (--counter);
+            continue;
+        }
+        else {
+            abs_h_dvd -= (h_s + carry);
+            l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
+                : (l_dvd - l_s);
+            h_s >>= 1;
+            l_s = abs_s << (--counter);
+            div |= 1;
+            continue;
+        }
+
+    } while (counter > -1);
+    /* overflow */
+    if (abs_h_dvd || (l_dvd > abs_s)) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    /* sign */
+    div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
+    mod = l_dvd;
+
+#endif
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    CLEAR_FLAG(F_SF);
+    SET_FLAG(F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
+
+    M.x86.R_EAX = (u32) div;
+    M.x86.R_EDX = (u32) mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DIV instruction and side effects.
+****************************************************************************/
+void
+div_byte(u8 s)
+{
+    u32 dvd, div, mod;
+
+    dvd = M.x86.R_AX;
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    div = dvd / (u8) s;
+    mod = dvd % (u8) s;
+    if (abs(div) > 0xff) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    M.x86.R_AL = (u8) div;
+    M.x86.R_AH = (u8) mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DIV instruction and side effects.
+****************************************************************************/
+void
+div_word(u16 s)
+{
+    u32 dvd, div, mod;
+
+    dvd = (((u32) M.x86.R_DX) << 16) | M.x86.R_AX;
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    div = dvd / (u16) s;
+    mod = dvd % (u16) s;
+    if (abs(div) > 0xffff) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_SF);
+    CONDITIONAL_SET_FLAG(div == 0, F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
+
+    M.x86.R_AX = (u16) div;
+    M.x86.R_DX = (u16) mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DIV instruction and side effects.
+****************************************************************************/
+void
+div_long(u32 s)
+{
+#ifdef __HAS_LONG_LONG__
+    u64 dvd, div, mod;
+
+    dvd = (((u64) M.x86.R_EDX) << 32) | M.x86.R_EAX;
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    div = dvd / (u32) s;
+    mod = dvd % (u32) s;
+    if (abs(div) > 0xffffffff) {
+        x86emu_intr_raise(0);
+        return;
+    }
+#else
+    s32 div = 0, mod;
+    s32 h_dvd = M.x86.R_EDX;
+    u32 l_dvd = M.x86.R_EAX;
+
+    u32 h_s = s;
+    u32 l_s = 0;
+    int counter = 32;
+    int carry;
+
+    if (s == 0) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    do {
+        div <<= 1;
+        carry = (l_dvd >= l_s) ? 0 : 1;
+
+        if (h_dvd < (h_s + carry)) {
+            h_s >>= 1;
+            l_s = s << (--counter);
+            continue;
+        }
+        else {
+            h_dvd -= (h_s + carry);
+            l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
+                : (l_dvd - l_s);
+            h_s >>= 1;
+            l_s = s << (--counter);
+            div |= 1;
+            continue;
+        }
+
+    } while (counter > -1);
+    /* overflow */
+    if (h_dvd || (l_dvd > s)) {
+        x86emu_intr_raise(0);
+        return;
+    }
+    mod = l_dvd;
+#endif
+    CLEAR_FLAG(F_CF);
+    CLEAR_FLAG(F_AF);
+    CLEAR_FLAG(F_SF);
+    SET_FLAG(F_ZF);
+    CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
+
+    M.x86.R_EAX = (u32) div;
+    M.x86.R_EDX = (u32) mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IN string instruction and side effects.
+****************************************************************************/
+void
+ins(int size)
+{
+    int inc = size;
+
+    if (ACCESS_FLAG(F_DF)) {
+        inc = -size;
+    }
+    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+        /* dont care whether REPE or REPNE */
+        /* in until CX is ZERO. */
+        u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
+                     M.x86.R_ECX : M.x86.R_CX);
+        switch (size) {
+        case 1:
+            while (count--) {
+                store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
+                                    (*sys_inb) (M.x86.R_DX));
+                M.x86.R_DI += inc;
+            }
+            break;
+
+        case 2:
+            while (count--) {
+                store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
+                                    (*sys_inw) (M.x86.R_DX));
+                M.x86.R_DI += inc;
+            }
+            break;
+        case 4:
+            while (count--) {
+                store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
+                                    (*sys_inl) (M.x86.R_DX));
+                M.x86.R_DI += inc;
+                break;
+            }
+        }
+        M.x86.R_CX = 0;
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            M.x86.R_ECX = 0;
+        }
+        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+    }
+    else {
+        switch (size) {
+        case 1:
+            store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
+                                (*sys_inb) (M.x86.R_DX));
+            break;
+        case 2:
+            store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
+                                (*sys_inw) (M.x86.R_DX));
+            break;
+        case 4:
+            store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
+                                (*sys_inl) (M.x86.R_DX));
+            break;
+        }
+        M.x86.R_DI += inc;
+    }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OUT string instruction and side effects.
+****************************************************************************/
+void
+outs(int size)
+{
+    int inc = size;
+
+    if (ACCESS_FLAG(F_DF)) {
+        inc = -size;
+    }
+    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+        /* dont care whether REPE or REPNE */
+        /* out until CX is ZERO. */
+        u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
+                     M.x86.R_ECX : M.x86.R_CX);
+        switch (size) {
+        case 1:
+            while (count--) {
+                (*sys_outb) (M.x86.R_DX,
+                             fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
+                M.x86.R_SI += inc;
+            }
+            break;
+
+        case 2:
+            while (count--) {
+                (*sys_outw) (M.x86.R_DX,
+                             fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
+                M.x86.R_SI += inc;
+            }
+            break;
+        case 4:
+            while (count--) {
+                (*sys_outl) (M.x86.R_DX,
+                             fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
+                M.x86.R_SI += inc;
+                break;
+            }
+        }
+        M.x86.R_CX = 0;
+        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+            M.x86.R_ECX = 0;
+        }
+        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+    }
+    else {
+        switch (size) {
+        case 1:
+            (*sys_outb) (M.x86.R_DX,
+                         fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
+            break;
+        case 2:
+            (*sys_outw) (M.x86.R_DX,
+                         fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
+            break;
+        case 4:
+            (*sys_outl) (M.x86.R_DX,
+                         fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
+            break;
+        }
+        M.x86.R_SI += inc;
+    }
+}
+
+/****************************************************************************
+PARAMETERS:
+addr   - Address to fetch word from
+
+REMARKS:
+Fetches a word from emulator memory using an absolute address.
+****************************************************************************/
+u16
+mem_access_word(int addr)
+{
+    DB(if (CHECK_MEM_ACCESS())
+       x86emu_check_mem_access(addr);)
+        return (*sys_rdw) (addr);
+}
+
+/****************************************************************************
+REMARKS:
+Pushes a word onto the stack.
+
+NOTE: Do not inline this, as (*sys_wrX) is already inline!
+****************************************************************************/
+void
+push_word(u16 w)
+{
+    DB(if (CHECK_SP_ACCESS())
+       x86emu_check_sp_access();)
+        M.x86.R_SP -= 2;
+    (*sys_wrw) (((u32) M.x86.R_SS << 4) + M.x86.R_SP, w);
+}
+
+/****************************************************************************
+REMARKS:
+Pushes a long onto the stack.
+
+NOTE: Do not inline this, as (*sys_wrX) is already inline!
+****************************************************************************/
+void
+push_long(u32 w)
+{
+    DB(if (CHECK_SP_ACCESS())
+       x86emu_check_sp_access();)
+        M.x86.R_SP -= 4;
+    (*sys_wrl) (((u32) M.x86.R_SS << 4) + M.x86.R_SP, w);
+}
+
+/****************************************************************************
+REMARKS:
+Pops a word from the stack.
+
+NOTE: Do not inline this, as (*sys_rdX) is already inline!
+****************************************************************************/
+u16
+pop_word(void)
+{
+    register u16 res;
+
+    DB(if (CHECK_SP_ACCESS())
+       x86emu_check_sp_access();)
+        res = (*sys_rdw) (((u32) M.x86.R_SS << 4) + M.x86.R_SP);
+    M.x86.R_SP += 2;
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+Pops a long from the stack.
+
+NOTE: Do not inline this, as (*sys_rdX) is already inline!
+****************************************************************************/
+u32
+pop_long(void)
+{
+    register u32 res;
+
+    DB(if (CHECK_SP_ACCESS())
+       x86emu_check_sp_access();)
+        res = (*sys_rdl) (((u32) M.x86.R_SS << 4) + M.x86.R_SP);
+    M.x86.R_SP += 4;
+    return res;
+}
+
+/****************************************************************************
+REMARKS:
+CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
+****************************************************************************/
+void
+cpuid(void)
+{
+    u32 feature = M.x86.R_EAX;
+
+#ifdef X86EMU_HAS_HW_CPUID
+    /* If the platform allows it, we will base our values on the real
+     * results from the CPUID instruction.  We limit support to the
+     * first two features, and the results of those are sanitized.
+     */
+    if (feature <= 1)
+        hw_cpuid(&M.x86.R_EAX, &M.x86.R_EBX, &M.x86.R_ECX, &M.x86.R_EDX);
+#endif
+
+    switch (feature) {
+    case 0:
+        /* Regardless if we have real data from the hardware, the emulator
+         * will only support upto feature 1, which we set in register EAX.
+         * Registers EBX:EDX:ECX contain a string identifying the CPU.
+         */
+        M.x86.R_EAX = 1;
+#ifndef X86EMU_HAS_HW_CPUID
+        /* EBX:EDX:ECX = "GenuineIntel" */
+        M.x86.R_EBX = 0x756e6547;
+        M.x86.R_EDX = 0x49656e69;
+        M.x86.R_ECX = 0x6c65746e;
+#endif
+        break;
+    case 1:
+#ifndef X86EMU_HAS_HW_CPUID
+        /* If we don't have x86 compatible hardware, we return values from an
+         * Intel 486dx4; which was one of the first processors to have CPUID.
+         */
+        M.x86.R_EAX = 0x00000480;
+        M.x86.R_EBX = 0x00000000;
+        M.x86.R_ECX = 0x00000000;
+        M.x86.R_EDX = 0x00000002;       /* VME */
+#else
+        /* In the case that we have hardware CPUID instruction, we make sure
+         * that the features reported are limited to TSC and VME.
+         */
+        M.x86.R_EDX &= 0x00000012;
+#endif
+        break;
+    default:
+        /* Finally, we don't support any additional features.  Most CPUs
+         * return all zeros when queried for invalid or unsupported feature
+         * numbers.
+         */
+        M.x86.R_EAX = 0;
+        M.x86.R_EBX = 0;
+        M.x86.R_ECX = 0;
+        M.x86.R_EDX = 0;
+        break;
+    }
+}
diff --git a/plat/pc86/emu/x86emu/sys.c b/plat/pc86/emu/x86emu/sys.c
new file mode 100644 (file)
index 0000000..ccce540
--- /dev/null
@@ -0,0 +1,550 @@
+/****************************************************************************
+*
+*                                              Realmode X86 Emulator Library
+*
+*              Copyright (C) 1996-1999 SciTech Software, Inc.
+*                                   Copyright (C) David Mosberger-Tang
+*                                         Copyright (C) 1999 Egbert Eich
+*
+*  ========================================================================
+*
+*  Permission to use, copy, modify, distribute, and sell this software and
+*  its documentation for any purpose is hereby granted without fee,
+*  provided that the above copyright notice appear in all copies and that
+*  both that copyright notice and this permission notice appear in
+*  supporting documentation, and that the name of the authors not be used
+*  in advertising or publicity pertaining to distribution of the software
+*  without specific, written prior permission.  The authors makes no
+*  representations about the suitability of this software for any purpose.
+*  It is provided "as is" without express or implied warranty.
+*
+*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+*  PERFORMANCE OF THIS SOFTWARE.
+*
+*  ========================================================================
+*
+* Language:            ANSI C
+* Environment: Any
+* Developer:    Kendall Bennett
+*
+* Description:  This file includes subroutines which are related to
+*                              programmed I/O and memory access. Included in this module
+*                              are default functions with limited usefulness. For real
+*                              uses these functions will most likely be overriden by the
+*                              user library.
+*
+****************************************************************************/
+
+#include "x86emu.h"
+#include "x86emu/x86emui.h"
+#include "x86emu/regs.h"
+#include "x86emu/debug.h"
+#include "x86emu/prim_ops.h"
+#ifndef NO_SYS_HEADERS
+#include <string.h>
+#endif
+
+#ifdef __GNUC__
+
+/* Define some packed structures to use with unaligned accesses */
+
+struct __una_u64 {
+    u64 x __attribute__ ((packed));
+};
+struct __una_u32 {
+    u32 x __attribute__ ((packed));
+};
+struct __una_u16 {
+    u16 x __attribute__ ((packed));
+};
+
+/* Elemental unaligned loads */
+
+static __inline__ u64
+ldq_u(u64 * p)
+{
+    const struct __una_u64 *ptr = (const struct __una_u64 *) p;
+
+    return ptr->x;
+}
+
+static __inline__ u32
+ldl_u(u32 * p)
+{
+    const struct __una_u32 *ptr = (const struct __una_u32 *) p;
+
+    return ptr->x;
+}
+
+static __inline__ u16
+ldw_u(u16 * p)
+{
+    const struct __una_u16 *ptr = (const struct __una_u16 *) p;
+
+    return ptr->x;
+}
+
+/* Elemental unaligned stores */
+
+static __inline__ void
+stq_u(u64 val, u64 * p)
+{
+    struct __una_u64 *ptr = (struct __una_u64 *) p;
+
+    ptr->x = val;
+}
+
+static __inline__ void
+stl_u(u32 val, u32 * p)
+{
+    struct __una_u32 *ptr = (struct __una_u32 *) p;
+
+    ptr->x = val;
+}
+
+static __inline__ void
+stw_u(u16 val, u16 * p)
+{
+    struct __una_u16 *ptr = (struct __una_u16 *) p;
+
+    ptr->x = val;
+}
+#else                           /* !__GNUC__ */
+
+static __inline__ u64
+ldq_u(u64 * p)
+{
+    u64 ret;
+
+    memmove(&ret, p, sizeof(*p));
+    return ret;
+}
+
+static __inline__ u32
+ldl_u(u32 * p)
+{
+    u32 ret;
+
+    memmove(&ret, p, sizeof(*p));
+    return ret;
+}
+
+static __inline__ u16
+ldw_u(u16 * p)
+{
+    u16 ret;
+
+    memmove(&ret, p, sizeof(*p));
+    return ret;
+}
+
+static __inline__ void
+stq_u(u64 val, u64 * p)
+{
+    u64 tmp = val;
+
+    memmove(p, &tmp, sizeof(*p));
+}
+
+static __inline__ void
+stl_u(u32 val, u32 * p)
+{
+    u32 tmp = val;
+
+    memmove(p, &tmp, sizeof(*p));
+}
+
+static __inline__ void
+stw_u(u16 val, u16 * p)
+{
+    u16 tmp = val;
+
+    memmove(p, &tmp, sizeof(*p));
+}
+
+#endif                          /* __GNUC__ */
+/*------------------------- Global Variables ------------------------------*/
+
+X86EMU_sysEnv _X86EMU_env;      /* Global emulator machine state */
+X86EMU_intrFuncs _X86EMU_intrTab[256];
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+addr   - Emulator memory address to read
+
+RETURNS:
+Byte value read from emulator memory.
+
+REMARKS:
+Reads a byte value from the emulator memory.
+****************************************************************************/
+u8 X86API
+rdb(u32 addr)
+{
+    u8 val;
+
+    if (addr > M.mem_size - 1) {
+        DB(printk("mem_read: address %#" PRIx32 " out of range!\n", addr);
+            )
+            HALT_SYS();
+    }
+    val = *(u8 *) (M.mem_base + addr);
+    DB(if (DEBUG_MEM_TRACE())
+       printk("%#08x 1 -> %#x\n", addr, val);)
+        return val;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr   - Emulator memory address to read
+
+RETURNS:
+Word value read from emulator memory.
+
+REMARKS:
+Reads a word value from the emulator memory.
+****************************************************************************/
+u16 X86API
+rdw(u32 addr)
+{
+    u16 val = 0;
+
+    if (addr > M.mem_size - 2) {
+        DB(printk("mem_read: address %#" PRIx32 " out of range!\n", addr);
+            )
+            HALT_SYS();
+    }
+#ifdef __BIG_ENDIAN__
+    if (addr & 0x1) {
+        val = (*(u8 *) (M.mem_base + addr) |
+               (*(u8 *) (M.mem_base + addr + 1) << 8));
+    }
+    else
+#endif
+        val = ldw_u((u16 *) (M.mem_base + addr));
+    DB(if (DEBUG_MEM_TRACE())
+       printk("%#08x 2 -> %#x\n", addr, val);)
+        return val;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr   - Emulator memory address to read
+
+RETURNS:
+Long value read from emulator memory.
+REMARKS:
+Reads a long value from the emulator memory.
+****************************************************************************/
+u32 X86API
+rdl(u32 addr)
+{
+    u32 val = 0;
+
+    if (addr > M.mem_size - 4) {
+        DB(printk("mem_read: address %#" PRIx32 " out of range!\n", addr);
+            )
+            HALT_SYS();
+    }
+#ifdef __BIG_ENDIAN__
+    if (addr & 0x3) {
+        val = (*(u8 *) (M.mem_base + addr + 0) |
+               (*(u8 *) (M.mem_base + addr + 1) << 8) |
+               (*(u8 *) (M.mem_base + addr + 2) << 16) |
+               (*(u8 *) (M.mem_base + addr + 3) << 24));
+    }
+    else
+#endif
+        val = ldl_u((u32 *) (M.mem_base + addr));
+    DB(if (DEBUG_MEM_TRACE())
+       printk("%#08x 4 -> %#x\n", addr, val);)
+        return val;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr   - Emulator memory address to read
+val            - Value to store
+
+REMARKS:
+Writes a byte value to emulator memory.
+****************************************************************************/
+void X86API
+wrb(u32 addr, u8 val)
+{
+    DB(if (DEBUG_MEM_TRACE())
+       printk("%#08x 1 <- %#x\n", addr, val);)
+        if (addr > M.mem_size - 1) {
+            DB(printk("mem_write: address %#" PRIx32 " out of range!\n",addr);
+                )
+                HALT_SYS();
+        }
+    *(u8 *) (M.mem_base + addr) = val;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr   - Emulator memory address to read
+val            - Value to store
+
+REMARKS:
+Writes a word value to emulator memory.
+****************************************************************************/
+void X86API
+wrw(u32 addr, u16 val)
+{
+    DB(if (DEBUG_MEM_TRACE())
+       printk("%#08x 2 <- %#x\n", addr, val);)
+        if (addr > M.mem_size - 2) {
+            DB(printk("mem_write: address %#" PRIx32 " out of range!\n",addr);
+                )
+                HALT_SYS();
+        }
+#ifdef __BIG_ENDIAN__
+    if (addr & 0x1) {
+        *(u8 *) (M.mem_base + addr + 0) = (val >> 0) & 0xff;
+        *(u8 *) (M.mem_base + addr + 1) = (val >> 8) & 0xff;
+    }
+    else
+#endif
+        stw_u(val, (u16 *) (M.mem_base + addr));
+}
+
+/****************************************************************************
+PARAMETERS:
+addr   - Emulator memory address to read
+val            - Value to store
+
+REMARKS:
+Writes a long value to emulator memory.
+****************************************************************************/
+void X86API
+wrl(u32 addr, u32 val)
+{
+    DB(if (DEBUG_MEM_TRACE())
+       printk("%#08x 4 <- %#x\n", addr, val);)
+        if (addr > M.mem_size - 4) {
+            DB(printk("mem_write: address %#" PRIx32 " out of range!\n",addr);
+                )
+                HALT_SYS();
+        }
+#ifdef __BIG_ENDIAN__
+    if (addr & 0x1) {
+        *(u8 *) (M.mem_base + addr + 0) = (val >> 0) & 0xff;
+        *(u8 *) (M.mem_base + addr + 1) = (val >> 8) & 0xff;
+        *(u8 *) (M.mem_base + addr + 2) = (val >> 16) & 0xff;
+        *(u8 *) (M.mem_base + addr + 3) = (val >> 24) & 0xff;
+    }
+    else
+#endif
+        stl_u(val, (u32 *) (M.mem_base + addr));
+}
+
+/****************************************************************************
+PARAMETERS:
+addr   - PIO address to read
+RETURN:
+0
+REMARKS:
+Default PIO byte read function. Doesn't perform real inb.
+****************************************************************************/
+static u8 X86API
+p_inb(X86EMU_pioAddr addr)
+{
+    DB(if (DEBUG_IO_TRACE())
+       printk("inb %#04x \n", addr);)
+        return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr   - PIO address to read
+RETURN:
+0
+REMARKS:
+Default PIO word read function. Doesn't perform real inw.
+****************************************************************************/
+static u16 X86API
+p_inw(X86EMU_pioAddr addr)
+{
+    DB(if (DEBUG_IO_TRACE())
+       printk("inw %#04x \n", addr);)
+        return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr   - PIO address to read
+RETURN:
+0
+REMARKS:
+Default PIO long read function. Doesn't perform real inl.
+****************************************************************************/
+static u32 X86API
+p_inl(X86EMU_pioAddr addr)
+{
+    DB(if (DEBUG_IO_TRACE())
+       printk("inl %#04x \n", addr);)
+        return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr   - PIO address to write
+val     - Value to store
+REMARKS:
+Default PIO byte write function. Doesn't perform real outb.
+****************************************************************************/
+static void X86API
+p_outb(X86EMU_pioAddr addr, u8 val)
+{
+    DB(if (DEBUG_IO_TRACE())
+       printk("outb %#02x -> %#04x \n", val, addr);)
+        return;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr   - PIO address to write
+val     - Value to store
+REMARKS:
+Default PIO word write function. Doesn't perform real outw.
+****************************************************************************/
+static void X86API
+p_outw(X86EMU_pioAddr addr, u16 val)
+{
+    DB(if (DEBUG_IO_TRACE())
+       printk("outw %#04x -> %#04x \n", val, addr);)
+        return;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr   - PIO address to write
+val     - Value to store
+REMARKS:
+Default PIO ;ong write function. Doesn't perform real outl.
+****************************************************************************/
+static void X86API
+p_outl(X86EMU_pioAddr addr, u32 val)
+{
+    DB(if (DEBUG_IO_TRACE())
+       printk("outl %#08x -> %#04x \n", val, addr);)
+        return;
+}
+
+/*------------------------- Global Variables ------------------------------*/
+
+u8(X86APIP sys_rdb) (u32 addr) = rdb;
+u16(X86APIP sys_rdw) (u32 addr) = rdw;
+u32(X86APIP sys_rdl) (u32 addr) = rdl;
+void (X86APIP sys_wrb) (u32 addr, u8 val) = wrb;
+void (X86APIP sys_wrw) (u32 addr, u16 val) = wrw;
+void (X86APIP sys_wrl) (u32 addr, u32 val) = wrl;
+
+u8(X86APIP sys_inb) (X86EMU_pioAddr addr) = p_inb;
+u16(X86APIP sys_inw) (X86EMU_pioAddr addr) = p_inw;
+u32(X86APIP sys_inl) (X86EMU_pioAddr addr) = p_inl;
+void (X86APIP sys_outb) (X86EMU_pioAddr addr, u8 val) = p_outb;
+void (X86APIP sys_outw) (X86EMU_pioAddr addr, u16 val) = p_outw;
+void (X86APIP sys_outl) (X86EMU_pioAddr addr, u32 val) = p_outl;
+
+/*----------------------------- Setup -------------------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+funcs  - New memory function pointers to make active
+
+REMARKS:
+This function is used to set the pointers to functions which access
+memory space, allowing the user application to override these functions
+and hook them out as necessary for their application.
+****************************************************************************/
+void
+X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs)
+{
+    sys_rdb = funcs->rdb;
+    sys_rdw = funcs->rdw;
+    sys_rdl = funcs->rdl;
+    sys_wrb = funcs->wrb;
+    sys_wrw = funcs->wrw;
+    sys_wrl = funcs->wrl;
+}
+
+/****************************************************************************
+PARAMETERS:
+funcs  - New programmed I/O function pointers to make active
+
+REMARKS:
+This function is used to set the pointers to functions which access
+I/O space, allowing the user application to override these functions
+and hook them out as necessary for their application.
+****************************************************************************/
+void
+X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs)
+{
+    sys_inb = funcs->inb;
+    sys_inw = funcs->inw;
+    sys_inl = funcs->inl;
+    sys_outb = funcs->outb;
+    sys_outw = funcs->outw;
+    sys_outl = funcs->outl;
+}
+
+/****************************************************************************
+PARAMETERS:
+funcs  - New interrupt vector table to make active
+
+REMARKS:
+This function is used to set the pointers to functions which handle
+interrupt processing in the emulator, allowing the user application to
+hook interrupts as necessary for their application. Any interrupts that
+are not hooked by the user application, and reflected and handled internally
+in the emulator via the interrupt vector table. This allows the application
+to get control when the code being emulated executes specific software
+interrupts.
+****************************************************************************/
+void
+X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[])
+{
+    int i;
+
+    for (i = 0; i < 256; i++)
+        _X86EMU_intrTab[i] = NULL;
+    if (funcs) {
+        for (i = 0; i < 256; i++)
+            _X86EMU_intrTab[i] = funcs[i];
+    }
+}
+
+/****************************************************************************
+PARAMETERS:
+int    - New software interrupt to prepare for
+
+REMARKS:
+This function is used to set up the emulator state to exceute a software
+interrupt. This can be used by the user application code to allow an
+interrupt to be hooked, examined and then reflected back to the emulator
+so that the code in the emulator will continue processing the software
+interrupt as per normal. This essentially allows system code to actively
+hook and handle certain software interrupts as necessary.
+****************************************************************************/
+void
+X86EMU_prepareForInt(int num)
+{
+    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(num * 4 + 2);
+    push_word(M.x86.R_IP);
+    M.x86.R_IP = mem_access_word(num * 4);
+    M.x86.intr = 0;
+}
diff --git a/plat/pc86/emu/x86emu/validate.c b/plat/pc86/emu/x86emu/validate.c
new file mode 100644 (file)
index 0000000..4c36e1d
--- /dev/null
@@ -0,0 +1,769 @@
+/****************************************************************************
+*
+*                                              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:  32-bit DOS
+* Developer:    Kendall Bennett
+*
+* Description:  Program to validate the x86 emulator library for
+*               correctness. We run the emulator primitive operations
+*               functions against the real x86 CPU, and compare the result
+*               and flags to ensure correctness.
+*
+*               We use inline assembler to compile and build this program.
+*
+****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "x86emu.h"
+#include "x86emu/prim_asm.h"
+
+/*-------------------------- Implementation -------------------------------*/
+
+#define true 1
+#define false 0
+
+#define ALL_FLAGS   (F_CF | F_PF | F_AF | F_ZF | F_SF | F_OF)
+
+#define VAL_START_BINARY(parm_type,res_type,dmax,smax,dincr,sincr)  \
+{                                                                   \
+    parm_type   d,s;                                                \
+    res_type    r,r_asm;                                            \
+       ulong           flags,inflags;                                      \
+       int         f,failed = false;                                   \
+    char        buf1[80],buf2[80];                                  \
+    for (d = 0; d < dmax; d += dincr) {                             \
+        for (s = 0; s < smax; s += sincr) {                         \
+            M.x86.R_EFLG = inflags = flags = def_flags;             \
+            for (f = 0; f < 2; f++) {
+
+#define VAL_TEST_BINARY(name)                                           \
+                r_asm = name##_asm(&flags,d,s);                         \
+                r = name(d,s);                                  \
+                if (r != r_asm || M.x86.R_EFLG != flags)                \
+                    failed = true;                                      \
+                if (failed || trace) {
+
+#define VAL_TEST_BINARY_VOID(name)                                      \
+                name##_asm(&flags,d,s);                                 \
+                name(d,s);                                      \
+                r = r_asm = 0;                                          \
+                if (M.x86.R_EFLG != flags)                              \
+                    failed = true;                                      \
+                if (failed || trace) {
+
+#define VAL_FAIL_BYTE_BYTE_BINARY(name)                                                                 \
+                    if (failed)                                                                         \
+                        printk("fail\n");                                                               \
+                    printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n",                         \
+                        r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));     \
+                    printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n",                         \
+                        r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_FAIL_WORD_WORD_BINARY(name)                                                                 \
+                    if (failed)                                                                         \
+                        printk("fail\n");                                                               \
+                    printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n",                         \
+                        r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));   \
+                    printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n",                         \
+                        r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_FAIL_LONG_LONG_BINARY(name)                                                                 \
+                    if (failed)                                                                         \
+                        printk("fail\n");                                                               \
+                    printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n",                         \
+                        r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+                    printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n",                         \
+                        r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_END_BINARY()                                                    \
+                    }                                                       \
+                M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF);   \
+                if (failed)                                                 \
+                    break;                                                  \
+                }                                                           \
+            if (failed)                                                     \
+                break;                                                      \
+            }                                                               \
+        if (failed)                                                         \
+            break;                                                          \
+        }                                                                   \
+    if (!failed)                                                            \
+        printk("passed\n");                                                 \
+}
+
+#define VAL_BYTE_BYTE_BINARY(name)          \
+    printk("Validating %s ... ", #name);    \
+    VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1)   \
+    VAL_TEST_BINARY(name)                   \
+    VAL_FAIL_BYTE_BYTE_BINARY(name)         \
+    VAL_END_BINARY()
+
+#define VAL_WORD_WORD_BINARY(name)                      \
+    printk("Validating %s ... ", #name);                \
+    VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \
+    VAL_TEST_BINARY(name)                               \
+    VAL_FAIL_WORD_WORD_BINARY(name)                     \
+    VAL_END_BINARY()
+
+#define VAL_LONG_LONG_BINARY(name)                                      \
+    printk("Validating %s ... ", #name);                                \
+    VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \
+    VAL_TEST_BINARY(name)                                               \
+    VAL_FAIL_LONG_LONG_BINARY(name)                                     \
+    VAL_END_BINARY()
+
+#define VAL_VOID_BYTE_BINARY(name)          \
+    printk("Validating %s ... ", #name);    \
+    VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1)   \
+    VAL_TEST_BINARY_VOID(name)              \
+    VAL_FAIL_BYTE_BYTE_BINARY(name)         \
+    VAL_END_BINARY()
+
+#define VAL_VOID_WORD_BINARY(name)                      \
+    printk("Validating %s ... ", #name);                \
+    VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \
+    VAL_TEST_BINARY_VOID(name)                          \
+    VAL_FAIL_WORD_WORD_BINARY(name)                     \
+    VAL_END_BINARY()
+
+#define VAL_VOID_LONG_BINARY(name)                                      \
+    printk("Validating %s ... ", #name);                                \
+    VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \
+    VAL_TEST_BINARY_VOID(name)                                          \
+    VAL_FAIL_LONG_LONG_BINARY(name)                                     \
+    VAL_END_BINARY()
+
+#define VAL_BYTE_ROTATE(name)               \
+    printk("Validating %s ... ", #name);    \
+    VAL_START_BINARY(u8,u8,0xFF,8,1,1)      \
+    VAL_TEST_BINARY(name)                   \
+    VAL_FAIL_BYTE_BYTE_BINARY(name)         \
+    VAL_END_BINARY()
+
+#define VAL_WORD_ROTATE(name)                           \
+    printk("Validating %s ... ", #name);                \
+    VAL_START_BINARY(u16,u16,0xFF00,16,0x100,1)         \
+    VAL_TEST_BINARY(name)                               \
+    VAL_FAIL_WORD_WORD_BINARY(name)                     \
+    VAL_END_BINARY()
+
+#define VAL_LONG_ROTATE(name)                                           \
+    printk("Validating %s ... ", #name);                                \
+    VAL_START_BINARY(u32,u32,0xFF000000,32,0x1000000,1)                 \
+    VAL_TEST_BINARY(name)                                               \
+    VAL_FAIL_LONG_LONG_BINARY(name)                                     \
+    VAL_END_BINARY()
+
+#define VAL_START_TERNARY(parm_type,res_type,dmax,smax,dincr,sincr,maxshift)\
+{                                                                   \
+    parm_type   d,s;                                                \
+    res_type    r,r_asm;                                            \
+    u8          shift;                                              \
+       u32         flags,inflags;                                      \
+    int         f,failed = false;                                   \
+    char        buf1[80],buf2[80];                                  \
+    for (d = 0; d < dmax; d += dincr) {                             \
+        for (s = 0; s < smax; s += sincr) {                         \
+            for (shift = 0; shift < maxshift; shift += 1) {        \
+                M.x86.R_EFLG = inflags = flags = def_flags;         \
+                for (f = 0; f < 2; f++) {
+
+#define VAL_TEST_TERNARY(name)                                          \
+                    r_asm = name##_asm(&flags,d,s,shift);               \
+                    r = name(d,s,shift);                           \
+                    if (r != r_asm || M.x86.R_EFLG != flags)            \
+                        failed = true;                                  \
+                    if (failed || trace) {
+
+#define VAL_FAIL_WORD_WORD_TERNARY(name)                                                                \
+                        if (failed)                                                                         \
+                            printk("fail\n");                                                               \
+                        printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n",                      \
+                            r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));   \
+                        printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n",                      \
+                            r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_FAIL_LONG_LONG_TERNARY(name)                                                                \
+                        if (failed)                                                                         \
+                            printk("fail\n");                                                               \
+                        printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n",                      \
+                            r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));  \
+                        printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n",                      \
+                            r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_END_TERNARY()                                                   \
+                        }                                                       \
+                    M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF);   \
+                    if (failed)                                                 \
+                        break;                                                  \
+                    }                                                           \
+                if (failed)                                                     \
+                    break;                                                      \
+                }                                                               \
+            if (failed)                                                     \
+                break;                                                      \
+            }                                                               \
+        if (failed)                                                         \
+            break;                                                          \
+        }                                                                   \
+    if (!failed)                                                            \
+        printk("passed\n");                                                 \
+}
+
+#define VAL_WORD_ROTATE_DBL(name)                           \
+    printk("Validating %s ... ", #name);                    \
+    VAL_START_TERNARY(u16,u16,0xFF00,0xFF00,0x100,0x100,16) \
+    VAL_TEST_TERNARY(name)                                  \
+    VAL_FAIL_WORD_WORD_TERNARY(name)                        \
+    VAL_END_TERNARY()
+
+#define VAL_LONG_ROTATE_DBL(name)                                           \
+    printk("Validating %s ... ", #name);                                    \
+    VAL_START_TERNARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000,32) \
+    VAL_TEST_TERNARY(name)                                                  \
+    VAL_FAIL_LONG_LONG_TERNARY(name)                                        \
+    VAL_END_TERNARY()
+
+#define VAL_START_UNARY(parm_type,max,incr)                 \
+{                                                           \
+    parm_type   d,r,r_asm;                                  \
+       u32         flags,inflags;                              \
+    int         f,failed = false;                           \
+    char        buf1[80],buf2[80];                          \
+    for (d = 0; d < max; d += incr) {                       \
+        M.x86.R_EFLG = inflags = flags = def_flags;         \
+        for (f = 0; f < 2; f++) {
+
+#define VAL_TEST_UNARY(name)                                \
+            r_asm = name##_asm(&flags,d);                   \
+            r = name(d);                                \
+            if (r != r_asm || M.x86.R_EFLG != flags) {      \
+                failed = true;
+
+#define VAL_FAIL_BYTE_UNARY(name)                                                               \
+                printk("fail\n");                                                               \
+                printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n",                            \
+                    r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));    \
+                printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n",                            \
+                    r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_FAIL_WORD_UNARY(name)                                                               \
+                printk("fail\n");                                                               \
+                printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n",                            \
+                    r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));  \
+                printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n",                            \
+                    r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_FAIL_LONG_UNARY(name)                                                               \
+                printk("fail\n");                                                               \
+                printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n",                            \
+                    r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));    \
+                printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n",                            \
+                    r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_END_UNARY()                                                 \
+                }                                                       \
+            M.x86.R_EFLG = inflags = flags = def_flags | ALL_FLAGS;     \
+            if (failed)                                                 \
+                break;                                                  \
+            }                                                           \
+        if (failed)                                                     \
+            break;                                                      \
+        }                                                               \
+    if (!failed)                                                        \
+        printk("passed\n");                                             \
+}
+
+#define VAL_BYTE_UNARY(name)                \
+    printk("Validating %s ... ", #name);    \
+    VAL_START_UNARY(u8,0xFF,0x1)            \
+    VAL_TEST_UNARY(name)                    \
+    VAL_FAIL_BYTE_UNARY(name)               \
+    VAL_END_UNARY()
+
+#define VAL_WORD_UNARY(name)                \
+    printk("Validating %s ... ", #name);    \
+    VAL_START_UNARY(u16,0xFF00,0x100)       \
+    VAL_TEST_UNARY(name)                    \
+    VAL_FAIL_WORD_UNARY(name)               \
+    VAL_END_UNARY()
+
+#define VAL_WORD_BYTE_UNARY(name)           \
+    printk("Validating %s ... ", #name);    \
+    VAL_START_UNARY(u16,0xFF,0x1)           \
+    VAL_TEST_UNARY(name)                    \
+    VAL_FAIL_WORD_UNARY(name)               \
+    VAL_END_UNARY()
+
+#define VAL_LONG_UNARY(name)                \
+    printk("Validating %s ... ", #name);    \
+    VAL_START_UNARY(u32,0xFF000000,0x1000000) \
+    VAL_TEST_UNARY(name)                    \
+    VAL_FAIL_LONG_UNARY(name)               \
+    VAL_END_UNARY()
+
+#define VAL_BYTE_MUL(name)                                              \
+    printk("Validating %s ... ", #name);                                \
+{                                                                       \
+    u8          d,s;                                                    \
+    u16         r,r_asm;                                                \
+       u32         flags,inflags;                                          \
+    int         f,failed = false;                                       \
+    char        buf1[80],buf2[80];                                      \
+    for (d = 0; d < 0xFF; d += 1) {                                     \
+        for (s = 0; s < 0xFF; s += 1) {                                 \
+            M.x86.R_EFLG = inflags = flags = def_flags;                 \
+            for (f = 0; f < 2; f++) {                                   \
+                name##_asm(&flags,&r_asm,d,s);                          \
+                M.x86.R_AL = d;                                         \
+                name(s);                                            \
+                r = M.x86.R_AX;                                         \
+                if (r != r_asm || M.x86.R_EFLG != flags)                \
+                    failed = true;                                      \
+                if (failed || trace) {                                  \
+                    if (failed)                                         \
+                        printk("fail\n");                               \
+                    printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n",                         \
+                        r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));     \
+                    printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n",                         \
+                        r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));  \
+                    }                                                       \
+                M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF);   \
+                if (failed)                                                 \
+                    break;                                                  \
+                }                                                           \
+            if (failed)                                                     \
+                break;                                                      \
+            }                                                               \
+        if (failed)                                                         \
+            break;                                                          \
+        }                                                                   \
+    if (!failed)                                                            \
+        printk("passed\n");                                                 \
+}
+
+#define VAL_WORD_MUL(name)                                              \
+    printk("Validating %s ... ", #name);                                \
+{                                                                       \
+    u16         d,s;                                                    \
+    u16         r_lo,r_asm_lo;                                          \
+    u16         r_hi,r_asm_hi;                                          \
+       u32         flags,inflags;                                          \
+    int         f,failed = false;                                       \
+    char        buf1[80],buf2[80];                                      \
+    for (d = 0; d < 0xFF00; d += 0x100) {                               \
+        for (s = 0; s < 0xFF00; s += 0x100) {                           \
+            M.x86.R_EFLG = inflags = flags = def_flags;                 \
+            for (f = 0; f < 2; f++) {                                   \
+                name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s);             \
+                M.x86.R_AX = d;                                         \
+                name(s);                                            \
+                r_lo = M.x86.R_AX;                                      \
+                r_hi = M.x86.R_DX;                                      \
+                if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\
+                    failed = true;                                      \
+                if (failed || trace) {                                  \
+                    if (failed)                                         \
+                        printk("fail\n");                               \
+                    printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n",                              \
+                        r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));       \
+                    printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n",                              \
+                        r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));  \
+                    }                                                                                               \
+                M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF);   \
+                if (failed)                                                 \
+                    break;                                                  \
+                }                                                           \
+            if (failed)                                                     \
+                break;                                                      \
+            }                                                               \
+        if (failed)                                                         \
+            break;                                                          \
+        }                                                                   \
+    if (!failed)                                                            \
+        printk("passed\n");                                                 \
+}
+
+#define VAL_LONG_MUL(name)                                              \
+    printk("Validating %s ... ", #name);                                \
+{                                                                       \
+    u32         d,s;                                                    \
+    u32         r_lo,r_asm_lo;                                          \
+    u32         r_hi,r_asm_hi;                                          \
+       u32         flags,inflags;                                          \
+    int         f,failed = false;                                       \
+    char        buf1[80],buf2[80];                                      \
+    for (d = 0; d < 0xFF000000; d += 0x1000000) {                       \
+        for (s = 0; s < 0xFF000000; s += 0x1000000) {                   \
+            M.x86.R_EFLG = inflags = flags = def_flags;                 \
+            for (f = 0; f < 2; f++) {                                   \
+                name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s);             \
+                M.x86.R_EAX = d;                                        \
+                name(s);                                            \
+                r_lo = M.x86.R_EAX;                                     \
+                r_hi = M.x86.R_EDX;                                     \
+                if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\
+                    failed = true;                                      \
+                if (failed || trace) {                                  \
+                    if (failed)                                         \
+                        printk("fail\n");                               \
+                    printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n",                              \
+                        r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));       \
+                    printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n",                              \
+                        r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));  \
+                    }                                                                                               \
+                M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF);   \
+                if (failed)                                                 \
+                    break;                                                  \
+                }                                                           \
+            if (failed)                                                     \
+                break;                                                      \
+            }                                                               \
+        if (failed)                                                         \
+            break;                                                          \
+        }                                                                   \
+    if (!failed)                                                            \
+        printk("passed\n");                                                 \
+}
+
+#define VAL_BYTE_DIV(name)                                              \
+    printk("Validating %s ... ", #name);                                \
+{                                                                       \
+    u16         d,s;                                                    \
+    u8          r_quot,r_rem,r_asm_quot,r_asm_rem;                      \
+       u32         flags,inflags;                                          \
+    int         f,failed = false;                                       \
+    char        buf1[80],buf2[80];                                      \
+    for (d = 0; d < 0xFF00; d += 0x100) {                               \
+        for (s = 1; s < 0xFF; s += 1) {                                 \
+            M.x86.R_EFLG = inflags = flags = def_flags;                 \
+            for (f = 0; f < 2; f++) {                                   \
+                M.x86.intr = 0;                                         \
+                M.x86.R_AX = d;                                         \
+                name(s);                                            \
+                r_quot = M.x86.R_AL;                                    \
+                r_rem = M.x86.R_AH;                                     \
+                if (M.x86.intr & INTR_SYNCH)                            \
+                    continue;                                           \
+                name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,s);          \
+                if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \
+                    failed = true;                                      \
+                if (failed || trace) {                                  \
+                    if (failed)                                         \
+                        printk("fail\n");                               \
+                    printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n",                      \
+                        r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));     \
+                    printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n",                      \
+                        r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));  \
+                    }                                                       \
+                M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF);   \
+                if (failed)                                                 \
+                    break;                                                  \
+                }                                                           \
+            if (failed)                                                     \
+                break;                                                      \
+            }                                                               \
+        if (failed)                                                         \
+            break;                                                          \
+        }                                                                   \
+    if (!failed)                                                            \
+        printk("passed\n");                                                 \
+}
+
+#define VAL_WORD_DIV(name)                                              \
+    printk("Validating %s ... ", #name);                                \
+{                                                                       \
+    u32         d,s;                                                    \
+    u16         r_quot,r_rem,r_asm_quot,r_asm_rem;                      \
+       u32         flags,inflags;                                          \
+    int         f,failed = false;                                       \
+    char        buf1[80],buf2[80];                                      \
+    for (d = 0; d < 0xFF000000; d += 0x1000000) {                       \
+        for (s = 0x100; s < 0xFF00; s += 0x100) {                       \
+            M.x86.R_EFLG = inflags = flags = def_flags;                 \
+            for (f = 0; f < 2; f++) {                                   \
+                M.x86.intr = 0;                                         \
+                M.x86.R_AX = d & 0xFFFF;                                \
+                M.x86.R_DX = d >> 16;                                   \
+                name(s);                                            \
+                r_quot = M.x86.R_AX;                                    \
+                r_rem = M.x86.R_DX;                                     \
+                if (M.x86.intr & INTR_SYNCH)                            \
+                    continue;                                           \
+                name##_asm(&flags,&r_asm_quot,&r_asm_rem,d & 0xFFFF,d >> 16,s);\
+                if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \
+                    failed = true;                                      \
+                if (failed || trace) {                                  \
+                    if (failed)                                         \
+                        printk("fail\n");                               \
+                    printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n",                      \
+                        r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));     \
+                    printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n",                      \
+                        r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));  \
+                    }                                                       \
+                M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF);   \
+                if (failed)                                                 \
+                    break;                                                  \
+                }                                                           \
+            if (failed)                                                     \
+                break;                                                      \
+            }                                                               \
+        if (failed)                                                         \
+            break;                                                          \
+        }                                                                   \
+    if (!failed)                                                            \
+        printk("passed\n");                                                 \
+}
+
+#define VAL_LONG_DIV(name)                                              \
+    printk("Validating %s ... ", #name);                                \
+{                                                                       \
+    u32         d,s;                                                    \
+    u32         r_quot,r_rem,r_asm_quot,r_asm_rem;                      \
+       u32         flags,inflags;                                          \
+    int         f,failed = false;                                       \
+    char        buf1[80],buf2[80];                                      \
+    for (d = 0; d < 0xFF000000; d += 0x1000000) {                       \
+        for (s = 0x100; s < 0xFF00; s += 0x100) {                       \
+            M.x86.R_EFLG = inflags = flags = def_flags;                 \
+            for (f = 0; f < 2; f++) {                                   \
+                M.x86.intr = 0;                                         \
+                M.x86.R_EAX = d;                                        \
+                M.x86.R_EDX = 0;                                        \
+                name(s);                                            \
+                r_quot = M.x86.R_EAX;                                   \
+                r_rem = M.x86.R_EDX;                                    \
+                if (M.x86.intr & INTR_SYNCH)                            \
+                    continue;                                           \
+                name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,0,s);        \
+                if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \
+                    failed = true;                                      \
+                if (failed || trace) {                                  \
+                    if (failed)                                         \
+                        printk("fail\n");                               \
+                    printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n",                       \
+                        r_quot, r_rem, #name, 0, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG));  \
+                    printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n",                       \
+                        r_asm_quot, r_asm_rem, #name"_asm", 0, d, s, print_flags(buf1,inflags), print_flags(buf2,flags));   \
+                    }                                                       \
+                M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF);   \
+                if (failed)                                                 \
+                    break;                                                  \
+                }                                                           \
+            if (failed)                                                     \
+                break;                                                      \
+            }                                                               \
+        if (failed)                                                         \
+            break;                                                          \
+        }                                                                   \
+    if (!failed)                                                            \
+        printk("passed\n");                                                 \
+}
+
+void
+printk(const char *fmt, ...)
+{
+    va_list argptr;
+
+    va_start(argptr, fmt);
+    vfprintf(stdout, fmt, argptr);
+    fflush(stdout);
+    va_end(argptr);
+}
+
+char *
+print_flags(char *buf, ulong flags)
+{
+    char *separator = "";
+
+    buf[0] = 0;
+    if (flags & F_CF) {
+        strcat(buf, separator);
+        strcat(buf, "CF");
+        separator = ",";
+    }
+    if (flags & F_PF) {
+        strcat(buf, separator);
+        strcat(buf, "PF");
+        separator = ",";
+    }
+    if (flags & F_AF) {
+        strcat(buf, separator);
+        strcat(buf, "AF");
+        separator = ",";
+    }
+    if (flags & F_ZF) {
+        strcat(buf, separator);
+        strcat(buf, "ZF");
+        separator = ",";
+    }
+    if (flags & F_SF) {
+        strcat(buf, separator);
+        strcat(buf, "SF");
+        separator = ",";
+    }
+    if (flags & F_OF) {
+        strcat(buf, separator);
+        strcat(buf, "OF");
+        separator = ",";
+    }
+    if (separator[0] == 0)
+        strcpy(buf, "None");
+    return buf;
+}
+
+int
+main(int argc)
+{
+    ulong def_flags;
+    int trace = false;
+
+    if (argc > 1)
+        trace = true;
+    memset(&M, 0, sizeof(M));
+    def_flags = get_flags_asm() & ~ALL_FLAGS;
+
+    VAL_WORD_UNARY(aaa_word);
+    VAL_WORD_UNARY(aas_word);
+
+    VAL_WORD_UNARY(aad_word);
+    VAL_WORD_UNARY(aam_word);
+
+    VAL_BYTE_BYTE_BINARY(adc_byte);
+    VAL_WORD_WORD_BINARY(adc_word);
+    VAL_LONG_LONG_BINARY(adc_long);
+
+    VAL_BYTE_BYTE_BINARY(add_byte);
+    VAL_WORD_WORD_BINARY(add_word);
+    VAL_LONG_LONG_BINARY(add_long);
+
+    VAL_BYTE_BYTE_BINARY(and_byte);
+    VAL_WORD_WORD_BINARY(and_word);
+    VAL_LONG_LONG_BINARY(and_long);
+
+    VAL_BYTE_BYTE_BINARY(cmp_byte);
+    VAL_WORD_WORD_BINARY(cmp_word);
+    VAL_LONG_LONG_BINARY(cmp_long);
+
+    VAL_BYTE_UNARY(daa_byte);
+    VAL_BYTE_UNARY(das_byte);   /* Fails for 0x9A (out of range anyway) */
+
+    VAL_BYTE_UNARY(dec_byte);
+    VAL_WORD_UNARY(dec_word);
+    VAL_LONG_UNARY(dec_long);
+
+    VAL_BYTE_UNARY(inc_byte);
+    VAL_WORD_UNARY(inc_word);
+    VAL_LONG_UNARY(inc_long);
+
+    VAL_BYTE_BYTE_BINARY(or_byte);
+    VAL_WORD_WORD_BINARY(or_word);
+    VAL_LONG_LONG_BINARY(or_long);
+
+    VAL_BYTE_UNARY(neg_byte);
+    VAL_WORD_UNARY(neg_word);
+    VAL_LONG_UNARY(neg_long);
+
+    VAL_BYTE_UNARY(not_byte);
+    VAL_WORD_UNARY(not_word);
+    VAL_LONG_UNARY(not_long);
+
+    VAL_BYTE_ROTATE(rcl_byte);
+    VAL_WORD_ROTATE(rcl_word);
+    VAL_LONG_ROTATE(rcl_long);
+
+    VAL_BYTE_ROTATE(rcr_byte);
+    VAL_WORD_ROTATE(rcr_word);
+    VAL_LONG_ROTATE(rcr_long);
+
+    VAL_BYTE_ROTATE(rol_byte);
+    VAL_WORD_ROTATE(rol_word);
+    VAL_LONG_ROTATE(rol_long);
+
+    VAL_BYTE_ROTATE(ror_byte);
+    VAL_WORD_ROTATE(ror_word);
+    VAL_LONG_ROTATE(ror_long);
+
+    VAL_BYTE_ROTATE(shl_byte);
+    VAL_WORD_ROTATE(shl_word);
+    VAL_LONG_ROTATE(shl_long);
+
+    VAL_BYTE_ROTATE(shr_byte);
+    VAL_WORD_ROTATE(shr_word);
+    VAL_LONG_ROTATE(shr_long);
+
+    VAL_BYTE_ROTATE(sar_byte);
+    VAL_WORD_ROTATE(sar_word);
+    VAL_LONG_ROTATE(sar_long);
+
+    VAL_WORD_ROTATE_DBL(shld_word);
+    VAL_LONG_ROTATE_DBL(shld_long);
+
+    VAL_WORD_ROTATE_DBL(shrd_word);
+    VAL_LONG_ROTATE_DBL(shrd_long);
+
+    VAL_BYTE_BYTE_BINARY(sbb_byte);
+    VAL_WORD_WORD_BINARY(sbb_word);
+    VAL_LONG_LONG_BINARY(sbb_long);
+
+    VAL_BYTE_BYTE_BINARY(sub_byte);
+    VAL_WORD_WORD_BINARY(sub_word);
+    VAL_LONG_LONG_BINARY(sub_long);
+
+    VAL_BYTE_BYTE_BINARY(xor_byte);
+    VAL_WORD_WORD_BINARY(xor_word);
+    VAL_LONG_LONG_BINARY(xor_long);
+
+    VAL_VOID_BYTE_BINARY(test_byte);
+    VAL_VOID_WORD_BINARY(test_word);
+    VAL_VOID_LONG_BINARY(test_long);
+
+    VAL_BYTE_MUL(imul_byte);
+    VAL_WORD_MUL(imul_word);
+    VAL_LONG_MUL(imul_long);
+
+    VAL_BYTE_MUL(mul_byte);
+    VAL_WORD_MUL(mul_word);
+    VAL_LONG_MUL(mul_long);
+
+    VAL_BYTE_DIV(idiv_byte);
+    VAL_WORD_DIV(idiv_word);
+    VAL_LONG_DIV(idiv_long);
+
+    VAL_BYTE_DIV(div_byte);
+    VAL_WORD_DIV(div_word);
+    VAL_LONG_DIV(div_long);
+
+    return 0;
+}
diff --git a/plat/pc86/emu/x86emu/x86emu.h b/plat/pc86/emu/x86emu/x86emu.h
new file mode 100644 (file)
index 0000000..501dd91
--- /dev/null
@@ -0,0 +1,197 @@
+/****************************************************************************
+*
+*                                              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
+*
+****************************************************************************/
+
+#ifndef __X86EMU_X86EMU_H
+#define __X86EMU_X86EMU_H
+
+#ifdef SCITECH
+#include "scitech.h"
+#define        X86API  _ASMAPI
+#define        X86APIP _ASMAPIP
+typedef int X86EMU_pioAddr;
+#else
+#include "x86emu/types.h"
+#define        X86API
+#define        X86APIP *
+#endif
+#include "x86emu/regs.h"
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#ifdef PACK
+#pragma        PACK                    /* Don't pack structs with function pointers! */
+#endif
+
+/****************************************************************************
+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);
+
+#ifdef END_PACK
+#pragma        END_PACK
+#endif
+
+/*--------------------- 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);
+
+/* decode.c */
+
+    void X86EMU_exec(void);
+    void X86EMU_halt_sys(void);
+
+#ifdef 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_SAVE_IP_CS_F      0x000040
+#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_EXIT              0x010000
+#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/plat/pc86/emu/x86emu/x86emu/debug.h b/plat/pc86/emu/x86emu/x86emu/debug.h
new file mode 100644 (file)
index 0000000..1f04b7b
--- /dev/null
@@ -0,0 +1,208 @@
+/****************************************************************************
+*
+*                                              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.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_DEBUG_H
+#define __X86EMU_DEBUG_H
+
+/*---------------------- 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 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 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_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_SYS()            0
+#define DEBUG_MEM_TRACE()      0
+#define DEBUG_IO_TRACE()       0
+#define DEBUG_DECODE_NOPRINT() 0
+#endif
+
+#ifdef DEBUG
+
+#define DECODE_PRINTF(x)       if (DEBUG_DECODE()) \
+                                                                       x86emu_decode_printf("%s",x)
+#define DECODE_PRINTF2(x,y)    if (DEBUG_DECODE()) \
+                                                                       x86emu_decode_printf(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 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 DEBUG
+#define SINGLE_STEP()          if (DEBUG_STEP()) x86emu_single_step()
+#else
+#define SINGLE_STEP()
+#endif
+
+#define TRACE_AND_STEP()       \
+       TRACE_REGS();                   \
+       SINGLE_STEP()
+
+#ifdef 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 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(n,u,v)                                    \
+       if (DEBUG_TRACECALLREGS())                                                                      \
+               x86emu_dump_regs();                                     \
+       if (DEBUG_TRACECALL())                                          \
+               printk("%04x:%04x: %s\n",u,v,n);
+#else
+#define CALL_TRACE(u,v,w,x,s)
+#define RETURN_TRACE(n,u,v)
+#endif
+
+#ifdef 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(const char *x, ...) _X_ATTRIBUTE_PRINTF(1,2);
+    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/plat/pc86/emu/x86emu/x86emu/decode.h b/plat/pc86/emu/x86emu/x86emu/decode.h
new file mode 100644 (file)
index 0000000..49a1f7b
--- /dev/null
@@ -0,0 +1,87 @@
+/****************************************************************************
+*
+*                                              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);
+    u32 decode_rm00_address(int rm);
+    u32 decode_rm01_address(int rm);
+    u32 decode_rm10_address(int rm);
+    u32 decode_sib_address(int sib, int mod);
+
+#ifdef  __cplusplus
+}                               /* End of "C" linkage for C++           */
+#endif
+#endif                          /* __X86EMU_DECODE_H */
diff --git a/plat/pc86/emu/x86emu/x86emu/fpu.h b/plat/pc86/emu/x86emu/x86emu/fpu.h
new file mode 100644 (file)
index 0000000..1c11498
--- /dev/null
@@ -0,0 +1,60 @@
+/****************************************************************************
+*
+*                                              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/plat/pc86/emu/x86emu/x86emu/fpu_regs.h b/plat/pc86/emu/x86emu/x86emu/fpu_regs.h
new file mode 100644 (file)
index 0000000..5a780e6
--- /dev/null
@@ -0,0 +1,119 @@
+/****************************************************************************
+*
+*                                              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
+
+#ifdef PACK
+#pragma PACK
+#endif
+
+/* 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;
+};
+
+#ifdef END_PACK
+#pragma END_PACK
+#endif
+
+/*
+ * 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 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/plat/pc86/emu/x86emu/x86emu/ops.h b/plat/pc86/emu/x86emu/x86emu/ops.h
new file mode 100644 (file)
index 0000000..1bc07a4
--- /dev/null
@@ -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/plat/pc86/emu/x86emu/x86emu/prim_asm.h b/plat/pc86/emu/x86emu/x86emu/prim_asm.h
new file mode 100644 (file)
index 0000000..aca132b
--- /dev/null
@@ -0,0 +1,1053 @@
+/****************************************************************************
+*
+*                                              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.
+*
+****************************************************************************/
+
+#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/plat/pc86/emu/x86emu/x86emu/prim_ops.h b/plat/pc86/emu/x86emu/x86emu/prim_ops.h
new file mode 100644 (file)
index 0000000..0f0e78d
--- /dev/null
@@ -0,0 +1,141 @@
+/****************************************************************************
+*
+*                                              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 primitive operation functions.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_PRIM_OPS_H
+#define __X86EMU_PRIM_OPS_H
+
+#ifdef  __cplusplus
+extern "C" {                    /* Use "C" linkage when in C++ mode */
+#endif
+
+    u16 aaa_word(u16 d);
+    u16 aas_word(u16 d);
+    u16 aad_word(u16 d);
+    u16 aam_word(u8 d);
+    u8 adc_byte(u8 d, u8 s);
+    u16 adc_word(u16 d, u16 s);
+    u32 adc_long(u32 d, u32 s);
+    u8 add_byte(u8 d, u8 s);
+    u16 add_word(u16 d, u16 s);
+    u32 add_long(u32 d, u32 s);
+    u8 and_byte(u8 d, u8 s);
+    u16 and_word(u16 d, u16 s);
+    u32 and_long(u32 d, u32 s);
+    u8 cmp_byte(u8 d, u8 s);
+    u16 cmp_word(u16 d, u16 s);
+    u32 cmp_long(u32 d, u32 s);
+    u8 daa_byte(u8 d);
+    u8 das_byte(u8 d);
+    u8 dec_byte(u8 d);
+    u16 dec_word(u16 d);
+    u32 dec_long(u32 d);
+    u8 inc_byte(u8 d);
+    u16 inc_word(u16 d);
+    u32 inc_long(u32 d);
+    u8 or_byte(u8 d, u8 s);
+    u16 or_word(u16 d, u16 s);
+    u32 or_long(u32 d, u32 s);
+    u8 neg_byte(u8 s);
+    u16 neg_word(u16 s);
+    u32 neg_long(u32 s);
+    u8 not_byte(u8 s);
+    u16 not_word(u16 s);
+    u32 not_long(u32 s);
+    u8 rcl_byte(u8 d, u8 s);
+    u16 rcl_word(u16 d, u8 s);
+    u32 rcl_long(u32 d, u8 s);
+    u8 rcr_byte(u8 d, u8 s);
+    u16 rcr_word(u16 d, u8 s);
+    u32 rcr_long(u32 d, u8 s);
+    u8 rol_byte(u8 d, u8 s);
+    u16 rol_word(u16 d, u8 s);
+    u32 rol_long(u32 d, u8 s);
+    u8 ror_byte(u8 d, u8 s);
+    u16 ror_word(u16 d, u8 s);
+    u32 ror_long(u32 d, u8 s);
+    u8 shl_byte(u8 d, u8 s);
+    u16 shl_word(u16 d, u8 s);
+    u32 shl_long(u32 d, u8 s);
+    u8 shr_byte(u8 d, u8 s);
+    u16 shr_word(u16 d, u8 s);
+    u32 shr_long(u32 d, u8 s);
+    u8 sar_byte(u8 d, u8 s);
+    u16 sar_word(u16 d, u8 s);
+    u32 sar_long(u32 d, u8 s);
+    u16 shld_word(u16 d, u16 fill, u8 s);
+    u32 shld_long(u32 d, u32 fill, u8 s);
+    u16 shrd_word(u16 d, u16 fill, u8 s);
+    u32 shrd_long(u32 d, u32 fill, u8 s);
+    u8 sbb_byte(u8 d, u8 s);
+    u16 sbb_word(u16 d, u16 s);
+    u32 sbb_long(u32 d, u32 s);
+    u8 sub_byte(u8 d, u8 s);
+    u16 sub_word(u16 d, u16 s);
+    u32 sub_long(u32 d, u32 s);
+    void test_byte(u8 d, u8 s);
+    void test_word(u16 d, u16 s);
+    void test_long(u32 d, u32 s);
+    u8 xor_byte(u8 d, u8 s);
+    u16 xor_word(u16 d, u16 s);
+    u32 xor_long(u32 d, u32 s);
+    void imul_byte(u8 s);
+    void imul_word(u16 s);
+    void imul_long(u32 s);
+    void imul_long_direct(u32 * res_lo, u32 * res_hi, u32 d, u32 s);
+    void mul_byte(u8 s);
+    void mul_word(u16 s);
+    void mul_long(u32 s);
+    void idiv_byte(u8 s);
+    void idiv_word(u16 s);
+    void idiv_long(u32 s);
+    void div_byte(u8 s);
+    void div_word(u16 s);
+    void div_long(u32 s);
+    void ins(int size);
+    void outs(int size);
+    u16 mem_access_word(int addr);
+    void push_word(u16 w);
+    void push_long(u32 w);
+    u16 pop_word(void);
+    u32 pop_long(void);
+    void cpuid(void);
+
+#ifdef  __cplusplus
+}                               /* End of "C" linkage for C++           */
+#endif
+#endif                          /* __X86EMU_PRIM_OPS_H */
diff --git a/plat/pc86/emu/x86emu/x86emu/prim_x86_gcc.h b/plat/pc86/emu/x86emu/x86emu/prim_x86_gcc.h
new file mode 100644 (file)
index 0000000..646ec9d
--- /dev/null
@@ -0,0 +1,77 @@
+/****************************************************************************
+*
+* Inline helpers for x86emu
+*
+* Copyright (C) 2008 Bart Trojanowski, Symbio Technologies, LLC
+*
+*  ========================================================================
+*
+*  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:     GNU C
+* Environment:  GCC on i386 or x86-64
+* Developer:    Bart Trojanowski
+*
+* Description:  This file defines a few x86 macros that can be used by the
+*               emulator to execute native instructions.
+*
+*               For PIC vs non-PIC code refer to:
+*               http://sam.zoy.org/blog/2007-04-13-shlib-with-non-pic-code-have-inline-assembly-and-pic-mix-well
+*
+****************************************************************************/
+#ifndef __X86EMU_PRIM_X86_GCC_H
+#define __X86EMU_PRIM_X86_GCC_H
+
+#include "x86emu/types.h"
+
+#if !defined(__GNUC__) || !(defined (__i386__) || defined(__i386) || defined(__AMD64__) || defined(__amd64__))
+#error This file is intended to be used by gcc on i386 or x86-64 system
+#endif
+
+#if defined(__PIC__) && defined(__i386__)
+
+#define X86EMU_HAS_HW_CPUID 1
+static inline void
+hw_cpuid(u32 * a, u32 * b, u32 * c, u32 * d)
+{
+    __asm__ __volatile__("pushl %%ebx      \n\t"
+                         "cpuid            \n\t"
+                         "movl %%ebx, %1   \n\t"
+                         "popl %%ebx       \n\t":"=a"(*a), "=r"(*b),
+                         "=c"(*c), "=d"(*d)
+                         :"a"(*a), "c"(*c)
+                         :"cc");
+}
+
+#else                           /* ! (__PIC__ && __i386__) */
+
+#define x86EMU_HAS_HW_CPUID 1
+static inline void
+hw_cpuid(u32 * a, u32 * b, u32 * c, u32 * d)
+{
+    __asm__ __volatile__("cpuid":"=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d)
+                         :"a"(*a), "c"(*c)
+                         :"cc");
+}
+
+#endif                          /* __PIC__ && __i386__ */
+
+#endif                          /* __X86EMU_PRIM_X86_GCC_H */
diff --git a/plat/pc86/emu/x86emu/x86emu/regs.h b/plat/pc86/emu/x86emu/x86emu/regs.h
new file mode 100644 (file)
index 0000000..3c9469f
--- /dev/null
@@ -0,0 +1,340 @@
+/****************************************************************************
+*
+*                                              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.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_REGS_H
+#define __X86EMU_REGS_H
+
+#include <X11/Xfuncproto.h>
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#ifdef PACK
+#pragma PACK
+#endif
+
+/*
+ * 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.
+ */
+
+#if defined(__sun) && defined(CS) /* avoid conflicts with Solaris sys/regset.h */
+# undef CS
+# undef DS
+# undef SS
+# undef ES
+# undef FS
+# undef GS
+#endif
+
+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_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
+#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)
+
+#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 */
+    int debug;
+#ifdef 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
+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;
+    void *private;
+    X86EMU_regs x86;
+} X86EMU_sysEnv;
+
+#ifdef END_PACK
+#pragma END_PACK
+#endif
+
+/*----------------------------- 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
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+/* Function to log information at runtime */
+
+    void printk(const char *fmt, ...)
+        _X_ATTRIBUTE_PRINTF(1, 2);
+
+#ifdef  __cplusplus
+}                               /* End of "C" linkage for C++           */
+#endif
+#endif                          /* __X86EMU_REGS_H */
diff --git a/plat/pc86/emu/x86emu/x86emu/types.h b/plat/pc86/emu/x86emu/x86emu/types.h
new file mode 100644 (file)
index 0000000..0559bc0
--- /dev/null
@@ -0,0 +1,81 @@
+/****************************************************************************
+*
+*                                              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.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_TYPES_H
+#define __X86EMU_TYPES_H
+
+#ifndef NO_SYS_HEADERS
+#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 ----------------------*/
+
+#include <stdint.h>
+#include <inttypes.h>
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+typedef int8_t s8;
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64;
+
+typedef unsigned int uint;
+typedef int sint;
+
+typedef u16 X86EMU_pioAddr;
+
+#endif                          /* __X86EMU_TYPES_H */
diff --git a/plat/pc86/emu/x86emu/x86emu/x86emui.h b/plat/pc86/emu/x86emu/x86emu/x86emui.h
new file mode 100644 (file)
index 0000000..01bd92a
--- /dev/null
@@ -0,0 +1,110 @@
+/****************************************************************************
+*
+*                                              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 system specific functions. These functions
+*                              are always compiled and linked in the OS depedent libraries,
+*                              and never in a binary portable driver.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_X86EMUI_H
+#define __X86EMU_X86EMUI_H
+
+/* If we are compiling in C++ mode, we can compile some functions as
+ * inline to increase performance (however the code size increases quite
+ * dramatically in this case).
+ */
+
+#if defined(__cplusplus)
+#define        _INLINE inline
+#else
+#define        _INLINE static
+#endif
+
+/* Get rid of unused parameters in C++ compilation mode */
+
+#ifdef __cplusplus
+#define        X86EMU_UNUSED(v)
+#else
+#define        X86EMU_UNUSED(v)        v
+#endif
+
+#include "x86emu.h"
+#include "x86emu/regs.h"
+#include "x86emu/debug.h"
+#include "x86emu/decode.h"
+#include "x86emu/ops.h"
+#include "x86emu/prim_ops.h"
+#include "x86emu/fpu.h"
+#include "x86emu/fpu_regs.h"
+
+#ifndef NO_SYS_HEADERS
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+/* avoid conflicts with Solaris sys/regset.h */
+# if defined(__sun) && defined(CS)
+#  undef CS
+#  undef DS
+#  undef SS
+#  undef ES
+#  undef FS
+#  undef GS
+# endif
+#endif /* NO_SYS_HEADERS */
+
+/*--------------------------- Inline Functions ----------------------------*/
+
+#ifdef  __cplusplus
+extern "C" {                    /* Use "C" linkage when in C++ mode */
+#endif
+
+    extern u8(X86APIP sys_rdb) (u32 addr);
+    extern u16(X86APIP sys_rdw) (u32 addr);
+    extern u32(X86APIP sys_rdl) (u32 addr);
+    extern void (X86APIP sys_wrb) (u32 addr, u8 val);
+    extern void (X86APIP sys_wrw) (u32 addr, u16 val);
+    extern void (X86APIP sys_wrl) (u32 addr, u32 val);
+
+    extern u8(X86APIP sys_inb) (X86EMU_pioAddr addr);
+    extern u16(X86APIP sys_inw) (X86EMU_pioAddr addr);
+    extern u32(X86APIP sys_inl) (X86EMU_pioAddr addr);
+    extern void (X86APIP sys_outb) (X86EMU_pioAddr addr, u8 val);
+    extern void (X86APIP sys_outw) (X86EMU_pioAddr addr, u16 val);
+    extern void (X86APIP sys_outl) (X86EMU_pioAddr addr, u32 val);
+
+#ifdef  __cplusplus
+}                               /* End of "C" linkage for C++           */
+#endif
+#endif                          /* __X86EMU_X86EMUI_H */