summaryrefslogtreecommitdiff
path: root/debian
diff options
context:
space:
mode:
authorGuillem Jover <guillem@debian.org>2007-03-06 05:16:27 +0000
committerGuillem Jover <guillem@debian.org>2007-03-06 05:16:27 +0000
commit3773ab60df88e85c5fc3525a25278566378283f1 (patch)
tree6675acc75f7bb8248a471f41e1d7e7fe1af71b81 /debian
parent0117590503d62f6021fa79f083f20ce03e619d9e (diff)
Fixed MMX register support. (Closes: #413177)
- debian/patches/20_mmx_support.patch: Updated. Thanks to Samuel Thibault <samuel.thibault@ens-lyon.org>.
Diffstat (limited to 'debian')
-rw-r--r--debian/changelog3
-rw-r--r--debian/patches/20_mmx_support.patch435
2 files changed, 305 insertions, 133 deletions
diff --git a/debian/changelog b/debian/changelog
index 7cadc46..4d6cce7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -6,6 +6,9 @@ gnumach (2:1.3.99.dfsg.cvs20070306-1) UNRELEASED; urgency=low
Thanks to Samuel Thibault <samuel.thibault@ens-lyon.org>.
- debian/patches/00_clean_gfdl.patch: Sync.
- debian/patches/90_autoconf_autogen.patch: Regenerated.
+ * Fixed MMX register support. (Closes: #413177)
+ - debian/patches/20_mmx_support.patch: Updated.
+ Thanks to Samuel Thibault <samuel.thibault@ens-lyon.org>.
-- Guillem Jover <guillem@debian.org> Tue, 6 Mar 2007 06:45:13 +0200
diff --git a/debian/patches/20_mmx_support.patch b/debian/patches/20_mmx_support.patch
index d7c7dfc..d9a4af9 100644
--- a/debian/patches/20_mmx_support.patch
+++ b/debian/patches/20_mmx_support.patch
@@ -1,136 +1,35 @@
-2007-01-05 Samuel Thibault <samuel.thibault@ens-lyon.org>
+2007-03-03 Samuel Thibault <samuel.thibault@ens-lyon.org>
- Add MMX FPU registers save/restore support. This needs 16-byte-aligned
- structures.
- * i386/include/mach/i386/fp_reg.h (struct i386_fp_regs): Invert array
- indices.
+ Add MMX FPU registers save/restore support.
+ * i386/include/mach/i386/fp_reg.h (struct i386_fp_regs): Invert array
+ indices.
(struct i386_xfp_save): New structure.
(FP_387X): New macro.
- * i386/i386/thread.h (struct i386_fpsave_state): Add xfp_save_state
- member, keep existing fp_save_state and fp_regs members in an unnamed
- union member. Move fp_valid member to the end of the structure.
+ * i386/i386/thread.h (struct i386_fpsave_state): Add xfp_save_state
+ member, keep existing fp_save_state and fp_regs members in an unnamed
+ union member. Move fp_valid member to the end of the structure.
* i386/i386/fpu.h (fxsave, fxrstor): New macros.
(fpu_save_context): Use fxsave() when FPU is FXSR-capable.
* i386/i386/fpu.c: Include <i386/locore.h>
(fp_save, fp_load): Add declaration.
(init_fpu): Add FXSR-capable FPU detection.
- (fpu_module_init): Request 16-byte alignment to zinit() for
- i386_fpsave_state structures.
- (fpu_set_state): Abort when FPU is FXSR-capable (not implemented yet).
+ (fpu_module_init): Request 16-byte alignment to zinit() for
+ i386_fpsave_state structures.
+ (fpu_set_state): Convert FPU state when FPU is FXSR-capable. Free the
+ just-allocated ifps, not the one currently in use.
(fpu_get_state): Convert FPU state when FPU is FXSR-capable.
(fp_save): Use fxsave() when FPU is FXSR-capable.
(fp_load): Use fxrstor() when FPU is FXSR-capable.
(fp_state_alloc): Add FXSR-aware initialization.
-Index: i386/include/mach/i386/fp_reg.h
-===================================================================
-RCS file: /cvsroot/hurd/gnumach/i386/include/mach/i386/fp_reg.h,v
-retrieving revision 1.1.1.1
-diff -u -p -r1.1.1.1 fp_reg.h
---- i386/include/mach/i386/fp_reg.h 25 Feb 1997 21:27:00 -0000 1.1.1.1
-+++ i386/include/mach/i386/fp_reg.h 4 Jan 2007 23:55:56 -0000
-@@ -46,10 +46,30 @@ struct i386_fp_save {
- };
-
- struct i386_fp_regs {
-- unsigned short fp_reg_word[5][8];
-+ unsigned short fp_reg_word[8][5];
- /* space for 8 80-bit FP registers */
- };
-
-+struct i386_xfp_save {
-+ unsigned short fp_control; /* control */
-+ unsigned short fp_status; /* status */
-+ unsigned short fp_tag; /* register tags */
-+ unsigned short fp_opcode; /* opcode of failed instruction */
-+ unsigned int fp_eip; /* eip at failed instruction */
-+ unsigned short fp_cs; /* cs at failed instruction */
-+ unsigned short fp_unused_1;
-+ unsigned int fp_dp; /* data address */
-+ unsigned short fp_ds; /* data segment */
-+ unsigned short fp_unused_2;
-+ unsigned int fp_mxcsr; /* MXCSR */
-+ unsigned int fp_mxcsr_mask; /* MXCSR_MASK */
-+ unsigned char fp_reg_word[8][16];
-+ /* space for 8 128-bit FP registers */
-+ unsigned char fp_xreg_word[8][16];
-+ /* space for 8 128-bit XMM registers */
-+ unsigned int padding[56];
-+} __attribute__((aligned(16)));
-+
- /*
- * Control register
- */
-@@ -104,5 +124,6 @@ struct i386_fp_regs {
- #define FP_SOFT 1 /* software FP emulator */
- #define FP_287 2 /* 80287 */
- #define FP_387 3 /* 80387 or 80486 */
-+#define FP_387X 4 /* FXSAVE/RSTOR-capable */
-
- #endif /* _MACH_I386_FP_REG_H_ */
-Index: i386/i386/thread.h
-===================================================================
-RCS file: /cvsroot/hurd/gnumach/i386/i386/thread.h,v
-retrieving revision 1.3.2.1
-diff -u -p -r1.3.2.1 thread.h
---- i386/i386/thread.h 5 Nov 2006 20:39:24 -0000 1.3.2.1
-+++ i386/i386/thread.h 4 Jan 2007 23:55:56 -0000
-@@ -112,9 +112,14 @@ struct i386_kernel_state {
- */
-
- struct i386_fpsave_state {
-+ union {
-+ struct {
-+ struct i386_fp_save fp_save_state;
-+ struct i386_fp_regs fp_regs;
-+ };
-+ struct i386_xfp_save xfp_save_state;
-+ };
- boolean_t fp_valid;
-- struct i386_fp_save fp_save_state;
-- struct i386_fp_regs fp_regs;
- };
-
- /*
-Index: i386/i386/fpu.h
-===================================================================
-RCS file: /cvsroot/hurd/gnumach/i386/i386/fpu.h,v
-retrieving revision 1.1.1.1.4.3
-diff -u -p -r1.1.1.1.4.3 fpu.h
---- i386/i386/fpu.h 12 Dec 2006 23:30:49 -0000 1.1.1.1.4.3
-+++ i386/i386/fpu.h 4 Jan 2007 23:55:56 -0000
-@@ -66,6 +66,12 @@
- #define frstor(state) \
- asm volatile("frstor %0" : : "m" (state))
-
-+#define fxsave(state) \
-+ asm volatile("fxsave %0" : "=m" (*state))
-+
-+#define fxrstor(state) \
-+ asm volatile("fxrstor %0" : : "m" (state))
-+
- #define fwait() \
- asm("fwait");
-
-@@ -85,7 +91,10 @@
- if (ifps != 0 && !ifps->fp_valid) { \
- /* registers are in FPU - save to memory */ \
- ifps->fp_valid = TRUE; \
-- fnsave(&ifps->fp_save_state); \
-+ if (fp_kind == FP_387X) \
-+ fxsave(&ifps->fp_save_state.xfp_state); \
-+ else \
-+ fnsave(&ifps->fp_save_state.fp_state); \
- set_ts(); \
- } \
- }
+
Index: i386/i386/fpu.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/i386/fpu.c,v
retrieving revision 1.2.4.10
diff -u -p -r1.2.4.10 fpu.c
--- i386/i386/fpu.c 4 Jan 2007 23:51:02 -0000 1.2.4.10
-+++ i386/i386/fpu.c 4 Jan 2007 23:55:56 -0000
++++ i386/i386/fpu.c 3 Mar 2007 21:05:32 -0000
@@ -43,6 +43,7 @@
#include <i386/thread.h>
#include <i386/fpu.h>
@@ -139,31 +38,40 @@ diff -u -p -r1.2.4.10 fpu.c
#include "cpu_number.h"
#if 0
-@@ -64,6 +65,9 @@ extern void i386_exception();
+@@ -63,6 +64,10 @@ extern void i386_exception();
+
int fp_kind = FP_387; /* 80387 present */
zone_t ifps_zone; /* zone for FPU save area */
-
++static unsigned long mxcsr_feature_mask = 0xffffffff; /* Always AND user-provided mxcsr with this security mask */
++
+void fp_save(thread_t thread);
+void fp_load(thread_t thread);
-+
+
#if NCPUS == 1
volatile thread_t fp_thread = THREAD_NULL;
- /* thread whose state is in FPU */
-@@ -130,7 +134,12 @@ init_fpu()
+@@ -130,7 +135,20 @@ init_fpu()
/*
* We have a 387.
*/
- fp_kind = FP_387;
+ if (CPU_HAS_FEATURE(CPU_FEATURE_FXSR)) {
++ static /* because we _need_ alignment */
++ struct i386_xfp_save save;
++ unsigned long mask;
+ fp_kind = FP_387X;
+ printf("Enabling FXSR\n");
+ set_cr4(get_cr4() | CR4_OSFXSR);
++ fxsave(&save);
++ mask = save.fp_mxcsr_mask;
++ if (!mask)
++ mask = 0x0000ffbf;
++ mxcsr_feature_mask &= mask;
+ } else
+ fp_kind = FP_387;
}
/*
* Trap wait instructions. Turn off FPU for now.
-@@ -152,7 +161,7 @@ init_fpu()
+@@ -152,7 +170,7 @@ init_fpu()
void
fpu_module_init()
{
@@ -172,18 +80,140 @@ diff -u -p -r1.2.4.10 fpu.c
THREAD_MAX * sizeof(struct i386_fpsave_state),
THREAD_CHUNK * sizeof(struct i386_fpsave_state),
0, "i386 fpsave state");
-@@ -202,6 +211,10 @@ ASSERT_IPL(SPL0);
- if (fp_kind == FP_NO)
- return KERN_FAILURE;
+@@ -183,6 +201,74 @@ ASSERT_IPL(SPL0);
+ zfree(ifps_zone, (vm_offset_t) fps);
+ }
-+ if (fp_kind == FP_387X)
-+ /* TODO */
-+ return KERN_FAILURE;
++/* The two following functions were stolen from Linux, and hence are covered
++ * by the GPL */
++static inline unsigned short
++twd_i387_to_fxsr (unsigned short twd)
++{
++ unsigned int tmp; /* to avoid 16 bit prefixes in the code */
+
- #if NCPUS == 1
++ /* Transform each pair of bits into 01 (valid) or 00 (empty) */
++ tmp = ~twd;
++ tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
++ /* and move the valid bits to the lower byte. */
++ tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
++ tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
++ tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
++ return tmp;
++}
++
++static inline unsigned long
++twd_fxsr_to_i387 (struct i386_xfp_save *fxsave)
++{
++ struct {
++ unsigned short significand[4];
++ unsigned short exponent;
++ unsigned short padding[3];
++ } *st = NULL;
++ unsigned long tos = (fxsave->fp_status >> 11) & 7;
++ unsigned long twd = (unsigned long) fxsave->fp_tag;
++ unsigned long tag;
++ unsigned long ret = 0xffff0000u;
++ int i;
++
++#define FPREG_ADDR(f, n) ((void *)&(f)->fp_reg_word + (n) * 16);
++
++ for (i = 0 ; i < 8 ; i++) {
++ if (twd & 0x1) {
++ st = FPREG_ADDR (fxsave, (i - tos) & 7);
++
++ switch (st->exponent & 0x7fff) {
++ case 0x7fff:
++ tag = 2; /* Special */
++ break;
++ case 0x0000:
++ if (!st->significand[0] &&
++ !st->significand[1] &&
++ !st->significand[2] &&
++ !st->significand[3] ) {
++ tag = 1; /* Zero */
++ } else {
++ tag = 2; /* Special */
++ }
++ break;
++ default:
++ if (st->significand[3] & 0x8000) {
++ tag = 0; /* Valid */
++ } else {
++ tag = 2; /* Special */
++ }
++ break;
++ }
++ } else {
++ tag = 3; /* Empty */
++ }
++ ret |= (tag << (2 * i));
++ twd = twd >> 1;
++ }
++ return ret;
++}
++
+ /*
+ * Set the floating-point state for a thread.
+ * If the thread is not the current thread, it is
+@@ -256,24 +340,43 @@ ASSERT_IPL(SPL0);
+ pcb->ims.ifps = ifps;
+ }
- /*
-@@ -339,15 +352,29 @@ ASSERT_IPL(SPL0);
+- /*
+- * Ensure that reserved parts of the environment are 0.
+- */
+- memset(&ifps->fp_save_state, 0, sizeof(struct i386_fp_save));
++ if (fp_kind == FP_387X) {
++ int i;
++ /*
++ * Ensure that reserved parts of the environment are 0.
++ */
++ memset(&ifps->xfp_save_state, 0, sizeof(struct i386_xfp_save));
++
++ ifps->xfp_save_state.fp_control = user_fp_state->fp_control;
++ ifps->xfp_save_state.fp_status = user_fp_state->fp_status;
++ ifps->xfp_save_state.fp_tag = twd_i387_to_fxsr(user_fp_state->fp_tag);
++ ifps->xfp_save_state.fp_eip = user_fp_state->fp_eip;
++ ifps->xfp_save_state.fp_cs = user_fp_state->fp_cs;
++ ifps->xfp_save_state.fp_opcode = user_fp_state->fp_opcode;
++ ifps->xfp_save_state.fp_dp = user_fp_state->fp_dp;
++ ifps->xfp_save_state.fp_ds = user_fp_state->fp_ds;
++ for (i=0; i<8; i++)
++ memcpy(&ifps->xfp_save_state.fp_reg_word[i], &user_fp_regs[i], sizeof(user_fp_regs[i]));
++ } else {
++ /*
++ * Ensure that reserved parts of the environment are 0.
++ */
++ memset(&ifps->fp_save_state, 0, sizeof(struct i386_fp_save));
+
+- ifps->fp_save_state.fp_control = user_fp_state->fp_control;
+- ifps->fp_save_state.fp_status = user_fp_state->fp_status;
+- ifps->fp_save_state.fp_tag = user_fp_state->fp_tag;
+- ifps->fp_save_state.fp_eip = user_fp_state->fp_eip;
+- ifps->fp_save_state.fp_cs = user_fp_state->fp_cs;
+- ifps->fp_save_state.fp_opcode = user_fp_state->fp_opcode;
+- ifps->fp_save_state.fp_dp = user_fp_state->fp_dp;
+- ifps->fp_save_state.fp_ds = user_fp_state->fp_ds;
+- ifps->fp_regs = *user_fp_regs;
++ ifps->fp_save_state.fp_control = user_fp_state->fp_control;
++ ifps->fp_save_state.fp_status = user_fp_state->fp_status;
++ ifps->fp_save_state.fp_tag = user_fp_state->fp_tag;
++ ifps->fp_save_state.fp_eip = user_fp_state->fp_eip;
++ ifps->fp_save_state.fp_cs = user_fp_state->fp_cs;
++ ifps->fp_save_state.fp_opcode = user_fp_state->fp_opcode;
++ ifps->fp_save_state.fp_dp = user_fp_state->fp_dp;
++ ifps->fp_save_state.fp_ds = user_fp_state->fp_ds;
++ ifps->fp_regs = *user_fp_regs;
++ }
+
+ simple_unlock(&pcb->lock);
+ if (new_ifps != 0)
+- zfree(ifps_zone, (vm_offset_t) ifps);
++ zfree(ifps_zone, (vm_offset_t) new_ifps);
+ }
+
+ return KERN_SUCCESS;
+@@ -339,15 +442,29 @@ ASSERT_IPL(SPL0);
*/
memset(user_fp_state, 0, sizeof(struct i386_fp_save));
@@ -200,7 +230,7 @@ diff -u -p -r1.2.4.10 fpu.c
+ int i;
+ user_fp_state->fp_control = ifps->xfp_save_state.fp_control;
+ user_fp_state->fp_status = ifps->xfp_save_state.fp_status;
-+ user_fp_state->fp_tag = ifps->xfp_save_state.fp_tag; /* TODO: convert */
++ user_fp_state->fp_tag = twd_fxsr_to_i387(&ifps->xfp_save_state);
+ user_fp_state->fp_eip = ifps->xfp_save_state.fp_eip;
+ user_fp_state->fp_cs = ifps->xfp_save_state.fp_cs;
+ user_fp_state->fp_opcode = ifps->xfp_save_state.fp_opcode;
@@ -222,7 +252,18 @@ diff -u -p -r1.2.4.10 fpu.c
}
simple_unlock(&pcb->lock);
-@@ -553,7 +580,10 @@ fp_save(thread)
+@@ -531,7 +648,9 @@ ASSERT_IPL(SPL0);
+ */
+ i386_exception(EXC_ARITHMETIC,
+ EXC_I386_EXTERR,
+- thread->pcb->ims.ifps->fp_save_state.fp_status);
++ fp_kind == FP_387X ?
++ thread->pcb->ims.ifps->xfp_save_state.fp_status :
++ thread->pcb->ims.ifps->fp_save_state.fp_status);
+ /*NOTREACHED*/
+ }
+
+@@ -553,7 +672,10 @@ fp_save(thread)
if (ifps != 0 && !ifps->fp_valid) {
/* registers are in FPU */
ifps->fp_valid = TRUE;
@@ -234,7 +275,17 @@ diff -u -p -r1.2.4.10 fpu.c
}
}
-@@ -601,7 +631,10 @@ ASSERT_IPL(SPL0);
+@@ -594,14 +716,19 @@ ASSERT_IPL(SPL0);
+ */
+ i386_exception(EXC_ARITHMETIC,
+ EXC_I386_EXTERR,
+- thread->pcb->ims.ifps->fp_save_state.fp_status);
++ fp_kind == FP_387X ?
++ thread->pcb->ims.ifps->xfp_save_state.fp_status :
++ thread->pcb->ims.ifps->fp_save_state.fp_status);
+ /*NOTREACHED*/
+ #endif
+ } else if (! ifps->fp_valid) {
printf("fp_load: invalid FPU state!\n");
fninit ();
} else {
@@ -246,7 +297,7 @@ diff -u -p -r1.2.4.10 fpu.c
}
ifps->fp_valid = FALSE; /* in FPU */
}
-@@ -623,11 +656,22 @@ fp_state_alloc()
+@@ -623,11 +750,22 @@ fp_state_alloc()
pcb->ims.ifps = ifps;
ifps->fp_valid = TRUE;
@@ -274,3 +325,121 @@ diff -u -p -r1.2.4.10 fpu.c
}
#if AT386
+Index: i386/i386/fpu.h
+===================================================================
+RCS file: /cvsroot/hurd/gnumach/i386/i386/fpu.h,v
+retrieving revision 1.1.1.1.4.3
+diff -u -p -r1.1.1.1.4.3 fpu.h
+--- i386/i386/fpu.h 12 Dec 2006 23:30:49 -0000 1.1.1.1.4.3
++++ i386/i386/fpu.h 3 Mar 2007 21:05:32 -0000
+@@ -66,6 +66,12 @@
+ #define frstor(state) \
+ asm volatile("frstor %0" : : "m" (state))
+
++#define fxsave(state) \
++ asm volatile("fxsave %0" : "=m" (*state))
++
++#define fxrstor(state) \
++ asm volatile("fxrstor %0" : : "m" (state))
++
+ #define fwait() \
+ asm("fwait");
+
+@@ -85,7 +91,10 @@
+ if (ifps != 0 && !ifps->fp_valid) { \
+ /* registers are in FPU - save to memory */ \
+ ifps->fp_valid = TRUE; \
+- fnsave(&ifps->fp_save_state); \
++ if (fp_kind == FP_387X) \
++ fxsave(&ifps->xfp_save_state); \
++ else \
++ fnsave(&ifps->fp_save_state); \
+ set_ts(); \
+ } \
+ }
+Index: i386/i386/thread.h
+===================================================================
+RCS file: /cvsroot/hurd/gnumach/i386/i386/thread.h,v
+retrieving revision 1.3.2.1
+diff -u -p -r1.3.2.1 thread.h
+--- i386/i386/thread.h 5 Nov 2006 20:39:24 -0000 1.3.2.1
++++ i386/i386/thread.h 3 Mar 2007 21:05:32 -0000
+@@ -112,9 +112,14 @@ struct i386_kernel_state {
+ */
+
+ struct i386_fpsave_state {
++ union {
++ struct {
++ struct i386_fp_save fp_save_state;
++ struct i386_fp_regs fp_regs;
++ };
++ struct i386_xfp_save xfp_save_state;
++ };
+ boolean_t fp_valid;
+- struct i386_fp_save fp_save_state;
+- struct i386_fp_regs fp_regs;
+ };
+
+ /*
+Index: i386/include/mach/i386/fp_reg.h
+===================================================================
+RCS file: /cvsroot/hurd/gnumach/i386/include/mach/i386/fp_reg.h,v
+retrieving revision 1.1.1.1
+diff -u -p -r1.1.1.1 fp_reg.h
+--- i386/include/mach/i386/fp_reg.h 25 Feb 1997 21:27:00 -0000 1.1.1.1
++++ i386/include/mach/i386/fp_reg.h 3 Mar 2007 21:05:32 -0000
+@@ -46,10 +46,30 @@ struct i386_fp_save {
+ };
+
+ struct i386_fp_regs {
+- unsigned short fp_reg_word[5][8];
++ unsigned short fp_reg_word[8][5];
+ /* space for 8 80-bit FP registers */
+ };
+
++struct i386_xfp_save {
++ unsigned short fp_control; /* control */
++ unsigned short fp_status; /* status */
++ unsigned short fp_tag; /* register tags */
++ unsigned short fp_opcode; /* opcode of failed instruction */
++ unsigned int fp_eip; /* eip at failed instruction */
++ unsigned short fp_cs; /* cs at failed instruction */
++ unsigned short fp_unused_1;
++ unsigned int fp_dp; /* data address */
++ unsigned short fp_ds; /* data segment */
++ unsigned short fp_unused_2;
++ unsigned int fp_mxcsr; /* MXCSR */
++ unsigned int fp_mxcsr_mask; /* MXCSR_MASK */
++ unsigned char fp_reg_word[8][16];
++ /* space for 8 128-bit FP registers */
++ unsigned char fp_xreg_word[8][16];
++ /* space for 8 128-bit XMM registers */
++ unsigned int padding[56];
++} __attribute__((aligned(16)));
++
+ /*
+ * Control register
+ */
+@@ -104,5 +124,6 @@ struct i386_fp_regs {
+ #define FP_SOFT 1 /* software FP emulator */
+ #define FP_287 2 /* 80287 */
+ #define FP_387 3 /* 80387 or 80486 */
++#define FP_387X 4 /* FXSAVE/RSTOR-capable */
+
+ #endif /* _MACH_I386_FP_REG_H_ */
+Index: i386/include/mach/i386/thread_status.h
+===================================================================
+RCS file: /cvsroot/hurd/gnumach/i386/include/mach/i386/thread_status.h,v
+retrieving revision 1.1.1.1
+diff -u -p -r1.1.1.1 thread_status.h
+--- i386/include/mach/i386/thread_status.h 25 Feb 1997 21:27:01 -0000 1.1.1.1
++++ i386/include/mach/i386/thread_status.h 3 Mar 2007 21:05:32 -0000
+@@ -111,7 +111,7 @@ struct i386_thread_state {
+ (sizeof (struct i386_fp_save) + sizeof (struct i386_fp_regs))
+
+ struct i386_float_state {
+- int fpkind; /* FP_NO..FP_387 (readonly) */
++ int fpkind; /* FP_NO..FP_387X (readonly) */
+ int initialized;
+ unsigned char hw_state[FP_STATE_BYTES]; /* actual "hardware" state */
+ int exc_status; /* exception status (readonly) */