c337f3715f
in a multiprocessor simulation. Imagine that! Without the patch, there is just one FPU for all the processors, which is clearly wrong. See bug [ 461762 ] multiple processors but only one FPU
145 lines
5.6 KiB
Plaintext
145 lines
5.6 KiB
Plaintext
----------------------------------------------------------------------
|
|
Patch name: patch.smp-fpu
|
|
Author: Bryce Denney <bryce@thedenneys.org>
|
|
Date: Sat Jun 22 20:12:43 EDT 2002
|
|
|
|
Detailed description:
|
|
|
|
This patch is an attempt to address the bug
|
|
[ 461762 ] multiple processors but only one FPU
|
|
http://sourceforge.net/tracker/?group_id=12580&atid=112580&func=detail&aid=461762
|
|
|
|
WARNING: This is highly experimental, and has no been adequately tested.
|
|
|
|
WARNING: I'm assuming that ALL data specific to a single FPU is stored in the
|
|
i387_t structure. I hope this assumption is valid.
|
|
|
|
It's pretty clear that in an SMP simulation each CPU needs to have its own
|
|
i387_t structure, so I have done that. Each CPU has a field called the_i387
|
|
which is a pointer to a i387_t structure. The pointer is declared as void*
|
|
because when cpu.h is compiled it doesn't know the details of the i387_t
|
|
structure. Only code in fpu/* knows about the complete i387_t structure,
|
|
so it just uses a typecast to cast the "the_i387" field into a pointer to
|
|
the right struct.
|
|
|
|
Part of what's tricky about the FPU code is that it's all written in C, so
|
|
it cannot read bochs.h or know anything about the Bochs types. The
|
|
C/C++ interface is in fpu/fpu.cc and fpu/wmFPUemu_glue.cc (mostly the latter).
|
|
|
|
All the C code was written with the assumption of having a global variable
|
|
called i387 available, but now when Bochs is simulating multiple processors,
|
|
there is a separate copy of the FPU registers in every CPU. I wanted to
|
|
leave all the C code alone, so I defined the i387 expression to mean
|
|
(*current_i387) which is a pointer to the i387 registers in the CPU that's
|
|
being simulated. When any FPU instruction is simulated, the current_i387
|
|
pointer is set according to i387 structure associated with the CPU that's
|
|
executing the instrution. Then all the C code operates on the correct i387
|
|
structure without having to know that there are others around. Only the
|
|
glue code is aware of the other i387 structures.
|
|
|
|
The danger of this approach is that there may be other global variables
|
|
within the fpu code that I'm not aware of that represent miscellaneous FPU
|
|
state. Someone who has the time and cares about correct FPU emulation under
|
|
SMP should look around for such variables. Probably the easiest way to
|
|
deal with them is to add them to the i387 struct.
|
|
|
|
Patch was created with:
|
|
cvs diff -u
|
|
Apply patch to what version:
|
|
cvs checked out on DATE, release version VER
|
|
Instructions:
|
|
To patch, go to main bochs directory.
|
|
Type "patch -p0 < THIS_PATCH_FILE".
|
|
----------------------------------------------------------------------
|
|
|
|
Index: cpu/cpu.h
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/cpu/cpu.h,v
|
|
retrieving revision 1.22
|
|
diff -u -r1.22 cpu.h
|
|
--- cpu/cpu.h 5 Jun 2002 21:51:30 -0000 1.22
|
|
+++ cpu/cpu.h 23 Jun 2002 00:31:47 -0000
|
|
@@ -1270,6 +1270,15 @@
|
|
BX_SMF void ESC6(BxInstruction_t *);
|
|
BX_SMF void ESC7(BxInstruction_t *);
|
|
|
|
+#if BX_SUPPORT_FPU
|
|
+ // This is a pointer to an actual i387_t structure defined in
|
|
+ // fpu/fpu_system.h. A void* is used because at present the fpu headers are
|
|
+ // not included when compiling the cpu or any other part of Bochs for that
|
|
+ // matter. The pointer is initialized to a newly allocated i387_t struct in
|
|
+ // BX_CPU_C::fpu_init() in fpu/wmFPUemu_glue.cc. It is only referenced
|
|
+ // within the fpu/* code.
|
|
+ void *the_i387;
|
|
+#endif
|
|
BX_SMF void fpu_execute(BxInstruction_t *i);
|
|
BX_SMF void fpu_init(void);
|
|
BX_SMF void fpu_print_regs (void);
|
|
Index: fpu/fpu_system.h
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/fpu/fpu_system.h,v
|
|
retrieving revision 1.3
|
|
diff -u -r1.3 fpu_system.h
|
|
--- fpu/fpu_system.h 6 Oct 2001 03:53:46 -0000 1.3
|
|
+++ fpu/fpu_system.h 23 Jun 2002 00:31:47 -0000
|
|
@@ -167,8 +167,15 @@
|
|
} GCC_ATTRIBUTE((aligned(16), packed)) soft;
|
|
} i387_t;
|
|
|
|
-extern i387_t i387;
|
|
+// The global variable current_i387 points to the i387_t structure of
|
|
+// the current CPU. In a multiprocessor simulation, whenever a processor
|
|
+// executes an FPU instruction, the current_i387 pointer is changed to
|
|
+// point to the FPU registers for that processor.
|
|
+extern i387_t *current_i387;
|
|
|
|
+// By defining i387 like this, all the code that expected to find a global
|
|
+// variable called i387 still works.
|
|
+#define i387 (*current_i387)
|
|
|
|
#endif
|
|
|
|
Index: fpu/wmFPUemu_glue.cc
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/fpu/wmFPUemu_glue.cc,v
|
|
retrieving revision 1.9
|
|
diff -u -r1.9 wmFPUemu_glue.cc
|
|
--- fpu/wmFPUemu_glue.cc 15 Sep 2001 06:55:14 -0000 1.9
|
|
+++ fpu/wmFPUemu_glue.cc 23 Jun 2002 00:31:47 -0000
|
|
@@ -44,8 +44,7 @@
|
|
// will ultimately call routines here.
|
|
static BxInstruction_t *fpu_iptr = NULL;
|
|
static BX_CPU_C *fpu_cpu_ptr = NULL;
|
|
-
|
|
-i387_t i387;
|
|
+i387_t *current_i387 = NULL;
|
|
|
|
extern "C" void
|
|
math_emulate2(fpu_addr_modes addr_modes,
|
|
@@ -62,6 +61,9 @@
|
|
void
|
|
BX_CPU_C::fpu_init(void)
|
|
{
|
|
+ BX_INFO (("initialized fpu"));
|
|
+ BX_CPU_THIS_PTR the_i387 = new i387_t;
|
|
+ current_i387 = (i387_t *)BX_CPU_THIS_PTR the_i387;
|
|
finit();
|
|
}
|
|
|
|
@@ -76,6 +78,15 @@
|
|
|
|
fpu_iptr = i;
|
|
fpu_cpu_ptr = this;
|
|
+#if BX_SMP_PROCESSORS==1
|
|
+ // For one processor, there's only one i387_t structure in existence, and the
|
|
+ // current_i387 pointer already points to it. Don't bother.
|
|
+#else
|
|
+ // Set the current_i387 pointer according to the processor that is being
|
|
+ // simulated. All the FPU emulation code will use current_i387 to access
|
|
+ // the FPU state, using the "i387" macro in fpu_system.h.
|
|
+ current_i387 = (i387_t *)BX_CPU_THIS_PTR the_i387;
|
|
+#endif
|
|
|
|
#if 0
|
|
addr_modes.default_mode = VM86;
|