OSDN Git Service

* debug/debug.h: Move to top-level bochs directory.
authorfitzsim <fitzsim>
Fri, 15 Feb 2002 01:18:43 +0000 (01:18 +0000)
committerfitzsim <fitzsim>
Fri, 15 Feb 2002 01:18:43 +0000 (01:18 +0000)
* debug: Remove directory.
* pic/*: New files.
* floppy/*: New files.
* cmos/*: New files.
* unmapped/*: New files.
* dma/*: New files.
* pit/*: New files.
* cpu/x86.h: Rename to sid-x86-cpu-wrapper.h.
* cpu/x86.cc: Rename to sid-x86-cpu-wrapper.cc.
* cpu/x86-memory-modes.cc: Rename to sid-x86-memory-modes.cc.
* memory/*: Move to cpu/memory/*.
* fpu/*: Move to cpu/fpu/*.
* bochs.h: Change #include's to reflect new and moved files.
Add sid expansions for A20ADDR(x), BX_INP(addr, len),
BX_OUTP(addr, val, len), BX_RAISE_HLDA(),
BX_SET_ENABLE_A20(enabled), BX_GET_ENABLE_A20(), and
BX_NULL_TIMER_HANDLE.
* components.cxx: Add support for cmos, dma, pic, pit, floppy,
unmapped.
* config.h.in: Set BX_SUPPORT_TASKING, BX_DMA_FLOPPY_IO and
BX_SUPPORT_A20 to 1 by default.
Set SMF macros to 0 for cmos, dma, pic, pit, floppy and unmapped
components.
* configure.in: Add pic, pit, cmos, dma, floppy, and unmapped
Makefiles to AC_OUTPUT.
* cpu/exception-sid.cc: Remove.  Merge differences into
cpu/exception.cc.
* cpu/cpu-sid.h: Remove.  Merge differences into cpu/cpu.h.
* cpu/cpu-sid.cc: Remove.  Merge differences into cpu/cpu.cc.
* cpu/init-sid.cc: Remove.  Merge differences into cpu/init.cc.
* cpu/soft_int-sid.cc: Remove.
* cpu/debugstuff-sid.cc: Remove.  Merge differences into
cpu/debugstuff.cc.
* cpu/ctrl_xfer32-sid.cc: Remove.
* cpu/fetchdecode-sid.cc: Remove.
* cpu/Makefile.am: Remove references to removed files.
(SUBDIRS) Add memory and fpu.
(SUBLIBS) Add memory/libmemory.la and fpu/libfpu.la.
(INCLUDES) Add memory and fpu directories.
* cpu/cpu.cc: Remove BX_HRQ related FIXME's.
Add interrupt pin support.
* cpu/debugstuff.cc (BX_SUPPORT_SID): Add implementations of
dbg_get_reg, dbg_set_reg, and dbg_get_eflags for when
BX_DEBUGGER isn't defined.
* cpu/io.cc: Remove #if 0's -- no longer needed.
* cpu/io_pro.cc: Likewise.
* gui/x-gui.cc: Change title bar messages.
* keyboard/keyboard.cc: Change keyboard to remove serial delay
pin.
* keyboard/sid-keyboard-wrapper.cc: Add a20-related pins.
Remove serial-delay pin.
Add cmos accessor.
Add trigger-irq pin.
* keyboard/sid-keyboard-wrapper.h: Likewise.
* vga/sid-vga-wrapper.cc: Rename buses from eg. 3b4 to 0x3b4.
Import imagemmap code from generic.cxx.
* vga/vga.cc: Cap number of rows at BX_MAX_TEXT_LINES.
* Makefile.am (SUBDIRLIST): Add pic, pit, cmos, dma, floppy,
unmapped.
Removed fpu, memory.
(SUBLIBLIST): Likewise.
(INCLUDES): Likewise.

163 files changed:
sid/component/bochs/ChangeLog
sid/component/bochs/Makefile.am
sid/component/bochs/Makefile.in
sid/component/bochs/README
sid/component/bochs/bochs.h
sid/component/bochs/cmos/Makefile.am [new file with mode: 0644]
sid/component/bochs/cmos/Makefile.in [new file with mode: 0644]
sid/component/bochs/cmos/cmos.cc [new file with mode: 0644]
sid/component/bochs/cmos/cmos.h [new file with mode: 0644]
sid/component/bochs/cmos/sid-cmos-wrapper.cc [new file with mode: 0644]
sid/component/bochs/cmos/sid-cmos-wrapper.h [new file with mode: 0644]
sid/component/bochs/components.cxx
sid/component/bochs/config.h.in
sid/component/bochs/configure
sid/component/bochs/configure.in
sid/component/bochs/cpu/Makefile.am
sid/component/bochs/cpu/Makefile.in
sid/component/bochs/cpu/cpu-sid.cc [deleted file]
sid/component/bochs/cpu/cpu-sid.h [deleted file]
sid/component/bochs/cpu/cpu.cc
sid/component/bochs/cpu/cpu.h
sid/component/bochs/cpu/ctrl_xfer32-sid.cc [deleted file]
sid/component/bochs/cpu/debugstuff-sid.cc [deleted file]
sid/component/bochs/cpu/debugstuff.cc
sid/component/bochs/cpu/decode16.cc
sid/component/bochs/cpu/exception-sid.cc [deleted file]
sid/component/bochs/cpu/exception.cc
sid/component/bochs/cpu/fetchdecode-sid.cc [deleted file]
sid/component/bochs/cpu/fpu/Makefile.am [new file with mode: 0644]
sid/component/bochs/cpu/fpu/Makefile.in [new file with mode: 0644]
sid/component/bochs/cpu/fpu/PORTING [new file with mode: 0644]
sid/component/bochs/cpu/fpu/README [new file with mode: 0644]
sid/component/bochs/cpu/fpu/control_w.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/div_Xsig.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/div_Xsig.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/div_small.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/div_small.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/errors.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/exception.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/fpu.cc [new file with mode: 0644]
sid/component/bochs/cpu/fpu/fpu_arith.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/fpu_asm.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/fpu_aux.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/fpu_emu.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/fpu_entry.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/fpu_etc.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/fpu_proto.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/fpu_system.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/fpu_tags.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/fpu_trig.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/get_address.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/load_store.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/mul_Xsig.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/mul_Xsig.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/poly.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/poly_2xm1.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/poly_atan.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/poly_l2.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/poly_sin.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/poly_tan.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/polynom_Xsig.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/polynom_Xsig.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_add_sub.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_compare.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_constant.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_constant.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_convert.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_divide.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_ld_str.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_mul.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_norm.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_norm.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_round.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_round.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_u_add.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_u_add.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_u_div.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_u_div.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_u_mul.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_u_mul.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_u_sub.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/reg_u_sub.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/round_Xsig.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/round_Xsig.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/shr_Xsig.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/shr_Xsig.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/status_w.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/stubs/asm/desc.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/stubs/asm/math_emu.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/stubs/asm/sigcontext.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/stubs/asm/types.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/stubs/asm/uaccess.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/stubs/linux/kernel.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/stubs/linux/linkage.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/stubs/linux/mm.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/stubs/linux/sched.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/stubs/linux/signal.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/stubs/linux/stddef.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/stubs/linux/types.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/version.h [new file with mode: 0644]
sid/component/bochs/cpu/fpu/wmFPUemu_glue.cc [new file with mode: 0644]
sid/component/bochs/cpu/fpu/wm_shrx.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/wm_shrx.c [new file with mode: 0644]
sid/component/bochs/cpu/fpu/wm_sqrt.S [new file with mode: 0644]
sid/component/bochs/cpu/fpu/wm_sqrt.c [new file with mode: 0644]
sid/component/bochs/cpu/init-sid.cc [deleted file]
sid/component/bochs/cpu/init.cc
sid/component/bochs/cpu/io.cc
sid/component/bochs/cpu/io_pro.cc
sid/component/bochs/cpu/main-hack.cc
sid/component/bochs/cpu/memory/Makefile.am [new file with mode: 0644]
sid/component/bochs/cpu/memory/Makefile.in [new file with mode: 0644]
sid/component/bochs/cpu/memory/sid-bochs-memory.cc [new file with mode: 0644]
sid/component/bochs/cpu/memory/sid-bochs-memory.h [new file with mode: 0644]
sid/component/bochs/cpu/paging.cc
sid/component/bochs/cpu/sid-x86-cpu-wrapper.cc [new file with mode: 0644]
sid/component/bochs/cpu/sid-x86-cpu-wrapper.h [new file with mode: 0644]
sid/component/bochs/cpu/sid-x86-memory-modes.cc [moved from sid/component/bochs/cpu/x86-memory-modes.cc with 99% similarity]
sid/component/bochs/cpu/soft_int-sid.cc [deleted file]
sid/component/bochs/cpu/tasking.cc
sid/component/bochs/cpu/vm8086.cc
sid/component/bochs/cpu/x86.cc [deleted file]
sid/component/bochs/cpu/x86.h [deleted file]
sid/component/bochs/debug.h [new file with mode: 0644]
sid/component/bochs/dma/Makefile.am [new file with mode: 0644]
sid/component/bochs/dma/Makefile.in [new file with mode: 0644]
sid/component/bochs/dma/dma.cc [new file with mode: 0644]
sid/component/bochs/dma/dma.h [new file with mode: 0644]
sid/component/bochs/dma/sid-dma-wrapper.cc [new file with mode: 0644]
sid/component/bochs/dma/sid-dma-wrapper.h [new file with mode: 0644]
sid/component/bochs/floppy/Makefile.am [new file with mode: 0644]
sid/component/bochs/floppy/Makefile.in [new file with mode: 0644]
sid/component/bochs/floppy/floppy.cc [new file with mode: 0644]
sid/component/bochs/floppy/floppy.h [new file with mode: 0644]
sid/component/bochs/floppy/sid-floppy-wrapper.cc [new file with mode: 0644]
sid/component/bochs/floppy/sid-floppy-wrapper.h [new file with mode: 0644]
sid/component/bochs/gui/x-gui.cc
sid/component/bochs/gui/x-gui.h
sid/component/bochs/keyboard/keyboard.cc
sid/component/bochs/keyboard/keyboard.h
sid/component/bochs/keyboard/sid-keyboard-wrapper.cc
sid/component/bochs/keyboard/sid-keyboard-wrapper.h
sid/component/bochs/pic/Makefile.am [new file with mode: 0644]
sid/component/bochs/pic/Makefile.in [new file with mode: 0644]
sid/component/bochs/pic/pic.cc [new file with mode: 0644]
sid/component/bochs/pic/pic.h [new file with mode: 0644]
sid/component/bochs/pic/sid-pic-wrapper.cc [new file with mode: 0644]
sid/component/bochs/pic/sid-pic-wrapper.h [new file with mode: 0644]
sid/component/bochs/pit/Makefile.am [new file with mode: 0644]
sid/component/bochs/pit/Makefile.in [new file with mode: 0644]
sid/component/bochs/pit/pit.cc [new file with mode: 0644]
sid/component/bochs/pit/pit.h [new file with mode: 0644]
sid/component/bochs/pit/sid-pit-wrapper.cc [new file with mode: 0644]
sid/component/bochs/pit/sid-pit-wrapper.h [new file with mode: 0644]
sid/component/bochs/unmapped/Makefile.am [new file with mode: 0644]
sid/component/bochs/unmapped/Makefile.in [new file with mode: 0644]
sid/component/bochs/unmapped/sid-unmapped-wrapper.cc [new file with mode: 0644]
sid/component/bochs/unmapped/sid-unmapped-wrapper.h [new file with mode: 0644]
sid/component/bochs/unmapped/unmapped.cc [new file with mode: 0644]
sid/component/bochs/unmapped/unmapped.h [new file with mode: 0644]
sid/component/bochs/vga/sid-vga-wrapper.cc
sid/component/bochs/vga/sid-vga-wrapper.h
sid/component/bochs/vga/vga.cc

index 0835c99..c9eec65 100644 (file)
@@ -1,3 +1,69 @@
+2002-02-14  Thomas Fitzsimmons  <fitzsim@redhat.com>
+
+       * debug/debug.h: Move to top-level bochs directory.
+       * debug: Remove directory.
+       * pic/*: New files.
+       * floppy/*: New files.
+       * cmos/*: New files.
+       * unmapped/*: New files.
+       * dma/*: New files.
+       * pit/*: New files.
+       * cpu/x86.h: Rename to sid-x86-cpu-wrapper.h.
+       * cpu/x86.cc: Rename to sid-x86-cpu-wrapper.cc.
+       * cpu/x86-memory-modes.cc: Rename to sid-x86-memory-modes.cc.
+       * memory/*: Move to cpu/memory/*.
+       * fpu/*: Move to cpu/fpu/*.
+       * bochs.h: Change #include's to reflect new and moved files.
+       Add sid expansions for A20ADDR(x), BX_INP(addr, len),
+       BX_OUTP(addr, val, len), BX_RAISE_HLDA(),
+       BX_SET_ENABLE_A20(enabled), BX_GET_ENABLE_A20(), and
+       BX_NULL_TIMER_HANDLE.
+       * components.cxx: Add support for cmos, dma, pic, pit, floppy,
+       unmapped.
+       * config.h.in: Set BX_SUPPORT_TASKING, BX_DMA_FLOPPY_IO and
+       BX_SUPPORT_A20 to 1 by default.
+       Set SMF macros to 0 for cmos, dma, pic, pit, floppy and unmapped
+       components.
+       * configure.in: Add pic, pit, cmos, dma, floppy, and unmapped
+       Makefiles to AC_OUTPUT.
+       * cpu/exception-sid.cc: Remove.  Merge differences into
+       cpu/exception.cc.
+       * cpu/cpu-sid.h: Remove.  Merge differences into cpu/cpu.h.
+       * cpu/cpu-sid.cc: Remove.  Merge differences into cpu/cpu.cc.
+       * cpu/init-sid.cc: Remove.  Merge differences into cpu/init.cc.
+       * cpu/soft_int-sid.cc: Remove.
+       * cpu/debugstuff-sid.cc: Remove.  Merge differences into
+       cpu/debugstuff.cc.
+       * cpu/ctrl_xfer32-sid.cc: Remove.
+       * cpu/fetchdecode-sid.cc: Remove.
+       * cpu/Makefile.am: Remove references to removed files.
+       (SUBDIRS) Add memory and fpu.
+       (SUBLIBS) Add memory/libmemory.la and fpu/libfpu.la.
+       (INCLUDES) Add memory and fpu directories.
+       * cpu/cpu.cc: Remove BX_HRQ related FIXME's.
+       Add interrupt pin support.
+       * cpu/debugstuff.cc (BX_SUPPORT_SID): Add implementations of
+       dbg_get_reg, dbg_set_reg, and dbg_get_eflags for when
+       BX_DEBUGGER isn't defined.
+       * cpu/io.cc: Remove #if 0's -- no longer needed.
+       * cpu/io_pro.cc: Likewise.
+       * gui/x-gui.cc: Change title bar messages.
+       * keyboard/keyboard.cc: Change keyboard to remove serial delay
+       pin.
+       * keyboard/sid-keyboard-wrapper.cc: Add a20-related pins.
+       Remove serial-delay pin.
+       Add cmos accessor.
+       Add trigger-irq pin.
+       * keyboard/sid-keyboard-wrapper.h: Likewise.
+       * vga/sid-vga-wrapper.cc: Rename buses from eg. 3b4 to 0x3b4.
+       Import imagemmap code from generic.cxx.
+       * vga/vga.cc: Cap number of rows at BX_MAX_TEXT_LINES.
+       * Makefile.am (SUBDIRLIST): Add pic, pit, cmos, dma, floppy,
+       unmapped.
+       Removed fpu, memory.
+       (SUBLIBLIST): Likewise.
+       (INCLUDES): Likewise.
+
 2002-01-29  Thomas Fitzsimmons  <fitzsim@redhat.com>
 
        * Makefile.am (SUBDIRLIST): Add keyboard.
index 5a24528..a279ffe 100644 (file)
@@ -6,8 +6,8 @@ ACLOCAL_AMFLAGS = -I ../../config
 pkglib_LTLIBRARIES = libx86.la
 
 if SIDTARGET_X86
-SUBDIRLIST = vga gui keyboard fpu cpu memory .
-SUBLIBLIST = vga/libvga.la gui/libgui.la keyboard/libkeyboard.la fpu/libfpu.la cpu/libcpu.la memory/libmemory.la 
+SUBDIRLIST = vga gui keyboard pic pit cmos dma floppy unmapped cpu .
+SUBLIBLIST = vga/libvga.la gui/libgui.la keyboard/libkeyboard.la pic/libpic.la pit/libpit.la cmos/libcmos.la dma/libdma.la floppy/libfloppy.la unmapped/libunmapped.la cpu/libcpu.la 
 else
 SUBDIRLIST =
 SUBLIBLIST =
@@ -15,7 +15,7 @@ endif
 
 SUBDIRS = $(SUBDIRLIST)
 
-INCLUDES = -I$(top_builddir)/.. -I$(top_builddir)/../../include -I$(srcdir)/../../include -I$(srcdir)/vga -I$(srcdir)/gui -I$(srcdir)/keyboard -I$(srcdir)/cpu -I$(srcdir)/memory -I$(srcdir)/../memory
+INCLUDES = -I$(top_builddir)/.. -I$(top_builddir)/../../include -I$(srcdir)/../../include -I$(srcdir)/vga -I$(srcdir)/gui -I$(srcdir)/keyboard -I$(srcdir)/pic -I$(srcdir)/pit -I$(srcdir)/cmos -I$(srcdir)/dma -I$(srcdir)/floppy -I$(srcdir)/unmapped -I$(srcdir)/cpu -I$(srcdir)/cpu/memory -I$(srcdir)/../memory
 
 libx86_la_SOURCES = components.cxx
 libx86_la_LDFLAGS = -module -no-undefined
@@ -23,4 +23,3 @@ libx86_la_LIBADD = $(SUBLIBLIST)
 libx86_la_DEPENDENCIES = $(SUBLIBLIST)
 
 AUTOHEADER = echo "Not running autoheader"
-
index a3603d5..0ec7b47 100644 (file)
@@ -130,14 +130,14 @@ AUTOMAKE_OPTIONS = foreign
 ACLOCAL_AMFLAGS = -I ../../config
 
 pkglib_LTLIBRARIES = libx86.la
-@SIDTARGET_X86_TRUE@SUBDIRLIST = @SIDTARGET_X86_TRUE@vga gui keyboard fpu cpu memory .
+@SIDTARGET_X86_TRUE@SUBDIRLIST = @SIDTARGET_X86_TRUE@vga gui keyboard pic pit cmos dma floppy unmapped cpu .
 @SIDTARGET_X86_FALSE@SUBDIRLIST = 
-@SIDTARGET_X86_TRUE@SUBLIBLIST = @SIDTARGET_X86_TRUE@vga/libvga.la gui/libgui.la keyboard/libkeyboard.la fpu/libfpu.la cpu/libcpu.la memory/libmemory.la 
+@SIDTARGET_X86_TRUE@SUBLIBLIST = @SIDTARGET_X86_TRUE@vga/libvga.la gui/libgui.la keyboard/libkeyboard.la pic/libpic.la pit/libpit.la cmos/libcmos.la dma/libdma.la floppy/libfloppy.la unmapped/libunmapped.la cpu/libcpu.la 
 @SIDTARGET_X86_FALSE@SUBLIBLIST = 
 
 SUBDIRS = $(SUBDIRLIST)
 
-INCLUDES = -I$(top_builddir)/.. -I$(top_builddir)/../../include -I$(srcdir)/../../include -I$(srcdir)/vga -I$(srcdir)/gui -I$(srcdir)/keyboard -I$(srcdir)/cpu -I$(srcdir)/memory -I$(srcdir)/../memory
+INCLUDES = -I$(top_builddir)/.. -I$(top_builddir)/../../include -I$(srcdir)/../../include -I$(srcdir)/vga -I$(srcdir)/gui -I$(srcdir)/keyboard -I$(srcdir)/pic -I$(srcdir)/pit -I$(srcdir)/cmos -I$(srcdir)/dma -I$(srcdir)/floppy -I$(srcdir)/unmapped -I$(srcdir)/cpu -I$(srcdir)/cpu/memory -I$(srcdir)/../memory
 
 libx86_la_SOURCES = components.cxx
 libx86_la_LDFLAGS = -module -no-undefined
@@ -174,7 +174,7 @@ install-sh ltconfig ltmain.sh missing mkinstalldirs
 DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
 GZIP_ENV = --best
-DIST_SUBDIRS =  vga gui keyboard fpu cpu memory .
+DIST_SUBDIRS =  vga gui keyboard pic pit cmos dma floppy unmapped cpu .
 DEP_FILES =  .deps/components.P
 SOURCES = $(libx86_la_SOURCES)
 OBJECTS = $(libx86_la_OBJECTS)
index 1292c16..43a0603 100644 (file)
@@ -3,23 +3,23 @@ This is the sid x86 component.  It is based heavily on code from bochs
 that new bochs releases can be easily incorporated. The design looks
 something like this:
 
-+-----------------------------------------------------+
-|                                                     |
-|  x86_cpu object (see cpu/x86.h)                     |<---+
-|                                                     |<-+ |
-|     +---------------------------------------------+ |  | |
-|     |  sid_cpu_c object (see cpu/cpu-sid.h)       | |  | |
-|     |                                             | |  | |
-|     |    x86_cpu * ------------------------------------+ |
-|     |                                             | |    |
-|     +---------------------------------------------+ |    |
-|     +---------------------------------------------+ |    |
-|     |  sid_mem_c object (see memory/memory-sid.h) | |    |  
-|     |                                             | |    |
-|     |    x86_cpu * --------------------------------------+
-|     |                                             | |
-|     +---------------------------------------------+ |
-+-----------------------------------------------------+
++---------------------------------------------------------+
+|                                                         |
+|  x86_cpu object (cpu/sid-x86-cpu-wrapper.h)             |<---+
+|                                                         |<-+ |
+|     +-------------------------------------------------+ |  | |
+|     | bx_cpu_c object (cpu/cpu.h)                     | |  | |
+|     |                                                 | |  | |
+|     |    x86_cpu * ----------------------------------------+ |
+|     |                                                 | |    |
+|     +-------------------------------------------------+ |    |
+|     +-------------------------------------------------+ |    |
+|     | sid_mem_c object (cpu/memory/sid-bochs-memory.h)| |    |
+|     |                                                 | |    |
+|     |    x86_cpu * ------------------------------------------+
+|     |                                                 | |
+|     +-------------------------------------------------+ |
++---------------------------------------------------------+
 
 The sid_cpu_c class inherits from bx_cpu_c which is the main bochs cpu
 class. Likewise, sid_mem_c inherits from bx_mem_c, the main bochs
index c569bde..ccb05b7 100644 (file)
@@ -80,7 +80,7 @@ extern "C" {
 
 #if BX_SUPPORT_SID
 #  include "config.h"      /* generated by configure script from config.h.in */
-#  include "debug/debug.h"
+#  include "debug.h"
 #  include "bxversion.h"
 #else
 #  include "config.h"      /* generated by configure script from config.h.in */
@@ -144,9 +144,13 @@ class sid_mem_c;
 #else
 #define BX_VGA_MEM_READ(addr) (bx_devices.vga->mem_read(addr))
 #define BX_VGA_MEM_WRITE(addr, val) bx_devices.vga->mem_write(addr, val)
-#endif
+#endif // BX_SUPPORT_SID
 #if BX_SUPPORT_A20
+#if BX_SUPPORT_SID
+#  define A20ADDR(x)               ( (x) & x86_cpu_component->a20_mask )
+#else
 #  define A20ADDR(x)               ( (x) & bx_pc_system.a20_mask )
+#endif
 #else
 #  define A20ADDR(x)               (x)
 #endif
@@ -156,10 +160,20 @@ class sid_mem_c;
 //
 // #define BX_INP(addr, len)        bx_pc_system.inp(addr, len)
 // #define BX_OUTP(addr, val, len)  bx_pc_system.outp(addr, val, len)
+#if BX_SUPPORT_SID
+// CAUTION: only use one of 1, 2, or 4 for len
+#define BX_INP(addr, len)           x86_cpu_component->read_io_memory_##len (addr)
+#define BX_OUTP(addr, val, len)     x86_cpu_component->write_io_memory_##len (addr, val)
+#else
 #define BX_INP(addr, len)           bx_devices.inp(addr, len)
 #define BX_OUTP(addr, val, len)     bx_devices.outp(addr, val, len)
+#endif
+#if BX_SUPPORT_SID
+#define BX_RAISE_HLDA()             x86_cpu_component->drive_hold_acknowledge_pin()
+#else
 #define BX_HRQ                      (bx_pc_system.HRQ)
 #define BX_RAISE_HLDA()             bx_pc_system.raise_HLDA()
+#endif
 #if BX_SUPPORT_SID
 #define BX_TICK1()
 #else
@@ -178,8 +192,8 @@ class sid_mem_c;
 #define BX_MEM(x)                   (bx_mem_array[x])
 #endif
 #if BX_SUPPORT_SID
-#define BX_SET_ENABLE_A20(enabled)  
-#define BX_GET_ENABLE_A20()         0
+#define BX_SET_ENABLE_A20(enabled)  kbd_component->drive_enable_a20_pin(enabled)
+#define BX_GET_ENABLE_A20()         kbd_component->sense_a20_enabled_pin()
 #else
 #define BX_SET_ENABLE_A20(enabled)  bx_pc_system.set_enable_a20(enabled)
 #define BX_GET_ENABLE_A20()         bx_pc_system.get_enable_a20()
@@ -462,7 +476,7 @@ extern logfunc_t *genlog;
 
 #if BX_PROVIDE_CPU_MEMORY==1
 #if BX_SUPPORT_SID
-#include "cpu/cpu-sid.h"
+#include "cpu/cpu.h"
 #else
 #  include "cpu/cpu.h"
 #endif
@@ -538,7 +552,7 @@ extern bx_debug_t bx_dbg;
 
 
 #if BX_SUPPORT_SID
-#include "memory/memory-sid.h"
+#include "cpu/memory/sid-bochs-memory.h"
 #else
 #include "memory/memory.h"
 #endif
@@ -548,6 +562,12 @@ enum PCS_OP { PCS_CLEAR, PCS_SET, PCS_TOGGLE };
 #if BX_SUPPORT_SID
 #include "vga/vga.h"
 #include "keyboard/keyboard.h"
+#include "pic/pic.h"
+#include "pit/pit.h"
+#include "dma/dma.h"
+#include "cmos/cmos.h"
+#include "floppy/floppy.h"
+#include "unmapped/unmapped.h"
 #else
 #include "pc_system.h"
 
@@ -690,4 +710,8 @@ int bx_bochs_init(int argc, char *argv[]);
 
 #include "instrument.h"
 
+#if BX_SUPPORT_SID
+#define BX_NULL_TIMER_HANDLE 10000 /* set uninitialized timer handles to this */
+#endif
+
 #endif  /* BX_BOCHS_H */
diff --git a/sid/component/bochs/cmos/Makefile.am b/sid/component/bochs/cmos/Makefile.am
new file mode 100644 (file)
index 0000000..2e5a404
--- /dev/null
@@ -0,0 +1,11 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../cpu
+
+noinst_LTLIBRARIES = libcmos.la
+
+libcmos_la_SOURCES = sid-cmos-wrapper.cc sid-cmos-wrapper.h cmos.cc cmos.h
+
+libcmos_la_LDFLAGS = -no-undefined
diff --git a/sid/component/bochs/cmos/Makefile.in b/sid/component/bochs/cmos/Makefile.in
new file mode 100644 (file)
index 0000000..3cdf38a
--- /dev/null
@@ -0,0 +1,412 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+APIC_OBJS = @APIC_OBJS@
+AR = @AR@
+AS = @AS@
+AS_DYNAMIC_INCS = @AS_DYNAMIC_INCS@
+AS_DYNAMIC_OBJS = @AS_DYNAMIC_OBJS@
+BX_LOADER_OBJS = @BX_LOADER_OBJS@
+BX_SPLIT_HD_SUPPORT = @BX_SPLIT_HD_SUPPORT@
+CC = @CC@
+CDROM_OBJS = @CDROM_OBJS@
+CD_UP_ONE = @CD_UP_ONE@
+CD_UP_TWO = @CD_UP_TWO@
+CFP = @CFP@
+COMMAND_SEPARATOR = @COMMAND_SEPARATOR@
+CPP_SUFFIX = @CPP_SUFFIX@
+CXX = @CXX@
+CXXFP = @CXXFP@
+DASH = @DASH@
+DEBUGGER_VAR = @DEBUGGER_VAR@
+DISASM_VAR = @DISASM_VAR@
+DLLTOOL = @DLLTOOL@
+DYNAMIC_VAR = @DYNAMIC_VAR@
+EXE = @EXE@
+EXEEXT = @EXEEXT@
+EXTERNAL_DEPENDENCY = @EXTERNAL_DEPENDENCY@
+FPU_GLUE_OBJ = @FPU_GLUE_OBJ@
+FPU_VAR = @FPU_VAR@
+GUI_LINK_OPTS = @GUI_LINK_OPTS@
+GUI_LINK_OPTS_TERM = @GUI_LINK_OPTS_TERM@
+GUI_OBJS = @GUI_OBJS@
+GZIP = @GZIP@
+INLINE_VAR = @INLINE_VAR@
+INSTRUMENT_DIR = @INSTRUMENT_DIR@
+INSTRUMENT_VAR = @INSTRUMENT_VAR@
+IOAPIC_OBJS = @IOAPIC_OBJS@
+IODEV_LIB_VAR = @IODEV_LIB_VAR@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LINK = @LINK@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKELIB = @MAKELIB@
+NE2K_OBJS = @NE2K_OBJS@
+NM = @NM@
+NONINLINE_VAR = @NONINLINE_VAR@
+OBJDUMP = @OBJDUMP@
+OFP = @OFP@
+PACKAGE = @PACKAGE@
+PCI_OBJ = @PCI_OBJ@
+PRIMARY_TARGET = @PRIMARY_TARGET@
+RANLIB = @RANLIB@
+READLINE_LIB = @READLINE_LIB@
+RFB_LIBS = @RFB_LIBS@
+RMCOMMAND = @RMCOMMAND@
+SB16_OBJS = @SB16_OBJS@
+SLASH = @SLASH@
+SUFFIX_LINE = @SUFFIX_LINE@
+TAR = @TAR@
+VERSION = @VERSION@
+VIDEO_OBJS = @VIDEO_OBJS@
+sidtarget_arm = @sidtarget_arm@
+sidtarget_m32r = @sidtarget_m32r@
+sidtarget_m68k = @sidtarget_m68k@
+sidtarget_mips = @sidtarget_mips@
+sidtarget_ppc = @sidtarget_ppc@
+sidtarget_x86 = @sidtarget_x86@
+sidtarget_xstormy16 = @sidtarget_xstormy16@
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../cpu
+
+noinst_LTLIBRARIES = libcmos.la
+
+libcmos_la_SOURCES = sid-cmos-wrapper.cc sid-cmos-wrapper.h cmos.cc cmos.h
+
+libcmos_la_LDFLAGS = -no-undefined
+mkinstalldirs = $(SHELL) $(top_srcdir)/../../config/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+LTLIBRARIES =  $(noinst_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libcmos_la_LIBADD = 
+libcmos_la_OBJECTS =  sid-cmos-wrapper.lo cmos.lo
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+GZIP_ENV = --best
+DEP_FILES =  .deps/cmos.P .deps/sid-cmos-wrapper.P
+SOURCES = $(libcmos_la_SOURCES)
+OBJECTS = $(libcmos_la_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .lo .o .s
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --foreign cmos/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLTLIBRARIES:
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+
+distclean-noinstLTLIBRARIES:
+
+maintainer-clean-noinstLTLIBRARIES:
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libcmos.la: $(libcmos_la_OBJECTS) $(libcmos_la_DEPENDENCIES)
+       $(CXXLINK)  $(libcmos_la_LDFLAGS) $(libcmos_la_OBJECTS) $(libcmos_la_LIBADD) $(LIBS)
+.cc.o:
+       $(CXXCOMPILE) -c $<
+.cc.lo:
+       $(LTCXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = cmos
+
+distdir: $(DISTFILES)
+       here=`cd $(top_builddir) && pwd`; \
+       top_distdir=`cd $(top_distdir) && pwd`; \
+       distdir=`cd $(distdir) && pwd`; \
+       cd $(top_srcdir) \
+         && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign cmos/Makefile
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+       -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+       @echo '$(COMPILE) -c $<'; \
+       $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.c
+       @echo '$(LTCOMPILE) -c $<'; \
+       $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+
+%.o: %.cc
+       @echo '$(CXXCOMPILE) -c $<'; \
+       $(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.cc
+       @echo '$(LTCXXCOMPILE) -c $<'; \
+       $(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LTLIBRARIES)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLTLIBRARIES mostlyclean-compile \
+               mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+               mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLTLIBRARIES clean-compile clean-libtool \
+               clean-tags clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLTLIBRARIES distclean-compile \
+               distclean-libtool distclean-tags distclean-depend \
+               distclean-generic clean-am
+       -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLTLIBRARIES \
+               maintainer-clean-compile maintainer-clean-libtool \
+               maintainer-clean-tags maintainer-clean-depend \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \
+clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sid/component/bochs/cmos/cmos.cc b/sid/component/bochs/cmos/cmos.cc
new file mode 100644 (file)
index 0000000..c84c15f
--- /dev/null
@@ -0,0 +1,819 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+
+
+
+#include "bochs.h"
+#if BX_SUPPORT_SID
+#define LOG_THIS
+#include "sid-cmos-wrapper.h"
+#else
+#define LOG_THIS bx_cmos.
+
+bx_cmos_c bx_cmos;
+#endif
+
+#if BX_USE_CMOS_SMF
+#define this (&bx_cmos)
+#endif
+
+
+// check that BX_NUM_CMOS_REGS is 64 or 128
+#if (BX_NUM_CMOS_REGS == 64)
+#elif (BX_NUM_CMOS_REGS == 128)
+#else
+#error "Invalid BX_NUM_CMOS_REGS value in config.h"
+#endif
+
+
+bx_cmos_c::bx_cmos_c(void)
+{
+#if BX_SUPPORT_SID
+  bx_dbg.cmos = 1;
+#endif
+       setprefix("[CMOS]");
+       settype(CMOSLOG);
+       BX_DEBUG(("Init.\n"));
+}
+
+bx_cmos_c::~bx_cmos_c(void)
+{
+  // nothing for now
+  BX_DEBUG(("Exit.\n"));
+}
+
+
+#if BX_SUPPORT_SID
+void
+bx_cmos_c::init(cmos *cmos_comp)
+#else
+  void
+bx_cmos_c::init(bx_devices_c *d)
+#endif
+{
+  unsigned i;
+
+  // CMOS RAM & RTC
+
+#if BX_SUPPORT_SID
+  cmos_component = cmos_comp;
+  cmos_component->drive_periodic_timer_control_pin (0, 0);
+  cmos_component->drive_one_second_timer_control_pin (0, 0);
+#else
+  BX_CMOS_THIS devices = d;
+
+  BX_CMOS_THIS devices->register_io_read_handler(this,
+       read_handler, 0x0070,
+       "CMOS RAM");
+  BX_CMOS_THIS devices->register_io_read_handler(this,
+       read_handler,
+       0x0071,
+       "CMOS RAM");
+  BX_CMOS_THIS devices->register_io_write_handler(this,
+       write_handler,
+       0x0070, "CMOS RAM");
+  BX_CMOS_THIS devices->register_io_write_handler(this,
+       write_handler,
+       0x0071, "CMOS RAM");
+  BX_CMOS_THIS devices->register_irq(8, "CMOS RTC");
+
+  BX_CMOS_THIS s.periodic_timer_index =
+    bx_pc_system.register_timer(this, periodic_timer_handler,
+      1000000, 1,0); // continuous, not-active
+  BX_CMOS_THIS s.one_second_timer_index =
+    bx_pc_system.register_timer(this, one_second_timer_handler,
+      1000000, 1,0); // continuous, not-active
+#endif
+
+  for (i=0; i<BX_NUM_CMOS_REGS; i++) {
+    BX_CMOS_THIS s.reg[i] = 0;
+    }
+
+#if BX_SUPPORT_SID
+  s.timeval = cmos_component->get_time();
+#else
+#if BX_USE_SPECIFIED_TIME0 == 0
+  // ??? this will not be correct for using an image file.
+  // perhaps take values in CMOS and work backwards to find
+  // s.timeval from values read in.
+  BX_CMOS_THIS s.timeval = time(NULL);
+#else
+  BX_CMOS_THIS s.timeval = BX_USE_SPECIFIED_TIME0;
+#endif
+
+  if (bx_options.cmos.time0 == 1)
+          BX_CMOS_THIS s.timeval = time(NULL);
+  else if (bx_options.cmos.time0 != 0)
+          BX_CMOS_THIS s.timeval = bx_options.cmos.time0;
+#endif // BX_SUPPORT_SID
+
+  BX_INFO(("Setting initial clock to: %s",
+    ctime(&(BX_CMOS_THIS s.timeval)) ));
+
+  update_clock();
+
+#if BX_SUPPORT_SID==0
+  // load CMOS from image file if requested.
+  if (bx_options.cmos.cmosImage) {
+    // CMOS image file requested
+    int fd, ret;
+    struct stat stat_buf;
+
+    fd = open(bx_options.cmos.path, O_RDONLY
+#ifdef O_BINARY
+            | O_BINARY
+#endif
+             );
+    if (fd < 0) {
+      BX_PANIC(("trying to open cmos image file '%s'\n",
+        bx_options.cmos.path));
+      }
+    ret = fstat(fd, &stat_buf);
+    if (ret) {
+      BX_PANIC(("CMOS: could not fstat() image file.\n"));
+      }
+    if (stat_buf.st_size != BX_NUM_CMOS_REGS) {
+      BX_PANIC(("CMOS: image file not same size as BX_NUM_CMOS_REGS.\n"));
+      }
+
+    ret = ::read(fd, (bx_ptr_t) BX_CMOS_THIS s.reg, BX_NUM_CMOS_REGS);
+    if (ret != BX_NUM_CMOS_REGS) {
+      BX_PANIC(("CMOS: error reading cmos file.\n"));
+      }
+    close(fd);
+    BX_INFO(("successfuly read from image file '%s'.\n",
+      bx_options.cmos.path));
+    }
+  else {
+    // CMOS values generated
+    BX_CMOS_THIS s.reg[0x0a] = 0x26;
+    BX_CMOS_THIS s.reg[0x0b] = 0x02;
+    BX_CMOS_THIS s.reg[0x0c] = 0x00;
+    BX_CMOS_THIS s.reg[0x0d] = 0x80;
+    }
+#endif // BX_SUPPORT_SID
+}
+
+#if BX_SUPPORT_SID
+void
+bx_cmos_c::load_cmos_image(std::string path)
+{
+  // load CMOS from image
+  int fd, ret;
+  struct stat stat_buf;
+  
+  fd = open(path.c_str(), O_RDONLY
+#ifdef O_BINARY
+            | O_BINARY
+#endif
+            );
+  if (fd < 0)
+    {
+      BX_PANIC(("trying to open cmos image file '%s'\n", path.c_str()));
+    }
+  ret = fstat(fd, &stat_buf);
+  if (ret)
+    {
+      BX_PANIC(("CMOS: could not fstat() image file.\n"));
+    }
+  if (stat_buf.st_size != BX_NUM_CMOS_REGS)
+    {
+      BX_PANIC(("CMOS: image file not same size as BX_NUM_CMOS_REGS.\n"));
+    }
+  
+  ret = ::read(fd, (bx_ptr_t) BX_CMOS_THIS s.reg, BX_NUM_CMOS_REGS);
+  if (ret != BX_NUM_CMOS_REGS)
+    {
+      BX_PANIC(("CMOS: error reading cmos file.\n"));
+    }
+  close(fd);
+  BX_INFO(("successfuly read from image file '%s'.\n", path.c_str()));
+}
+
+void
+bx_cmos_c::generate_cmos_values(void)
+{
+#if BX_SUPPORT_SID
+  BX_CMOS_THIS s.reg[0x2d] |= 0x20; // system boot sequence A:, C:
+#endif
+  // CMOS values generated
+  BX_CMOS_THIS s.reg[0x0a] = 0x26;
+  BX_CMOS_THIS s.reg[0x0b] = 0x02;
+  BX_CMOS_THIS s.reg[0x0c] = 0x00;
+  BX_CMOS_THIS s.reg[0x0d] = 0x80;
+}
+#endif // BX_SUPPORT_SID
+
+  void
+bx_cmos_c::reset(void)
+{
+  BX_CMOS_THIS s.cmos_mem_address = 0;
+
+  // RESET affects the following registers:
+  //  CRA: no effects
+  //  CRB: bits 4,5,6 forced to 0
+  //  CRC: bits 4,5,6,7 forced to 0
+  //  CRD: no effects
+  BX_CMOS_THIS s.reg[0x0b] &= 0x8f;
+  BX_CMOS_THIS s.reg[0x0c] = 0;
+
+#if BX_SUPPORT_SID
+  if (cmos_component)
+    cmos_component->drive_one_second_timer_control_pin(1000000, 1);
+  else
+    {
+      cerr << "cmos: Drive init pin before other cmos pins." << endl;
+      exit(1);
+    }
+#else
+  // One second timer for updating clock & alarm functions
+  bx_pc_system.activate_timer(BX_CMOS_THIS s.one_second_timer_index,
+                              1000000, 1);
+#endif
+
+  // handle periodic interrupt rate select
+  BX_CMOS_THIS CRA_change();
+}
+
+  void
+bx_cmos_c::CRA_change(void)
+{
+  unsigned nibble;
+
+  // Periodic Interrupt timer
+  nibble = BX_CMOS_THIS s.reg[0x0a] & 0x0f;
+  if (nibble == 0) {
+    // No Periodic Interrupt Rate when 0, deactivate timer
+#if BX_SUPPORT_SID
+    if (cmos_component)
+      cmos_component->drive_periodic_timer_control_pin(0, 0);
+    else
+      {
+        cerr << "cmos: Drive init pin before other cmos pins." << endl;
+        exit(1);
+      }
+#else
+    bx_pc_system.deactivate_timer(BX_CMOS_THIS s.periodic_timer_index);
+#endif
+    BX_CMOS_THIS s.periodic_interval_usec = (Bit32u) -1; // max value
+    }
+  else {
+    // values 0001b and 0010b are the same as 1000b and 1001b
+    if (nibble <= 2)
+      nibble += 7;
+    BX_CMOS_THIS s.periodic_interval_usec = (unsigned) (1000000.0L /
+        (32768.0L / (1 << (nibble - 1))));
+
+    // if Periodic Interrupt Enable bit set, activate timer
+    if ( BX_CMOS_THIS s.reg[0x0b] & 0x40 )
+#if BX_SUPPORT_SID
+      if (cmos_component)
+        cmos_component->drive_periodic_timer_control_pin(BX_CMOS_THIS s.periodic_interval_usec, 1);
+      else
+        {
+          cerr << "cmos: Drive init pin before other cmos pins." << endl;
+          exit(1);
+        }
+#else
+      bx_pc_system.activate_timer(BX_CMOS_THIS s.periodic_timer_index,
+        BX_CMOS_THIS s.periodic_interval_usec, 1);
+#endif
+    else
+#if BX_SUPPORT_SID
+      if (cmos_component)
+        cmos_component->drive_periodic_timer_control_pin(0, 0);
+      else
+        {
+          cerr << "cmos: Drive init pin before other cmos pins." << endl;
+          exit(1);
+        }
+#else
+      bx_pc_system.deactivate_timer(BX_CMOS_THIS s.periodic_timer_index);
+#endif
+    }
+}
+
+
+  // static IO port read callback handler
+  // redirects to non-static class handler to avoid virtual functions
+
+  Bit32u
+bx_cmos_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
+{
+#if !BX_USE_CMOS_SMF
+  bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr;
+
+  return( class_ptr->read(address, io_len) );
+}
+
+  Bit32u
+bx_cmos_c::read(Bit32u address, unsigned io_len)
+{
+#else
+  UNUSED(this_ptr);
+#endif
+  Bit8u ret8;
+
+  if (io_len > 1)
+    BX_PANIC(("cmos: io read from address %08x len=%u\n",
+             (unsigned) address, (unsigned) io_len));
+
+  if (bx_dbg.cmos)
+    BX_INFO(("CMOS read of CMOS register 0x%x\n",
+      (unsigned) BX_CMOS_THIS s.cmos_mem_address));
+
+
+  switch (address) {
+    case 0x0071:
+      if (BX_CMOS_THIS s.cmos_mem_address >= BX_NUM_CMOS_REGS) {
+        BX_PANIC(("unsupported cmos io read, register(0x%02x)!\n",
+            (unsigned) BX_CMOS_THIS s.cmos_mem_address));
+        }
+
+      ret8 = BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address];
+      // all bits of Register C are cleared after a read occurs.
+      if (BX_CMOS_THIS s.cmos_mem_address == 0x0c)
+        BX_CMOS_THIS s.reg[0x0c] = 0x00;
+      return(ret8);
+      break;
+
+    default:
+      BX_PANIC(("unsupported cmos read, address=%0x%x!\n",
+        (unsigned) address));
+      return(0);
+      break;
+    }
+}
+
+
+  // static IO port write callback handler
+  // redirects to non-static class handler to avoid virtual functions
+
+  void
+bx_cmos_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
+{
+#if !BX_USE_CMOS_SMF
+  bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr;
+
+  class_ptr->write(address, value, io_len);
+}
+
+  void
+bx_cmos_c::write(Bit32u address, Bit32u value, unsigned io_len)
+{
+#else
+  UNUSED(this_ptr);
+#endif  // !BX_USE_CMOS_SMF
+
+  if (io_len > 1)
+    BX_PANIC(("cmos: io write to address %08x len=%u\n",
+             (unsigned) address, (unsigned) io_len));
+
+  if (bx_dbg.cmos)
+    BX_INFO(("CMOS write to address: 0x%x = 0x%x\n",
+      (unsigned) address, (unsigned) value));
+
+
+  switch (address) {
+    case 0x0070:
+#if (BX_NUM_CMOS_REGS == 64)
+      BX_CMOS_THIS s.cmos_mem_address = value & 0x3F;
+#else
+      BX_CMOS_THIS s.cmos_mem_address = value & 0x7F;
+#endif
+      break;
+
+    case 0x0071:
+      if (BX_CMOS_THIS s.cmos_mem_address >= BX_NUM_CMOS_REGS) {
+        BX_PANIC(("unsupported cmos io write, register(0x%02x)=%02x!\n",
+            (unsigned) BX_CMOS_THIS s.cmos_mem_address, (unsigned) value));
+        return;
+        }
+      switch (BX_CMOS_THIS s.cmos_mem_address) {
+        case 0x00: // seconds
+        case 0x01: // seconds alarm
+        case 0x02: // minutes
+        case 0x03: // minutes alarm
+        case 0x04: // hours
+        case 0x05: // hours alarm
+        case 0x06: // day of the week
+        case 0x07: // day of the month
+        case 0x08: // month
+        case 0x09: // year
+          //BX_INFO(("write reg %02xh: value = %02xh\n",
+          //    (unsigned) BX_CMOS_THIS s.cmos_mem_address, (unsigned) value);
+          BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address] = value;
+          return;
+          break;
+
+        case 0x0a: // Control Register A
+          // bit 7: Update in Progress (read-only)
+          //   1 = signifies time registers will be updated within 244us
+          //   0 = time registers will not occur before 244us
+          //   note: this bit reads 0 when CRB bit 7 is 1
+          // bit 6..4: Divider Chain Control
+          //   000 oscillator disabled
+          //   001 oscillator disabled
+          //   010 Normal operation
+          //   011 TEST
+          //   100 TEST
+          //   101 TEST
+          //   110 Divider Chain RESET
+          //   111 Divider Chain RESET
+          // bit 3..0: Periodic Interrupt Rate Select
+          //   0000 None
+          //   0001 3.90625  ms
+          //   0010 7.8125   ms
+          //   0011 122.070  us
+          //   0100 244.141  us
+          //   0101 488.281  us
+          //   0110 976.562  us
+          //   0111 1.953125 ms
+          //   1000 3.90625  ms
+          //   1001 7.8125   ms
+          //   1010 15.625   ms
+          //   1011 31.25    ms
+          //   1100 62.5     ms
+          //   1101 125      ms
+          //   1110 250      ms
+          //   1111 500      ms
+
+          unsigned dcc;
+          dcc = (value >> 4) & 0x07;
+          if (dcc != 0x02) {
+            BX_PANIC(("cmos: CRA: divider chain control 0x%x\n", dcc));
+            }
+          BX_CMOS_THIS s.reg[0x0a] = value & 0x7f;
+          BX_CMOS_THIS CRA_change();
+          return;
+          break;
+
+        case 0x0b: // Control Register B
+          // bit 0: Daylight Savings Enable
+          //   1 = enable daylight savings
+          //   0 = disable daylight savings
+          // bit 1: 24/12 houre mode
+          //   1 = 24 hour format
+          //   0 = 12 hour format
+          // bit 2: Data Mode
+          //   1 = binary format
+          //   0 = BCD format
+          // bit 3: "square wave enable"
+          //   Not supported and always read as 0
+          // bit 4: Update Ended Interrupt Enable
+          //   1 = enable generation of update ended interrupt
+          //   0 = disable
+          // bit 5: Alarm Interrupt Enable
+          //   1 = enable generation of alarm interrupt
+          //   0 = disable
+          // bit 6: Periodic Interrupt Enable
+          //   1 = enable generation of periodic interrupt
+          //   0 = disable
+          // bit 7: Set mode
+          //   1 = user copy of time is "frozen" allowing time registers
+          //       to be accessed without regard for an occurance of an update
+          //   0 = time updates occur normally
+
+          // can not handle binary or 12-hour mode yet.
+          if (value & 0x04)
+            BX_PANIC(("cmos: write status reg B, binary format enabled.\n"));
+          if ( !(value & 0x02) )
+            BX_PANIC(("cmos: write status reg B, 12 hour mode enabled.\n"));
+
+          value &= 0xf7; // bit3 always 0
+          // Note: setting bit 7 clears bit 4
+          if (value & 0x80)
+            value &= 0xef;
+
+          unsigned prev_CRB;
+          prev_CRB = BX_CMOS_THIS s.reg[0x0b];
+          BX_CMOS_THIS s.reg[0x0b] = value;
+          if ( (prev_CRB & 0x40) != (value & 0x40) ) {
+            // Periodic Interrupt Enabled changed
+            if (prev_CRB & 0x40) {
+              // transition from 1 to 0, deactivate timer
+#if BX_SUPPORT_SID
+              if (cmos_component)
+                cmos_component->drive_periodic_timer_control_pin(0, 0);
+              else
+                {
+                  cerr << "cmos: Drive init pin before other cmos pins." << endl;
+                  exit(1);
+                }
+#else
+              bx_pc_system.deactivate_timer(
+                BX_CMOS_THIS s.periodic_timer_index);
+#endif
+              }
+            else {
+              // transition from 0 to 1
+              // if rate select is not 0, activate timer
+              if ( (BX_CMOS_THIS s.reg[0x0a] & 0x0f) != 0 ) {
+#if BX_SUPPORT_SID
+                if (cmos_component)
+                  cmos_component->drive_periodic_timer_control_pin(BX_CMOS_THIS s.periodic_interval_usec, 1);
+                else
+                  {
+                    cerr << "cmos: Drive init pin before other cmos pins." << endl;
+                    exit(1);
+                  }
+#else
+                bx_pc_system.activate_timer(
+                  BX_CMOS_THIS s.periodic_timer_index,
+                  BX_CMOS_THIS s.periodic_interval_usec, 1);
+#endif
+                }
+              }
+            }
+          return;
+          break;
+
+        case 0x0c: // Control Register C
+        case 0x0d: // Control Register D
+          BX_PANIC(("cmos: write to control register 0x%x (read-only)\n",
+                   BX_CMOS_THIS s.cmos_mem_address));
+          break;
+
+        case 0x0e: // diagnostic status
+          BX_INFO(("write register 0Eh: %02x\n", (unsigned) value));;
+          break;
+
+       case 0x0f: // shutdown status
+          switch (value) {
+            case 0x00: /* proceed with normal POST (soft reset) */
+              if (bx_dbg.reset)
+                BX_INFO(("Reg 0F set to 0: shutdown action = normal POST\n"));;
+              break;
+            case 0x02: /* shutdown after memory test */
+              if (bx_dbg.reset)
+                BX_INFO(("Reg 0Fh: request to change shutdown action"
+                             " to shutdown after memory test\n"));
+              break;
+            case 0x03:
+              BX_INFO(("Reg 0Fh(03) : Shutdown after memory test !\n"));;
+              break;
+            case 0x04: /* jump to disk bootstrap routine */
+              BX_INFO(("Reg 0Fh: request to change shutdown action "
+                             "to jump to disk bootstrap routine.\n"));
+              break;
+            case 0x06:
+              BX_INFO(("Reg 0Fh(06) : Shutdown after memory test !\n"));;
+              break;
+            case 0x09: /* return to BIOS extended memory block move
+                       (interrupt 15h, func 87h was in progress) */
+              if (bx_dbg.reset)
+                BX_INFO(("Reg 0Fh: request to change shutdown action "
+                             "to return to BIOS extended memory block move.\n"));
+              break;
+            case 0x0a: /* jump to DWORD pointer at 40:67 */
+              if (bx_dbg.reset)
+                BX_INFO(("Reg 0Fh: request to change shutdown action"
+                             " to jump to DWORD at 40:67\n"));
+              break;
+            default:
+              BX_PANIC(("unsupported cmos io write to reg F, case %x!\n",
+                (unsigned) value));
+              break;
+            }
+          break;
+
+        default:
+          BX_INFO(("write reg %02xh: value = %02xh\n",
+            (unsigned) BX_CMOS_THIS s.cmos_mem_address, (unsigned) value));
+          break;
+        }
+
+      BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address] = value;
+      break;
+    }
+}
+
+
+  void
+bx_cmos_c::checksum_cmos(void)
+{
+  unsigned i;
+  Bit16u sum;
+
+  sum = 0;
+  for (i=0x10; i<=0x2d; i++) {
+    sum += BX_CMOS_THIS s.reg[i];
+    }
+  BX_CMOS_THIS s.reg[0x2e] = (sum >> 8) & 0xff; /* checksum high */
+  BX_CMOS_THIS s.reg[0x2f] = (sum & 0xff);      /* checksum low */
+}
+
+#if BX_SUPPORT_SID
+void
+bx_cmos_c::periodic_timer_handler(void)
+{
+  // if periodic interrupts are enabled, trip IRQ 8, and
+  // update status register C
+  if (s.reg[0x0b] & 0x40)
+    {
+      s.reg[0x0c] |= 0xc0; // Interrupt Request, Periodic Int
+      if (cmos_component)
+        cmos_component->drive_trigger_irq_pin();
+      else
+        {
+          cerr << "cmos: Drive init pin before other cmos pins." << endl;
+          exit(1);
+        }
+    }
+}
+
+void
+bx_cmos_c::one_second_timer_handler(void)
+{
+  // update internal time/date buffer
+  s.timeval++;
+
+  // Dont update CMOS user copy of time/date if CRB bit7 is 1
+  // Nothing else do to
+  if (s.reg[0x0b] & 0x80)
+    return;
+
+  update_clock();
+
+  // if update interrupts are enabled, trip IRQ 8, and
+  // update status register C
+  if (s.reg[0x0b] & 0x10)
+    {
+      s.reg[0x0c] |= 0x90; // Interrupt Request, Update Ended
+      if (cmos_component)
+        cmos_component->drive_trigger_irq_pin();
+      else
+        {
+          cerr << "cmos: Drive init pin before other cmos pins." << endl;
+          exit(1);
+        }
+    }
+
+  // compare CMOS user copy of time/date to alarm time/date here
+  if (s.reg[0x0b] & 0x20)
+    {
+      // Alarm interrupts enabled
+      Boolean alarm_match = 1;
+      if ((s.reg[0x01] & 0xc0) != 0xc0)
+        {
+          // seconds alarm not in dont care mode
+          if (s.reg[0x00] != s.reg[0x01])
+            alarm_match = 0;
+      }
+    if ((s.reg[0x03] & 0xc0) != 0xc0)
+      {
+        // minutes alarm not in dont care mode
+        if (s.reg[0x02] != s.reg[0x03])
+          alarm_match = 0;
+      }
+    if ((s.reg[0x05] & 0xc0) != 0xc0)
+      {
+        // hours alarm not in dont care mode
+        if (s.reg[0x04] != s.reg[0x05])
+          alarm_match = 0;
+      }
+    if (alarm_match)
+      {
+        s.reg[0x0c] |= 0xa0; // Interrupt Request, Alarm Int
+        if (cmos_component)
+          cmos_component->drive_trigger_irq_pin();
+        else
+          {
+            cerr << "cmos: Drive init pin before other cmos pins." << endl;
+            exit(1);
+          }
+      }
+    }
+}
+#else
+  void
+bx_cmos_c::periodic_timer_handler(void *this_ptr)
+{
+  bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr;
+
+  // if periodic interrupts are enabled, trip IRQ 8, and
+  // update status register C
+  if (class_ptr->s.reg[0x0b] & 0x40) {
+    class_ptr->s.reg[0x0c] |= 0xc0; // Interrupt Request, Periodic Int
+    class_ptr->devices->pic->trigger_irq(8);
+    }
+}
+
+  void
+bx_cmos_c::one_second_timer_handler(void *this_ptr)
+{
+  bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr;
+
+  // update internal time/date buffer
+  class_ptr->s.timeval++;
+
+  // Dont update CMOS user copy of time/date if CRB bit7 is 1
+  // Nothing else do to
+  if (class_ptr->s.reg[0x0b] & 0x80)
+    return;
+
+  class_ptr->update_clock();
+
+  // if update interrupts are enabled, trip IRQ 8, and
+  // update status register C
+  if (class_ptr->s.reg[0x0b] & 0x10) {
+    class_ptr->s.reg[0x0c] |= 0x90; // Interrupt Request, Update Ended
+    class_ptr->devices->pic->trigger_irq(8);
+    }
+
+  // compare CMOS user copy of time/date to alarm time/date here
+  if (class_ptr->s.reg[0x0b] & 0x20) {
+    // Alarm interrupts enabled
+    Boolean alarm_match = 1;
+    if ( (class_ptr->s.reg[0x01] & 0xc0) != 0xc0 ) {
+      // seconds alarm not in dont care mode
+      if (class_ptr->s.reg[0x00] != class_ptr->s.reg[0x01])
+        alarm_match = 0;
+      }
+    if ( (class_ptr->s.reg[0x03] & 0xc0) != 0xc0 ) {
+      // minutes alarm not in dont care mode
+      if (class_ptr->s.reg[0x02] != class_ptr->s.reg[0x03])
+        alarm_match = 0;
+      }
+    if ( (class_ptr->s.reg[0x05] & 0xc0) != 0xc0 ) {
+      // hours alarm not in dont care mode
+      if (class_ptr->s.reg[0x04] != class_ptr->s.reg[0x05])
+        alarm_match = 0;
+      }
+    if (alarm_match) {
+      class_ptr->s.reg[0x0c] |= 0xa0; // Interrupt Request, Alarm Int
+      class_ptr->devices->pic->trigger_irq(8);
+      }
+    }
+}
+#endif
+
+
+  void
+bx_cmos_c::update_clock()
+{
+  struct tm *time_calendar;
+  unsigned year, month, day, century;
+  Bit8u val_bcd;
+
+  time_calendar = localtime(& BX_CMOS_THIS s.timeval);
+
+  // update seconds
+  val_bcd =
+     ((time_calendar->tm_sec  / 10) << 4) |
+     (time_calendar->tm_sec % 10);
+  BX_CMOS_THIS s.reg[0x00] = val_bcd;
+
+  // update minutes
+  val_bcd =
+     ((time_calendar->tm_min  / 10) << 4) |
+     (time_calendar->tm_min % 10);
+  BX_CMOS_THIS s.reg[0x02] = val_bcd;
+
+  // update hours
+  val_bcd =
+     ((time_calendar->tm_hour  / 10) << 4) |
+     (time_calendar->tm_hour % 10);
+  BX_CMOS_THIS s.reg[0x04] = val_bcd;
+
+  // update day of the week
+  day = time_calendar->tm_wday + 1; // 0..6 to 1..7
+  BX_CMOS_THIS s.reg[0x06] = ((day / 10) << 4) | (day % 10);
+
+  // update day of the month
+  day = time_calendar->tm_mday;
+  BX_CMOS_THIS s.reg[0x07] = ((day / 10) << 4) | (day % 10);
+
+  // update month
+  month   = time_calendar->tm_mon + 1;
+  BX_CMOS_THIS s.reg[0x08] = ((month / 10) << 4) | (month % 10);
+
+  // update year
+  year = time_calendar->tm_year % 100;
+  BX_CMOS_THIS s.reg[0x09] = ((year  / 10) << 4) | (year % 10);
+
+  // update century
+  century = (time_calendar->tm_year / 100) + 19;
+  BX_CMOS_THIS s.reg[0x32] = ((century  / 10) << 4) | (century % 10);
+}
diff --git a/sid/component/bochs/cmos/cmos.h b/sid/component/bochs/cmos/cmos.h
new file mode 100644 (file)
index 0000000..95681e4
--- /dev/null
@@ -0,0 +1,101 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+
+
+#if BX_SUPPORT_SID
+#include <string>
+#endif
+
+
+#if BX_USE_CMOS_SMF
+#  define BX_CMOS_SMF  static
+#  define BX_CMOS_THIS bx_cmos.
+#else
+#  define BX_CMOS_SMF
+#  define BX_CMOS_THIS this->
+#endif
+
+
+#if BX_SUPPORT_SID
+class cmos;
+#endif
+class bx_cmos_c : public logfunctions {
+public:
+  bx_cmos_c(void);
+  ~bx_cmos_c(void);
+
+#if BX_SUPPORT_SID
+  BX_CMOS_SMF void init(cmos *cmos_comp);
+#else
+  BX_CMOS_SMF void init(bx_devices_c *);
+#endif
+  BX_CMOS_SMF void checksum_cmos(void);
+  BX_CMOS_SMF void reset(void);
+
+  struct {
+    int     periodic_timer_index;
+    Bit32u  periodic_interval_usec;
+    int     one_second_timer_index;
+    time_t  timeval;
+    Bit8u   cmos_mem_address;
+
+    Bit8u   reg[BX_NUM_CMOS_REGS];
+    } s;  // state information
+
+private:
+#if BX_SUPPORT_SID
+  cmos *cmos_component;
+#else
+  bx_devices_c *devices;
+#endif
+
+  static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
+  static void   write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
+#if BX_SUPPORT_SID
+ public:
+#endif // BX_SUPPORT_SID
+#if !BX_USE_CMOS_SMF
+  Bit32u read(Bit32u address, unsigned io_len);
+  void   write(Bit32u address, Bit32u value, unsigned len);
+#endif
+
+#if BX_SUPPORT_SID
+  void periodic_timer_handler(void);
+  void one_second_timer_handler(void);
+  void load_cmos_image(std::string path);
+  void generate_cmos_values(void);
+#else
+public:
+  static void periodic_timer_handler(void *);
+  static void one_second_timer_handler(void *);
+#endif
+private:
+  BX_CMOS_SMF void update_clock(void);
+  BX_CMOS_SMF void CRA_change(void);
+  };
+
+
+#if BX_SUPPORT_SID
+extern bx_cmos_c bx_cmos;
+#endif
diff --git a/sid/component/bochs/cmos/sid-cmos-wrapper.cc b/sid/component/bochs/cmos/sid-cmos-wrapper.cc
new file mode 100644 (file)
index 0000000..5c6134b
--- /dev/null
@@ -0,0 +1,152 @@
+// sid-cmos-wrapper.cc - SID import of the bochs cmos component.  -*- C++ -*-
+
+// Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
+// This file is part of SID and is licensed under the GPL.
+// See the file COPYING.SID for conditions for redistribution.
+
+#include "sid-cmos-wrapper.h"
+
+cmos::cmos ()
+    : init_pin(this, & cmos::init),
+      reset_pin(this, & cmos::reset),
+      image_load_pin(this, & cmos::image_load),
+      periodic_timer_pin(this, & cmos::periodic_timer),
+      one_second_timer_pin(this, & cmos::one_second_timer),
+      register_0x10 (& this->register_bus, host_int_4(0x10), little_int_1(0xff),
+                     true, true, this, & cmos::set_register_0x10, & cmos::get_register_0x10),
+      register_0x14 (& this->register_bus, host_int_4(0x14), little_int_1(0xff),
+                     true, true, this, & cmos::set_register_0x14, & cmos::get_register_0x14),
+      ports_0x70_0x71_bus(this, & cmos::read_port_0x70_0x71, & cmos::write_port_0x70_0x71),
+      cmos_irq_number(8), use_host_time(true), start_time(917385580), use_image_file(false)
+{
+  add_pin("trigger-irq", & this->trigger_irq_pin);
+
+  add_pin("periodic-timer-control", & this->periodic_timer_control_pin);
+  add_pin("one-second-timer-control", & this->one_second_timer_control_pin);
+
+  add_pin("init", & this->init_pin);
+  add_pin("reset", & this->reset_pin);
+  add_pin("image-load", & this->image_load_pin);
+  add_pin("periodic-timer", & this->periodic_timer_pin);
+  add_pin("one-second-timer", & this->one_second_timer_pin);
+  add_pin("host-time", & this->host_time_pin);
+  add_pin("time-query", & this->time_query_pin);
+
+  add_bus("ports-0x70-0x71", & this->ports_0x70_0x71_bus);
+  add_bus("registers", & this->register_bus);
+
+  add_attribute("image-file", & this->image_file_path, "setting");
+  add_attribute("use-image-file?", & this->use_image_file, "setting");
+  add_attribute("irq-number", & this->cmos_irq_number, "setting");
+  add_attribute("use-host-time?", & this->use_host_time, "setting");
+  add_attribute("start-time", & this->start_time, "setting");
+}
+
+void
+cmos::init(host_int_4)
+{
+  bx_cmos.init(this);
+  bx_cmos.checksum_cmos();
+}
+
+void
+cmos::reset(host_int_4)
+{
+  bx_cmos.reset();
+}
+
+void
+cmos::image_load(host_int_4)
+{
+  if (use_image_file)
+    bx_cmos.load_cmos_image(image_file_path);
+  else
+    bx_cmos.generate_cmos_values();
+}
+
+void
+cmos::periodic_timer(host_int_4)
+{
+  bx_cmos.periodic_timer_handler();
+}
+
+void
+cmos::one_second_timer(host_int_4)
+{
+  bx_cmos.one_second_timer_handler();
+}
+
+void
+cmos::drive_trigger_irq_pin(void)
+{
+  trigger_irq_pin.drive(cmos_irq_number);
+}
+
+void
+cmos::drive_periodic_timer_control_pin(host_int_4 value, bool regular)
+{
+  host_int_4 code = value | (regular << 31);
+
+  periodic_timer_control_pin.drive(code);
+}
+
+void
+cmos::drive_one_second_timer_control_pin(host_int_4 value, bool regular)
+{
+  host_int_4 code = value | (regular << 31);
+
+  one_second_timer_control_pin.drive(code);
+}
+
+host_int_4
+cmos::get_time(void)
+{
+  static host_int_4 host_start_time = host_time_pin.sense();
+
+  time_query_pin.drive(1);
+
+  if (use_host_time)
+    return host_time_pin.sense();
+  else
+    return start_time + (host_time_pin.sense() - host_start_time);
+}
+
+bus::status
+cmos::read_port_0x70_0x71 (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+{
+  addr += 0x70;
+  data = bx_cmos.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+cmos::write_port_0x70_0x71 (host_int_4 addr, little_int_1 mask, little_int_1 data)
+{
+  addr += 0x70;
+  bx_cmos.write(addr, data, 1);
+  return bus::ok;
+}
+
+void
+cmos::set_register_0x10 (little_int_1 data, little_int_1 mask)
+{
+  bx_cmos.s.reg[0x10] = data;
+}
+
+little_int_1
+cmos::get_register_0x10 (void)
+{
+  return bx_cmos.s.reg[0x10];
+}
+
+void
+cmos::set_register_0x14 (little_int_1 data, little_int_1 mask)
+{
+  bx_cmos.s.reg[0x14] = data;
+}
+
+little_int_1
+cmos::get_register_0x14 (void)
+{
+  return bx_cmos.s.reg[0x14];
+}
diff --git a/sid/component/bochs/cmos/sid-cmos-wrapper.h b/sid/component/bochs/cmos/sid-cmos-wrapper.h
new file mode 100644 (file)
index 0000000..f73720a
--- /dev/null
@@ -0,0 +1,97 @@
+// sid-cmos-wrapper.h - SID import of the bochs cmos component.  -*- C++ -*-
+
+// Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
+// This file is part of SID and is licensed under the GPL.
+// See the file COPYING.SID for conditions for redistribution.
+
+#ifndef SID_CMOS_WRAPPER_DEF_H
+#define SID_CMOS_WRAPPER_DEF_H 1
+
+#include <sidtypes.h>
+#include <sidcomp.h>
+#include <sidcomputil.h>
+#include <sidpinutil.h>
+#include <sidbusutil.h>
+#include <sidattrutil.h>
+#include <sidcpuutil.h>
+#include <sidpinattrutil.h>
+#include <sidmiscutil.h>
+#include <sidwatchutil.h>
+#include <sidso.h>
+
+#include "bochs.h"
+
+using sid::component;
+using sid::bus;
+using sid::host_int_4;
+using sid::little_int_1;
+using sidutil::callback_word_bus;
+using sidutil::callback_pin;
+using sidutil::output_pin;
+using sidutil::input_pin;
+using sidutil::callback_control_register;
+using sidutil::control_register_bus;
+using sidutil::fixed_control_register;
+
+class cmos : public sidutil::fixed_pin_map_component,
+             public sidutil::no_accessor_component,
+             public sidutil::fixed_attribute_map_component,
+             public sidutil::no_relation_component,
+             public sidutil::fixed_bus_map_component
+{
+public:
+  cmos();
+  ~cmos() throw() {};
+
+  void init(host_int_4);
+  void reset(host_int_4);
+  void image_load(host_int_4);
+  void periodic_timer(host_int_4);
+  void one_second_timer(host_int_4);
+
+  void drive_trigger_irq_pin(void);
+  void drive_periodic_timer_control_pin(host_int_4 value, bool regular);
+  void drive_one_second_timer_control_pin(host_int_4 value, bool regular);
+  host_int_4 get_time(void);
+
+protected:
+
+  callback_pin<cmos> init_pin;
+  callback_pin<cmos> reset_pin;
+  callback_pin<cmos> image_load_pin;
+  callback_pin<cmos> periodic_timer_pin;
+  callback_pin<cmos> one_second_timer_pin;
+  input_pin host_time_pin;
+
+  output_pin trigger_irq_pin;
+  output_pin periodic_timer_control_pin;
+  output_pin one_second_timer_control_pin;
+  output_pin time_query_pin;
+
+  bus::status read_port_0x70_0x71 (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x70_0x71 (host_int_4 addr, little_int_1 mask, little_int_1 data);
+
+  callback_word_bus<cmos, little_int_1> ports_0x70_0x71_bus;
+
+  // register_bus must be declared before the control_registers
+  // because member constructors are called in the order in which
+  // they're declared
+  control_register_bus<little_int_1> register_bus;
+
+  void set_register_0x10 (little_int_1 data, little_int_1 mask);
+  little_int_1 get_register_0x10 (void);
+
+  void set_register_0x14 (little_int_1 data, little_int_1 mask);
+  little_int_1 get_register_0x14 (void);
+
+  callback_control_register<little_int_1, cmos> register_0x10;
+  callback_control_register<little_int_1, cmos> register_0x14;
+
+  bool use_image_file;
+  std::string image_file_path;
+  host_int_4 cmos_irq_number;
+  bool use_host_time;
+  host_int_4 start_time;
+  bx_cmos_c bx_cmos;
+};
+#endif // SID_CMOS_WRAPPER_DEF_H
index 700a1da..e32d23c 100644 (file)
 #include <vector>
 #include <string>
 
-#include "x86.h"
+#include "sid-x86-cpu-wrapper.h"
 #include "sid-vga-wrapper.h"
 #if HAVE_X11_XOS_H
 #include "x-gui.h"
 #endif
+#include "sid-cmos-wrapper.h"
+#include "sid-dma-wrapper.h"
 #include "sid-keyboard-wrapper.h"
+#include "sid-pic-wrapper.h"
+#include "sid-pit-wrapper.h"
+#include "sid-floppy-wrapper.h"
+#include "sid-unmapped-wrapper.h"
 
 using std::vector;
 using std::string;
@@ -44,7 +50,13 @@ compX86ListTypes()
 #if HAVE_X11_XOS_H
   types.push_back("sid-io-vga-x");
 #endif
+  types.push_back("hw-cmos-x86");
+  types.push_back("hw-dma-x86");
   types.push_back("hw-input-keyboard");
+  types.push_back("hw-interrupt-x86");
+  types.push_back("hw-timer-x86");
+  types.push_back("hw-disk-floppy");
+  types.push_back("hw-bochs-misc");
 #endif
 
   return types;
@@ -67,8 +79,20 @@ compX86Create(const string& typeName)
       else if(typeName == "sid-io-vga-x")
         return new x_gui();
 #endif
+      else if(typeName == "hw-cmos-x86")
+        return new cmos();
+      else if(typeName == "hw-dma-x86")
+        return new dma();
       else if(typeName == "hw-input-keyboard")
         return new keyboard();
+      else if(typeName == "hw-interrupt-x86")
+        return new pic();
+      else if(typeName == "hw-timer-x86")
+        return new pit();
+      else if(typeName == "hw-disk-floppy")
+        return new floppy();
+      else if(typeName == "hw-bochs-misc")
+        return new unmapped();
     }
   catch (...) { }
 #endif
@@ -101,12 +125,48 @@ compX86Delete(component* c)
       return;
     }
 #endif
-  keyboard *d4 = dynamic_cast<keyboard *>(c);
+  cmos *d4 = dynamic_cast<cmos *>(c);
   if(d4)
     {
       delete d4;
       return;
     }
+  dma *d5 = dynamic_cast<dma *>(c);
+  if(d5)
+    {
+      delete d5;
+      return;
+    }
+  keyboard *d6 = dynamic_cast<keyboard *>(c);
+  if(d6)
+    {
+      delete d6;
+      return;
+    }
+  pic *d7 = dynamic_cast<pic *>(c);
+  if(d7)
+    {
+      delete d7;
+      return;
+    }
+  pit *d8 = dynamic_cast<pit *>(c);
+  if(d8)
+    {
+      delete d8;
+      return;
+    }
+  floppy *d9 = dynamic_cast<floppy *>(c);
+  if(d9)
+    {
+      delete d9;
+      return;
+    }
+  unmapped *d10 = dynamic_cast<unmapped *>(c);
+  if(d10)
+    {
+      delete d10;
+      return;
+    }
 #endif
 }
 
index 7c5e3f9..4d29902 100644 (file)
@@ -86,7 +86,7 @@
 //   1 = use settable A20 line. (normal)
 //   0 = A20 is like the rest of the address lines
 
-#define BX_SUPPORT_A20 
+#define BX_SUPPORT_A20 1
 
 // Processor Instructions Per Second
 // To find out what value to use for the 'ips' directive
 // you're environment doesn't require it, you can change
 // it to 0.
 
-#define BX_DMA_FLOPPY_IO 0
+#define BX_DMA_FLOPPY_IO 1
 
 
 // Default number of Megs of memory to emulate.  The
 // then set this to 0.
 //
 
-#define BX_SUPPORT_TASKING    0
+#define BX_SUPPORT_TASKING    1
 
 
 // CPU level emulation.  Default level is set in
 //       multiple instances of a device class
 
 #define BX_USE_HD_SMF   1  // Hard drive
-#define BX_USE_CMOS_SMF 1  // CMOS
-#define BX_USE_DMA_SMF  1  // DMA
-#define BX_USE_FD_SMF   1  // Floppy
+#define BX_USE_CMOS_SMF 0  // CMOS
+#define BX_USE_DMA_SMF  0  // DMA
+#define BX_USE_FD_SMF   0  // Floppy
 #define BX_USE_KEY_SMF  0  // Keyboard
 #define BX_USE_PAR_SMF  1  // Parallel
-#define BX_USE_PIC_SMF  1  // PIC
-#define BX_USE_PIT_SMF  1  // PIT
+#define BX_USE_PIC_SMF  0  // PIC
+#define BX_USE_PIT_SMF  0  // PIT
 #define BX_USE_SER_SMF  1  // Serial
-#define BX_USE_UM_SMF   1  // Unmapped
+#define BX_USE_UM_SMF   0  // Unmapped
 #define BX_USE_VGA_SMF  0  // VGA
 #define BX_USE_SB16_SMF 1  // Sound (SB 16)
 #define BX_USE_DEV_SMF  1  // System Devices (port92)
index 9ba6785..e13ddaf 100755 (executable)
@@ -5673,7 +5673,7 @@ esac
 
 
 echo $ac_n "checking ARM family support""... $ac_c" 1>&6
-echo "configure:5677: checking ARM family support" >&5
+echo "configure:5734: checking ARM family support" >&5
 
 
 
@@ -5687,7 +5687,7 @@ fi
 echo "$ac_t""$sidtarget_arm" 1>&6
 
 echo $ac_n "checking X86 family support""... $ac_c" 1>&6
-echo "configure:5691: checking X86 family support" >&5
+echo "configure:5748: checking X86 family support" >&5
 
 
 
@@ -5701,7 +5701,7 @@ fi
 echo "$ac_t""$sidtarget_x86" 1>&6
 
 echo $ac_n "checking MIPS family support""... $ac_c" 1>&6
-echo "configure:5705: checking MIPS family support" >&5
+echo "configure:5778: checking MIPS family support" >&5
 
 
 
@@ -5715,7 +5715,7 @@ fi
 echo "$ac_t""$sidtarget_mips" 1>&6
 
 echo $ac_n "checking M32R family support""... $ac_c" 1>&6
-echo "configure:5719: checking M32R family support" >&5
+echo "configure:5792: checking M32R family support" >&5
 
 
 
@@ -5729,7 +5729,7 @@ fi
 echo "$ac_t""$sidtarget_m32r" 1>&6
 
 echo $ac_n "checking M68K family support""... $ac_c" 1>&6
-echo "configure:5733: checking M68K family support" >&5
+echo "configure:5806: checking M68K family support" >&5
 
 
 
@@ -5743,7 +5743,7 @@ fi
 echo "$ac_t""$sidtarget_m68k" 1>&6
 
 echo $ac_n "checking PPC family support""... $ac_c" 1>&6
-echo "configure:5747: checking PPC family support" >&5
+echo "configure:5836: checking PPC family support" >&5
 
 
 
@@ -5757,7 +5757,7 @@ fi
 echo "$ac_t""$sidtarget_ppc" 1>&6
 
 echo $ac_n "checking Sanyo Xstormy16 family support""... $ac_c" 1>&6
-echo "configure:5761: checking Sanyo Xstormy16 family support" >&5
+echo "configure:5927: checking Sanyo Xstormy16 family support" >&5
 
 
 
@@ -5873,7 +5873,7 @@ done
 ac_given_srcdir=$srcdir
 ac_given_INSTALL="$INSTALL"
 
-trap 'rm -fr `echo "Makefile vga/Makefile gui/Makefile keyboard/Makefile cpu/Makefile memory/Makefile fpu/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+trap 'rm -fr `echo "Makefile vga/Makefile gui/Makefile keyboard/Makefile pic/Makefile pit/Makefile cmos/Makefile dma/Makefile floppy/Makefile unmapped/Makefile cpu/Makefile cpu/memory/Makefile cpu/fpu/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
 EOF
 cat >> $CONFIG_STATUS <<EOF
 
@@ -6051,7 +6051,7 @@ EOF
 
 cat >> $CONFIG_STATUS <<EOF
 
-CONFIG_FILES=\${CONFIG_FILES-"Makefile vga/Makefile gui/Makefile keyboard/Makefile cpu/Makefile memory/Makefile fpu/Makefile"}
+CONFIG_FILES=\${CONFIG_FILES-"Makefile vga/Makefile gui/Makefile keyboard/Makefile pic/Makefile pit/Makefile cmos/Makefile dma/Makefile floppy/Makefile unmapped/Makefile cpu/Makefile cpu/memory/Makefile cpu/fpu/Makefile"}
 EOF
 cat >> $CONFIG_STATUS <<\EOF
 for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
index bec25db..1daef29 100644 (file)
@@ -928,4 +928,4 @@ AC_PATH_PROG(TAR, tar)
 dnl Perform --target/--enable-targets processing.
 CY_SIDTARGET_CHECK
 
-AC_OUTPUT(Makefile vga/Makefile gui/Makefile keyboard/Makefile cpu/Makefile memory/Makefile fpu/Makefile)
+AC_OUTPUT(Makefile vga/Makefile gui/Makefile keyboard/Makefile pic/Makefile pit/Makefile cmos/Makefile dma/Makefile floppy/Makefile unmapped/Makefile cpu/Makefile cpu/memory/Makefile cpu/fpu/Makefile)
index cf73d0a..ee8f29c 100644 (file)
@@ -2,11 +2,15 @@
 
 AUTOMAKE_OPTIONS = foreign
 
-##         sid/include in build tree       bochs/cpu   component/bochs sid/include in src tree     bochs/memory
-INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../memory -I$(srcdir)/../debug
+SUBDIRS = memory fpu
 
-noinst_LTLIBRARIES = libcpu.la
+SUBLIBS = memory/libmemory.la fpu/libfpu.la
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/memory
 
-libcpu_la_SOURCES =  exception-sid.cc cpu.cc cpu.h cpu-sid.h cpu-sid.cc init-sid.cc state_file.h main-hack.cc x86.cc access.cc ctrl_xfer8.cc flag_ctrl.cc mult32.cc shift16.cc ctrl_xfer_pro.cc flag_ctrl_pro.cc mult8.cc shift32.cc arith16.cc data_xfer16.cc init.cc paging.cc shift8.cc arith32.cc data_xfer32.cc io.cc proc_ctrl.cc soft_int.cc soft_int-sid.cc arith8.cc data_xfer8.cc io_pro.cc protect_ctrl.cc stack16.cc bcd.cc debugstuff.cc debugstuff-sid.cc lazy_flags.cc protect_ctrl_pro.cc stack32.cc bit.cc decode16.cc logical16.cc resolve16.cc stack_pro.cc decode32.cc logical32.cc resolve32.cc string.cc ctrl_xfer16.cc exception.cc logical8.cc segment_ctrl.cc tasking.cc ctrl_xfer32.cc ctrl_xfer32-sid.cc fetchdecode.cc fetchdecode-sid.cc mult16.cc segment_ctrl_pro.cc vm8086.cc lazy_flags.h x86.h x86-memory-modes.cc
+noinst_LTLIBRARIES = libcpu.la
 
+libcpu_la_SOURCES =  cpu.cc cpu.h state_file.h main-hack.cc sid-x86-cpu-wrapper.cc access.cc ctrl_xfer8.cc flag_ctrl.cc mult32.cc shift16.cc ctrl_xfer_pro.cc flag_ctrl_pro.cc mult8.cc shift32.cc arith16.cc data_xfer16.cc init.cc paging.cc shift8.cc arith32.cc data_xfer32.cc io.cc proc_ctrl.cc soft_int.cc arith8.cc data_xfer8.cc io_pro.cc protect_ctrl.cc stack16.cc bcd.cc debugstuff.cc lazy_flags.cc protect_ctrl_pro.cc stack32.cc bit.cc decode16.cc logical16.cc resolve16.cc stack_pro.cc decode32.cc logical32.cc resolve32.cc string.cc ctrl_xfer16.cc exception.cc logical8.cc segment_ctrl.cc tasking.cc ctrl_xfer32.cc fetchdecode.cc mult16.cc segment_ctrl_pro.cc vm8086.cc lazy_flags.h sid-x86-cpu-wrapper.h sid-x86-memory-modes.cc
 libcpu_la_LDFLAGS = -no-undefined
+libcpu_la_LIBADD = $(SUBLIBS)
+libcpu_la_DEPENDENCIES = $(SUBLIBS)
index 3121600..abee246 100644 (file)
@@ -129,13 +129,18 @@ sidtarget_xstormy16 = @sidtarget_xstormy16@
 
 AUTOMAKE_OPTIONS = foreign
 
-INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../memory -I$(srcdir)/../debug
+SUBDIRS = memory fpu
 
-noinst_LTLIBRARIES = libcpu.la
+SUBLIBS = memory/libmemory.la fpu/libfpu.la
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/memory
 
-libcpu_la_SOURCES = exception-sid.cc cpu.cc cpu.h cpu-sid.h cpu-sid.cc init-sid.cc state_file.h main-hack.cc x86.cc access.cc ctrl_xfer8.cc flag_ctrl.cc mult32.cc shift16.cc ctrl_xfer_pro.cc flag_ctrl_pro.cc mult8.cc shift32.cc arith16.cc data_xfer16.cc init.cc paging.cc shift8.cc arith32.cc data_xfer32.cc io.cc proc_ctrl.cc soft_int.cc soft_int-sid.cc arith8.cc data_xfer8.cc io_pro.cc protect_ctrl.cc stack16.cc bcd.cc debugstuff.cc debugstuff-sid.cc lazy_flags.cc protect_ctrl_pro.cc stack32.cc bit.cc decode16.cc logical16.cc resolve16.cc stack_pro.cc decode32.cc logical32.cc resolve32.cc string.cc ctrl_xfer16.cc exception.cc logical8.cc segment_ctrl.cc tasking.cc ctrl_xfer32.cc ctrl_xfer32-sid.cc fetchdecode.cc fetchdecode-sid.cc mult16.cc segment_ctrl_pro.cc vm8086.cc lazy_flags.h x86.h x86-memory-modes.cc
+noinst_LTLIBRARIES = libcpu.la
 
+libcpu_la_SOURCES = cpu.cc cpu.h state_file.h main-hack.cc sid-x86-cpu-wrapper.cc access.cc ctrl_xfer8.cc flag_ctrl.cc mult32.cc shift16.cc ctrl_xfer_pro.cc flag_ctrl_pro.cc mult8.cc shift32.cc arith16.cc data_xfer16.cc init.cc paging.cc shift8.cc arith32.cc data_xfer32.cc io.cc proc_ctrl.cc soft_int.cc arith8.cc data_xfer8.cc io_pro.cc protect_ctrl.cc stack16.cc bcd.cc debugstuff.cc lazy_flags.cc protect_ctrl_pro.cc stack32.cc bit.cc decode16.cc logical16.cc resolve16.cc stack_pro.cc decode32.cc logical32.cc resolve32.cc string.cc ctrl_xfer16.cc exception.cc logical8.cc segment_ctrl.cc tasking.cc ctrl_xfer32.cc fetchdecode.cc mult16.cc segment_ctrl_pro.cc vm8086.cc lazy_flags.h sid-x86-cpu-wrapper.h sid-x86-memory-modes.cc
 libcpu_la_LDFLAGS = -no-undefined
+libcpu_la_LIBADD = $(SUBLIBS)
+libcpu_la_DEPENDENCIES = $(SUBLIBS)
 mkinstalldirs = $(SHELL) $(top_srcdir)/../../config/mkinstalldirs
 CONFIG_HEADER = ../config.h
 CONFIG_CLEAN_FILES = 
@@ -150,19 +155,17 @@ X_CFLAGS = @X_CFLAGS@
 X_LIBS = @X_LIBS@
 X_EXTRA_LIBS = @X_EXTRA_LIBS@
 X_PRE_LIBS = @X_PRE_LIBS@
-libcpu_la_LIBADD = 
-libcpu_la_OBJECTS =  exception-sid.lo cpu.lo cpu-sid.lo init-sid.lo \
-main-hack.lo x86.lo access.lo ctrl_xfer8.lo flag_ctrl.lo mult32.lo \
-shift16.lo ctrl_xfer_pro.lo flag_ctrl_pro.lo mult8.lo shift32.lo \
-arith16.lo data_xfer16.lo init.lo paging.lo shift8.lo arith32.lo \
-data_xfer32.lo io.lo proc_ctrl.lo soft_int.lo soft_int-sid.lo arith8.lo \
-data_xfer8.lo io_pro.lo protect_ctrl.lo stack16.lo bcd.lo debugstuff.lo \
-debugstuff-sid.lo lazy_flags.lo protect_ctrl_pro.lo stack32.lo bit.lo \
-decode16.lo logical16.lo resolve16.lo stack_pro.lo decode32.lo \
-logical32.lo resolve32.lo string.lo ctrl_xfer16.lo exception.lo \
-logical8.lo segment_ctrl.lo tasking.lo ctrl_xfer32.lo \
-ctrl_xfer32-sid.lo fetchdecode.lo fetchdecode-sid.lo mult16.lo \
-segment_ctrl_pro.lo vm8086.lo x86-memory-modes.lo
+libcpu_la_OBJECTS =  cpu.lo main-hack.lo sid-x86-cpu-wrapper.lo \
+access.lo ctrl_xfer8.lo flag_ctrl.lo mult32.lo shift16.lo \
+ctrl_xfer_pro.lo flag_ctrl_pro.lo mult8.lo shift32.lo arith16.lo \
+data_xfer16.lo init.lo paging.lo shift8.lo arith32.lo data_xfer32.lo \
+io.lo proc_ctrl.lo soft_int.lo arith8.lo data_xfer8.lo io_pro.lo \
+protect_ctrl.lo stack16.lo bcd.lo debugstuff.lo lazy_flags.lo \
+protect_ctrl_pro.lo stack32.lo bit.lo decode16.lo logical16.lo \
+resolve16.lo stack_pro.lo decode32.lo logical32.lo resolve32.lo \
+string.lo ctrl_xfer16.lo exception.lo logical8.lo segment_ctrl.lo \
+tasking.lo ctrl_xfer32.lo fetchdecode.lo mult16.lo segment_ctrl_pro.lo \
+vm8086.lo sid-x86-memory-modes.lo
 CXXFLAGS = @CXXFLAGS@
 CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
 LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@@ -179,22 +182,20 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
 GZIP_ENV = --best
 DEP_FILES =  .deps/access.P .deps/arith16.P .deps/arith32.P \
-.deps/arith8.P .deps/bcd.P .deps/bit.P .deps/cpu-sid.P .deps/cpu.P \
-.deps/ctrl_xfer16.P .deps/ctrl_xfer32-sid.P .deps/ctrl_xfer32.P \
-.deps/ctrl_xfer8.P .deps/ctrl_xfer_pro.P .deps/data_xfer16.P \
-.deps/data_xfer32.P .deps/data_xfer8.P .deps/debugstuff-sid.P \
-.deps/debugstuff.P .deps/decode16.P .deps/decode32.P \
-.deps/exception-sid.P .deps/exception.P .deps/fetchdecode-sid.P \
+.deps/arith8.P .deps/bcd.P .deps/bit.P .deps/cpu.P .deps/ctrl_xfer16.P \
+.deps/ctrl_xfer32.P .deps/ctrl_xfer8.P .deps/ctrl_xfer_pro.P \
+.deps/data_xfer16.P .deps/data_xfer32.P .deps/data_xfer8.P \
+.deps/debugstuff.P .deps/decode16.P .deps/decode32.P .deps/exception.P \
 .deps/fetchdecode.P .deps/flag_ctrl.P .deps/flag_ctrl_pro.P \
-.deps/init-sid.P .deps/init.P .deps/io.P .deps/io_pro.P \
-.deps/lazy_flags.P .deps/logical16.P .deps/logical32.P .deps/logical8.P \
-.deps/main-hack.P .deps/mult16.P .deps/mult32.P .deps/mult8.P \
-.deps/paging.P .deps/proc_ctrl.P .deps/protect_ctrl.P \
-.deps/protect_ctrl_pro.P .deps/resolve16.P .deps/resolve32.P \
-.deps/segment_ctrl.P .deps/segment_ctrl_pro.P .deps/shift16.P \
-.deps/shift32.P .deps/shift8.P .deps/soft_int-sid.P .deps/soft_int.P \
-.deps/stack16.P .deps/stack32.P .deps/stack_pro.P .deps/string.P \
-.deps/tasking.P .deps/vm8086.P .deps/x86-memory-modes.P .deps/x86.P
+.deps/init.P .deps/io.P .deps/io_pro.P .deps/lazy_flags.P \
+.deps/logical16.P .deps/logical32.P .deps/logical8.P .deps/main-hack.P \
+.deps/mult16.P .deps/mult32.P .deps/mult8.P .deps/paging.P \
+.deps/proc_ctrl.P .deps/protect_ctrl.P .deps/protect_ctrl_pro.P \
+.deps/resolve16.P .deps/resolve32.P .deps/segment_ctrl.P \
+.deps/segment_ctrl_pro.P .deps/shift16.P .deps/shift32.P .deps/shift8.P \
+.deps/sid-x86-cpu-wrapper.P .deps/sid-x86-memory-modes.P \
+.deps/soft_int.P .deps/stack16.P .deps/stack32.P .deps/stack_pro.P \
+.deps/string.P .deps/tasking.P .deps/vm8086.P
 SOURCES = $(libcpu_la_SOURCES)
 OBJECTS = $(libcpu_la_OBJECTS)
 
@@ -257,6 +258,61 @@ libcpu.la: $(libcpu_la_OBJECTS) $(libcpu_la_DEPENDENCIES)
 .cc.lo:
        $(LTCXXCOMPILE) -c $<
 
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+
+@SET_MAKE@
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive  \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+         rev="$$subdir $$rev"; \
+         test "$$subdir" = "." && dot_seen=yes; \
+       done; \
+       test "$$dot_seen" = "no" && rev=". $$rev"; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+
 tags: TAGS
 
 ID: $(HEADERS) $(SOURCES) $(LISP)
@@ -267,9 +323,14 @@ ID: $(HEADERS) $(SOURCES) $(LISP)
        here=`pwd` && cd $(srcdir) \
          && mkid -f$$here/ID $$unique $(LISP)
 
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
        tags=; \
        here=`pwd`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+   if test "$$subdir" = .; then :; else \
+           test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+   fi; \
+       done; \
        list='$(SOURCES) $(HEADERS)'; \
        unique=`for i in $$list; do echo $$i; done | \
          awk '    { files[$$0] = 1; } \
@@ -306,6 +367,16 @@ distdir: $(DISTFILES)
            || cp -p $$d/$$file $(distdir)/$$file || :; \
          fi; \
        done
+       for subdir in $(SUBDIRS); do \
+         if test "$$subdir" = .; then :; else \
+           test -d $(distdir)/$$subdir \
+           || mkdir $(distdir)/$$subdir \
+           || exit 1; \
+           chmod 777 $(distdir)/$$subdir; \
+           (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \
+             || exit 1; \
+         fi; \
+       done
 
 DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
 
@@ -358,29 +429,30 @@ maintainer-clean-depend:
            >> .deps/$(*F).P; \
        rm -f .deps/$(*F).pp
 info-am:
-info: info-am
+info: info-recursive
 dvi-am:
-dvi: dvi-am
+dvi: dvi-recursive
 check-am: all-am
-check: check-am
+check: check-recursive
 installcheck-am:
-installcheck: installcheck-am
+installcheck: installcheck-recursive
 install-exec-am:
-install-exec: install-exec-am
+install-exec: install-exec-recursive
 
 install-data-am:
-install-data: install-data-am
+install-data: install-data-recursive
 
 install-am: all-am
        @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
+install: install-recursive
 uninstall-am:
-uninstall: uninstall-am
+uninstall: uninstall-recursive
 all-am: Makefile $(LTLIBRARIES)
-all-redirect: all-am
+all-redirect: all-recursive
 install-strip:
        $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
-installdirs:
+installdirs: installdirs-recursive
+installdirs-am:
 
 
 mostlyclean-generic:
@@ -396,19 +468,19 @@ mostlyclean-am:  mostlyclean-noinstLTLIBRARIES mostlyclean-compile \
                mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
                mostlyclean-generic
 
-mostlyclean: mostlyclean-am
+mostlyclean: mostlyclean-recursive
 
 clean-am:  clean-noinstLTLIBRARIES clean-compile clean-libtool \
                clean-tags clean-depend clean-generic mostlyclean-am
 
-clean: clean-am
+clean: clean-recursive
 
 distclean-am:  distclean-noinstLTLIBRARIES distclean-compile \
                distclean-libtool distclean-tags distclean-depend \
                distclean-generic clean-am
        -rm -f libtool
 
-distclean: distclean-am
+distclean: distclean-recursive
 
 maintainer-clean-am:  maintainer-clean-noinstLTLIBRARIES \
                maintainer-clean-compile maintainer-clean-libtool \
@@ -417,19 +489,24 @@ maintainer-clean-am:  maintainer-clean-noinstLTLIBRARIES \
        @echo "This command is intended for maintainers to use;"
        @echo "it deletes files that may require special tools to rebuild."
 
-maintainer-clean: maintainer-clean-am
+maintainer-clean: maintainer-clean-recursive
 
 .PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \
 clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \
 mostlyclean-compile distclean-compile clean-compile \
 maintainer-clean-compile mostlyclean-libtool distclean-libtool \
-clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+clean-libtool maintainer-clean-libtool install-data-recursive \
+uninstall-data-recursive install-exec-recursive \
+uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
+all-recursive check-recursive installcheck-recursive info-recursive \
+dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
 distclean-tags clean-tags maintainer-clean-tags distdir \
 mostlyclean-depend distclean-depend clean-depend \
 maintainer-clean-depend info-am info dvi-am dvi check check-am \
 installcheck-am installcheck install-exec-am install-exec \
 install-data-am install-data install-am install uninstall-am uninstall \
-all-redirect all-am all installdirs mostlyclean-generic \
+all-redirect all-am all installdirs-am installdirs mostlyclean-generic \
 distclean-generic clean-generic maintainer-clean-generic clean \
 mostlyclean distclean maintainer-clean
 
diff --git a/sid/component/bochs/cpu/cpu-sid.cc b/sid/component/bochs/cpu/cpu-sid.cc
deleted file mode 100644 (file)
index f8b1b21..0000000
+++ /dev/null
@@ -1,582 +0,0 @@
-//  cpu-sid.cc - override some important bx_cpu_c member functions. -*- C++ -*-
-//
-//  Copyright (C) 2001 Red Hat.
-//
-//  Copyright (C) 2001  MandrakeSoft S.A.
-//
-//    MandrakeSoft S.A.
-//    43, rue d'Aboukir
-//    75002 Paris - France
-//    http://www.linux-mandrake.com/
-//    http://www.mandrakesoft.com/
-//
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-#include "bochs.h"
-#define LOG_THIS BX_CPU_THIS_PTR
-
-static Bit8u *sid_prefetch_data = NULL;
-
-void
-sid_cpu_c::cpu_loop(Bit32s max_instr_count)
-{
-  unsigned ret;
-  BxInstruction_t i;
-  unsigned maxisize;
-  Bit8u *fetch_ptr;
-  Boolean is_32;
-
-  static int num_loops = 0;
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR break_point = 0;
-#ifdef MAGIC_BREAKPOINT
-  BX_CPU_THIS_PTR magic_break = 0;
-#endif // MAGIC_BREAKPOINT
-  BX_CPU_THIS_PTR stop_reason = STOP_NO_REASON;
-#endif // BX_DEBUGGER
-
-  (void) setjmp( BX_CPU_THIS_PTR jmp_buf_env );
-
-  BX_CPU_THIS_PTR prev_eip = EIP; // commit new EIP
-  BX_CPU_THIS_PTR prev_esp = ESP; // commit new ESP
-
-#if X86_CPU_DEBUG
-    printf("At top of main loop, EIP = %p, ESP = %p\n", EIP, ESP);
-#endif
-    
-main_cpu_loop:  
-
-  // ???
-  BX_CPU_THIS_PTR EXT = 0;
-  BX_CPU_THIS_PTR errorno = 0;
-
-  // First check on events which occurred for previous instructions
-  // (traps) and ones which are asynchronous to the CPU
-  // (hardware interrupts).
-  if (BX_CPU_THIS_PTR async_event)
-    goto handle_async_event;
-
-async_events_processed:
-
-  // Now we can handle things which are synchronous to instruction
-  // execution.
-  if (BX_CPU_THIS_PTR eflags.rf) {
-    BX_CPU_THIS_PTR eflags.rf = 0;
-    }
-#if BX_X86_DEBUGGER
-  else {
-    // only bother comparing if any breakpoints enabled
-    if ( BX_CPU_THIS_PTR dr7 & 0x000000ff ) {
-      Bit32u iaddr =
-        BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base +
-        BX_CPU_THIS_PTR prev_eip;
-      Bit32u dr6_bits;
-      if ( (dr6_bits = hwdebug_compare(iaddr, 1, BX_HWDebugInstruction,
-                                       BX_HWDebugInstruction)) ) {
-        // Add to the list of debug events thus far.
-        BX_CPU_THIS_PTR debug_trap |= dr6_bits;
-        BX_CPU_THIS_PTR async_event = 1;
-        // If debug events are not inhibited on this boundary,
-        // fire off a debug fault.  Otherwise handle it on the next
-        // boundary. (becomes a trap)
-        if ( !(BX_CPU_THIS_PTR inhibit_mask & BX_INHIBIT_DEBUG) ) {
-          // Commit debug events to DR6
-          BX_CPU_THIS_PTR dr6 = BX_CPU_THIS_PTR debug_trap;
-          exception(BX_DB_EXCEPTION, 0, 0); // no error, not interrupt
-          }
-        }
-      }
-    }
-#endif
-
-  // We have ignored processing of external interrupts and
-  // debug events on this boundary.  Reset the mask so they
-  // will be processed on the next boundary.
-  BX_CPU_THIS_PTR inhibit_mask = 0;
-
-
-#if BX_DEBUGGER
-  {
-  Bit32u debug_eip = BX_CPU_THIS_PTR prev_eip;
-  if ( dbg_is_begin_instr_bpoint(
-         BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
-         debug_eip,
-         BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base + debug_eip,
-         BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b) ) {
-    return;
-    }
-  }
-#endif  // #if BX_DEBUGGER
-
-
-  is_32 = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b;
-
-  if (BX_CPU_THIS_PTR bytesleft == 0) {
-      prefetch();
-    }
-  fetch_ptr = BX_CPU_THIS_PTR fetch_ptr;
-
-  maxisize = 16;
-  if (BX_CPU_THIS_PTR bytesleft < 16)
-    maxisize = BX_CPU_THIS_PTR bytesleft;
-
-  ret = FetchDecode(fetch_ptr, &i, maxisize, is_32);
-
-#if X86_CPU_DEBUG
-  printf("FetchDecode returned: %d\n", ret);
-  printf("Current opcode: %p, with length: %d, EIP = %p\n", i.b1, i.ilen, this->eip);
-#endif
-  
-  if (ret) {
-    if (i.ResolveModrm) {
-      // call method on sid_cpu_c object
-      BX_CPU_CALL_METHOD_FROM_SID(i.ResolveModrm, (&i));
-      }
-    BX_CPU_THIS_PTR fetch_ptr += i.ilen;
-    BX_CPU_THIS_PTR bytesleft -= i.ilen;
-fetch_decode_OK:
-
-    if (i.rep_used && (i.attr & BxRepeatable)) {
-repeat_loop:
-      if (i.attr & BxRepeatableZF) {
-        if (i.as_32) {
-          if (ECX != 0) {
-            BX_CPU_CALL_METHOD_FROM_SID(i.execute_sid, (&i));
-            ECX -= 1;
-            }
-          if ((i.rep_used==0xf3) && (get_ZF()==0)) goto repeat_done;
-          if ((i.rep_used==0xf2) && (get_ZF()!=0)) goto repeat_done;
-          if (ECX == 0) goto repeat_done;
-          goto repeat_not_done;
-          }
-        else {
-          if (CX != 0) {
-            BX_CPU_CALL_METHOD_FROM_SID(i.execute_sid, (&i));
-            CX -= 1;
-            }
-          if ((i.rep_used==0xf3) && (get_ZF()==0)) goto repeat_done;
-          if ((i.rep_used==0xf2) && (get_ZF()!=0)) goto repeat_done;
-          if (CX == 0) goto repeat_done;
-          goto repeat_not_done;
-          }
-        }
-      else { // normal repeat, no concern for ZF
-        if (i.as_32) {
-          if (ECX != 0) {
-            BX_CPU_CALL_METHOD_FROM_SID(i.execute_sid, (&i));
-            ECX -= 1;
-            }
-          if (ECX == 0) goto repeat_done;
-          goto repeat_not_done;
-          }
-        else { // 16bit addrsize
-          if (CX != 0) {
-            BX_CPU_CALL_METHOD_FROM_SID(i.execute_sid, (&i));
-            CX -= 1;
-            }
-          if (CX == 0) goto repeat_done;
-          goto repeat_not_done;
-          }
-        }
-      // shouldn't get here from above
-repeat_not_done:
-#ifdef REGISTER_IADDR
-      REGISTER_IADDR(BX_CPU_THIS_PTR eip + BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.base);
-#endif
-
-#if BX_DEBUGGER == 0
-      if (BX_CPU_THIS_PTR async_event) {
-        invalidate_prefetch_q();
-        goto debugger_check;
-      }
-      goto repeat_loop;
-#else  /* if BX_DEBUGGER == 1 */
-      invalidate_prefetch_q();
-      goto debugger_check;
-#endif
-
-
-repeat_done:
-      BX_CPU_THIS_PTR eip += i.ilen;
-    }
-    else {
-      // non repeating instruction
-      BX_CPU_THIS_PTR eip += i.ilen;
-      BX_CPU_CALL_METHOD_FROM_SID(i.execute_sid, (&i));
-    }
-
-    BX_CPU_THIS_PTR prev_eip = EIP; // commit new EIP
-    BX_CPU_THIS_PTR prev_esp = ESP; // commit new ESP
-#ifdef REGISTER_IADDR
-    REGISTER_IADDR(BX_CPU_THIS_PTR eip + BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.base);
-#endif
-
-debugger_check:
-
-    // The CHECK_MAX_INSTRUCTIONS macro allows cpu_loop to execute a few
-    // instructions and then return so that the other processors have a chance
-    // to run.  Every time sid pulses the step pin, cpu_loop executes once
-    CHECK_MAX_INSTRUCTIONS(max_instr_count);
-
-#if BX_DEBUGGER
-    // BW vm mode switch support is in dbg_is_begin_instr_bpoint
-    // note instr generating exceptions never reach this point.
-
-    // (mch) Read/write, time break point support
-    if (BX_CPU_THIS_PTR break_point) {
-         switch (BX_CPU_THIS_PTR break_point) {
-               case BREAK_POINT_TIME:
-                     BX_CPU_THIS_PTR info("[%lld] Caught time breakpoint\n", bx_pc_system.time_ticks());
-                     BX_CPU_THIS_PTR stop_reason = STOP_TIME_BREAK_POINT;
-                     return;
-               case BREAK_POINT_READ:
-                     BX_CPU_THIS_PTR info("[%lld] Caught read watch point\n", bx_pc_system.time_ticks());
-                     BX_CPU_THIS_PTR stop_reason = STOP_READ_WATCH_POINT;
-                     return;
-               case BREAK_POINT_WRITE:
-                     BX_CPU_THIS_PTR info("[%lld] Caught write watch point\n", bx_pc_system.time_ticks());
-                     BX_CPU_THIS_PTR stop_reason = STOP_WRITE_WATCH_POINT;
-                     return;
-               default:
-                     BX_PANIC(("Weird break point condition"));
-         }
-    }
-#ifdef MAGIC_BREAKPOINT
-    // (mch) Magic break point support
-    if (BX_CPU_THIS_PTR magic_break) {
-         if (bx_dbg.magic_break_enabled) {
-               BX_CPU_THIS_PTR info("Stopped on MAGIC BREAKPOINT\n");
-               BX_CPU_THIS_PTR stop_reason = STOP_MAGIC_BREAK_POINT;
-               return;
-         } else {
-               BX_CPU_THIS_PTR magic_break = 0;
-               BX_CPU_THIS_PTR stop_reason = STOP_NO_REASON;
-               BX_CPU_THIS_PTR info("Ignoring MAGIC BREAKPOINT\n");
-         }
-    }
-#endif
-    if (BX_CPU_THIS_PTR trace) {
-         BX_CPU_THIS_PTR stop_reason = STOP_TRACE;
-         return;
-    }
-#endif
-
-#if BX_DEBUGGER
-    {
-    Bit32u debug_eip = BX_CPU_THIS_PTR prev_eip;
-    if ( dbg_is_end_instr_bpoint(
-           BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
-           debug_eip,
-           BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base + debug_eip,
-           BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b) ) {
-      return;
-      }
-    }
-#endif  // #if BX_DEBUGGER
-    goto main_cpu_loop;
-  }
-  else {
-    unsigned remain, j;
-    static Bit8u FetchBuffer[16];
-    Bit8u *temp_ptr;
-
-    // read all leftover bytes in current page
-    for (j=0; j<BX_CPU_THIS_PTR bytesleft; j++) {
-      FetchBuffer[j] = *fetch_ptr++;
-      }
-
-    // get remaining bytes for prefetch in next page
-    // prefetch() needs eip current
-    BX_CPU_THIS_PTR eip += BX_CPU_THIS_PTR bytesleft;
-    remain = BX_CPU_THIS_PTR bytesleft;
-    prefetch();
-
-    if (BX_CPU_THIS_PTR bytesleft < 16) {
-      // make sure (bytesleft - remain) below doesn't go negative
-      BX_PANIC(("fetch_decode: bytesleft==0 after prefetch\n"));
-      }
-    temp_ptr = fetch_ptr = BX_CPU_THIS_PTR fetch_ptr;
-
-    // read leftover bytes in next page
-    for (; j<16; j++) {
-      FetchBuffer[j] = *temp_ptr++;
-      }
-
-    ret = FetchDecode(FetchBuffer, &i, 16, is_32);
-
-#if X86_CPU_DEBUG
-      printf("Just returned from prefetch...\n");
-      printf("FetchDecode returned: %d\n", ret);
-      printf("Current opcode: %p, with length: %d, EIP = %p, prev_eip = %p\n", i.b1, i.ilen, this->eip, this->prev_eip);
-#endif
-
-    if (ret==0)
-      BX_PANIC(("fetchdecode: cross boundary: ret==0\n"));
-    if (i.ResolveModrm) {
-      BX_CPU_CALL_METHOD_FROM_SID(i.ResolveModrm, (&i));
-      }
-    remain = i.ilen - remain;
-
-    // note: eip has already been advanced to beginning of page
-    BX_CPU_THIS_PTR fetch_ptr = fetch_ptr + remain;
-    BX_CPU_THIS_PTR bytesleft -= remain;
-    //BX_CPU_THIS_PTR eip += remain;
-    BX_CPU_THIS_PTR eip = BX_CPU_THIS_PTR prev_eip;
-    goto fetch_decode_OK;
-  }
-
-
-
-  //
-  // This area is where we process special conditions and events.
-  //
-
-handle_async_event:
-
-  if (BX_CPU_THIS_PTR debug_trap & 0x80000000) {
-    // I made up the bitmask above to mean HALT state.
-#if BX_SMP_PROCESSORS==1
-#else      /* BX_SMP_PROCESSORS != 1 */
-    // for multiprocessor simulation, even if this CPU is halted we still
-    // must give the others a chance to simulate.  If an interrupt has 
-    // arrived, then clear the HALT condition; otherwise just return from
-    // the CPU loop with stop_reason STOP_CPU_HALTED.
-    if (BX_CPU_THIS_PTR INTR && BX_CPU_THIS_PTR eflags.if_) {
-      // interrupt ends the HALT condition
-      BX_CPU_THIS_PTR debug_trap = 0; // clear traps for after resume
-      BX_CPU_THIS_PTR inhibit_mask = 0; // clear inhibits for after resume
-      //bx_printf ("halt condition has been cleared in %s\n", name);
-    } else {
-      // HALT condition remains, return so other CPUs have a chance
-#if BX_DEBUGGER
-      BX_CPU_THIS_PTR stop_reason = STOP_CPU_HALTED;
-#endif
-      return;
-    }
-#endif
-  }
-
-
-  // Priority 1: Hardware Reset and Machine Checks
-  //   RESET
-  //   Machine Check
-  // (bochs doesn't support these)
-
-  // Priority 2: Trap on Task Switch
-  //   T flag in TSS is set
-  if (BX_CPU_THIS_PTR debug_trap & 0x00008000) {
-    BX_CPU_THIS_PTR dr6 |= BX_CPU_THIS_PTR debug_trap;
-    exception(BX_DB_EXCEPTION, 0, 0); // no error, not interrupt
-    }
-
-  // Priority 3: External Hardware Interventions
-  //   FLUSH
-  //   STOPCLK
-  //   SMI
-  //   INIT
-  // (bochs doesn't support these)
-
-  // Priority 4: Traps on Previous Instruction
-  //   Breakpoints
-  //   Debug Trap Exceptions (TF flag set or data/IO breakpoint)
-  if ( BX_CPU_THIS_PTR debug_trap &&
-       !(BX_CPU_THIS_PTR inhibit_mask & BX_INHIBIT_DEBUG) ) {
-    // A trap may be inhibited on this boundary due to an instruction
-    // which loaded SS.  If so we clear the inhibit_mask below
-    // and don't execute this code until the next boundary.
-    // Commit debug events to DR6
-    BX_CPU_THIS_PTR dr6 |= BX_CPU_THIS_PTR debug_trap;
-    exception(BX_DB_EXCEPTION, 0, 0); // no error, not interrupt
-    }
-
-  // Priority 5: External Interrupts
-  //   NMI Interrupts
-  //   Maskable Hardware Interrupts
-  if (BX_CPU_THIS_PTR inhibit_mask & BX_INHIBIT_INTERRUPTS) {
-    // Processing external interrupts is inhibited on this
-    // boundary because of certain instructions like STI.
-    // inhibit_mask is cleared below, in which case we will have
-    // an opportunity to check interrupts on the next instruction
-    // boundary.
-    }
-  else if (BX_CPU_THIS_PTR INTR && BX_CPU_THIS_PTR eflags.if_ && BX_DBG_ASYNC_INTR) {
-    Bit8u vector;
-
-    // NOTE: similar code in ::take_irq()
-#if BX_SUPPORT_APIC
-    if (BX_CPU_THIS_PTR int_from_local_apic)
-      vector = BX_CPU_THIS_PTR local_apic.acknowledge_int ();
-    else
-      vector = BX_IAC(); // may set INTR with next interrupt
-#else
-#if 0 // FIXME: this will eventually be included
-    // if no local APIC, always acknowledge the PIC.
-    vector = BX_IAC(); // may set INTR with next interrupt
-#endif
-#endif
-    //if (bx_dbg.interrupts) BX_INFO(("decode: interrupt %u\n",
-    //                                   (unsigned) vector));
-    BX_CPU_THIS_PTR errorno = 0;
-    BX_CPU_THIS_PTR EXT   = 1; /* external event */
-    interrupt(vector, 0, 0, 0);
-    BX_INSTR_HWINTERRUPT(vector, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, BX_CPU_THIS_PTR eip);
-    }
-#if 0 // FIXME: this will eventually be included
-  else if (BX_HRQ && BX_DBG_ASYNC_DMA) {
-    // NOTE: similar code in ::take_dma()
-    // assert Hold Acknowledge (HLDA) and go into a bus hold state
-    BX_RAISE_HLDA();
-    }
-#endif
-  // Priority 6: Faults from fetching next instruction
-  //   Code breakpoint fault
-  //   Code segment limit violation (priority 7 on 486/Pentium)
-  //   Code page fault (priority 7 on 486/Pentium)
-  // (handled in main decode loop)
-
-  // Priority 7: Faults from decoding next instruction
-  //   Instruction length > 15 bytes
-  //   Illegal opcode
-  //   Coprocessor not available
-  // (handled in main decode loop etc)
-
-  // Priority 8: Faults on executing an instruction
-  //   Floating point execution
-  //   Overflow
-  //   Bound error
-  //   Invalid TSS
-  //   Segment not present
-  //   Stack fault
-  //   General protection
-  //   Data page fault
-  //   Alignment check
-  // (handled by rest of the code)
-
-
-  if (BX_CPU_THIS_PTR eflags.tf) {
-    // TF is set before execution of next instruction.  Schedule
-    // a debug trap (#DB) after execution.  After completion of
-    // next instruction, the code above will invoke the trap.
-    BX_CPU_THIS_PTR debug_trap |= 0x00004000; // BS flag in DR6
-    }
-#if 0 // FIXME: this will eventually be included
-  if ( !(BX_CPU_THIS_PTR INTR ||
-         BX_CPU_THIS_PTR debug_trap ||
-         BX_HRQ ||
-         BX_CPU_THIS_PTR eflags.tf) )
-    BX_CPU_THIS_PTR async_event = 0;
-  goto async_events_processed;
-#endif
-}
-
-// boundaries of consideration:
-//
-//  * physical memory boundary: 1024k (1Megabyte) (increments of...)
-//  * A20 boundary:             1024k (1Megabyte)
-//  * page boundary:            4k
-//  * ROM boundary:             2k (dont care since we are only reading)
-//  * segment boundary:         any
-
-
-
-  void
-sid_cpu_c::prefetch(void)
-{
-  // cs:eIP
-  // prefetch QSIZE byte quantity aligned on corresponding boundary
-  Bit32u new_linear_addr;
-  Bit32u new_phy_addr;
-  Bit32u temp_eip, temp_limit;
-
-  temp_eip   = BX_CPU_THIS_PTR eip;
-  temp_limit = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled;
-
-  new_linear_addr = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base + temp_eip;
-  BX_CPU_THIS_PTR prev_linear_page = new_linear_addr & 0xfffff000;
-  if (temp_eip > temp_limit) {
-    BX_PANIC(("prefetch: EIP > CS.limit\n"));
-    }
-
-#if BX_SUPPORT_PAGING
-  if (BX_CPU_THIS_PTR cr0.pg) {
-    // aligned block guaranteed to be all in one page, same A20 address
-    new_phy_addr = itranslate_linear(new_linear_addr, CPL==3);
-    new_phy_addr = A20ADDR(new_phy_addr);
-    }
-  else {
-#endif // BX_SUPPORT_PAGING
-    new_phy_addr = A20ADDR(new_linear_addr);
-#if BX_SUPPORT_PAGING
-    }
-#endif // BX_SUPPORT_PAGING
-
-  // max physical address as confined by page boundary
-  BX_CPU_THIS_PTR prev_phy_page = new_phy_addr & 0xfffff000;
-  BX_CPU_THIS_PTR max_phy_addr = BX_CPU_THIS_PTR prev_phy_page | 0x00000fff;
-
-  // check if segment boundary comes into play
-  //if ((temp_limit - temp_eip) < 4096) {
-  //  }
-
-  BX_CPU_THIS_PTR bytesleft = 16;
-  
-  if(!sid_prefetch_data)
-      sid_prefetch_data = new Bit8u[16];
-
-#if X86_CPU_DEBUG
-    printf("Prefetching 16 new bytes from %p...\n", new_phy_addr);
-#endif
-    
-  BX_CPU_THIS_PTR mem->read_physical(this, new_phy_addr, 16, (void *)sid_prefetch_data);
-
-  BX_CPU_THIS_PTR fetch_ptr = sid_prefetch_data;
-}
-
-
-  // If control has transfered locally, it is possible the prefetch Q is
-  // still valid.  This would happen for repeat instructions, and small
-  // branches.
-  void
-sid_cpu_c::revalidate_prefetch_q(void)
-{
-  Bit32u new_linear_addr, new_linear_page, new_linear_offset;
-  Bit32u new_phy_addr;
-
-  new_linear_addr = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base + BX_CPU_THIS_PTR eip;
-
-  new_linear_page = new_linear_addr & 0xfffff000;
-  if (new_linear_page == BX_CPU_THIS_PTR prev_linear_page) {
-    // same linear address, old linear->physical translation valid
-    new_linear_offset = new_linear_addr & 0x00000fff;
-    new_phy_addr = BX_CPU_THIS_PTR prev_phy_page | new_linear_offset;
-
-    BX_CPU_THIS_PTR bytesleft = 16;
-  
-    if(!sid_prefetch_data)
-        sid_prefetch_data = new Bit8u[16];
-
-#if X86_CPU_DEBUG
-      printf("Revalidating prefetch: Prefetching 16 new bytes from %p...\n", new_phy_addr);
-#endif
-      
-    BX_CPU_THIS_PTR mem->read_physical(this, new_phy_addr, 16, (void *)sid_prefetch_data);
-    
-    BX_CPU_THIS_PTR fetch_ptr = sid_prefetch_data;
-  }
-  else {
-    BX_CPU_THIS_PTR bytesleft = 0; // invalidate prefetch Q
-    }
-}
diff --git a/sid/component/bochs/cpu/cpu-sid.h b/sid/component/bochs/cpu/cpu-sid.h
deleted file mode 100644 (file)
index 3edf6ae..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-//  cpu-sid.h - declaration of the sid_cpu_c class. -*- C++ -*-
-//
-//  Copyright (C) 2001 Red Hat.
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-#ifndef __CPU_SID_H__
-#define __CPU_SID_H__
-
-// The CHECK_MAX_INSTRUCTIONS macro allows cpu_loop to execute a few
-// instructions and then return so that the other processors have a chance to
-// run.  This is used only when simulating multiple processors.
-// 
-// If maximum instructions have been executed, return.  A count less
-// than zero means run forever.
-#define CHECK_MAX_INSTRUCTIONS(count) \
-  if (count >= 0) {                   \
-    count--; if (count == 0) return;  \
-  }
-
-#define NEED_CPU_REG_SHORTCUTS 1
-
-#include "cpu.h"
-
-class x86_cpu;
-
-class sid_cpu_c : public BX_CPU_C {
-  public:
-    x86_cpu *sid_cpu;
-    
-    void init (sid_mem_c *addrspace);
-    void interrupt(Bit8u vector, Boolean is_INT, Boolean is_error_code,
-                   Bit16u error_code);
-    void set_INTR(Boolean value);
-    void cpu_loop(Bit32s max_instr_count);
-    void prefetch(void);
-    void revalidate_prefetch_q(void);
-
-    Bit32u dbg_get_eflags(void);
-    Bit32u dbg_get_reg(unsigned reg);
-    Boolean dbg_set_reg(unsigned reg, Bit32u val);
-    void JCC_Jd(BxInstruction_t *i);
-    void INT3(BxInstruction_t *i);
-    void INT_Ib(BxInstruction_t *i);
-    unsigned FetchDecode(Bit8u *iptr, BxInstruction_t *instruction,
-                         unsigned remain, Boolean is_32);
-};
-
-typedef void (sid_cpu_c::*SidExecutePtr_t)(BxInstruction_t *);
-
-#  define BX_CPU_CALL_METHOD_FROM_SID(func, args) \
-    (this->*((SidExecutePtr_t) (func))) args
-
-extern sid_cpu_c bx_cpu;
-
-#endif // __CPU_SID_H__
index 753d49c..e994976 100644 (file)
@@ -27,6 +27,9 @@
 #include "bochs.h"
 #define LOG_THIS BX_CPU_THIS_PTR
 
+#if BX_SUPPORT_SID
+#include "sid-x86-cpu-wrapper.h"
+#endif
 #if BX_USE_CPU_SMF
 #define this (BX_CPU(0))
 #endif
@@ -59,12 +62,12 @@ const Boolean bx_parity_lookup[256] = {
   };
 #endif
 
+#if BX_SUPPORT_SID
+static Bit8u *sid_prefetch_data = NULL;
+#endif
 
 #if BX_SMP_PROCESSORS==1
-#if BX_SUPPORT_SID
-sid_cpu_c bx_cpu;
-sid_mem_c bx_mem;
-#else
+#if BX_SUPPORT_SID==0
 // single processor simulation, so there's one of everything
 BX_CPU_C    bx_cpu;
 BX_MEM_C    bx_mem;
@@ -202,7 +205,19 @@ async_events_processed:
   if (BX_CPU_THIS_PTR bytesleft < 16)
     maxisize = BX_CPU_THIS_PTR bytesleft;
   ret = FetchDecode(fetch_ptr, &i, maxisize, is_32);
+#if BX_SUPPORT_SID
+#if X86_CPU_DEBUG
+  //  fprintf(stderr, "FetchDecode returned: %d\n", ret);
+  if (ret)
+    {
+      for (int deb = 0; deb < i.ilen; deb++)
+        printf("%c", *(fetch_ptr + deb));
+    }
 
+  //  if (ret)
+  //    printf("Current opcode: %p, with length: %d, EIP = %p\n", i.b1, i.ilen, this->eip);
+#endif // X86_CPU_DEBUG
+#endif // BX_SUPPORT_SID
   if (ret) {
     if (i.ResolveModrm) {
       // call method on BX_CPU_C object
@@ -291,6 +306,9 @@ repeat_done:
 
 debugger_check:
 
+#if BX_SUPPORT_SID
+    CHECK_MAX_INSTRUCTIONS(max_instr_count);
+#else    
 #if (BX_SMP_PROCESSORS>1 && BX_DEBUGGER==0)
     // The CHECK_MAX_INSTRUCTIONS macro allows cpu_loop to execute a few
     // instructions and then return so that the other processors have a chance
@@ -300,6 +318,7 @@ debugger_check:
     // functionality.
     CHECK_MAX_INSTRUCTIONS(max_instr_count);
 #endif
+#endif
 
 #if BX_DEBUGGER
     // BW vm mode switch support is in dbg_is_begin_instr_bpoint
@@ -385,6 +404,18 @@ static Bit8u FetchBuffer[16];
       FetchBuffer[j] = *temp_ptr++;
       }
     ret = FetchDecode(FetchBuffer, &i, 16, is_32);
+#if BX_SUPPORT_SID
+#if X86_CPU_DEBUG
+    //  fprintf(stderr, "Prefetch: FetchDecode returned: %d\n", ret);
+    if (ret)
+      {
+        for (int deb = 0; deb < i.ilen; deb++)
+          printf("%c", *(fetch_ptr + deb));
+      }
+                 //      printf("Current opcode: %p, with length: %d, EIP = %p\n", i.b1, i.ilen, this->eip);
+#endif // X86_CPU_DEBUG
+#endif // BX_SUPPORT_SID
+
     if (ret==0)
       BX_PANIC(("fetchdecode: cross boundary: ret==0\n"));
     if (i.ResolveModrm) {
@@ -411,6 +442,13 @@ handle_async_event:
   if (BX_CPU_THIS_PTR debug_trap & 0x80000000) {
     // I made up the bitmask above to mean HALT state.
 #if BX_SMP_PROCESSORS==1
+#if BX_SUPPORT_SID
+    // XXX: not tested yet:
+    if (!(BX_CPU_THIS_PTR INTR && BX_CPU_THIS_PTR eflags.if_))
+      {
+        x86_cpu_component->yield();
+      }
+#else
     // for one processor, pass the time as quickly as possible until
     // an interrupt wakes up the CPU.
     while (1) {
@@ -419,6 +457,7 @@ handle_async_event:
         }
       BX_TICK1();
     }
+#endif
 #else      /* BX_SMP_PROCESSORS != 1 */
     // for multiprocessor simulation, even if this CPU is halted we still
     // must give the others a chance to simulate.  If an interrupt has 
@@ -492,7 +531,10 @@ handle_async_event:
     else
       vector = BX_IAC(); // may set INTR with next interrupt
 #else
-#if 0 // FIXME: look into this later
+#if BX_SUPPORT_SID
+    x86_cpu_component->drive_interrupt_acknowledge_pin();
+    vector = x86_cpu_component->interrupt_acknowledged();
+#else
     // if no local APIC, always acknowledge the PIC.
     vector = BX_IAC(); // may set INTR with next interrupt
 #endif
@@ -504,13 +546,12 @@ handle_async_event:
     interrupt(vector, 0, 0, 0);
     BX_INSTR_HWINTERRUPT(vector, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, BX_CPU_THIS_PTR eip);
     }
-#if 0 // FIXME: look into this later
   else if (BX_HRQ && BX_DBG_ASYNC_DMA) {
     // NOTE: similar code in ::take_dma()
     // assert Hold Acknowledge (HLDA) and go into a bus hold state
     BX_RAISE_HLDA();
     }
-#endif
+
   // Priority 6: Faults from fetching next instruction
   //   Code breakpoint fault
   //   Code segment limit violation (priority 7 on 486/Pentium)
@@ -542,13 +583,13 @@ handle_async_event:
     // next instruction, the code above will invoke the trap.
     BX_CPU_THIS_PTR debug_trap |= 0x00004000; // BS flag in DR6
     }
-#if 0 // FIXME: look into this later
+
   if ( !(BX_CPU_THIS_PTR INTR ||
          BX_CPU_THIS_PTR debug_trap ||
          BX_HRQ ||
          BX_CPU_THIS_PTR eflags.tf) )
     BX_CPU_THIS_PTR async_event = 0;
-#endif
+
   goto async_events_processed;
 }
 #endif  // #if BX_DYNAMIC_TRANSLATION == 0
@@ -597,6 +638,19 @@ BX_CPU_C::prefetch(void)
     }
 #endif // BX_SUPPORT_PAGING
 
+#if BX_SUPPORT_SID
+  // max physical address as confined by page boundary
+  BX_CPU_THIS_PTR prev_phy_page = new_phy_addr & 0xfffff000;
+  BX_CPU_THIS_PTR max_phy_addr = BX_CPU_THIS_PTR prev_phy_page | 0x00000fff;
+
+  if(!sid_prefetch_data)
+    sid_prefetch_data = new Bit8u[16];
+
+  BX_CPU_THIS_PTR mem->read_physical(this, new_phy_addr, 16, (void *)sid_prefetch_data);
+
+  BX_CPU_THIS_PTR bytesleft = 16;
+  BX_CPU_THIS_PTR fetch_ptr = sid_prefetch_data;
+#else
   if ( new_phy_addr >= BX_CPU_THIS_PTR mem->len ) {
     // don't take this out if dynamic translation enabled,
     // otherwise you must make a check to see if bytesleft is 0 after
@@ -614,6 +668,7 @@ BX_CPU_C::prefetch(void)
 
   BX_CPU_THIS_PTR bytesleft = (BX_CPU_THIS_PTR max_phy_addr - new_phy_addr) + 1;
   BX_CPU_THIS_PTR fetch_ptr = &BX_CPU_THIS_PTR mem->vector[new_phy_addr];
+#endif
 }
 
 
@@ -633,8 +688,18 @@ BX_CPU_C::revalidate_prefetch_q(void)
     // same linear address, old linear->physical translation valid
     new_linear_offset = new_linear_addr & 0x00000fff;
     new_phy_addr = BX_CPU_THIS_PTR prev_phy_page | new_linear_offset;
+#if BX_SUPPORT_SID
+    if(!sid_prefetch_data)
+        sid_prefetch_data = new Bit8u[16];
+
+    BX_CPU_THIS_PTR mem->read_physical(this, new_phy_addr, 16, (void *)sid_prefetch_data);
+
+    BX_CPU_THIS_PTR bytesleft = 16;
+    BX_CPU_THIS_PTR fetch_ptr = sid_prefetch_data;
+#else
     BX_CPU_THIS_PTR bytesleft = (BX_CPU_THIS_PTR max_phy_addr - new_phy_addr) + 1;
     BX_CPU_THIS_PTR fetch_ptr = &BX_CPU_THIS_PTR mem->vector[new_phy_addr];
+#endif
     }
   else {
     BX_CPU_THIS_PTR bytesleft = 0; // invalidate prefetch Q
index 006e326..ddddf89 100644 (file)
@@ -383,7 +383,7 @@ typedef struct {
 typedef void * (*BxVoidFPtr_t)(void);
 class BX_CPU_C;
 #if BX_SUPPORT_SID
-class sid_cpu_c;
+class x86_cpu;
 #endif
 
 typedef struct BxInstruction_tag {
@@ -419,9 +419,6 @@ typedef struct BxInstruction_tag {
 #else
   void (BX_CPU_C::*ResolveModrm)(BxInstruction_tag *);
   void (BX_CPU_C::*execute)(BxInstruction_tag *);
-#if BX_SUPPORT_SID
-  void (sid_cpu_c::*execute_sid)(BxInstruction_tag *);
-#endif
 #endif
 
 #if BX_DYNAMIC_TRANSLATION
@@ -649,7 +646,7 @@ extern bx_generic_apic_c *apic_index[APIC_MAX_ID];
 typedef void (*BxDTShim_t)(void);
 
 #if BX_SUPPORT_SID
-class sid_mem_c;
+class sid_bx_mem_c;
 #else
 class BX_MEM_C;
 #endif
@@ -752,12 +749,13 @@ public: // for now...
 #endif
 
 #if BX_SUPPORT_SID
-  sid_mem_c *mem;
+  x86_cpu *x86_cpu_component;
+  sid_bx_mem_c *mem;
 #else
   // pointer to the address space that this processor uses.
   BX_MEM_C *mem;
 #endif
-  
+
   Boolean EXT; /* 1 if processing external interrupt or exception
                 * or if not related to current instruction,
                 * 0 if current CS:IP caused exception */
@@ -767,6 +765,9 @@ public: // for now...
   volatile Boolean async_event;
   volatile Boolean INTR;
 
+#if BX_SUPPORT_SID
+  Boolean BX_HRQ;
+#endif
   // for accessing registers by index number
   Bit16u *_16bit_base_reg[8];
   Bit16u *_16bit_index_reg[8];
@@ -840,7 +841,7 @@ public: // for now...
   BX_CPU_C();
   ~BX_CPU_C(void);
 #if BX_SUPPORT_SID
-  void init (sid_mem_c *addrspace);
+  void init (x86_cpu *x86_cpu_comp, sid_bx_mem_c *addrspace);
 #else
   void init (BX_MEM_C *addrspace);
 #endif
@@ -1355,6 +1356,11 @@ public: // for now...
 
   BX_SMF void REP(void (*)(void));
   BX_SMF void REP_ZF(void (*)(void), unsigned rep_prefix);
+#if BX_SUPPORT_SID
+  BX_SMF Boolean  dbg_set_reg(unsigned reg, Bit32u val);
+  BX_SMF Bit32u   dbg_get_reg(unsigned reg);
+  BX_SMF Bit32u   dbg_get_eflags(void);
+#else
 #if BX_DEBUGGER
   BX_SMF void     dbg_take_irq(void);
   BX_SMF void     dbg_force_interrupt(unsigned vector);
@@ -1373,6 +1379,7 @@ public: // for now...
   BX_SMF Boolean  dbg_is_end_instr_bpoint(Bit32u cs, Bit32u eip,
                                           Bit32u laddr, Bit32u is_32);
 #endif
+#endif
 #if BX_DEBUGGER || BX_DISASM || BX_INSTRUMENTATION
   BX_SMF void     dbg_xlate_linear2phy(Bit32u linear, Bit32u *phy, Boolean *valid);
 #endif
@@ -1413,6 +1420,9 @@ public: // for now...
   BX_SMF void TLB_clear(void);
   BX_SMF void TLB_init(void);
   BX_SMF void set_INTR(Boolean value);
+#if BX_SUPPORT_SID
+  void set_HRQ(Boolean value);
+#endif
   BX_SMF char *strseg(bx_segment_reg_t *seg);
   BX_SMF void interrupt(Bit8u vector, Boolean is_INT, Boolean is_error_code,
                  Bit16u error_code);
@@ -1539,8 +1549,8 @@ public: // for now...
 #define BX_HWDebugMemRW         0x03
 #endif
 
-#if BX_SUPPORT_SID
-#else
+
+#if BX_SUPPORT_SID==0
 #if BX_SMP_PROCESSORS==1
 // single processor simulation, so there's one of everything
 extern BX_CPU_C       bx_cpu;
diff --git a/sid/component/bochs/cpu/ctrl_xfer32-sid.cc b/sid/component/bochs/cpu/ctrl_xfer32-sid.cc
deleted file mode 100644 (file)
index 18d74b8..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-//  Copyright (C) 2001  MandrakeSoft S.A.
-//
-//    MandrakeSoft S.A.
-//    43, rue d'Aboukir
-//    75002 Paris - France
-//    http://www.linux-mandrake.com/
-//    http://www.mandrakesoft.com/
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-
-
-#define NEED_CPU_REG_SHORTCUTS 1
-#include "bochs.h"
-#define LOG_THIS BX_CPU_THIS_PTR
-
-
-
-
-
-#if 0
-  void
-BX_CPU_C::RETnear32_Iw(BxInstruction_t *i)
-{
-  Bit16u imm16;
-  Bit32u temp_ESP;
-  Bit32u return_EIP;
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_ret;
-#endif
-
-  if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) /* 32bit stack */
-    temp_ESP = ESP;
-  else
-    temp_ESP = SP;
-
-  imm16 = i->Iw;
-
-  invalidate_prefetch_q();
-
-
-    if (protected_mode()) {
-      if ( !can_pop(4) ) {
-        BX_PANIC(("retnear_iw: can't pop EIP\n"));
-        /* ??? #SS(0) -or #GP(0) */
-        }
-
-      access_linear(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base + temp_ESP + 0,
-        4, CPL==3, BX_READ, &return_EIP);
-
-      if (protected_mode() &&
-          (return_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) ) {
-        BX_DEBUG(("retnear_iw: EIP > limit\n"));
-        exception(BX_GP_EXCEPTION, 0, 0);
-        }
-
-      /* Pentium book says imm16 is number of words ??? */
-      if ( !can_pop(4 + imm16) ) {
-        BX_PANIC(("retnear_iw: can't release bytes from stack\n"));
-        /* #GP(0) -or #SS(0) ??? */
-        }
-
-      BX_CPU_THIS_PTR eip = return_EIP;
-      if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) /* 32bit stack */
-        ESP += 4 + imm16; /* ??? should it be 2*imm16 ? */
-      else
-        SP  += 4 + imm16;
-      }
-    else {
-      pop_32(&return_EIP);
-      BX_CPU_THIS_PTR eip = return_EIP;
-      if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) /* 32bit stack */
-        ESP += imm16; /* ??? should it be 2*imm16 ? */
-      else
-        SP  += imm16;
-      }
-
-  BX_INSTR_UCNEAR_BRANCH(BX_INSTR_IS_RET, BX_CPU_THIS_PTR eip);
-}
-
-  void
-BX_CPU_C::RETnear32(BxInstruction_t *i)
-{
-  Bit32u temp_ESP;
-  Bit32u return_EIP;
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_ret;
-#endif
-
-  invalidate_prefetch_q();
-
-  if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) /* 32bit stack */
-    temp_ESP = ESP;
-  else
-    temp_ESP = SP;
-
-
-    if (protected_mode()) {
-      if ( !can_pop(4) ) {
-        BX_PANIC(("retnear: can't pop EIP\n"));
-        /* ??? #SS(0) -or #GP(0) */
-        }
-
-      access_linear(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base + temp_ESP + 0,
-        4, CPL==3, BX_READ, &return_EIP);
-
-      if ( return_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled ) {
-        BX_PANIC(("retnear: EIP > limit\n"));
-        //exception(BX_GP_EXCEPTION, 0, 0);
-        }
-      BX_CPU_THIS_PTR eip = return_EIP;
-      if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) /* 32bit stack */
-        ESP += 4;
-      else
-        SP  += 4;
-      }
-    else {
-      pop_32(&return_EIP);
-      BX_CPU_THIS_PTR eip = return_EIP;
-      }
-
-  BX_INSTR_UCNEAR_BRANCH(BX_INSTR_IS_RET, BX_CPU_THIS_PTR eip);
-}
-
-  void
-BX_CPU_C::RETfar32_Iw(BxInstruction_t *i)
-{
-  Bit32u eip, ecs_raw;
-  Bit16s imm16;
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_ret;
-#endif
-  /* ??? is imm16, number of bytes/words depending on operandsize ? */
-
-  imm16 = i->Iw;
-
-  invalidate_prefetch_q();
-
-#if BX_CPU_LEVEL >= 2
-  if (protected_mode()) {
-    BX_CPU_THIS_PTR return_protected(i, imm16);
-    goto done;
-    }
-#endif
-
-
-    pop_32(&eip);
-    pop_32(&ecs_raw);
-    BX_CPU_THIS_PTR eip = eip;
-    load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u) ecs_raw);
-    if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
-      ESP += imm16;
-    else
-      SP  += imm16;
-
-done:
-  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_RET,
-                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, BX_CPU_THIS_PTR eip);
-  return;
-}
-
-  void
-BX_CPU_C::RETfar32(BxInstruction_t *i)
-{
-  Bit32u eip, ecs_raw;
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_ret;
-#endif
-
-  invalidate_prefetch_q();
-
-#if BX_CPU_LEVEL >= 2
-  if ( protected_mode() ) {
-    BX_CPU_THIS_PTR return_protected(i, 0);
-    goto done;
-    }
-#endif
-
-
-    pop_32(&eip);
-    pop_32(&ecs_raw); /* 32bit pop, MSW discarded */
-    BX_CPU_THIS_PTR eip = eip;
-    load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u) ecs_raw);
-
-done:
-  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_RET,
-                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, BX_CPU_THIS_PTR eip);
-  return;
-}
-
-
-
-  void
-BX_CPU_C::CALL_Ad(BxInstruction_t *i)
-{
-  Bit32u new_EIP;
-  Bit32s disp32;
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_call;
-#endif
-
-  disp32 = i->Id;
-  invalidate_prefetch_q();
-
-  new_EIP = EIP + disp32;
-
-  if ( protected_mode() ) {
-    if ( new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled ) {
-      BX_PANIC(("call_av: offset outside of CS limits\n"));
-      exception(BX_GP_EXCEPTION, 0, 0);
-      }
-    }
-
-  /* push 32 bit EA of next instruction */
-  push_32(BX_CPU_THIS_PTR eip);
-  BX_CPU_THIS_PTR eip = new_EIP;
-
-  BX_INSTR_UCNEAR_BRANCH(BX_INSTR_IS_CALL, BX_CPU_THIS_PTR eip);
-}
-
-  void
-BX_CPU_C::CALL32_Ap(BxInstruction_t *i)
-{
-  Bit16u cs_raw;
-  Bit32u disp32;
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_call;
-#endif
-
-  disp32 = i->Id;
-  cs_raw = i->Iw2;
-  invalidate_prefetch_q();
-
-  if (protected_mode()) {
-    BX_CPU_THIS_PTR call_protected(i, cs_raw, disp32);
-    goto done;
-    }
-  push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
-  push_32(BX_CPU_THIS_PTR eip);
-  BX_CPU_THIS_PTR eip = disp32;
-  load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
-
-done:
-  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_CALL,
-                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, BX_CPU_THIS_PTR eip);
-  return;
-}
-
-  void
-BX_CPU_C::CALL_Ed(BxInstruction_t *i)
-{
-  Bit32u temp_ESP;
-  Bit32u op1_32;
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_call;
-#endif
-
-  if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
-    temp_ESP = ESP;
-  else
-    temp_ESP = SP;
-
-
-    /* op1_32 is a register or memory reference */
-    if (i->mod == 0xc0) {
-      op1_32 = BX_READ_32BIT_REG(i->rm);
-      }
-    else {
-      read_virtual_dword(i->seg, i->rm_addr, &op1_32);
-      }
-    invalidate_prefetch_q();
-
-    if (protected_mode()) {
-      if (op1_32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
-        BX_DEBUG(("call_ev: EIP out of CS limits! at %s:%d\n"));
-        exception(BX_GP_EXCEPTION, 0, 0);
-        }
-      if ( !can_push(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache, temp_ESP, 4) ) {
-        BX_PANIC(("call_ev: can't push EIP\n"));
-        }
-      }
-
-    push_32(BX_CPU_THIS_PTR eip);
-
-    BX_CPU_THIS_PTR eip = op1_32;
-
-  BX_INSTR_UCNEAR_BRANCH(BX_INSTR_IS_CALL, BX_CPU_THIS_PTR eip);
-}
-
-  void
-BX_CPU_C::CALL32_Ep(BxInstruction_t *i)
-{
-  Bit16u cs_raw;
-  Bit32u op1_32;
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_call;
-#endif
-
-    /* op1_32 is a register or memory reference */
-    if (i->mod == 0xc0) {
-      BX_PANIC(("CALL_Ep: op1 is a register\n"));
-      }
-
-    /* pointer, segment address pair */
-    read_virtual_dword(i->seg, i->rm_addr, &op1_32);
-    read_virtual_word(i->seg, i->rm_addr+4, &cs_raw);
-    invalidate_prefetch_q();
-
-    if ( protected_mode() ) {
-      BX_CPU_THIS_PTR call_protected(i, cs_raw, op1_32);
-      goto done;
-      }
-
-    push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
-    push_32(BX_CPU_THIS_PTR eip);
-
-    BX_CPU_THIS_PTR eip = op1_32;
-    load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
-
-done:
-  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_CALL,
-                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, BX_CPU_THIS_PTR eip);
-  return;
-}
-
-
-  void
-BX_CPU_C::JMP_Jd(BxInstruction_t *i)
-{
-  Bit32u new_EIP;
-
-    invalidate_prefetch_q();
-
-    new_EIP = EIP + (Bit32s) i->Id;
-
-#if BX_CPU_LEVEL >= 2
-  if (protected_mode()) {
-    if ( new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled ) {
-      BX_PANIC(("jmp_jv: offset outside of CS limits\n"));
-      exception(BX_GP_EXCEPTION, 0, 0);
-      }
-    }
-#endif
-
-  BX_CPU_THIS_PTR eip = new_EIP;
-  BX_INSTR_UCNEAR_BRANCH(BX_INSTR_IS_JMP, new_EIP);
-}
-#endif
-
-  void
-sid_cpu_c::JCC_Jd(BxInstruction_t *i)
-{
-  Boolean condition = 0;
-
-  switch (i->b1 & 0x0f) {
-    case 0x00: /* JO */ condition = get_OF(); break;
-    case 0x01: /* JNO */ condition = !get_OF(); break;
-    case 0x02: /* JB */ condition = get_CF(); break;
-    case 0x03: /* JNB */ condition = !get_CF(); break;
-    case 0x04: /* JZ */ condition = get_ZF(); break;
-    case 0x05: /* JNZ */ condition = !get_ZF(); break;
-    case 0x06: /* JBE */ condition = get_CF() || get_ZF(); break;
-    case 0x07: /* JNBE */ condition = !get_CF() && !get_ZF(); break;
-    case 0x08: /* JS */ condition = get_SF(); break;
-    case 0x09: /* JNS */ condition = !get_SF(); break;
-    case 0x0A: /* JP */ condition = get_PF(); break;
-    case 0x0B: /* JNP */ condition = !get_PF(); break;
-    case 0x0C: /* JL */ condition = get_SF() != get_OF(); break;
-    case 0x0D: /* JNL */ condition = get_SF() == get_OF(); break;
-    case 0x0E: /* JLE */ condition = get_ZF() || (get_SF() != get_OF());
-      break;
-    case 0x0F: /* JNLE */ condition = (get_SF() == get_OF()) &&
-                            !get_ZF();
-      break;
-    }
-
-  if (condition) {
-    Bit32u new_EIP;
-
-    new_EIP = EIP + (Bit32s) i->Id;
-#if BX_CPU_LEVEL >= 2
-    if (protected_mode()) {
-      if ( new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled ) {
-        BX_PANIC(("jo_routine: offset outside of CS limits\n"));
-        exception(BX_GP_EXCEPTION, 0, 0);
-        }
-      }
-#endif
-    EIP = new_EIP;
-    BX_INSTR_CNEAR_BRANCH_TAKEN(new_EIP);
-    revalidate_prefetch_q();
-    }
-#if BX_INSTRUMENTATION
-  else {
-    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN();
-    }
-#endif
-}
-#if 0
-  void
-BX_CPU_C::JMP_Ap(BxInstruction_t *i)
-{
-  Bit32u disp32;
-  Bit16u cs_raw;
-
-  invalidate_prefetch_q();
-
-  if (i->os_32) {
-    disp32 = i->Id;
-    }
-  else {
-    disp32 = i->Iw;
-    }
-  cs_raw = i->Iw2;
-
-#if BX_CPU_LEVEL >= 2
-  if (protected_mode()) {
-    BX_CPU_THIS_PTR jump_protected(i, cs_raw, disp32);
-    goto done;
-    }
-#endif
-
-  load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
-  BX_CPU_THIS_PTR eip = disp32;
-
-done:
-  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_JMP,
-                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, BX_CPU_THIS_PTR eip);
-  return;
-}
-
-
-
-
-  void
-BX_CPU_C::JMP_Ed(BxInstruction_t *i)
-{
-  Bit32u new_EIP;
-  Bit32u op1_32;
-
-    /* op1_32 is a register or memory reference */
-    if (i->mod == 0xc0) {
-      op1_32 = BX_READ_32BIT_REG(i->rm);
-      }
-    else {
-      /* pointer, segment address pair */
-      read_virtual_dword(i->seg, i->rm_addr, &op1_32);
-      }
-
-    invalidate_prefetch_q();
-    new_EIP = op1_32;
-
-#if BX_CPU_LEVEL >= 2
-  if (protected_mode()) {
-    if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
-      BX_PANIC(("jmp_ev: IP out of CS limits!\n"));
-      exception(BX_GP_EXCEPTION, 0, 0);
-      }
-    }
-#endif
-
-  BX_CPU_THIS_PTR eip = new_EIP;
-
-  BX_INSTR_UCNEAR_BRANCH(BX_INSTR_IS_JMP, new_EIP);
-}
-
-  /* Far indirect jump */
-
-  void
-BX_CPU_C::JMP32_Ep(BxInstruction_t *i)
-{
-  Bit16u cs_raw;
-  Bit32u op1_32;
-
-    /* op1_32 is a register or memory reference */
-    if (i->mod == 0xc0) {
-      /* far indirect must specify a memory address */
-      BX_PANIC(("JMP_Ep(): op1 is a register\n"));
-      }
-
-    /* pointer, segment address pair */
-    read_virtual_dword(i->seg, i->rm_addr, &op1_32);
-    read_virtual_word(i->seg, i->rm_addr+4, &cs_raw);
-    invalidate_prefetch_q();
-
-    if ( protected_mode() ) {
-      BX_CPU_THIS_PTR jump_protected(i, cs_raw, op1_32);
-      goto done;
-      }
-
-    BX_CPU_THIS_PTR eip = op1_32;
-    load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
-
-done:
-  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_JMP,
-                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, BX_CPU_THIS_PTR eip);
-  return;
-}
-
-  void
-BX_CPU_C::IRET32(BxInstruction_t *i)
-{
-  Bit32u eip, ecs_raw, eflags;
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_iret;
-  BX_CPU_THIS_PTR show_eip = BX_CPU_THIS_PTR eip;
-#endif
-
-  invalidate_prefetch_q();
-
-  if (v8086_mode()) {
-    // IOPL check in stack_return_from_v86()
-    stack_return_from_v86(i);
-    goto done;
-    }
-
-#if BX_CPU_LEVEL >= 2
-  if (BX_CPU_THIS_PTR cr0.pe) {
-    iret_protected(i);
-    goto done;
-    }
-#endif
-
-
-    pop_32(&eip);
-    pop_32(&ecs_raw);
-    pop_32(&eflags);
-
-    load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u) ecs_raw);
-    BX_CPU_THIS_PTR eip = eip;
-    write_eflags(eflags, /* change IOPL? */ 1, /* change IF? */ 1, 0, 1);
-
-done:
-  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_IRET,
-                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, BX_CPU_THIS_PTR eip);
-  return;
-}
-#endif
diff --git a/sid/component/bochs/cpu/debugstuff-sid.cc b/sid/component/bochs/cpu/debugstuff-sid.cc
deleted file mode 100644 (file)
index fd1014f..0000000
+++ /dev/null
@@ -1,1024 +0,0 @@
-//  Copyright (C) 2001  MandrakeSoft S.A.
-//
-//    MandrakeSoft S.A.
-//    43, rue d'Aboukir
-//    75002 Paris - France
-//    http://www.linux-mandrake.com/
-//    http://www.mandrakesoft.com/
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-
-
-
-#define NEED_CPU_REG_SHORTCUTS 1
-#include "bochs.h"
-#define LOG_THIS BX_CPU_THIS_PTR
-
-#if BX_DEBUGGER
-
-  void
-BX_CPU_C::debug(Bit32u offset)
-{
-  BX_INFO(("| EAX=%08x  EBX=%08x  ECX=%08x  EDX=%08x\n",
-          (unsigned) EAX, (unsigned) EBX, (unsigned) ECX, (unsigned) EDX));
-  BX_INFO(("| ESP=%08x  EBP=%08x  ESI=%08x  EDI=%08x\n",
-          (unsigned) ESP, (unsigned) EBP, (unsigned) ESI, (unsigned) EDI));
-  BX_INFO(("| IOPL=%1u %s %s %s %s %s %s %s %s\n",
-    BX_CPU_THIS_PTR eflags.iopl,
-    BX_CPU_THIS_PTR get_OF()       ? "OV" : "NV",
-    BX_CPU_THIS_PTR eflags.df  ? "DW" : "UP",
-    BX_CPU_THIS_PTR eflags.if_ ? "EI" : "DI",
-    BX_CPU_THIS_PTR get_SF()       ? "NG" : "PL",
-    BX_CPU_THIS_PTR get_ZF()       ? "ZR" : "NZ",
-    BX_CPU_THIS_PTR get_AF()       ? "AC" : "NA",
-    BX_CPU_THIS_PTR get_PF()       ? "PE" : "PO",
-    BX_CPU_THIS_PTR get_CF()       ? "CY" : "NC"));
-  BX_INFO(("| SEG selector     base    limit G D\n"));
-  BX_INFO(("| SEG sltr(index|ti|rpl)     base    limit G D\n"));
-  BX_INFO(("|  DS:%04x( %04x| %01u|  %1u) %08x %08x %1u %1u\n",
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.index,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.ti,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.rpl,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.base,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.g,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.d_b));
-  BX_INFO(("|  ES:%04x( %04x| %01u|  %1u) %08x %08x %1u %1u\n",
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.index,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.ti,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.rpl,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.base,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.limit,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.g,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.d_b));
-  BX_INFO(("|  FS:%04x( %04x| %01u|  %1u) %08x %08x %1u %1u\n",
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.index,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.ti,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.rpl,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.base,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.limit,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.g,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.d_b));
-  BX_INFO(("|  GS:%04x( %04x| %01u|  %1u) %08x %08x %1u %1u\n",
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.index,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.ti,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.rpl,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.base,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.limit,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.g,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.d_b));
-  BX_INFO(("|  SS:%04x( %04x| %01u|  %1u) %08x %08x %1u %1u\n",
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.index,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.ti,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.rpl,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b));
-  BX_INFO(("|  CS:%04x( %04x| %01u|  %1u) %08x %08x %1u %1u\n",
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.index,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.ti,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g,
-    (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b));
-  BX_INFO(("| EIP=%08x (%08x)\n", (unsigned) BX_CPU_THIS_PTR eip,
-    (unsigned) BX_CPU_THIS_PTR prev_eip));
-
-#if 0
-  /* (mch) Hack to display the area round EIP and prev_EIP */
-  char buf[100];
-  sprintf(buf, "%04x:%08x  ", BX_CPU_THIS_PTR sregs[BX_SREG_CS].selector.value, BX_CPU_THIS_PTR eip);
-  for (int i = 0; i < 8; i++) {
-    Bit8u data;
-    BX_CPU_THIS_PTR read_virtual_byte(BX_SREG_CS, BX_CPU_THIS_PTR eip + i, &data);
-    sprintf(buf+strlen(buf), "%02x ", data);
-    }
-  sprintf(buf+strlen(buf), "\n");
-  BX_INFO((buf));
-
-  sprintf(buf, "%04x:%08x  ", BX_CPU_THIS_PTR sregs[BX_SREG_CS].selector.value, BX_CPU_THIS_PTR prev_eip);
-  for (int i = 0; i < 8; i++) {
-    Bit8u data;
-    BX_CPU_THIS_PTR read_virtual_byte(BX_SREG_CS, BX_CPU_THIS_PTR prev_eip + i, &data);
-    sprintf(buf+strlen(buf), "%02x ", data);
-    }
-  sprintf(buf+strlen(buf), "\n");
-  BX_INFO((buf));
-#endif
-
-
-#if BX_DISASM
-  Boolean valid;
-  Bit32u  phy_addr;
-  Bit8u   instr_buf[32];
-  char    char_buf[256];
-  unsigned isize;
-
-  dbg_xlate_linear2phy(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base + offset,
-                       &phy_addr, &valid);
-  if (valid) {
-    BX_CPU_THIS_PTR mem->dbg_fetch_mem(phy_addr, 16, instr_buf);
-    isize = bx_disassemble.disasm(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b,
-                        instr_buf, char_buf);
-    for (unsigned j=0; j<isize; j++)
-      BX_INFO((">> %02x\n", (unsigned) instr_buf[j]));
-    BX_INFO((">> : %s\n", char_buf));
-    }
-  else {
-    BX_INFO(("(instruction unavailable) page not present\n"));
-    }
-#else
-  UNUSED(offset);
-#endif  // #if BX_DISASM
-}
-
-#endif // BX_DEBUGGER
-
-
-  Bit32u
-sid_cpu_c::dbg_get_reg(unsigned reg)
-{
-  Bit32u return_val32;
-
-  switch (reg) {
-    case BX_DBG_REG_EAX: return(EAX);
-    case BX_DBG_REG_ECX: return(ECX);
-    case BX_DBG_REG_EDX: return(EDX);
-    case BX_DBG_REG_EBX: return(EBX);
-    case BX_DBG_REG_ESP: return(ESP);
-    case BX_DBG_REG_EBP: return(EBP);
-    case BX_DBG_REG_ESI: return(ESI);
-    case BX_DBG_REG_EDI: return(EDI);
-    case BX_DBG_REG_EIP: return(EIP);
-    case BX_DBG_REG_EFLAGS:
-      return_val32 = dbg_get_eflags();
-      return(return_val32);
-    case BX_DBG_REG_CS: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
-    case BX_DBG_REG_SS: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value);
-    case BX_DBG_REG_DS: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value);
-    case BX_DBG_REG_ES: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value);
-    case BX_DBG_REG_FS: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value);
-    case BX_DBG_REG_GS: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value);
-    default:
-      BX_PANIC(("get_reg: request for unknown register\n"));
-      return(0);
-    }
-}
-
-  Boolean
-sid_cpu_c::dbg_set_reg(unsigned reg, Bit32u val)
-{
-  // returns 1=OK, 0=can't change
-  bx_segment_reg_t *seg;
-  Bit32u current_sys_bits;
-
-  switch (reg) {
-    case BX_DBG_REG_EAX: EAX = val; return(1);
-    case BX_DBG_REG_ECX: ECX = val; return(1);
-    case BX_DBG_REG_EDX: EDX = val; return(1);
-    case BX_DBG_REG_EBX: EBX = val; return(1);
-    case BX_DBG_REG_ESP: ESP = val; return(1);
-    case BX_DBG_REG_EBP: EBP = val; return(1);
-    case BX_DBG_REG_ESI: ESI = val; return(1);
-    case BX_DBG_REG_EDI: EDI = val; return(1);
-    case BX_DBG_REG_EIP: EIP = val; return(1);
-    case BX_DBG_REG_EFLAGS:
-#if 0
-      BX_INFO(("dbg_set_reg: can not handle eflags yet.\n"));
-      if ( val & 0xffff0000 ) {
-        BX_INFO(("dbg_set_reg: can not set upper 16 bits of eflags.\n"));
-        return(0);
-        }
-      // make sure none of the system bits are being changed
-      current_sys_bits = (BX_CPU_THIS_PTR eflags.nt << 14) |
-                         (BX_CPU_THIS_PTR eflags.iopl << 12) |
-                         (BX_CPU_THIS_PTR eflags.tf << 8);
-      if ( current_sys_bits != (val & 0x0000f100) ) {
-        BX_INFO(("dbg_set_reg: can not modify NT, IOPL, or TF.\n"));
-        return(0);
-        }
-#endif
-      BX_CPU_THIS_PTR set_CF(val & 0x01); val >>= 2;
-      BX_CPU_THIS_PTR set_PF(val & 0x01); val >>= 2;
-      BX_CPU_THIS_PTR set_AF(val & 0x01); val >>= 2;
-      BX_CPU_THIS_PTR set_ZF(val & 0x01); val >>= 1;
-      BX_CPU_THIS_PTR set_SF(val & 0x01); val >>= 2;
-      BX_CPU_THIS_PTR eflags.if_ = val & 0x01; val >>= 1;
-      BX_CPU_THIS_PTR eflags.df  = val & 0x01; val >>= 1;
-      BX_CPU_THIS_PTR set_OF(val & 0x01);
-      if (BX_CPU_THIS_PTR eflags.if_)
-        BX_CPU_THIS_PTR async_event = 1;
-      return(1);
-    case BX_DBG_REG_CS:
-      seg = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS];
-      break;
-    case BX_DBG_REG_SS:
-      seg = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS];
-      break;
-    case BX_DBG_REG_DS:
-      seg = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS];
-      break;
-    case BX_DBG_REG_ES:
-      seg = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES];
-      break;
-    case BX_DBG_REG_FS:
-      seg = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS];
-      break;
-    case BX_DBG_REG_GS:
-      seg = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS];
-      break;
-    default:
-      BX_PANIC(("dbg_set_reg: unrecognized register ID (%u)\n", reg));
-      return(0);
-    }
-
-  if (BX_CPU_THIS_PTR real_mode()) {
-    seg->selector.value = val;
-    seg->cache.valid = 1;
-    seg->cache.p = 1;
-    seg->cache.dpl = 0;
-    seg->cache.segment = 1; // regular segment
-    if (reg == BX_DBG_REG_CS) {
-      seg->cache.u.segment.executable = 1; // code segment
-      }
-    else {
-      seg->cache.u.segment.executable = 0; // data segment
-      }
-    seg->cache.u.segment.c_ed = 0;       // expand up/non-conforming
-    seg->cache.u.segment.r_w = 1;        // writeable
-    seg->cache.u.segment.a = 1;          // accessed
-    seg->cache.u.segment.base = val << 4;
-    seg->cache.u.segment.limit        = 0xffff;
-    seg->cache.u.segment.limit_scaled = 0xffff;
-    seg->cache.u.segment.g     = 0;      // byte granular
-    seg->cache.u.segment.d_b   = 0;      // default 16bit size
-    seg->cache.u.segment.avl   = 0;
-    return(1); // ok
-    }
-
-  return(0); // can't change when not in real mode
-}
-#if BX_DEBUGGER
-  unsigned
-BX_CPU_C::dbg_query_pending(void)
-{
-  unsigned ret = 0;
-
-  if ( BX_HRQ ) {  // DMA Hold Request
-    ret |= BX_DBG_PENDING_DMA;
-    }
-
-  if ( BX_CPU_THIS_PTR INTR && BX_CPU_THIS_PTR eflags.if_ ) {
-    ret |= BX_DBG_PENDING_IRQ;
-    }
-
-  return(ret);
-}
-
-#endif // BX_DEBUGGER
-
-  Bit32u
-sid_cpu_c::dbg_get_eflags(void)
-{
-  Bit32u val32;
-
-  val32 =
-    (BX_CPU_THIS_PTR get_CF()) |
-    (BX_CPU_THIS_PTR eflags.bit1 << 1) |
-    ((BX_CPU_THIS_PTR get_PF()) << 2) |
-    (BX_CPU_THIS_PTR eflags.bit3 << 3) |
-    ((BX_CPU_THIS_PTR get_AF()>0) << 4) |
-    (BX_CPU_THIS_PTR eflags.bit5 << 5) |
-    ((BX_CPU_THIS_PTR get_ZF()>0) << 6) |
-    ((BX_CPU_THIS_PTR get_SF()>0) << 7) |
-    (BX_CPU_THIS_PTR eflags.tf << 8) |
-    (BX_CPU_THIS_PTR eflags.if_ << 9) |
-    (BX_CPU_THIS_PTR eflags.df << 10) |
-    ((BX_CPU_THIS_PTR get_OF()>0) << 11) |
-    (BX_CPU_THIS_PTR eflags.iopl << 12) |
-    (BX_CPU_THIS_PTR eflags.nt << 14) |
-    (BX_CPU_THIS_PTR eflags.bit15 << 15) |
-    (BX_CPU_THIS_PTR eflags.rf << 16) |
-    (BX_CPU_THIS_PTR eflags.vm << 17);
-#if BX_CPU_LEVEL >= 4
-  val32 |= (BX_CPU_THIS_PTR eflags.ac << 18);
-  //val32 |= (BX_CPU_THIS_PTR eflags.vif << 19);
-  //val32 |= (BX_CPU_THIS_PTR eflags.vip << 20);
-  val32 |= (BX_CPU_THIS_PTR eflags.id << 21);
-#endif
-  return(val32);
-}
-
-#if BX_DEBUGGER
-  Bit32u
-BX_CPU_C::dbg_get_descriptor_l(bx_descriptor_t *d)
-{
-  Bit32u val;
-
-  if (d->valid == 0) {
-    return(0);
-    }
-
-  if (d->segment) {
-    val = ((d->u.segment.base & 0xffff) << 16) |
-          (d->u.segment.limit & 0xffff);
-    return(val);
-    }
-  else {
-    switch (d->type) {
-      case 0: // Reserved (not yet defined)
-        BX_ERROR(( "#get_descriptor_l(): type %d not finished\n", d->type ));
-        return(0);
-
-      case 1: // available 16bit TSS
-        val = ((d->u.tss286.base & 0xffff) << 16) |
-               (d->u.tss286.limit & 0xffff);
-        return(val);
-
-      case 2: // LDT
-        val = ((d->u.ldt.base & 0xffff) << 16) |
-              d->u.ldt.limit;
-        return(val);
-
-      case 9: // available 32bit TSS
-        val = ((d->u.tss386.base & 0xffff) << 16) |
-               (d->u.tss386.limit & 0xffff);
-        return(val);
-
-      default:
-        BX_ERROR(( "#get_descriptor_l(): type %d not finished\n", d->type ));
-        return(0);
-      }
-    }
-}
-
-  Bit32u
-BX_CPU_C::dbg_get_descriptor_h(bx_descriptor_t *d)
-{
-  Bit32u val;
-
-  if (d->valid == 0) {
-    return(0);
-    }
-
-  if (d->segment) {
-    val = (d->u.segment.base & 0xff000000) |
-          ((d->u.segment.base >> 16) & 0x000000ff) |
-          (d->u.segment.executable << 11) |
-          (d->u.segment.c_ed << 10) |
-          (d->u.segment.r_w << 9) |
-          (d->u.segment.a << 8) |
-          (d->segment << 12) |
-          (d->dpl << 13) |
-          (d->p << 15) |
-          (d->u.segment.limit & 0xf0000) |
-          (d->u.segment.avl << 20) |
-          (d->u.segment.d_b << 22) |
-          (d->u.segment.g << 23);
-    return(val);
-    }
-  else {
-    switch (d->type) {
-      case 0: // Reserved (not yet defined)
-        BX_ERROR(( "#get_descriptor_h(): type %d not finished\n", d->type ));
-        return(0);
-
-      case 1: // available 16bit TSS
-        val = ((d->u.tss286.base >> 16) & 0xff) |
-              (d->type << 8) |
-              (d->dpl << 13) |
-              (d->p << 15);
-        return(val);
-
-      case 2: // LDT
-        val = ((d->u.ldt.base >> 16) & 0xff) |
-              (d->type << 8) |
-              (d->dpl << 13) |
-              (d->p << 15) |
-              (d->u.ldt.base & 0xff000000);
-        return(val);
-
-      case 9: // available 32bit TSS
-        val = ((d->u.tss386.base >> 16) & 0xff) |
-              (d->type << 8) |
-              (d->dpl << 13) |
-              (d->p << 15) |
-              (d->u.tss386.limit & 0xf0000) |
-              (d->u.tss386.avl << 20) |
-              (d->u.tss386.g << 23) |
-              (d->u.tss386.base & 0xff000000);
-        return(val);
-
-      default:
-        BX_ERROR(( "#get_descriptor_h(): type %d not finished\n", d->type ));
-        return(0);
-      }
-    }
-}
-
-  Boolean
-BX_CPU_C::dbg_get_sreg(bx_dbg_sreg_t *sreg, unsigned sreg_no)
-{
-  if (sreg_no > 5)
-    return(0);
-  sreg->sel   = BX_CPU_THIS_PTR sregs[sreg_no].selector.value;
-  sreg->des_l = dbg_get_descriptor_l(&BX_CPU_THIS_PTR sregs[sreg_no].cache);
-  sreg->des_h = dbg_get_descriptor_h(&BX_CPU_THIS_PTR sregs[sreg_no].cache);
-  sreg->valid = BX_CPU_THIS_PTR sregs[sreg_no].cache.valid;
-  return(1);
-}
-
-  Boolean
-BX_CPU_C::dbg_get_cpu(bx_dbg_cpu_t *cpu)
-{
-  cpu->eax = EAX;
-  cpu->ebx = EBX;
-  cpu->ecx = ECX;
-  cpu->edx = EDX;
-
-  cpu->ebp = EBP;
-  cpu->esi = ESI;
-  cpu->edi = EDI;
-  cpu->esp = ESP;
-
-  cpu->eflags = dbg_get_eflags();
-  cpu->eip    = BX_CPU_THIS_PTR eip;
-
-  cpu->cs.sel   = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
-  cpu->cs.des_l = dbg_get_descriptor_l(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache);
-  cpu->cs.des_h = dbg_get_descriptor_h(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache);
-  cpu->cs.valid = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid;
-
-  cpu->ss.sel   = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value;
-  cpu->ss.des_l = dbg_get_descriptor_l(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache);
-  cpu->ss.des_h = dbg_get_descriptor_h(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache);
-  cpu->ss.valid = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid;
-
-  cpu->ds.sel   = BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value;
-  cpu->ds.des_l = dbg_get_descriptor_l(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache);
-  cpu->ds.des_h = dbg_get_descriptor_h(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache);
-  cpu->ds.valid = BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.valid;
-
-  cpu->es.sel   = BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value;
-  cpu->es.des_l = dbg_get_descriptor_l(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache);
-  cpu->es.des_h = dbg_get_descriptor_h(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache);
-  cpu->es.valid = BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.valid;
-
-  cpu->fs.sel   = BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value;
-  cpu->fs.des_l = dbg_get_descriptor_l(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache);
-  cpu->fs.des_h = dbg_get_descriptor_h(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache);
-  cpu->fs.valid = BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.valid;
-
-  cpu->gs.sel   = BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value;
-  cpu->gs.des_l = dbg_get_descriptor_l(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache);
-  cpu->gs.des_h = dbg_get_descriptor_h(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache);
-  cpu->gs.valid = BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.valid;
-
-
-  cpu->ldtr.sel   = BX_CPU_THIS_PTR ldtr.selector.value;
-  cpu->ldtr.des_l = dbg_get_descriptor_l(&BX_CPU_THIS_PTR ldtr.cache);
-  cpu->ldtr.des_h = dbg_get_descriptor_h(&BX_CPU_THIS_PTR ldtr.cache);
-  cpu->ldtr.valid = BX_CPU_THIS_PTR ldtr.cache.valid;
-
-  cpu->tr.sel   = BX_CPU_THIS_PTR tr.selector.value;
-  cpu->tr.des_l = dbg_get_descriptor_l(&BX_CPU_THIS_PTR tr.cache);
-  cpu->tr.des_h = dbg_get_descriptor_h(&BX_CPU_THIS_PTR tr.cache);
-  cpu->tr.valid = BX_CPU_THIS_PTR tr.cache.valid;
-
-  cpu->gdtr.base  = BX_CPU_THIS_PTR gdtr.base;
-  cpu->gdtr.limit = BX_CPU_THIS_PTR gdtr.limit;
-
-  cpu->idtr.base  = BX_CPU_THIS_PTR idtr.base;
-  cpu->idtr.limit = BX_CPU_THIS_PTR idtr.limit;
-
-  cpu->dr0 = BX_CPU_THIS_PTR dr0;
-  cpu->dr1 = BX_CPU_THIS_PTR dr1;
-  cpu->dr2 = BX_CPU_THIS_PTR dr2;
-  cpu->dr3 = BX_CPU_THIS_PTR dr3;
-  cpu->dr6 = BX_CPU_THIS_PTR dr6;
-  cpu->dr7 = BX_CPU_THIS_PTR dr7;
-
-  cpu->tr3 = 0;
-  cpu->tr4 = 0;
-  cpu->tr5 = 0;
-  cpu->tr6 = 0;
-  cpu->tr7 = 0;
-
-  // cr0:32=pg,cd,nw,am,wp,ne,ts,em,mp,pe
-  cpu->cr0 = BX_CPU_THIS_PTR cr0.val32;
-  cpu->cr1 = 0;
-  cpu->cr2 = BX_CPU_THIS_PTR cr2;
-  cpu->cr3 = BX_CPU_THIS_PTR cr3;
-  cpu->cr4 = 0;
-
-  cpu->inhibit_mask = BX_CPU_THIS_PTR inhibit_mask;
-
-  return(1);
-}
-
-  Boolean
-BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
-{
-  // returns 1=OK, 0=Error
-  Bit32u val;
-  Bit32u type;
-
-  // =================================================
-  // Do checks first, before setting any CPU registers
-  // =================================================
-
-  // CS, SS, DS, ES, FS, GS descriptor checks
-  if (!cpu->cs.valid) {
-    BX_ERROR(( "Error: CS not valid\n" ));
-    return(0); // error
-    }
-  if ( (cpu->cs.des_h & 0x1000) == 0 ) {
-    BX_ERROR(( "Error: CS not application type\n" ));
-    return(0); // error
-    }
-  if ( (cpu->cs.des_h & 0x0800) == 0 ) {
-    BX_ERROR(( "Error: CS not executable\n" ));
-    return(0); // error
-    }
-
-  if (!cpu->ss.valid) {
-    BX_ERROR(( "Error: SS not valid\n" ));
-    return(0); // error
-    }
-  if ( (cpu->ss.des_h & 0x1000) == 0 ) {
-    BX_ERROR(( "Error: SS not application type\n" ));
-    return(0); // error
-    }
-
-  if (cpu->ds.valid) {
-    if ( (cpu->ds.des_h & 0x1000) == 0 ) {
-      BX_ERROR(( "Error: DS not application type\n" ));
-      return(0); // error
-      }
-    }
-
-  if (cpu->es.valid) {
-    if ( (cpu->es.des_h & 0x1000) == 0 ) {
-      BX_ERROR(( "Error: ES not application type\n" ));
-      return(0); // error
-      }
-    }
-
-  if (cpu->fs.valid) {
-    if ( (cpu->fs.des_h & 0x1000) == 0 ) {
-      BX_ERROR(( "Error: FS not application type\n" ));
-      return(0); // error
-      }
-    }
-
-  if (cpu->gs.valid) {
-    if ( (cpu->gs.des_h & 0x1000) == 0 ) {
-      BX_ERROR(( "Error: GS not application type\n" ));
-      return(0); // error
-      }
-    }
-
-  if (cpu->ldtr.valid) {
-    if ( cpu->ldtr.des_h & 0x1000 ) {
-      BX_ERROR(( "Error: LDTR not system type\n" ));
-      return(0); // error
-      }
-    if ( ((cpu->ldtr.des_h >> 8) & 0x0f) != 2 ) {
-      BX_ERROR(( "Error: LDTR descriptor type not LDT\n" ));
-      return(0); // error
-      }
-    }
-
-  if (cpu->tr.valid) {
-    if ( cpu->tr.des_h & 0x1000 ) {
-      BX_ERROR(( "Error: TR not system type\n"));
-      return(0); // error
-      }
-    type = (cpu->tr.des_h >> 8) & 0x0f;
-
-    if ( (type != 1) && (type != 9) ) {
-      BX_ERROR(( "Error: TR descriptor type not TSS\n" ));
-      return(0); // error
-      }
-    }
-
-  // =============
-  // end of checks
-  // =============
-
-  EAX = cpu->eax;
-  EBX = cpu->ebx;
-  ECX = cpu->ecx;
-  EDX = cpu->edx;
-  EBP = cpu->ebp;
-  ESI = cpu->esi;
-  EDI = cpu->edi;
-  ESP = cpu->esp;
-
-  // eflags
-  val = cpu->eflags;
-  BX_CPU_THIS_PTR set_CF(val & 0x01); val >>= 2;
-  BX_CPU_THIS_PTR set_PF(val & 0x01); val >>= 2;
-  BX_CPU_THIS_PTR set_AF(val & 0x01); val >>= 2;
-  BX_CPU_THIS_PTR set_ZF(val & 0x01); val >>= 1;
-  BX_CPU_THIS_PTR set_SF(val & 0x01); val >>= 1;
-  BX_CPU_THIS_PTR eflags.tf  = val & 0x01; val >>= 1;
-  BX_CPU_THIS_PTR eflags.if_ = val & 0x01; val >>= 1;
-  BX_CPU_THIS_PTR eflags.df  = val & 0x01; val >>= 1;
-  BX_CPU_THIS_PTR set_OF(val & 0x01); val >>= 1;
-  BX_CPU_THIS_PTR eflags.iopl = val & 0x03; val >>= 2;
-  BX_CPU_THIS_PTR eflags.nt   = val & 0x01; val >>= 2;
-  BX_CPU_THIS_PTR eflags.rf   = val & 0x01; val >>= 1;
-  BX_CPU_THIS_PTR eflags.vm   = val & 0x01; val >>= 1;
-#if BX_CPU_LEVEL >= 4
-  BX_CPU_THIS_PTR eflags.ac   = val & 0x01; val >>= 1;
-  //BX_CPU_THIS_PTR eflags.vif  = val & 0x01;
-  val >>= 1;
-  //BX_CPU_THIS_PTR eflags.vip  = val & 0x01;
-  val >>= 1;
-  BX_CPU_THIS_PTR eflags.id   = val & 0x01;
-#endif
-
-  BX_CPU_THIS_PTR eip = cpu->eip;
-
-
-
-  // CS:
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = cpu->cs.sel;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.index = cpu->cs.sel >> 3;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.ti    = (cpu->cs.sel >> 2) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl   = cpu->cs.sel & 0x03;
-
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid            = cpu->cs.valid;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p                = (cpu->cs.des_h >> 15) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl              = (cpu->cs.des_h >> 13) & 0x03;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment          = (cpu->cs.des_h >> 12) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type             = (cpu->cs.des_h >> 8) & 0x0f;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = (cpu->cs.des_h >> 11) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed   = (cpu->cs.des_h >> 10) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w    = (cpu->cs.des_h >> 9) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.a      = (cpu->cs.des_h >> 8) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base   = (cpu->cs.des_l >> 16);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base  |= (cpu->cs.des_h & 0xff) << 16;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base  |= (cpu->cs.des_h & 0xff000000);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit  = (cpu->cs.des_l & 0xffff);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit |= (cpu->cs.des_h & 0x000f0000);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g      = (cpu->cs.des_h >> 23) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b    = (cpu->cs.des_h >> 22) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl    = (cpu->cs.des_h >> 20) & 0x01;
-  if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g)
-    BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled =
-      (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit << 12) | 0x0fff;
-  else
-    BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled =
-      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit;
-
-
-  // SS:
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value = cpu->ss.sel;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.index = cpu->ss.sel >> 3;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.ti    = (cpu->ss.sel >> 2) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.rpl   = cpu->ss.sel & 0x03;
-
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid            = cpu->ss.valid;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p                = (cpu->ss.des_h >> 15) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl              = (cpu->ss.des_h >> 13) & 0x03;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment          = (cpu->ss.des_h >> 12) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type             = (cpu->ss.des_h >> 8) & 0x0f;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.executable = (cpu->ss.des_h >> 11) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.c_ed   = (cpu->ss.des_h >> 10) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.r_w    = (cpu->ss.des_h >> 9) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.a      = (cpu->ss.des_h >> 8) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base   = (cpu->ss.des_l >> 16);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base  |= (cpu->ss.des_h & 0xff) << 16;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base  |= (cpu->ss.des_h & 0xff000000);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit  = (cpu->ss.des_l & 0xffff);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit |= (cpu->ss.des_h & 0x000f0000);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g      = (cpu->ss.des_h >> 23) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b    = (cpu->ss.des_h >> 22) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.avl    = (cpu->ss.des_h >> 20) & 0x01;
-  if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g)
-    BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled =
-      (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit << 12) | 0x0fff;
-  else
-    BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled =
-      BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit;
-
-
-  // DS:
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value = cpu->ds.sel;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.index = cpu->ds.sel >> 3;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.ti    = (cpu->ds.sel >> 2) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.rpl   = cpu->ds.sel & 0x03;
-
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.valid            = cpu->ds.valid;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.p                = (cpu->ds.des_h >> 15) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.dpl              = (cpu->ds.des_h >> 13) & 0x03;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.segment          = (cpu->ds.des_h >> 12) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.type             = (cpu->ds.des_h >> 8) & 0x0f;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.executable = (cpu->ds.des_h >> 11) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.c_ed   = (cpu->ds.des_h >> 10) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.r_w    = (cpu->ds.des_h >> 9) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.a      = (cpu->ds.des_h >> 8) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.base   = (cpu->ds.des_l >> 16);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.base  |= (cpu->ds.des_h & 0xff) << 16;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.base  |= (cpu->ds.des_h & 0xff000000);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit  = (cpu->ds.des_l & 0xffff);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit |= (cpu->ds.des_h & 0x000f0000);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.g      = (cpu->ds.des_h >> 23) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.d_b    = (cpu->ds.des_h >> 22) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.avl    = (cpu->ds.des_h >> 20) & 0x01;
-  if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.g)
-    BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled =
-      (BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit << 12) | 0x0fff;
-  else
-    BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled =
-      BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit;
-
-
-
-  // ES:
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value = cpu->es.sel;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.index = cpu->es.sel >> 3;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.ti    = (cpu->es.sel >> 2) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.rpl   = cpu->es.sel & 0x03;
-
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.valid            = cpu->es.valid;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.p                = (cpu->es.des_h >> 15) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.dpl              = (cpu->es.des_h >> 13) & 0x03;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.segment          = (cpu->es.des_h >> 12) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.type             = (cpu->es.des_h >> 8) & 0x0f;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.executable = (cpu->es.des_h >> 11) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.c_ed   = (cpu->es.des_h >> 10) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.r_w    = (cpu->es.des_h >> 9) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.a      = (cpu->es.des_h >> 8) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.base   = (cpu->es.des_l >> 16);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.base  |= (cpu->es.des_h & 0xff) << 16;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.base  |= (cpu->es.des_h & 0xff000000);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.limit  = (cpu->es.des_l & 0xffff);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.limit |= (cpu->es.des_h & 0x000f0000);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.g      = (cpu->es.des_h >> 23) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.d_b    = (cpu->es.des_h >> 22) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.avl    = (cpu->es.des_h >> 20) & 0x01;
-  if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.g)
-    BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.limit_scaled =
-      (BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.limit << 12) | 0x0fff;
-  else
-    BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.limit_scaled =
-      BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.limit;
-
-
-  // FS:
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value = cpu->fs.sel;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.index = cpu->fs.sel >> 3;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.ti    = (cpu->fs.sel >> 2) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.rpl   = cpu->fs.sel & 0x03;
-
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.valid            = cpu->fs.valid;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.p                = (cpu->fs.des_h >> 15) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.dpl              = (cpu->fs.des_h >> 13) & 0x03;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.segment          = (cpu->fs.des_h >> 12) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.type             = (cpu->fs.des_h >> 8) & 0x0f;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.executable = (cpu->fs.des_h >> 11) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.c_ed   = (cpu->fs.des_h >> 10) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.r_w    = (cpu->fs.des_h >> 9) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.a      = (cpu->fs.des_h >> 8) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.base   = (cpu->fs.des_l >> 16);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.base  |= (cpu->fs.des_h & 0xff) << 16;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.base  |= (cpu->fs.des_h & 0xff000000);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.limit  = (cpu->fs.des_l & 0xffff);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.limit |= (cpu->fs.des_h & 0x000f0000);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.g      = (cpu->fs.des_h >> 23) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.d_b    = (cpu->fs.des_h >> 22) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.avl    = (cpu->fs.des_h >> 20) & 0x01;
-  if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.g)
-    BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.limit_scaled =
-      (BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.limit << 12) | 0x0fff;
-  else
-    BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.limit_scaled =
-      BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.limit;
-
-
-  // GS:
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value = cpu->gs.sel;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.index = cpu->gs.sel >> 3;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.ti    = (cpu->gs.sel >> 2) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.rpl   = cpu->gs.sel & 0x03;
-
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.valid            = cpu->gs.valid;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.p                = (cpu->gs.des_h >> 15) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.dpl              = (cpu->gs.des_h >> 13) & 0x03;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.segment          = (cpu->gs.des_h >> 12) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.type             = (cpu->gs.des_h >> 8) & 0x0f;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.executable = (cpu->gs.des_h >> 11) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.c_ed   = (cpu->gs.des_h >> 10) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.r_w    = (cpu->gs.des_h >> 9) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.a      = (cpu->gs.des_h >> 8) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.base   = (cpu->gs.des_l >> 16);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.base  |= (cpu->gs.des_h & 0xff) << 16;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.base  |= (cpu->gs.des_h & 0xff000000);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.limit  = (cpu->gs.des_l & 0xffff);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.limit |= (cpu->gs.des_h & 0x000f0000);
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.g      = (cpu->gs.des_h >> 23) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.d_b    = (cpu->gs.des_h >> 22) & 0x01;
-  BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.avl    = (cpu->gs.des_h >> 20) & 0x01;
-  if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.g)
-    BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.limit_scaled =
-      (BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.limit << 12) | 0x0fff;
-  else
-    BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.limit_scaled =
-      BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.limit;
-
-  // LDTR:
-  BX_CPU_THIS_PTR ldtr.selector.value = cpu->ldtr.sel;
-  BX_CPU_THIS_PTR ldtr.selector.index = cpu->ldtr.sel >> 3;
-  BX_CPU_THIS_PTR ldtr.selector.ti    = (cpu->ldtr.sel >> 2) & 0x01;
-  BX_CPU_THIS_PTR ldtr.selector.rpl   = cpu->ldtr.sel & 0x03;
-
-  BX_CPU_THIS_PTR ldtr.cache.valid            = cpu->ldtr.valid;
-  BX_CPU_THIS_PTR ldtr.cache.p                = (cpu->ldtr.des_h >> 15) & 0x01;
-  BX_CPU_THIS_PTR ldtr.cache.dpl              = (cpu->ldtr.des_h >> 13) & 0x03;
-  BX_CPU_THIS_PTR ldtr.cache.segment          = (cpu->ldtr.des_h >> 12) & 0x01;
-  BX_CPU_THIS_PTR ldtr.cache.type             = (cpu->ldtr.des_h >> 8) & 0x0f;
-  BX_CPU_THIS_PTR ldtr.cache.u.ldt.base       = (cpu->ldtr.des_l >> 16);
-  BX_CPU_THIS_PTR ldtr.cache.u.ldt.base      |= (cpu->ldtr.des_h & 0xff) << 16;
-  BX_CPU_THIS_PTR ldtr.cache.u.ldt.base      |= (cpu->ldtr.des_h & 0xff000000);
-  BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit      = (cpu->ldtr.des_l & 0xffff);
-
-  // TR
-  type = (cpu->tr.des_h >> 8) & 0x0f;
-  BX_CPU_THIS_PTR tr.selector.value = cpu->tr.sel;
-  BX_CPU_THIS_PTR tr.selector.index = cpu->tr.sel >> 3;
-  BX_CPU_THIS_PTR tr.selector.ti    = (cpu->tr.sel >> 2) & 0x01;
-  BX_CPU_THIS_PTR tr.selector.rpl   = cpu->tr.sel & 0x03;
-
-  BX_CPU_THIS_PTR tr.cache.valid            = cpu->tr.valid;
-  BX_CPU_THIS_PTR tr.cache.p                = (cpu->tr.des_h >> 15) & 0x01;
-  BX_CPU_THIS_PTR tr.cache.dpl              = (cpu->tr.des_h >> 13) & 0x03;
-  BX_CPU_THIS_PTR tr.cache.segment          = (cpu->tr.des_h >> 12) & 0x01;
-  BX_CPU_THIS_PTR tr.cache.type             = type;
-  if (type == 1) { // 286 TSS
-    BX_CPU_THIS_PTR tr.cache.u.tss286.base   = (cpu->tr.des_l >> 16);
-    BX_CPU_THIS_PTR tr.cache.u.tss286.base  |= (cpu->tr.des_h & 0xff) << 16;
-    BX_CPU_THIS_PTR tr.cache.u.tss286.limit  = (cpu->tr.des_l & 0xffff);
-    }
-  else { // type == 9, 386 TSS
-    BX_CPU_THIS_PTR tr.cache.u.tss386.base   = (cpu->tr.des_l >> 16);
-    BX_CPU_THIS_PTR tr.cache.u.tss386.base  |= (cpu->tr.des_h & 0xff) << 16;
-    BX_CPU_THIS_PTR tr.cache.u.tss386.base  |= (cpu->tr.des_h & 0xff000000);
-    BX_CPU_THIS_PTR tr.cache.u.tss386.limit  = (cpu->tr.des_l & 0xffff);
-    BX_CPU_THIS_PTR tr.cache.u.tss386.limit |= (cpu->tr.des_h & 0x000f0000);
-    BX_CPU_THIS_PTR tr.cache.u.tss386.g      = (cpu->tr.des_h >> 23) & 0x01;
-    BX_CPU_THIS_PTR tr.cache.u.tss386.avl    = (cpu->tr.des_h >> 20) & 0x01;
-    }
-
-
-  // gdtr
-  BX_CPU_THIS_PTR gdtr.base  = cpu->gdtr.base;
-  BX_CPU_THIS_PTR gdtr.limit = cpu->gdtr.limit;
-
-  // idtr
-  BX_CPU_THIS_PTR idtr.base  = cpu->idtr.base;
-  BX_CPU_THIS_PTR idtr.limit = cpu->idtr.limit;
-
-
-  BX_CPU_THIS_PTR dr0 = cpu->dr0;
-  BX_CPU_THIS_PTR dr1 = cpu->dr1;
-  BX_CPU_THIS_PTR dr2 = cpu->dr2;
-  BX_CPU_THIS_PTR dr3 = cpu->dr3;
-  BX_CPU_THIS_PTR dr6 = cpu->dr6;
-  BX_CPU_THIS_PTR dr7 = cpu->dr7;
-
-  // BX_CPU_THIS_PTR tr3 = cpu->tr3;
-  // BX_CPU_THIS_PTR tr4 = cpu->tr4;
-  // BX_CPU_THIS_PTR tr5 = cpu->tr5;
-  // BX_CPU_THIS_PTR tr6 = cpu->tr6;
-  // BX_CPU_THIS_PTR tr7 = cpu->tr7;
-
-
-  // cr0, cr1, cr2, cr3, cr4
-  SetCR0(cpu->cr0);
-  BX_CPU_THIS_PTR cr1 = cpu->cr1;
-  BX_CPU_THIS_PTR cr2 = cpu->cr2;
-  BX_CPU_THIS_PTR cr3 = cpu->cr3;
-#if BX_CPU_LEVEL >= 5
-  BX_CPU_THIS_PTR cr4 = cpu->cr4;
-#endif
-
-  BX_CPU_THIS_PTR inhibit_mask = cpu->inhibit_mask;
-
-  //
-  // flush cached items, prefetch, paging, etc
-  //
-  BX_CPU_THIS_PTR CR3_change(cpu->cr3);
-  BX_CPU_THIS_PTR invalidate_prefetch_q();
-  BX_CPU_THIS_PTR async_event = 1;
-
-  return(1);
-}
-
-#if BX_SIM_ID == 0
-#  define BX_DBG_NULL_CALLBACK bx_dbg_null_callback0
-#else
-#  define BX_DBG_NULL_CALLBACK bx_dbg_null_callback1
-#endif
-  void
-BX_DBG_NULL_CALLBACK(unsigned val)
-{
-  // bochs uses the pc_system variables, so this function is
-  // a stub for notification by the debugger, that a change
-  // occurred.
-  UNUSED(val);
-}
-
-  void
-#if BX_SIM_ID == 0
-bx_dbg_init_cpu_mem_env0(bx_dbg_callback_t *callback, int argc, char *argv[])
-#else
-bx_dbg_init_cpu_mem_env1(bx_dbg_callback_t *callback, int argc, char *argv[])
-#endif
-{
-  UNUSED(argc);
-  UNUSED(argv);
-
-#if 0
-#warning hardcoding BX_CPU_THIS_PTR mem[0] and cpu[0]
-  callback->setphymem           = BX_MEM(0)->dbg_set_mem;
-  callback->getphymem           = BX_MEM(0)->dbg_fetch_mem;
-  callback->xlate_linear2phy    = BX_CPU(0)->dbg_xlate_linear2phy;
-  callback->set_reg             = BX_CPU(0)->dbg_set_reg;
-  callback->get_reg             = BX_CPU(0)->dbg_get_reg;
-  callback->get_sreg            = BX_CPU(0)->dbg_get_sreg;
-  callback->get_cpu             = BX_CPU(0)->dbg_get_cpu;
-  callback->set_cpu             = BX_CPU(0)->dbg_set_cpu;
-  callback->dirty_page_tbl_size = sizeof(BX_MEM(0)->dbg_dirty_pages);
-  callback->dirty_page_tbl      = BX_MEM(0)->dbg_dirty_pages;
-  callback->atexit              = BX_CPU(0)->atexit;
-  callback->query_pending       = BX_CPU(0)->dbg_query_pending;
-  callback->execute             = BX_CPU(0)->cpu_loop;
-  callback->take_irq            = BX_CPU(0)->dbg_take_irq;
-  callback->take_dma            = BX_CPU(0)->dbg_take_dma;
-  callback->reset_cpu           = BX_CPU(0)->reset;
-  callback->init_mem            = BX_MEM(0)->init_memory;
-  callback->load_ROM            = BX_MEM(0)->load_ROM;
-  callback->set_A20             = NULL;
-  callback->set_NMI             = BX_DBG_NULL_CALLBACK;
-  callback->set_RESET           = BX_DBG_NULL_CALLBACK;
-  callback->set_INTR            = BX_CPU(0)->set_INTR;
-  callback->force_interrupt     = BX_CPU(0)->dbg_force_interrupt;
-
-#if BX_INSTRUMENTATION
-  callback->instr_start         = bx_instr_start;
-  callback->instr_stop          = bx_instr_stop;
-  callback->instr_reset         = bx_instr_reset;
-  callback->instr_print         = bx_instr_print;
-#endif
-#if BX_USE_LOADER
-  callback->loader              = bx_dbg_loader;
-#endif
-  callback->crc32               = BX_MEM(0)->dbg_crc32;
-#endif
-}
-
-
-
-  void
-BX_CPU_C::atexit(void)
-{
-  if (protected_mode()) BX_INFO(("protected mode\n" ));
-  else if (v8086_mode()) BX_INFO(("v8086 mode\n" ));
-  else BX_INFO(("real mode\n"));
-  BX_INFO(("CS.d_b = %u bit\n",
-    BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.d_b ? 32 : 16 ));
-  if (protected_mode()) BX_INFO(("protected mode\n"));
-  else if (v8086_mode()) BX_INFO(("v8086 mode\n"));
-  else BX_INFO(("real mode\n"));
-  BX_INFO(("CS.d_b = %u bit\n",
-    BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.d_b ? 32 : 16));
-  BX_INFO(("SS.d_b = %u bit\n",
-    BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.d_b ? 32 : 16));
-
-  debug(BX_CPU_THIS_PTR prev_eip);
-}
-#endif  // #if BX_DEBUGGER
index ae4da69..44cc96e 100644 (file)
@@ -152,7 +152,161 @@ BX_CPU_C::debug(Bit32u offset)
 #endif  // #if BX_DISASM
 }
 
+#if BX_SUPPORT_SID
+  Bit32u
+BX_CPU_C::dbg_get_reg(unsigned reg)
+{
+  Bit32u return_val32;
+
+  switch (reg) {
+    case BX_DBG_REG_EAX: return(EAX);
+    case BX_DBG_REG_ECX: return(ECX);
+    case BX_DBG_REG_EDX: return(EDX);
+    case BX_DBG_REG_EBX: return(EBX);
+    case BX_DBG_REG_ESP: return(ESP);
+    case BX_DBG_REG_EBP: return(EBP);
+    case BX_DBG_REG_ESI: return(ESI);
+    case BX_DBG_REG_EDI: return(EDI);
+    case BX_DBG_REG_EIP: return(EIP);
+    case BX_DBG_REG_EFLAGS:
+      return_val32 = dbg_get_eflags();
+      return(return_val32);
+    case BX_DBG_REG_CS: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
+    case BX_DBG_REG_SS: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value);
+    case BX_DBG_REG_DS: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value);
+    case BX_DBG_REG_ES: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value);
+    case BX_DBG_REG_FS: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value);
+    case BX_DBG_REG_GS: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value);
+    default:
+      BX_PANIC(("get_reg: request for unknown register\n"));
+      return(0);
+    }
+}
+
+  Boolean
+BX_CPU_C::dbg_set_reg(unsigned reg, Bit32u val)
+{
+  // returns 1=OK, 0=can't change
+  bx_segment_reg_t *seg;
+  Bit32u current_sys_bits;
+
+  switch (reg) {
+    case BX_DBG_REG_EAX: EAX = val; return(1);
+    case BX_DBG_REG_ECX: ECX = val; return(1);
+    case BX_DBG_REG_EDX: EDX = val; return(1);
+    case BX_DBG_REG_EBX: EBX = val; return(1);
+    case BX_DBG_REG_ESP: ESP = val; return(1);
+    case BX_DBG_REG_EBP: EBP = val; return(1);
+    case BX_DBG_REG_ESI: ESI = val; return(1);
+    case BX_DBG_REG_EDI: EDI = val; return(1);
+    case BX_DBG_REG_EIP: EIP = val; return(1);
+    case BX_DBG_REG_EFLAGS:
+      BX_INFO(("dbg_set_reg: can not handle eflags yet.\n"));
+      if ( val & 0xffff0000 ) {
+        BX_INFO(("dbg_set_reg: can not set upper 16 bits of eflags.\n"));
+        return(0);
+        }
+      // make sure none of the system bits are being changed
+      current_sys_bits = (BX_CPU_THIS_PTR eflags.nt << 14) |
+                         (BX_CPU_THIS_PTR eflags.iopl << 12) |
+                         (BX_CPU_THIS_PTR eflags.tf << 8);
+      if ( current_sys_bits != (val & 0x0000f100) ) {
+        BX_INFO(("dbg_set_reg: can not modify NT, IOPL, or TF.\n"));
+        return(0);
+        }
+      BX_CPU_THIS_PTR set_CF(val & 0x01); val >>= 2;
+      BX_CPU_THIS_PTR set_PF(val & 0x01); val >>= 2;
+      BX_CPU_THIS_PTR set_AF(val & 0x01); val >>= 2;
+      BX_CPU_THIS_PTR set_ZF(val & 0x01); val >>= 1;
+      BX_CPU_THIS_PTR set_SF(val & 0x01); val >>= 2;
+      BX_CPU_THIS_PTR eflags.if_ = val & 0x01; val >>= 1;
+      BX_CPU_THIS_PTR eflags.df  = val & 0x01; val >>= 1;
+      BX_CPU_THIS_PTR set_OF(val & 0x01);
+      if (BX_CPU_THIS_PTR eflags.if_)
+        BX_CPU_THIS_PTR async_event = 1;
+      return(1);
+    case BX_DBG_REG_CS:
+      seg = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS];
+      break;
+    case BX_DBG_REG_SS:
+      seg = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS];
+      break;
+    case BX_DBG_REG_DS:
+      seg = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS];
+      break;
+    case BX_DBG_REG_ES:
+      seg = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES];
+      break;
+    case BX_DBG_REG_FS:
+      seg = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS];
+      break;
+    case BX_DBG_REG_GS:
+      seg = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS];
+      break;
+    default:
+      BX_PANIC(("dbg_set_reg: unrecognized register ID (%u)\n", reg));
+      return(0);
+    }
+
+  if (BX_CPU_THIS_PTR real_mode()) {
+    seg->selector.value = val;
+    seg->cache.valid = 1;
+    seg->cache.p = 1;
+    seg->cache.dpl = 0;
+    seg->cache.segment = 1; // regular segment
+    if (reg == BX_DBG_REG_CS) {
+      seg->cache.u.segment.executable = 1; // code segment
+      }
+    else {
+      seg->cache.u.segment.executable = 0; // data segment
+      }
+    seg->cache.u.segment.c_ed = 0;       // expand up/non-conforming
+    seg->cache.u.segment.r_w = 1;        // writeable
+    seg->cache.u.segment.a = 1;          // accessed
+    seg->cache.u.segment.base = val << 4;
+    seg->cache.u.segment.limit        = 0xffff;
+    seg->cache.u.segment.limit_scaled = 0xffff;
+    seg->cache.u.segment.g     = 0;      // byte granular
+    seg->cache.u.segment.d_b   = 0;      // default 16bit size
+    seg->cache.u.segment.avl   = 0;
+    return(1); // ok
+    }
+
+  return(0); // can't change when not in real mode
+}
 
+  Bit32u
+BX_CPU_C::dbg_get_eflags(void)
+{
+  Bit32u val32;
+
+  val32 =
+    (BX_CPU_THIS_PTR get_CF()) |
+    (BX_CPU_THIS_PTR eflags.bit1 << 1) |
+    ((BX_CPU_THIS_PTR get_PF()) << 2) |
+    (BX_CPU_THIS_PTR eflags.bit3 << 3) |
+    ((BX_CPU_THIS_PTR get_AF()>0) << 4) |
+    (BX_CPU_THIS_PTR eflags.bit5 << 5) |
+    ((BX_CPU_THIS_PTR get_ZF()>0) << 6) |
+    ((BX_CPU_THIS_PTR get_SF()>0) << 7) |
+    (BX_CPU_THIS_PTR eflags.tf << 8) |
+    (BX_CPU_THIS_PTR eflags.if_ << 9) |
+    (BX_CPU_THIS_PTR eflags.df << 10) |
+    ((BX_CPU_THIS_PTR get_OF()>0) << 11) |
+    (BX_CPU_THIS_PTR eflags.iopl << 12) |
+    (BX_CPU_THIS_PTR eflags.nt << 14) |
+    (BX_CPU_THIS_PTR eflags.bit15 << 15) |
+    (BX_CPU_THIS_PTR eflags.rf << 16) |
+    (BX_CPU_THIS_PTR eflags.vm << 17);
+#if BX_CPU_LEVEL >= 4
+  val32 |= (BX_CPU_THIS_PTR eflags.ac << 18);
+  //val32 |= (BX_CPU_THIS_PTR eflags.vif << 19);
+  //val32 |= (BX_CPU_THIS_PTR eflags.vip << 20);
+  val32 |= (BX_CPU_THIS_PTR eflags.id << 21);
+#endif
+  return(val32);
+}
+#else // BX_SUPPORT_SID
 #if BX_DEBUGGER
   Bit32u
 BX_CPU_C::dbg_get_reg(unsigned reg)
@@ -998,6 +1152,7 @@ bx_dbg_init_cpu_mem_env1(bx_dbg_callback_t *callback, int argc, char *argv[])
 }
 
 #endif  // #if BX_DEBUGGER
+#endif // BX_SUPPORT_SID
 
   void
 BX_CPU_C::atexit(void)
index c1951b4..eaf6494 100644 (file)
@@ -28,7 +28,9 @@
 #include "bochs.h"
 #define LOG_THIS BX_CPU_THIS_PTR
 
-#if BX_USE_CPU_SMF
+
+
+#if 0
 static Bit16u *aaa[8] = {
   & BX,
   & BX,
@@ -50,7 +52,8 @@ static Bit16u *bbb[8] = {
   (Bit16u *) & BX_CPU_THIS_PTR empty_register,
   (Bit16u *) & BX_CPU_THIS_PTR empty_register
   };
-#endif  // BX_USE_CPU_SMF
+#endif
+
 
 
 
diff --git a/sid/component/bochs/cpu/exception-sid.cc b/sid/component/bochs/cpu/exception-sid.cc
deleted file mode 100644 (file)
index 9bef31f..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-//  exception-sid.cc - override the bochs cpu interrupt member function. -*- C++ -*-
-//
-//  Copyright (C) 2001 Red Hat.
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-
-
-#define NEED_CPU_REG_SHORTCUTS 1
-#include "bochs.h"
-#define LOG_THIS BX_CPU_THIS_PTR
-
-#include "x86.h"
-
-  void
-sid_cpu_c::interrupt(Bit8u vector, Boolean is_INT, Boolean is_error_code,
-                    Bit16u error_code)
-{
-    if (vector == 0x80)
-    {
-        int temp = this->gen_reg[0].erx;
-        this->sid_cpu->do_syscall();
-#if X86_CPU_DEBUG
-        printf("Syscall number: %d was executed with the following return value: %d\n", temp, this->gen_reg[0].erx);
-#endif
-    }
-    else if (vector == 0x03)
-    {
-        // INT3 was encountered -- trap to debugger
-        this->sid_cpu->do_breakpoint();
-    }
-    else
-    {
-        BX_CPU_C::interrupt(vector, is_INT, is_error_code, error_code);
-    }
-}
index d3561cc..adf2c68 100644 (file)
@@ -27,6 +27,9 @@
 #define LOG_THIS BX_CPU_THIS_PTR
 
 
+#if BX_SUPPORT_SID
+#include "sid-x86-cpu-wrapper.h"
+#endif
 
 
 /* Exception classes.  These are used as indexes into the 'is_exception_OK'
@@ -50,6 +53,30 @@ const Boolean BX_CPU_C::is_exception_OK[3][3] = {
 BX_CPU_C::interrupt(Bit8u vector, Boolean is_INT, Boolean is_error_code,
                     Bit16u error_code)
 {
+#if BX_SUPPORT_SID
+  bx_dbg.interrupts = 1;
+  if (!x86_cpu_component->hardware_mode())
+    {
+      // Use 0x80 as the syscall interrupt number.
+      if (vector == 0x80)
+        {
+          int temp = this->gen_reg[0].erx;
+          x86_cpu_component->do_syscall();
+#if X86_CPU_DEBUG
+          printf("Syscall number: %d was executed with the following return value: %d\n", temp, this->gen_reg[0].erx);
+#endif
+          return;
+        }
+      else if (vector == 0x03)
+        {
+          // INT3 was encountered -- trap to debugger.
+          x86_cpu_component->do_breakpoint();
+          return;
+        }
+      // If not performing a syscall, or trapping to the debugger,
+      // fall through to generic interrupt handling.
+    }
+#endif
 #if BX_DEBUGGER
   BX_CPU_THIS_PTR show_flag |= Flag_intsig;
 #if BX_DEBUG_LINUX
diff --git a/sid/component/bochs/cpu/fetchdecode-sid.cc b/sid/component/bochs/cpu/fetchdecode-sid.cc
deleted file mode 100644 (file)
index 9aebcae..0000000
+++ /dev/null
@@ -1,1905 +0,0 @@
-//  fetchdecode-sid.cc - override the bochs cpu fetchdecode member function. -*- C++ -*-
-//
-//  Copyright (C) 2001 Red Hat.
-//
-//  Copyright (C) 2001  MandrakeSoft S.A.
-//
-//    MandrakeSoft S.A.
-//    43, rue d'Aboukir
-//    75002 Paris - France
-//    http://www.linux-mandrake.com/
-//    http://www.mandrakesoft.com/
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-
-#define NEED_CPU_REG_SHORTCUTS 1
-#include "bochs.h"
-#define LOG_THIS BX_CPU_THIS_PTR
-
-
-///////////////////////////
-// prefix bytes
-// opcode bytes
-// modrm/sib
-// address displacement
-// immediate constant
-///////////////////////////
-
-
-
-// sign extended to osize:
-//   6a push ib
-//   6b imul gvevib
-//   70..7f jo..jnle
-//   83 G1 0..7 ADD..CMP Evib
-
-// is 6b imul_gvevib sign extended?  don't think
-//   I'm sign extending it properly in old decode/execute
-
-//check all the groups.  Make sure to add duplicates rather
-// than error.
-
-// mark instructions as changing control transfer, then
-// don't always load from fetch_ptr, etc.
-
-// cant use immediate as another because of Group3 where
-// some have immediate and some don't, and those won't
-// be picked up by logic until indirection.
-
-// get attr and execute ptr at same time
-
-// maybe move 16bit only i's like  MOV_EwSw, MOV_SwEw
-// to 32 bit modules.
-
-// use 0F as a prefix too?
-
-
-
-#if 0
-void BxResolveError(BxInstruction_t *);
-#endif
-
-#if BX_DYNAMIC_TRANSLATION
-// For 16-bit address mode, this matrix describes the registers
-// used to formulate the offset, indexed by the RM field.
-// This info is needed by the dynamic translation code for dataflow.
-static unsigned BxMemRegsUsed16[8] = {
-  (1<<3) | (1<<6), // BX + SI
-  (1<<3) | (1<<7), // BX + DI
-  (1<<5) | (1<<6), // BP + SI
-  (1<<5) | (1<<7), // BP + DI
-  (1<<6),          // SI
-  (1<<7),          // DI
-  (1<<5),          // BP
-  (1<<3)           // BX
-  };
-#endif
-
-static BxExecutePtr_t BxResolve16Mod0[8] = {
-  &BX_CPU_C::Resolve16Mod0Rm0,
-  &BX_CPU_C::Resolve16Mod0Rm1,
-  &BX_CPU_C::Resolve16Mod0Rm2,
-  &BX_CPU_C::Resolve16Mod0Rm3,
-  &BX_CPU_C::Resolve16Mod0Rm4,
-  &BX_CPU_C::Resolve16Mod0Rm5,
-  NULL, // d16, no registers used
-  &BX_CPU_C::Resolve16Mod0Rm7
-  };
-
-static BxExecutePtr_t BxResolve16Mod1or2[8] = {
-  &BX_CPU_C::Resolve16Mod1or2Rm0,
-  &BX_CPU_C::Resolve16Mod1or2Rm1,
-  &BX_CPU_C::Resolve16Mod1or2Rm2,
-  &BX_CPU_C::Resolve16Mod1or2Rm3,
-  &BX_CPU_C::Resolve16Mod1or2Rm4,
-  &BX_CPU_C::Resolve16Mod1or2Rm5,
-  &BX_CPU_C::Resolve16Mod1or2Rm6,
-  &BX_CPU_C::Resolve16Mod1or2Rm7
-  };
-
-static BxExecutePtr_t BxResolve32Mod0[8] = {
-  &BX_CPU_C::Resolve32Mod0Rm0,
-  &BX_CPU_C::Resolve32Mod0Rm1,
-  &BX_CPU_C::Resolve32Mod0Rm2,
-  &BX_CPU_C::Resolve32Mod0Rm3,
-  NULL, // escape to 2-byte
-  NULL, // d32, no registers used
-  &BX_CPU_C::Resolve32Mod0Rm6,
-  &BX_CPU_C::Resolve32Mod0Rm7
-  };
-
-static BxExecutePtr_t BxResolve32Mod1or2[8] = {
-  &BX_CPU_C::Resolve32Mod1or2Rm0,
-  &BX_CPU_C::Resolve32Mod1or2Rm1,
-  &BX_CPU_C::Resolve32Mod1or2Rm2,
-  &BX_CPU_C::Resolve32Mod1or2Rm3,
-  NULL, // escape to 2-byte
-  &BX_CPU_C::Resolve32Mod1or2Rm5,
-  &BX_CPU_C::Resolve32Mod1or2Rm6,
-  &BX_CPU_C::Resolve32Mod1or2Rm7
-  };
-
-static BxExecutePtr_t BxResolve32Mod0Base[8] = {
-  &BX_CPU_C::Resolve32Mod0Base0,
-  &BX_CPU_C::Resolve32Mod0Base1,
-  &BX_CPU_C::Resolve32Mod0Base2,
-  &BX_CPU_C::Resolve32Mod0Base3,
-  &BX_CPU_C::Resolve32Mod0Base4,
-  &BX_CPU_C::Resolve32Mod0Base5,
-  &BX_CPU_C::Resolve32Mod0Base6,
-  &BX_CPU_C::Resolve32Mod0Base7,
-  };
-
-static BxExecutePtr_t BxResolve32Mod1or2Base[8] = {
-  &BX_CPU_C::Resolve32Mod1or2Base0,
-  &BX_CPU_C::Resolve32Mod1or2Base1,
-  &BX_CPU_C::Resolve32Mod1or2Base2,
-  &BX_CPU_C::Resolve32Mod1or2Base3,
-  &BX_CPU_C::Resolve32Mod1or2Base4,
-  &BX_CPU_C::Resolve32Mod1or2Base5,
-  &BX_CPU_C::Resolve32Mod1or2Base6,
-  &BX_CPU_C::Resolve32Mod1or2Base7,
-  };
-
-typedef struct BxOpcodeInfo_t {
-  Bit16u         Attr;
-  SidExecutePtr_t ExecutePtr;
-  struct BxOpcodeInfo_t *AnotherArray;
-} BxOpcodeInfo_t;
-
-static BxOpcodeInfo_t BxOpcodeInfoG1EbIb[8] = {
-  /* 0 */  { BxImmediate_Ib,  &BX_CPU_C::ADD_EbIb },
-  /* 1 */  { BxImmediate_Ib,  &BX_CPU_C::OR_EbIb },
-  /* 2 */  { BxImmediate_Ib,  &BX_CPU_C::ADC_EbIb },
-  /* 3 */  { BxImmediate_Ib,  &BX_CPU_C::SBB_EbIb },
-  /* 4 */  { BxImmediate_Ib,  &BX_CPU_C::AND_EbIb },
-  /* 5 */  { BxImmediate_Ib,  &BX_CPU_C::SUB_EbIb },
-  /* 6 */  { BxImmediate_Ib,  &BX_CPU_C::XOR_EbIb },
-  /* 7 */  { BxImmediate_Ib,  &BX_CPU_C::CMP_EbIb }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG1Ew[8] = {
-  // attributes defined in main area
-  /* 0 */  { 0,  &BX_CPU_C::ADD_EwIw },
-  /* 1 */  { 0,  &BX_CPU_C::OR_EwIw },
-  /* 2 */  { 0,  &BX_CPU_C::ADC_EwIw },
-  /* 3 */  { 0,  &BX_CPU_C::SBB_EwIw },
-  /* 4 */  { 0,  &BX_CPU_C::AND_EwIw },
-  /* 5 */  { 0,  &BX_CPU_C::SUB_EwIw },
-  /* 6 */  { 0,  &BX_CPU_C::XOR_EwIw },
-  /* 7 */  { 0,  &BX_CPU_C::CMP_EwIw }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG1Ed[8] = {
-  // attributes defined in main area
-  /* 0 */  { 0,  &BX_CPU_C::ADD_EdId },
-  /* 1 */  { 0,  &BX_CPU_C::OR_EdId },
-  /* 2 */  { 0,  &BX_CPU_C::ADC_EdId },
-  /* 3 */  { 0,  &BX_CPU_C::SBB_EdId },
-  /* 4 */  { 0,  &BX_CPU_C::AND_EdId },
-  /* 5 */  { 0,  &BX_CPU_C::SUB_EdId },
-  /* 6 */  { 0,  &BX_CPU_C::XOR_EdId },
-  /* 7 */  { 0,  &BX_CPU_C::CMP_EdId }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG2Eb[8] = {
-  // attributes defined in main area
-  /* 0 */  { 0,  &BX_CPU_C::ROL_Eb },
-  /* 1 */  { 0,  &BX_CPU_C::ROR_Eb },
-  /* 2 */  { 0,  &BX_CPU_C::RCL_Eb },
-  /* 3 */  { 0,  &BX_CPU_C::RCR_Eb },
-  /* 4 */  { 0,  &BX_CPU_C::SHL_Eb },
-  /* 5 */  { 0,  &BX_CPU_C::SHR_Eb },
-  /* 6 */  { 0,  &BX_CPU_C::SHL_Eb },
-  /* 7 */  { 0,  &BX_CPU_C::SAR_Eb }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG2Ew[8] = {
-  // attributes defined in main area
-  /* 0 */  { 0,  &BX_CPU_C::ROL_Ew },
-  /* 1 */  { 0,  &BX_CPU_C::ROR_Ew },
-  /* 2 */  { 0,  &BX_CPU_C::RCL_Ew },
-  /* 3 */  { 0,  &BX_CPU_C::RCR_Ew },
-  /* 4 */  { 0,  &BX_CPU_C::SHL_Ew },
-  /* 5 */  { 0,  &BX_CPU_C::SHR_Ew },
-  /* 6 */  { 0,  &BX_CPU_C::SHL_Ew },
-  /* 7 */  { 0,  &BX_CPU_C::SAR_Ew }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG2Ed[8] = {
-  // attributes defined in main area
-  /* 0 */  { 0,  &BX_CPU_C::ROL_Ed },
-  /* 1 */  { 0,  &BX_CPU_C::ROR_Ed },
-  /* 2 */  { 0,  &BX_CPU_C::RCL_Ed },
-  /* 3 */  { 0,  &BX_CPU_C::RCR_Ed },
-  /* 4 */  { 0,  &BX_CPU_C::SHL_Ed },
-  /* 5 */  { 0,  &BX_CPU_C::SHR_Ed },
-  /* 6 */  { 0,  &BX_CPU_C::SHL_Ed },
-  /* 7 */  { 0,  &BX_CPU_C::SAR_Ed }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG3Eb[8] = {
-  /* 0 */  { BxImmediate_Ib,  &BX_CPU_C::TEST_EbIb },
-  /* 1 */  { BxImmediate_Ib,  &BX_CPU_C::TEST_EbIb },
-  /* 2 */  { 0,             &BX_CPU_C::NOT_Eb },
-  /* 3 */  { 0,             &BX_CPU_C::NEG_Eb },
-  /* 4 */  { 0,             &BX_CPU_C::MUL_ALEb },
-  /* 5 */  { 0,             &BX_CPU_C::IMUL_ALEb },
-  /* 6 */  { 0,             &BX_CPU_C::DIV_ALEb },
-  /* 7 */  { 0,             &BX_CPU_C::IDIV_ALEb }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG3Ew[8] = {
-  /* 0 */  { BxImmediate_Iw,  &BX_CPU_C::TEST_EwIw },
-  /* 1 */  { BxImmediate_Iw,  &BX_CPU_C::TEST_EwIw },
-  /* 2 */  { 0,             &BX_CPU_C::NOT_Ew },
-  /* 3 */  { 0,             &BX_CPU_C::NEG_Ew },
-  /* 4 */  { 0,             &BX_CPU_C::MUL_AXEw },
-  /* 5 */  { 0,             &BX_CPU_C::IMUL_AXEw },
-  /* 6 */  { 0,             &BX_CPU_C::DIV_AXEw },
-  /* 7 */  { 0,             &BX_CPU_C::IDIV_AXEw }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG3Ed[8] = {
-  /* 0 */  { BxImmediate_Iv,  &BX_CPU_C::TEST_EdId },
-  /* 1 */  { BxImmediate_Iv,  &BX_CPU_C::TEST_EdId },
-  /* 2 */  { 0,             &BX_CPU_C::NOT_Ed },
-  /* 3 */  { 0,             &BX_CPU_C::NEG_Ed },
-  /* 4 */  { 0,             &BX_CPU_C::MUL_EAXEd },
-  /* 5 */  { 0,             &BX_CPU_C::IMUL_EAXEd },
-  /* 6 */  { 0,             &BX_CPU_C::DIV_EAXEd },
-  /* 7 */  { 0,             &BX_CPU_C::IDIV_EAXEd }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG4[8] = {
-  /* 0 */  { 0,  &BX_CPU_C::INC_Eb },
-  /* 1 */  { 0,  &BX_CPU_C::DEC_Eb },
-  /* 2 */  { 0,  &BX_CPU_C::BxError },
-  /* 3 */  { 0,  &BX_CPU_C::BxError },
-  /* 4 */  { 0,  &BX_CPU_C::BxError },
-  /* 5 */  { 0,  &BX_CPU_C::BxError },
-  /* 6 */  { 0,  &BX_CPU_C::BxError },
-  /* 7 */  { 0,  &BX_CPU_C::BxError }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG5w[8] = {
-  // attributes defined in main area
-  /* 0 */  { 0,  &BX_CPU_C::INC_Ew },
-  /* 1 */  { 0,  &BX_CPU_C::DEC_Ew },
-  /* 2 */  { 0,  &BX_CPU_C::CALL_Ew },
-  /* 3 */  { 0,  &BX_CPU_C::CALL16_Ep },
-  /* 4 */  { 0,  &BX_CPU_C::JMP_Ew },
-  /* 5 */  { 0,  &BX_CPU_C::JMP16_Ep },
-  /* 6 */  { 0,  &BX_CPU_C::PUSH_Ew },
-  /* 7 */  { 0,  &BX_CPU_C::BxError }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG5d[8] = {
-  // attributes defined in main area
-  /* 0 */  { 0,  &BX_CPU_C::INC_Ed },
-  /* 1 */  { 0,  &BX_CPU_C::DEC_Ed },
-  /* 2 */  { 0,  &BX_CPU_C::CALL_Ed },
-  /* 3 */  { 0,  &BX_CPU_C::CALL32_Ep },
-  /* 4 */  { 0,  &BX_CPU_C::JMP_Ed },
-  /* 5 */  { 0,  &BX_CPU_C::JMP32_Ep },
-  /* 6 */  { 0,  &BX_CPU_C::PUSH_Ed },
-  /* 7 */  { 0,  &BX_CPU_C::BxError }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG6[8] = {
-  // attributes defined in main area
-  /* 0 */  { 0,  &BX_CPU_C::SLDT_Ew },
-  /* 1 */  { 0,  &BX_CPU_C::STR_Ew },
-  /* 2 */  { 0,  &BX_CPU_C::LLDT_Ew },
-  /* 3 */  { 0,  &BX_CPU_C::LTR_Ew },
-  /* 4 */  { 0,  &BX_CPU_C::VERR_Ew },
-  /* 5 */  { 0,  &BX_CPU_C::VERW_Ew },
-  /* 6 */  { 0,  &BX_CPU_C::BxError },
-  /* 7 */  { 0,  &BX_CPU_C::BxError }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG7[8] = {
-  /* 0 */  { 0,  &BX_CPU_C::SGDT_Ms },
-  /* 1 */  { 0,  &BX_CPU_C::SIDT_Ms },
-  /* 2 */  { 0,  &BX_CPU_C::LGDT_Ms },
-  /* 3 */  { 0,  &BX_CPU_C::LIDT_Ms },
-  /* 4 */  { 0,  &BX_CPU_C::SMSW_Ew },
-  /* 5 */  { 0,  &BX_CPU_C::BxError },
-  /* 6 */  { 0,  &BX_CPU_C::LMSW_Ew },
-  /* 7 */  { 0,  &BX_CPU_C::INVLPG }
-  }; 
-
-
-static BxOpcodeInfo_t BxOpcodeInfoG8EvIb[8] = {
-  /* 0 */  { 0,  &BX_CPU_C::BxError },
-  /* 1 */  { 0,  &BX_CPU_C::BxError },
-  /* 2 */  { 0,  &BX_CPU_C::BxError },
-  /* 3 */  { 0,  &BX_CPU_C::BxError },
-  /* 4 */  { BxImmediate_Ib,  &BX_CPU_C::BT_EvIb },
-  /* 5 */  { BxImmediate_Ib,  &BX_CPU_C::BTS_EvIb },
-  /* 6 */  { BxImmediate_Ib,  &BX_CPU_C::BTR_EvIb },
-  /* 7 */  { BxImmediate_Ib,  &BX_CPU_C::BTC_EvIb }
-  }; 
-
-static BxOpcodeInfo_t BxOpcodeInfoG9[8] = {
-  /* 0 */  { 0,  &BX_CPU_C::BxError },
-  /* 1 */  { 0,  &BX_CPU_C::CMPXCHG8B },
-  /* 2 */  { 0,  &BX_CPU_C::BxError },
-  /* 3 */  { 0,  &BX_CPU_C::BxError },
-  /* 4 */  { 0,  &BX_CPU_C::BxError },
-  /* 5 */  { 0,  &BX_CPU_C::BxError },
-  /* 6 */  { 0,  &BX_CPU_C::BxError },
-  /* 7 */  { 0,  &BX_CPU_C::BxError }
-  };
-
-
-// 512 entries for 16bit mode
-// 512 entries for 32bit mode
-
-static BxOpcodeInfo_t BxOpcodeInfo[512*2] = {
-  // 512 entries for 16bit mode
-  /* 00 */  { BxAnother,  &BX_CPU_C::ADD_EbGb },
-  /* 01 */  { BxAnother,  &BX_CPU_C::ADD_EwGw },
-  /* 02 */  { BxAnother,  &BX_CPU_C::ADD_GbEb },
-  /* 03 */  { BxAnother,  &BX_CPU_C::ADD_GwEw },
-  /* 04 */  { BxImmediate_Ib,  &BX_CPU_C::ADD_ALIb },
-  /* 05 */  { BxImmediate_Iv,  &BX_CPU_C::ADD_AXIw },
-  /* 06 */  { 0,  &BX_CPU_C::PUSH_ES },
-  /* 07 */  { 0,  &BX_CPU_C::POP_ES },
-  /* 08 */  { BxAnother,  &BX_CPU_C::OR_EbGb },
-  /* 09 */  { BxAnother,  &BX_CPU_C::OR_EwGw },
-  /* 0A */  { BxAnother,  &BX_CPU_C::OR_GbEb },
-  /* 0B */  { BxAnother,  &BX_CPU_C::OR_GwEw },
-  /* 0C */  { BxImmediate_Ib,  &BX_CPU_C::OR_ALIb },
-  /* 0D */  { BxImmediate_Iv,  &BX_CPU_C::OR_AXIw },
-  /* 0E */  { 0,  &BX_CPU_C::PUSH_CS },
-  /* 0F */  { BxAnother,  &BX_CPU_C::BxError }, // 2-byte escape
-  /* 10 */  { BxAnother,  &BX_CPU_C::ADC_EbGb },
-  /* 11 */  { BxAnother,  &BX_CPU_C::ADC_EwGw },
-  /* 12 */  { BxAnother,  &BX_CPU_C::ADC_GbEb },
-  /* 13 */  { BxAnother,  &BX_CPU_C::ADC_GwEw },
-  /* 14 */  { BxImmediate_Ib,  &BX_CPU_C::ADC_ALIb },
-  /* 15 */  { BxImmediate_Iv,  &BX_CPU_C::ADC_AXIw },
-  /* 16 */  { 0,  &BX_CPU_C::PUSH_SS },
-  /* 17 */  { 0,  &BX_CPU_C::POP_SS },
-  /* 18 */  { BxAnother,  &BX_CPU_C::SBB_EbGb },
-  /* 19 */  { BxAnother,  &BX_CPU_C::SBB_EwGw },
-  /* 1A */  { BxAnother,  &BX_CPU_C::SBB_GbEb },
-  /* 1B */  { BxAnother,  &BX_CPU_C::SBB_GwEw },
-  /* 1C */  { BxImmediate_Ib,  &BX_CPU_C::SBB_ALIb },
-  /* 1D */  { BxImmediate_Iv,  &BX_CPU_C::SBB_AXIw },
-  /* 1E */  { 0,  &BX_CPU_C::PUSH_DS },
-  /* 1F */  { 0,  &BX_CPU_C::POP_DS },
-  /* 20 */  { BxAnother,  &BX_CPU_C::AND_EbGb },
-  /* 21 */  { BxAnother,  &BX_CPU_C::AND_EwGw },
-  /* 22 */  { BxAnother,  &BX_CPU_C::AND_GbEb },
-  /* 23 */  { BxAnother,  &BX_CPU_C::AND_GwEw },
-  /* 24 */  { BxImmediate_Ib,  &BX_CPU_C::AND_ALIb },
-  /* 25 */  { BxImmediate_Iv,  &BX_CPU_C::AND_AXIw },
-  /* 26 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // ES:
-  /* 27 */  { 0,  &BX_CPU_C::DAA },
-  /* 28 */  { BxAnother,  &BX_CPU_C::SUB_EbGb },
-  /* 29 */  { BxAnother,  &BX_CPU_C::SUB_EwGw },
-  /* 2A */  { BxAnother,  &BX_CPU_C::SUB_GbEb },
-  /* 2B */  { BxAnother,  &BX_CPU_C::SUB_GwEw },
-  /* 2C */  { BxImmediate_Ib,  &BX_CPU_C::SUB_ALIb },
-  /* 2D */  { BxImmediate_Iv,  &BX_CPU_C::SUB_AXIw },
-  /* 2E */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // CS:
-  /* 2F */  { 0,  &BX_CPU_C::DAS },
-  /* 30 */  { BxAnother,  &BX_CPU_C::XOR_EbGb },
-  /* 31 */  { BxAnother,  &BX_CPU_C::XOR_EwGw },
-  /* 32 */  { BxAnother,  &BX_CPU_C::XOR_GbEb },
-  /* 33 */  { BxAnother,  &BX_CPU_C::XOR_GwEw },
-  /* 34 */  { BxImmediate_Ib,  &BX_CPU_C::XOR_ALIb },
-  /* 35 */  { BxImmediate_Iv,  &BX_CPU_C::XOR_AXIw },
-  /* 36 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // SS:
-  /* 37 */  { 0,  &BX_CPU_C::AAA },
-  /* 38 */  { BxAnother,  &BX_CPU_C::CMP_EbGb },
-  /* 39 */  { BxAnother,  &BX_CPU_C::CMP_EwGw },
-  /* 3A */  { BxAnother,  &BX_CPU_C::CMP_GbEb },
-  /* 3B */  { BxAnother,  &BX_CPU_C::CMP_GwEw },
-  /* 3C */  { BxImmediate_Ib,  &BX_CPU_C::CMP_ALIb },
-  /* 3D */  { BxImmediate_Iv,  &BX_CPU_C::CMP_AXIw },
-  /* 3E */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // DS:
-  /* 3F */  { 0,  &BX_CPU_C::AAS },
-  /* 40 */  { 0,  &BX_CPU_C::INC_RX },
-  /* 41 */  { 0,  &BX_CPU_C::INC_RX },
-  /* 42 */  { 0,  &BX_CPU_C::INC_RX },
-  /* 43 */  { 0,  &BX_CPU_C::INC_RX },
-  /* 44 */  { 0,  &BX_CPU_C::INC_RX },
-  /* 45 */  { 0,  &BX_CPU_C::INC_RX },
-  /* 46 */  { 0,  &BX_CPU_C::INC_RX },
-  /* 47 */  { 0,  &BX_CPU_C::INC_RX },
-  /* 48 */  { 0,  &BX_CPU_C::DEC_RX },
-  /* 49 */  { 0,  &BX_CPU_C::DEC_RX },
-  /* 4A */  { 0,  &BX_CPU_C::DEC_RX },
-  /* 4B */  { 0,  &BX_CPU_C::DEC_RX },
-  /* 4C */  { 0,  &BX_CPU_C::DEC_RX },
-  /* 4D */  { 0,  &BX_CPU_C::DEC_RX },
-  /* 4E */  { 0,  &BX_CPU_C::DEC_RX },
-  /* 4F */  { 0,  &BX_CPU_C::DEC_RX },
-  /* 50 */  { 0,  &BX_CPU_C::PUSH_RX },
-  /* 51 */  { 0,  &BX_CPU_C::PUSH_RX },
-  /* 52 */  { 0,  &BX_CPU_C::PUSH_RX },
-  /* 53 */  { 0,  &BX_CPU_C::PUSH_RX },
-  /* 54 */  { 0,  &BX_CPU_C::PUSH_RX },
-  /* 55 */  { 0,  &BX_CPU_C::PUSH_RX },
-  /* 56 */  { 0,  &BX_CPU_C::PUSH_RX },
-  /* 57 */  { 0,  &BX_CPU_C::PUSH_RX },
-  /* 58 */  { 0,  &BX_CPU_C::POP_RX },
-  /* 59 */  { 0,  &BX_CPU_C::POP_RX },
-  /* 5A */  { 0,  &BX_CPU_C::POP_RX },
-  /* 5B */  { 0,  &BX_CPU_C::POP_RX },
-  /* 5C */  { 0,  &BX_CPU_C::POP_RX },
-  /* 5D */  { 0,  &BX_CPU_C::POP_RX },
-  /* 5E */  { 0,  &BX_CPU_C::POP_RX },
-  /* 5F */  { 0,  &BX_CPU_C::POP_RX },
-  /* 60 */  { 0,  &BX_CPU_C::PUSHAD16 },
-  /* 61 */  { 0,  &BX_CPU_C::POPAD16 },
-  /* 62 */  { BxAnother,  &BX_CPU_C::BOUND_GvMa },
-  /* 63 */  { BxAnother,  &BX_CPU_C::ARPL_EwGw },
-  /* 64 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // FS:
-  /* 65 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // GS:
-  /* 66 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // OS:
-  /* 67 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // AS:
-  /* 68 */  { BxImmediate_Iv,  &BX_CPU_C::PUSH_Iw },
-  /* 69 */  { BxAnother | BxImmediate_Iv,  &BX_CPU_C::IMUL_GwEwIw },
-  /* 6A */  { BxImmediate_Ib_SE,  &BX_CPU_C::PUSH_Iw },
-  /* 6B */  { BxAnother | BxImmediate_Ib_SE,  &BX_CPU_C::IMUL_GwEwIw },
-  /* 6C */  { BxRepeatable,  &BX_CPU_C::INSB_YbDX },
-  /* 6D */  { BxRepeatable,  &BX_CPU_C::INSW_YvDX },
-  /* 6E */  { BxRepeatable,  &BX_CPU_C::OUTSB_DXXb },
-  /* 6F */  { BxRepeatable,  &BX_CPU_C::OUTSW_DXXv },
-  /* 70 */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 71 */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 72 */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 73 */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 74 */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 75 */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 76 */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 77 */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 78 */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 79 */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 7A */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 7B */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 7C */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 7D */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 7E */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 7F */  { BxImmediate_BrOff8,  &BX_CPU_C::JCC_Jw },
-  /* 80 */  { BxAnother | BxGroup1, NULL, BxOpcodeInfoG1EbIb },
-  /* 81 */  { BxAnother | BxGroup1 | BxImmediate_Iv, NULL, BxOpcodeInfoG1Ew },
-  /* 82 */  { BxAnother | BxGroup1,  NULL, BxOpcodeInfoG1EbIb },
-  /* 83 */  { BxAnother | BxGroup1 | BxImmediate_Ib_SE, NULL, BxOpcodeInfoG1Ew },
-  /* 84 */  { BxAnother,  &BX_CPU_C::TEST_EbGb },
-  /* 85 */  { BxAnother,  &BX_CPU_C::TEST_EwGw },
-  /* 86 */  { BxAnother,  &BX_CPU_C::XCHG_EbGb },
-  /* 87 */  { BxAnother,  &BX_CPU_C::XCHG_EwGw },
-  /* 88 */  { BxAnother,  &BX_CPU_C::MOV_EbGb },
-  /* 89 */  { BxAnother,  &BX_CPU_C::MOV_EwGw },
-  /* 8A */  { BxAnother,  &BX_CPU_C::MOV_GbEb },
-  /* 8B */  { BxAnother,  &BX_CPU_C::MOV_GwEw },
-  /* 8C */  { BxAnother,  &BX_CPU_C::MOV_EwSw },
-  /* 8D */  { BxAnother,  &BX_CPU_C::LEA_GwM },
-  /* 8E */  { BxAnother,  &BX_CPU_C::MOV_SwEw },
-  /* 8F */  { BxAnother,  &BX_CPU_C::POP_Ew },
-  /* 90 */  { 0,  &BX_CPU_C::NOP },
-  /* 91 */  { 0,  &BX_CPU_C::XCHG_RXAX },
-  /* 92 */  { 0,  &BX_CPU_C::XCHG_RXAX },
-  /* 93 */  { 0,  &BX_CPU_C::XCHG_RXAX },
-  /* 94 */  { 0,  &BX_CPU_C::XCHG_RXAX },
-  /* 95 */  { 0,  &BX_CPU_C::XCHG_RXAX },
-  /* 96 */  { 0,  &BX_CPU_C::XCHG_RXAX },
-  /* 97 */  { 0,  &BX_CPU_C::XCHG_RXAX },
-  /* 98 */  { 0,  &BX_CPU_C::CBW },
-  /* 99 */  { 0,  &BX_CPU_C::CWD },
-  /* 9A */  { BxImmediate_IvIw,  &BX_CPU_C::CALL16_Ap },
-  /* 9B */  { 0,  &BX_CPU_C::FWAIT },
-  /* 9C */  { 0,  &BX_CPU_C::PUSHF_Fv },
-  /* 9D */  { 0,  &BX_CPU_C::POPF_Fv },
-  /* 9E */  { 0,  &BX_CPU_C::SAHF },
-  /* 9F */  { 0,  &BX_CPU_C::LAHF },
-  /* A0 */  { BxImmediate_O,  &BX_CPU_C::MOV_ALOb },
-  /* A1 */  { BxImmediate_O,  &BX_CPU_C::MOV_AXOw },
-  /* A2 */  { BxImmediate_O,  &BX_CPU_C::MOV_ObAL },
-  /* A3 */  { BxImmediate_O,  &BX_CPU_C::MOV_OwAX },
-  /* A4 */  { BxRepeatable,  &BX_CPU_C::MOVSB_XbYb },
-  /* A5 */  { BxRepeatable,  &BX_CPU_C::MOVSW_XvYv },
-  /* A6 */  { BxRepeatable | BxRepeatableZF,  &BX_CPU_C::CMPSB_XbYb },
-  /* A7 */  { BxRepeatable | BxRepeatableZF,  &BX_CPU_C::CMPSW_XvYv },
-  /* A8 */  { BxImmediate_Ib,  &BX_CPU_C::TEST_ALIb },
-  /* A9 */  { BxImmediate_Iv,  &BX_CPU_C::TEST_AXIw },
-  /* AA */  { BxRepeatable,  &BX_CPU_C::STOSB_YbAL },
-  /* AB */  { BxRepeatable,  &BX_CPU_C::STOSW_YveAX },
-  /* AC */  { BxRepeatable,  &BX_CPU_C::LODSB_ALXb },
-  /* AD */  { BxRepeatable,  &BX_CPU_C::LODSW_eAXXv },
-  /* AE */  { BxRepeatable | BxRepeatableZF,  &BX_CPU_C::SCASB_ALXb },
-  /* AF */  { BxRepeatable | BxRepeatableZF,  &BX_CPU_C::SCASW_eAXXv },
-  /* B0 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RLIb },
-  /* B1 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RLIb },
-  /* B2 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RLIb },
-  /* B3 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RLIb },
-  /* B4 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RHIb },
-  /* B5 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RHIb },
-  /* B6 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RHIb },
-  /* B7 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RHIb },
-  /* B8 */  { BxImmediate_Iv,  &BX_CPU_C::MOV_RXIw },
-  /* B9 */  { BxImmediate_Iv,  &BX_CPU_C::MOV_RXIw },
-  /* BA */  { BxImmediate_Iv,  &BX_CPU_C::MOV_RXIw },
-  /* BB */  { BxImmediate_Iv,  &BX_CPU_C::MOV_RXIw },
-  /* BC */  { BxImmediate_Iv,  &BX_CPU_C::MOV_RXIw },
-  /* BD */  { BxImmediate_Iv,  &BX_CPU_C::MOV_RXIw },
-  /* BE */  { BxImmediate_Iv,  &BX_CPU_C::MOV_RXIw },
-  /* BF */  { BxImmediate_Iv,  &BX_CPU_C::MOV_RXIw },
-  /* C0 */  { BxAnother | BxGroup2 | BxImmediate_Ib, NULL, BxOpcodeInfoG2Eb },
-  /* C1 */  { BxAnother | BxGroup2 | BxImmediate_Ib, NULL, BxOpcodeInfoG2Ew },
-  /* C2 */  { BxImmediate_Iw,  &BX_CPU_C::RETnear16_Iw },
-  /* C3 */  { 0,             &BX_CPU_C::RETnear16 },
-  /* C4 */  { BxAnother,  &BX_CPU_C::LES_GvMp },
-  /* C5 */  { BxAnother,  &BX_CPU_C::LDS_GvMp },
-  /* C6 */  { BxAnother | BxImmediate_Ib,  &BX_CPU_C::MOV_EbIb },
-  /* C7 */  { BxAnother | BxImmediate_Iv,  &BX_CPU_C::MOV_EwIw },
-  /* C8 */  { BxImmediate_IwIb,  &BX_CPU_C::ENTER_IwIb },
-  /* C9 */  { 0,  &BX_CPU_C::LEAVE },
-  /* CA */  { BxImmediate_Iw,  &BX_CPU_C::RETfar16_Iw },
-  /* CB */  { 0,  &BX_CPU_C::RETfar16 },
-  /* CC */  { 0,  &sid_cpu_c::INT3 },
-  /* CD */  { BxImmediate_Ib,  &sid_cpu_c::INT_Ib },
-  /* CE */  { 0,  &BX_CPU_C::INTO },
-  /* CF */  { 0,  &BX_CPU_C::IRET16 },
-  /* D0 */  { BxAnother | BxGroup2,  NULL, BxOpcodeInfoG2Eb },
-  /* D1 */  { BxAnother | BxGroup2,  NULL, BxOpcodeInfoG2Ew },
-  /* D2 */  { BxAnother | BxGroup2,  NULL, BxOpcodeInfoG2Eb },
-  /* D3 */  { BxAnother | BxGroup2,  NULL, BxOpcodeInfoG2Ew },
-  /* D4 */  { BxImmediate_Ib,  &BX_CPU_C::AAM },
-  /* D5 */  { BxImmediate_Ib,  &BX_CPU_C::AAD },
-  /* D6 */  { 0,  &BX_CPU_C::SALC },
-  /* D7 */  { 0,  &BX_CPU_C::XLAT },
-  /* D8 */  { BxAnother,  &BX_CPU_C::ESC0 },
-  /* D9 */  { BxAnother,  &BX_CPU_C::ESC1 },
-  /* DA */  { BxAnother,  &BX_CPU_C::ESC2 },
-  /* DB */  { BxAnother,  &BX_CPU_C::ESC3 },
-  /* DC */  { BxAnother,  &BX_CPU_C::ESC4 },
-  /* DD */  { BxAnother,  &BX_CPU_C::ESC5 },
-  /* DE */  { BxAnother,  &BX_CPU_C::ESC6 },
-  /* DF */  { BxAnother,  &BX_CPU_C::ESC7 },
-  /* E0 */  { BxImmediate_BrOff8,  &BX_CPU_C::LOOPNE_Jb },
-  /* E1 */  { BxImmediate_BrOff8,  &BX_CPU_C::LOOPE_Jb },
-  /* E2 */  { BxImmediate_BrOff8,  &BX_CPU_C::LOOP_Jb },
-  /* E3 */  { BxImmediate_BrOff8,  &BX_CPU_C::JCXZ_Jb },
-  /* E4 */  { BxImmediate_Ib,  &BX_CPU_C::IN_ALIb },
-  /* E5 */  { BxImmediate_Ib,  &BX_CPU_C::IN_eAXIb },
-  /* E6 */  { BxImmediate_Ib,  &BX_CPU_C::OUT_IbAL },
-  /* E7 */  { BxImmediate_Ib,  &BX_CPU_C::OUT_IbeAX },
-  /* E8 */  { BxImmediate_BrOff16,  &BX_CPU_C::CALL_Aw },
-  /* E9 */  { BxImmediate_BrOff16,  &BX_CPU_C::JMP_Jw },
-  /* EA */  { BxImmediate_IvIw,  &BX_CPU_C::JMP_Ap },
-  /* EB */  { BxImmediate_BrOff8,  &BX_CPU_C::JMP_Jw },
-  /* EC */  { 0,  &BX_CPU_C::IN_ALDX },
-  /* ED */  { 0,  &BX_CPU_C::IN_eAXDX },
-  /* EE */  { 0,  &BX_CPU_C::OUT_DXAL },
-  /* EF */  { 0,  &BX_CPU_C::OUT_DXeAX },
-  /* F0 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // LOCK
-  /* F1 */  { 0,  &BX_CPU_C::INT1 },
-  /* F2 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // REPNE/REPNZ
-  /* F3 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // REP, REPE/REPZ
-  /* F4 */  { 0,  &BX_CPU_C::HLT },
-  /* F5 */  { 0,  &BX_CPU_C::CMC },
-  /* F6 */  { BxAnother | BxGroup3,  NULL, BxOpcodeInfoG3Eb },
-  /* F7 */  { BxAnother | BxGroup3,  NULL, BxOpcodeInfoG3Ew },
-  /* F8 */  { 0,  &BX_CPU_C::CLC },
-  /* F9 */  { 0,  &BX_CPU_C::STC },
-  /* FA */  { 0,  &BX_CPU_C::CLI },
-  /* FB */  { 0,  &BX_CPU_C::STI },
-  /* FC */  { 0,  &BX_CPU_C::CLD },
-  /* FD */  { 0,  &BX_CPU_C::STD },
-  /* FE */  { BxAnother | BxGroup4,  NULL, BxOpcodeInfoG4 },
-  /* FF */  { BxAnother | BxGroup5,  NULL, BxOpcodeInfoG5w },
-
-  /* 0F 00 */  { BxAnother | BxGroup6,  NULL, BxOpcodeInfoG6 },
-  /* 0F 01 */  { BxAnother | BxGroup7,  NULL, BxOpcodeInfoG7 },
-  /* 0F 02 */  { BxAnother,  &BX_CPU_C::LAR_GvEw },
-  /* 0F 03 */  { BxAnother,  &BX_CPU_C::LSL_GvEw },
-  /* 0F 04 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 05 */  { 0,  &BX_CPU_C::LOADALL },
-  /* 0F 06 */  { 0,  &BX_CPU_C::CLTS },
-  /* 0F 07 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 08 */  { 0,  &BX_CPU_C::INVD },
-  /* 0F 09 */  { 0,  &BX_CPU_C::WBINVD },
-  /* 0F 0A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 0B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 0C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 0D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 0E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 0F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 10 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 11 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 12 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 13 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 14 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 15 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 16 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 17 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 18 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 19 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 1A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 1B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 1C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 1D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 1E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 1F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 20 */  { BxAnother,  &BX_CPU_C::MOV_RdCd },
-  /* 0F 21 */  { BxAnother,  &BX_CPU_C::MOV_RdDd },
-  /* 0F 22 */  { BxAnother,  &BX_CPU_C::MOV_CdRd },
-  /* 0F 23 */  { BxAnother,  &BX_CPU_C::MOV_DdRd },
-  /* 0F 24 */  { BxAnother,  &BX_CPU_C::MOV_RdTd },
-  /* 0F 25 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 26 */  { BxAnother,  &BX_CPU_C::MOV_TdRd },
-  /* 0F 27 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 28 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 29 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 2A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 2B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 2C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 2D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 2E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 2F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 30 */  { 0,  &BX_CPU_C::WRMSR },
-  /* 0F 31 */  { 0,  &BX_CPU_C::RDTSC },
-  /* 0F 32 */  { 0,  &BX_CPU_C::RDMSR },
-  /* 0F 33 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 34 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 35 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 36 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 37 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 38 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 39 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 3A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 3B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 3C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 3D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 3E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 3F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 40 */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 41 */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 42 */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 43 */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 44 */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 45 */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 46 */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 47 */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 48 */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 49 */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 4A */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 4B */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 4C */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 4D */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 4E */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 4F */  { BxAnother,  &BX_CPU_C::CMOV_GwEw },
-  /* 0F 50 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 51 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 52 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 53 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 54 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 55 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 56 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 57 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 58 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 59 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 5A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 5B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 5C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 5D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 5E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 5F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 60 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 61 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 62 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 63 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 64 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 65 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 66 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 67 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 68 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 69 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 6A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 6B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 6C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 6D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 6E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 6F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 70 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 71 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 72 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 73 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 74 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 75 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 76 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 77 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 78 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 79 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 7A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 7B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 7C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 7D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 7E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 7F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 80 */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 81 */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 82 */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 83 */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 84 */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 85 */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 86 */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 87 */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 88 */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 89 */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 8A */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 8B */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 8C */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 8D */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 8E */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 8F */  { BxImmediate_BrOff16,  &BX_CPU_C::JCC_Jw },
-  /* 0F 90 */  { BxAnother,  &BX_CPU_C::SETO_Eb },
-  /* 0F 91 */  { BxAnother,  &BX_CPU_C::SETNO_Eb },
-  /* 0F 92 */  { BxAnother,  &BX_CPU_C::SETB_Eb },
-  /* 0F 93 */  { BxAnother,  &BX_CPU_C::SETNB_Eb },
-  /* 0F 94 */  { BxAnother,  &BX_CPU_C::SETZ_Eb },
-  /* 0F 95 */  { BxAnother,  &BX_CPU_C::SETNZ_Eb },
-  /* 0F 96 */  { BxAnother,  &BX_CPU_C::SETBE_Eb },
-  /* 0F 97 */  { BxAnother,  &BX_CPU_C::SETNBE_Eb },
-  /* 0F 98 */  { BxAnother,  &BX_CPU_C::SETS_Eb },
-  /* 0F 99 */  { BxAnother,  &BX_CPU_C::SETNS_Eb },
-  /* 0F 9A */  { BxAnother,  &BX_CPU_C::SETP_Eb },
-  /* 0F 9B */  { BxAnother,  &BX_CPU_C::SETNP_Eb },
-  /* 0F 9C */  { BxAnother,  &BX_CPU_C::SETL_Eb },
-  /* 0F 9D */  { BxAnother,  &BX_CPU_C::SETNL_Eb },
-  /* 0F 9E */  { BxAnother,  &BX_CPU_C::SETLE_Eb },
-  /* 0F 9F */  { BxAnother,  &BX_CPU_C::SETNLE_Eb },
-  /* 0F A0 */  { 0,  &BX_CPU_C::PUSH_FS },
-  /* 0F A1 */  { 0,  &BX_CPU_C::POP_FS },
-  /* 0F A2 */  { 0,  &BX_CPU_C::CPUID },
-  /* 0F A3 */  { BxAnother,  &BX_CPU_C::BT_EvGv },
-  /* 0F A4 */  { BxAnother | BxImmediate_Ib,  &BX_CPU_C::SHLD_EwGw },
-  /* 0F A5 */  { BxAnother,                 &BX_CPU_C::SHLD_EwGw },
-  /* 0F A6 */  { 0,  &BX_CPU_C::CMPXCHG_XBTS },
-  /* 0F A7 */  { 0,  &BX_CPU_C::CMPXCHG_IBTS },
-  /* 0F A8 */  { 0,  &BX_CPU_C::PUSH_GS },
-  /* 0F A9 */  { 0,  &BX_CPU_C::POP_GS },
-  /* 0F AA */  { 0,  &BX_CPU_C::RSM },
-  /* 0F AB */  { BxAnother,  &BX_CPU_C::BTS_EvGv },
-  /* 0F AC */  { BxAnother | BxImmediate_Ib,  &BX_CPU_C::SHRD_EwGw },
-  /* 0F AD */  { BxAnother,                 &BX_CPU_C::SHRD_EwGw },
-  /* 0F AE */  { 0,  &BX_CPU_C::BxError },
-  /* 0F AF */  { BxAnother,  &BX_CPU_C::IMUL_GwEw },
-  /* 0F B0 */  { BxAnother,  &BX_CPU_C::CMPXCHG_EbGb },
-  /* 0F B1 */  { BxAnother,  &BX_CPU_C::CMPXCHG_EwGw },
-  /* 0F B2 */  { BxAnother,  &BX_CPU_C::LSS_GvMp },
-  /* 0F B3 */  { BxAnother,  &BX_CPU_C::BTR_EvGv },
-  /* 0F B4 */  { BxAnother,  &BX_CPU_C::LFS_GvMp },
-  /* 0F B5 */  { BxAnother,  &BX_CPU_C::LGS_GvMp },
-  /* 0F B6 */  { BxAnother,  &BX_CPU_C::MOVZX_GwEb },
-  /* 0F B7 */  { BxAnother,  &BX_CPU_C::MOVZX_GwEw },
-  /* 0F B8 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F B9 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F BA */  { BxAnother | BxGroup8, NULL, BxOpcodeInfoG8EvIb },
-  /* 0F BB */  { BxAnother,  &BX_CPU_C::BTC_EvGv },
-  /* 0F BC */  { BxAnother,  &BX_CPU_C::BSF_GvEv },
-  /* 0F BD */  { BxAnother,  &BX_CPU_C::BSR_GvEv },
-  /* 0F BE */  { BxAnother,  &BX_CPU_C::MOVSX_GwEb },
-  /* 0F BF */  { BxAnother,  &BX_CPU_C::MOVSX_GwEw },
-  /* 0F C0 */  { BxAnother,  &BX_CPU_C::XADD_EbGb },
-  /* 0F C1 */  { BxAnother,  &BX_CPU_C::XADD_EwGw },
-  /* 0F C2 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F C3 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F C4 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F C5 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F C6 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F C7 */  { BxAnother | BxGroup9,  NULL, BxOpcodeInfoG9 },
-  /* 0F C8 */  { 0,  &BX_CPU_C::BSWAP_EAX },
-  /* 0F C9 */  { 0,  &BX_CPU_C::BSWAP_ECX },
-  /* 0F CA */  { 0,  &BX_CPU_C::BSWAP_EDX },
-  /* 0F CB */  { 0,  &BX_CPU_C::BSWAP_EBX },
-  /* 0F CC */  { 0,  &BX_CPU_C::BSWAP_ESP },
-  /* 0F CD */  { 0,  &BX_CPU_C::BSWAP_EBP },
-  /* 0F CE */  { 0,  &BX_CPU_C::BSWAP_ESI },
-  /* 0F CF */  { 0,  &BX_CPU_C::BSWAP_EDI },
-  /* 0F D0 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D1 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D2 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D3 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D4 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D5 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D6 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D7 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D8 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D9 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F DA */  { 0,  &BX_CPU_C::BxError },
-  /* 0F DB */  { 0,  &BX_CPU_C::BxError },
-  /* 0F DC */  { 0,  &BX_CPU_C::BxError },
-  /* 0F DD */  { 0,  &BX_CPU_C::BxError },
-  /* 0F DE */  { 0,  &BX_CPU_C::BxError },
-  /* 0F DF */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E0 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E1 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E2 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E3 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E4 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E5 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E6 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E7 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E8 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E9 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F EA */  { 0,  &BX_CPU_C::BxError },
-  /* 0F EB */  { 0,  &BX_CPU_C::BxError },
-  /* 0F EC */  { 0,  &BX_CPU_C::BxError },
-  /* 0F ED */  { 0,  &BX_CPU_C::BxError },
-  /* 0F EE */  { 0,  &BX_CPU_C::BxError },
-  /* 0F EF */  { 0,  &BX_CPU_C::BxError },
-  /* 0F F0 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F1 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F2 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F3 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F4 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F5 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F6 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F7 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F8 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F9 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F FA */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F FB */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F FC */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F FD */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F FE */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F FF */  { 0,  &BX_CPU_C::UndefinedOpcode },
-
-  // 512 entries for 32bit mod
-  /* 00 */  { BxAnother,  &BX_CPU_C::ADD_EbGb },
-  /* 01 */  { BxAnother,  &BX_CPU_C::ADD_EdGd },
-  /* 02 */  { BxAnother,  &BX_CPU_C::ADD_GbEb },
-  /* 03 */  { BxAnother,  &BX_CPU_C::ADD_GdEd },
-  /* 04 */  { BxImmediate_Ib,  &BX_CPU_C::ADD_ALIb },
-  /* 05 */  { BxImmediate_Iv,  &BX_CPU_C::ADD_EAXId },
-  /* 06 */  { 0,  &BX_CPU_C::PUSH_ES },
-  /* 07 */  { 0,  &BX_CPU_C::POP_ES },
-  /* 08 */  { BxAnother,  &BX_CPU_C::OR_EbGb },
-  /* 09 */  { BxAnother,  &BX_CPU_C::OR_EdGd },
-  /* 0A */  { BxAnother,  &BX_CPU_C::OR_GbEb },
-  /* 0B */  { BxAnother,  &BX_CPU_C::OR_GdEd },
-  /* 0C */  { BxImmediate_Ib,  &BX_CPU_C::OR_ALIb },
-  /* 0D */  { BxImmediate_Iv,  &BX_CPU_C::OR_EAXId },
-  /* 0E */  { 0,  &BX_CPU_C::PUSH_CS },
-  /* 0F */  { BxAnother,  &BX_CPU_C::BxError }, // 2-byte escape
-  /* 10 */  { BxAnother,  &BX_CPU_C::ADC_EbGb },
-  /* 11 */  { BxAnother,  &BX_CPU_C::ADC_EdGd },
-  /* 12 */  { BxAnother,  &BX_CPU_C::ADC_GbEb },
-  /* 13 */  { BxAnother,  &BX_CPU_C::ADC_GdEd },
-  /* 14 */  { BxImmediate_Ib,  &BX_CPU_C::ADC_ALIb },
-  /* 15 */  { BxImmediate_Iv,  &BX_CPU_C::ADC_EAXId },
-  /* 16 */  { 0,  &BX_CPU_C::PUSH_SS },
-  /* 17 */  { 0,  &BX_CPU_C::POP_SS },
-  /* 18 */  { BxAnother,  &BX_CPU_C::SBB_EbGb },
-  /* 19 */  { BxAnother,  &BX_CPU_C::SBB_EdGd },
-  /* 1A */  { BxAnother,  &BX_CPU_C::SBB_GbEb },
-  /* 1B */  { BxAnother,  &BX_CPU_C::SBB_GdEd },
-  /* 1C */  { BxImmediate_Ib,  &BX_CPU_C::SBB_ALIb },
-  /* 1D */  { BxImmediate_Iv,  &BX_CPU_C::SBB_EAXId },
-  /* 1E */  { 0,  &BX_CPU_C::PUSH_DS },
-  /* 1F */  { 0,  &BX_CPU_C::POP_DS },
-  /* 20 */  { BxAnother,  &BX_CPU_C::AND_EbGb },
-  /* 21 */  { BxAnother,  &BX_CPU_C::AND_EdGd },
-  /* 22 */  { BxAnother,  &BX_CPU_C::AND_GbEb },
-  /* 23 */  { BxAnother,  &BX_CPU_C::AND_GdEd },
-  /* 24 */  { BxImmediate_Ib,  &BX_CPU_C::AND_ALIb },
-  /* 25 */  { BxImmediate_Iv,  &BX_CPU_C::AND_EAXId },
-  /* 26 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // ES:
-  /* 27 */  { 0,  &BX_CPU_C::DAA },
-  /* 28 */  { BxAnother,  &BX_CPU_C::SUB_EbGb },
-  /* 29 */  { BxAnother,  &BX_CPU_C::SUB_EdGd },
-  /* 2A */  { BxAnother,  &BX_CPU_C::SUB_GbEb },
-  /* 2B */  { BxAnother,  &BX_CPU_C::SUB_GdEd },
-  /* 2C */  { BxImmediate_Ib,  &BX_CPU_C::SUB_ALIb },
-  /* 2D */  { BxImmediate_Iv,  &BX_CPU_C::SUB_EAXId },
-  /* 2E */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // CS:
-  /* 2F */  { 0,  &BX_CPU_C::DAS },
-  /* 30 */  { BxAnother,  &BX_CPU_C::XOR_EbGb },
-  /* 31 */  { BxAnother,  &BX_CPU_C::XOR_EdGd },
-  /* 32 */  { BxAnother,  &BX_CPU_C::XOR_GbEb },
-  /* 33 */  { BxAnother,  &BX_CPU_C::XOR_GdEd },
-  /* 34 */  { BxImmediate_Ib,  &BX_CPU_C::XOR_ALIb },
-  /* 35 */  { BxImmediate_Iv,  &BX_CPU_C::XOR_EAXId },
-  /* 36 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // SS:
-  /* 37 */  { 0,  &BX_CPU_C::AAA },
-  /* 38 */  { BxAnother,  &BX_CPU_C::CMP_EbGb },
-  /* 39 */  { BxAnother,  &BX_CPU_C::CMP_EdGd },
-  /* 3A */  { BxAnother,  &BX_CPU_C::CMP_GbEb },
-  /* 3B */  { BxAnother,  &BX_CPU_C::CMP_GdEd },
-  /* 3C */  { BxImmediate_Ib,  &BX_CPU_C::CMP_ALIb },
-  /* 3D */  { BxImmediate_Iv,  &BX_CPU_C::CMP_EAXId },
-  /* 3E */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // DS:
-  /* 3F */  { 0,  &BX_CPU_C::AAS },
-  /* 40 */  { 0,  &BX_CPU_C::INC_ERX },
-  /* 41 */  { 0,  &BX_CPU_C::INC_ERX },
-  /* 42 */  { 0,  &BX_CPU_C::INC_ERX },
-  /* 43 */  { 0,  &BX_CPU_C::INC_ERX },
-  /* 44 */  { 0,  &BX_CPU_C::INC_ERX },
-  /* 45 */  { 0,  &BX_CPU_C::INC_ERX },
-  /* 46 */  { 0,  &BX_CPU_C::INC_ERX },
-  /* 47 */  { 0,  &BX_CPU_C::INC_ERX },
-  /* 48 */  { 0,  &BX_CPU_C::DEC_ERX },
-  /* 49 */  { 0,  &BX_CPU_C::DEC_ERX },
-  /* 4A */  { 0,  &BX_CPU_C::DEC_ERX },
-  /* 4B */  { 0,  &BX_CPU_C::DEC_ERX },
-  /* 4C */  { 0,  &BX_CPU_C::DEC_ERX },
-  /* 4D */  { 0,  &BX_CPU_C::DEC_ERX },
-  /* 4E */  { 0,  &BX_CPU_C::DEC_ERX },
-  /* 4F */  { 0,  &BX_CPU_C::DEC_ERX },
-  /* 50 */  { 0,  &BX_CPU_C::PUSH_ERX },
-  /* 51 */  { 0,  &BX_CPU_C::PUSH_ERX },
-  /* 52 */  { 0,  &BX_CPU_C::PUSH_ERX },
-  /* 53 */  { 0,  &BX_CPU_C::PUSH_ERX },
-  /* 54 */  { 0,  &BX_CPU_C::PUSH_ERX },
-  /* 55 */  { 0,  &BX_CPU_C::PUSH_ERX },
-  /* 56 */  { 0,  &BX_CPU_C::PUSH_ERX },
-  /* 57 */  { 0,  &BX_CPU_C::PUSH_ERX },
-  /* 58 */  { 0,  &BX_CPU_C::POP_ERX },
-  /* 59 */  { 0,  &BX_CPU_C::POP_ERX },
-  /* 5A */  { 0,  &BX_CPU_C::POP_ERX },
-  /* 5B */  { 0,  &BX_CPU_C::POP_ERX },
-  /* 5C */  { 0,  &BX_CPU_C::POP_ERX },
-  /* 5D */  { 0,  &BX_CPU_C::POP_ERX },
-  /* 5E */  { 0,  &BX_CPU_C::POP_ERX },
-  /* 5F */  { 0,  &BX_CPU_C::POP_ERX },
-  /* 60 */  { 0,  &BX_CPU_C::PUSHAD32 },
-  /* 61 */  { 0,  &BX_CPU_C::POPAD32 },
-  /* 62 */  { BxAnother,  &BX_CPU_C::BOUND_GvMa },
-  /* 63 */  { BxAnother,  &BX_CPU_C::ARPL_EwGw },
-  /* 64 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // FS:
-  /* 65 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // GS:
-  /* 66 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // OS:
-  /* 67 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // AS:
-  /* 68 */  { BxImmediate_Iv,  &BX_CPU_C::PUSH_Id },
-  /* 69 */  { BxAnother | BxImmediate_Iv,  &BX_CPU_C::IMUL_GdEdId },
-  /* 6A */  { BxImmediate_Ib_SE,  &BX_CPU_C::PUSH_Id },
-  /* 6B */  { BxAnother | BxImmediate_Ib_SE,  &BX_CPU_C::IMUL_GdEdId },
-  /* 6C */  { BxRepeatable,  &BX_CPU_C::INSB_YbDX },
-  /* 6D */  { BxRepeatable,  &BX_CPU_C::INSW_YvDX },
-  /* 6E */  { BxRepeatable,  &BX_CPU_C::OUTSB_DXXb },
-  /* 6F */  { BxRepeatable,  &BX_CPU_C::OUTSW_DXXv },
-  /* 70 */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 71 */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 72 */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 73 */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 74 */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 75 */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 76 */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 77 */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 78 */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 79 */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 7A */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 7B */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 7C */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 7D */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 7E */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 7F */  { BxImmediate_BrOff8,  &sid_cpu_c::JCC_Jd },
-  /* 80 */  { BxAnother | BxGroup1,  NULL, BxOpcodeInfoG1EbIb },
-  /* 81 */  { BxAnother | BxGroup1 | BxImmediate_Iv, NULL, BxOpcodeInfoG1Ed },
-  /* 82 */  { BxAnother | BxGroup1,  NULL, BxOpcodeInfoG1EbIb },
-  /* 83 */  { BxAnother | BxGroup1 | BxImmediate_Ib_SE, NULL, BxOpcodeInfoG1Ed },
-  /* 84 */  { BxAnother,  &BX_CPU_C::TEST_EbGb },
-  /* 85 */  { BxAnother,  &BX_CPU_C::TEST_EdGd },
-  /* 86 */  { BxAnother,  &BX_CPU_C::XCHG_EbGb },
-  /* 87 */  { BxAnother,  &BX_CPU_C::XCHG_EdGd },
-  /* 88 */  { BxAnother,  &BX_CPU_C::MOV_EbGb },
-  /* 89 */  { BxAnother,  &BX_CPU_C::MOV_EdGd },
-  /* 8A */  { BxAnother,  &BX_CPU_C::MOV_GbEb },
-  /* 8B */  { BxAnother,  &BX_CPU_C::MOV_GdEd },
-  /* 8C */  { BxAnother,  &BX_CPU_C::MOV_EwSw },
-  /* 8D */  { BxAnother,  &BX_CPU_C::LEA_GdM },
-  /* 8E */  { BxAnother,  &BX_CPU_C::MOV_SwEw },
-  /* 8F */  { BxAnother,  &BX_CPU_C::POP_Ed },
-  /* 90 */  { 0,  &BX_CPU_C::NOP },
-  /* 91 */  { 0,  &BX_CPU_C::XCHG_ERXEAX },
-  /* 92 */  { 0,  &BX_CPU_C::XCHG_ERXEAX },
-  /* 93 */  { 0,  &BX_CPU_C::XCHG_ERXEAX },
-  /* 94 */  { 0,  &BX_CPU_C::XCHG_ERXEAX },
-  /* 95 */  { 0,  &BX_CPU_C::XCHG_ERXEAX },
-  /* 96 */  { 0,  &BX_CPU_C::XCHG_ERXEAX },
-  /* 97 */  { 0,  &BX_CPU_C::XCHG_ERXEAX },
-  /* 98 */  { 0,  &BX_CPU_C::CWDE },
-  /* 99 */  { 0,  &BX_CPU_C::CDQ },
-  /* 9A */  { BxImmediate_IvIw,  &BX_CPU_C::CALL32_Ap },
-  /* 9B */  { 0,  &BX_CPU_C::FWAIT },
-  /* 9C */  { 0,  &BX_CPU_C::PUSHF_Fv },
-  /* 9D */  { 0,  &BX_CPU_C::POPF_Fv },
-  /* 9E */  { 0,  &BX_CPU_C::SAHF },
-  /* 9F */  { 0,  &BX_CPU_C::LAHF },
-  /* A0 */  { BxImmediate_O,  &BX_CPU_C::MOV_ALOb },
-  /* A1 */  { BxImmediate_O,  &BX_CPU_C::MOV_EAXOd },
-  /* A2 */  { BxImmediate_O,  &BX_CPU_C::MOV_ObAL },
-  /* A3 */  { BxImmediate_O,  &BX_CPU_C::MOV_OdEAX },
-  /* A4 */  { BxRepeatable,  &BX_CPU_C::MOVSB_XbYb },
-  /* A5 */  { BxRepeatable,  &BX_CPU_C::MOVSW_XvYv },
-  /* A6 */  { BxRepeatable | BxRepeatableZF,  &BX_CPU_C::CMPSB_XbYb },
-  /* A7 */  { BxRepeatable | BxRepeatableZF,  &BX_CPU_C::CMPSW_XvYv },
-  /* A8 */  { BxImmediate_Ib,  &BX_CPU_C::TEST_ALIb },
-  /* A9 */  { BxImmediate_Iv,  &BX_CPU_C::TEST_EAXId },
-  /* AA */  { BxRepeatable,  &BX_CPU_C::STOSB_YbAL },
-  /* AB */  { BxRepeatable,  &BX_CPU_C::STOSW_YveAX },
-  /* AC */  { BxRepeatable,  &BX_CPU_C::LODSB_ALXb },
-  /* AD */  { BxRepeatable,  &BX_CPU_C::LODSW_eAXXv },
-  /* AE */  { BxRepeatable | BxRepeatableZF,  &BX_CPU_C::SCASB_ALXb },
-  /* AF */  { BxRepeatable | BxRepeatableZF,  &BX_CPU_C::SCASW_eAXXv },
-  /* B0 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RLIb },
-  /* B1 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RLIb },
-  /* B2 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RLIb },
-  /* B3 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RLIb },
-  /* B4 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RHIb },
-  /* B5 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RHIb },
-  /* B6 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RHIb },
-  /* B7 */  { BxImmediate_Ib,  &BX_CPU_C::MOV_RHIb },
-  /* B8 */  { BxImmediate_Iv,  &BX_CPU_C::MOV_ERXId },
-  /* B9 */  { BxImmediate_Iv,  &BX_CPU_C::MOV_ERXId },
-  /* BA */  { BxImmediate_Iv,  &BX_CPU_C::MOV_ERXId },
-  /* BB */  { BxImmediate_Iv,  &BX_CPU_C::MOV_ERXId },
-  /* BC */  { BxImmediate_Iv,  &BX_CPU_C::MOV_ERXId },
-  /* BD */  { BxImmediate_Iv,  &BX_CPU_C::MOV_ERXId },
-  /* BE */  { BxImmediate_Iv,  &BX_CPU_C::MOV_ERXId },
-  /* BF */  { BxImmediate_Iv,  &BX_CPU_C::MOV_ERXId },
-  /* C0 */  { BxAnother | BxGroup2 | BxImmediate_Ib, NULL, BxOpcodeInfoG2Eb },
-  /* C1 */  { BxAnother | BxGroup2 | BxImmediate_Ib, NULL, BxOpcodeInfoG2Ed },
-  /* C2 */  { BxImmediate_Iw,  &BX_CPU_C::RETnear32_Iw },
-  /* C3 */  { 0,             &BX_CPU_C::RETnear32 },
-  /* C4 */  { BxAnother,  &BX_CPU_C::LES_GvMp },
-  /* C5 */  { BxAnother,  &BX_CPU_C::LDS_GvMp },
-  /* C6 */  { BxAnother | BxImmediate_Ib,  &BX_CPU_C::MOV_EbIb },
-  /* C7 */  { BxAnother | BxImmediate_Iv,  &BX_CPU_C::MOV_EdId },
-  /* C8 */  { BxImmediate_IwIb,  &BX_CPU_C::ENTER_IwIb },
-  /* C9 */  { 0,  &BX_CPU_C::LEAVE },
-  /* CA */  { BxImmediate_Iw,  &BX_CPU_C::RETfar32_Iw },
-  /* CB */  { 0,  &BX_CPU_C::RETfar32 },
-  /* CC */  { 0,  &sid_cpu_c::INT3 },
-  /* CD */  { BxImmediate_Ib,  &sid_cpu_c::INT_Ib },
-  /* CE */  { 0,  &BX_CPU_C::INTO },
-  /* CF */  { 0,  &BX_CPU_C::IRET32 },
-  /* D0 */  { BxAnother | BxGroup2,  NULL, BxOpcodeInfoG2Eb },
-  /* D1 */  { BxAnother | BxGroup2,  NULL, BxOpcodeInfoG2Ed },
-  /* D2 */  { BxAnother | BxGroup2,  NULL, BxOpcodeInfoG2Eb },
-  /* D3 */  { BxAnother | BxGroup2,  NULL, BxOpcodeInfoG2Ed },
-  /* D4 */  { BxImmediate_Ib,  &BX_CPU_C::AAM },
-  /* D5 */  { BxImmediate_Ib,  &BX_CPU_C::AAD },
-  /* D6 */  { 0,  &BX_CPU_C::SALC },
-  /* D7 */  { 0,  &BX_CPU_C::XLAT },
-  /* D8 */  { BxAnother,  &BX_CPU_C::ESC0 },
-  /* D9 */  { BxAnother,  &BX_CPU_C::ESC1 },
-  /* DA */  { BxAnother,  &BX_CPU_C::ESC2 },
-  /* DB */  { BxAnother,  &BX_CPU_C::ESC3 },
-  /* DC */  { BxAnother,  &BX_CPU_C::ESC4 },
-  /* DD */  { BxAnother,  &BX_CPU_C::ESC5 },
-  /* DE */  { BxAnother,  &BX_CPU_C::ESC6 },
-  /* DF */  { BxAnother,  &BX_CPU_C::ESC7 },
-  /* E0 */  { BxImmediate_BrOff8,  &BX_CPU_C::LOOPNE_Jb },
-  /* E1 */  { BxImmediate_BrOff8,  &BX_CPU_C::LOOPE_Jb },
-  /* E2 */  { BxImmediate_BrOff8,  &BX_CPU_C::LOOP_Jb },
-  /* E3 */  { BxImmediate_BrOff8,  &BX_CPU_C::JCXZ_Jb },
-  /* E4 */  { BxImmediate_Ib,  &BX_CPU_C::IN_ALIb },
-  /* E5 */  { BxImmediate_Ib,  &BX_CPU_C::IN_eAXIb },
-  /* E6 */  { BxImmediate_Ib,  &BX_CPU_C::OUT_IbAL },
-  /* E7 */  { BxImmediate_Ib,  &BX_CPU_C::OUT_IbeAX },
-  /* E8 */  { BxImmediate_BrOff32,  &BX_CPU_C::CALL_Ad },
-  /* E9 */  { BxImmediate_BrOff32,  &BX_CPU_C::JMP_Jd },
-  /* EA */  { BxImmediate_IvIw,  &BX_CPU_C::JMP_Ap },
-  /* EB */  { BxImmediate_BrOff8,  &BX_CPU_C::JMP_Jd },
-  /* EC */  { 0,  &BX_CPU_C::IN_ALDX },
-  /* ED */  { 0,  &BX_CPU_C::IN_eAXDX },
-  /* EE */  { 0,  &BX_CPU_C::OUT_DXAL },
-  /* EF */  { 0,  &BX_CPU_C::OUT_DXeAX },
-  /* F0 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // LOCK:
-  /* F1 */  { 0,  &BX_CPU_C::INT1 },
-  /* F2 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // REPNE/REPNZ
-  /* F3 */  { BxPrefix | BxAnother,  &BX_CPU_C::BxError }, // REP,REPE/REPZ
-  /* F4 */  { 0,  &BX_CPU_C::HLT },
-  /* F5 */  { 0,  &BX_CPU_C::CMC },
-  /* F6 */  { BxAnother | BxGroup3,  NULL, BxOpcodeInfoG3Eb },
-  /* F7 */  { BxAnother | BxGroup3,  NULL, BxOpcodeInfoG3Ed },
-  /* F8 */  { 0,  &BX_CPU_C::CLC },
-  /* F9 */  { 0,  &BX_CPU_C::STC },
-  /* FA */  { 0,  &BX_CPU_C::CLI },
-  /* FB */  { 0,  &BX_CPU_C::STI },
-  /* FC */  { 0,  &BX_CPU_C::CLD },
-  /* FD */  { 0,  &BX_CPU_C::STD },
-  /* FE */  { BxAnother | BxGroup4,  NULL, BxOpcodeInfoG4 },
-  /* FF */  { BxAnother | BxGroup5,  NULL, BxOpcodeInfoG5d },
-
-  /* 0F 00 */  { BxAnother | BxGroup6,  NULL, BxOpcodeInfoG6 },
-  /* 0F 01 */  { BxAnother | BxGroup7,  NULL, BxOpcodeInfoG7 },
-  /* 0F 02 */  { BxAnother,  &BX_CPU_C::LAR_GvEw },
-  /* 0F 03 */  { BxAnother,  &BX_CPU_C::LSL_GvEw },
-  /* 0F 04 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 05 */  { 0,  &BX_CPU_C::LOADALL },
-  /* 0F 06 */  { 0,  &BX_CPU_C::CLTS },
-  /* 0F 07 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 08 */  { 0,  &BX_CPU_C::INVD },
-  /* 0F 09 */  { 0,  &BX_CPU_C::WBINVD },
-  /* 0F 0A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 0B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 0C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 0D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 0E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 0F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 10 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 11 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 12 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 13 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 14 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 15 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 16 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 17 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 18 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 19 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 1A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 1B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 1C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 1D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 1E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 1F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 20 */  { BxAnother,  &BX_CPU_C::MOV_RdCd },
-  /* 0F 21 */  { BxAnother,  &BX_CPU_C::MOV_RdDd },
-  /* 0F 22 */  { BxAnother,  &BX_CPU_C::MOV_CdRd },
-  /* 0F 23 */  { BxAnother,  &BX_CPU_C::MOV_DdRd },
-  /* 0F 24 */  { BxAnother,  &BX_CPU_C::MOV_RdTd },
-  /* 0F 25 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 26 */  { BxAnother,  &BX_CPU_C::MOV_TdRd },
-  /* 0F 27 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 28 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 29 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 2A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 2B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 2C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 2D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 2E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 2F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 30 */  { 0,  &BX_CPU_C::WRMSR },
-  /* 0F 31 */  { 0,  &BX_CPU_C::RDTSC },
-  /* 0F 32 */  { 0,  &BX_CPU_C::RDMSR },
-  /* 0F 33 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 34 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 35 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 36 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 37 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 38 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 39 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 3A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 3B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 3C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 3D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 3E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 3F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 40 */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 41 */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 42 */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 43 */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 44 */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 45 */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 46 */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 47 */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 48 */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 49 */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 4A */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 4B */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 4C */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 4D */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 4E */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 4F */  { BxAnother,  &BX_CPU_C::CMOV_GdEd },
-  /* 0F 50 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 51 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 52 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 53 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 54 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 55 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 56 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 57 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 58 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 59 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 5A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 5B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 5C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 5D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 5E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 5F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 60 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 61 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 62 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 63 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 64 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 65 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 66 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 67 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 68 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 69 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 6A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 6B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 6C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 6D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 6E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 6F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 70 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 71 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 72 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 73 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 74 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 75 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 76 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 77 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 78 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 79 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 7A */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 7B */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 7C */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 7D */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 7E */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 7F */  { 0,  &BX_CPU_C::BxError },
-  /* 0F 80 */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 81 */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 82 */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 83 */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 84 */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 85 */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 86 */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 87 */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 88 */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 89 */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 8A */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 8B */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 8C */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 8D */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 8E */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 8F */  { BxImmediate_BrOff32,  &sid_cpu_c::JCC_Jd },
-  /* 0F 90 */  { BxAnother,  &BX_CPU_C::SETO_Eb },
-  /* 0F 91 */  { BxAnother,  &BX_CPU_C::SETNO_Eb },
-  /* 0F 92 */  { BxAnother,  &BX_CPU_C::SETB_Eb },
-  /* 0F 93 */  { BxAnother,  &BX_CPU_C::SETNB_Eb },
-  /* 0F 94 */  { BxAnother,  &BX_CPU_C::SETZ_Eb },
-  /* 0F 95 */  { BxAnother,  &BX_CPU_C::SETNZ_Eb },
-  /* 0F 96 */  { BxAnother,  &BX_CPU_C::SETBE_Eb },
-  /* 0F 97 */  { BxAnother,  &BX_CPU_C::SETNBE_Eb },
-  /* 0F 98 */  { BxAnother,  &BX_CPU_C::SETS_Eb },
-  /* 0F 99 */  { BxAnother,  &BX_CPU_C::SETNS_Eb },
-  /* 0F 9A */  { BxAnother,  &BX_CPU_C::SETP_Eb },
-  /* 0F 9B */  { BxAnother,  &BX_CPU_C::SETNP_Eb },
-  /* 0F 9C */  { BxAnother,  &BX_CPU_C::SETL_Eb },
-  /* 0F 9D */  { BxAnother,  &BX_CPU_C::SETNL_Eb },
-  /* 0F 9E */  { BxAnother,  &BX_CPU_C::SETLE_Eb },
-  /* 0F 9F */  { BxAnother,  &BX_CPU_C::SETNLE_Eb },
-  /* 0F A0 */  { 0,  &BX_CPU_C::PUSH_FS },
-  /* 0F A1 */  { 0,  &BX_CPU_C::POP_FS },
-  /* 0F A2 */  { 0,  &BX_CPU_C::CPUID },
-  /* 0F A3 */  { BxAnother,  &BX_CPU_C::BT_EvGv },
-  /* 0F A4 */  { BxAnother | BxImmediate_Ib,  &BX_CPU_C::SHLD_EdGd },
-  /* 0F A5 */  { BxAnother,                 &BX_CPU_C::SHLD_EdGd },
-  /* 0F A6 */  { 0,  &BX_CPU_C::CMPXCHG_XBTS },
-  /* 0F A7 */  { 0,  &BX_CPU_C::CMPXCHG_IBTS },
-  /* 0F A8 */  { 0,  &BX_CPU_C::PUSH_GS },
-  /* 0F A9 */  { 0,  &BX_CPU_C::POP_GS },
-  /* 0F AA */  { 0,  &BX_CPU_C::RSM },
-  /* 0F AB */  { BxAnother,  &BX_CPU_C::BTS_EvGv },
-  /* 0F AC */  { BxAnother | BxImmediate_Ib,  &BX_CPU_C::SHRD_EdGd },
-  /* 0F AD */  { BxAnother,                 &BX_CPU_C::SHRD_EdGd },
-  /* 0F AE */  { 0,  &BX_CPU_C::BxError },
-  /* 0F AF */  { BxAnother,  &BX_CPU_C::IMUL_GdEd },
-  /* 0F B0 */  { BxAnother,  &BX_CPU_C::CMPXCHG_EbGb },
-  /* 0F B1 */  { BxAnother,  &BX_CPU_C::CMPXCHG_EdGd },
-  /* 0F B2 */  { BxAnother,  &BX_CPU_C::LSS_GvMp },
-  /* 0F B3 */  { BxAnother,  &BX_CPU_C::BTR_EvGv },
-  /* 0F B4 */  { BxAnother,  &BX_CPU_C::LFS_GvMp },
-  /* 0F B5 */  { BxAnother,  &BX_CPU_C::LGS_GvMp },
-  /* 0F B6 */  { BxAnother,  &BX_CPU_C::MOVZX_GdEb },
-  /* 0F B7 */  { BxAnother,  &BX_CPU_C::MOVZX_GdEw },
-  /* 0F B8 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F B9 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F BA */  { BxAnother | BxGroup8,  NULL, BxOpcodeInfoG8EvIb },
-  /* 0F BB */  { BxAnother,  &BX_CPU_C::BTC_EvGv },
-  /* 0F BC */  { BxAnother,  &BX_CPU_C::BSF_GvEv },
-  /* 0F BD */  { BxAnother,  &BX_CPU_C::BSR_GvEv },
-  /* 0F BE */  { BxAnother,  &BX_CPU_C::MOVSX_GdEb },
-  /* 0F BF */  { BxAnother,  &BX_CPU_C::MOVSX_GdEw },
-  /* 0F C0 */  { BxAnother,  &BX_CPU_C::XADD_EbGb },
-  /* 0F C1 */  { BxAnother,  &BX_CPU_C::XADD_EdGd },
-  /* 0F C2 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F C3 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F C4 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F C5 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F C6 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F C7 */  { BxAnother | BxGroup9,  NULL, BxOpcodeInfoG9 },
-  /* 0F C8 */  { 0,  &BX_CPU_C::BSWAP_EAX },
-  /* 0F C9 */  { 0,  &BX_CPU_C::BSWAP_ECX },
-  /* 0F CA */  { 0,  &BX_CPU_C::BSWAP_EDX },
-  /* 0F CB */  { 0,  &BX_CPU_C::BSWAP_EBX },
-  /* 0F CC */  { 0,  &BX_CPU_C::BSWAP_ESP },
-  /* 0F CD */  { 0,  &BX_CPU_C::BSWAP_EBP },
-  /* 0F CE */  { 0,  &BX_CPU_C::BSWAP_ESI },
-  /* 0F CF */  { 0,  &BX_CPU_C::BSWAP_EDI },
-  /* 0F D0 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D1 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D2 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D3 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D4 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D5 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D6 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D7 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D8 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F D9 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F DA */  { 0,  &BX_CPU_C::BxError },
-  /* 0F DB */  { 0,  &BX_CPU_C::BxError },
-  /* 0F DC */  { 0,  &BX_CPU_C::BxError },
-  /* 0F DD */  { 0,  &BX_CPU_C::BxError },
-  /* 0F DE */  { 0,  &BX_CPU_C::BxError },
-  /* 0F DF */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E0 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E1 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E2 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E3 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E4 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E5 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E6 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E7 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E8 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F E9 */  { 0,  &BX_CPU_C::BxError },
-  /* 0F EA */  { 0,  &BX_CPU_C::BxError },
-  /* 0F EB */  { 0,  &BX_CPU_C::BxError },
-  /* 0F EC */  { 0,  &BX_CPU_C::BxError },
-  /* 0F ED */  { 0,  &BX_CPU_C::BxError },
-  /* 0F EE */  { 0,  &BX_CPU_C::BxError },
-  /* 0F EF */  { 0,  &BX_CPU_C::BxError },
-  /* 0F F0 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F1 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F2 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F3 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F4 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F5 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F6 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F7 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F8 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F F9 */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F FA */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F FB */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F FC */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F FD */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F FE */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  /* 0F FF */  { 0,  &BX_CPU_C::UndefinedOpcode },
-  };
-
-
-
-
-  unsigned
-sid_cpu_c::FetchDecode(Bit8u *iptr, BxInstruction_t *instruction,
-                      unsigned remain, Boolean is_32)
-{
-  // remain must be at least 1
-
-  unsigned b1, b2, ilen=1, attr;
-  unsigned imm_mode, offset;
-
-  instruction->os_32 = instruction->as_32 = is_32;
-  instruction->ResolveModrm = NULL;
-  instruction->seg = BX_SEG_REG_NULL;
-  instruction->rep_used = 0;
-
-fetch_b1:
-  b1 = *iptr++;
-
-another_byte:
-  offset = instruction->os_32 << 9; // * 512
-  instruction->attr = attr = BxOpcodeInfo[b1+offset].Attr;
-
-  if (attr & BxAnother) {
-    if (attr & BxPrefix) {
-      switch (b1) {
-        case 0x66: // OpSize
-          instruction->os_32 = !is_32;
-          if (ilen < remain) {
-            ilen++;
-            goto fetch_b1;
-            }
-          return(0);
-
-        case 0x67: // AddrSize
-          instruction->as_32 = !is_32;
-          if (ilen < remain) {
-            ilen++;
-            goto fetch_b1;
-            }
-          return(0);
-
-        case 0xf2: // REPNE/REPNZ
-        case 0xf3: // REP/REPE/REPZ
-          instruction->rep_used = b1;
-          if (ilen < remain) {
-            ilen++;
-            goto fetch_b1;
-            }
-          return(0);
-          break;
-
-        case 0x2e: // CS:
-          instruction->seg = BX_SEG_REG_CS;
-          ilen++; goto fetch_b1;
-          break;
-        case 0x26: // ES:
-          instruction->seg = BX_SEG_REG_ES;
-          ilen++; goto fetch_b1;
-          break;
-        case 0x36: // SS:
-          instruction->seg = BX_SEG_REG_SS;
-          ilen++; goto fetch_b1;
-          break;
-        case 0x3e: // DS:
-          instruction->seg = BX_SEG_REG_DS;
-          ilen++; goto fetch_b1;
-          break;
-        case 0x64: // FS:
-          instruction->seg = BX_SEG_REG_FS;
-          ilen++; goto fetch_b1;
-          break;
-        case 0x65: // GS:
-          instruction->seg = BX_SEG_REG_GS;
-          ilen++; goto fetch_b1;
-          break;
-        case 0xf0: // LOCK:
-          ilen++; goto fetch_b1;
-          break;
-
-        default:
-BX_PANIC(("fetch_decode: prefix default = 0x%02x\n", b1));
-        }
-      }
-    // opcode requires another byte
-    if (ilen < remain) {
-      ilen++;
-      b2 = *iptr++;
-      if (b1 == 0x0f) {
-        // 2-byte prefix
-        b1 = 0x100 | b2;
-        goto another_byte;
-        }
-      }
-    else
-      return(0);
-
-    // Parse mod-nnn-rm and related bytes
-    unsigned rm;
-    instruction->modrm = b2;
-    rm =
-    instruction->rm    = b2 & 0x07;
-    instruction->mod   = b2 & 0xc0; // leave unshifted
-    instruction->nnn   = (b2 >> 3) & 0x07;
-    if (instruction->mod == 0xc0) { // mod == 11b
-      goto modrm_done;
-      }
-    if (instruction->as_32) {
-      // 32-bit addressing modes; note that mod==11b handled above
-      if (rm != 4) { // no s-i-b byte
-#if BX_DYNAMIC_TRANSLATION
-        instruction->DTMemRegsUsed = 1<<rm; // except for mod=00b rm=100b
-#endif
-        if (instruction->mod == 0x00) { // mod == 00b
-          instruction->ResolveModrm = BxResolve32Mod0[rm];
-#if BX_DYNAMIC_TRANSLATION
-          instruction->DTResolveModrm = (BxVoidFPtr_t) BxDTResolve32Mod0[rm];
-#endif
-          if (BX_NULL_SEG_REG(instruction->seg))
-            instruction->seg = BX_SEG_REG_DS;
-          if (rm == 5) {
-            if ((ilen+3) < remain) {
-              Bit32u imm32u;
-              imm32u = *iptr++;
-              imm32u |= (*iptr++) << 8;
-              imm32u |= (*iptr++) << 16;
-              imm32u |= (*iptr++) << 24;
-              instruction->rm_addr = imm32u;
-              ilen += 4;
-#if BX_DYNAMIC_TRANSLATION
-              instruction->DTMemRegsUsed = 0;
-#endif
-              goto modrm_done;
-              }
-            else {
-              return(0);
-              }
-            }
-          // mod==00b, rm!=4, rm!=5
-          goto modrm_done;
-          }
-        if (instruction->mod == 0x40) { // mod == 01b
-          instruction->ResolveModrm = BxResolve32Mod1or2[rm];
-#if BX_DYNAMIC_TRANSLATION
-          instruction->DTResolveModrm = (BxVoidFPtr_t) BxDTResolve32Mod1or2[rm];
-#endif
-          if (BX_NULL_SEG_REG(instruction->seg))
-            instruction->seg = BX_CPU_THIS_PTR sreg_mod01_rm32[rm];
-get_8bit_displ:
-          if (ilen < remain) {
-            // 8 sign extended to 32
-            instruction->displ32u = (Bit8s) *iptr++;
-            ilen++;
-            goto modrm_done;
-            }
-          else {
-            return(0);
-            }
-          }
-        // (mod == 0x80) mod == 10b
-        instruction->ResolveModrm = BxResolve32Mod1or2[rm];
-#if BX_DYNAMIC_TRANSLATION
-        instruction->DTResolveModrm = (BxVoidFPtr_t) BxDTResolve32Mod1or2[rm];
-#endif
-        if (BX_NULL_SEG_REG(instruction->seg))
-          instruction->seg = BX_CPU_THIS_PTR sreg_mod10_rm32[rm];
-get_32bit_displ:
-        if ((ilen+3) < remain) {
-          Bit32u imm32u;
-          imm32u = *iptr++;
-          imm32u |= (*iptr++) << 8;
-          imm32u |= (*iptr++) << 16;
-          imm32u |= (*iptr++) << 24;
-          instruction->displ32u = imm32u;
-          ilen += 4;
-          goto modrm_done;
-          }
-        else {
-          return(0);
-          }
-        }
-      else { // mod!=11b, rm==4, s-i-b byte follows
-        unsigned sib, base;
-        if (ilen < remain) {
-          sib = *iptr++;
-          ilen++;
-          }
-        else {
-          return(0);
-          }
-        instruction->sib   = sib;
-        base =
-        instruction->base  = sib & 0x07; sib >>= 3;
-        instruction->index = sib & 0x07; sib >>= 3;
-        instruction->scale = sib;
-#if BX_DYNAMIC_TRANSLATION
-        if (instruction->index == 0x04) // 100b
-          instruction->DTMemRegsUsed = 0;
-        else
-          instruction->DTMemRegsUsed = 1<<instruction->index;
-#endif
-        if (instruction->mod == 0x00) { // mod==00b, rm==4
-          instruction->ResolveModrm = BxResolve32Mod0Base[base];
-#if BX_DYNAMIC_TRANSLATION
-          instruction->DTResolveModrm = (BxVoidFPtr_t) BxDTResolve32Mod0Base[base];
-#endif
-          if (BX_NULL_SEG_REG(instruction->seg))
-            instruction->seg = BX_CPU_THIS_PTR sreg_mod0_base32[base];
-          if (instruction->base == 0x05) {
-            goto get_32bit_displ;
-            }
-          // mod==00b, rm==4, base!=5
-#if BX_DYNAMIC_TRANSLATION
-          instruction->DTMemRegsUsed |= 1<<base;
-#endif
-          goto modrm_done;
-          }
-#if BX_DYNAMIC_TRANSLATION
-        // for remaining 32bit cases
-        instruction->DTMemRegsUsed |= 1<<base;
-#endif
-        if (instruction->mod == 0x40) { // mod==01b, rm==4
-          instruction->ResolveModrm = BxResolve32Mod1or2Base[base];
-#if BX_DYNAMIC_TRANSLATION
-          instruction->DTResolveModrm = (BxVoidFPtr_t) BxDTResolve32Mod1or2Base[base];
-#endif
-          if (BX_NULL_SEG_REG(instruction->seg))
-            instruction->seg = BX_CPU_THIS_PTR sreg_mod1or2_base32[base];
-          goto get_8bit_displ;
-          }
-        // (instruction->mod == 0x80),  mod==10b, rm==4
-        instruction->ResolveModrm = BxResolve32Mod1or2Base[base];
-#if BX_DYNAMIC_TRANSLATION
-        instruction->DTResolveModrm = (BxVoidFPtr_t) BxDTResolve32Mod1or2Base[base];
-#endif
-        if (BX_NULL_SEG_REG(instruction->seg))
-          instruction->seg = BX_CPU_THIS_PTR sreg_mod1or2_base32[base];
-        goto get_32bit_displ;
-        }
-      }
-    else {
-      // 16-bit addressing modes, mod==11b handled above
-      if (instruction->mod == 0x40) { // mod == 01b
-        instruction->ResolveModrm = BxResolve16Mod1or2[rm];
-#if BX_DYNAMIC_TRANSLATION
-        instruction->DTResolveModrm = (BxVoidFPtr_t) BxDTResolve16Mod1or2[rm];
-#endif
-        if (BX_NULL_SEG_REG(instruction->seg))
-          instruction->seg = BX_CPU_THIS_PTR sreg_mod01_rm16[rm];
-#if BX_DYNAMIC_TRANSLATION
-        instruction->DTMemRegsUsed = BxMemRegsUsed16[rm];
-#endif
-        if (ilen < remain) {
-          // 8 sign extended to 16
-          instruction->displ16u = (Bit8s) *iptr++;
-          ilen++;
-          goto modrm_done;
-          }
-        else {
-          return(0);
-          }
-        }
-      if (instruction->mod == 0x80) { // mod == 10b
-        instruction->ResolveModrm = BxResolve16Mod1or2[rm];
-#if BX_DYNAMIC_TRANSLATION
-        instruction->DTResolveModrm = (BxVoidFPtr_t) BxDTResolve16Mod1or2[rm];
-#endif
-        if (BX_NULL_SEG_REG(instruction->seg))
-          instruction->seg = BX_CPU_THIS_PTR sreg_mod10_rm16[rm];
-#if BX_DYNAMIC_TRANSLATION
-        instruction->DTMemRegsUsed = BxMemRegsUsed16[rm];
-#endif
-        if ((ilen+1) < remain) {
-          Bit16u displ16u;
-          displ16u = *iptr++;
-          displ16u |= (*iptr++) << 8;
-          instruction->displ16u = displ16u;
-          ilen += 2;
-          goto modrm_done;
-          }
-        else {
-          return(0);
-          }
-        }
-      // mod must be 00b at this point
-      instruction->ResolveModrm = BxResolve16Mod0[rm];
-#if BX_DYNAMIC_TRANSLATION
-      instruction->DTResolveModrm = (BxVoidFPtr_t) BxDTResolve16Mod0[rm];
-#endif
-      if (BX_NULL_SEG_REG(instruction->seg))
-        instruction->seg = BX_CPU_THIS_PTR sreg_mod00_rm16[rm];
-      if (rm == 0x06) {
-        if ((ilen+1) < remain) {
-          Bit16u displ16u;
-          displ16u = *iptr++;
-          displ16u |= (*iptr++) << 8;
-          instruction->rm_addr = displ16u;
-          ilen += 2;
-          goto modrm_done;
-          }
-        else {
-          return(0);
-          }
-        }
-      // mod=00b rm!=6
-#if BX_DYNAMIC_TRANSLATION
-      instruction->DTMemRegsUsed = BxMemRegsUsed16[rm];
-#endif
-      }
-
-modrm_done:
-    if (attr & BxGroupN) {
-      BxOpcodeInfo_t *OpcodeInfoPtr;
-
-      OpcodeInfoPtr = BxOpcodeInfo[b1+offset].AnotherArray;
-      instruction->execute_sid = OpcodeInfoPtr[instruction->nnn].ExecutePtr;
-      // get additional attributes from group table
-      attr |= OpcodeInfoPtr[instruction->nnn].Attr;
-      instruction->attr = attr;
-#if BX_DYNAMIC_TRANSLATION
-      instruction->DTAttr = 0; // for now
-#endif
-      }
-    else {
-      instruction->execute_sid = BxOpcodeInfo[b1+offset].ExecutePtr;
-#if BX_DYNAMIC_TRANSLATION
-      instruction->DTAttr = BxDTOpcodeInfo[b1+offset].DTAttr;
-      instruction->DTFPtr = BxDTOpcodeInfo[b1+offset].DTASFPtr;
-#endif
-      }
-    }
-  else {
-    // Opcode does not require a MODRM byte.
-    // Note that a 2-byte opcode (0F XX) will jump to before
-    // the if() above after fetching the 2nd byte, so this path is
-    // taken in all cases if a modrm byte is NOT required.
-    instruction->execute_sid = BxOpcodeInfo[b1+offset].ExecutePtr;
-#if BX_DYNAMIC_TRANSLATION
-    instruction->DTAttr = BxDTOpcodeInfo[b1+offset].DTAttr;
-    instruction->DTFPtr = BxDTOpcodeInfo[b1+offset].DTASFPtr;
-#endif
-    }
-
-
-  imm_mode = attr & BxImmediate;
-
-  if (imm_mode) {
-    switch (imm_mode) {
-      case BxImmediate_Ib:
-        if (ilen < remain) {
-          instruction->Ib = *iptr;
-          ilen++;
-          }
-        else {
-          return(0);
-          }
-        break;
-      case BxImmediate_Ib_SE: // Sign extend to OS size
-        if (ilen < remain) {
-          Bit8s temp8s;
-          temp8s = *iptr;
-          if (instruction->os_32)
-            instruction->Id = (Bit32s) temp8s;
-          else
-            instruction->Iw = (Bit16s) temp8s;
-          ilen++;
-          }
-        else {
-          return(0);
-          }
-        break;
-      case BxImmediate_Iv: // same as BxImmediate_BrOff32
-      case BxImmediate_IvIw: // CALL_Ap
-        if (instruction->os_32) {
-          if ((ilen+3) < remain) {
-            Bit32u imm32u;
-            imm32u = *iptr++;
-            imm32u |= (*iptr++) << 8;
-            imm32u |= (*iptr++) << 16;
-            imm32u |= (*iptr) << 24;
-            instruction->Id = imm32u;
-            ilen += 4;
-            }
-          else {
-            return(0);
-            }
-          }
-        else {
-          if ((ilen+1) < remain) {
-            Bit16u imm16u;
-            imm16u = *iptr++;
-            imm16u |= (*iptr) << 8;
-            instruction->Iw = imm16u;
-            ilen += 2;
-            }
-          else {
-            return(0);
-            }
-          }
-        if (imm_mode != BxImmediate_IvIw)
-          break;
-        iptr++;
-        // Get Iw for BxImmediate_IvIw
-        if ((ilen+1) < remain) {
-          Bit16u imm16u;
-          imm16u = *iptr++;
-          imm16u |= (*iptr) << 8;
-          instruction->Iw2 = imm16u;
-          ilen += 2;
-          }
-        else {
-          return(0);
-          }
-        break;
-      case BxImmediate_O:
-        if (instruction->as_32) {
-          // fetch 32bit address into Id
-          if ((ilen+3) < remain) {
-            Bit32u imm32u;
-            imm32u = *iptr++;
-            imm32u |= (*iptr++) << 8;
-            imm32u |= (*iptr++) << 16;
-            imm32u |= (*iptr) << 24;
-            instruction->Id = imm32u;
-            ilen += 4;
-            }
-          else {
-            return(0);
-            }
-          }
-        else {
-          // fetch 16bit address into Id
-          if ((ilen+1) < remain) {
-            Bit32u imm32u;
-            imm32u = *iptr++;
-            imm32u |= (*iptr) << 8;
-            instruction->Id = imm32u;
-            ilen += 2;
-            }
-          else {
-            return(0);
-            }
-          }
-        break;
-      case BxImmediate_Iw:
-      case BxImmediate_IwIb:
-        if ((ilen+1) < remain) {
-          Bit16u imm16u;
-          imm16u = *iptr++;
-          imm16u |= (*iptr) << 8;
-          instruction->Iw = imm16u;
-          ilen += 2;
-          }
-        else {
-          return(0);
-          }
-        if (imm_mode == BxImmediate_Iw) break;
-        iptr++;
-        if (ilen < remain) {
-          instruction->Ib2 = *iptr;
-          ilen++;
-          }
-        else {
-          return(0);
-          }
-        break;
-      case BxImmediate_BrOff8:
-        if (ilen < remain) {
-          Bit8s temp8s;
-          temp8s = *iptr;
-          instruction->Id = temp8s;
-          ilen++;
-          }
-        else {
-          return(0);
-          }
-        break;
-      case BxImmediate_BrOff16:
-        if ((ilen+1) < remain) {
-          Bit16u imm16u;
-          imm16u = *iptr++;
-          imm16u |= (*iptr) << 8;
-          instruction->Id = (Bit16s) imm16u;
-          ilen += 2;
-          }
-        else {
-          return(0);
-          }
-        break;
-      default:
-BX_INFO(("b1 was %x\n", b1));
-        BX_PANIC(("fetchdecode: imm_mode = %u\n", imm_mode));
-      }
-    }
-
-  instruction->b1 = b1;
-  instruction->ilen = ilen;
-  //instruction->flags_in  = 0; // for now
-  //instruction->flags_out = 0; // for now
-  return(1);
-}
-#if 0
-  void
-BX_CPU_C::BxError(BxInstruction_t *i)
-{
-  // extern void dump_core();
-  BX_INFO(("BxError: instruction with op1=0x%x\n", i->b1));
-  BX_INFO(("nnn was %u\n", i->nnn));
-
-  BX_INFO(("WARNING: Encountered an unknown instruction (signalling illegal instruction):\n"));
-  // dump_core();
-
-  BX_CPU_THIS_PTR UndefinedOpcode(i);
-}
-
-  void
-BX_CPU_C::BxResolveError(BxInstruction_t *i)
-{
-  BX_PANIC(("BxResolveError: instruction with op1=0x%x\n", i->b1));
-}
-#endif
diff --git a/sid/component/bochs/cpu/fpu/Makefile.am b/sid/component/bochs/cpu/fpu/Makefile.am
new file mode 100644 (file)
index 0000000..f6977d5
--- /dev/null
@@ -0,0 +1,11 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(srcdir)/../.. -I$(srcdir) -I$(srcdir)/stubs -DUSE_WITH_CPU_SIM -DPARANOID -DNO_ASSEMBLER
+
+noinst_LTLIBRARIES = libfpu.la
+
+libfpu_la_SOURCES = fpu.cc wmFPUemu_glue.cc fpu_entry.c errors.c reg_ld_str.c load_store.c fpu_arith.c fpu_aux.c fpu_etc.c fpu_tags.c fpu_trig.c poly_atan.c poly_l2.c poly_2xm1.c poly_sin.c poly_tan.c reg_add_sub.c reg_compare.c reg_constant.c reg_convert.c reg_divide.c reg_mul.c reg_u_add.c reg_u_div.c reg_u_mul.c reg_u_sub.c div_small.c reg_norm.c reg_round.c wm_shrx.c wm_sqrt.c div_Xsig.c polynom_Xsig.c round_Xsig.c shr_Xsig.c mul_Xsig.c
+
+libfpu_la_LDFLAGS = -no-undefined
diff --git a/sid/component/bochs/cpu/fpu/Makefile.in b/sid/component/bochs/cpu/fpu/Makefile.in
new file mode 100644 (file)
index 0000000..85c073c
--- /dev/null
@@ -0,0 +1,429 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+APIC_OBJS = @APIC_OBJS@
+AR = @AR@
+AS = @AS@
+AS_DYNAMIC_INCS = @AS_DYNAMIC_INCS@
+AS_DYNAMIC_OBJS = @AS_DYNAMIC_OBJS@
+BX_LOADER_OBJS = @BX_LOADER_OBJS@
+BX_SPLIT_HD_SUPPORT = @BX_SPLIT_HD_SUPPORT@
+CC = @CC@
+CDROM_OBJS = @CDROM_OBJS@
+CD_UP_ONE = @CD_UP_ONE@
+CD_UP_TWO = @CD_UP_TWO@
+CFP = @CFP@
+COMMAND_SEPARATOR = @COMMAND_SEPARATOR@
+CPP_SUFFIX = @CPP_SUFFIX@
+CXX = @CXX@
+CXXFP = @CXXFP@
+DASH = @DASH@
+DEBUGGER_VAR = @DEBUGGER_VAR@
+DISASM_VAR = @DISASM_VAR@
+DLLTOOL = @DLLTOOL@
+DYNAMIC_VAR = @DYNAMIC_VAR@
+EXE = @EXE@
+EXEEXT = @EXEEXT@
+EXTERNAL_DEPENDENCY = @EXTERNAL_DEPENDENCY@
+FPU_GLUE_OBJ = @FPU_GLUE_OBJ@
+FPU_VAR = @FPU_VAR@
+GUI_LINK_OPTS = @GUI_LINK_OPTS@
+GUI_LINK_OPTS_TERM = @GUI_LINK_OPTS_TERM@
+GUI_OBJS = @GUI_OBJS@
+GZIP = @GZIP@
+INLINE_VAR = @INLINE_VAR@
+INSTRUMENT_DIR = @INSTRUMENT_DIR@
+INSTRUMENT_VAR = @INSTRUMENT_VAR@
+IOAPIC_OBJS = @IOAPIC_OBJS@
+IODEV_LIB_VAR = @IODEV_LIB_VAR@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LINK = @LINK@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKELIB = @MAKELIB@
+NE2K_OBJS = @NE2K_OBJS@
+NM = @NM@
+NONINLINE_VAR = @NONINLINE_VAR@
+OBJDUMP = @OBJDUMP@
+OFP = @OFP@
+PACKAGE = @PACKAGE@
+PCI_OBJ = @PCI_OBJ@
+PRIMARY_TARGET = @PRIMARY_TARGET@
+RANLIB = @RANLIB@
+READLINE_LIB = @READLINE_LIB@
+RFB_LIBS = @RFB_LIBS@
+RMCOMMAND = @RMCOMMAND@
+SB16_OBJS = @SB16_OBJS@
+SLASH = @SLASH@
+SUFFIX_LINE = @SUFFIX_LINE@
+TAR = @TAR@
+VERSION = @VERSION@
+VIDEO_OBJS = @VIDEO_OBJS@
+sidtarget_arm = @sidtarget_arm@
+sidtarget_m32r = @sidtarget_m32r@
+sidtarget_m68k = @sidtarget_m68k@
+sidtarget_mips = @sidtarget_mips@
+sidtarget_ppc = @sidtarget_ppc@
+sidtarget_x86 = @sidtarget_x86@
+sidtarget_xstormy16 = @sidtarget_xstormy16@
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(srcdir)/../.. -I$(srcdir) -I$(srcdir)/stubs -DUSE_WITH_CPU_SIM -DPARANOID -DNO_ASSEMBLER
+
+noinst_LTLIBRARIES = libfpu.la
+
+libfpu_la_SOURCES = fpu.cc wmFPUemu_glue.cc fpu_entry.c errors.c reg_ld_str.c load_store.c fpu_arith.c fpu_aux.c fpu_etc.c fpu_tags.c fpu_trig.c poly_atan.c poly_l2.c poly_2xm1.c poly_sin.c poly_tan.c reg_add_sub.c reg_compare.c reg_constant.c reg_convert.c reg_divide.c reg_mul.c reg_u_add.c reg_u_div.c reg_u_mul.c reg_u_sub.c div_small.c reg_norm.c reg_round.c wm_shrx.c wm_sqrt.c div_Xsig.c polynom_Xsig.c round_Xsig.c shr_Xsig.c mul_Xsig.c
+
+libfpu_la_LDFLAGS = -no-undefined
+mkinstalldirs = $(SHELL) $(top_srcdir)/../../config/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LTLIBRARIES =  $(noinst_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libfpu_la_LIBADD = 
+libfpu_la_OBJECTS =  fpu.lo wmFPUemu_glue.lo fpu_entry.lo errors.lo \
+reg_ld_str.lo load_store.lo fpu_arith.lo fpu_aux.lo fpu_etc.lo \
+fpu_tags.lo fpu_trig.lo poly_atan.lo poly_l2.lo poly_2xm1.lo \
+poly_sin.lo poly_tan.lo reg_add_sub.lo reg_compare.lo reg_constant.lo \
+reg_convert.lo reg_divide.lo reg_mul.lo reg_u_add.lo reg_u_div.lo \
+reg_u_mul.lo reg_u_sub.lo div_small.lo reg_norm.lo reg_round.lo \
+wm_shrx.lo wm_sqrt.lo div_Xsig.lo polynom_Xsig.lo round_Xsig.lo \
+shr_Xsig.lo mul_Xsig.lo
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+DIST_COMMON =  README Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+GZIP_ENV = --best
+DEP_FILES =  .deps/div_Xsig.P .deps/div_small.P .deps/errors.P \
+.deps/fpu.P .deps/fpu_arith.P .deps/fpu_aux.P .deps/fpu_entry.P \
+.deps/fpu_etc.P .deps/fpu_tags.P .deps/fpu_trig.P .deps/load_store.P \
+.deps/mul_Xsig.P .deps/poly_2xm1.P .deps/poly_atan.P .deps/poly_l2.P \
+.deps/poly_sin.P .deps/poly_tan.P .deps/polynom_Xsig.P \
+.deps/reg_add_sub.P .deps/reg_compare.P .deps/reg_constant.P \
+.deps/reg_convert.P .deps/reg_divide.P .deps/reg_ld_str.P \
+.deps/reg_mul.P .deps/reg_norm.P .deps/reg_round.P .deps/reg_u_add.P \
+.deps/reg_u_div.P .deps/reg_u_mul.P .deps/reg_u_sub.P \
+.deps/round_Xsig.P .deps/shr_Xsig.P .deps/wmFPUemu_glue.P \
+.deps/wm_shrx.P .deps/wm_sqrt.P
+SOURCES = $(libfpu_la_SOURCES)
+OBJECTS = $(libfpu_la_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .lo .o .s
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --foreign cpu/fpu/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLTLIBRARIES:
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+
+distclean-noinstLTLIBRARIES:
+
+maintainer-clean-noinstLTLIBRARIES:
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libfpu.la: $(libfpu_la_OBJECTS) $(libfpu_la_DEPENDENCIES)
+       $(CXXLINK)  $(libfpu_la_LDFLAGS) $(libfpu_la_OBJECTS) $(libfpu_la_LIBADD) $(LIBS)
+.cc.o:
+       $(CXXCOMPILE) -c $<
+.cc.lo:
+       $(LTCXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = cpu/fpu
+
+distdir: $(DISTFILES)
+       here=`cd $(top_builddir) && pwd`; \
+       top_distdir=`cd $(top_distdir) && pwd`; \
+       distdir=`cd $(distdir) && pwd`; \
+       cd $(top_srcdir) \
+         && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign cpu/fpu/Makefile
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+       -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+       @echo '$(COMPILE) -c $<'; \
+       $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.c
+       @echo '$(LTCOMPILE) -c $<'; \
+       $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+
+%.o: %.cc
+       @echo '$(CXXCOMPILE) -c $<'; \
+       $(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.cc
+       @echo '$(LTCXXCOMPILE) -c $<'; \
+       $(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LTLIBRARIES)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLTLIBRARIES mostlyclean-compile \
+               mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+               mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLTLIBRARIES clean-compile clean-libtool \
+               clean-tags clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLTLIBRARIES distclean-compile \
+               distclean-libtool distclean-tags distclean-depend \
+               distclean-generic clean-am
+       -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLTLIBRARIES \
+               maintainer-clean-compile maintainer-clean-libtool \
+               maintainer-clean-tags maintainer-clean-depend \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \
+clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sid/component/bochs/cpu/fpu/PORTING b/sid/component/bochs/cpu/fpu/PORTING
new file mode 100644 (file)
index 0000000..532972d
--- /dev/null
@@ -0,0 +1,13 @@
+Portable i387 emulator
+
+22 Nov 99  Version 2.02:
+
+First pseudo-portable version for little-endian machines.
+
+Beginning of big-endian support provided through the pre-processor
+symbol BIG_ENDIAN.
+
+Some of the code in fpu_entry.c and get_address.c is still in a
+non-portable form and these two files still contain assembler code.
+
+
diff --git a/sid/component/bochs/cpu/fpu/README b/sid/component/bochs/cpu/fpu/README
new file mode 100644 (file)
index 0000000..d13efbc
--- /dev/null
@@ -0,0 +1,427 @@
+ +---------------------------------------------------------------------------+
+ |  wm-FPU-emu   an FPU emulator for 80386 and 80486SX microprocessors.      |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1995,1996,1997,1999                          |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@melbpc.org.au              |
+ |                                                                           |
+ |    This program is free software; you can redistribute it and/or modify   |
+ |    it under the terms of the GNU General Public License version 2 as      |
+ |    published by the Free Software Foundation.                             |
+ |                                                                           |
+ |    This program is distributed in the hope that it will be useful,        |
+ |    but WITHOUT ANY WARRANTY; without even the implied warranty of         |
+ |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          |
+ |    GNU General Public License for more details.                           |
+ |                                                                           |
+ |    You should have received a copy of the GNU General Public License      |
+ |    along with this program; if not, write to the Free Software            |
+ |    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              |
+ |                                                                           |
+ +---------------------------------------------------------------------------+
+
+
+
+wm-FPU-emu is an FPU emulator for Linux. It is derived from wm-emu387
+which was my 80387 emulator for early versions of djgpp (gcc under
+msdos); wm-emu387 was in turn based upon emu387 which was written by
+DJ Delorie for djgpp.  The interface to the Linux kernel is based upon
+the original Linux math emulator by Linus Torvalds.
+
+My target FPU for wm-FPU-emu is that described in the Intel486
+Programmer's Reference Manual (1992 edition). Unfortunately, numerous
+facets of the functioning of the FPU are not well covered in the
+Reference Manual. The information in the manual has been supplemented
+with measurements on real 80486's. Unfortunately, it is simply not
+possible to be sure that all of the peculiarities of the 80486 have
+been discovered, so there is always likely to be obscure differences
+in the detailed behaviour of the emulator and a real 80486.
+
+wm-FPU-emu does not implement all of the behaviour of the 80486 FPU,
+but is very close.  See "Limitations" later in this file for a list of
+some differences.
+
+Please report bugs, etc to me at:
+       billm@melbpc.org.au
+or     b.metzenthen@medoto.unimelb.edu.au
+
+For more information on the emulator and on floating point topics, see
+my web pages, currently at  http://www.suburbia.net/~billm/
+
+
+--Bill Metzenthen
+  December 1999
+
+
+----------------------- Internals of wm-FPU-emu -----------------------
+
+Numeric algorithms:
+(1) Add, subtract, and multiply. Nothing remarkable in these.
+(2) Divide has been tuned to get reasonable performance. The algorithm
+    is not the obvious one which most people seem to use, but is designed
+    to take advantage of the characteristics of the 80386. I expect that
+    it has been invented many times before I discovered it, but I have not
+    seen it. It is based upon one of those ideas which one carries around
+    for years without ever bothering to check it out.
+(3) The sqrt function has been tuned to get good performance. It is based
+    upon Newton's classic method. Performance was improved by capitalizing
+    upon the properties of Newton's method, and the code is once again
+    structured taking account of the 80386 characteristics.
+(4) The trig, log, and exp functions are based in each case upon quasi-
+    "optimal" polynomial approximations. My definition of "optimal" was
+    based upon getting good accuracy with reasonable speed.
+(5) The argument reducing code for the trig function effectively uses
+    a value of pi which is accurate to more than 128 bits. As a consequence,
+    the reduced argument is accurate to more than 64 bits for arguments up
+    to a few pi, and accurate to more than 64 bits for most arguments,
+    even for arguments approaching 2^63. This is far superior to an
+    80486, which uses a value of pi which is accurate to 66 bits.
+
+The code of the emulator is complicated slightly by the need to
+account for a limited form of re-entrancy. Normally, the emulator will
+emulate each FPU instruction to completion without interruption.
+However, it may happen that when the emulator is accessing the user
+memory space, swapping may be needed. In this case the emulator may be
+temporarily suspended while disk i/o takes place. During this time
+another process may use the emulator, thereby perhaps changing static
+variables. The code which accesses user memory is confined to five
+files:
+    fpu_entry.c
+    reg_ld_str.c
+    load_store.c
+    get_address.c
+    errors.c
+As from version 1.12 of the emulator, no static variables are used
+(apart from those in the kernel's per-process tables). The emulator is
+therefore now fully re-entrant, rather than having just the restricted
+form of re-entrancy which is required by the Linux kernel.
+
+----------------------- Limitations of wm-FPU-emu -----------------------
+
+There are a number of differences between the current wm-FPU-emu
+(version 2.05) and the 80486 FPU (apart from bugs).  The differences
+are fewer than those which applied to the 1.xx series of the emulator.
+Some of the more important differences are listed below:
+
+The Roundup flag does not have much meaning for the transcendental
+functions and its 80486 value with these functions is likely to differ
+from its emulator value.
+
+In a few rare cases the Underflow flag obtained with the emulator will
+be different from that obtained with an 80486. This occurs when the
+following conditions apply simultaneously:
+(a) the operands have a higher precision than the current setting of the
+    precision control (PC) flags.
+(b) the underflow exception is masked.
+(c) the magnitude of the exact result (before rounding) is less than 2^-16382.
+(d) the magnitude of the final result (after rounding) is exactly 2^-16382.
+(e) the magnitude of the exact result would be exactly 2^-16382 if the
+    operands were rounded to the current precision before the arithmetic
+    operation was performed.
+If all of these apply, the emulator will set the Underflow flag but a real
+80486 will not.
+
+NOTE: Certain formats of Extended Real are UNSUPPORTED. They are
+unsupported by the 80486. They are the Pseudo-NaNs, Pseudoinfinities,
+and Unnormals. None of these will be generated by an 80486 or by the
+emulator. Do not use them. The emulator treats them differently in
+detail from the way an 80486 does.
+
+Self modifying code can cause the emulator to fail. An example of such
+code is:
+          movl %esp,[%ebx]
+         fld1
+The FPU instruction may be (usually will be) loaded into the pre-fetch
+queue of the CPU before the mov instruction is executed. If the
+destination of the 'movl' overlaps the FPU instruction then the bytes
+in the prefetch queue and memory will be inconsistent when the FPU
+instruction is executed. The emulator will be invoked but will not be
+able to find the instruction which caused the device-not-present
+exception. For this case, the emulator cannot emulate the behaviour of
+an 80486DX.
+
+Handling of the address size override prefix byte (0x67) has not been
+extensively tested yet. A major problem exists because using it in
+vm86 mode can cause a general protection fault. Address offsets
+greater than 0xffff appear to be illegal in vm86 mode but are quite
+acceptable (and work) in real mode. A small test program developed to
+check the addressing, and which runs successfully in real mode,
+crashes dosemu under Linux and also brings Windows down with a general
+protection fault message when run under the MS-DOS prompt of Windows
+3.1. (The program simply reads data from a valid address).
+
+The emulator supports 16-bit protected mode, with one difference from
+an 80486DX.  A 80486DX will allow some floating point instructions to
+write a few bytes below the lowest address of the stack.  The emulator
+will not allow this in 16-bit protected mode: no instructions are
+allowed to write outside the bounds set by the protection.
+
+----------------------- Performance of wm-FPU-emu -----------------------
+
+Speed.
+-----
+
+The speed of floating point computation with the emulator will depend
+upon instruction mix. Relative performance is best for the instructions
+which require most computation. The simple instructions are adversely
+affected by the FPU instruction trap overhead.
+
+
+Timing: Some simple timing tests have been made on the emulator functions.
+The times include load/store instructions. All times are in microseconds
+measured on a 33MHz 386 with 64k cache. The Turbo C tests were under
+ms-dos, the next two columns are for emulators running with the djgpp
+ms-dos extender. The final column is for wm-FPU-emu in Linux 0.97,
+using libm4.0 (hard).
+
+function      Turbo C        djgpp 1.06        WM-emu387     wm-FPU-emu
+
+   +          60.5           154.8              76.5          139.4
+   -          61.1-65.5      157.3-160.8        76.2-79.5     142.9-144.7
+   *          71.0           190.8              79.6          146.6
+   /          61.2-75.0      261.4-266.9        75.3-91.6     142.2-158.1
+
+ sin()        310.8          4692.0            319.0          398.5
+ cos()        284.4          4855.2            308.0          388.7
+ tan()        495.0          8807.1            394.9          504.7
+ atan()       328.9          4866.4            601.1          419.5-491.9
+
+ sqrt()       128.7          crashed           145.2          227.0
+ log()        413.1-419.1    5103.4-5354.21    254.7-282.2    409.4-437.1
+ exp()        479.1          6619.2            469.1          850.8
+
+
+The performance under Linux is improved by the use of look-ahead code.
+The following results show the improvement which is obtained under
+Linux due to the look-ahead code. Also given are the times for the
+original Linux emulator with the 4.1 'soft' lib.
+
+ [ Linus' note: I changed look-ahead to be the default under linux, as
+   there was no reason not to use it after I had edited it to be
+   disabled during tracing ]
+
+            wm-FPU-emu w     original w
+            look-ahead       'soft' lib
+   +         106.4             190.2
+   -         108.6-111.6      192.4-216.2
+   *         113.4             193.1
+   /         108.8-124.4      700.1-706.2
+
+ sin()       390.5            2642.0
+ cos()       381.5            2767.4
+ tan()       496.5            3153.3
+ atan()      367.2-435.5     2439.4-3396.8
+
+ sqrt()      195.1            4732.5
+ log()       358.0-387.5     3359.2-3390.3
+ exp()       619.3            4046.4
+
+
+These figures are now somewhat out-of-date. The emulator has become
+progressively slower for most functions as more of the 80486 features
+have been implemented.
+
+
+----------------------- Accuracy of wm-FPU-emu -----------------------
+
+
+The accuracy of the emulator is in almost all cases equal to or better
+than that of an Intel 80486 FPU.
+
+The results of the basic arithmetic functions (+,-,*,/), and fsqrt
+match those of an 80486 FPU. They are the best possible; the error for
+these never exceeds 1/2 an lsb. The fprem and fprem1 instructions
+return exact results; they have no error.
+
+
+The following table compares the emulator accuracy for the sqrt(),
+trig and log functions against the Turbo C "emulator". For this table,
+each function was tested at about 400 points. Ideal worst-case results
+would be 64 bits. The reduced Turbo C accuracy of cos() and tan() for
+arguments greater than pi/4 can be thought of as being related to the
+precision of the argument x; e.g. an argument of pi/2-(1e-10) which is
+accurate to 64 bits can result in a relative accuracy in cos() of
+about 64 + log2(cos(x)) = 31 bits.
+
+
+Function      Tested x range            Worst result                Turbo C
+                                        (relative bits)
+
+sqrt(x)       1 .. 2                    64.1                         63.2
+atan(x)       1e-10 .. 200              64.2                         62.8
+cos(x)        0 .. pi/2-(1e-10)         64.4 (x <= pi/4)             62.4
+                                        64.1 (x = pi/2-(1e-10))      31.9
+sin(x)        1e-10 .. pi/2             64.0                         62.8
+tan(x)        1e-10 .. pi/2-(1e-10)     64.0 (x <= pi/4)             62.1
+                                        64.1 (x = pi/2-(1e-10))      31.9
+exp(x)        0 .. 1                    63.1 **                      62.9
+log(x)        1+1e-6 .. 2               63.8 **                      62.1
+
+** The accuracy for exp() and log() is low because the FPU (emulator)
+does not compute them directly; two operations are required.
+
+
+The emulator passes the "paranoia" tests (compiled with gcc 2.3.3 or
+later) for 'float' variables (24 bit precision numbers) when precision
+control is set to 24, 53 or 64 bits, and for 'double' variables (53
+bit precision numbers) when precision control is set to 53 bits (a
+properly performing FPU cannot pass the 'paranoia' tests for 'double'
+variables when precision control is set to 64 bits).
+
+The code for reducing the argument for the trig functions (fsin, fcos,
+fptan and fsincos) has been improved and now effectively uses a value
+for pi which is accurate to more than 128 bits precision. As a
+consequence, the accuracy of these functions for large arguments has
+been dramatically improved (and is now very much better than an 80486
+FPU). There is also now no degradation of accuracy for fcos and fptan
+for operands close to pi/2. Measured results are (note that the
+definition of accuracy has changed slightly from that used for the
+above table):
+
+Function      Tested x range          Worst result
+                                     (absolute bits)
+
+cos(x)        0 .. 9.22e+18              62.0
+sin(x)        1e-16 .. 9.22e+18          62.1
+tan(x)        1e-16 .. 9.22e+18          61.8
+
+It is possible with some effort to find very large arguments which
+give much degraded precision. For example, the integer number
+           8227740058411162616.0
+is within about 10e-7 of a multiple of pi. To find the tan (for
+example) of this number to 64 bits precision it would be necessary to
+have a value of pi which had about 150 bits precision. The FPU
+emulator computes the result to about 42.6 bits precision (the correct
+result is about -9.739715e-8). On the other hand, an 80486 FPU returns
+0.01059, which in relative terms is hopelessly inaccurate.
+
+For arguments close to critical angles (which occur at multiples of
+pi/2) the emulator is more accurate than an 80486 FPU. For very large
+arguments, the emulator is far more accurate.
+
+
+Prior to version 1.20 of the emulator, the accuracy of the results for
+the transcendental functions (in their principal range) was not as
+good as the results from an 80486 FPU. From version 1.20, the accuracy
+has been considerably improved and these functions now give measured
+worst-case results which are better than the worst-case results given
+by an 80486 FPU.
+
+The following table gives the measured results for the emulator. The
+number of randomly selected arguments in each case is about half a
+million.  The group of three columns gives the frequency of the given
+accuracy in number of times per million, thus the second of these
+columns shows that an accuracy of between 63.80 and 63.89 bits was
+found at a rate of 133 times per one million measurements for fsin.
+The results show that the fsin, fcos and fptan instructions return
+results which are in error (i.e. less accurate than the best possible
+result (which is 64 bits)) for about one per cent of all arguments
+between -pi/2 and +pi/2.  The other instructions have a lower
+frequency of results which are in error.  The last two columns give
+the worst accuracy which was found (in bits) and the approximate value
+of the argument which produced it.
+
+                                frequency (per M)
+                               -------------------   ---------------
+instr   arg range    # tests   63.7   63.8    63.9   worst   at arg
+                               bits   bits    bits    bits
+-----  ------------  -------   ----   ----   -----   -----  --------
+fsin     (0,pi/2)     547756      0    133   10673   63.89  0.451317
+fcos     (0,pi/2)     547563      0    126   10532   63.85  0.700801
+fptan    (0,pi/2)     536274     11    267   10059   63.74  0.784876
+fpatan  4 quadrants   517087      0      8    1855   63.88  0.435121 (4q)
+fyl2x     (0,20)      541861      0      0    1323   63.94  1.40923  (x)
+fyl2xp1 (-.293,.414)  520256      0      0    5678   63.93  0.408542 (x)
+f2xm1     (-1,1)      538847      4    481    6488   63.79  0.167709
+
+
+Tests performed on an 80486 FPU showed results of lower accuracy. The
+following table gives the results which were obtained with an AMD
+486DX2/66 (other tests indicate that an Intel 486DX produces
+identical results).  The tests were basically the same as those used
+to measure the emulator (the values, being random, were in general not
+the same).  The total number of tests for each instruction are given
+at the end of the table, in case each about 100k tests were performed.
+Another line of figures at the end of the table shows that most of the
+instructions return results which are in error for more than 10
+percent of the arguments tested.
+
+The numbers in the body of the table give the approx number of times a
+result of the given accuracy in bits (given in the left-most column)
+was obtained per one million arguments. For three of the instructions,
+two columns of results are given: * The second column for f2xm1 gives
+the number cases where the results of the first column were for a
+positive argument, this shows that this instruction gives better
+results for positive arguments than it does for negative.  * In the
+cases of fcos and fptan, the first column gives the results when all
+cases where arguments greater than 1.5 were removed from the results
+given in the second column. Unlike the emulator, an 80486 FPU returns
+results of relatively poor accuracy for these instructions when the
+argument approaches pi/2. The table does not show those cases when the
+accuracy of the results were less than 62 bits, which occurs quite
+often for fsin and fptan when the argument approaches pi/2. This poor
+accuracy is discussed above in relation to the Turbo C "emulator", and
+the accuracy of the value of pi.
+
+
+bits   f2xm1  f2xm1 fpatan   fcos   fcos  fyl2x fyl2xp1  fsin  fptan  fptan
+62.0       0      0      0      0    437      0      0      0      0    925
+62.1       0      0     10      0    894      0      0      0      0   1023
+62.2      14      0      0      0   1033      0      0      0      0    945
+62.3      57      0      0      0   1202      0      0      0      0   1023
+62.4     385      0      0     10   1292      0     23      0      0   1178
+62.5    1140      0      0    119   1649      0     39      0      0   1149
+62.6    2037      0      0    189   1620      0     16      0      0   1169
+62.7    5086     14      0    646   2315     10    101     35     39   1402
+62.8    8818     86      0    984   3050     59    287    131    224   2036
+62.9   11340   1355      0   2126   4153     79    605    357    321   1948
+63.0   15557   4750      0   3319   5376    246   1281    862    808   2688
+63.1   20016   8288      0   4620   6628    511   2569   1723   1510   3302
+63.2   24945  11127     10   6588   8098   1120   4470   2968   2990   4724
+63.3   25686  12382     69   8774  10682   1906   6775   4482   5474   7236
+63.4   29219  14722     79  11109  12311   3094   9414   7259   8912  10587
+63.5   30458  14936    393  13802  15014   5874  12666   9609  13762  15262
+63.6   32439  16448   1277  17945  19028  10226  15537  14657  19158  20346
+63.7   35031  16805   4067  23003  23947  18910  20116  21333  25001  26209
+63.8   33251  15820   7673  24781  25675  24617  25354  24440  29433  30329
+63.9   33293  16833  18529  28318  29233  31267  31470  27748  29676  30601
+
+Per cent with error:
+        30.9           3.2          18.5    9.8   13.1   11.6          17.4
+Total arguments tested:
+       70194  70099 101784 100641 100641 101799 128853 114893 102675 102675
+
+
+------------------------- Contributors -------------------------------
+
+A number of people have contributed to the development of the
+emulator, often by just reporting bugs, sometimes with suggested
+fixes, and a few kind people have provided me with access in one way
+or another to an 80486 machine. Contributors include (to those people
+who I may have forgotten, please forgive me):
+
+Linus Torvalds
+Tommy.Thorn@daimi.aau.dk
+Andrew.Tridgell@anu.edu.au
+Nick Holloway, alfie@dcs.warwick.ac.uk
+Hermano Moura, moura@dcs.gla.ac.uk
+Jon Jagger, J.Jagger@scp.ac.uk
+Lennart Benschop
+Brian Gallew, geek+@CMU.EDU
+Thomas Staniszewski, ts3v+@andrew.cmu.edu
+Martin Howell, mph@plasma.apana.org.au
+M Saggaf, alsaggaf@athena.mit.edu
+Peter Barker, PETER@socpsy.sci.fau.edu
+tom@vlsivie.tuwien.ac.at
+Dan Russel, russed@rpi.edu
+Daniel Carosone, danielce@ee.mu.oz.au
+cae@jpmorgan.com
+Hamish Coleman, t933093@minyos.xx.rmit.oz.au
+Bruce Evans, bde@kralizec.zeta.org.au
+Timo Korvola, Timo.Korvola@hut.fi
+Rick Lyons, rick@razorback.brisnet.org.au
+Rick, jrs@world.std.com
+...and numerous others who responded to my request for help with
+a real 80486.
+
diff --git a/sid/component/bochs/cpu/fpu/control_w.h b/sid/component/bochs/cpu/fpu/control_w.h
new file mode 100644 (file)
index 0000000..ae2274d
--- /dev/null
@@ -0,0 +1,45 @@
+/*---------------------------------------------------------------------------+
+ |  control_w.h                                                              |
+ |                                                                           |
+ | Copyright (C) 1992,1993                                                   |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#ifndef _CONTROLW_H_
+#define _CONTROLW_H_
+
+#ifdef __ASSEMBLY__
+#define        _Const_(x)      $##x
+#else
+#define        _Const_(x)      x
+#endif
+
+#define CW_RC          _Const_(0x0C00) /* rounding control */
+#define CW_PC          _Const_(0x0300) /* precision control */
+
+#define CW_Precision   Const_(0x0020)  /* loss of precision mask */
+#define CW_Underflow   Const_(0x0010)  /* underflow mask */
+#define CW_Overflow    Const_(0x0008)  /* overflow mask */
+#define CW_ZeroDiv     Const_(0x0004)  /* divide by zero mask */
+#define CW_Denormal    Const_(0x0002)  /* denormalized operand mask */
+#define CW_Invalid     Const_(0x0001)  /* invalid operation mask */
+
+#define CW_Exceptions          _Const_(0x003f) /* all masks */
+
+#define RC_RND         _Const_(0x0000)
+#define RC_DOWN                _Const_(0x0400)
+#define RC_UP          _Const_(0x0800)
+#define RC_CHOP                _Const_(0x0C00)
+
+/* p 15-5: Precision control bits affect only the following:
+   ADD, SUB(R), MUL, DIV(R), and SQRT */
+#define PR_24_BITS        _Const_(0x000)
+#define PR_53_BITS        _Const_(0x200)
+#define PR_64_BITS        _Const_(0x300)
+#define PR_RESERVED_BITS  _Const_(0x100)
+/* FULL_PRECISION simulates all exceptions masked */
+#define FULL_PRECISION  (PR_64_BITS | RC_RND | 0x3f)
+
+#endif /* _CONTROLW_H_ */
diff --git a/sid/component/bochs/cpu/fpu/div_Xsig.S b/sid/component/bochs/cpu/fpu/div_Xsig.S
new file mode 100644 (file)
index 0000000..d94d85e
--- /dev/null
@@ -0,0 +1,365 @@
+       .file   "div_Xsig.S"
+/*---------------------------------------------------------------------------+
+ |  div_Xsig.S                                                               |
+ |                                                                           |
+ | Division subroutine for 96 bit quantities                                 |
+ |                                                                           |
+ | Copyright (C) 1994,1995                                                   |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | Divide the 96 bit quantity pointed to by a, by that pointed to by b, and  |
+ | put the 96 bit result at the location d.                                  |
+ |                                                                           |
+ | The result may not be accurate to 96 bits. It is intended for use where   |
+ | a result better than 64 bits is required. The result should usually be    |
+ | good to at least 94 bits.                                                 |
+ | The returned result is actually divided by one half. This is done to      |
+ | prevent overflow.                                                         |
+ |                                                                           |
+ |  .aaaaaaaaaaaaaa / .bbbbbbbbbbbbb  ->  .dddddddddddd                      |
+ |                                                                           |
+ |  void div_Xsig(Xsig *a, Xsig *b, Xsig *dest)                              |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "fpu_emu.h"
+
+
+#define        XsigLL(x)       (x)
+#define        XsigL(x)        4(x)
+#define        XsigH(x)        8(x)
+
+
+#ifndef NON_REENTRANT_FPU
+/*
+       Local storage on the stack:
+       Accumulator:    FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0
+ */
+#define FPU_accum_3    -4(%ebp)
+#define FPU_accum_2    -8(%ebp)
+#define FPU_accum_1    -12(%ebp)
+#define FPU_accum_0    -16(%ebp)
+#define FPU_result_3   -20(%ebp)
+#define FPU_result_2   -24(%ebp)
+#define FPU_result_1   -28(%ebp)
+
+#else
+.data
+/*
+       Local storage in a static area:
+       Accumulator:    FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0
+ */
+       .align 4,0
+FPU_accum_3:
+       .long   0
+FPU_accum_2:
+       .long   0
+FPU_accum_1:
+       .long   0
+FPU_accum_0:
+       .long   0
+FPU_result_3:
+       .long   0
+FPU_result_2:
+       .long   0
+FPU_result_1:
+       .long   0
+#endif /* NON_REENTRANT_FPU */
+
+
+.text
+ENTRY(div_Xsig)
+       pushl   %ebp
+       movl    %esp,%ebp
+#ifndef NON_REENTRANT_FPU
+       subl    $28,%esp
+#endif /* NON_REENTRANT_FPU */
+
+       pushl   %esi
+       pushl   %edi
+       pushl   %ebx
+
+       movl    PARAM1,%esi     /* pointer to num */
+       movl    PARAM2,%ebx     /* pointer to denom */
+
+#ifdef PARANOID
+       testl   $0x80000000, XsigH(%ebx)        /* Divisor */
+       je      L_bugged
+#endif /* PARANOID */
+
+
+/*---------------------------------------------------------------------------+
+ |  Divide:   Return  arg1/arg2 to arg3.                                     |
+ |                                                                           |
+ |  The maximum returned value is (ignoring exponents)                       |
+ |               .ffffffff ffffffff                                          |
+ |               ------------------  =  1.ffffffff fffffffe                  |
+ |               .80000000 00000000                                          |
+ | and the minimum is                                                        |
+ |               .80000000 00000000                                          |
+ |               ------------------  =  .80000000 00000001   (rounded)       |
+ |               .ffffffff ffffffff                                          |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+       /* Save extended dividend in local register */
+
+       /* Divide by 2 to prevent overflow */
+       clc
+       movl    XsigH(%esi),%eax
+       rcrl    %eax
+       movl    %eax,FPU_accum_3
+       movl    XsigL(%esi),%eax
+       rcrl    %eax
+       movl    %eax,FPU_accum_2
+       movl    XsigLL(%esi),%eax
+       rcrl    %eax
+       movl    %eax,FPU_accum_1
+       movl    $0,%eax
+       rcrl    %eax
+       movl    %eax,FPU_accum_0
+
+       movl    FPU_accum_2,%eax        /* Get the current num */
+       movl    FPU_accum_3,%edx
+
+/*----------------------------------------------------------------------*/
+/* Initialization done.
+   Do the first 32 bits. */
+
+       /* We will divide by a number which is too large */
+       movl    XsigH(%ebx),%ecx
+       addl    $1,%ecx
+       jnc     LFirst_div_not_1
+
+       /* here we need to divide by 100000000h,
+          i.e., no division at all.. */
+       mov     %edx,%eax
+       jmp     LFirst_div_done
+
+LFirst_div_not_1:
+       divl    %ecx            /* Divide the numerator by the augmented
+                                  denom ms dw */
+
+LFirst_div_done:
+       movl    %eax,FPU_result_3       /* Put the result in the answer */
+
+       mull    XsigH(%ebx)     /* mul by the ms dw of the denom */
+
+       subl    %eax,FPU_accum_2        /* Subtract from the num local reg */
+       sbbl    %edx,FPU_accum_3
+
+       movl    FPU_result_3,%eax       /* Get the result back */
+       mull    XsigL(%ebx)     /* now mul the ls dw of the denom */
+
+       subl    %eax,FPU_accum_1        /* Subtract from the num local reg */
+       sbbl    %edx,FPU_accum_2
+       sbbl    $0,FPU_accum_3
+       je      LDo_2nd_32_bits         /* Must check for non-zero result here */
+
+#ifdef PARANOID
+       jb      L_bugged_1
+#endif /* PARANOID */
+
+       /* need to subtract another once of the denom */
+       incl    FPU_result_3    /* Correct the answer */
+
+       movl    XsigL(%ebx),%eax
+       movl    XsigH(%ebx),%edx
+       subl    %eax,FPU_accum_1        /* Subtract from the num local reg */
+       sbbl    %edx,FPU_accum_2
+
+#ifdef PARANOID
+       sbbl    $0,FPU_accum_3
+       jne     L_bugged_1      /* Must check for non-zero result here */
+#endif /* PARANOID */
+
+/*----------------------------------------------------------------------*/
+/* Half of the main problem is done, there is just a reduced numerator
+   to handle now.
+   Work with the second 32 bits, FPU_accum_0 not used from now on */
+LDo_2nd_32_bits:
+       movl    FPU_accum_2,%edx        /* get the reduced num */
+       movl    FPU_accum_1,%eax
+
+       /* need to check for possible subsequent overflow */
+       cmpl    XsigH(%ebx),%edx
+       jb      LDo_2nd_div
+       ja      LPrevent_2nd_overflow
+
+       cmpl    XsigL(%ebx),%eax
+       jb      LDo_2nd_div
+
+LPrevent_2nd_overflow:
+/* The numerator is greater or equal, would cause overflow */
+       /* prevent overflow */
+       subl    XsigL(%ebx),%eax
+       sbbl    XsigH(%ebx),%edx
+       movl    %edx,FPU_accum_2
+       movl    %eax,FPU_accum_1
+
+       incl    FPU_result_3    /* Reflect the subtraction in the answer */
+
+#ifdef PARANOID
+       je      L_bugged_2      /* Can't bump the result to 1.0 */
+#endif /* PARANOID */
+
+LDo_2nd_div:
+       cmpl    $0,%ecx         /* augmented denom msw */
+       jnz     LSecond_div_not_1
+
+       /* %ecx == 0, we are dividing by 1.0 */
+       mov     %edx,%eax
+       jmp     LSecond_div_done
+
+LSecond_div_not_1:
+       divl    %ecx            /* Divide the numerator by the denom ms dw */
+
+LSecond_div_done:
+       movl    %eax,FPU_result_2       /* Put the result in the answer */
+
+       mull    XsigH(%ebx)     /* mul by the ms dw of the denom */
+
+       subl    %eax,FPU_accum_1        /* Subtract from the num local reg */
+       sbbl    %edx,FPU_accum_2
+
+#ifdef PARANOID
+       jc      L_bugged_2
+#endif /* PARANOID */
+
+       movl    FPU_result_2,%eax       /* Get the result back */
+       mull    XsigL(%ebx)     /* now mul the ls dw of the denom */
+
+       subl    %eax,FPU_accum_0        /* Subtract from the num local reg */
+       sbbl    %edx,FPU_accum_1        /* Subtract from the num local reg */
+       sbbl    $0,FPU_accum_2
+
+#ifdef PARANOID
+       jc      L_bugged_2
+#endif /* PARANOID */
+
+       jz      LDo_3rd_32_bits
+
+#ifdef PARANOID
+       cmpl    $1,FPU_accum_2
+       jne     L_bugged_2
+#endif /* PARANOID */
+
+       /* need to subtract another once of the denom */
+       movl    XsigL(%ebx),%eax
+       movl    XsigH(%ebx),%edx
+       subl    %eax,FPU_accum_0        /* Subtract from the num local reg */
+       sbbl    %edx,FPU_accum_1
+       sbbl    $0,FPU_accum_2
+
+#ifdef PARANOID
+       jc      L_bugged_2
+       jne     L_bugged_2
+#endif /* PARANOID */
+
+       addl    $1,FPU_result_2 /* Correct the answer */
+       adcl    $0,FPU_result_3
+
+#ifdef PARANOID
+       jc      L_bugged_2      /* Must check for non-zero result here */
+#endif /* PARANOID */
+
+/*----------------------------------------------------------------------*/
+/* The division is essentially finished here, we just need to perform
+   tidying operations.
+   Deal with the 3rd 32 bits */
+LDo_3rd_32_bits:
+       /* We use an approximation for the third 32 bits.
+       To take account of the 3rd 32 bits of the divisor
+       (call them del), we subtract  del * (a/b) */
+
+       movl    FPU_result_3,%eax       /* a/b */
+       mull    XsigLL(%ebx)            /* del */
+
+       subl    %edx,FPU_accum_1
+
+       /* A borrow indicates that the result is negative */
+       jnb     LTest_over
+
+       movl    XsigH(%ebx),%edx
+       addl    %edx,FPU_accum_1
+
+       subl    $1,FPU_result_2         /* Adjust the answer */
+       sbbl    $0,FPU_result_3
+
+       /* The above addition might not have been enough, check again. */
+       movl    FPU_accum_1,%edx        /* get the reduced num */
+       cmpl    XsigH(%ebx),%edx        /* denom */
+       jb      LDo_3rd_div
+
+       movl    XsigH(%ebx),%edx
+       addl    %edx,FPU_accum_1
+
+       subl    $1,FPU_result_2         /* Adjust the answer */
+       sbbl    $0,FPU_result_3
+       jmp     LDo_3rd_div
+
+LTest_over:
+       movl    FPU_accum_1,%edx        /* get the reduced num */
+
+       /* need to check for possible subsequent overflow */
+       cmpl    XsigH(%ebx),%edx        /* denom */
+       jb      LDo_3rd_div
+
+       /* prevent overflow */
+       subl    XsigH(%ebx),%edx
+       movl    %edx,FPU_accum_1
+
+       addl    $1,FPU_result_2 /* Reflect the subtraction in the answer */
+       adcl    $0,FPU_result_3
+
+LDo_3rd_div:
+       movl    FPU_accum_0,%eax
+       movl    FPU_accum_1,%edx
+       divl    XsigH(%ebx)
+
+       movl    %eax,FPU_result_1       /* Rough estimate of third word */
+
+       movl    PARAM3,%esi             /* pointer to answer */
+
+       movl    FPU_result_1,%eax
+       movl    %eax,XsigLL(%esi)
+       movl    FPU_result_2,%eax
+       movl    %eax,XsigL(%esi)
+       movl    FPU_result_3,%eax
+       movl    %eax,XsigH(%esi)
+
+L_exit:
+       popl    %ebx
+       popl    %edi
+       popl    %esi
+
+       leave
+       ret
+
+
+#ifdef PARANOID
+/* The logic is wrong if we got here */
+L_bugged:
+       pushl   EX_INTERNAL|0x240
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_exit
+
+L_bugged_1:
+       pushl   EX_INTERNAL|0x241
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_exit
+
+L_bugged_2:
+       pushl   EX_INTERNAL|0x242
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_exit
+#endif /* PARANOID */
diff --git a/sid/component/bochs/cpu/fpu/div_Xsig.c b/sid/component/bochs/cpu/fpu/div_Xsig.c
new file mode 100644 (file)
index 0000000..36e7c2a
--- /dev/null
@@ -0,0 +1,185 @@
+/*---------------------------------------------------------------------------+
+ |  div_Xsig.S                                                               |
+ |                                                                           |
+ | Division subroutine for 96 bit quantities                                 |
+ |                                                                           |
+ | Copyright (C) 1994,1995,1999                                              |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@melbpc.org.au              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | Divide the 96 bit quantity pointed to by a, by that pointed to by b, and  |
+ | put the 96 bit result at the location d.                                  |
+ |                                                                           |
+ | The result may not be accurate to 96 bits. It is intended for use where   |
+ | a result better than 64 bits is required. The result should usually be    |
+ | good to at least 94 bits.                                                 |
+ | The returned result is actually divided by one half. This is done to      |
+ | prevent overflow.                                                         |
+ |                                                                           |
+ |  .aaaaaaaaaaaaaa / .bbbbbbbbbbbbb  ->  .dddddddddddd                      |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "fpu_emu.h"
+#include "poly.h"
+
+
+void div_Xsig(const Xsig *aa, const Xsig *b, Xsig *dest)
+{
+  Xsig a = *aa, xpr, result;
+  u32  prodh, prodl, den, wd;
+  u64  num, prod;
+
+#ifdef PARANOID
+  if ( (b->msw & 0x80000000) == 0 )
+    {
+      EXCEPTION(EX_INTERNAL|0x240);
+      return;
+    }
+#endif
+
+  /* Shift a right */
+  a.lsw >>= 1;
+  if ( a.midw & 1 )
+    a.lsw |= 0x80000000;
+  a.midw >>= 1;
+  if ( a.msw & 1 )
+    a.midw |= 0x80000000;
+  a.msw >>= 1;
+
+  num = a.msw;
+  num <<= 32;
+  num |= a.midw;
+
+  den = b->msw + 1;
+  if ( den )
+    {
+      result.msw = num / den;
+    }
+  else
+    result.msw = a.msw;
+
+  xpr = *b;
+  mul32_Xsig(&xpr, result.msw);
+  a.msw -= xpr.msw;
+  wd = a.midw;
+  a.midw -= xpr.midw;
+  if ( a.midw > wd )
+    a.msw --;
+  wd = a.lsw;
+  a.lsw -= xpr.lsw;
+  if ( a.lsw > wd )
+    {
+      a.midw --;
+      if ( a.midw == 0xffffffff )
+       a.msw --;
+    }
+
+#ifdef PARANOID
+      if ( a.msw > 1 )
+       {
+         EXCEPTION(EX_INTERNAL|0x241);
+       }
+#endif
+
+  while ( (a.msw != 0) || (a.midw > b->msw) )
+    {
+      wd = a.midw;
+      a.midw -= b->msw;
+      if ( a.midw > wd )
+       a.msw --;
+      wd = a.lsw;
+      a.lsw -= b->midw;
+      if ( a.lsw > wd )
+       {
+         a.midw --;
+         if ( a.midw == 0xffffffff )
+           a.msw --;
+       }
+      result.msw ++;
+    }
+
+  /* Whew! result.msw is now done. */
+
+  num = a.midw;
+  num <<= 32;
+  num |= a.lsw;
+
+  if ( den )
+    {
+      result.midw = num / den;
+    }
+  else
+    result.midw = a.midw;
+
+  prod = result.midw;
+  prod *= b->msw;
+  a.midw -= prod >> 32;
+  prodl = prod;
+  wd = a.lsw;
+  a.lsw -= prodl;
+  if ( a.lsw > wd )
+    a.midw --;
+
+  prod = result.midw;
+  prod *= b->midw;
+  prodh = prod >> 32;
+  wd = a.lsw;
+  a.lsw -= prodh;
+  if ( a.lsw > wd )
+    a.midw --;
+
+#ifdef PARANOID
+      if ( a.midw > 1 )
+       {
+          EXCEPTION(EX_INTERNAL|0x242);
+       }
+#endif
+
+  while ( (a.midw != 0) || (a.lsw > b->msw) )
+    {
+      wd = a.lsw;
+      a.lsw -= b->msw;
+      if ( a.lsw > wd )
+       a.midw --;
+      result.midw ++;
+    }
+
+
+  /* Now result.msw is done, the lsw is next... */
+
+  num = a.lsw;
+  num <<= 32;
+
+  if ( den )
+    {
+      result.lsw = num / den;
+    }
+  else
+    result.lsw = a.lsw;
+
+  prod = result.lsw;
+  prod *= b->msw;
+  a.lsw -= prod >> 32;
+
+#ifdef PARANOID
+  if ( a.lsw > 2 )
+    {
+      EXCEPTION(EX_INTERNAL|0x243);
+    }
+#endif
+
+  result.lsw -= a.lsw;
+
+  /* Hey! we're done. */
+
+  *dest = result;
+
+}
+
diff --git a/sid/component/bochs/cpu/fpu/div_small.S b/sid/component/bochs/cpu/fpu/div_small.S
new file mode 100644 (file)
index 0000000..4709962
--- /dev/null
@@ -0,0 +1,47 @@
+       .file   "div_small.S"
+/*---------------------------------------------------------------------------+
+ |  div_small.S                                                              |
+ |                                                                           |
+ | Divide a 64 bit integer by a 32 bit integer & return remainder.           |
+ |                                                                           |
+ | Copyright (C) 1992,1995                                                   |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ |    unsigned long FPU_div_small(unsigned long long *x, unsigned long y)    |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_emu.h"
+
+.text
+ENTRY(FPU_div_small)
+       pushl   %ebp
+       movl    %esp,%ebp
+
+       pushl   %esi
+
+       movl    PARAM1,%esi     /* pointer to num */
+       movl    PARAM2,%ecx     /* The denominator */
+
+       movl    4(%esi),%eax    /* Get the current num msw */
+       xorl    %edx,%edx
+       divl    %ecx
+
+       movl    %eax,4(%esi)
+
+       movl    (%esi),%eax     /* Get the num lsw */
+       divl    %ecx
+
+       movl    %eax,(%esi)
+
+       movl    %edx,%eax       /* Return the remainder in eax */
+
+       popl    %esi
+
+       leave
+       ret
+
diff --git a/sid/component/bochs/cpu/fpu/div_small.c b/sid/component/bochs/cpu/fpu/div_small.c
new file mode 100644 (file)
index 0000000..9559a15
--- /dev/null
@@ -0,0 +1,26 @@
+/*---------------------------------------------------------------------------+
+ |  div_small.S                                                              |
+ |                                                                           |
+ | Divide a 64 bit integer by a 32 bit integer & return remainder.           |
+ |                                                                           |
+ | Copyright (C) 1992,1995,1999                                              |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@melbpc.org.au              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+
+#include "fpu_emu.h"
+
+u32 FPU_div_small(u64 *x, u32 y)
+{
+  u32 retval;
+
+  retval = *x % y;
+
+  *x /= y;
+
+  return retval;
+}
+
diff --git a/sid/component/bochs/cpu/fpu/errors.c b/sid/component/bochs/cpu/fpu/errors.c
new file mode 100644 (file)
index 0000000..fd9a4e4
--- /dev/null
@@ -0,0 +1,799 @@
+/*---------------------------------------------------------------------------+
+ |  errors.c                                                                 |
+ |                                                                           |
+ |  The error handling functions for wm-FPU-emu                              |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1996                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@jacobi.maths.monash.edu.au                |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | Note:                                                                     |
+ |    The file contains code which accesses user memory.                     |
+ |    Emulator static data may change when user memory is accessed, due to   |
+ |    other processes using the emulator while swapping is in progress.      |
+ +---------------------------------------------------------------------------*/
+
+#include <linux/signal.h>
+#include <asm/uaccess.h>
+#include <stdio.h>
+
+#include "fpu_emu.h"
+#include "fpu_system.h"
+#include "exception.h"
+#include "status_w.h"
+#include "control_w.h"
+#include "reg_constant.h"
+#include "version.h"
+
+/* */
+#undef PRINT_MESSAGES
+/* */
+
+
+#ifndef USE_WITH_CPU_SIM
+void Un_impl(void)
+{
+  u_char byte1, FPU_modrm;
+  u32 address = FPU_ORIG_EIP;
+
+  RE_ENTRANT_CHECK_OFF;
+  /* No need to verify_area(), we have previously fetched these bytes. */
+  printk("Unimplemented FPU Opcode at eip=%p : ", (void *) address);
+  if ( FPU_CS == __USER_CS )
+    {
+      while ( 1 )
+       {
+         FPU_get_user(byte1, (u_char *) address);
+         if ( (byte1 & 0xf8) == 0xd8 ) break;
+         printk("[%02x]", byte1);
+         address++;
+       }
+      printk("%02x ", byte1);
+      FPU_get_user(FPU_modrm, 1 + (u_char *) address);
+      
+      if (FPU_modrm >= 0300)
+       printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
+      else
+       printk("/%d\n", (FPU_modrm >> 3) & 7);
+    }
+  else
+    {
+      printk("cs selector = %04x\n", FPU_CS);
+    }
+
+  RE_ENTRANT_CHECK_ON;
+
+  EXCEPTION(EX_Invalid);
+
+}
+#endif
+
+
+/*
+   Called for opcodes which are illegal and which are known to result in a
+   SIGILL with a real 80486.
+   */
+void FPU_illegal(void)
+{
+  math_abort(FPU_info,SIGILL);
+}
+
+
+
+#ifndef USE_WITH_CPU_SIM
+void FPU_printall(void)
+{
+  int i;
+  static const char *tag_desc[] = { "Valid", "Zero", "ERROR", "Empty",
+                              "DeNorm", "Inf", "NaN" };
+  u_char byte1, FPU_modrm;
+  u32 address = FPU_ORIG_EIP;
+
+  RE_ENTRANT_CHECK_OFF;
+  /* No need to verify_area(), we have previously fetched these bytes. */
+  printk("At %p:", (void *) address);
+  if ( FPU_CS == __USER_CS )
+    {
+#define MAX_PRINTED_BYTES 20
+      for ( i = 0; i < MAX_PRINTED_BYTES; i++ )
+       {
+         FPU_get_user(byte1, (u_char *) address);
+         if ( (byte1 & 0xf8) == 0xd8 )
+           {
+             printk(" %02x", byte1);
+             break;
+           }
+         printk(" [%02x]", byte1);
+         address++;
+       }
+      if ( i == MAX_PRINTED_BYTES )
+       printk(" [more..]\n");
+      else
+       {
+         FPU_get_user(FPU_modrm, 1 + (u_char *) address);
+         
+         if (FPU_modrm >= 0300)
+           printk(" %02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
+         else
+           printk(" /%d, mod=%d rm=%d\n",
+                  (FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7);
+       }
+    }
+  else
+    {
+      printk("%04x\n", FPU_CS);
+    }
+
+  partial_status = status_word();
+
+
+  printk(" SW: b=%d st=%ld es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n",
+        partial_status & 0x8000 ? 1 : 0,   /* busy */
+        (partial_status & 0x3800) >> 11,   /* stack top pointer */
+        partial_status & 0x80 ? 1 : 0,     /* Error summary status */
+        partial_status & 0x40 ? 1 : 0,     /* Stack flag */
+        partial_status & SW_C3?1:0, partial_status & SW_C2?1:0, /* cc */
+        partial_status & SW_C1?1:0, partial_status & SW_C0?1:0, /* cc */
+        partial_status & SW_Precision?1:0, partial_status & SW_Underflow?1:0,
+        partial_status & SW_Overflow?1:0, partial_status & SW_Zero_Div?1:0,
+        partial_status & SW_Denorm_Op?1:0, partial_status & SW_Invalid?1:0);
+  
+printk(" CW: ic=%d rc=%ld%ld pc=%ld%ld iem=%d     ef=%d%d%d%d%d%d\n",
+        control_word & 0x1000 ? 1 : 0,
+        (control_word & 0x800) >> 11, (control_word & 0x400) >> 10,
+        (control_word & 0x200) >> 9, (control_word & 0x100) >> 8,
+        control_word & 0x80 ? 1 : 0,
+        control_word & SW_Precision?1:0, control_word & SW_Underflow?1:0,
+        control_word & SW_Overflow?1:0, control_word & SW_Zero_Div?1:0,
+        control_word & SW_Denorm_Op?1:0, control_word & SW_Invalid?1:0);
+
+  for ( i = 0; i < 8; i++ )
+    {
+      FPU_REG *r = &st(i);
+      u_char tagi = FPU_gettagi(i);
+      switch (tagi)
+       {
+       case TAG_Empty:
+         continue;
+         break;
+       case TAG_Zero:
+       case TAG_Special:
+         tagi = FPU_Special(r);
+       case TAG_Valid:
+         printk("st(%d)  %c .%04lx %04lx %04lx %04lx e%+-6d ", i,
+                getsign(r) ? '-' : '+',
+                (s32)(r->sigh >> 16),
+                (s32)(r->sigh & 0xFFFF),
+                (s32)(r->sigl >> 16),
+                (s32)(r->sigl & 0xFFFF),
+                exponent(r) - EXP_BIAS + 1);
+         break;
+       default:
+         printk("Whoops! Error in errors.c: tag%d is %d ", i, tagi);
+         continue;
+         break;
+       }
+      printk("%s\n", tag_desc[(int) (unsigned) tagi]);
+    }
+
+  RE_ENTRANT_CHECK_ON;
+
+}
+#endif
+
+static struct {
+  int type;
+  const char *name;
+} exception_names[] = {
+  { EX_StackOver, "stack overflow" },
+  { EX_StackUnder, "stack underflow" },
+  { EX_Precision, "loss of precision" },
+  { EX_Underflow, "underflow" },
+  { EX_Overflow, "overflow" },
+  { EX_ZeroDiv, "divide by zero" },
+  { EX_Denormal, "denormalized operand" },
+  { EX_Invalid, "invalid operation" },
+  { EX_INTERNAL, "INTERNAL BUG in "FPU_VERSION },
+  { 0, NULL }
+};
+
+/*
+ EX_INTERNAL is always given with a code which indicates where the
+ error was detected.
+
+ Internal error types:
+       0x14   in fpu_etc.c
+       0x1nn  in a *.c file:
+              0x101  in reg_add_sub.c
+              0x102  in reg_mul.c
+              0x104  in poly_atan.c
+              0x105  in reg_mul.c
+              0x107  in fpu_trig.c
+             0x108  in reg_compare.c
+             0x109  in reg_compare.c
+             0x110  in reg_add_sub.c
+             0x111  in fpe_entry.c
+             0x112  in fpu_trig.c
+             0x113  in errors.c
+             0x115  in fpu_trig.c
+             0x116  in fpu_trig.c
+             0x117  in fpu_trig.c
+             0x118  in fpu_trig.c
+             0x119  in fpu_trig.c
+             0x120  in poly_atan.c
+             0x121  in reg_compare.c
+             0x122  in reg_compare.c
+             0x123  in reg_compare.c
+             0x125  in fpu_trig.c
+             0x126  in fpu_entry.c
+             0x127  in poly_2xm1.c
+             0x128  in fpu_entry.c
+             0x129  in fpu_entry.c
+             0x130  in get_address.c
+             0x131  in get_address.c
+             0x132  in get_address.c
+             0x133  in get_address.c
+             0x140  in load_store.c
+             0x141  in load_store.c
+              0x150  in poly_sin.c
+              0x151  in poly_sin.c
+             0x160  in reg_ld_str.c
+             0x161  in reg_ld_str.c
+             0x162  in reg_ld_str.c
+             0x163  in reg_ld_str.c
+             0x164  in reg_ld_str.c
+             0x170  in fpu_tags.c
+             0x171  in fpu_tags.c
+             0x172  in fpu_tags.c
+             0x180  in reg_convert.c
+       0x2nn  in an *.S file:
+              0x201  in reg_u_add.S
+              0x202  in reg_u_div.S
+              0x203  in reg_u_div.S
+              0x204  in reg_u_div.S
+              0x205  in reg_u_mul.S
+              0x206  in reg_u_sub.S
+              0x207  in wm_sqrt.S
+             0x208  in reg_div.S
+              0x209  in reg_u_sub.S
+              0x210  in reg_u_sub.S
+              0x211  in reg_u_sub.S
+              0x212  in reg_u_sub.S
+             0x213  in wm_sqrt.S
+             0x214  in wm_sqrt.S
+             0x215  in wm_sqrt.S
+             0x220  in reg_norm.S
+             0x221  in reg_norm.S
+             0x230  in reg_round.S
+             0x231  in reg_round.S
+             0x232  in reg_round.S
+             0x233  in reg_round.S
+             0x234  in reg_round.S
+             0x235  in reg_round.S
+             0x236  in reg_round.S
+             0x240  in div_Xsig.S
+             0x241  in div_Xsig.S
+             0x242  in div_Xsig.S
+ */
+
+void FPU_exception(int n)
+{
+  int i, int_type;
+
+  int_type = 0;         /* Needed only to stop compiler warnings */
+  if ( n & EX_INTERNAL )
+    {
+      int_type = n - EX_INTERNAL;
+      n = EX_INTERNAL;
+      /* Set lots of exception bits! */
+      partial_status |= (SW_Exc_Mask | SW_Summary | SW_Backward);
+    }
+  else
+    {
+      /* Extract only the bits which we use to set the status word */
+      n &= (SW_Exc_Mask);
+      /* Set the corresponding exception bit */
+      partial_status |= n;
+      /* Set summary bits iff exception isn't masked */
+      if ( partial_status & ~control_word & CW_Exceptions )
+       partial_status |= (SW_Summary | SW_Backward);
+      if ( n & (SW_Stack_Fault | EX_Precision) )
+       {
+         if ( !(n & SW_C1) )
+           /* This bit distinguishes over- from underflow for a stack fault,
+              and roundup from round-down for precision loss. */
+           partial_status &= ~SW_C1;
+       }
+    }
+
+  RE_ENTRANT_CHECK_OFF;
+  if ( (~control_word & n & CW_Exceptions) || (n == EX_INTERNAL) )
+    {
+#ifdef PRINT_MESSAGES
+      /* My message from the sponsor */
+      printk(FPU_VERSION" "__DATE__" (C) W. Metzenthen.\n");
+#endif /* PRINT_MESSAGES */
+      
+      /* Get a name string for error reporting */
+      for (i=0; exception_names[i].type; i++)
+       if ( (exception_names[i].type & n) == exception_names[i].type )
+         break;
+      
+      if (exception_names[i].type)
+       {
+#ifdef PRINT_MESSAGES
+         printk("FP Exception: %s!\n", exception_names[i].name);
+#endif /* PRINT_MESSAGES */
+       }
+      else
+       printk("FPU emulator: Unknown Exception: 0x%04x!\n", n);
+      
+      if ( n == EX_INTERNAL )
+       {
+         printk("FPU emulator: Internal error type 0x%04x\n", int_type);
+         FPU_printall();
+       }
+#ifdef PRINT_MESSAGES
+      else
+       FPU_printall();
+#endif /* PRINT_MESSAGES */
+
+      /*
+       * The 80486 generates an interrupt on the next non-control FPU
+       * instruction. So we need some means of flagging it.
+       * We use the ES (Error Summary) bit for this.
+       */
+    }
+  RE_ENTRANT_CHECK_ON;
+
+
+}
+
+
+/* Real operation attempted on a NaN. */
+/* Returns < 0 if the exception is unmasked */
+int real_1op_NaN(FPU_REG *a)
+{
+  int signalling, isNaN;
+
+  isNaN = (exponent(a) == EXP_OVER) && (a->sigh & 0x80000000);
+
+  /* The default result for the case of two "equal" NaNs (signs may
+     differ) is chosen to reproduce 80486 behaviour */
+  signalling = isNaN && !(a->sigh & 0x40000000);
+
+  if ( !signalling )
+    {
+      if ( !isNaN )  /* pseudo-NaN, or other unsupported? */
+       {
+         if ( control_word & CW_Invalid )
+           {
+             /* Masked response */
+             reg_copy(&CONST_QNaN, a);
+           }
+         EXCEPTION(EX_Invalid);
+         return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
+       }
+      return TAG_Special;
+    }
+
+  if ( control_word & CW_Invalid )
+    {
+      /* The masked response */
+      if ( !(a->sigh & 0x80000000) )  /* pseudo-NaN ? */
+       {
+         reg_copy(&CONST_QNaN, a);
+       }
+      /* ensure a Quiet NaN */
+      a->sigh |= 0x40000000;
+    }
+
+  EXCEPTION(EX_Invalid);
+
+  return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
+}
+
+
+/* Real operation attempted on two operands, one a NaN. */
+/* Returns < 0 if the exception is unmasked */
+int real_2op_NaN(FPU_REG const *b, u_char tagb,
+                int deststnr,
+                FPU_REG const *defaultNaN)
+{
+  FPU_REG *dest = &st(deststnr);
+  FPU_REG const *a = dest;
+  u_char taga = FPU_gettagi(deststnr);
+  FPU_REG const *x;
+  int signalling, unsupported;
+
+  if ( taga == TAG_Special )
+    taga = FPU_Special(a);
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+
+  /* TW_NaN is also used for unsupported data types. */
+  unsupported = ((taga == TW_NaN)
+                && !((exponent(a) == EXP_OVER) && (a->sigh & 0x80000000)))
+    || ((tagb == TW_NaN)
+       && !((exponent(b) == EXP_OVER) && (b->sigh & 0x80000000)));
+  if ( unsupported )
+    {
+      if ( control_word & CW_Invalid )
+       {
+         /* Masked response */
+         FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr);
+       }
+      EXCEPTION(EX_Invalid);
+      return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
+    }
+
+  if (taga == TW_NaN)
+    {
+      x = a;
+      if (tagb == TW_NaN)
+       {
+         signalling = !(a->sigh & b->sigh & 0x40000000);
+         if ( significand(b) > significand(a) )
+           x = b;
+         else if ( significand(b) == significand(a) )
+           {
+             /* The default result for the case of two "equal" NaNs (signs may
+                differ) is chosen to reproduce 80486 behaviour */
+             x = defaultNaN;
+           }
+       }
+      else
+       {
+         /* return the quiet version of the NaN in a */
+         signalling = !(a->sigh & 0x40000000);
+       }
+    }
+  else
+#ifdef PARANOID
+    if (tagb == TW_NaN)
+#endif /* PARANOID */
+    {
+      signalling = !(b->sigh & 0x40000000);
+      x = b;
+    }
+#ifdef PARANOID
+  else
+    {
+      signalling = 0;
+      EXCEPTION(EX_INTERNAL|0x113);
+      x = &CONST_QNaN;
+    }
+#endif /* PARANOID */
+
+  if ( (!signalling) || (control_word & CW_Invalid) )
+    {
+      if ( ! x )
+       x = b;
+
+      if ( !(x->sigh & 0x80000000) )  /* pseudo-NaN ? */
+       x = &CONST_QNaN;
+
+      FPU_copy_to_regi(x, TAG_Special, deststnr);
+
+      if ( !signalling )
+       return TAG_Special;
+
+      /* ensure a Quiet NaN */
+      dest->sigh |= 0x40000000;
+    }
+
+  EXCEPTION(EX_Invalid);
+
+  return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
+}
+
+
+/* Invalid arith operation on Valid registers */
+/* Returns < 0 if the exception is unmasked */
+asmlinkage int arith_invalid(int deststnr)
+{
+
+  EXCEPTION(EX_Invalid);
+  
+  if ( control_word & CW_Invalid )
+    {
+      /* The masked response */
+      FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr);
+    }
+  
+  return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Valid;
+
+}
+
+
+/* Divide a finite number by zero */
+asmlinkage int FPU_divide_by_zero(int deststnr, u_char sign)
+{
+  FPU_REG *dest = &st(deststnr);
+  int tag = TAG_Valid;
+
+  if ( control_word & CW_ZeroDiv )
+    {
+      /* The masked response */
+      FPU_copy_to_regi(&CONST_INF, TAG_Special, deststnr);
+      setsign(dest, sign);
+      tag = TAG_Special;
+    }
+  EXCEPTION(EX_ZeroDiv);
+
+  return (!(control_word & CW_ZeroDiv) ? FPU_Exception : 0) | tag;
+
+}
+
+
+/* This may be called often, so keep it lean */
+int set_precision_flag(int flags)
+{
+  if ( control_word & CW_Precision )
+    {
+      partial_status &= ~(SW_C1 & flags);
+      partial_status |= flags;   /* The masked response */
+      return 0;
+    }
+  else
+    {
+      EXCEPTION(flags);
+      return 1;
+    }
+}
+
+
+/* This may be called often, so keep it lean */
+asmlinkage void set_precision_flag_up(void)
+{
+  if ( control_word & CW_Precision )
+    partial_status |= (SW_Precision | SW_C1);   /* The masked response */
+  else
+    EXCEPTION(EX_Precision | SW_C1);
+}
+
+
+/* This may be called often, so keep it lean */
+asmlinkage void set_precision_flag_down(void)
+{
+  if ( control_word & CW_Precision )
+    {   /* The masked response */
+      partial_status &= ~SW_C1;
+      partial_status |= SW_Precision;
+    }
+  else
+    EXCEPTION(EX_Precision);
+}
+
+
+asmlinkage int denormal_operand(void)
+{
+  if ( control_word & CW_Denormal )
+    {   /* The masked response */
+      partial_status |= SW_Denorm_Op;
+      return TAG_Special;
+    }
+  else
+    {
+      EXCEPTION(EX_Denormal);
+      return TAG_Special | FPU_Exception;
+    }
+}
+
+
+asmlinkage int arith_overflow(FPU_REG *dest)
+{
+  int tag = TAG_Valid;
+
+  if ( control_word & CW_Overflow )
+    {
+      /* The masked response */
+      reg_copy(&CONST_INF, dest);
+      tag = TAG_Special;
+    }
+  else
+    {
+      /* Subtract the magic number from the exponent */
+      addexponent(dest, (-3 * (1 << 13)));
+    }
+
+  EXCEPTION(EX_Overflow);
+  if ( control_word & CW_Overflow )
+    {
+      /* The overflow exception is masked. */
+      /* By definition, precision is lost.
+        The roundup bit (C1) is also set because we have
+        "rounded" upwards to Infinity. */
+      EXCEPTION(EX_Precision | SW_C1);
+      return tag;
+    }
+
+  return tag;
+
+}
+
+
+asmlinkage int arith_round_overflow(FPU_REG *dest, u8 sign)
+{
+  int tag = TAG_Valid;
+  int largest;
+
+  if ( control_word & CW_Overflow )
+    {
+      /* The masked response */
+      /* The response here depends upon the rounding mode */
+      switch ( control_word & CW_RC )
+       {
+       case RC_CHOP:           /* Truncate */
+         largest = 1;
+         break;
+       case RC_UP:             /* Towards +infinity */
+         largest = (sign == SIGN_NEG);
+         break;
+       case RC_DOWN:           /* Towards -infinity */
+         largest = (sign == SIGN_POS);
+         break;
+       default:
+         largest = 0;
+         break;
+       }
+      if ( ! largest )
+       {
+         reg_copy(&CONST_INF, dest);
+         tag = TAG_Special;
+       }
+      else
+       {
+         dest->exp = EXTENDED_Ebias+EXP_OVER-1;
+         switch ( control_word & CW_PC )
+           {
+           case 01:
+           case PR_64_BITS:
+             significand(dest) = BX_CONST64(0xffffffffffffffff);
+             break;
+           case PR_53_BITS:
+             significand(dest) = BX_CONST64(0xfffffffffffff800);
+             break;
+           case PR_24_BITS:
+             significand(dest) = BX_CONST64(0xffffff0000000000);
+             break;
+           }
+       }
+    }
+  else
+    {
+      /* Subtract the magic number from the exponent */
+      addexponent(dest, (-3 * (1 << 13)));
+      largest = 0;
+    }
+
+  EXCEPTION(EX_Overflow);
+  if ( control_word & CW_Overflow )
+    {
+      /* The overflow exception is masked. */
+      if ( largest )
+       {
+         EXCEPTION(EX_Precision);
+       }
+      else
+       {
+         /* By definition, precision is lost.
+            The roundup bit (C1) is also set because we have
+            "rounded" upwards to Infinity. */
+         EXCEPTION(EX_Precision | SW_C1);
+       }
+      return tag;
+    }
+
+  return tag;
+
+}
+
+
+asmlinkage int arith_underflow(FPU_REG *dest)
+{
+  int tag = TAG_Valid;
+
+  if ( control_word & CW_Underflow )
+    {
+      /* The masked response */
+      if ( exponent16(dest) <= EXP_UNDER - 63 )
+       {
+         reg_copy(&CONST_Z, dest);
+         partial_status &= ~SW_C1;       /* Round down. */
+         tag = TAG_Zero;
+       }
+      else
+       {
+         stdexp(dest);
+       }
+    }
+  else
+    {
+      /* Add the magic number to the exponent. */
+      addexponent(dest, (3 * (1 << 13)) + EXTENDED_Ebias);
+    }
+
+  EXCEPTION(EX_Underflow);
+  if ( control_word & CW_Underflow )
+    {
+      /* The underflow exception is masked. */
+      EXCEPTION(EX_Precision);
+      return tag;
+    }
+
+  return tag;
+
+}
+
+
+void FPU_stack_overflow(void)
+{
+
+ if ( control_word & CW_Invalid )
+    {
+      /* The masked response */
+      top--;
+      FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
+    }
+
+  EXCEPTION(EX_StackOver);
+
+  return;
+
+}
+
+
+void FPU_stack_underflow(void)
+{
+
+ if ( control_word & CW_Invalid )
+    {
+      /* The masked response */
+      FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
+    }
+
+  EXCEPTION(EX_StackUnder);
+
+  return;
+
+}
+
+
+void FPU_stack_underflow_i(int i)
+{
+
+ if ( control_word & CW_Invalid )
+    {
+      /* The masked response */
+      FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i);
+    }
+
+  EXCEPTION(EX_StackUnder);
+
+  return;
+
+}
+
+
+void FPU_stack_underflow_pop(int i)
+{
+
+ if ( control_word & CW_Invalid )
+    {
+      /* The masked response */
+      FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i);
+      FPU_pop();
+    }
+
+  EXCEPTION(EX_StackUnder);
+
+  return;
+
+}
+
diff --git a/sid/component/bochs/cpu/fpu/exception.h b/sid/component/bochs/cpu/fpu/exception.h
new file mode 100644 (file)
index 0000000..2b9b3ce
--- /dev/null
@@ -0,0 +1,48 @@
+/*---------------------------------------------------------------------------+
+ |  exception.h                                                              |
+ |                                                                           |
+ | Copyright (C) 1992    W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#ifndef _EXCEPTION_H_
+#define _EXCEPTION_H_
+
+
+#ifdef __ASSEMBLY__
+#define        Const_(x)       $##x
+#else
+#define        Const_(x)       x
+#endif
+
+#ifndef SW_C1
+#include "fpu_emu.h"
+#endif /* SW_C1 */
+
+#define FPU_BUSY        Const_(0x8000)   /* FPU busy bit (8087 compatibility) */
+#define EX_ErrorSummary Const_(0x0080)   /* Error summary status */
+/* Special exceptions: */
+#define        EX_INTERNAL     Const_(0x8000)  /* Internal error in wm-FPU-emu */
+#define EX_StackOver   Const_(0x0041|SW_C1)    /* stack overflow */
+#define EX_StackUnder  Const_(0x0041)  /* stack underflow */
+/* Exception flags: */
+#define EX_Precision   Const_(0x0020)  /* loss of precision */
+#define EX_Underflow   Const_(0x0010)  /* underflow */
+#define EX_Overflow    Const_(0x0008)  /* overflow */
+#define EX_ZeroDiv     Const_(0x0004)  /* divide by zero */
+#define EX_Denormal    Const_(0x0002)  /* denormalized operand */
+#define EX_Invalid     Const_(0x0001)  /* invalid operation */
+
+
+#define PRECISION_LOST_UP    Const_((EX_Precision | SW_C1))
+#define PRECISION_LOST_DOWN  Const_(EX_Precision)
+
+
+#ifndef __ASSEMBLY__
+
+#define        EXCEPTION(x)    FPU_exception(x)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _EXCEPTION_H_ */
diff --git a/sid/component/bochs/cpu/fpu/fpu.cc b/sid/component/bochs/cpu/fpu/fpu.cc
new file mode 100644 (file)
index 0000000..9178389
--- /dev/null
@@ -0,0 +1,179 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+#include "bochs.h"
+
+#define LOG_THIS genlog->
+
+// Nomenclature used to signify argument types
+//
+// Es = single real
+// El = double real
+// Ea = 14/28 bytes    98/108b bytes (FRSTOR,FSAVE)???
+// Ew = word integer (2 bytes)
+// Ed = dword integer (4 bytes) (short int)
+// Et = extended real
+// Eb = packed BCD
+// Eq = quadword integer (8 bytes) (long integer)
+
+
+
+  void
+BX_CPU_C::ESC0(BxInstruction_t *i)
+{
+  if ( BX_CPU_THIS_PTR cr0.em || BX_CPU_THIS_PTR cr0.ts ) {
+    exception(BX_NM_EXCEPTION, 0, 0);
+    }
+#if BX_SUPPORT_FPU
+  fpu_execute(i);
+#else
+  BX_INFO(("ESC0 not implemented\n"));
+#endif
+}
+
+  void
+BX_CPU_C::ESC1(BxInstruction_t *i)
+{
+  if ( BX_CPU_THIS_PTR cr0.em || BX_CPU_THIS_PTR cr0.ts ) {
+    exception(BX_NM_EXCEPTION, 0, 0);
+    }
+#if BX_SUPPORT_FPU
+  fpu_execute(i);
+#else
+  BX_INFO(("ESC1 not implemented\n"));
+#endif
+}
+
+  void
+BX_CPU_C::ESC2(BxInstruction_t *i)
+{
+  if ( BX_CPU_THIS_PTR cr0.em || BX_CPU_THIS_PTR cr0.ts ) {
+    exception(BX_NM_EXCEPTION, 0, 0);
+    }
+#if BX_SUPPORT_FPU
+  fpu_execute(i);
+#else
+  BX_INFO(("ESC2 not implemented\n"));
+#endif
+}
+
+  void
+BX_CPU_C::ESC3(BxInstruction_t *i)
+{
+  if ( BX_CPU_THIS_PTR cr0.em || BX_CPU_THIS_PTR cr0.ts ) {
+    exception(BX_NM_EXCEPTION, 0, 0);
+    }
+
+//BX_DEBUG(( "CS:EIP = %04x:%08x\n",
+//  BX_CPU.sregs[BX_SEG_REG_CS].selector.value, BX_CPU.prev_eip));
+
+#if BX_SUPPORT_FPU
+  fpu_execute(i);
+#else
+  BX_INFO(("ESC3 not implemented\n"));
+#endif
+}
+
+  void
+BX_CPU_C::ESC4(BxInstruction_t *i)
+{
+  if ( BX_CPU_THIS_PTR cr0.em || BX_CPU_THIS_PTR cr0.ts ) {
+    exception(BX_NM_EXCEPTION, 0, 0);
+    }
+#if BX_SUPPORT_FPU
+  fpu_execute(i);
+#else
+  BX_INFO(("ESC4 not implemented\n"));
+#endif
+}
+
+  void
+BX_CPU_C::ESC5(BxInstruction_t *i)
+{
+  if ( BX_CPU_THIS_PTR cr0.em || BX_CPU_THIS_PTR cr0.ts ) {
+    exception(BX_NM_EXCEPTION, 0, 0);
+    }
+#if BX_SUPPORT_FPU
+  fpu_execute(i);
+#else
+  BX_INFO(("ESC5 not implemented\n"));
+#endif
+}
+
+  void
+BX_CPU_C::ESC6(BxInstruction_t *i)
+{
+  if ( BX_CPU_THIS_PTR cr0.em || BX_CPU_THIS_PTR cr0.ts ) {
+    exception(BX_NM_EXCEPTION, 0, 0);
+    }
+#if BX_SUPPORT_FPU
+  fpu_execute(i);
+#else
+  BX_INFO(("ESC6 not implemented\n"));
+#endif
+}
+
+  void
+BX_CPU_C::ESC7(BxInstruction_t *i)
+{
+  if ( BX_CPU_THIS_PTR cr0.em || BX_CPU_THIS_PTR cr0.ts ) {
+    exception(BX_NM_EXCEPTION, 0, 0);
+    }
+#if BX_SUPPORT_FPU
+  fpu_execute(i);
+#else
+  BX_INFO(("ESC7 not implemented\n"));
+#endif
+}
+
+  void
+BX_CPU_C::FWAIT(BxInstruction_t *i)
+{
+#if BX_CPU_LEVEL < 3
+  // WAIT doesn't generate single steps on 8086.
+  // The same goes for prefix instructions, and instructions which
+  // modify segment registers. (pg4-16)
+  // single_step_event = 0;
+  BX_PANIC(("WAIT: not implemented for < 386\n"));
+#else // BX_CPU_LEVEL >= 3
+
+  if ( BX_CPU_THIS_PTR cr0.ts && BX_CPU_THIS_PTR cr0.mp ) {
+    exception(BX_NM_EXCEPTION, 0, 0); // no error
+    }
+#if BX_SUPPORT_FPU
+  fpu_execute(i);
+#else
+  BX_INFO(("FWAIT: no FPU\n"));
+#endif
+
+#endif
+}
+
+
+#if BX_SUPPORT_FPU==0
+  // if supporting FPU, this function in glue logic file
+  void
+BX_CPU_C::fpu_init(void)
+{
+}
+#endif
diff --git a/sid/component/bochs/cpu/fpu/fpu_arith.c b/sid/component/bochs/cpu/fpu/fpu_arith.c
new file mode 100644 (file)
index 0000000..f012174
--- /dev/null
@@ -0,0 +1,174 @@
+/*---------------------------------------------------------------------------+
+ |  fpu_arith.c                                                              |
+ |                                                                           |
+ | Code to implement the FPU register/register arithmetic instructions       |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1997                                              |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_system.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+#include "status_w.h"
+
+
+void fadd__()
+{
+  /* fadd st,st(i) */
+  int i = FPU_rm;
+  clear_C1();
+  FPU_add(&st(i), FPU_gettagi(i), 0, control_word);
+}
+
+
+void fmul__()
+{
+  /* fmul st,st(i) */
+  int i = FPU_rm;
+  clear_C1();
+  FPU_mul(&st(i), FPU_gettagi(i), 0, control_word);
+}
+
+
+
+void fsub__()
+{
+  /* fsub st,st(i) */
+  clear_C1();
+  FPU_sub(0, REGNO2PTR(FPU_rm), control_word);
+}
+
+
+void fsubr_()
+{
+  /* fsubr st,st(i) */
+  clear_C1();
+  FPU_sub(REV, REGNO2PTR(FPU_rm), control_word);
+}
+
+
+void fdiv__()
+{
+  /* fdiv st,st(i) */
+  clear_C1();
+  FPU_div(0, REGNO2PTR(FPU_rm), control_word);
+}
+
+
+void fdivr_()
+{
+  /* fdivr st,st(i) */
+  clear_C1();
+  FPU_div(REV, REGNO2PTR(FPU_rm), control_word);
+}
+
+
+
+void fadd_i()
+{
+  /* fadd st(i),st */
+  int i = FPU_rm;
+  clear_C1();
+  FPU_add(&st(i), FPU_gettagi(i), i, control_word);
+}
+
+
+void fmul_i()
+{
+  /* fmul st(i),st */
+  clear_C1();
+  FPU_mul(&st(0), FPU_gettag0(), FPU_rm, control_word);
+}
+
+
+void fsubri()
+{
+  /* fsubr st(i),st */
+  clear_C1();
+  FPU_sub(DEST_RM, REGNO2PTR(FPU_rm), control_word);
+}
+
+
+void fsub_i()
+{
+  /* fsub st(i),st */
+  clear_C1();
+  FPU_sub(REV|DEST_RM, REGNO2PTR(FPU_rm), control_word);
+}
+
+
+void fdivri()
+{
+  /* fdivr st(i),st */
+  clear_C1();
+  FPU_div(DEST_RM, REGNO2PTR(FPU_rm), control_word);
+}
+
+
+void fdiv_i()
+{
+  /* fdiv st(i),st */
+  clear_C1();
+  FPU_div(REV|DEST_RM, REGNO2PTR(FPU_rm), control_word);
+}
+
+
+
+void faddp_()
+{
+  /* faddp st(i),st */
+  int i = FPU_rm;
+  clear_C1();
+  if ( FPU_add(&st(i), FPU_gettagi(i), i, control_word) >= 0 )
+    FPU_pop();
+}
+
+
+void fmulp_()
+{
+  /* fmulp st(i),st */
+  clear_C1();
+  if ( FPU_mul(&st(0), FPU_gettag0(), FPU_rm, control_word) >= 0 )
+    FPU_pop();
+}
+
+
+
+void fsubrp()
+{
+  /* fsubrp st(i),st */
+  clear_C1();
+  if ( FPU_sub(DEST_RM, REGNO2PTR(FPU_rm), control_word) >= 0 )
+    FPU_pop();
+}
+
+
+void fsubp_()
+{
+  /* fsubp st(i),st */
+  clear_C1();
+  if ( FPU_sub(REV|DEST_RM, REGNO2PTR(FPU_rm), control_word) >= 0 )
+    FPU_pop();
+}
+
+
+void fdivrp()
+{
+  /* fdivrp st(i),st */
+  clear_C1();
+  if ( FPU_div(DEST_RM, REGNO2PTR(FPU_rm), control_word) >= 0 )
+    FPU_pop();
+}
+
+
+void fdivp_()
+{
+  /* fdivp st(i),st */
+  clear_C1();
+  if ( FPU_div(REV|DEST_RM, REGNO2PTR(FPU_rm), control_word) >= 0 )
+    FPU_pop();
+}
diff --git a/sid/component/bochs/cpu/fpu/fpu_asm.h b/sid/component/bochs/cpu/fpu/fpu_asm.h
new file mode 100644 (file)
index 0000000..5665f09
--- /dev/null
@@ -0,0 +1,32 @@
+/*---------------------------------------------------------------------------+
+ |  fpu_asm.h                                                                |
+ |                                                                           |
+ | Copyright (C) 1992,1995,1997                                              |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@suburbia.net               |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#ifndef _FPU_ASM_H_
+#define _FPU_ASM_H_
+
+#include <linux/linkage.h>
+
+#define        EXCEPTION       SYMBOL_NAME(FPU_exception)
+
+
+#define PARAM1 8(%ebp)
+#define        PARAM2  12(%ebp)
+#define        PARAM3  16(%ebp)
+#define        PARAM4  20(%ebp)
+#define        PARAM5  24(%ebp)
+#define        PARAM6  28(%ebp)
+#define        PARAM7  32(%ebp)
+
+#define SIGL_OFFSET 0
+#define        EXP(x)  8(x)
+#define SIG(x) SIGL_OFFSET##(x)
+#define        SIGL(x) SIGL_OFFSET##(x)
+#define        SIGH(x) 4(x)
+
+#endif /* _FPU_ASM_H_ */
diff --git a/sid/component/bochs/cpu/fpu/fpu_aux.c b/sid/component/bochs/cpu/fpu/fpu_aux.c
new file mode 100644 (file)
index 0000000..a2cea50
--- /dev/null
@@ -0,0 +1,204 @@
+/*---------------------------------------------------------------------------+
+ |  fpu_aux.c                                                                |
+ |                                                                           |
+ | Code to implement some of the FPU auxiliary instructions.                 |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_system.h"
+#include "exception.h"
+#include "fpu_emu.h"
+#include "status_w.h"
+#include "control_w.h"
+
+
+static void fnop(void)
+{
+}
+
+void fclex(void)
+{
+  partial_status &= ~(SW_Backward|SW_Summary|SW_Stack_Fault|SW_Precision|
+                  SW_Underflow|SW_Overflow|SW_Zero_Div|SW_Denorm_Op|
+                  SW_Invalid);
+  no_ip_update = 1;
+}
+
+/* Needs to be externally visible */
+void finit()
+{
+  control_word = 0x037f;
+  partial_status = 0;
+  top = 0;            /* We don't keep top in the status word internally. */
+  fpu_tag_word = 0xffff;
+  /* The behaviour is different from that detailed in
+     Section 15.1.6 of the Intel manual */
+  operand_address.offset = 0;
+  operand_address.selector = 0;
+  instruction_address.offset = 0;
+  instruction_address.selector = 0;
+  instruction_address.opcode = 0;
+  no_ip_update = 1;
+}
+
+/*
+ * These are nops on the i387..
+ */
+#define feni fnop
+#define fdisi fnop
+#define fsetpm fnop
+
+static FUNC const finit_table[] = {
+  feni, fdisi, fclex, finit,
+  fsetpm, FPU_illegal, FPU_illegal, FPU_illegal
+};
+
+void finit_()
+{
+  (finit_table[FPU_rm])();
+}
+
+
+static void fstsw_ax(void)
+{
+  SET_AX(status_word()); // KPL
+  no_ip_update = 1;
+}
+
+static FUNC const fstsw_table[] = {
+  fstsw_ax, FPU_illegal, FPU_illegal, FPU_illegal,
+  FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal
+};
+
+void fstsw_()
+{
+  (fstsw_table[FPU_rm])();
+}
+
+
+static FUNC const fp_nop_table[] = {
+  fnop, FPU_illegal, FPU_illegal, FPU_illegal,
+  FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal
+};
+
+void fp_nop()
+{
+  (fp_nop_table[FPU_rm])();
+}
+
+
+void fld_i_()
+{
+  FPU_REG *st_new_ptr;
+  int i;
+  u_char tag;
+
+  if ( STACK_OVERFLOW )
+    { FPU_stack_overflow(); return; }
+
+  /* fld st(i) */
+  i = FPU_rm;
+  if ( NOT_EMPTY(i) )
+    {
+      reg_copy(&st(i), st_new_ptr);
+      tag = FPU_gettagi(i);
+      push();
+      FPU_settag0(tag);
+    }
+  else
+    {
+      if ( control_word & CW_Invalid )
+       {
+         /* The masked response */
+         FPU_stack_underflow();
+       }
+      else
+       EXCEPTION(EX_StackUnder);
+    }
+
+}
+
+
+void fxch_i()
+{
+  /* fxch st(i) */
+  FPU_REG t;
+  int i = FPU_rm;
+  FPU_REG *st0_ptr = &st(0), *sti_ptr = &st(i);
+  s32 tag_word = fpu_tag_word;
+  int regnr = top & 7, regnri = ((regnr + i) & 7);
+  u_char st0_tag = (tag_word >> (regnr*2)) & 3;
+  u_char sti_tag = (tag_word >> (regnri*2)) & 3;
+
+  if ( st0_tag == TAG_Empty )
+    {
+      if ( sti_tag == TAG_Empty )
+       {
+         FPU_stack_underflow();
+         FPU_stack_underflow_i(i);
+         return;
+       }
+      if ( control_word & CW_Invalid )
+       {
+         /* Masked response */
+         FPU_copy_to_reg0(sti_ptr, sti_tag);
+       }
+      FPU_stack_underflow_i(i);
+      return;
+    }
+  if ( sti_tag == TAG_Empty )
+    {
+      if ( control_word & CW_Invalid )
+       {
+         /* Masked response */
+         FPU_copy_to_regi(st0_ptr, st0_tag, i);
+       }
+      FPU_stack_underflow();
+      return;
+    }
+  clear_C1();
+
+  reg_copy(st0_ptr, &t);
+  reg_copy(sti_ptr, st0_ptr);
+  reg_copy(&t, sti_ptr);
+
+  tag_word &= ~(3 << (regnr*2)) & ~(3 << (regnri*2));
+  tag_word |= (sti_tag << (regnr*2)) | (st0_tag << (regnri*2));
+  fpu_tag_word = tag_word;
+}
+
+
+void ffree_()
+{
+  /* ffree st(i) */
+  FPU_settagi(FPU_rm, TAG_Empty);
+}
+
+
+void ffreep()
+{
+  /* ffree st(i) + pop - unofficial code */
+  FPU_settagi(FPU_rm, TAG_Empty);
+  FPU_pop();
+}
+
+
+void fst_i_()
+{
+  /* fst st(i) */
+  FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm);
+}
+
+
+void fstp_i()
+{
+  /* fstp st(i) */
+  FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm);
+  FPU_pop();
+}
+
diff --git a/sid/component/bochs/cpu/fpu/fpu_emu.h b/sid/component/bochs/cpu/fpu/fpu_emu.h
new file mode 100644 (file)
index 0000000..2e9d4bd
--- /dev/null
@@ -0,0 +1,251 @@
+/*---------------------------------------------------------------------------+
+ |  fpu_emu.h                                                                |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail   billm@suburbia.net             |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+
+#ifndef _FPU_EMU_H_
+#define _FPU_EMU_H_
+
+/*
+ * Define PECULIAR_486 to get a closer approximation to 80486 behaviour,
+ * rather than behaviour which appears to be cleaner.
+ * This is a matter of opinion: for all I know, the 80486 may simply
+ * be complying with the IEEE spec. Maybe one day I'll get to see the
+ * spec...
+ */
+#define PECULIAR_486
+
+// change a pointer to an int, with type conversions that make it legal.
+// On machines with 64-bit pointers, compilers complain when you typecast
+// a 64-bit pointer into a 32-bit integer.
+#define PTR2INT(x) ((bx_ptr_equiv_t)(void *)(x))
+
+#ifdef __ASSEMBLY__
+#include "fpu_asm.h"
+#define        Const(x)        $##x
+#else
+#include <asm/types.h>
+#define        Const(x)        x
+#endif
+
+#define EXP_BIAS       Const(0)
+#define EXP_OVER       Const(0x4000)    /* smallest invalid large exponent */
+#define        EXP_UNDER       Const(-0x3fff)   /* largest invalid small exponent */
+#define EXP_WAY_UNDER   Const(-0x6000)   /* Below the smallest denormal, but
+                                           still a 16 bit nr. */
+#define EXP_Infinity    EXP_OVER
+#define EXP_NaN         EXP_OVER
+
+#define EXTENDED_Ebias Const(0x3fff)
+#define EXTENDED_Emin (-0x3ffe)  /* smallest valid exponent */
+
+#define SIGN_POS       Const(0)
+#define SIGN_NEG       Const(0x80)
+
+#define SIGN_Positive  Const(0)
+#define SIGN_Negative  Const(0x8000)
+
+
+/* Keep the order TAG_Valid, TAG_Zero, TW_Denormal */
+/* The following fold to 2 (Special) in the Tag Word */
+#define TW_Denormal     Const(4)        /* De-normal */
+#define TW_Infinity    Const(5)        /* + or - infinity */
+#define        TW_NaN          Const(6)        /* Not a Number */
+#define        TW_Unsupported  Const(7)        /* Not supported by an 80486 */
+
+#define TAG_Valid      Const(0)        /* valid */
+#define TAG_Zero       Const(1)        /* zero */
+#define TAG_Special    Const(2)        /* De-normal, + or - infinity,
+                                          or Not a Number */
+#define TAG_Empty      Const(3)        /* empty */
+
+#define LOADED_DATA    Const(10101)    /* Special st() number to identify
+                                          loaded data (not on stack). */
+
+/* A few flags (must be >= 0x10). */
+#define REV             0x10
+#define DEST_RM         0x20
+#define LOADED          0x40
+
+#define FPU_Exception   Const(0x80000000)   /* Added to tag returns. */
+
+
+#ifndef __ASSEMBLY__
+
+#include "fpu_system.h"
+
+#include <asm/sigcontext.h>   /* for struct _fpstate */
+#include <asm/math_emu.h>
+#include <linux/linkage.h>
+
+/*
+#define RE_ENTRANT_CHECKING
+ */
+
+#ifdef RE_ENTRANT_CHECKING
+extern u_char emulating;
+#  define RE_ENTRANT_CHECK_OFF emulating = 0
+#  define RE_ENTRANT_CHECK_ON emulating = 1
+#else
+#  define RE_ENTRANT_CHECK_OFF
+#  define RE_ENTRANT_CHECK_ON
+#endif /* ifdef RE_ENTRANT_CHECKING */
+
+#define FWAIT_OPCODE 0x9b
+#define OP_SIZE_PREFIX 0x66
+#define ADDR_SIZE_PREFIX 0x67
+#define PREFIX_CS 0x2e
+#define PREFIX_DS 0x3e
+#define PREFIX_ES 0x26
+#define PREFIX_SS 0x36
+#define PREFIX_FS 0x64
+#define PREFIX_GS 0x65
+#define PREFIX_REPE 0xf3
+#define PREFIX_REPNE 0xf2
+#define PREFIX_LOCK 0xf0
+#define PREFIX_CS_ 1
+#define PREFIX_DS_ 2
+#define PREFIX_ES_ 3
+#define PREFIX_FS_ 4
+#define PREFIX_GS_ 5
+#define PREFIX_SS_ 6
+#define PREFIX_DEFAULT 7
+
+struct address {
+  u32 offset;
+#ifdef EMU_BIG_ENDIAN
+  u32 empty:5;
+  u32 opcode:11;
+  u32 selector:16;
+#else
+  u32 selector:16;
+  u32 opcode:11;
+  u32 empty:5;
+#endif
+} GCC_ATTRIBUTE((packed));
+
+struct fpu__reg {
+#ifdef EMU_BIG_ENDIAN
+  u32 sigh;
+  u32 sigl;
+  s16 exp;   /* Signed quantity used in internal arithmetic. */
+#else
+  u32 sigl;
+  u32 sigh;
+  s16 exp;   /* Signed quantity used in internal arithmetic. */
+#endif
+} GCC_ATTRIBUTE((aligned(16), packed));
+
+#ifdef EMU_BIG_ENDIAN
+#define MAKE_REG(s,e,l,h) { h, l, \
+                           ((EXTENDED_Ebias+(e)) | ((SIGN_##s != 0)*0x8000)) }
+#else
+#define MAKE_REG(s,e,l,h) { l, h, \
+                           ((EXTENDED_Ebias+(e)) | ((SIGN_##s != 0)*0x8000)) }
+#endif
+
+typedef void (*FUNC)(void);
+typedef struct fpu__reg FPU_REG;
+typedef void (*FUNC_ST0)(FPU_REG *st0_ptr, u_char st0_tag);
+typedef struct { u_char address_size, operand_size, segment; }
+        GCC_ATTRIBUTE((packed)) overrides;
+/* This structure is 32 bits: */
+typedef struct { overrides override;
+                u_char default_mode; } 
+    GCC_ATTRIBUTE((packed)) fpu_addr_modes;
+/* PROTECTED has a restricted meaning in the emulator; it is used
+   to signal that the emulator needs to do special things to ensure
+   that protection is respected in a segmented model. */
+#define PROTECTED 4
+#define SIXTEEN   1         /* We rely upon this being 1 (true) */
+#define VM86      SIXTEEN
+#define PM16      (SIXTEEN | PROTECTED)
+#define SEG32     PROTECTED
+extern u_char const data_sizes_16[32];
+
+#define register_base ((u_char *) registers )
+#define fpu_register(x)  ( * ((FPU_REG *)( register_base + sizeof(FPU_REG) * (x & 7) )) )
+#define        st(x)      ( * ((FPU_REG *)( register_base + sizeof(FPU_REG) * ((top+x) & 7) )) )
+
+#define        STACK_OVERFLOW  (FPU_stackoverflow(&st_new_ptr))
+#define        NOT_EMPTY(i)    (!FPU_empty_i(i))
+
+#define        NOT_EMPTY_ST0   (st0_tag ^ TAG_Empty)
+
+#define poppop() { FPU_pop(); FPU_pop(); }
+
+/* push() does not affect the tags */
+#define push() { top--; }
+
+#ifdef EMU_BIG_ENDIAN
+#define signbyte(a) (((u_char *)(a))[8])
+#else
+#define signbyte(a) (((u_char *)(a))[9])
+#endif
+#define getsign(a) (signbyte(a) & 0x80)
+#define setsign(a,b) { if (b) signbyte(a) |= 0x80; else signbyte(a) &= 0x7f; }
+#define copysign(a,b) { if (getsign(a)) signbyte(b) |= 0x80; \
+                        else signbyte(b) &= 0x7f; }
+#define changesign(a) { signbyte(a) ^= 0x80; }
+#define setpositive(a) { signbyte(a) &= 0x7f; }
+#define setnegative(a) { signbyte(a) |= 0x80; }
+#define signpositive(a) ( (signbyte(a) & 0x80) == 0 )
+#define signnegative(a) (signbyte(a) & 0x80)
+
+#ifdef EMU_BIG_ENDIAN
+#define significand(x) ( ((u64 *)&((x)->sigh))[0] )
+#else
+#define significand(x) ( ((u64 *)&((x)->sigl))[0] )
+#endif
+
+BX_C_INLINE
+void reg_copy(FPU_REG const *x, FPU_REG *y)
+{
+  y->exp = x->exp;
+  significand(y) = significand(x);
+}
+
+#define exponent(x)  (((x)->exp & 0x7fff) - EXTENDED_Ebias)
+#define setexponentpos(x,y) { (x)->exp = ((y) + EXTENDED_Ebias) & 0x7fff; }
+#define exponent16(x)         (x)->exp
+#define setexponent16(x,y)  { (x)->exp = (y); }
+#define addexponent(x,y)    { (x)->exp += (y); }
+#define stdexp(x)           { (x)->exp += EXTENDED_Ebias; }
+
+#define isdenormal(ptr)   (exponent(ptr) == EXP_BIAS+EXP_UNDER)
+
+/*----- Prototypes for functions written in assembler -----*/
+/* extern void reg_move(FPU_REG *a, FPU_REG *b); */
+
+asmlinkage int FPU_normalize_nuo(FPU_REG *x, int bias);
+asmlinkage int FPU_u_sub(FPU_REG const *arg1, FPU_REG const *arg2,
+                        FPU_REG *answ, u16 control_w, u_char sign,
+                        s32 expa, s32 expb);
+asmlinkage int FPU_u_mul(FPU_REG const *arg1, FPU_REG const *arg2,
+                        FPU_REG *answ, u16 control_w, u_char sign,
+                        s32 expon);
+asmlinkage int FPU_u_div(FPU_REG const *arg1, FPU_REG const *arg2,
+                        FPU_REG *answ, u16 control_w, u_char sign);
+asmlinkage int FPU_u_add(FPU_REG const *arg1, FPU_REG const *arg2,
+                        FPU_REG *answ, u16 control_w, u_char sign,
+                        s32 expa, s32 expb);
+asmlinkage int wm_sqrt(FPU_REG *n, int dummy1, int dummy2,
+                      u16 control_w, u_char sign);
+asmlinkage u32 FPU_shrx(void *l, u32 x);
+asmlinkage u32 FPU_shrxs(void *v, u32 x);
+asmlinkage u32 FPU_div_small(u64 *x, u32 y);
+asmlinkage int FPU_round(FPU_REG *arg, u32 extent, int dummy,
+                        u16 control_w, u_char sign);
+
+#ifndef MAKING_PROTO
+#include "fpu_proto.h"
+#endif
+
+#endif /* defined __ASSEMBLY__ */
+
+#endif /* !defined _FPU_EMU_H_ */
diff --git a/sid/component/bochs/cpu/fpu/fpu_entry.c b/sid/component/bochs/cpu/fpu/fpu_entry.c
new file mode 100644 (file)
index 0000000..567c87a
--- /dev/null
@@ -0,0 +1,1074 @@
+/*---------------------------------------------------------------------------+
+ |  fpu_entry.c                                                              |
+ |                                                                           |
+ | The entry functions for wm-FPU-emu                                        |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1996,1997                                    |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ | See the files "README" and "COPYING" for further copyright and warranty   |
+ | information.                                                              |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | Note:                                                                     |
+ |    The file contains code which accesses user memory.                     |
+ |    Emulator static data may change when user memory is accessed, due to   |
+ |    other processes using the emulator while swapping is in progress.      |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | math_emulate(), restore_i387_soft() and save_i387_soft() are the only     |
+ | entry points for wm-FPU-emu.                                              |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_system.h"
+#include "fpu_emu.h"
+#include "exception.h"
+#include "control_w.h"
+#include "status_w.h"
+
+#include <linux/signal.h>
+
+#include <asm/uaccess.h>
+#include <asm/desc.h>
+
+
+#define __BAD__ FPU_illegal   /* Illegal on an 80486, causes SIGILL */
+
+#ifndef NO_UNDOC_CODE    /* Un-documented FPU op-codes supported by default. */
+
+/* WARNING: These codes are not documented by Intel in their 80486 manual
+   and may not work on FPU clones or later Intel FPUs. */
+
+/* Changes to support the un-doc codes provided by Linus Torvalds. */
+
+#define _d9_d8_ fstp_i    /* unofficial code (19) */
+#define _dc_d0_ fcom_st   /* unofficial code (14) */
+#define _dc_d8_ fcompst   /* unofficial code (1c) */
+#define _dd_c8_ fxch_i    /* unofficial code (0d) */
+#define _de_d0_ fcompst   /* unofficial code (16) */
+#define _df_c0_ ffreep    /* unofficial code (07) ffree + pop */
+#define _df_c8_ fxch_i    /* unofficial code (0f) */
+#define _df_d0_ fstp_i    /* unofficial code (17) */
+#define _df_d8_ fstp_i    /* unofficial code (1f) */
+
+static FUNC const st_instr_table[64] = {
+  fadd__,   fld_i_,     __BAD__, __BAD__, fadd_i,  ffree_,  faddp_,  _df_c0_,
+  fmul__,   fxch_i,     __BAD__, __BAD__, fmul_i,  _dd_c8_, fmulp_,  _df_c8_,
+  fcom_st,  fp_nop,     __BAD__, __BAD__, _dc_d0_, fst_i_,  _de_d0_, _df_d0_,
+  fcompst,  _d9_d8_,    __BAD__, __BAD__, _dc_d8_, fstp_i,  fcompp,  _df_d8_,
+  fsub__,   FPU_etc,    __BAD__, finit_,  fsubri,  fucom_,  fsubrp,  fstsw_,
+  fsubr_,   fconst,     fucompp, __BAD__, fsub_i,  fucomp,  fsubp_,  __BAD__,
+  fdiv__,   FPU_triga,  __BAD__, __BAD__, fdivri,  __BAD__, fdivrp,  __BAD__,
+  fdivr_,   FPU_trigb,  __BAD__, __BAD__, fdiv_i,  __BAD__, fdivp_,  __BAD__,
+};
+
+#else     /* Support only documented FPU op-codes */
+
+static FUNC const st_instr_table[64] = {
+  fadd__,   fld_i_,     __BAD__, __BAD__, fadd_i,  ffree_,  faddp_,  __BAD__,
+  fmul__,   fxch_i,     __BAD__, __BAD__, fmul_i,  __BAD__, fmulp_,  __BAD__,
+  fcom_st,  fp_nop,     __BAD__, __BAD__, __BAD__, fst_i_,  __BAD__, __BAD__,
+  fcompst,  __BAD__,    __BAD__, __BAD__, __BAD__, fstp_i,  fcompp,  __BAD__,
+  fsub__,   FPU_etc,    __BAD__, finit_,  fsubri,  fucom_,  fsubrp,  fstsw_,
+  fsubr_,   fconst,     fucompp, __BAD__, fsub_i,  fucomp,  fsubp_,  __BAD__,
+  fdiv__,   FPU_triga,  __BAD__, __BAD__, fdivri,  __BAD__, fdivrp,  __BAD__,
+  fdivr_,   FPU_trigb,  __BAD__, __BAD__, fdiv_i,  __BAD__, fdivp_,  __BAD__,
+};
+
+#endif /* NO_UNDOC_CODE */
+
+
+#define _NONE_ 0   /* Take no special action */
+#define _REG0_ 1   /* Need to check for not empty st(0) */
+#define _REGI_ 2   /* Need to check for not empty st(0) and st(rm) */
+#define _REGi_ 0   /* Uses st(rm) */
+#define _PUSH_ 3   /* Need to check for space to push onto stack */
+#define _null_ 4   /* Function illegal or not implemented */
+#define _REGIi 5   /* Uses st(0) and st(rm), result to st(rm) */
+#define _REGIp 6   /* Uses st(0) and st(rm), result to st(rm) then pop */
+#define _REGIc 0   /* Compare st(0) and st(rm) */
+#define _REGIn 0   /* Uses st(0) and st(rm), but handle checks later */
+
+#ifndef NO_UNDOC_CODE
+
+/* Un-documented FPU op-codes supported by default. (see above) */
+
+static u_char const type_table[64] = {
+  _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_,
+  _REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_,
+  _REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
+  _REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
+  _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
+  _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
+  _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
+  _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
+};
+
+#else     /* Support only documented FPU op-codes */
+
+static u_char const type_table[64] = {
+  _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_,
+  _REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
+  _REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_,
+  _REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_,
+  _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
+  _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
+  _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
+  _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
+};
+
+#endif /* NO_UNDOC_CODE */
+
+
+#ifndef USE_WITH_CPU_SIM
+
+
+#ifdef RE_ENTRANT_CHECKING
+u_char emulating=0;
+#endif /* RE_ENTRANT_CHECKING */
+
+static int valid_prefix(u_char *Byte, u_char **fpu_eip,
+                       overrides *override);
+
+asmlinkage void math_emulate(long arg)
+{
+  u_char  FPU_modrm, byte1;
+  unsigned short code;
+  fpu_addr_modes addr_modes;
+  int unmasked;
+  FPU_REG loaded_data;
+  FPU_REG *st0_ptr;
+  u_char         loaded_tag, st0_tag;
+  void *data_address;
+  struct address data_sel_off;
+  struct address entry_sel_off;
+  u32 code_base = 0;
+  u32 code_limit = 0;  /* Initialized to stop compiler warnings */
+  struct desc_struct code_descriptor;
+
+#ifdef RE_ENTRANT_CHECKING
+  if ( emulating )
+    {
+      printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
+    }
+  RE_ENTRANT_CHECK_ON;
+#endif /* RE_ENTRANT_CHECKING */
+
+  if (!current->used_math)
+    {
+      finit();
+      current->used_math = 1;
+    }
+
+  SETUP_DATA_AREA(arg);
+
+  FPU_ORIG_EIP = FPU_EIP;
+
+  if ( (FPU_EFLAGS & 0x00020000) != 0 )
+    {
+      /* Virtual 8086 mode */
+      addr_modes.default_mode = VM86;
+      FPU_EIP += code_base = FPU_CS << 4;
+      code_limit = code_base + 0xffff;  /* Assumes code_base <= 0xffff0000 */
+    }
+  else if ( FPU_CS == __USER_CS && FPU_DS == __USER_DS )
+    {
+      addr_modes.default_mode = 0;
+    }
+  else if ( FPU_CS == __KERNEL_CS )
+    {
+      printk("math_emulate: %04x:%08lx\n",FPU_CS,FPU_EIP);
+      panic("Math emulation needed in kernel");
+    }
+  else
+    {
+
+      if ( (FPU_CS & 4) != 4 )   /* Must be in the LDT */
+       {
+         /* Can only handle segmented addressing via the LDT
+            for now, and it must be 16 bit */
+         printk("FPU emulator: Unsupported addressing mode\n");
+         math_abort(FPU_info, SIGILL);
+       }
+
+      if ( SEG_D_SIZE(code_descriptor = LDT_DESCRIPTOR(FPU_CS)) )
+       {
+         /* The above test may be wrong, the book is not clear */
+         /* Segmented 32 bit protected mode */
+         addr_modes.default_mode = SEG32;
+       }
+      else
+       {
+         /* 16 bit protected mode */
+         addr_modes.default_mode = PM16;
+       }
+      FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor);
+      code_limit = code_base
+       + (SEG_LIMIT(code_descriptor)+1) * SEG_GRANULARITY(code_descriptor)
+         - 1;
+      if ( code_limit < code_base ) code_limit = 0xffffffff;
+    }
+
+  FPU_lookahead = 1;
+  if (current->flags & PF_PTRACED)
+    FPU_lookahead = 0;
+
+  if ( !valid_prefix(&byte1, (u_char **)&FPU_EIP,
+                    &addr_modes.override) )
+    {
+      RE_ENTRANT_CHECK_OFF;
+      printk("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
+            "FPU emulator: self-modifying code! (emulation impossible)\n",
+            byte1);
+      RE_ENTRANT_CHECK_ON;
+      EXCEPTION(EX_INTERNAL|0x126);
+      math_abort(FPU_info,SIGILL);
+    }
+
+do_another_FPU_instruction:
+
+  no_ip_update = 0;
+
+  FPU_EIP++;  /* We have fetched the prefix and first code bytes. */
+
+  if ( addr_modes.default_mode )
+    {
+      /* This checks for the minimum instruction bytes.
+        We also need to check any extra (address mode) code access. */
+      if ( FPU_EIP > code_limit )
+       math_abort(FPU_info,SIGSEGV);
+    }
+
+  if ( (byte1 & 0xf8) != 0xd8 )
+    {
+      if ( byte1 == FWAIT_OPCODE )
+       {
+         if (partial_status & SW_Summary)
+           goto do_the_FPU_interrupt;
+         else
+           goto FPU_fwait_done;
+       }
+#ifdef PARANOID
+      EXCEPTION(EX_INTERNAL|0x128);
+      math_abort(FPU_info,SIGILL);
+#endif /* PARANOID */
+    }
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_code_verify_area(1);
+  FPU_get_user(FPU_modrm, (u_char *) FPU_EIP);
+  RE_ENTRANT_CHECK_ON;
+  FPU_EIP++;
+
+  if (partial_status & SW_Summary)
+    {
+      /* Ignore the error for now if the current instruction is a no-wait
+        control instruction */
+      /* The 80486 manual contradicts itself on this topic,
+        but a real 80486 uses the following instructions:
+        fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
+       */
+      code = (FPU_modrm << 8) | byte1;
+      if ( ! ( (((code & 0xf803) == 0xe003) ||    /* fnclex, fninit, fnstsw */
+               (((code & 0x3003) == 0x3001) &&   /* fnsave, fnstcw, fnstenv,
+                                                    fnstsw */
+                ((code & 0xc000) != 0xc000))) ) )
+       {
+         /*
+          *  We need to simulate the action of the kernel to FPU
+          *  interrupts here.
+          */
+       do_the_FPU_interrupt:
+
+         FPU_EIP = FPU_ORIG_EIP;       /* Point to current FPU instruction. */
+
+         RE_ENTRANT_CHECK_OFF;
+         current->tss.trap_no = 16;
+         current->tss.error_code = 0;
+         send_sig(SIGFPE, current, 1);
+         return;
+       }
+    }
+
+  entry_sel_off.offset = FPU_ORIG_EIP;
+  entry_sel_off.selector = FPU_CS;
+  entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
+
+  FPU_rm = FPU_modrm & 7;
+
+  if ( FPU_modrm < 0300 )
+    {
+      /* All of these instructions use the mod/rm byte to get a data address */
+
+      if ( (addr_modes.default_mode & SIXTEEN)
+         ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX) )
+       data_address = FPU_get_address_16(FPU_modrm, (u32 *)&FPU_EIP, &data_sel_off,
+                                         addr_modes);
+      else
+       data_address = FPU_get_address(FPU_modrm, (u32 *)&FPU_EIP, &data_sel_off,
+                                      addr_modes);
+
+      if ( addr_modes.default_mode )
+       {
+         if ( FPU_EIP-1 > code_limit )
+           math_abort(FPU_info,SIGSEGV);
+       }
+
+      if ( !(byte1 & 1) )
+       {
+         unsigned short status1 = partial_status;
+
+         st0_ptr = &st(0);
+         st0_tag = FPU_gettag0();
+
+         /* Stack underflow has priority */
+         if ( NOT_EMPTY_ST0 )
+           {
+             if ( addr_modes.default_mode & PROTECTED )
+               {
+                 /* This table works for 16 and 32 bit protected mode */
+                 if ( access_limit < data_sizes_16[(byte1 >> 1) & 3] )
+                   math_abort(FPU_info,SIGSEGV);
+               }
+
+             unmasked = 0;  /* Do this here to stop compiler warnings. */
+             switch ( (byte1 >> 1) & 3 )
+               {
+               case 0:
+                 unmasked = FPU_load_single((float *)data_address,
+                                            &loaded_data);
+                 loaded_tag = unmasked & 0xff;
+                 unmasked &= ~0xff;
+                 break;
+               case 1:
+                 loaded_tag = FPU_load_int32((s32 *)data_address, &loaded_data); // bbd: was (u32*)
+                 break;
+               case 2:
+                 unmasked = FPU_load_double((double *)data_address,
+                                            &loaded_data);
+                 loaded_tag = unmasked & 0xff;
+                 unmasked &= ~0xff;
+                 break;
+               case 3:
+               default:  /* Used here to suppress gcc warnings. */
+                 loaded_tag = FPU_load_int16((short *)data_address, &loaded_data);
+                 break;
+               }
+
+             /* No more access to user memory, it is safe
+                to use static data now */
+
+             /* NaN operands have the next priority. */
+             /* We have to delay looking at st(0) until after
+                loading the data, because that data might contain an SNaN */
+             if ( ((st0_tag == TAG_Special) && isNaN(st0_ptr)) ||
+                 ((loaded_tag == TAG_Special) && isNaN(&loaded_data)) )
+               {
+                 /* Restore the status word; we might have loaded a
+                    denormal. */
+                 partial_status = status1;
+                 if ( (FPU_modrm & 0x30) == 0x10 )
+                   {
+                     /* fcom or fcomp */
+                     EXCEPTION(EX_Invalid);
+                     setcc(SW_C3 | SW_C2 | SW_C0);
+                     if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
+                       FPU_pop();             /* fcomp, masked, so we pop. */
+                   }
+                 else
+                   {
+                     if ( loaded_tag == TAG_Special )
+                       loaded_tag = FPU_Special(&loaded_data);
+#ifdef PECULIAR_486
+                     /* This is not really needed, but gives behaviour
+                        identical to an 80486 */
+                     if ( (FPU_modrm & 0x28) == 0x20 )
+                       /* fdiv or fsub */
+                       real_2op_NaN(&loaded_data, loaded_tag, 0, &loaded_data);
+                     else
+#endif /* PECULIAR_486 */
+                       /* fadd, fdivr, fmul, or fsubr */
+                       real_2op_NaN(&loaded_data, loaded_tag, 0, st0_ptr);
+                   }
+                 goto reg_mem_instr_done;
+               }
+
+             if ( unmasked && !((FPU_modrm & 0x30) == 0x10) )
+               {
+                 /* Is not a comparison instruction. */
+                 if ( (FPU_modrm & 0x38) == 0x38 )
+                   {
+                     /* fdivr */
+                     if ( (st0_tag == TAG_Zero) &&
+                          ((loaded_tag == TAG_Valid)
+                           || (loaded_tag == TAG_Special
+                               && isdenormal(&loaded_data))) )
+                       {
+                         if ( FPU_divide_by_zero(0, getsign(&loaded_data))
+                              < 0 )
+                           {
+                             /* We use the fact here that the unmasked
+                                exception in the loaded data was for a
+                                denormal operand */
+                             /* Restore the state of the denormal op bit */
+                             partial_status &= ~SW_Denorm_Op;
+                             partial_status |= status1 & SW_Denorm_Op;
+                           }
+                         else
+                           setsign(st0_ptr, getsign(&loaded_data));
+                       }
+                   }
+                 goto reg_mem_instr_done;
+               }
+
+             switch ( (FPU_modrm >> 3) & 7 )
+               {
+               case 0:         /* fadd */
+                 clear_C1();
+                 FPU_add(&loaded_data, loaded_tag, 0, control_word);
+                 break;
+               case 1:         /* fmul */
+                 clear_C1();
+                 FPU_mul(&loaded_data, loaded_tag, 0, control_word);
+                 break;
+               case 2:         /* fcom */
+                 FPU_compare_st_data(&loaded_data, loaded_tag);
+                 break;
+               case 3:         /* fcomp */
+                 if ( !FPU_compare_st_data(&loaded_data, loaded_tag)
+                      && !unmasked )
+                   FPU_pop();
+                 break;
+               case 4:         /* fsub */
+                 clear_C1();
+                 // bbd: loaded_data used to be typecast to an int, but 
+                 // this corrupted the pointer on 64-bit machines.
+                 // Now FPU_sub and similar take a FPU_REG* here instead. 
+                 FPU_sub(LOADED|loaded_tag, &loaded_data, control_word);
+                 break;
+               case 5:         /* fsubr */
+                 clear_C1();
+                 FPU_sub(REV|LOADED|loaded_tag, &loaded_data, control_word);
+                 break;
+               case 6:         /* fdiv */
+                 clear_C1();
+                 FPU_div(LOADED|loaded_tag, &loaded_data, control_word);
+                 break;
+               case 7:         /* fdivr */
+                 clear_C1();
+                 if ( st0_tag == TAG_Zero )
+                   partial_status = status1;  /* Undo any denorm tag,
+                                                 zero-divide has priority. */
+                 FPU_div(REV|LOADED|loaded_tag, &loaded_data, control_word);
+                 break;
+               }
+           }
+         else
+           {
+             if ( (FPU_modrm & 0x30) == 0x10 )
+               {
+                 /* The instruction is fcom or fcomp */
+                 EXCEPTION(EX_StackUnder);
+                 setcc(SW_C3 | SW_C2 | SW_C0);
+                 if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
+                   FPU_pop();             /* fcomp */
+               }
+             else
+               FPU_stack_underflow();
+           }
+       reg_mem_instr_done:
+         operand_address = data_sel_off;
+       }
+      else
+       {
+         if ( !(no_ip_update =
+                FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1,
+                               addr_modes, data_address)) )
+           {
+             operand_address = data_sel_off;
+           }
+       }
+
+    }
+  else
+    {
+      /* None of these instructions access user memory */
+      u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
+
+#ifdef PECULIAR_486
+      /* This is supposed to be undefined, but a real 80486 seems
+        to do this: */
+      operand_address.offset = 0;
+      operand_address.selector = FPU_DS;
+#endif /* PECULIAR_486 */
+
+      st0_ptr = &st(0);
+      st0_tag = FPU_gettag0();
+      switch ( type_table[(int) instr_index] )
+       {
+       case _NONE_:   /* also _REGIc: _REGIn */
+         break;
+       case _REG0_:
+         if ( !NOT_EMPTY_ST0 )
+           {
+             FPU_stack_underflow();
+             goto FPU_instruction_done;
+           }
+         break;
+       case _REGIi:
+         if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
+           {
+             FPU_stack_underflow_i(FPU_rm);
+             goto FPU_instruction_done;
+           }
+         break;
+       case _REGIp:
+         if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
+           {
+             FPU_stack_underflow_pop(FPU_rm);
+             goto FPU_instruction_done;
+           }
+         break;
+       case _REGI_:
+         if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
+           {
+             FPU_stack_underflow();
+             goto FPU_instruction_done;
+           }
+         break;
+       case _PUSH_:     /* Only used by the fld st(i) instruction */
+         break;
+       case _null_:
+         FPU_illegal();
+         goto FPU_instruction_done;
+       default:
+         EXCEPTION(EX_INTERNAL|0x111);
+         goto FPU_instruction_done;
+       }
+      (*st_instr_table[(int) instr_index])();
+
+FPU_instruction_done:
+      ;
+    }
+
+  if ( ! no_ip_update )
+    instruction_address = entry_sel_off;
+
+FPU_fwait_done:
+
+  if (FPU_lookahead && !current->need_resched)
+    {
+      FPU_ORIG_EIP = FPU_EIP - code_base;
+      if ( valid_prefix(&byte1, (u_char **)&FPU_EIP,
+                       &addr_modes.override) )
+       goto do_another_FPU_instruction;
+    }
+
+  if ( addr_modes.default_mode )
+    FPU_EIP -= code_base;
+
+  RE_ENTRANT_CHECK_OFF;
+}
+
+
+/* Support for prefix bytes is not yet complete. To properly handle
+   all prefix bytes, further changes are needed in the emulator code
+   which accesses user address space. Access to separate segments is
+   important for msdos emulation. */
+static int valid_prefix(u_char *Byte, u_char **fpu_eip,
+                       overrides *override)
+{
+  u_char byte;
+  u_char *ip = *fpu_eip;
+
+  *override = (overrides) { 0, 0, PREFIX_DEFAULT };       /* defaults */
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_code_verify_area(1);
+  FPU_get_user(byte, ip);
+  RE_ENTRANT_CHECK_ON;
+
+  while ( 1 )
+    {
+      switch ( byte )
+       {
+       case ADDR_SIZE_PREFIX:
+         override->address_size = ADDR_SIZE_PREFIX;
+         goto do_next_byte;
+
+       case OP_SIZE_PREFIX:
+         override->operand_size = OP_SIZE_PREFIX;
+         goto do_next_byte;
+
+       case PREFIX_CS:
+         override->segment = PREFIX_CS_;
+         goto do_next_byte;
+       case PREFIX_ES:
+         override->segment = PREFIX_ES_;
+         goto do_next_byte;
+       case PREFIX_SS:
+         override->segment = PREFIX_SS_;
+         goto do_next_byte;
+       case PREFIX_FS:
+         override->segment = PREFIX_FS_;
+         goto do_next_byte;
+       case PREFIX_GS:
+         override->segment = PREFIX_GS_;
+         goto do_next_byte;
+       case PREFIX_DS:
+         override->segment = PREFIX_DS_;
+         goto do_next_byte;
+
+/* lock is not a valid prefix for FPU instructions,
+   let the cpu handle it to generate a SIGILL. */
+/*     case PREFIX_LOCK: */
+
+         /* rep.. prefixes have no meaning for FPU instructions */
+       case PREFIX_REPE:
+       case PREFIX_REPNE:
+
+       do_next_byte:
+         ip++;
+         RE_ENTRANT_CHECK_OFF;
+         FPU_code_verify_area(1);
+         FPU_get_user(byte, ip);
+         RE_ENTRANT_CHECK_ON;
+         break;
+       case FWAIT_OPCODE:
+         *Byte = byte;
+         return 1;
+       default:
+         if ( (byte & 0xf8) == 0xd8 )
+           {
+             *Byte = byte;
+             *fpu_eip = ip;
+             return 1;
+           }
+         else
+           {
+             /* Not a valid sequence of prefix bytes followed by
+                an FPU instruction. */
+             *Byte = byte;  /* Needed for error message. */
+             return 0;
+           }
+       }
+    }
+}
+
+
+void math_abort(struct info * info, unsigned int signal)
+{
+       FPU_EIP = FPU_ORIG_EIP;
+       current->tss.trap_no = 16;
+       current->tss.error_code = 0;
+       send_sig(signal,current,1);
+       RE_ENTRANT_CHECK_OFF;
+       __asm__("movl %0,%%esp ; ret": :"g" (((long) info)-4));
+#ifdef PARANOID
+      printk("ERROR: wm-FPU-emu math_abort failed!\n");
+#endif /* PARANOID */
+}
+
+
+
+#define S387 ((struct i387_soft_struct *)s387)
+#define sstatus_word() \
+  ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
+
+int restore_i387_soft(void *s387, struct _fpstate *buf)
+{
+  u_char *d = (u_char *)buf;
+  int offset, other, i, tags, regnr, tag, newtop;
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_READ, d, 7*4 + 8*10);
+  if (__copy_from_user(&S387->cwd, d, 7*4))
+    return -1;
+  RE_ENTRANT_CHECK_ON;
+
+  d += 7*4;
+
+  S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
+  offset = (S387->ftop & 7) * 10;
+  other = 80 - offset;
+
+  RE_ENTRANT_CHECK_OFF;
+  /* Copy all registers in stack order. */
+  if (__copy_from_user(((u_char *)&S387->st_space)+offset, d, other))
+    return -1;
+  if ( offset )
+    if (__copy_from_user((u_char *)&S387->st_space, d+other, offset))
+      return -1;
+  RE_ENTRANT_CHECK_ON;
+
+  /* The tags may need to be corrected now. */
+  tags = S387->twd;
+  newtop = S387->ftop;
+  for ( i = 0; i < 8; i++ )
+    {
+      regnr = (i+newtop) & 7;
+      if ( ((tags >> ((regnr & 7)*2)) & 3) != TAG_Empty )
+       {
+         /* The loaded data over-rides all other cases. */
+         tag = FPU_tagof((FPU_REG *)((u_char *)S387->st_space + 10*regnr));
+         tags &= ~(3 << (regnr*2));
+         tags |= (tag & 3) << (regnr*2);
+       }
+    }
+  S387->twd = tags;
+
+  return 0;
+}
+
+
+int save_i387_soft(void *s387, struct _fpstate * buf)
+{
+  u_char *d = (u_char *)buf;
+  int offset = (S387->ftop & 7) * 10, other = 80 - offset;
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_WRITE, d, 7*4 + 8*10);
+#ifdef PECULIAR_486
+  S387->cwd &= ~0xe080;
+  /* An 80486 sets nearly all of the reserved bits to 1. */
+  S387->cwd |= 0xffff0040;
+  S387->swd = sstatus_word() | 0xffff0000;
+  S387->twd |= 0xffff0000;
+  S387->fcs &= ~0xf8000000;
+  S387->fos |= 0xffff0000;
+#endif /* PECULIAR_486 */
+  __copy_to_user(d, &S387->cwd, 7*4);
+  RE_ENTRANT_CHECK_ON;
+
+  d += 7*4;
+
+  RE_ENTRANT_CHECK_OFF;
+  /* Copy all registers in stack order. */
+  if (__copy_to_user(d, ((u_char *)&S387->st_space)+offset, other))
+    return -1;
+  if ( offset )
+    if (__copy_to_user(d+other, (u_char *)&S387->st_space, offset))
+      return -1
+  RE_ENTRANT_CHECK_ON;
+
+  return 1;
+}
+
+#else  /* #ifndef USE_WITH_CPU_SIM */
+
+
+/* Note, this is a version of fpu_entry.c, modified to interface
+ * to a CPU simulator, rather than a kernel.
+ *
+ * Ported by Kevin Lawton Sep 20, 1999
+ */
+
+
+  asmlinkage void
+math_emulate2(fpu_addr_modes addr_modes,
+              u_char  FPU_modrm,
+              u_char byte1,
+              void *data_address,
+              struct address data_sel_off,
+              struct address entry_sel_off)
+{
+  u16 code;
+  int unmasked;
+  FPU_REG loaded_data;
+  FPU_REG *st0_ptr;
+  u_char    loaded_tag, st0_tag;
+
+
+  // assuming byte is 0xd8..0xdf or 0xdb==FWAIT
+
+  // lock is not a valid prefix for FPU instructions, +++
+  // let the cpu handle it to generate a SIGILL.
+
+
+  no_ip_update = 0;
+
+  if ( byte1 == FWAIT_OPCODE ) {
+    if (partial_status & SW_Summary)
+      goto do_the_FPU_interrupt;
+    else
+      goto FPU_fwait_done;
+    }
+
+  if (partial_status & SW_Summary) {
+    /* Ignore the error for now if the current instruction is a no-wait
+       control instruction */
+    /* The 80486 manual contradicts itself on this topic,
+       but a real 80486 uses the following instructions:
+       fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
+       */
+    code = (FPU_modrm << 8) | byte1;
+    if ( ! ( (((code & 0xf803) == 0xe003) ||    /* fnclex, fninit, fnstsw */
+              (((code & 0x3003) == 0x3001) &&   /* fnsave, fnstcw, fnstenv,
+                                                   fnstsw */
+               ((code & 0xc000) != 0xc000))) ) ) {
+      /*
+       *  We need to simulate the action of the kernel to FPU
+       *  interrupts here.
+       */
+do_the_FPU_interrupt:
+
+      math_abort(FPU_info, SIGFPE);
+      }
+    }
+
+  entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
+
+  FPU_rm = FPU_modrm & 7;
+
+  if ( FPU_modrm < 0300 ) {
+      /* All of these instructions use the mod/rm byte to get a data address */
+
+      if ( !(byte1 & 1) ) {
+          u16 status1 = partial_status;
+
+          st0_ptr = &st(0);
+          st0_tag = FPU_gettag0();
+
+          /* Stack underflow has priority */
+          if ( NOT_EMPTY_ST0 ) {
+              if ( addr_modes.default_mode & PROTECTED )
+                {
+                  /* This table works for 16 and 32 bit protected mode */
+                  if ( access_limit < data_sizes_16[(byte1 >> 1) & 3] )
+                    math_abort(FPU_info, SIGSEGV);
+                }
+
+              unmasked = 0;  /* Do this here to stop compiler warnings. */
+              switch ( (byte1 >> 1) & 3 )
+                {
+                case 0:
+                  unmasked = FPU_load_single((float *)data_address,
+                                             &loaded_data);
+                  loaded_tag = unmasked & 0xff;
+                  unmasked &= ~0xff;
+                  break;
+                case 1:
+                  loaded_tag = FPU_load_int32((s32 *)data_address, &loaded_data);  // bbd: was (u32 *)
+                  break;
+                case 2:
+                  unmasked = FPU_load_double((double *)data_address,
+                                             &loaded_data);
+                  loaded_tag = unmasked & 0xff;
+                  unmasked &= ~0xff;
+                  break;
+                case 3:
+                default:  /* Used here to suppress gcc warnings. */
+                  loaded_tag = FPU_load_int16((s16 *)data_address, &loaded_data);
+                  break;
+                }
+
+              /* No more access to user memory, it is safe
+                 to use static data now */
+
+              /* NaN operands have the next priority. */
+              /* We have to delay looking at st(0) until after
+                 loading the data, because that data might contain an SNaN */
+              if ( ((st0_tag == TAG_Special) && isNaN(st0_ptr)) ||
+                  ((loaded_tag == TAG_Special) && isNaN(&loaded_data)) )
+                {
+                  /* Restore the status word; we might have loaded a
+                     denormal. */
+                  partial_status = status1;
+                  if ( (FPU_modrm & 0x30) == 0x10 )
+                    {
+                      /* fcom or fcomp */
+                      EXCEPTION(EX_Invalid);
+                      setcc(SW_C3 | SW_C2 | SW_C0);
+                      if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
+                        FPU_pop();             /* fcomp, masked, so we pop. */
+                    }
+                  else
+                    {
+                      if ( loaded_tag == TAG_Special )
+                        loaded_tag = FPU_Special(&loaded_data);
+#ifdef PECULIAR_486
+                      /* This is not really needed, but gives behaviour
+                         identical to an 80486 */
+                      if ( (FPU_modrm & 0x28) == 0x20 )
+                        /* fdiv or fsub */
+                        real_2op_NaN(&loaded_data, loaded_tag, 0, &loaded_data);
+                      else
+#endif /* PECULIAR_486 */
+                        /* fadd, fdivr, fmul, or fsubr */
+                        real_2op_NaN(&loaded_data, loaded_tag, 0, st0_ptr);
+                    }
+                  goto reg_mem_instr_done;
+                }
+
+              if ( unmasked && !((FPU_modrm & 0x30) == 0x10) )
+                {
+                  /* Is not a comparison instruction. */
+                  if ( (FPU_modrm & 0x38) == 0x38 )
+                    {
+                      /* fdivr */
+                      if ( (st0_tag == TAG_Zero) &&
+                           ((loaded_tag == TAG_Valid)
+                            || (loaded_tag == TAG_Special
+                                && isdenormal(&loaded_data))) )
+                        {
+                          if ( FPU_divide_by_zero(0, getsign(&loaded_data))
+                               < 0 )
+                            {
+                              /* We use the fact here that the unmasked
+                                 exception in the loaded data was for a
+                                 denormal operand */
+                              /* Restore the state of the denormal op bit */
+                              partial_status &= ~SW_Denorm_Op;
+                              partial_status |= status1 & SW_Denorm_Op;
+                            }
+                          else
+                            setsign(st0_ptr, getsign(&loaded_data));
+                        }
+                    }
+                  goto reg_mem_instr_done;
+                }
+
+              switch ( (FPU_modrm >> 3) & 7 )
+                {
+                case 0:         /* fadd */
+                  clear_C1();
+                  FPU_add(&loaded_data, loaded_tag, 0, control_word);
+                  break;
+                case 1:         /* fmul */
+                  clear_C1();
+                  FPU_mul(&loaded_data, loaded_tag, 0, control_word);
+                  break;
+                case 2:         /* fcom */
+                  FPU_compare_st_data(&loaded_data, loaded_tag);
+                  break;
+                case 3:         /* fcomp */
+                 // bbd: used to typecase to int first, but this corrupted the
+                 // pointer on 64 bit machines.
+                  if ( !FPU_compare_st_data(&loaded_data, loaded_tag)
+                       && !unmasked )
+                    FPU_pop();
+                  break;
+                case 4:         /* fsub */
+                  clear_C1();
+                  FPU_sub(LOADED|loaded_tag, &loaded_data, control_word);
+                  break;
+                case 5:         /* fsubr */
+                  clear_C1();
+                  FPU_sub(REV|LOADED|loaded_tag, &loaded_data, control_word);
+                  break;
+                case 6:         /* fdiv */
+                  clear_C1();
+                  FPU_div(LOADED|loaded_tag, &loaded_data, control_word);
+                  break;
+                case 7:         /* fdivr */
+                  clear_C1();
+                  if ( st0_tag == TAG_Zero )
+                    partial_status = status1;  /* Undo any denorm tag,
+                                                  zero-divide has priority. */
+                  FPU_div(REV|LOADED|loaded_tag, &loaded_data, control_word);
+                  break;
+                }
+            }
+          else
+            {
+              if ( (FPU_modrm & 0x30) == 0x10 )
+                {
+                  /* The instruction is fcom or fcomp */
+                  EXCEPTION(EX_StackUnder);
+                  setcc(SW_C3 | SW_C2 | SW_C0);
+                  if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
+                    FPU_pop();             /* fcomp */
+                }
+              else
+                FPU_stack_underflow();
+            }
+        reg_mem_instr_done:
+          operand_address = data_sel_off;
+        }
+      else {
+          if ( !(no_ip_update =
+                 FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1,
+                                addr_modes, data_address)) )
+            {
+              operand_address = data_sel_off;
+            }
+        }
+    }
+  else {
+      /* None of these instructions access user memory */
+      u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
+
+#ifdef PECULIAR_486
+      /* This is supposed to be undefined, but a real 80486 seems
+         to do this: */
+      operand_address.offset = 0;
+      operand_address.selector = FPU_DS;
+#endif /* PECULIAR_486 */
+
+      st0_ptr = &st(0);
+      st0_tag = FPU_gettag0();
+      switch ( type_table[(int) instr_index] )
+        {
+        case _NONE_:   /* also _REGIc: _REGIn */
+          break;
+        case _REG0_:
+          if ( !NOT_EMPTY_ST0 )
+            {
+              FPU_stack_underflow();
+              goto FPU_instruction_done;
+            }
+          break;
+        case _REGIi:
+          if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
+            {
+              FPU_stack_underflow_i(FPU_rm);
+              goto FPU_instruction_done;
+            }
+          break;
+        case _REGIp:
+          if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
+            {
+              FPU_stack_underflow_pop(FPU_rm);
+              goto FPU_instruction_done;
+            }
+          break;
+        case _REGI_:
+          if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
+            {
+              FPU_stack_underflow();
+              goto FPU_instruction_done;
+            }
+          break;
+        case _PUSH_:     /* Only used by the fld st(i) instruction */
+          break;
+        case _null_:
+          FPU_illegal();
+          goto FPU_instruction_done;
+        default:
+          EXCEPTION(EX_INTERNAL|0x111);
+          goto FPU_instruction_done;
+        }
+      (*st_instr_table[(int) instr_index])();
+
+FPU_instruction_done:
+      ;
+    }
+
+  if ( ! no_ip_update )
+    instruction_address = entry_sel_off;
+
+FPU_fwait_done:
+
+#ifdef DEBUG
+  FPU_printall();
+#endif /* DEBUG */
+#ifdef BX_NO_BLANK_LABELS
+  if(0);
+#endif
+}
+
+#endif  /* #ifndef USE_WITH_CPU_SIM */
diff --git a/sid/component/bochs/cpu/fpu/fpu_etc.c b/sid/component/bochs/cpu/fpu/fpu_etc.c
new file mode 100644 (file)
index 0000000..b7d288d
--- /dev/null
@@ -0,0 +1,143 @@
+/*---------------------------------------------------------------------------+
+ |  fpu_etc.c                                                                |
+ |                                                                           |
+ | Implement a few FPU instructions.                                         |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail   billm@suburbia.net             |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_system.h"
+#include "exception.h"
+#include "fpu_emu.h"
+#include "status_w.h"
+#include "reg_constant.h"
+
+
+static void fchs(FPU_REG *st0_ptr, u_char st0tag)
+{
+  if ( st0tag ^ TAG_Empty )
+    {
+      signbyte(st0_ptr) ^= SIGN_NEG;
+      clear_C1();
+    }
+  else
+    FPU_stack_underflow();
+}
+
+
+static void fpu_fabs(FPU_REG *st0_ptr, u_char st0tag)
+{
+  if ( st0tag ^ TAG_Empty )
+    {
+      setpositive(st0_ptr);
+      clear_C1();
+    }
+  else
+    FPU_stack_underflow();
+}
+
+
+static void ftst_(FPU_REG *st0_ptr, u_char st0tag)
+{
+  switch (st0tag)
+    {
+    case TAG_Zero:
+      setcc(SW_C3);
+      break;
+    case TAG_Valid:
+      if (getsign(st0_ptr) == SIGN_POS)
+        setcc(0);
+      else
+        setcc(SW_C0);
+      break;
+    case TAG_Special:
+      switch ( FPU_Special(st0_ptr) )
+       {
+       case TW_Denormal:
+         if (getsign(st0_ptr) == SIGN_POS)
+           setcc(0);
+         else
+           setcc(SW_C0);
+         if ( denormal_operand() < 0 )
+           {
+#ifdef PECULIAR_486
+             /* This is weird! */
+             if (getsign(st0_ptr) == SIGN_POS)
+               setcc(SW_C3);
+#endif /* PECULIAR_486 */
+             return;
+           }
+         break;
+       case TW_NaN:
+         setcc(SW_C0|SW_C2|SW_C3);   /* Operand is not comparable */ 
+         EXCEPTION(EX_Invalid);
+         break;
+       case TW_Infinity:
+         if (getsign(st0_ptr) == SIGN_POS)
+           setcc(0);
+         else
+           setcc(SW_C0);
+         break;
+       default:
+         setcc(SW_C0|SW_C2|SW_C3);   /* Operand is not comparable */ 
+         EXCEPTION(EX_INTERNAL|0x14);
+         break;
+       }
+      break;
+    case TAG_Empty:
+      setcc(SW_C0|SW_C2|SW_C3);
+      EXCEPTION(EX_StackUnder);
+      break;
+    }
+}
+
+
+static void fxam(FPU_REG *st0_ptr, u_char st0tag)
+{
+  int c = 0;
+  switch (st0tag)
+    {
+    case TAG_Empty:
+      c = SW_C3|SW_C0;
+      break;
+    case TAG_Zero:
+      c = SW_C3;
+      break;
+    case TAG_Valid:
+      c = SW_C2;
+      break;
+    case TAG_Special:
+      switch ( FPU_Special(st0_ptr) )
+       {
+       case TW_Denormal:
+         c = SW_C2|SW_C3;  /* Denormal */
+         break;
+       case TW_NaN:
+         /* We also use NaN for unsupported types. */
+         if ( (st0_ptr->sigh & 0x80000000) && (exponent(st0_ptr) == EXP_OVER) )
+           c = SW_C0;
+         break;
+       case TW_Infinity:
+         c = SW_C2|SW_C0;
+         break;
+       }
+    }
+  if ( getsign(st0_ptr) == SIGN_NEG )
+    c |= SW_C1;
+  setcc(c);
+}
+
+
+static FUNC_ST0 const fp_etc_table[] = {
+  fchs, fpu_fabs, (FUNC_ST0)FPU_illegal, (FUNC_ST0)FPU_illegal,
+  ftst_, fxam, (FUNC_ST0)FPU_illegal, (FUNC_ST0)FPU_illegal
+};
+
+void FPU_etc()
+{
+  (fp_etc_table[FPU_rm])(&st(0), FPU_gettag0());
+}
diff --git a/sid/component/bochs/cpu/fpu/fpu_proto.h b/sid/component/bochs/cpu/fpu/fpu_proto.h
new file mode 100644 (file)
index 0000000..7d010ec
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef _FPU_PROTO_H
+#define _FPU_PROTO_H
+
+/* errors.c */
+extern void Un_impl(void);
+extern void FPU_illegal(void);
+extern void FPU_printall(void);
+asmlinkage void FPU_exception(int n);
+extern int real_1op_NaN(FPU_REG *a);
+extern int real_2op_NaN(FPU_REG const *b, u_char tagb, int deststnr,
+                       FPU_REG const *defaultNaN);
+extern int arith_invalid(int deststnr);
+extern int FPU_divide_by_zero(int deststnr, u_char sign);
+extern int set_precision_flag(int flags);
+extern void set_precision_flag_up(void);
+extern void set_precision_flag_down(void);
+extern int denormal_operand(void);
+extern int arith_overflow(FPU_REG *dest);
+extern int arith_round_overflow(FPU_REG *dest, u8 sign);
+extern int arith_underflow(FPU_REG *dest);
+extern void FPU_stack_overflow(void);
+extern void FPU_stack_underflow(void);
+extern void FPU_stack_underflow_i(int i);
+extern void FPU_stack_underflow_pop(int i);
+/* fpu_arith.c */
+extern void fadd__(void);
+extern void fmul__(void);
+extern void fsub__(void);
+extern void fsubr_(void);
+extern void fdiv__(void);
+extern void fdivr_(void);
+extern void fadd_i(void);
+extern void fmul_i(void);
+extern void fsubri(void);
+extern void fsub_i(void);
+extern void fdivri(void);
+extern void fdiv_i(void);
+extern void faddp_(void);
+extern void fmulp_(void);
+extern void fsubrp(void);
+extern void fsubp_(void);
+extern void fdivrp(void);
+extern void fdivp_(void);
+/* fpu_aux.c */
+extern void fclex(void);
+extern void finit(void);
+extern void finit_(void);
+extern void fstsw_(void);
+extern void fp_nop(void);
+extern void fld_i_(void);
+extern void fxch_i(void);
+extern void ffree_(void);
+extern void ffreep(void);
+extern void fst_i_(void);
+extern void fstp_i(void);
+/* fpu_entry.c */
+extern void math_emulate(long arg);
+extern void math_abort(struct info *info, unsigned int signal);
+/* fpu_etc.c */
+extern void FPU_etc(void);
+/* fpu_tags.c */
+extern int FPU_gettag0(void);
+extern int FPU_gettagi(int stnr);
+extern int FPU_gettag(int regnr);
+extern void FPU_settag0(int tag);
+extern void FPU_settagi(int stnr, int tag);
+extern void FPU_settag(int regnr, int tag);
+extern int FPU_Special(FPU_REG const *ptr);
+extern int isNaN(FPU_REG const *ptr);
+extern void FPU_pop(void);
+extern int FPU_empty_i(int stnr);
+extern int FPU_stackoverflow(FPU_REG **st_new_ptr);
+extern void FPU_sync_tags(void);
+extern void FPU_copy_to_regi(FPU_REG const *r, u_char tag, int stnr);
+extern void FPU_copy_to_reg1(FPU_REG const *r, u_char tag);
+extern void FPU_copy_to_reg0(FPU_REG const *r, u_char tag);
+/* fpu_trig.c */
+extern void FPU_triga(void);
+extern void FPU_trigb(void);
+/* get_address.c */
+extern void *FPU_get_address(u_char FPU_modrm, u32 *fpu_eip,
+                        struct address *addr, fpu_addr_modes addr_modes);
+extern void *FPU_get_address_16(u_char FPU_modrm, u32 *fpu_eip,
+                           struct address *addr, fpu_addr_modes addr_modes);
+/* load_store.c */
+extern int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
+                           void *data_address);
+/* poly_2xm1.c */
+extern int poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result);
+/* poly_atan.c */
+extern void poly_atan(FPU_REG *st0_ptr, u_char st0_tag, FPU_REG *st1_ptr,
+                     u_char st1_tag);
+/* poly_l2.c */
+extern void poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign);
+extern int poly_l2p1(u_char s0, u_char s1, FPU_REG *r0, FPU_REG *r1,
+                    FPU_REG *d);
+/* poly_sin.c */
+extern void poly_sine(FPU_REG *st0_ptr);
+extern void poly_cos(FPU_REG *st0_ptr);
+/* poly_tan.c */
+extern void poly_tan(FPU_REG *st0_ptr, int flag);
+/* reg_add_sub.c */
+extern int FPU_add(FPU_REG const *b, u_char tagb, int destrnr, u16 control_w);
+extern int FPU_sub(int flags, FPU_REG *rm, u16 control_w);   // bbd: changed arg2 from int to FPU_REG*
+/* reg_compare.c */
+extern int FPU_compare_st_data(FPU_REG const *loaded_data, u_char loaded_tag);
+extern void fcom_st(void);
+extern void fcompst(void);
+extern void fcompp(void);
+extern void fucom_(void);
+extern void fucomp(void);
+extern void fucompp(void);
+/* reg_constant.c */
+extern void fconst(void);
+/* reg_ld_str.c */
+extern int FPU_load_extended(long double *s, int stnr);
+extern int FPU_load_double(double *dfloat, FPU_REG *loaded_data);
+extern int FPU_load_single(float *single, FPU_REG *loaded_data);
+extern int FPU_load_int64(s64 *_s);
+extern int FPU_load_int32(s32 *_s, FPU_REG *loaded_data);
+extern int FPU_load_int16(s16 *_s, FPU_REG *loaded_data);
+extern int FPU_load_bcd(u_char *s);
+extern int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag,
+                             long double *d);
+extern int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double *dfloat);
+extern int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float *single);
+extern int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, s64 *d);
+extern int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, s32 *d);
+extern int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, s16 *d);
+extern int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char *d);
+extern int FPU_round_to_int(FPU_REG *r, u_char tag);
+extern u_char *fldenv(fpu_addr_modes addr_modes, u_char *s);
+extern void frstor(fpu_addr_modes addr_modes, u_char *data_address);
+extern u_char *fstenv(fpu_addr_modes addr_modes, u_char *d);
+extern void fsave(fpu_addr_modes addr_modes, u_char *data_address);
+extern int FPU_tagof(FPU_REG *ptr);
+/* reg_mul.c */
+extern int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w);
+
+extern int FPU_div(int flags, FPU_REG *regrm, int control_w); // bbd: changed arg2 from int to FPU_REG*
+/* reg_convert.c */
+extern int FPU_to_exp16(FPU_REG const *a, FPU_REG *x);
+#endif /* _FPU_PROTO_H */
+
diff --git a/sid/component/bochs/cpu/fpu/fpu_system.h b/sid/component/bochs/cpu/fpu/fpu_system.h
new file mode 100644 (file)
index 0000000..96dc4ea
--- /dev/null
@@ -0,0 +1,218 @@
+/*---------------------------------------------------------------------------+
+ |  fpu_system.h                                                             |
+ |                                                                           |
+ | Copyright (C) 1992,1994,1997                                              |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail   billm@suburbia.net             |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#ifndef _FPU_SYSTEM_H
+#define _FPU_SYSTEM_H
+
+#ifndef USE_WITH_CPU_SIM
+
+/* system dependent definitions */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+/* This sets the pointer FPU_info to point to the argument part
+   of the stack frame of math_emulate() */
+#define SETUP_DATA_AREA(arg)   FPU_info = (struct info *) &arg
+
+#define LDT_DESCRIPTOR(s)      (((struct desc_struct *)current->mm->segments)[(s) >> 3])
+#define SEG_D_SIZE(x)          ((x).b & (3 << 21))
+#define SEG_G_BIT(x)           ((x).b & (1 << 23))
+#define SEG_GRANULARITY(x)     (((x).b & (1 << 23)) ? 4096 : 1)
+#define SEG_286_MODE(x)                ((x).b & ( 0xff000000 | 0xf0000 | (1 << 23)))
+#define SEG_BASE_ADDR(s)       (((s).b & 0xff000000) \
+                                | (((s).b & 0xff) << 16) | ((s).a >> 16))
+#define SEG_LIMIT(s)           (((s).b & 0xff0000) | ((s).a & 0xffff))
+#define SEG_EXECUTE_ONLY(s)    (((s).b & ((1 << 11) | (1 << 9))) == (1 << 11))
+#define SEG_WRITE_PERM(s)      (((s).b & ((1 << 11) | (1 << 9))) == (1 << 9))
+#define SEG_EXPAND_DOWN(s)     (((s).b & ((1 << 11) | (1 << 10))) \
+                                == (1 << 10))
+
+#define I387                   (current->tss.i387)
+#define FPU_info               (I387.soft.info)
+
+#define FPU_CS                 (*(u16 *) &(FPU_info->___cs))
+#define FPU_SS                 (*(u16 *) &(FPU_info->___ss))
+#define FPU_DS                 (*(u16 *) &(FPU_info->___ds))
+#define FPU_EAX                        (FPU_info->___eax)
+#define FPU_EFLAGS             (FPU_info->___eflags)
+#define FPU_EIP                        (FPU_info->___eip)
+#define FPU_ORIG_EIP           (FPU_info->___orig_eip)
+
+#define FPU_lookahead           (I387.soft.lookahead)
+
+#define SET_AX(val16)           *(s16 *) &FPU_EAX = val16
+
+/* nz if ip_offset and cs_selector are not to be set for the current
+   instruction. */
+#define no_ip_update           (*(u_char *)&(I387.soft.no_update))
+#define FPU_rm                 (*(u_char *)&(I387.soft.rm))
+
+/* Number of bytes of data which can be legally accessed by the current
+   instruction. This only needs to hold a number <= 108, so a byte will do. */
+#define access_limit           (*(u_char *)&(I387.soft.alimit))
+
+#define partial_status         (I387.soft.swd)
+#define control_word           (I387.soft.cwd)
+#define fpu_tag_word           (I387.soft.twd)
+#define registers              (I387.soft.st_space)
+#define top                    (I387.soft.ftop)
+
+#define instruction_address    (*(struct address *)&I387.soft.fip)
+#define operand_address                (*(struct address *)&I387.soft.foo)
+
+#define FPU_verify_area(x,y,z) if ( verify_area(x,y,z) ) \
+                               math_abort(FPU_info,SIGSEGV)
+
+#undef FPU_IGNORE_CODE_SEGV
+#ifdef FPU_IGNORE_CODE_SEGV
+/* verify_area() is very expensive, and causes the emulator to run
+   about 20% slower if applied to the code. Anyway, errors due to bad
+   code addresses should be much rarer than errors due to bad data
+   addresses. */
+#define        FPU_code_verify_area(z)
+#else
+/* A simpler test than verify_area() can probably be done for
+   FPU_code_verify_area() because the only possible error is to step
+   past the upper boundary of a legal code area. */
+#define        FPU_code_verify_area(z) FPU_verify_area(VERIFY_READ,(void *)FPU_EIP,z)
+#endif
+
+#define FPU_get_user(x,y)       get_user((x),(y))
+#define FPU_put_user(x,y)       put_user((x),(y))
+
+#else  /* USE_WITH_CPU_SIM */
+
+/* -----------------------------------------------------------
+ * Slimmed down version used to compile against a CPU simulator
+ * rather than a kernel (ported by Kevin Lawton)
+ * ------------------------------------------------------------ */
+
+/* Get data sizes from config.h generated from simulator's
+ * configure script
+ */
+#include "config.h"
+typedef Bit8u  u8;
+typedef Bit8s  s8;
+typedef Bit16u u16;
+typedef Bit16s s16;
+typedef Bit32u u32;
+typedef Bit32s s32;
+typedef Bit64u u64;
+typedef Bit64s s64;
+
+/* bbd: include ported linux headers after config.h for GCC_ATTRIBUTE macro */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <asm/math_emu.h>
+#include <linux/types.h>
+
+#ifndef WORDS_BIGENDIAN
+#error "WORDS_BIGENDIAN not defined in config.h"
+#elif WORDS_BIGENDIAN == 1
+#define EMU_BIG_ENDIAN 1
+#else
+/* Nothing needed.  Lack of defining EMU_BIG_ENDIAN means
+ * small endian
+ */
+#endif
+
+
+extern unsigned fpu_get_user(void *ptr, unsigned len);
+extern void fpu_put_user(unsigned val, void *ptr, unsigned len);
+
+extern void fpu_verify_area(unsigned what, void *ptr, unsigned n);
+extern void math_emulate_init(void);
+extern unsigned fpu_get_ds(void);
+extern void fpu_set_ax(u16);
+
+#ifndef __ASSEMBLY__
+
+struct info {
+#ifdef BX_NO_EMPTY_STRUCTS
+  unsigned char donotindexme;
+#endif
+  };
+
+#define FPU_info ((struct info *) NULL)
+
+
+//
+// Minimal i387 structure, pruned from the linux headers.  Only
+// the fields which were necessary are included.
+//
+typedef struct {
+  struct {
+    s32      cwd;
+    s32      swd;
+    s32      twd;
+    s32      fip;
+    s32      fcs;
+    s32      foo;
+    s32      fos;
+    u32      fill0; /* to make sure the following aligns on an 8byte boundary */
+    u64      st_space[16];   /* 8*16 bytes per FP-reg (aligned) = 128 bytes */
+    unsigned char   ftop;
+    unsigned char   no_update;
+    unsigned char   rm;
+    unsigned char   alimit;
+    } GCC_ATTRIBUTE((aligned(16), packed)) soft;
+  } i387_t;
+
+extern i387_t i387;
+
+
+#endif
+
+#define SIGSEGV  11
+
+#define I387     i387
+
+
+#define SET_AX(val16)           fpu_set_ax(val16);
+
+#define no_ip_update            (*(u_char *)&(I387.soft.no_update))
+#define FPU_rm                  (*(u_char *)&(I387.soft.rm))
+
+
+/* Number of bytes of data which can be legally accessed by the current
+   instruction. This only needs to hold a number <= 108, so a byte will do. */
+#define access_limit            (*(u_char *)&(I387.soft.alimit))
+
+#define partial_status          (I387.soft.swd)
+#define control_word            (I387.soft.cwd)
+#define fpu_tag_word            (I387.soft.twd)
+#define registers               (I387.soft.st_space)
+#define top                     (I387.soft.ftop)
+
+#define instruction_address     (*(struct address *)&I387.soft.fip)
+#define operand_address         (*(struct address *)&I387.soft.foo)
+
+#define FPU_verify_area(x,y,z) fpu_verify_area(x,y,z)
+#define FPU_get_user(x,y)       ((x) = fpu_get_user((y), sizeof(*(y))))
+#define FPU_put_user(val,ptr)   fpu_put_user((val),(ptr),sizeof(*(ptr)))
+
+#define FPU_DS  (fpu_get_ds())
+
+#endif  /* USE_WITH_CPU_SIM */
+
+// bbd: Change a pointer to an int, with type conversions that make it legal.
+// First make it a void pointer, then convert to an integer of the same
+// size as the pointer.  Otherwise, on machines with 64-bit pointers, 
+// compilers complain when you typecast a 64-bit pointer into a 32-bit integer.
+#define PTR2INT(x) ((bx_ptr_equiv_t)(void *)(x))
+
+// bbd: Change an int to a pointer, with type conversions that make it legal.
+// Same strategy as PTR2INT: change to bx_ptr_equiv_t which is an integer
+// type of the same size as FPU_REG*.  Then the conversion to pointer
+// is legal.
+#define REGNO2PTR(x)           ((FPU_REG*)((bx_ptr_equiv_t)(x)))
+
+#endif
diff --git a/sid/component/bochs/cpu/fpu/fpu_tags.c b/sid/component/bochs/cpu/fpu/fpu_tags.c
new file mode 100644 (file)
index 0000000..cb436fe
--- /dev/null
@@ -0,0 +1,127 @@
+/*---------------------------------------------------------------------------+
+ |  fpu_tags.c                                                               |
+ |                                                                           |
+ |  Set FPU register tags.                                                   |
+ |                                                                           |
+ | Copyright (C) 1997                                                        |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@jacobi.maths.monash.edu.au                |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_emu.h"
+#include "fpu_system.h"
+#include "exception.h"
+
+
+void FPU_pop(void)
+{
+  fpu_tag_word |= 3 << ((top & 7)*2);
+  top++;
+}
+
+
+int FPU_gettag0(void)
+{
+  return (fpu_tag_word >> ((top & 7)*2)) & 3;
+}
+
+
+int FPU_gettagi(int stnr)
+{
+  return (fpu_tag_word >> (((top+stnr) & 7)*2)) & 3;
+}
+
+
+int FPU_gettag(int regnr)
+{
+  return (fpu_tag_word >> ((regnr & 7)*2)) & 3;
+}
+
+
+void FPU_settag0(int tag)
+{
+  int regnr = top;
+  regnr &= 7;
+  fpu_tag_word &= ~(3 << (regnr*2));
+  fpu_tag_word |= (tag & 3) << (regnr*2);
+}
+
+
+void FPU_settagi(int stnr, int tag)
+{
+  int regnr = stnr+top;
+  regnr &= 7;
+  fpu_tag_word &= ~(3 << (regnr*2));
+  fpu_tag_word |= (tag & 3) << (regnr*2);
+}
+
+
+void FPU_settag(int regnr, int tag)
+{
+  regnr &= 7;
+  fpu_tag_word &= ~(3 << (regnr*2));
+  fpu_tag_word |= (tag & 3) << (regnr*2);
+}
+
+
+int FPU_Special(FPU_REG const *ptr)
+{
+  int exp = exponent(ptr);
+
+  if ( exp == EXP_BIAS+EXP_UNDER )
+    return TW_Denormal;
+  else if ( exp != EXP_BIAS+EXP_OVER )
+    return TW_NaN;
+  else if ( (ptr->sigh == 0x80000000) && (ptr->sigl == 0) )
+    return TW_Infinity;
+  return TW_NaN;
+}
+
+
+int isNaN(FPU_REG const *ptr)
+{
+  return ( (exponent(ptr) == EXP_BIAS+EXP_OVER)
+          && !((ptr->sigh == 0x80000000) && (ptr->sigl == 0)) );
+}
+
+
+int FPU_empty_i(int stnr)
+{
+  int regnr = (top+stnr) & 7;
+
+  return ((fpu_tag_word >> (regnr*2)) & 3) == TAG_Empty;
+}
+
+
+int FPU_stackoverflow(FPU_REG **st_new_ptr)
+{
+  *st_new_ptr = &st(-1);
+
+  return ((fpu_tag_word >> (((top - 1) & 7)*2)) & 3) != TAG_Empty;
+}
+
+
+void FPU_copy_to_regi(FPU_REG const *r, u_char tag, int stnr)
+{
+  reg_copy(r, &st(stnr));
+  FPU_settagi(stnr, tag);
+}
+
+void FPU_copy_to_reg1(FPU_REG const *r, u_char tag)
+{
+  reg_copy(r, &st(1));
+  FPU_settagi(1, tag);
+}
+
+void FPU_copy_to_reg0(FPU_REG const *r, u_char tag)
+{
+  int regnr = top;
+  regnr &= 7;
+
+  reg_copy(r, &st(0));
+
+  fpu_tag_word &= ~(3 << (regnr*2));
+  fpu_tag_word |= (tag & 3) << (regnr*2);
+}
diff --git a/sid/component/bochs/cpu/fpu/fpu_trig.c b/sid/component/bochs/cpu/fpu/fpu_trig.c
new file mode 100644 (file)
index 0000000..1714771
--- /dev/null
@@ -0,0 +1,1890 @@
+/*---------------------------------------------------------------------------+
+ |  fpu_trig.c                                                               |
+ |                                                                           |
+ | Implementation of the FPU "transcendental" functions.                     |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997,1999                                    |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail   billm@melbpc.org.au            |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_system.h"
+#include "exception.h"
+#include "fpu_emu.h"
+#include "status_w.h"
+#include "control_w.h"
+#include "reg_constant.h"      
+
+static void rem_kernel(u64 st0, u64 *y, u64 st1, u64 q, int n);
+
+#define BETTER_THAN_486
+
+#define FCOS  4
+#define FPTAN  8
+
+/* Used only by fptan, fsin, fcos, and fsincos. */
+/* This routine produces very accurate results, similar to
+   using a value of pi with more than 128 bits precision. */
+/* Limited measurements show no results worse than 64 bit precision
+   except for the results for arguments close to 2^63, where the
+   precision of the result sometimes degrades to about 63.9 bits */
+static int trig_arg(FPU_REG *st0_ptr, int flags)
+{
+  FPU_REG tmp;
+  u_char tmptag;
+  u64 q;
+  int old_cw = control_word, saved_status = partial_status;
+  int tag, st0_tag = TAG_Valid;
+
+  if ( exponent(st0_ptr) >= 63 )
+    {
+      partial_status |= SW_C2;     /* Reduction incomplete. */
+      return -1;
+    }
+
+  if ( flags & FPTAN )
+    st0_ptr->exp ++;         /* Effectively base the following upon pi/4 */
+
+  control_word &= ~CW_RC;
+  control_word |= RC_CHOP;
+
+  setpositive(st0_ptr);
+  tag = FPU_u_div(st0_ptr,
+                 &CONST_PI2,
+                 &tmp, PR_64_BITS | RC_CHOP | 0x3f, SIGN_POS);
+
+  FPU_round_to_int(&tmp, tag);  /* Fortunately, this can't overflow
+                                  to 2^64 */
+  q = significand(&tmp);
+
+  if ( q )
+    {
+      rem_kernel(significand(st0_ptr),
+                &significand(&tmp),
+                significand(&CONST_PI2),
+                q, exponent(st0_ptr) - exponent(&CONST_PI2));
+      setexponent16(&tmp, exponent(&CONST_PI2));
+      st0_tag = FPU_normalize_nuo(&tmp,
+                                 EXTENDED_Ebias);  /* No underflow or overflow
+                                                      is possible */
+
+      FPU_copy_to_reg0(&tmp, st0_tag);
+    }
+
+  if ( ((flags & FCOS) && !(q & 1)) || (!(flags & FCOS) && (q & 1)) )
+    {
+      st0_tag = FPU_sub(REV|LOADED|TAG_Valid, &CONST_PI2, FULL_PRECISION); //bbd: arg2 used to typecast to (int)
+
+#ifdef BETTER_THAN_486
+      /* So far, the results are exact but based upon a 64 bit
+        precision approximation to pi/2. The technique used
+        now is equivalent to using an approximation to pi/2 which
+        is accurate to about 128 bits. */
+      if ( (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64) || (q > 1) )
+       {
+         /* This code gives the effect of having pi/2 to better than
+            128 bits precision. */
+
+         significand(&tmp) = q + 1;
+         setexponent16(&tmp, 63);
+          FPU_normalize_nuo(&tmp,
+                            EXTENDED_Ebias);  /* No underflow or overflow
+                                                 is possible */
+         tmptag =
+           FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION, SIGN_POS,
+                     exponent(&CONST_PI2extra) + exponent(&tmp));
+         setsign(&tmp, getsign(&CONST_PI2extra));
+         st0_tag = FPU_add(&tmp, tmptag, 0, FULL_PRECISION);
+          if ( signnegative(st0_ptr) && !(flags & FPTAN) )
+           {
+             /* CONST_PI2extra is negative, so the result of the addition
+                can be negative. This means that the argument is actually
+                in a different quadrant. The correction is always < pi/2,
+                so it can't overflow into yet another quadrant. */
+              /* The function is even, so we need just adjust the sign
+                 and q. */
+             setpositive(st0_ptr);
+             q++;
+           }
+       }
+#endif /* BETTER_THAN_486 */
+    }
+#ifdef BETTER_THAN_486
+  else
+    {
+      /* So far, the results are exact but based upon a 64 bit
+        precision approximation to pi/2. The technique used
+        now is equivalent to using an approximation to pi/2 which
+        is accurate to about 128 bits. */
+      if ( ((q > 0)
+           && (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64))
+          || (q > 1) )
+       {
+         /* This code gives the effect of having p/2 to better than
+            128 bits precision. */
+
+         significand(&tmp) = q;
+         setexponent16(&tmp, 63);
+          FPU_normalize_nuo(&tmp,
+                            EXTENDED_Ebias);  /* No underflow or overflow
+                                                 is possible.
+                                                 This must return TAG_Valid */
+         tmptag = FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION,
+                            SIGN_POS,
+                            exponent(&CONST_PI2extra) + exponent(&tmp));
+         setsign(&tmp, getsign(&CONST_PI2extra));
+         st0_tag = FPU_sub(LOADED|(tmptag & 0x0f), &tmp,
+                           FULL_PRECISION);
+         if ( (exponent(st0_ptr) == exponent(&CONST_PI2)) &&
+             ((st0_ptr->sigh > CONST_PI2.sigh)
+              || ((st0_ptr->sigh == CONST_PI2.sigh)
+                  && (st0_ptr->sigl > CONST_PI2.sigl))) )
+           {
+             /* CONST_PI2extra is negative, so the result of the
+                subtraction can be larger than pi/2. This means
+                that the argument is actually in a different quadrant.
+                The correction is always < pi/2, so it can't overflow
+                into yet another quadrant. 
+                bbd: arg2 used to typecast to (int), corrupting 64-bit ptrs
+              */
+             st0_tag = FPU_sub(REV|LOADED|TAG_Valid, &CONST_PI2,
+                               FULL_PRECISION);
+             q++;
+           }
+       }
+    }
+#endif /* BETTER_THAN_486 */
+
+  FPU_settag0(st0_tag);
+  control_word = old_cw;
+  partial_status = saved_status & ~SW_C2;     /* Reduction complete. */
+
+  if ( flags & FPTAN )
+    {
+      st0_ptr->exp --;
+      return q & 7;
+    }
+
+  return (q & 3) | (flags & FCOS);
+}
+
+
+/* Convert a s32 to register */
+static void convert_l2reg(s32 const *arg, int deststnr)
+{
+  int tag;
+  s32 num = *arg;
+  u_char sign;
+  FPU_REG *dest = &st(deststnr);
+
+  if (num == 0)
+    {
+      FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
+      return;
+    }
+
+  if (num > 0)
+    { sign = SIGN_POS; }
+  else
+    { num = -num; sign = SIGN_NEG; }
+
+  dest->sigh = num;
+  dest->sigl = 0;
+  setexponent16(dest, 31);
+  tag = FPU_normalize_nuo(dest,
+                         EXTENDED_Ebias);  /* No underflow or overflow
+                                              is possible */
+  FPU_settagi(deststnr, tag);
+  setsign(dest, sign);
+  return;
+}
+
+
+static void single_arg_error(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  if ( st0_tag == TAG_Empty )
+    FPU_stack_underflow();  /* Puts a QNaN in st(0) */
+  else if ( st0_tag == TW_NaN )
+    real_1op_NaN(st0_ptr);       /* return with a NaN in st(0) */
+#ifdef PARANOID
+  else
+    EXCEPTION(EX_INTERNAL|0x0112);
+#endif /* PARANOID */
+}
+
+
+static void single_arg_2_error(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  int isNaN;
+
+  switch ( st0_tag )
+    {
+    case TW_NaN:
+      isNaN = (exponent(st0_ptr) == EXP_OVER) && (st0_ptr->sigh & 0x80000000);
+      if ( isNaN && !(st0_ptr->sigh & 0x40000000) )   /* Signaling ? */
+       {
+         EXCEPTION(EX_Invalid);
+         if ( control_word & CW_Invalid )
+           {
+             /* The masked response */
+             /* Convert to a QNaN */
+             st0_ptr->sigh |= 0x40000000;
+             push();
+             FPU_copy_to_reg0(st0_ptr, TAG_Special);
+           }
+       }
+      else if ( isNaN )
+       {
+         /* A QNaN */
+         push();
+         FPU_copy_to_reg0(st0_ptr, TAG_Special);
+       }
+      else
+       {
+         /* pseudoNaN or other unsupported */
+         EXCEPTION(EX_Invalid);
+         if ( control_word & CW_Invalid )
+           {
+             /* The masked response */
+             FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
+             push();
+             FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
+           }
+       }
+      break;              /* return with a NaN in st(0) */
+#ifdef PARANOID
+    default:
+      EXCEPTION(EX_INTERNAL|0x0112);
+#endif /* PARANOID */
+    }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+static void f2xm1(FPU_REG *st0_ptr, u_char tag)
+{
+  FPU_REG a;
+
+  clear_C1();
+
+  if ( tag == TAG_Valid )
+    {
+      /* For an 80486 FPU, the result is undefined if the arg is >= 1.0 */
+      if ( exponent(st0_ptr) < 0 )
+       {
+       denormal_arg:
+
+         FPU_to_exp16(st0_ptr, &a);
+
+         /* poly_2xm1(x) requires 0 < st(0) < 1. */
+         poly_2xm1(getsign(st0_ptr), &a, st0_ptr);
+       }
+      set_precision_flag_up();   /* 80486 appears to always do this */
+      return;
+    }
+
+  if ( tag == TAG_Zero )
+    return;
+
+  if ( tag == TAG_Special )
+    tag = FPU_Special(st0_ptr);
+
+  switch ( tag )
+    {
+    case TW_Denormal:
+      if ( denormal_operand() < 0 )
+       return;
+      goto denormal_arg;
+    case TW_Infinity:
+      if ( signnegative(st0_ptr) )
+       {
+         /* -infinity gives -1 (p16-10) */
+         FPU_copy_to_reg0(&CONST_1, TAG_Valid);
+         setnegative(st0_ptr);
+       }
+      return;
+    default:
+      single_arg_error(st0_ptr, tag);
+    }
+}
+
+
+static void fptan(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  FPU_REG *st_new_ptr;
+  u32 q;
+  u_char arg_sign = getsign(st0_ptr);
+  int invert[] = { 0, 1, 1, 0, 0, 1, 1, 0 };
+
+  /* Stack underflow has higher priority */
+  if ( st0_tag == TAG_Empty )
+    {
+      FPU_stack_underflow();  /* Puts a QNaN in st(0) */
+      if ( control_word & CW_Invalid )
+       {
+         st_new_ptr = &st(-1);
+         push();
+         FPU_stack_underflow();  /* Puts a QNaN in the new st(0) */
+       }
+      return;
+    }
+
+  if ( STACK_OVERFLOW )
+    { FPU_stack_overflow(); return; }
+
+  if ( st0_tag == TAG_Valid )
+    {
+      if ( exponent(st0_ptr) > -40 )
+       {
+          if ( (q = trig_arg(st0_ptr, FPTAN)) == -1 )
+           {
+             /* Operand is out of range */
+             return;
+           }
+
+          poly_tan(st0_ptr, invert[q]);
+          setsign(st0_ptr, ((q & 2) != 0) ^ (arg_sign != 0));
+         set_precision_flag_up();  /* We do not really know if up or down */
+       }
+      else
+       {
+         /* For a small arg, the result == the argument */
+         /* Underflow may happen */
+
+       denormal_arg:
+
+         FPU_to_exp16(st0_ptr, st0_ptr);
+      
+         st0_tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign);
+         FPU_settag0(st0_tag);
+       }
+      push();
+      FPU_copy_to_reg0(&CONST_1, TAG_Valid);
+      return;
+    }
+
+  if ( st0_tag == TAG_Zero )
+    {
+      push();
+      FPU_copy_to_reg0(&CONST_1, TAG_Valid);
+      setcc(0);
+      return;
+    }
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+
+  if ( st0_tag == TW_Denormal )
+    {
+      if ( denormal_operand() < 0 )
+       return;
+
+      goto denormal_arg;
+    }
+
+  if ( st0_tag == TW_Infinity )
+    {
+      /* The 80486 treats infinity as an invalid operand */
+      if ( arith_invalid(0) >= 0 )
+       {
+         st_new_ptr = &st(-1);
+         push();
+         arith_invalid(0);
+       }
+      return;
+    }
+
+  single_arg_2_error(st0_ptr, st0_tag);
+}
+
+
+static void fxtract(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  FPU_REG *st_new_ptr;
+  u_char sign;
+  register FPU_REG *st1_ptr = st0_ptr;  /* anticipate */
+
+  if ( STACK_OVERFLOW )
+    {  FPU_stack_overflow(); return; }
+
+  clear_C1();
+
+  if ( st0_tag == TAG_Valid )
+    {
+      s32 e;
+
+      push();
+      sign = getsign(st1_ptr);
+      reg_copy(st1_ptr, st_new_ptr);
+      setexponent16(st_new_ptr, exponent(st_new_ptr));
+
+    denormal_arg:
+
+      e = exponent16(st_new_ptr);
+      convert_l2reg(&e, 1);
+      setexponentpos(st_new_ptr, 0);
+      setsign(st_new_ptr, sign);
+      FPU_settag0(TAG_Valid);       /* Needed if arg was a denormal */
+      return;
+    }
+  else if ( st0_tag == TAG_Zero )
+    {
+      sign = getsign(st0_ptr);
+
+      if ( FPU_divide_by_zero(0, SIGN_NEG) < 0 )
+       return;
+
+      push();
+      FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
+      setsign(st_new_ptr, sign);
+      return;
+    }
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+
+  if ( st0_tag == TW_Denormal )
+    {
+      if (denormal_operand() < 0 )
+       return;
+
+      push();
+      sign = getsign(st1_ptr);
+      FPU_to_exp16(st1_ptr, st_new_ptr);
+      goto denormal_arg;
+    }
+  else if ( st0_tag == TW_Infinity )
+    {
+      sign = getsign(st0_ptr);
+      setpositive(st0_ptr);
+      push();
+      FPU_copy_to_reg0(&CONST_INF, TAG_Special);
+      setsign(st_new_ptr, sign);
+      return;
+    }
+  else if ( st0_tag == TW_NaN )
+    {
+      if ( real_1op_NaN(st0_ptr) < 0 )
+       return;
+
+      push();
+      FPU_copy_to_reg0(st0_ptr, TAG_Special);
+      return;
+    }
+  else if ( st0_tag == TAG_Empty )
+    {
+      /* Is this the correct behaviour? */
+      if ( control_word & EX_Invalid )
+       {
+         FPU_stack_underflow();
+         push();
+         FPU_stack_underflow();
+       }
+      else
+       EXCEPTION(EX_StackUnder);
+    }
+#ifdef PARANOID
+  else
+    EXCEPTION(EX_INTERNAL | 0x119);
+#endif /* PARANOID */
+}
+
+
+static void fdecstp(void)
+{
+  clear_C1();
+  top--;
+}
+
+static void fincstp(void)
+{
+  clear_C1();
+  top++;
+}
+
+
+static void fsqrt_(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  int expon;
+
+  clear_C1();
+
+  if ( st0_tag == TAG_Valid )
+    {
+      u_char tag;
+      
+      if (signnegative(st0_ptr))
+       {
+         arith_invalid(0);  /* sqrt(negative) is invalid */
+         return;
+       }
+
+      /* make st(0) in  [1.0 .. 4.0) */
+      expon = exponent(st0_ptr);
+
+    denormal_arg:
+
+      setexponent16(st0_ptr, (expon & 1));
+
+      /* Do the computation, the sign of the result will be positive. */
+      tag = wm_sqrt(st0_ptr, 0, 0, control_word, SIGN_POS);
+      addexponent(st0_ptr, expon >> 1);
+      FPU_settag0(tag);
+      return;
+    }
+
+  if ( st0_tag == TAG_Zero )
+    return;
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+
+  if ( st0_tag == TW_Infinity )
+    {
+      if ( signnegative(st0_ptr) )
+       arith_invalid(0);  /* sqrt(-Infinity) is invalid */
+      return;
+    }
+  else if ( st0_tag == TW_Denormal )
+    {
+      if (signnegative(st0_ptr))
+       {
+         arith_invalid(0);  /* sqrt(negative) is invalid */
+         return;
+       }
+
+      if ( denormal_operand() < 0 )
+       return;
+
+      FPU_to_exp16(st0_ptr, st0_ptr);
+
+      expon = exponent16(st0_ptr);
+
+      goto denormal_arg;
+    }
+
+  single_arg_error(st0_ptr, st0_tag);
+
+}
+
+
+static void frndint_(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  int flags, tag;
+
+  if ( st0_tag == TAG_Valid )
+    {
+      u_char sign;
+
+    denormal_arg:
+
+      sign = getsign(st0_ptr);
+
+      if (exponent(st0_ptr) > 63)
+       return;
+
+      if ( st0_tag == TW_Denormal )
+       {
+         if (denormal_operand() < 0 )
+           return;
+       }
+
+      /* Fortunately, this can't overflow to 2^64 */
+      if ( (flags = FPU_round_to_int(st0_ptr, st0_tag)) )
+       set_precision_flag(flags);
+
+      setexponent16(st0_ptr, 63);
+      tag = FPU_normalize_nuo(st0_ptr,
+                             EXTENDED_Ebias);  /* No underflow or overflow
+                                                  is possible */
+      setsign(st0_ptr, sign);
+      FPU_settag0(tag);
+      return;
+    }
+
+  if ( st0_tag == TAG_Zero )
+    return;
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+
+  if ( st0_tag == TW_Denormal )
+    goto denormal_arg;
+  else if ( st0_tag == TW_Infinity )
+    return;
+  else
+    single_arg_error(st0_ptr, st0_tag);
+}
+
+
+static int fsin(FPU_REG *st0_ptr, u_char tag)
+{
+  u_char arg_sign = getsign(st0_ptr);
+
+  if ( tag == TAG_Valid )
+    {
+      u32 q;
+
+      if ( exponent(st0_ptr) > -40 )
+       {
+         if ( (q = trig_arg(st0_ptr, 0)) == -1 )
+           {
+             /* Operand is out of range */
+             return 1;
+           }
+
+         poly_sine(st0_ptr);
+         
+         if (q & 2)
+           changesign(st0_ptr);
+
+         setsign(st0_ptr, getsign(st0_ptr) ^ arg_sign);
+
+         /* We do not really know if up or down */
+         set_precision_flag_up();
+         return 0;
+       }
+      else
+       {
+         /* For a small arg, the result == the argument */
+         set_precision_flag_up();  /* Must be up. */
+         return 0;
+       }
+    }
+
+  if ( tag == TAG_Zero )
+    {
+      setcc(0);
+      return 0;
+    }
+
+  if ( tag == TAG_Special )
+    tag = FPU_Special(st0_ptr);
+
+  if ( tag == TW_Denormal )
+    {
+      if ( denormal_operand() < 0 )
+       return 1;
+
+      /* For a small arg, the result == the argument */
+      /* Underflow may happen */
+      FPU_to_exp16(st0_ptr, st0_ptr);
+      
+      tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign);
+
+      FPU_settag0(tag);
+
+      return 0;
+    }
+  else if ( tag == TW_Infinity )
+    {
+      /* The 80486 treats infinity as an invalid operand */
+      arith_invalid(0);
+      return 1;
+    }
+  else
+    {
+      single_arg_error(st0_ptr, tag);
+      return 1;
+    }
+}
+
+
+static int f_cos(FPU_REG *st0_ptr, u_char tag)
+{
+  u_char st0_sign;
+
+  st0_sign = getsign(st0_ptr);
+
+  if ( tag == TAG_Valid )
+    {
+      u32 q;
+
+      if ( exponent(st0_ptr) > -40 )
+       {
+         if ( (exponent(st0_ptr) < 0)
+             || ((exponent(st0_ptr) == 0)
+                 && (significand(st0_ptr) <= BX_CONST64(0xc90fdaa22168c234))) )
+           {
+             poly_cos(st0_ptr);
+
+             /* We do not really know if up or down */
+             set_precision_flag_down();
+         
+             return 0;
+           }
+         else if ( (q = trig_arg(st0_ptr, FCOS)) != -1 )
+           {
+             poly_sine(st0_ptr);
+
+             if ((q+1) & 2)
+               changesign(st0_ptr);
+
+             /* We do not really know if up or down */
+             set_precision_flag_down();
+         
+             return 0;
+           }
+         else
+           {
+             /* Operand is out of range */
+             return 1;
+           }
+       }
+      else
+       {
+       denormal_arg:
+
+         setcc(0);
+         FPU_copy_to_reg0(&CONST_1, TAG_Valid);
+#ifdef PECULIAR_486
+         set_precision_flag_down();  /* 80486 appears to do this. */
+#else
+         set_precision_flag_up();  /* Must be up. */
+#endif /* PECULIAR_486 */
+         return 0;
+       }
+    }
+  else if ( tag == TAG_Zero )
+    {
+      FPU_copy_to_reg0(&CONST_1, TAG_Valid);
+      setcc(0);
+      return 0;
+    }
+
+  if ( tag == TAG_Special )
+    tag = FPU_Special(st0_ptr);
+
+  if ( tag == TW_Denormal )
+    {
+      if ( denormal_operand() < 0 )
+       return 1;
+
+      goto denormal_arg;
+    }
+  else if ( tag == TW_Infinity )
+    {
+      /* The 80486 treats infinity as an invalid operand */
+      arith_invalid(0);
+      return 1;
+    }
+  else
+    {
+      single_arg_error(st0_ptr, tag);  /* requires st0_ptr == &st(0) */
+      return 1;
+    }
+}
+
+
+static void fcos(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  f_cos(st0_ptr, st0_tag);
+}
+
+
+static void fsincos(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  FPU_REG *st_new_ptr;
+  FPU_REG arg;
+  u_char tag;
+
+  /* Stack underflow has higher priority */
+  if ( st0_tag == TAG_Empty )
+    {
+      FPU_stack_underflow();  /* Puts a QNaN in st(0) */
+      if ( control_word & CW_Invalid )
+       {
+         st_new_ptr = &st(-1);
+         push();
+         FPU_stack_underflow();  /* Puts a QNaN in the new st(0) */
+       }
+      return;
+    }
+
+  if ( STACK_OVERFLOW )
+    { FPU_stack_overflow(); return; }
+
+  if ( st0_tag == TAG_Special )
+    tag = FPU_Special(st0_ptr);
+  else
+    tag = st0_tag;
+
+  if ( tag == TW_NaN )
+    {
+      single_arg_2_error(st0_ptr, TW_NaN);
+      return;
+    }
+  else if ( tag == TW_Infinity )
+    {
+      /* The 80486 treats infinity as an invalid operand */
+      if ( arith_invalid(0) >= 0 )
+       {
+         /* Masked response */
+         push();
+         arith_invalid(0);
+       }
+      return;
+    }
+
+  reg_copy(st0_ptr, &arg);
+  if ( !fsin(st0_ptr, st0_tag) )
+    {
+      push();
+      FPU_copy_to_reg0(&arg, st0_tag);
+      f_cos(&st(0), st0_tag);
+    }
+  else
+    {
+      /* An error, so restore st(0) */
+      FPU_copy_to_reg0(&arg, st0_tag);
+    }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* The following all require two arguments: st(0) and st(1) */
+
+/* A lean, mean kernel for the fprem instructions. This relies upon
+   the division and rounding to an integer in do_fprem giving an
+   exact result. Because of this, rem_kernel() needs to deal only with
+   the least significant 64 bits, the more significant bits of the
+   result must be zero.
+ */
+static void rem_kernel(u64 st0, u64 *y, u64 st1, u64 q, int n)
+{
+  u64 x;
+
+#ifdef NO_ASSEMBLER
+  u64 work;
+
+  x = st0 << n;
+
+  work = (u32)st1;
+  work *= (u32)q;
+  x -= work;
+
+  work = st1 >> 32;
+  work *= (u32)q;
+  x -= work;
+
+  work = (u32)st1;
+  work *= q >> 32;
+  x -= work;
+  
+#else
+  int dummy;
+
+  x = st0 << n;
+
+  /* Do the required multiplication and subtraction in the one operation */
+
+  /* lsw x -= lsw st1 * lsw q */
+  asm volatile ("mull %4; subl %%eax,%0; sbbl %%edx,%1"
+               :"=m" (((u32 *)&x)[0]), "=m" (((u32 *)&x)[1]),
+               "=a" (dummy)
+               :"2" (((u32 *)&st1)[0]), "m" (((u32 *)&q)[0])
+               :"%dx");
+  /* msw x -= msw st1 * lsw q */
+  asm volatile ("mull %3; subl %%eax,%0"
+               :"=m" (((u32 *)&x)[1]), "=a" (dummy)
+               :"1" (((u32 *)&st1)[1]), "m" (((u32 *)&q)[0])
+               :"%dx");
+  /* msw x -= lsw st1 * msw q */
+  asm volatile ("mull %3; subl %%eax,%0"
+               :"=m" (((u32 *)&x)[1]), "=a" (dummy)
+               :"1" (((u32 *)&st1)[0]), "m" (((u32 *)&q)[1])
+               :"%dx");
+#endif
+
+  *y = x;
+}
+
+
+/* Remainder of st(0) / st(1) */
+/* This routine produces exact results, i.e. there is never any
+   rounding or truncation, etc of the result. */
+static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
+{
+  FPU_REG *st1_ptr = &st(1);
+  u_char st1_tag = FPU_gettagi(1);
+
+  if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
+    {
+      FPU_REG tmp, st0, st1;
+      u_char st0_sign, st1_sign;
+      u_char tmptag;
+      int tag;
+      int old_cw;
+      int expdif;
+      s64 q;
+      u16 saved_status;
+      int cc;
+
+    fprem_valid:
+      /* Convert registers for internal use. */
+      st0_sign = FPU_to_exp16(st0_ptr, &st0);
+      st1_sign = FPU_to_exp16(st1_ptr, &st1);
+      expdif = exponent16(&st0) - exponent16(&st1);
+
+      old_cw = control_word;
+      cc = 0;
+
+      /* We want the status following the denorm tests, but don't want
+        the status changed by the arithmetic operations. */
+      saved_status = partial_status;
+      control_word &= ~CW_RC;
+      control_word |= RC_CHOP;
+
+      if ( expdif < 64 )
+       {
+         /* This should be the most common case */
+
+         if ( expdif > -2 )
+           {
+             u_char sign = st0_sign ^ st1_sign;
+             tag = FPU_u_div(&st0, &st1, &tmp,
+                             PR_64_BITS | RC_CHOP | 0x3f,
+                             sign);
+             setsign(&tmp, sign);
+
+             if ( exponent(&tmp) >= 0 )
+               {
+                 FPU_round_to_int(&tmp, tag);  /* Fortunately, this can't
+                                                  overflow to 2^64 */
+                 q = significand(&tmp);
+
+                 rem_kernel(significand(&st0),
+                            &significand(&tmp),
+                            significand(&st1),
+                            q, expdif);
+
+                 setexponent16(&tmp, exponent16(&st1));
+               }
+             else
+               {
+                 reg_copy(&st0, &tmp);
+                 q = 0;
+               }
+
+             if ( (round == RC_RND) && (tmp.sigh & 0xc0000000) )
+               {
+                 /* We may need to subtract st(1) once more,
+                    to get a result <= 1/2 of st(1). */
+                 u64 x;
+                 expdif = exponent16(&st1) - exponent16(&tmp);
+                 if ( expdif <= 1 )
+                   {
+                     if ( expdif == 0 )
+                       x = significand(&st1) - significand(&tmp);
+                     else /* expdif is 1 */
+                       x = (significand(&st1) << 1) - significand(&tmp);
+                     if ( (x < significand(&tmp)) ||
+                         /* or equi-distant (from 0 & st(1)) and q is odd */
+                         ((x == significand(&tmp)) && (q & 1) ) )
+                       {
+                         st0_sign = ! st0_sign;
+                         significand(&tmp) = x;
+                         q++;
+                       }
+                   }
+               }
+
+             if (q & 4) cc |= SW_C0;
+             if (q & 2) cc |= SW_C3;
+             if (q & 1) cc |= SW_C1;
+           }
+         else
+           {
+             control_word = old_cw;
+             setcc(0);
+             return;
+           }
+       }
+      else
+       {
+         /* There is a large exponent difference ( >= 64 ) */
+         /* To make much sense, the code in this section should
+            be done at high precision. */
+         int exp_1, N;
+         u_char sign;
+
+         /* prevent overflow here */
+         /* N is 'a number between 32 and 63' (p26-113) */
+         reg_copy(&st0, &tmp);
+         tmptag = st0_tag;
+         N = (expdif & 0x0000001f) + 32;  /* This choice gives results
+                                             identical to an AMD 486 */
+         setexponent16(&tmp, N);
+         exp_1 = exponent16(&st1);
+         setexponent16(&st1, 0);
+         expdif -= N;
+
+         sign = getsign(&tmp) ^ st1_sign;
+         tag = FPU_u_div(&tmp, &st1, &tmp, PR_64_BITS | RC_CHOP | 0x3f,
+                         sign);
+         setsign(&tmp, sign);
+
+         FPU_round_to_int(&tmp, tag);  /* Fortunately, this can't
+                                          overflow to 2^64 */
+
+         rem_kernel(significand(&st0),
+                    &significand(&tmp),
+                    significand(&st1),
+                    significand(&tmp),
+                    exponent(&tmp)
+                    ); 
+         setexponent16(&tmp, exp_1 + expdif);
+
+         /* It is possible for the operation to be complete here.
+            What does the IEEE standard say? The Intel 80486 manual
+            implies that the operation will never be completed at this
+            point, and the behaviour of a real 80486 confirms this.
+          */
+         if ( !(tmp.sigh | tmp.sigl) )
+           {
+             /* The result is zero */
+             control_word = old_cw;
+             partial_status = saved_status;
+             FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
+             setsign(&st0, st0_sign);
+#ifdef PECULIAR_486
+             setcc(SW_C2);
+#else
+             setcc(0);
+#endif /* PECULIAR_486 */
+             return;
+           }
+         cc = SW_C2;
+       }
+
+      control_word = old_cw;
+      partial_status = saved_status;
+      tag = FPU_normalize_nuo(&tmp, 0);
+      reg_copy(&tmp, st0_ptr);
+
+      /* The only condition to be looked for is underflow,
+        and it can occur here only if underflow is unmasked. */
+      if ( (exponent16(&tmp) <= EXP_UNDER) && (tag != TAG_Zero)
+         && !(control_word & CW_Underflow) )
+       {
+         setcc(cc);
+         tag = arith_underflow(st0_ptr);
+         setsign(st0_ptr, st0_sign);
+         FPU_settag0(tag);
+         return;
+       }
+      else if ( (exponent16(&tmp) > EXP_UNDER) || (tag == TAG_Zero) )
+       {
+         stdexp(st0_ptr);
+         setsign(st0_ptr, st0_sign);
+       }
+      else
+       {
+         tag = FPU_round(st0_ptr, 0, 0, FULL_PRECISION, st0_sign);
+       }
+      FPU_settag0(tag);
+      setcc(cc);
+
+      return;
+    }
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+  if ( st1_tag == TAG_Special )
+    st1_tag = FPU_Special(st1_ptr);
+
+  if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
+           || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
+           || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )
+    {
+      if ( denormal_operand() < 0 )
+       return;
+      goto fprem_valid;
+    }
+  else if ( (st0_tag == TAG_Empty) | (st1_tag == TAG_Empty) )
+    {
+      FPU_stack_underflow();
+      return;
+    }
+  else if ( st0_tag == TAG_Zero )
+    {
+      if ( st1_tag == TAG_Valid )
+       {
+         setcc(0); return;
+       }
+      else if ( st1_tag == TW_Denormal )
+       {
+         if ( denormal_operand() < 0 )
+           return;
+         setcc(0); return;
+       }
+      else if ( st1_tag == TAG_Zero )
+       { arith_invalid(0); return; } /* fprem(?,0) always invalid */
+      else if ( st1_tag == TW_Infinity )
+       { setcc(0); return; }
+    }
+  else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
+    {
+      if ( st1_tag == TAG_Zero )
+       {
+         arith_invalid(0); /* fprem(Valid,Zero) is invalid */
+         return;
+       }
+      else if ( st1_tag != TW_NaN )
+       {
+         if ( ((st0_tag == TW_Denormal) || (st1_tag == TW_Denormal))
+              && (denormal_operand() < 0) )
+           return;
+
+         if ( st1_tag == TW_Infinity )
+           {
+             /* fprem(Valid,Infinity) is o.k. */
+             setcc(0); return;
+           }
+       }
+    }
+  else if ( st0_tag == TW_Infinity )
+    {
+      if ( st1_tag != TW_NaN )
+       {
+         arith_invalid(0); /* fprem(Infinity,?) is invalid */
+         return;
+       }
+    }
+
+  /* One of the registers must contain a NaN if we got here. */
+
+#ifdef PARANOID
+  if ( (st0_tag != TW_NaN) && (st1_tag != TW_NaN) )
+      EXCEPTION(EX_INTERNAL | 0x118);
+#endif /* PARANOID */
+
+  real_2op_NaN(st1_ptr, st1_tag, 0, st1_ptr);
+
+}
+
+
+/* ST(1) <- ST(1) * log ST;  pop ST */
+static void fyl2x(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  FPU_REG *st1_ptr = &st(1), exponent;
+  u_char st1_tag = FPU_gettagi(1);
+  u_char sign;
+  int e, tag;
+
+  clear_C1();
+
+  if ( (st0_tag == TAG_Valid) && (st1_tag == TAG_Valid) )
+    {
+    both_valid:
+      /* Both regs are Valid or Denormal */
+      if ( signpositive(st0_ptr) )
+       {
+         if ( st0_tag == TW_Denormal )
+           FPU_to_exp16(st0_ptr, st0_ptr);
+         else
+           /* Convert st(0) for internal use. */
+           setexponent16(st0_ptr, exponent(st0_ptr));
+
+         if ( (st0_ptr->sigh == 0x80000000) && (st0_ptr->sigl == 0) )
+           {
+             /* Special case. The result can be precise. */
+             u_char esign;
+             e = exponent16(st0_ptr);
+             if ( e >= 0 )
+               {
+                 exponent.sigh = e;
+                 esign = SIGN_POS;
+               }
+             else
+               {
+                 exponent.sigh = -e;
+                 esign = SIGN_NEG;
+               }
+             exponent.sigl = 0;
+             setexponent16(&exponent, 31);
+              tag = FPU_normalize_nuo(&exponent, 0);
+             stdexp(&exponent);
+             setsign(&exponent, esign);
+             tag = FPU_mul(&exponent, tag, 1, FULL_PRECISION);
+             if ( tag >= 0 )
+               FPU_settagi(1, tag);
+           }
+         else
+           {
+             /* The usual case */
+             sign = getsign(st1_ptr);
+             if ( st1_tag == TW_Denormal )
+               FPU_to_exp16(st1_ptr, st1_ptr);
+             else
+               /* Convert st(1) for internal use. */
+               setexponent16(st1_ptr, exponent(st1_ptr));
+             poly_l2(st0_ptr, st1_ptr, sign);
+           }
+       }
+      else
+       {
+         /* negative */
+         if ( arith_invalid(1) < 0 )
+           return;
+       }
+
+      FPU_pop();
+
+      return;
+    }
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+  if ( st1_tag == TAG_Special )
+    st1_tag = FPU_Special(st1_ptr);
+
+  if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) )
+    {
+      FPU_stack_underflow_pop(1);
+      return;
+    }
+  else if ( (st0_tag <= TW_Denormal) && (st1_tag <= TW_Denormal) )
+    {
+      if ( st0_tag == TAG_Zero )
+       {
+         if ( st1_tag == TAG_Zero )
+           {
+             /* Both args zero is invalid */
+             if ( arith_invalid(1) < 0 )
+               return;
+           }
+         else
+           {
+             u_char sign;
+             sign = getsign(st1_ptr)^SIGN_NEG;
+             if ( FPU_divide_by_zero(1, sign) < 0 )
+               return;
+
+             setsign(st1_ptr, sign);
+           }
+       }
+      else if ( st1_tag == TAG_Zero )
+       {
+         /* st(1) contains zero, st(0) valid <> 0 */
+         /* Zero is the valid answer */
+         sign = getsign(st1_ptr);
+         
+         if ( signnegative(st0_ptr) )
+           {
+             /* log(negative) */
+             if ( arith_invalid(1) < 0 )
+               return;
+           }
+         else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+           return;
+         else
+           {
+             if ( exponent(st0_ptr) < 0 )
+               sign ^= SIGN_NEG;
+
+             FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
+             setsign(st1_ptr, sign);
+           }
+       }
+      else
+       {
+         /* One or both operands are denormals. */
+         if ( denormal_operand() < 0 )
+           return;
+         goto both_valid;
+       }
+    }
+  else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )
+    {
+      if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
+       return;
+    }
+  /* One or both arg must be an infinity */
+  else if ( st0_tag == TW_Infinity )
+    {
+      if ( (signnegative(st0_ptr)) || (st1_tag == TAG_Zero) )
+       {
+         /* log(-infinity) or 0*log(infinity) */
+         if ( arith_invalid(1) < 0 )
+           return;
+       }
+      else
+       {
+         u_char sign = getsign(st1_ptr);
+
+         if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
+           return;
+
+         FPU_copy_to_reg1(&CONST_INF, TAG_Special);
+         setsign(st1_ptr, sign);
+       }
+    }
+  /* st(1) must be infinity here */
+  else if ( ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal))
+           && ( signpositive(st0_ptr) ) )
+    {
+      if ( exponent(st0_ptr) >= 0 )
+       {
+         if ( (exponent(st0_ptr) == 0) &&
+             (st0_ptr->sigh == 0x80000000) &&
+             (st0_ptr->sigl == 0) )
+           {
+             /* st(0) holds 1.0 */
+             /* infinity*log(1) */
+             if ( arith_invalid(1) < 0 )
+               return;
+           }
+         /* else st(0) is positive and > 1.0 */
+       }
+      else
+       {
+         /* st(0) is positive and < 1.0 */
+
+         if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+           return;
+
+         changesign(st1_ptr);
+       }
+    }
+  else
+    {
+      /* st(0) must be zero or negative */
+      if ( st0_tag == TAG_Zero )
+       {
+         /* This should be invalid, but a real 80486 is happy with it. */
+
+#ifndef PECULIAR_486
+         sign = getsign(st1_ptr);
+         if ( FPU_divide_by_zero(1, sign) < 0 )
+           return;
+#endif /* PECULIAR_486 */
+
+         changesign(st1_ptr);
+       }
+      else if ( arith_invalid(1) < 0 )   /* log(negative) */
+       return;
+    }
+
+  FPU_pop();
+}
+
+
+static void fpatan(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  FPU_REG *st1_ptr = &st(1);
+  u_char st1_tag = FPU_gettagi(1);
+  int tag;
+
+  clear_C1();
+  if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
+    {
+    valid_atan:
+
+      poly_atan(st0_ptr, st0_tag, st1_ptr, st1_tag);
+
+      FPU_pop();
+
+      return;
+    }
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+  if ( st1_tag == TAG_Special )
+    st1_tag = FPU_Special(st1_ptr);
+
+  if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
+           || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
+           || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )
+    {
+      if ( denormal_operand() < 0 )
+       return;
+
+      goto valid_atan;
+    }
+  else if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) )
+    {
+      FPU_stack_underflow_pop(1);
+      return;
+    }
+  else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )
+    {
+      if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) >= 0 )
+         FPU_pop();
+      return;
+    }
+  else if ( (st0_tag == TW_Infinity) || (st1_tag == TW_Infinity) )
+    {
+      u_char sign = getsign(st1_ptr);
+      if ( st0_tag == TW_Infinity )
+       {
+         if ( st1_tag == TW_Infinity )
+           {
+             if ( signpositive(st0_ptr) )
+               {
+                 FPU_copy_to_reg1(&CONST_PI4, TAG_Valid);
+               }
+             else
+               {
+                 setpositive(st1_ptr);
+                 tag = FPU_u_add(&CONST_PI4, &CONST_PI2, st1_ptr,
+                                 FULL_PRECISION, SIGN_POS,
+                                 exponent(&CONST_PI4), exponent(&CONST_PI2));
+                 if ( tag >= 0 )
+                   FPU_settagi(1, tag);
+               }
+           }
+         else
+           {
+             if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
+               return;
+
+             if ( signpositive(st0_ptr) )
+               {
+                 FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
+                 setsign(st1_ptr, sign);   /* An 80486 preserves the sign */
+                 FPU_pop();
+                 return;
+               }
+             else
+               {
+                 FPU_copy_to_reg1(&CONST_PI, TAG_Valid);
+               }
+           }
+       }
+      else
+       {
+         /* st(1) is infinity, st(0) not infinity */
+         if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+           return;
+
+         FPU_copy_to_reg1(&CONST_PI2, TAG_Valid);
+       }
+      setsign(st1_ptr, sign);
+    }
+  else if ( st1_tag == TAG_Zero )
+    {
+      /* st(0) must be valid or zero */
+      u_char sign = getsign(st1_ptr);
+
+      if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+       return;
+
+      if ( signpositive(st0_ptr) )
+       {
+         /* An 80486 preserves the sign */
+         FPU_pop();
+         return;
+       }
+
+      FPU_copy_to_reg1(&CONST_PI, TAG_Valid);
+      setsign(st1_ptr, sign);
+    }
+  else if ( st0_tag == TAG_Zero )
+    {
+      /* st(1) must be TAG_Valid here */
+      u_char sign = getsign(st1_ptr);
+
+      if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
+       return;
+
+      FPU_copy_to_reg1(&CONST_PI2, TAG_Valid);
+      setsign(st1_ptr, sign);
+    }
+#ifdef PARANOID
+  else
+    EXCEPTION(EX_INTERNAL | 0x125);
+#endif /* PARANOID */
+
+  FPU_pop();
+  set_precision_flag_up();  /* We do not really know if up or down */
+}
+
+
+static void fprem(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  do_fprem(st0_ptr, st0_tag, RC_CHOP);
+}
+
+
+static void fprem1(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  do_fprem(st0_ptr, st0_tag, RC_RND);
+}
+
+
+static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  u_char sign, sign1;
+  FPU_REG *st1_ptr = &st(1), a, b;
+  u_char st1_tag = FPU_gettagi(1);
+
+  clear_C1();
+  if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
+    {
+    valid_yl2xp1:
+
+      sign = getsign(st0_ptr);
+      sign1 = getsign(st1_ptr);
+
+      FPU_to_exp16(st0_ptr, &a);
+      FPU_to_exp16(st1_ptr, &b);
+
+      if ( poly_l2p1(sign, sign1, &a, &b, st1_ptr) )
+       return;
+
+      FPU_pop();
+      return;
+    }
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+  if ( st1_tag == TAG_Special )
+    st1_tag = FPU_Special(st1_ptr);
+
+  if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
+           || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
+           || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )
+    {
+      if ( denormal_operand() < 0 )
+       return;
+
+      goto valid_yl2xp1;
+    }
+  else if ( (st0_tag == TAG_Empty) | (st1_tag == TAG_Empty) )
+    {
+      FPU_stack_underflow_pop(1);
+      return;
+    }
+  else if ( st0_tag == TAG_Zero )
+    {
+      switch ( st1_tag )
+       {
+       case TW_Denormal:
+         if ( denormal_operand() < 0 )
+           return;
+
+       case TAG_Zero:
+       case TAG_Valid:
+         setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr));
+         FPU_copy_to_reg1(st0_ptr, st0_tag);
+         break;
+
+       case TW_Infinity:
+         /* Infinity*log(1) */
+         if ( arith_invalid(1) < 0 )
+           return;
+         break;
+
+       case TW_NaN:
+         if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
+           return;
+         break;
+
+       default:
+#ifdef PARANOID
+         EXCEPTION(EX_INTERNAL | 0x116);
+         return;
+#endif /* PARANOID */
+       }
+    }
+  else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
+    {
+      switch ( st1_tag )
+       {
+       case TAG_Zero:
+         if ( signnegative(st0_ptr) )
+           {
+             if ( exponent(st0_ptr) >= 0 )
+               {
+                 /* st(0) holds <= -1.0 */
+#ifdef PECULIAR_486   /* Stupid 80486 doesn't worry about log(negative). */
+                 changesign(st1_ptr);
+#else
+                 if ( arith_invalid(1) < 0 )
+                   return;
+#endif /* PECULIAR_486 */
+               }
+             else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+               return;
+             else
+               changesign(st1_ptr);
+           }
+         else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+           return;
+         break;
+
+       case TW_Infinity:
+         if ( signnegative(st0_ptr) )
+           {
+             if ( (exponent(st0_ptr) >= 0) &&
+                 !((st0_ptr->sigh == 0x80000000) &&
+                   (st0_ptr->sigl == 0)) )
+               {
+                 /* st(0) holds < -1.0 */
+#ifdef PECULIAR_486   /* Stupid 80486 doesn't worry about log(negative). */
+                 changesign(st1_ptr);
+#else
+                 if ( arith_invalid(1) < 0 ) return;
+#endif /* PECULIAR_486 */
+               }
+             else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+               return;
+             else
+               changesign(st1_ptr);
+           }
+         else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+           return;
+         break;
+
+       case TW_NaN:
+         if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
+           return;
+       }
+
+    }
+  else if ( st0_tag == TW_NaN )
+    {
+      if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
+       return;
+    }
+  else if ( st0_tag == TW_Infinity )
+    {
+      if ( st1_tag == TW_NaN )
+       {
+         if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
+           return;
+       }
+      else if ( signnegative(st0_ptr) )
+       {
+#ifndef PECULIAR_486
+         /* This should have higher priority than denormals, but... */
+         if ( arith_invalid(1) < 0 )  /* log(-infinity) */
+           return;
+#endif /* PECULIAR_486 */
+         if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
+           return;
+#ifdef PECULIAR_486
+         /* Denormal operands actually get higher priority */
+         if ( arith_invalid(1) < 0 )  /* log(-infinity) */
+           return;
+#endif /* PECULIAR_486 */
+       }
+      else if ( st1_tag == TAG_Zero )
+       {
+         /* log(infinity) */
+         if ( arith_invalid(1) < 0 )
+           return;
+       }
+       
+      /* st(1) must be valid here. */
+
+      else if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
+       return;
+
+      /* The Manual says that log(Infinity) is invalid, but a real
+        80486 sensibly says that it is o.k. */
+      else
+       {
+         u_char sign = getsign(st1_ptr);
+         FPU_copy_to_reg1(&CONST_INF, TAG_Special);
+         setsign(st1_ptr, sign);
+       }
+    }
+#ifdef PARANOID
+  else
+    {
+      EXCEPTION(EX_INTERNAL | 0x117);
+      return;
+    }
+#endif /* PARANOID */
+
+  FPU_pop();
+  return;
+
+}
+
+
+static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
+{
+  FPU_REG *st1_ptr = &st(1);
+  u_char st1_tag = FPU_gettagi(1);
+  int old_cw = control_word;
+  u_char sign = getsign(st0_ptr);
+
+  clear_C1();
+  if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
+    {
+      s32 scale;
+      FPU_REG tmp;
+
+      /* Convert register for internal use. */
+      setexponent16(st0_ptr, exponent(st0_ptr));
+
+    valid_scale:
+
+      if ( exponent(st1_ptr) > 30 )
+       {
+         /* 2^31 is far too large, would require 2^(2^30) or 2^(-2^30) */
+
+         if ( signpositive(st1_ptr) )
+           {
+             EXCEPTION(EX_Overflow);
+             FPU_copy_to_reg0(&CONST_INF, TAG_Special);
+           }
+         else
+           {
+             EXCEPTION(EX_Underflow);
+             FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
+           }
+         setsign(st0_ptr, sign);
+         return;
+       }
+
+      control_word &= ~CW_RC;
+      control_word |= RC_CHOP;
+      reg_copy(st1_ptr, &tmp);
+      FPU_round_to_int(&tmp, st1_tag);      /* This can never overflow here */
+      control_word = old_cw;
+      scale = signnegative(st1_ptr) ? -tmp.sigl : tmp.sigl;
+      scale += exponent16(st0_ptr);
+
+      setexponent16(st0_ptr, scale);
+
+      /* Use FPU_round() to properly detect under/overflow etc */
+      FPU_round(st0_ptr, 0, 0, control_word, sign);
+
+      return;
+    }
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+  if ( st1_tag == TAG_Special )
+    st1_tag = FPU_Special(st1_ptr);
+
+  if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
+    {
+      switch ( st1_tag )
+       {
+       case TAG_Valid:
+         /* st(0) must be a denormal */
+         if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+           return;
+
+         FPU_to_exp16(st0_ptr, st0_ptr);  /* Will not be left on stack */
+         goto valid_scale;
+
+       case TAG_Zero:
+         if ( st0_tag == TW_Denormal )
+           denormal_operand();
+         return;
+
+       case TW_Denormal:
+         denormal_operand();
+         return;
+
+       case TW_Infinity:
+         if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+           return;
+
+         if ( signpositive(st1_ptr) )
+           FPU_copy_to_reg0(&CONST_INF, TAG_Special);
+         else
+           FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
+         setsign(st0_ptr, sign);
+         return;
+
+       case TW_NaN:
+         real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
+         return;
+       }
+    }
+  else if ( st0_tag == TAG_Zero )
+    {
+      switch ( st1_tag )
+       {
+       case TAG_Valid:
+       case TAG_Zero:
+         return;
+
+       case TW_Denormal:
+         denormal_operand();
+         return;
+
+       case TW_Infinity:
+         if ( signpositive(st1_ptr) )
+           arith_invalid(0); /* Zero scaled by +Infinity */
+         return;
+
+       case TW_NaN:
+         real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
+         return;
+       }
+    }
+  else if ( st0_tag == TW_Infinity )
+    {
+      switch ( st1_tag )
+       {
+       case TAG_Valid:
+       case TAG_Zero:
+         return;
+
+       case TW_Denormal:
+         denormal_operand();
+         return;
+
+       case TW_Infinity:
+         if ( signnegative(st1_ptr) )
+           arith_invalid(0); /* Infinity scaled by -Infinity */
+         return;
+
+       case TW_NaN:
+         real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
+         return;
+       }
+    }
+  else if ( st0_tag == TW_NaN )
+    {
+      if ( st1_tag != TAG_Empty )
+       { real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); return; }
+    }
+
+#ifdef PARANOID
+  if ( !((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) )
+    {
+      EXCEPTION(EX_INTERNAL | 0x115);
+      return;
+    }
+#endif
+
+  /* At least one of st(0), st(1) must be empty */
+  FPU_stack_underflow();
+
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+static FUNC_ST0 const trig_table_a[] = {
+  f2xm1, fyl2x, fptan, fpatan,
+  fxtract, fprem1, (FUNC_ST0)fdecstp, (FUNC_ST0)fincstp
+};
+
+void FPU_triga(void)
+{
+  (trig_table_a[FPU_rm])(&st(0), FPU_gettag0());
+}
+
+
+static FUNC_ST0 const trig_table_b[] =
+  {
+    fprem, fyl2xp1, fsqrt_, fsincos, frndint_, fscale, (FUNC_ST0)fsin, fcos
+  };
+
+void FPU_trigb(void)
+{
+  (trig_table_b[FPU_rm])(&st(0), FPU_gettag0());
+}
diff --git a/sid/component/bochs/cpu/fpu/get_address.c b/sid/component/bochs/cpu/fpu/get_address.c
new file mode 100644 (file)
index 0000000..e54c0cc
--- /dev/null
@@ -0,0 +1,445 @@
+/*---------------------------------------------------------------------------+
+ |  get_address.c                                                            |
+ |                                                                           |
+ | Get the effective address from an FPU instruction.                        |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail   billm@suburbia.net             |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | Note:                                                                     |
+ |    The file contains code which accesses user memory.                     |
+ |    Emulator static data may change when user memory is accessed, due to   |
+ |    other processes using the emulator while swapping is in progress.      |
+ +---------------------------------------------------------------------------*/
+
+
+#include <linux/stddef.h>
+
+#include <asm/uaccess.h>
+#include <asm/desc.h>
+
+#include "fpu_system.h"
+#include "exception.h"
+#include "fpu_emu.h"
+
+
+#define FPU_WRITE_BIT 0x10
+
+static int reg_offset[] = {
+       offsetof(struct info,___eax),
+       offsetof(struct info,___ecx),
+       offsetof(struct info,___edx),
+       offsetof(struct info,___ebx),
+       offsetof(struct info,___esp),
+       offsetof(struct info,___ebp),
+       offsetof(struct info,___esi),
+       offsetof(struct info,___edi)
+};
+
+#define REG_(x) (*(s32 *)(reg_offset[(x)]+(u_char *) FPU_info))
+
+static int reg_offset_vm86[] = {
+       offsetof(struct info,___cs),
+       offsetof(struct info,___vm86_ds),
+       offsetof(struct info,___vm86_es),
+       offsetof(struct info,___vm86_fs),
+       offsetof(struct info,___vm86_gs),
+       offsetof(struct info,___ss),
+       offsetof(struct info,___vm86_ds)
+      };
+
+#define VM86_REG_(x) (*(unsigned short *) \
+                     (reg_offset_vm86[((unsigned)x)]+(u_char *) FPU_info))
+
+/* These are dummy, fs and gs are not saved on the stack. */
+#define ___FS ___ds
+#define ___GS ___ds
+
+static int reg_offset_pm[] = {
+       offsetof(struct info,___cs),
+       offsetof(struct info,___ds),
+       offsetof(struct info,___es),
+       offsetof(struct info,___FS),
+       offsetof(struct info,___GS),
+       offsetof(struct info,___ss),
+       offsetof(struct info,___ds)
+      };
+
+#define PM_REG_(x) (*(unsigned short *) \
+                     (reg_offset_pm[((unsigned)x)]+(u_char *) FPU_info))
+
+
+/* Decode the SIB byte. This function assumes mod != 0 */
+static int sib(int mod, u32 *fpu_eip)
+{
+  u_char ss,index,base;
+  s32 offset;
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_code_verify_area(1);
+  FPU_get_user(base, (u_char *) (*fpu_eip));   /* The SIB byte */
+  RE_ENTRANT_CHECK_ON;
+  (*fpu_eip)++;
+  ss = base >> 6;
+  index = (base >> 3) & 7;
+  base &= 7;
+
+  if ((mod == 0) && (base == 5))
+    offset = 0;              /* No base register */
+  else
+    offset = REG_(base);
+
+  if (index == 4)
+    {
+      /* No index register */
+      /* A non-zero ss is illegal */
+      if ( ss )
+       EXCEPTION(EX_Invalid);
+    }
+  else
+    {
+      offset += (REG_(index)) << ss;
+    }
+
+  if (mod == 1)
+    {
+      /* 8 bit signed displacement */
+      s32 displacement;
+      RE_ENTRANT_CHECK_OFF;
+      FPU_code_verify_area(1);
+      FPU_get_user(displacement, (signed char *) (*fpu_eip));
+      offset += displacement;
+      RE_ENTRANT_CHECK_ON;
+      (*fpu_eip)++;
+    }
+  else if (mod == 2 || base == 5) /* The second condition also has mod==0 */
+    {
+      /* 32 bit displacement */
+      s32 displacement;
+      RE_ENTRANT_CHECK_OFF;
+      FPU_code_verify_area(4);
+      FPU_get_user(displacement, (s32 *) (*fpu_eip));
+      offset += displacement;
+      RE_ENTRANT_CHECK_ON;
+      (*fpu_eip) += 4;
+    }
+
+  return offset;
+}
+
+
+static u32 vm86_segment(u_char segment,
+                                 struct address *addr)
+{
+  segment--;
+#ifdef PARANOID
+  if ( segment > PREFIX_SS_ )
+    {
+      EXCEPTION(EX_INTERNAL|0x130);
+      math_abort(FPU_info,SIGSEGV);
+    }
+#endif /* PARANOID */
+  addr->selector = VM86_REG_(segment);
+  return (u32)VM86_REG_(segment) << 4;
+}
+
+
+/* This should work for 16 and 32 bit protected mode. */
+static s32 pm_address(u_char FPU_modrm, u_char segment,
+                      struct address *addr, s32 offset)
+{ 
+  struct desc_struct descriptor;
+  u32 base_address, limit, address, seg_top;
+
+  segment--;
+
+#ifdef PARANOID
+  /* segment is unsigned, so this also detects if segment was 0: */
+  if ( segment > PREFIX_SS_ )
+    {
+      EXCEPTION(EX_INTERNAL|0x132);
+      math_abort(FPU_info,SIGSEGV);
+    }
+#endif /* PARANOID */
+
+  switch ( segment )
+    {
+      /* fs and gs aren't used by the kernel, so they still have their
+        user-space values. */
+    case PREFIX_FS_-1:
+      /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register
+        in the assembler statement. */
+      __asm__("mov %%fs,%0":"=r" ((unsigned short)addr->selector));
+      break;
+    case PREFIX_GS_-1:
+      /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register
+        in the assembler statement. */
+      __asm__("mov %%gs,%0":"=r" ((unsigned short)addr->selector));
+      break;
+    default:
+      addr->selector = PM_REG_(segment);
+    }
+
+  descriptor = LDT_DESCRIPTOR(PM_REG_(segment));
+  base_address = SEG_BASE_ADDR(descriptor);
+  address = base_address + offset;
+  limit = base_address
+       + (SEG_LIMIT(descriptor)+1) * SEG_GRANULARITY(descriptor) - 1;
+  if ( limit < base_address ) limit = 0xffffffff;
+
+  if ( SEG_EXPAND_DOWN(descriptor) )
+    {
+      if ( SEG_G_BIT(descriptor) )
+       seg_top = 0xffffffff;
+      else
+       {
+         seg_top = base_address + (1 << 20);
+         if ( seg_top < base_address ) seg_top = 0xffffffff;
+       }
+      access_limit =
+       (address <= limit) || (address >= seg_top) ? 0 :
+         ((seg_top-address) >= 255 ? 255 : seg_top-address);
+    }
+  else
+    {
+      access_limit =
+       (address > limit) || (address < base_address) ? 0 :
+         ((limit-address) >= 254 ? 255 : limit-address+1);
+    }
+  if ( SEG_EXECUTE_ONLY(descriptor) ||
+      (!SEG_WRITE_PERM(descriptor) && (FPU_modrm & FPU_WRITE_BIT)) )
+    {
+      access_limit = 0;
+    }
+  return address;
+}
+
+
+/*
+       MOD R/M byte:  MOD == 3 has a special use for the FPU
+                      SIB byte used iff R/M = 100b
+
+       7   6   5   4   3   2   1   0
+       .....   .........   .........
+        MOD    OPCODE(2)     R/M
+
+
+       SIB byte
+
+       7   6   5   4   3   2   1   0
+       .....   .........   .........
+        SS      INDEX        BASE
+
+*/
+
+void *FPU_get_address(u_char FPU_modrm, u32 *fpu_eip,
+                     struct address *addr,
+                     fpu_addr_modes addr_modes)
+{
+  u_char mod;
+  unsigned rm = FPU_modrm & 7;
+  s32 *cpu_reg_ptr;
+  int address = 0;     /* Initialized just to stop compiler warnings. */
+
+  /* Memory accessed via the cs selector is write protected
+     in `non-segmented' 32 bit protected mode. */
+  if ( !addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT)
+      && (addr_modes.override.segment == PREFIX_CS_) )
+    {
+      math_abort(FPU_info,SIGSEGV);
+    }
+
+  addr->selector = FPU_DS;   /* Default, for 32 bit non-segmented mode. */
+
+  mod = (FPU_modrm >> 6) & 3;
+
+  if (rm == 4 && mod != 3)
+    {
+      address = sib(mod, fpu_eip);
+    }
+  else
+    {
+      cpu_reg_ptr = & REG_(rm);
+      switch (mod)
+       {
+       case 0:
+         if (rm == 5)
+           {
+             /* Special case: disp32 */
+             RE_ENTRANT_CHECK_OFF;
+             FPU_code_verify_area(4);
+             FPU_get_user(address, (u32 *) (*fpu_eip));
+             (*fpu_eip) += 4;
+             RE_ENTRANT_CHECK_ON;
+             addr->offset = address;
+             return (void *) address;
+           }
+         else
+           {
+             address = *cpu_reg_ptr;  /* Just return the contents
+                                         of the cpu register */
+             addr->offset = address;
+             return (void *) address;
+           }
+       case 1:
+         /* 8 bit signed displacement */
+         RE_ENTRANT_CHECK_OFF;
+         FPU_code_verify_area(1);
+         FPU_get_user(address, (signed char *) (*fpu_eip));
+         RE_ENTRANT_CHECK_ON;
+         (*fpu_eip)++;
+         break;
+       case 2:
+         /* 32 bit displacement */
+         RE_ENTRANT_CHECK_OFF;
+         FPU_code_verify_area(4);
+         FPU_get_user(address, (s32 *) (*fpu_eip));
+         (*fpu_eip) += 4;
+         RE_ENTRANT_CHECK_ON;
+         break;
+       case 3:
+         /* Not legal for the FPU */
+         EXCEPTION(EX_Invalid);
+       }
+      address += *cpu_reg_ptr;
+    }
+
+  addr->offset = address;
+
+  switch ( addr_modes.default_mode )
+    {
+    case 0:
+      break;
+    case VM86:
+      address += vm86_segment(addr_modes.override.segment, addr);
+      break;
+    case PM16:
+    case SEG32:
+      address = pm_address(FPU_modrm, addr_modes.override.segment,
+                          addr, address);
+      break;
+    default:
+      EXCEPTION(EX_INTERNAL|0x133);
+    }
+
+  return (void *)address;
+}
+
+
+void *FPU_get_address_16(u_char FPU_modrm, u32 *fpu_eip,
+                        struct address *addr,
+                        fpu_addr_modes addr_modes)
+{
+  u_char mod;
+  unsigned rm = FPU_modrm & 7;
+  int address = 0;     /* Default used for mod == 0 */
+
+  /* Memory accessed via the cs selector is write protected
+     in `non-segmented' 32 bit protected mode. */
+  if ( !addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT)
+      && (addr_modes.override.segment == PREFIX_CS_) )
+    {
+      math_abort(FPU_info,SIGSEGV);
+    }
+
+  addr->selector = FPU_DS;   /* Default, for 32 bit non-segmented mode. */
+
+  mod = (FPU_modrm >> 6) & 3;
+
+  switch (mod)
+    {
+    case 0:
+      if (rm == 6)
+       {
+         /* Special case: disp16 */
+         RE_ENTRANT_CHECK_OFF;
+         FPU_code_verify_area(2);
+         FPU_get_user(address, (unsigned short *) (*fpu_eip));
+         (*fpu_eip) += 2;
+         RE_ENTRANT_CHECK_ON;
+         goto add_segment;
+       }
+      break;
+    case 1:
+      /* 8 bit signed displacement */
+      RE_ENTRANT_CHECK_OFF;
+      FPU_code_verify_area(1);
+      FPU_get_user(address, (signed char *) (*fpu_eip));
+      RE_ENTRANT_CHECK_ON;
+      (*fpu_eip)++;
+      break;
+    case 2:
+      /* 16 bit displacement */
+      RE_ENTRANT_CHECK_OFF;
+      FPU_code_verify_area(2);
+      FPU_get_user(address, (unsigned short *) (*fpu_eip));
+      (*fpu_eip) += 2;
+      RE_ENTRANT_CHECK_ON;
+      break;
+    case 3:
+      /* Not legal for the FPU */
+      EXCEPTION(EX_Invalid);
+      break;
+    }
+  switch ( rm )
+    {
+    case 0:
+      address += FPU_info->___ebx + FPU_info->___esi;
+      break;
+    case 1:
+      address += FPU_info->___ebx + FPU_info->___edi;
+      break;
+    case 2:
+      address += FPU_info->___ebp + FPU_info->___esi;
+      if ( addr_modes.override.segment == PREFIX_DEFAULT )
+       addr_modes.override.segment = PREFIX_SS_;
+      break;
+    case 3:
+      address += FPU_info->___ebp + FPU_info->___edi;
+      if ( addr_modes.override.segment == PREFIX_DEFAULT )
+       addr_modes.override.segment = PREFIX_SS_;
+      break;
+    case 4:
+      address += FPU_info->___esi;
+      break;
+    case 5:
+      address += FPU_info->___edi;
+      break;
+    case 6:
+      address += FPU_info->___ebp;
+      if ( addr_modes.override.segment == PREFIX_DEFAULT )
+       addr_modes.override.segment = PREFIX_SS_;
+      break;
+    case 7:
+      address += FPU_info->___ebx;
+      break;
+    }
+
+ add_segment:
+  address &= 0xffff;
+
+  addr->offset = address;
+
+  switch ( addr_modes.default_mode )
+    {
+    case 0:
+      break;
+    case VM86:
+      address += vm86_segment(addr_modes.override.segment, addr);
+      break;
+    case PM16:
+    case SEG32:
+      address = pm_address(FPU_modrm, addr_modes.override.segment,
+                          addr, address);
+      break;
+    default:
+      EXCEPTION(EX_INTERNAL|0x131);
+    }
+
+  return (void *)address ;
+}
diff --git a/sid/component/bochs/cpu/fpu/load_store.c b/sid/component/bochs/cpu/fpu/load_store.c
new file mode 100644 (file)
index 0000000..488fa92
--- /dev/null
@@ -0,0 +1,270 @@
+/*---------------------------------------------------------------------------+
+ |  load_store.c                                                             |
+ |                                                                           |
+ | This file contains most of the code to interpret the FPU instructions     |
+ | which load and store from user memory.                                    |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail   billm@suburbia.net             |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | Note:                                                                     |
+ |    The file contains code which accesses user memory.                     |
+ |    Emulator static data may change when user memory is accessed, due to   |
+ |    other processes using the emulator while swapping is in progress.      |
+ +---------------------------------------------------------------------------*/
+
+#include <asm/uaccess.h>
+
+#include "fpu_system.h"
+#include "exception.h"
+#include "fpu_emu.h"
+#include "status_w.h"
+#include "control_w.h"
+
+
+#define _NONE_ 0   /* st0_ptr etc not needed */
+#define _REG0_ 1   /* Will be storing st(0) */
+#define _PUSH_ 3   /* Need to check for space to push onto stack */
+#define _null_ 4   /* Function illegal or not implemented */
+
+#define pop_0()        { FPU_settag0(TAG_Empty); top++; }
+
+
+static u_char const type_table[32] = {
+  _PUSH_, _PUSH_, _PUSH_, _PUSH_,
+  _null_, _null_, _null_, _null_,
+  _REG0_, _REG0_, _REG0_, _REG0_,
+  _REG0_, _REG0_, _REG0_, _REG0_,
+  _NONE_, _null_, _NONE_, _PUSH_,
+  _NONE_, _PUSH_, _null_, _PUSH_,
+  _NONE_, _null_, _NONE_, _REG0_,
+  _NONE_, _REG0_, _NONE_, _REG0_
+  };
+
+u_char const data_sizes_16[32] = {
+  4,  4,  8,  2,  0,  0,  0,  0,
+  4,  4,  8,  2,  4,  4,  8,  2,
+  14, 0, 94, 10,  2, 10,  0,  8,  
+  14, 0, 94, 10,  2, 10,  2,  8
+};
+
+u_char const data_sizes_32[32] = {
+  4,  4,  8,  2,  0,  0,  0,  0,
+  4,  4,  8,  2,  4,  4,  8,  2,
+  28, 0,108, 10,  2, 10,  0,  8,  
+  28, 0,108, 10,  2, 10,  2,  8
+};
+
+int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
+                    void *data_address)
+{
+  FPU_REG loaded_data;
+  FPU_REG *st0_ptr;
+  u_char st0_tag = TAG_Empty;  /* This is just to stop a gcc warning. */
+  u_char loaded_tag;
+
+  st0_ptr = NULL;    /* Initialized just to stop compiler warnings. */
+
+  if ( addr_modes.default_mode & PROTECTED )
+    {
+      if ( addr_modes.default_mode == SEG32 )
+       {
+         if ( access_limit < data_sizes_32[type] )
+           math_abort(FPU_info,SIGSEGV);
+       }
+      else if ( addr_modes.default_mode == PM16 )
+       {
+         if ( access_limit < data_sizes_16[type] )
+           math_abort(FPU_info,SIGSEGV);
+       }
+#ifdef PARANOID
+      else
+       EXCEPTION(EX_INTERNAL|0x140);
+#endif /* PARANOID */
+    }
+
+  switch ( type_table[type] )
+    {
+    case _NONE_:
+      break;
+    case _REG0_:
+      st0_ptr = &st(0);       /* Some of these instructions pop after
+                                storing */
+      st0_tag = FPU_gettag0();
+      break;
+    case _PUSH_:
+      {
+       if ( FPU_gettagi(-1) != TAG_Empty )
+         { FPU_stack_overflow(); return 0; }
+       top--;
+       st0_ptr = &st(0);
+      }
+      break;
+    case _null_:
+      FPU_illegal();
+      return 0;
+#ifdef PARANOID
+    default:
+      EXCEPTION(EX_INTERNAL|0x141);
+      return 0;
+#endif /* PARANOID */
+    }
+
+  switch ( type )
+    {
+    case 000:       /* fld m32real */
+      clear_C1();
+      loaded_tag = FPU_load_single((float *)data_address, &loaded_data);
+      if ( (loaded_tag == TAG_Special)
+          && isNaN(&loaded_data)
+          && (real_1op_NaN(&loaded_data) < 0) )
+       {
+         top++;
+         break;
+       }
+      FPU_copy_to_reg0(&loaded_data, loaded_tag);
+      break;
+    case 001:      /* fild m32int */
+      clear_C1();
+      loaded_tag = FPU_load_int32((s32 *)data_address, &loaded_data);
+      FPU_copy_to_reg0(&loaded_data, loaded_tag);
+      break;
+    case 002:      /* fld m64real */
+      clear_C1();
+      loaded_tag = FPU_load_double((double *)data_address, &loaded_data);
+      if ( (loaded_tag == TAG_Special)
+          && isNaN(&loaded_data)
+          && (real_1op_NaN(&loaded_data) < 0) )
+       {
+         top++;
+         break;
+       }
+      FPU_copy_to_reg0(&loaded_data, loaded_tag);
+      break;
+    case 003:      /* fild m16int */
+      clear_C1();
+      loaded_tag = FPU_load_int16((s16 *)data_address, &loaded_data);
+      FPU_copy_to_reg0(&loaded_data, loaded_tag);
+      break;
+    case 010:      /* fst m32real */
+      clear_C1();
+      FPU_store_single(st0_ptr, st0_tag, (float *)data_address);
+      break;
+    case 011:      /* fist m32int */
+      clear_C1();
+      FPU_store_int32(st0_ptr, st0_tag, (s32 *)data_address);
+      break;
+    case 012:     /* fst m64real */
+      clear_C1();
+      FPU_store_double(st0_ptr, st0_tag, (double *)data_address);
+      break;
+    case 013:     /* fist m16int */
+      clear_C1();
+      FPU_store_int16(st0_ptr, st0_tag, (s16 *)data_address);
+      break;
+    case 014:     /* fstp m32real */
+      clear_C1();
+      if ( FPU_store_single(st0_ptr, st0_tag, (float *)data_address) )
+       pop_0();  /* pop only if the number was actually stored
+                    (see the 80486 manual p16-28) */
+      break;
+    case 015:     /* fistp m32int */
+      clear_C1();
+      if ( FPU_store_int32(st0_ptr, st0_tag, (s32 *)data_address) )
+       pop_0();  /* pop only if the number was actually stored
+                    (see the 80486 manual p16-28) */
+      break;
+    case 016:     /* fstp m64real */
+      clear_C1();
+      if ( FPU_store_double(st0_ptr, st0_tag, (double *)data_address) )
+       pop_0();  /* pop only if the number was actually stored
+                    (see the 80486 manual p16-28) */
+      break;
+    case 017:     /* fistp m16int */
+      clear_C1();
+      if ( FPU_store_int16(st0_ptr, st0_tag, (s16 *)data_address) )
+       pop_0();  /* pop only if the number was actually stored
+                    (see the 80486 manual p16-28) */
+      break;
+    case 020:     /* fldenv  m14/28byte */
+      fldenv(addr_modes, (u_char *)data_address);
+      /* Ensure that the values just loaded are not changed by
+        fix-up operations. */
+      return 1;
+    case 022:     /* frstor m94/108byte */
+      frstor(addr_modes, (u_char *)data_address);
+      /* Ensure that the values just loaded are not changed by
+        fix-up operations. */
+      return 1;
+    case 023:     /* fbld m80dec */
+      clear_C1();
+      loaded_tag = FPU_load_bcd((u_char *)data_address);
+      FPU_settag0(loaded_tag);
+      break;
+    case 024:     /* fldcw */
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_READ, data_address, 2);
+      FPU_get_user(control_word, (u16 *) data_address);
+      RE_ENTRANT_CHECK_ON;
+      if ( partial_status & ~control_word & CW_Exceptions )
+       partial_status |= (SW_Summary | SW_Backward);
+      else
+       partial_status &= ~(SW_Summary | SW_Backward);
+#ifdef PECULIAR_486
+      control_word |= 0x40;  /* An 80486 appears to always set this bit */
+#endif /* PECULIAR_486 */
+      return 1;
+    case 025:      /* fld m80real */
+      clear_C1();
+      loaded_tag = FPU_load_extended((long double *)data_address, 0);
+      FPU_settag0(loaded_tag);
+      break;
+    case 027:      /* fild m64int */
+      clear_C1();
+      loaded_tag = FPU_load_int64((s64 *)data_address);
+      FPU_settag0(loaded_tag);
+      break;
+    case 030:     /* fstenv  m14/28byte */
+      fstenv(addr_modes, (u_char *)data_address);
+      return 1;
+    case 032:      /* fsave */
+      fsave(addr_modes, (u_char *)data_address);
+      return 1;
+    case 033:      /* fbstp m80dec */
+      clear_C1();
+      if ( FPU_store_bcd(st0_ptr, st0_tag, (u_char *)data_address) )
+       pop_0();  /* pop only if the number was actually stored
+                    (see the 80486 manual p16-28) */
+      break;
+    case 034:      /* fstcw m16int */
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_WRITE,data_address,2);
+      FPU_put_user(control_word, (u16 *) data_address);
+      RE_ENTRANT_CHECK_ON;
+      return 1;
+    case 035:      /* fstp m80real */
+      clear_C1();
+      if ( FPU_store_extended(st0_ptr, st0_tag, (long double *)data_address) )
+       pop_0();  /* pop only if the number was actually stored
+                    (see the 80486 manual p16-28) */
+      break;
+    case 036:      /* fstsw m2byte */
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_WRITE,data_address,2);
+      FPU_put_user(status_word(),(u16 *) data_address);
+      RE_ENTRANT_CHECK_ON;
+      return 1;
+    case 037:      /* fistp m64int */
+      clear_C1();
+      if ( FPU_store_int64(st0_ptr, st0_tag, (s64 *)data_address) )
+       pop_0();  /* pop only if the number was actually stored
+                    (see the 80486 manual p16-28) */
+      break;
+    }
+  return 0;
+}
diff --git a/sid/component/bochs/cpu/fpu/mul_Xsig.S b/sid/component/bochs/cpu/fpu/mul_Xsig.S
new file mode 100644 (file)
index 0000000..717785a
--- /dev/null
@@ -0,0 +1,176 @@
+/*---------------------------------------------------------------------------+
+ |  mul_Xsig.S                                                               |
+ |                                                                           |
+ | Multiply a 12 byte fixed point number by another fixed point number.      |
+ |                                                                           |
+ | Copyright (C) 1992,1994,1995                                              |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                                                                           |
+ | Call from C as:                                                           |
+ |   void mul32_Xsig(Xsig *x, unsigned b)                                    |
+ |                                                                           |
+ |   void mul64_Xsig(Xsig *x, unsigned long long *b)                         |
+ |                                                                           |
+ |   void mul_Xsig_Xsig(Xsig *x, unsigned *b)                                |
+ |                                                                           |
+ | The result is neither rounded nor normalized, and the ls bit or so may    |
+ | be wrong.                                                                 |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+       .file   "mul_Xsig.S"
+
+
+#include "fpu_emu.h"
+
+.text
+ENTRY(mul32_Xsig)
+       pushl %ebp
+       movl %esp,%ebp
+       subl $16,%esp
+       pushl %esi
+
+       movl PARAM1,%esi
+       movl PARAM2,%ecx
+
+       xor %eax,%eax
+       movl %eax,-4(%ebp)
+       movl %eax,-8(%ebp)
+
+       movl (%esi),%eax        /* lsl of Xsig */
+       mull %ecx               /* msl of b */
+       movl %edx,-12(%ebp)
+
+       movl 4(%esi),%eax       /* midl of Xsig */
+       mull %ecx               /* msl of b */
+       addl %eax,-12(%ebp)
+       adcl %edx,-8(%ebp)
+       adcl $0,-4(%ebp)
+
+       movl 8(%esi),%eax       /* msl of Xsig */
+       mull %ecx               /* msl of b */
+       addl %eax,-8(%ebp)
+       adcl %edx,-4(%ebp)
+
+       movl -12(%ebp),%eax
+       movl %eax,(%esi)
+       movl -8(%ebp),%eax
+       movl %eax,4(%esi)
+       movl -4(%ebp),%eax
+       movl %eax,8(%esi)
+
+       popl %esi
+       leave
+       ret
+
+
+ENTRY(mul64_Xsig)
+       pushl %ebp
+       movl %esp,%ebp
+       subl $16,%esp
+       pushl %esi
+
+       movl PARAM1,%esi
+       movl PARAM2,%ecx
+
+       xor %eax,%eax
+       movl %eax,-4(%ebp)
+       movl %eax,-8(%ebp)
+
+       movl (%esi),%eax        /* lsl of Xsig */
+       mull 4(%ecx)            /* msl of b */
+       movl %edx,-12(%ebp)
+
+       movl 4(%esi),%eax       /* midl of Xsig */
+       mull (%ecx)             /* lsl of b */
+       addl %edx,-12(%ebp)
+       adcl $0,-8(%ebp)
+       adcl $0,-4(%ebp)
+
+       movl 4(%esi),%eax       /* midl of Xsig */
+       mull 4(%ecx)            /* msl of b */
+       addl %eax,-12(%ebp)
+       adcl %edx,-8(%ebp)
+       adcl $0,-4(%ebp)
+
+       movl 8(%esi),%eax       /* msl of Xsig */
+       mull (%ecx)             /* lsl of b */
+       addl %eax,-12(%ebp)
+       adcl %edx,-8(%ebp)
+       adcl $0,-4(%ebp)
+
+       movl 8(%esi),%eax       /* msl of Xsig */
+       mull 4(%ecx)            /* msl of b */
+       addl %eax,-8(%ebp)
+       adcl %edx,-4(%ebp)
+
+       movl -12(%ebp),%eax
+       movl %eax,(%esi)
+       movl -8(%ebp),%eax
+       movl %eax,4(%esi)
+       movl -4(%ebp),%eax
+       movl %eax,8(%esi)
+
+       popl %esi
+       leave
+       ret
+
+
+
+ENTRY(mul_Xsig_Xsig)
+       pushl %ebp
+       movl %esp,%ebp
+       subl $16,%esp
+       pushl %esi
+
+       movl PARAM1,%esi
+       movl PARAM2,%ecx
+
+       xor %eax,%eax
+       movl %eax,-4(%ebp)
+       movl %eax,-8(%ebp)
+
+       movl (%esi),%eax        /* lsl of Xsig */
+       mull 8(%ecx)            /* msl of b */
+       movl %edx,-12(%ebp)
+
+       movl 4(%esi),%eax       /* midl of Xsig */
+       mull 4(%ecx)            /* midl of b */
+       addl %edx,-12(%ebp)
+       adcl $0,-8(%ebp)
+       adcl $0,-4(%ebp)
+
+       movl 8(%esi),%eax       /* msl of Xsig */
+       mull (%ecx)             /* lsl of b */
+       addl %edx,-12(%ebp)
+       adcl $0,-8(%ebp)
+       adcl $0,-4(%ebp)
+
+       movl 4(%esi),%eax       /* midl of Xsig */
+       mull 8(%ecx)            /* msl of b */
+       addl %eax,-12(%ebp)
+       adcl %edx,-8(%ebp)
+       adcl $0,-4(%ebp)
+
+       movl 8(%esi),%eax       /* msl of Xsig */
+       mull 4(%ecx)            /* midl of b */
+       addl %eax,-12(%ebp)
+       adcl %edx,-8(%ebp)
+       adcl $0,-4(%ebp)
+
+       movl 8(%esi),%eax       /* msl of Xsig */
+       mull 8(%ecx)            /* msl of b */
+       addl %eax,-8(%ebp)
+       adcl %edx,-4(%ebp)
+
+       movl -12(%ebp),%edx
+       movl %edx,(%esi)
+       movl -8(%ebp),%edx
+       movl %edx,4(%esi)
+       movl -4(%ebp),%edx
+       movl %edx,8(%esi)
+
+       popl %esi
+       leave
+       ret
+
diff --git a/sid/component/bochs/cpu/fpu/mul_Xsig.c b/sid/component/bochs/cpu/fpu/mul_Xsig.c
new file mode 100644 (file)
index 0000000..8dc4c94
--- /dev/null
@@ -0,0 +1,95 @@
+/*---------------------------------------------------------------------------+
+ |  mul_Xsig.S                                                               |
+ |                                                                           |
+ | Multiply a 12 byte fixed point number by another fixed point number.      |
+ |                                                                           |
+ | Copyright (C) 1992,1994,1995                                              |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                                                                           |
+ |                                                                           |
+ | The result is neither rounded nor normalized, and the ls bit or so may    |
+ | be wrong.                                                                 |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+
+#include "fpu_emu.h"
+#include "poly.h"
+
+
+void mul32_Xsig(Xsig *x, const u32 ba)
+{
+  Xsig y;
+  u32 zl;
+  u64 b = ba, z;
+
+  z = b * x->lsw;
+  y.lsw = z >> 32;
+
+  z = b * x->midw;
+  y.midw = z >> 32;
+  zl = z;
+  y.lsw += zl;
+  if ( zl > y.lsw )
+    y.midw ++;
+
+  z = b * x->msw;
+  y.msw = z >> 32;
+  zl = z;
+  y.midw += zl;
+  if ( zl > y.midw )
+    y.msw ++;
+
+  *x = y;
+
+}
+
+
+void mul64_Xsig(Xsig *x, const u64 *b)
+{
+  Xsig yh, yl;
+
+  yh = *x;
+  yl = *x;
+  mul32_Xsig(&yh, (*b) >> 32);
+  mul32_Xsig(&yl, *b);
+
+  x->msw = yh.msw;
+  x->midw = yh.midw + yl.msw;
+  if ( yh.midw > x->midw )
+    x->msw ++;
+  x->lsw = yh.lsw + yl.midw;
+  if ( yh.lsw > x->lsw )
+    {
+      x->midw ++;
+      if ( x->midw == 0 )
+       x->msw ++;
+    }
+
+}
+
+
+void mul_Xsig_Xsig(Xsig *x, const Xsig *b)
+{
+  u32 yh;
+  u64 y, z;
+
+  y = b->lsw;
+  y *= x->msw;
+  yh = y >> 32;
+
+  z = b->msw;
+  z <<= 32;
+  z += b->midw;
+  mul64_Xsig(x, &z);
+
+  x->lsw += yh;
+  if ( yh > x->lsw )
+    {
+      x->midw ++;
+      if ( x->midw == 0 )
+       x->msw ++;
+    }
+}
+
diff --git a/sid/component/bochs/cpu/fpu/poly.h b/sid/component/bochs/cpu/fpu/poly.h
new file mode 100644 (file)
index 0000000..558269f
--- /dev/null
@@ -0,0 +1,215 @@
+/*---------------------------------------------------------------------------+
+ |  poly.h                                                                   |
+ |                                                                           |
+ |  Header file for the FPU-emu poly*.c source files.                        |
+ |                                                                           |
+ | Copyright (C) 1994,1999                                                   |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail   billm@melbpc.org.au            |
+ |                                                                           |
+ | Declarations and definitions for functions operating on Xsig (12-byte     |
+ | extended-significand) quantities.                                         |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#ifndef _POLY_H
+#define _POLY_H
+
+/* This 12-byte structure is used to improve the accuracy of computation
+   of transcendental functions.
+   Intended to be used to get results better than 8-byte computation
+   allows. 9-byte would probably be sufficient.
+   */
+typedef struct {
+#ifdef EMU_BIG_ENDIAN
+  u32 msw;
+  u32 midw;
+  u32 lsw;
+#else
+  u32 lsw;
+  u32 midw;
+  u32 msw;
+#endif
+} GCC_ATTRIBUTE((packed)) Xsig;
+
+asmlinkage void mul64(u64 const *a, u64 const *b,
+                     u64 *result);
+asmlinkage void polynomial_Xsig(Xsig *, const u64 *x,
+                               const u64 terms[], const int n);
+
+asmlinkage void mul32_Xsig(Xsig *, const u32 mult);
+asmlinkage void mul64_Xsig(Xsig *, const u64 *mult);
+asmlinkage void mul_Xsig_Xsig(Xsig *dest, const Xsig *mult);
+
+asmlinkage void shr_Xsig(Xsig *, const int n);
+asmlinkage int round_Xsig(Xsig *);
+asmlinkage int norm_Xsig(Xsig *);
+asmlinkage void div_Xsig(const Xsig *x1, const Xsig *x2, Xsig *dest);
+
+/* Macro to extract the most significant 32 bits from a 64bit quantity */
+#ifdef EMU_BIG_ENDIAN
+#define LL_MSW(x)     (((u32 *)&x)[0])
+#else
+#define LL_MSW(x)     (((u32 *)&x)[1])
+#endif
+
+/* Macro to initialize an Xsig struct */
+#ifdef EMU_BIG_ENDIAN
+#define MK_XSIG(a,b,c)     { a, b, c }
+#else
+#define MK_XSIG(a,b,c)     { c, b, a }
+#endif
+
+/* Macro to access the 8 ms bytes of an Xsig as a 64bit quantity */
+#ifdef EMU_BIG_ENDIAN
+#define XSIG_LL(x)         (*(u64 *)&x.msw)
+#else
+#define XSIG_LL(x)         (*(u64 *)&x.midw)
+#endif
+
+
+/*
+   Need to run gcc with optimizations on to get these to
+   actually be in-line.
+   */
+
+/* Multiply two fixed-point 32 bit numbers, producing a 32 bit result.
+   The answer is the ms word of the product.  */
+BX_C_INLINE
+u32 mul_32_32(const u32 arg1, const u32 arg2)
+{
+#ifdef NO_ASSEMBLER
+  return (((u64)arg1) * arg2) >> 32;
+#else
+/* Some versions of gcc make it difficult to stop eax from being clobbered.
+   Merely specifying that it is used doesn't work...
+ */
+  int retval;
+  asm volatile ("mull %2; movl %%edx,%%eax" \
+               :"=a" (retval) \
+               :"0" (arg1), "g" (arg2) \
+               :"dx");
+  return retval;
+#endif
+}
+
+
+/* Add the 12 byte Xsig x2 to Xsig dest, with no checks for overflow. */
+BX_C_INLINE
+void add_Xsig_Xsig(Xsig *dest, const Xsig *x2)
+{
+#ifdef NO_ASSEMBLER
+  dest->lsw += x2->lsw;
+  if ( dest->lsw < x2->lsw )
+    {
+      dest->midw ++;
+      if ( dest->midw == 0 )
+       dest->msw ++;
+    }
+  dest->midw += x2->midw;
+  if ( dest->midw < x2->midw )
+    {
+      dest->msw ++;
+    }
+  dest->msw += x2->msw;
+#else
+  asm volatile ("movl %1,%%edi; movl %2,%%esi;
+                 movl (%%esi),%%eax; addl %%eax,(%%edi);
+                 movl 4(%%esi),%%eax; adcl %%eax,4(%%edi);
+                 movl 8(%%esi),%%eax; adcl %%eax,8(%%edi);"
+                 :"=g" (*dest):"g" (dest), "g" (x2)
+                 :"ax","si","di");
+#endif
+}
+
+
+/* Add the 12 byte Xsig x2 to Xsig dest, adjust exp if overflow occurs. */
+BX_C_INLINE
+void add_two_Xsig(Xsig *dest, const Xsig *x2, s32 *exp)
+{
+#ifdef NO_ASSEMBLER
+  int ovfl = 0;
+
+  dest->lsw += x2->lsw;
+  if ( dest->lsw < x2->lsw )
+    {
+      dest->midw ++;
+      if ( dest->midw == 0 )
+       {
+         dest->msw ++;
+         if ( dest->msw == 0 )
+           ovfl = 1;
+       }
+    }
+  dest->midw += x2->midw;
+  if ( dest->midw < x2->midw )
+    {
+      dest->msw ++;
+      if ( dest->msw == 0 )
+       ovfl = 1;
+    }
+  dest->msw += x2->msw;
+  if ( dest->msw < x2->msw )
+    ovfl = 1;
+  if ( ovfl )
+    {
+      (*exp) ++;
+      dest->lsw >>= 1;
+      if ( dest->midw & 1 )
+       dest->lsw |= 0x80000000;
+      dest->midw >>= 1;
+      if ( dest->msw & 1 )
+       dest->midw |= 0x80000000;
+      dest->msw >>= 1;
+      dest->msw |= 0x80000000;
+    }
+#else
+/* Note: the constraints in the asm statement didn't always work properly
+   with gcc 2.5.8.  Changing from using edi to using ecx got around the
+   problem, but keep fingers crossed! */
+  asm volatile ("movl %2,%%ecx; movl %3,%%esi;
+                 movl (%%esi),%%eax; addl %%eax,(%%ecx);
+                 movl 4(%%esi),%%eax; adcl %%eax,4(%%ecx);
+                 movl 8(%%esi),%%eax; adcl %%eax,8(%%ecx);
+                 jnc 0f;
+                rcrl 8(%%ecx); rcrl 4(%%ecx); rcrl (%%ecx)
+                 movl %4,%%ecx; incl (%%ecx)
+                 movl $1,%%eax; jmp 1f;
+                 0: xorl %%eax,%%eax;
+                 1:"
+               :"=g" (*exp), "=g" (*dest)
+               :"g" (dest), "g" (x2), "g" (exp)
+               :"cx","si","ax");
+#endif
+}
+
+
+/* Negate the 12 byte Xsig */
+BX_C_INLINE
+void negate_Xsig(Xsig *x)
+{
+#ifdef NO_ASSEMBLER
+  x->lsw = ~x->lsw;
+  x->midw = ~x->midw;
+  x->msw = ~x->msw;
+  x->lsw ++;
+  if ( x->lsw == 0 )
+    {
+      x->midw ++;
+      if ( x->midw == 0 )
+       x->msw ++;
+    }
+#else
+/* Negate (subtract from 1.0) the 12 byte Xsig */
+/* This is faster in a loop on my 386 than using the "neg" instruction. */
+  asm volatile("movl %1,%%esi; "
+               "xorl %%ecx,%%ecx; "
+               "movl %%ecx,%%eax; subl (%%esi),%%eax; movl %%eax,(%%esi); "
+               "movl %%ecx,%%eax; sbbl 4(%%esi),%%eax; movl %%eax,4(%%esi); "
+               "movl %%ecx,%%eax; sbbl 8(%%esi),%%eax; movl %%eax,8(%%esi); "
+               :"=g" (*x):"g" (x):"si","ax","cx");
+#endif
+}
+
+
+#endif /* _POLY_H */
diff --git a/sid/component/bochs/cpu/fpu/poly_2xm1.c b/sid/component/bochs/cpu/fpu/poly_2xm1.c
new file mode 100644 (file)
index 0000000..249c423
--- /dev/null
@@ -0,0 +1,156 @@
+/*---------------------------------------------------------------------------+
+ |  poly_2xm1.c                                                              |
+ |                                                                           |
+ | Function to compute 2^x-1 by a polynomial approximation.                  |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "reg_constant.h"
+#include "fpu_emu.h"
+#include "fpu_system.h"
+#include "control_w.h"
+#include "poly.h"
+
+
+#define        HIPOWER 11
+static const u64 lterms[HIPOWER] =
+{
+  BX_CONST64(0x0000000000000000),  /* This term done separately as 12 bytes */
+  BX_CONST64(0xf5fdeffc162c7543),
+  BX_CONST64(0x1c6b08d704a0bfa6),
+  BX_CONST64(0x0276556df749cc21),
+  BX_CONST64(0x002bb0ffcf14f6b8),
+  BX_CONST64(0x0002861225ef751c),
+  BX_CONST64(0x00001ffcbfcd5422),
+  BX_CONST64(0x00000162c005d5f1),
+  BX_CONST64(0x0000000da96ccb1b),
+  BX_CONST64(0x0000000078d1b897),
+  BX_CONST64(0x000000000422b029)
+};
+
+static const Xsig hiterm = MK_XSIG(0xb17217f7, 0xd1cf79ab, 0xc8a39194);
+
+/* Four slices: 0.0 : 0.25 : 0.50 : 0.75 : 1.0,
+   These numbers are 2^(1/4), 2^(1/2), and 2^(3/4)
+ */
+static const Xsig shiftterm0 = MK_XSIG(0, 0, 0);
+static const Xsig shiftterm1 = MK_XSIG(0x9837f051, 0x8db8a96f, 0x46ad2318);
+static const Xsig shiftterm2 = MK_XSIG(0xb504f333, 0xf9de6484, 0x597d89b3);
+static const Xsig shiftterm3 = MK_XSIG(0xd744fcca, 0xd69d6af4, 0x39a68bb9);
+
+static const Xsig *shiftterm[] = { &shiftterm0, &shiftterm1,
+                                    &shiftterm2, &shiftterm3 };
+
+
+/*--- poly_2xm1() -----------------------------------------------------------+
+ | Requires st(0) which is TAG_Valid and < 1.                                |
+ +---------------------------------------------------------------------------*/
+int    poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result)
+{
+  s32       exponent, shift;
+  u64       Xll;
+  Xsig      accumulator, Denom, argSignif;
+  u_char    tag;
+
+  exponent = exponent16(arg);
+
+#ifdef PARANOID
+  if ( exponent >= 0 )         /* Don't want a |number| >= 1.0 */
+    {
+      /* Number negative, too large, or not Valid. */
+      EXCEPTION(EX_INTERNAL|0x127);
+      return 1;
+    }
+#endif /* PARANOID */
+
+  argSignif.lsw = 0;
+  XSIG_LL(argSignif) = Xll = significand(arg);
+
+  if ( exponent == -1 )
+    {
+      shift = (argSignif.msw & 0x40000000) ? 3 : 2;
+      /* subtract 0.5 or 0.75 */
+      exponent -= 2;
+      XSIG_LL(argSignif) <<= 2;
+      Xll <<= 2;
+    }
+  else if ( exponent == -2 )
+    {
+      shift = 1;
+      /* subtract 0.25 */
+      exponent--;
+      XSIG_LL(argSignif) <<= 1;
+      Xll <<= 1;
+    }
+  else
+    shift = 0;
+
+  if ( exponent < -2 )
+    {
+      /* Shift the argument right by the required places. */
+      if ( FPU_shrx(&Xll, -2-exponent) >= 0x80000000U )
+       Xll++;  /* round up */
+    }
+
+  accumulator.lsw = accumulator.midw = accumulator.msw = 0;
+  polynomial_Xsig(&accumulator, &Xll, lterms, HIPOWER-1);
+  mul_Xsig_Xsig(&accumulator, &argSignif);
+  shr_Xsig(&accumulator, 3);
+
+  mul_Xsig_Xsig(&argSignif, &hiterm);   /* The leading term */
+  add_two_Xsig(&accumulator, &argSignif, &exponent);
+
+  if ( shift )
+    {
+      /* The argument is large, use the identity:
+        f(x+a) = f(a) * (f(x) + 1) - 1;
+        */
+      shr_Xsig(&accumulator, - exponent);
+      accumulator.msw |= 0x80000000;      /* add 1.0 */
+      mul_Xsig_Xsig(&accumulator, shiftterm[shift]);
+      accumulator.msw &= 0x3fffffff;      /* subtract 1.0 */
+      exponent = 1;
+    }
+
+  if ( sign != SIGN_POS )
+    {
+      /* The argument is negative, use the identity:
+            f(-x) = -f(x) / (1 + f(x))
+        */
+      Denom.lsw = accumulator.lsw;
+      XSIG_LL(Denom) = XSIG_LL(accumulator);
+      if ( exponent < 0 )
+       shr_Xsig(&Denom, - exponent);
+      else if ( exponent > 0 )
+       {
+         /* exponent must be 1 here */
+         XSIG_LL(Denom) <<= 1;
+         if ( Denom.lsw & 0x80000000 )
+           XSIG_LL(Denom) |= 1;
+         (Denom.lsw) <<= 1;
+       }
+      Denom.msw |= 0x80000000;      /* add 1.0 */
+      div_Xsig(&accumulator, &Denom, &accumulator);
+    }
+
+  /* Convert to 64 bit signed-compatible */
+  exponent += round_Xsig(&accumulator);
+
+  result = &st(0);
+  significand(result) = XSIG_LL(accumulator);
+  setexponent16(result, exponent);
+
+  tag = FPU_round(result, 1, 0, FULL_PRECISION, sign);
+
+  setsign(result, sign);
+  FPU_settag0(tag);
+
+  return 0;
+
+}
diff --git a/sid/component/bochs/cpu/fpu/poly_atan.c b/sid/component/bochs/cpu/fpu/poly_atan.c
new file mode 100644 (file)
index 0000000..e984ace
--- /dev/null
@@ -0,0 +1,229 @@
+/*---------------------------------------------------------------------------+
+ |  poly_atan.c                                                              |
+ |                                                                           |
+ | Compute the arctan of a FPU_REG, using a polynomial approximation.        |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997,1999                                    |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@melbpc.org.au                             |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "reg_constant.h"
+#include "fpu_emu.h"
+#include "fpu_system.h"
+#include "status_w.h"
+#include "control_w.h"
+#include "poly.h"
+
+#define        HIPOWERon       6       /* odd poly, negative terms */
+static const u64 oddnegterms[HIPOWERon] =
+{
+  BX_CONST64(0x0000000000000000), /* Dummy (not for - 1.0) */
+  BX_CONST64(0x015328437f756467),
+  BX_CONST64(0x0005dda27b73dec6),
+  BX_CONST64(0x0000226bf2bfb91a),
+  BX_CONST64(0x000000ccc439c5f7),
+  BX_CONST64(0x0000000355438407)
+} ;
+
+#define        HIPOWERop       6       /* odd poly, positive terms */
+static const u64 oddplterms[HIPOWERop] =
+{
+/*  BX_CONST64(0xaaaaaaaaaaaaaaab),  transferred to fixedpterm[] */
+  BX_CONST64(0x0db55a71875c9ac2),
+  BX_CONST64(0x0029fce2d67880b0),
+  BX_CONST64(0x0000dfd3908b4596),
+  BX_CONST64(0x00000550fd61dab4),
+  BX_CONST64(0x0000001c9422b3f9),
+  BX_CONST64(0x000000003e3301e1)
+};
+
+static const u64 denomterm = BX_CONST64(0xebd9b842c5c53a0e);
+
+static const Xsig fixedpterm = MK_XSIG(0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa);
+
+static const Xsig pi_signif = MK_XSIG(0xc90fdaa2, 0x2168c234, 0xc4c6628b);
+
+
+/*--- poly_atan() -----------------------------------------------------------+
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+void   poly_atan(FPU_REG *st0_ptr, u_char st0_tag,
+                 FPU_REG *st1_ptr, u_char st1_tag)
+{
+  u_char       transformed, inverted,
+                sign1, sign2;
+  s32           exponent;
+  s32          dummy_exp;
+  Xsig          accumulator, Numer, Denom, accumulatore, argSignif,
+                argSq, argSqSq;
+  u_char        tag;
+  
+  sign1 = getsign(st0_ptr);
+  sign2 = getsign(st1_ptr);
+  if ( st0_tag == TAG_Valid )
+    {
+      exponent = exponent(st0_ptr);
+    }
+  else
+    {
+      /* This gives non-compatible stack contents... */
+      FPU_to_exp16(st0_ptr, st0_ptr);
+      exponent = exponent16(st0_ptr);
+    }
+  if ( st1_tag == TAG_Valid )
+    {
+      exponent -= exponent(st1_ptr);
+    }
+  else
+    {
+      /* This gives non-compatible stack contents... */
+      FPU_to_exp16(st1_ptr, st1_ptr);
+      exponent -= exponent16(st1_ptr);
+    }
+
+  if ( (exponent < 0) || ((exponent == 0) &&
+                         ((st0_ptr->sigh < st1_ptr->sigh) ||
+                          ((st0_ptr->sigh == st1_ptr->sigh) &&
+                           (st0_ptr->sigl < st1_ptr->sigl))) ) )
+    {
+      inverted = 1;
+      Numer.lsw = Denom.lsw = 0;
+      XSIG_LL(Numer) = significand(st0_ptr);
+      XSIG_LL(Denom) = significand(st1_ptr);
+    }
+  else
+    {
+      inverted = 0;
+      exponent = -exponent;
+      Numer.lsw = Denom.lsw = 0;
+      XSIG_LL(Numer) = significand(st1_ptr);
+      XSIG_LL(Denom) = significand(st0_ptr);
+     }
+  div_Xsig(&Numer, &Denom, &argSignif);
+  exponent += norm_Xsig(&argSignif);
+
+  if ( (exponent >= -1)
+      || ((exponent == -2) && (argSignif.msw > 0xd413ccd0)) )
+    {
+      /* The argument is greater than sqrt(2)-1 (=0.414213562...) */
+      /* Convert the argument by an identity for atan */
+      transformed = 1;
+
+      if ( exponent >= 0 )
+       {
+#ifdef PARANOID
+         if ( !( (exponent == 0) && 
+                (argSignif.lsw == 0) && (argSignif.midw == 0) &&
+                (argSignif.msw == 0x80000000) ) )
+           {
+             EXCEPTION(EX_INTERNAL|0x104);  /* There must be a logic error */
+             return;
+           }
+#endif /* PARANOID */
+         argSignif.msw = 0;   /* Make the transformed arg -> 0.0 */
+       }
+      else
+       {
+         Numer.lsw = Denom.lsw = argSignif.lsw;
+         XSIG_LL(Numer) = XSIG_LL(Denom) = XSIG_LL(argSignif);
+
+         if ( exponent < -1 )
+           shr_Xsig(&Numer, -1-exponent);
+         negate_Xsig(&Numer);
+      
+         shr_Xsig(&Denom, -exponent);
+         Denom.msw |= 0x80000000;
+      
+         div_Xsig(&Numer, &Denom, &argSignif);
+
+         exponent = -1 + norm_Xsig(&argSignif);
+       }
+    }
+  else
+    {
+      transformed = 0;
+    }
+
+  argSq.lsw = argSignif.lsw; argSq.midw = argSignif.midw;
+  argSq.msw = argSignif.msw;
+  mul_Xsig_Xsig(&argSq, &argSq);
+  
+  argSqSq.lsw = argSq.lsw; argSqSq.midw = argSq.midw; argSqSq.msw = argSq.msw;
+  mul_Xsig_Xsig(&argSqSq, &argSqSq);
+
+  accumulatore.lsw = argSq.lsw;
+  XSIG_LL(accumulatore) = XSIG_LL(argSq);
+
+  shr_Xsig(&argSq, 2*(-1-exponent-1));
+  shr_Xsig(&argSqSq, 4*(-1-exponent-1));
+
+  /* Now have argSq etc with binary point at the left
+     .1xxxxxxxx */
+
+  /* Do the basic fixed point polynomial evaluation */
+  accumulator.msw = accumulator.midw = accumulator.lsw = 0;
+  polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq),
+                  oddplterms, HIPOWERop-1);
+  mul64_Xsig(&accumulator, &XSIG_LL(argSq));
+  negate_Xsig(&accumulator);
+  polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq), oddnegterms, HIPOWERon-1);
+  negate_Xsig(&accumulator);
+  add_two_Xsig(&accumulator, &fixedpterm, &dummy_exp);
+
+  mul64_Xsig(&accumulatore, &denomterm);
+  shr_Xsig(&accumulatore, 1 + 2*(-1-exponent));
+  accumulatore.msw |= 0x80000000;
+
+  div_Xsig(&accumulator, &accumulatore, &accumulator);
+
+  mul_Xsig_Xsig(&accumulator, &argSignif);
+  mul_Xsig_Xsig(&accumulator, &argSq);
+
+  shr_Xsig(&accumulator, 3);
+  negate_Xsig(&accumulator);
+  add_Xsig_Xsig(&accumulator, &argSignif);
+
+  if ( transformed )
+    {
+      /* compute pi/4 - accumulator */
+      shr_Xsig(&accumulator, -1-exponent);
+      negate_Xsig(&accumulator);
+      add_Xsig_Xsig(&accumulator, &pi_signif);
+      exponent = -1;
+    }
+
+  if ( inverted )
+    {
+      /* compute pi/2 - accumulator */
+      shr_Xsig(&accumulator, -exponent);
+      negate_Xsig(&accumulator);
+      add_Xsig_Xsig(&accumulator, &pi_signif);
+      exponent = 0;
+    }
+
+  if ( sign1 )
+    {
+      /* compute pi - accumulator */
+      shr_Xsig(&accumulator, 1 - exponent);
+      negate_Xsig(&accumulator);
+      add_Xsig_Xsig(&accumulator, &pi_signif);
+      exponent = 1;
+    }
+
+  exponent += round_Xsig(&accumulator);
+
+  significand(st1_ptr) = XSIG_LL(accumulator);
+  setexponent16(st1_ptr, exponent);
+
+  tag = FPU_round(st1_ptr, 1, 0, FULL_PRECISION, sign2);
+  FPU_settagi(1, tag);
+
+
+  set_precision_flag_up();  /* We do not really know if up or down,
+                              use this as the default. */
+
+}
diff --git a/sid/component/bochs/cpu/fpu/poly_l2.c b/sid/component/bochs/cpu/fpu/poly_l2.c
new file mode 100644 (file)
index 0000000..26e4393
--- /dev/null
@@ -0,0 +1,272 @@
+/*---------------------------------------------------------------------------+
+ |  poly_l2.c                                                                |
+ |                                                                           |
+ | Compute the base 2 log of a FPU_REG, using a polynomial approximation.    |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+
+#include "exception.h"
+#include "reg_constant.h"
+#include "fpu_emu.h"
+#include "fpu_system.h"
+#include "control_w.h"
+#include "poly.h"
+
+
+static void log2_kernel(FPU_REG const *arg, u_char argsign,
+                       Xsig *accum_result, s32 *expon);
+
+
+/*--- poly_l2() -------------------------------------------------------------+
+ |   Base 2 logarithm by a polynomial approximation.                         |
+ +---------------------------------------------------------------------------*/
+void   poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign)
+{
+  s32         exponent, expon, expon_expon;
+  Xsig         accumulator, expon_accum, yaccum;
+  u_char       sign, argsign;
+  FPU_REG      x;
+  int          tag;
+
+  exponent = exponent16(st0_ptr);
+
+  /* From st0_ptr, make a number > sqrt(2)/2 and < sqrt(2) */
+  if ( st0_ptr->sigh > (unsigned)0xb504f334 )
+    {
+      /* Treat as  sqrt(2)/2 < st0_ptr < 1 */
+      significand(&x) = - significand(st0_ptr);
+      setexponent16(&x, -1);
+      exponent++;
+      argsign = SIGN_NEG;
+    }
+  else
+    {
+      /* Treat as  1 <= st0_ptr < sqrt(2) */
+      x.sigh = st0_ptr->sigh - 0x80000000;
+      x.sigl = st0_ptr->sigl;
+      setexponent16(&x, 0);
+      argsign = SIGN_POS;
+    }
+  tag = FPU_normalize_nuo(&x, 0);
+
+  if ( tag == TAG_Zero )
+    {
+      expon = 0;
+      accumulator.msw = accumulator.midw = accumulator.lsw = 0;
+    }
+  else
+    {
+      log2_kernel(&x, argsign, &accumulator, &expon);
+    }
+
+  if ( exponent < 0 )
+    {
+      sign = SIGN_NEG;
+      exponent = -exponent;
+    }
+  else
+    sign = SIGN_POS;
+  expon_accum.msw = exponent; expon_accum.midw = expon_accum.lsw = 0;
+  if ( exponent )
+    {
+      expon_expon = 31 + norm_Xsig(&expon_accum);
+      shr_Xsig(&accumulator, expon_expon - expon);
+
+      if ( sign ^ argsign )
+       negate_Xsig(&accumulator);
+      add_Xsig_Xsig(&accumulator, &expon_accum);
+    }
+  else
+    {
+      expon_expon = expon;
+      sign = argsign;
+    }
+
+  yaccum.lsw = 0; XSIG_LL(yaccum) = significand(st1_ptr);
+  mul_Xsig_Xsig(&accumulator, &yaccum);
+
+  expon_expon += round_Xsig(&accumulator);
+
+  if ( accumulator.msw == 0 )
+    {
+      FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
+      return;
+    }
+
+  significand(st1_ptr) = XSIG_LL(accumulator);
+  setexponent16(st1_ptr, expon_expon + exponent16(st1_ptr) + 1);
+
+  tag = FPU_round(st1_ptr, 1, 0, FULL_PRECISION, sign ^ st1_sign);
+  FPU_settagi(1, tag);
+
+  set_precision_flag_up();  /* 80486 appears to always do this */
+
+  return;
+
+}
+
+
+/*--- poly_l2p1() -----------------------------------------------------------+
+ |   Base 2 logarithm by a polynomial approximation.                         |
+ |   log2(x+1)                                                               |
+ +---------------------------------------------------------------------------*/
+int    poly_l2p1(u_char sign0, u_char sign1,
+                 FPU_REG *st0_ptr, FPU_REG *st1_ptr, FPU_REG *dest)
+{
+  u_char               tag;
+  s32          exponent;
+  Xsig                 accumulator, yaccum;
+
+  if ( exponent16(st0_ptr) < 0 )
+    {
+      log2_kernel(st0_ptr, sign0, &accumulator, &exponent);
+
+      yaccum.lsw = 0;
+      XSIG_LL(yaccum) = significand(st1_ptr);
+      mul_Xsig_Xsig(&accumulator, &yaccum);
+
+      exponent += round_Xsig(&accumulator);
+
+      exponent += exponent16(st1_ptr) + 1;
+      if ( exponent < EXP_WAY_UNDER ) exponent = EXP_WAY_UNDER;
+
+      significand(dest) = XSIG_LL(accumulator);
+      setexponent16(dest, exponent);
+
+      tag = FPU_round(dest, 1, 0, FULL_PRECISION, sign0 ^ sign1);
+      FPU_settagi(1, tag);
+
+      if ( tag == TAG_Valid )
+       set_precision_flag_up();   /* 80486 appears to always do this */
+    }
+  else
+    {
+      /* The magnitude of st0_ptr is far too large. */
+
+      if ( sign0 != SIGN_POS )
+       {
+         /* Trying to get the log of a negative number. */
+#ifdef PECULIAR_486   /* Stupid 80486 doesn't worry about log(negative). */
+         changesign(st1_ptr);
+#else
+         if ( arith_invalid(1) < 0 )
+           return 1;
+#endif /* PECULIAR_486 */
+       }
+
+      /* 80486 appears to do this */
+      if ( sign0 == SIGN_NEG )
+       set_precision_flag_down();
+      else
+       set_precision_flag_up();
+    }
+
+  if ( exponent(dest) <= EXP_UNDER )
+    EXCEPTION(EX_Underflow);
+
+  return 0;
+
+}
+
+
+
+
+#undef HIPOWER
+#define        HIPOWER 10
+static const u64 logterms[HIPOWER] =
+{
+  BX_CONST64(0x2a8eca5705fc2ef0),
+  BX_CONST64(0xf6384ee1d01febce),
+  BX_CONST64(0x093bb62877cdf642),
+  BX_CONST64(0x006985d8a9ec439b),
+  BX_CONST64(0x0005212c4f55a9c8),
+  BX_CONST64(0x00004326a16927f0),
+  BX_CONST64(0x0000038d1d80a0e7),
+  BX_CONST64(0x0000003141cc80c6),
+  BX_CONST64(0x00000002b1668c9f),
+  BX_CONST64(0x000000002c7a46aa)
+};
+
+static const u32 leadterm = 0xb8000000;
+
+
+/*--- log2_kernel() ---------------------------------------------------------+
+ |   Base 2 logarithm by a polynomial approximation.                         |
+ |   log2(x+1)                                                               |
+ +---------------------------------------------------------------------------*/
+static void log2_kernel(FPU_REG const *arg, u_char argsign, Xsig *accum_result,
+                       s32 *expon)
+{
+  s32    exponent, adj;
+  u64    Xsq;
+  Xsig   accumulator, Numer, Denom, argSignif, arg_signif;
+
+  exponent = exponent16(arg);
+  Numer.lsw = Denom.lsw = 0;
+  XSIG_LL(Numer) = XSIG_LL(Denom) = significand(arg);
+  if ( argsign == SIGN_POS )
+    {
+      shr_Xsig(&Denom, 2 - (1 + exponent));
+      Denom.msw |= 0x80000000;
+      div_Xsig(&Numer, &Denom, &argSignif);
+    }
+  else
+    {
+      shr_Xsig(&Denom, 1 - (1 + exponent));
+      negate_Xsig(&Denom);
+      if ( Denom.msw & 0x80000000 )
+       {
+         div_Xsig(&Numer, &Denom, &argSignif);
+         exponent ++;
+       }
+      else
+       {
+         /* Denom must be 1.0 */
+         argSignif.lsw = Numer.lsw; argSignif.midw = Numer.midw;
+         argSignif.msw = Numer.msw;
+       }
+    }
+
+#ifndef PECULIAR_486
+  /* Should check here that  |local_arg|  is within the valid range */
+  if ( exponent >= -2 )
+    {
+      if ( (exponent > -2) ||
+         (argSignif.msw > (unsigned)0xafb0ccc0) )
+       {
+         /* The argument is too large */
+       }
+    }
+#endif /* PECULIAR_486 */
+
+  arg_signif.lsw = argSignif.lsw; XSIG_LL(arg_signif) = XSIG_LL(argSignif);
+  adj = norm_Xsig(&argSignif);
+  accumulator.lsw = argSignif.lsw; XSIG_LL(accumulator) = XSIG_LL(argSignif);
+  mul_Xsig_Xsig(&accumulator, &accumulator);
+  shr_Xsig(&accumulator, 2*(-1 - (1 + exponent + adj)));
+  Xsq = XSIG_LL(accumulator);
+  if ( accumulator.lsw & 0x80000000 )
+    Xsq++;
+
+  accumulator.msw = accumulator.midw = accumulator.lsw = 0;
+  /* Do the basic fixed point polynomial evaluation */
+  polynomial_Xsig(&accumulator, &Xsq, logterms, HIPOWER-1);
+
+  mul_Xsig_Xsig(&accumulator, &argSignif);
+  shr_Xsig(&accumulator, 6 - adj);
+
+  mul32_Xsig(&arg_signif, leadterm);
+  add_two_Xsig(&accumulator, &arg_signif, &exponent);
+
+  *expon = exponent + 1;
+  accum_result->lsw = accumulator.lsw;
+  accum_result->midw = accumulator.midw;
+  accum_result->msw = accumulator.msw;
+
+}
diff --git a/sid/component/bochs/cpu/fpu/poly_sin.c b/sid/component/bochs/cpu/fpu/poly_sin.c
new file mode 100644 (file)
index 0000000..71a63f2
--- /dev/null
@@ -0,0 +1,397 @@
+/*---------------------------------------------------------------------------+
+ |  poly_sin.c                                                               |
+ |                                                                           |
+ |  Computation of an approximation of the sin function and the cosine       |
+ |  function by a polynomial.                                                |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997,1999                                    |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@melbpc.org.au                             |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+
+#include "exception.h"
+#include "reg_constant.h"
+#include "fpu_emu.h"
+#include "fpu_system.h"
+#include "control_w.h"
+#include "poly.h"
+
+
+#define        N_COEFF_P       4
+#define        N_COEFF_N       4
+
+static const u64 pos_terms_l[N_COEFF_P] =
+{
+  BX_CONST64(0xaaaaaaaaaaaaaaab),
+  BX_CONST64(0x00d00d00d00cf906),
+  BX_CONST64(0x000006b99159a8bb),
+  BX_CONST64(0x000000000d7392e6)
+};
+
+static const u64 neg_terms_l[N_COEFF_N] =
+{
+  BX_CONST64(0x2222222222222167),
+  BX_CONST64(0x0002e3bc74aab624),
+  BX_CONST64(0x0000000b09229062),
+  BX_CONST64(0x00000000000c7973)
+};
+
+
+
+#define        N_COEFF_PH      4
+#define        N_COEFF_NH      4
+static const u64 pos_terms_h[N_COEFF_PH] =
+{
+  BX_CONST64(0x0000000000000000),
+  BX_CONST64(0x05b05b05b05b0406),
+  BX_CONST64(0x000049f93edd91a9),
+  BX_CONST64(0x00000000c9c9ed62)
+};
+
+static const u64 neg_terms_h[N_COEFF_NH] =
+{
+  BX_CONST64(0xaaaaaaaaaaaaaa98),
+  BX_CONST64(0x001a01a01a019064),
+  BX_CONST64(0x0000008f76c68a77),
+  BX_CONST64(0x0000000000d58f5e)
+};
+
+
+/*--- poly_sine() -----------------------------------------------------------+
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+void   poly_sine(FPU_REG *st0_ptr)
+{
+  int       exponent, echange;
+  Xsig      accumulator, argSqrd, argTo4;
+  s32       fix_up, adj;
+  u64       fixed_arg;
+  FPU_REG   result;
+
+  exponent = exponent(st0_ptr);
+
+  accumulator.lsw = accumulator.midw = accumulator.msw = 0;
+
+  /* Split into two ranges, for arguments below and above 1.0 */
+  /* The boundary between upper and lower is approx 0.88309101259 */
+  if ( (exponent < -1) || ((exponent == -1) && (st0_ptr->sigh <= 0xe21240aa)) )
+    {
+      /* The argument is <= 0.88309101259 */
+
+      argSqrd.msw = st0_ptr->sigh; argSqrd.midw = st0_ptr->sigl; argSqrd.lsw = 0;
+      mul64_Xsig(&argSqrd, &significand(st0_ptr));
+      shr_Xsig(&argSqrd, 2*(-1-exponent));
+      argTo4.msw = argSqrd.msw; argTo4.midw = argSqrd.midw;
+      argTo4.lsw = argSqrd.lsw;
+      mul_Xsig_Xsig(&argTo4, &argTo4);
+
+      polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_l,
+                     N_COEFF_N-1);
+      mul_Xsig_Xsig(&accumulator, &argSqrd);
+      negate_Xsig(&accumulator);
+
+      polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_l,
+                     N_COEFF_P-1);
+
+      shr_Xsig(&accumulator, 2);    /* Divide by four */
+      accumulator.msw |= 0x80000000;  /* Add 1.0 */
+
+      mul64_Xsig(&accumulator, &significand(st0_ptr));
+      mul64_Xsig(&accumulator, &significand(st0_ptr));
+      mul64_Xsig(&accumulator, &significand(st0_ptr));
+
+      /* Divide by four, FPU_REG compatible, etc */
+      exponent = 3*exponent;
+
+      /* The minimum exponent difference is 3 */
+      shr_Xsig(&accumulator, exponent(st0_ptr) - exponent);
+
+      negate_Xsig(&accumulator);
+      XSIG_LL(accumulator) += significand(st0_ptr);
+
+      echange = round_Xsig(&accumulator);
+
+      setexponentpos(&result, exponent(st0_ptr) + echange);
+    }
+  else
+    {
+      /* The argument is > 0.88309101259 */
+      /* We use sin(st(0)) = cos(pi/2-st(0)) */
+
+      fixed_arg = significand(st0_ptr);
+
+      if ( exponent == 0 )
+       {
+         /* The argument is >= 1.0 */
+
+         /* Put the binary point at the left. */
+         fixed_arg <<= 1;
+       }
+      /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
+      fixed_arg = BX_CONST64(0x921fb54442d18469) - fixed_arg;
+      /* There is a special case which arises due to rounding, to fix here. */
+      if ( fixed_arg == BX_CONST64(0xffffffffffffffff))
+       fixed_arg = 0;
+
+      XSIG_LL(argSqrd) = fixed_arg; argSqrd.lsw = 0;
+      mul64_Xsig(&argSqrd, &fixed_arg);
+
+      XSIG_LL(argTo4) = XSIG_LL(argSqrd); argTo4.lsw = argSqrd.lsw;
+      mul_Xsig_Xsig(&argTo4, &argTo4);
+
+      polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_h,
+                     N_COEFF_NH-1);
+      mul_Xsig_Xsig(&accumulator, &argSqrd);
+      negate_Xsig(&accumulator);
+
+      polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_h,
+                     N_COEFF_PH-1);
+      negate_Xsig(&accumulator);
+
+      mul64_Xsig(&accumulator, &fixed_arg);
+      mul64_Xsig(&accumulator, &fixed_arg);
+
+      shr_Xsig(&accumulator, 3);
+      negate_Xsig(&accumulator);
+
+      add_Xsig_Xsig(&accumulator, &argSqrd);
+
+      shr_Xsig(&accumulator, 1);
+
+      accumulator.lsw |= 1;  /* A zero accumulator here would cause problems */
+      negate_Xsig(&accumulator);
+
+      /* The basic computation is complete. Now fix the answer to
+        compensate for the error due to the approximation used for
+        pi/2
+        */
+
+      /* This has an exponent of -65 */
+      fix_up = 0x898cc517;
+      /* The fix-up needs to be improved for larger args */
+      if ( argSqrd.msw & 0xffc00000 )
+       {
+         /* Get about 32 bit precision in these: */
+         fix_up -= mul_32_32(0x898cc517, argSqrd.msw) / 6;
+       }
+      fix_up = mul_32_32(fix_up, LL_MSW(fixed_arg));
+
+      adj = accumulator.lsw;    /* temp save */
+      accumulator.lsw -= fix_up;
+      if ( accumulator.lsw > adj )
+       XSIG_LL(accumulator) --;
+
+      echange = round_Xsig(&accumulator);
+
+      setexponentpos(&result, echange - 1);
+    }
+
+  significand(&result) = XSIG_LL(accumulator);
+  setsign(&result, getsign(st0_ptr));
+  FPU_copy_to_reg0(&result, TAG_Valid);
+
+#ifdef PARANOID
+  if ( (exponent(&result) >= 0)
+      && (significand(&result) > BX_CONST64(0x8000000000000000)) )
+    {
+      EXCEPTION(EX_INTERNAL|0x150);
+    }
+#endif /* PARANOID */
+
+}
+
+
+
+/*--- poly_cos() ------------------------------------------------------------+
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+void   poly_cos(FPU_REG *st0_ptr)
+{
+  FPU_REG    result;
+  s32        exponent, exp2, echange;
+  Xsig       accumulator, argSqrd, fix_up, argTo4;
+  u64        fixed_arg;
+
+#ifdef PARANOID
+  if ( (exponent(st0_ptr) > 0)
+      || ((exponent(st0_ptr) == 0)
+         && (significand(st0_ptr) > BX_CONST64(0xc90fdaa22168c234))) )
+    {
+      EXCEPTION(EX_Invalid);
+      FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
+      return;
+    }
+#endif /* PARANOID */
+
+  exponent = exponent(st0_ptr);
+
+  accumulator.lsw = accumulator.midw = accumulator.msw = 0;
+
+  if ( (exponent < -1) || ((exponent == -1) && (st0_ptr->sigh <= 0xb00d6f54)) )
+    {
+      /* arg is < 0.687705 */
+
+      argSqrd.msw = st0_ptr->sigh; argSqrd.midw = st0_ptr->sigl;
+      argSqrd.lsw = 0;
+      mul64_Xsig(&argSqrd, &significand(st0_ptr));
+
+      if ( exponent < -1 )
+       {
+         /* shift the argument right by the required places */
+         shr_Xsig(&argSqrd, 2*(-1-exponent));
+       }
+
+      argTo4.msw = argSqrd.msw; argTo4.midw = argSqrd.midw;
+      argTo4.lsw = argSqrd.lsw;
+      mul_Xsig_Xsig(&argTo4, &argTo4);
+
+      polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_h,
+                     N_COEFF_NH-1);
+      mul_Xsig_Xsig(&accumulator, &argSqrd);
+      negate_Xsig(&accumulator);
+
+      polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_h,
+                     N_COEFF_PH-1);
+      negate_Xsig(&accumulator);
+
+      mul64_Xsig(&accumulator, &significand(st0_ptr));
+      mul64_Xsig(&accumulator, &significand(st0_ptr));
+      shr_Xsig(&accumulator, -2*(1+exponent));
+
+      shr_Xsig(&accumulator, 3);
+      negate_Xsig(&accumulator);
+
+      add_Xsig_Xsig(&accumulator, &argSqrd);
+
+      shr_Xsig(&accumulator, 1);
+
+      /* It doesn't matter if accumulator is all zero here, the
+        following code will work ok */
+      negate_Xsig(&accumulator);
+
+      if ( accumulator.lsw & 0x80000000 )
+       XSIG_LL(accumulator) ++;
+      if ( accumulator.msw == 0 )
+       {
+         /* The result is 1.0 */
+         FPU_copy_to_reg0(&CONST_1, TAG_Valid);
+         return;
+       }
+      else
+       {
+         significand(&result) = XSIG_LL(accumulator);
+      
+         /* will be a valid positive nr with expon = -1 */
+         setexponentpos(&result, -1);
+       }
+    }
+  else
+    {
+      fixed_arg = significand(st0_ptr);
+
+      if ( exponent == 0 )
+       {
+         /* The argument is >= 1.0 */
+
+         /* Put the binary point at the left. */
+         fixed_arg <<= 1;
+       }
+      /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
+      fixed_arg = BX_CONST64(0x921fb54442d18469) - fixed_arg;
+      /* There is a special case which arises due to rounding, to fix here. */
+      if ( fixed_arg == BX_CONST64(0xffffffffffffffff))
+       fixed_arg = 0;
+
+      exponent = -1;
+      exp2 = -1;
+
+      /* A shift is needed here only for a narrow range of arguments,
+        i.e. for fixed_arg approx 2^-32, but we pick up more... */
+      if ( !(LL_MSW(fixed_arg) & 0xffff0000) )
+       {
+         fixed_arg <<= 16;
+         exponent -= 16;
+         exp2 -= 16;
+       }
+
+      XSIG_LL(argSqrd) = fixed_arg; argSqrd.lsw = 0;
+      mul64_Xsig(&argSqrd, &fixed_arg);
+
+      if ( exponent < -1 )
+       {
+         /* shift the argument right by the required places */
+         shr_Xsig(&argSqrd, 2*(-1-exponent));
+       }
+
+      argTo4.msw = argSqrd.msw; argTo4.midw = argSqrd.midw;
+      argTo4.lsw = argSqrd.lsw;
+      mul_Xsig_Xsig(&argTo4, &argTo4);
+
+      polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_l,
+                     N_COEFF_N-1);
+      mul_Xsig_Xsig(&accumulator, &argSqrd);
+      negate_Xsig(&accumulator);
+
+      polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_l,
+                     N_COEFF_P-1);
+
+      shr_Xsig(&accumulator, 2);    /* Divide by four */
+      accumulator.msw |= 0x80000000;  /* Add 1.0 */
+
+      mul64_Xsig(&accumulator, &fixed_arg);
+      mul64_Xsig(&accumulator, &fixed_arg);
+      mul64_Xsig(&accumulator, &fixed_arg);
+
+      /* Divide by four, FPU_REG compatible, etc */
+      exponent = 3*exponent;
+
+      /* The minimum exponent difference is 3 */
+      shr_Xsig(&accumulator, exp2 - exponent);
+
+      negate_Xsig(&accumulator);
+      XSIG_LL(accumulator) += fixed_arg;
+
+      /* The basic computation is complete. Now fix the answer to
+        compensate for the error due to the approximation used for
+        pi/2
+        */
+
+      /* This has an exponent of -65 */
+      XSIG_LL(fix_up) = BX_CONST64(0x898cc51701b839a2);
+      fix_up.lsw = 0;
+
+      /* The fix-up needs to be improved for larger args */
+      if ( argSqrd.msw & 0xffc00000 )
+       {
+         /* Get about 32 bit precision in these: */
+         fix_up.msw -= mul_32_32(0x898cc517, argSqrd.msw) / 2;
+         fix_up.msw += mul_32_32(0x898cc517, argTo4.msw) / 24;
+       }
+
+      exp2 += norm_Xsig(&accumulator);
+      shr_Xsig(&accumulator, 1); /* Prevent overflow */
+      exp2++;
+      shr_Xsig(&fix_up, 65 + exp2);
+
+      add_Xsig_Xsig(&accumulator, &fix_up);
+
+      echange = round_Xsig(&accumulator);
+
+      setexponentpos(&result, exp2 + echange);
+      significand(&result) = XSIG_LL(accumulator);
+    }
+
+  FPU_copy_to_reg0(&result, TAG_Valid);
+
+#ifdef PARANOID
+  if ( (exponent(&result) >= 0)
+      && (significand(&result) > BX_CONST64(0x8000000000000000)) )
+    {
+      EXCEPTION(EX_INTERNAL|0x151);
+    }
+#endif /* PARANOID */
+
+}
diff --git a/sid/component/bochs/cpu/fpu/poly_tan.c b/sid/component/bochs/cpu/fpu/poly_tan.c
new file mode 100644 (file)
index 0000000..f7ab00a
--- /dev/null
@@ -0,0 +1,161 @@
+/*---------------------------------------------------------------------------+
+ |  poly_tan.c                                                               |
+ |                                                                           |
+ | Compute the tan of a FPU_REG, using a polynomial approximation.           |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997,1999                                    |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail   billm@melbpc.org.au            |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "reg_constant.h"
+#include "fpu_emu.h"
+#include "fpu_system.h"
+#include "control_w.h"
+#include "poly.h"
+
+//#define DEBUG_POLY_TAN // ***********
+
+#define        HiPOWERop       3       /* odd poly, positive terms */
+static const u64 oddplterm[HiPOWERop] =
+{
+  BX_CONST64(0x0000000000000000),
+  BX_CONST64(0x0051a1cf08fca228),
+  BX_CONST64(0x0000000071284ff7)
+};
+
+#define        HiPOWERon       2       /* odd poly, negative terms */
+static const u64 oddnegterm[HiPOWERon] =
+{
+   BX_CONST64(0x1291a9a184244e80),
+   BX_CONST64(0x0000583245819c21)
+};
+
+#define        HiPOWERep       2       /* even poly, positive terms */
+static const u64 evenplterm[HiPOWERep] =
+{
+  BX_CONST64(0x0e848884b539e888),
+  BX_CONST64(0x00003c7f18b887da)
+};
+
+#define        HiPOWERen       2       /* even poly, negative terms */
+static const u64 evennegterm[HiPOWERen] =
+{
+  BX_CONST64(0xf1f0200fd51569cc),
+  BX_CONST64(0x003afb46105c4432)
+};
+
+static const u64 twothirds = BX_CONST64(0xaaaaaaaaaaaaaaab);
+
+
+/*--- poly_tan() ------------------------------------------------------------+
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+void   poly_tan(FPU_REG *st0_ptr, int invert)
+{
+  s32         exponent;
+  Xsig        argSq, argSqSq, accumulatoro, accumulatore, accum,
+              argSignif;
+
+  exponent = exponent(st0_ptr);
+
+
+#ifdef PARANOID
+  if ( signnegative(st0_ptr) ) /* Can't hack a number < 0.0 */
+    { arith_invalid(0); return; }  /* Need a positive number */
+#endif /* PARANOID */
+
+  if ( (exponent >= 0)
+       || ((exponent == -1) && (st0_ptr->sigh > 0xc90fdaa2)) )
+    {
+    EXCEPTION(0x250);
+    }
+  else
+    {
+      argSignif.lsw = 0;
+      XSIG_LL(accum) = XSIG_LL(argSignif) = significand(st0_ptr);
+      if ( exponent < -1 )
+       {
+         /* shift the argument right by the required places */
+         if ( FPU_shrx(&XSIG_LL(accum), -1-exponent) >= 0x80000000U )
+           XSIG_LL(accum) ++;  /* round up */
+       }
+    }
+
+  XSIG_LL(argSq) = XSIG_LL(accum); argSq.lsw = accum.lsw;
+  mul_Xsig_Xsig(&argSq, &argSq);
+  XSIG_LL(argSqSq) = XSIG_LL(argSq); argSqSq.lsw = argSq.lsw;
+  mul_Xsig_Xsig(&argSqSq, &argSqSq);
+
+  /* Compute the negative terms for the numerator polynomial */
+  accumulatoro.msw = accumulatoro.midw = accumulatoro.lsw = 0;
+  polynomial_Xsig(&accumulatoro, &XSIG_LL(argSqSq), oddnegterm, HiPOWERon-1);
+  mul_Xsig_Xsig(&accumulatoro, &argSq);
+  negate_Xsig(&accumulatoro);
+  /* Add the positive terms */
+  polynomial_Xsig(&accumulatoro, &XSIG_LL(argSqSq), oddplterm, HiPOWERop-1);
+
+  
+  /* Compute the positive terms for the denominator polynomial */
+  accumulatore.msw = accumulatore.midw = accumulatore.lsw = 0;
+  polynomial_Xsig(&accumulatore, &XSIG_LL(argSqSq), evenplterm, HiPOWERep-1);
+  mul_Xsig_Xsig(&accumulatore, &argSq);
+  negate_Xsig(&accumulatore);
+  /* Add the negative terms */
+  polynomial_Xsig(&accumulatore, &XSIG_LL(argSqSq), evennegterm, HiPOWERen-1);
+  /* Multiply by arg^2 */
+  mul64_Xsig(&accumulatore, &XSIG_LL(argSignif));
+  mul64_Xsig(&accumulatore, &XSIG_LL(argSignif));
+  /* de-normalize and divide by 2 */
+  shr_Xsig(&accumulatore, -2*(1+exponent) + 1);
+  negate_Xsig(&accumulatore);      /* This does 1 - accumulator */
+
+  /* Now find the ratio. */
+  if ( accumulatore.msw == 0 )
+    {
+      /* accumulatoro must contain 1.0 here, (actually, 0) but it
+        really doesn't matter what value we use because it will
+        have negligible effect in later calculations
+        */
+      XSIG_LL(accum) = BX_CONST64(0x8000000000000000);
+      accum.lsw = 0;
+    }
+  else
+    {
+      div_Xsig(&accumulatoro, &accumulatore, &accum);
+    }
+
+  /* Multiply by 1/3 * arg^3 */
+  mul64_Xsig(&accum, &XSIG_LL(argSignif));
+  mul64_Xsig(&accum, &XSIG_LL(argSignif));
+  mul64_Xsig(&accum, &XSIG_LL(argSignif));
+  mul64_Xsig(&accum, &twothirds);
+  shr_Xsig(&accum, -2*(exponent+1));
+
+
+  /* tan(arg) = arg + accum */
+  add_two_Xsig(&accum, &argSignif, &exponent);
+
+  if ( invert )
+    {
+      /* accum now contains tan(pi/2 - arg).
+        Use tan(arg) = 1.0 / tan(pi/2 - arg)
+        */
+      accumulatoro.lsw = accumulatoro.midw = 0;
+      accumulatoro.msw = 0x80000000;
+      div_Xsig(&accumulatoro, &accum, &accum);
+      exponent = - exponent;
+    }
+
+
+  /* Transfer the result */
+  exponent += round_Xsig(&accum);
+  FPU_settag0(TAG_Valid);
+  significand(st0_ptr) = XSIG_LL(accum);
+  setexponent16(st0_ptr, exponent + EXTENDED_Ebias);  /* Result is positive. */
+
+}
diff --git a/sid/component/bochs/cpu/fpu/polynom_Xsig.S b/sid/component/bochs/cpu/fpu/polynom_Xsig.S
new file mode 100644 (file)
index 0000000..7829503
--- /dev/null
@@ -0,0 +1,142 @@
+/*---------------------------------------------------------------------------+
+ |  polynomial_Xsig.S                                                        |
+ |                                                                           |
+ | Fixed point arithmetic polynomial evaluation.                             |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1995,1999                                    |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@melbpc.org.au              |
+ |                                                                           |
+ | Call from C as:                                                           |
+ |   void polynomial_Xsig(Xsig *accum, unsigned long long *x,                |
+ |                        unsigned long long terms[], int n)                 |
+ |                                                                           |
+ | Computes:                                                                 |
+ | terms[0] + (terms[1] + (terms[2] + ... + (terms[n]*x)*x)*x)*x) ... )*x    |
+ | and adds the result to the 12 byte Xsig.                                  |
+ | The terms[] are each 8 bytes, but all computation is performed to 12 byte |
+ | precision.                                                                |
+ |                                                                           |
+ | This function must be used carefully: most overflow of intermediate       |
+ | results is controlled, but overflow of the result is not.                 |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+       .file   "polynomial_Xsig.S"
+
+#include "fpu_emu.h"
+
+
+#define        TERM_SIZE       $8
+#define        SUM_MS          -20(%ebp)       /* sum ms long */
+#define SUM_MIDDLE     -24(%ebp)       /* sum middle long */
+#define        SUM_LS          -28(%ebp)       /* sum ls long */
+#define        ACCUM_MS        -4(%ebp)        /* accum ms long */
+#define        ACCUM_MIDDLE    -8(%ebp)        /* accum middle long */
+#define        ACCUM_LS        -12(%ebp)       /* accum ls long */
+#define OVERFLOWED      -16(%ebp)      /* addition overflow flag */
+
+.text
+ENTRY(polynomial_Xsig)
+       pushl   %ebp
+       movl    %esp,%ebp
+       subl    $32,%esp
+       pushl   %esi
+       pushl   %edi
+       pushl   %ebx
+
+       movl    PARAM2,%esi             /* x */
+       movl    PARAM3,%edi             /* terms */
+
+       movl    TERM_SIZE,%eax
+       mull    PARAM4                  /* n */
+       addl    %eax,%edi
+
+       movl    4(%edi),%edx            /* terms[n] */
+       movl    %edx,SUM_MS
+       movl    (%edi),%edx             /* terms[n] */
+       movl    %edx,SUM_MIDDLE
+       xor     %eax,%eax
+       movl    %eax,SUM_LS
+       movb    %al,OVERFLOWED
+
+       subl    TERM_SIZE,%edi
+       decl    PARAM4
+       js      L_accum_done
+
+L_accum_loop:
+       xor     %eax,%eax
+       movl    %eax,ACCUM_MS
+       movl    %eax,ACCUM_MIDDLE
+
+       movl    SUM_MIDDLE,%eax
+       mull    (%esi)                  /* x ls long */
+       movl    %edx,ACCUM_LS
+
+       movl    SUM_LS,%eax
+       mull    4(%esi)                 /* x ms long */
+       addl    %edx,ACCUM_LS
+       adcl    $0,ACCUM_MIDDLE
+       adcl    $0,ACCUM_MS
+
+       movl    SUM_MIDDLE,%eax
+       mull    4(%esi)                 /* x ms long */
+       addl    %eax,ACCUM_LS
+       adcl    %edx,ACCUM_MIDDLE
+       adcl    $0,ACCUM_MS
+
+       movl    SUM_MS,%eax
+       mull    (%esi)                  /* x ls long */
+       addl    %eax,ACCUM_LS
+       adcl    %edx,ACCUM_MIDDLE
+       adcl    $0,ACCUM_MS
+
+       movl    SUM_MS,%eax
+       mull    4(%esi)                 /* x ms long */
+       addl    %eax,ACCUM_MIDDLE
+       adcl    %edx,ACCUM_MS
+
+       testb   $0xff,OVERFLOWED
+       jz      L_no_overflow
+
+       movl    (%esi),%eax
+       addl    %eax,ACCUM_MIDDLE
+       movl    4(%esi),%eax
+       adcl    %eax,ACCUM_MS           /* This could overflow too */
+
+L_no_overflow:
+
+/*
+ * Now put the sum of next term and the accumulator
+ * into the sum register
+ */
+       movl    ACCUM_LS,%eax
+//     addl    (%edi),%eax             /* term ls long */
+       movl    %eax,SUM_LS
+       movl    ACCUM_MIDDLE,%eax
+//     adcl    (%edi),%eax             /* term ls long */
+       addl    (%edi),%eax             /* term ls long */
+       movl    %eax,SUM_MIDDLE
+       movl    ACCUM_MS,%eax
+       adcl    4(%edi),%eax            /* term ms long */
+       movl    %eax,SUM_MS
+       sbbb    %al,%al
+       movb    %al,OVERFLOWED          /* Used in the next iteration */
+
+       subl    TERM_SIZE,%edi
+       decl    PARAM4
+       jns     L_accum_loop
+
+L_accum_done:
+       movl    PARAM1,%edi             /* accum */
+       movl    SUM_LS,%eax
+       addl    %eax,(%edi)
+       movl    SUM_MIDDLE,%eax
+       adcl    %eax,4(%edi)
+       movl    SUM_MS,%eax
+       adcl    %eax,8(%edi)
+
+       popl    %ebx
+       popl    %edi
+       popl    %esi
+       leave
+       ret
diff --git a/sid/component/bochs/cpu/fpu/polynom_Xsig.c b/sid/component/bochs/cpu/fpu/polynom_Xsig.c
new file mode 100644 (file)
index 0000000..6cce9e0
--- /dev/null
@@ -0,0 +1,132 @@
+/*---------------------------------------------------------------------------+
+ |  polynomial_Xsig.c                                                        |
+ |                                                                           |
+ | Fixed point arithmetic polynomial evaluation.                             |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1995,1999                                    |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@melbpc.org.au              |
+ |                                                                           |
+ | Computes:                                                                 |
+ | terms[0] + (terms[1] + (terms[2] + ... + (terms[n]*x)*x)*x)*x) ... )*x    |
+ | and adds the result to the 12 byte Xsig.                                  |
+ | The terms[] are each 8 bytes, but all computation is performed to 12 byte |
+ | precision.                                                                |
+ |                                                                           |
+ | This function must be used carefully: most overflow of intermediate       |
+ | results is controlled, but overflow of the result is not.                 |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_emu.h"
+#include "poly.h"
+
+
+void polynomial_Xsig(Xsig *accum, const u64 *x, const u64 terms[], const int n)
+{
+  int  i;
+  Xsig acc, Xprod;
+  u32  lprod;
+  u64  xlwr, xupr, prod;
+  char overflowed;
+
+  xlwr = (u32)(*x);
+  xupr = (u32)((*x) >> 32);
+
+  acc.msw = terms[n] >> 32;
+  acc.midw = terms[n];
+  acc.lsw = 0;
+  overflowed = 0;
+
+  for ( i = n-1; i >= 0; i-- )
+    {
+      /* Split the product into five parts to get a 16 byte result */
+
+      /* first word by first word */
+      prod = acc.msw * xupr;
+      Xprod.midw = prod;
+      Xprod.msw = prod >> 32;
+
+      /* first word by second word */
+      prod = acc.msw * xlwr;
+      Xprod.lsw = prod;
+      lprod = prod >> 32;
+      Xprod.midw += lprod;
+      if ( lprod > Xprod.midw )
+       Xprod.msw ++;
+
+      /* second word by first word */
+      prod = acc.midw * xupr;
+      Xprod.lsw += prod;
+      if ( (u32)prod > Xprod.lsw )
+       {
+         Xprod.midw ++;
+         if ( Xprod.midw == 0 )
+           Xprod.msw ++;
+       }
+      lprod = prod >> 32;
+      Xprod.midw += lprod;
+      if ( lprod > Xprod.midw )
+       Xprod.msw ++;
+
+      /* second word by second word */
+      prod = acc.midw * xlwr;
+      lprod = prod >> 32;
+      Xprod.lsw += lprod;
+      if ( lprod > Xprod.lsw )
+       {
+         Xprod.midw ++;
+         if ( Xprod.midw == 0 )
+           Xprod.msw ++;
+       }
+
+      /* third word by first word */
+      prod = acc.lsw * xupr;
+      lprod = prod >> 32;
+      Xprod.lsw += lprod;
+      if ( lprod > Xprod.lsw )
+       {
+         Xprod.midw ++;
+         if ( Xprod.midw == 0 )
+           Xprod.msw ++;
+       }
+
+      if ( overflowed )
+       {
+         Xprod.midw += xlwr;
+         if ( (u32)xlwr > Xprod.midw )
+           Xprod.msw ++;
+         Xprod.msw += xupr;
+         overflowed = 0;    /* We don't check this addition for overflow */
+       }
+      
+      acc.lsw = Xprod.lsw;
+      acc.midw = (u32)terms[i] + Xprod.midw;
+      acc.msw = (terms[i] >> 32) + Xprod.msw;
+      if ( Xprod.msw > acc.msw )
+       overflowed = 1;
+      if ( (u32)terms[i] > acc.midw )
+       {
+         acc.msw ++;
+         if ( acc.msw == 0 )
+           overflowed = 1;
+       }
+    }
+
+  /* We don't check the addition to accum for overflow */
+  accum->lsw += acc.lsw;
+  if ( acc.lsw > accum->lsw )
+    {
+      accum->midw ++;
+      if ( accum->midw == 0 )
+       accum->msw ++;
+    }
+  accum->midw += acc.midw;
+  if ( acc.midw > accum->midw )
+    {
+      accum->msw ++;
+    }
+  accum->msw += acc.msw;
+}
+
+
diff --git a/sid/component/bochs/cpu/fpu/reg_add_sub.c b/sid/component/bochs/cpu/fpu/reg_add_sub.c
new file mode 100644 (file)
index 0000000..5b507a1
--- /dev/null
@@ -0,0 +1,380 @@
+/*---------------------------------------------------------------------------+
+ |  reg_add_sub.c                                                            |
+ |                                                                           |
+ | Functions to add or subtract two registers and put the result in a third. |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1997                                              |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ |  For each function, the destination may be any FPU_REG, including one of  |
+ | the source FPU_REGs.                                                      |
+ |  Each function returns 0 if the answer is o.k., otherwise a non-zero      |
+ | value is returned, indicating either an exception condition or an         |
+ | internal error.                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "reg_constant.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+#include "fpu_system.h"
+
+static
+int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa,
+                    FPU_REG const *b, u_char tagb, u_char signb,
+                    FPU_REG *dest, int deststnr, u16 control_w);
+
+/*
+  Operates on st(0) and st(n), or on st(0) and temporary data.
+  The destination must be one of the source st(x).
+  */
+int FPU_add(FPU_REG const *b, u_char tagb, int deststnr, u16 control_w)
+{
+  FPU_REG *a = &st(0);
+  FPU_REG *dest = &st(deststnr);
+  u_char signb = getsign(b);
+  u_char taga = FPU_gettag0();
+  u_char signa = getsign(a);
+  u_char saved_sign = getsign(dest);
+  int diff, tag, expa, expb;
+  
+  if ( !(taga | tagb) )
+    {
+      expa = exponent(a);
+      expb = exponent(b);
+
+    valid_add:
+      /* Both registers are valid */
+      if (!(signa ^ signb))
+       {
+         /* signs are the same */
+         tag = FPU_u_add(a, b, dest, control_w, signa, expa, expb);
+       }
+      else
+       {
+         /* The signs are different, so do a subtraction */
+         diff = expa - expb;
+         if (!diff)
+           {
+             diff = a->sigh - b->sigh;  /* This works only if the ms bits
+                                           are identical. */
+             if (!diff)
+               {
+                 diff = a->sigl > b->sigl;
+                 if (!diff)
+                   diff = -(a->sigl < b->sigl);
+               }
+           }
+      
+         if (diff > 0)
+           {
+             tag = FPU_u_sub(a, b, dest, control_w, signa, expa, expb);
+           }
+         else if ( diff < 0 )
+           {
+             tag = FPU_u_sub(b, a, dest, control_w, signb, expb, expa);
+           }
+         else
+           {
+             FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
+             /* sign depends upon rounding mode */
+             setsign(dest, ((control_w & CW_RC) != RC_DOWN)
+                     ? SIGN_POS : SIGN_NEG);
+             return TAG_Zero;
+           }
+       }
+
+      if ( tag < 0 )
+       {
+         setsign(dest, saved_sign);
+         return tag;
+       }
+      FPU_settagi(deststnr, tag);
+      return tag;
+    }
+
+  if ( taga == TAG_Special )
+    taga = FPU_Special(a);
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+
+  if ( ((taga == TAG_Valid) && (tagb == TW_Denormal))
+           || ((taga == TW_Denormal) && (tagb == TAG_Valid))
+           || ((taga == TW_Denormal) && (tagb == TW_Denormal)) )
+    {
+      FPU_REG x, y;
+
+      if ( denormal_operand() < 0 )
+       return FPU_Exception;
+
+      FPU_to_exp16(a, &x);
+      FPU_to_exp16(b, &y);
+      a = &x;
+      b = &y;
+      expa = exponent16(a);
+      expb = exponent16(b);
+      goto valid_add;
+    }
+
+  if ( (taga == TW_NaN) || (tagb == TW_NaN) )
+    {
+      if ( deststnr == 0 )
+       return real_2op_NaN(b, tagb, deststnr, a);
+      else
+       return real_2op_NaN(a, taga, deststnr, a);
+    }
+
+  return add_sub_specials(a, taga, signa, b, tagb, signb,
+                         dest, deststnr, control_w);
+}
+
+
+/* Subtract b from a.  (a-b) -> dest
+ bbd: arg2 used to be int type, but sometimes pointers were forced
+ in with typecasts.  On Alphas pointers are 64 bits and ints are 32,
+ so when rm was cast back to a pointer...SEGFAULT.  Pass the pointers
+ around instead, since they are always larger precision than the
+ register numbers. */
+int FPU_sub(int flags, FPU_REG *rm, u16 control_w)
+{
+  FPU_REG const *a, *b;
+  FPU_REG *dest;
+  u_char taga, tagb, signa, signb, saved_sign, sign;
+  int diff, tag, expa, expb, deststnr;
+
+  a = &st(0);
+  taga = FPU_gettag0();
+
+  deststnr = 0;
+  if ( flags & LOADED )
+    {
+      b = rm;
+      tagb = flags & 0x0f;
+    }
+  else
+    {
+      int rmint = PTR2INT(rm);
+      b = &st(rmint);
+      tagb = FPU_gettagi(rmint);
+
+      if ( flags & DEST_RM )
+       deststnr = rmint;
+    }
+
+  signa = getsign(a);
+  signb = getsign(b);
+
+  if ( flags & REV )
+    {
+      signa ^= SIGN_NEG;
+      signb ^= SIGN_NEG;
+    }
+
+  dest = &st(deststnr);
+  saved_sign = getsign(dest);
+
+  if ( !(taga | tagb) )
+    {
+      expa = exponent(a);
+      expb = exponent(b);
+
+    valid_subtract:
+      /* Both registers are valid */
+
+      diff = expa - expb;
+
+      if (!diff)
+       {
+         diff = a->sigh - b->sigh;  /* Works only if ms bits are identical */
+         if (!diff)
+           {
+             diff = a->sigl > b->sigl;
+             if (!diff)
+               diff = -(a->sigl < b->sigl);
+           }
+       }
+
+      switch ( (((int)signa)*2 + signb) / SIGN_NEG )
+       {
+       case 0: /* P - P */
+       case 3: /* N - N */
+         if (diff > 0)
+           {
+             /* |a| > |b| */
+             tag = FPU_u_sub(a, b, dest, control_w, signa, expa, expb);
+           }
+         else if ( diff == 0 )
+           {
+             FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
+
+             /* sign depends upon rounding mode */
+             setsign(dest, ((control_w & CW_RC) != RC_DOWN)
+               ? SIGN_POS : SIGN_NEG);
+             return TAG_Zero;
+           }
+         else
+           {
+             sign = signa ^ SIGN_NEG;
+             tag = FPU_u_sub(b, a, dest, control_w, sign, expb, expa);
+           }
+         break;
+       case 1: /* P - N */
+         tag = FPU_u_add(a, b, dest, control_w, SIGN_POS, expa, expb);
+         break;
+       case 2: /* N - P */
+         tag = FPU_u_add(a, b, dest, control_w, SIGN_NEG, expa, expb);
+         break;
+#ifdef PARANOID
+       default:
+         EXCEPTION(EX_INTERNAL|0x111);
+         return -1;
+#endif
+       }
+      if ( tag < 0 )
+       {
+         setsign(dest, saved_sign);
+         return tag;
+       }
+      FPU_settagi(deststnr, tag);
+      return tag;
+    }
+
+  if ( taga == TAG_Special )
+    taga = FPU_Special(a);
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+
+  if ( ((taga == TAG_Valid) && (tagb == TW_Denormal))
+           || ((taga == TW_Denormal) && (tagb == TAG_Valid))
+           || ((taga == TW_Denormal) && (tagb == TW_Denormal)) )
+    {
+      FPU_REG x, y;
+
+      if ( denormal_operand() < 0 )
+       return FPU_Exception;
+
+      FPU_to_exp16(a, &x);
+      FPU_to_exp16(b, &y);
+      a = &x;
+      b = &y;
+      expa = exponent16(a);
+      expb = exponent16(b);
+
+      goto valid_subtract;
+    }
+
+  if ( (taga == TW_NaN) || (tagb == TW_NaN) )
+    {
+      FPU_REG const *d1, *d2;
+      if ( flags & REV )
+       {
+         d1 = b;
+         d2 = a;
+       }
+      else
+       {
+         d1 = a;
+         d2 = b;
+       }
+      if ( flags & LOADED )
+       return real_2op_NaN(b, tagb, deststnr, d1);
+      if ( flags & DEST_RM )
+       return real_2op_NaN(a, taga, deststnr, d2);
+      else
+       return real_2op_NaN(b, tagb, deststnr, d2);
+    }
+
+    return add_sub_specials(a, taga, signa, b, tagb, signb ^ SIGN_NEG,
+                           dest, deststnr, control_w);
+}
+
+
+static
+int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa,
+                    FPU_REG const *b, u_char tagb, u_char signb,
+                    FPU_REG *dest, int deststnr, u16 control_w)
+{
+  if ( ((taga == TW_Denormal) || (tagb == TW_Denormal))
+       && (denormal_operand() < 0) )
+    return FPU_Exception;
+
+  if (taga == TAG_Zero)
+    {
+      if (tagb == TAG_Zero)
+       {
+         /* Both are zero, result will be zero. */
+         u_char different_signs = signa ^ signb;
+
+         FPU_copy_to_regi(a, TAG_Zero, deststnr);
+         if ( different_signs )
+           {
+             /* Signs are different. */
+             /* Sign of answer depends upon rounding mode. */
+             setsign(dest, ((control_w & CW_RC) != RC_DOWN)
+                     ? SIGN_POS : SIGN_NEG);
+           }
+         else
+           setsign(dest, signa);  /* signa may differ from the sign of a. */
+         return TAG_Zero;
+       }
+      else
+       {
+         reg_copy(b, dest);
+         if ( (tagb == TW_Denormal) && (b->sigh & 0x80000000) )
+           {
+             /* A pseudoDenormal, convert it. */
+             addexponent(dest, 1);
+             tagb = TAG_Valid;
+           }
+         else if ( tagb > TAG_Empty )
+           tagb = TAG_Special;
+         setsign(dest, signb);  /* signb may differ from the sign of b. */
+         FPU_settagi(deststnr, tagb);
+         return tagb;
+       }
+    }
+  else if (tagb == TAG_Zero)
+    {
+      reg_copy(a, dest);
+      if ( (taga == TW_Denormal) && (a->sigh & 0x80000000) )
+       {
+         /* A pseudoDenormal */
+         addexponent(dest, 1);
+         taga = TAG_Valid;
+       }
+      else if ( taga > TAG_Empty )
+       taga = TAG_Special;
+      setsign(dest, signa);  /* signa may differ from the sign of a. */
+      FPU_settagi(deststnr, taga);
+      return taga;
+    }
+  else if (taga == TW_Infinity)
+    {
+      if ( (tagb != TW_Infinity) || (signa == signb) )
+       {
+         FPU_copy_to_regi(a, TAG_Special, deststnr);
+         setsign(dest, signa);  /* signa may differ from the sign of a. */
+         return taga;
+       }
+      /* Infinity-Infinity is undefined. */
+      return arith_invalid(deststnr);
+    }
+  else if (tagb == TW_Infinity)
+    {
+      FPU_copy_to_regi(b, TAG_Special, deststnr);
+      setsign(dest, signb);  /* signb may differ from the sign of b. */
+      return tagb;
+    }
+
+#ifdef PARANOID
+  EXCEPTION(EX_INTERNAL|0x101);
+#endif
+
+  return FPU_Exception;
+}
+
diff --git a/sid/component/bochs/cpu/fpu/reg_compare.c b/sid/component/bochs/cpu/fpu/reg_compare.c
new file mode 100644 (file)
index 0000000..8e3cfa1
--- /dev/null
@@ -0,0 +1,381 @@
+/*---------------------------------------------------------------------------+
+ |  reg_compare.c                                                            |
+ |                                                                           |
+ | Compare two floating point registers                                      |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | compare() is the core FPU_REG comparison function                         |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_system.h"
+#include "exception.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+#include "status_w.h"
+
+
+static int compare(FPU_REG const *b, int tagb)
+{
+  int diff, exp0, expb;
+  u_char               st0_tag;
+  FPU_REG      *st0_ptr;
+  FPU_REG      x, y;
+  u_char               st0_sign, signb = getsign(b);
+
+  st0_ptr = &st(0);
+  st0_tag = FPU_gettag0();
+  st0_sign = getsign(st0_ptr);
+
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+
+  if ( ((st0_tag != TAG_Valid) && (st0_tag != TW_Denormal))
+       || ((tagb != TAG_Valid) && (tagb != TW_Denormal)) )
+    {
+      if ( st0_tag == TAG_Zero )
+       {
+         if ( tagb == TAG_Zero ) return COMP_A_eq_B;
+         if ( tagb == TAG_Valid )
+           return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B);
+         if ( tagb == TW_Denormal )
+           return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
+           | COMP_Denormal;
+       }
+      else if ( tagb == TAG_Zero )
+       {
+         if ( st0_tag == TAG_Valid )
+           return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
+         if ( st0_tag == TW_Denormal )
+           return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
+           | COMP_Denormal;
+       }
+
+      if ( st0_tag == TW_Infinity )
+       {
+         if ( (tagb == TAG_Valid) || (tagb == TAG_Zero) )
+           return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
+         else if ( tagb == TW_Denormal )
+           return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
+             | COMP_Denormal;
+         else if ( tagb == TW_Infinity )
+           {
+             /* The 80486 book says that infinities can be equal! */
+             return (st0_sign == signb) ? COMP_A_eq_B :
+               ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
+           }
+         /* Fall through to the NaN code */
+       }
+      else if ( tagb == TW_Infinity )
+       {
+         if ( (st0_tag == TAG_Valid) || (st0_tag == TAG_Zero) )
+           return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B);
+         if ( st0_tag == TW_Denormal )
+           return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
+               | COMP_Denormal;
+         /* Fall through to the NaN code */
+       }
+
+      /* The only possibility now should be that one of the arguments
+        is a NaN */
+      if ( (st0_tag == TW_NaN) || (tagb == TW_NaN) )
+       {
+         int signalling = 0, unsupported = 0;
+         if ( st0_tag == TW_NaN )
+           {
+             signalling = (st0_ptr->sigh & 0xc0000000) == 0x80000000;
+             unsupported = !((exponent(st0_ptr) == EXP_OVER)
+                             && (st0_ptr->sigh & 0x80000000));
+           }
+         if ( tagb == TW_NaN )
+           {
+             signalling |= (b->sigh & 0xc0000000) == 0x80000000;
+             unsupported |= !((exponent(b) == EXP_OVER)
+                              && (b->sigh & 0x80000000));
+           }
+         if ( signalling || unsupported )
+           return COMP_No_Comp | COMP_SNaN | COMP_NaN;
+         else
+           /* Neither is a signaling NaN */
+           return COMP_No_Comp | COMP_NaN;
+       }
+      
+      EXCEPTION(EX_Invalid);
+    }
+  
+  if (st0_sign != signb)
+    {
+      return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
+       | ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
+           COMP_Denormal : 0);
+    }
+
+  if ( (st0_tag == TW_Denormal) || (tagb == TW_Denormal) )
+    {
+      FPU_to_exp16(st0_ptr, &x);
+      FPU_to_exp16(b, &y);
+      st0_ptr = &x;
+      b = &y;
+      exp0 = exponent16(st0_ptr);
+      expb = exponent16(b);
+    }
+  else
+    {
+      exp0 = exponent(st0_ptr);
+      expb = exponent(b);
+    }
+
+#ifdef PARANOID
+  if (!(st0_ptr->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
+  if (!(b->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
+#endif /* PARANOID */
+
+  diff = exp0 - expb;
+  if ( diff == 0 )
+    {
+      diff = st0_ptr->sigh - b->sigh;  /* Works only if ms bits are
+                                             identical */
+      if ( diff == 0 )
+       {
+       diff = st0_ptr->sigl > b->sigl;
+       if ( diff == 0 )
+         diff = -(st0_ptr->sigl < b->sigl);
+       }
+    }
+
+  if ( diff > 0 )
+    {
+      return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
+       | ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
+           COMP_Denormal : 0);
+    }
+  if ( diff < 0 )
+    {
+      return ((st0_sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
+       | ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
+           COMP_Denormal : 0);
+    }
+
+  return COMP_A_eq_B
+    | ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
+       COMP_Denormal : 0);
+
+}
+
+
+/* This function requires that st(0) is not empty */
+int FPU_compare_st_data(FPU_REG const *loaded_data, u_char loaded_tag)
+{
+  int f, c;
+
+  c = compare(loaded_data, loaded_tag);
+
+  if (c & COMP_NaN)
+    {
+      EXCEPTION(EX_Invalid);
+      f = SW_C3 | SW_C2 | SW_C0;
+    }
+  else
+    switch (c & 7)
+      {
+      case COMP_A_lt_B:
+       f = SW_C0;
+       break;
+      case COMP_A_eq_B:
+       f = SW_C3;
+       break;
+      case COMP_A_gt_B:
+       f = 0;
+       break;
+      case COMP_No_Comp:
+       f = SW_C3 | SW_C2 | SW_C0;
+       break;
+#ifdef PARANOID
+      default:
+       EXCEPTION(EX_INTERNAL|0x121);
+       f = SW_C3 | SW_C2 | SW_C0;
+       break;
+#endif /* PARANOID */
+      }
+  setcc(f);
+  if (c & COMP_Denormal)
+    {
+      return denormal_operand() < 0;
+    }
+  return 0;
+}
+
+
+static int compare_st_st(int nr)
+{
+  int f, c;
+  FPU_REG *st_ptr;
+
+  if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) )
+    {
+      setcc(SW_C3 | SW_C2 | SW_C0);
+      /* Stack fault */
+      EXCEPTION(EX_StackUnder);
+      return !(control_word & CW_Invalid);
+    }
+
+  st_ptr = &st(nr);
+  c = compare(st_ptr, FPU_gettagi(nr));
+  if (c & COMP_NaN)
+    {
+      setcc(SW_C3 | SW_C2 | SW_C0);
+      EXCEPTION(EX_Invalid);
+      return !(control_word & CW_Invalid);
+    }
+  else
+    switch (c & 7)
+      {
+      case COMP_A_lt_B:
+       f = SW_C0;
+       break;
+      case COMP_A_eq_B:
+       f = SW_C3;
+       break;
+      case COMP_A_gt_B:
+       f = 0;
+       break;
+      case COMP_No_Comp:
+       f = SW_C3 | SW_C2 | SW_C0;
+       break;
+#ifdef PARANOID
+      default:
+       EXCEPTION(EX_INTERNAL|0x122);
+       f = SW_C3 | SW_C2 | SW_C0;
+       break;
+#endif /* PARANOID */
+      }
+  setcc(f);
+  if (c & COMP_Denormal)
+    {
+      return denormal_operand() < 0;
+    }
+  return 0;
+}
+
+
+static int compare_u_st_st(int nr)
+{
+  int f, c;
+  FPU_REG *st_ptr;
+
+  if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) )
+    {
+      setcc(SW_C3 | SW_C2 | SW_C0);
+      /* Stack fault */
+      EXCEPTION(EX_StackUnder);
+      return !(control_word & CW_Invalid);
+    }
+
+  st_ptr = &st(nr);
+  c = compare(st_ptr, FPU_gettagi(nr));
+  if (c & COMP_NaN)
+    {
+      setcc(SW_C3 | SW_C2 | SW_C0);
+      if (c & COMP_SNaN)       /* This is the only difference between
+                                 un-ordered and ordinary comparisons */
+       {
+         EXCEPTION(EX_Invalid);
+         return !(control_word & CW_Invalid);
+       }
+      return 0;
+    }
+  else
+    switch (c & 7)
+      {
+      case COMP_A_lt_B:
+       f = SW_C0;
+       break;
+      case COMP_A_eq_B:
+       f = SW_C3;
+       break;
+      case COMP_A_gt_B:
+       f = 0;
+       break;
+      case COMP_No_Comp:
+       f = SW_C3 | SW_C2 | SW_C0;
+       break;
+#ifdef PARANOID
+      default:
+       EXCEPTION(EX_INTERNAL|0x123);
+       f = SW_C3 | SW_C2 | SW_C0;
+       break;
+#endif /* PARANOID */
+      }
+  setcc(f);
+  if (c & COMP_Denormal)
+    {
+      return denormal_operand() < 0;
+    }
+  return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+void fcom_st()
+{
+  /* fcom st(i) */
+  compare_st_st(FPU_rm);
+}
+
+
+void fcompst()
+{
+  /* fcomp st(i) */
+  if ( !compare_st_st(FPU_rm) )
+    FPU_pop();
+}
+
+
+void fcompp()
+{
+  /* fcompp */
+  if (FPU_rm != 1)
+    {
+      FPU_illegal();
+      return;
+    }
+  if ( !compare_st_st(1) )
+      poppop();
+}
+
+
+void fucom_()
+{
+  /* fucom st(i) */
+  compare_u_st_st(FPU_rm);
+
+}
+
+
+void fucomp()
+{
+  /* fucomp st(i) */
+  if ( !compare_u_st_st(FPU_rm) )
+    FPU_pop();
+}
+
+
+void fucompp()
+{
+  /* fucompp */
+  if (FPU_rm == 1)
+    {
+      if ( !compare_u_st_st(1) )
+       poppop();
+    }
+  else
+    FPU_illegal();
+}
diff --git a/sid/component/bochs/cpu/fpu/reg_constant.c b/sid/component/bochs/cpu/fpu/reg_constant.c
new file mode 100644 (file)
index 0000000..1d60636
--- /dev/null
@@ -0,0 +1,119 @@
+/*---------------------------------------------------------------------------+
+ |  reg_constant.c                                                           |
+ |                                                                           |
+ | All of the constant FPU_REGs                                              |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                     W. Metzenthen, 22 Parker St, Ormond, Vic 3163,        |
+ |                     Australia.  E-mail   billm@suburbia.net               |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_system.h"
+#include "fpu_emu.h"
+#include "status_w.h"
+#include "reg_constant.h"
+#include "control_w.h"
+
+
+
+FPU_REG const CONST_1    = MAKE_REG(POS, 0, 0x00000000, 0x80000000);
+FPU_REG const CONST_2    = MAKE_REG(POS, 1, 0x00000000, 0x80000000);
+FPU_REG const CONST_HALF = MAKE_REG(POS, -1, 0x00000000, 0x80000000);
+FPU_REG const CONST_L2T  = MAKE_REG(POS, 1, 0xcd1b8afe, 0xd49a784b);
+FPU_REG const CONST_L2E  = MAKE_REG(POS, 0, 0x5c17f0bc, 0xb8aa3b29);
+FPU_REG const CONST_PI   = MAKE_REG(POS, 1, 0x2168c235, 0xc90fdaa2);
+// bbd: make CONST_PI2 non-const so that you can write "&CONST_PI2" when
+// calling a function.  Otherwise you get const warnings.  Surely there's
+// a better way.
+FPU_REG CONST_PI2  = MAKE_REG(POS, 0, 0x2168c235, 0xc90fdaa2);
+FPU_REG const CONST_PI4  = MAKE_REG(POS, -1, 0x2168c235, 0xc90fdaa2);
+FPU_REG const CONST_LG2  = MAKE_REG(POS, -2, 0xfbcff799, 0x9a209a84);
+FPU_REG const CONST_LN2  = MAKE_REG(POS, -1, 0xd1cf79ac, 0xb17217f7);
+
+/* Extra bits to take pi/2 to more than 128 bits precision. */
+FPU_REG const CONST_PI2extra = MAKE_REG(NEG, -66,
+                                        0xfc8f8cbb, 0xece675d1);
+
+/* Only the sign (and tag) is used in internal zeroes */
+FPU_REG const CONST_Z    = MAKE_REG(POS, EXP_UNDER, 0x0, 0x0);
+
+/* Only the sign and significand (and tag) are used in internal NaNs */
+/* The 80486 never generates one of these 
+FPU_REG const CONST_SNAN = MAKE_REG(POS, EXP_OVER, 0x00000001, 0x80000000);
+ */
+/* This is the real indefinite QNaN */
+FPU_REG const CONST_QNaN = MAKE_REG(NEG, EXP_OVER, 0x00000000, 0xC0000000);
+
+/* Only the sign (and tag) is used in internal infinities */
+FPU_REG const CONST_INF  = MAKE_REG(POS, EXP_OVER, 0x00000000, 0x80000000);
+
+
+static void fld_const(FPU_REG const *c, int adj, u_char tag)
+{
+  FPU_REG *st_new_ptr;
+
+  if ( STACK_OVERFLOW )
+    {
+      FPU_stack_overflow();
+      return;
+    }
+  push();
+  reg_copy(c, st_new_ptr);
+  st_new_ptr->sigl += adj;  /* For all our fldxxx constants, we don't need to
+                              borrow or carry. */
+  FPU_settag0(tag);
+  clear_C1();
+}
+
+/* A fast way to find out whether x is one of RC_DOWN or RC_CHOP
+   (and not one of RC_RND or RC_UP).
+   */
+#define DOWN_OR_CHOP(x)  (x & RC_DOWN)
+
+static void fld1(int rc)
+{
+  fld_const(&CONST_1, 0, TAG_Valid);
+}
+
+static void fldl2t(int rc)
+{
+  fld_const(&CONST_L2T, (rc == RC_UP) ? 1 : 0, TAG_Valid);
+}
+
+static void fldl2e(int rc)
+{
+  fld_const(&CONST_L2E, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid);
+}
+
+static void fldpi(int rc)
+{
+  fld_const(&CONST_PI, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid);
+}
+
+static void fldlg2(int rc)
+{
+  fld_const(&CONST_LG2, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid);
+}
+
+static void fldln2(int rc)
+{
+  fld_const(&CONST_LN2, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid);
+}
+
+static void fldz(int rc)
+{
+  fld_const(&CONST_Z, 0, TAG_Zero);
+}
+
+typedef void (*FUNC_RC)(int);
+
+static FUNC_RC constants_table[] = {
+  fld1, fldl2t, fldl2e, fldpi, fldlg2, fldln2, fldz, (FUNC_RC)FPU_illegal
+};
+
+void fconst(void)
+{
+  (constants_table[FPU_rm])(control_word & CW_RC);
+}
diff --git a/sid/component/bochs/cpu/fpu/reg_constant.h b/sid/component/bochs/cpu/fpu/reg_constant.h
new file mode 100644 (file)
index 0000000..f16aaec
--- /dev/null
@@ -0,0 +1,34 @@
+/*---------------------------------------------------------------------------+
+ |  reg_constant.h                                                           |
+ |                                                                           |
+ | Copyright (C) 1992    W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#ifndef _REG_CONSTANT_H_
+#define _REG_CONSTANT_H_
+
+#include "fpu_emu.h"
+
+extern FPU_REG const CONST_1;
+extern FPU_REG const CONST_2;
+extern FPU_REG const CONST_HALF;
+extern FPU_REG const CONST_L2T;
+extern FPU_REG const CONST_L2E;
+extern FPU_REG const CONST_PI;
+// bbd: make CONST_PI2 non-const so that you can write "&CONST_PI2" when
+// calling a function.  Otherwise you get const warnings.  Surely there's
+// a better way.
+extern FPU_REG CONST_PI2;
+extern FPU_REG const CONST_PI2extra;
+extern FPU_REG const CONST_PI4;
+extern FPU_REG const CONST_LG2;
+extern FPU_REG const CONST_LN2;
+extern FPU_REG const CONST_Z;
+extern FPU_REG const CONST_PINF;
+extern FPU_REG const CONST_INF;
+extern FPU_REG const CONST_MINF;
+extern FPU_REG const CONST_QNaN;
+
+#endif /* _REG_CONSTANT_H_ */
diff --git a/sid/component/bochs/cpu/fpu/reg_convert.c b/sid/component/bochs/cpu/fpu/reg_convert.c
new file mode 100644 (file)
index 0000000..1c285ee
--- /dev/null
@@ -0,0 +1,57 @@
+/*---------------------------------------------------------------------------+
+ |  reg_convert.c                                                            |
+ |                                                                           |
+ |  Convert register representation.                                         |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1996,1997                                    |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "fpu_emu.h"
+
+
+int FPU_to_exp16(FPU_REG const *a, FPU_REG *x)
+{
+  int sign = getsign(a);
+
+#ifndef EMU_BIG_ENDIAN
+  *(s64 *)&(x->sigl) = *(const s64 *)&(a->sigl);
+#else
+  *(s64 *)&(x->sigh) = *(const s64 *)&(a->sigh);
+#endif
+
+  /* Set up the exponent as a 16 bit quantity. */
+  setexponent16(x, exponent(a));
+
+  if ( exponent16(x) == EXP_UNDER )
+    {
+      /* The number is a de-normal or pseudodenormal. */
+      /* We only deal with the significand and exponent. */
+
+      if (x->sigh & 0x80000000)
+       {
+         /* Is a pseudodenormal. */
+         /* This is non-80486 behaviour because the number
+            loses its 'denormal' identity. */
+         addexponent(x, 1);
+       }
+      else
+       {
+         /* Is a denormal. */
+         addexponent(x, 1);
+          FPU_normalize_nuo(x, 0);
+       }
+    }
+
+  if ( !(x->sigh & 0x80000000) )
+    {
+      EXCEPTION(EX_INTERNAL | 0x180);
+    }
+
+  return sign;
+}
+
diff --git a/sid/component/bochs/cpu/fpu/reg_divide.c b/sid/component/bochs/cpu/fpu/reg_divide.c
new file mode 100644 (file)
index 0000000..11be79d
--- /dev/null
@@ -0,0 +1,208 @@
+/*---------------------------------------------------------------------------+
+ |  reg_divide.c                                                             |
+ |                                                                           |
+ | Divide one FPU_REG by another and put the result in a destination FPU_REG.|
+ |                                                                           |
+ | Copyright (C) 1996                                                        |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@jacobi.maths.monash.edu.au                |
+ |                                                                           |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | The destination may be any FPU_REG, including one of the source FPU_REGs. |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "reg_constant.h"
+#include "fpu_emu.h"
+#include "fpu_system.h"
+
+/*
+  Divide one register by another and put the result into a third register.
+bbd: arg2 used to be an int, see comments on FPU_sub.
+  */
+int FPU_div(int flags, FPU_REG *rm, int control_w)
+{
+  FPU_REG x, y;
+  FPU_REG const *a, *b, *st0_ptr, *st_ptr;
+  FPU_REG *dest;
+  u_char taga, tagb, signa, signb, sign, saved_sign;
+  int tag, deststnr;
+  int rmint = PTR2INT(rm);
+
+  if ( flags & DEST_RM )
+    deststnr = rmint;
+  else
+    deststnr = 0;
+
+  if ( flags & REV )
+    {
+      b = &st(0);
+      st0_ptr = b;
+      tagb = FPU_gettag0();
+      if ( flags & LOADED )
+       {
+         a = rm;
+         taga = flags & 0x0f;
+       }
+      else
+       {
+         a = &st(rmint);
+         st_ptr = a;
+         taga = FPU_gettagi(rmint);
+       }
+    }
+  else
+    {
+      a = &st(0);
+      st0_ptr = a;
+      taga = FPU_gettag0();
+      if ( flags & LOADED )
+       {
+         b = rm;
+         tagb = flags & 0x0f;
+       }
+      else
+       {
+         b = &st(rmint);
+         st_ptr = b;
+         tagb = FPU_gettagi(rmint);
+       }
+    }
+
+  signa = getsign(a);
+  signb = getsign(b);
+
+  sign = signa ^ signb;
+
+  dest = &st(deststnr);
+  saved_sign = getsign(dest);
+
+  if ( !(taga | tagb) )
+    {
+      /* Both regs Valid, this should be the most common case. */
+      reg_copy(a, &x);
+      reg_copy(b, &y);
+      setpositive(&x);
+      setpositive(&y);
+      tag = FPU_u_div(&x, &y, dest, control_w, sign);
+
+      if ( tag < 0 )
+       return tag;
+
+      FPU_settagi(deststnr, tag);
+      return tag;
+    }
+
+  if ( taga == TAG_Special )
+    taga = FPU_Special(a);
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+
+  if ( ((taga == TAG_Valid) && (tagb == TW_Denormal))
+           || ((taga == TW_Denormal) && (tagb == TAG_Valid))
+           || ((taga == TW_Denormal) && (tagb == TW_Denormal)) )
+    {
+      if ( denormal_operand() < 0 )
+       return FPU_Exception;
+
+      FPU_to_exp16(a, &x);
+      FPU_to_exp16(b, &y);
+      tag = FPU_u_div(&x, &y, dest, control_w, sign);
+      if ( tag < 0 )
+       return tag;
+
+      FPU_settagi(deststnr, tag);
+      return tag;
+    }
+  else if ( (taga <= TW_Denormal) && (tagb <= TW_Denormal) )
+    {
+      if ( tagb != TAG_Zero )
+       {
+         /* Want to find Zero/Valid */
+         if ( tagb == TW_Denormal )
+           {
+             if ( denormal_operand() < 0 )
+               return FPU_Exception;
+           }
+
+         /* The result is zero. */
+         FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
+         setsign(dest, sign);
+         return TAG_Zero;
+       }
+      /* We have an exception condition, either 0/0 or Valid/Zero. */
+      if ( taga == TAG_Zero )
+       {
+         /* 0/0 */
+         return arith_invalid(deststnr);
+       }
+      /* Valid/Zero */
+      return FPU_divide_by_zero(deststnr, sign);
+    }
+  /* Must have infinities, NaNs, etc */
+  else if ( (taga == TW_NaN) || (tagb == TW_NaN) )
+    {
+      if ( flags & LOADED )
+       return real_2op_NaN((FPU_REG *)rm, flags & 0x0f, 0, st0_ptr);
+
+      if ( flags & DEST_RM )
+       {
+         int tag;
+         tag = FPU_gettag0();
+         if ( tag == TAG_Special )
+           tag = FPU_Special(st0_ptr);
+         return real_2op_NaN(st0_ptr, tag, rmint, (flags & REV) ? st0_ptr : &st(rmint));
+       }
+      else
+       {
+         int tag;
+         tag = FPU_gettagi(rmint);
+         if ( tag == TAG_Special )
+           tag = FPU_Special(&st(rmint));
+         return real_2op_NaN(&st(rmint), tag, 0, (flags & REV) ? st0_ptr : &st(rmint));
+       }
+    }
+  else if (taga == TW_Infinity)
+    {
+      if (tagb == TW_Infinity)
+       {
+         /* infinity/infinity */
+         return arith_invalid(deststnr);
+       }
+      else
+       {
+         /* tagb must be Valid or Zero */
+         if ( (tagb == TW_Denormal) && (denormal_operand() < 0) )
+           return FPU_Exception;
+         
+         /* Infinity divided by Zero or Valid does
+            not raise and exception, but returns Infinity */
+         FPU_copy_to_regi(a, TAG_Special, deststnr);
+         setsign(dest, sign);
+         return taga;
+       }
+    }
+  else if (tagb == TW_Infinity)
+    {
+      if ( (taga == TW_Denormal) && (denormal_operand() < 0) )
+       return FPU_Exception;
+
+      /* The result is zero. */
+      FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
+      setsign(dest, sign);
+      return TAG_Zero;
+    }
+#ifdef PARANOID
+  else
+    {
+      EXCEPTION(EX_INTERNAL|0x102);
+      return FPU_Exception;
+    }
+#endif /* PARANOID */
+
+}
diff --git a/sid/component/bochs/cpu/fpu/reg_ld_str.c b/sid/component/bochs/cpu/fpu/reg_ld_str.c
new file mode 100644 (file)
index 0000000..fb2cec0
--- /dev/null
@@ -0,0 +1,1460 @@
+/*---------------------------------------------------------------------------+
+ |  reg_ld_str.c                                                             |
+ |                                                                           |
+ | All of the functions which transfer data between user memory and FPU_REGs.|
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1996,1997                                    |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | Note:                                                                     |
+ |    The file contains code which accesses user memory.                     |
+ |    Emulator static data may change when user memory is accessed, due to   |
+ |    other processes using the emulator while swapping is in progress.      |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_emu.h"
+
+#include <asm/uaccess.h>
+
+#include "fpu_system.h"
+#include "exception.h"
+#include "reg_constant.h"
+#include "control_w.h"
+#include "status_w.h"
+
+
+#define DOUBLE_Emax 1023         /* largest valid exponent */
+#define DOUBLE_Ebias 1023
+#define DOUBLE_Emin (-1022)      /* smallest valid exponent */
+
+#define SINGLE_Emax 127          /* largest valid exponent */
+#define SINGLE_Ebias 127
+#define SINGLE_Emin (-126)       /* smallest valid exponent */
+
+
+static u_char normalize_no_excep(FPU_REG *r, int exp, int sign)
+{
+  u_char tag;
+
+  setexponent16(r, exp);
+
+  tag = FPU_normalize_nuo(r, 0);
+  stdexp(r);
+  if ( sign )
+    setnegative(r);
+
+  return tag;
+}
+
+
+int FPU_tagof(FPU_REG *ptr)
+{
+  int exp;
+
+  exp = exponent16(ptr) & 0x7fff;
+  if ( exp == 0 )
+    {
+      if ( !(ptr->sigh | ptr->sigl) )
+       {
+         return TAG_Zero;
+       }
+      /* The number is a de-normal or pseudodenormal. */
+      return TAG_Special;
+    }
+
+  if ( exp == 0x7fff )
+    {
+      /* Is an Infinity, a NaN, or an unsupported data type. */
+      return TAG_Special;
+    }
+
+  if ( !(ptr->sigh & 0x80000000) )
+    {
+      /* Unsupported data type. */
+      /* Valid numbers have the ms bit set to 1. */
+      /* Unnormal. */
+      return TAG_Special;
+    }
+
+  return TAG_Valid;
+}
+
+
+/* Get a long double from user memory */
+int FPU_load_extended(long double *s, int stnr)
+{
+  FPU_REG *sti_ptr = &st(stnr);
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_READ, s, 10);
+#ifndef USE_WITH_CPU_SIM
+  __copy_from_user(sti_ptr, s, 10);
+#else
+  FPU_get_user(sti_ptr->sigl, (u32*)(((u8*)s)+0));
+  FPU_get_user(sti_ptr->sigh, (u32*)(((u8*)s)+4));
+  FPU_get_user(sti_ptr->exp,  (u16*)(((u8*)s)+8));
+#endif
+  RE_ENTRANT_CHECK_ON;
+
+  return FPU_tagof(sti_ptr);
+}
+
+
+/* Get a double from user memory */
+int FPU_load_double(double *dfloat, FPU_REG *loaded_data)
+{
+  int exp, tag, negative;
+  u32 m64, l64;
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_READ, dfloat, 8);
+  FPU_get_user(m64, 1 + (u32 *) dfloat);
+  FPU_get_user(l64, (u32 *) dfloat);
+  RE_ENTRANT_CHECK_ON;
+
+  negative = (m64 & 0x80000000) ? SIGN_Negative : SIGN_Positive;
+  exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias + EXTENDED_Ebias;
+  m64 &= 0xfffff;
+  if ( exp > DOUBLE_Emax + EXTENDED_Ebias )
+    {
+      /* Infinity or NaN */
+      if ((m64 == 0) && (l64 == 0))
+       {
+         /* +- infinity */
+         loaded_data->sigh = 0x80000000;
+         loaded_data->sigl = 0x00000000;
+         exp = EXP_Infinity + EXTENDED_Ebias;
+         tag = TAG_Special;
+       }
+      else
+       {
+         /* Must be a signaling or quiet NaN */
+         exp = EXP_NaN + EXTENDED_Ebias;
+         loaded_data->sigh = (m64 << 11) | 0x80000000;
+         loaded_data->sigh |= l64 >> 21;
+         loaded_data->sigl = l64 << 11;
+         tag = TAG_Special;    /* The calling function must look for NaNs */
+       }
+    }
+  else if ( exp < DOUBLE_Emin + EXTENDED_Ebias )
+    {
+      /* Zero or de-normal */
+      if ((m64 == 0) && (l64 == 0))
+       {
+         /* Zero */
+         reg_copy(&CONST_Z, loaded_data);
+         exp = 0;
+         tag = TAG_Zero;
+       }
+      else
+       {
+         /* De-normal */
+         loaded_data->sigh = m64 << 11;
+         loaded_data->sigh |= l64 >> 21;
+         loaded_data->sigl = l64 << 11;
+
+         return normalize_no_excep(loaded_data, DOUBLE_Emin, negative)
+           | (denormal_operand() < 0 ? FPU_Exception : 0);
+       }
+    }
+  else
+    {
+      loaded_data->sigh = (m64 << 11) | 0x80000000;
+      loaded_data->sigh |= l64 >> 21;
+      loaded_data->sigl = l64 << 11;
+
+      tag = TAG_Valid;
+    }
+
+  setexponent16(loaded_data, exp | negative);
+
+  return tag;
+}
+
+
+/* Get a float from user memory */
+int FPU_load_single(float *single, FPU_REG *loaded_data)
+{
+  u32 m32;
+  int exp, tag, negative;
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_READ, single, 4);
+  FPU_get_user(m32, (u32 *) single);
+  RE_ENTRANT_CHECK_ON;
+
+  negative = (m32 & 0x80000000) ? SIGN_Negative : SIGN_Positive;
+
+  if (!(m32 & 0x7fffffff))
+    {
+      /* Zero */
+      reg_copy(&CONST_Z, loaded_data);
+      addexponent(loaded_data, negative);
+      return TAG_Zero;
+    }
+  exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias + EXTENDED_Ebias;
+  m32 = (m32 & 0x7fffff) << 8;
+  if ( exp < SINGLE_Emin + EXTENDED_Ebias )
+    {
+      /* De-normals */
+      loaded_data->sigh = m32;
+      loaded_data->sigl = 0;
+
+      return normalize_no_excep(loaded_data, SINGLE_Emin, negative)
+       | (denormal_operand() < 0 ? FPU_Exception : 0);
+    }
+  else if ( exp > SINGLE_Emax + EXTENDED_Ebias )
+    {
+    /* Infinity or NaN */
+      if ( m32 == 0 )
+       {
+         /* +- infinity */
+         loaded_data->sigh = 0x80000000;
+         loaded_data->sigl = 0x00000000;
+         exp = EXP_Infinity + EXTENDED_Ebias;
+         tag = TAG_Special;
+       }
+      else
+       {
+         /* Must be a signaling or quiet NaN */
+         exp = EXP_NaN + EXTENDED_Ebias;
+         loaded_data->sigh = m32 | 0x80000000;
+         loaded_data->sigl = 0;
+         tag = TAG_Special;  /* The calling function must look for NaNs */
+       }
+    }
+  else
+    {
+      loaded_data->sigh = m32 | 0x80000000;
+      loaded_data->sigl = 0;
+      tag = TAG_Valid;
+    }
+
+  setexponent16(loaded_data, exp | negative);  /* Set the sign. */
+
+  return tag;
+}
+
+
+/* Get a 64bit quantity from user memory */
+int FPU_load_int64(s64 *_s)
+{
+  s64 s;
+  int sign;
+  FPU_REG *st0_ptr = &st(0);
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_READ, _s, 8);
+#ifndef USE_WITH_CPU_SIM
+  copy_from_user(&s,_s,8);
+#else
+  {
+  u32 chunk0, chunk1;
+  FPU_get_user(chunk0, (u32*)(((u8*)_s)+0));
+  FPU_get_user(chunk1, (u32*)(((u8*)_s)+4));
+  s = chunk0;
+  s |= (((u64)chunk1) << 32);
+  }
+#endif
+  RE_ENTRANT_CHECK_ON;
+
+  if (s == 0)
+    {
+      reg_copy(&CONST_Z, st0_ptr);
+      return TAG_Zero;
+    }
+
+  if (s > 0)
+    sign = SIGN_Positive;
+  else
+  {
+    s = -s;
+    sign = SIGN_Negative;
+  }
+
+  significand(st0_ptr) = s;
+
+  return normalize_no_excep(st0_ptr, 63, sign);
+}
+
+
+/* Get a long from user memory */
+int FPU_load_int32(s32 *_s, FPU_REG *loaded_data)
+{
+  s32 s;
+  int negative;
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_READ, _s, 4);
+  FPU_get_user(s, _s);
+  RE_ENTRANT_CHECK_ON;
+
+  if (s == 0)
+    { reg_copy(&CONST_Z, loaded_data); return TAG_Zero; }
+
+  if (s > 0)
+    negative = SIGN_Positive;
+  else
+    {
+      s = -s;
+      negative = SIGN_Negative;
+    }
+
+  loaded_data->sigh = s;
+  loaded_data->sigl = 0;
+
+  return normalize_no_excep(loaded_data, 31, negative);
+}
+
+
+/* Get a short from user memory */
+int FPU_load_int16(s16 *_s, FPU_REG *loaded_data)
+{
+  int s, negative;
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_READ, _s, 2);
+  /* Cast as short to get the sign extended. */
+  FPU_get_user(s, _s);
+  RE_ENTRANT_CHECK_ON;
+
+  if (s == 0)
+    { reg_copy(&CONST_Z, loaded_data); return TAG_Zero; }
+
+  if (s > 0)
+    negative = SIGN_Positive;
+  else
+    {
+      s = -s;
+      negative = SIGN_Negative;
+    }
+
+  loaded_data->sigh = s << 16;
+  loaded_data->sigl = 0;
+
+  return normalize_no_excep(loaded_data, 15, negative);
+}
+
+
+/* Get a packed bcd array from user memory */
+int FPU_load_bcd(u_char *s)
+{
+  FPU_REG *st0_ptr = &st(0);
+  int pos;
+  u_char bcd;
+  s64 l=0;
+  int sign;
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_READ, s, 10);
+  RE_ENTRANT_CHECK_ON;
+  for ( pos = 8; pos >= 0; pos--)
+    {
+      l *= 10;
+      RE_ENTRANT_CHECK_OFF;
+      FPU_get_user(bcd, (u_char *) s+pos);
+      RE_ENTRANT_CHECK_ON;
+      l += bcd >> 4;
+      l *= 10;
+      l += bcd & 0x0f;
+    }
+  RE_ENTRANT_CHECK_OFF;
+  FPU_get_user(sign, (u_char *) s+9);
+  sign = sign & 0x80 ? SIGN_Negative : SIGN_Positive;
+  RE_ENTRANT_CHECK_ON;
+
+  if ( l == 0 )
+    {
+      reg_copy(&CONST_Z, st0_ptr);
+      addexponent(st0_ptr, sign);   /* Set the sign. */
+      return TAG_Zero;
+    }
+  else
+    {
+      significand(st0_ptr) = l;
+      return normalize_no_excep(st0_ptr, 63, sign);
+    }
+}
+
+/*===========================================================================*/
+
+/* Put a long double into user memory */
+int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double *d)
+{
+  /*
+    The only exception raised by an attempt to store to an
+    extended format is the Invalid Stack exception, i.e.
+    attempting to store from an empty register.
+   */
+
+  if ( st0_tag != TAG_Empty )
+    {
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_WRITE, d, 10);
+
+      FPU_put_user(st0_ptr->sigl, (u32 *) d);
+      FPU_put_user(st0_ptr->sigh, (u32 *) ((u_char *)d + 4));
+      FPU_put_user(exponent16(st0_ptr), (u16 *) ((u_char *)d + 8));
+      RE_ENTRANT_CHECK_ON;
+
+      return 1;
+    }
+
+  /* Empty register (stack underflow) */
+  EXCEPTION(EX_StackUnder);
+  if ( control_word & CW_Invalid )
+    {
+      /* The masked response */
+      /* Put out the QNaN indefinite */
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_WRITE,d,10);
+      FPU_put_user(0, (u32 *) d);
+      FPU_put_user(0xc0000000, 1 + (u32 *) d);
+      FPU_put_user(0xffff, 4 + (s16 *) d);
+      RE_ENTRANT_CHECK_ON;
+      return 1;
+    }
+  else
+    return 0;
+
+}
+
+
+/* Put a double into user memory */
+int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double *dfloat)
+{
+  u32 l[2];
+  u32 increment = 0;   /* avoid gcc warnings */
+  int precision_loss;
+  int exp;
+  FPU_REG tmp;
+
+  if ( st0_tag == TAG_Valid )
+    {
+      reg_copy(st0_ptr, &tmp);
+      exp = exponent(&tmp);
+
+      if ( exp < DOUBLE_Emin )     /* It may be a denormal */
+       {
+         addexponent(&tmp, -DOUBLE_Emin + 52);  /* largest exp to be 51 */
+
+       denormal_arg:
+
+         if ( (precision_loss = FPU_round_to_int(&tmp, st0_tag)) )
+           {
+#ifdef PECULIAR_486
+             /* Did it round to a non-denormal ? */
+             /* This behaviour might be regarded as peculiar, it appears
+                that the 80486 rounds to the dest precision, then
+                converts to decide underflow. */
+             if ( !((tmp.sigh == 0x00100000) && (tmp.sigl == 0) &&
+                 (st0_ptr->sigl & 0x000007ff)) )
+#endif /* PECULIAR_486 */
+               {
+                 EXCEPTION(EX_Underflow);
+                 /* This is a special case: see sec 16.2.5.1 of
+                    the 80486 book */
+                 if ( !(control_word & CW_Underflow) )
+                   return 0;
+               }
+             EXCEPTION(precision_loss);
+             if ( !(control_word & CW_Precision) )
+               return 0;
+           }
+         l[0] = tmp.sigl;
+         l[1] = tmp.sigh;
+       }
+      else
+       {
+         if ( tmp.sigl & 0x000007ff )
+           {
+             precision_loss = 1;
+             switch (control_word & CW_RC)
+               {
+               case RC_RND:
+                 /* Rounding can get a little messy.. */
+                 increment = ((tmp.sigl & 0x7ff) > 0x400) |  /* nearest */
+                   ((tmp.sigl & 0xc00) == 0xc00);            /* odd -> even */
+                 break;
+               case RC_DOWN:   /* towards -infinity */
+                 increment = signpositive(&tmp) ? 0 : tmp.sigl & 0x7ff;
+                 break;
+               case RC_UP:     /* towards +infinity */
+                 increment = signpositive(&tmp) ? tmp.sigl & 0x7ff : 0;
+                 break;
+               case RC_CHOP:
+                 increment = 0;
+                 break;
+               }
+         
+             /* Truncate the mantissa */
+             tmp.sigl &= 0xfffff800;
+         
+             if ( increment )
+               {
+                 if ( tmp.sigl >= 0xfffff800 )
+                   {
+                     /* the sigl part overflows */
+                     if ( tmp.sigh == 0xffffffff )
+                       {
+                         /* The sigh part overflows */
+                         tmp.sigh = 0x80000000;
+                         exp++;
+                         if (exp >= EXP_OVER)
+                           goto overflow;
+                       }
+                     else
+                       {
+                         tmp.sigh ++;
+                       }
+                     tmp.sigl = 0x00000000;
+                   }
+                 else
+                   {
+                     /* We only need to increment sigl */
+                     tmp.sigl += 0x00000800;
+                   }
+               }
+           }
+         else
+           precision_loss = 0;
+         
+         l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21);
+         l[1] = ((tmp.sigh >> 11) & 0xfffff);
+
+         if ( exp > DOUBLE_Emax )
+           {
+           overflow:
+             EXCEPTION(EX_Overflow);
+             if ( !(control_word & CW_Overflow) )
+               return 0;
+             set_precision_flag_up();
+             if ( !(control_word & CW_Precision) )
+               return 0;
+
+             /* This is a special case: see sec 16.2.5.1 of the 80486 book */
+             /* Overflow to infinity */
+             l[0] = 0x00000000;        /* Set to */
+             l[1] = 0x7ff00000;        /* + INF */
+           }
+         else
+           {
+             if ( precision_loss )
+               {
+                 if ( increment )
+                   set_precision_flag_up();
+                 else
+                   set_precision_flag_down();
+               }
+             /* Add the exponent */
+             l[1] |= (((exp+DOUBLE_Ebias) & 0x7ff) << 20);
+           }
+       }
+    }
+  else if (st0_tag == TAG_Zero)
+    {
+      /* Number is zero */
+      l[0] = 0;
+      l[1] = 0;
+    }
+  else if ( st0_tag == TAG_Special )
+    {
+      st0_tag = FPU_Special(st0_ptr);
+      if ( st0_tag == TW_Denormal )
+       {
+         /* A denormal will always underflow. */
+#ifndef PECULIAR_486
+         /* An 80486 is supposed to be able to generate
+            a denormal exception here, but... */
+         /* Underflow has priority. */
+         if ( control_word & CW_Underflow )
+           denormal_operand();
+#endif /* PECULIAR_486 */
+         reg_copy(st0_ptr, &tmp);
+         goto denormal_arg;
+       }
+      else if (st0_tag == TW_Infinity)
+       {
+         l[0] = 0;
+         l[1] = 0x7ff00000;
+       }
+      else if (st0_tag == TW_NaN)
+       {
+         /* Is it really a NaN ? */
+         if ( (exponent(st0_ptr) == EXP_OVER)
+              && (st0_ptr->sigh & 0x80000000) )
+           {
+             /* See if we can get a valid NaN from the FPU_REG */
+             l[0] = (st0_ptr->sigl >> 11) | (st0_ptr->sigh << 21);
+             l[1] = ((st0_ptr->sigh >> 11) & 0xfffff);
+             if ( !(st0_ptr->sigh & 0x40000000) )
+               {
+                 /* It is a signalling NaN */
+                 EXCEPTION(EX_Invalid);
+                 if ( !(control_word & CW_Invalid) )
+                   return 0;
+                 l[1] |= (0x40000000 >> 11);
+               }
+             l[1] |= 0x7ff00000;
+           }
+         else
+           {
+             /* It is an unsupported data type */
+             EXCEPTION(EX_Invalid);
+             if ( !(control_word & CW_Invalid) )
+               return 0;
+             l[0] = 0;
+             l[1] = 0xfff80000;
+           }
+       }
+    }
+  else if ( st0_tag == TAG_Empty )
+    {
+      /* Empty register (stack underflow) */
+      EXCEPTION(EX_StackUnder);
+      if ( control_word & CW_Invalid )
+       {
+         /* The masked response */
+         /* Put out the QNaN indefinite */
+         RE_ENTRANT_CHECK_OFF;
+         FPU_verify_area(VERIFY_WRITE,(void *)dfloat,8);
+         FPU_put_user(0, (u32 *) dfloat);
+         FPU_put_user(0xfff80000, 1 + (u32 *) dfloat);
+         RE_ENTRANT_CHECK_ON;
+         return 1;
+       }
+      else
+       return 0;
+    }
+  if ( getsign(st0_ptr) )
+    l[1] |= 0x80000000;
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_WRITE,(void *)dfloat,8);
+  FPU_put_user(l[0], (u32 *)dfloat);
+  FPU_put_user(l[1], 1 + (u32 *)dfloat);
+  RE_ENTRANT_CHECK_ON;
+
+  return 1;
+}
+
+
+/* Put a float into user memory */
+int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float *single)
+{
+  s32 templ;
+  u32 increment = 0;           /* avoid gcc warnings */
+  int precision_loss;
+  int exp;
+  FPU_REG tmp;
+
+  if ( st0_tag == TAG_Valid )
+    {
+
+      reg_copy(st0_ptr, &tmp);
+      exp = exponent(&tmp);
+
+      if ( exp < SINGLE_Emin )
+       {
+         addexponent(&tmp, -SINGLE_Emin + 23);  /* largest exp to be 22 */
+
+       denormal_arg:
+
+         if ( (precision_loss = FPU_round_to_int(&tmp, st0_tag)) )
+           {
+#ifdef PECULIAR_486
+             /* Did it round to a non-denormal ? */
+             /* This behaviour might be regarded as peculiar, it appears
+                that the 80486 rounds to the dest precision, then
+                converts to decide underflow. */
+             if ( !((tmp.sigl == 0x00800000) &&
+                 ((st0_ptr->sigh & 0x000000ff) || st0_ptr->sigl)) )
+#endif /* PECULIAR_486 */
+               {
+                 EXCEPTION(EX_Underflow);
+                 /* This is a special case: see sec 16.2.5.1 of
+                    the 80486 book */
+                 if ( !(control_word & CW_Underflow) )
+                   return 0;
+               }
+             EXCEPTION(precision_loss);
+             if ( !(control_word & CW_Precision) )
+               return 0;
+           }
+         templ = tmp.sigl;
+      }
+      else
+       {
+         if ( tmp.sigl | (tmp.sigh & 0x000000ff) )
+           {
+             u32 sigh = tmp.sigh;
+             u32 sigl = tmp.sigl;
+             
+             precision_loss = 1;
+             switch (control_word & CW_RC)
+               {
+               case RC_RND:
+                 increment = ((sigh & 0xff) > 0x80)       /* more than half */
+                   || (((sigh & 0xff) == 0x80) && sigl)   /* more than half */
+                   || ((sigh & 0x180) == 0x180);        /* round to even */
+                 break;
+               case RC_DOWN:   /* towards -infinity */
+                 increment = signpositive(&tmp)
+                   ? 0 : (sigl | (sigh & 0xff));
+                 break;
+               case RC_UP:     /* towards +infinity */
+                 increment = signpositive(&tmp)
+                   ? (sigl | (sigh & 0xff)) : 0;
+                 break;
+               case RC_CHOP:
+                 increment = 0;
+                 break;
+               }
+         
+             /* Truncate part of the mantissa */
+             tmp.sigl = 0;
+         
+             if (increment)
+               {
+                 if ( sigh >= 0xffffff00 )
+                   {
+                     /* The sigh part overflows */
+                     tmp.sigh = 0x80000000;
+                     exp++;
+                     if ( exp >= EXP_OVER )
+                       goto overflow;
+                   }
+                 else
+                   {
+                     tmp.sigh &= 0xffffff00;
+                     tmp.sigh += 0x100;
+                   }
+               }
+             else
+               {
+                 tmp.sigh &= 0xffffff00;  /* Finish the truncation */
+               }
+           }
+         else
+           precision_loss = 0;
+      
+         templ = (tmp.sigh >> 8) & 0x007fffff;
+
+         if ( exp > SINGLE_Emax )
+           {
+           overflow:
+             EXCEPTION(EX_Overflow);
+             if ( !(control_word & CW_Overflow) )
+               return 0;
+             set_precision_flag_up();
+             if ( !(control_word & CW_Precision) )
+               return 0;
+
+             /* This is a special case: see sec 16.2.5.1 of the 80486 book. */
+             /* Masked response is overflow to infinity. */
+             templ = 0x7f800000;
+           }
+         else
+           {
+             if ( precision_loss )
+               {
+                 if ( increment )
+                   set_precision_flag_up();
+                 else
+                   set_precision_flag_down();
+               }
+             /* Add the exponent */
+             templ |= ((exp+SINGLE_Ebias) & 0xff) << 23;
+           }
+       }
+    }
+  else if (st0_tag == TAG_Zero)
+    {
+      templ = 0;
+    }
+  else if ( st0_tag == TAG_Special )
+    {
+      st0_tag = FPU_Special(st0_ptr);
+      if (st0_tag == TW_Denormal)
+       {
+         reg_copy(st0_ptr, &tmp);
+
+         /* A denormal will always underflow. */
+#ifndef PECULIAR_486
+         /* An 80486 is supposed to be able to generate
+            a denormal exception here, but... */
+         /* Underflow has priority. */
+         if ( control_word & CW_Underflow )
+           denormal_operand();
+#endif /* PECULIAR_486 */
+         goto denormal_arg;
+       }
+      else if (st0_tag == TW_Infinity)
+       {
+         templ = 0x7f800000;
+       }
+      else if (st0_tag == TW_NaN)
+       {
+         /* Is it really a NaN ? */
+         if ( (exponent(st0_ptr) == EXP_OVER) && (st0_ptr->sigh & 0x80000000) )
+           {
+             /* See if we can get a valid NaN from the FPU_REG */
+             templ = st0_ptr->sigh >> 8;
+             if ( !(st0_ptr->sigh & 0x40000000) )
+               {
+                 /* It is a signalling NaN */
+                 EXCEPTION(EX_Invalid);
+                 if ( !(control_word & CW_Invalid) )
+                   return 0;
+                 templ |= (0x40000000 >> 8);
+               }
+             templ |= 0x7f800000;
+           }
+         else
+           {
+             /* It is an unsupported data type */
+             EXCEPTION(EX_Invalid);
+             if ( !(control_word & CW_Invalid) )
+               return 0;
+             templ = 0xffc00000;
+           }
+       }
+#ifdef PARANOID
+      else
+       {
+         EXCEPTION(EX_INTERNAL|0x164);
+         return 0;
+       }
+#endif
+    }
+  else if ( st0_tag == TAG_Empty )
+    {
+      /* Empty register (stack underflow) */
+      EXCEPTION(EX_StackUnder);
+      if ( control_word & EX_Invalid )
+       {
+         /* The masked response */
+         /* Put out the QNaN indefinite */
+         RE_ENTRANT_CHECK_OFF;
+         FPU_verify_area(VERIFY_WRITE,(void *)single,4);
+         FPU_put_user(0xffc00000, (u32 *) single);
+         RE_ENTRANT_CHECK_ON;
+         return 1;
+       }
+      else
+       return 0;
+    }
+#ifdef PARANOID
+  else
+    {
+      EXCEPTION(EX_INTERNAL|0x163);
+      return 0;
+    }
+#endif
+  if ( getsign(st0_ptr) )
+    templ |= 0x80000000;
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_WRITE,(void *)single,4);
+  FPU_put_user(templ,(u32 *) single);
+  RE_ENTRANT_CHECK_ON;
+
+  return 1;
+}
+
+
+/* Put a 64bit quantity into user memory */
+int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, s64 *d)
+{
+  FPU_REG t;
+  s64 tll;
+  int precision_loss;
+
+  if ( st0_tag == TAG_Empty )
+    {
+      /* Empty register (stack underflow) */
+      EXCEPTION(EX_StackUnder);
+      goto invalid_operand;
+    }
+  else if ( st0_tag == TAG_Special )
+    {
+      st0_tag = FPU_Special(st0_ptr);
+      if ( (st0_tag == TW_Infinity) ||
+          (st0_tag == TW_NaN) )
+       {
+         EXCEPTION(EX_Invalid);
+         goto invalid_operand;
+       }
+    }
+
+  reg_copy(st0_ptr, &t);
+  precision_loss = FPU_round_to_int(&t, st0_tag);
+#ifndef EMU_BIG_ENDIAN
+  ((u32 *)&tll)[0] = t.sigl;
+  ((u32 *)&tll)[1] = t.sigh;
+#else
+  ((u32 *)&tll)[0] = t.sigh;
+  ((u32 *)&tll)[1] = t.sigl;
+#endif
+  if ( (precision_loss == 1) ||
+      ((t.sigh & 0x80000000) &&
+       !((t.sigh == 0x80000000) && (t.sigl == 0) &&
+        signnegative(&t))) )
+    {
+      EXCEPTION(EX_Invalid);
+      /* This is a special case: see sec 16.2.5.1 of the 80486 book */
+    invalid_operand:
+      if ( control_word & EX_Invalid )
+       {
+         /* Produce something like QNaN "indefinite" */
+         tll = BX_CONST64(0x8000000000000000);
+       }
+      else
+       return 0;
+    }
+  else
+    {
+      if ( precision_loss )
+       set_precision_flag(precision_loss);
+      if ( signnegative(&t) )
+       tll = - tll;
+    }
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_WRITE,(void *)d,8);
+#ifndef USE_WITH_CPU_SIM
+  copy_to_user(d, &tll, 8);
+#else
+  FPU_put_user((u32) tll,       (u32*)(((u8 *)d)+0));
+  FPU_put_user((u32) (tll>>32), (u32*)(((u8 *)d)+4));
+#endif
+  RE_ENTRANT_CHECK_ON;
+
+  return 1;
+}
+
+
+/* Put a long into user memory */
+int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, s32 *d)
+{
+  FPU_REG t;
+  int precision_loss;
+
+  if ( st0_tag == TAG_Empty )
+    {
+      /* Empty register (stack underflow) */
+      EXCEPTION(EX_StackUnder);
+      goto invalid_operand;
+    }
+  else if ( st0_tag == TAG_Special )
+    {
+      st0_tag = FPU_Special(st0_ptr);
+      if ( (st0_tag == TW_Infinity) ||
+          (st0_tag == TW_NaN) )
+       {
+         EXCEPTION(EX_Invalid);
+         goto invalid_operand;
+       }
+    }
+
+  reg_copy(st0_ptr, &t);
+  precision_loss = FPU_round_to_int(&t, st0_tag);
+  if (t.sigh ||
+      ((t.sigl & 0x80000000) &&
+       !((t.sigl == 0x80000000) && signnegative(&t))) )
+    {
+      EXCEPTION(EX_Invalid);
+      /* This is a special case: see sec 16.2.5.1 of the 80486 book */
+    invalid_operand:
+      if ( control_word & EX_Invalid )
+       {
+         /* Produce something like QNaN "indefinite" */
+         t.sigl = 0x80000000;
+       }
+      else
+       return 0;
+    }
+  else
+    {
+      if ( precision_loss )
+       set_precision_flag(precision_loss);
+      if ( signnegative(&t) )
+       t.sigl = -(s32)t.sigl;
+    }
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_WRITE,d,4);
+  FPU_put_user(t.sigl, (u32 *) d);
+  RE_ENTRANT_CHECK_ON;
+
+  return 1;
+}
+
+
+/* Put a short into user memory */
+int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, s16 *d)
+{
+  FPU_REG t;
+  int precision_loss;
+
+  if ( st0_tag == TAG_Empty )
+    {
+      /* Empty register (stack underflow) */
+      EXCEPTION(EX_StackUnder);
+      goto invalid_operand;
+    }
+  else if ( st0_tag == TAG_Special )
+    {
+      st0_tag = FPU_Special(st0_ptr);
+      if ( (st0_tag == TW_Infinity) ||
+          (st0_tag == TW_NaN) )
+       {
+         EXCEPTION(EX_Invalid);
+         goto invalid_operand;
+       }
+    }
+
+  reg_copy(st0_ptr, &t);
+  precision_loss = FPU_round_to_int(&t, st0_tag);
+  if (t.sigh ||
+      ((t.sigl & 0xffff8000) &&
+       !((t.sigl == 0x8000) && signnegative(&t))) )
+    {
+      EXCEPTION(EX_Invalid);
+      /* This is a special case: see sec 16.2.5.1 of the 80486 book */
+    invalid_operand:
+      if ( control_word & EX_Invalid )
+       {
+         /* Produce something like QNaN "indefinite" */
+         t.sigl = 0x8000;
+       }
+      else
+       return 0;
+    }
+  else
+    {
+      if ( precision_loss )
+       set_precision_flag(precision_loss);
+      if ( signnegative(&t) )
+       t.sigl = -t.sigl;
+    }
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_WRITE,d,2);
+  FPU_put_user((s16)t.sigl,(s16 *) d);
+  RE_ENTRANT_CHECK_ON;
+
+  return 1;
+}
+
+
+/* Put a packed bcd array into user memory */
+int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char *d)
+{
+  FPU_REG t;
+  u64 ll;
+  u_char b;
+  int i, precision_loss;
+  u_char sign = (getsign(st0_ptr) == SIGN_NEG) ? 0x80 : 0;
+
+  if ( st0_tag == TAG_Empty )
+    {
+      /* Empty register (stack underflow) */
+      EXCEPTION(EX_StackUnder);
+      goto invalid_operand;
+    }
+  else if ( st0_tag == TAG_Special )
+    {
+      st0_tag = FPU_Special(st0_ptr);
+      if ( (st0_tag == TW_Infinity) ||
+          (st0_tag == TW_NaN) )
+       {
+         EXCEPTION(EX_Invalid);
+         goto invalid_operand;
+       }
+    }
+
+  reg_copy(st0_ptr, &t);
+  precision_loss = FPU_round_to_int(&t, st0_tag);
+  ll = significand(&t);
+
+  /* Check for overflow, by comparing with 999999999999999999 decimal. */
+  if ( (t.sigh > 0x0de0b6b3) ||
+      ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff)) )
+    {
+      EXCEPTION(EX_Invalid);
+      /* This is a special case: see sec 16.2.5.1 of the 80486 book */
+    invalid_operand:
+      if ( control_word & CW_Invalid )
+       {
+         /* Produce the QNaN "indefinite" */
+         RE_ENTRANT_CHECK_OFF;
+         FPU_verify_area(VERIFY_WRITE,d,10);
+         for ( i = 0; i < 7; i++)
+           FPU_put_user(0, (u_char *) d+i); /* These bytes "undefined" */
+         FPU_put_user(0xc0, (u_char *) d+7); /* This byte "undefined" */
+         FPU_put_user(0xff, (u_char *) d+8);
+         FPU_put_user(0xff, (u_char *) d+9);
+         RE_ENTRANT_CHECK_ON;
+         return 1;
+       }
+      else
+       return 0;
+    }
+  else if ( precision_loss )
+    {
+      /* Precision loss doesn't stop the data transfer */
+      set_precision_flag(precision_loss);
+    }
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_WRITE,d,10);
+  RE_ENTRANT_CHECK_ON;
+  for ( i = 0; i < 9; i++)
+    {
+      b = FPU_div_small(&ll, 10);
+      b |= (FPU_div_small(&ll, 10)) << 4;
+      RE_ENTRANT_CHECK_OFF;
+      FPU_put_user(b,(u_char *) d+i);
+      RE_ENTRANT_CHECK_ON;
+    }
+  RE_ENTRANT_CHECK_OFF;
+  FPU_put_user(sign,(u_char *) d+9);
+  RE_ENTRANT_CHECK_ON;
+
+  return 1;
+}
+
+/*===========================================================================*/
+
+/* r gets mangled such that sig is int, sign: 
+   it is NOT normalized */
+/* The return value (in eax) is zero if the result is exact,
+   if bits are changed due to rounding, truncation, etc, then
+   a non-zero value is returned */
+/* Overflow is signalled by a non-zero return value (in eax).
+   In the case of overflow, the returned significand always has the
+   largest possible value */
+int FPU_round_to_int(FPU_REG *r, u_char tag)
+{
+  u_char     very_big;
+  unsigned eax;
+
+  if (tag == TAG_Zero)
+    {
+      /* Make sure that zero is returned */
+      significand(r) = 0;
+      return 0;        /* o.k. */
+    }
+
+  if (exponent(r) > 63)
+    {
+      r->sigl = r->sigh = ~0;      /* The largest representable number */
+      return 1;        /* overflow */
+    }
+
+#ifndef EMU_BIG_ENDIAN
+  eax = FPU_shrxs(&r->sigl, 63 - exponent(r));
+#else
+  eax = FPU_shrxs(&r->sigh, 63 - exponent(r));
+#endif
+  very_big = !(~(r->sigh) | ~(r->sigl));  /* test for 0xfff...fff */
+#define        half_or_more    (eax & 0x80000000)
+#define        frac_part       (eax)
+#define more_than_half  ((eax & 0x80000001) == 0x80000001)
+  switch (control_word & CW_RC)
+    {
+    case RC_RND:
+      if ( more_than_half                      /* nearest */
+         || (half_or_more && (r->sigl & 1)) )  /* odd -> even */
+       {
+         if ( very_big ) return 1;        /* overflow */
+         significand(r) ++;
+         return PRECISION_LOST_UP;
+       }
+      break;
+    case RC_DOWN:
+      if (frac_part && getsign(r))
+       {
+         if ( very_big ) return 1;        /* overflow */
+         significand(r) ++;
+         return PRECISION_LOST_UP;
+       }
+      break;
+    case RC_UP:
+      if (frac_part && !getsign(r))
+       {
+         if ( very_big ) return 1;        /* overflow */
+         significand(r) ++;
+         return PRECISION_LOST_UP;
+       }
+      break;
+    case RC_CHOP:
+      break;
+    }
+
+  return eax ? PRECISION_LOST_DOWN : 0;
+
+}
+
+/*===========================================================================*/
+
+u_char *fldenv(fpu_addr_modes addr_modes, u_char *s)
+{
+  u16 tag_word = 0;
+  u_char tag;
+  int i;
+
+  if ( (addr_modes.default_mode == VM86) ||
+      ((addr_modes.default_mode == PM16)
+      ^ (addr_modes.override.operand_size == OP_SIZE_PREFIX)) )
+    {
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_READ, s, 0x0e);
+      FPU_get_user(control_word, (u16 *) s);
+      FPU_get_user(partial_status, (u16 *) (s+2));
+      FPU_get_user(tag_word, (u16 *) (s+4));
+      FPU_get_user(instruction_address.offset, (u16 *) (s+6));
+      FPU_get_user(instruction_address.selector, (u16 *) (s+8));
+      FPU_get_user(operand_address.offset, (u16 *) (s+0x0a));
+      FPU_get_user(operand_address.selector, (u16 *) (s+0x0c));
+      RE_ENTRANT_CHECK_ON;
+      s += 0x0e;
+      if ( addr_modes.default_mode == VM86 )
+       {
+         instruction_address.offset
+           += (instruction_address.selector & 0xf000) << 4;
+         operand_address.offset += (operand_address.selector & 0xf000) << 4;
+       }
+    }
+  else
+    {
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_READ, s, 0x1c);
+      FPU_get_user(control_word, (u16 *) s);
+      FPU_get_user(partial_status, (u16 *) (s+4));
+      FPU_get_user(tag_word, (u16 *) (s+8));
+      FPU_get_user(instruction_address.offset, (u32 *) (s+0x0c));
+      FPU_get_user(instruction_address.selector, (u16 *) (s+0x10));
+      FPU_get_user(instruction_address.opcode, (u16 *) (s+0x12));
+      FPU_get_user(operand_address.offset, (u32 *) (s+0x14));
+      FPU_get_user(operand_address.selector, (u32 *) (s+0x18));
+      RE_ENTRANT_CHECK_ON;
+      s += 0x1c;
+    }
+
+#ifdef PECULIAR_486
+  control_word &= ~0xe080;
+#endif /* PECULIAR_486 */
+
+  top = (partial_status >> SW_Top_Shift) & 7;
+
+  if ( partial_status & ~control_word & CW_Exceptions )
+    partial_status |= (SW_Summary | SW_Backward);
+  else
+    partial_status &= ~(SW_Summary | SW_Backward);
+
+  for ( i = 0; i < 8; i++ )
+    {
+      tag = tag_word & 3;
+      tag_word >>= 2;
+
+      if ( tag == TAG_Empty )
+       /* New tag is empty.  Accept it */
+       FPU_settag(i, TAG_Empty);
+      else if ( FPU_gettag(i) == TAG_Empty )
+       {
+         /* Old tag is empty and new tag is not empty.  New tag is determined
+            by old reg contents */
+         if ( exponent(&fpu_register(i)) == - EXTENDED_Ebias )
+           {
+             if ( !(fpu_register(i).sigl | fpu_register(i).sigh) )
+               FPU_settag(i, TAG_Zero);
+             else
+               FPU_settag(i, TAG_Special);
+           }
+         else if ( exponent(&fpu_register(i)) == 0x7fff - EXTENDED_Ebias )
+           {
+             FPU_settag(i, TAG_Special);
+           }
+         else if ( fpu_register(i).sigh & 0x80000000 )
+           FPU_settag(i, TAG_Valid);
+         else
+           FPU_settag(i, TAG_Special);   /* An Un-normal */
+       }
+      /* Else old tag is not empty and new tag is not empty.  Old tag
+        remains correct */
+    }
+
+  return s;
+}
+
+
+void frstor(fpu_addr_modes addr_modes, u_char *data_address)
+{
+  int i, regnr;
+  u_char *s = fldenv(addr_modes, data_address);
+  int offset = (top & 7) * sizeof(FPU_REG), other = 8*sizeof(FPU_REG) - offset;
+
+  /* Copy all registers in stack order. */
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_READ,s,80);
+#ifndef USE_WITH_CPU_SIM
+  __copy_from_user(register_base+offset, s, other);
+  if ( offset )
+    __copy_from_user(register_base, s+other, offset);
+#else
+  {
+  FPU_REG *fpu_reg_p;
+
+  fpu_reg_p = (FPU_REG *) (register_base+offset);
+  while (other>0) {
+    FPU_get_user(fpu_reg_p->sigl, (u32*)(s+0));
+    FPU_get_user(fpu_reg_p->sigh, (u32*)(s+4));
+    FPU_get_user(fpu_reg_p->exp,  (u16*)(s+8));
+    fpu_reg_p++;
+    s += 10;
+    other -= sizeof(FPU_REG);
+    }
+  fpu_reg_p = (FPU_REG *) register_base;
+  while (offset>0) {
+    FPU_get_user(fpu_reg_p->sigl, (u32*)(s+0));
+    FPU_get_user(fpu_reg_p->sigh, (u32*)(s+4));
+    FPU_get_user(fpu_reg_p->exp,  (u16*)(s+8));
+    fpu_reg_p++;
+    s += 10;
+    offset -= sizeof(FPU_REG);
+    }
+  }
+#endif
+  RE_ENTRANT_CHECK_ON;
+
+  for ( i = 0; i < 8; i++ )
+    {
+      regnr = (i+top) & 7;
+      if ( FPU_gettag(regnr) != TAG_Empty )
+       /* The loaded data over-rides all other cases. */
+       FPU_settag(regnr, FPU_tagof(&st(i)));
+    }
+
+}
+
+
+u_char *fstenv(fpu_addr_modes addr_modes, u_char *d)
+{
+  if ( (addr_modes.default_mode == VM86) ||
+      ((addr_modes.default_mode == PM16)
+      ^ (addr_modes.override.operand_size == OP_SIZE_PREFIX)) )
+    {
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_WRITE,d,14);
+#ifdef PECULIAR_486
+      FPU_put_user(control_word & ~0xe080, (u32 *) d);
+#else
+      FPU_put_user(control_word, (u16 *) d);
+#endif /* PECULIAR_486 */
+      FPU_put_user(status_word(), (u16 *) (d+2));
+      FPU_put_user(fpu_tag_word, (u16 *) (d+4));
+      FPU_put_user(instruction_address.offset, (u16 *) (d+6));
+      FPU_put_user(operand_address.offset, (u16 *) (d+0x0a));
+      if ( addr_modes.default_mode == VM86 )
+       {
+         FPU_put_user((instruction_address.offset & 0xf0000) >> 4,
+                     (u16 *) (d+8));
+         FPU_put_user((operand_address.offset & 0xf0000) >> 4,
+                     (u16 *) (d+0x0c));
+       }
+      else
+       {
+         FPU_put_user(instruction_address.selector, (u16 *) (d+8));
+         FPU_put_user(operand_address.selector, (u16 *) (d+0x0c));
+       }
+      RE_ENTRANT_CHECK_ON;
+      d += 0x0e;
+    }
+  else
+    {
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_WRITE, d, 7*4);
+#ifdef PECULIAR_486
+      control_word &= ~0xe080;
+      /* An 80486 sets nearly all of the reserved bits to 1. */
+      control_word |= 0xffff0040;
+      partial_status = status_word() | 0xffff0000;
+      fpu_tag_word |= 0xffff0000;
+      I387.soft.fcs &= ~0xf8000000;
+      I387.soft.fos |= 0xffff0000;
+#endif /* PECULIAR_486 */
+#ifndef USE_WITH_CPU_SIM
+      __copy_to_user(d, &control_word, 7*4);
+#else
+      FPU_put_user((u32) I387.soft.cwd, (u32*)(((u8 *)d)+0));
+      FPU_put_user((u32) I387.soft.swd, (u32*)(((u8 *)d)+4));
+      FPU_put_user((u32) I387.soft.twd, (u32*)(((u8 *)d)+8));
+      FPU_put_user((u32) I387.soft.fip, (u32*)(((u8 *)d)+12));
+      FPU_put_user((u32) I387.soft.fcs, (u32*)(((u8 *)d)+16));
+      FPU_put_user((u32) I387.soft.foo, (u32*)(((u8 *)d)+20));
+      FPU_put_user((u32) I387.soft.fos, (u32*)(((u8 *)d)+24));
+#endif
+      RE_ENTRANT_CHECK_ON;
+      d += 0x1c;
+    }
+  
+  control_word |= CW_Exceptions;
+  partial_status &= ~(SW_Summary | SW_Backward);
+
+  return d;
+}
+
+
+void fsave(fpu_addr_modes addr_modes, u_char *data_address)
+{
+  u_char *d;
+  int offset = (top & 7) * sizeof(FPU_REG), other = 8*sizeof(FPU_REG) - offset;
+
+  d = fstenv(addr_modes, data_address);
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_WRITE,d,80);
+
+  /* Copy all registers in stack order. */
+#ifndef USE_WITH_CPU_SIM
+  __copy_to_user(d, register_base+offset, other);
+  if ( offset )
+    __copy_to_user(d+other, register_base, offset);
+#else
+  {
+  FPU_REG *fpu_reg_p;
+
+  fpu_reg_p = (FPU_REG *) (register_base+offset);
+  while (other>0) {
+    FPU_put_user(fpu_reg_p->sigl, (u32*)(d+0));
+    FPU_put_user(fpu_reg_p->sigh, (u32*)(d+4));
+    FPU_put_user(fpu_reg_p->exp,  (u16*)(d+8));
+    fpu_reg_p++;
+    d += 10;
+    other -= sizeof(FPU_REG);
+    }
+  fpu_reg_p = (FPU_REG *) register_base;
+  while (offset>0) {
+    FPU_put_user(fpu_reg_p->sigl, (u32*)(d+0));
+    FPU_put_user(fpu_reg_p->sigh, (u32*)(d+4));
+    FPU_put_user(fpu_reg_p->exp,  (u16*)(d+8));
+    fpu_reg_p++;
+    d += 10;
+    offset -= sizeof(FPU_REG);
+    }
+  }
+#endif
+  RE_ENTRANT_CHECK_ON;
+
+  finit();
+}
+
+/*===========================================================================*/
diff --git a/sid/component/bochs/cpu/fpu/reg_mul.c b/sid/component/bochs/cpu/fpu/reg_mul.c
new file mode 100644 (file)
index 0000000..04f68b7
--- /dev/null
@@ -0,0 +1,131 @@
+/*---------------------------------------------------------------------------+
+ |  reg_mul.c                                                                |
+ |                                                                           |
+ | Multiply one FPU_REG by another, put the result in a destination FPU_REG. |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1997                                              |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ | Returns the tag of the result if no exceptions or errors occurred.        |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | The destination may be any FPU_REG, including one of the source FPU_REGs. |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_emu.h"
+#include "exception.h"
+#include "reg_constant.h"
+#include "fpu_system.h"
+
+
+/*
+  Multiply two registers to give a register result.
+  The sources are st(deststnr) and (b,tagb,signb).
+  The destination is st(deststnr).
+  */
+/* This routine must be called with non-empty source registers */
+int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w)
+{
+  FPU_REG *a = &st(deststnr);
+  FPU_REG *dest = a;
+  u_char taga = FPU_gettagi(deststnr);
+  u_char saved_sign = getsign(dest);
+  u_char sign = (getsign(a) ^ getsign(b));
+  int tag;
+
+
+  if ( !(taga | tagb) )
+    {
+      /* Both regs Valid, this should be the most common case. */
+
+      tag = FPU_u_mul(a, b, dest, control_w, sign, exponent(a) + exponent(b));
+      if ( tag < 0 )
+       {
+         setsign(dest, saved_sign);
+         return tag;
+       }
+      FPU_settagi(deststnr, tag);
+      return tag;
+    }
+
+  if ( taga == TAG_Special )
+    taga = FPU_Special(a);
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+
+  if ( ((taga == TAG_Valid) && (tagb == TW_Denormal))
+           || ((taga == TW_Denormal) && (tagb == TAG_Valid))
+           || ((taga == TW_Denormal) && (tagb == TW_Denormal)) )
+    {
+      FPU_REG x, y;
+      if ( denormal_operand() < 0 )
+       return FPU_Exception;
+
+      FPU_to_exp16(a, &x);
+      FPU_to_exp16(b, &y);
+      tag = FPU_u_mul(&x, &y, dest, control_w, sign,
+                     exponent16(&x) + exponent16(&y));
+      if ( tag < 0 )
+       {
+         setsign(dest, saved_sign);
+         return tag;
+       }
+      FPU_settagi(deststnr, tag);
+      return tag;
+    }
+  else if ( (taga <= TW_Denormal) && (tagb <= TW_Denormal) )
+    {
+      if ( ((tagb == TW_Denormal) || (taga == TW_Denormal))
+          && (denormal_operand() < 0) )
+       return FPU_Exception;
+
+      /* Must have either both arguments == zero, or
+        one valid and the other zero.
+        The result is therefore zero. */
+      FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
+      /* The 80486 book says that the answer is +0, but a real
+        80486 behaves this way.
+        IEEE-754 apparently says it should be this way. */
+      setsign(dest, sign);
+      return TAG_Zero;
+    }
+      /* Must have infinities, NaNs, etc */
+  else if ( (taga == TW_NaN) || (tagb == TW_NaN) )
+    {
+      return real_2op_NaN(b, tagb, deststnr, &st(0));
+    }
+  else if ( ((taga == TW_Infinity) && (tagb == TAG_Zero))
+           || ((tagb == TW_Infinity) && (taga == TAG_Zero)) )
+    {
+      return arith_invalid(deststnr);  /* Zero*Infinity is invalid */
+    }
+  else if ( ((taga == TW_Denormal) || (tagb == TW_Denormal))
+           && (denormal_operand() < 0) )
+    {
+      return FPU_Exception;
+    }
+  else if (taga == TW_Infinity)
+    {
+      FPU_copy_to_regi(a, TAG_Special, deststnr);
+      setsign(dest, sign);
+      return TAG_Special;
+    }
+  else if (tagb == TW_Infinity)
+    {
+      FPU_copy_to_regi(b, TAG_Special, deststnr);
+      setsign(dest, sign);
+      return TAG_Special;
+    }
+
+#ifdef PARANOID
+  else
+    {
+      EXCEPTION(EX_INTERNAL|0x102);
+      return FPU_Exception;
+    }
+#endif /* PARANOID */
+
+}
diff --git a/sid/component/bochs/cpu/fpu/reg_norm.S b/sid/component/bochs/cpu/fpu/reg_norm.S
new file mode 100644 (file)
index 0000000..65e6a69
--- /dev/null
@@ -0,0 +1,71 @@
+/*---------------------------------------------------------------------------+
+ |  reg_norm.S                                                               |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1995,1997,1999                               |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@melbpc.org.au              |
+ |                                                                           |
+ | Normalize the value in a FPU_REG.                                         |
+ |                                                                           |
+ | Call from C as:                                                           |
+ |    int FPU_normalize_nuo(FPU_REG *n, int bias)                            |
+ |                                                                           |
+ |    Return value is the tag of the answer.                                 |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_emu.h"
+
+
+/* Normalise without reporting underflow or overflow */
+ENTRY(FPU_normalize_nuo)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+
+       movl    PARAM1,%ebx
+
+       movl    SIGH(%ebx),%edx
+       movl    SIGL(%ebx),%eax
+
+       orl     %edx,%edx       /* ms bits */
+       js      L_exit_nuo_valid        /* Already normalized */
+       jnz     L_nuo_shift_1   /* Shift left 1 - 31 bits */
+
+       orl     %eax,%eax
+       jz      L_exit_nuo_zero         /* The contents are zero */
+
+       movl    %eax,%edx
+       xorl    %eax,%eax
+       subw    $32,EXP(%ebx)   /* This can cause an underflow */
+
+/* We need to shift left by 1 - 31 bits */
+L_nuo_shift_1:
+       bsrl    %edx,%ecx       /* get the required shift in %ecx */
+       subl    $31,%ecx
+       negl    %ecx
+       shld    %cl,%eax,%edx
+       shl     %cl,%eax
+       subw    %cx,EXP(%ebx)   /* This can cause an underflow */
+
+       movl    %edx,SIGH(%ebx)
+       movl    %eax,SIGL(%ebx)
+
+L_exit_nuo_valid:
+        movl    PARAM2,%eax
+        addw    %ax,EXP(%ebx)
+       movl    TAG_Valid,%eax
+
+       popl    %ebx
+       leave
+       ret
+
+L_exit_nuo_zero:
+       movw    EXP_UNDER,EXP(%ebx)
+        movl    PARAM2,%eax
+        addw    %ax,EXP(%ebx)
+        movl    TAG_Zero,%eax
+
+       popl    %ebx
+       leave
+       ret
diff --git a/sid/component/bochs/cpu/fpu/reg_norm.c b/sid/component/bochs/cpu/fpu/reg_norm.c
new file mode 100644 (file)
index 0000000..b08dbc8
--- /dev/null
@@ -0,0 +1,48 @@
+/*---------------------------------------------------------------------------+
+ |  reg_norm.c                                                               |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1995,1997,1999                               |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@melbpc.org.au              |
+ |                                                                           |
+ | Normalize the value in a FPU_REG.                                         |
+ |                                                                           |
+ |                                                                           |
+ |    Return value is the tag of the answer.                                 |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_emu.h"
+
+
+
+int FPU_normalize_nuo(FPU_REG *x, int bias)
+{
+
+  if ( ! (x->sigh & 0x80000000) )
+    {
+      if ( x->sigh == 0 )
+       {
+         if ( x->sigl == 0 )
+           {
+             x->exp = EXP_UNDER;
+             return TAG_Zero;
+           }
+         x->sigh = x->sigl;
+         x->sigl = 0;
+         x->exp -= 32;
+       }
+      while ( !(x->sigh & 0x80000000) )
+       {
+         x->sigh <<= 1;
+         if ( x->sigl & 0x80000000 )
+           x->sigh |= 1;
+         x->sigl <<= 1;
+         x->exp --;
+       }
+    }
+
+  x->exp += bias;
+
+  return TAG_Valid;
+}
diff --git a/sid/component/bochs/cpu/fpu/reg_round.S b/sid/component/bochs/cpu/fpu/reg_round.S
new file mode 100644 (file)
index 0000000..6e7bb24
--- /dev/null
@@ -0,0 +1,710 @@
+       .file "reg_round.S"
+/*---------------------------------------------------------------------------+
+ |  reg_round.S                                                              |
+ |                                                                           |
+ | Rounding/truncation/etc for FPU basic arithmetic functions.               |
+ |                                                                           |
+ | Copyright (C) 1993,1995,1997                                              |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@suburbia.net               |
+ |                                                                           |
+ | This code has four possible entry points.                                 |
+ | The following must be entered by a jmp instruction:                       |
+ |   fpu_reg_round, fpu_reg_round_sqrt, and fpu_Arith_exit.                  |
+ |                                                                           |
+ | The FPU_round entry point is intended to be used by C code.               |
+ | From C, call as:                                                          |
+ |  int FPU_round(FPU_REG *arg, unsigned int extent, unsigned int control_w) |
+ |                                                                           |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
+ |                                                                           |
+ | For correct "up" and "down" rounding, the argument must have the correct  |
+ | sign.                                                                     |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | Four entry points.                                                        |
+ |                                                                           |
+ | Needed by both the fpu_reg_round and fpu_reg_round_sqrt entry points:     |
+ |  %eax:%ebx  64 bit significand                                            |
+ |  %edx       32 bit extension of the significand                           |
+ |  %edi       pointer to an FPU_REG for the result to be stored             |
+ |  stack      calling function must have set up a C stack frame and         |
+ |             pushed %esi, %edi, and %ebx                                   |
+ |                                                                           |
+ | Needed just for the fpu_reg_round_sqrt entry point:                       |
+ |  %cx  A control word in the same format as the FPU control word.          |
+ | Otherwise, PARAM4 must give such a value.                                 |
+ |                                                                           |
+ |                                                                           |
+ | The significand and its extension are assumed to be exact in the          |
+ | following sense:                                                          |
+ |   If the significand by itself is the exact result then the significand   |
+ |   extension (%edx) must contain 0, otherwise the significand extension    |
+ |   must be non-zero.                                                       |
+ |   If the significand extension is non-zero then the significand is        |
+ |   smaller than the magnitude of the correct exact result by an amount     |
+ |   greater than zero and less than one ls bit of the significand.          |
+ |   The significand extension is only required to have three possible       |
+ |   non-zero values:                                                        |
+ |       less than 0x80000000  <=> the significand is less than 1/2 an ls    |
+ |                                 bit smaller than the magnitude of the     |
+ |                                 true exact result.                        |
+ |         exactly 0x80000000  <=> the significand is exactly 1/2 an ls bit  |
+ |                                 smaller than the magnitude of the true    |
+ |                                 exact result.                             |
+ |    greater than 0x80000000  <=> the significand is more than 1/2 an ls    |
+ |                                 bit smaller than the magnitude of the     |
+ |                                 true exact result.                        |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ |  The code in this module has become quite complex, but it should handle   |
+ |  all of the FPU flags which are set at this stage of the basic arithmetic |
+ |  computations.                                                            |
+ |  There are a few rare cases where the results are not set identically to  |
+ |  a real FPU. These require a bit more thought because at this stage the   |
+ |  results of the code here appear to be more consistent...                 |
+ |  This may be changed in a future version.                                 |
+ +---------------------------------------------------------------------------*/
+
+
+#include "fpu_emu.h"
+#include "exception.h"
+#include "control_w.h"
+
+/* Flags for FPU_bits_lost */
+#define        LOST_DOWN       $1
+#define        LOST_UP         $2
+
+/* Flags for FPU_denormal */
+#define        DENORMAL        $1
+#define        UNMASKED_UNDERFLOW $2
+
+
+#ifndef NON_REENTRANT_FPU
+/*     Make the code re-entrant by putting
+       local storage on the stack: */
+#define FPU_bits_lost  (%esp)
+#define FPU_denormal   1(%esp)
+
+#else
+/*     Not re-entrant, so we can gain speed by putting
+       local storage in a static area: */
+.data
+       .align 4,0
+FPU_bits_lost:
+       .byte   0
+FPU_denormal:
+       .byte   0
+#endif /* NON_REENTRANT_FPU */
+
+
+.text
+.globl fpu_reg_round
+.globl fpu_reg_round_sqrt
+.globl fpu_Arith_exit
+
+/* Entry point when called from C */
+ENTRY(FPU_round)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %esi
+       pushl   %edi
+       pushl   %ebx
+
+       movl    PARAM1,%edi
+       movl    SIGH(%edi),%eax
+       movl    SIGL(%edi),%ebx
+       movl    PARAM2,%edx
+
+fpu_reg_round:                 /* Normal entry point */
+       movl    PARAM4,%ecx
+
+#ifndef NON_REENTRANT_FPU
+       pushl   %ebx            /* adjust the stack pointer */
+#endif /* NON_REENTRANT_FPU */
+
+#ifdef PARANOID
+/* Cannot use this here yet */
+/*     orl     %eax,%eax */
+/*     jns     L_entry_bugged */
+#endif /* PARANOID */
+
+       cmpw    EXP_UNDER,EXP(%edi)
+       jle     L_Make_denorm                   /* The number is a de-normal */
+
+       movb    $0,FPU_denormal                 /* 0 -> not a de-normal */
+
+Denorm_done:
+       movb    $0,FPU_bits_lost                /* No bits yet lost in rounding */
+
+       movl    %ecx,%esi
+       andl    CW_PC,%ecx
+       cmpl    PR_64_BITS,%ecx
+       je      LRound_To_64
+
+       cmpl    PR_53_BITS,%ecx
+       je      LRound_To_53
+
+       cmpl    PR_24_BITS,%ecx
+       je      LRound_To_24
+
+#ifdef PECULIAR_486
+/* With the precision control bits set to 01 "(reserved)", a real 80486
+   behaves as if the precision control bits were set to 11 "64 bits" */
+       cmpl    PR_RESERVED_BITS,%ecx
+       je      LRound_To_64
+#ifdef PARANOID
+       jmp     L_bugged_denorm_486
+#endif /* PARANOID */
+#else
+#ifdef PARANOID
+       jmp     L_bugged_denorm /* There is no bug, just a bad control word */
+#endif /* PARANOID */
+#endif /* PECULIAR_486 */
+
+
+/* Round etc to 24 bit precision */
+LRound_To_24:
+       movl    %esi,%ecx
+       andl    CW_RC,%ecx
+       cmpl    RC_RND,%ecx
+       je      LRound_nearest_24
+
+       cmpl    RC_CHOP,%ecx
+       je      LCheck_truncate_24
+
+       cmpl    RC_UP,%ecx              /* Towards +infinity */
+       je      LUp_24
+
+       cmpl    RC_DOWN,%ecx            /* Towards -infinity */
+       je      LDown_24
+
+#ifdef PARANOID
+       jmp     L_bugged_round24
+#endif /* PARANOID */
+
+LUp_24:
+       cmpb    SIGN_POS,PARAM5
+       jne     LCheck_truncate_24      /* If negative then  up==truncate */
+
+       jmp     LCheck_24_round_up
+
+LDown_24:
+       cmpb    SIGN_POS,PARAM5
+       je      LCheck_truncate_24      /* If positive then  down==truncate */
+
+LCheck_24_round_up:
+       movl    %eax,%ecx
+       andl    $0x000000ff,%ecx
+       orl     %ebx,%ecx
+       orl     %edx,%ecx
+       jnz     LDo_24_round_up
+       jmp     L_Re_normalise
+
+LRound_nearest_24:
+       /* Do rounding of the 24th bit if needed (nearest or even) */
+       movl    %eax,%ecx
+       andl    $0x000000ff,%ecx
+       cmpl    $0x00000080,%ecx
+       jc      LCheck_truncate_24      /* less than half, no increment needed */
+
+       jne     LGreater_Half_24        /* greater than half, increment needed */
+
+       /* Possibly half, we need to check the ls bits */
+       orl     %ebx,%ebx
+       jnz     LGreater_Half_24        /* greater than half, increment needed */
+
+       orl     %edx,%edx
+       jnz     LGreater_Half_24        /* greater than half, increment needed */
+
+       /* Exactly half, increment only if 24th bit is 1 (round to even) */
+       testl   $0x00000100,%eax
+       jz      LDo_truncate_24
+
+LGreater_Half_24:                      /* Rounding: increment at the 24th bit */
+LDo_24_round_up:
+       andl    $0xffffff00,%eax        /* Truncate to 24 bits */
+       xorl    %ebx,%ebx
+       movb    LOST_UP,FPU_bits_lost
+       addl    $0x00000100,%eax
+       jmp     LCheck_Round_Overflow
+
+LCheck_truncate_24:
+       movl    %eax,%ecx
+       andl    $0x000000ff,%ecx
+       orl     %ebx,%ecx
+       orl     %edx,%ecx
+       jz      L_Re_normalise          /* No truncation needed */
+
+LDo_truncate_24:
+       andl    $0xffffff00,%eax        /* Truncate to 24 bits */
+       xorl    %ebx,%ebx
+       movb    LOST_DOWN,FPU_bits_lost
+       jmp     L_Re_normalise
+
+
+/* Round etc to 53 bit precision */
+LRound_To_53:
+       movl    %esi,%ecx
+       andl    CW_RC,%ecx
+       cmpl    RC_RND,%ecx
+       je      LRound_nearest_53
+
+       cmpl    RC_CHOP,%ecx
+       je      LCheck_truncate_53
+
+       cmpl    RC_UP,%ecx              /* Towards +infinity */
+       je      LUp_53
+
+       cmpl    RC_DOWN,%ecx            /* Towards -infinity */
+       je      LDown_53
+
+#ifdef PARANOID
+       jmp     L_bugged_round53
+#endif /* PARANOID */
+
+LUp_53:
+       cmpb    SIGN_POS,PARAM5
+       jne     LCheck_truncate_53      /* If negative then  up==truncate */
+
+       jmp     LCheck_53_round_up
+
+LDown_53:
+       cmpb    SIGN_POS,PARAM5
+       je      LCheck_truncate_53      /* If positive then  down==truncate */
+
+LCheck_53_round_up:
+       movl    %ebx,%ecx
+       andl    $0x000007ff,%ecx
+       orl     %edx,%ecx
+       jnz     LDo_53_round_up
+       jmp     L_Re_normalise
+
+LRound_nearest_53:
+       /* Do rounding of the 53rd bit if needed (nearest or even) */
+       movl    %ebx,%ecx
+       andl    $0x000007ff,%ecx
+       cmpl    $0x00000400,%ecx
+       jc      LCheck_truncate_53      /* less than half, no increment needed */
+
+       jnz     LGreater_Half_53        /* greater than half, increment needed */
+
+       /* Possibly half, we need to check the ls bits */
+       orl     %edx,%edx
+       jnz     LGreater_Half_53        /* greater than half, increment needed */
+
+       /* Exactly half, increment only if 53rd bit is 1 (round to even) */
+       testl   $0x00000800,%ebx
+       jz      LTruncate_53
+
+LGreater_Half_53:                      /* Rounding: increment at the 53rd bit */
+LDo_53_round_up:
+       movb    LOST_UP,FPU_bits_lost
+       andl    $0xfffff800,%ebx        /* Truncate to 53 bits */
+       addl    $0x00000800,%ebx
+       adcl    $0,%eax
+       jmp     LCheck_Round_Overflow
+
+LCheck_truncate_53:
+       movl    %ebx,%ecx
+       andl    $0x000007ff,%ecx
+       orl     %edx,%ecx
+       jz      L_Re_normalise
+
+LTruncate_53:
+       movb    LOST_DOWN,FPU_bits_lost
+       andl    $0xfffff800,%ebx        /* Truncate to 53 bits */
+       jmp     L_Re_normalise
+
+
+/* Round etc to 64 bit precision */
+LRound_To_64:
+       movl    %esi,%ecx
+       andl    CW_RC,%ecx
+       cmpl    RC_RND,%ecx
+       je      LRound_nearest_64
+
+       cmpl    RC_CHOP,%ecx
+       je      LCheck_truncate_64
+
+       cmpl    RC_UP,%ecx              /* Towards +infinity */
+       je      LUp_64
+
+       cmpl    RC_DOWN,%ecx            /* Towards -infinity */
+       je      LDown_64
+
+#ifdef PARANOID
+       jmp     L_bugged_round64
+#endif /* PARANOID */
+
+LUp_64:
+       cmpb    SIGN_POS,PARAM5
+       jne     LCheck_truncate_64      /* If negative then  up==truncate */
+
+       orl     %edx,%edx
+       jnz     LDo_64_round_up
+       jmp     L_Re_normalise
+
+LDown_64:
+       cmpb    SIGN_POS,PARAM5
+       je      LCheck_truncate_64      /* If positive then  down==truncate */
+
+       orl     %edx,%edx
+       jnz     LDo_64_round_up
+       jmp     L_Re_normalise
+
+LRound_nearest_64:
+       cmpl    $0x80000000,%edx
+       jc      LCheck_truncate_64
+
+       jne     LDo_64_round_up
+
+       /* Now test for round-to-even */
+       testb   $1,%bl
+       jz      LCheck_truncate_64
+
+LDo_64_round_up:
+       movb    LOST_UP,FPU_bits_lost
+       addl    $1,%ebx
+       adcl    $0,%eax
+
+LCheck_Round_Overflow:
+       jnc     L_Re_normalise
+
+       /* Overflow, adjust the result (significand to 1.0) */
+       rcrl    $1,%eax
+       rcrl    $1,%ebx
+       incw    EXP(%edi)
+       jmp     L_Re_normalise
+
+LCheck_truncate_64:
+       orl     %edx,%edx
+       jz      L_Re_normalise
+
+LTruncate_64:
+       movb    LOST_DOWN,FPU_bits_lost
+
+L_Re_normalise:
+       testb   $0xff,FPU_denormal
+       jnz     Normalise_result
+
+L_Normalised:
+       movl    TAG_Valid,%edx
+
+L_deNormalised:
+       cmpb    LOST_UP,FPU_bits_lost
+       je      L_precision_lost_up
+
+       cmpb    LOST_DOWN,FPU_bits_lost
+       je      L_precision_lost_down
+
+L_no_precision_loss:
+       /* store the result */
+
+L_Store_significand:
+       movl    %eax,SIGH(%edi)
+       movl    %ebx,SIGL(%edi)
+
+       cmpw    EXP_OVER,EXP(%edi)
+       jge     L_overflow
+
+       movl    %edx,%eax
+
+       /* Convert the exponent to 80x87 form. */
+       addw    EXTENDED_Ebias,EXP(%edi)
+       andw    $0x7fff,EXP(%edi)
+
+fpu_reg_round_signed_special_exit:
+
+       cmpb    SIGN_POS,PARAM5
+       je      fpu_reg_round_special_exit
+
+       orw     $0x8000,EXP(%edi)       /* Negative sign for the result. */
+
+fpu_reg_round_special_exit:
+
+#ifndef NON_REENTRANT_FPU
+       popl    %ebx            /* adjust the stack pointer */
+#endif /* NON_REENTRANT_FPU */
+
+fpu_Arith_exit:
+       popl    %ebx
+       popl    %edi
+       popl    %esi
+       leave
+       ret
+
+
+/*
+ * Set the FPU status flags to represent precision loss due to
+ * round-up.
+ */
+L_precision_lost_up:
+       push    %edx
+       push    %eax
+       call    SYMBOL_NAME(set_precision_flag_up)
+       popl    %eax
+       popl    %edx
+       jmp     L_no_precision_loss
+
+/*
+ * Set the FPU status flags to represent precision loss due to
+ * truncation.
+ */
+L_precision_lost_down:
+       push    %edx
+       push    %eax
+       call    SYMBOL_NAME(set_precision_flag_down)
+       popl    %eax
+       popl    %edx
+       jmp     L_no_precision_loss
+
+
+/*
+ * The number is a denormal (which might get rounded up to a normal)
+ * Shift the number right the required number of bits, which will
+ * have to be undone later...
+ */
+L_Make_denorm:
+       /* The action to be taken depends upon whether the underflow
+          exception is masked */
+       testb   CW_Underflow,%cl                /* Underflow mask. */
+       jz      Unmasked_underflow              /* Do not make a denormal. */
+
+       movb    DENORMAL,FPU_denormal
+
+       pushl   %ecx            /* Save */
+       movw    EXP_UNDER+1,%cx
+       subw    EXP(%edi),%cx
+
+       cmpw    $64,%cx /* shrd only works for 0..31 bits */
+       jnc     Denorm_shift_more_than_63
+
+       cmpw    $32,%cx /* shrd only works for 0..31 bits */
+       jnc     Denorm_shift_more_than_32
+
+/*
+ * We got here without jumps by assuming that the most common requirement
+ *   is for a small de-normalising shift.
+ * Shift by [1..31] bits
+ */
+       addw    %cx,EXP(%edi)
+       orl     %edx,%edx       /* extension */
+       setne   %ch             /* Save whether %edx is non-zero */
+       xorl    %edx,%edx
+       shrd    %cl,%ebx,%edx
+       shrd    %cl,%eax,%ebx
+       shr     %cl,%eax
+       orb     %ch,%dl
+       popl    %ecx
+       jmp     Denorm_done
+
+/* Shift by [32..63] bits */
+Denorm_shift_more_than_32:
+       addw    %cx,EXP(%edi)
+       subb    $32,%cl
+       orl     %edx,%edx
+       setne   %ch
+       orb     %ch,%bl
+       xorl    %edx,%edx
+       shrd    %cl,%ebx,%edx
+       shrd    %cl,%eax,%ebx
+       shr     %cl,%eax
+       orl     %edx,%edx               /* test these 32 bits */
+       setne   %cl
+       orb     %ch,%bl
+       orb     %cl,%bl
+       movl    %ebx,%edx
+       movl    %eax,%ebx
+       xorl    %eax,%eax
+       popl    %ecx
+       jmp     Denorm_done
+
+/* Shift by [64..) bits */
+Denorm_shift_more_than_63:
+       cmpw    $64,%cx
+       jne     Denorm_shift_more_than_64
+
+/* Exactly 64 bit shift */
+       addw    %cx,EXP(%edi)
+       xorl    %ecx,%ecx
+       orl     %edx,%edx
+       setne   %cl
+       orl     %ebx,%ebx
+       setne   %ch
+       orb     %ch,%cl
+       orb     %cl,%al
+       movl    %eax,%edx
+       xorl    %eax,%eax
+       xorl    %ebx,%ebx
+       popl    %ecx
+       jmp     Denorm_done
+
+Denorm_shift_more_than_64:
+       movw    EXP_UNDER+1,EXP(%edi)
+/* This is easy, %eax must be non-zero, so.. */
+       movl    $1,%edx
+       xorl    %eax,%eax
+       xorl    %ebx,%ebx
+       popl    %ecx
+       jmp     Denorm_done
+
+
+Unmasked_underflow:
+       movb    UNMASKED_UNDERFLOW,FPU_denormal
+       jmp     Denorm_done
+
+
+/* Undo the de-normalisation. */
+Normalise_result:
+       cmpb    UNMASKED_UNDERFLOW,FPU_denormal
+       je      Signal_underflow
+
+/* The number must be a denormal if we got here. */
+#ifdef PARANOID
+       /* But check it... just in case. */
+       cmpw    EXP_UNDER+1,EXP(%edi)
+       jne     L_norm_bugged
+#endif /* PARANOID */
+
+#ifdef PECULIAR_486
+       /*
+        * This implements a special feature of 80486 behaviour.
+        * Underflow will be signalled even if the number is
+        * not a denormal after rounding.
+        * This difference occurs only for masked underflow, and not
+        * in the unmasked case.
+        * Actual 80486 behaviour differs from this in some circumstances.
+        */
+       orl     %eax,%eax               /* ms bits */
+       js      LPseudoDenormal         /* Will be masked underflow */
+#else
+       orl     %eax,%eax               /* ms bits */
+       js      L_Normalised            /* No longer a denormal */
+#endif /* PECULIAR_486 */
+
+       jnz     LDenormal_adj_exponent
+
+       orl     %ebx,%ebx
+       jz      L_underflow_to_zero     /* The contents are zero */
+
+LDenormal_adj_exponent:
+       decw    EXP(%edi)
+
+LPseudoDenormal:
+       testb   $0xff,FPU_bits_lost     /* bits lost == underflow */
+       movl    TAG_Special,%edx
+       jz      L_deNormalised
+
+       /* There must be a masked underflow */
+       push    %eax
+       pushl   EX_Underflow
+       call    EXCEPTION
+       popl    %eax
+       popl    %eax
+       movl    TAG_Special,%edx
+       jmp     L_deNormalised
+
+
+/*
+ * The operations resulted in a number too small to represent.
+ * Masked response.
+ */
+L_underflow_to_zero:
+       push    %eax
+       call    SYMBOL_NAME(set_precision_flag_down)
+       popl    %eax
+
+       push    %eax
+       pushl   EX_Underflow
+       call    EXCEPTION
+       popl    %eax
+       popl    %eax
+
+/* Reduce the exponent to EXP_UNDER */
+       movw    EXP_UNDER,EXP(%edi)
+       movl    TAG_Zero,%edx
+       jmp     L_Store_significand
+
+
+/* The operations resulted in a number too large to represent. */
+L_overflow:
+        pushw   PARAM5
+       addw    EXTENDED_Ebias,EXP(%edi)        /* Set for unmasked response. */
+       push    %edi
+        call    SYMBOL_NAME(arith_round_overflow)
+       pop     %edi
+       jmp     fpu_reg_round_signed_special_exit
+
+
+Signal_underflow:
+       /* The number may have been changed to a non-denormal */
+       /* by the rounding operations. */
+       cmpw    EXP_UNDER,EXP(%edi)
+       jle     Do_unmasked_underflow
+
+       jmp     L_Normalised
+
+Do_unmasked_underflow:
+       /* Increase the exponent by the magic number */
+       addw    $(3*(1<<13)),EXP(%edi)
+       push    %eax
+       pushl   EX_Underflow
+       call    EXCEPTION
+       popl    %eax
+       popl    %eax
+       jmp     L_Normalised
+
+
+#ifdef PARANOID
+#ifdef PECULIAR_486
+L_bugged_denorm_486:
+       pushl   EX_INTERNAL|0x236
+       call    EXCEPTION
+       popl    %ebx
+       jmp     L_exception_exit
+#else
+L_bugged_denorm:
+       pushl   EX_INTERNAL|0x230
+       call    EXCEPTION
+       popl    %ebx
+       jmp     L_exception_exit
+#endif /* PECULIAR_486 */
+
+L_bugged_round24:
+       pushl   EX_INTERNAL|0x231
+       call    EXCEPTION
+       popl    %ebx
+       jmp     L_exception_exit
+
+L_bugged_round53:
+       pushl   EX_INTERNAL|0x232
+       call    EXCEPTION
+       popl    %ebx
+       jmp     L_exception_exit
+
+L_bugged_round64:
+       pushl   EX_INTERNAL|0x233
+       call    EXCEPTION
+       popl    %ebx
+       jmp     L_exception_exit
+
+L_norm_bugged:
+       pushl   EX_INTERNAL|0x234
+       call    EXCEPTION
+       popl    %ebx
+       jmp     L_exception_exit
+
+L_entry_bugged:
+       pushl   EX_INTERNAL|0x235
+       call    EXCEPTION
+       popl    %ebx
+L_exception_exit:
+       mov     $-1,%eax
+       jmp     fpu_reg_round_special_exit
+#endif /* PARANOID */
diff --git a/sid/component/bochs/cpu/fpu/reg_round.c b/sid/component/bochs/cpu/fpu/reg_round.c
new file mode 100644 (file)
index 0000000..37af469
--- /dev/null
@@ -0,0 +1,538 @@
+/*---------------------------------------------------------------------------+
+ |  reg_round.c                                                              |
+ |                                                                           |
+ | Rounding/truncation/etc for FPU basic arithmetic functions.               |
+ |                                                                           |
+ | Copyright (C) 1993,1995,1997,1999                                         |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@melbpc.org.au              |
+ |                                                                           |
+ | This code has four possible entry points.                                 |
+ | The following must be entered by a jmp instruction:                       |
+ |   fpu_reg_round, fpu_reg_round_sqrt, and fpu_Arith_exit.                  |
+ |                                                                           |
+ | The FPU_round entry point is intended to be used by C code.               |
+ |                                                                           |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
+ |                                                                           |
+ | For correct "up" and "down" rounding, the argument must have the correct  |
+ | sign.                                                                     |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ |                                                                           |
+ | The significand and its extension are assumed to be exact in the          |
+ | following sense:                                                          |
+ |   If the significand by itself is the exact result then the significand   |
+ |   extension (%edx) must contain 0, otherwise the significand extension    |
+ |   must be non-zero.                                                       |
+ |   If the significand extension is non-zero then the significand is        |
+ |   smaller than the magnitude of the correct exact result by an amount     |
+ |   greater than zero and less than one ls bit of the significand.          |
+ |   The significand extension is only required to have three possible       |
+ |   non-zero values:                                                        |
+ |       less than 0x80000000  <=> the significand is less than 1/2 an ls    |
+ |                                 bit smaller than the magnitude of the     |
+ |                                 true exact result.                        |
+ |         exactly 0x80000000  <=> the significand is exactly 1/2 an ls bit  |
+ |                                 smaller than the magnitude of the true    |
+ |                                 exact result.                             |
+ |    greater than 0x80000000  <=> the significand is more than 1/2 an ls    |
+ |                                 bit smaller than the magnitude of the     |
+ |                                 true exact result.                        |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ |  The code in this module has become quite complex, but it should handle   |
+ |  all of the FPU flags which are set at this stage of the basic arithmetic |
+ |  computations.                                                            |
+ |  There are a few rare cases where the results are not set identically to  |
+ |  a real FPU. These require a bit more thought because at this stage the   |
+ |  results of the code here appear to be more consistent...                 |
+ |  This may be changed in a future version.                                 |
+ +---------------------------------------------------------------------------*/
+
+
+#include "fpu_emu.h"
+#include "exception.h"
+#include "control_w.h"
+
+/* Flags for FPU_bits_lost */
+#define        LOST_DOWN       1
+#define        LOST_UP         2
+
+/* Flags for FPU_denormal */
+#define        DENORMAL        1
+#define        UNMASKED_UNDERFLOW 2
+
+
+int round_up_64(FPU_REG *x, u32 extent)
+{
+  x->sigl ++;
+  if ( x->sigl == 0 )
+    {
+      x->sigh ++;
+      if ( x->sigh == 0 )
+       {
+         x->sigh = 0x80000000;
+         x->exp ++;
+       }
+    }
+  return LOST_UP;
+}
+
+
+int truncate_64(FPU_REG *x, u32 extent)
+{
+  return LOST_DOWN;
+}
+
+
+int round_up_53(FPU_REG *x, u32 extent)
+{
+  x->sigl &= 0xfffff800;
+  x->sigl += 0x800;
+  if ( x->sigl == 0 )
+    {
+      x->sigh ++;
+      if ( x->sigh == 0 )
+       {
+         x->sigh = 0x80000000;
+         x->exp ++;
+       }
+    }
+  return LOST_UP;
+}
+
+
+int truncate_53(FPU_REG *x, u32 extent)
+{
+  x->sigl &= 0xfffff800;
+  return LOST_DOWN;
+}
+
+
+int round_up_24(FPU_REG *x, u32 extent)
+{
+  x->sigl = 0;
+  x->sigh &= 0xffffff00;
+  x->sigh += 0x100;
+  if ( x->sigh == 0 )
+    {
+      x->sigh = 0x80000000;
+      x->exp ++;
+    }
+  return LOST_UP;
+}
+
+
+int truncate_24(FPU_REG *x, u32 extent)
+{
+  x->sigl = 0;
+  x->sigh &= 0xffffff00;
+  return LOST_DOWN;
+}
+
+
+int FPU_round(FPU_REG *x, u32 extent, int dummy, u16 control_w, u8 sign)
+{
+  u64 work;
+  u32 leading;
+  s16 expon = x->exp;
+  int FPU_bits_lost = 0, FPU_denormal, shift, tag;
+
+  if ( expon <= EXP_UNDER )
+    {
+      /* A denormal or zero */
+      if ( control_w & CW_Underflow )
+       {
+         /* Underflow is masked. */
+         FPU_denormal = DENORMAL;
+         shift = EXP_UNDER+1 - expon;
+         if ( shift >= 64 )
+           {
+             if ( shift == 64 )
+               {
+                 x->exp += 64;
+                 if ( extent | x->sigl )
+                   extent = x->sigh | 1;
+                 else
+                   extent = x->sigh;
+               }
+             else
+               {
+                 x->exp = EXP_UNDER+1;
+                 extent = 1;
+               }
+             significand(x) = 0;
+           }
+         else
+           {
+             x->exp += shift;
+             if ( shift >= 32 )
+               {
+                 shift -= 32;
+                 if ( shift )
+                   {
+                     extent |= x->sigl;
+                     work = significand(x) >> shift;
+                     if ( extent )
+                       extent = work | 1;
+                     else
+                       extent = work;
+                     x->sigl = x->sigh >>= shift;
+                   }
+                 else
+                   {
+                     if ( extent )
+                       extent = x->sigl | 1;
+                     else
+                       extent = x->sigl;
+                     x->sigl = x->sigh;
+                   }
+                 x->sigh = 0;
+               }
+             else
+               {
+                 /* Shift by 1 to 32 places. */
+                 work = x->sigl;
+                 work <<= 32;
+                 work |= extent;
+                 work >>= shift;
+                 if ( extent )
+                   extent = 1;
+                 extent |= work;
+                 significand(x) >>= shift;
+               }
+           }
+       }
+      else
+       {
+         /* Unmasked underflow. */
+         FPU_denormal = UNMASKED_UNDERFLOW;
+       }
+    }
+  else
+    FPU_denormal = 0;
+
+  switch ( control_w & CW_PC )
+    {
+    case 01:
+#ifndef PECULIAR_486
+      /* With the precision control bits set to 01 "(reserved)", a real 80486
+        behaves as if the precision control bits were set to 11 "64 bits" */
+#ifdef PARANOID
+       EXCEPTION(EX_INTERNAL|0x236);
+       return -1;
+#endif
+#endif
+       /* Fall through to the 64 bit case. */
+    case PR_64_BITS:
+      if ( extent )
+       {
+         switch ( control_w & CW_RC )
+           {
+           case RC_RND:                /* Nearest or even */
+             /* See if there is exactly half a ulp. */
+             if ( extent == 0x80000000 )
+               {
+                 /* Round to even. */
+                 if ( x->sigl & 0x1 )
+                   /* Odd */
+                   FPU_bits_lost = round_up_64(x, extent);
+                 else
+                   /* Even */
+                   FPU_bits_lost = truncate_64(x, extent);
+               }
+             else if ( extent > 0x80000000 )
+               {
+                 /* Greater than half */
+                 FPU_bits_lost = round_up_64(x, extent);
+               }
+             else
+               {
+                 /* Less than half */
+                 FPU_bits_lost = truncate_64(x, extent);
+               }
+             break;
+
+           case RC_CHOP:               /* Truncate */
+             FPU_bits_lost = truncate_64(x, extent);
+             break;
+             
+           case RC_UP:         /* Towards +infinity */
+             if ( sign == SIGN_POS)
+               {
+                 FPU_bits_lost = round_up_64(x, extent);
+               }
+             else
+               {
+                 FPU_bits_lost = truncate_64(x, extent);
+               }
+             break;
+
+           case RC_DOWN:               /* Towards -infinity */
+             if ( sign != SIGN_POS)
+               {
+                 FPU_bits_lost = round_up_64(x, extent);
+               }
+             else
+               {
+                 FPU_bits_lost = truncate_64(x, extent);
+               }
+             break;
+
+           default:
+             EXCEPTION(EX_INTERNAL|0x231);
+             return -1;
+           }
+       }
+      break;
+
+    case PR_53_BITS:
+      leading = x->sigl & 0x7ff;
+      if ( extent || leading )
+       {
+         switch ( control_w & CW_RC )
+           {
+           case RC_RND:                /* Nearest or even */
+             /* See if there is exactly half a ulp. */
+             if ( leading == 0x400 )
+               {
+                 if ( extent == 0 )
+                   {
+                     /* Round to even. */
+                     if ( x->sigl & 0x800 )
+                       /* Odd */
+                       FPU_bits_lost = round_up_53(x, extent);
+                     else
+                       /* Even */
+                       FPU_bits_lost = truncate_53(x, extent);
+                   }
+                 else
+                   {
+                     /* Greater than half */
+                     FPU_bits_lost = round_up_53(x, extent);
+                   }
+               }
+             else if ( leading > 0x400 )
+               {
+                 /* Greater than half */
+                 FPU_bits_lost = round_up_53(x, extent);
+               }
+             else
+               {
+                 /* Less than half */
+                 FPU_bits_lost = truncate_53(x, extent);
+               }
+             break;
+
+           case RC_CHOP:               /* Truncate */
+             FPU_bits_lost = truncate_53(x, extent);
+             break;
+
+           case RC_UP:         /* Towards +infinity */
+             if ( sign == SIGN_POS)
+               {
+                 FPU_bits_lost = round_up_53(x, extent);
+               }
+             else
+               {
+                 FPU_bits_lost = truncate_53(x, extent);
+               }
+             break;
+
+           case RC_DOWN:               /* Towards -infinity */
+             if ( sign != SIGN_POS)
+               {
+                 FPU_bits_lost = round_up_53(x, extent);
+               }
+             else
+               {
+                 FPU_bits_lost = truncate_53(x, extent);
+               }
+             break;
+
+           default:
+             EXCEPTION(EX_INTERNAL|0x231);
+             return -1;
+           }
+       }
+      break;
+
+    case PR_24_BITS:
+      leading = x->sigh & 0xff;
+      if ( leading || x->sigl || extent )
+       {
+         switch ( control_w & CW_RC )
+           {
+           case RC_RND:                /* Nearest or even */
+             /* See if there is exactly half a ulp. */
+             if ( leading == 0x80 )
+               {
+                 if ( (x->sigl == 0) && (extent == 0) )
+                   {
+                     /* Round to even. */
+                     if ( x->sigh & 0x100 )
+                       /* Odd */
+                       FPU_bits_lost = round_up_24(x, extent);
+                     else
+                       /* Even */
+                       FPU_bits_lost = truncate_24(x, extent);
+                   }
+                 else
+                   {
+                     /* Greater than half */
+                     FPU_bits_lost = round_up_24(x, extent);
+                   }
+               }
+             else if ( leading > 0x80 )
+               {
+                 /* Greater than half */
+                 FPU_bits_lost = round_up_24(x, extent);
+               }
+             else
+               {
+                 /* Less than half */
+                 FPU_bits_lost = truncate_24(x, extent);
+               }
+             break;
+
+           case RC_CHOP:               /* Truncate */
+             FPU_bits_lost = truncate_24(x, extent);
+             break;
+
+           case RC_UP:         /* Towards +infinity */
+             if ( sign == SIGN_POS)
+               {
+                 FPU_bits_lost = round_up_24(x, extent);
+               }
+             else
+               {
+                 FPU_bits_lost = truncate_24(x, extent);
+               }
+             break;
+
+           case RC_DOWN:               /* Towards -infinity */
+             if ( sign != SIGN_POS)
+               {
+                 FPU_bits_lost = round_up_24(x, extent);
+               }
+             else
+               {
+                 FPU_bits_lost = truncate_24(x, extent);
+               }
+             break;
+
+           default:
+             EXCEPTION(EX_INTERNAL|0x231);
+             return -1;
+           }
+       }
+      break;
+
+    default:
+#ifdef PARANOID
+       EXCEPTION(EX_INTERNAL|0x230);
+       return -1;
+#endif
+      break;
+    }
+
+  tag = TAG_Valid;
+
+  if ( FPU_denormal )
+    {
+      /* Undo the de-normalisation. */
+      if ( FPU_denormal == UNMASKED_UNDERFLOW )
+       {
+         if ( x->exp <= EXP_UNDER )
+           {
+             /* Increase the exponent by the magic number */
+             x->exp += 3 * (1 << 13);
+             EXCEPTION(EX_Underflow);
+           }
+       }
+      else
+       {
+         if ( x->exp != EXP_UNDER+1 )
+           {
+             EXCEPTION(EX_INTERNAL|0x234);
+           }
+         if ( (x->sigh == 0) && (x->sigl == 0) )
+           {
+             /* Underflow to zero */
+             set_precision_flag_down();
+             EXCEPTION(EX_Underflow);
+             x->exp = EXP_UNDER;
+             tag = TAG_Zero;
+             FPU_bits_lost = 0;  /* Stop another call to
+                                    set_precision_flag_down() */
+           }
+         else
+           {
+             if ( x->sigh & 0x80000000 )
+               {
+#ifdef PECULIAR_486
+       /*
+        * This implements a special feature of 80486 behaviour.
+        * Underflow will be signalled even if the number is
+        * not a denormal after rounding.
+        * This difference occurs only for masked underflow, and not
+        * in the unmasked case.
+        * Actual 80486 behaviour differs from this in some circumstances.
+        */
+             /* Will be masked underflow */
+#else
+             /* No longer a denormal */
+#endif
+               }
+             else
+#ifndef PECULIAR_486
+               {
+#endif
+               x->exp --;
+
+             if ( FPU_bits_lost )
+               {
+                 /* There must be a masked underflow */
+                 EXCEPTION(EX_Underflow);
+               }
+
+             tag = TAG_Special;
+#ifndef PECULIAR_486
+               }
+#endif
+           }
+       }
+    }
+
+
+  if ( FPU_bits_lost == LOST_UP )
+    set_precision_flag_up();
+  else   if ( FPU_bits_lost == LOST_DOWN )
+    set_precision_flag_down();
+
+  if ( x->exp >= EXP_OVER )
+    {
+      x->exp += EXTENDED_Ebias;
+      tag = arith_round_overflow(x, sign);
+    }
+  else
+    {
+      x->exp += EXTENDED_Ebias;
+      x->exp &= 0x7fff;
+    }
+
+  if ( sign != SIGN_POS )
+    x->exp |= 0x8000;
+
+  return tag;
+
+}
+
+
+
diff --git a/sid/component/bochs/cpu/fpu/reg_u_add.S b/sid/component/bochs/cpu/fpu/reg_u_add.S
new file mode 100644 (file)
index 0000000..47c4c24
--- /dev/null
@@ -0,0 +1,167 @@
+       .file   "reg_u_add.S"
+/*---------------------------------------------------------------------------+
+ |  reg_u_add.S                                                              |
+ |                                                                           |
+ | Add two valid (TAG_Valid) FPU_REG numbers, of the same sign, and put the  |
+ |   result in a destination FPU_REG.                                        |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1995,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ | Call from C as:                                                           |
+ |   int  FPU_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,             |
+ |                                                int control_w)             |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*
+ |    Kernel addition routine FPU_u_add(reg *arg1, reg *arg2, reg *answ).
+ |    Takes two valid reg f.p. numbers (TAG_Valid), which are
+ |    treated as unsigned numbers,
+ |    and returns their sum as a TAG_Valid or TAG_Special f.p. number.
+ |    The returned number is normalized.
+ |    Basic checks are performed if PARANOID is defined.
+ */
+
+#include "exception.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+
+.text
+ENTRY(FPU_u_add)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %esi
+       pushl   %edi
+       pushl   %ebx
+
+       movl    PARAM1,%esi             /* source 1 */
+       movl    PARAM2,%edi             /* source 2 */
+
+       movl    PARAM6,%ecx
+       movl    %ecx,%edx
+       subl    PARAM7,%ecx                     /* exp1 - exp2 */
+       jge     L_arg1_larger
+
+       /* num1 is smaller */
+       movl    SIGL(%esi),%ebx
+       movl    SIGH(%esi),%eax
+
+       movl    %edi,%esi
+       movl    PARAM7,%edx
+       negw    %cx
+       jmp     L_accum_loaded
+
+L_arg1_larger:
+       /* num1 has larger or equal exponent */
+       movl    SIGL(%edi),%ebx
+       movl    SIGH(%edi),%eax
+
+L_accum_loaded:
+       movl    PARAM3,%edi             /* destination */
+       movw    %dx,EXP(%edi)           /* Copy exponent to destination */
+
+       xorl    %edx,%edx               /* clear the extension */
+
+#ifdef PARANOID
+       testl   $0x80000000,%eax
+       je      L_bugged
+
+       testl   $0x80000000,SIGH(%esi)
+       je      L_bugged
+#endif /* PARANOID */
+
+/* The number to be shifted is in %eax:%ebx:%edx */
+       cmpw    $32,%cx         /* shrd only works for 0..31 bits */
+       jnc     L_more_than_31
+
+/* less than 32 bits */
+       shrd    %cl,%ebx,%edx
+       shrd    %cl,%eax,%ebx
+       shr     %cl,%eax
+       jmp     L_shift_done
+
+L_more_than_31:
+       cmpw    $64,%cx
+       jnc     L_more_than_63
+
+       subb    $32,%cl
+       jz      L_exactly_32
+
+       shrd    %cl,%eax,%edx
+       shr     %cl,%eax
+       orl     %ebx,%ebx
+       jz      L_more_31_no_low        /* none of the lowest bits is set */
+
+       orl     $1,%edx                 /* record the fact in the extension */
+
+L_more_31_no_low:
+       movl    %eax,%ebx
+       xorl    %eax,%eax
+       jmp     L_shift_done
+
+L_exactly_32:
+       movl    %ebx,%edx
+       movl    %eax,%ebx
+       xorl    %eax,%eax
+       jmp     L_shift_done
+
+L_more_than_63:
+       cmpw    $65,%cx
+       jnc     L_more_than_64
+
+       movl    %eax,%edx
+       orl     %ebx,%ebx
+       jz      L_more_63_no_low
+
+       orl     $1,%edx
+       jmp     L_more_63_no_low
+
+L_more_than_64:
+       movl    $1,%edx         /* The shifted nr always at least one '1' */
+
+L_more_63_no_low:
+       xorl    %ebx,%ebx
+       xorl    %eax,%eax
+
+L_shift_done:
+       /* Now do the addition */
+       addl    SIGL(%esi),%ebx
+       adcl    SIGH(%esi),%eax
+       jnc     L_round_the_result
+
+       /* Overflow, adjust the result */
+       rcrl    $1,%eax
+       rcrl    $1,%ebx
+       rcrl    $1,%edx
+       jnc     L_no_bit_lost
+
+       orl     $1,%edx
+
+L_no_bit_lost:
+       incw    EXP(%edi)
+
+L_round_the_result:
+       jmp     fpu_reg_round   /* Round the result */
+
+
+
+#ifdef PARANOID
+/* If we ever get here then we have problems! */
+L_bugged:
+       pushl   EX_INTERNAL|0x201
+       call    EXCEPTION
+       pop     %ebx
+       movl    $-1,%eax
+       jmp     L_exit
+
+L_exit:
+       popl    %ebx
+       popl    %edi
+       popl    %esi
+       leave
+       ret
+#endif /* PARANOID */
diff --git a/sid/component/bochs/cpu/fpu/reg_u_add.c b/sid/component/bochs/cpu/fpu/reg_u_add.c
new file mode 100644 (file)
index 0000000..60a81b5
--- /dev/null
@@ -0,0 +1,140 @@
+/*---------------------------------------------------------------------------+
+ |  reg_u_add.c                                                              |
+ |                                                                           |
+ | Add two valid (TAG_Valid) FPU_REG numbers, of the same sign, and put the  |
+ |   result in a destination FPU_REG.                                        |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1995,1997,1999                                    |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@melbpc.org.au                             |
+ |                                                                           |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*
+ |    Kernel addition routine FPU_u_add(reg *arg1, reg *arg2, reg *answ).
+ |    Takes two valid reg f.p. numbers (TAG_Valid), which are
+ |    treated as unsigned numbers,
+ |    and returns their sum as a TAG_Valid or TAG_Special f.p. number.
+ |    The returned number is normalized.
+ |    Basic checks are performed if PARANOID is defined.
+ */
+
+#include "exception.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+
+
+int  FPU_u_add(const FPU_REG *arg1, const FPU_REG *arg2, FPU_REG *answ,
+              u16 control_w, u_char sign, s32 expa, s32 expb)
+{
+  const FPU_REG *rtmp;
+  FPU_REG shifted;
+  u32 extent = 0;
+  int ediff = expa - expb, ed2, eflag, ovfl, carry;
+
+  if ( ediff < 0 )
+    {
+      ediff = -ediff;
+      rtmp = arg1;
+      arg1 = arg2;
+      arg2 = rtmp;
+      expa = expb;
+    }
+
+  /* Now we have exponent of arg1 >= exponent of arg2 */
+  
+  answ->exp = expa;
+
+#ifdef PARANOID
+  if ( !(arg1->sigh & 0x80000000) || !(arg2->sigh & 0x80000000) )
+    {
+      EXCEPTION(EX_INTERNAL|0x201);
+      return -1;
+    }
+#endif
+
+  if ( ediff == 0 )
+    {
+      extent = 0;
+      shifted.sigl = arg2->sigl;
+      shifted.sigh = arg2->sigh;
+    }
+  else if ( ediff < 32 )
+    {
+      ed2 = 32 - ediff;
+      extent = arg2->sigl << ed2;
+      shifted.sigl = arg2->sigl >> ediff;
+      shifted.sigl |= (arg2->sigh << ed2);
+      shifted.sigh = arg2->sigh >> ediff;
+    }
+  else if ( ediff < 64 )
+    {
+      ediff -= 32;
+      if ( ! ediff )
+       {
+         eflag = 0;
+         extent = arg2->sigl;
+         shifted.sigl = arg2->sigh;
+       }
+      else
+       {
+         ed2 = 32 - ediff;
+         eflag = arg2->sigl;
+         if ( eflag )
+           extent |= 1;
+         extent = arg2->sigl >> ediff;
+         extent |= (arg2->sigh << ed2);
+         shifted.sigl = arg2->sigh >> ediff;
+       }
+      shifted.sigh = 0;
+    }
+  else
+    {
+      ediff -= 64;
+      if ( ! ediff )
+       {
+         eflag = arg2->sigl;
+         extent = arg2->sigh;
+       }
+      else
+       {
+         ed2 = 64 - ediff;
+         eflag = arg2->sigl | arg2->sigh;
+         extent = arg2->sigh >> ediff;
+       }
+      shifted.sigl = 0;
+      shifted.sigh = 0;
+      if ( eflag )
+       extent |= 1;
+    }
+
+  answ->sigh = arg1->sigh + shifted.sigh;
+  ovfl = shifted.sigh > answ->sigh;
+  answ->sigl = arg1->sigl + shifted.sigl;
+  if ( shifted.sigl > answ->sigl )
+    {
+      answ->sigh ++;
+      if ( answ->sigh == 0 )
+       ovfl = 1;
+    }
+  if ( ovfl )
+    {
+      carry = extent & 1;
+      extent >>= 1;
+      extent |= carry;
+      if ( answ->sigl & 1 )
+       extent |= 0x80000000;
+      answ->sigl >>= 1;
+      if ( answ->sigh & 1 )
+       answ->sigl |= 0x80000000;
+      answ->sigh >>= 1;
+      answ->sigh |= 0x80000000;
+      answ->exp ++;
+    }
+
+  return FPU_round(answ, extent, 0, control_w, sign);
+
+}
diff --git a/sid/component/bochs/cpu/fpu/reg_u_div.S b/sid/component/bochs/cpu/fpu/reg_u_div.S
new file mode 100644 (file)
index 0000000..663fa7b
--- /dev/null
@@ -0,0 +1,473 @@
+       .file   "reg_u_div.S"
+/*---------------------------------------------------------------------------+
+ |  reg_u_div.S                                                              |
+ |                                                                           |
+ | Divide one FPU_REG by another and put the result in a destination FPU_REG.|
+ |                                                                           |
+ | Copyright (C) 1992,1993,1995,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | Call from C as:                                                           |
+ |    int FPU_u_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest,                   |
+ |                unsigned int control_word, char *sign)                     |
+ |                                                                           |
+ |  Does not compute the destination exponent, but does adjust it.           |
+ |                                                                           |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+
+
+/* #define     dSIGL(x)        (x) */
+/* #define     dSIGH(x)        4(x) */
+
+
+#ifndef NON_REENTRANT_FPU
+/*
+       Local storage on the stack:
+       Result:         FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0
+       Overflow flag:  ovfl_flag
+ */
+#define FPU_accum_3    -4(%ebp)
+#define FPU_accum_2    -8(%ebp)
+#define FPU_accum_1    -12(%ebp)
+#define FPU_accum_0    -16(%ebp)
+#define FPU_result_1   -20(%ebp)
+#define FPU_result_2   -24(%ebp)
+#define FPU_ovfl_flag  -28(%ebp)
+
+#else
+.data
+/*
+       Local storage in a static area:
+       Result:         FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0
+       Overflow flag:  ovfl_flag
+ */
+       .align 4,0
+FPU_accum_3:
+       .long   0
+FPU_accum_2:
+       .long   0
+FPU_accum_1:
+       .long   0
+FPU_accum_0:
+       .long   0
+FPU_result_1:
+       .long   0
+FPU_result_2:
+       .long   0
+FPU_ovfl_flag:
+       .byte   0
+#endif /* NON_REENTRANT_FPU */
+
+#define REGA   PARAM1
+#define REGB   PARAM2
+#define DEST   PARAM3
+
+.text
+ENTRY(FPU_u_div)
+       pushl   %ebp
+       movl    %esp,%ebp
+#ifndef NON_REENTRANT_FPU
+       subl    $28,%esp
+#endif /* NON_REENTRANT_FPU */
+
+       pushl   %esi
+       pushl   %edi
+       pushl   %ebx
+
+       movl    REGA,%esi
+       movl    REGB,%ebx
+       movl    DEST,%edi
+
+       movw    EXP(%esi),%dx
+       movw    EXP(%ebx),%ax
+       .byte   0x0f,0xbf,0xc0  /* movsx        %ax,%eax */
+       .byte   0x0f,0xbf,0xd2  /* movsx        %dx,%edx */
+       subl    %eax,%edx
+       addl    EXP_BIAS,%edx
+
+       /* A denormal and a large number can cause an exponent underflow */
+       cmpl    EXP_WAY_UNDER,%edx
+       jg      xExp_not_underflow
+
+       /* Set to a really low value allow correct handling */
+       movl    EXP_WAY_UNDER,%edx
+
+xExp_not_underflow:
+
+       movw    %dx,EXP(%edi)
+
+#ifdef PARANOID
+/*     testl   $0x80000000, SIGH(%esi) // Dividend */
+/*     je      L_bugged */
+       testl   $0x80000000, SIGH(%ebx) /* Divisor */
+       je      L_bugged
+#endif /* PARANOID */
+
+/* Check if the divisor can be treated as having just 32 bits */
+       cmpl    $0,SIGL(%ebx)
+       jnz     L_Full_Division /* Can't do a quick divide */
+
+/* We should be able to zip through the division here */
+       movl    SIGH(%ebx),%ecx /* The divisor */
+       movl    SIGH(%esi),%edx /* Dividend */
+       movl    SIGL(%esi),%eax /* Dividend */
+
+       cmpl    %ecx,%edx
+       setaeb  FPU_ovfl_flag   /* Keep a record */
+       jb      L_no_adjust
+
+       subl    %ecx,%edx       /* Prevent the overflow */
+
+L_no_adjust:
+       /* Divide the 64 bit number by the 32 bit denominator */
+       divl    %ecx
+       movl    %eax,FPU_result_2
+
+       /* Work on the remainder of the first division */
+       xorl    %eax,%eax
+       divl    %ecx
+       movl    %eax,FPU_result_1
+
+       /* Work on the remainder of the 64 bit division */
+       xorl    %eax,%eax
+       divl    %ecx
+
+       testb   $255,FPU_ovfl_flag      /* was the num > denom ? */
+       je      L_no_overflow
+
+       /* Do the shifting here */
+       /* increase the exponent */
+       incw    EXP(%edi)
+
+       /* shift the mantissa right one bit */
+       stc                     /* To set the ms bit */
+       rcrl    FPU_result_2
+       rcrl    FPU_result_1
+       rcrl    %eax
+
+L_no_overflow:
+       jmp     LRound_precision        /* Do the rounding as required */
+
+
+/*---------------------------------------------------------------------------+
+ |  Divide:   Return  arg1/arg2 to arg3.                                     |
+ |                                                                           |
+ |  This routine does not use the exponents of arg1 and arg2, but does       |
+ |  adjust the exponent of arg3.                                             |
+ |                                                                           |
+ |  The maximum returned value is (ignoring exponents)                       |
+ |               .ffffffff ffffffff                                          |
+ |               ------------------  =  1.ffffffff fffffffe                  |
+ |               .80000000 00000000                                          |
+ | and the minimum is                                                        |
+ |               .80000000 00000000                                          |
+ |               ------------------  =  .80000000 00000001   (rounded)       |
+ |               .ffffffff ffffffff                                          |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+
+L_Full_Division:
+       /* Save extended dividend in local register */
+       movl    SIGL(%esi),%eax
+       movl    %eax,FPU_accum_2
+       movl    SIGH(%esi),%eax
+       movl    %eax,FPU_accum_3
+       xorl    %eax,%eax
+       movl    %eax,FPU_accum_1        /* zero the extension */
+       movl    %eax,FPU_accum_0        /* zero the extension */
+
+       movl    SIGL(%esi),%eax /* Get the current num */
+       movl    SIGH(%esi),%edx
+
+/*----------------------------------------------------------------------*/
+/* Initialization done.
+   Do the first 32 bits. */
+
+       movb    $0,FPU_ovfl_flag
+       cmpl    SIGH(%ebx),%edx /* Test for imminent overflow */
+       jb      LLess_than_1
+       ja      LGreater_than_1
+
+       cmpl    SIGL(%ebx),%eax
+       jb      LLess_than_1
+
+LGreater_than_1:
+/* The dividend is greater or equal, would cause overflow */
+       setaeb  FPU_ovfl_flag           /* Keep a record */
+
+       subl    SIGL(%ebx),%eax
+       sbbl    SIGH(%ebx),%edx /* Prevent the overflow */
+       movl    %eax,FPU_accum_2
+       movl    %edx,FPU_accum_3
+
+LLess_than_1:
+/* At this point, we have a dividend < divisor, with a record of
+   adjustment in FPU_ovfl_flag */
+
+       /* We will divide by a number which is too large */
+       movl    SIGH(%ebx),%ecx
+       addl    $1,%ecx
+       jnc     LFirst_div_not_1
+
+       /* here we need to divide by 100000000h,
+          i.e., no division at all.. */
+       mov     %edx,%eax
+       jmp     LFirst_div_done
+
+LFirst_div_not_1:
+       divl    %ecx            /* Divide the numerator by the augmented
+                                  denom ms dw */
+
+LFirst_div_done:
+       movl    %eax,FPU_result_2       /* Put the result in the answer */
+
+       mull    SIGH(%ebx)      /* mul by the ms dw of the denom */
+
+       subl    %eax,FPU_accum_2        /* Subtract from the num local reg */
+       sbbl    %edx,FPU_accum_3
+
+       movl    FPU_result_2,%eax       /* Get the result back */
+       mull    SIGL(%ebx)      /* now mul the ls dw of the denom */
+
+       subl    %eax,FPU_accum_1        /* Subtract from the num local reg */
+       sbbl    %edx,FPU_accum_2
+       sbbl    $0,FPU_accum_3
+       je      LDo_2nd_32_bits         /* Must check for non-zero result here */
+
+#ifdef PARANOID
+       jb      L_bugged_1
+#endif /* PARANOID */
+
+       /* need to subtract another once of the denom */
+       incl    FPU_result_2    /* Correct the answer */
+
+       movl    SIGL(%ebx),%eax
+       movl    SIGH(%ebx),%edx
+       subl    %eax,FPU_accum_1        /* Subtract from the num local reg */
+       sbbl    %edx,FPU_accum_2
+
+#ifdef PARANOID
+       sbbl    $0,FPU_accum_3
+       jne     L_bugged_1      /* Must check for non-zero result here */
+#endif /* PARANOID */
+
+/*----------------------------------------------------------------------*/
+/* Half of the main problem is done, there is just a reduced numerator
+   to handle now.
+   Work with the second 32 bits, FPU_accum_0 not used from now on */
+LDo_2nd_32_bits:
+       movl    FPU_accum_2,%edx        /* get the reduced num */
+       movl    FPU_accum_1,%eax
+
+       /* need to check for possible subsequent overflow */
+       cmpl    SIGH(%ebx),%edx
+       jb      LDo_2nd_div
+       ja      LPrevent_2nd_overflow
+
+       cmpl    SIGL(%ebx),%eax
+       jb      LDo_2nd_div
+
+LPrevent_2nd_overflow:
+/* The numerator is greater or equal, would cause overflow */
+       /* prevent overflow */
+       subl    SIGL(%ebx),%eax
+       sbbl    SIGH(%ebx),%edx
+       movl    %edx,FPU_accum_2
+       movl    %eax,FPU_accum_1
+
+       incl    FPU_result_2    /* Reflect the subtraction in the answer */
+
+#ifdef PARANOID
+       je      L_bugged_2      /* Can't bump the result to 1.0 */
+#endif /* PARANOID */
+
+LDo_2nd_div:
+       cmpl    $0,%ecx         /* augmented denom msw */
+       jnz     LSecond_div_not_1
+
+       /* %ecx == 0, we are dividing by 1.0 */
+       mov     %edx,%eax
+       jmp     LSecond_div_done
+
+LSecond_div_not_1:
+       divl    %ecx            /* Divide the numerator by the denom ms dw */
+
+LSecond_div_done:
+       movl    %eax,FPU_result_1       /* Put the result in the answer */
+
+       mull    SIGH(%ebx)      /* mul by the ms dw of the denom */
+
+       subl    %eax,FPU_accum_1        /* Subtract from the num local reg */
+       sbbl    %edx,FPU_accum_2
+
+#ifdef PARANOID
+       jc      L_bugged_2
+#endif /* PARANOID */
+
+       movl    FPU_result_1,%eax       /* Get the result back */
+       mull    SIGL(%ebx)      /* now mul the ls dw of the denom */
+
+       subl    %eax,FPU_accum_0        /* Subtract from the num local reg */
+       sbbl    %edx,FPU_accum_1        /* Subtract from the num local reg */
+       sbbl    $0,FPU_accum_2
+
+#ifdef PARANOID
+       jc      L_bugged_2
+#endif /* PARANOID */
+
+       jz      LDo_3rd_32_bits
+
+#ifdef PARANOID
+       cmpl    $1,FPU_accum_2
+       jne     L_bugged_2
+#endif /* PARANOID */
+
+       /* need to subtract another once of the denom */
+       movl    SIGL(%ebx),%eax
+       movl    SIGH(%ebx),%edx
+       subl    %eax,FPU_accum_0        /* Subtract from the num local reg */
+       sbbl    %edx,FPU_accum_1
+       sbbl    $0,FPU_accum_2
+
+#ifdef PARANOID
+       jc      L_bugged_2
+       jne     L_bugged_2
+#endif /* PARANOID */
+
+       addl    $1,FPU_result_1 /* Correct the answer */
+       adcl    $0,FPU_result_2
+
+#ifdef PARANOID
+       jc      L_bugged_2      /* Must check for non-zero result here */
+#endif /* PARANOID */
+
+/*----------------------------------------------------------------------*/
+/* The division is essentially finished here, we just need to perform
+   tidying operations.
+   Deal with the 3rd 32 bits */
+LDo_3rd_32_bits:
+       movl    FPU_accum_1,%edx                /* get the reduced num */
+       movl    FPU_accum_0,%eax
+
+       /* need to check for possible subsequent overflow */
+       cmpl    SIGH(%ebx),%edx /* denom */
+       jb      LRound_prep
+       ja      LPrevent_3rd_overflow
+
+       cmpl    SIGL(%ebx),%eax /* denom */
+       jb      LRound_prep
+
+LPrevent_3rd_overflow:
+       /* prevent overflow */
+       subl    SIGL(%ebx),%eax
+       sbbl    SIGH(%ebx),%edx
+       movl    %edx,FPU_accum_1
+       movl    %eax,FPU_accum_0
+
+       addl    $1,FPU_result_1 /* Reflect the subtraction in the answer */
+       adcl    $0,FPU_result_2
+       jne     LRound_prep
+       jnc     LRound_prep
+
+       /* This is a tricky spot, there is an overflow of the answer */
+       movb    $255,FPU_ovfl_flag              /* Overflow -> 1.000 */
+
+LRound_prep:
+/*
+ * Prepare for rounding.
+ * To test for rounding, we just need to compare 2*accum with the
+ * denom.
+ */
+       movl    FPU_accum_0,%ecx
+       movl    FPU_accum_1,%edx
+       movl    %ecx,%eax
+       orl     %edx,%eax
+       jz      LRound_ovfl             /* The accumulator contains zero. */
+
+       /* Multiply by 2 */
+       clc
+       rcll    $1,%ecx
+       rcll    $1,%edx
+       jc      LRound_large            /* No need to compare, denom smaller */
+
+       subl    SIGL(%ebx),%ecx
+       sbbl    SIGH(%ebx),%edx
+       jnc     LRound_not_small
+
+       movl    $0x70000000,%eax        /* Denom was larger */
+       jmp     LRound_ovfl
+
+LRound_not_small:
+       jnz     LRound_large
+
+       movl    $0x80000000,%eax        /* Remainder was exactly 1/2 denom */
+       jmp     LRound_ovfl
+
+LRound_large:
+       movl    $0xff000000,%eax        /* Denom was smaller */
+
+LRound_ovfl:
+/* We are now ready to deal with rounding, but first we must get
+   the bits properly aligned */
+       testb   $255,FPU_ovfl_flag      /* was the num > denom ? */
+       je      LRound_precision
+
+       incw    EXP(%edi)
+
+       /* shift the mantissa right one bit */
+       stc                     /* Will set the ms bit */
+       rcrl    FPU_result_2
+       rcrl    FPU_result_1
+       rcrl    %eax
+
+/* Round the result as required */
+LRound_precision:
+       decw    EXP(%edi)       /* binary point between 1st & 2nd bits */
+
+       movl    %eax,%edx
+       movl    FPU_result_1,%ebx
+       movl    FPU_result_2,%eax
+       jmp     fpu_reg_round
+
+
+#ifdef PARANOID
+/* The logic is wrong if we got here */
+L_bugged:
+       pushl   EX_INTERNAL|0x202
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_exit
+
+L_bugged_1:
+       pushl   EX_INTERNAL|0x203
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_exit
+
+L_bugged_2:
+       pushl   EX_INTERNAL|0x204
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_exit
+
+L_exit:
+       movl    $-1,%eax
+       popl    %ebx
+       popl    %edi
+       popl    %esi
+
+       leave
+       ret
+#endif /* PARANOID */
diff --git a/sid/component/bochs/cpu/fpu/reg_u_div.c b/sid/component/bochs/cpu/fpu/reg_u_div.c
new file mode 100644 (file)
index 0000000..c063a61
--- /dev/null
@@ -0,0 +1,276 @@
+/*---------------------------------------------------------------------------+
+ |  reg_u_div.c                                                              |
+ |                                                                           |
+ | Divide one FPU_REG by another and put the result in a destination FPU_REG.|
+ |                                                                           |
+ | Copyright (C) 1992,1993,1995,1997,1999                                    |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@melbpc.org.au                             |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ |                                                                           |
+ |  Does not compute the destination exponent, but does adjust it.           |
+ |                                                                           |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+#include <asm/types.h>
+
+
+int FPU_u_div(const FPU_REG *a, const FPU_REG *b, FPU_REG *dest,
+             u16 control_w, u8 sign)
+{
+  s32 exp;
+  u32 divr32, rem, rat1, rat2, work32, accum3, prodh;
+  u64 work64, divr64, prod64, accum64;
+  u8 ovfl;
+
+  exp = (s32)a->exp - (s32)b->exp;
+
+  if ( exp < EXP_WAY_UNDER )
+    exp = EXP_WAY_UNDER;
+
+  dest->exp = exp;
+#ifdef PARANOID
+  if ( !(b->sigh & 0x80000000) )
+    {
+      EXCEPTION(EX_INTERNAL|0x202);
+    }
+#endif
+
+  work64 = significand(a);
+
+  /* We can save a lot of time if the divisor has all its lowest
+     32 bits equal to zero. */
+  if ( b->sigl == 0 )
+    {
+      divr32 = b->sigh;
+      ovfl = a->sigh >= divr32;
+      rat1 = work64 / divr32;
+      rem = work64 % divr32;
+      work64 = rem;
+      work64 <<= 32;
+      rat2 = work64 / divr32;
+      rem = work64 % divr32;
+
+      work64 = rem;
+      work64 <<= 32;
+      rem = work64 / divr32;
+
+      if ( ovfl )
+       {
+         rem >>= 1;
+         if ( rat2 & 1 )
+           rem |= 0x80000000;
+         rat2 >>= 1;
+         if ( rat1 & 1 )
+           rat2 |= 0x80000000;
+         rat1 >>= 1;
+         rat1 |= 0x80000000;
+         dest->exp ++;
+       }
+      dest->sigh = rat1;
+      dest->sigl = rat2;
+
+      dest->exp --;
+      return FPU_round(dest, rem, 0, control_w, sign);
+    }
+
+  /* This may take a little time... */
+
+  accum64 = work64;
+  divr64 = significand(b);
+
+  if ( (ovfl = accum64 >= divr64) )
+    accum64 -= divr64;
+  divr32 = b->sigh+1;
+
+  if ( divr32 != 0 )
+    {
+      rat1 = accum64 / divr32;
+    }
+  else
+    rat1 = accum64 >> 32;
+  prod64 = rat1 * (u64)b->sigh;
+
+  accum64 -= prod64;
+  prod64 = rat1 * (u64)b->sigl;
+  accum3 = prod64;
+  if ( accum3 )
+    {
+      accum3 = -accum3;
+      accum64 --;
+    }
+  prodh = prod64 >> 32;
+  accum64 -= prodh;
+
+  work32 = accum64 >> 32;
+  if ( work32 )
+    {
+#ifdef PARANOID
+      if ( work32 != 1 )
+       {
+         EXCEPTION(EX_INTERNAL|0x203);
+       }
+#endif
+
+      /* Need to subtract the divisor once more. */
+      work32 = accum3;
+      accum3 = work32 - b->sigl;
+      if ( accum3 > work32 )
+       accum64 --;
+      rat1 ++;
+      accum64 -= b->sigh;
+
+#ifdef PARANOID
+      if ( (accum64 >> 32) )
+       {
+         EXCEPTION(EX_INTERNAL|0x203);
+       }
+#endif
+    }
+
+  /* Now we essentially repeat what we have just done, but shifted
+     32 bits. */
+
+  accum64 <<= 32;
+  accum64 |= accum3;
+  if ( accum64 >= divr64 )
+    {
+      accum64 -= divr64;
+      rat1 ++;
+    }
+  if ( divr32 != 0 )
+    {
+      rat2 = accum64 / divr32;
+    }
+  else
+    rat2 = accum64 >> 32;
+  prod64 = rat2 * (u64)b->sigh;
+
+  accum64 -= prod64;
+  prod64 = rat2 * (u64)b->sigl;
+  accum3 = prod64;
+  if ( accum3 )
+    {
+      accum3 = -accum3;
+      accum64 --;
+    }
+  prodh = prod64 >> 32;
+  accum64 -= prodh;
+
+  work32 = accum64 >> 32;
+  if ( work32 )
+    {
+#ifdef PARANOID
+      if ( work32 != 1 )
+       {
+         EXCEPTION(EX_INTERNAL|0x203);
+       }
+#endif
+
+      /* Need to subtract the divisor once more. */
+      work32 = accum3;
+      accum3 = work32 - b->sigl;
+      if ( accum3 > work32 )
+       accum64 --;
+      rat2 ++;
+      if ( rat2 == 0 )
+       rat1 ++;
+      accum64 -= b->sigh;
+
+#ifdef PARANOID
+      if ( (accum64 >> 32) )
+       {
+         EXCEPTION(EX_INTERNAL|0x203);
+       }
+#endif
+    }
+
+  /* Tidy up the remainder */
+
+  accum64 <<= 32;
+  accum64 |= accum3;
+  if ( accum64 >= divr64 )
+    {
+      accum64 -= divr64;
+      rat2 ++;
+      if ( rat2 == 0 )
+       {
+         rat1 ++;
+#ifdef PARANOID
+         /* No overflow should be possible here */
+         if ( rat1 == 0 )
+           {
+             EXCEPTION(EX_INTERNAL|0x203);
+           }
+       }
+#endif
+    }
+
+  /* The basic division is done, now we must be careful with the
+     remainder. */
+
+  if ( ovfl )
+    {
+      if ( rat2 & 1 )
+       rem = 0x80000000;
+      else
+       rem = 0;
+      rat2 >>= 1;
+      if ( rat1 & 1 )
+       rat2 |= 0x80000000;
+      rat1 >>= 1;
+      rat1 |= 0x80000000;
+
+      if ( accum64 )
+       rem |= 0xff0000;
+
+      dest->exp ++;
+    }
+  else
+    {
+      /* Now we just need to know how large the remainder is
+        relative to half the divisor. */
+      if ( accum64 == 0 )
+       rem = 0;
+      else
+       {
+         accum3 = accum64 >> 32;
+         if ( accum3 & 0x80000000 )
+           {
+             /* The remainder is definitely larger than 1/2 divisor. */
+             rem = 0xff000000;
+           }
+         else
+           {
+             accum64 <<= 1;
+             if ( accum64 >= divr64 )
+               {
+                 accum64 -= divr64;
+                 if ( accum64 == 0 )
+                   rem = 0x80000000;
+                 else
+                   rem = 0xff000000;
+               }
+             else
+               rem = 0x7f000000;
+           }
+       }
+    }
+
+  dest->sigh = rat1;
+  dest->sigl = rat2;
+
+  dest->exp --;
+  return FPU_round(dest, rem, 0, control_w, sign);
+
+}
+
diff --git a/sid/component/bochs/cpu/fpu/reg_u_mul.S b/sid/component/bochs/cpu/fpu/reg_u_mul.S
new file mode 100644 (file)
index 0000000..c84360d
--- /dev/null
@@ -0,0 +1,148 @@
+       .file   "reg_u_mul.S"
+/*---------------------------------------------------------------------------+
+ |  reg_u_mul.S                                                              |
+ |                                                                           |
+ | Core multiplication routine                                               |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1995,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ |   Basic multiplication routine.                                           |
+ |   Does not check the resulting exponent for overflow/underflow            |
+ |                                                                           |
+ |   FPU_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw);         |
+ |                                                                           |
+ |   Internal working is at approx 128 bits.                                 |
+ |   Result is rounded to nearest 53 or 64 bits, using "nearest or even".    |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+
+
+
+#ifndef NON_REENTRANT_FPU
+/*  Local storage on the stack: */
+#define FPU_accum_0    -4(%ebp)        /* ms word */
+#define FPU_accum_1    -8(%ebp)
+
+#else
+/*  Local storage in a static area: */
+.data
+       .align 4,0
+FPU_accum_0:
+       .long   0
+FPU_accum_1:
+       .long   0
+#endif /* NON_REENTRANT_FPU */
+
+
+.text
+ENTRY(FPU_u_mul)
+       pushl   %ebp
+       movl    %esp,%ebp
+#ifndef NON_REENTRANT_FPU
+       subl    $8,%esp
+#endif /* NON_REENTRANT_FPU */
+
+       pushl   %esi
+       pushl   %edi
+       pushl   %ebx
+
+       movl    PARAM1,%esi
+       movl    PARAM2,%edi
+
+#ifdef PARANOID
+       testl   $0x80000000,SIGH(%esi)
+       jz      L_bugged
+       testl   $0x80000000,SIGH(%edi)
+       jz      L_bugged
+#endif /* PARANOID */
+
+       xorl    %ecx,%ecx
+       xorl    %ebx,%ebx
+
+       movl    SIGL(%esi),%eax
+       mull    SIGL(%edi)
+       movl    %eax,FPU_accum_0
+       movl    %edx,FPU_accum_1
+
+       movl    SIGL(%esi),%eax
+       mull    SIGH(%edi)
+       addl    %eax,FPU_accum_1
+       adcl    %edx,%ebx
+/*     adcl    $0,%ecx         // overflow here is not possible */
+
+       movl    SIGH(%esi),%eax
+       mull    SIGL(%edi)
+       addl    %eax,FPU_accum_1
+       adcl    %edx,%ebx
+       adcl    $0,%ecx
+
+       movl    SIGH(%esi),%eax
+       mull    SIGH(%edi)
+       addl    %eax,%ebx
+       adcl    %edx,%ecx
+
+       /* Get the sum of the exponents. */
+       movl    PARAM6,%eax
+       subl    EXP_BIAS-1,%eax
+
+       /* Two denormals can cause an exponent underflow */
+       cmpl    EXP_WAY_UNDER,%eax
+       jg      Exp_not_underflow
+
+       /* Set to a really low value allow correct handling */
+       movl    EXP_WAY_UNDER,%eax
+
+Exp_not_underflow:
+
+/*  Have now finished with the sources */
+       movl    PARAM3,%edi     /* Point to the destination */
+       movw    %ax,EXP(%edi)
+
+/*  Now make sure that the result is normalized */
+       testl   $0x80000000,%ecx
+       jnz     LResult_Normalised
+
+       /* Normalize by shifting left one bit */
+       shll    $1,FPU_accum_0
+       rcll    $1,FPU_accum_1
+       rcll    $1,%ebx
+       rcll    $1,%ecx
+       decw    EXP(%edi)
+
+LResult_Normalised:
+       movl    FPU_accum_0,%eax
+       movl    FPU_accum_1,%edx
+       orl     %eax,%eax
+       jz      L_extent_zero
+
+       orl     $1,%edx
+
+L_extent_zero:
+       movl    %ecx,%eax
+       jmp     fpu_reg_round
+
+
+#ifdef PARANOID
+L_bugged:
+       pushl   EX_INTERNAL|0x205
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_exit
+
+L_exit:
+       popl    %ebx
+       popl    %edi
+       popl    %esi
+       leave
+       ret
+#endif /* PARANOID */
+
diff --git a/sid/component/bochs/cpu/fpu/reg_u_mul.c b/sid/component/bochs/cpu/fpu/reg_u_mul.c
new file mode 100644 (file)
index 0000000..690a00a
--- /dev/null
@@ -0,0 +1,95 @@
+/*---------------------------------------------------------------------------+
+ |  reg_u_mul.c                                                              |
+ |                                                                           |
+ | Core multiplication routine                                               |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1995,1997,1999                                    |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@melbpc.org.au                             |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ |   Basic multiplication routine.                                           |
+ |   Does not check the resulting exponent for overflow/underflow            |
+ |                                                                           |
+ |   Internal working is at approx 128 bits.                                 |
+ |   Result is rounded to nearest 53 or 64 bits, using "nearest or even".    |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+
+
+int FPU_u_mul(const FPU_REG *a, const FPU_REG *b, FPU_REG *c, u16 cw,
+             u_char sign, int expon)
+{
+  u64 mu, ml, mi;
+  u32 lh, ll, th, tl;
+
+#ifdef PARANOID
+  if ( ! (a->sigh & 0x80000000) || ! (b->sigh & 0x80000000) )
+    {
+      EXCEPTION(EX_INTERNAL|0x205);
+    }
+#endif
+
+  ml = a->sigl;
+  ml *= b->sigl;
+  ll = ml;
+  lh = ml >> 32;
+
+  mu = a->sigh;
+  mu *= b->sigh;
+
+  mi = a->sigh;
+  mi *= b->sigl;
+  tl = mi;
+  th = mi >> 32;
+  lh += tl;
+  if ( tl > lh )
+    mu ++;
+  mu += th;
+
+  mi = a->sigl;
+  mi *= b->sigh;
+  tl = mi;
+  th = mi >> 32;
+  lh += tl;
+  if ( tl > lh )
+    mu ++;
+  mu += th;
+
+  ml = lh;
+  ml <<= 32;
+  ml += ll;
+
+  expon -= EXP_BIAS-1;
+  if ( expon <= EXP_WAY_UNDER )
+    expon = EXP_WAY_UNDER;
+
+  c->exp = expon;
+
+  if ( ! (mu & BX_CONST64(0x8000000000000000)) )
+    {
+      mu <<= 1;
+      if ( ml & BX_CONST64(0x8000000000000000) )
+       mu |= 1;
+      ml <<= 1;
+      c->exp --;
+    }
+
+  ll = ml;
+  lh = ml >> 32;
+
+  if ( ll )
+    lh |= 1;
+
+  c->sigl = mu;
+  c->sigh = mu >> 32;
+
+  return FPU_round(c, lh, 0, cw, sign);
+  
+}
diff --git a/sid/component/bochs/cpu/fpu/reg_u_sub.S b/sid/component/bochs/cpu/fpu/reg_u_sub.S
new file mode 100644 (file)
index 0000000..236d3f1
--- /dev/null
@@ -0,0 +1,272 @@
+       .file   "reg_u_sub.S"
+/*---------------------------------------------------------------------------+
+ |  reg_u_sub.S                                                              |
+ |                                                                           |
+ | Core floating point subtraction routine.                                  |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1995,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ | Call from C as:                                                           |
+ |    int FPU_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,             |
+ |                                                int control_w)             |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*
+ |    Kernel subtraction routine FPU_u_sub(reg *arg1, reg *arg2, reg *answ).
+ |    Takes two valid reg f.p. numbers (TAG_Valid), which are
+ |    treated as unsigned numbers,
+ |    and returns their difference as a TAG_Valid or TAG_Zero f.p.
+ |    number.
+ |    The first number (arg1) must be the larger.
+ |    The returned number is normalized.
+ |    Basic checks are performed if PARANOID is defined.
+ */
+
+#include "exception.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+
+.text
+ENTRY(FPU_u_sub)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %esi
+       pushl   %edi
+       pushl   %ebx
+
+       movl    PARAM1,%esi     /* source 1 */
+       movl    PARAM2,%edi     /* source 2 */
+       
+       movl    PARAM6,%ecx
+       subl    PARAM7,%ecx     /* exp1 - exp2 */
+
+#ifdef PARANOID
+       /* source 2 is always smaller than source 1 */
+       js      L_bugged_1
+
+       testl   $0x80000000,SIGH(%edi)  /* The args are assumed to be be normalized */
+       je      L_bugged_2
+
+       testl   $0x80000000,SIGH(%esi)
+       je      L_bugged_2
+#endif /* PARANOID */
+
+/*--------------------------------------+
+ |     Form a register holding the     |
+ |     smaller number                  |
+ +--------------------------------------*/
+       movl    SIGH(%edi),%eax /* register ms word */
+       movl    SIGL(%edi),%ebx /* register ls word */
+
+       movl    PARAM3,%edi     /* destination */
+       movl    PARAM6,%edx
+       movw    %dx,EXP(%edi)   /* Copy exponent to destination */
+
+       xorl    %edx,%edx       /* register extension */
+
+/*--------------------------------------+
+ |     Shift the temporary register    |
+ |      right the required number of   |
+ |     places.                         |
+ +--------------------------------------*/
+
+       cmpw    $32,%cx         /* shrd only works for 0..31 bits */
+       jnc     L_more_than_31
+
+/* less than 32 bits */
+       shrd    %cl,%ebx,%edx
+       shrd    %cl,%eax,%ebx
+       shr     %cl,%eax
+       jmp     L_shift_done
+
+L_more_than_31:
+       cmpw    $64,%cx
+       jnc     L_more_than_63
+
+       subb    $32,%cl
+       jz      L_exactly_32
+
+       shrd    %cl,%eax,%edx
+       shr     %cl,%eax
+       orl     %ebx,%ebx
+       jz      L_more_31_no_low        /* none of the lowest bits is set */
+
+       orl     $1,%edx                 /* record the fact in the extension */
+
+L_more_31_no_low:
+       movl    %eax,%ebx
+       xorl    %eax,%eax
+       jmp     L_shift_done
+
+L_exactly_32:
+       movl    %ebx,%edx
+       movl    %eax,%ebx
+       xorl    %eax,%eax
+       jmp     L_shift_done
+
+L_more_than_63:
+       cmpw    $65,%cx
+       jnc     L_more_than_64
+
+       /* Shift right by 64 bits */
+       movl    %eax,%edx
+       orl     %ebx,%ebx
+       jz      L_more_63_no_low
+
+       orl     $1,%edx
+       jmp     L_more_63_no_low
+
+L_more_than_64:
+       jne     L_more_than_65
+
+       /* Shift right by 65 bits */
+       /* Carry is clear if we get here */
+       movl    %eax,%edx
+       rcrl    %edx
+       jnc     L_shift_65_nc
+
+       orl     $1,%edx
+       jmp     L_more_63_no_low
+
+L_shift_65_nc:
+       orl     %ebx,%ebx
+       jz      L_more_63_no_low
+
+       orl     $1,%edx
+       jmp     L_more_63_no_low
+
+L_more_than_65:
+       movl    $1,%edx         /* The shifted nr always at least one '1' */
+
+L_more_63_no_low:
+       xorl    %ebx,%ebx
+       xorl    %eax,%eax
+
+L_shift_done:
+L_subtr:
+/*------------------------------+
+ |     Do the subtraction      |
+ +------------------------------*/
+       xorl    %ecx,%ecx
+       subl    %edx,%ecx
+       movl    %ecx,%edx
+       movl    SIGL(%esi),%ecx
+       sbbl    %ebx,%ecx
+       movl    %ecx,%ebx
+       movl    SIGH(%esi),%ecx
+       sbbl    %eax,%ecx
+       movl    %ecx,%eax
+
+#ifdef PARANOID
+       /* We can never get a borrow */
+       jc      L_bugged
+#endif /* PARANOID */
+
+/*--------------------------------------+
+ |     Normalize the result            |
+ +--------------------------------------*/
+       testl   $0x80000000,%eax
+       jnz     L_round         /* no shifting needed */
+
+       orl     %eax,%eax
+       jnz     L_shift_1       /* shift left 1 - 31 bits */
+
+       orl     %ebx,%ebx
+       jnz     L_shift_32      /* shift left 32 - 63 bits */
+
+/*
+ *      A rare case, the only one which is non-zero if we got here
+ *         is:           1000000 .... 0000
+ *                      -0111111 .... 1111 1
+ *                       -------------------- 
+ *                       0000000 .... 0000 1 
+ */
+
+       cmpl    $0x80000000,%edx
+       jnz     L_must_be_zero
+
+       /* Shift left 64 bits */
+       subw    $64,EXP(%edi)
+       xchg    %edx,%eax
+       jmp     fpu_reg_round
+
+L_must_be_zero:
+#ifdef PARANOID
+       orl     %edx,%edx
+       jnz     L_bugged_3
+#endif /* PARANOID */
+
+       /* The result is zero */
+       movw    $0,EXP(%edi)            /* exponent */
+       movl    $0,SIGL(%edi)
+       movl    $0,SIGH(%edi)
+       movl    TAG_Zero,%eax
+       jmp     L_exit
+
+L_shift_32:
+       movl    %ebx,%eax
+       movl    %edx,%ebx
+       movl    $0,%edx
+       subw    $32,EXP(%edi)   /* Can get underflow here */
+
+/* We need to shift left by 1 - 31 bits */
+L_shift_1:
+       bsrl    %eax,%ecx       /* get the required shift in %ecx */
+       subl    $31,%ecx
+       negl    %ecx
+       shld    %cl,%ebx,%eax
+       shld    %cl,%edx,%ebx
+       shl     %cl,%edx
+       subw    %cx,EXP(%edi)   /* Can get underflow here */
+
+L_round:
+       jmp     fpu_reg_round   /* Round the result */
+
+
+#ifdef PARANOID
+L_bugged_1:
+       pushl   EX_INTERNAL|0x206
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_error_exit
+
+L_bugged_2:
+       pushl   EX_INTERNAL|0x209
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_error_exit
+
+L_bugged_3:
+       pushl   EX_INTERNAL|0x210
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_error_exit
+
+L_bugged_4:
+       pushl   EX_INTERNAL|0x211
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_error_exit
+
+L_bugged:
+       pushl   EX_INTERNAL|0x212
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_error_exit
+
+L_error_exit:
+       movl    $-1,%eax
+
+#endif /* PARANOID */
+
+L_exit:
+       popl    %ebx
+       popl    %edi
+       popl    %esi
+       leave
+       ret
diff --git a/sid/component/bochs/cpu/fpu/reg_u_sub.c b/sid/component/bochs/cpu/fpu/reg_u_sub.c
new file mode 100644 (file)
index 0000000..657e512
--- /dev/null
@@ -0,0 +1,221 @@
+/*---------------------------------------------------------------------------+
+ |  reg_u_sub.c                                                              |
+ |                                                                           |
+ | Core floating point subtraction routine.                                  |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1995,1997,1999                                    |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@melbpc.org.au                             |
+ |                                                                           |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*
+ |    Kernel subtraction routine FPU_u_sub(reg *arg1, reg *arg2, reg *answ).
+ |    Takes two valid reg f.p. numbers (TAG_Valid), which are
+ |    treated as unsigned numbers,
+ |    and returns their difference as a TAG_Valid or TAG_Zero f.p.
+ |    number.
+ |    The first number (arg1) must be the larger.
+ |    The returned number is normalized.
+ |    Basic checks are performed if PARANOID is defined.
+ */
+
+#include "exception.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+
+
+
+int  FPU_u_sub(const FPU_REG *arg1, const FPU_REG *arg2, FPU_REG *dest,
+              u16 control_w, u_char sign, int expa, int expb)
+{
+  FPU_REG shifted, answ;
+  u32 extent;
+  int ediff = expa - expb, ed2, borrow;
+
+#ifdef PARANOID
+  if ( ediff < 0 )
+    {
+      EXCEPTION(EX_INTERNAL|0x206);
+      return -1;
+    }
+#endif
+  
+  answ.exp = expa;
+
+#ifdef PARANOID
+  if ( !(arg1->sigh & 0x80000000) || !(arg2->sigh & 0x80000000) )
+    {
+      EXCEPTION(EX_INTERNAL|0x209);
+      return -1;
+    }
+#endif
+
+  if ( ediff == 0 )
+    {
+      shifted.sigl = arg2->sigl;
+      shifted.sigh = arg2->sigh;
+      extent = 0;
+    }
+  else if ( ediff < 32 )
+    {
+      ed2 = 32 - ediff;
+      extent = arg2->sigl << ed2;
+      shifted.sigl = arg2->sigl >> ediff;
+      shifted.sigl |= (arg2->sigh << ed2);
+      shifted.sigh = arg2->sigh >> ediff;
+    }
+  else if ( ediff < 64 )
+    {
+      ediff -= 32;
+      if ( ! ediff )
+       {
+         extent = arg2->sigl;
+         shifted.sigl = arg2->sigh;
+         shifted.sigh = 0;
+       }
+      else
+       {
+         ed2 = 32 - ediff;
+         extent = arg2->sigl >> ediff;
+         extent |= (arg2->sigh << ed2);
+         if ( arg2->sigl << ed2 )
+           extent |= 1;
+         shifted.sigl = arg2->sigh >> ediff;
+         shifted.sigh = 0;
+       }
+    }
+  else
+    {
+      ediff -= 64;
+      if ( ! ediff )
+       {
+         extent = arg2->sigh;
+         if ( arg2->sigl )
+           extent |= 1;
+         shifted.sigl = 0;
+         shifted.sigh = 0;
+       }
+      else
+       {
+         if ( ediff < 32 )
+           {
+             extent = arg2->sigh >> ediff;
+             if ( arg2->sigl || (arg2->sigh << (32-ediff)) )
+               extent |= 1;
+           }
+         else
+           extent = 1;
+         shifted.sigl = 0;
+         shifted.sigh = 0;
+       }
+    }
+
+  extent = -extent;
+  borrow = extent;
+  answ.sigl = arg1->sigl - shifted.sigl;
+  if ( answ.sigl > arg1->sigl )
+    {
+      if ( borrow )
+       answ.sigl --;
+      borrow = 1;
+    }
+  else if ( borrow )
+    {
+      answ.sigl --;
+      if ( answ.sigl != 0xffffffff )
+       borrow = 0;
+    }
+  answ.sigh = arg1->sigh - shifted.sigh;
+  if ( answ.sigh > arg1->sigh )
+    {
+      if ( borrow )
+       answ.sigh --;
+      borrow = 1;
+    }
+  else if ( borrow )
+    {
+      answ.sigh --;
+      if ( answ.sigh != 0xffffffff )
+       borrow = 0;
+    }
+
+#ifdef PARANOID
+  if ( borrow )
+    {
+      /* This can only occur if the code is bugged */
+      EXCEPTION(EX_INTERNAL|0x212);
+      return -1;
+    }
+#endif
+
+  if ( answ.sigh & 0x80000000 )
+    {
+      /*
+       The simpler "*dest = answ" is broken in gcc
+      */
+      dest->exp = answ.exp;
+      dest->sigh = answ.sigh;
+      dest->sigl = answ.sigl;
+      return FPU_round(dest, extent, 0, control_w, sign);
+    }
+
+  if ( answ.sigh == 0 )
+    {
+      if ( answ.sigl )
+       {
+         answ.sigh = answ.sigl;
+         answ.sigl = extent;
+         extent = 0;
+         answ.exp -= 32;
+       }
+      else if ( extent )
+       {
+/*
+ *      A rare case, the only one which is non-zero if we got here
+ *         is:           1000000 .... 0000
+ *                      -0111111 .... 1111 1
+ *                       -------------------- 
+ *                       0000000 .... 0000 1 
+ */
+         if ( extent != 0x80000000 )
+           {
+             /* This can only occur if the code is bugged */
+             EXCEPTION(EX_INTERNAL|0x210);
+             return -1;
+           }
+         dest->sigh = extent;
+         dest->sigl = extent = 0;
+         dest->exp -= 64;
+         return FPU_round(dest, extent, 0, control_w, sign);
+       }
+      else
+       {
+         dest->exp = 0;
+         dest->sigh = dest->sigl = 0;
+         return TAG_Zero;
+       }
+    }
+
+  while ( !(answ.sigh & 0x80000000) )
+    {
+      answ.sigh <<= 1;
+      if ( answ.sigl & 0x80000000 )
+       answ.sigh |= 1;
+      answ.sigl <<= 1;
+      if ( extent & 0x80000000 )
+       answ.sigl |= 1;
+      extent <<= 1;
+      answ.exp --;
+    }
+
+  dest->exp = answ.exp;
+  dest->sigh = answ.sigh;
+  dest->sigl = answ.sigl;
+
+  return FPU_round(dest, extent, 0, control_w, sign);
+
+}
diff --git a/sid/component/bochs/cpu/fpu/round_Xsig.S b/sid/component/bochs/cpu/fpu/round_Xsig.S
new file mode 100644 (file)
index 0000000..bbe0e87
--- /dev/null
@@ -0,0 +1,141 @@
+/*---------------------------------------------------------------------------+
+ |  round_Xsig.S                                                             |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1995                                         |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                                                                           |
+ | Normalize and round a 12 byte quantity.                                   |
+ | Call from C as:                                                           |
+ |   int round_Xsig(Xsig *n)                                                 |
+ |                                                                           |
+ | Normalize a 12 byte quantity.                                             |
+ | Call from C as:                                                           |
+ |   int norm_Xsig(Xsig *n)                                                  |
+ |                                                                           |
+ | Each function returns the size of the shift (nr of bits).                 |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+       .file   "round_Xsig.S"
+
+#include "fpu_emu.h"
+
+
+.text
+ENTRY(round_Xsig)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx            /* Reserve some space */
+       pushl   %ebx
+       pushl   %esi
+
+       movl    PARAM1,%esi
+
+       movl    8(%esi),%edx
+       movl    4(%esi),%ebx
+       movl    (%esi),%eax
+
+       movl    $0,-4(%ebp)
+
+       orl     %edx,%edx       /* ms bits */
+       js      L_round         /* Already normalized */
+       jnz     L_shift_1       /* Shift left 1 - 31 bits */
+
+       movl    %ebx,%edx
+       movl    %eax,%ebx
+       xorl    %eax,%eax
+       movl    $-32,-4(%ebp)
+
+/* We need to shift left by 1 - 31 bits */
+L_shift_1:
+       bsrl    %edx,%ecx       /* get the required shift in %ecx */
+       subl    $31,%ecx
+       negl    %ecx
+       subl    %ecx,-4(%ebp)
+       shld    %cl,%ebx,%edx
+       shld    %cl,%eax,%ebx
+       shl     %cl,%eax
+
+L_round:
+       testl   $0x80000000,%eax
+       jz      L_exit
+
+       addl    $1,%ebx
+       adcl    $0,%edx
+       jnz     L_exit
+
+       movl    $0x80000000,%edx
+       incl    -4(%ebp)
+
+L_exit:
+       movl    %edx,8(%esi)
+       movl    %ebx,4(%esi)
+       movl    %eax,(%esi)
+
+       movl    -4(%ebp),%eax
+
+       popl    %esi
+       popl    %ebx
+       leave
+       ret
+
+
+
+
+ENTRY(norm_Xsig)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx            /* Reserve some space */
+       pushl   %ebx
+       pushl   %esi
+
+       movl    PARAM1,%esi
+
+       movl    8(%esi),%edx
+       movl    4(%esi),%ebx
+       movl    (%esi),%eax
+
+       movl    $0,-4(%ebp)
+
+       orl     %edx,%edx       /* ms bits */
+       js      L_n_exit                /* Already normalized */
+       jnz     L_n_shift_1     /* Shift left 1 - 31 bits */
+
+       movl    %ebx,%edx
+       movl    %eax,%ebx
+       xorl    %eax,%eax
+       movl    $-32,-4(%ebp)
+
+       orl     %edx,%edx       /* ms bits */
+       js      L_n_exit        /* Normalized now */
+       jnz     L_n_shift_1     /* Shift left 1 - 31 bits */
+
+       movl    %ebx,%edx
+       movl    %eax,%ebx
+       xorl    %eax,%eax
+       addl    $-32,-4(%ebp)
+       jmp     L_n_exit        /* Might not be normalized,
+                                  but shift no more. */
+
+/* We need to shift left by 1 - 31 bits */
+L_n_shift_1:
+       bsrl    %edx,%ecx       /* get the required shift in %ecx */
+       subl    $31,%ecx
+       negl    %ecx
+       subl    %ecx,-4(%ebp)
+       shld    %cl,%ebx,%edx
+       shld    %cl,%eax,%ebx
+       shl     %cl,%eax
+
+L_n_exit:
+       movl    %edx,8(%esi)
+       movl    %ebx,4(%esi)
+       movl    %eax,(%esi)
+
+       movl    -4(%ebp),%eax
+
+       popl    %esi
+       popl    %ebx
+       leave
+       ret
+
diff --git a/sid/component/bochs/cpu/fpu/round_Xsig.c b/sid/component/bochs/cpu/fpu/round_Xsig.c
new file mode 100644 (file)
index 0000000..adf45b5
--- /dev/null
@@ -0,0 +1,95 @@
+/*---------------------------------------------------------------------------+
+ |  round_Xsig.c                                                             |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1995,1999                                    |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@melbpc.org.au              |
+ |                                                                           |
+ | Normalize and round a 12 byte quantity.                                   |
+ |   int round_Xsig(Xsig *n)                                                 |
+ |                                                                           |
+ | Normalize a 12 byte quantity.                                             |
+ |   int norm_Xsig(Xsig *n)                                                  |
+ |                                                                           |
+ | Each function returns the size of the shift (nr of bits).                 |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_emu.h"
+#include "poly.h"
+
+int round_Xsig(Xsig *x)
+{
+  int n = 0;
+
+  if ( x->msw == 0 )
+    {
+      x->msw = x->midw;
+      x->midw = x->lsw;
+      x->lsw = 0;
+      n = 32;
+    }
+  while ( !(x->msw & 0x80000000) )
+    {
+      x->msw <<= 1;
+      if ( x->midw & 0x80000000 ) x->msw |= 1;
+      x->midw <<= 1;
+      if ( x->lsw & 0x80000000 ) x->midw |= 1;
+      x->lsw <<= 1;
+      n++;
+    }
+  if ( x->lsw & 0x80000000 )
+    {
+      x->midw ++;
+      if ( x->midw == 0 )
+       x->msw ++;
+      if ( x->msw == 0 )
+       {
+         x->msw = 0x80000000;
+         n--;
+       }
+    }
+  
+
+  return -n;
+}
+
+
+int norm_Xsig(Xsig *x)
+{
+  int n = 0;
+
+  if ( x->msw == 0 )
+    {
+      if ( x->midw == 0 )
+       {
+         x->msw = x->lsw;
+         x->midw = 0;
+         x->lsw = 0;
+         n = 64;
+       }
+      else
+       {
+         x->msw = x->midw;
+         x->midw = x->lsw;
+         x->lsw = 0;
+         n = 32;
+       }
+    }
+  while ( !(x->msw & 0x80000000) )
+    {
+      x->msw <<= 1;
+      if ( x->midw & 0x80000000 ) x->msw |= 1;
+      x->midw <<= 1;
+      if ( x->lsw & 0x80000000 ) x->midw |= 1;
+      x->lsw <<= 1;
+      n++;
+    }
+
+  return -n;
+}
+
+
+
+
+
diff --git a/sid/component/bochs/cpu/fpu/shr_Xsig.S b/sid/component/bochs/cpu/fpu/shr_Xsig.S
new file mode 100644 (file)
index 0000000..31cdd11
--- /dev/null
@@ -0,0 +1,87 @@
+       .file   "shr_Xsig.S"
+/*---------------------------------------------------------------------------+
+ |  shr_Xsig.S                                                               |
+ |                                                                           |
+ | 12 byte right shift function                                              |
+ |                                                                           |
+ | Copyright (C) 1992,1994,1995                                              |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                                                                           |
+ | Call from C as:                                                           |
+ |   void shr_Xsig(Xsig *arg, unsigned nr)                                   |
+ |                                                                           |
+ |   Extended shift right function.                                          |
+ |   Fastest for small shifts.                                               |
+ |   Shifts the 12 byte quantity pointed to by the first arg (arg)           |
+ |   right by the number of bits specified by the second arg (nr).           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_emu.h"
+
+.text
+ENTRY(shr_Xsig)
+       push    %ebp
+       movl    %esp,%ebp
+       pushl   %esi
+       movl    PARAM2,%ecx
+       movl    PARAM1,%esi
+       cmpl    $32,%ecx        /* shrd only works for 0..31 bits */
+       jnc     L_more_than_31
+
+/* less than 32 bits */
+       pushl   %ebx
+       movl    (%esi),%eax     /* lsl */
+       movl    4(%esi),%ebx    /* midl */
+       movl    8(%esi),%edx    /* msl */
+       shrd    %cl,%ebx,%eax
+       shrd    %cl,%edx,%ebx
+       shr     %cl,%edx
+       movl    %eax,(%esi)
+       movl    %ebx,4(%esi)
+       movl    %edx,8(%esi)
+       popl    %ebx
+       popl    %esi
+       leave
+       ret
+
+L_more_than_31:
+       cmpl    $64,%ecx
+       jnc     L_more_than_63
+
+       subb    $32,%cl
+       movl    4(%esi),%eax    /* midl */
+       movl    8(%esi),%edx    /* msl */
+       shrd    %cl,%edx,%eax
+       shr     %cl,%edx
+       movl    %eax,(%esi)
+       movl    %edx,4(%esi)
+       movl    $0,8(%esi)
+       popl    %esi
+       leave
+       ret
+
+L_more_than_63:
+       cmpl    $96,%ecx
+       jnc     L_more_than_95
+
+       subb    $64,%cl
+       movl    8(%esi),%eax    /* msl */
+       shr     %cl,%eax
+       xorl    %edx,%edx
+       movl    %eax,(%esi)
+       movl    %edx,4(%esi)
+       movl    %edx,8(%esi)
+       popl    %esi
+       leave
+       ret
+
+L_more_than_95:
+       xorl    %eax,%eax
+       movl    %eax,(%esi)
+       movl    %eax,4(%esi)
+       movl    %eax,8(%esi)
+       popl    %esi
+       leave
+       ret
diff --git a/sid/component/bochs/cpu/fpu/shr_Xsig.c b/sid/component/bochs/cpu/fpu/shr_Xsig.c
new file mode 100644 (file)
index 0000000..a259b87
--- /dev/null
@@ -0,0 +1,41 @@
+/*---------------------------------------------------------------------------+
+ |  shr_Xsig.S                                                               |
+ |                                                                           |
+ | 12 byte right shift function                                              |
+ |                                                                           |
+ | Copyright (C) 1992,1994,1995                                              |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                                                                           |
+ |                                                                           |
+ |   Extended shift right function.                                          |
+ |   Fastest for small shifts.                                               |
+ |   Shifts the 12 byte quantity pointed to by the first arg (arg)           |
+ |   right by the number of bits specified by the second arg (nr).           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_emu.h"
+#include "poly.h"
+
+void shr_Xsig(Xsig *arg, const int nr)
+{
+  int n = nr;
+
+  while ( n >= 32 )
+    {
+      arg->lsw = arg->midw;
+      arg->midw = arg->msw;
+      arg->msw = 0;
+      n -= 32;
+    }
+
+  if ( n <= 0 )
+    return;
+
+  arg->lsw = (arg->lsw >> n) | (arg->midw << (32-n));
+  arg->midw = (arg->midw >> n) | (arg->msw << (32-n));
+  arg->msw >>= n;
+
+}
+
diff --git a/sid/component/bochs/cpu/fpu/status_w.h b/sid/component/bochs/cpu/fpu/status_w.h
new file mode 100644 (file)
index 0000000..d38e3a9
--- /dev/null
@@ -0,0 +1,67 @@
+/*---------------------------------------------------------------------------+
+ |  status_w.h                                                               |
+ |                                                                           |
+ | Copyright (C) 1992,1993                                                   |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#ifndef _STATUS_H_
+#define _STATUS_H_
+
+#include "fpu_emu.h"    /* for definition of PECULIAR_486 */
+
+#ifdef __ASSEMBLY__
+#define        Const__(x)      $##x
+#else
+#define        Const__(x)      x
+#endif
+
+#define SW_Backward            Const__(0x8000) /* backward compatibility */
+#define SW_C3          Const__(0x4000) /* condition bit 3 */
+#define SW_Top         Const__(0x3800) /* top of stack */
+#define SW_Top_Shift   Const__(11)     /* shift for top of stack bits */
+#define SW_C2          Const__(0x0400) /* condition bit 2 */
+#define SW_C1          Const__(0x0200) /* condition bit 1 */
+#define SW_C0          Const__(0x0100) /* condition bit 0 */
+#define SW_Summary             Const__(0x0080) /* exception summary */
+#define SW_Stack_Fault Const__(0x0040) /* stack fault */
+#define SW_Precision           Const__(0x0020) /* loss of precision */
+#define SW_Underflow           Const__(0x0010) /* underflow */
+#define SW_Overflow            Const__(0x0008) /* overflow */
+#define SW_Zero_Div            Const__(0x0004) /* divide by zero */
+#define SW_Denorm_Op           Const__(0x0002) /* denormalized operand */
+#define SW_Invalid             Const__(0x0001) /* invalid operation */
+
+#define SW_Exc_Mask     Const__(0x27f)  /* Status word exception bit mask */
+
+#ifndef __ASSEMBLY__
+
+#define COMP_A_gt_B    1
+#define COMP_A_eq_B    2
+#define COMP_A_lt_B    3
+#define COMP_No_Comp   4
+#define COMP_Denormal   0x20
+#define COMP_NaN       0x40
+#define COMP_SNaN      0x80
+
+#define status_word() \
+  ((partial_status & ~SW_Top & 0xffff) | ((top << SW_Top_Shift) & SW_Top))
+// bbd: use do {...} while (0) structure instead of using curly brackets
+// inside parens, which most compilers do not like.
+#define setcc(cc) do { \
+  partial_status &= ~(SW_C0|SW_C1|SW_C2|SW_C3); \
+  partial_status |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3); } while(0)
+
+#ifdef PECULIAR_486
+   /* Default, this conveys no information, but an 80486 does it. */
+   /* Clear the SW_C1 bit, "other bits undefined". */
+#  define clear_C1()  { partial_status &= ~SW_C1; }
+# else
+#  define clear_C1()
+#endif /* PECULIAR_486 */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _STATUS_H_ */
diff --git a/sid/component/bochs/cpu/fpu/stubs/asm/desc.h b/sid/component/bochs/cpu/fpu/stubs/asm/desc.h
new file mode 100644 (file)
index 0000000..d369d01
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef __ARCH_DESC_H
+#define __ARCH_DESC_H
+
+struct desc_struct {
+       unsigned long a,b;
+};
+
+extern struct desc_struct gdt_table[];
+extern struct desc_struct *idt, *gdt;
+
+struct Xgt_desc_struct {
+       unsigned short size;
+       unsigned long address GCC_ATTRIBUTE((packed));
+};
+
+#define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2))
+#define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2))
+
+/*
+ * Entry into gdt where to find first TSS. GDT layout:
+ *   0 - null
+ *   1 - not used
+ *   2 - kernel code segment
+ *   3 - kernel data segment
+ *   4 - user code segment
+ *   5 - user data segment
+ *   6 - not used
+ *   7 - not used
+ *   8 - APM BIOS support
+ *   9 - APM BIOS support
+ *  10 - APM BIOS support
+ *  11 - APM BIOS support
+ *  12 - TSS #0
+ *  13 - LDT #0
+ *  14 - TSS #1
+ *  15 - LDT #1
+ */
+#define FIRST_TSS_ENTRY 12
+#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
+#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
+#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
+#define load_TR(n) __asm__ __volatile__("ltr %%ax": /* no output */ :"a" (_TSS(n)))
+#define load_ldt(n) __asm__ __volatile__("lldt %%ax": /* no output */ :"a" (_LDT(n)))
+#define store_TR(n) \
+__asm__("str %%ax\n\t" \
+       "subl %2,%%eax\n\t" \
+       "shrl $4,%%eax" \
+       :"=a" (n) \
+       :"0" (0),"i" (FIRST_TSS_ENTRY<<3))
+
+extern void set_intr_gate(unsigned int irq, void * addr);
+extern void set_ldt_desc(unsigned int n, void *addr, unsigned int size);
+extern void set_tss_desc(unsigned int n, void *addr);
+
+/*
+ * This is the ldt that every process will get unless we need
+ * something other than this.
+ */
+extern struct desc_struct default_ldt;
+
+#endif
diff --git a/sid/component/bochs/cpu/fpu/stubs/asm/math_emu.h b/sid/component/bochs/cpu/fpu/stubs/asm/math_emu.h
new file mode 100644 (file)
index 0000000..adb1118
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _I386_MATH_EMU_H
+#define _I386_MATH_EMU_H
+
+// Don't really need anything in here.
+
+#endif
diff --git a/sid/component/bochs/cpu/fpu/stubs/asm/sigcontext.h b/sid/component/bochs/cpu/fpu/stubs/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..d7b2f58
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef _ASMi386_SIGCONTEXT_H
+#define _ASMi386_SIGCONTEXT_H
+
+/*
+ * As documented in the iBCS2 standard..
+ *
+ * The first part of "struct _fpstate" is just the
+ * normal i387 hardware setup, the extra "status"
+ * word is used to save the coprocessor status word
+ * before entering the handler.
+ */
+struct _fpreg {
+       unsigned short significand[4];
+       unsigned short exponent;
+};
+
+struct _fpstate {
+       unsigned long   cw,
+                       sw,
+                       tag,
+                       ipoff,
+                       cssel,
+                       dataoff,
+                       datasel;
+       struct _fpreg   _st[8];
+       unsigned long   status;
+};
+
+#if 0
+/* sigcontext is not needed by bochs, and it conflicts with some other
+   machine types (DEC OSF1) */
+struct sigcontext {
+       unsigned short gs, __gsh;
+       unsigned short fs, __fsh;
+       unsigned short es, __esh;
+       unsigned short ds, __dsh;
+       unsigned long edi;
+       unsigned long esi;
+       unsigned long ebp;
+       unsigned long esp;
+       unsigned long ebx;
+       unsigned long edx;
+       unsigned long ecx;
+       unsigned long eax;
+       unsigned long trapno;
+       unsigned long err;
+       unsigned long eip;
+       unsigned short cs, __csh;
+       unsigned long eflags;
+       unsigned long esp_at_signal;
+       unsigned short ss, __ssh;
+       struct _fpstate * fpstate;
+       unsigned long oldmask;
+       unsigned long cr2;
+};
+#endif
+
+
+#endif
diff --git a/sid/component/bochs/cpu/fpu/stubs/asm/types.h b/sid/component/bochs/cpu/fpu/stubs/asm/types.h
new file mode 100644 (file)
index 0000000..a963dca
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _I386_TYPES_H
+#define _I386_TYPES_H
+
+#ifndef __ASSEMBLY__
+#endif
+
+#endif  /* _I386_TYPES_H */
diff --git a/sid/component/bochs/cpu/fpu/stubs/asm/uaccess.h b/sid/component/bochs/cpu/fpu/stubs/asm/uaccess.h
new file mode 100644 (file)
index 0000000..4cd87bb
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _I386_UACCESS_H
+#define _I386_UACCESS_H
+
+
+
+#endif
diff --git a/sid/component/bochs/cpu/fpu/stubs/linux/kernel.h b/sid/component/bochs/cpu/fpu/stubs/linux/kernel.h
new file mode 100644 (file)
index 0000000..05372b6
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _LINUX_KERNEL_H
+#define _LINUX_KERNEL_H
+
+int printk(const char * fmt, ...)
+        GCC_ATTRIBUTE((format (printf, 1, 2)));
+
+#endif
diff --git a/sid/component/bochs/cpu/fpu/stubs/linux/linkage.h b/sid/component/bochs/cpu/fpu/stubs/linux/linkage.h
new file mode 100644 (file)
index 0000000..b1856a7
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef _LINUX_LINKAGE_H
+#define _LINUX_LINKAGE_H
+
+#ifdef __cplusplus
+#define CPP_ASMLINKAGE extern "C"
+#else
+#define CPP_ASMLINKAGE
+#endif
+
+#if defined __i386__ && (__GNUC__ > 2 || __GNUC_MINOR__ > 7)
+#define asmlinkage CPP_ASMLINKAGE GCC_ATTRIBUTE((regparm(0)))
+#else
+#define asmlinkage CPP_ASMLINKAGE
+#endif
+
+#define SYMBOL_NAME_STR(X) #X
+#define SYMBOL_NAME(X) X
+#ifdef __STDC__
+#define SYMBOL_NAME_LABEL(X) X##:
+#else
+#define SYMBOL_NAME_LABEL(X) X/**/:
+#endif
+
+#ifdef __arm__
+#define __ALIGN .align 0
+#define __ALIGN_STR ".align 0"
+#else
+#ifdef __mc68000__
+#define __ALIGN .align 4
+#define __ALIGN_STR ".align 4"
+#else
+#if !defined(__i486__) && !defined(__i586__)
+#define __ALIGN .align 4,0x90
+#define __ALIGN_STR ".align 4,0x90"
+#else  /* __i486__/__i586__ */
+#define __ALIGN .align 16,0x90
+#define __ALIGN_STR ".align 16,0x90"
+#endif /* __i486__/__i586__ */
+#endif /* __mc68000__ */
+#endif /* __arm__ */
+
+#ifdef __ASSEMBLY__
+
+#define ALIGN __ALIGN
+#define ALIGN_STR __ALIGN_STR
+
+#define ENTRY(name) \
+  .globl SYMBOL_NAME(name); \
+  ALIGN; \
+  SYMBOL_NAME_LABEL(name)
+
+#endif
+
+#endif
diff --git a/sid/component/bochs/cpu/fpu/stubs/linux/mm.h b/sid/component/bochs/cpu/fpu/stubs/linux/mm.h
new file mode 100644 (file)
index 0000000..e6d6cc2
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _LINUX_MM_H
+#define _LINUX_MM_H
+
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+#endif
diff --git a/sid/component/bochs/cpu/fpu/stubs/linux/sched.h b/sid/component/bochs/cpu/fpu/stubs/linux/sched.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/sid/component/bochs/cpu/fpu/stubs/linux/signal.h b/sid/component/bochs/cpu/fpu/stubs/linux/signal.h
new file mode 100644 (file)
index 0000000..457158d
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _ASMi386_SIGNAL_H
+#define _ASMi386_SIGNAL_H
+
+#define SIGILL           4
+#define SIGFPE           8
+#define SIGSEGV         11
+
+#endif
diff --git a/sid/component/bochs/cpu/fpu/stubs/linux/stddef.h b/sid/component/bochs/cpu/fpu/stubs/linux/stddef.h
new file mode 100644 (file)
index 0000000..c6221e7
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _LINUX_STDDEF_H
+#define _LINUX_STDDEF_H
+
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef unsigned int size_t;
+#endif
+
+#undef NULL
+#define NULL ((void *)0)
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#endif
diff --git a/sid/component/bochs/cpu/fpu/stubs/linux/types.h b/sid/component/bochs/cpu/fpu/stubs/linux/types.h
new file mode 100644 (file)
index 0000000..5ea5a61
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _LINUX_TYPES_H
+#define _LINUX_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+#define u_char bx_u_char
+#define u_short bx_u_short
+#define u_int bx_u_int
+#define u_long bx_u_long
+#define unchar bx_unchar
+#define ushort bx_ushort
+#define uint bx_uint
+#define ulong bx_ulong
+
+/* bsd */
+typedef unsigned char           u_char;
+typedef unsigned short          u_short;
+typedef unsigned int            u_int;
+typedef unsigned long           u_long;
+
+/* sysv */
+typedef unsigned char           unchar;
+typedef unsigned short          ushort;
+typedef unsigned int            uint;
+typedef unsigned long           ulong;
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#endif
+
+#endif /* _LINUX_TYPES_H */
diff --git a/sid/component/bochs/cpu/fpu/version.h b/sid/component/bochs/cpu/fpu/version.h
new file mode 100644 (file)
index 0000000..23fcd25
--- /dev/null
@@ -0,0 +1,12 @@
+/*---------------------------------------------------------------------------+
+ |  version.h                                                                |
+ |                                                                           |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1996,1997,1999                               |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@melbpc.org.au                             |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#define FPU_VERSION "wm-FPU-emu version 2.05"
diff --git a/sid/component/bochs/cpu/fpu/wmFPUemu_glue.cc b/sid/component/bochs/cpu/fpu/wmFPUemu_glue.cc
new file mode 100644 (file)
index 0000000..a450e10
--- /dev/null
@@ -0,0 +1,260 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+//
+// This is the glue logic needed to connect the wm-FPU-emu
+// FPU emulator written by Bill Metzenthen to bochs.
+//
+
+
+#include "bochs.h"
+extern "C" {
+#include "fpu_emu.h"
+#include "linux/signal.h"
+}
+
+#define LOG_THIS genlog->
+#if BX_USE_CPU_SMF
+#define this (BX_CPU(0))
+#endif
+
+// Use this to hold a pointer to the instruction since
+// we can't pass this to the FPU emulation routines, which
+// will ultimately call routines here.
+static BxInstruction_t *fpu_iptr = NULL;
+static BX_CPU_C *fpu_cpu_ptr = NULL;
+
+i387_t i387;
+
+extern "C" void
+math_emulate2(fpu_addr_modes addr_modes,
+              u_char  FPU_modrm,
+              u_char byte1,
+              void *data_address,
+              struct address data_sel_off,
+              struct address entry_sel_off);
+
+extern "C" void printfp(char *s, FPU_REG *r);
+
+
+  // This is called by bochs upon reset
+  void
+BX_CPU_C::fpu_init(void)
+{
+  finit();
+}
+
+  void
+BX_CPU_C::fpu_execute(BxInstruction_t *i)
+{
+  fpu_addr_modes addr_modes;
+  void *data_address;
+  struct address data_sel_off;
+  struct address entry_sel_off;
+  Boolean is_32;
+
+  fpu_iptr = i;
+  fpu_cpu_ptr = this;
+
+#if 0
+  addr_modes.default_mode = VM86;
+  addr_modes.default_mode = 0; // FPU_CS == __USER_CS && FPU_DS == __USER_DS
+  addr_modes.default_mode = SEG32;
+  addr_modes.default_mode = PM16;
+#endif
+  if (protected_mode()) {
+    addr_modes.default_mode = SEG32;
+    }
+  else if (v8086_mode()) {
+    addr_modes.default_mode = VM86;
+    }
+  else {
+    // real mode, use vm86 for now
+    addr_modes.default_mode = VM86;
+    }
+
+
+  // Mark if instruction used opsize or addrsize prefixes
+  // Actually, addr_modes.override.address_size is not used,
+  // could delete that code.
+  is_32 = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b;
+  if (i->as_32 == is_32)
+    addr_modes.override.address_size = 0;
+  else
+    addr_modes.override.address_size = ADDR_SIZE_PREFIX;
+  if (i->os_32 == is_32)
+    addr_modes.override.operand_size = 0;
+  else
+    addr_modes.override.operand_size = OP_SIZE_PREFIX;
+
+  // For now set access_limit to max.  It seems to be
+  // a number from 0..255 denoting how many bytes the
+  // current instruction can access according to its
+  // memory operand.  255 means >= 255.
+access_limit = 0xff;
+
+  // fill in orig eip here in offset
+  // fill in CS in selector
+  entry_sel_off.offset = BX_CPU_THIS_PTR prev_eip;
+  entry_sel_off.selector = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
+
+// should set these fields to 0 if mem operand not used
+  data_address = (void *) i->rm_addr;
+  data_sel_off.offset = i->rm_addr;
+  data_sel_off.selector = BX_CPU_THIS_PTR sregs[i->seg].selector.value;
+
+  math_emulate2(addr_modes, i->modrm, i->b1, data_address,
+                data_sel_off, entry_sel_off);
+}
+
+
+  unsigned
+fpu_get_ds(void)
+{
+  return(fpu_cpu_ptr->sregs[BX_SEG_REG_DS].selector.value);
+}
+
+  void
+fpu_set_ax(unsigned short val16)
+{
+// define to set AX in the current CPU -- not ideal.
+#undef AX
+#define AX (fpu_cpu_ptr->gen_reg[0].word.rx)
+  AX = val16;
+#undef AX
+//BX_DEBUG(( "fpu_set_ax(0x%04x)\n", (unsigned) val16));
+}
+
+  void
+fpu_verify_area(unsigned what, void *ptr, unsigned n)
+{
+  bx_segment_reg_t *seg;
+
+  seg = &fpu_cpu_ptr->sregs[fpu_iptr->seg];
+
+  if (what == VERIFY_READ) {
+    fpu_cpu_ptr->read_virtual_checks(seg, PTR2INT(ptr), n);
+    }
+  else {  // VERIFY_WRITE
+    fpu_cpu_ptr->write_virtual_checks(seg, PTR2INT(ptr), n);
+    }
+//BX_DEBUG(( "verify_area: 0x%x\n", PTR2INT(ptr)));
+}
+
+
+  void
+FPU_printall(void)
+{
+  BX_PANIC(("FPU_printall\n"));
+}
+
+
+  unsigned
+fpu_get_user(void *ptr, unsigned len)
+{
+  Bit32u val32;
+  Bit16u val16;
+  Bit8u  val8;
+
+  switch (len) {
+    case 1:
+      fpu_cpu_ptr->read_virtual_byte(fpu_iptr->seg, PTR2INT(ptr), &val8);
+      val32 = val8;
+      break;
+    case 2:
+      fpu_cpu_ptr->read_virtual_word(fpu_iptr->seg, PTR2INT(ptr), &val16);
+      val32 = val16;
+      break;
+    case 4:
+      fpu_cpu_ptr->read_virtual_dword(fpu_iptr->seg, PTR2INT(ptr), &val32);
+      break;
+    default:
+      BX_PANIC(("fpu_get_user: len=%u\n", len));
+    }
+  return(val32);
+}
+
+  void
+fpu_put_user(unsigned val, void *ptr, unsigned len)
+{
+  Bit32u val32;
+  Bit16u val16;
+  Bit8u  val8;
+
+  switch (len) {
+    case 1:
+      val8 = val;
+      fpu_cpu_ptr->write_virtual_byte(fpu_iptr->seg, PTR2INT(ptr), &val8);
+      break;
+    case 2:
+      val16 = val;
+      fpu_cpu_ptr->write_virtual_word(fpu_iptr->seg, PTR2INT(ptr), &val16);
+      break;
+    case 4:
+      val32 = val;
+      fpu_cpu_ptr->write_virtual_dword(fpu_iptr->seg, PTR2INT(ptr), &val32);
+      break;
+    default:
+      BX_PANIC(("fpu_put_user: len=%u\n", len));
+    }
+}
+
+  void
+math_abort(struct info *info, unsigned int signal)
+{
+  UNUSED(info); // info is always passed NULL
+#if BX_CPU_LEVEL >= 4
+
+// values of signal:
+//   SIGILL  : opcodes which are illegal
+//   SIGFPE  : unmasked FP exception before WAIT or non-control instruction
+//   SIGSEGV : access data beyond segment violation
+  switch (signal) {
+    case SIGFPE:
+      if (fpu_cpu_ptr->cr0.ne == 0) {
+        // MSDOS compatibility external interrupt (IRQ13)
+        BX_PANIC (("math_abort: MSDOS compatibility not supported yet\n"));
+        }
+      fpu_cpu_ptr->exception(BX_MF_EXCEPTION, 0, 0);
+      // execution does not reach here
+
+    case SIGILL:
+      BX_PANIC (("math_abort: SIGILL not implemented yet.\n"));
+      break;
+    case SIGSEGV:
+      BX_PANIC (("math_abort: SIGSEGV not implemented yet.\n"));
+      break;
+    }
+
+#else
+  UNUSED(signal);
+  BX_INFO(("math_abort: CPU<4 not supported yet\n"));
+#endif
+}
+
+  int
+printk(const char * fmt, ...)
+{
+  BX_INFO(("printk not complete: %s\n", fmt));
+  return(0); // for now
+}
diff --git a/sid/component/bochs/cpu/fpu/wm_shrx.S b/sid/component/bochs/cpu/fpu/wm_shrx.S
new file mode 100644 (file)
index 0000000..5184283
--- /dev/null
@@ -0,0 +1,204 @@
+       .file   "wm_shrx.S"
+/*---------------------------------------------------------------------------+
+ |  wm_shrx.S                                                                |
+ |                                                                           |
+ | 64 bit right shift functions                                              |
+ |                                                                           |
+ | Copyright (C) 1992,1995                                                   |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                                                                           |
+ | Call from C as:                                                           |
+ |   unsigned FPU_shrx(void *arg1, unsigned arg2)                            |
+ | and                                                                       |
+ |   unsigned FPU_shrxs(void *arg1, unsigned arg2)                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_emu.h"
+
+.text
+/*---------------------------------------------------------------------------+
+ |   unsigned FPU_shrx(void *arg1, unsigned arg2)                            |
+ |                                                                           |
+ |   Extended shift right function.                                          |
+ |   Fastest for small shifts.                                               |
+ |   Shifts the 64 bit quantity pointed to by the first arg (arg1)           |
+ |   right by the number of bits specified by the second arg (arg2).         |
+ |   Forms a 96 bit quantity from the 64 bit arg and eax:                    |
+ |                [  64 bit arg ][ eax ]                                     |
+ |            shift right  --------->                                        |
+ |   The eax register is initialized to 0 before the shifting.               |
+ |   Results returned in the 64 bit arg and eax.                             |
+ +---------------------------------------------------------------------------*/
+
+ENTRY(FPU_shrx)
+       push    %ebp
+       movl    %esp,%ebp
+       pushl   %esi
+       movl    PARAM2,%ecx
+       movl    PARAM1,%esi
+       cmpl    $32,%ecx        /* shrd only works for 0..31 bits */
+       jnc     L_more_than_31
+
+/* less than 32 bits */
+       pushl   %ebx
+       movl    (%esi),%ebx     /* lsl */
+       movl    4(%esi),%edx    /* msl */
+       xorl    %eax,%eax       /* extension */
+       shrd    %cl,%ebx,%eax
+       shrd    %cl,%edx,%ebx
+       shr     %cl,%edx
+       movl    %ebx,(%esi)
+       movl    %edx,4(%esi)
+       popl    %ebx
+       popl    %esi
+       leave
+       ret
+
+L_more_than_31:
+       cmpl    $64,%ecx
+       jnc     L_more_than_63
+
+       subb    $32,%cl
+       movl    (%esi),%eax     /* lsl */
+       movl    4(%esi),%edx    /* msl */
+       shrd    %cl,%edx,%eax
+       shr     %cl,%edx
+       movl    %edx,(%esi)
+       movl    $0,4(%esi)
+       popl    %esi
+       leave
+       ret
+
+L_more_than_63:
+       cmpl    $96,%ecx
+       jnc     L_more_than_95
+
+       subb    $64,%cl
+       movl    4(%esi),%eax    /* msl */
+       shr     %cl,%eax
+       xorl    %edx,%edx
+       movl    %edx,(%esi)
+       movl    %edx,4(%esi)
+       popl    %esi
+       leave
+       ret
+
+L_more_than_95:
+       xorl    %eax,%eax
+       movl    %eax,(%esi)
+       movl    %eax,4(%esi)
+       popl    %esi
+       leave
+       ret
+
+
+/*---------------------------------------------------------------------------+
+ |   unsigned FPU_shrxs(void *arg1, unsigned arg2)                           |
+ |                                                                           |
+ |   Extended shift right function (optimized for small floating point       |
+ |   integers).                                                              |
+ |   Shifts the 64 bit quantity pointed to by the first arg (arg1)           |
+ |   right by the number of bits specified by the second arg (arg2).         |
+ |   Forms a 96 bit quantity from the 64 bit arg and eax:                    |
+ |                [  64 bit arg ][ eax ]                                     |
+ |            shift right  --------->                                        |
+ |   The eax register is initialized to 0 before the shifting.               |
+ |   The lower 8 bits of eax are lost and replaced by a flag which is        |
+ |   set (to 0x01) if any bit, apart from the first one, is set in the       |
+ |   part which has been shifted out of the arg.                             |
+ |   Results returned in the 64 bit arg and eax.                             |
+ +---------------------------------------------------------------------------*/
+ENTRY(FPU_shrxs)
+       push    %ebp
+       movl    %esp,%ebp
+       pushl   %esi
+       pushl   %ebx
+       movl    PARAM2,%ecx
+       movl    PARAM1,%esi
+       cmpl    $64,%ecx        /* shrd only works for 0..31 bits */
+       jnc     Ls_more_than_63
+
+       cmpl    $32,%ecx        /* shrd only works for 0..31 bits */
+       jc      Ls_less_than_32
+
+/* We got here without jumps by assuming that the most common requirement
+   is for small integers */
+/* Shift by [32..63] bits */
+       subb    $32,%cl
+       movl    (%esi),%eax     /* lsl */
+       movl    4(%esi),%edx    /* msl */
+       xorl    %ebx,%ebx
+       shrd    %cl,%eax,%ebx
+       shrd    %cl,%edx,%eax
+       shr     %cl,%edx
+       orl     %ebx,%ebx               /* test these 32 bits */
+       setne   %bl
+       test    $0x7fffffff,%eax        /* and 31 bits here */
+       setne   %bh
+       orw     %bx,%bx                 /* Any of the 63 bit set ? */
+       setne   %al
+       movl    %edx,(%esi)
+       movl    $0,4(%esi)
+       popl    %ebx
+       popl    %esi
+       leave
+       ret
+
+/* Shift by [0..31] bits */
+Ls_less_than_32:
+       movl    (%esi),%ebx     /* lsl */
+       movl    4(%esi),%edx    /* msl */
+       xorl    %eax,%eax       /* extension */
+       shrd    %cl,%ebx,%eax
+       shrd    %cl,%edx,%ebx
+       shr     %cl,%edx
+       test    $0x7fffffff,%eax        /* only need to look at eax here */
+       setne   %al
+       movl    %ebx,(%esi)
+       movl    %edx,4(%esi)
+       popl    %ebx
+       popl    %esi
+       leave
+       ret
+
+/* Shift by [64..95] bits */
+Ls_more_than_63:
+       cmpl    $96,%ecx
+       jnc     Ls_more_than_95
+
+       subb    $64,%cl
+       movl    (%esi),%ebx     /* lsl */
+       movl    4(%esi),%eax    /* msl */
+       xorl    %edx,%edx       /* extension */
+       shrd    %cl,%ebx,%edx
+       shrd    %cl,%eax,%ebx
+       shr     %cl,%eax
+       orl     %ebx,%edx
+       setne   %bl
+       test    $0x7fffffff,%eax        /* only need to look at eax here */
+       setne   %bh
+       orw     %bx,%bx
+       setne   %al
+       xorl    %edx,%edx
+       movl    %edx,(%esi)     /* set to zero */
+       movl    %edx,4(%esi)    /* set to zero */
+       popl    %ebx
+       popl    %esi
+       leave
+       ret
+
+Ls_more_than_95:
+/* Shift by [96..inf) bits */
+       xorl    %eax,%eax
+       movl    (%esi),%ebx
+       orl     4(%esi),%ebx
+       setne   %al
+       xorl    %ebx,%ebx
+       movl    %ebx,(%esi)
+       movl    %ebx,4(%esi)
+       popl    %ebx
+       popl    %esi
+       leave
+       ret
diff --git a/sid/component/bochs/cpu/fpu/wm_shrx.c b/sid/component/bochs/cpu/fpu/wm_shrx.c
new file mode 100644 (file)
index 0000000..fd9cb74
--- /dev/null
@@ -0,0 +1,151 @@
+/*---------------------------------------------------------------------------+
+ |  wm_shrx.c                                                                |
+ |                                                                           |
+ | 64 bit right shift functions                                              |
+ |                                                                           |
+ | Copyright (C) 1992,1995,1999                                              |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@melbpc.org.au              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ |   unsigned FPU_shrx(void *arg1, unsigned arg2)                            |
+ |                                                                           |
+ |   Extended shift right function.                                          |
+ |   Fastest for small shifts.                                               |
+ |   Shifts the 64 bit quantity pointed to by the first arg (arg1)           |
+ |   right by the number of bits specified by the second arg (arg2).         |
+ |   Forms a 96 bit quantity from the 64 bit arg and eax:                    |
+ |                [  64 bit arg ][ eax ]                                     |
+ |            shift right  --------->                                        |
+ |   The eax register is initialized to 0 before the shifting.               |
+ |   Results returned in the 64 bit arg and eax.                             |
+ +---------------------------------------------------------------------------*/
+
+
+#include "fpu_emu.h"
+
+unsigned FPU_shrx(void *arg1, u32 arg2)
+{
+  u32 x;
+
+  if ( arg2 >= 64 )
+    {
+      if ( arg2 >= 96 )
+       {
+         *(u64 *)arg1 = 0;
+         return 0;
+       }
+      arg2 -= 64;
+      x = (*(u64 *)arg1) >> 32;
+      *(u64 *)arg1 = 0;
+
+      if ( arg2 )
+       return x >> arg2;
+      else
+       return x;
+    }
+
+  if ( arg2 < 32 )
+    {
+      if ( arg2 == 0 )
+       return 0;
+
+      x = (*(u64 *)arg1) << (32 - arg2);
+    }
+  else if ( arg2 > 32 )
+    {
+      x = (*(u64 *)arg1) >> (arg2 - 32);
+    }
+  else
+    {
+      /* arg2 == 32 */
+      x = *(u64 *)arg1;
+    }
+
+  (*(u64 *)arg1) >>= arg2;
+
+  return x;
+
+}
+
+
+/*---------------------------------------------------------------------------+
+ |   unsigned FPU_shrxs(void *arg1, unsigned arg2)                           |
+ |                                                                           |
+ |   Extended shift right function (optimized for small floating point       |
+ |   integers).                                                              |
+ |   Shifts the 64 bit quantity pointed to by the first arg (arg1)           |
+ |   right by the number of bits specified by the second arg (arg2).         |
+ |   Forms a 96 bit quantity from the 64 bit arg and eax:                    |
+ |                [  64 bit arg ][ eax ]                                     |
+ |            shift right  --------->                                        |
+ |   The eax register is initialized to 0 before the shifting.               |
+ |   The lower 8 bits of eax are lost and replaced by a flag which is        |
+ |   set (to 0x01) if any bit, apart from the first one, is set in the       |
+ |   part which has been shifted out of the arg.                             |
+ |   Results returned in the 64 bit arg and eax.                             |
+ +---------------------------------------------------------------------------*/
+
+unsigned FPU_shrxs(void *arg1, u32 arg2)
+{
+  u32 x, bits;
+  u64 lost;
+
+  if ( arg2 >= 64 )
+    {
+      if ( arg2 >= 96 )
+       {
+         bits = *(u64 *)arg1 != 0;
+         *(u64 *)arg1 = 0;
+         return bits ? 1 : 0;
+       }
+      arg2 -= 64;
+      lost = (*(u64 *)arg1) << (32 - arg2);
+      x = (*(u64 *)arg1) >> 32;
+      *(u64 *)arg1 = 0;
+
+      if ( arg2 )
+       x >>= arg2;
+
+      if ( lost )
+       x |= 1;
+
+      return x;
+    }
+
+  if ( arg2 < 32 )
+    {
+      if ( arg2 == 0 )
+       /* No bits are lost */
+       return 0;
+
+      /* No bits are lost */
+      x = (*(u64 *)arg1) << (32 - arg2);
+    }
+  else if ( arg2 > 32 )
+    {
+      bits = (*(u64 *)arg1);
+      bits <<= (64 - arg2);
+      x = (*(u64 *)arg1) >> (arg2 - 32);
+      if ( bits )
+       x |= 1;
+    }
+  else
+    {
+      /* arg2 == 32 */
+      /* No bits are lost */
+      x = *(u64 *)arg1;
+    }
+
+  (*(u64 *)arg1) >>= arg2;
+
+  if ( x & 0x7fffffff )
+    x |= 1;
+
+  return x;
+
+}
+
diff --git a/sid/component/bochs/cpu/fpu/wm_sqrt.S b/sid/component/bochs/cpu/fpu/wm_sqrt.S
new file mode 100644 (file)
index 0000000..b261dc4
--- /dev/null
@@ -0,0 +1,470 @@
+       .file   "wm_sqrt.S"
+/*---------------------------------------------------------------------------+
+ |  wm_sqrt.S                                                                |
+ |                                                                           |
+ | Fixed point arithmetic square root evaluation.                            |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1995,1997                                         |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@suburbia.net               |
+ |                                                                           |
+ | Call from C as:                                                           |
+ |    int wm_sqrt(FPU_REG *n, unsigned int control_word)                     |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ |  wm_sqrt(FPU_REG *n, unsigned int control_word)                           |
+ |    returns the square root of n in n.                                     |
+ |                                                                           |
+ |  Use Newton's method to compute the square root of a number, which must   |
+ |  be in the range  [1.0 .. 4.0),  to 64 bits accuracy.                     |
+ |  Does not check the sign or tag of the argument.                          |
+ |  Sets the exponent, but not the sign or tag of the result.                |
+ |                                                                           |
+ |  The guess is kept in %esi:%edi                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "fpu_emu.h"
+
+
+#ifndef NON_REENTRANT_FPU
+/*     Local storage on the stack: */
+#define FPU_accum_3    -4(%ebp)        /* ms word */
+#define FPU_accum_2    -8(%ebp)
+#define FPU_accum_1    -12(%ebp)
+#define FPU_accum_0    -16(%ebp)
+
+/*
+ * The de-normalised argument:
+ *                  sq_2                  sq_1              sq_0
+ *        b b b b b b b ... b b b   b b b .... b b b   b 0 0 0 ... 0
+ *           ^ binary point here
+ */
+#define FPU_fsqrt_arg_2        -20(%ebp)       /* ms word */
+#define FPU_fsqrt_arg_1        -24(%ebp)
+#define FPU_fsqrt_arg_0        -28(%ebp)       /* ls word, at most the ms bit is set */
+
+#else
+/*     Local storage in a static area: */
+.data
+       .align 4,0
+FPU_accum_3:
+       .long   0               /* ms word */
+FPU_accum_2:
+       .long   0
+FPU_accum_1:
+       .long   0
+FPU_accum_0:
+       .long   0
+
+/* The de-normalised argument:
+                    sq_2                  sq_1              sq_0
+          b b b b b b b ... b b b   b b b .... b b b   b 0 0 0 ... 0
+             ^ binary point here
+ */
+FPU_fsqrt_arg_2:
+       .long   0               /* ms word */
+FPU_fsqrt_arg_1:
+       .long   0
+FPU_fsqrt_arg_0:
+       .long   0               /* ls word, at most the ms bit is set */
+#endif /* NON_REENTRANT_FPU */
+
+
+.text
+ENTRY(wm_sqrt)
+       pushl   %ebp
+       movl    %esp,%ebp
+#ifndef NON_REENTRANT_FPU
+       subl    $28,%esp
+#endif /* NON_REENTRANT_FPU */
+       pushl   %esi
+       pushl   %edi
+       pushl   %ebx
+
+       movl    PARAM1,%esi
+
+       movl    SIGH(%esi),%eax
+       movl    SIGL(%esi),%ecx
+       xorl    %edx,%edx
+
+/* We use a rough linear estimate for the first guess.. */
+
+       cmpw    EXP_BIAS,EXP(%esi)
+       jnz     sqrt_arg_ge_2
+
+       shrl    $1,%eax                 /* arg is in the range  [1.0 .. 2.0) */
+       rcrl    $1,%ecx
+       rcrl    $1,%edx
+
+sqrt_arg_ge_2:
+/* From here on, n is never accessed directly again until it is
+   replaced by the answer. */
+
+       movl    %eax,FPU_fsqrt_arg_2            /* ms word of n */
+       movl    %ecx,FPU_fsqrt_arg_1
+       movl    %edx,FPU_fsqrt_arg_0
+
+/* Make a linear first estimate */
+       shrl    $1,%eax
+       addl    $0x40000000,%eax
+       movl    $0xaaaaaaaa,%ecx
+       mull    %ecx
+       shll    %edx                    /* max result was 7fff... */
+       testl   $0x80000000,%edx        /* but min was 3fff... */
+       jnz     sqrt_prelim_no_adjust
+
+       movl    $0x80000000,%edx        /* round up */
+
+sqrt_prelim_no_adjust:
+       movl    %edx,%esi       /* Our first guess */
+
+/* We have now computed (approx)   (2 + x) / 3, which forms the basis
+   for a few iterations of Newton's method */
+
+       movl    FPU_fsqrt_arg_2,%ecx    /* ms word */
+
+/*
+ * From our initial estimate, three iterations are enough to get us
+ * to 30 bits or so. This will then allow two iterations at better
+ * precision to complete the process.
+ */
+
+/* Compute  (g + n/g)/2  at each iteration (g is the guess). */
+       shrl    %ecx            /* Doing this first will prevent a divide */
+                               /* overflow later. */
+
+       movl    %ecx,%edx       /* msw of the arg / 2 */
+       divl    %esi            /* current estimate */
+       shrl    %esi            /* divide by 2 */
+       addl    %eax,%esi       /* the new estimate */
+
+       movl    %ecx,%edx
+       divl    %esi
+       shrl    %esi
+       addl    %eax,%esi
+
+       movl    %ecx,%edx
+       divl    %esi
+       shrl    %esi
+       addl    %eax,%esi
+
+/*
+ * Now that an estimate accurate to about 30 bits has been obtained (in %esi),
+ * we improve it to 60 bits or so.
+ *
+ * The strategy from now on is to compute new estimates from
+ *      guess := guess + (n - guess^2) / (2 * guess)
+ */
+
+/* First, find the square of the guess */
+       movl    %esi,%eax
+       mull    %esi
+/* guess^2 now in %edx:%eax */
+
+       movl    FPU_fsqrt_arg_1,%ecx
+       subl    %ecx,%eax
+       movl    FPU_fsqrt_arg_2,%ecx    /* ms word of normalized n */
+       sbbl    %ecx,%edx
+       jnc     sqrt_stage_2_positive
+
+/* Subtraction gives a negative result,
+   negate the result before division. */
+       notl    %edx
+       notl    %eax
+       addl    $1,%eax
+       adcl    $0,%edx
+
+       divl    %esi
+       movl    %eax,%ecx
+
+       movl    %edx,%eax
+       divl    %esi
+       jmp     sqrt_stage_2_finish
+
+sqrt_stage_2_positive:
+       divl    %esi
+       movl    %eax,%ecx
+
+       movl    %edx,%eax
+       divl    %esi
+
+       notl    %ecx
+       notl    %eax
+       addl    $1,%eax
+       adcl    $0,%ecx
+
+sqrt_stage_2_finish:
+       sarl    $1,%ecx         /* divide by 2 */
+       rcrl    $1,%eax
+
+       /* Form the new estimate in %esi:%edi */
+       movl    %eax,%edi
+       addl    %ecx,%esi
+
+       jnz     sqrt_stage_2_done       /* result should be [1..2) */
+
+#ifdef PARANOID
+/* It should be possible to get here only if the arg is ffff....ffff */
+       cmp     $0xffffffff,FPU_fsqrt_arg_1
+       jnz     sqrt_stage_2_error
+#endif /* PARANOID */
+
+/* The best rounded result. */
+       xorl    %eax,%eax
+       decl    %eax
+       movl    %eax,%edi
+       movl    %eax,%esi
+       movl    $0x7fffffff,%eax
+       jmp     sqrt_round_result
+
+#ifdef PARANOID
+sqrt_stage_2_error:
+       pushl   EX_INTERNAL|0x213
+       call    EXCEPTION
+#endif /* PARANOID */
+
+sqrt_stage_2_done:
+
+/* Now the square root has been computed to better than 60 bits. */
+
+/* Find the square of the guess. */
+       movl    %edi,%eax               /* ls word of guess */
+       mull    %edi
+       movl    %edx,FPU_accum_1
+
+       movl    %esi,%eax
+       mull    %esi
+       movl    %edx,FPU_accum_3
+       movl    %eax,FPU_accum_2
+
+       movl    %edi,%eax
+       mull    %esi
+       addl    %eax,FPU_accum_1
+       adcl    %edx,FPU_accum_2
+       adcl    $0,FPU_accum_3
+
+/*     movl    %esi,%eax */
+/*     mull    %edi */
+       addl    %eax,FPU_accum_1
+       adcl    %edx,FPU_accum_2
+       adcl    $0,FPU_accum_3
+
+/* guess^2 now in FPU_accum_3:FPU_accum_2:FPU_accum_1 */
+
+       movl    FPU_fsqrt_arg_0,%eax            /* get normalized n */
+       subl    %eax,FPU_accum_1
+       movl    FPU_fsqrt_arg_1,%eax
+       sbbl    %eax,FPU_accum_2
+       movl    FPU_fsqrt_arg_2,%eax            /* ms word of normalized n */
+       sbbl    %eax,FPU_accum_3
+       jnc     sqrt_stage_3_positive
+
+/* Subtraction gives a negative result,
+   negate the result before division */
+       notl    FPU_accum_1
+       notl    FPU_accum_2
+       notl    FPU_accum_3
+       addl    $1,FPU_accum_1
+       adcl    $0,FPU_accum_2
+
+#ifdef PARANOID
+       adcl    $0,FPU_accum_3  /* This must be zero */
+       jz      sqrt_stage_3_no_error
+
+sqrt_stage_3_error:
+       pushl   EX_INTERNAL|0x207
+       call    EXCEPTION
+
+sqrt_stage_3_no_error:
+#endif /* PARANOID */
+
+       movl    FPU_accum_2,%edx
+       movl    FPU_accum_1,%eax
+       divl    %esi
+       movl    %eax,%ecx
+
+       movl    %edx,%eax
+       divl    %esi
+
+       sarl    $1,%ecx         /* divide by 2 */
+       rcrl    $1,%eax
+
+       /* prepare to round the result */
+
+       addl    %ecx,%edi
+       adcl    $0,%esi
+
+       jmp     sqrt_stage_3_finished
+
+sqrt_stage_3_positive:
+       movl    FPU_accum_2,%edx
+       movl    FPU_accum_1,%eax
+       divl    %esi
+       movl    %eax,%ecx
+
+       movl    %edx,%eax
+       divl    %esi
+
+       sarl    $1,%ecx         /* divide by 2 */
+       rcrl    $1,%eax
+
+       /* prepare to round the result */
+
+       notl    %eax            /* Negate the correction term */
+       notl    %ecx
+       addl    $1,%eax
+       adcl    $0,%ecx         /* carry here ==> correction == 0 */
+       adcl    $0xffffffff,%esi
+
+       addl    %ecx,%edi
+       adcl    $0,%esi
+
+sqrt_stage_3_finished:
+
+/*
+ * The result in %esi:%edi:%eax should be good to about 90 bits here,
+ * and the rounding information here does not have sufficient accuracy
+ * in a few rare cases.
+ */
+       cmpl    $0xffffffe0,%eax
+       ja      sqrt_near_exact_x
+
+       cmpl    $0x00000020,%eax
+       jb      sqrt_near_exact
+
+       cmpl    $0x7fffffe0,%eax
+       jb      sqrt_round_result
+
+       cmpl    $0x80000020,%eax
+       jb      sqrt_get_more_precision
+
+sqrt_round_result:
+/* Set up for rounding operations */
+       movl    %eax,%edx
+       movl    %esi,%eax
+       movl    %edi,%ebx
+       movl    PARAM1,%edi
+       movw    EXP_BIAS,EXP(%edi)      /* Result is in  [1.0 .. 2.0) */
+       jmp     fpu_reg_round
+
+
+sqrt_near_exact_x:
+/* First, the estimate must be rounded up. */
+       addl    $1,%edi
+       adcl    $0,%esi
+
+sqrt_near_exact:
+/*
+ * This is an easy case because x^1/2 is monotonic.
+ * We need just find the square of our estimate, compare it
+ * with the argument, and deduce whether our estimate is
+ * above, below, or exact. We use the fact that the estimate
+ * is known to be accurate to about 90 bits.
+ */
+       movl    %edi,%eax               /* ls word of guess */
+       mull    %edi
+       movl    %edx,%ebx               /* 2nd ls word of square */
+       movl    %eax,%ecx               /* ls word of square */
+
+       movl    %edi,%eax
+       mull    %esi
+       addl    %eax,%ebx
+       addl    %eax,%ebx
+
+#ifdef PARANOID
+       cmp     $0xffffffb0,%ebx
+       jb      sqrt_near_exact_ok
+
+       cmp     $0x00000050,%ebx
+       ja      sqrt_near_exact_ok
+
+       pushl   EX_INTERNAL|0x214
+       call    EXCEPTION
+
+sqrt_near_exact_ok:
+#endif /* PARANOID */
+
+       or      %ebx,%ebx
+       js      sqrt_near_exact_small
+
+       jnz     sqrt_near_exact_large
+
+       or      %ebx,%edx
+       jnz     sqrt_near_exact_large
+
+/* Our estimate is exactly the right answer */
+       xorl    %eax,%eax
+       jmp     sqrt_round_result
+
+sqrt_near_exact_small:
+/* Our estimate is too small */
+       movl    $0x000000ff,%eax
+       jmp     sqrt_round_result
+       
+sqrt_near_exact_large:
+/* Our estimate is too large, we need to decrement it */
+       subl    $1,%edi
+       sbbl    $0,%esi
+       movl    $0xffffff00,%eax
+       jmp     sqrt_round_result
+
+
+sqrt_get_more_precision:
+/* This case is almost the same as the above, except we start
+   with an extra bit of precision in the estimate. */
+       stc                     /* The extra bit. */
+       rcll    $1,%edi         /* Shift the estimate left one bit */
+       rcll    $1,%esi
+
+       movl    %edi,%eax               /* ls word of guess */
+       mull    %edi
+       movl    %edx,%ebx               /* 2nd ls word of square */
+       movl    %eax,%ecx               /* ls word of square */
+
+       movl    %edi,%eax
+       mull    %esi
+       addl    %eax,%ebx
+       addl    %eax,%ebx
+
+/* Put our estimate back to its original value */
+       stc                     /* The ms bit. */
+       rcrl    $1,%esi         /* Shift the estimate left one bit */
+       rcrl    $1,%edi
+
+#ifdef PARANOID
+       cmp     $0xffffff60,%ebx
+       jb      sqrt_more_prec_ok
+
+       cmp     $0x000000a0,%ebx
+       ja      sqrt_more_prec_ok
+
+       pushl   EX_INTERNAL|0x215
+       call    EXCEPTION
+
+sqrt_more_prec_ok:
+#endif /* PARANOID */
+
+       or      %ebx,%ebx
+       js      sqrt_more_prec_small
+
+       jnz     sqrt_more_prec_large
+
+       or      %ebx,%ecx
+       jnz     sqrt_more_prec_large
+
+/* Our estimate is exactly the right answer */
+       movl    $0x80000000,%eax
+       jmp     sqrt_round_result
+
+sqrt_more_prec_small:
+/* Our estimate is too small */
+       movl    $0x800000ff,%eax
+       jmp     sqrt_round_result
+       
+sqrt_more_prec_large:
+/* Our estimate is too large */
+       movl    $0x7fffff00,%eax
+       jmp     sqrt_round_result
diff --git a/sid/component/bochs/cpu/fpu/wm_sqrt.c b/sid/component/bochs/cpu/fpu/wm_sqrt.c
new file mode 100644 (file)
index 0000000..1b8e900
--- /dev/null
@@ -0,0 +1,340 @@
+/*---------------------------------------------------------------------------+
+ |  wm_sqrt.c                                                                |
+ |                                                                           |
+ | Fixed point arithmetic square root evaluation.                            |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1995,1997,1999                                    |
+ |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
+ |                       Australia.  E-mail billm@melbpc.org.au              |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ |    returns the square root of n in n.                                     |
+ |                                                                           |
+ |  Use Newton's method to compute the square root of a number, which must   |
+ |  be in the range  [1.0 .. 4.0),  to 64 bits accuracy.                     |
+ |  Does not check the sign or tag of the argument.                          |
+ |  Sets the exponent, but not the sign or tag of the result.                |
+ |                                                                           |
+ |  The guess is kept in %esi:%edi                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "fpu_emu.h"
+
+/*
+  The following value indicates the trailing bits (of 96 bits)
+  which may be in error when the final Newton iteration is finished
+  (0x20 corresponds to the last 5 bits in error, i.e. 91 bits precision).
+  A check of the following code with more than 3 billion (3.0e9) random
+  and selected values showed that 0x10 was always a large enough value,
+  so 0x20 should be a conservative choice.
+ */
+#define ERR_MARGIN 0x20
+
+
+int wm_sqrt(FPU_REG *n, s32 dummy1, s32 dummy2, u16 control_w, u8 sign)
+{
+  u64 nn, guess, halfn, lowr, mid, upr, diff, uwork;
+  s64 work;
+  u32 ne, guess32, work32, diff32, mid32;
+  int shifted;
+
+  nn = significand(n);
+  ne = 0;
+  if ( exponent16(n) == EXP_BIAS )
+    {
+      /* Shift the argument right one position. */
+      if ( nn & 1 )
+       ne = 0x80000000;
+      nn >>= 1;
+      guess = n->sigh >> 2;
+      shifted = 1;
+    }
+  else
+    {
+      guess = n->sigh >> 1;
+      shifted = 0;
+    }
+
+  guess += 0x40000000;
+  guess *= 0xaaaaaaaa;
+  guess <<= 1;
+  guess32 = guess >> 32;
+  if ( !(guess32 & 0x80000000) )
+    guess32 = 0x80000000;
+  halfn = nn >> 1;
+
+  guess32 = halfn / guess32 + (guess32 >> 1);
+  guess32 = halfn / guess32 + (guess32 >> 1);
+  guess32 = halfn / guess32 + (guess32 >> 1);
+
+
+/*
+ * Now that an estimate accurate to about 30 bits has been obtained,
+ * we improve it to 60 bits or so.
+ *
+ * The strategy from now on is to compute new estimates from
+ *      guess := guess + (n - guess^2) / (2 * guess)
+ */
+
+  work = guess32;
+  work = nn - work * guess32;
+  work <<= 28;       /* 29 - 1 */
+  work /= guess32;
+  work <<= 3;        /* 29 + 3 = 32 */
+  work += ((u64)guess32) << 32;
+
+  if ( work == 0 )  /* This happens in one or two special cases */
+    work = BX_CONST64(0xffffffffffffffff);
+
+  guess = work;
+
+  /* guess is now accurate to about 60 bits */
+
+
+  if ( work > 0 )
+    {
+#ifdef PARANOID
+      if ( (n->sigh != 0xffffffff) && (n->sigl != 0xffffffff) )
+       {
+         EXCEPTION(EX_INTERNAL|0x213);
+       }
+#endif
+      /* We know the answer here. */
+      return FPU_round(n, 0x7fffffff, 0, control_w, sign);
+    }
+
+  /* Refine the guess to significantly more than 64 bits. */
+
+  /* First, square the current guess. */
+
+  guess32 = guess >> 32;
+  work32 = guess;
+
+  /* lower 32 times lower 32 */
+  lowr = work32;
+  lowr *= work32;
+
+  /* lower 32 times upper 32 */
+  mid = guess32;
+  mid *= work32;
+
+  /* upper 32 times upper 32 */
+  upr = guess32;
+  upr *= guess32;
+
+  /* upper 32 bits of the middle product times 2 */
+  upr += mid >> (32-1);
+
+  /* lower 32 bits of the middle product times 2 */
+  work32 = mid << 1;
+
+  /* upper 32 bits of the lower product */
+  mid32 = lowr >> 32;
+  mid32 += work32;
+  if ( mid32 < work32 )
+    upr ++;
+
+  /* We now have the first 96 bits (truncated) of the square of the guess */
+
+  diff = upr - nn;
+  diff32 = mid32 - ne;
+  if ( diff32 > mid32 )
+    diff --;
+
+  if ( ((s64)diff) < 0 )
+    {
+      /* The difference is negative, negate it. */
+      diff32 = -((s32)diff32);
+      diff = ~diff;
+      if ( diff32 == 0 )
+       diff ++;
+#ifdef PARANOID
+      if ( (diff >> 32) != 0 )
+       {
+         EXCEPTION(EX_INTERNAL|0x207);
+       }
+#endif
+
+      diff <<= 32;
+      diff |= diff32;
+      work32 = diff / guess32;
+      work = work32;
+      work <<= 32;
+
+      diff = diff % guess32;
+      diff <<= 32;
+      work32 = diff / guess32;
+
+      work |= work32;
+
+      work >>= 1;
+      work32 = work >> 32;
+
+
+      guess += work32;       /* The first 64 bits */
+      guess32 = work;        /* The next 32 bits */
+      /* The guess should now be good to about 90 bits */
+    }
+  else
+    {
+      /* The difference is positive. */
+      diff <<= 32;
+      diff |= diff32;
+
+      work32 = diff / guess32;
+      work = work32;
+      work <<= 32;
+
+      diff = diff % guess32;
+      diff <<= 32;
+      work32 = diff / guess32;
+
+      work |= work32;
+
+      work >>= 1;
+      work32 = work >> 32;
+
+      guess32 = work;        /* The last 32 bits (of 96) */
+      guess32 = -guess32;
+      if ( guess32 )
+       guess --;
+      guess -= work32;       /* The first 64 bits */
+      /* The guess should now be good to about 90 bits */
+    }
+
+
+  setexponent16(n, 0);
+
+  if ( guess32 >= (u32) -ERR_MARGIN )
+    {
+      /* Nearly exact, we round the 64 bit result upward. */
+      guess ++;
+    }
+  else if ( (guess32 > ERR_MARGIN) &&
+          ((guess32 < 0x80000000-ERR_MARGIN)
+           || (guess32 > 0x80000000+ERR_MARGIN)) )
+    {
+      /* We have enough accuracy to decide rounding */
+      significand(n) = guess;
+      return FPU_round(n, guess32, 0, control_w, sign);
+    }
+
+  if ( (guess32 <= ERR_MARGIN) || (guess32 >= (u32) -ERR_MARGIN) )
+    {
+      /*
+       * This is an easy case because x^1/2 is monotonic.
+       * We need just find the square of our estimate, compare it
+       * with the argument, and deduce whether our estimate is
+       * above, below, or exact. We use the fact that the estimate
+       * is known to be accurate to about 90 bits.
+       */
+
+
+      /* We compute the lower 64 bits of the 128 bit product */
+      work32 = guess;
+      lowr = work32;
+      lowr *= work32;
+
+      uwork = guess >> 32;
+      work32 = guess;
+      uwork *= work32;
+      uwork <<= 33;   /* 33 = 32+1 (for two times the product) */
+
+      lowr += uwork;  /* We now have the 64 bits */
+
+      /* We need only look at bits 65..96 of the square of guess. */
+      if ( shifted )
+       work32 = lowr >> 31;
+      else
+       work32 = lowr >> 32;
+
+#ifdef PARANOID
+      if ( ((s32)work32 > 3*ERR_MARGIN) || ((s32)work32 < -3*ERR_MARGIN) )
+       {
+         EXCEPTION(EX_INTERNAL|0x214);
+       }
+#endif
+
+      significand(n) = guess;
+      if ( (s32)work32 > 0 )
+       {
+         /* guess is too large */
+         significand(n) --;
+         return FPU_round(n, 0xffffff00, 0, control_w, sign);
+       }
+      else if ( (s32)work32 < 0 )
+       {
+         /* guess is a little too small */
+         return FPU_round(n, 0x000000ff, 0, control_w, sign);
+       }
+
+      else if ( (u32)lowr != 0 )
+       {
+
+         /* guess is too large */
+         significand(n) --;
+         return FPU_round(n, 0xffffff00, 0, control_w, sign);
+       }
+
+      /* Our guess is precise. */
+      return FPU_round(n, 0, 0, control_w, sign);
+    }
+
+  /* Very similar to the case above, but the last bit is near 0.5.
+     We handle this just like the case above but we shift everything
+     by one bit. */
+
+
+  uwork = guess;
+  uwork <<= 1;
+  uwork |= 1;      /* add the half bit */
+
+  /* We compute the lower 64 bits of the 128 bit product */
+  work32 = uwork;
+  lowr = work32;
+  lowr *= work32;
+
+  work32 = uwork >> 32;
+  uwork &= 0xffffffff;
+  uwork *= work32;
+  uwork <<= 33;   /* 33 = 32+1 (for two times the product) */
+
+  lowr += uwork;  /* We now have the 64 bits. The lowest 32 bits of lowr
+                    are not all zero (the lsb is 1). */
+
+  /* We need only look at bits 65..96 of the square of guess. */
+  if ( shifted )
+    work32 = lowr >> 31;
+  else
+    work32 = lowr >> 32;
+
+#ifdef PARANOID
+  if ( ((s32)work32 > 4*3*ERR_MARGIN) || ((s32)work32 < -4*3*ERR_MARGIN) )
+    {
+      EXCEPTION(EX_INTERNAL|0x215);
+    }
+#endif
+
+  significand(n) = guess;
+  if ( (s32)work32 < 0 )
+    {
+      /* guess plus half bit is a little too small */
+      return FPU_round(n, 0x800000ff, 0, control_w, sign);
+    }
+  else /* Note that the lower 64 bits of the product are not all zero */
+    {
+      /* guess plus half bit is too large */
+      return FPU_round(n, 0x7fffff00, 0, control_w, sign);
+    }
+
+  /*
+    Note that the result of a square root cannot have precisely a half bit
+    of a least significant place (it is left as an exercise for the reader
+    to prove this! (hint: 65 bit*65 bit => n bits)).
+  */
+
+}
+
diff --git a/sid/component/bochs/cpu/init-sid.cc b/sid/component/bochs/cpu/init-sid.cc
deleted file mode 100644 (file)
index fa9dbc1..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-//  Copyright (C) 2001  MandrakeSoft S.A.
-//
-//    MandrakeSoft S.A.
-//    43, rue d'Aboukir
-//    75002 Paris - France
-//    http://www.linux-mandrake.com/
-//    http://www.mandrakesoft.com/
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-#include "bochs.h"
-#define LOG_THIS BX_CPU_THIS_PTR
-
-     // sid_cpu_c constructor
-void sid_cpu_c::init(sid_mem_c *addrspace)
-{
-    // To deal with initialization order problems inherent in C++, use
-  // the macros SAFE_GET_IOFUNC and SAFE_GET_GENLOG to retrieve "io" and "genlog"
-  // in all constructors or functions called by constructors.  The macros
-  // test for NULL and create the object if necessary, then return it.
-  // Ensure that io and genlog get created, by making one reference to
-  // each macro right here.  All other code can call them directly.
-  SAFE_GET_IOFUNC();
-  SAFE_GET_GENLOG();
-
-  BX_CPU_THIS_PTR set_INTR (0);
-#if BX_SUPPORT_APIC
-  local_apic.init ();
-#endif
-  setprefix("[CPU ]");
-  // in SMP mode, the prefix of the CPU will be changed to [CPUn] in 
-  // bx_local_apic_c::set_id as soon as the apic ID is assigned.
-
-  /* hack for the following fields.  Its easier to decode mod-rm bytes if
-     you can assume there's always a base & index register used.  For
-     modes which don't really use them, point to an empty (zeroed) register.
-   */
-  empty_register = 0;
-
-  // 16bit address mode base register, used for mod-rm decoding
-
-  _16bit_base_reg[0] = &gen_reg[BX_16BIT_REG_BX].word.rx;
-  _16bit_base_reg[1] = &gen_reg[BX_16BIT_REG_BX].word.rx;
-  _16bit_base_reg[2] = &gen_reg[BX_16BIT_REG_BP].word.rx;
-  _16bit_base_reg[3] = &gen_reg[BX_16BIT_REG_BP].word.rx;
-  _16bit_base_reg[4] = (Bit16u*) &empty_register;
-  _16bit_base_reg[5] = (Bit16u*) &empty_register;
-  _16bit_base_reg[6] = &gen_reg[BX_16BIT_REG_BP].word.rx;
-  _16bit_base_reg[7] = &gen_reg[BX_16BIT_REG_BX].word.rx;
-
-  // 16bit address mode index register, used for mod-rm decoding
-  _16bit_index_reg[0] = &gen_reg[BX_16BIT_REG_SI].word.rx;
-  _16bit_index_reg[1] = &gen_reg[BX_16BIT_REG_DI].word.rx;
-  _16bit_index_reg[2] = &gen_reg[BX_16BIT_REG_SI].word.rx;
-  _16bit_index_reg[3] = &gen_reg[BX_16BIT_REG_DI].word.rx;
-  _16bit_index_reg[4] = &gen_reg[BX_16BIT_REG_SI].word.rx;
-  _16bit_index_reg[5] = &gen_reg[BX_16BIT_REG_DI].word.rx;
-  _16bit_index_reg[6] = (Bit16u*) &empty_register;
-  _16bit_index_reg[7] = (Bit16u*) &empty_register;
-
-  // for decoding instructions: access to seg reg's via index number
-  sreg_mod00_rm16[0] = BX_SEG_REG_DS;
-  sreg_mod00_rm16[1] = BX_SEG_REG_DS;
-  sreg_mod00_rm16[2] = BX_SEG_REG_SS;
-  sreg_mod00_rm16[3] = BX_SEG_REG_SS;
-  sreg_mod00_rm16[4] = BX_SEG_REG_DS;
-  sreg_mod00_rm16[5] = BX_SEG_REG_DS;
-  sreg_mod00_rm16[6] = BX_SEG_REG_DS;
-  sreg_mod00_rm16[7] = BX_SEG_REG_DS;
-
-  sreg_mod01_rm16[0] = BX_SEG_REG_DS;
-  sreg_mod01_rm16[1] = BX_SEG_REG_DS;
-  sreg_mod01_rm16[2] = BX_SEG_REG_SS;
-  sreg_mod01_rm16[3] = BX_SEG_REG_SS;
-  sreg_mod01_rm16[4] = BX_SEG_REG_DS;
-  sreg_mod01_rm16[5] = BX_SEG_REG_DS;
-  sreg_mod01_rm16[6] = BX_SEG_REG_SS;
-  sreg_mod01_rm16[7] = BX_SEG_REG_DS;
-
-  sreg_mod10_rm16[0] = BX_SEG_REG_DS;
-  sreg_mod10_rm16[1] = BX_SEG_REG_DS;
-  sreg_mod10_rm16[2] = BX_SEG_REG_SS;
-  sreg_mod10_rm16[3] = BX_SEG_REG_SS;
-  sreg_mod10_rm16[4] = BX_SEG_REG_DS;
-  sreg_mod10_rm16[5] = BX_SEG_REG_DS;
-  sreg_mod10_rm16[6] = BX_SEG_REG_SS;
-  sreg_mod10_rm16[7] = BX_SEG_REG_DS;
-
-  // the default segment to use for a one-byte modrm with mod==01b
-  // and rm==i
-  //
-  sreg_mod01_rm32[0] = BX_SEG_REG_DS;
-  sreg_mod01_rm32[1] = BX_SEG_REG_DS;
-  sreg_mod01_rm32[2] = BX_SEG_REG_DS;
-  sreg_mod01_rm32[3] = BX_SEG_REG_DS;
-  sreg_mod01_rm32[4] = BX_SEG_REG_NULL;
-    // this entry should never be accessed
-    // (escape to 2-byte)
-  sreg_mod01_rm32[5] = BX_SEG_REG_SS;
-  sreg_mod01_rm32[6] = BX_SEG_REG_DS;
-  sreg_mod01_rm32[7] = BX_SEG_REG_DS;
-
-  // the default segment to use for a one-byte modrm with mod==10b
-  // and rm==i
-  //
-  sreg_mod10_rm32[0] = BX_SEG_REG_DS;
-  sreg_mod10_rm32[1] = BX_SEG_REG_DS;
-  sreg_mod10_rm32[2] = BX_SEG_REG_DS;
-  sreg_mod10_rm32[3] = BX_SEG_REG_DS;
-  sreg_mod10_rm32[4] = BX_SEG_REG_NULL;
-    // this entry should never be accessed
-    // (escape to 2-byte)
-  sreg_mod10_rm32[5] = BX_SEG_REG_SS;
-  sreg_mod10_rm32[6] = BX_SEG_REG_DS;
-  sreg_mod10_rm32[7] = BX_SEG_REG_DS;
-
-
-  // the default segment to use for a two-byte modrm with mod==00b
-  // and base==i
-  //
-  sreg_mod0_base32[0] = BX_SEG_REG_DS;
-  sreg_mod0_base32[1] = BX_SEG_REG_DS;
-  sreg_mod0_base32[2] = BX_SEG_REG_DS;
-  sreg_mod0_base32[3] = BX_SEG_REG_DS;
-  sreg_mod0_base32[4] = BX_SEG_REG_SS;
-  sreg_mod0_base32[5] = BX_SEG_REG_DS;
-  sreg_mod0_base32[6] = BX_SEG_REG_DS;
-  sreg_mod0_base32[7] = BX_SEG_REG_DS;
-
-  // the default segment to use for a two-byte modrm with
-  // mod==01b or mod==10b and base==i
-  sreg_mod1or2_base32[0] = BX_SEG_REG_DS;
-  sreg_mod1or2_base32[1] = BX_SEG_REG_DS;
-  sreg_mod1or2_base32[2] = BX_SEG_REG_DS;
-  sreg_mod1or2_base32[3] = BX_SEG_REG_DS;
-  sreg_mod1or2_base32[4] = BX_SEG_REG_SS;
-  sreg_mod1or2_base32[5] = BX_SEG_REG_SS;
-  sreg_mod1or2_base32[6] = BX_SEG_REG_DS;
-  sreg_mod1or2_base32[7] = BX_SEG_REG_DS;
-
-#if BX_DYNAMIC_TRANSLATION
-  DTWrite8vShim = NULL;
-  DTWrite16vShim = NULL;
-  DTWrite32vShim = NULL;
-  DTRead8vShim = NULL;
-  DTRead16vShim = NULL;
-  DTRead32vShim = NULL;
-  DTReadRMW8vShim = (BxDTShim_t) DTASReadRMW8vShim;
-  BX_DEBUG(( "DTReadRMW8vShim is %x\n", (unsigned) DTReadRMW8vShim ));
-  BX_DEBUG(( "&DTReadRMW8vShim is %x\n", (unsigned) &DTReadRMW8vShim ));
-  DTReadRMW16vShim = NULL;
-  DTReadRMW32vShim = NULL;
-  DTWriteRMW8vShim = (BxDTShim_t) DTASWriteRMW8vShim;
-  DTWriteRMW16vShim = NULL;
-  DTWriteRMW32vShim = NULL;
-  DTSetFlagsOSZAPCPtr = (BxDTShim_t) DTASSetFlagsOSZAPC;
-  DTIndBrHandler = (BxDTShim_t) DTASIndBrHandler;
-  DTDirBrHandler = (BxDTShim_t) DTASDirBrHandler;
-#endif
-
-  mem = addrspace;
-  sprintf (name, "CPU %p", this);
-
-  BX_INSTR_INIT();
-  BX_DEBUG(( "Init.\n"));
-}
-
-  void
-sid_cpu_c::set_INTR(Boolean value)
-{
-  BX_CPU_THIS_PTR INTR = value;
-  BX_CPU_THIS_PTR async_event = 0;
-}
index a4934bc..f247164 100644 (file)
 #include "bochs.h"
 #define LOG_THIS BX_CPU_THIS_PTR
 
+#if BX_SUPPORT_SID
+#include "sid-x86-cpu-wrapper.h"
+#endif
+
 
 /* the device id and stepping id are loaded into DH & DL upon processor
    startup.  for device id: 3 = 80386, 4 = 80486.  just make up a
@@ -43,13 +47,17 @@ BX_CPU_C::BX_CPU_C()
 }
 
 #if BX_SUPPORT_SID
-void BX_CPU_C::init(sid_mem_c *addrspace)
+void BX_CPU_C::init(x86_cpu *x86_cpu_comp, sid_bx_mem_c *addrspace)
 #else
 void BX_CPU_C::init(BX_MEM_C *addrspace)
 #endif
 {
   // BX_CPU_C constructor
   BX_CPU_THIS_PTR set_INTR (0);
+#if BX_SUPPORT_SID
+  BX_CPU_THIS_PTR set_HRQ (0);
+#endif
+
 #if BX_SUPPORT_APIC
   local_apic.init ();
 #endif
@@ -184,7 +192,12 @@ void BX_CPU_C::init(BX_MEM_C *addrspace)
   DTDirBrHandler = (BxDTShim_t) DTASDirBrHandler;
 #endif
 
+#if BX_SUPPORT_SID
+  x86_cpu_component = x86_cpu_comp;
+#endif
   mem = addrspace;
+  mem->init(x86_cpu_component);
+
   sprintf (name, "CPU %p", this);
 
   BX_INSTR_INIT();
@@ -557,7 +570,7 @@ BX_CPU_C::reset(unsigned source)
 
   BX_CPU_THIS_PTR EXT = 0;
   //BX_INTR = 0;
-  
+
 #if BX_SUPPORT_PAGING
 #if BX_USE_TLB
   TLB_init();
@@ -687,3 +700,13 @@ BX_CPU_C::set_INTR(Boolean value)
   BX_CPU_THIS_PTR INTR = value;
   BX_CPU_THIS_PTR async_event = 1;
 }
+
+#if BX_SUPPORT_SID
+void
+BX_CPU_C::set_HRQ(Boolean value)
+{
+  BX_CPU_THIS_PTR BX_HRQ = value;
+  if (value)
+    BX_CPU_THIS_PTR async_event = 1;
+}
+#endif
index 2bed6f0..0520d83 100644 (file)
 #define LOG_THIS BX_CPU_THIS_PTR
 
 
+#if BX_SUPPORT_SID
+#include "sid-x86-cpu-wrapper.h"
+#endif
 
 
 
   void
 BX_CPU_C::INSB_YbDX(BxInstruction_t *i)
 {
-#if 0
   Bit8u value8=0;
 
   if (BX_CPU_THIS_PTR cr0.pe && (BX_CPU_THIS_PTR eflags.vm || (CPL>IOPL))) {
@@ -80,14 +82,12 @@ BX_CPU_C::INSB_YbDX(BxInstruction_t *i)
       DI = DI + 1;
       }
     }
-#endif
 }
 
   void
 BX_CPU_C::INSW_YvDX(BxInstruction_t *i)
   // input word/doubleword from port to string
 {
-#if 0
   Bit32u edi;
   unsigned int incr;
 
@@ -147,13 +147,11 @@ BX_CPU_C::INSW_YvDX(BxInstruction_t *i)
     else
       DI = DI + incr;
     }
-#endif
 }
 
   void
 BX_CPU_C::OUTSB_DXXb(BxInstruction_t *i)
 {
-#if 0
   unsigned seg;
   Bit8u value8;
   Bit32u esi;
@@ -192,14 +190,12 @@ BX_CPU_C::OUTSB_DXXb(BxInstruction_t *i)
     else
       SI += 1;
     }
-#endif
 }
 
   void
 BX_CPU_C::OUTSW_DXXv(BxInstruction_t *i)
   // output word/doubleword string to port
 {
-#if 0
   unsigned seg;
   Bit32u esi;
   unsigned int incr;
@@ -257,7 +253,6 @@ BX_CPU_C::OUTSW_DXXv(BxInstruction_t *i)
     else
       SI = SI + incr;
     }
-#endif
 }
 
 
index 65d28e4..6040fae 100644 (file)
 #include "bochs.h"
 #define LOG_THIS BX_CPU_THIS_PTR
 
+#if BX_SUPPORT_SID
+#include "sid-x86-cpu-wrapper.h"
+#endif
 
 
 
   Bit16u
 BX_CPU_C::inp16(Bit16u addr)
 {
-#if 0
   Bit16u ret16;
 
   if (BX_CPU_THIS_PTR cr0.pe && (BX_CPU_THIS_PTR eflags.vm || (CPL>IOPL))) {
@@ -49,14 +51,11 @@ BX_CPU_C::inp16(Bit16u addr)
 
   ret16 = BX_INP(addr, 2);
   return( ret16 );
-#endif
-  return 0;
 }
 
   void
 BX_CPU_C::outp16(Bit16u addr, Bit16u value)
 {
-#if 0
   /* If CPL <= IOPL, then all IO addresses are accessible.
    * Otherwise, must check the IO permission map on >286.
    * On the 286, there is no IO permissions map */
@@ -70,13 +69,11 @@ BX_CPU_C::outp16(Bit16u addr, Bit16u value)
     }
 
   BX_OUTP(addr, value, 2);
-#endif
 }
 
   Bit32u
 BX_CPU_C::inp32(Bit16u addr)
 {
-#if 0
   Bit32u ret32;
 
   if (BX_CPU_THIS_PTR cr0.pe && (BX_CPU_THIS_PTR eflags.vm || (CPL>IOPL))) {
@@ -89,14 +86,11 @@ BX_CPU_C::inp32(Bit16u addr)
 
   ret32 = BX_INP(addr, 4);
   return( ret32 );
-#endif
-  return 0;
 }
 
   void
 BX_CPU_C::outp32(Bit16u addr, Bit32u value)
 {
-#if 0
   /* If CPL <= IOPL, then all IO addresses are accessible.
    * Otherwise, must check the IO permission map on >286.
    * On the 286, there is no IO permissions map */
@@ -110,13 +104,11 @@ BX_CPU_C::outp32(Bit16u addr, Bit32u value)
     }
 
   BX_OUTP(addr, value, 4);
-#endif 
 }
 
   Bit8u
 BX_CPU_C::inp8(Bit16u addr)
 {
-#if 0
   Bit8u ret8;
 
   if (BX_CPU_THIS_PTR cr0.pe && (BX_CPU_THIS_PTR eflags.vm || (CPL>IOPL))) {
@@ -129,15 +121,12 @@ BX_CPU_C::inp8(Bit16u addr)
 
   ret8 = BX_INP(addr, 1);
   return( ret8 );
-#endif
-  return 0;
 }
 
 
   void
 BX_CPU_C::outp8(Bit16u addr, Bit8u value)
 {
-#if 0
   /* If CPL <= IOPL, then all IO addresses are accessible.
    * Otherwise, must check the IO permission map on >286.
    * On the 286, there is no IO permissions map */
@@ -151,14 +140,12 @@ BX_CPU_C::outp8(Bit16u addr, Bit8u value)
     }
 
   BX_OUTP(addr, value, 1);
-#endif
 }
 
 
   Boolean
 BX_CPU_C::allow_io(Bit16u addr, unsigned len)
 {
-#if 0
   Bit16u io_base, permission16;
   unsigned bit_index, i;
 
@@ -198,7 +185,6 @@ BX_INFO(("len is %u\n", len));
       return(0);
     permission16 >>= 1;
     }
-#endif
 
   return(1);
 }
index e30b42c..c5a1922 100644 (file)
@@ -73,8 +73,8 @@ bx_options_t bx_options = {
   { NULL, NULL, NULL, 0, 0, 0, 0 },     // SB16
   "a",                                  // boot drive
   300000,                               // vga update interval
-  20,  // default keyboard serial path delay (usec in bochs, msec in sid)
-  50000,  // default floppy command delay (usec)
+  250,  // default keyboard serial path delay (usec)
+  500,  // default floppy command delay (usec)
   500000,  // default ips (instructions-per-second)
   0,       // default mouse_enabled
   0,       // default private_colormap
@@ -528,11 +528,13 @@ bx_bochs_init(int argc, char *argv[])
 #endif
 
 #if BX_SMP_PROCESSORS==1
+#if BX_SUPPORT_SID==0
   BX_MEM(0)->init_memory(bx_options.memory.megs * 1024*1024);
   BX_MEM(0)->load_ROM(bx_options.rom.path, bx_options.rom.address);
   BX_MEM(0)->load_ROM(bx_options.vgarom.path, 0xc0000);
   BX_CPU(0)->init (BX_MEM(0));
   BX_CPU(0)->reset(BX_RESET_HARDWARE);
+#endif
 #else
   // SMP initialization
   bx_mem_array[0] = new BX_MEM_C ();
@@ -580,7 +582,7 @@ bx_bochs_init(int argc, char *argv[])
   void
 bx_init_debug(void)
 {
-  bx_dbg.floppy = 0;
+  bx_dbg.floppy = 1;
   bx_dbg.keyboard = 0;
   bx_dbg.video = 0;
   bx_dbg.disk = 0;
@@ -621,12 +623,12 @@ bx_atexit(void)
     bx_pc_system.exit();
     }
 #endif
-
+#if BX_SUPPORT_SID==0
 #if BX_DEBUGGER == 0
   for (int cpu=0; cpu<BX_SMP_PROCESSORS; cpu++)
     if (BX_CPU(cpu)) BX_CPU(cpu)->atexit();
 #endif
-
+#endif
 #if BX_PCI_SUPPORT
     if (bx_options.i440FXSupport) {
       bx_devices.pci->print_i440fx_state();
diff --git a/sid/component/bochs/cpu/memory/Makefile.am b/sid/component/bochs/cpu/memory/Makefile.am
new file mode 100644 (file)
index 0000000..334ee0c
--- /dev/null
@@ -0,0 +1,11 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../.. -I$(srcdir)/../../../../include
+
+noinst_LTLIBRARIES = libmemory.la
+
+libmemory_la_SOURCES = sid-bochs-memory.cc sid-bochs-memory.cc
+
+libmemory_la_LDFLAGS = -no-undefined
diff --git a/sid/component/bochs/cpu/memory/Makefile.in b/sid/component/bochs/cpu/memory/Makefile.in
new file mode 100644 (file)
index 0000000..58a6cca
--- /dev/null
@@ -0,0 +1,408 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+APIC_OBJS = @APIC_OBJS@
+AR = @AR@
+AS = @AS@
+AS_DYNAMIC_INCS = @AS_DYNAMIC_INCS@
+AS_DYNAMIC_OBJS = @AS_DYNAMIC_OBJS@
+BX_LOADER_OBJS = @BX_LOADER_OBJS@
+BX_SPLIT_HD_SUPPORT = @BX_SPLIT_HD_SUPPORT@
+CC = @CC@
+CDROM_OBJS = @CDROM_OBJS@
+CD_UP_ONE = @CD_UP_ONE@
+CD_UP_TWO = @CD_UP_TWO@
+CFP = @CFP@
+COMMAND_SEPARATOR = @COMMAND_SEPARATOR@
+CPP_SUFFIX = @CPP_SUFFIX@
+CXX = @CXX@
+CXXFP = @CXXFP@
+DASH = @DASH@
+DEBUGGER_VAR = @DEBUGGER_VAR@
+DISASM_VAR = @DISASM_VAR@
+DLLTOOL = @DLLTOOL@
+DYNAMIC_VAR = @DYNAMIC_VAR@
+EXE = @EXE@
+EXEEXT = @EXEEXT@
+EXTERNAL_DEPENDENCY = @EXTERNAL_DEPENDENCY@
+FPU_GLUE_OBJ = @FPU_GLUE_OBJ@
+FPU_VAR = @FPU_VAR@
+GUI_LINK_OPTS = @GUI_LINK_OPTS@
+GUI_LINK_OPTS_TERM = @GUI_LINK_OPTS_TERM@
+GUI_OBJS = @GUI_OBJS@
+GZIP = @GZIP@
+INLINE_VAR = @INLINE_VAR@
+INSTRUMENT_DIR = @INSTRUMENT_DIR@
+INSTRUMENT_VAR = @INSTRUMENT_VAR@
+IOAPIC_OBJS = @IOAPIC_OBJS@
+IODEV_LIB_VAR = @IODEV_LIB_VAR@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LINK = @LINK@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKELIB = @MAKELIB@
+NE2K_OBJS = @NE2K_OBJS@
+NM = @NM@
+NONINLINE_VAR = @NONINLINE_VAR@
+OBJDUMP = @OBJDUMP@
+OFP = @OFP@
+PACKAGE = @PACKAGE@
+PCI_OBJ = @PCI_OBJ@
+PRIMARY_TARGET = @PRIMARY_TARGET@
+RANLIB = @RANLIB@
+READLINE_LIB = @READLINE_LIB@
+RFB_LIBS = @RFB_LIBS@
+RMCOMMAND = @RMCOMMAND@
+SB16_OBJS = @SB16_OBJS@
+SLASH = @SLASH@
+SUFFIX_LINE = @SUFFIX_LINE@
+TAR = @TAR@
+VERSION = @VERSION@
+VIDEO_OBJS = @VIDEO_OBJS@
+sidtarget_arm = @sidtarget_arm@
+sidtarget_m32r = @sidtarget_m32r@
+sidtarget_m68k = @sidtarget_m68k@
+sidtarget_mips = @sidtarget_mips@
+sidtarget_ppc = @sidtarget_ppc@
+sidtarget_x86 = @sidtarget_x86@
+sidtarget_xstormy16 = @sidtarget_xstormy16@
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../.. -I$(srcdir)/../../../../include
+
+noinst_LTLIBRARIES = libmemory.la
+
+libmemory_la_SOURCES = sid-bochs-memory.cc sid-bochs-memory.cc
+
+libmemory_la_LDFLAGS = -no-undefined
+mkinstalldirs = $(SHELL) $(top_srcdir)/../../config/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LTLIBRARIES =  $(noinst_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libmemory_la_LIBADD = 
+libmemory_la_OBJECTS =  sid-bochs-memory.lo sid-bochs-memory.lo
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+GZIP_ENV = --best
+DEP_FILES =  .deps/sid-bochs-memory.P
+SOURCES = $(libmemory_la_SOURCES)
+OBJECTS = $(libmemory_la_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .lo .o .s
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --foreign cpu/memory/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLTLIBRARIES:
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+
+distclean-noinstLTLIBRARIES:
+
+maintainer-clean-noinstLTLIBRARIES:
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libmemory.la: $(libmemory_la_OBJECTS) $(libmemory_la_DEPENDENCIES)
+       $(CXXLINK)  $(libmemory_la_LDFLAGS) $(libmemory_la_OBJECTS) $(libmemory_la_LIBADD) $(LIBS)
+.cc.o:
+       $(CXXCOMPILE) -c $<
+.cc.lo:
+       $(LTCXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = cpu/memory
+
+distdir: $(DISTFILES)
+       here=`cd $(top_builddir) && pwd`; \
+       top_distdir=`cd $(top_distdir) && pwd`; \
+       distdir=`cd $(distdir) && pwd`; \
+       cd $(top_srcdir) \
+         && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign cpu/memory/Makefile
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+       -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+       @echo '$(COMPILE) -c $<'; \
+       $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.c
+       @echo '$(LTCOMPILE) -c $<'; \
+       $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+
+%.o: %.cc
+       @echo '$(CXXCOMPILE) -c $<'; \
+       $(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.cc
+       @echo '$(LTCXXCOMPILE) -c $<'; \
+       $(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LTLIBRARIES)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLTLIBRARIES mostlyclean-compile \
+               mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+               mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLTLIBRARIES clean-compile clean-libtool \
+               clean-tags clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLTLIBRARIES distclean-compile \
+               distclean-libtool distclean-tags distclean-depend \
+               distclean-generic clean-am
+       -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLTLIBRARIES \
+               maintainer-clean-compile maintainer-clean-libtool \
+               maintainer-clean-tags maintainer-clean-depend \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \
+clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sid/component/bochs/cpu/memory/sid-bochs-memory.cc b/sid/component/bochs/cpu/memory/sid-bochs-memory.cc
new file mode 100644 (file)
index 0000000..d8f09f3
--- /dev/null
@@ -0,0 +1,136 @@
+//  sid-bochs-memory.cc - route bochs memory calls to sid cpu component. -*- C++ -*-
+//
+//  Copyright (C) 2001 Red Hat.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+#include "bochs.h"
+#include "sid-x86-cpu-wrapper.h"
+#define LOG_THIS this->
+
+void
+sid_bx_mem_c::init(x86_cpu *x86_cpu_comp)
+{
+  x86_cpu_component = x86_cpu_comp;
+}
+
+void
+sid_bx_mem_c::write_physical(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data)
+{
+  Bit32u a20addr;
+
+  a20addr = A20ADDR(addr);
+
+  try
+    {
+      switch(len)
+        {
+        case 4:
+          {
+            Bit32u data32 = * ((Bit32u *) data);
+            x86_cpu_component->write_data_memory_4 (cpu->eip, a20addr, data32);
+            break;
+          }
+        case 2:
+          {
+            Bit16u data16 = * ((Bit16u *) data);
+            x86_cpu_component->write_data_memory_2 (cpu->eip, a20addr, data16);
+            break;
+          }
+        case 1:
+          {
+            Bit8u data8 =  * ((Bit8u *) data);
+            x86_cpu_component->write_data_memory_1 (cpu->eip, a20addr, data8);
+            break;
+          }
+        default:
+          {
+            Bit8u data8;
+            Bit8u *data_ptr = (Bit8u *) data;
+            
+            for (unsigned i = 0; i < len; i++)
+              {
+                data8 = * data_ptr;
+                x86_cpu_component->write_data_memory_1 (cpu->eip, a20addr, data8);
+                data_ptr++;
+                addr++;
+                a20addr = A20ADDR(addr);
+              }
+            break;
+          }
+        }
+    }
+  catch (sidutil::cpu_memory_fault e)
+    {
+      cerr << "[MEM ] caught cpu_memory_fault exeception" << endl;
+      cerr << "[MEM ] pc = " << setbase(16) << e.pc << endl;
+      cerr << "[MEM ] addr = " << e.address << endl;
+      cerr << "[MEM ] status: " << (e.status == sid::bus::ok ? "ok" :
+                                    (e.status == sid::bus::misaligned ? "misaligned" :
+                                     (e.status == sid::bus::unmapped ? "unmapped" : "unpermitted"))) << endl;
+      
+      cerr << "[MEM ] operation: " << e.operation << setbase(10) << endl;
+      BX_PANIC(("sid_bx_mem_c::write_physical: error\n"));
+    }
+}
+
+void
+sid_bx_mem_c::read_physical(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data)
+{
+
+  Bit32u a20addr;
+
+  a20addr = A20ADDR(addr);
+
+  try
+    {
+      switch (len)
+        {
+        case 4:
+          * ((Bit32u *) data) = x86_cpu_component->read_data_memory_4 (cpu->eip, a20addr);
+          break;
+        case 2:
+          * ((Bit16u *) data) = x86_cpu_component->read_data_memory_2 (cpu->eip, a20addr);
+          break;
+        case 1:
+          * ((Bit8u *) data) = x86_cpu_component->read_data_memory_1 (cpu->eip, a20addr);
+          break;
+        default:
+          Bit8u data8;
+          Bit8u * data_ptr = (Bit8u *) data;
+          
+          for (unsigned i = 0; i < len; i++)
+            {
+              * data_ptr = x86_cpu_component->read_data_memory_1 (cpu->eip, a20addr);
+              data_ptr++;
+              addr++;
+              a20addr = A20ADDR(addr);
+            }
+          break;          
+        }
+    }
+  catch (sidutil::cpu_memory_fault e)
+    {
+      cerr << "[MEM ] caught cpu_memory_fault exeception" << endl;
+      cerr << "[MEM ] pc = " << setbase(16) << e.pc << endl;
+      cerr << "[MEM ] addr = " << e.address << endl;
+      cerr << "[MEM ] status: " << (e.status == sid::bus::ok ? "ok" :
+                                    (e.status == sid::bus::misaligned ? "misaligned" :
+                                     (e.status == sid::bus::unmapped ? "unmapped" : "unpermitted"))) << endl;
+      
+      cerr << "[MEM ] operation: " << e.operation << setbase(10) << endl;
+      BX_PANIC(("sid_bx_mem_c::read_physical: error\n"));
+    }
+}
diff --git a/sid/component/bochs/cpu/memory/sid-bochs-memory.h b/sid/component/bochs/cpu/memory/sid-bochs-memory.h
new file mode 100644 (file)
index 0000000..26d97f2
--- /dev/null
@@ -0,0 +1,37 @@
+//  sid-bochs-memory.h - declaration of the sid_bx_mem_c class. -*- C++ -*-
+//
+//  Copyright (C) 2001 Red Hat.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+#ifndef __SID_BX_MEMORY_H__
+#define __SID_BX_MEMORY_H__
+
+class x86_cpu;
+
+// This class takes bochs calls to read_physical and write_physical,
+// and calls the corresponding sid cpu read_data_memory and
+// write_data_memory functions.
+class sid_bx_mem_c : public logfunctions
+{
+public:
+  void init(x86_cpu *x86_cpu_comp);
+  void read_physical(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data);
+  void write_physical(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data);
+
+protected:
+  x86_cpu *x86_cpu_component;
+};
+#endif // __SID_BX_MEMORY_H__
index 7f75c9a..c26470a 100644 (file)
@@ -953,6 +953,7 @@ BX_CPU_C::access_linear(Bit32u laddress, unsigned length, unsigned pl,
   BX_PANIC(("access_linear: paging not supported\n"));
 }
 
+
   void
 BX_CPU_C::INVLPG(BxInstruction_t* i)
 {}
diff --git a/sid/component/bochs/cpu/sid-x86-cpu-wrapper.cc b/sid/component/bochs/cpu/sid-x86-cpu-wrapper.cc
new file mode 100644 (file)
index 0000000..6ff4ac0
--- /dev/null
@@ -0,0 +1,390 @@
+//  sid-x86-cpu-wrapper.cc - member function implementations for the sid x86 cpu component. -*- C++ -*-
+//
+//  Copyright (C) 2001 Red Hat.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+#include "sid-x86-cpu-wrapper.h"
+
+x86_cpu::x86_cpu ()
+    : interrupt_pin(this, & x86_cpu::interrupt),
+      hold_request_pin(this, & x86_cpu::hold_request),
+      enable_a20_pin(this, & x86_cpu::enable_a20),
+      in_hardware_mode(false),
+      _a20_enabled(true),
+      a20_mask(0xffffffff),
+      memory_mode("default"),
+      blocking_on_syscall(false),
+      verbose_p(false),
+      io_memory_bus(0)
+{
+  bx_cpu.init(this, &bx_mem);
+
+  add_pin("interrupt", & this->interrupt_pin);
+  add_pin("interrupt-acknowledge", & this->interrupt_acknowledge_pin);
+  add_pin("interrupt-ack-response", & this->interrupt_acknowledge_response_pin);
+
+  add_pin("hold-request", & this->hold_request_pin);
+  add_pin("hold-acknowledge", & this->hold_acknowledge_pin);
+
+  add_pin("enable-a20", & this->enable_a20_pin);
+  add_pin("a20-enabled", & this->a20_enabled_pin);
+
+  add_accessor("io-memory", & this->io_memory_bus);
+
+  // set up registers for use by gloss component.
+  // see libgloss/i386/* for calling conventions
+  // and exception-sid.cc for handling of int 0x80
+  add_watchable_register (string("syscall-arg0"), &bx_cpu.gen_reg[0].erx);
+  add_watchable_register (string("syscall-arg1"), &bx_cpu.gen_reg[3].erx);
+  add_watchable_register (string("syscall-arg2"), &bx_cpu.gen_reg[1].erx);
+  add_watchable_register (string("syscall-arg3"), &bx_cpu.gen_reg[2].erx);
+  add_watchable_register (string("syscall-result"), &bx_cpu.gen_reg[0].erx);
+
+  add_watchable_register (string("syscall-trap"), &bx_cpu.gen_reg[0].erx);    
+  add_watchable_register (string("syscall-error"), &syscall_error);
+
+  // set up debugging interface
+  // there are 16 integer registers
+  create_gdb_register_attrs (16, "4;5;8;9", & this->bx_cpu.eip);
+  
+  add_attribute ("enable-warnings?", & this->warnings_enabled, "setting");
+  add_attribute ("hardware-mode?", & this->in_hardware_mode, "setting");
+  add_attribute ("memory-mode", & this->memory_mode, "setting");
+  add_attribute("verbose?", & this->verbose_p, "setting");
+}
+
+void
+x86_cpu::do_syscall()
+{
+  sid::host_int_4 tempAX = bx_cpu.gen_reg[0].erx;
+  sid::host_int_4 tempBX = bx_cpu.gen_reg[3].erx;
+  sid::host_int_4 tempCX = bx_cpu.gen_reg[1].erx;
+  sid::host_int_4 tempDX = bx_cpu.gen_reg[2].erx;
+  
+  sidutil::cpu_trap_disposition whatnext = signal_trap(sidutil::cpu_trap_software, bx_cpu.gen_reg[0].erx);
+  
+  switch (whatnext)
+    {
+    case sidutil::cpu_trap_unhandled:
+      cerr << "hw-cpu-x86: cpu syscall trap unhandled" << endl;
+      this->blocking_on_syscall = false;
+      return;
+    case sidutil::cpu_trap_reissue:
+      bx_cpu.gen_reg[0].erx = tempAX;
+      bx_cpu.gen_reg[3].erx = tempBX;
+      bx_cpu.gen_reg[1].erx = tempCX;
+      bx_cpu.gen_reg[2].erx = tempDX;
+      this->blocking_on_syscall = true;
+      return;
+    case sidutil::cpu_trap_skip:
+      /* fall-through */
+    case sidutil::cpu_trap_handled:
+      this->blocking_on_syscall = false;
+      return;
+    default:
+      abort ();
+    }
+  this->yield();
+  throw sidutil::cpu_exception();
+}
+
+void
+x86_cpu::do_breakpoint()
+{
+  sidutil::cpu_trap_disposition whatnext = signal_trap(sidutil::cpu_trap_breakpoint, 0);
+  
+  switch (whatnext)
+    {
+    case sidutil::cpu_trap_unhandled:
+      cerr << "hw-cpu-x86: cpu breakpoint trap unhandled" << endl;
+      break;
+      
+    case sidutil::cpu_trap_skip:
+    case sidutil::cpu_trap_handled:
+    case sidutil::cpu_trap_reissue:
+      break;
+      
+    default:
+      abort();
+    }
+  this->yield();
+  throw sidutil::cpu_exception();
+}
+
+void
+x86_cpu::step_insns ()
+{
+  try
+    {
+      if (!this->blocking_on_syscall)
+        bx_cpu.cpu_loop(1);
+      else
+        do_syscall();
+    }
+  catch (sidutil::cpu_exception& t)
+    {
+      this->yield();
+    }
+  
+  if (this->enable_step_trap_p) 
+    this->signal_trap (sidutil::cpu_trap_stepped);
+}
+
+void
+x86_cpu::reset ()
+{
+  bx_cpu.reset(BX_RESET_HARDWARE);
+
+  if (!in_hardware_mode)
+    enter_protected_mode();
+}
+
+void
+x86_cpu::flush_icache ()
+{
+  bx_cpu.invalidate_prefetch_q();
+}
+
+void
+x86_cpu::set_pc (sid::host_int_4 value)
+{
+  // FIXME: this should check if we're using the extended (32-bit)
+  // instruction pointer or the 16-bit one
+  bx_cpu.eip = value - bx_cpu.sregs[BX_SEG_REG_CS].cache.u.segment.base;
+}
+
+string
+x86_cpu::dbg_get_reg(unsigned int reg)
+{
+  string attr;
+  sid::host_int_4 val;
+  val = bx_cpu.dbg_get_reg(reg + 10);
+  
+  // Change to "target endian".
+  sid::little_int_4 v = val;
+  for (unsigned i = 0; i < 4; i++)
+    attr += v.read_byte (i);
+  
+  if (verbose_p)
+    cerr << "dbg_get_reg: reg = " << reg << endl;
+  
+  return attr;
+}
+
+sid::component::status
+x86_cpu::dbg_set_reg(unsigned int reg, const string &attr)
+{
+  // change from "target endian"
+  sid::little_int_4 v;
+  for (unsigned i = 0; i < 4; i++)
+    v.write_byte (i, attr[i]);
+  sid::host_int_4 val = v;
+  
+  if (verbose_p)
+    {
+      cerr << "dbg_set_reg: reg = " << reg;
+      fprintf(stderr, " val = %p\n", val);
+    }
+  
+  if(bx_cpu.dbg_set_reg(reg + 10, val))
+    return sid::component::ok;
+  else
+    return sid::component::bad_value;
+}
+
+void
+x86_cpu::interrupt(host_int_4 val)
+{
+  bx_cpu.set_INTR(val);
+}
+
+void
+x86_cpu::hold_request(host_int_4 val)
+{
+  bx_cpu.set_HRQ(val);
+}
+
+void
+x86_cpu::enable_a20(host_int_4 val)
+{
+  if (val)
+    {
+      _a20_enabled = true;
+      a20_mask   = 0xffffffff;
+    }
+  else
+    {
+      _a20_enabled = false;
+      a20_mask   = 0xffefffff;
+    }
+}
+
+host_int_4
+x86_cpu::a20_enabled(void)
+{
+  if(_a20_enabled)
+    return 1;
+  else
+    return 0;
+}
+
+bool
+x86_cpu::hardware_mode(void)
+{
+  return in_hardware_mode;
+}
+
+void
+x86_cpu::drive_interrupt_acknowledge_pin(void)
+{
+  interrupt_acknowledge_pin.drive(1);
+}
+
+host_int_1
+x86_cpu::interrupt_acknowledged(void)
+{
+  return interrupt_acknowledge_response_pin.sense();
+}
+
+void
+x86_cpu::drive_hold_acknowledge_pin(void)
+{
+  hold_acknowledge_pin.drive(1);
+}
+
+little_int_1
+x86_cpu::read_io_memory_1 (host_int_4 addr)
+{
+  little_int_1 val;
+  bus::status status;
+
+  status = io_memory_bus->read(addr, val);
+
+  if (status != bus::ok)
+    {
+      cerr << "[IOMEM ] operation: read_1" << endl;
+      cerr << "[IOMEM ] addr: " << setbase(16) << addr << setbase(10) << endl;
+      cerr << "[IOMEM ] val: " << setbase(16) << addr << setbase(10) << endl;
+      cerr << "[IOMEM ] status: " << (status == bus::misaligned ? "misaligned" :
+                                     (status == bus::unmapped ? "unmapped" : "unpermitted")) << endl;
+      //      exit(0);
+    }
+  else
+    {
+      return val;
+    }
+}
+
+void
+x86_cpu::write_io_memory_1 (host_int_4 addr, little_int_1 value)
+{
+  bus::status status;
+
+  status = io_memory_bus->write(addr, value);
+
+  if (status != bus::ok)
+    {
+      cerr << "[IOMEM ] operation: write_1" << endl;
+      cerr << "[IOMEM ] addr: " << setbase(16) << addr << setbase(10) << endl;
+      cerr << "[IOMEM ] val: " << setbase(16) << value << setbase(10) << endl;
+      cerr << "[IOMEM ] status: " << (status == bus::misaligned ? "misaligned" :
+                                      (status == bus::unmapped ? "unmapped" : "unpermitted")) << endl;
+      //      exit(0);
+    }
+}
+
+little_int_2
+x86_cpu::read_io_memory_2 (host_int_4 addr)
+{
+  little_int_2 val;
+  bus::status status;
+
+  status = io_memory_bus->read(addr, val);
+
+  if (status != bus::ok)
+    {
+      cerr << "[IOMEM ] operation: read_2" << endl;
+      cerr << "[IOMEM ] addr: " << setbase(16) << addr << setbase(10) << endl;
+      cerr << "[IOMEM ] val: " << setbase(16) << addr << setbase(10) << endl;
+      cerr << "[IOMEM ] status: " << (status == bus::misaligned ? "misaligned" :
+                                     (status == bus::unmapped ? "unmapped" : "unpermitted")) << endl;
+      //      exit(0);
+    }
+  else
+    {
+      return val;
+    }
+}
+
+void
+x86_cpu::write_io_memory_2 (host_int_4 addr, little_int_2 value)
+{
+  bus::status status;
+  
+  status = io_memory_bus->write(addr, value);
+  
+  if (status != bus::ok)
+    {
+      cerr << "[IOMEM ] operation: write_2" << endl;
+      cerr << "[IOMEM ] addr: " << setbase(16) << addr << setbase(10) << endl;
+      cerr << "[IOMEM ] val: " << setbase(16) << value << setbase(10) << endl;
+      cerr << "[IOMEM ] status: " << (status == bus::misaligned ? "misaligned" :
+                                      (status == bus::unmapped ? "unmapped" : "unpermitted")) << endl;
+      //      exit(0);
+    }
+}
+
+little_int_4
+x86_cpu::read_io_memory_4 (host_int_4 addr)
+{
+  little_int_4 val;
+  bus::status status;
+
+  status = io_memory_bus->read(addr, val);
+
+  if (status != bus::ok)
+    {
+      cerr << "[IOMEM ] operation: read_4" << endl;
+      cerr << "[IOMEM ] addr: " << setbase(16) << addr << setbase(10) << endl;
+      cerr << "[IOMEM ] val: " << setbase(16) << addr << setbase(10) << endl;
+      cerr << "[IOMEM ] status: " << (status == bus::misaligned ? "misaligned" :
+                                     (status == bus::unmapped ? "unmapped" : "unpermitted")) << endl;
+      //      exit(0);
+    }
+  else
+    {
+      return val;
+    }
+}
+
+void
+x86_cpu::write_io_memory_4 (host_int_4 addr, little_int_4 value)
+{
+  bus::status status;
+  
+  status = io_memory_bus->write(addr, value);
+  
+  if (status != bus::ok)
+    {
+      cerr << "[IOMEM ] operation: write_4" << endl;
+      cerr << "[IOMEM ] addr: " << setbase(16) << addr << setbase(10) << endl;
+      cerr << "[IOMEM ] val: " << setbase(16) << value << setbase(10) << endl;
+      cerr << "[IOMEM ] status: " << (status == bus::misaligned ? "misaligned" :
+                                      (status == bus::unmapped ? "unmapped" : "unpermitted")) << endl;
+      //      exit(0);
+    }
+}
+
diff --git a/sid/component/bochs/cpu/sid-x86-cpu-wrapper.h b/sid/component/bochs/cpu/sid-x86-cpu-wrapper.h
new file mode 100644 (file)
index 0000000..9003030
--- /dev/null
@@ -0,0 +1,123 @@
+//  sid-x86-cpu-wrapper.h - class declaration for the sid x86 cpu component. -*- C++ -*-
+//
+//  Copyright (C) 2001 Red Hat.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+#ifndef __X86_H__
+#define __X86_H__ 1
+#include <sidcomp.h>
+#include <sidcpuutil.h>
+
+#include "bochs.h"
+#include "sid-bochs-memory.h"
+#include "cpu.h"
+
+#define X86_CPU_DEBUG 0
+
+using sid::component;
+using sid::host_int_4;
+using sid::host_int_1;
+using sid::little_int_1;
+using sid::little_int_2;
+using sid::little_int_4;
+using sid::bus;
+using sidutil::callback_pin;
+using sidutil::output_pin;
+using sidutil::input_pin;
+
+class x86_cpu : public sidutil::basic_bi_endian_cpu
+{
+  friend void BX_CPU_C::INSB_YbDX(BxInstruction_t *i);
+  friend void BX_CPU_C::INSW_YvDX(BxInstruction_t *i);
+  friend void BX_CPU_C::OUTSB_DXXb(BxInstruction_t *i);
+  friend void BX_CPU_C::OUTSW_DXXv(BxInstruction_t *i);
+  friend Bit32u BX_CPU_C::inp32(Bit16u addr);
+  friend Bit16u BX_CPU_C::inp16(Bit16u addr);
+  friend Bit8u BX_CPU_C::inp8(Bit16u addr);
+  friend void BX_CPU_C::outp32(Bit16u addr, Bit32u value);
+  friend void BX_CPU_C::outp16(Bit16u addr, Bit16u value);
+  friend void BX_CPU_C::outp8(Bit16u addr, Bit8u value);
+
+  friend void sid_bx_mem_c::read_physical(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data);
+  friend void sid_bx_mem_c::write_physical(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data);
+
+public:
+  x86_cpu ();
+  ~x86_cpu () throw () {}
+
+  void do_syscall();
+  void do_breakpoint();
+  
+  void step_insns ();
+  void reset ();
+  void flush_icache ();
+  void set_pc (sid::host_int_4 value);
+  string dbg_get_reg(unsigned int);
+  component::status dbg_set_reg(unsigned int, const string &);
+
+  void interrupt(host_int_4 val);
+  void hold_request(host_int_4 val);
+  void enable_a20(host_int_4 val);
+  host_int_4 a20_enabled(void);
+
+  bool hardware_mode(void);
+
+  void drive_hold_acknowledge_pin(void);
+
+  void drive_interrupt_acknowledge_pin(void);
+  host_int_1 interrupt_acknowledged(void);
+  
+  host_int_4 a20_mask;
+protected:
+  bx_cpu_c bx_cpu;
+  sid_bx_mem_c bx_mem;
+  
+  host_int_4 syscall_error;
+  
+  bool warnings_enabled;
+  bool blocking_on_syscall;
+  bool verbose_p;
+
+  callback_pin<x86_cpu> interrupt_pin;
+  output_pin interrupt_acknowledge_pin;
+  input_pin interrupt_acknowledge_response_pin;
+
+  output_pin hold_acknowledge_pin;
+
+  callback_pin<x86_cpu> hold_request_pin;
+
+  callback_pin<x86_cpu> enable_a20_pin;
+  output_pin a20_enabled_pin;
+
+  little_int_1 read_io_memory_1 (host_int_4 addr);
+  void write_io_memory_1 (host_int_4 addr, little_int_1 value);
+
+  little_int_2 read_io_memory_2 (host_int_4 addr);
+  void write_io_memory_2 (host_int_4 addr, little_int_2 value);
+
+  little_int_4 read_io_memory_4 (host_int_4 addr);
+  void write_io_memory_4 (host_int_4 addr, little_int_4 value);
+
+  bus *io_memory_bus;
+
+  bool in_hardware_mode;
+  bool _a20_enabled;
+
+  string memory_mode;
+
+  void enter_protected_mode();
+};
+#endif // __X86_H__
@@ -1,4 +1,4 @@
-//  x86-memory-modes.cc - set up protected mode. -*- C++ -*-
+//  sid-x86-memory-modes.cc - set up protected mode. -*- C++ -*-
 //
 //  Copyright (C) 2001 Red Hat.
 //
@@ -24,7 +24,7 @@
 //  License along with this library; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
-#include "x86.h"
+#include "sid-x86-cpu-wrapper.h"
 
 void x86_cpu::enter_protected_mode()
 {
diff --git a/sid/component/bochs/cpu/soft_int-sid.cc b/sid/component/bochs/cpu/soft_int-sid.cc
deleted file mode 100644 (file)
index 89a3f0a..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-//  Copyright (C) 2001  MandrakeSoft S.A.
-//
-//    MandrakeSoft S.A.
-//    43, rue d'Aboukir
-//    75002 Paris - France
-//    http://www.linux-mandrake.com/
-//    http://www.mandrakesoft.com/
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-
-
-
-
-
-
-
-#define NEED_CPU_REG_SHORTCUTS 1
-#include "bochs.h"
-#define LOG_THIS BX_CPU_THIS_PTR
-
-
-
-
-#if 0
-  void
-BX_CPU_C::BOUND_GvMa(BxInstruction_t *i)
-{
-#if BX_CPU_LEVEL < 2
-  BX_PANIC(("BOUND_GvMa: not supported on 8086!\n"));
-#else
-
-  if (i->mod == 0xc0) {
-    /* undefined opcode exception */
-    BX_PANIC(("bound: op2 must be mem ref\n"));
-    UndefinedOpcode(i);
-    }
-
-  if (i->os_32) {
-    Bit32s bound_min, bound_max;
-    Bit32s op1_32;
-
-    op1_32 = BX_READ_32BIT_REG(i->nnn);
-
-    read_virtual_dword(i->seg, i->rm_addr, (Bit32u *) &bound_min);
-    read_virtual_dword(i->seg, i->rm_addr+4, (Bit32u *) &bound_max);
-
-    /* ??? */
-    if ( (op1_32 < bound_min) || (op1_32 > bound_max) ) {
-      BX_INFO(("BOUND: fails bounds test\n"));
-      exception(5, 0, 0);
-      }
-    }
-  else {
-    Bit16s bound_min, bound_max;
-    Bit16s op1_16;
-
-    op1_16 = BX_READ_16BIT_REG(i->nnn);
-
-    read_virtual_word(i->seg, i->rm_addr, (Bit16u *) &bound_min);
-    read_virtual_word(i->seg, i->rm_addr+2, (Bit16u *) &bound_max);
-
-    /* ??? */
-    if ( (op1_16 < bound_min) || (op1_16 > bound_max) ) {
-      BX_INFO(("BOUND: fails bounds test\n"));
-      exception(5, 0, 0);
-      }
-    }
-
-#endif
-}
-
-  void
-BX_CPU_C::INT1(BxInstruction_t *i)
-{
-  // This is an undocumented instrucion (opcode 0xf1)
-  // which is useful for an ICE system.
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_int;
-#endif
-
-  interrupt(1, 1, 0, 0);
-  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_INT,
-                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
-                      BX_CPU_THIS_PTR eip);
-}
-#endif
-
-  void
-sid_cpu_c::INT3(BxInstruction_t *i)
-{
-  // INT 3 is not IOPL sensitive
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_int;
-#endif
-
-//BX_PANIC(("INT3: bailing\n"));
-  interrupt(3, 1, 0, 0);
-  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_INT,
-                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
-                      BX_CPU_THIS_PTR eip);
-}
-
-
-  void
-sid_cpu_c::INT_Ib(BxInstruction_t *i)
-{
-  Bit8u imm8;
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_int;
-#endif
-
-  imm8 = i->Ib;
-
-  if (v8086_mode() && (IOPL<3)) {
-    //BX_INFO(("int_ib: v8086: IOPL<3\n"));
-    exception(BX_GP_EXCEPTION, 0, 0);
-    }
-
-#ifdef SHOW_EXIT_STATUS
-if ( (imm8 == 0x21) && (AH == 0x4c) ) {
-  BX_INFO(("INT 21/4C called AL=0x%02x, BX=0x%04x\n", (unsigned) AL, (unsigned) BX));
-  }
-#endif
-
-  interrupt(imm8, 1, 0, 0);
-  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_INT,
-                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
-                      BX_CPU_THIS_PTR eip);
-}
-#if 0
-
-  void
-BX_CPU_C::INTO(BxInstruction_t *i)
-{
-
-#if BX_DEBUGGER
-  BX_CPU_THIS_PTR show_flag |= Flag_int;
-#endif
-
-  /* ??? is this IOPL sensitive ? */
-  if (v8086_mode()) BX_PANIC(("soft_int: v8086 mode unsupported\n"));
-
-  if (get_OF()) {
-    interrupt(4, 1, 0, 0);
-    BX_INSTR_FAR_BRANCH(BX_INSTR_IS_INT,
-                        BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
-                        BX_CPU_THIS_PTR eip);
-    }
-}
-#endif
index 2bb59ba..fd4d5e4 100644 (file)
@@ -975,5 +975,4 @@ BX_CPU_C::get_SS_ESP_from_TSS(unsigned pl, Bit16u *ss, Bit32u *esp)
 }
 #endif
 
-
 #endif // BX_SUPPORT_TASKING
index 71f4fc4..170c37e 100644 (file)
@@ -284,7 +284,7 @@ BX_CPU_C::stack_return_to_v86(Bit32u new_eip, Bit32u raw_cs_selector, Bit32u fla
 }
 
   void
-BX_CPU_C::stack_return_from_v86(BxInstruction_t *i)
+BX_CPU_C::stack_return_from_v86(void)
 {
   BX_INFO(("stack_return_from_v86:\n"));
   v8086_message();
diff --git a/sid/component/bochs/cpu/x86.cc b/sid/component/bochs/cpu/x86.cc
deleted file mode 100644 (file)
index edecc7b..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-//  x86.cc - member function implementations for the x86 sid component. -*- C++ -*-
-//
-//  Copyright (C) 2001 Red Hat.
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-#include "x86.h"
-
-x86_cpu::x86_cpu () :
-    memory_mode("default"),
-    blocking_on_syscall(false),
-    verbose_p(false)
-{
-  bx_mem.sid_cpu = this;
-  bx_cpu.sid_cpu = this;
-  
-  bx_cpu.init(&bx_mem);
-
-  // set up registers for use by gloss component.
-  // see libgloss/i386/* for calling conventions
-  // and exception-sid.cc for handling of int 0x80
-  this->add_watchable_register (string("syscall-arg0"), &bx_cpu.gen_reg[0].erx);
-  this->add_watchable_register (string("syscall-arg1"), &bx_cpu.gen_reg[3].erx);
-  this->add_watchable_register (string("syscall-arg2"), &bx_cpu.gen_reg[1].erx);
-  this->add_watchable_register (string("syscall-arg3"), &bx_cpu.gen_reg[2].erx);
-  this->add_watchable_register (string("syscall-result"), &bx_cpu.gen_reg[0].erx);
-  
-  this->add_watchable_register (string("syscall-trap"), &bx_cpu.gen_reg[0].erx);    
-  this->add_watchable_register (string("syscall-error"), &syscall_error);
-
-  // set up debugging interface
-  // there are 16 integer registers
-  create_gdb_register_attrs (16, "4;5;8;9", & this->bx_cpu.eip);
-  
-  this->add_attribute ("enable-warnings?", & warnings_enabled, "setting");
-  this->add_attribute ("memory-mode", & memory_mode, "setting");
-  this->add_attribute("verbose?", &this->verbose_p, "setting");
-}
-
-void x86_cpu::do_syscall()
-{
-    sid::host_int_4 tempAX = bx_cpu.gen_reg[0].erx;
-    sid::host_int_4 tempBX = bx_cpu.gen_reg[3].erx;
-    sid::host_int_4 tempCX = bx_cpu.gen_reg[1].erx;
-    sid::host_int_4 tempDX = bx_cpu.gen_reg[2].erx;
-        
-    sidutil::cpu_trap_disposition whatnext = signal_trap(sidutil::cpu_trap_software, bx_cpu.gen_reg[0].erx);
-
-    switch (whatnext)
-    {
-      case sidutil::cpu_trap_unhandled:
-          cerr << "hw-cpu-x86: cpu syscall trap unhandled" << endl;
-          this->blocking_on_syscall = false;
-          return;
-      case sidutil::cpu_trap_reissue:
-          bx_cpu.gen_reg[0].erx = tempAX;
-          bx_cpu.gen_reg[3].erx = tempBX;
-          bx_cpu.gen_reg[1].erx = tempCX;
-          bx_cpu.gen_reg[2].erx = tempDX;
-          this->blocking_on_syscall = true;
-          return;
-      case sidutil::cpu_trap_skip:
-          /* fall-through */
-      case sidutil::cpu_trap_handled:
-          this->blocking_on_syscall = false;
-          return;
-      default:
-          abort ();
-    }
-    this->yield();
-    throw sidutil::cpu_exception();
-}
-
-void x86_cpu::do_breakpoint()
-{
-    sidutil::cpu_trap_disposition whatnext = signal_trap(sidutil::cpu_trap_breakpoint, 0);
-
-    switch (whatnext)
-    {
-      case sidutil::cpu_trap_unhandled:
-          cerr << "hw-cpu-x86: cpu breakpoint trap unhandled" << endl;
-          break;
-
-      case sidutil::cpu_trap_skip:
-      case sidutil::cpu_trap_handled:
-      case sidutil::cpu_trap_reissue:
-          break;
-
-      default:
-          abort();
-    }
-    this->yield();
-    throw sidutil::cpu_exception();
-}
-
-void x86_cpu::step_insns () {
-    try {
-        if (!this->blocking_on_syscall)
-            bx_cpu.cpu_loop(1);
-        else
-            do_syscall();
-    }
-    catch (sidutil::cpu_exception& t)
-    {
-        this->yield();
-    }
-
-    if (this->enable_step_trap_p) 
-        this->signal_trap (sidutil::cpu_trap_stepped);
-}
-
-void x86_cpu::reset () {
-    bx_cpu.reset(BX_RESET_HARDWARE);
-
-    enter_protected_mode();
-}
-
-void x86_cpu::flush_icache () {
-    bx_cpu.invalidate_prefetch_q();
-}
-
-void x86_cpu::set_pc (sid::host_int_4 value) {
-        // FIXME: this should check if we're using the extended (32-bit)
-        // instruction pointer or the 16-bit one
-    bx_cpu.eip = value - bx_cpu.sregs[BX_SEG_REG_CS].cache.u.segment.base;
-}
-
-string x86_cpu::dbg_get_reg(unsigned int reg)
-{
-    string attr;
-    sid::host_int_4 val;
-    val = bx_cpu.dbg_get_reg(reg + 10);
-
-    // Change to "target endian".
-    sid::little_int_4 v = val;
-    for (unsigned i = 0; i < 4; i++)
-        attr += v.read_byte (i);
-
-    if (verbose_p)
-        cerr << "dbg_get_reg: reg = " << reg << endl;
-    
-    return attr;
-}
-
-sid::component::status x86_cpu::dbg_set_reg(unsigned int reg, const string &attr)
-{
-    // change from "target endian"
-    sid::little_int_4 v;
-    for (unsigned i = 0; i < 4; i++)
-        v.write_byte (i, attr[i]);
-    sid::host_int_4 val = v;
-
-    if (verbose_p)
-    {
-        cerr << "dbg_set_reg: reg = " << reg;
-        fprintf(stderr, " val = %p\n", val);
-    }
-    
-    if(bx_cpu.dbg_set_reg(reg + 10, val))
-        return sid::component::ok;
-    else
-        return sid::component::bad_value;
-}
-
diff --git a/sid/component/bochs/cpu/x86.h b/sid/component/bochs/cpu/x86.h
deleted file mode 100644 (file)
index bd77b8f..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-//  x86.h - x86_cpu class declaration for the x86 sid component. -*- C++ -*-
-//
-//  Copyright (C) 2001 Red Hat.
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-#ifndef __X86_H__
-#define __X86_H__ 1
-#include "sidcomp.h"
-#include "sidcpuutil.h"
-#include "bochs.h"
-#include "memory-sid.h"
-#include "cpu-sid.h"
-
-#define X86_CPU_DEBUG 0
-
-class x86_cpu : public sidutil::basic_bi_endian_cpu {
-    friend void sid_mem_c::read_physical(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data);
-    friend void sid_mem_c::write_physical(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data);
-  public:
-    sid_cpu_c bx_cpu;
-    sid_mem_c bx_mem;
-
-    sid::host_int_4 syscall_error;
-
-    bool warnings_enabled;
-    bool blocking_on_syscall;
-    bool verbose_p;
-    
-    x86_cpu ();
-    ~x86_cpu () throw () {}
-
-    void do_syscall();
-    void do_breakpoint();
-
-    void step_insns ();
-    void reset ();
-    void flush_icache ();
-    void set_pc (sid::host_int_4 value);
-    string dbg_get_reg(unsigned int);
-    sid::component::status dbg_set_reg(unsigned int, const string &);
-  private:
-    string memory_mode;
-    
-    void enter_protected_mode();
-    
-};
-
-#endif // __X86_H__
diff --git a/sid/component/bochs/debug.h b/sid/component/bochs/debug.h
new file mode 100644 (file)
index 0000000..c612621
--- /dev/null
@@ -0,0 +1,413 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+// if including from C parser, need basic types etc
+#include "config.h"
+#if BX_DEBUGGER
+#include "osdep.h"
+#endif
+#if BX_USE_LOADER
+#include "loader_misc.h"
+void bx_dbg_loader(char *path, bx_loader_misc_t *misc_ptr);
+#endif
+
+#if BX_DBG_ICOUNT_SIZE == 32
+  typedef Bit32u bx_dbg_icount_t;
+#elif BX_DBG_ICOUNT_SIZE == 64
+  typedef Bit64u bx_dbg_icount_t;
+#else
+#  error "BX_DBG_ICOUNT_SIZE incorrect."
+#endif
+
+
+#define BX_DBG_NO_HANDLE 1000
+
+extern Bit32u dbg_cpu;
+
+unsigned long crc32(unsigned char *buf, int len);
+
+#if BX_DEBUGGER
+
+// some strict C declarations needed by the parser/lexer
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Flex defs
+extern int bxlex(void);
+extern char *bxtext;  // Using the pointer option rather than array
+extern int bxwrap(void);
+void bx_add_lex_input(char *buf);
+
+// Yacc defs
+extern int bxparse(void);
+extern void bxerror(char *s);
+
+typedef struct {
+  Bit64s from;
+  Bit64s to;
+} bx_num_range;
+#define EMPTY_ARG (-1)
+
+bx_num_range make_num_range (Bit64s from, Bit64s to);
+char* bx_dbg_symbolic_address(Bit32u context, Bit32u eip, Bit32u base);
+void bx_dbg_symbol_command(char* filename, Boolean global, Bit32u offset);
+void bx_dbg_trace_on_command(void);
+void bx_dbg_trace_off_command(void);
+void bx_dbg_ptime_command(void);
+void bx_dbg_timebp_command(Boolean absolute, Bit64u time);
+void bx_dbg_diff_memory(void);
+void bx_dbg_always_check(Bit32u page_start, Boolean on);
+void bx_dbg_sync_memory(Boolean set);
+void bx_dbg_sync_cpu(Boolean set);
+void bx_dbg_fast_forward(Bit32u num);
+void bx_dbg_info_address(Bit32u seg_reg_num, Bit32u offset);
+#define MAX_CONCURRENT_BPS 5
+extern int timebp_timer;
+extern Bit64u timebp_queue[MAX_CONCURRENT_BPS];
+extern int timebp_queue_size;
+void bx_dbg_record_command(char*);
+void bx_dbg_playback_command(char*);
+void bx_dbg_modebp_command(char*); /* BW */
+void bx_dbg_where_command(void);
+void bx_dbg_print_string_command(Bit32u addr);
+void bx_dbg_show_command(char*); /* BW */
+void enter_playback_entry();
+void bx_dbg_print_stack_command(int nwords);
+void bx_dbg_watch(int read, Bit32u address);
+void bx_dbg_unwatch(int read, Bit32u address);
+void bx_dbg_continue_command(void);
+void bx_dbg_stepN_command(bx_dbg_icount_t count);
+void bx_dbg_set_command(char *p1, char *p2, char *p3);
+void bx_dbg_del_breakpoint_command(unsigned handle);
+void bx_dbg_vbreakpoint_command(Boolean specific, Bit32u cs, Bit32u eip);
+void bx_dbg_lbreakpoint_command(Boolean specific, Bit32u laddress);
+void bx_dbg_pbreakpoint_command(Boolean specific, Bit32u paddress);
+void bx_dbg_info_bpoints_command(void);
+void bx_dbg_quit_command(void);
+void bx_dbg_info_program_command(void);
+void bx_dbg_info_registers_command(void);
+void bx_dbg_info_dirty_command(void);
+void bx_dbg_info_idt_command(bx_num_range);
+void bx_dbg_info_gdt_command(bx_num_range);
+void bx_dbg_info_ldt_command(bx_num_range);
+void bx_dbg_info_tss_command(bx_num_range);
+void bx_dbg_info_control_regs_command(void);
+void bx_dbg_info_linux_command(void);
+void bx_dbg_examine_command(char *command, char *format, Boolean format_passed,
+                    Bit32u addr, Boolean addr_passed, int simulator);
+void bx_dbg_setpmem_command(Bit32u addr, unsigned len, Bit32u val);
+void bx_dbg_set_symbol_command(char *symbol, Bit32u val);
+void bx_dbg_query_command(char *);
+void bx_dbg_take_command(char *, unsigned n);
+void bx_dbg_dump_cpu_command(void);
+void bx_dbg_set_cpu_command(void);
+void bx_dbg_disassemble_command(bx_num_range);
+void bx_dbg_instrument_command(char *);
+void bx_dbg_loader_command(char *);
+void bx_dbg_doit_command(unsigned);
+void bx_dbg_crc_command(Bit32u addr1, Bit32u addr2);
+void bx_dbg_maths_command(char *command, int data1, int data2);
+void bx_dbg_maths_expression_command(char *expr);
+void bx_dbg_v2l_command(unsigned seg_no, Bit32u offset);
+extern Boolean watchpoint_continue;
+void bx_dbg_linux_syscall ();
+
+#ifdef __cplusplus
+}
+#endif
+
+// the rest for C++
+#ifdef __cplusplus
+
+// (mch) Read/write watchpoint hack
+#define MAX_WRITE_WATCHPOINTS 16
+#define MAX_READ_WATCHPOINTS 16
+extern int num_write_watchpoints;
+extern Bit32u write_watchpoint[MAX_WRITE_WATCHPOINTS];
+extern int num_read_watchpoints;
+extern Bit32u read_watchpoint[MAX_READ_WATCHPOINTS];
+
+typedef enum {
+      STOP_NO_REASON = 0, STOP_TIME_BREAK_POINT, STOP_READ_WATCH_POINT, STOP_WRITE_WATCH_POINT, STOP_MAGIC_BREAK_POINT, STOP_TRACE, STOP_MODE_BREAK_POINT, STOP_CPU_HALTED
+} stop_reason_t;
+
+typedef enum {
+      BREAK_POINT_MAGIC, BREAK_POINT_READ, BREAK_POINT_WRITE, BREAK_POINT_TIME
+} break_point_t;
+#endif // __cplusplus
+#endif // BX_DEBUGGER
+#ifdef __cplusplus
+#define BX_DBG_REG_EAX          10
+#define BX_DBG_REG_ECX          11
+#define BX_DBG_REG_EDX          12
+#define BX_DBG_REG_EBX          13
+#define BX_DBG_REG_ESP          14
+#define BX_DBG_REG_EBP          15
+#define BX_DBG_REG_ESI          16
+#define BX_DBG_REG_EDI          17
+#define BX_DBG_REG_EIP          18
+#define BX_DBG_REG_EFLAGS       19
+#define BX_DBG_REG_CS           20
+#define BX_DBG_REG_SS           21
+#define BX_DBG_REG_DS           22
+#define BX_DBG_REG_ES           23
+#define BX_DBG_REG_FS           24
+#define BX_DBG_REG_GS           25
+#endif // __cplusplus
+#if BX_DEBUGGER
+#ifdef __cplusplus
+#define BX_DBG_PENDING_DMA 1
+#define BX_DBG_PENDING_IRQ 2
+
+
+
+
+void bx_dbg_exit(int code);
+#if BX_DBG_EXTENSIONS
+  int bx_dbg_extensions(char *command);
+#else
+#define bx_dbg_extensions(command) 0
+#endif
+
+
+//
+// code for guards...
+//
+
+#define BX_DBG_GUARD_INSTR_BEGIN   0x0001
+#define BX_DBG_GUARD_INSTR_END     0x0002
+#define BX_DBG_GUARD_EXCEP_BEGIN   0x0004
+#define BX_DBG_GUARD_EXCEP_END     0x0008
+#define BX_DBG_GUARD_INTER_BEGIN   0x0010
+#define BX_DBG_GUARD_INTER_END     0x0020
+#define BX_DBG_GUARD_INSTR_MAP     0x0040
+
+// following 3 go along with BX_DBG_GUARD_INSTR_BEGIN
+// to provide breakpointing
+#define BX_DBG_GUARD_IADDR_VIR     0x0080
+#define BX_DBG_GUARD_IADDR_LIN     0x0100
+#define BX_DBG_GUARD_IADDR_PHY     0x0200
+#define BX_DBG_GUARD_IADDR_ALL (BX_DBG_GUARD_IADDR_VIR | \
+                                BX_DBG_GUARD_IADDR_LIN | \
+                                BX_DBG_GUARD_IADDR_PHY)
+
+#define BX_DBG_GUARD_ICOUNT        0x0400
+#define BX_DBG_GUARD_CTRL_C        0x0800
+
+
+typedef struct {
+  unsigned long guard_for;
+
+  // instruction address breakpoints
+  struct {
+#if BX_DBG_SUPPORT_VIR_BPOINT
+    unsigned num_virtual;
+    struct {
+      Bit32u cs;  // only use 16 bits
+      Bit32u eip;
+      unsigned bpoint_id;
+      } vir[BX_DBG_MAX_VIR_BPOINTS];
+#endif
+
+#if BX_DBG_SUPPORT_LIN_BPOINT
+    unsigned num_linear;
+    struct {
+      Bit32u addr;
+      unsigned bpoint_id;
+      } lin[BX_DBG_MAX_LIN_BPOINTS];
+#endif
+
+#if BX_DBG_SUPPORT_PHY_BPOINT
+    unsigned num_physical;
+    struct {
+      Bit32u addr;
+      unsigned bpoint_id;
+      } phy[BX_DBG_MAX_PHY_BPOINTS];
+#endif
+    } iaddr;
+
+  bx_dbg_icount_t icount; // stop after completing this many instructions
+
+  // user typed Ctrl-C, requesting simulator stop at next convient spot
+  volatile Boolean interrupt_requested;
+
+  // booleans to control whether simulator should report events
+  // to debug controller
+  struct {
+   Boolean irq;
+   Boolean a20;
+   Boolean io;
+   Boolean ucmem;
+   Boolean dma;
+   } report;
+
+  struct {
+    Boolean irq;  // should process IRQs asynchronously
+    Boolean dma;  // should process DMAs asynchronously
+    } async;
+
+#define BX_DBG_ASYNC_PENDING_A20   0x01
+#define BX_DBG_ASYNC_PENDING_RESET 0x02
+#define BX_DBG_ASYNC_PENDING_NMI   0x04
+
+  // Asynchronous changes which are pending.  These are Q'd by
+  // the debugger, as the master simulator is notified of a pending
+  // async change.  At the simulator's next point, where it checks for
+  // such events, it notifies the debugger with acknowlegement.  This
+  // field contains a logically or'd list of all events which should
+  // be checked, and ack'd.
+  struct {
+    unsigned which; // logical OR of above constants
+    Boolean a20;
+    Boolean reset;
+    Boolean nmi;
+    } async_changes_pending;
+  } bx_guard_t;
+
+// working information for each simulator to update when a guard
+// is reached (found)
+typedef struct bx_guard_found_t {
+  unsigned long guard_found;
+  unsigned iaddr_index;
+  bx_dbg_icount_t icount; // number of completed instructions
+  Bit32u   cs;     // cs:eip and linear addr of instruction at guard point
+  Bit32u   eip;
+  Bit32u   laddr;
+  Boolean  is_32bit_code; // CS seg size at guard point
+  Boolean  ctrl_c; // simulator stopped due to Ctrl-C request
+  } bx_guard_found_t;
+
+extern bx_guard_t        bx_guard;
+
+
+
+
+
+int  bx_dbg_main(int argc, char *argv[]);
+void bx_dbg_user_input_loop(void);
+
+
+typedef struct {
+  Bit16u sel;
+  Bit32u des_l, des_h, valid;
+  } bx_dbg_sreg_t;
+
+typedef struct {
+    Bit32u eax;
+    Bit32u ebx;
+    Bit32u ecx;
+    Bit32u edx;
+    Bit32u ebp;
+    Bit32u esi;
+    Bit32u edi;
+    Bit32u esp;
+    Bit32u eflags;
+    Bit32u eip;
+    bx_dbg_sreg_t cs;
+    bx_dbg_sreg_t ss;
+    bx_dbg_sreg_t ds;
+    bx_dbg_sreg_t es;
+    bx_dbg_sreg_t fs;
+    bx_dbg_sreg_t gs;
+    bx_dbg_sreg_t ldtr;
+    bx_dbg_sreg_t tr;
+    struct { Bit32u base, limit; } gdtr;
+    struct { Bit32u base, limit; } idtr;
+    Bit32u dr0, dr1, dr2, dr3, dr6, dr7;
+    Bit32u tr3, tr4, tr5, tr6, tr7;
+    Bit32u cr0, cr1, cr2, cr3, cr4;
+    unsigned inhibit_mask;
+    } bx_dbg_cpu_t;
+
+
+
+
+typedef struct {
+  // call back functions specific to each simulator
+  Boolean (*setphymem)(Bit32u addr, unsigned len, Bit8u *buf);
+  Boolean (*getphymem)(Bit32u addr, unsigned len, Bit8u *buf);
+  void    (*xlate_linear2phy)(Bit32u linear, Bit32u *phy, Boolean *valid);
+  Boolean (*set_reg)(unsigned reg, Bit32u val);
+  Bit32u  (*get_reg)(unsigned reg);
+  Boolean (*get_sreg)(bx_dbg_sreg_t *sreg, unsigned sreg_no);
+  Boolean (*set_cpu)(bx_dbg_cpu_t *cpu);
+  Boolean (*get_cpu)(bx_dbg_cpu_t *cpu);
+  unsigned       dirty_page_tbl_size;
+  unsigned char *dirty_page_tbl;
+  void    (*atexit)(void);
+  unsigned (*query_pending)(void);
+  void     (*execute)(void);
+  void     (*take_irq)(void);
+  void     (*take_dma)(void);
+  void     (*reset_cpu)(unsigned source);
+  void     (*init_mem)(int size_in_bytes);
+  void     (*load_ROM)(const char *path, Bit32u romaddress);
+
+  // for asynchronous environment handling
+  void     (*set_A20)(unsigned val);
+  void     (*set_NMI)(unsigned val);
+  void     (*set_RESET)(unsigned val);
+  void     (*set_INTR)(unsigned val);
+  void     (*force_interrupt)(unsigned vector);
+
+#if BX_INSTRUMENTATION
+  void    (*instr_start)(void);
+  void    (*instr_stop)(void);
+  void    (*instr_reset)(void);
+  void    (*instr_print)(void);
+#endif
+#if BX_USE_LOADER
+  void    (*loader)(char *path, bx_loader_misc_t *misc_ptr);
+#endif
+  Boolean (*crc32)(unsigned long (*f)(unsigned char *buf, int len),
+                   Bit32u addr1, Bit32u addr2, Bit32u *crc);
+  } bx_dbg_callback_t;
+
+extern bx_dbg_callback_t bx_dbg_callback[BX_NUM_SIMULATORS];
+
+void BX_SIM1_INIT(bx_dbg_callback_t *, int argc, char *argv[]);
+#ifdef BX_SIM2_INIT
+void BX_SIM2_INIT(bx_dbg_callback_t *, int argc, char *argv[]);
+#endif
+
+
+void bx_dbg_dma_report(Bit32u addr, unsigned len, unsigned what, Bit32u val);
+void bx_dbg_iac_report(unsigned vector, unsigned irq);
+void bx_dbg_a20_report(unsigned val);
+void bx_dbg_io_report(Bit32u addr, unsigned size, unsigned op, Bit32u val);
+void bx_dbg_ucmem_report(Bit32u addr, unsigned size, unsigned op, Bit32u val);
+
+Bit8u   bx_dbg_ucmem_read(Bit32u addr);
+void    bx_dbg_ucmem_write(Bit32u addr, Bit8u value);
+void    bx_dbg_async_pin_request(unsigned what, Boolean val);
+void    bx_dbg_async_pin_ack(unsigned what, Boolean val);
+Bit32u  bx_dbg_inp(Bit16u addr, unsigned len);
+void    bx_dbg_outp(Bit16u addr, Bit32u value, unsigned len);
+void    bx_dbg_raise_HLDA(void);
+Bit8u   bx_dbg_IAC(void);
+void    bx_dbg_set_INTR(Boolean b);
+
+int bx_dbg_symbolic_output(void); /* BW */
+#endif // #ifdef __cplusplus
+#endif // #if BX_DEBUGGER
diff --git a/sid/component/bochs/dma/Makefile.am b/sid/component/bochs/dma/Makefile.am
new file mode 100644 (file)
index 0000000..f29bdfb
--- /dev/null
@@ -0,0 +1,11 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../cpu
+
+noinst_LTLIBRARIES = libdma.la
+
+libdma_la_SOURCES = sid-dma-wrapper.cc sid-dma-wrapper.h dma.cc dma.h
+
+libdma_la_LDFLAGS = -no-undefined
diff --git a/sid/component/bochs/dma/Makefile.in b/sid/component/bochs/dma/Makefile.in
new file mode 100644 (file)
index 0000000..2e3e760
--- /dev/null
@@ -0,0 +1,412 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+APIC_OBJS = @APIC_OBJS@
+AR = @AR@
+AS = @AS@
+AS_DYNAMIC_INCS = @AS_DYNAMIC_INCS@
+AS_DYNAMIC_OBJS = @AS_DYNAMIC_OBJS@
+BX_LOADER_OBJS = @BX_LOADER_OBJS@
+BX_SPLIT_HD_SUPPORT = @BX_SPLIT_HD_SUPPORT@
+CC = @CC@
+CDROM_OBJS = @CDROM_OBJS@
+CD_UP_ONE = @CD_UP_ONE@
+CD_UP_TWO = @CD_UP_TWO@
+CFP = @CFP@
+COMMAND_SEPARATOR = @COMMAND_SEPARATOR@
+CPP_SUFFIX = @CPP_SUFFIX@
+CXX = @CXX@
+CXXFP = @CXXFP@
+DASH = @DASH@
+DEBUGGER_VAR = @DEBUGGER_VAR@
+DISASM_VAR = @DISASM_VAR@
+DLLTOOL = @DLLTOOL@
+DYNAMIC_VAR = @DYNAMIC_VAR@
+EXE = @EXE@
+EXEEXT = @EXEEXT@
+EXTERNAL_DEPENDENCY = @EXTERNAL_DEPENDENCY@
+FPU_GLUE_OBJ = @FPU_GLUE_OBJ@
+FPU_VAR = @FPU_VAR@
+GUI_LINK_OPTS = @GUI_LINK_OPTS@
+GUI_LINK_OPTS_TERM = @GUI_LINK_OPTS_TERM@
+GUI_OBJS = @GUI_OBJS@
+GZIP = @GZIP@
+INLINE_VAR = @INLINE_VAR@
+INSTRUMENT_DIR = @INSTRUMENT_DIR@
+INSTRUMENT_VAR = @INSTRUMENT_VAR@
+IOAPIC_OBJS = @IOAPIC_OBJS@
+IODEV_LIB_VAR = @IODEV_LIB_VAR@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LINK = @LINK@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKELIB = @MAKELIB@
+NE2K_OBJS = @NE2K_OBJS@
+NM = @NM@
+NONINLINE_VAR = @NONINLINE_VAR@
+OBJDUMP = @OBJDUMP@
+OFP = @OFP@
+PACKAGE = @PACKAGE@
+PCI_OBJ = @PCI_OBJ@
+PRIMARY_TARGET = @PRIMARY_TARGET@
+RANLIB = @RANLIB@
+READLINE_LIB = @READLINE_LIB@
+RFB_LIBS = @RFB_LIBS@
+RMCOMMAND = @RMCOMMAND@
+SB16_OBJS = @SB16_OBJS@
+SLASH = @SLASH@
+SUFFIX_LINE = @SUFFIX_LINE@
+TAR = @TAR@
+VERSION = @VERSION@
+VIDEO_OBJS = @VIDEO_OBJS@
+sidtarget_arm = @sidtarget_arm@
+sidtarget_m32r = @sidtarget_m32r@
+sidtarget_m68k = @sidtarget_m68k@
+sidtarget_mips = @sidtarget_mips@
+sidtarget_ppc = @sidtarget_ppc@
+sidtarget_x86 = @sidtarget_x86@
+sidtarget_xstormy16 = @sidtarget_xstormy16@
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../cpu
+
+noinst_LTLIBRARIES = libdma.la
+
+libdma_la_SOURCES = sid-dma-wrapper.cc sid-dma-wrapper.h dma.cc dma.h
+
+libdma_la_LDFLAGS = -no-undefined
+mkinstalldirs = $(SHELL) $(top_srcdir)/../../config/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+LTLIBRARIES =  $(noinst_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libdma_la_LIBADD = 
+libdma_la_OBJECTS =  sid-dma-wrapper.lo dma.lo
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+GZIP_ENV = --best
+DEP_FILES =  .deps/dma.P .deps/sid-dma-wrapper.P
+SOURCES = $(libdma_la_SOURCES)
+OBJECTS = $(libdma_la_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .lo .o .s
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --foreign dma/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLTLIBRARIES:
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+
+distclean-noinstLTLIBRARIES:
+
+maintainer-clean-noinstLTLIBRARIES:
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libdma.la: $(libdma_la_OBJECTS) $(libdma_la_DEPENDENCIES)
+       $(CXXLINK)  $(libdma_la_LDFLAGS) $(libdma_la_OBJECTS) $(libdma_la_LIBADD) $(LIBS)
+.cc.o:
+       $(CXXCOMPILE) -c $<
+.cc.lo:
+       $(LTCXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = dma
+
+distdir: $(DISTFILES)
+       here=`cd $(top_builddir) && pwd`; \
+       top_distdir=`cd $(top_distdir) && pwd`; \
+       distdir=`cd $(distdir) && pwd`; \
+       cd $(top_srcdir) \
+         && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign dma/Makefile
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+       -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+       @echo '$(COMPILE) -c $<'; \
+       $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.c
+       @echo '$(LTCOMPILE) -c $<'; \
+       $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+
+%.o: %.cc
+       @echo '$(CXXCOMPILE) -c $<'; \
+       $(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.cc
+       @echo '$(LTCXXCOMPILE) -c $<'; \
+       $(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LTLIBRARIES)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLTLIBRARIES mostlyclean-compile \
+               mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+               mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLTLIBRARIES clean-compile clean-libtool \
+               clean-tags clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLTLIBRARIES distclean-compile \
+               distclean-libtool distclean-tags distclean-depend \
+               distclean-generic clean-am
+       -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLTLIBRARIES \
+               maintainer-clean-compile maintainer-clean-libtool \
+               maintainer-clean-tags maintainer-clean-depend \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \
+clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sid/component/bochs/dma/dma.cc b/sid/component/bochs/dma/dma.cc
new file mode 100644 (file)
index 0000000..1b9283f
--- /dev/null
@@ -0,0 +1,689 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+
+#include "bochs.h"
+#if BX_SUPPORT_SID
+#define LOG_THIS
+#else
+#define LOG_THIS bx_dma.
+#endif
+
+#define DMA_MODE_DEMAND  0
+#define DMA_MODE_SINGLE  1
+#define DMA_MODE_BLOCK   2
+#define DMA_MODE_CASCADE 3
+
+
+
+#if BX_SUPPORT_SID
+#include "sid-dma-wrapper.h"
+#else
+bx_dma_c bx_dma;
+#endif
+#if BX_USE_DMA_SMF
+#define this (&bx_dma)
+#endif
+
+
+
+bx_dma_c::bx_dma_c(void)
+{
+#if BX_SUPPORT_SID
+  bx_dbg.dma = 1;
+#endif
+       setprefix("[DMA ]");
+       settype(DMALOG);
+       BX_DEBUG(("Init.\n"));
+}
+
+bx_dma_c::~bx_dma_c(void)
+{
+       BX_DEBUG(("Exit.\n"));
+}
+
+
+#if BX_SUPPORT_SID
+void
+bx_dma_c::init(dma *dma_comp)
+#else
+  void
+bx_dma_c::init(bx_devices_c *d)
+#endif
+{
+  unsigned c;
+
+#if BX_SUPPORT_SID==0
+  BX_DMA_THIS devices = d;
+
+  /* 8237 DMA controller */
+
+  // 0000..000F
+  unsigned i;
+  for (i=0x0000; i<=0x000F; i++) {
+    BX_DMA_THIS devices->register_io_read_handler(this, read_handler,
+                                        i, "DMA controller");
+    BX_DMA_THIS devices->register_io_write_handler(this, write_handler,
+                                        i, "DMA controller");
+    }
+
+  // 00081..008D
+  for (i=0x0081; i<=0x008D; i++) {
+    BX_DMA_THIS devices->register_io_read_handler(this, read_handler,
+                                        i, "DMA controller");
+    BX_DMA_THIS devices->register_io_write_handler(this, write_handler,
+                                        i, "DMA controller");
+    }
+
+  // 0008F..008F
+  for (i=0x008F; i<=0x008F; i++) {
+    BX_DMA_THIS devices->register_io_read_handler(this, read_handler,
+                                        i, "DMA controller");
+    BX_DMA_THIS devices->register_io_write_handler(this, write_handler,
+                                        i, "DMA controller");
+    }
+
+  // 000C0..00DE
+  for (i=0x00C0; i<=0x00DE; i++) {
+    BX_DMA_THIS devices->register_io_read_handler(this, read_handler,
+                                        i, "DMA controller");
+    BX_DMA_THIS devices->register_io_write_handler(this, write_handler,
+                                        i, "DMA controller");
+    }
+#endif
+
+
+  BX_DMA_THIS s.mask[0] = 1; // channel 0 masked
+  BX_DMA_THIS s.mask[1] = 1; // channel 1 masked
+  BX_DMA_THIS s.mask[2] = 1; // channel 2 masked
+  BX_DMA_THIS s.mask[3] = 1; // channel 3 masked
+
+  BX_DMA_THIS s.flip_flop = 0; /* cleared */
+  BX_DMA_THIS s.status_reg = 0; // no requests, no terminal counts reached
+  for (c=0; c<4; c++) {
+    BX_DMA_THIS s.chan[c].mode.mode_type = 0;         // demand mode
+    BX_DMA_THIS s.chan[c].mode.address_decrement = 0; // address increment
+    BX_DMA_THIS s.chan[c].mode.autoinit_enable = 0;   // autoinit disable
+    BX_DMA_THIS s.chan[c].mode.transfer_type = 0;     // verify
+    BX_DMA_THIS s.chan[c].base_address = 0;
+    BX_DMA_THIS s.chan[c].current_address = 0;
+    BX_DMA_THIS s.chan[c].base_count = 0;
+    BX_DMA_THIS s.chan[c].current_count = 0;
+    BX_DMA_THIS s.chan[c].page_reg = 0;
+    }
+#if BX_SUPPORT_SID
+  dma_component = dma_comp;
+#endif
+}
+
+
+
+  // index to find channel from register number (only [0],[1],[2],[6] used)
+  Bit8u channelindex[7] = {2, 3, 1, 0, 0, 0, 0};
+
+
+  // static IO port read callback handler
+  // redirects to non-static class handler to avoid virtual functions
+
+  Bit32u
+bx_dma_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
+{
+#if !BX_USE_DMA_SMF
+  bx_dma_c *class_ptr = (bx_dma_c *) this_ptr;
+
+  return( class_ptr->read(address, io_len) );
+}
+
+  /* 8237 DMA controller */
+  Bit32u
+bx_dma_c::read( Bit32u   address, unsigned io_len)
+{
+#else
+  UNUSED(this_ptr);
+#endif  // !BX_USE_DMA_SMF
+
+  Bit8u retval;
+  Bit8u channel;
+
+  if (io_len > 1) {
+    BX_PANIC(("dma: io read from address %08x, len=%u\n",
+             (unsigned) address, (unsigned) io_len));
+    }
+
+  if (bx_dbg.dma)
+    BX_INFO(("dma: read addr=%04x\n", (unsigned) address));
+
+#if BX_DMA_FLOPPY_IO < 1
+  /* if we're not supporting DMA/floppy IO just return a bogus value */
+  return(0xff);
+#endif
+
+  switch (address) {
+    case 0x00: /* DMA-1 current address, channel 0 */
+    case 0x02: /* DMA-1 current address, channel 1 */
+    case 0x04: /* DMA-1 current address, channel 2 */
+    case 0x06: /* DMA-1 current address, channel 3 */
+      channel = address >> 1;
+      if (BX_DMA_THIS s.flip_flop==0) {
+        BX_DMA_THIS s.flip_flop = !BX_DMA_THIS s.flip_flop;
+        return(BX_DMA_THIS s.chan[channel].current_address & 0xff);
+        }
+      else {
+        BX_DMA_THIS s.flip_flop = !BX_DMA_THIS s.flip_flop;
+        return(BX_DMA_THIS s.chan[channel].current_address >> 8);
+        }
+
+    case 0x01: /* DMA-1 current count, channel 0 */
+    case 0x03: /* DMA-1 current count, channel 1 */
+    case 0x05: /* DMA-1 current count, channel 2 */
+    case 0x07: /* DMA-1 current count, channel 3 */
+      channel = address >> 1;
+      if (BX_DMA_THIS s.flip_flop==0) {
+        BX_DMA_THIS s.flip_flop = !BX_DMA_THIS s.flip_flop;
+        return(BX_DMA_THIS s.chan[channel].current_count & 0xff);
+        }
+      else {
+        BX_DMA_THIS s.flip_flop = !BX_DMA_THIS s.flip_flop;
+        return(BX_DMA_THIS s.chan[channel].current_count >> 8);
+        }
+
+    case 0x08: // DMA-1 Status Register
+      // bit 7: 1 = channel 3 request
+      // bit 6: 1 = channel 2 request
+      // bit 5: 1 = channel 1 request
+      // bit 4: 1 = channel 0 request
+      // bit 3: 1 = channel 3 has reached terminal count
+      // bit 2: 1 = channel 2 has reached terminal count
+      // bit 1: 1 = channel 1 has reached terminal count
+      // bit 0: 1 = channel 0 has reached terminal count
+      // reading this register clears lower 4 bits (hold flags)
+      retval = BX_DMA_THIS s.status_reg;
+      BX_DMA_THIS s.status_reg &= 0xf0;
+      return(retval);
+      break;
+    case 0x0d: // dma-1: temporary register
+      BX_PANIC(("dma-1: read of temporary register\n"));
+      // Note: write to 0x0D clears temporary register
+      return(0);
+      break;
+
+    case 0x0081: // DMA-1 page register, channel 2
+    case 0x0082: // DMA-1 page register, channel 3
+    case 0x0083: // DMA-1 page register, channel 1
+    case 0x0087: // DMA-1 page register, channel 0
+      channel = channelindex[address - 0x81];
+      return( BX_DMA_THIS s.chan[channel].page_reg );
+
+    case 0x0084: // ???
+      return(0);
+
+    case 0x0089: // DMA-2 page register, channel 6
+    case 0x008a: // DMA-2 page register, channel 7
+    case 0x008b: // DMA-2 page register, channel 5
+    case 0x008f: // DMA-2 page register, channel 4
+      channel = channelindex[address - 0x89] + 4;
+      BX_INFO(("dma: read: unsupported address=%04x (channel %d)\n", 
+               (unsigned) address, channel));
+      return( 0x00 );
+
+    case 0x00c0:
+    case 0x00c2:
+    case 0x00c4:
+    case 0x00c6:
+    case 0x00c8:
+    case 0x00ca:
+    case 0x00cc:
+    case 0x00ce:
+    case 0x00d0:
+    case 0x00d2:
+    case 0x00d4:
+    case 0x00d6:
+    case 0x00d8:
+    case 0x00da:
+    case 0x00dc:
+    case 0x00de:
+      BX_INFO(("dma: read: unsupported address=%04x\n", (unsigned) address));
+      return(0x0000);
+      break;
+
+    default:
+      BX_PANIC(("dma: read: unsupported address=%04x\n", (unsigned) address));
+      return(0);
+    }
+}
+
+
+  // static IO port write callback handler
+  // redirects to non-static class handler to avoid virtual functions
+
+  void
+bx_dma_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
+{
+#if !BX_USE_DMA_SMF
+  bx_dma_c *class_ptr = (bx_dma_c *) this_ptr;
+
+  class_ptr->write(address, value, io_len);
+}
+
+
+  /* 8237 DMA controller */
+  void
+bx_dma_c::write(Bit32u   address, Bit32u   value, unsigned io_len)
+{
+#else
+  UNUSED(this_ptr);
+#endif  // !BX_USE_DMA_SMF
+  Bit8u set_mask_bit;
+  Bit8u channel;
+
+  if (io_len > 1) {
+    if ( (io_len == 2) && (address == 0x0b) ) {
+#if BX_USE_DMA_SMF
+      BX_DMA_THIS write_handler(NULL, address,   value & 0xff, 1);
+      BX_DMA_THIS write_handler(NULL, address+1, value >> 8,   1);
+#else
+      BX_DMA_THIS write(address,   value & 0xff, 1);
+      BX_DMA_THIS write(address+1, value >> 8,   1);
+#endif
+      return;
+      }
+
+    BX_PANIC(("dma: io write to address %08x, len=%u\n",
+             (unsigned) address, (unsigned) io_len));
+    }
+
+  if (bx_dbg.dma)
+    BX_INFO(("\ndma: write: address=%04x value=%02x\n",
+      (unsigned) address, (unsigned) value));
+
+#if BX_DMA_FLOPPY_IO < 1
+  /* if we're not supporting DMA/floppy IO just return */
+  return;
+#endif
+
+  switch (address) {
+    case 0x00:
+    case 0x02:
+    case 0x04:
+    case 0x06:
+      channel = address >> 1;
+      if (bx_dbg.dma)
+        BX_INFO(("  DMA-1 base and current address, channel %d\n", channel));
+      if (BX_DMA_THIS s.flip_flop==0) { /* 1st byte */
+        BX_DMA_THIS s.chan[channel].base_address = value;
+        BX_DMA_THIS s.chan[channel].current_address = value;
+        }
+      else { /* 2nd byte */
+        BX_DMA_THIS s.chan[channel].base_address |= (value << 8);
+        BX_DMA_THIS s.chan[channel].current_address |= (value << 8);
+        if (bx_dbg.dma) {
+          BX_INFO(("    base = %04x\n",
+            (unsigned) BX_DMA_THIS s.chan[channel].base_address));
+          BX_INFO(("    curr = %04x\n",
+            (unsigned) BX_DMA_THIS s.chan[channel].current_address));
+          }
+        }
+      BX_DMA_THIS s.flip_flop = !BX_DMA_THIS s.flip_flop;
+      return;
+      break;
+
+    case 0x01:
+    case 0x03:
+    case 0x05:
+    case 0x07:
+      channel = address >> 1;
+      if (bx_dbg.dma)
+        BX_INFO(("  DMA-1 base and current count, channel %d\n", channel));
+      if (BX_DMA_THIS s.flip_flop==0) { /* 1st byte */
+        BX_DMA_THIS s.chan[channel].base_count = value;
+        BX_DMA_THIS s.chan[channel].current_count = value;
+        }
+      else { /* 2nd byte */
+        BX_DMA_THIS s.chan[channel].base_count |= (value << 8);
+        BX_DMA_THIS s.chan[channel].current_count |= (value << 8);
+        if (bx_dbg.dma) {
+          BX_INFO(("    base = %04x\n",
+            (unsigned) BX_DMA_THIS s.chan[channel].base_count));
+          BX_INFO(("    curr = %04x\n",
+            (unsigned) BX_DMA_THIS s.chan[channel].current_count));
+          }
+        }
+      BX_DMA_THIS s.flip_flop = !BX_DMA_THIS s.flip_flop;
+      return;
+      break;
+
+    case 0x08: /* DMA-1: command register */
+      if (value != 0x04)
+        BX_INFO(("DMA: write to 0008: value(%02xh) not 04h\n",
+          (unsigned) value));
+      BX_DMA_THIS s.command_reg = value;
+      return;
+      break;
+
+    case 0x09: // DMA-1: request register
+      BX_INFO(("DMA-1: write to request register (%02x)\n", (unsigned) value));
+      // note: write to 0x0d clears this register
+      if (value & 0x04) {
+        // set request bit
+        }
+      else {
+        Bit8u channel;
+
+        // clear request bit
+        channel = value & 0x03;
+        BX_DMA_THIS s.status_reg &= ~(1 << (channel+4));
+        BX_INFO(("dma-1: cleared request bit for channel %u\n", (unsigned) channel));
+        }
+      return;
+      break;
+
+    case 0x0a:
+      set_mask_bit = value & 0x04;
+      channel = value & 0x03;
+      BX_DMA_THIS s.mask[channel] = (set_mask_bit > 0);
+      if (bx_dbg.dma)
+        BX_INFO(("DMA1: set_mask_bit=%u, channel=%u, mask now=%02xh\n",
+          (unsigned) set_mask_bit, (unsigned) channel, (unsigned) BX_DMA_THIS s.mask[channel]));
+      return;
+      break;
+
+    case 0x0b: /* dma-1 mode register */
+      channel = value & 0x03;
+      BX_DMA_THIS s.chan[channel].mode.mode_type = (value >> 6) & 0x03;
+      BX_DMA_THIS s.chan[channel].mode.address_decrement = (value >> 5) & 0x01;
+      BX_DMA_THIS s.chan[channel].mode.autoinit_enable = (value >> 4) & 0x01;
+      BX_DMA_THIS s.chan[channel].mode.transfer_type = (value >> 2) & 0x03;
+//BX_INFO(("DMA1: mode register[%u] = %02x\n",
+//(unsigned) channel, (unsigned) value));
+      if (bx_dbg.dma)
+        BX_INFO(("DMA1: mode register[%u] = %02x\n",
+          (unsigned) channel, (unsigned) value));
+      return;
+      break;
+
+    case 0x0c: /* dma-1 clear byte flip/flop */
+      if (bx_dbg.dma)
+        BX_INFO(("DMA1: clear flip/flop\n"));
+      BX_DMA_THIS s.flip_flop = 0;
+      return;
+      break;
+
+    case 0x0d: // dma-1: master disable
+      /* ??? */
+      BX_INFO(("dma: master disable\n"));
+      // writing any value to this port resets DMA controller 1
+      // same action as a hardware reset
+      // mask register is set (chan 0..3 disabled)
+      // command, status, request, temporary, and byte flip-flop are all cleared
+      BX_DMA_THIS s.mask[0] = 1;
+      BX_DMA_THIS s.mask[1] = 1;
+      BX_DMA_THIS s.mask[2] = 1;
+      BX_DMA_THIS s.mask[3] = 1;
+      BX_DMA_THIS s.command_reg = 0;
+      BX_DMA_THIS s.status_reg = 0;
+      BX_DMA_THIS s.request_reg = 0;
+      BX_DMA_THIS s.temporary_reg = 0;
+      BX_DMA_THIS s.flip_flop = 0;
+      return;
+      break;
+
+    case 0x0e: // dma-1: clear mask register
+      BX_INFO(("dma-1: clear mask register\n"));
+      BX_DMA_THIS s.mask[0] = 0;
+      BX_DMA_THIS s.mask[1] = 0;
+      BX_DMA_THIS s.mask[2] = 0;
+      BX_DMA_THIS s.mask[3] = 0;
+      return;
+      break;
+
+    case 0x0f: // dma-1: write all mask bits
+      BX_INFO(("dma-1: write all mask bits\n"));
+      BX_DMA_THIS s.mask[0] = value & 0x01; value >>= 1;
+      BX_DMA_THIS s.mask[1] = value & 0x01; value >>= 1;
+      BX_DMA_THIS s.mask[2] = value & 0x01; value >>= 1;
+      BX_DMA_THIS s.mask[3] = value & 0x01;
+      return;
+      break;
+
+    case 0x81: /* dma page register, channel 2 */
+    case 0x82: /* dma page register, channel 3 */
+    case 0x83: /* dma page register, channel 1 */
+    case 0x87: /* dma page register, channel 0 */
+      /* address bits A16-A23 for DMA channel */
+      channel = channelindex[address - 0x81];
+      BX_DMA_THIS s.chan[channel].page_reg = value;
+      if (bx_dbg.dma)
+        BX_INFO(("DMA1: page register %d = %02x\n", channel, (unsigned) value));
+      return;
+      break;
+
+    case 0x0084: // ???
+      return;
+      break;
+
+    //case 0xd0: /* DMA-2 command register */
+    //  if (value != 0x04)
+    //    BX_INFO(("DMA2: write command register: value(%02xh)!=04h\n",
+    //      (unsigned) value));
+    //  return;
+    //  break;
+
+    case 0x00c0:
+    case 0x00c2:
+    case 0x00c4:
+    case 0x00c6:
+    case 0x00c8:
+    case 0x00ca:
+    case 0x00cc:
+    case 0x00ce:
+    case 0x00d0:
+    case 0x00d2:
+    case 0x00d4:
+    case 0x00d6:
+    case 0x00d8:
+    case 0x00da:
+    case 0x00dc:
+    case 0x00de:
+      BX_INFO(("DMA(ignored): write: %04xh = %04xh\n",
+        (unsigned) address, (unsigned) value));
+      return;
+      break;
+
+
+    default:
+      BX_INFO(("DMA(ignored): write: %04xh = %02xh\n",
+        (unsigned) address, (unsigned) value));
+    }
+}
+
+  void
+bx_dma_c::DRQ(unsigned channel, Boolean val)
+{
+  Bit32u dma_base, dma_roof;
+
+#if BX_SUPPORT_SB16
+  if ( (channel != 2) && (channel != (unsigned) BX_SB16_DMAL) )
+    BX_PANIC(("bx_dma_c::DRQ(): channel %d != 2 or %d (SB16) (\n",
+            channel, BX_SB16_DMAL));
+#else
+  if ( channel != 2 )
+    BX_PANIC(("bx_dma_c::DRQ(): channel %d != 2\n",
+            channel));
+#endif
+  if (!val) {
+    //BX_INFO(("bx_dma_c::DRQ(): val == 0\n"));
+    // clear bit in status reg
+    // deassert HRQ if not pending DRQ's ?
+    // etc.
+    BX_DMA_THIS s.status_reg &= ~(1 << (channel+4));
+    return;
+    }
+
+#if 0
+  BX_INFO(("BX_DMA_THIS s.mask[2]: %02x\n", (unsigned) BX_DMA_THIS s.mask[2]));
+  BX_INFO(("BX_DMA_THIS s.flip_flop: %u\n", (unsigned) BX_DMA_THIS s.flip_flop));
+  BX_INFO(("BX_DMA_THIS s.status_reg: %02x\n", (unsigned) BX_DMA_THIS s.status_reg));
+  BX_INFO(("mode_type: %02x\n", (unsigned) BX_DMA_THIS s.chan[channel].mode.mode_type));
+  BX_INFO(("address_decrement: %02x\n", (unsigned) BX_DMA_THIS s.chan[channel].mode.address_decrement));
+  BX_INFO(("autoinit_enable: %02x\n", (unsigned) BX_DMA_THIS s.chan[channel].mode.autoinit_enable));
+  BX_INFO(("transfer_type: %02x\n", (unsigned) BX_DMA_THIS s.chan[channel].mode.transfer_type));
+  BX_INFO((".base_address: %04x\n", (unsigned) BX_DMA_THIS s.chan[channel].base_address));
+  BX_INFO((".current_address: %04x\n", (unsigned) BX_DMA_THIS s.chan[channel].current_address));
+  BX_INFO((".base_count: %04x\n", (unsigned) BX_DMA_THIS s.chan[channel].base_count));
+  BX_INFO((".current_count: %04x\n", (unsigned) BX_DMA_THIS s.chan[channel].current_count));
+  BX_INFO((".page_reg: %02x\n", (unsigned) BX_DMA_THIS s.chan[channel].page_reg));
+#endif
+
+  BX_DMA_THIS s.status_reg |= (1 << (channel+4));
+
+  //  if (BX_DMA_THIS s.mask[channel])
+  //    BX_PANIC(("bx_dma_c::DRQ(): BX_DMA_THIS s.mask[] is set\n"));
+
+
+  if ( (BX_DMA_THIS s.chan[channel].mode.mode_type != DMA_MODE_SINGLE) &&
+       (BX_DMA_THIS s.chan[channel].mode.mode_type != DMA_MODE_DEMAND) )
+    BX_PANIC(("bx_dma_c::DRQ: mode_type(%02x) not handled\n",
+      (unsigned) BX_DMA_THIS s.chan[channel].mode.mode_type));
+  if (BX_DMA_THIS s.chan[channel].mode.address_decrement != 0)
+    BX_PANIC(("bx_dma_c::DRQ: address_decrement != 0\n"));
+  //if (BX_DMA_THIS s.chan[channel].mode.autoinit_enable != 0)
+  //  BX_PANIC(("bx_dma_c::DRQ: autoinit_enable != 0\n"));
+
+  dma_base = (BX_DMA_THIS s.chan[channel].page_reg << 16) | BX_DMA_THIS s.chan[channel].base_address;
+  dma_roof = dma_base + BX_DMA_THIS s.chan[channel].base_count;
+  if ( (dma_base & 0xffff0000) != (dma_roof & 0xffff0000) ) {
+BX_INFO(("dma_base = %08x\n", (unsigned) dma_base));
+BX_INFO(("dma_base_count = %08x\n", (unsigned) BX_DMA_THIS s.chan[channel].base_count));
+BX_INFO(("dma_roof = %08x\n", (unsigned) dma_roof));
+    BX_PANIC(("dma: DMA request outside 64k boundary\n"));
+    }
+
+
+  //BX_INFO(("DRQ set up for single mode, increment, auto-init disabled, write\n"));
+  // should check mask register VS DREQ's in status register here?
+  // assert Hold ReQuest line to CPU
+#if BX_SUPPORT_SID
+  dma_component->drive_hold_request_pin(1);
+#else
+  bx_pc_system.set_HRQ(1);
+#endif
+}
+
+#if BX_SUPPORT_SID
+void
+bx_dma_c::raise_HLDA(void)
+#else
+  void
+bx_dma_c::raise_HLDA(bx_pc_system_c *pc_sys)
+#endif
+{
+  unsigned channel;
+  Bit32u phy_addr;
+  Boolean count_expired = 0;
+
+  // find highest priority channel
+  for (channel=0; channel<4; channel++) {
+    if ( (BX_DMA_THIS s.status_reg & (1 << (channel+4))) &&
+         (BX_DMA_THIS s.mask[channel]==0) ) {
+      break;
+      }
+    }
+  if (channel >= 4) {
+       // don't panic, just wait till they're unmasked
+    //    BX_PANIC(("hlda: no unmasked requests\n"));
+    return;
+    }
+
+  //BX_INFO(("hlda: OK in response to DRQ(%u)\n", (unsigned) channel));
+  phy_addr = (BX_DMA_THIS s.chan[channel].page_reg << 16) |
+             BX_DMA_THIS s.chan[channel].current_address;
+
+#if BX_SUPPORT_SID==0
+  bx_pc_system.set_DACK(channel, 1);
+#endif
+  // check for expiration of count, so we can signal TC and DACK(n)
+  // at the same time.
+  if (BX_DMA_THIS s.chan[channel].mode.address_decrement==0) {
+    // address increment
+    BX_DMA_THIS s.chan[channel].current_address++;
+    BX_DMA_THIS s.chan[channel].current_count--;
+    if (BX_DMA_THIS s.chan[channel].current_count == 0xffff) 
+      if (BX_DMA_THIS s.chan[channel].mode.autoinit_enable == 0) {
+       // count expired, done with transfer
+       // assert TC, deassert HRQ & DACK(n) lines
+       BX_DMA_THIS s.status_reg |= (1 << channel); // hold TC in status reg
+#if BX_SUPPORT_SID
+        dma_component->drive_terminal_count_pin(1);
+#else
+       bx_pc_system.set_TC(1);
+#endif
+       count_expired = 1;
+      } else {
+       // count expired, but in autoinit mode
+       // reload count and base address
+       BX_DMA_THIS s.chan[channel].current_address = 
+         BX_DMA_THIS s.chan[channel].base_address;
+       BX_DMA_THIS s.chan[channel].current_count =
+         BX_DMA_THIS s.chan[channel].base_count;
+      }
+    
+    }
+  else {
+    // address decrement
+    BX_PANIC(("hlda: decrement not implemented\n"));
+    }
+
+  if (BX_DMA_THIS s.chan[channel].mode.transfer_type == 1) { // write
+    // xfer from I/O to Memory
+#if BX_SUPPORT_SID
+    dma_component->drive_channel_pin(channel, phy_addr, 0);
+#else
+    pc_sys->dma_write8(phy_addr, channel);
+#endif
+    }
+  else if (BX_DMA_THIS s.chan[channel].mode.transfer_type == 2) { // read
+    // xfer from Memory to I/O
+#if BX_SUPPORT_SID
+    dma_component->drive_channel_pin(channel, phy_addr, 1);
+#else
+    pc_sys->dma_read8(phy_addr, channel);
+#endif
+    }
+  else {
+    BX_PANIC(("hlda: transfer_type of %u not handled\n",
+      (unsigned) BX_DMA_THIS s.chan[channel].mode.transfer_type));
+    }
+
+  if (count_expired) {
+#if BX_SUPPORT_SID
+    dma_component->drive_terminal_count_pin(0);
+    dma_component->drive_hold_request_pin(0);
+#else
+    bx_pc_system.set_TC(0);            // clear TC, adapter card already notified
+    bx_pc_system.set_HRQ(0);           // clear HRQ to CPU
+#endif
+#if BX_SUPPORT_SID==0
+    bx_pc_system.set_DACK(channel, 0); // clear DACK to adapter card
+#endif
+    }
+}
diff --git a/sid/component/bochs/dma/dma.h b/sid/component/bochs/dma/dma.h
new file mode 100644 (file)
index 0000000..1e3e157
--- /dev/null
@@ -0,0 +1,110 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+#ifndef _PCDMA_H
+#define _PCDMA_H
+
+
+#define BX_KBD_ELEMENTS 16
+#define BX_MOUSE_BUFF_SIZE 48
+
+
+#if BX_USE_DMA_SMF
+#  define BX_DMA_SMF  static
+#  define BX_DMA_THIS bx_dma.
+#else
+#  define BX_DMA_SMF
+#  define BX_DMA_THIS this->
+#endif
+
+
+#if BX_SUPPORT_SID
+class dma;
+#endif
+
+class bx_dma_c : public logfunctions {
+public:
+
+  bx_dma_c();
+  ~bx_dma_c(void);
+
+#if BX_SUPPORT_SID
+  BX_DMA_SMF void     init(dma *dma_comp);
+#else
+  BX_DMA_SMF void     init(bx_devices_c *);
+#endif
+  BX_DMA_SMF void     DRQ(unsigned channel, Boolean val);
+#if BX_SUPPORT_SID
+  BX_DMA_SMF void     raise_HLDA(void);
+#else
+  BX_DMA_SMF void     raise_HLDA(bx_pc_system_c *pc_sys);
+#endif
+
+private:
+
+  static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
+  static void   write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
+#if BX_SUPPORT_SID
+ public:
+#endif
+#if !BX_USE_DMA_SMF
+  Bit32u   read( Bit32u   address, unsigned io_len);
+  void     write(Bit32u   address, Bit32u   value, unsigned io_len);
+#endif
+#if BX_SUPPORT_SID
+ private:
+#endif
+  struct {
+    Boolean mask[4];
+    Boolean flip_flop;
+    Bit8u   status_reg;
+    Bit8u   command_reg;
+    Bit8u   request_reg;
+    Bit8u   temporary_reg;
+    struct {
+      struct {
+        Bit8u mode_type;
+        Bit8u address_decrement;
+        Bit8u autoinit_enable;
+        Bit8u transfer_type;
+        } mode;
+      Bit16u  base_address;
+      Bit16u  current_address;
+      Bit16u  base_count;
+      Bit16u  current_count;
+      Bit8u   page_reg;
+      } chan[4]; /* DMA channels 0..3 */
+    } s;  // state information
+
+#if BX_SUPPORT_SID==0
+  bx_devices_c *devices;
+#else
+  dma *dma_component;
+#endif
+  };
+
+#if BX_SUPPORT_SID==0
+extern bx_dma_c bx_dma;
+#endif
+
+#endif  // #ifndef _PCDMA_H
diff --git a/sid/component/bochs/dma/sid-dma-wrapper.cc b/sid/component/bochs/dma/sid-dma-wrapper.cc
new file mode 100644 (file)
index 0000000..3a7ca62
--- /dev/null
@@ -0,0 +1,151 @@
+// sid-dma-wrapper.cc - SID import of the bochs dma component.  -*- C++ -*-
+
+// Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
+// This file is part of SID and is licensed under the GPL.
+// See the file COPYING.SID for conditions for redistribution.
+
+#include "sid-dma-wrapper.h"
+
+dma::dma ()
+    : init_pin(this, & dma::init),
+      hold_acknowledge_pin(this, & dma::hold_acknowledge),
+      ports_0x00_0x0f_bus(this, & dma::read_port_0x00_0x0f, & dma::write_port_0x00_0x0f),
+      ports_0x81_0x8d_bus(this, & dma::read_port_0x81_0x8d, & dma::write_port_0x81_0x8d),
+      port_0x8f_bus(this, & dma::read_port_0x8f, & dma::write_port_0x8f),
+      ports_0xc0_0xde_bus(this, & dma::read_port_0xc0_0xde, & dma::write_port_0xc0_0xde),
+      channels_bus(this, & dma::channel_read_request, & dma::channel_write_request)
+{
+  add_pin("hold-request", & this->hold_request_pin);
+  add_pin("terminal-count", & this->terminal_count_pin);
+
+  add_pin("init", & this->init_pin);
+  add_pin("hold-acknowledge", & this->hold_acknowledge_pin);
+
+  add_bus("ports-0x00-0x0f", & this->ports_0x00_0x0f_bus);
+  add_bus("ports-0x81-0x8d", & this->ports_0x81_0x8d_bus);
+  add_bus("port-0x8f", & this->port_0x8f_bus);
+  add_bus("ports-0xc0-0xde", & this->ports_0xc0_0xde_bus);
+  add_bus("channels", & this->channels_bus);
+
+  add_pin("read-write", & this->read_write_pin);
+
+  add_pin("channel-0", & this->channel_pin[0]);
+  add_pin("channel-1", & this->channel_pin[1]);
+  add_pin("channel-2", & this->channel_pin[2]);
+  add_pin("channel-3", & this->channel_pin[3]);
+  add_pin("channel-4", & this->channel_pin[4]);
+  add_pin("channel-5", & this->channel_pin[5]);
+  add_pin("channel-6", & this->channel_pin[6]);
+  add_pin("channel-7", & this->channel_pin[7]);
+}
+
+void
+dma::init(host_int_4)
+{
+  bx_dma.init(this);
+}
+
+void
+dma::hold_acknowledge(host_int_4)
+{
+  bx_dma.raise_HLDA();
+}
+
+void
+dma::drive_hold_request_pin(host_int_4 value)
+{
+  hold_request_pin.drive(value);
+}
+
+void
+dma::drive_terminal_count_pin(host_int_4 value)
+{
+  terminal_count_pin.drive(value);
+}
+
+void
+dma::drive_channel_pin(host_int_4 channel, host_int_4 value, bool read_mode)
+{
+  read_write_pin.drive(read_mode);
+
+  channel_pin[channel].drive(value);
+}
+
+bus::status
+dma::read_port_0x00_0x0f (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+{
+  addr += 0x00;
+  data = bx_dma.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+dma::write_port_0x00_0x0f (host_int_4 addr, little_int_1 mask, little_int_1 data)
+{
+  addr += 0x00;
+  bx_dma.write(addr, data, 1);
+  return bus::ok;
+}
+
+bus::status
+dma::read_port_0x81_0x8d (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+{
+  addr += 0x81;
+  data = bx_dma.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+dma::write_port_0x81_0x8d (host_int_4 addr, little_int_1 mask, little_int_1 data)
+{
+  addr += 0x81;
+  bx_dma.write(addr, data, 1);
+  return bus::ok;
+}
+
+bus::status
+dma::read_port_0x8f (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+{
+  addr += 0x8f;
+  data = bx_dma.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+dma::write_port_0x8f (host_int_4 addr, little_int_1 mask, little_int_1 data)
+{
+  addr += 0x8f;
+  bx_dma.write(addr, data, 1);
+  return bus::ok;
+}
+
+bus::status
+dma::read_port_0xc0_0xde (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+{
+  addr += 0xc0;
+  data = bx_dma.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+dma::write_port_0xc0_0xde (host_int_4 addr, little_int_1 mask, little_int_1 data)
+{
+  addr += 0xc0;
+  bx_dma.write(addr, data, 1);
+  return bus::ok;
+}
+
+bus::status
+dma::channel_read_request(host_int_4 channel, little_int_1 mask, little_int_1 &val)
+{
+  // not used
+  val = 0;
+  return bus::ok;
+}
+
+bus::status
+dma::channel_write_request(host_int_4 channel, little_int_1 mask, little_int_1 val)
+{
+  bx_dma.DRQ(channel, val);
+  return bus::ok;
+}
diff --git a/sid/component/bochs/dma/sid-dma-wrapper.h b/sid/component/bochs/dma/sid-dma-wrapper.h
new file mode 100644 (file)
index 0000000..27c4fc0
--- /dev/null
@@ -0,0 +1,87 @@
+// sid-dma-wrapper.h - SID import of the bochs dma component.  -*- C++ -*-
+
+// Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
+// This file is part of SID and is licensed under the GPL.
+// See the file COPYING.SID for conditions for redistribution.
+
+#ifndef SID_DMA_WRAPPER_DEF_H
+#define SID_DMA_WRAPPER_DEF_H  1
+
+#include <sidtypes.h>
+#include <sidcomp.h>
+#include <sidcomputil.h>
+#include <sidpinutil.h>
+#include <sidbusutil.h>
+#include <sidattrutil.h>
+#include <sidcpuutil.h>
+#include <sidpinattrutil.h>
+#include <sidmiscutil.h>
+#include <sidwatchutil.h>
+#include <sidso.h>
+
+#include "bochs.h"
+
+using sid::bus;
+using sid::component;
+using sid::host_int_4;
+using sid::little_int_1;
+using sidutil::callback_pin;
+using sidutil::callback_word_bus;
+using sidutil::output_pin;
+
+class dma : public sidutil::fixed_pin_map_component,
+            public sidutil::fixed_accessor_map_component,
+            public sidutil::fixed_attribute_map_component,
+            public sidutil::no_relation_component,
+            public sidutil::fixed_bus_map_component
+{
+public:
+  dma();
+  ~dma() throw() {};
+
+  void init(host_int_4);
+
+  void hold_acknowledge(host_int_4);
+
+  void drive_hold_request_pin(host_int_4 value);
+  void drive_terminal_count_pin(host_int_4 value);
+
+  void drive_channel_pin(host_int_4 channel, host_int_4 value, bool read_mode);
+protected:
+
+  output_pin hold_request_pin;
+  output_pin terminal_count_pin;
+
+  callback_pin<dma> init_pin;
+  callback_pin<dma> hold_acknowledge_pin;
+
+  // Some ports in these ranges are not valid DMA ports.
+  bus::status read_port_0x00_0x0f (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x00_0x0f (host_int_4 addr, little_int_1 mask, little_int_1 data);
+
+  bus::status read_port_0x81_0x8d (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x81_0x8d (host_int_4 addr, little_int_1 mask, little_int_1 data);
+
+  bus::status read_port_0x8f (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x8f (host_int_4 addr, little_int_1 mask, little_int_1 data);
+
+  bus::status read_port_0xc0_0xde (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0xc0_0xde (host_int_4 addr, little_int_1 mask, little_int_1 data);
+
+  callback_word_bus<dma, little_int_1> ports_0x00_0x0f_bus;
+  callback_word_bus<dma, little_int_1> ports_0x81_0x8d_bus;
+  callback_word_bus<dma, little_int_1> port_0x8f_bus;
+  callback_word_bus<dma, little_int_1> ports_0xc0_0xde_bus;
+
+  bus::status channel_read_request(host_int_4 channel, little_int_1 mask, little_int_1 &val);
+  bus::status channel_write_request(host_int_4 channel, little_int_1 mask, little_int_1 val);
+
+  callback_word_bus<dma, little_int_1> channels_bus;
+
+  // read == 1, write == 0
+  output_pin read_write_pin;
+  output_pin channel_pin[8];
+
+  bx_dma_c bx_dma;
+};
+#endif // SID_DMA_WRAPPER_DEF_H
diff --git a/sid/component/bochs/floppy/Makefile.am b/sid/component/bochs/floppy/Makefile.am
new file mode 100644 (file)
index 0000000..c2f5b9d
--- /dev/null
@@ -0,0 +1,11 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../cpu
+
+noinst_LTLIBRARIES = libfloppy.la
+
+libfloppy_la_SOURCES = sid-floppy-wrapper.cc sid-floppy-wrapper.h floppy.cc floppy.h
+
+libfloppy_la_LDFLAGS = -no-undefined
diff --git a/sid/component/bochs/floppy/Makefile.in b/sid/component/bochs/floppy/Makefile.in
new file mode 100644 (file)
index 0000000..859f6f2
--- /dev/null
@@ -0,0 +1,412 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+APIC_OBJS = @APIC_OBJS@
+AR = @AR@
+AS = @AS@
+AS_DYNAMIC_INCS = @AS_DYNAMIC_INCS@
+AS_DYNAMIC_OBJS = @AS_DYNAMIC_OBJS@
+BX_LOADER_OBJS = @BX_LOADER_OBJS@
+BX_SPLIT_HD_SUPPORT = @BX_SPLIT_HD_SUPPORT@
+CC = @CC@
+CDROM_OBJS = @CDROM_OBJS@
+CD_UP_ONE = @CD_UP_ONE@
+CD_UP_TWO = @CD_UP_TWO@
+CFP = @CFP@
+COMMAND_SEPARATOR = @COMMAND_SEPARATOR@
+CPP_SUFFIX = @CPP_SUFFIX@
+CXX = @CXX@
+CXXFP = @CXXFP@
+DASH = @DASH@
+DEBUGGER_VAR = @DEBUGGER_VAR@
+DISASM_VAR = @DISASM_VAR@
+DLLTOOL = @DLLTOOL@
+DYNAMIC_VAR = @DYNAMIC_VAR@
+EXE = @EXE@
+EXEEXT = @EXEEXT@
+EXTERNAL_DEPENDENCY = @EXTERNAL_DEPENDENCY@
+FPU_GLUE_OBJ = @FPU_GLUE_OBJ@
+FPU_VAR = @FPU_VAR@
+GUI_LINK_OPTS = @GUI_LINK_OPTS@
+GUI_LINK_OPTS_TERM = @GUI_LINK_OPTS_TERM@
+GUI_OBJS = @GUI_OBJS@
+GZIP = @GZIP@
+INLINE_VAR = @INLINE_VAR@
+INSTRUMENT_DIR = @INSTRUMENT_DIR@
+INSTRUMENT_VAR = @INSTRUMENT_VAR@
+IOAPIC_OBJS = @IOAPIC_OBJS@
+IODEV_LIB_VAR = @IODEV_LIB_VAR@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LINK = @LINK@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKELIB = @MAKELIB@
+NE2K_OBJS = @NE2K_OBJS@
+NM = @NM@
+NONINLINE_VAR = @NONINLINE_VAR@
+OBJDUMP = @OBJDUMP@
+OFP = @OFP@
+PACKAGE = @PACKAGE@
+PCI_OBJ = @PCI_OBJ@
+PRIMARY_TARGET = @PRIMARY_TARGET@
+RANLIB = @RANLIB@
+READLINE_LIB = @READLINE_LIB@
+RFB_LIBS = @RFB_LIBS@
+RMCOMMAND = @RMCOMMAND@
+SB16_OBJS = @SB16_OBJS@
+SLASH = @SLASH@
+SUFFIX_LINE = @SUFFIX_LINE@
+TAR = @TAR@
+VERSION = @VERSION@
+VIDEO_OBJS = @VIDEO_OBJS@
+sidtarget_arm = @sidtarget_arm@
+sidtarget_m32r = @sidtarget_m32r@
+sidtarget_m68k = @sidtarget_m68k@
+sidtarget_mips = @sidtarget_mips@
+sidtarget_ppc = @sidtarget_ppc@
+sidtarget_x86 = @sidtarget_x86@
+sidtarget_xstormy16 = @sidtarget_xstormy16@
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../cpu
+
+noinst_LTLIBRARIES = libfloppy.la
+
+libfloppy_la_SOURCES = sid-floppy-wrapper.cc sid-floppy-wrapper.h floppy.cc floppy.h
+
+libfloppy_la_LDFLAGS = -no-undefined
+mkinstalldirs = $(SHELL) $(top_srcdir)/../../config/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+LTLIBRARIES =  $(noinst_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libfloppy_la_LIBADD = 
+libfloppy_la_OBJECTS =  sid-floppy-wrapper.lo floppy.lo
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+GZIP_ENV = --best
+DEP_FILES =  .deps/floppy.P .deps/sid-floppy-wrapper.P
+SOURCES = $(libfloppy_la_SOURCES)
+OBJECTS = $(libfloppy_la_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .lo .o .s
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --foreign floppy/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLTLIBRARIES:
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+
+distclean-noinstLTLIBRARIES:
+
+maintainer-clean-noinstLTLIBRARIES:
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libfloppy.la: $(libfloppy_la_OBJECTS) $(libfloppy_la_DEPENDENCIES)
+       $(CXXLINK)  $(libfloppy_la_LDFLAGS) $(libfloppy_la_OBJECTS) $(libfloppy_la_LIBADD) $(LIBS)
+.cc.o:
+       $(CXXCOMPILE) -c $<
+.cc.lo:
+       $(LTCXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = floppy
+
+distdir: $(DISTFILES)
+       here=`cd $(top_builddir) && pwd`; \
+       top_distdir=`cd $(top_distdir) && pwd`; \
+       distdir=`cd $(distdir) && pwd`; \
+       cd $(top_srcdir) \
+         && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign floppy/Makefile
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+       -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+       @echo '$(COMPILE) -c $<'; \
+       $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.c
+       @echo '$(LTCOMPILE) -c $<'; \
+       $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+
+%.o: %.cc
+       @echo '$(CXXCOMPILE) -c $<'; \
+       $(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.cc
+       @echo '$(LTCXXCOMPILE) -c $<'; \
+       $(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LTLIBRARIES)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLTLIBRARIES mostlyclean-compile \
+               mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+               mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLTLIBRARIES clean-compile clean-libtool \
+               clean-tags clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLTLIBRARIES distclean-compile \
+               distclean-libtool distclean-tags distclean-depend \
+               distclean-generic clean-am
+       -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLTLIBRARIES \
+               maintainer-clean-compile maintainer-clean-libtool \
+               maintainer-clean-tags maintainer-clean-depend \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \
+clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sid/component/bochs/floppy/floppy.cc b/sid/component/bochs/floppy/floppy.cc
new file mode 100644 (file)
index 0000000..3973068
--- /dev/null
@@ -0,0 +1,1432 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+extern "C" {
+#include <errno.h>
+}
+
+#include "bochs.h"
+#if BX_SUPPORT_SID
+#define LOG_THIS
+#include "sid-floppy-wrapper.h"
+#else // BX_SUPPORT_SID
+#define LOG_THIS bx_floppy.
+
+
+bx_floppy_ctrl_c bx_floppy;
+#endif // BX_SUPPORT_SID
+
+#if BX_USE_FD_SMF
+#define this (&bx_floppy)
+#endif
+
+
+
+/* for main status register */
+#define FD_MS_MRQ  0x80
+#define FD_MS_DIO  0x40
+#define FD_MS_NDMA 0x20
+#define FD_MS_BUSY 0x10
+#define FD_MS_ACTD 0x08
+#define FD_MS_ACTC 0x04
+#define FD_MS_ACTB 0x02
+#define FD_MS_ACTA 0x01
+
+#define FROM_FLOPPY 10
+#define TO_FLOPPY   11
+
+#define FLOPPY_DMA_CHAN floppy_component->dma_channel_number()
+
+
+
+bx_floppy_ctrl_c::bx_floppy_ctrl_c(void)
+{
+#if BX_SUPPORT_SID
+  bx_dbg.floppy = 1;
+#endif
+       setprefix("[FDD ]");
+       settype(FDLOG);
+       BX_DEBUG(("Init.\n"));
+}
+
+bx_floppy_ctrl_c::~bx_floppy_ctrl_c(void)
+{
+       // nothing for now
+       BX_DEBUG(("Exit.\n"));
+}
+
+
+#if BX_SUPPORT_SID
+void
+bx_floppy_ctrl_c::init(floppy *floppy_comp)
+#else
+  void
+bx_floppy_ctrl_c::init(bx_devices_c *d, bx_cmos_c *cmos)
+#endif
+{
+#if BX_SUPPORT_SID==0
+  BX_FD_THIS devices = d;
+
+  BX_FD_THIS devices->register_irq(6, "Floppy Drive");
+  for (unsigned addr=0x03F2; addr<=0x03F7; addr++) {
+    BX_FD_THIS devices->register_io_read_handler(this, read_handler,
+                                      addr, "Floppy Drive");
+    BX_FD_THIS devices->register_io_write_handler(this, write_handler,
+                                      addr, "Floppy Drive");
+    }
+
+
+  cmos->s.reg[0x10] = 0x00; /* start out with: no drive 0, no drive 1 */
+
+  BX_FD_THIS s.num_supported_floppies = 0;
+#endif
+
+  //
+  // Floppy A setup
+  //
+  BX_FD_THIS s.media[0].sectors_per_track = 0;
+  BX_FD_THIS s.media[0].tracks            = 0;
+  BX_FD_THIS s.media[0].heads             = 0;
+  BX_FD_THIS s.media[0].sectors           = 0;
+  BX_FD_THIS s.media[0].type              = BX_FLOPPY_NONE;
+  BX_FD_THIS s.media[0].fd = -1;
+  BX_FD_THIS s.media_present[0] = 0;
+
+
+#if BX_SUPPORT_SID==0
+  switch (bx_options.floppya.type) {
+    case BX_FLOPPY_NONE:
+      cmos->s.reg[0x10] = (cmos->s.reg[0x10] & 0x0f) | 0x00;
+      break;
+    case BX_FLOPPY_1_2:
+      cmos->s.reg[0x10] = (cmos->s.reg[0x10] & 0x0f) | 0x20;
+      break;
+    case BX_FLOPPY_720K:
+      cmos->s.reg[0x10] = (cmos->s.reg[0x10] & 0x0f) | 0x30;
+      break;
+    case BX_FLOPPY_1_44:
+      cmos->s.reg[0x10] = (cmos->s.reg[0x10] & 0x0f) | 0x40;
+      break;
+    case BX_FLOPPY_2_88:
+      cmos->s.reg[0x10] = (cmos->s.reg[0x10] & 0x0f) | 0x50;
+      break;
+    default:
+      BX_PANIC(( "unknown floppya type\n" ));
+    }
+
+  if (bx_options.floppya.type != BX_FLOPPY_NONE) {
+    BX_FD_THIS s.num_supported_floppies++;
+    if ( bx_options.floppya.initial_status == BX_INSERTED) {
+      if (evaluate_media(bx_options.floppya.type, bx_options.floppya.path,
+                   & BX_FD_THIS s.media[0]))
+        BX_FD_THIS s.media_present[0] = 1;
+      }
+    }
+#endif
+
+
+  //
+  // Floppy B setup
+  //
+  BX_FD_THIS s.media[1].sectors_per_track = 0;
+  BX_FD_THIS s.media[1].tracks            = 0;
+  BX_FD_THIS s.media[1].heads             = 0;
+  BX_FD_THIS s.media[1].sectors           = 0;
+  BX_FD_THIS s.media[1].type              = BX_FLOPPY_NONE;
+  BX_FD_THIS s.media[1].fd = -1;
+  BX_FD_THIS s.media_present[1] = 0;
+
+#if BX_SUPPORT_SID==0
+  switch (bx_options.floppyb.type) {
+    case BX_FLOPPY_NONE:
+      cmos->s.reg[0x10] = (cmos->s.reg[0x10] & 0xf0) | 0x00;
+      break;
+    case BX_FLOPPY_1_2:
+      cmos->s.reg[0x10] = (cmos->s.reg[0x10] & 0xf0) | 0x02;
+      break;
+    case BX_FLOPPY_720K:
+      cmos->s.reg[0x10] = (cmos->s.reg[0x10] & 0xf0) | 0x03;
+      break;
+    case BX_FLOPPY_1_44:
+      cmos->s.reg[0x10] = (cmos->s.reg[0x10] & 0xf0) | 0x04;
+      break;
+    case BX_FLOPPY_2_88:
+      cmos->s.reg[0x10] = (cmos->s.reg[0x10] & 0xf0) | 0x05;
+      break;
+    default:
+      BX_PANIC(("unknown floppyb type\n"));
+    }
+
+  if (bx_options.floppyb.type != BX_FLOPPY_NONE) {
+    BX_FD_THIS s.num_supported_floppies++;
+    if ( bx_options.floppyb.initial_status == BX_INSERTED) {
+      if (evaluate_media(bx_options.floppyb.type, bx_options.floppyb.path,
+                   & BX_FD_THIS s.media[1]))
+        BX_FD_THIS s.media_present[1] = 1;
+      }
+    }
+
+
+
+  /* CMOS Equipment Byte register */
+  if (BX_FD_THIS s.num_supported_floppies > 0)
+    cmos->s.reg[0x14] = (cmos->s.reg[0x14] & 0x3e) |
+                        ((BX_FD_THIS s.num_supported_floppies-1) << 6) |
+                        1;
+  else
+    cmos->s.reg[0x14] = (cmos->s.reg[0x14] & 0x3e);
+#endif
+
+#if BX_SUPPORT_SID
+  floppy_component = floppy_comp;
+  floppy_component->drive_command_delay_control_pin(0, 0);
+#else
+
+  BX_FD_THIS s.floppy_timer_index =
+    bx_pc_system.register_timer( this, timer_handler,
+      bx_options.floppy_command_delay, 0,0);
+#endif
+
+  BX_INFO(("bx_options.floppy_command_delay = %u\n",
+    (unsigned) bx_options.floppy_command_delay));
+}
+
+
+
+  void
+bx_floppy_ctrl_c::reset(unsigned source)
+{
+  Bit32u i;
+
+  BX_FD_THIS s.data_rate = 0; /* 500 Kbps */
+
+  BX_FD_THIS s.command_complete = 1; /* waiting for new command */
+  BX_FD_THIS s.command_index = 0;
+  BX_FD_THIS s.command_size = 0;
+  BX_FD_THIS s.pending_command = 0;
+
+  BX_FD_THIS s.result_index = 0;
+  BX_FD_THIS s.result_size = 0;
+
+  /* data register ready, not in DMA mode */
+  BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
+  BX_FD_THIS s.status_reg0 = 0;
+  BX_FD_THIS s.status_reg1 = 0;
+  BX_FD_THIS s.status_reg2 = 0;
+  BX_FD_THIS s.status_reg3 = 0;
+
+  // software reset (via DOR port 0x3f2 bit 2) does not change DOR
+  if (source == BX_RESET_HARDWARE) {
+    BX_FD_THIS s.DOR = 0x0c;
+    // motor off, drive 3..0
+    // DMA/INT enabled
+    // normal operation
+    // drive select 0
+
+    // DIR affected only by hard reset
+    BX_FD_THIS s.DIR |= 0x80; // disk changed
+    }
+
+  for (i=0; i<4; i++) {
+    BX_FD_THIS s.cylinder[i] = 0;
+    BX_FD_THIS s.head[i] = 0;
+    BX_FD_THIS s.sector[i] = 0;
+    }
+
+  BX_FD_THIS s.floppy_buffer_index = 0;
+
+}
+
+
+  // static IO port read callback handler
+  // redirects to non-static class handler to avoid virtual functions
+
+  Bit32u
+bx_floppy_ctrl_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
+{
+#if !BX_USE_FD_SMF
+  bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr;
+
+  return( class_ptr->read(address, io_len) );
+}
+
+
+  /* reads from the floppy io ports */
+  Bit32u
+bx_floppy_ctrl_c::read(Bit32u address, unsigned io_len)
+{
+#else
+  UNUSED(this_ptr);
+#endif  // !BX_USE_FD_SMF
+  Bit8u status, value;
+
+  if (io_len > 1)
+    BX_PANIC(("io read from address %08x, len=%u\n",
+             (unsigned) address, (unsigned) io_len));
+
+// ???
+//if (bx_cpu.cs.selector.value != 0xf000) {
+//  BX_INFO(("BIOS: floppy: read access to port %04x\n", (unsigned) address);
+//  }
+
+  if (bx_dbg.floppy)
+    BX_INFO(("read access to port %04x\n", (unsigned) address));
+
+  switch (address) {
+#if BX_DMA_FLOPPY_IO
+    case 0x3F2: // diskette controller digital output register
+      value = BX_FD_THIS s.DOR;
+      return(value);
+      break;
+
+    case 0x3F4: /* diskette controller main status register */
+      status = BX_FD_THIS s.main_status_reg;
+      return(status);
+      break;
+
+    case 0x3F5: /* diskette controller data */
+      if (BX_FD_THIS s.result_size == 0) {
+        BX_PANIC(("diskette controller:port3f5: no results to read\n"));
+        }
+
+      value = BX_FD_THIS s.result[BX_FD_THIS s.result_index++];
+      if (BX_FD_THIS s.result_index >= BX_FD_THIS s.result_size) {
+        BX_FD_THIS s.result_size = 0;
+        BX_FD_THIS s.result_index = 0;
+        BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
+        }
+      return(value);
+      break;
+#endif  // #if BX_DMA_FLOPPY_IO
+
+    case 0x3F6: // Reserved for future floppy controllers
+                // This address shared with the hard drive controller
+#if 0  // Change this when adding bochs hard drive component to sid.
+      value = BX_FD_THIS devices->hard_drive->read_handler(BX_FD_THIS devices->hard_drive, address, io_len);
+#else
+      value = 0;
+#endif
+      return( value );
+      break;
+
+    case 0x3F7: // diskette controller digital input register
+      // This address shared with the hard drive controller:
+      //   Bit  7   : floppy
+      //   Bits 6..0: hard drive
+#if 0 // Change this when adding bochs hard drive component to sid.
+      value = BX_FD_THIS devices->hard_drive->read_handler(BX_FD_THIS devices->hard_drive, address, io_len);
+#else
+      value = 0;
+#endif
+      value &= 0x7f;
+      // add in diskette change line
+      value |= (BX_FD_THIS s.DIR & 0x80);
+      return( value );
+      break;
+    }
+
+#if BX_DMA_FLOPPY_IO
+  BX_PANIC(("io_read: bailing\n"));
+  return(0);
+#endif  // #if BX_DMA_FLOPPY_IO
+}
+
+
+  // static IO port write callback handler
+  // redirects to non-static class handler to avoid virtual functions
+
+  void
+bx_floppy_ctrl_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
+{
+#if !BX_USE_FD_SMF
+  bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr;
+
+  class_ptr->write(address, value, io_len);
+}
+
+  /* writes to the floppy io ports */
+  void
+bx_floppy_ctrl_c::write(Bit32u address, Bit32u value, unsigned io_len)
+{
+#else
+  UNUSED(this_ptr);
+#endif  // !BX_USE_FD_SMF
+  Bit8u dma_and_interrupt_enable;
+  Bit8u normal_operation, prev_normal_operation;
+  Bit8u drive_select;
+  Bit8u motor_on_drive0, motor_on_drive1;
+
+  if (io_len > 1)
+    BX_PANIC(("io write to address %08x, len=%u\n",
+             (unsigned) address, (unsigned) io_len));
+
+// ???
+//if (bx_cpu.cs.selector.value != 0xf000) {
+//  BX_INFO(("BIOS: floppy: write access to port %04x, value=%02x\n",
+//      (unsigned) address, (unsigned) value));
+//  }
+
+  if (bx_dbg.floppy)
+    BX_INFO(("write access to port %04x, value=%02x\n",
+      (unsigned) address, (unsigned) value));
+
+  switch (address) {
+#if BX_DMA_FLOPPY_IO
+    case 0x3F2: /* diskette controller digital output register */
+      motor_on_drive1 = value & 0x20;
+      motor_on_drive0 = value & 0x10;
+      dma_and_interrupt_enable = value & 0x08;
+      if (!dma_and_interrupt_enable)
+        BX_DEBUG(("DMA and interrupt capabilities disabled\n"));
+      normal_operation = value & 0x04;
+      drive_select = value & 0x03;
+
+      prev_normal_operation = BX_FD_THIS s.DOR & 0x04;
+      BX_FD_THIS s.DOR = value;
+
+      if (prev_normal_operation==0 && normal_operation) {
+        // transition from RESET to NORMAL
+#if 0
+
+        BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
+        BX_FD_THIS s.pending_command = 0xfe; // RESET pending
+
+        bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
+             bx_options.floppy_command_delay, 0 );
+#endif
+        }
+      else if (prev_normal_operation && normal_operation==0) {
+        // transition from NORMAL to RESET
+        BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
+        BX_FD_THIS s.pending_command = 0xfe; // RESET pending
+
+#if BX_SUPPORT_SID
+        floppy_component->drive_command_delay_control_pin(bx_options.floppy_command_delay, 0);
+#else
+        bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
+             bx_options.floppy_command_delay, 0 );
+#endif
+        }
+      if (bx_dbg.floppy) {
+        BX_INFO(("io_write: digital output register\n"));
+        BX_INFO(("  motor on, drive1 = %d\n", motor_on_drive1 > 0));
+        BX_INFO(("  motor on, drive0 = %d\n", motor_on_drive0 > 0));
+        BX_INFO(("  dma_and_interrupt_enable=%02x\n",
+          (unsigned) dma_and_interrupt_enable));
+        BX_INFO(("  normal_operation=%02x\n",
+          (unsigned) normal_operation));
+        BX_INFO(("  drive_select=%02x\n",
+          (unsigned) drive_select));
+        }
+      if (drive_select>1) {
+        BX_PANIC(("io_write: drive_select>1\n"));
+        }
+      break;
+
+    case 0x3f4: /* diskette controller data rate select register */
+      BX_PANIC(("io_write: data rate select register\n"));
+      break;
+
+    case 0x3F5: /* diskette controller data */
+      if (bx_dbg.floppy)
+        BX_INFO(("command = %02x\n", (unsigned) value));
+      if (BX_FD_THIS s.command_complete) {
+        if (BX_FD_THIS s.pending_command!=0)
+          BX_PANIC(("io: 3f5: receiving new comm, old one (%02x) pending\n",
+            (unsigned) BX_FD_THIS s.pending_command));
+        BX_FD_THIS s.command[0] = value;
+        BX_FD_THIS s.command_complete = 0;
+        BX_FD_THIS s.command_index = 1;
+        /* read/write command in progress */
+        BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_BUSY;
+        switch (value) {
+          case 0x03: /* specify */
+            BX_FD_THIS s.command_size = 3;
+            break;
+          case 0x04: // get status
+            BX_FD_THIS s.command_size = 2;
+            break;
+          case 0x07: /* recalibrate */
+            BX_FD_THIS s.command_size = 2;
+            break;
+          case 0x08: /* sense interrupt status */
+            BX_FD_THIS s.command_size = 1;
+            floppy_command();
+            BX_FD_THIS s.command_complete = 1;
+            break;
+          case 0x0f: /* seek */
+            BX_FD_THIS s.command_size = 3;
+            break;
+          case 0x4a: /* read ID */
+            BX_FD_THIS s.command_size = 2;
+            break;
+          case 0xc5: /* write normal data */
+            BX_FD_THIS s.command_size = 9;
+            break;
+          case 0xe6: /* read normal data */
+            BX_FD_THIS s.command_size = 9;
+            break;
+
+          case 0x13: // Configure command (Enhanced)
+            BX_FD_THIS s.command_size = 3;
+            break;
+
+          case 0x0e: // dump registers (Enhanced drives)
+          case 0x10: // Version command, standard controller returns 80h
+          case 0x18: // National Semiconductor version command; return 80h
+            // These commands are not implemented on the standard
+            // controller and return an error.  They are available on
+            // the enhanced controller.
+            BX_FD_THIS s.command_size = 1;
+            BX_FD_THIS s.result[0] = 0x80;
+            BX_FD_THIS s.result_size = 1;
+            BX_FD_THIS s.result_index = 0;
+            BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+            BX_FD_THIS s.command_complete = 1;
+            break;
+
+          default:
+            BX_PANIC(("io write:3f5: unsupported case 0x%02x\n",
+              (unsigned) value));
+            break;
+          }
+        }
+      else {
+        BX_FD_THIS s.command[BX_FD_THIS s.command_index++] =
+          value;
+        if (BX_FD_THIS s.command_index ==
+            BX_FD_THIS s.command_size) {
+          /* read/write command not in progress any more */
+          floppy_command();
+          BX_FD_THIS s.command_complete = 1;
+          }
+        }
+      if (bx_dbg.floppy)
+        BX_INFO(("io_write: diskette controller data\n"));
+      return;
+      break;
+#endif  // #if BX_DMA_FLOPPY_IO
+
+    case 0x3F6: /* diskette controller (reserved) */
+      if (bx_dbg.floppy)
+        BX_INFO(("io_write: reserved register unsupported\n"));
+      // this address shared with the hard drive controller
+#if 0  // Change this when adding bochs hard drive component to sid.
+      BX_FD_THIS devices->hard_drive->write_handler(BX_FD_THIS devices->hard_drive, address, value, io_len);
+#endif
+      break;
+
+#if BX_DMA_FLOPPY_IO
+    case 0x3F7: /* diskette controller configuration control register */
+      if (bx_dbg.floppy)
+        BX_INFO(("io_write: config control register\n"));
+      BX_FD_THIS s.data_rate = value & 0x03;
+      if (bx_dbg.floppy)
+        switch (BX_FD_THIS s.data_rate) {
+          case 0: BX_INFO(("  500 Kbps\n")); break;
+          case 1: BX_INFO(("  300 Kbps\n")); break;
+          case 2: BX_INFO(("  250 Kbps\n")); break;
+          case 3: BX_INFO(("  1 Mbps\n")); break;
+          }
+      return;
+      break;
+
+   default:
+      BX_PANIC(("io_write: unknown port %04h\n", (unsigned) address));
+      break;
+#endif  // #if BX_DMA_FLOPPY_IO
+    }
+}
+
+
+
+  void
+bx_floppy_ctrl_c::floppy_command(void)
+{
+#if BX_PROVIDE_CPU_MEMORY==0
+  BX_PANIC(("floppy_command(): uses DMA: not supported for"
+           " external environment\n"));
+#else
+  unsigned i;
+  Bit8u step_rate_time;
+  Bit8u head_unload_time;
+  Bit8u head_load_time;
+  Bit8u motor_on;
+  Bit8u head, drive, cylinder, sector, eot;
+  Bit8u sector_size, data_length;
+  Bit32u logical_sector;
+
+
+  if (bx_dbg.floppy) {
+    BX_INFO(("FLOPPY COMMAND: "));
+    for (i=0; i<BX_FD_THIS s.command_size; i++)
+      BX_INFO(("[%02x] ", (unsigned) BX_FD_THIS s.command[i]));
+    BX_INFO(("\n"));
+    }
+
+#if 0
+  /* execute phase of command is in progress (non DMA mode) */
+  BX_FD_THIS s.main_status_reg |= 20;
+#endif
+
+  switch (BX_FD_THIS s.command[0]) {
+    case 0x03: // specify
+//BX_INFO(("floppy_command specify\n"));
+      // execution: specified parameters are loaded
+      // result: no result bytes, no interrupt
+      step_rate_time = BX_FD_THIS s.command[1] >> 4;
+      head_unload_time = BX_FD_THIS s.command[1] & 0x0f;
+      head_load_time = BX_FD_THIS s.command[2] >> 1;
+      BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
+      return;
+      break;
+
+    case 0x04: // get status
+      BX_FD_THIS s.result[0] = 0x00;
+      BX_FD_THIS s.result_size = 1;
+      BX_FD_THIS s.result_index = 0;
+      BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+      return;
+      break;
+
+    case 0x07: // recalibrate
+//BX_INFO(("floppy_command recalibrate\n"));
+      drive = (BX_FD_THIS s.command[1] & 0x03);
+      BX_FD_THIS s.DOR &= 0xfc;
+      BX_FD_THIS s.DOR |= drive;
+      if (bx_dbg.floppy)
+        BX_INFO(("floppy_command(): recalibrate drive %u\n",
+          (unsigned) drive));
+      if (drive > 1)
+        BX_PANIC(("floppy_command(): drive > 1\n"));
+      //motor_on = BX_FD_THIS s.DOR & 0xf0;
+      motor_on = ( (BX_FD_THIS s.DOR>>(drive+4))
+                     & 0x01 );
+      if (motor_on == 0) {
+        BX_INFO(("floppy_command(): recal drive with motor off\n"));
+        }
+      if (drive==0)
+        BX_FD_THIS s.DOR |= 0x10; // turn on MOTA
+      else
+        BX_FD_THIS s.DOR |= 0x20; // turn on MOTB
+      BX_FD_THIS s.cylinder[drive] = 0;
+
+#if BX_SUPPORT_SID
+      floppy_component->drive_command_delay_control_pin(bx_options.floppy_command_delay, 0);
+#else
+      bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
+        bx_options.floppy_command_delay, 0 );
+#endif
+      /* command head to track 0
+       * controller set to non-busy
+       * error condition noted in Status reg 0's equipment check bit
+       * seek end bit set to 1 in Status reg 0 regardless of outcome
+       */
+      /* data reg not ready, controller busy */
+      BX_FD_THIS s.main_status_reg = FD_MS_DIO | FD_MS_BUSY;
+      BX_FD_THIS s.pending_command = 0x07; // recalibrate pending
+      return;
+      break;
+
+    case 0x08: /* sense interrupt status */
+//BX_INFO(("floppy_command sense interrupt status\n"));
+      /* execution:
+       *   get status
+       * result:
+       *   no interupt
+       *   byte0 = status reg0
+       *   byte1 = current cylinder number (0 to 79)
+       */
+      /*BX_FD_THIS s.status_reg0 = ;*/
+      drive = BX_FD_THIS s.DOR & 0x03;
+      BX_FD_THIS s.result[0] = 0x20 | drive;
+      BX_FD_THIS s.result[1] = BX_FD_THIS s.cylinder[drive];
+      BX_FD_THIS s.result_size = 2;
+      BX_FD_THIS s.result_index = 0;
+
+      /* read ready */
+      BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+      if (bx_dbg.floppy)
+        BX_INFO(("sense interrupt status\n"));
+      return;
+      break;
+
+    case 0x0f: /* seek */
+//BX_INFO(("floppy_command seek\n"));
+      /* command:
+       *   byte0 = 0F
+       *   byte1 = drive & head select
+       *   byte2 = cylinder number
+       * execution:
+       *   postion head over specified cylinder
+       * result:
+       *   no result bytes, issues an interrupt
+       */
+      drive = BX_FD_THIS s.command[1] & 0x03;
+      BX_FD_THIS s.DOR &= 0xfc;
+      BX_FD_THIS s.DOR |= drive;
+
+      BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01;
+      BX_FD_THIS s.cylinder[drive] = BX_FD_THIS s.command[2];
+      if (drive > 1)
+        BX_PANIC(("floppy_command(): seek: drive>1\n"));
+      /* ??? should also check cylinder validity */
+
+#if BX_SUPPORT_SID
+      floppy_component->drive_command_delay_control_pin(bx_options.floppy_command_delay, 0);
+#else
+      bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
+        bx_options.floppy_command_delay, 0 );
+#endif
+      /* data reg not ready, controller busy */
+      BX_FD_THIS s.main_status_reg = FD_MS_DIO | FD_MS_BUSY;
+      BX_FD_THIS s.pending_command = 0x0f; /* seek pending */
+      return;
+      break;
+
+    case 0x13: // Configure
+      BX_DEBUG(("io: configure (mode=%02xh, pretrack=%02xh)\n",
+(unsigned)(BX_FD_THIS s.command[2]), (unsigned)(BX_FD_THIS s.command[3]) ));
+      BX_FD_THIS s.result_size = 0;
+      BX_FD_THIS s.result_index = 0;
+      BX_FD_THIS s.pending_command = 0;
+      BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+      return;
+      break;
+
+    case 0x4a: // read ID
+//BX_INFO(("floppy_command read ID\n")); // ???
+      drive = BX_FD_THIS s.command[1] & 0x03;
+      BX_FD_THIS s.DOR &= 0xfc;
+      BX_FD_THIS s.DOR |= drive;
+
+      motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01;
+      if (motor_on == 0)
+        BX_PANIC(("floppy_command(): 4a: motor not on\n"));
+      if (drive > 1)
+        BX_PANIC(("io: 4a: bad drive #\n"));
+      BX_FD_THIS s.result_size = 7;
+      BX_FD_THIS s.result_index = 0;
+      BX_FD_THIS s.result[0] = 0; /* ??? */
+      BX_FD_THIS s.result[1] = 0;
+      BX_FD_THIS s.result[2] = 0;
+      BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
+      BX_FD_THIS s.result[4] = 0; /* head */
+      BX_FD_THIS s.result[5] = 0; /* sector at completion */
+      BX_FD_THIS s.result[6] = 2;
+#if BX_SUPPORT_SID
+      floppy_component->drive_command_delay_control_pin(bx_options.floppy_command_delay, 0);
+#else
+      bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
+        bx_options.floppy_command_delay, 0 );
+#endif
+      /* data reg not ready, controller busy */
+      BX_FD_THIS s.main_status_reg = FD_MS_DIO | FD_MS_BUSY;
+      BX_FD_THIS s.pending_command = 0x4a; /* read ID pending */
+      return;
+      break;
+
+
+    case 0xe6: // read normal data
+//BX_INFO(("floppy_command read normal data\n"));
+    case 0xc5: // write normal data
+//BX_INFO(("floppy_command write normal data\n"));
+      if ( (BX_FD_THIS s.DOR & 0x08) == 0 )
+        BX_PANIC(("read/write command with DMA and int disabled\n"));
+      drive = BX_FD_THIS s.command[1] & 0x03;
+      BX_FD_THIS s.DOR &= 0xfc;
+      BX_FD_THIS s.DOR |= drive;
+
+      motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01;
+      if (motor_on == 0)
+        BX_PANIC(("floppy_command(): read/write: motor not on\n"));
+      head = BX_FD_THIS s.command[3] & 0x01;
+      cylinder = BX_FD_THIS s.command[2]; /* 0..79 depending */
+      sector = BX_FD_THIS s.command[4];   /* 1..36 depending */
+      eot = BX_FD_THIS s.command[6];      /* 1..36 depending */
+      sector_size = BX_FD_THIS s.command[5];
+      data_length = BX_FD_THIS s.command[8];
+      if (bx_dbg.floppy) {
+        BX_INFO(("\n\nread/write normal data\n"));
+        BX_INFO(("BEFORE\n"));
+        BX_INFO(("  drive    = %u\n", (unsigned) drive));
+        BX_INFO(("  head     = %u\n", (unsigned) head));
+        BX_INFO(("  cylinder = %u\n", (unsigned) cylinder));
+        BX_INFO(("  sector   = %u\n", (unsigned) sector));
+        BX_INFO(("  eot      = %u\n", (unsigned) eot));
+        }
+      if (drive > 1)
+        BX_PANIC(("io: bad drive #\n"));
+      if (head > 1)
+        BX_PANIC(("io: bad head #\n"));
+
+      if ( BX_FD_THIS s.media_present[drive] == 0 ) {
+        // media not in drive, return error
+
+        BX_INFO(("attempt to read/write sector %u,"
+                     " sectors/track=%u\n", (unsigned) sector,
+                     (unsigned) BX_FD_THIS s.media[drive].sectors_per_track));
+        BX_FD_THIS s.result_size = 7;
+        BX_FD_THIS s.result_index = 0;
+        BX_FD_THIS s.result[0] = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination
+        BX_FD_THIS s.result[1] = 0x25; // 0010 0101
+        BX_FD_THIS s.result[2] = 0x31; // 0011 0001
+        BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
+        BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
+        BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
+        BX_FD_THIS s.result[6] = 2; // sector size = 512
+
+        BX_FD_THIS s.pending_command = 0;
+        BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+#if BX_SUPPORT_SID
+        floppy_component->drive_trigger_irq_pin();
+#else
+        BX_FD_THIS devices->pic->trigger_irq(6);
+#endif
+        return;
+        }
+
+      if (sector_size != 0x02) { // 512 bytes
+        BX_PANIC(("sector_size not 512\n"));
+        }
+      if ( cylinder >= BX_FD_THIS s.media[drive].tracks ) {
+        BX_INFO(("\nio: normal read/write: params out of range\n"));
+        BX_INFO(("*** sector # %02xh\n", (unsigned) sector));
+        BX_INFO(("*** cylinder #%02xh\n", (unsigned) cylinder));
+        BX_INFO(("*** eot #%02xh\n", (unsigned) eot));
+        BX_INFO(("*** head #%02xh\n", (unsigned) head));
+        BX_PANIC(("bailing\n"));
+        return;
+        }
+
+      if (sector > BX_FD_THIS s.media[drive].sectors_per_track) {
+        // requested sector > last sector on track
+        BX_INFO(("attempt to read/write sector %u,"
+                     " sectors/track=%u\n", (unsigned) sector,
+                     (unsigned) BX_FD_THIS s.media[drive].sectors_per_track));
+        // set controller to where drive would have left off
+        // after it discovered the sector was past EOT
+        BX_FD_THIS s.cylinder[drive] = cylinder;
+        BX_FD_THIS s.head[drive]     = head;
+        BX_FD_THIS s.sector[drive]   = BX_FD_THIS s.media[drive].sectors_per_track;
+
+        BX_FD_THIS s.result_size = 7;
+
+        BX_FD_THIS s.result_index = 0;
+        // 0100 0HDD abnormal termination
+        BX_FD_THIS s.result[0] = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive;
+        // 1000 0101 end of cyl/NDAT/NID
+        BX_FD_THIS s.result[1] = 0x86;
+        // 0000 0000
+        BX_FD_THIS s.result[2] = 0x00;
+        BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
+        BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
+        BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
+        BX_FD_THIS s.result[6] = 2; // sector size = 512
+
+
+#if BX_SUPPORT_SID
+      floppy_component->drive_command_delay_control_pin(bx_options.floppy_command_delay, 0);
+#else
+        bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
+          bx_options.floppy_command_delay, 0 );
+#endif
+        /* data reg not ready, controller busy */
+        BX_FD_THIS s.main_status_reg = FD_MS_DIO | FD_MS_BUSY;
+        BX_FD_THIS s.pending_command = BX_FD_THIS s.command[0];
+        return;
+        }
+
+#if 0
+      if (eot != BX_FD_THIS s.media[drive].sectors_per_track)
+        BX_DEBUG(("io: bad eot #%02xh\n", (unsigned) eot));
+#endif
+
+      if (cylinder != BX_FD_THIS s.cylinder[drive])
+        BX_DEBUG(("io: cylinder request != current cylinder\n"));
+
+      logical_sector = (cylinder * 2 * BX_FD_THIS s.media[drive].sectors_per_track) +
+                       (head * BX_FD_THIS s.media[drive].sectors_per_track) +
+                       (sector - 1);
+
+      if (logical_sector >= BX_FD_THIS s.media[drive].sectors) {
+        BX_PANIC(("io: logical sector out of bounds\n"));
+        }
+
+      BX_FD_THIS s.cylinder[drive] = cylinder;
+      BX_FD_THIS s.sector[drive]   = sector;
+      BX_FD_THIS s.head[drive]     = head;
+
+      if (BX_FD_THIS s.command[0] == 0xe6) { // read
+        floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
+                    512, FROM_FLOPPY);
+        BX_FD_THIS s.floppy_buffer_index = 0;
+
+#if BX_SUPPORT_SID
+        floppy_component->channel_request(FLOPPY_DMA_CHAN, 1);
+#else
+        bx_pc_system.set_DRQ(FLOPPY_DMA_CHAN, 1);
+#endif
+
+        /* data reg not ready, controller busy */
+        BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+        BX_FD_THIS s.pending_command = BX_FD_THIS s.command[0];
+        return;
+        }
+      else if (BX_FD_THIS s.command[0] == 0xc5) { // write
+        BX_FD_THIS s.floppy_buffer_index = 0;
+
+#if BX_SUPPORT_SID
+        floppy_component->channel_request(FLOPPY_DMA_CHAN, 1);
+#else
+        bx_pc_system.set_DRQ(FLOPPY_DMA_CHAN, 1);
+#endif
+
+        /* data reg not ready, controller busy */
+        BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+        BX_FD_THIS s.pending_command = BX_FD_THIS s.command[0];
+        return;
+        }
+      else
+        BX_PANIC(("floppy_command(): unknown read/write command\n"));
+
+      return;
+      break;
+
+    default:
+      BX_PANIC(("floppy_command(): unknown function\n"));
+    }
+  BX_PANIC(("\nfloppy_command()\n"));
+#endif
+}
+
+  void
+bx_floppy_ctrl_c::floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer,
+            Bit32u bytes, Bit8u direction)
+{
+  int ret;
+
+  if (drive > 1)
+    BX_PANIC(("floppy_xfer: drive > 1\n"));
+
+  if (bx_dbg.floppy) {
+    BX_INFO(("drive=%u\n", (unsigned) drive));
+    BX_INFO(("offset=%u\n", (unsigned) offset));
+    BX_INFO(("bytes=%u\n", (unsigned) bytes));
+    BX_INFO(("direction=%s\n", (direction==FROM_FLOPPY)? "from" : "to"));
+    }
+
+#ifdef macintosh
+  if (strcmp(bx_options.floppya.path, SuperDrive))
+#endif
+    {
+    ret = lseek(BX_FD_THIS s.media[drive].fd, offset, SEEK_SET);
+    if (ret < 0) {
+      BX_PANIC(("could not perform lseek() on floppy image file\n"));
+      }
+    }
+
+  if (direction == FROM_FLOPPY) {
+#ifdef macintosh
+    if (!strcmp(bx_options.floppya.path, SuperDrive))
+      ret = fd_read((char *) buffer, offset, bytes);
+    else
+#endif
+      ret = ::read(BX_FD_THIS s.media[drive].fd, (bx_ptr_t) buffer, bytes);
+    if (ret < int(bytes)) {
+      /* ??? */
+      if (ret > 0) {
+        BX_INFO(("partial read() on floppy image returns %u/%u\n",
+          (unsigned) ret, (unsigned) bytes));
+        memset(buffer + ret, 0, bytes - ret);
+        }
+      else {
+        BX_INFO(("read() on floppy image returns 0\n"));
+        memset(buffer, 0, bytes);
+        }
+      }
+    }
+
+  else { // TO_FLOPPY
+#ifdef macintosh
+    if (!strcmp(bx_options.floppya.path, SuperDrive))
+      ret = fd_write((char *) buffer, offset, bytes);
+    else
+#endif
+      ret = ::write(BX_FD_THIS s.media[drive].fd, (bx_ptr_t) buffer, bytes);
+    if (ret < int(bytes)) {
+      BX_PANIC(("could not perform write() on floppy image file\n"));
+      }
+    }
+}
+
+
+
+  void
+bx_floppy_ctrl_c::timer_handler(void *this_ptr)
+{
+#if defined(SIMX86)
+  printf("Floppy timer\n");
+#endif
+
+  bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr;
+
+  class_ptr->timer();
+}
+
+  void
+bx_floppy_ctrl_c::timer()
+{
+  switch ( BX_FD_THIS s.pending_command ) {
+    case 0x07: // recal
+      BX_FD_THIS s.pending_command = 0;
+      /* write ready, not busy */
+      BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
+#if BX_SUPPORT_SID
+      floppy_component->drive_trigger_irq_pin();
+#else
+      BX_FD_THIS devices->pic->trigger_irq(6);
+#endif
+      goto reset_changeline;
+      break;
+
+    case 0x0f: // seek
+      BX_FD_THIS s.pending_command = 0;
+      /* write ready, not busy */
+      BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
+#if BX_SUPPORT_SID
+      floppy_component->drive_trigger_irq_pin();
+#else
+      BX_FD_THIS devices->pic->trigger_irq(6);
+#endif
+      goto reset_changeline;
+      break;
+
+
+    case 0x4a: /* read ID */
+    case 0xc5: // write normal data
+    case 0xe6: // read normal data
+      BX_FD_THIS s.pending_command = 0;
+      /* read ready, busy */
+      BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO;
+#if BX_SUPPORT_SID
+      floppy_component->drive_trigger_irq_pin();
+#else
+      BX_FD_THIS devices->pic->trigger_irq(6);
+#endif
+      break;
+
+    case 0xfe: // (contrived) RESET
+      reset(BX_RESET_SOFTWARE);
+      BX_FD_THIS s.pending_command = 0;
+      BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
+#if BX_SUPPORT_SID
+      floppy_component->drive_trigger_irq_pin();
+#else
+      BX_FD_THIS devices->pic->trigger_irq(6);
+#endif
+      break;
+
+    default:
+      BX_PANIC(("floppy:timer(): unknown case %02x\n",
+        (unsigned) BX_FD_THIS s.pending_command));
+    }
+  return;
+
+reset_changeline:
+  unsigned drive = BX_FD_THIS s.DOR & 0x3;
+  if (drive > 1) return;
+  if (BX_FD_THIS s.media_present[drive])
+    BX_FD_THIS s.DIR &= ~0x80; // clear disk change line
+}
+
+#if BX_SUPPORT_SID
+void
+bx_floppy_ctrl_c::dma_write(Bit32u phy_addr)
+#else
+  void
+bx_floppy_ctrl_c::dma_write(Bit8u *data_byte)
+#endif
+{
+  // A DMA write is from I/O to Memory
+  // We need to return then next data byte from the floppy buffer
+  // to be transfered via the DMA to memory. (read block from floppy)
+
+
+#if BX_SUPPORT_SID
+  floppy_component->dma_write(phy_addr, s.floppy_buffer[s.floppy_buffer_index++]);
+#else
+  *data_byte = BX_FD_THIS s.floppy_buffer[BX_FD_THIS s.floppy_buffer_index++];
+#endif
+
+  if (BX_FD_THIS s.floppy_buffer_index >= 512) {
+    Bit8u drive;
+
+    drive = BX_FD_THIS s.DOR & 0x03;
+    increment_sector(); // increment to next sector before retrieving next one
+    BX_FD_THIS s.floppy_buffer_index = 0;
+#if BX_SUPPORT_SID
+    if (floppy_component->terminal_count()) {
+#else
+    if (bx_pc_system.TC) { // Terminal Count line, done
+#endif
+      BX_FD_THIS s.pending_command = 0;
+      BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+      BX_FD_THIS s.result_size = 7;
+      BX_FD_THIS s.result_index = 0;
+      BX_FD_THIS s.result[0] = (BX_FD_THIS s.head[drive] << 2) | drive;
+      BX_FD_THIS s.result[1] = 0;
+      BX_FD_THIS s.result[2] = 0;
+      BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
+      BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
+      BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
+      BX_FD_THIS s.result[6] = 2;
+
+      if (bx_dbg.floppy) {
+        BX_INFO(("<<READ DONE>>\n"));
+        BX_INFO(("AFTER\n"));
+        BX_INFO(("  drive    = %u\n", (unsigned) drive));
+        BX_INFO(("  head     = %u\n", (unsigned) BX_FD_THIS s.head[drive]));
+        BX_INFO(("  cylinder = %u\n", (unsigned) BX_FD_THIS s.cylinder[drive]));
+        BX_INFO(("  sector   = %u\n", (unsigned) BX_FD_THIS s.sector[drive]));
+        }
+
+#if BX_SUPPORT_SID
+      floppy_component->drive_trigger_irq_pin();
+      floppy_component->channel_request(FLOPPY_DMA_CHAN, 0);
+#else
+      BX_FD_THIS devices->pic->trigger_irq(6);
+      bx_pc_system.set_DRQ(FLOPPY_DMA_CHAN, 0);
+#endif
+      }
+    else { // more data to transfer
+      Bit32u logical_sector;
+      logical_sector = (BX_FD_THIS s.cylinder[drive] * 2 *
+                        BX_FD_THIS s.media[drive].sectors_per_track) +
+                       (BX_FD_THIS s.head[drive] *
+                        BX_FD_THIS s.media[drive].sectors_per_track) +
+                       (BX_FD_THIS s.sector[drive] - 1);
+      floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
+                  512, FROM_FLOPPY);
+      }
+    }
+}
+
+#if BX_SUPPORT_SID
+  void
+bx_floppy_ctrl_c::dma_read(Bit32u phy_addr)
+#else
+  void
+bx_floppy_ctrl_c::dma_read(Bit8u *data_byte)
+#endif
+{
+  // A DMA read is from Memory to I/O
+  // We need to write the data_byte which was already transfered from memory
+  // via DMA to I/O (write block to floppy)
+
+  Bit8u drive;
+  Bit32u logical_sector;
+
+#if BX_SUPPORT_SID
+  floppy_component->dma_read(phy_addr, & s.floppy_buffer[s.floppy_buffer_index++]);
+#else
+  BX_FD_THIS s.floppy_buffer[BX_FD_THIS s.floppy_buffer_index++] = *data_byte;
+#endif
+
+  if (BX_FD_THIS s.floppy_buffer_index >= 512) {
+    drive = BX_FD_THIS s.DOR & 0x03;
+    logical_sector = (BX_FD_THIS s.cylinder[drive] * 2 * BX_FD_THIS s.media[drive].sectors_per_track) +
+                     (BX_FD_THIS s.head[drive] * BX_FD_THIS s.media[drive].sectors_per_track) +
+                     (BX_FD_THIS s.sector[drive] - 1);
+    floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
+                512, TO_FLOPPY);
+    increment_sector(); // increment to next sector after writing current one
+    BX_FD_THIS s.floppy_buffer_index = 0;
+#if BX_SUPPORT_SID
+    if (floppy_component->terminal_count()) {
+#else
+    if (bx_pc_system.TC) { // Terminal Count line, done
+#endif
+      BX_FD_THIS s.pending_command = 0;
+      BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+      BX_FD_THIS s.result_size = 7;
+      BX_FD_THIS s.result_index = 0;
+      BX_FD_THIS s.result[0] = (BX_FD_THIS s.head[drive] << 2) | drive;
+      BX_FD_THIS s.result[1] = 0;
+      BX_FD_THIS s.result[2] = 0;
+      BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
+      BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
+      BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
+      BX_FD_THIS s.result[6] = 2;
+      if (bx_dbg.floppy) {
+        BX_INFO(("<<WRITE DONE>>\n"));
+        BX_INFO(("AFTER\n"));
+        BX_INFO(("  drive    = %u\n", (unsigned) drive));
+        BX_INFO(("  head     = %u\n", (unsigned) BX_FD_THIS s.head[drive]));
+        BX_INFO(("  cylinder = %u\n", (unsigned) BX_FD_THIS s.cylinder[drive]));
+        BX_INFO(("  sector   = %u\n", (unsigned) BX_FD_THIS s.sector[drive]));
+        }
+
+#if BX_SUPPORT_SID
+      floppy_component->drive_trigger_irq_pin();
+      floppy_component->channel_request(FLOPPY_DMA_CHAN, 0);
+#else
+      BX_FD_THIS devices->pic->trigger_irq(6);
+      bx_pc_system.set_DRQ(FLOPPY_DMA_CHAN, 0);
+#endif
+      }
+    else { // more data to transfer
+      } // else
+    } // if BX_FD_THIS s.floppy_buffer_index >= 512
+}
+
+
+
+  void
+bx_floppy_ctrl_c::increment_sector(void)
+{
+  Bit8u drive;
+
+  drive = BX_FD_THIS s.DOR & 0x03;
+
+  // values after completion of data xfer
+  // ??? calculation depends on base_count being multiple of 512
+  BX_FD_THIS s.sector[drive] ++;
+  if (BX_FD_THIS s.sector[drive] > BX_FD_THIS s.media[drive].sectors_per_track) {
+    BX_FD_THIS s.sector[drive] -= BX_FD_THIS s.media[drive].sectors_per_track;
+    BX_FD_THIS s.head[drive] ++;
+    if (BX_FD_THIS s.head[drive] > 1) {
+      BX_FD_THIS s.head[drive] = 0;
+      BX_FD_THIS s.cylinder[drive] ++;
+      if (BX_FD_THIS s.cylinder[drive] >= BX_FD_THIS s.media[drive].tracks) {
+        // Set to 1 past last possible cylinder value.
+        // I notice if I set it to tracks-1, prama linux won't boot.
+        BX_FD_THIS s.cylinder[drive] = BX_FD_THIS s.media[drive].tracks;
+        BX_INFO(("increment_sector: clamping cylinder to max\n"));
+        }
+      }
+    }
+}
+
+  unsigned
+bx_floppy_ctrl_c::set_media_status(unsigned drive, unsigned status)
+{
+  char *path;
+  unsigned type;
+
+  // if setting to the current value, nothing to do
+  if (status == BX_FD_THIS s.media_present[drive])
+    return(status);
+
+  if (status == 0) {
+    // eject floppy
+    if (BX_FD_THIS s.media[drive].fd >= 0) {
+      close( BX_FD_THIS s.media[drive].fd );
+      BX_FD_THIS s.media[drive].fd = -1;
+      }
+    BX_FD_THIS s.media_present[drive] = 0;
+    BX_FD_THIS s.DIR |= 0x80; // disk changed line
+    return(0);
+    }
+  else {
+    // insert floppy
+    if (drive == 0) {
+      path = bx_options.floppya.path;
+      type = bx_options.floppya.type;
+      }
+    else {
+      path = bx_options.floppyb.path;
+      type = bx_options.floppyb.type;
+      }
+    if (evaluate_media(type, path, & BX_FD_THIS s.media[drive])) {
+      BX_FD_THIS s.media_present[drive] = 1;
+      BX_FD_THIS s.DIR |= 0x80; // disk changed line
+      return(1);
+      }
+    else {
+      BX_FD_THIS s.media_present[drive] = 0;
+      return(0);
+      }
+    }
+}
+
+  unsigned
+bx_floppy_ctrl_c::get_media_status(unsigned drive)
+{
+  return( BX_FD_THIS s.media_present[drive] );
+}
+
+#if BX_SUPPORT_SID
+  Boolean
+bx_floppy_ctrl_c::evaluate_media(unsigned type, const char *path, floppy_t *media)
+#else
+  Boolean
+bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media)
+#endif
+{
+  struct stat stat_buf;
+  int ret;
+  char sTemp[1024];
+
+  if (type == BX_FLOPPY_NONE)
+    return(0);
+
+  // open media file (image file or device)
+#ifdef macintosh
+  media->fd = 0;
+  if (strcmp(bx_options.floppya.path, SuperDrive))
+#endif
+    media->fd = open(path, O_RDWR
+#ifdef O_BINARY
+                   | O_BINARY
+#endif
+                  );
+
+  if (media->fd < 0) {
+    BX_INFO(( "floppy open of %s:\n",path,strerror(errno) ));
+    return(0);
+    }
+
+#if BX_WITH_MACOS
+  if (!strcmp(bx_options.floppya.path, SuperDrive))
+    ret = fd_stat(&stat_buf);
+  else
+    ret = fstat(media->fd, &stat_buf);
+#elif BX_WITH_WIN32
+  stat_buf.st_mode = S_IFCHR;
+  // maybe replace with code that sets ret to -1 if the disk is not available
+  ret = 0;
+#else
+  // unix
+  ret = fstat(media->fd, &stat_buf);
+#endif
+  if (ret) {
+    BX_PANIC(("fstat()'ing floppy 0 drive image file returns error!\n"));
+    return(0);
+    }
+
+  if ( S_ISREG(stat_buf.st_mode) ) {
+    // regular file
+    switch (type) {
+      case BX_FLOPPY_720K: // 720K 3.5"
+        media->type              = BX_FLOPPY_720K;
+        media->sectors_per_track = 9;
+        media->tracks            = 80;
+        media->heads             = 2;
+        break;
+      case BX_FLOPPY_1_2: // 1.2M 5.25"
+        media->type              = BX_FLOPPY_1_2;
+        media->sectors_per_track = 15;
+        media->tracks            = 80;
+        media->heads             = 2;
+        break;
+      case BX_FLOPPY_1_44: // 1.44M 3.5"
+        media->type              = BX_FLOPPY_1_44;
+        if (stat_buf.st_size <= 1474560) {
+          media->sectors_per_track = 18;
+          media->tracks            = 80;
+          media->heads             = 2;
+          }
+        else if (stat_buf.st_size == 1720320) {
+          media->sectors_per_track = 21;
+          media->tracks            = 80;
+          media->heads             = 2;
+          }
+       else if (stat_buf.st_size == 1763328) {
+          media->sectors_per_track = 21;
+          media->tracks            = 82;
+          media->heads             = 2;
+         }
+        else {
+          BX_INFO(("evaluate_media: file '%s' of unknown size %lu\n",
+            path, (unsigned long) stat_buf.st_size));
+          return(0);
+          }
+        break;
+      case BX_FLOPPY_2_88: // 2.88M 3.5"
+        media->type              = BX_FLOPPY_2_88;
+        media->sectors_per_track = 36;
+        media->tracks            = 80;
+        media->heads             = 2;
+        break;
+      default:
+        BX_PANIC(("evaluate_media: unknown media type\n"));
+      }
+    media->sectors = media->heads * media->tracks * media->sectors_per_track;
+    return(1); // success
+    }
+
+  else if ( S_ISCHR(stat_buf.st_mode)
+#if BX_WITH_MACOS == 0
+#ifdef S_ISBLK
+            || S_ISBLK(stat_buf.st_mode)
+#endif
+#endif
+           ) {
+    // character or block device
+    // assume media is formatted to typical geometry for drive
+    switch (type) {
+      case BX_FLOPPY_720K: // 720K 3.5"
+        media->type              = BX_FLOPPY_720K;
+        media->sectors_per_track = 9;
+        media->tracks            = 80;
+        media->heads             = 2;
+        break;
+      case BX_FLOPPY_1_2: // 1.2M 5.25"
+        media->type              = BX_FLOPPY_1_2;
+        media->sectors_per_track = 15;
+        media->tracks            = 80;
+        media->heads             = 2;
+        break;
+      case BX_FLOPPY_1_44: // 1.44M 3.5"
+        media->type              = BX_FLOPPY_1_44;
+        media->sectors_per_track = 18;
+        media->tracks            = 80;
+        media->heads             = 2;
+        break;
+      case BX_FLOPPY_2_88: // 2.88M 3.5"
+        media->type              = BX_FLOPPY_2_88;
+        media->sectors_per_track = 36;
+        media->tracks            = 80;
+        media->heads             = 2;
+        break;
+      default:
+        BX_PANIC(("evaluate_media: unknown media type\n"));
+      }
+    media->sectors = media->heads * media->tracks * media->sectors_per_track;
+    return(1); // success
+    }
+  else {
+    // unknown file type
+    BX_INFO(("unknown mode type\n"));
+    return(0);
+    }
+}
+
+#if BX_SUPPORT_SID
+void
+bx_floppy_ctrl_c::call_evaluate_media(unsigned type, const char * path, unsigned floppy_num)
+{
+  if (evaluate_media(type, path, & BX_FD_THIS s.media[floppy_num]))
+        BX_FD_THIS s.media_present[floppy_num] = 1;
+}
+#endif
diff --git a/sid/component/bochs/floppy/floppy.h b/sid/component/bochs/floppy/floppy.h
new file mode 100644 (file)
index 0000000..46a950e
--- /dev/null
@@ -0,0 +1,155 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+
+#define FROM_FLOPPY 10
+#define TO_FLOPPY   11
+
+
+#if BX_USE_FD_SMF
+#  define BX_FD_SMF  static
+#  define BX_FD_THIS bx_floppy.
+#else
+#  define BX_FD_SMF
+#  define BX_FD_THIS this->
+#endif
+
+#if BX_SUPPORT_SID
+class floppy;
+#endif
+typedef struct {
+  int      fd;         /* file descriptor of floppy image file */
+  unsigned sectors_per_track;    /* number of sectors/track */
+  unsigned sectors;    /* number of formatted sectors on diskette */
+  unsigned tracks;      /* number of tracks */
+  unsigned heads;      /* number of heads */
+  unsigned type;
+  } floppy_t;
+
+class bx_floppy_ctrl_c : public logfunctions {
+public:
+
+  bx_floppy_ctrl_c(void);
+  ~bx_floppy_ctrl_c(void);
+#if BX_SUPPORT_SID
+  BX_FD_SMF void   init(floppy *floppy_comp);
+#else
+  BX_FD_SMF void   init(bx_devices_c *d, bx_cmos_c *cmos);
+#endif
+  BX_FD_SMF void   reset(unsigned source);
+#if BX_SUPPORT_SID
+  BX_FD_SMF void   dma_write(Bit32u phy_addr);
+  BX_FD_SMF void   dma_read(Bit32u phy_addr);
+#else  
+  BX_FD_SMF void   dma_write(Bit8u *data_byte);
+  BX_FD_SMF void   dma_read(Bit8u *data_byte);
+#endif
+  BX_FD_SMF unsigned set_media_status(unsigned drive, unsigned status);
+  BX_FD_SMF unsigned get_media_status(unsigned drive);
+
+private:
+
+  struct {
+    Bit8u   data_rate;
+
+    Bit8u   command[10]; /* largest command size ??? */
+    Bit8u   command_index;
+    Bit8u   command_size;
+    Boolean command_complete;
+    Bit8u   pending_command;
+
+    Bit8u   result[10];
+    Bit8u   result_index;
+    Bit8u   result_size;
+
+    Bit8u   DOR; // Digital Ouput Register
+    Bit8u   TDR; // Tape Drive Register
+    Bit8u   cylinder[4]; // really only using 2 drives
+    Bit8u   head[4];     // really only using 2 drives
+    Bit8u   sector[4];   // really only using 2 drives
+
+    /* MAIN STATUS REGISTER
+     * b7: MRQ: main request 1=data register ready     0=data register not ready
+     * b6: DIO: data input/output:
+     *     1=controller->CPU (ready for data read)
+     *     0=CPU->controller (ready for data write)
+     * b5: NDMA: non-DMA mode: 1=controller not in DMA modes
+     *                         0=controller in DMA mode
+     * b4: BUSY: instruction(device busy) 1=active 0=not active
+     * b3-0: ACTD, ACTC, ACTB, ACTA:
+     *       drive D,C,B,A in positioning mode 1=active 0=not active
+     */
+    Bit8u   main_status_reg;
+
+    Bit8u   status_reg0;
+    Bit8u   status_reg1;
+    Bit8u   status_reg2;
+    Bit8u   status_reg3;
+
+    floppy_t media[2];
+    unsigned num_supported_floppies;
+    Bit8u    floppy_buffer[512+2]; // 2 extra for good measure
+    unsigned floppy_buffer_index;
+    int      floppy_timer_index;
+    Boolean  media_present[2];
+    Bit8u    DIR; // Digital Input Register:
+                  // b7: 0=diskette is present and has not been changed
+                  //     1=diskette missing or changed
+    } s;  // state information
+
+#if BX_SUPPORT_SID
+  floppy *floppy_component;
+#else
+  bx_devices_c *devices;
+#endif
+
+  static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
+  static void   write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
+#if BX_SUPPORT_SID
+ public:
+#endif
+#if !BX_USE_FD_SMF
+  Bit32u read(Bit32u address, unsigned io_len);
+  void   write(Bit32u address, Bit32u value, unsigned io_len);
+#endif
+#if BX_SUPPORT_SID
+ private:
+#endif
+  BX_FD_SMF void   floppy_command(void);
+  BX_FD_SMF void   floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer, Bit32u bytes, Bit8u direction);
+  static void   timer_handler(void *);
+
+public:
+  BX_FD_SMF void   timer(void);
+  BX_FD_SMF void   increment_sector(void);
+#if BX_SUPPORT_SID
+  BX_FD_SMF void call_evaluate_media(unsigned type, const char * path, unsigned floppy_num);
+  BX_FD_SMF Boolean evaluate_media(unsigned type, const char *path, floppy_t *floppy);
+#else
+  BX_FD_SMF Boolean evaluate_media(unsigned type, char *path, floppy_t *floppy);
+#endif
+  };
+
+#if BX_SUPPORT_SID
+extern bx_floppy_ctrl_c bx_floppy;
+#endif
diff --git a/sid/component/bochs/floppy/sid-floppy-wrapper.cc b/sid/component/bochs/floppy/sid-floppy-wrapper.cc
new file mode 100644 (file)
index 0000000..9462e65
--- /dev/null
@@ -0,0 +1,245 @@
+// sid-floppy-wrapper.cc - SID import of the bochs floppy component.  -*- C++ -*-
+
+// Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
+// This file is part of SID and is licensed under the GPL.
+// See the file COPYING.SID for conditions for redistribution.
+
+#include "sid-floppy-wrapper.h"
+
+floppy::floppy ()
+    : init_pin(this, & floppy::init),
+      reset_pin(this, & floppy::reset),
+      command_delay_pin(this, & floppy::command_delay),
+      dma_channel_pin(this, & floppy::dma_channel),
+      ports_0x3f2_0x3f7_bus(this, & floppy::read_port_0x3f2_0x3f7, & floppy::write_port_0x3f2_0x3f7),
+      floppy_dma_channel(2), floppy_irq_number(6), floppy_a_type("1.44"), floppy_b_type("none"),
+      cmos_registers_bus(0), dma_channels_bus(0), dma_bus(0)
+{
+  add_pin("terminal-count", & this->terminal_count_pin);
+
+  add_pin("trigger-irq", & this->trigger_irq_pin);
+  add_pin("command-delay-control", & this->command_delay_control_pin);
+
+  add_pin("init", & this->init_pin);
+  add_pin("reset", & this->reset_pin);
+  add_pin("command-delay", & this->command_delay_pin);
+
+  add_bus("ports-0x3f2-0x3f7", & this->ports_0x3f2_0x3f7_bus);
+
+  add_accessor("cmos-registers", & this->cmos_registers_bus);
+  add_accessor("dma-channels", & this->dma_channels_bus);
+  add_accessor("dma", & this->dma_bus);
+
+  add_pin("read-write", & this->read_write_pin);
+  add_pin("dma-channel", & this->dma_channel_pin);
+
+  add_attribute("floppy-a-type", & this->floppy_a_type, "setting");
+  add_attribute("floppy-b-type", & this->floppy_b_type, "setting");
+
+  add_attribute("floppy-a-path", & this->floppy_a_path, "setting");
+  add_attribute("floppy-b-path", & this->floppy_b_path, "setting");
+
+  add_attribute("floppy-a-inserted?", & this->floppy_a_is_inserted, "setting");
+  add_attribute("floppy-b-inserted?", & this->floppy_b_is_inserted, "setting");
+
+  add_attribute("dma-channel", & this->floppy_dma_channel, "setting");
+  add_attribute("irq-number", & this->floppy_irq_number, "setting");
+}
+
+void
+floppy::init(host_int_4)
+{
+  host_int_1 num_floppies = 0;
+  host_int_1 bx_floppy_type = BX_FLOPPY_NONE;
+  little_int_1 old_register_value;
+  little_int_1 new_register_value;
+
+  bx_floppy.init(this);
+
+  // Check for floppy a:
+
+  // start out with no drive 0 and no drive 1
+  old_register_value = 0x0;
+
+  if (cmos_registers_bus)
+    cmos_registers_bus->write(host_int_4(0x10), old_register_value);
+
+  if (floppy_a_type == "none")
+    {
+      new_register_value = (old_register_value & 0x0f) | 0x00;
+      bx_floppy_type = BX_FLOPPY_NONE;
+    }
+  else if (floppy_a_type == "1.2")
+    {
+      new_register_value = (old_register_value & 0x0f) | 0x20;
+      bx_floppy_type = BX_FLOPPY_1_2;
+    }
+  else if (floppy_a_type == "720")
+    {
+      new_register_value = (old_register_value & 0x0f) | 0x30;
+      bx_floppy_type = BX_FLOPPY_720K;
+    }
+  else if (floppy_a_type == "1.44")
+    {
+      new_register_value = (old_register_value & 0x0f) | 0x40;
+      bx_floppy_type = BX_FLOPPY_1_44;
+    }
+  else if (floppy_a_type == "2.88")
+    {
+      new_register_value = (old_register_value & 0x0f) | 0x50;
+      bx_floppy_type = BX_FLOPPY_2_88;
+    }
+  else
+    cerr << "floppy: Invalid floppy a type." << endl;
+
+  if (bx_floppy_type != BX_FLOPPY_NONE)
+    {
+      num_floppies++;
+      if (floppy_a_is_inserted)
+        bx_floppy.call_evaluate_media(bx_floppy_type, floppy_a_path.c_str(), 0);
+    }
+
+  // Check for floppy b:
+  if (floppy_b_type == "none")
+    {
+      new_register_value = (new_register_value & 0xf0) | 0x00;
+      bx_floppy_type = BX_FLOPPY_NONE;        
+    }
+  else if (floppy_b_type == "1.2")
+    {
+      new_register_value = (new_register_value & 0xf0) | 0x02;
+      bx_floppy_type = BX_FLOPPY_1_2;
+    }
+  else if (floppy_b_type == "720")
+    {
+      new_register_value = (new_register_value & 0xf0) | 0x03;
+      bx_floppy_type = BX_FLOPPY_720K;
+    }
+  else if (floppy_b_type == "1.44")
+    {
+      new_register_value = (new_register_value & 0xf0) | 0x04;
+      bx_floppy_type = BX_FLOPPY_1_44;
+    }
+  else if (floppy_b_type == "2.88")
+    {
+      new_register_value = (new_register_value & 0xf0) | 0x05;
+      bx_floppy_type = BX_FLOPPY_2_88;
+    }
+  else
+    cerr << "floppy: Invalid floppy b type." << endl;
+  
+  if (bx_floppy_type != BX_FLOPPY_NONE)
+    {
+      num_floppies++;
+      if (floppy_b_is_inserted)
+        bx_floppy.call_evaluate_media(bx_floppy_type, floppy_b_path.c_str(), 1);
+    }
+
+  if (cmos_registers_bus)
+    {
+      cmos_registers_bus->write(host_int_4(0x10), new_register_value);
+
+      cmos_registers_bus->read(host_int_4(0x14), old_register_value);
+
+      if (num_floppies > 0)
+        {
+          new_register_value = (old_register_value & 0x3e) | ((num_floppies - 1) << 6) | 1;
+          cmos_registers_bus->write(host_int_4(0x14), new_register_value);
+        }
+      else
+        {
+          new_register_value = old_register_value & 0x3e;
+          cmos_registers_bus->write(host_int_4(0x14), new_register_value);
+        }
+    }
+}
+
+void
+floppy::reset(host_int_4)
+{
+  bx_floppy.reset(BX_RESET_HARDWARE);
+}
+
+void
+floppy::drive_trigger_irq_pin(void)
+{
+  trigger_irq_pin.drive(floppy_irq_number);
+}
+
+void
+floppy::drive_command_delay_control_pin(host_int_4 value, bool regular)
+{
+  host_int_4 code = value | (regular << 31);
+
+  command_delay_control_pin.drive(code);
+}
+
+void
+floppy::channel_request(host_int_4 channel, little_int_1 val)
+{
+  if (dma_channels_bus)
+    dma_channels_bus->write(channel, val);
+  else
+    cerr << "floppy: dma-channels bus not connected." << endl;
+}
+
+bool
+floppy::terminal_count(void)
+{
+  return terminal_count_pin.sense();
+}
+
+bus::status
+floppy::read_port_0x3f2_0x3f7 (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+{
+  addr += 0x3f2;
+  data = bx_floppy.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+floppy::write_port_0x3f2_0x3f7 (host_int_4 addr, little_int_1 mask, little_int_1 data)
+{
+  addr += 0x3f2;
+  bx_floppy.write(addr, data, 1);
+  return bus::ok;
+}
+
+host_int_4
+floppy::dma_channel_number(void)
+{
+  return floppy_dma_channel;
+}
+
+void
+floppy::dma_channel(host_int_4 phy_addr)
+{
+  if (read_write_pin.sense())
+    // read mode
+    bx_floppy.dma_read(phy_addr);
+  else
+    // write mode
+    bx_floppy.dma_write(phy_addr);
+}
+
+void
+floppy::dma_write(host_int_4 addr, little_int_1 data)
+{
+  dma_bus->write(addr, data);
+}
+
+void
+floppy::dma_read(host_int_4 addr, unsigned char *data)
+{
+  little_int_1 read_data;
+
+  dma_bus->read(addr, read_data);
+
+  *data = read_data;
+}
+
+void
+floppy::command_delay(host_int_4)
+{
+  bx_floppy.timer();
+}
diff --git a/sid/component/bochs/floppy/sid-floppy-wrapper.h b/sid/component/bochs/floppy/sid-floppy-wrapper.h
new file mode 100644 (file)
index 0000000..6130962
--- /dev/null
@@ -0,0 +1,93 @@
+// sid-floppy-wrapper.h - SID import of the bochs floppy component.  -*- C++ -*-
+
+// Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
+// This file is part of SID and is licensed under the GPL.
+// See the file COPYING.SID for conditions for redistribution.
+
+#ifndef SID_FLOPPY_WRAPPER_DEF_H
+#define SID_FLOPPY_WRAPPER_DEF_H       1
+
+#include <sidtypes.h>
+#include <sidcomp.h>
+#include <sidcomputil.h>
+#include <sidpinutil.h>
+#include <sidbusutil.h>
+#include <sidattrutil.h>
+#include <sidcpuutil.h>
+#include <sidpinattrutil.h>
+#include <sidmiscutil.h>
+#include <sidwatchutil.h>
+#include <sidso.h>
+
+#include "bochs.h"
+
+using sid::component;
+using sid::bus;
+using sid::host_int_1;
+using sid::host_int_4;
+using sid::little_int_1;
+using sidutil::callback_word_bus;
+using sidutil::callback_pin;
+using sidutil::output_pin;
+using sidutil::input_pin;
+
+class floppy : public sidutil::fixed_pin_map_component,
+               public sidutil::fixed_accessor_map_component,
+               public sidutil::fixed_attribute_map_component,
+               public sidutil::no_relation_component,
+               public sidutil::fixed_bus_map_component
+{
+public:
+  floppy();
+  ~floppy() throw() {};
+
+  void init(host_int_4);
+  void reset(host_int_4);
+  void drive_trigger_irq_pin(void);
+  void drive_command_delay_control_pin(host_int_4 value, bool regular);
+  void channel_request(host_int_4 channel, little_int_1 val);
+  bool terminal_count(void);
+  host_int_4 dma_channel_number(void);
+  void dma_channel(host_int_4 phy_addr);
+  void dma_write(host_int_4 addr, little_int_1 data);
+  void dma_read(host_int_4 addr, unsigned char *data);
+  void command_delay(host_int_4);
+protected:
+
+  // read == 1, write == 0
+  input_pin read_write_pin;
+  callback_pin<floppy> dma_channel_pin;
+
+  input_pin terminal_count_pin;
+
+  callback_pin<floppy> command_delay_pin;
+  output_pin command_delay_control_pin;
+
+  output_pin trigger_irq_pin;
+
+  callback_pin<floppy> init_pin;
+  callback_pin<floppy> reset_pin;
+
+  bus::status read_port_0x3f2_0x3f7 (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x3f2_0x3f7 (host_int_4 addr, little_int_1 mask, little_int_1 data);
+
+  callback_word_bus<floppy, little_int_1> ports_0x3f2_0x3f7_bus;
+
+  bus *cmos_registers_bus;
+  bus *dma_channels_bus;
+  bus *dma_bus;
+
+  std::string floppy_a_type;
+  std::string floppy_b_type;
+
+  std::string floppy_a_path;
+  std::string floppy_b_path;
+
+  bool floppy_a_is_inserted;
+  bool floppy_b_is_inserted;
+
+  host_int_4 floppy_dma_channel;
+  host_int_4 floppy_irq_number;
+  bx_floppy_ctrl_c bx_floppy;
+};
+#endif // SID_FLOPPY_WRAPPER_DEF_H
index 8bb0a2a..304ddef 100644 (file)
@@ -217,17 +217,17 @@ x_gui::init(host_int_4)
   int x, y;   /* window position */
   unsigned int border_width = 4;  /* four pixels */
 #if BX_CPU_LEVEL < 2
-  char *window_name = "Bochs 8086 emulator, http://bochs.sourceforge.net/";
+  char *window_name = "SID Import of the Bochs 8086 Emulator";
 #elif BX_CPU_LEVEL == 2
-  char *window_name = "Bochs 80286 emulator, http://bochs.sourceforge.net/";
+  char *window_name = "SID Import of the Bochs 80286 Emulator";
 #elif BX_CPU_LEVEL == 3
-  char *window_name = "Bochs 80386 emulator, http://bochs.sourceforge.net/";
+  char *window_name = "SID Import of the Bochs 80386 Emulator";
 #elif BX_CPU_LEVEL == 4
-  char *window_name = "Bochs 80486 emulator, http://bochs.sourceforge.net/";
+  char *window_name = "SID Import of the Bochs 80486 Emulator";
 #else
-  char *window_name = "Bochs Pentium emulator, http://bochs.sourceforge.net/";
+  char *window_name = "SID Import of the Bochs Pentium Emulator";
 #endif
-  char *icon_name = "Bochs";
+  char *icon_name = "SID Bochs";
   Pixmap icon_pixmap;
   XSizeHints size_hints;
   char *display_name = NULL;
@@ -571,7 +571,6 @@ x_gui::update_display(host_int_4)
           dimension_x = x;
           dimension_y = y;
         }
-      XFlush(bx_x_display);
       dimensions_updated_pin.driven(0);
     }
 
@@ -659,7 +658,6 @@ x_gui::update_display(host_int_4)
                            (char *) string,
                            1);
         }
-      XFlush(bx_x_display);
       text_memory_updated_pin.driven(0);
     }
 }
index 0cc446b..3ed9907 100644 (file)
@@ -95,4 +95,5 @@ private:
 
   bool private_colormap;
 };
-#endif X_GUI_DEF_H
+#endif // X_GUI_DEF_H
+
index 5a750c3..146790c 100644 (file)
 
 
 #include "bochs.h"
+#if BX_SUPPORT_SID
 #include "sid-keyboard-wrapper.h"
 #define LOG_THIS
-
+#else
+#define LOG_THIS  bx_keyboard.
+#endif
 
 #define VERBOSE_KBD_DEBUG 0
 
@@ -40,7 +43,9 @@
 #define MOUSE_MODE_STREAM 11
 #define MOUSE_MODE_REMOTE 12
 #define MOUSE_MODE_WRAP   13
-
+#if BX_SUPPORT_SID==0
+bx_keyb_c bx_keyboard;
+#endif
 #if BX_USE_KEY_SMF
 #define this (&bx_keyboard)
 #endif
@@ -49,6 +54,9 @@
 
 bx_keyb_c::bx_keyb_c(void)
 {
+#if BX_SUPPORT_SID
+  bx_dbg.keyboard = 1;
+#endif
   // constructor
   // should zero out state info here???
   memset( &s, 0, sizeof(s) );
@@ -153,11 +161,11 @@ bx_keyb_c::init(bx_devices_c *d, bx_cmos_c *cmos)
     BX_KEY_THIS s.controller_Q[i] = 0;
   BX_KEY_THIS s.controller_Qsize = 0;
   BX_KEY_THIS s.controller_Qsource = 0;
-#if BX_SUPPORT_SID==0
+#if BX_SUPPORT_SID
+  kbd_component = kbd_comp;
+#else
   // mouse port installed on system board
   cmos->s.reg[0x14] |= 0x04;
-#else
-  kbd_component = kbd_comp;
 #endif
   BX_DEBUG(("Init.\n"));
 }
@@ -323,6 +331,8 @@ bx_keyb_c::write( Bit32u   address, Bit32u   value, unsigned io_len)
 
   if (bx_dbg.keyboard)
        BX_INFO(("keyboard: 8-bit write to %04x = %02x\n", (unsigned)address, (unsigned)value));
+
+
 //BX_DEBUG(("WRITE(%02x) = %02x\n", (unsigned) address,
 //      (unsigned) value));
 
@@ -1064,7 +1074,7 @@ bx_keyb_c::periodic( Bit32u   usec_delta )
   retval = BX_KEY_THIS s.kbd_controller.irq1_requested | (BX_KEY_THIS s.kbd_controller.irq12_requested << 1);
   BX_KEY_THIS s.kbd_controller.irq1_requested = 0;
   BX_KEY_THIS s.kbd_controller.irq12_requested = 0;
-#if BX_SUPPORT_SID==0
+
   if ( BX_KEY_THIS s.kbd_controller.timer_pending == 0 ) {
     return(retval);
     }
@@ -1076,7 +1086,7 @@ bx_keyb_c::periodic( Bit32u   usec_delta )
     BX_KEY_THIS s.kbd_controller.timer_pending -= usec_delta;
     return(retval);
     }
-#endif
+
   if (BX_KEY_THIS s.kbd_controller.outb) {
     return(retval);
     }
@@ -1131,7 +1141,6 @@ bx_keyb_c::activate_timer(void)
 {
   if (BX_KEY_THIS s.kbd_controller.timer_pending == 0) {
     BX_KEY_THIS s.kbd_controller.timer_pending = bx_options.keyboard_serial_delay;
-    kbd_component->drive_serial_delay_pin(bx_options.keyboard_serial_delay);
     }
 }
 
index 7a09837..c9e5892 100644 (file)
 
 #ifndef _PCKEY_H
 #define _PCKEY_H
+#if BX_SUPPORT_SID
 #include "keysymbols.h"
 class keyboard;
+#endif
+
 #define BX_KBD_ELEMENTS 16
 #define BX_MOUSE_BUFF_SIZE 48
 
@@ -35,7 +38,9 @@ class keyboard;
 #  define BX_KEY_SMF
 #  define BX_KEY_THIS this->
 #endif
-
+#if BX_SUPPORT_SID==0
+extern bx_keyb_c bx_keyboard;
+#endif
 class bx_keyb_c : public logfunctions {
 public:
   bx_keyb_c(void);
@@ -136,7 +141,13 @@ private:
          case 8:
            ret = 3;
            break;
-         };
+#if BX_SUPPORT_SID==0
+          default:
+#define LOG_THIS bx_keyboard.
+           BX_PANIC(("mouse: invalid resolution_cpmm"));
+#undef LOG_THIS
+#endif
+          };
          return ret;
        }
 
@@ -165,10 +176,10 @@ private:
     unsigned controller_Qsize;
     unsigned controller_Qsource; // 0=keyboard, 1=mouse
     } s; // State information for saving/loading
-#if BX_SUPPORT_SID==0
-  bx_devices_c *devices;
-#else
+#if BX_SUPPORT_SID
   keyboard *kbd_component;
+#else
+  bx_devices_c *devices;
 #endif
   BX_KEY_SMF void     resetinternals(Boolean powerup);
   BX_KEY_SMF void     set_kbd_clock_enable(Bit8u   value);
index 48592b3..f367240 100644 (file)
@@ -11,21 +11,44 @@ keyboard::keyboard ()
       generate_scancode_pin(this, & keyboard::generate_scancode),
       update_keyboard_pin(this, & keyboard::update_keyboard),
       port_0x60_bus(this, & keyboard::read_port_0x60, & keyboard::write_port_0x60),
-      port_0x64_bus(this, & keyboard::read_port_0x64, & keyboard::write_port_0x64)
+      port_0x64_bus(this, & keyboard::read_port_0x64, & keyboard::write_port_0x64),
+      cmos_registers_bus(0), timer_delta(100), keyboard_irq_number(1), have_mouse(false)
 {
+  add_pin("trigger-irq", & this->trigger_irq_pin);
+  add_pin("enable-a20", & this->enable_a20_pin);
+  add_pin("a20-enabled", & this->a20_enabled_pin);
+
   add_pin("init", & this->init_pin);
   add_pin("generate-scancode", & this->generate_scancode_pin);
   add_pin("update-keyboard", & this->update_keyboard_pin);
-  add_pin("serial-delay", & this->serial_delay_pin);
 
   add_bus("port-0x60", & this->port_0x60_bus);
   add_bus("port-0x64", & this->port_0x64_bus);
+
+  add_attribute("timer-delta", & this->timer_delta, "setting");
+  add_attribute("keyboard-irq-number", & this->keyboard_irq_number, "setting");
+  add_attribute("have-mouse?", & this->have_mouse, "setting");
+
+  add_accessor("cmos-registers", & this->cmos_registers_bus);
 }
 
 void
 keyboard::init(host_int_4)
 {
   bx_keyboard.init(this);
+  if (have_mouse)
+    {
+      // mouse port installed on system board
+      if (cmos_registers_bus)
+        {
+          little_int_1 old_register_value;
+          little_int_1 new_register_value;
+
+          cmos_registers_bus->read(host_int_4(0x14), old_register_value);
+          new_register_value = old_register_value | 0x04;
+          cmos_registers_bus->write(host_int_4(0x14), new_register_value);
+        }
+    }
 }
 
 void
@@ -37,21 +60,22 @@ keyboard::generate_scancode(host_int_4 code)
 void
 keyboard::update_keyboard(host_int_4)
 {
-  bx_keyboard.periodic(0);
+  unsigned val = bx_keyboard.periodic(timer_delta);
+
+  if((val & 0x01))
+    trigger_irq_pin.drive(keyboard_irq_number);
 }
 
 void
-keyboard::drive_serial_delay_pin(host_int_4 delay)
+keyboard::drive_enable_a20_pin(host_int_4 value)
+{
+  enable_a20_pin.drive(value);
+}
+
+host_int_4
+keyboard::sense_a20_enabled_pin(void)
 {
-  // The serial-delay pin is intended to be connected to
-  // a sid-sched component's N-control pin, and the
-  // update-keyboard pin is intended to be connected to
-  // the corresponding N-event pin.  Since update-keyboard
-  // should be driven regularly, we must ensure that the
-  // the top bit (the regular? flag) of the code driven on
-  // the serial-delay pin is 1.
-  host_int_4 code = delay | 0x80000000;
-  serial_delay_pin.drive(code);
+  return a20_enabled_pin.sense();
 }
 
 bus::status
index a954767..1385c9e 100644 (file)
@@ -28,9 +28,12 @@ using sid::little_int_1;
 using sidutil::callback_word_bus;
 using sidutil::callback_pin;
 using sidutil::output_pin;
+using sidutil::input_pin;
+using sidutil::word_bus;
+using sidutil::control_register_bus;
 
 class keyboard : public sidutil::fixed_pin_map_component,
-                 public sidutil::no_accessor_component,
+                 public sidutil::fixed_accessor_map_component,
                  public sidutil::fixed_attribute_map_component,
                  public sidutil::no_relation_component,
                  public sidutil::fixed_bus_map_component
@@ -42,17 +45,18 @@ public:
   void init(host_int_4);
   void generate_scancode(host_int_4 code);
   void update_keyboard(host_int_4);
-
-  void drive_serial_delay_pin(host_int_4 delay);
-  
+  void drive_enable_a20_pin(host_int_4 value);
+  host_int_4 sense_a20_enabled_pin(void);
 protected:
 
+  output_pin trigger_irq_pin;
+  output_pin enable_a20_pin;
+  input_pin a20_enabled_pin;
+  
   callback_pin<keyboard> init_pin;
   callback_pin<keyboard> generate_scancode_pin;
   callback_pin<keyboard> update_keyboard_pin;
 
-  output_pin serial_delay_pin;
-
   bus::status read_port_0x60 (host_int_4 addr, little_int_1 mask, little_int_1 & data);
   bus::status write_port_0x60 (host_int_4 addr, little_int_1 mask, little_int_1 data);
 
@@ -62,6 +66,12 @@ protected:
   callback_word_bus<keyboard, little_int_1> port_0x60_bus;
   callback_word_bus<keyboard, little_int_1> port_0x64_bus;
 
+  bus *cmos_registers_bus;
+
+  host_int_4 timer_delta;
+  host_int_4 keyboard_irq_number;
+  bool have_mouse;
+
   bx_keyb_c bx_keyboard;
 };
 #endif // SID_KEYBOARD_WRAPPER_DEF_H
diff --git a/sid/component/bochs/pic/Makefile.am b/sid/component/bochs/pic/Makefile.am
new file mode 100644 (file)
index 0000000..24676d1
--- /dev/null
@@ -0,0 +1,11 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../cpu
+
+noinst_LTLIBRARIES = libpic.la
+
+libpic_la_SOURCES = sid-pic-wrapper.cc sid-pic-wrapper.h pic.cc pic.h
+
+libpic_la_LDFLAGS = -no-undefined
diff --git a/sid/component/bochs/pic/Makefile.in b/sid/component/bochs/pic/Makefile.in
new file mode 100644 (file)
index 0000000..95a2870
--- /dev/null
@@ -0,0 +1,412 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+APIC_OBJS = @APIC_OBJS@
+AR = @AR@
+AS = @AS@
+AS_DYNAMIC_INCS = @AS_DYNAMIC_INCS@
+AS_DYNAMIC_OBJS = @AS_DYNAMIC_OBJS@
+BX_LOADER_OBJS = @BX_LOADER_OBJS@
+BX_SPLIT_HD_SUPPORT = @BX_SPLIT_HD_SUPPORT@
+CC = @CC@
+CDROM_OBJS = @CDROM_OBJS@
+CD_UP_ONE = @CD_UP_ONE@
+CD_UP_TWO = @CD_UP_TWO@
+CFP = @CFP@
+COMMAND_SEPARATOR = @COMMAND_SEPARATOR@
+CPP_SUFFIX = @CPP_SUFFIX@
+CXX = @CXX@
+CXXFP = @CXXFP@
+DASH = @DASH@
+DEBUGGER_VAR = @DEBUGGER_VAR@
+DISASM_VAR = @DISASM_VAR@
+DLLTOOL = @DLLTOOL@
+DYNAMIC_VAR = @DYNAMIC_VAR@
+EXE = @EXE@
+EXEEXT = @EXEEXT@
+EXTERNAL_DEPENDENCY = @EXTERNAL_DEPENDENCY@
+FPU_GLUE_OBJ = @FPU_GLUE_OBJ@
+FPU_VAR = @FPU_VAR@
+GUI_LINK_OPTS = @GUI_LINK_OPTS@
+GUI_LINK_OPTS_TERM = @GUI_LINK_OPTS_TERM@
+GUI_OBJS = @GUI_OBJS@
+GZIP = @GZIP@
+INLINE_VAR = @INLINE_VAR@
+INSTRUMENT_DIR = @INSTRUMENT_DIR@
+INSTRUMENT_VAR = @INSTRUMENT_VAR@
+IOAPIC_OBJS = @IOAPIC_OBJS@
+IODEV_LIB_VAR = @IODEV_LIB_VAR@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LINK = @LINK@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKELIB = @MAKELIB@
+NE2K_OBJS = @NE2K_OBJS@
+NM = @NM@
+NONINLINE_VAR = @NONINLINE_VAR@
+OBJDUMP = @OBJDUMP@
+OFP = @OFP@
+PACKAGE = @PACKAGE@
+PCI_OBJ = @PCI_OBJ@
+PRIMARY_TARGET = @PRIMARY_TARGET@
+RANLIB = @RANLIB@
+READLINE_LIB = @READLINE_LIB@
+RFB_LIBS = @RFB_LIBS@
+RMCOMMAND = @RMCOMMAND@
+SB16_OBJS = @SB16_OBJS@
+SLASH = @SLASH@
+SUFFIX_LINE = @SUFFIX_LINE@
+TAR = @TAR@
+VERSION = @VERSION@
+VIDEO_OBJS = @VIDEO_OBJS@
+sidtarget_arm = @sidtarget_arm@
+sidtarget_m32r = @sidtarget_m32r@
+sidtarget_m68k = @sidtarget_m68k@
+sidtarget_mips = @sidtarget_mips@
+sidtarget_ppc = @sidtarget_ppc@
+sidtarget_x86 = @sidtarget_x86@
+sidtarget_xstormy16 = @sidtarget_xstormy16@
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../cpu
+
+noinst_LTLIBRARIES = libpic.la
+
+libpic_la_SOURCES = sid-pic-wrapper.cc sid-pic-wrapper.h pic.cc pic.h
+
+libpic_la_LDFLAGS = -no-undefined
+mkinstalldirs = $(SHELL) $(top_srcdir)/../../config/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+LTLIBRARIES =  $(noinst_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libpic_la_LIBADD = 
+libpic_la_OBJECTS =  sid-pic-wrapper.lo pic.lo
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+GZIP_ENV = --best
+DEP_FILES =  .deps/pic.P .deps/sid-pic-wrapper.P
+SOURCES = $(libpic_la_SOURCES)
+OBJECTS = $(libpic_la_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .lo .o .s
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --foreign pic/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLTLIBRARIES:
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+
+distclean-noinstLTLIBRARIES:
+
+maintainer-clean-noinstLTLIBRARIES:
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libpic.la: $(libpic_la_OBJECTS) $(libpic_la_DEPENDENCIES)
+       $(CXXLINK)  $(libpic_la_LDFLAGS) $(libpic_la_OBJECTS) $(libpic_la_LIBADD) $(LIBS)
+.cc.o:
+       $(CXXCOMPILE) -c $<
+.cc.lo:
+       $(LTCXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = pic
+
+distdir: $(DISTFILES)
+       here=`cd $(top_builddir) && pwd`; \
+       top_distdir=`cd $(top_distdir) && pwd`; \
+       distdir=`cd $(distdir) && pwd`; \
+       cd $(top_srcdir) \
+         && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign pic/Makefile
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+       -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+       @echo '$(COMPILE) -c $<'; \
+       $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.c
+       @echo '$(LTCOMPILE) -c $<'; \
+       $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+
+%.o: %.cc
+       @echo '$(CXXCOMPILE) -c $<'; \
+       $(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.cc
+       @echo '$(LTCXXCOMPILE) -c $<'; \
+       $(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LTLIBRARIES)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLTLIBRARIES mostlyclean-compile \
+               mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+               mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLTLIBRARIES clean-compile clean-libtool \
+               clean-tags clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLTLIBRARIES distclean-compile \
+               distclean-libtool distclean-tags distclean-depend \
+               distclean-generic clean-am
+       -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLTLIBRARIES \
+               maintainer-clean-compile maintainer-clean-libtool \
+               maintainer-clean-tags maintainer-clean-depend \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \
+clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sid/component/bochs/pic/pic.cc b/sid/component/bochs/pic/pic.cc
new file mode 100644 (file)
index 0000000..fd4d19a
--- /dev/null
@@ -0,0 +1,726 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+
+#include "bochs.h"
+#if BX_SUPPORT_SID
+#define LOG_THIS
+#else
+#define LOG_THIS bx_pic.
+
+
+
+bx_pic_c bx_pic;
+#endif
+#if BX_USE_PIC_SMF
+#define this (&bx_pic)
+#endif
+
+
+#if BX_SUPPORT_SID
+#include "sid-pic-wrapper.h"
+#endif
+
+
+bx_pic_c::bx_pic_c(void)
+{
+#if BX_SUPPORT_SID
+  bx_dbg.pic = 1;
+#endif
+       setprefix("[PIC ]");
+       settype(PICLOG);
+}
+
+bx_pic_c::~bx_pic_c(void)
+{
+  // nothing for now
+}
+
+
+#if BX_SUPPORT_SID
+void
+bx_pic_c::init(pic *pic_comp)
+#else
+  void
+bx_pic_c::init(bx_devices_c *d)
+#endif
+{
+#if BX_SUPPORT_SID==0
+  BX_PIC_THIS devices = d;
+
+  /* 8259 PIC (Programmable Interrupt Controller) */
+  BX_PIC_THIS devices->register_io_read_handler(this, read_handler, 0x0020, "8259 PIC");
+  BX_PIC_THIS devices->register_io_read_handler(this, read_handler, 0x0021, "8259 PIC");
+  BX_PIC_THIS devices->register_io_read_handler(this, read_handler, 0x00A0, "8259 PIC");
+  BX_PIC_THIS devices->register_io_read_handler(this, read_handler, 0x00A1, "8259 PIC");
+
+  BX_PIC_THIS devices->register_io_write_handler(this, write_handler, 0x0020, "8259 PIC");
+  BX_PIC_THIS devices->register_io_write_handler(this, write_handler, 0x0021, "8259 PIC");
+  BX_PIC_THIS devices->register_io_write_handler(this, write_handler, 0x00A0, "8259 PIC");
+  BX_PIC_THIS devices->register_io_write_handler(this, write_handler, 0x00A1, "8259 PIC");
+#endif
+
+
+  BX_PIC_THIS s.master_pic.single_PIC = 0;
+  BX_PIC_THIS s.master_pic.interrupt_offset = 0x08; /* IRQ0 = INT 0x08 */
+  /* slave PIC connected to IRQ2 of master */
+  BX_PIC_THIS s.master_pic.u.slave_connect_mask = 0x04;
+  BX_PIC_THIS s.master_pic.sfnm = 0; /* normal nested mode */
+  BX_PIC_THIS s.master_pic.buffered_mode = 0; /* unbuffered mode */
+  BX_PIC_THIS s.master_pic.master_slave  = 0; /* no meaning, buffered_mode=0 */
+  BX_PIC_THIS s.master_pic.auto_eoi      = 0; /* manual EOI from CPU */
+  BX_PIC_THIS s.master_pic.imr           = 0xFF; /* all IRQ's initially masked */
+  BX_PIC_THIS s.master_pic.isr           = 0x00; /* no IRQ's in service */
+  BX_PIC_THIS s.master_pic.irr           = 0x00; /* no IRQ's requested */
+  BX_PIC_THIS s.master_pic.read_reg_select = 0; /* IRR */
+  BX_PIC_THIS s.master_pic.irq = 0;
+  BX_PIC_THIS s.master_pic.INT = 0;
+  BX_PIC_THIS s.master_pic.init.in_init = 0;
+  BX_PIC_THIS s.master_pic.init.requires_4 = 0;
+  BX_PIC_THIS s.master_pic.init.byte_expected = 0;
+  BX_PIC_THIS s.master_pic.special_mask = 0;
+
+  BX_PIC_THIS s.slave_pic.single_PIC = 0;
+  BX_PIC_THIS s.slave_pic.interrupt_offset = 0x70; /* IRQ8 = INT 0x70 */
+  BX_PIC_THIS s.slave_pic.u.slave_id = 0x02; /* slave PIC connected to IRQ2 of master */
+  BX_PIC_THIS s.slave_pic.sfnm       = 0; /* normal nested mode */
+  BX_PIC_THIS s.slave_pic.buffered_mode = 0; /* unbuffered mode */
+  BX_PIC_THIS s.slave_pic.master_slave  = 0; /* no meaning, buffered_mode=0 */
+  BX_PIC_THIS s.slave_pic.auto_eoi      = 0; /* manual EOI from CPU */
+  BX_PIC_THIS s.slave_pic.imr           = 0xFF; /* all IRQ's initially masked */
+  BX_PIC_THIS s.slave_pic.isr           = 0x00; /* no IRQ's in service */
+  BX_PIC_THIS s.slave_pic.irr           = 0x00; /* no IRQ's requested */
+  BX_PIC_THIS s.slave_pic.read_reg_select = 0; /* IRR */
+  BX_PIC_THIS s.slave_pic.irq = 0;
+  BX_PIC_THIS s.slave_pic.INT = 0;
+  BX_PIC_THIS s.slave_pic.init.in_init = 0;
+  BX_PIC_THIS s.slave_pic.init.requires_4 = 0;
+  BX_PIC_THIS s.slave_pic.init.byte_expected = 0;
+  BX_PIC_THIS s.slave_pic.special_mask = 0;
+
+  pic_component = pic_comp;
+}
+
+
+
+  // static IO port read callback handler
+  // redirects to non-static class handler to avoid virtual functions
+
+  Bit32u
+bx_pic_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
+{
+#if !BX_USE_PIC_SMF
+  bx_pic_c *class_ptr = (bx_pic_c *) this_ptr;
+
+  return( class_ptr->read(address, io_len) );
+}
+
+
+
+  Bit32u
+bx_pic_c::read(Bit32u address, unsigned io_len)
+{
+#else
+  UNUSED(this_ptr);
+#endif // !BX_USE_PIC_SMF
+  if (io_len > 1)
+    BX_PANIC(("io read from port %04x, len=%u\n", (unsigned) address,
+             (unsigned) io_len));
+
+  BX_DEBUG(("IO read from %04x\n", (unsigned) address));
+
+  /*
+   8259A PIC
+   */
+
+  switch (address) {
+    case 0x20:
+      if (BX_PIC_THIS s.master_pic.read_reg_select) { /* ISR */
+        if (bx_dbg.pic) BX_INFO(("read master ISR = %02x\n",
+                         (unsigned) BX_PIC_THIS s.master_pic.isr));
+       return(BX_PIC_THIS s.master_pic.isr);
+       }
+      else { /* IRR */
+        if (bx_dbg.pic) BX_INFO(("read master IRR = %02x\n",
+                         (unsigned) BX_PIC_THIS s.master_pic.irr));
+       return(BX_PIC_THIS s.master_pic.irr);
+       }
+      break;
+    case 0x21:
+      if (bx_dbg.pic) BX_INFO(("read master IMR = %02x\n",
+                        (unsigned) BX_PIC_THIS s.master_pic.imr));
+      return(BX_PIC_THIS s.master_pic.imr);
+      break;
+    case 0xA0:
+      if (BX_PIC_THIS s.slave_pic.read_reg_select) { /* ISR */
+        if (bx_dbg.pic) BX_INFO(("read slave ISR = %02x\n",
+                          (unsigned) BX_PIC_THIS s.slave_pic.isr));
+       return(BX_PIC_THIS s.slave_pic.isr);
+       }
+      else { /* IRR */
+        if (bx_dbg.pic) BX_INFO(("read slave IRR = %02x\n",
+                          (unsigned) BX_PIC_THIS s.slave_pic.irr));
+       return(BX_PIC_THIS s.slave_pic.irr);
+       }
+      break;
+    case 0xA1:
+      if (bx_dbg.pic) BX_INFO(("read slave IMR = %02x\n",
+                        (unsigned) BX_PIC_THIS s.slave_pic.imr));
+      return(BX_PIC_THIS s.slave_pic.imr);
+      break;
+    }
+
+  BX_PANIC(("io read to address %04x\n", (unsigned) address));
+  return(0); /* default if not found above */
+}
+
+
+  // static IO port write callback handler
+  // redirects to non-static class handler to avoid virtual functions
+
+  void
+bx_pic_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
+{
+#if !BX_USE_PIC_SMF
+  bx_pic_c *class_ptr = (bx_pic_c *) this_ptr;
+
+  class_ptr->write(address, value, io_len);
+}
+
+  void
+bx_pic_c::write(Bit32u address, Bit32u value, unsigned io_len)
+{
+#else
+  UNUSED(this_ptr);
+#endif // !BX_USE_PIC_SMF
+  int irq;
+
+  if (io_len > 1)
+    BX_PANIC(("io write to port %04x, len=%u\n", (unsigned) address,
+             (unsigned) io_len));
+
+  if (bx_dbg.pic)
+    BX_INFO(("IO write to %04x = %02x\n",
+      (unsigned) address, (unsigned) value));
+
+  /*
+   8259A PIC
+   */
+
+  switch (address) {
+    case 0x20:
+      if (value & 0x10) { /* initialization command 1 */
+           // (mch) Ignore...
+           // BX_INFO(("pic:master: init command 1 found %02x\n", (unsigned) value));
+        if (bx_dbg.pic) {
+          BX_INFO(("pic:master: init command 1 found\n"));
+          BX_INFO(("            requires 4 = %u\n",
+            (unsigned) (value & 0x01) ));
+          BX_INFO(("            cascade mode: [0=cascade,1=single] %u\n",
+            (unsigned) ((value & 0x02) >> 1)));
+          }
+        BX_PIC_THIS s.master_pic.init.in_init = 1;
+        BX_PIC_THIS s.master_pic.init.requires_4 = (value & 0x01);
+        BX_PIC_THIS s.master_pic.init.byte_expected = 2; /* operation command 2 */
+        BX_PIC_THIS s.master_pic.imr           = 0xFF; /* all IRQ's initially masked */
+        BX_PIC_THIS s.master_pic.isr           = 0x00; /* no IRQ's in service */
+        BX_PIC_THIS s.master_pic.irr           = 0x00; /* no IRQ's requested */
+        BX_PIC_THIS s.master_pic.INT = 0; /* reprogramming clears previous INTR request */
+        if ( (value & 0x02) == 1 )
+          BX_PANIC(("pic:master: init command: single mode\n"));
+#if BX_SUPPORT_SID
+        pic_component->drive_interrupt_pin(0);
+#else
+        BX_SET_INTR(0);
+#endif
+        return;
+        }
+
+      if ( (value & 0x18) == 0x08 ) { /* OCW3 */
+        Bit8u special_mask, poll, read_op;
+
+        special_mask = (value & 0x60) >> 5;
+        poll         = (value & 0x04) >> 2;
+        read_op      = (value & 0x03);
+        if (poll)
+          BX_PANIC(("pic:master:OCW3: poll bit set\n"));
+        if (read_op == 0x02) /* read IRR */
+         BX_PIC_THIS s.master_pic.read_reg_select = 0;
+        else if (read_op == 0x03) /* read ISR */
+         BX_PIC_THIS s.master_pic.read_reg_select = 1;
+        if (special_mask == 0x02) { /* cancel special mask */
+          BX_PIC_THIS s.master_pic.special_mask = 0;
+          }
+        else if (special_mask == 0x03) { /* set specific mask */
+          BX_PIC_THIS s.master_pic.special_mask = 1;
+          service_master_pic();
+          }
+        return;
+        }
+
+      /* OCW2 */
+      switch (value) {
+        case 0x00: // Rotate in Auto-EOI mode
+          BX_PANIC(("PIC: Rotate in Auto-EOI mode command received.\n"));
+       case 0x0A: /* select read interrupt request register */
+         BX_PIC_THIS s.master_pic.read_reg_select = 0;
+         break;
+       case 0x0B: /* select read interrupt in-service register */
+         BX_PIC_THIS s.master_pic.read_reg_select = 1;
+         break;
+
+       case 0x20: /* end of interrupt command */
+          /* clear highest current in service bit */
+          for (irq=0; irq<=7; irq++) {
+            if (BX_PIC_THIS s.master_pic.isr & (1 << irq)) {
+              BX_PIC_THIS s.master_pic.isr &= ~(1 << irq);
+              break; /* out of for loop */
+              }
+            }
+          service_master_pic();
+         break;
+
+        case 0x60: /* specific EOI 0 */
+        case 0x61: /* specific EOI 1 */
+        case 0x62: /* specific EOI 2 */
+        case 0x63: /* specific EOI 3 */
+        case 0x64: /* specific EOI 4 */
+        case 0x65: /* specific EOI 5 */
+        case 0x66: /* specific EOI 6 */
+        case 0x67: /* specific EOI 7 */
+          BX_PIC_THIS s.master_pic.isr &= ~(1 << (value-0x60));
+          service_master_pic();
+         break;
+
+        // IRQ lowest priority commands
+        case 0xC0: // 0 7 6 5 4 3 2 1
+        case 0xC1: // 1 0 7 6 5 4 3 2
+        case 0xC2: // 2 1 0 7 6 5 4 3
+        case 0xC3: // 3 2 1 0 7 6 5 4
+        case 0xC4: // 4 3 2 1 0 7 6 5
+        case 0xC5: // 5 4 3 2 1 0 7 6
+        case 0xC6: // 6 5 4 3 2 1 0 7
+        case 0xC7: // 7 6 5 4 3 2 1 0
+          // ignore for now
+          BX_INFO(("IRQ lowest command 0x%x\n", value));
+          break;
+
+        default:
+          BX_PANIC(("PIC: write to port 20h = %02x\n", value));
+       } /* switch (value) */
+      break;
+
+    case 0x21:
+      /* initialization mode operation */
+      if (BX_PIC_THIS s.master_pic.init.in_init) {
+        switch (BX_PIC_THIS s.master_pic.init.byte_expected) {
+          case 2:
+            BX_PIC_THIS s.master_pic.interrupt_offset = value & 0xf8;
+            BX_PIC_THIS s.master_pic.init.byte_expected = 3;
+           if (bx_dbg.pic) {
+                 BX_INFO(("pic:master: init command 2 = %02x\n", (unsigned) value));
+                 BX_INFO(("            offset = INT %02x\n",
+                           BX_PIC_THIS s.master_pic.interrupt_offset));
+           }
+            return;
+            break;
+          case 3:
+           if (bx_dbg.pic)
+                 BX_INFO(("pic:master: init command 3 = %02x\n", (unsigned) value));
+            if (BX_PIC_THIS s.master_pic.init.requires_4) {
+              BX_PIC_THIS s.master_pic.init.byte_expected = 4;
+             }
+            else {
+              BX_PIC_THIS s.master_pic.init.in_init = 0;
+             }
+            return;
+            break;
+          case 4:
+           if (bx_dbg.pic) {
+                 BX_INFO(("pic:master: init command 4 = %02x\n", (unsigned) value));
+                 if (value & 0x02) BX_INFO(("       auto EOI\n"));
+                 else BX_INFO(("normal EOI interrupt\n"));
+           }
+           if (value & 0x01) {
+                 if (bx_dbg.pic)
+                       BX_INFO(("       80x86 mode\n"));
+           } else
+                 BX_PANIC(("       not 80x86 mode\n"));
+            BX_PIC_THIS s.master_pic.init.in_init = 0;
+            return;
+            break;
+          default:
+            BX_PANIC(("pic:master expecting bad init command\n"));
+          }
+        }
+
+      /* normal operation */
+      if (bx_dbg.pic)
+        BX_INFO(("setting master pic IMR to %02x\n", value));
+      BX_PIC_THIS s.master_pic.imr = value;
+      service_master_pic();
+      return;
+      break;
+
+    case 0xA0:
+      if (value & 0x10) { /* initialization command 1 */
+        BX_DEBUG(("slave: init command 1 found\n"));
+        BX_DEBUG(("           requires 4 = %u\n",
+            (unsigned) (value & 0x01) ));
+        BX_DEBUG(("           cascade mode: [0=cascade,1=single] %u\n",
+            (unsigned) ((value & 0x02) >> 1)));
+        BX_PIC_THIS s.slave_pic.init.in_init = 1;
+        BX_PIC_THIS s.slave_pic.init.requires_4 = (value & 0x01);
+        BX_PIC_THIS s.slave_pic.init.byte_expected = 2; /* operation command 2 */
+        BX_PIC_THIS s.slave_pic.imr           = 0xFF; /* all IRQ's initially masked */
+        BX_PIC_THIS s.slave_pic.isr           = 0x00; /* no IRQ's in service */
+        BX_PIC_THIS s.slave_pic.irr           = 0x00; /* no IRQ's requested */
+        BX_PIC_THIS s.slave_pic.INT = 0; /* reprogramming clears previous INTR request */
+        if ( (value & 0x02) == 1 )
+          BX_PANIC(("slave: init command: single mode\n"));
+        return;
+        }
+
+      if ( (value & 0x18) == 0x08 ) { /* OCW3 */
+        Bit8u special_mask, poll, read_op;
+
+        special_mask = (value & 0x60) >> 5;
+        poll         = (value & 0x04) >> 2;
+        read_op      = (value & 0x03);
+        if (poll)
+          BX_PANIC(("slave:OCW3: poll bit set\n"));
+        if (read_op == 0x02) /* read IRR */
+         BX_PIC_THIS s.slave_pic.read_reg_select = 0;
+        else if (read_op == 0x03) /* read ISR */
+         BX_PIC_THIS s.slave_pic.read_reg_select = 1;
+        if (special_mask == 0x02) { /* cancel special mask */
+          BX_PIC_THIS s.slave_pic.special_mask = 0;
+          }
+        else if (special_mask == 0x03) { /* set specific mask */
+          BX_PIC_THIS s.slave_pic.special_mask = 1;
+          service_slave_pic();
+          BX_ERROR(("slave: OCW3 not implemented (%02x)\n",
+            (unsigned) value));
+          }
+        return;
+        }
+
+      switch (value) {
+       case 0x0A: /* select read interrupt request register */
+         BX_PIC_THIS s.slave_pic.read_reg_select = 0;
+         break;
+       case 0x0B: /* select read interrupt in-service register */
+         BX_PIC_THIS s.slave_pic.read_reg_select = 1;
+         break;
+       case 0x20: /* end of interrupt command */
+          /* clear highest current in service bit */
+          for (irq=0; irq<=7; irq++) {
+            if (BX_PIC_THIS s.slave_pic.isr & (1 << irq)) {
+              BX_PIC_THIS s.slave_pic.isr &= ~(1 << irq);
+              break; /* out of for loop */
+              }
+            }
+          service_slave_pic();
+         break;
+
+        case 0x60: /* specific EOI 0 */
+        case 0x61: /* specific EOI 1 */
+        case 0x62: /* specific EOI 2 */
+        case 0x63: /* specific EOI 3 */
+        case 0x64: /* specific EOI 4 */
+        case 0x65: /* specific EOI 5 */
+        case 0x66: /* specific EOI 6 */
+        case 0x67: /* specific EOI 7 */
+          BX_PIC_THIS s.slave_pic.isr &= ~(1 << (value-0x60));
+          service_slave_pic();
+         break;
+
+        default:
+          BX_PANIC(("PIC: write to port A0h = %02x\n", value));
+       } /* switch (value) */
+      break;
+
+    case 0xA1:
+      /* initialization mode operation */
+      if (BX_PIC_THIS s.slave_pic.init.in_init) {
+        switch (BX_PIC_THIS s.slave_pic.init.byte_expected) {
+          case 2:
+            BX_PIC_THIS s.slave_pic.interrupt_offset = value & 0xf8;
+            BX_PIC_THIS s.slave_pic.init.byte_expected = 3;
+           if (bx_dbg.pic) {
+                 BX_DEBUG(("slave: init command 2 = %02x\n", (unsigned) value));
+                 BX_DEBUG(("           offset = INT %02x\n",
+                           BX_PIC_THIS s.slave_pic.interrupt_offset));
+           }
+            return;
+            break;
+          case 3:
+                 BX_DEBUG(("slave: init command 3 = %02x\n", (unsigned) value));
+            if (BX_PIC_THIS s.slave_pic.init.requires_4) {
+              BX_PIC_THIS s.slave_pic.init.byte_expected = 4;
+               } else {
+              BX_PIC_THIS s.slave_pic.init.in_init = 0;
+             }
+            return;
+            break;
+          case 4:
+               if (bx_dbg.pic) {
+                     BX_DEBUG(("slave: init command 4 = %02x\n", (unsigned) value));
+                     if (value & 0x02) BX_INFO(("      auto EOI\n"));
+                     else BX_DEBUG(("normal EOI interrupt\n"));
+               }
+               if (value & 0x01) {
+                     if (bx_dbg.pic)
+                           BX_INFO(("      80x86 mode\n"));
+               } else BX_PANIC(("not 80x86 mode\n"));
+            BX_PIC_THIS s.slave_pic.init.in_init = 0;
+            return;
+            break;
+          default:
+            BX_PANIC(("slave: expecting bad init command\n"));
+          }
+        }
+
+      /* normal operation */
+      if (bx_dbg.pic)
+        BX_INFO(("setting slave pic IMR to %02x\n", value));
+      BX_PIC_THIS s.slave_pic.imr = value;
+      service_slave_pic();
+      return;
+      break;
+    } /* switch (address) */
+
+  return;
+}
+
+  void
+bx_pic_c::trigger_irq(unsigned irq_no)
+{
+#if BX_SUPPORT_APIC
+  // forward this function call to the ioapic too
+  BX_PIC_THIS devices->ioapic->trigger_irq (irq_no, -1);
+#endif
+
+  int irq_no_bitmask;
+
+#if BX_DEBUG
+  if ( irq_no > 15 )
+    BX_PANIC(("trigger_irq: irq out of range\n"));
+#endif
+
+  if (bx_dbg.pic)
+    BX_INFO(("trigger_irq(%d decimal)\n", (unsigned) irq_no));
+
+  if (irq_no <= 7) {
+    irq_no_bitmask = 1 << irq_no;
+    BX_PIC_THIS s.master_pic.irr |= irq_no_bitmask;
+    service_master_pic();
+    }
+  else { // irq = 8..15
+    irq_no_bitmask = 1 << (irq_no - 8);
+    BX_PIC_THIS s.slave_pic.irr |= irq_no_bitmask;
+    service_slave_pic();
+    }
+}
+
+  void
+bx_pic_c::untrigger_irq(unsigned irq_no)
+{
+#if BX_SUPPORT_APIC
+  // forward this function call to the ioapic too
+  BX_PIC_THIS devices->ioapic->untrigger_irq (irq_no, -1);
+#endif
+
+  int irq_no_bitmask;
+
+#if BX_DEBUG
+  if ( irq_no > 15 )
+    BX_PANIC(("untrigger_irq: irq out of range\n"));
+#endif
+
+  if (bx_dbg.pic)
+    BX_INFO(("untrigger_irq(%d decimal)\n", (unsigned) irq_no));
+
+  if (irq_no <= 7) {
+    irq_no_bitmask = 1 << irq_no;
+    if (BX_PIC_THIS s.master_pic.imr & irq_no_bitmask) {
+      BX_PIC_THIS s.master_pic.irr &= ~irq_no_bitmask;
+    }
+  }
+  else { // irq = 8..15
+    irq_no_bitmask = 1 << (irq_no - 8);
+    if (BX_PIC_THIS s.slave_pic.imr & irq_no_bitmask) {
+      BX_PIC_THIS s.slave_pic.irr &= ~irq_no_bitmask;
+    }
+  }
+}
+
+  /* */
+  void
+bx_pic_c::service_master_pic(void)
+{
+  Bit8u unmasked_requests;
+  int irq;
+  Bit8u isr, max_irq;
+
+  if (BX_PIC_THIS s.master_pic.INT) { /* last interrupt still not acknowleged */
+    return;
+    }
+
+  if (BX_PIC_THIS s.master_pic.special_mask) {
+    /* all priorities may be enabled.  check all IRR bits except ones
+     * which have corresponding ISR bits set
+     */
+    max_irq = 7;
+    }
+  else { /* normal mode */
+    /* Find the highest priority IRQ that is enabled due to current ISR */
+    isr = BX_PIC_THIS s.master_pic.isr;
+    if (isr) {
+      max_irq = 0;
+      while ( (isr & 0x01) == 0 ) {
+        isr >>= 1;
+        max_irq++;
+        }
+      if (max_irq == 0 ) return; /* IRQ0 in-service, no other priorities allowed */
+      if (max_irq > 7) BX_PANIC(("error in service_master_pic()\n"));
+      }
+    else
+      max_irq = 7; /* 0..7 bits in ISR are cleared */
+    }
+
+
+  /* now, see if there are any higher priority requests */
+  if ((unmasked_requests = (BX_PIC_THIS s.master_pic.irr & ~BX_PIC_THIS s.master_pic.imr)) ) {
+    for (irq=0; irq<=max_irq; irq++) {
+      /* for special mode, since we're looking at all IRQ's, skip if
+       * current IRQ is already in-service
+       */
+      if ( BX_PIC_THIS s.master_pic.special_mask && ((BX_PIC_THIS s.master_pic.isr >> irq) & 0x01) )
+        continue;
+      if (unmasked_requests & (1 << irq)) {
+        BX_DEBUG(("signalling IRQ(%u)\n", (unsigned) irq));
+        BX_PIC_THIS s.master_pic.irr &= ~(1 << irq);
+        /*??? do for slave too: BX_PIC_THIS s.master_pic.isr |=  (1 << irq);*/
+        BX_PIC_THIS s.master_pic.INT = 1;
+#if BX_SUPPORT_SID
+        pic_component->drive_interrupt_pin(1);
+#else
+        BX_SET_INTR(1);
+#endif
+        BX_PIC_THIS s.master_pic.irq = irq;
+        return;
+        } /* if (unmasked_requests & ... */
+      } /* for (irq=7 ... */
+    } /* if (unmasked_requests = ... */
+}
+
+
+  void
+bx_pic_c::service_slave_pic(void)
+{
+  Bit8u unmasked_requests;
+  int irq;
+  Bit8u isr, lowest_priority_irq;
+
+  if (BX_PIC_THIS s.slave_pic.INT) { /* last interrupt still not acknowleged */
+    return;
+    }
+
+  /* Find the highest priority IRQ that is enabled due to current ISR */
+  isr = BX_PIC_THIS s.slave_pic.isr;
+  if (isr) {
+    lowest_priority_irq = 0;
+    while ( !(isr & 0x01) ) {
+      isr >>= 1;
+      lowest_priority_irq++;
+      }
+    if (lowest_priority_irq > 7) BX_PANIC(("error in service_slave_pic()\n"));
+    }
+  else
+    lowest_priority_irq = 8;
+
+
+  /* now, see if there are any higher priority requests */
+  if ((unmasked_requests = (BX_PIC_THIS s.slave_pic.irr & ~BX_PIC_THIS s.slave_pic.imr)) ) {
+    for (irq=0; irq<lowest_priority_irq; irq++) {
+      if (unmasked_requests & (1 << irq)) {
+        if (bx_dbg.pic)
+          BX_DEBUG(("slave: signalling IRQ(%u)\n",
+            (unsigned) 8 + irq));
+        BX_PIC_THIS s.slave_pic.irr &= ~(1 << irq);
+        BX_PIC_THIS s.slave_pic.INT = 1;
+        BX_PIC_THIS s.master_pic.irr |= 0x04; /* request IRQ 2 on master pic */
+        BX_PIC_THIS s.slave_pic.irq = irq;
+        service_master_pic();
+        return;
+        } /* if (unmasked_requests & ... */
+      } /* for (irq=7 ... */
+    } /* if (unmasked_requests = ... */
+}
+
+
+  /* CPU handshakes with PIC after acknowledging interrupt */
+  Bit8u
+bx_pic_c::IAC(void)
+{
+  Bit8u vector;
+  Bit8u irq;
+
+#if BX_SUPPORT_SID
+  pic_component->drive_interrupt_pin(0);
+#else
+  BX_SET_INTR(0);
+#endif
+  BX_PIC_THIS s.master_pic.INT = 0;
+  BX_PIC_THIS s.master_pic.isr |= (1 << BX_PIC_THIS s.master_pic.irq);
+  BX_PIC_THIS s.master_pic.irr &= ~(1 << BX_PIC_THIS s.master_pic.irq);
+
+  if (BX_PIC_THIS s.master_pic.irq != 2) {
+    irq    = BX_PIC_THIS s.master_pic.irq;
+    vector = irq + BX_PIC_THIS s.master_pic.interrupt_offset;
+    }
+  else { /* IRQ2 = slave pic IRQ8..15 */
+    BX_PIC_THIS s.slave_pic.INT = 0;
+    irq    = BX_PIC_THIS s.slave_pic.irq;
+    vector = irq + BX_PIC_THIS s.slave_pic.interrupt_offset;
+    BX_PIC_THIS s.slave_pic.isr |= (1 << BX_PIC_THIS s.slave_pic.irq);
+    BX_PIC_THIS s.slave_pic.irr &= ~(1 << BX_PIC_THIS s.slave_pic.irq);
+    service_slave_pic();
+    irq += 8; // for debug printing purposes
+    }
+
+  service_master_pic();
+
+  BX_DBG_IAC_REPORT(vector, irq);
+  return(vector);
+}
+
+  void
+bx_pic_c::show_pic_state(void)
+{
+BX_INFO(("s.master_pic.imr = %02x\n", BX_PIC_THIS s.master_pic.imr));
+BX_INFO(("s.master_pic.isr = %02x\n", BX_PIC_THIS s.master_pic.isr));
+BX_INFO(("s.master_pic.irr = %02x\n", BX_PIC_THIS s.master_pic.irr));
+BX_INFO(("s.master_pic.irq = %02x\n", BX_PIC_THIS s.master_pic.irq));
+}
diff --git a/sid/component/bochs/pic/pic.h b/sid/component/bochs/pic/pic.h
new file mode 100644 (file)
index 0000000..5507cd2
--- /dev/null
@@ -0,0 +1,105 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+#if BX_USE_PIC_SMF
+#  define BX_PIC_SMF  static
+#  define BX_PIC_THIS bx_pic.
+#else
+#  define BX_PIC_SMF
+#  define BX_PIC_THIS this->
+#endif
+
+#if BX_SUPPORT_SID
+class pic;
+#endif
+
+typedef struct {
+  Bit8u single_PIC;        /* 0=cascaded PIC, 1=master only */
+  Bit8u interrupt_offset;  /* programmable interrupt vector offset */
+  union {
+    Bit8u   slave_connect_mask; /* for master, a bit for each interrupt line
+                                   0=not connect to a slave, 1=connected */
+    Bit8u   slave_id;           /* for slave, id number of slave PIC */
+    } u;
+  Bit8u sfnm;              /* specially fully nested mode: 0=no, 1=yes*/
+  Bit8u buffered_mode;     /* 0=no buffered mode, 1=buffered mode */
+  Bit8u master_slave;      /* master/slave: 0=slave PIC, 1=master PIC */
+  Bit8u auto_eoi;          /* 0=manual EOI, 1=automatic EOI */
+  Bit8u imr;               /* interrupt mask register, 1=masked */
+  Bit8u isr;               /* in service register */
+  Bit8u irr;               /* interrupt request register */
+  Bit8u read_reg_select;   /* 0=IRR, 1=ISR */
+  Bit8u irq;               /* current IRQ number */
+  Boolean INT;             /* INT request pin of PIC */
+  struct {
+    Boolean    in_init;
+    Boolean    requires_4;
+    int        byte_expected;
+    } init;
+  Boolean special_mask;
+  } bx_pic_t;
+
+
+class bx_pic_c : public logfunctions {
+
+public:
+  bx_pic_c(void);
+  ~bx_pic_c(void);
+#if BX_SUPPORT_SID
+  BX_PIC_SMF void   init(pic *pic_comp);
+#else
+  BX_PIC_SMF void   init(bx_devices_c *);
+#endif
+  BX_PIC_SMF void   trigger_irq(unsigned irq_no);
+  BX_PIC_SMF void   untrigger_irq(unsigned irq_no);
+  BX_PIC_SMF Bit8u  IAC(void);
+
+private:
+  struct {
+    bx_pic_t master_pic;
+    bx_pic_t slave_pic;
+    } s;
+#if BX_SUPPORT_SID
+  pic *pic_component;
+#else
+  bx_devices_c *devices;
+#endif
+  static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
+  static void   write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
+#if BX_SUPPORT_SID
+ public:
+#endif
+#if !BX_USE_PIC_SMF
+  Bit32u read(Bit32u address, unsigned io_len);
+  void   write(Bit32u address, Bit32u value, unsigned io_len);
+#endif
+#if BX_SUPPORT_SID
+ private:
+#endif
+  BX_PIC_SMF void   service_master_pic(void);
+  BX_PIC_SMF void   service_slave_pic(void);
+  BX_PIC_SMF void   show_pic_state(void);
+  };
+#if BX_SUPPORT_SID==0
+extern bx_pic_c bx_pic;
+#endif
diff --git a/sid/component/bochs/pic/sid-pic-wrapper.cc b/sid/component/bochs/pic/sid-pic-wrapper.cc
new file mode 100644 (file)
index 0000000..e0f68da
--- /dev/null
@@ -0,0 +1,90 @@
+// sid-pic-wrapper.cc - SID import of the bochs pic component.  -*- C++ -*-
+
+// Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
+// This file is part of SID and is licensed under the GPL.
+// See the file COPYING.SID for conditions for redistribution.
+
+#include "sid-pic-wrapper.h"
+
+pic::pic ()
+    : init_pin(this, & pic::init),
+      trigger_irq_pin(this, & pic::trigger_irq),
+      untrigger_irq_pin(this, & pic::untrigger_irq),
+      interrupt_acknowledge_pin(this, & pic::interrupt_acknowledge),
+      ports_0x20_0x21_bus(this, & pic::read_port_0x20_0x21, & pic::write_port_0x20_0x21),
+      ports_0xa0_0xa1_bus(this, & pic::read_port_0xa0_0xa1, & pic::write_port_0xa0_0xa1)
+{
+  add_pin("interrupt", & this->interrupt_pin);
+  
+  add_pin("interrupt-acknowledge", & this->interrupt_acknowledge_pin);
+  add_pin("interrupt-ack-response", & this->interrupt_acknowledge_response_pin);
+
+  add_pin("init", & this->init_pin);
+  add_pin("trigger-irq", & this->trigger_irq_pin);
+  add_pin("untrigger-irq", & this->untrigger_irq_pin);
+
+  add_bus("ports-0x20-0x21", & this->ports_0x20_0x21_bus);
+  add_bus("ports-0xa0-0xa1", & this->ports_0xa0_0xa1_bus);
+}
+
+void
+pic::init(host_int_4)
+{
+  bx_pic.init(this);
+}
+
+void
+pic::trigger_irq(host_int_4 irq_number)
+{
+  bx_pic.trigger_irq(irq_number);
+}
+
+void
+pic::untrigger_irq(host_int_4 irq_number)
+{
+  bx_pic.untrigger_irq(irq_number);
+}
+
+void
+pic::interrupt_acknowledge(host_int_4)
+{
+  interrupt_acknowledge_response_pin.drive(bx_pic.IAC());
+}
+
+void
+pic::drive_interrupt_pin(host_int_4 value)
+{
+  interrupt_pin.drive(value);
+}
+
+bus::status
+pic::read_port_0x20_0x21 (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+{
+  addr += 0x20;
+  data = bx_pic.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+pic::write_port_0x20_0x21 (host_int_4 addr, little_int_1 mask, little_int_1 data)
+{
+  addr += 0x20;
+  bx_pic.write(addr, data, 1);
+  return bus::ok;
+}
+
+bus::status
+pic::read_port_0xa0_0xa1 (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+{
+  addr += 0xa0;
+  data = bx_pic.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+pic::write_port_0xa0_0xa1 (host_int_4 addr, little_int_1 mask, little_int_1 data)
+{
+  addr += 0xa0;
+  bx_pic.write(addr, data, 1);
+  return bus::ok;
+}
diff --git a/sid/component/bochs/pic/sid-pic-wrapper.h b/sid/component/bochs/pic/sid-pic-wrapper.h
new file mode 100644 (file)
index 0000000..8fc96a1
--- /dev/null
@@ -0,0 +1,70 @@
+// sid-pic-wrapper.h - SID import of the bochs pic component.  -*- C++ -*-
+
+// Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
+// This file is part of SID and is licensed under the GPL.
+// See the file COPYING.SID for conditions for redistribution.
+
+#ifndef SID_PIC_WRAPPER_DEF_H
+#define SID_PIC_WRAPPER_DEF_H  1
+
+#include <sidtypes.h>
+#include <sidcomp.h>
+#include <sidcomputil.h>
+#include <sidpinutil.h>
+#include <sidbusutil.h>
+#include <sidattrutil.h>
+#include <sidcpuutil.h>
+#include <sidpinattrutil.h>
+#include <sidmiscutil.h>
+#include <sidwatchutil.h>
+#include <sidso.h>
+
+#include "bochs.h"
+
+using sid::component;
+using sid::bus;
+using sid::host_int_4;
+using sid::little_int_1;
+using sidutil::callback_word_bus;
+using sidutil::callback_pin;
+using sidutil::output_pin;
+
+class pic : public sidutil::fixed_pin_map_component,
+            public sidutil::no_accessor_component,
+            public sidutil::fixed_attribute_map_component,
+            public sidutil::no_relation_component,
+            public sidutil::fixed_bus_map_component
+{
+public:
+  pic();
+  ~pic() throw() {};
+
+  void init(host_int_4);
+  void trigger_irq(host_int_4 irq_number);
+  void untrigger_irq(host_int_4 irq_number);
+  void interrupt_acknowledge(host_int_4);
+
+  void drive_interrupt_pin(host_int_4 value);
+
+protected:
+
+  output_pin interrupt_pin;
+  output_pin interrupt_acknowledge_response_pin;
+
+  callback_pin<pic> interrupt_acknowledge_pin;
+  callback_pin<pic> init_pin;
+  callback_pin<pic> trigger_irq_pin;
+  callback_pin<pic> untrigger_irq_pin;
+
+  bus::status read_port_0x20_0x21 (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x20_0x21 (host_int_4 addr, little_int_1 mask, little_int_1 data);
+
+  bus::status read_port_0xa0_0xa1 (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0xa0_0xa1 (host_int_4 addr, little_int_1 mask, little_int_1 data);
+
+  callback_word_bus<pic, little_int_1> ports_0x20_0x21_bus;
+  callback_word_bus<pic, little_int_1> ports_0xa0_0xa1_bus;
+
+  bx_pic_c bx_pic;
+};
+#endif // SID_PIC_WRAPPER_DEF_H
diff --git a/sid/component/bochs/pit/Makefile.am b/sid/component/bochs/pit/Makefile.am
new file mode 100644 (file)
index 0000000..ec73ee9
--- /dev/null
@@ -0,0 +1,11 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../cpu
+
+noinst_LTLIBRARIES = libpit.la
+
+libpit_la_SOURCES = sid-pit-wrapper.cc sid-pit-wrapper.h pit.cc pit.h
+
+libpit_la_LDFLAGS = -no-undefined
diff --git a/sid/component/bochs/pit/Makefile.in b/sid/component/bochs/pit/Makefile.in
new file mode 100644 (file)
index 0000000..f66cff5
--- /dev/null
@@ -0,0 +1,412 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+APIC_OBJS = @APIC_OBJS@
+AR = @AR@
+AS = @AS@
+AS_DYNAMIC_INCS = @AS_DYNAMIC_INCS@
+AS_DYNAMIC_OBJS = @AS_DYNAMIC_OBJS@
+BX_LOADER_OBJS = @BX_LOADER_OBJS@
+BX_SPLIT_HD_SUPPORT = @BX_SPLIT_HD_SUPPORT@
+CC = @CC@
+CDROM_OBJS = @CDROM_OBJS@
+CD_UP_ONE = @CD_UP_ONE@
+CD_UP_TWO = @CD_UP_TWO@
+CFP = @CFP@
+COMMAND_SEPARATOR = @COMMAND_SEPARATOR@
+CPP_SUFFIX = @CPP_SUFFIX@
+CXX = @CXX@
+CXXFP = @CXXFP@
+DASH = @DASH@
+DEBUGGER_VAR = @DEBUGGER_VAR@
+DISASM_VAR = @DISASM_VAR@
+DLLTOOL = @DLLTOOL@
+DYNAMIC_VAR = @DYNAMIC_VAR@
+EXE = @EXE@
+EXEEXT = @EXEEXT@
+EXTERNAL_DEPENDENCY = @EXTERNAL_DEPENDENCY@
+FPU_GLUE_OBJ = @FPU_GLUE_OBJ@
+FPU_VAR = @FPU_VAR@
+GUI_LINK_OPTS = @GUI_LINK_OPTS@
+GUI_LINK_OPTS_TERM = @GUI_LINK_OPTS_TERM@
+GUI_OBJS = @GUI_OBJS@
+GZIP = @GZIP@
+INLINE_VAR = @INLINE_VAR@
+INSTRUMENT_DIR = @INSTRUMENT_DIR@
+INSTRUMENT_VAR = @INSTRUMENT_VAR@
+IOAPIC_OBJS = @IOAPIC_OBJS@
+IODEV_LIB_VAR = @IODEV_LIB_VAR@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LINK = @LINK@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKELIB = @MAKELIB@
+NE2K_OBJS = @NE2K_OBJS@
+NM = @NM@
+NONINLINE_VAR = @NONINLINE_VAR@
+OBJDUMP = @OBJDUMP@
+OFP = @OFP@
+PACKAGE = @PACKAGE@
+PCI_OBJ = @PCI_OBJ@
+PRIMARY_TARGET = @PRIMARY_TARGET@
+RANLIB = @RANLIB@
+READLINE_LIB = @READLINE_LIB@
+RFB_LIBS = @RFB_LIBS@
+RMCOMMAND = @RMCOMMAND@
+SB16_OBJS = @SB16_OBJS@
+SLASH = @SLASH@
+SUFFIX_LINE = @SUFFIX_LINE@
+TAR = @TAR@
+VERSION = @VERSION@
+VIDEO_OBJS = @VIDEO_OBJS@
+sidtarget_arm = @sidtarget_arm@
+sidtarget_m32r = @sidtarget_m32r@
+sidtarget_m68k = @sidtarget_m68k@
+sidtarget_mips = @sidtarget_mips@
+sidtarget_ppc = @sidtarget_ppc@
+sidtarget_x86 = @sidtarget_x86@
+sidtarget_xstormy16 = @sidtarget_xstormy16@
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../cpu
+
+noinst_LTLIBRARIES = libpit.la
+
+libpit_la_SOURCES = sid-pit-wrapper.cc sid-pit-wrapper.h pit.cc pit.h
+
+libpit_la_LDFLAGS = -no-undefined
+mkinstalldirs = $(SHELL) $(top_srcdir)/../../config/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+LTLIBRARIES =  $(noinst_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libpit_la_LIBADD = 
+libpit_la_OBJECTS =  sid-pit-wrapper.lo pit.lo
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+GZIP_ENV = --best
+DEP_FILES =  .deps/pit.P .deps/sid-pit-wrapper.P
+SOURCES = $(libpit_la_SOURCES)
+OBJECTS = $(libpit_la_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .lo .o .s
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --foreign pit/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLTLIBRARIES:
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+
+distclean-noinstLTLIBRARIES:
+
+maintainer-clean-noinstLTLIBRARIES:
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libpit.la: $(libpit_la_OBJECTS) $(libpit_la_DEPENDENCIES)
+       $(CXXLINK)  $(libpit_la_LDFLAGS) $(libpit_la_OBJECTS) $(libpit_la_LIBADD) $(LIBS)
+.cc.o:
+       $(CXXCOMPILE) -c $<
+.cc.lo:
+       $(LTCXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = pit
+
+distdir: $(DISTFILES)
+       here=`cd $(top_builddir) && pwd`; \
+       top_distdir=`cd $(top_distdir) && pwd`; \
+       distdir=`cd $(distdir) && pwd`; \
+       cd $(top_srcdir) \
+         && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign pit/Makefile
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+       -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+       @echo '$(COMPILE) -c $<'; \
+       $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.c
+       @echo '$(LTCOMPILE) -c $<'; \
+       $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+
+%.o: %.cc
+       @echo '$(CXXCOMPILE) -c $<'; \
+       $(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.cc
+       @echo '$(LTCXXCOMPILE) -c $<'; \
+       $(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LTLIBRARIES)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLTLIBRARIES mostlyclean-compile \
+               mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+               mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLTLIBRARIES clean-compile clean-libtool \
+               clean-tags clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLTLIBRARIES distclean-compile \
+               distclean-libtool distclean-tags distclean-depend \
+               distclean-generic clean-am
+       -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLTLIBRARIES \
+               maintainer-clean-compile maintainer-clean-libtool \
+               maintainer-clean-tags maintainer-clean-depend \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \
+clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sid/component/bochs/pit/pit.cc b/sid/component/bochs/pit/pit.cc
new file mode 100644 (file)
index 0000000..873583a
--- /dev/null
@@ -0,0 +1,873 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+
+#include "bochs.h"
+#if BX_SUPPORT_SID
+#define LOG_THIS
+#else
+#define LOG_THIS bx_pit.
+#endif
+
+// NOTES ON THE 8253/8254 PIT MODES
+
+// MODE 0: Interrupt on Terminal Count
+// ===================================
+// Writing new count action:
+//   loaded upon next CLK pulse.  counting doesn't start until GATE=1
+// GATE 0..1 transition:
+//   ???
+// GATE 1..0 transition:
+// counter expiration action:
+//   wraps to FFFF
+// * OUT rises until new count val or new control word for mode 0 written
+
+// MODE 1: Programmable Monoflop
+// =============================
+// Writing new count action:
+//   not effective for current process
+// GATE 0..1 transition:
+//   loads counter
+// counter expiration action:
+//   wraps to FFFF
+// NOTES:
+//   OUT rises until new count val or new control word for mode 0 written
+
+// MODE 2: Rate Generator
+// ======================
+// Writing new count action:
+//   ???
+// GATE 0..1 transition:
+//   loads initial count val and starts counting
+// counter expiration action:
+//   reloads after count expires
+// NOTES:
+// * after control word & initial count val N loaded, PIT starts
+//   counting upon next CLK pulse.
+// * when counter reaches 1, OUT drops to a low level, for one
+//   CLK cycle. (short peak pulse generated)
+// * afterwards, the initial count val is automatically reloaded
+//   and the PIT restarts the same counting operation again.
+// * distance of two OUT pulses is N CLK cycles long.
+// * GATE=1 enables, GATE=0 disables counter.
+// * if GATE drops to low level during counting operation and rises
+//     to high level later, PIT loads initial count value at the
+//     rise and starts counting.
+// * PIT starts counting after last data byte written if GATE=1
+// * if the output is low when the gate goes low, the output is
+//   immediately set high.
+
+// MODE 3: Square Wave Generator
+// =============================
+// Writing new count action:
+//   ???
+// GATE 0..1 transition:
+//   ???
+// counter expiration action:
+//   reloads after count expires
+// NOTES:
+// * initially OUT at a high level
+// * drop of GATE to a low level while OUT low, raises OUT to a high level
+// * a rise from a low to a high level at GATE (trigger pulse),
+//   loads the counter with the initial count value and starts
+//   counting operation
+// * a new count value supplied during the course of an active
+//   counting operation doesn't affect the current process.
+//   At the end of the current half cycle, the PIT loads the new value
+// * if the GATE line goes low, count is temporarily halted until GATE
+//   returns high
+// * if the OUT line is high when GATE goes low, OUT is forced low.
+// ??? different for odd/even counts
+
+// MODE 4: Software Triggered Pulse
+// ================================
+// Writing new count action:
+//   ???
+// GATE 0..1 transition:
+//   ???
+// counter expiration action:
+//   wraps to FFFF
+// NOTES:
+
+// MODE 5: Hardware Triggered Pulse
+// ================================
+// Writing new count action:
+//   ???
+// GATE 0..1 transition:
+//   ???
+// counter expiration action:
+//   wraps to FFFF
+// NOTES:
+
+
+
+#define BX_PIT_LATCH_MODE_LSB   10
+#define BX_PIT_LATCH_MODE_MSB   11
+#define BX_PIT_LATCH_MODE_16BIT 12
+
+
+#if BX_SUPPORT_SID==0
+bx_pit_c bx_pit;
+#endif
+#if BX_USE_PIT_SMF
+#define this (&bx_pit)
+#endif
+
+#ifdef OUT
+#  undef OUT
+#endif
+
+
+bx_pit_c::bx_pit_c( void )
+{
+#if BX_SUPPORT_SID
+  bx_dbg.pit = 1;
+#endif
+  setprefix("[PIT ]");
+  settype(PITLOG);
+  memset(&s, 0, sizeof(s));
+
+  /* 8254 PIT (Programmable Interval Timer) */
+
+  BX_PIT_THIS s.timer_handle[1] = BX_NULL_TIMER_HANDLE;
+  BX_PIT_THIS s.timer_handle[2] = BX_NULL_TIMER_HANDLE;
+}
+
+bx_pit_c::~bx_pit_c( void )
+{
+}
+
+#if BX_SUPPORT_SID
+void
+bx_pit_c::init(void)
+#else
+  int
+bx_pit_c::init( bx_devices_c *d )
+#endif
+{
+#if BX_SUPPORT_SID==0
+  BX_PIT_THIS devices = d;
+
+  BX_PIT_THIS devices->register_irq(0, "8254 PIT");
+  BX_PIT_THIS devices->register_io_read_handler(this, read_handler, 0x0040, "8254 PIT");
+  BX_PIT_THIS devices->register_io_read_handler(this, read_handler, 0x0041, "8254 PIT");
+  BX_PIT_THIS devices->register_io_read_handler(this, read_handler, 0x0042, "8254 PIT");
+  BX_PIT_THIS devices->register_io_read_handler(this, read_handler, 0x0043, "8254 PIT");
+  BX_PIT_THIS devices->register_io_read_handler(this, read_handler, 0x0061, "8254 PIT");
+
+  BX_PIT_THIS devices->register_io_write_handler(this, write_handler, 0x0040, "8254 PIT");
+  BX_PIT_THIS devices->register_io_write_handler(this, write_handler, 0x0041, "8254 PIT");
+  BX_PIT_THIS devices->register_io_write_handler(this, write_handler, 0x0042, "8254 PIT");
+  BX_PIT_THIS devices->register_io_write_handler(this, write_handler, 0x0043, "8254 PIT");
+  BX_PIT_THIS devices->register_io_write_handler(this, write_handler, 0x0061, "8254 PIT");
+#endif
+  BX_PIT_THIS s.speaker_data_on = 0;
+  BX_PIT_THIS s.refresh_clock_div2 = 0;
+
+  BX_PIT_THIS s.timer[0].mode        = 3;  /* periodic rate generator */
+  BX_PIT_THIS s.timer[0].latch_mode  = BX_PIT_LATCH_MODE_16BIT;
+  BX_PIT_THIS s.timer[0].input_latch_value = 0;
+  BX_PIT_THIS s.timer[0].input_latch_toggle = 0;
+  BX_PIT_THIS s.timer[0].output_latch_value = 0;
+  BX_PIT_THIS s.timer[0].output_latch_toggle = 0;
+  BX_PIT_THIS s.timer[0].output_latch_full = 0;
+  BX_PIT_THIS s.timer[0].counter_max = 0;  /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */
+  BX_PIT_THIS s.timer[0].counter     = 0;  /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */
+  BX_PIT_THIS s.timer[0].bcd_mode    = 0;  /* binary counting mode */
+  BX_PIT_THIS s.timer[0].GATE        = 1;  /* GATE tied to + logic */
+  BX_PIT_THIS s.timer[0].OUT         = 1;
+  BX_PIT_THIS s.timer[0].active      = 0;
+
+  BX_PIT_THIS s.timer[1].mode        = 3;  /* periodic rate generator */
+  BX_PIT_THIS s.timer[1].latch_mode  = BX_PIT_LATCH_MODE_16BIT;
+  BX_PIT_THIS s.timer[1].input_latch_value = 0;
+  BX_PIT_THIS s.timer[1].input_latch_toggle = 0;
+  BX_PIT_THIS s.timer[1].output_latch_value = 0;
+  BX_PIT_THIS s.timer[1].output_latch_toggle = 0;
+  BX_PIT_THIS s.timer[1].output_latch_full = 0;
+  BX_PIT_THIS s.timer[1].counter_max = 0;  /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */
+  BX_PIT_THIS s.timer[1].counter     = 0;  /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */
+  BX_PIT_THIS s.timer[1].bcd_mode    = 0;  /* binary counting mode */
+  BX_PIT_THIS s.timer[1].GATE        = 1;  /* GATE tied to + logic */
+  BX_PIT_THIS s.timer[1].OUT         = 1;
+  BX_PIT_THIS s.timer[1].active      = 0;
+
+  BX_PIT_THIS s.timer[2].mode        = 3;  /* periodic rate generator */
+  BX_PIT_THIS s.timer[2].latch_mode  = BX_PIT_LATCH_MODE_16BIT;
+  BX_PIT_THIS s.timer[2].input_latch_value = 0;
+  BX_PIT_THIS s.timer[2].input_latch_toggle = 0;
+  BX_PIT_THIS s.timer[2].output_latch_value = 0;
+  BX_PIT_THIS s.timer[2].output_latch_toggle = 0;
+  BX_PIT_THIS s.timer[2].output_latch_full = 0;
+  BX_PIT_THIS s.timer[2].counter_max = 0;  /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */
+  BX_PIT_THIS s.timer[2].counter     = 0;  /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */
+  BX_PIT_THIS s.timer[2].bcd_mode    = 0;  /* binary counting mode */
+  BX_PIT_THIS s.timer[2].GATE        = 0;  /* timer2 gate controlled by port 61h bit 0 */
+  BX_PIT_THIS s.timer[2].OUT         = 1;
+  BX_PIT_THIS s.timer[2].active      = 0;
+#if BX_SUPPORT_SID==0
+  return(1);
+#endif
+}
+
+
+
+
+
+
+  // static IO port read callback handler
+  // redirects to non-static class handler to avoid virtual functions
+
+  Bit32u
+bx_pit_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
+{
+#if !BX_USE_PIT_SMF
+  bx_pit_c *class_ptr = (bx_pit_c *) this_ptr;
+
+  return( class_ptr->read(address, io_len) );
+}
+
+
+  Bit32u
+bx_pit_c::read( Bit32u   address, unsigned int io_len )
+{
+#else
+  UNUSED(this_ptr);
+#endif  // !BX_USE_PIT_SMF
+  if (io_len > 1)
+    BX_PANIC(("pit: io read from port %04x, len=%u\n", (unsigned) address,
+             (unsigned) io_len));
+
+  if (bx_dbg.pit)
+    BX_INFO(("pit: io read from port %04x\n", (unsigned) address));
+
+  switch (address) {
+    case 0x40: /* timer 0 - system ticks */
+      return( read_counter(0) );
+      break;
+
+    case 0x42: /* timer 2 read */
+      return( read_counter(2) );
+      break;
+
+    case 0x61:
+      /* AT, port 61h */
+      BX_PIT_THIS s.refresh_clock_div2 = !BX_PIT_THIS s.refresh_clock_div2;
+      return( (BX_PIT_THIS s.timer[2].OUT<<5) |
+              (BX_PIT_THIS s.refresh_clock_div2<<4) |
+              (BX_PIT_THIS s.speaker_data_on<<1) |
+              (BX_PIT_THIS s.timer[2].GATE) );
+      break;
+
+    default:
+      BX_PANIC(("pit: unsupported io read from port %04x\n", address));
+    }
+  return(0); /* keep compiler happy */
+}
+
+
+  // static IO port write callback handler
+  // redirects to non-static class handler to avoid virtual functions
+
+  void
+bx_pit_c::write_handler(void *this_ptr, Bit32u address, Bit32u dvalue, unsigned io_len)
+{
+#if !BX_USE_PIT_SMF
+  bx_pit_c *class_ptr = (bx_pit_c *) this_ptr;
+
+  class_ptr->write(address, dvalue, io_len);
+}
+
+  void
+bx_pit_c::write( Bit32u   address, Bit32u   dvalue,
+                unsigned int io_len )
+{
+#else
+  UNUSED(this_ptr);
+#endif  // !BX_USE_PIT_SMF
+  Bit8u    command, mode, bcd_mode;
+  Bit8u   value;
+
+  value = (Bit8u  ) dvalue;
+
+  if (io_len > 1)
+    BX_PANIC(("pit: io write to port %04x, len=%u\n", (unsigned) address,
+             (unsigned) io_len));
+
+  if (bx_dbg.pit)
+    BX_INFO(("pit: write to port %04x = %02x\n",
+      (unsigned) address, (unsigned) value));
+
+  switch (address) {
+    case 0x40: /* timer 0: write count register */
+      write_count_reg( value, 0 );
+      break;
+
+    case 0x41: /* timer 1: write count register */
+      write_count_reg( value, 1 );
+      break;
+
+    case 0x42: /* timer 2: write count register */
+      write_count_reg( value, 2 );
+      break;
+
+    case 0x43: /* timer 0-2 mode control */
+      /* |7 6 5 4|3 2 1|0|
+       * |-------|-----|-|
+       * |command|mode |bcd/binary|
+       */
+      command  = value >> 4;
+      mode     = (value >> 1) & 0x07;
+      bcd_mode = value & 0x01;
+#if 0
+BX_INFO(("timer 0-2 mode control: comm:%02x mode:%02x bcd_mode:%u\n",
+  (unsigned) command, (unsigned) mode, (unsigned) bcd_mode));
+#endif
+
+      if ( (mode > 5) || (command > 0x0e) )
+        BX_PANIC(("pit: outp(43h)=%02xh out of range\n", (unsigned) value));
+      if (bcd_mode)
+        BX_PANIC(("pit: outp(43h)=%02xh: bcd mode unhandled\n",
+          (unsigned) bcd_mode));
+
+      switch (command) {
+        case 0x0: /* timer 0: counter latch */
+          latch( 0 );
+          break;
+
+        case 0x1: /* timer 0: LSB mode */
+        case 0x2: /* timer 0: MSB mode */
+          BX_PANIC(("pit: outp(43h): command %02xh unhandled\n",
+            (unsigned) command));
+          break;
+        case 0x3: /* timer 0: 16-bit mode */
+          BX_PIT_THIS s.timer[0].mode = mode;
+          BX_PIT_THIS s.timer[0].latch_mode   = BX_PIT_LATCH_MODE_16BIT;
+          BX_PIT_THIS s.timer[0].input_latch_value = 0;
+          BX_PIT_THIS s.timer[0].input_latch_toggle = 0;
+          BX_PIT_THIS s.timer[0].bcd_mode    = bcd_mode;
+          if ( (mode!=3 && mode!=2 && mode!=0) || bcd_mode!=0 )
+            BX_PANIC(("pit: outp(43h): comm 3, mode %02x, bcd %02x unhandled\n",
+              (unsigned) mode, bcd_mode));
+          break;
+        case 0x4: /* timer 1: counter latch */
+          latch( 1 );
+          break;
+
+        case 0x5: /* timer 1: LSB mode */
+        case 0x6: /* timer 1: MSB mode */
+          BX_INFO(("pit: outp(43h): command %02xh unhandled (ignored)\n",
+            (unsigned) command));
+          break;
+        case 0x7: /* timer 1: 16-bit mode */
+          BX_PIT_THIS s.timer[1].mode = mode;
+          BX_PIT_THIS s.timer[1].latch_mode   = BX_PIT_LATCH_MODE_16BIT;
+          BX_PIT_THIS s.timer[1].input_latch_value = 0;
+          BX_PIT_THIS s.timer[1].input_latch_toggle = 0;
+          BX_PIT_THIS s.timer[1].bcd_mode    = bcd_mode;
+          if ( (mode!=3 && mode!=2 && mode!=0) || bcd_mode!=0 )
+            BX_PANIC(("pit: outp(43h): comm 7, mode %02x, bcd %02x unhandled\n",
+              (unsigned) mode, bcd_mode));
+          break;
+        case 0x8: /* timer 2: counter latch */
+          latch( 2 );
+          break;
+
+        case 0x9: /* timer 2: LSB mode */
+        case 0xa: /* timer 2: MSB mode */
+          BX_PANIC(("pit: outp(43h): command %02xh unhandled\n",
+            (unsigned) command));
+          break;
+        case 0xb: /* timer 2: 16-bit mode */
+          BX_PIT_THIS s.timer[2].mode = mode;
+          BX_PIT_THIS s.timer[2].latch_mode   = BX_PIT_LATCH_MODE_16BIT;
+          BX_PIT_THIS s.timer[2].input_latch_value = 0;
+          BX_PIT_THIS s.timer[2].input_latch_toggle = 0;
+          BX_PIT_THIS s.timer[2].bcd_mode    = bcd_mode;
+          if ( (mode!=3 && mode!=2 && mode!=0) || bcd_mode!=0 )
+            BX_PANIC(("pit: outp(43h): comm Bh, mode %02x, bcd %02x unhandled\n",
+              (unsigned) mode, bcd_mode));
+          break;
+#if 0
+        case 0xd: /* general counter latch */
+          if (value & 0x08) /* select counter 2 */
+            latch( 2 );
+          if (value & 0x04) /* select counter 1 */
+            latch( 1 );
+          if (value & 0x02) /* select counter 0 */
+            latch( 0 );
+          break;
+
+        case 0xe: /* latch status of timers */
+          BX_PANIC(("pit: outp(43h): command %02xh unhandled\n",
+            (unsigned) command);
+          break;
+#endif
+        case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+          BX_INFO(("pit: ignoring 8254 command %u\n", (unsigned) command));
+          break;
+
+        default: /* 0xc & 0xf */
+          BX_PANIC(("pit: outp(43h) command %1xh unhandled\n",
+            (unsigned) command));
+          break;
+        }
+      break;
+
+    case 0x61:
+      BX_PIT_THIS s.speaker_data_on = (value >> 1) & 0x01;
+/*??? only on AT+ */
+      set_GATE(2, value & 0x01);
+#if BX_CPU_LEVEL < 2
+      /* ??? XT: */
+      bx_kbd_port61h_write(value);
+#endif
+      break;
+
+    default:
+      BX_PANIC(("pit: unsupported io write to port %04x = %02x\n",
+        (unsigned) address, (unsigned) value));
+    }
+}
+
+
+
+
+  void
+bx_pit_c::write_count_reg( Bit8u   value, unsigned timerid )
+{
+  Boolean xfer_complete;
+
+  switch ( BX_PIT_THIS s.timer[timerid].latch_mode ) {
+    case BX_PIT_LATCH_MODE_16BIT: /* write1=LSB, write2=MSB */
+      if (BX_PIT_THIS s.timer[timerid].input_latch_toggle==0) {
+        BX_PIT_THIS s.timer[timerid].input_latch_value = value;
+        BX_PIT_THIS s.timer[timerid].input_latch_toggle = 1;
+        xfer_complete = 0;
+        if (bx_dbg.pit)
+          BX_INFO(("pit: BX_PIT_THIS s.timer[timerid] write L = %02x\n", (unsigned) value));
+        }
+      else {
+        BX_PIT_THIS s.timer[timerid].input_latch_value |= (value << 8);
+        BX_PIT_THIS s.timer[timerid].input_latch_toggle = 0;
+        xfer_complete = 1;
+        if (bx_dbg.pit)
+          BX_INFO(("pit: BX_PIT_THIS s.timer[timerid] write H = %02x\n", (unsigned) value));
+        }
+      break;
+
+    case BX_PIT_LATCH_MODE_MSB: /* write1=MSB, LSB=0 */
+      BX_PIT_THIS s.timer[timerid].input_latch_value = (value << 8);
+      xfer_complete = 1;
+      if (bx_dbg.pit)
+        BX_INFO(("pit: BX_PIT_THIS s.timer[timerid] write H = %02x\n", (unsigned) value));
+      break;
+
+    case BX_PIT_LATCH_MODE_LSB: /* write1=LSB, MSB=0 */
+      BX_PIT_THIS s.timer[timerid].input_latch_value = value;
+      xfer_complete = 1;
+      if (bx_dbg.pit)
+        BX_INFO(("pit: BX_PIT_THIS s.timer[timerid] write L = %02x\n", (unsigned) value));
+      break;
+
+    default:
+      BX_PANIC(("write_count_reg: latch_mode unknown\n"));
+      xfer_complete = 0;
+    }
+
+  if (xfer_complete) {
+    BX_PIT_THIS s.timer[timerid].counter_max = BX_PIT_THIS s.timer[timerid].input_latch_value;
+
+    // reprogramming counter clears latch
+    BX_PIT_THIS s.timer[timerid].output_latch_full = 0;
+
+    // counter bounds
+    // mode      minimum    maximum
+    //  0           1          0
+    //  1           1          0
+    //  2           2          0
+    //  3           2          0
+    //  4           1          0
+    //  5           1          0
+    switch (BX_PIT_THIS s.timer[timerid].mode) {
+      case 0:
+        BX_PIT_THIS s.timer[timerid].counter = BX_PIT_THIS s.timer[timerid].counter_max;
+        BX_PIT_THIS s.timer[timerid].active = 1;
+        if (BX_PIT_THIS s.timer[timerid].GATE) {
+          BX_PIT_THIS s.timer[timerid].OUT = 0; // OUT pin starts low
+          start( timerid );
+          }
+        break;
+      case 1:
+        BX_PANIC(("pit:write_count_reg(%u): mode1 unsupported\n",
+                 timerid));
+        break;
+      case 2:
+        if ( BX_PIT_THIS s.timer[timerid].counter_max == 1 )
+          BX_PANIC(("pit:write_count_reg(%u): mode %u counter_max=1\n",
+                   timerid, (unsigned) BX_PIT_THIS s.timer[timerid].mode));
+        if ( BX_PIT_THIS s.timer[timerid].GATE && !BX_PIT_THIS s.timer[timerid].active ) {
+          // software triggered
+          BX_PIT_THIS s.timer[timerid].counter = BX_PIT_THIS s.timer[timerid].counter_max;
+          BX_PIT_THIS s.timer[timerid].active  = 1;
+          BX_PIT_THIS s.timer[timerid].OUT     = 1; // initially set high
+          start( timerid );
+          }
+        break;
+      case 3:
+        if ( BX_PIT_THIS s.timer[timerid].counter_max == 1 )
+          BX_PANIC(("pit:write_count_reg(%u): mode %u counter_max=1\n",
+                   timerid, (unsigned) BX_PIT_THIS s.timer[timerid].mode));
+        BX_PIT_THIS s.timer[timerid].counter_max = BX_PIT_THIS s.timer[timerid].counter_max & 0xfffe;
+        if ( BX_PIT_THIS s.timer[timerid].GATE && !BX_PIT_THIS s.timer[timerid].active ) {
+          // software triggered
+          BX_PIT_THIS s.timer[timerid].counter = BX_PIT_THIS s.timer[timerid].counter_max;
+          BX_PIT_THIS s.timer[timerid].active  = 1;
+          BX_PIT_THIS s.timer[timerid].OUT     = 1; // initially set high
+          start( timerid );
+          }
+        break;
+      case 4:
+        BX_PANIC(("pit:write_count_reg(%u): mode4 unsupported\n",
+                 timerid));
+        break;
+      case 5:
+        BX_PANIC(("pit:write_count_reg(%u): mode5 unsupported\n",
+                 timerid));
+        break;
+      }
+    }
+}
+
+
+  Bit8u
+bx_pit_c::read_counter( unsigned timerid )
+{
+  Bit16u  counter_value;
+  Bit8u    retval;
+
+  if (BX_PIT_THIS s.timer[timerid].output_latch_full) { /* latched read */
+    counter_value = BX_PIT_THIS s.timer[timerid].output_latch_value;
+    }
+  else { /* direct unlatched read */
+    counter_value = BX_PIT_THIS s.timer[timerid].counter;
+BX_INFO(("CV=%04x\n", (unsigned) BX_PIT_THIS s.timer[timerid].counter));
+    }
+
+  switch (BX_PIT_THIS s.timer[timerid].latch_mode) {
+    case BX_PIT_LATCH_MODE_LSB:
+      retval = (Bit8u  ) counter_value;
+      BX_PIT_THIS s.timer[timerid].output_latch_full = 0;
+      break;
+    case BX_PIT_LATCH_MODE_MSB:
+      retval = (Bit8u  ) ( counter_value >> 8 );
+      BX_PIT_THIS s.timer[timerid].output_latch_full = 0;
+      break;
+    case BX_PIT_LATCH_MODE_16BIT:
+      if (BX_PIT_THIS s.timer[timerid].output_latch_toggle==0) { /* LSB 1st */
+        retval = (Bit8u  ) counter_value;
+        }
+      else { /* MSB 2nd */
+        retval = (Bit8u  ) ( counter_value >> 8 );
+        }
+      BX_PIT_THIS s.timer[timerid].output_latch_toggle = !BX_PIT_THIS s.timer[timerid].output_latch_toggle;
+      if (BX_PIT_THIS s.timer[timerid].output_latch_toggle == 0)
+        BX_PIT_THIS s.timer[timerid].output_latch_full = 0;
+      break;
+    default:
+      BX_PANIC(("pit: io read from port 40h: unknown latch mode\n"));
+      retval = 0; /* keep compiler happy */
+    }
+  return( retval );
+}
+
+
+  void
+bx_pit_c::latch( unsigned timerid )
+{
+  /* subsequent counter latch commands are ignored until value read out */
+  if (BX_PIT_THIS s.timer[timerid].output_latch_full) {
+    BX_INFO(("pit: pit(%u) latch: output latch full, ignoring\n",
+              timerid));
+    return;
+    }
+
+  BX_PIT_THIS s.timer[timerid].output_latch_value = BX_PIT_THIS s.timer[timerid].counter;
+
+  if (bx_dbg.pit)
+    BX_INFO(("pit: latch_value = %lu\n", BX_PIT_THIS s.timer[timerid].output_latch_value));
+  BX_PIT_THIS s.timer[timerid].output_latch_toggle = 0;
+  BX_PIT_THIS s.timer[timerid].output_latch_full   = 1;
+}
+
+  void
+bx_pit_c::set_GATE(unsigned pit_id, unsigned value)
+{
+  // GATE's for Timer 0 & Timer 1 are tied high.
+  if (pit_id != 2)
+    BX_PANIC(("pit:set_GATE: pit_id != 2\n"));
+
+  value = (value > 0);
+
+  /* if no transition of GATE input line, then nothing to do */
+  if (value == BX_PIT_THIS s.timer[2].GATE)
+    return;
+
+  if (value) { /* PIT2: GATE transition from 0 to 1 */
+    BX_PIT_THIS s.timer[2].GATE  = 1;
+    switch ( BX_PIT_THIS s.timer[2].mode ) {
+      case 0:
+        BX_PIT_THIS s.timer[2].counter = BX_PIT_THIS s.timer[2].counter_max;
+        if (BX_PIT_THIS s.timer[2].active) {
+          BX_PIT_THIS s.timer[2].OUT = 0;
+          }
+        start( 2 );
+        break;
+      case 2:
+        // begin counting, reload counter
+        BX_PIT_THIS s.timer[2].active = 1;
+        BX_PIT_THIS s.timer[2].OUT = 1;
+        BX_PIT_THIS s.timer[2].counter = BX_PIT_THIS s.timer[2].counter_max;
+        start( 2 );
+        break;
+      case 3:
+        // begin counting, reload counter
+        BX_PIT_THIS s.timer[2].active = 1;
+        BX_PIT_THIS s.timer[2].OUT = 1;
+        BX_PIT_THIS s.timer[2].counter = BX_PIT_THIS s.timer[2].counter_max;
+        start( 2 );
+        break;
+      case 1:
+      case 4:
+      case 5:
+      default:
+        BX_PANIC(("bx_pit_c::set_GATE: unhandled timer2 mode %u\n",
+                 (unsigned) BX_PIT_THIS s.timer[2].mode));
+      }
+    }
+  else {       // PIT2: GATE transition from 1 to 0, deactivate
+    BX_PIT_THIS s.timer[2].GATE  = 0;
+    switch ( BX_PIT_THIS s.timer[2].mode ) {
+      case 0:
+        break;
+      case 2:
+        // 1) stops count, 2) OUT goes immediately high
+        BX_PIT_THIS s.timer[2].active = 0;
+        BX_PIT_THIS s.timer[2].OUT = 1;
+        break;
+      case 3:
+        // 1) stops count, 2) OUT goes immediately high
+        BX_PIT_THIS s.timer[2].active = 0;
+        BX_PIT_THIS s.timer[2].OUT = 1;
+        break;
+      case 1:
+      case 4:
+      case 5:
+      default:
+        BX_PANIC(("bx_pit_c::set_GATE: unhandled timer2 mode %u\n",
+                 (unsigned) BX_PIT_THIS s.timer[2].mode));
+      }
+    }
+}
+
+
+  void
+bx_pit_c::start(unsigned timerid)
+{
+  unsigned long period_hz;
+
+  if (BX_PIT_THIS s.timer[timerid].counter_max == 0x0000) {
+    period_hz   = 1193182 / 65536;
+    }
+  else {
+    period_hz = 1193182 / BX_PIT_THIS s.timer[timerid].counter_max;
+    }
+  BX_INFO(("timer%u period set to %lu hz\n", timerid, period_hz));
+
+
+  switch (BX_PIT_THIS s.timer[timerid].mode) {
+    case 0: /* single timeout */
+      break;
+    case 1: /* retriggerable one-shot */
+      BX_PANIC(("start: mode %u unhandled\n",
+               (unsigned) BX_PIT_THIS s.timer[timerid].mode));
+      break;
+    case 2: /* rate generator */
+      break;
+    case 3: /* square wave mode */
+      break;
+    case 4: /* software triggered strobe */
+      BX_PANIC(("start: mode %u unhandled\n",
+               (unsigned) BX_PIT_THIS s.timer[timerid].mode));
+      break;
+    case 5: /* hardware retriggerable strobe */
+      BX_PANIC(("start: mode %u unhandled\n",
+               (unsigned) BX_PIT_THIS s.timer[timerid].mode));
+      break;
+    default:
+      BX_PANIC(("start: timer%u has bad mode\n",
+               (unsigned) BX_PIT_THIS s.timer[timerid].mode));
+    }
+}
+
+
+#if BX_SUPPORT_SID==0
+
+  int
+bx_pit_c::SaveState( class state_file *fd )
+{
+  fd->write_check ("8254 start");
+  fd->write (&BX_PIT_THIS s, sizeof (BX_PIT_THIS s));
+  fd->write_check ("8254 end");
+  return(0);
+}
+
+
+  int
+bx_pit_c::LoadState( class state_file *fd )
+{
+  fd->read_check ("8254 start");
+  fd->read (&BX_PIT_THIS s, sizeof (BX_PIT_THIS s));
+  fd->read_check ("8254 end");
+  return(0);
+}
+
+#endif
+#if 0
+  void
+bx_kbd_port61h_write(Bit8u   value)
+{
+//  PcError("KBD_PORT61H_WRITE(): not implemented yet");
+  UNUSED( value );
+}
+#endif
+
+
+  Boolean
+bx_pit_c::periodic( Bit32u   usec_delta )
+{
+  Boolean prev_timer0_out;
+
+  prev_timer0_out = BX_PIT_THIS s.timer[0].OUT;
+
+  for (unsigned i = 0; i < 3; i++) {
+    // is timer enabled and active?
+    if ( BX_PIT_THIS s.timer[i].GATE && BX_PIT_THIS s.timer[i].active ) {
+      switch ( BX_PIT_THIS s.timer[i].mode ) {
+        case 0: // Mode 0: Single Timeout
+          // wraps after count expires
+          if ( BX_PIT_THIS s.timer[i].counter == 0 ) {
+            // counter previously expired, wrap counter
+            BX_PIT_THIS s.timer[i].counter = 0xffff;
+            }
+          else if ( usec_delta >= BX_PIT_THIS s.timer[i].counter ) {
+            // counter expired
+            BX_PIT_THIS s.timer[i].counter = 0;
+            BX_PIT_THIS s.timer[i].OUT     = 1;
+            }
+          else {
+            // decrement counter by elapsed useconds
+            BX_PIT_THIS s.timer[i].counter -= (Bit16u ) usec_delta;
+            }
+          break;
+
+        case 1: // Mode 1: Retriggerable One-Shot
+          // wraps after count expires
+          BX_PANIC(("bx_pit_c::periodic: bad mode: timer[%u], mode %u\n",
+                        i, (unsigned) BX_PIT_THIS s.timer[i].mode));
+          break;
+
+        case 2: // Mode 2: Rate Generator
+          // reloads after count expires
+          // OUT is low when counter=1, high otherwise
+          // min count=2, max count=0
+          if ( BX_PIT_THIS s.timer[i].counter == 0 ) {
+            // max counter val, just wrap
+            BX_PIT_THIS s.timer[i].counter = 0xffff;
+            BX_PIT_THIS s.timer[i].OUT     = 1;
+            }
+          else if ( BX_PIT_THIS s.timer[i].counter == 1 ) {
+            // counter previously expired, reload
+            BX_PIT_THIS s.timer[i].counter = BX_PIT_THIS s.timer[i].counter_max;
+            BX_PIT_THIS s.timer[i].OUT     = 1;
+            }
+          else if ( (BX_PIT_THIS s.timer[i].counter == 2) ||
+                    (usec_delta >= (Bit32u(BX_PIT_THIS s.timer[i].counter) - 1)) ) {
+            // in either case, counter will reach 1
+            BX_PIT_THIS s.timer[i].counter = 1;
+            BX_PIT_THIS s.timer[i].OUT = 0;
+            }
+          else {
+            // decrement counter by elapsed useconds
+            BX_PIT_THIS s.timer[i].counter -= (Bit16u ) usec_delta;
+            }
+          break;
+
+        case 3: // Mode 3: Square Wave Mode
+          // reloads after count expires
+          // min count=2, max count=0
+          if ( BX_PIT_THIS s.timer[i].counter == 0 ) {
+            // max count, dec by 2
+            BX_PIT_THIS s.timer[i].counter = 0xfffe;
+            }
+          else if ( (BX_PIT_THIS s.timer[i].counter <= 2) ||
+                    ( (usec_delta*2) >= BX_PIT_THIS s.timer[i].counter ) ) {
+            // counter expired, reload
+            BX_PIT_THIS s.timer[i].counter = BX_PIT_THIS s.timer[i].counter_max;
+            BX_PIT_THIS s.timer[i].OUT     = !BX_PIT_THIS s.timer[i].OUT;
+            //BX_INFO(("CV: reload t%u to %04x\n", (unsigned) i, (unsigned)
+            //  BX_PIT_THIS s.timer[i].counter));
+            }
+          else {
+            // decrement counter by elapsed useconds
+            BX_PIT_THIS s.timer[i].counter -= (Bit16u ) ( 2*usec_delta );
+            //BX_INFO(("CV: dec count to %04x\n",
+            //          (unsigned) BX_PIT_THIS s.timer[i].counter));
+            }
+          break;
+
+        case 4: // Mode 4: Software Triggered Strobe
+          // wraps after count expires
+          BX_PANIC(("bx_pit_c::periodic: bad mode: timer[%u], mode %u\n",
+                        i, (unsigned) BX_PIT_THIS s.timer[i].mode));
+          break;
+
+        case 5: // Mode 5: Hardware Retriggerable Strobe
+          // wraps after count expires
+          BX_PANIC(("bx_pit_c::periodic: bad mode: timer[%u], mode %u\n",
+                        i, (unsigned) BX_PIT_THIS s.timer[i].mode));
+          break;
+        default:
+          BX_PANIC(("bx_pit_c::periodic: bad mode: timer[%u], mode %u\n",
+                        i, (unsigned) BX_PIT_THIS s.timer[i].mode));
+          break;
+        } // switch ( BX_PIT_THIS s.tim...
+      } // if ( BX_PIT_THIS s.timer[i]...
+    } // for (unsigned i...
+
+  // see if there's a rising edge on timer0's output to trigger an IRQ0.
+  if ( (prev_timer0_out==0) && (BX_PIT_THIS s.timer[0].OUT==1) )
+    return(1); // request IRQ 0
+  else
+    return(0);
+}
diff --git a/sid/component/bochs/pit/pit.h b/sid/component/bochs/pit/pit.h
new file mode 100644 (file)
index 0000000..ff578a2
--- /dev/null
@@ -0,0 +1,105 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+#ifndef _BX_PIT_H
+#define _BX_PIT_H
+
+
+#if BX_USE_PIT_SMF
+#  define BX_PIT_SMF  static
+#  define BX_PIT_THIS bx_pit.
+#else
+#  define BX_PIT_SMF
+#  define BX_PIT_THIS this->
+#endif
+
+#ifdef OUT
+#  undef OUT
+#endif
+
+
+typedef struct {
+  Bit8u      mode;
+  Bit8u      latch_mode;
+  Bit16u     input_latch_value;
+  Boolean    input_latch_toggle;
+  Bit16u     output_latch_value;
+  Boolean    output_latch_toggle;
+  Boolean    output_latch_full;
+  Bit16u     counter_max;
+  Bit16u     counter;
+  Boolean    bcd_mode;
+  Boolean    active;
+  Boolean    GATE;     // GATE input  pin
+  Boolean    OUT;      // OUT  output pin
+  } bx_pit_t;
+
+
+
+
+class bx_pit_c : public logfunctions {
+public:
+  bx_pit_c( void );
+  ~bx_pit_c( void );
+#if BX_SUPPORT_SID
+  BX_PIT_SMF void init(void);
+#else
+  BX_PIT_SMF int init( bx_devices_c *);
+#endif
+  BX_PIT_SMF Boolean periodic( Bit32u   usec_delta );
+#if BX_SUPPORT_SID==0
+  BX_PIT_SMF int SaveState( class state_file *fd );
+  BX_PIT_SMF int LoadState( class state_file *fd );
+#endif
+private:
+
+  static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
+  static void   write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
+#if BX_SUPPORT_SID
+ public:
+#endif
+#if !BX_USE_PIT_SMF
+  Bit32u   read( Bit32u   addr, unsigned int len );
+  void write( Bit32u   addr, Bit32u   Value, unsigned int len );
+#endif
+#if BX_SUPPORT_SID
+ private:
+#endif
+  struct {
+    bx_pit_t timer[3];
+    Bit8u   speaker_data_on;
+    Boolean refresh_clock_div2;
+    int  timer_handle[3];
+    } s;
+#if BX_SUPPORT_SID==0
+  bx_devices_c *devices;
+#endif
+  BX_PIT_SMF void  write_count_reg( Bit8u   value, unsigned timerid );
+  BX_PIT_SMF Bit8u read_counter( unsigned timerid );
+  BX_PIT_SMF void  latch( unsigned timerid );
+  BX_PIT_SMF void  set_GATE(unsigned pit_id, unsigned value);
+  BX_PIT_SMF void  start(unsigned timerid);
+  };
+#if BX_SUPPORT_SID==0
+extern bx_pit_c bx_pit;
+#endif
+#endif  // #ifndef _BX_PIT_H
diff --git a/sid/component/bochs/pit/sid-pit-wrapper.cc b/sid/component/bochs/pit/sid-pit-wrapper.cc
new file mode 100644 (file)
index 0000000..0e65b86
--- /dev/null
@@ -0,0 +1,71 @@
+// sid-pit-wrapper.cc - SID import of the bochs pit component.  -*- C++ -*-
+
+// Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
+// This file is part of SID and is licensed under the GPL.
+// See the file COPYING.SID for conditions for redistribution.
+
+#include "sid-pit-wrapper.h"
+
+pit::pit ()
+    : init_pin(this, & pit::init),
+      update_pit_pin(this, & pit::update_pit),
+      ports_0x40_0x43_bus(this, & pit::read_port_0x40_0x43, & pit::write_port_0x40_0x43),
+      port_0x61_bus(this, & pit::read_port_0x61, & pit::write_port_0x61),
+      timer_delta(100), pit_irq_number(0)
+{
+  add_pin("trigger-irq", & this->trigger_irq_pin);
+
+  add_pin("init", & this->init_pin);
+  add_pin("update-pit", & this->update_pit_pin);
+
+  add_bus("ports-0x40-0x43", & this->ports_0x40_0x43_bus);
+  add_bus("port-0x61", & this->port_0x61_bus);
+
+  add_attribute("irq-number", & this->pit_irq_number, "setting");
+  add_attribute("timer-delta", & this->timer_delta, "setting");
+}
+
+void
+pit::init(host_int_4)
+{
+  bx_pit.init();
+}
+
+void
+pit::update_pit(host_int_4)
+{
+  if(bx_pit.periodic(timer_delta))
+    trigger_irq_pin.drive(pit_irq_number);
+}
+
+bus::status
+pit::read_port_0x40_0x43 (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+{
+  addr += 0x40;
+  data = bx_pit.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+pit::write_port_0x40_0x43 (host_int_4 addr, little_int_1 mask, little_int_1 data)
+{
+  addr += 0x40;
+  bx_pit.write(addr, data, 1);
+  return bus::ok;
+}
+
+bus::status
+pit::read_port_0x61 (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+{
+  addr += 0x61;
+  data = bx_pit.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+pit::write_port_0x61 (host_int_4 addr, little_int_1 mask, little_int_1 data)
+{
+  addr += 0x61;
+  bx_pit.write(addr, data, 1);
+  return bus::ok;
+}
diff --git a/sid/component/bochs/pit/sid-pit-wrapper.h b/sid/component/bochs/pit/sid-pit-wrapper.h
new file mode 100644 (file)
index 0000000..f40af5a
--- /dev/null
@@ -0,0 +1,65 @@
+// sid-pit-wrapper.h - SID import of the bochs pit component.  -*- C++ -*-
+
+// Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
+// This file is part of SID and is licensed under the GPL.
+// See the file COPYING.SID for conditions for redistribution.
+
+#ifndef SID_PIT_WRAPPER_DEF_H
+#define SID_PIT_WRAPPER_DEF_H  1
+
+#include <sidtypes.h>
+#include <sidcomp.h>
+#include <sidcomputil.h>
+#include <sidpinutil.h>
+#include <sidbusutil.h>
+#include <sidattrutil.h>
+#include <sidcpuutil.h>
+#include <sidpinattrutil.h>
+#include <sidmiscutil.h>
+#include <sidwatchutil.h>
+#include <sidso.h>
+
+#include "bochs.h"
+
+using sid::component;
+using sid::bus;
+using sid::host_int_4;
+using sid::little_int_1;
+using sidutil::callback_word_bus;
+using sidutil::callback_pin;
+using sidutil::output_pin;
+
+class pit : public sidutil::fixed_pin_map_component,
+            public sidutil::no_accessor_component,
+            public sidutil::fixed_attribute_map_component,
+            public sidutil::no_relation_component,
+            public sidutil::fixed_bus_map_component
+{
+public:
+  pit();
+  ~pit() throw() {};
+
+  void init(host_int_4);
+  void update_pit(host_int_4);
+  
+protected:
+
+  output_pin trigger_irq_pin;
+
+  callback_pin<pit> init_pin;
+  callback_pin<pit> update_pit_pin;
+
+  bus::status read_port_0x40_0x43 (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x40_0x43 (host_int_4 addr, little_int_1 mask, little_int_1 data);
+
+  bus::status read_port_0x61 (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x61 (host_int_4 addr, little_int_1 mask, little_int_1 data);
+
+  callback_word_bus<pit, little_int_1> ports_0x40_0x43_bus;
+  callback_word_bus<pit, little_int_1> port_0x61_bus;
+
+  host_int_4 timer_delta;
+  host_int_4 pit_irq_number;
+  bx_pit_c bx_pit;
+};
+#endif // SID_PIT_WRAPPER_DEF_H
diff --git a/sid/component/bochs/unmapped/Makefile.am b/sid/component/bochs/unmapped/Makefile.am
new file mode 100644 (file)
index 0000000..410f0f4
--- /dev/null
@@ -0,0 +1,11 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../cpu
+
+noinst_LTLIBRARIES = libunmapped.la
+
+libunmapped_la_SOURCES = sid-unmapped-wrapper.cc sid-unmapped-wrapper.h unmapped.cc unmapped.h
+
+libunmapped_la_LDFLAGS = -no-undefined
diff --git a/sid/component/bochs/unmapped/Makefile.in b/sid/component/bochs/unmapped/Makefile.in
new file mode 100644 (file)
index 0000000..f1a4102
--- /dev/null
@@ -0,0 +1,412 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+APIC_OBJS = @APIC_OBJS@
+AR = @AR@
+AS = @AS@
+AS_DYNAMIC_INCS = @AS_DYNAMIC_INCS@
+AS_DYNAMIC_OBJS = @AS_DYNAMIC_OBJS@
+BX_LOADER_OBJS = @BX_LOADER_OBJS@
+BX_SPLIT_HD_SUPPORT = @BX_SPLIT_HD_SUPPORT@
+CC = @CC@
+CDROM_OBJS = @CDROM_OBJS@
+CD_UP_ONE = @CD_UP_ONE@
+CD_UP_TWO = @CD_UP_TWO@
+CFP = @CFP@
+COMMAND_SEPARATOR = @COMMAND_SEPARATOR@
+CPP_SUFFIX = @CPP_SUFFIX@
+CXX = @CXX@
+CXXFP = @CXXFP@
+DASH = @DASH@
+DEBUGGER_VAR = @DEBUGGER_VAR@
+DISASM_VAR = @DISASM_VAR@
+DLLTOOL = @DLLTOOL@
+DYNAMIC_VAR = @DYNAMIC_VAR@
+EXE = @EXE@
+EXEEXT = @EXEEXT@
+EXTERNAL_DEPENDENCY = @EXTERNAL_DEPENDENCY@
+FPU_GLUE_OBJ = @FPU_GLUE_OBJ@
+FPU_VAR = @FPU_VAR@
+GUI_LINK_OPTS = @GUI_LINK_OPTS@
+GUI_LINK_OPTS_TERM = @GUI_LINK_OPTS_TERM@
+GUI_OBJS = @GUI_OBJS@
+GZIP = @GZIP@
+INLINE_VAR = @INLINE_VAR@
+INSTRUMENT_DIR = @INSTRUMENT_DIR@
+INSTRUMENT_VAR = @INSTRUMENT_VAR@
+IOAPIC_OBJS = @IOAPIC_OBJS@
+IODEV_LIB_VAR = @IODEV_LIB_VAR@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LINK = @LINK@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKELIB = @MAKELIB@
+NE2K_OBJS = @NE2K_OBJS@
+NM = @NM@
+NONINLINE_VAR = @NONINLINE_VAR@
+OBJDUMP = @OBJDUMP@
+OFP = @OFP@
+PACKAGE = @PACKAGE@
+PCI_OBJ = @PCI_OBJ@
+PRIMARY_TARGET = @PRIMARY_TARGET@
+RANLIB = @RANLIB@
+READLINE_LIB = @READLINE_LIB@
+RFB_LIBS = @RFB_LIBS@
+RMCOMMAND = @RMCOMMAND@
+SB16_OBJS = @SB16_OBJS@
+SLASH = @SLASH@
+SUFFIX_LINE = @SUFFIX_LINE@
+TAR = @TAR@
+VERSION = @VERSION@
+VIDEO_OBJS = @VIDEO_OBJS@
+sidtarget_arm = @sidtarget_arm@
+sidtarget_m32r = @sidtarget_m32r@
+sidtarget_m68k = @sidtarget_m68k@
+sidtarget_mips = @sidtarget_mips@
+sidtarget_ppc = @sidtarget_ppc@
+sidtarget_x86 = @sidtarget_x86@
+sidtarget_xstormy16 = @sidtarget_xstormy16@
+
+AUTOMAKE_OPTIONS = foreign
+
+INCLUDES = -I$(top_builddir)/../../include -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../../include -I$(srcdir)/../cpu
+
+noinst_LTLIBRARIES = libunmapped.la
+
+libunmapped_la_SOURCES = sid-unmapped-wrapper.cc sid-unmapped-wrapper.h unmapped.cc unmapped.h
+
+libunmapped_la_LDFLAGS = -no-undefined
+mkinstalldirs = $(SHELL) $(top_srcdir)/../../config/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+LTLIBRARIES =  $(noinst_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libunmapped_la_LIBADD = 
+libunmapped_la_OBJECTS =  sid-unmapped-wrapper.lo unmapped.lo
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+GZIP_ENV = --best
+DEP_FILES =  .deps/sid-unmapped-wrapper.P .deps/unmapped.P
+SOURCES = $(libunmapped_la_SOURCES)
+OBJECTS = $(libunmapped_la_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .lo .o .s
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --foreign unmapped/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLTLIBRARIES:
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+
+distclean-noinstLTLIBRARIES:
+
+maintainer-clean-noinstLTLIBRARIES:
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libunmapped.la: $(libunmapped_la_OBJECTS) $(libunmapped_la_DEPENDENCIES)
+       $(CXXLINK)  $(libunmapped_la_LDFLAGS) $(libunmapped_la_OBJECTS) $(libunmapped_la_LIBADD) $(LIBS)
+.cc.o:
+       $(CXXCOMPILE) -c $<
+.cc.lo:
+       $(LTCXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = unmapped
+
+distdir: $(DISTFILES)
+       here=`cd $(top_builddir) && pwd`; \
+       top_distdir=`cd $(top_distdir) && pwd`; \
+       distdir=`cd $(distdir) && pwd`; \
+       cd $(top_srcdir) \
+         && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign unmapped/Makefile
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+       -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+       @echo '$(COMPILE) -c $<'; \
+       $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.c
+       @echo '$(LTCOMPILE) -c $<'; \
+       $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+
+%.o: %.cc
+       @echo '$(CXXCOMPILE) -c $<'; \
+       $(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-cp .deps/$(*F).pp .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm .deps/$(*F).pp
+
+%.lo: %.cc
+       @echo '$(LTCXXCOMPILE) -c $<'; \
+       $(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+       @-sed -e 's/^\([^:]*\)\.o[      ]*:/\1.lo \1.o :/' \
+         < .deps/$(*F).pp > .deps/$(*F).P; \
+       tr ' ' '\012' < .deps/$(*F).pp \
+         | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+           >> .deps/$(*F).P; \
+       rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LTLIBRARIES)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLTLIBRARIES mostlyclean-compile \
+               mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+               mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLTLIBRARIES clean-compile clean-libtool \
+               clean-tags clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLTLIBRARIES distclean-compile \
+               distclean-libtool distclean-tags distclean-depend \
+               distclean-generic clean-am
+       -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLTLIBRARIES \
+               maintainer-clean-compile maintainer-clean-libtool \
+               maintainer-clean-tags maintainer-clean-depend \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \
+clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sid/component/bochs/unmapped/sid-unmapped-wrapper.cc b/sid/component/bochs/unmapped/sid-unmapped-wrapper.cc
new file mode 100644 (file)
index 0000000..cf8af98
--- /dev/null
@@ -0,0 +1,65 @@
+// sid-unmapped-wrapper.cc - SID import of the bochs unmapped component.  -*- C++ -*-
+
+// Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
+// This file is part of SID and is licensed under the GPL.
+// See the file COPYING.SID for conditions for redistribution.
+
+#include "sid-unmapped-wrapper.h"
+
+unmapped::unmapped ()
+    : port_0xfff0_bus(this, & unmapped::read_port_0xfff0, & unmapped::write_port_0xfff0),
+      port_0x400_bus(this, & unmapped::read_port_0x400, & unmapped::write_port_0x400),
+      port_0x80_bus(this, & unmapped::read_port_0x80, & unmapped::write_port_0x80)
+{
+  add_bus("port-0xfff0", & this->port_0xfff0_bus);
+  add_bus("port-0x400", & this->port_0x400_bus);
+  add_bus("port-0x80", & this->port_0x80_bus);
+}
+
+bus::status
+unmapped::read_port_0xfff0 (host_int_4 addr, little_int_4 mask, little_int_4 & data)
+{
+  addr += 0xfff0;
+  data = bx_unmapped.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+unmapped::write_port_0xfff0 (host_int_4 addr, little_int_4 mask, little_int_4 data)
+{
+  addr += 0xfff0;
+  bx_unmapped.write(addr, data, 1);
+  return bus::ok;
+}
+
+bus::status
+unmapped::read_port_0x400 (host_int_4 addr, little_int_4 mask, little_int_4 & data)
+{
+  addr += 0x400;
+  data = bx_unmapped.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+unmapped::write_port_0x400 (host_int_4 addr, little_int_4 mask, little_int_4 data)
+{
+  addr += 0x400;
+  bx_unmapped.write(addr, data, 1);
+  return bus::ok;
+}
+
+bus::status
+unmapped::read_port_0x80 (host_int_4 addr, little_int_4 mask, little_int_4 & data)
+{
+  addr += 0x80;
+  data = bx_unmapped.read(addr, 1);
+  return bus::ok;
+}
+
+bus::status
+unmapped::write_port_0x80 (host_int_4 addr, little_int_4 mask, little_int_4 data)
+{
+  addr += 0x80;
+  bx_unmapped.write(addr, data, 1);
+  return bus::ok;
+}
diff --git a/sid/component/bochs/unmapped/sid-unmapped-wrapper.h b/sid/component/bochs/unmapped/sid-unmapped-wrapper.h
new file mode 100644 (file)
index 0000000..df59a11
--- /dev/null
@@ -0,0 +1,59 @@
+// sid-unmapped-wrapper.h - SID import of the bochs unmapped component.  -*- C++ -*-
+
+// Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
+// This file is part of SID and is licensed under the GPL.
+// See the file COPYING.SID for conditions for redistribution.
+
+#ifndef SID_UNMAPPED_WRAPPER_DEF_H
+#define SID_UNMAPPED_WRAPPER_DEF_H     1
+
+#include <sidtypes.h>
+#include <sidcomp.h>
+#include <sidcomputil.h>
+#include <sidpinutil.h>
+#include <sidbusutil.h>
+#include <sidattrutil.h>
+#include <sidcpuutil.h>
+#include <sidpinattrutil.h>
+#include <sidmiscutil.h>
+#include <sidwatchutil.h>
+#include <sidso.h>
+
+#include "bochs.h"
+
+using sid::component;
+using sid::bus;
+using sid::host_int_4;
+using sid::little_int_4;
+using sidutil::callback_word_bus;
+using sidutil::callback_pin;
+using sidutil::output_pin;
+
+class unmapped : public sidutil::fixed_pin_map_component,
+            public sidutil::no_accessor_component,
+            public sidutil::fixed_attribute_map_component,
+            public sidutil::no_relation_component,
+            public sidutil::fixed_bus_map_component
+{
+public:
+  unmapped();
+  ~unmapped() throw() {};
+
+protected:
+
+  bus::status read_port_0xfff0 (host_int_4 addr, little_int_4 mask, little_int_4 & data);
+  bus::status write_port_0xfff0 (host_int_4 addr, little_int_4 mask, little_int_4 data);
+
+  bus::status read_port_0x400 (host_int_4 addr, little_int_4 mask, little_int_4 & data);
+  bus::status write_port_0x400 (host_int_4 addr, little_int_4 mask, little_int_4 data);
+
+  bus::status read_port_0x80 (host_int_4 addr, little_int_4 mask, little_int_4 & data);
+  bus::status write_port_0x80 (host_int_4 addr, little_int_4 mask, little_int_4 data);
+
+  callback_word_bus<unmapped, little_int_4> port_0xfff0_bus;
+  callback_word_bus<unmapped, little_int_4> port_0x400_bus;
+  callback_word_bus<unmapped, little_int_4> port_0x80_bus;
+
+  bx_unmapped_c bx_unmapped;
+};
+#endif // SID_UNMAPPED_WRAPPER_DEF_H
diff --git a/sid/component/bochs/unmapped/unmapped.cc b/sid/component/bochs/unmapped/unmapped.cc
new file mode 100644 (file)
index 0000000..a4f7eda
--- /dev/null
@@ -0,0 +1,292 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+
+#include "bochs.h"
+#if BX_SUPPORT_SID
+#define LOG_THIS
+#include "sid-unmapped-wrapper.h"
+#else
+#define LOG_THIS bx_unmapped.
+
+
+bx_unmapped_c bx_unmapped;
+#endif
+
+#if BX_USE_UM_SMF
+#define this (&bx_unmapped)
+#endif
+
+
+bx_unmapped_c::bx_unmapped_c(void)
+{
+  s.port80 = 0x00;
+  s.port8e = 0x00;
+
+  s.bios_message_i = 0;
+}
+
+bx_unmapped_c::~bx_unmapped_c(void)
+{
+  // nothing for now
+}
+
+#if BX_SUPPORT_SID
+void
+bx_unmapped_c::init(void)
+#else
+  void
+bx_unmapped_c::init(bx_devices_c *d)
+#endif
+{
+#if BX_SUPPORT_SID==0
+  BX_UM_THIS devices = d;
+
+  for (Bit32u addr=0; addr<0x10000; addr++) {
+    BX_UM_THIS devices->register_io_read_handler(this, read_handler,
+                                      addr, "Unmapped");
+    BX_UM_THIS devices->register_io_write_handler(this, write_handler,
+                                      addr, "Unmapped");
+    }
+#endif // BX_SUPPORT_SID==0
+}
+
+
+  // static IO port read callback handler
+  // redirects to non-static class handler to avoid virtual functions
+
+  Bit32u
+bx_unmapped_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
+{
+#if !BX_USE_UM_SMF
+  bx_unmapped_c *class_ptr = (bx_unmapped_c *) this_ptr;
+
+  return( class_ptr->read(address, io_len) );
+}
+
+  Bit32u
+bx_unmapped_c::read(Bit32u address, unsigned io_len)
+{
+#else
+  UNUSED(this_ptr);
+#endif  // !BX_USE_UM_SMF
+  UNUSED(io_len);
+
+  Bit32u retval;
+
+  // This function gets called for access to any IO ports which
+  // are not mapped to any device handler.  Reads return 0
+
+  if (address >= 0x02e0 && address <= 0x02ef) {
+       retval = 0;
+       goto return_from_read;
+  }
+
+  switch (address) {
+    case 0x80:
+         retval = BX_UM_THIS s.port80;
+         break;
+    case 0x8e:
+         retval = BX_UM_THIS s.port8e;
+         break;
+#if BX_PORT_E9_HACK
+    // Unused port on ISA - this can be used by the emulated code
+    // to detect it is running inside Bochs and that the debugging
+    // features are available (write 0xFF or something on unused
+    // port 0x80, then read from 0xe9, if value is 0xe9, debug
+    // output is available) (see write() for that) -- Andreas and Emmanuel
+    case 0xe9:
+         retval = 0xe9;
+         break;
+#endif
+    case 0x03df:
+         retval = 0xffffffff;
+      BX_DEBUG(("unsupported IO read from port %04x (CGA)\n", address));
+      break;
+    case 0x023a:
+    case 0x02f8: /* UART */
+    case 0x02f9: /* UART */
+    case 0x02fb: /* UART */
+    case 0x02fc: /* UART */
+    case 0x02fd: /* UART */
+    case 0x02ea:
+    case 0x02eb:
+    case 0x03e8:
+    case 0x03e9:
+    case 0x03ea:
+    case 0x03eb:
+    case 0x03ec:
+    case 0x03ed:
+    case 0x03f8: /* UART */
+    case 0x03f9: /* UART */
+    case 0x03fb: /* UART */
+    case 0x03fc: /* UART */
+    case 0x03fd: /* UART */
+    case 0x17c6:
+         retval = 0xffffffff;
+      BX_DEBUG(("unsupported IO read from port %04x\n", address));
+      break;
+    default:
+         retval = 0xffffffff;
+    }
+
+  return_from_read:
+  if (bx_dbg.unsupported_io)
+         switch (io_len) {
+         case 1:
+                 retval = (Bit8u)retval;
+                 BX_DEBUG(("unmapped: 8-bit read from %04x = %02x\n", address, retval));
+                 break;
+         case 2:
+                 retval = (Bit16u)retval;
+                 BX_DEBUG(("unmapped: 16-bit read from %04x = %04x\n", address, retval));
+                 break;
+         case 4:
+                 BX_DEBUG(("unmapped: 32-bit read from %04x = %08x\n", address, retval));
+                 break;
+         default:
+                 BX_DEBUG(("unmapped: ??-bit read from %04x = %x\n", address, retval));
+         }
+  return retval;
+}
+
+
+  // static IO port write callback handler
+  // redirects to non-static class handler to avoid virtual functions
+
+  void
+bx_unmapped_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
+{
+#if !BX_USE_UM_SMF
+  bx_unmapped_c *class_ptr = (bx_unmapped_c *) this_ptr;
+
+  class_ptr->write(address, value, io_len);
+}
+
+  void
+bx_unmapped_c::write(Bit32u address, Bit32u value, unsigned io_len)
+{
+#else
+  UNUSED(this_ptr);
+#endif  // !BX_USE_UM_SMF
+  UNUSED(io_len);
+
+
+  // This function gets called for access to any IO ports which
+  // are not mapped to any device handler.  Writes to an unmapped
+  // IO port are ignored.
+
+// ???
+
+
+  if (address >= 0x02e0 && address <= 0x02ef)
+       goto return_from_write;
+
+  switch (address) {
+    case 0x80: // diagnostic test port to display progress of POST
+      //BX_DEBUG(("Diagnostic port 80h: write = %02xh\n", (unsigned) value));
+      BX_UM_THIS s.port80 = value;
+      break;
+
+    case 0x8e: // ???
+      BX_UM_THIS s.port8e = value;
+      break;
+
+#if BX_PORT_E9_HACK
+    // This port doesn't exist on normal ISA architecture. However,
+    // we define a convention here, to display on the console of the
+    // system running Bochs, anything that is written to it. The
+    // idea is to provide debug output very early when writing
+    // BIOS or OS code for example, without having to bother with
+    // properly setting up a serial port or anything.
+    //
+    // Idea by Andreas Beck (andreas.beck@ggi-project.org)
+
+    case 0xe9:
+      putchar(value);
+      fflush(stdout);
+      break;
+#endif
+    case 0xed: // Dummy port used as I/O delay
+         break;
+    case 0xee: // ???
+         break;
+
+    case 0x2f2:
+    case 0x2f3:
+    case 0x2f4:
+    case 0x2f5:
+    case 0x2f6:
+    case 0x2f7:
+    case 0x3e8:
+    case 0x3e9:
+    case 0x3eb:
+    case 0x3ec:
+    case 0x3ed:
+           // BX_DEBUG(("unsupported IO write to port %04x of %02x\n",
+           // address, value));
+      break;
+    case 0x0400:
+      BX_PANIC(("BIOS panic at rombios.c, line %d\n", value));
+      break;
+    case 0xfedc:
+      bx_dbg.debugger = (value > 0);
+               BX_DEBUG(( "DEBUGGER = %u\n", (unsigned) bx_dbg.debugger));
+      break;
+
+    case 0xfff0:
+      BX_UM_THIS s.bios_message[BX_UM_THIS s.bios_message_i] =
+        (Bit8u) value;
+      BX_UM_THIS s.bios_message_i ++;
+      if ( BX_UM_THIS s.bios_message_i >= BX_BIOS_MESSAGE_SIZE ) {
+        BX_UM_THIS s.bios_message[ BX_BIOS_MESSAGE_SIZE - 1] = 0;
+        BX_UM_THIS s.bios_message_i = 0;
+        BX_INFO(("BIOS message: %s", BX_UM_THIS s.bios_message));
+        }
+      else if ((value & 0xff) == '\n') {
+        BX_UM_THIS s.bios_message[ BX_UM_THIS s.bios_message_i ] = 0;
+        BX_UM_THIS s.bios_message_i = 0;
+        BX_INFO(("BIOS message: %s", BX_UM_THIS s.bios_message));
+        }
+      break;
+
+    default:
+           break;
+    }
+  return_from_write:
+  if (bx_dbg.unsupported_io)
+         switch (io_len) {
+         case 1:
+                 BX_INFO(("unmapped: 8-bit write to %04x = %02x\n", address, value));
+                 break;
+         case 2:
+                 BX_INFO(("unmapped: 16-bit write to %04x = %04x\n", address, value));
+                 break;
+         case 4:
+                 BX_INFO(("unmapped: 32-bit write to %04x = %08x\n", address, value));
+                 break;
+         default:
+                 BX_INFO(("unmapped: ??-bit write to %04x = %x\n", address, value));
+                 break;
+         }
+}
diff --git a/sid/component/bochs/unmapped/unmapped.h b/sid/component/bochs/unmapped/unmapped.h
new file mode 100644 (file)
index 0000000..d98b36b
--- /dev/null
@@ -0,0 +1,79 @@
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+
+
+#define BX_BIOS_MESSAGE_SIZE 80
+
+
+#if BX_USE_UM_SMF
+#  define BX_UM_SMF  static
+#  define BX_UM_THIS bx_unmapped.
+#else
+#  define BX_UM_SMF
+#  define BX_UM_THIS this->
+#endif
+
+
+
+class bx_unmapped_c : public logfunctions {
+public:
+  bx_unmapped_c(void);
+  ~bx_unmapped_c(void);
+#if BX_SUPPORT_SID
+  BX_UM_SMF void   init(void);
+#else
+  BX_UM_SMF void   init(bx_devices_c *d);
+#endif
+
+private:
+
+  static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
+  static void   write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
+#if BX_SUPPORT_SID
+ public:
+#endif
+#if !BX_USE_UM_SMF
+  Bit32u read(Bit32u address, unsigned io_len);
+  void   write(Bit32u address, Bit32u value, unsigned io_len);
+#endif
+#if BX_SUPPORT_SID
+ private:
+#endif
+
+  struct {
+    Bit8u port80;
+    Bit8u port8e;
+
+    Bit8u bios_message[BX_BIOS_MESSAGE_SIZE];
+    unsigned int bios_message_i;
+    } s;  // state information
+
+#if BX_SUPPORT_SID==0
+  bx_devices_c *devices;
+#endif
+  };
+
+#if BX_SUPPORT_SID==0
+extern bx_unmapped_c bx_unmapped;
+#endif
index b6e49d5..e450f05 100644 (file)
@@ -6,14 +6,34 @@
 
 #include "sid-vga-wrapper.h"
 
+#include <cstdlib>
+#include <cerrno>
+#include <ctime>
+#include <unistd.h>
+#include <fstream>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+using sidutil::make_attribute;
+using sidutil::parse_attribute;
+using sidutil::find_sid_data_file;
+using sidutil::std_error_string;
+
 vga::vga ()
     : init_pin(this, & vga::init),
-      ports_3b4_3b5_bus(this, & vga::read_port_3b4_3b5, &vga::write_port_3b4_3b5),
-      ports_3ba_bus(this, & vga::read_port_3ba, &vga::write_port_3ba),
-      ports_3c0_3cf_bus(this, & vga::read_port_3c0_3cf, &vga::write_port_3c0_3cf),
-      ports_3d4_3d5_bus(this, & vga::read_port_3d4_3d5, &vga::write_port_3d4_3d5),
-      ports_3da_bus(this, & vga::read_port_3da, &vga::write_port_3da),
-      framebuffer_bus(this, & vga::read_mem, &vga::write_mem)
+      ports_0x3b4_0x3b5_bus(this, & vga::read_port_0x3b4_0x3b5, &vga::write_port_0x3b4_0x3b5),
+      port_0x3ba_bus(this, & vga::read_port_0x3ba, &vga::write_port_0x3ba),
+      ports_0x3c0_0x3cf_bus(this, & vga::read_port_0x3c0_0x3cf, &vga::write_port_0x3c0_0x3cf),
+      ports_0x3d4_0x3d5_bus(this, & vga::read_port_0x3d4_0x3d5, &vga::write_port_0x3d4_0x3d5),
+      port_0x3da_bus(this, & vga::read_port_0x3da, &vga::write_port_0x3da),
+      cmos_registers_bus(0),
+      framebuffer_bus(this, & vga::read_mem, &vga::write_mem),
+      imageload_pin (this, & vga::imageload_handler),
+      imagestore_pin (this, & vga::imagestore_handler),
+      imagemmap_pin (this, & vga::imagemmap_handler),
+      imagemsync_pin (this, & vga::imagemsync_handler)
 {
   add_pin("init", & this->init_pin);
 
@@ -28,97 +48,129 @@ vga::vga ()
 
   add_pin("palette-change-index", & this->palette_change_index_pin);
 
-  add_bus("ports-0x3b4-0x3b5", & this->ports_3b4_3b5_bus);
-  add_bus("port-0x3ba", & this->ports_3ba_bus);
-  add_bus("ports-0x3c0-0x3cf", & this->ports_3c0_3cf_bus);
-  add_bus("ports-0x3d4-0x3d5", & this->ports_3d4_3d5_bus);
-  add_bus("port-0x3da", & this->ports_3da_bus);
+  add_bus("ports-0x3b4-0x3b5", & this->ports_0x3b4_0x3b5_bus);
+  add_bus("port-0x3ba", & this->port_0x3ba_bus);
+  add_bus("ports-0x3c0-0x3cf", & this->ports_0x3c0_0x3cf_bus);
+  add_bus("ports-0x3d4-0x3d5", & this->ports_0x3d4_0x3d5_bus);
+  add_bus("port-0x3da", & this->port_0x3da_bus);
 
   add_bus("framebuffer", & this->framebuffer_bus);
+
+  add_accessor("cmos-registers", & this->cmos_registers_bus);
+
+  // copied from sid/component/memory/generic.cxx
+
+  add_attribute_virtual ("size", this,
+                        & vga::get_size_attr,
+                        & vga::set_size_attr, "setting");
+
+  this->max_buffer_length = 32UL * 1024UL * 1024UL;
+  this->buffer = 0;
+  this->buffer_length = 0;
+  this->mmapping_p = false;
+
+  add_attribute ("image-file", & this->image_file_name, "setting");
+  add_pin ("image-load", & this->imageload_pin);
+  add_attribute ("image-load", & this->imageload_pin, "pin");
+  add_pin ("image-store", & this->imagestore_pin);
+  add_attribute ("image-store", & this->imagestore_pin, "pin");
+  add_pin ("image-mmap", & this->imagemmap_pin);
+  add_attribute ("image-mmap", & this->imagemmap_pin, "pin");
+  add_pin ("image-msync", & this->imagemsync_pin);
+  add_attribute ("image-msync", & this->imagemsync_pin, "pin");
 }
 
 void
 vga::init (host_int_4)
 {
   bx_vga.init(this, this->buffer);
+  if (cmos_registers_bus)
+    {
+      little_int_1 old_register_value;
+      little_int_1 new_register_value;
+
+      cmos_registers_bus->read(host_int_4(0x14), old_register_value);
+      new_register_value = (old_register_value & 0xcf) | 0x00;
+      cmos_registers_bus->write(host_int_4(0x14), little_int_1(0x00)); /* video card with BIOS ROM */
+    }
 }
 
 bus::status
-vga::read_port_3b4_3b5 (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+vga::read_port_0x3b4_0x3b5 (host_int_4 addr, little_int_1 mask, little_int_1 & data)
 {
-  addr += 0x03b4;
+  addr += 0x3b4;
   data = bx_vga.read(addr, 1);
   return bus::ok;
 }
 
 bus::status
-vga::write_port_3b4_3b5 (host_int_4 addr, little_int_1 mask, little_int_1 data)
+vga::write_port_0x3b4_0x3b5 (host_int_4 addr, little_int_1 mask, little_int_1 data)
 {
-  addr += 0x03b4;
+  addr += 0x3b4;
   bx_vga.write(addr, data, 1, true);
   return bus::ok;
 }
 
 bus::status
-vga::read_port_3ba (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+vga::read_port_0x3ba (host_int_4 addr, little_int_1 mask, little_int_1 & data)
 {
-  addr += 0x03ba;
+  addr += 0x3ba;
   data = bx_vga.read(addr, 1);
   return bus::ok;
 }
 
 bus::status
-vga::write_port_3ba (host_int_4 addr, little_int_1 mask, little_int_1 data)
+vga::write_port_0x3ba (host_int_4 addr, little_int_1 mask, little_int_1 data)
 {
-  addr += 0x03ba;
+  addr += 0x3ba;
   bx_vga.write(addr, data, 1, true);
   return bus::ok;
 }
 
 bus::status
-vga::read_port_3c0_3cf (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+vga::read_port_0x3c0_0x3cf (host_int_4 addr, little_int_1 mask, little_int_1 & data)
 {
-  addr += 0x03c0;
+  addr += 0x3c0;
   data = bx_vga.read(addr, 1);
   return bus::ok;
 }
 
 bus::status
-vga::write_port_3c0_3cf (host_int_4 addr, little_int_1 mask, little_int_1 data)
+vga::write_port_0x3c0_0x3cf (host_int_4 addr, little_int_1 mask, little_int_1 data)
 {
-  addr += 0x03c0;
+  addr += 0x3c0;
   bx_vga.write(addr, data, 1, true);
   return bus::ok;
 }
 
 bus::status
-vga::read_port_3d4_3d5 (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+vga::read_port_0x3d4_0x3d5 (host_int_4 addr, little_int_1 mask, little_int_1 & data)
 {
-  addr += 0x03d4;
+  addr += 0x3d4;
   data = bx_vga.read(addr, 1);
   return bus::ok;
 }
 
 bus::status
-vga::write_port_3d4_3d5 (host_int_4 addr, little_int_1 mask, little_int_1 data)
+vga::write_port_0x3d4_0x3d5 (host_int_4 addr, little_int_1 mask, little_int_1 data)
 {
-  addr += 0x03d4;
+  addr += 0x3d4;
   bx_vga.write(addr, data, 1, true);
   return bus::ok;
 }
 
 bus::status
-vga::read_port_3da (host_int_4 addr, little_int_1 mask, little_int_1 & data)
+vga::read_port_0x3da (host_int_4 addr, little_int_1 mask, little_int_1 & data)
 {
-  addr += 0x03da;
+  addr += 0x3da;
   data = bx_vga.read(addr, 1);
   return bus::ok;
 }
 
 bus::status
-vga::write_port_3da (host_int_4 addr, little_int_1 mask, little_int_1 data)
+vga::write_port_0x3da (host_int_4 addr, little_int_1 mask, little_int_1 data)
 {
-  addr += 0x03da;
+  addr += 0x3da;
   bx_vga.write(addr, data, 1, true);
   return bus::ok;
 }
@@ -186,3 +238,186 @@ vga::drive_palette_change_index_pin (host_int_4 index)
 {
   this->palette_change_index_pin.drive(index);
 }
+
+bool
+vga::attempt_resize (host_int_4 new_length) throw()
+{
+  if (new_length > max_buffer_length)
+    return false;
+  
+  host_int_1* new_buffer = new (nothrow) host_int_1[new_length];
+  if (new_buffer == 0)
+    {
+      cerr << "memory: error allocating memory buffer: " << std_error_string() << endl;
+      this->error_pin.drive (0);
+      return false;
+    }
+
+  if (this->mmapping_p)
+    {
+      munmap (reinterpret_cast<char*>(this->buffer), this->buffer_length);
+      this->mmapping_p = false;
+    }
+  else
+    delete [] this->buffer;
+
+  this->buffer = new_buffer;
+  this->buffer_length = new_length;
+  memset(this->buffer, 0, this->buffer_length);
+
+  return true;
+}
+
+string
+vga::get_size_attr ()
+{
+  return make_attribute (this->buffer_length);
+}
+
+
+component::status
+vga::set_size_attr (const string& s)
+{
+  host_int_4 new_size;
+  component::status st = parse_attribute(s, new_size);
+  if (st == component::ok)
+    {
+      bool ok = this->attempt_resize (new_size);
+      if (! ok)
+       return component::bad_value;
+    }
+  return st;
+}
+
+void
+vga::imageload_handler (host_int_4)
+{
+  assert(this->buffer != 0);
+
+  // Do nothing if file name was empty.
+  if (this->image_file_name == "")
+    {
+      cerr << "memory: no image-file set for image-load" << endl;
+      this->error_pin.drive (0);
+      return;
+    }
+
+  ifstream f (find_sid_data_file(this->image_file_name).c_str(), ios::binary | ios::in);
+  if (! f.good())
+    {
+      cerr << "memory: error opening " << this->image_file_name << ": "
+          << std_error_string() << endl;
+      this->error_pin.drive (0);
+      return;
+    }
+
+  // Load whole darned file
+  memset (& this->buffer[0], 0, this->buffer_length);
+  f.read (reinterpret_cast<char*>(& this->buffer[0]), this->buffer_length);
+}
+
+
+
+void
+vga::imagestore_handler (host_int_4)
+{
+  assert(this->buffer != 0);
+
+  // Do nothing if file name was empty.
+  if (this->image_file_name == "")
+    {
+      cerr << "memory: no image-file set for image-store" << endl;
+      this->error_pin.drive (0);
+      return;
+    }
+
+  ofstream f (find_sid_data_file(this->image_file_name).c_str(),
+             ios::binary | ios::out | ios::trunc);
+  if (! f.good())
+    {
+      cerr << "memory: error opening " << this->image_file_name << ": "
+       << std_error_string() << endl;
+      this->error_pin.drive (0);
+      return;
+    }
+
+  // Save whole darned file
+  f.write (reinterpret_cast<const char*>(& this->buffer[0]), this->buffer_length);
+  // if (! f.good())
+  //  cerr << "memory: short write to " << this->image_file_name << endl;
+}
+
+
+
+
+void
+vga::imagemsync_handler (host_int_4)
+{
+  assert (this->buffer);
+  if (this->mmapping_p)
+    {
+      int rc = msync (reinterpret_cast<char*>(this->buffer),
+                     this->buffer_length, MS_SYNC|MS_INVALIDATE);
+      if (rc < 0) 
+       cerr << "memory: failed in mmap:" << std_error_string() << endl;
+    }
+}
+
+
+
+void
+vga::imagemmap_handler (host_int_4)
+{
+  assert (this->buffer);
+
+  // Do nothing if file name was empty.
+  if (this->image_file_name == "")
+    {
+      cerr << "memory: no image-file set for image-mmap" << endl;
+      this->error_pin.drive (0);
+      return;
+    }
+
+  int fd = open (find_sid_data_file(this->image_file_name).c_str(), O_RDWR);
+  if (fd < 0)
+    {
+      cerr << "memory: cannot open image-file during image-mmap:" << std_error_string() << endl;
+      this->error_pin.drive (0);
+      return;
+    }
+
+  /* Some kernels will SIGBUS the application if mmap'd file is not large enough.  */ 
+  struct stat desc;
+  int rc = fstat (fd, & desc);
+  if (rc < 0 || desc.st_size < this->buffer_length)
+    {
+      cerr << "memory: cannot confirm that mmap file is large enough (>= " 
+          << this->buffer_length << " bytes)." << endl;
+      this->error_pin.drive (0);
+      return;
+    }
+
+  char* new_buffer = reinterpret_cast<char*>(mmap (0, this->buffer_length, 
+                                                  PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0));
+#ifndef MAP_FAILED
+#define MAP_FAILED ((char*)-1)
+#endif
+  if (new_buffer == 0 || new_buffer == MAP_FAILED)
+    {
+      cerr << "memory: failed in mmap:" << std_error_string() << endl;
+      close (fd);
+      this->error_pin.drive (0);
+      return;
+    }
+
+  if (this->mmapping_p)
+    {
+      // Unmap previous block first
+      munmap (reinterpret_cast<char*>(this->buffer), this->buffer_length);
+      this->mmapping_p = false;
+    }
+
+  this->buffer = reinterpret_cast<host_int_1*>(new_buffer);
+  close (fd);
+  this->mmapping_p = true;
+}
index a1ebfb9..a5c47ab 100644 (file)
 #include <sidmiscutil.h>
 #include <sidwatchutil.h>
 #include <sidso.h>
-#include "generic.h"
 
 #include "bochs.h"
 
 using sid::component;
 using sid::bus;
+using sid::host_int_1;
 using sid::host_int_4;
 using sid::little_int_1;
+
 using sidutil::callback_word_bus;
 using sidutil::callback_pin;
 using sidutil::output_pin;
 
-class vga : public generic_memory
+class vga : public sidutil::fixed_pin_map_component,
+            public sidutil::fixed_accessor_map_component,
+            public sidutil::fixed_attribute_map_component,
+            public sidutil::no_relation_component,
+            public sidutil::fixed_bus_map_component
 {
 public:
   vga();
@@ -63,28 +68,54 @@ protected:
 
   output_pin palette_change_index_pin;
 
-  bus::status read_port_3b4_3b5 (host_int_4 addr, little_int_1 mask, little_int_1 & data);
-  bus::status write_port_3b4_3b5 (host_int_4 addr, little_int_1 mask, little_int_1 data);
-  bus::status read_port_3ba (host_int_4 addr, little_int_1 mask, little_int_1 & data);
-  bus::status write_port_3ba (host_int_4 addr, little_int_1 mask, little_int_1 data);
-  bus::status read_port_3c0_3cf (host_int_4 addr, little_int_1 mask, little_int_1 & data);
-  bus::status write_port_3c0_3cf (host_int_4 addr, little_int_1 mask, little_int_1 data);
-  bus::status read_port_3d4_3d5 (host_int_4 addr, little_int_1 mask, little_int_1 & data);
-  bus::status write_port_3d4_3d5 (host_int_4 addr, little_int_1 mask, little_int_1 data);
-  bus::status read_port_3da (host_int_4 addr, little_int_1 mask, little_int_1 & data);
-  bus::status write_port_3da (host_int_4 addr, little_int_1 mask, little_int_1 data);
+  bus::status read_port_0x3b4_0x3b5 (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x3b4_0x3b5 (host_int_4 addr, little_int_1 mask, little_int_1 data);
+  bus::status read_port_0x3ba (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x3ba (host_int_4 addr, little_int_1 mask, little_int_1 data);
+  bus::status read_port_0x3c0_0x3cf (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x3c0_0x3cf (host_int_4 addr, little_int_1 mask, little_int_1 data);
+  bus::status read_port_0x3d4_0x3d5 (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x3d4_0x3d5 (host_int_4 addr, little_int_1 mask, little_int_1 data);
+  bus::status read_port_0x3da (host_int_4 addr, little_int_1 mask, little_int_1 & data);
+  bus::status write_port_0x3da (host_int_4 addr, little_int_1 mask, little_int_1 data);
   
-  callback_word_bus<vga, little_int_1> ports_3b4_3b5_bus;
-  callback_word_bus<vga, little_int_1> ports_3ba_bus;
-  callback_word_bus<vga, little_int_1> ports_3c0_3cf_bus;
-  callback_word_bus<vga, little_int_1> ports_3d4_3d5_bus;
-  callback_word_bus<vga, little_int_1> ports_3da_bus;
+  callback_word_bus<vga, little_int_1> ports_0x3b4_0x3b5_bus;
+  callback_word_bus<vga, little_int_1> port_0x3ba_bus;
+  callback_word_bus<vga, little_int_1> ports_0x3c0_0x3cf_bus;
+  callback_word_bus<vga, little_int_1> ports_0x3d4_0x3d5_bus;
+  callback_word_bus<vga, little_int_1> port_0x3da_bus;
 
   bus::status read_mem (host_int_4 addr, little_int_1 mask, little_int_1 & data);
   bus::status write_mem (host_int_4 addr, little_int_1 mask, little_int_1 data);
 
   callback_word_bus<vga, little_int_1> framebuffer_bus;
 
+  bus *cmos_registers_bus;
+
   bx_vga_c bx_vga;
+
+  // copied from sid/component/memory/generic.h
+
+  host_int_1* buffer;
+  host_int_4 buffer_length;
+  bool mmapping_p;
+
+  host_int_4 max_buffer_length;
+  bool attempt_resize (host_int_4 new_length) throw();
+
+  string get_size_attr ();
+  component::status set_size_attr (const string& s);
+
+  string image_file_name;
+  callback_pin<vga> imageload_pin;
+  void imageload_handler (host_int_4);
+  callback_pin<vga> imagestore_pin;
+  void imagestore_handler (host_int_4);
+  output_pin error_pin;
+  callback_pin<vga> imagemmap_pin;
+  void imagemmap_handler (host_int_4);
+  callback_pin<vga> imagemsync_pin;
+  void imagemsync_handler (host_int_4);
+
 };
 #endif // SID_VGA_WRAPPER_DEF_H
index 34b6fc5..ca2cc67 100644 (file)
@@ -1344,7 +1344,10 @@ BX_VGA_THIS s.vga_tile_updated[x_tileno][y_tileno] = 1;
     }
   else {
     BX_VGA_THIS s.vga_memory[addr - 0xa0000] = value;
-    vga_component->drive_text_memory_updated_pin();
+    // only update on odd address writes,
+    // so that color values go through
+    if (addr % 2)
+      vga_component->drive_text_memory_updated_pin();
     BX_VGA_THIS s.vga_mem_updated = 1;
     }
 }
@@ -1443,7 +1446,11 @@ bx_vga_c::update_dimension_pins(bool schedule_update)
           MSL = BX_VGA_THIS s.CRTC.reg[9] & 0x1f;
           rows = (VDE + 1) / (MSL + 1);
           if (rows > BX_MAX_TEXT_LINES)
+#if BX_SUPPORT_SID
+            rows = BX_MAX_TEXT_LINES;
+#else
             BX_PANIC(("text rows>50\n"));
+#endif
           
           piHeight = rows;
         }