In <[EMAIL PROTECTED]>, Bruce Evans wrote: > >Guessing from LINT's comments, you had to leave out npx and include > >one of the emulators, but -current's config refuses to config a kernel > >file without npx support. > > This was broken by adding "mandatory" to the npx line in file.i386. > > >I also tried to add "disable" to npx's config line, which compiles and > >runs ok, but still uses the hardware FPU (timing and exception test). > > This may be because npx0 now attaches to nexus, but "disable" only works > for isa devices. It's annoying that userconfig doesn't support displaying > or changing npx0. BTW, PCI devices are no longer displayed by userconfig. The following diff makes FPU and FPU emulators selectable from userconfig. npx0 is still mandatory, but it gets an additional flag bit 0x08, which requests the hardware FPU to be ignored and an emulator to be used if one is compiled in. If none is compiled into the kernel, a warning is printed and the hardware FPU is used. The diff also contains the FPE trapcode stuff, which is now found to run with GPL_MATH_EMUL (although actualy computing of error codes isn't done in this case) and not to make things worse for (non-GPL) MATH_EMUL. I plan to commit this, unless someone objets (the impressive-looking trapcode table is only 127 bytes in size, to pre-comment on one issue). Martin -- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Martin Cracauer <[EMAIL PROTECTED]> http://www.cons.org/cracauer/ Tel.: (private) +4940 5221829 Fax.: (private) +4940 5228536
Index: i386/conf/LINT =================================================================== RCS file: /home/CVS-FreeBSD/src/sys/i386/conf/LINT,v retrieving revision 1.617 diff -c -r1.617 LINT *** LINT 1999/07/09 04:29:56 1.617 --- LINT 1999/07/22 22:16:32 *************** *** 956,973 **** options SC_NO_SYSMOUSE # ! # The Numeric Processing eXtension driver. This should be configured if ! # your machine has a math co-processor, unless the coprocessor is very ! # buggy. If it is not configured then you *must* configure math emulation ! # (see above). If both npx0 and emulation are configured, then only npx0 ! # is used (provided it works). device npx0 at nexus? port IO_NPX flags 0x0 irq 13 # # `flags' for npx0: ! # 0x01 don't use the npx registers to optimize bcopy ! # 0x02 don't use the npx registers to optimize bzero # 0x04 don't use the npx registers to optimize copyin or copyout. # The npx registers are normally used to optimize copying and zeroing when # all of the following conditions are satisfied: # I586_CPU is an option --- 956,975 ---- options SC_NO_SYSMOUSE # ! # The Numeric Processing eXtension driver. In addition to this, you ! # may configure a math emulator (see above). If your machine has a ! # hardware FPU and the kernel configuration includes the npx device ! # *and* a math emulator compiled into the kernel, the hardware FPU ! # will be used, unless it is found to be broken or unless "flags" to ! # npx0 includes "0x08", which requests preference for the emulator. device npx0 at nexus? port IO_NPX flags 0x0 irq 13 # # `flags' for npx0: ! # 0x01 don't use the npx registers to optimize bcopy. ! # 0x02 don't use the npx registers to optimize bzero. # 0x04 don't use the npx registers to optimize copyin or copyout. + # 0x08 use emulator even if hardware FPU is available. # The npx registers are normally used to optimize copying and zeroing when # all of the following conditions are satisfied: # I586_CPU is an option *************** *** 978,983 **** --- 980,988 ---- # The flags can be used to control cases where it doesn't work or is slower. # Setting them at boot time using userconfig works right (the optimizations # are not used until later in the bootstrap when npx0 is attached). + # Flag 0x08 does not imply any settings of the other flags, you may run + # with FPU preference set to emulator, but still using the i586 optimized + # memory routines. # # *************** *** 1149,1154 **** --- 1154,1160 ---- # higher priority console). This replaces the COMCONSOLE option. # 0x40 reserve this unit for low level console operations. Do not # access the device in any normal way. + # 0x80 use this port for serial line gdb support in ddb. # # PnP `flags' (set via userconfig using pnp x flags y) # 0x1 disable probing of this device. Used to prevent your modem Index: i386/i386/trap.c =================================================================== RCS file: /home/CVS-FreeBSD/src/sys/i386/i386/trap.c,v retrieving revision 1.139 diff -c -r1.139 trap.c *** trap.c 1999/06/18 14:32:16 1.139 --- trap.c 1999/07/22 19:13:55 *************** *** 360,366 **** break; case T_DIVIDE: /* integer divide fault */ ! ucode = FPE_INTDIV_TRAP; i = SIGFPE; break; --- 360,366 ---- break; case T_DIVIDE: /* integer divide fault */ ! ucode = FPE_INTDIV; i = SIGFPE; break; *************** *** 382,393 **** #endif /* NISA > 0 */ case T_OFLOW: /* integer overflow fault */ ! ucode = FPE_INTOVF_TRAP; i = SIGFPE; break; case T_BOUND: /* bounds check fault */ ! ucode = FPE_SUBRNG_TRAP; i = SIGFPE; break; --- 382,393 ---- #endif /* NISA > 0 */ case T_OFLOW: /* integer overflow fault */ ! ucode = FPE_INTOVF; i = SIGFPE; break; case T_BOUND: /* bounds check fault */ ! ucode = FPE_FLTSUB; i = SIGFPE; break; Index: i386/i386/userconfig.c =================================================================== RCS file: /home/CVS-FreeBSD/src/sys/i386/i386/userconfig.c,v retrieving revision 1.148 diff -c -r1.148 userconfig.c *** userconfig.c 1999/07/09 04:29:54 1.148 --- userconfig.c 1999/07/22 19:52:10 *************** *** 458,464 **** {"apm", "Advanced Power Management", FLG_FIXED, CLS_MISC}, {"labpc", "National Instruments Lab-PC/Lab-PC+", 0, CLS_MISC}, ! {"npx", "Math coprocessor", FLG_INVISIBLE, CLS_MISC}, {"lkm", "Loadable PCI driver support", FLG_INVISIBLE, CLS_MISC}, {"vga", "Catchall PCI VGA driver", FLG_INVISIBLE, CLS_MISC}, {"chip", "PCI chipset support", FLG_INVISIBLE, CLS_MISC}, --- 458,464 ---- {"apm", "Advanced Power Management", FLG_FIXED, CLS_MISC}, {"labpc", "National Instruments Lab-PC/Lab-PC+", 0, CLS_MISC}, ! {"npx", "Math coprocessor", FLG_IMMUTABLE, CLS_MISC}, {"lkm", "Loadable PCI driver support", FLG_INVISIBLE, CLS_MISC}, {"vga", "Catchall PCI VGA driver", FLG_INVISIBLE, CLS_MISC}, {"chip", "PCI chipset support", FLG_INVISIBLE, CLS_MISC}, Index: i386/include/ieeefp.h =================================================================== RCS file: /home/CVS-FreeBSD/src/sys/i386/include/ieeefp.h,v retrieving revision 1.5 diff -c -r1.5 ieeefp.h *** ieeefp.h 1997/02/22 09:34:41 1.5 --- ieeefp.h 1999/07/22 19:13:55 *************** *** 72,77 **** --- 72,78 ---- #define FP_X_OFL 0x08 /* overflow */ #define FP_X_UFL 0x10 /* underflow */ #define FP_X_IMP 0x20 /* (im)precision */ + #define FP_X_STK 0x40 /* stack fault */ /* * FP registers Index: i386/include/trap.h =================================================================== RCS file: /home/CVS-FreeBSD/src/sys/i386/include/trap.h,v retrieving revision 1.7 diff -c -r1.7 trap.h *** trap.h 1997/02/22 09:35:19 1.7 --- trap.h 1999/07/22 19:13:55 *************** *** 76,88 **** #define ILL_ALIGN_FAULT T_ALIGNFLT #define ILL_FPOP_FAULT T_FPOPFLT /* coprocessor operand fault */ ! /* codes for SIGFPE/ARITHTRAP */ #define FPE_INTOVF_TRAP 0x1 /* integer overflow */ #define FPE_INTDIV_TRAP 0x2 /* integer divide by zero */ #define FPE_FLTDIV_TRAP 0x3 /* floating/decimal divide by zero */ #define FPE_FLTOVF_TRAP 0x4 /* floating overflow */ #define FPE_FLTUND_TRAP 0x5 /* floating underflow */ ! #define FPE_FPU_NP_TRAP 0x6 /* floating point unit not present */ #define FPE_SUBRNG_TRAP 0x7 /* subrange out of bounds */ /* codes for SIGBUS */ --- 76,104 ---- #define ILL_ALIGN_FAULT T_ALIGNFLT #define ILL_FPOP_FAULT T_FPOPFLT /* coprocessor operand fault */ ! /* ! * codes for SIGFPE/ARITHTRAP ! * ! */ ! /* portable macros */ ! #define FPE_INTDIV 1 /* integer divide by zero */ ! #define FPE_INTOVF 2 /* integer overflow */ ! #define FPE_FLTDIV 3 /* floating point divide by zero */ ! #define FPE_FLTOVF 4 /* floating point overflow */ ! #define FPE_FLTUND 5 /* floating point underflow */ ! #define FPE_FLTRES 6 /* floating point inexact result */ ! #define FPE_FLTINV 7 /* invalid floating point operation */ ! #define FPE_FLTSUB 8 /* subscript out of range */ ! ! /* old FreeBSD macros, deprecated */ #define FPE_INTOVF_TRAP 0x1 /* integer overflow */ #define FPE_INTDIV_TRAP 0x2 /* integer divide by zero */ #define FPE_FLTDIV_TRAP 0x3 /* floating/decimal divide by zero */ #define FPE_FLTOVF_TRAP 0x4 /* floating overflow */ #define FPE_FLTUND_TRAP 0x5 /* floating underflow */ ! #define FPE_FPU_NP_TRAP 0x6 /* floating point unit not present ! * - won't happen in practice ! */ #define FPE_SUBRNG_TRAP 0x7 /* subrange out of bounds */ /* codes for SIGBUS */ Index: i386/isa/npx.c =================================================================== RCS file: /home/CVS-FreeBSD/src/sys/i386/isa/npx.c,v retrieving revision 1.73 diff -c -r1.73 npx.c *** npx.c 1999/05/15 17:58:58 1.73 --- npx.c 1999/07/22 22:14:19 *************** *** 86,91 **** --- 86,92 ---- #define NPX_DISABLE_I586_OPTIMIZED_BCOPY (1 << 0) #define NPX_DISABLE_I586_OPTIMIZED_BZERO (1 << 1) #define NPX_DISABLE_I586_OPTIMIZED_COPYIO (1 << 2) + #define NPX_PREFER_EMULATOR (1 << 3) #ifdef __GNUC__ *************** *** 396,429 **** npx_attach(dev) device_t dev; { - #ifdef I586_CPU int flags; ! #endif device_print_prettyname(dev); if (npx_irq13) { printf("using IRQ 13 interface\n"); } else { - if (npx_ex16) - printf("INT 16 interface\n"); #if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE) ! else if (npx_exists) { printf("error reporting broken; using 387 emulator\n"); hw_float = npx_exists = 0; } else printf("387 emulator\n"); #else ! else ! printf("no 387 emulator in kernel!\n"); #endif } npxinit(__INITIAL_NPXCW__); #ifdef I586_CPU ! if (resource_int_value("npx", 0, "flags", &flags) != 0) ! flags = 0; ! ! if (cpu_class == CPUCLASS_586 && npx_ex16 && timezero("i586_bzero()", i586_bzero) < timezero("bzero()", bzero) * 4 / 5) { if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY)) { --- 397,440 ---- npx_attach(dev) device_t dev; { int flags; ! ! if (resource_int_value("npx", 0, "flags", &flags) != 0) ! flags = 0; device_print_prettyname(dev); if (npx_irq13) { printf("using IRQ 13 interface\n"); } else { #if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE) ! if (npx_ex16) { ! if (!(flags & NPX_PREFER_EMULATOR)) ! printf("INT 16 interface\n"); ! else { ! printf("FPU exists, but flags request " ! "emulator\n"); ! hw_float = npx_exists = 0; ! } ! } else if (npx_exists) { printf("error reporting broken; using 387 emulator\n"); hw_float = npx_exists = 0; } else printf("387 emulator\n"); #else ! if (npx_ex16) { ! printf("INT 16 interface\n"); ! if (flags & NPX_PREFER_EMULATOR) { ! printf("emulator requested, but none compiled " ! "into kernel, using FPU\n"); ! } ! } else ! printf("no 387 emulator in kernel and no FPU!\n"); #endif } npxinit(__INITIAL_NPXCW__); #ifdef I586_CPU ! if (cpu_class == CPUCLASS_586 && npx_ex16 && npx_exists && timezero("i586_bzero()", i586_bzero) < timezero("bzero()", bzero) * 4 / 5) { if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY)) { *************** *** 494,513 **** #endif } /* * Preserve the FP status word, clear FP exceptions, then generate a SIGFPE. * * Clearing exceptions is necessary mainly to avoid IRQ13 bugs. We now * depend on longjmp() restoring a usable state. Restoring the state * or examining it might fail if we didn't clear exceptions. - * - * XXX there is no standard way to tell SIGFPE handlers about the error - * state. The old interface: - * - * void handler(int sig, int code, struct sigcontext *scp); * ! * is broken because it is non-ANSI and because the FP state is not in ! * struct sigcontext. * * XXX the FP state is not preserved across signal handlers. So signal * handlers cannot afford to do FP unless they preserve the state or --- 505,693 ---- #endif } + /* + * The following mechanism is used to ensure that the FPE_... value + * that is passed as a trapcode to the signal handler of the user + * process does not have more than one bit set. + * + * Multiple bits may be set if the user process modifies the control + * word while a status word bit is already set. While this is a sign + * of bad coding, we have no choise than to narrow them down to one + * bit, since we must not send a trapcode that is not exactly one of + * the FPE_ macros. + * + * The mechanism has a static table with 127 entries. Each combination + * of the 7 FPU status word exception bits directly translates to a + * position in this table, where a single FPE_... value is stored. + * This FPE_... value stored there is considered the "most important" + * of the exception bits and will be sent as the signal code. The + * precedence of the bits is based upon Intel Document "Numerical + * Applications", Chapter "Special Computational Situations". + * + * The macro to choose one of these values does these steps: 1) Throw + * away status word bits that cannot be masked. 2) Throw away the bits + * currently masked in the control word, assuming the user isn't + * interested in them anymore. 3) Reinsert status word bit 7 (stack + * fault) if it is set, which cannot be masked but must be presered. + * 4) Use the remaining bits to point into the trapcode table. + * + * The 6 maskable bits in order of their preference, as stated in the + * above referenced Intel manual: + * 1 Invalid operation (FP_X_INV) + * 1a Stack underflow + * 1b Stack overflow + * 1c Operand of unsupported format + * 1d SNaN operand. + * 2 QNaN operand (not an exception, irrelavant here) + * 3 Any other invalid-operation not mentioned above or zero divide + * (FP_X_INV, FP_X_DZ) + * 4 Denormal operand (FP_X_DNML) + * 5 Numeric over/underflow (FP_X_OFL, FP_X_UFL) + * 6 Inexact result (FP_X_IMP) */ + + static char fpetable[128] = { + 0, + FPE_FLTINV, /* 1 - INV */ + FPE_FLTUND, /* 2 - DNML */ + FPE_FLTINV, /* 3 - INV | DNML */ + FPE_FLTDIV, /* 4 - DZ */ + FPE_FLTINV, /* 5 - INV | DZ */ + FPE_FLTDIV, /* 6 - DNML | DZ */ + FPE_FLTINV, /* 7 - INV | DNML | DZ */ + FPE_FLTOVF, /* 8 - OFL */ + FPE_FLTINV, /* 9 - INV | OFL */ + FPE_FLTUND, /* A - DNML | OFL */ + FPE_FLTINV, /* B - INV | DNML | OFL */ + FPE_FLTDIV, /* C - DZ | OFL */ + FPE_FLTINV, /* D - INV | DZ | OFL */ + FPE_FLTDIV, /* E - DNML | DZ | OFL */ + FPE_FLTINV, /* F - INV | DNML | DZ | OFL */ + FPE_FLTUND, /* 10 - UFL */ + FPE_FLTINV, /* 11 - INV | UFL */ + FPE_FLTUND, /* 12 - DNML | UFL */ + FPE_FLTINV, /* 13 - INV | DNML | UFL */ + FPE_FLTDIV, /* 14 - DZ | UFL */ + FPE_FLTINV, /* 15 - INV | DZ | UFL */ + FPE_FLTDIV, /* 16 - DNML | DZ | UFL */ + FPE_FLTINV, /* 17 - INV | DNML | DZ | UFL */ + FPE_FLTOVF, /* 18 - OFL | UFL */ + FPE_FLTINV, /* 19 - INV | OFL | UFL */ + FPE_FLTUND, /* 1A - DNML | OFL | UFL */ + FPE_FLTINV, /* 1B - INV | DNML | OFL | UFL */ + FPE_FLTDIV, /* 1C - DZ | OFL | UFL */ + FPE_FLTINV, /* 1D - INV | DZ | OFL | UFL */ + FPE_FLTDIV, /* 1E - DNML | DZ | OFL | UFL */ + FPE_FLTINV, /* 1F - INV | DNML | DZ | OFL | UFL */ + FPE_FLTRES, /* 20 - IMP */ + FPE_FLTINV, /* 21 - INV | IMP */ + FPE_FLTUND, /* 22 - DNML | IMP */ + FPE_FLTINV, /* 23 - INV | DNML | IMP */ + FPE_FLTDIV, /* 24 - DZ | IMP */ + FPE_FLTINV, /* 25 - INV | DZ | IMP */ + FPE_FLTDIV, /* 26 - DNML | DZ | IMP */ + FPE_FLTINV, /* 27 - INV | DNML | DZ | IMP */ + FPE_FLTOVF, /* 28 - OFL | IMP */ + FPE_FLTINV, /* 29 - INV | OFL | IMP */ + FPE_FLTUND, /* 2A - DNML | OFL | IMP */ + FPE_FLTINV, /* 2B - INV | DNML | OFL | IMP */ + FPE_FLTDIV, /* 2C - DZ | OFL | IMP */ + FPE_FLTINV, /* 2D - INV | DZ | OFL | IMP */ + FPE_FLTDIV, /* 2E - DNML | DZ | OFL | IMP */ + FPE_FLTINV, /* 2F - INV | DNML | DZ | OFL | IMP */ + FPE_FLTUND, /* 30 - UFL | IMP */ + FPE_FLTINV, /* 31 - INV | UFL | IMP */ + FPE_FLTUND, /* 32 - DNML | UFL | IMP */ + FPE_FLTINV, /* 33 - INV | DNML | UFL | IMP */ + FPE_FLTDIV, /* 34 - DZ | UFL | IMP */ + FPE_FLTINV, /* 35 - INV | DZ | UFL | IMP */ + FPE_FLTDIV, /* 36 - DNML | DZ | UFL | IMP */ + FPE_FLTINV, /* 37 - INV | DNML | DZ | UFL | IMP */ + FPE_FLTOVF, /* 38 - OFL | UFL | IMP */ + FPE_FLTINV, /* 39 - INV | OFL | UFL | IMP */ + FPE_FLTUND, /* 3A - DNML | OFL | UFL | IMP */ + FPE_FLTINV, /* 3B - INV | DNML | OFL | UFL | IMP */ + FPE_FLTDIV, /* 3C - DZ | OFL | UFL | IMP */ + FPE_FLTINV, /* 3D - INV | DZ | OFL | UFL | IMP */ + FPE_FLTDIV, /* 3E - DNML | DZ | OFL | UFL | IMP */ + FPE_FLTINV, /* 3F - INV | DNML | DZ | OFL | UFL | IMP */ + FPE_FLTSUB, /* 40 - STK */ + FPE_FLTSUB, /* 41 - INV | STK */ + FPE_FLTUND, /* 42 - DNML | STK */ + FPE_FLTSUB, /* 43 - INV | DNML | STK */ + FPE_FLTDIV, /* 44 - DZ | STK */ + FPE_FLTSUB, /* 45 - INV | DZ | STK */ + FPE_FLTDIV, /* 46 - DNML | DZ | STK */ + FPE_FLTSUB, /* 47 - INV | DNML | DZ | STK */ + FPE_FLTOVF, /* 48 - OFL | STK */ + FPE_FLTSUB, /* 49 - INV | OFL | STK */ + FPE_FLTUND, /* 4A - DNML | OFL | STK */ + FPE_FLTSUB, /* 4B - INV | DNML | OFL | STK */ + FPE_FLTDIV, /* 4C - DZ | OFL | STK */ + FPE_FLTSUB, /* 4D - INV | DZ | OFL | STK */ + FPE_FLTDIV, /* 4E - DNML | DZ | OFL | STK */ + FPE_FLTSUB, /* 4F - INV | DNML | DZ | OFL | STK */ + FPE_FLTUND, /* 50 - UFL | STK */ + FPE_FLTSUB, /* 51 - INV | UFL | STK */ + FPE_FLTUND, /* 52 - DNML | UFL | STK */ + FPE_FLTSUB, /* 53 - INV | DNML | UFL | STK */ + FPE_FLTDIV, /* 54 - DZ | UFL | STK */ + FPE_FLTSUB, /* 55 - INV | DZ | UFL | STK */ + FPE_FLTDIV, /* 56 - DNML | DZ | UFL | STK */ + FPE_FLTSUB, /* 57 - INV | DNML | DZ | UFL | STK */ + FPE_FLTOVF, /* 58 - OFL | UFL | STK */ + FPE_FLTSUB, /* 59 - INV | OFL | UFL | STK */ + FPE_FLTUND, /* 5A - DNML | OFL | UFL | STK */ + FPE_FLTSUB, /* 5B - INV | DNML | OFL | UFL | STK */ + FPE_FLTDIV, /* 5C - DZ | OFL | UFL | STK */ + FPE_FLTSUB, /* 5D - INV | DZ | OFL | UFL | STK */ + FPE_FLTDIV, /* 5E - DNML | DZ | OFL | UFL | STK */ + FPE_FLTSUB, /* 5F - INV | DNML | DZ | OFL | UFL | STK */ + FPE_FLTRES, /* 60 - IMP | STK */ + FPE_FLTSUB, /* 61 - INV | IMP | STK */ + FPE_FLTUND, /* 62 - DNML | IMP | STK */ + FPE_FLTSUB, /* 63 - INV | DNML | IMP | STK */ + FPE_FLTDIV, /* 64 - DZ | IMP | STK */ + FPE_FLTSUB, /* 65 - INV | DZ | IMP | STK */ + FPE_FLTDIV, /* 66 - DNML | DZ | IMP | STK */ + FPE_FLTSUB, /* 67 - INV | DNML | DZ | IMP | STK */ + FPE_FLTOVF, /* 68 - OFL | IMP | STK */ + FPE_FLTSUB, /* 69 - INV | OFL | IMP | STK */ + FPE_FLTUND, /* 6A - DNML | OFL | IMP | STK */ + FPE_FLTSUB, /* 6B - INV | DNML | OFL | IMP | STK */ + FPE_FLTDIV, /* 6C - DZ | OFL | IMP | STK */ + FPE_FLTSUB, /* 6D - INV | DZ | OFL | IMP | STK */ + FPE_FLTDIV, /* 6E - DNML | DZ | OFL | IMP | STK */ + FPE_FLTSUB, /* 6F - INV | DNML | DZ | OFL | IMP | STK */ + FPE_FLTUND, /* 70 - UFL | IMP | STK */ + FPE_FLTSUB, /* 71 - INV | UFL | IMP | STK */ + FPE_FLTUND, /* 72 - DNML | UFL | IMP | STK */ + FPE_FLTSUB, /* 73 - INV | DNML | UFL | IMP | STK */ + FPE_FLTDIV, /* 74 - DZ | UFL | IMP | STK */ + FPE_FLTSUB, /* 75 - INV | DZ | UFL | IMP | STK */ + FPE_FLTDIV, /* 76 - DNML | DZ | UFL | IMP | STK */ + FPE_FLTSUB, /* 77 - INV | DNML | DZ | UFL | IMP | STK */ + FPE_FLTOVF, /* 78 - OFL | UFL | IMP | STK */ + FPE_FLTSUB, /* 79 - INV | OFL | UFL | IMP | STK */ + FPE_FLTUND, /* 7A - DNML | OFL | UFL | IMP | STK */ + FPE_FLTSUB, /* 7B - INV | DNML | OFL | UFL | IMP | STK */ + FPE_FLTDIV, /* 7C - DZ | OFL | UFL | IMP | STK */ + FPE_FLTSUB, /* 7D - INV | DZ | OFL | UFL | IMP | STK */ + FPE_FLTDIV, /* 7E - DNML | DZ | OFL | UFL | IMP | STK */ + FPE_FLTSUB, /* 7F - INV | DNML | DZ | OFL | UFL | IMP | STK */ + }; + + #define ENCODE(_sw, _cw) (fpetable[(_sw & ~_cw & 0x3f) | (_sw & 0x40)]) + /* * Preserve the FP status word, clear FP exceptions, then generate a SIGFPE. * * Clearing exceptions is necessary mainly to avoid IRQ13 bugs. We now * depend on longjmp() restoring a usable state. Restoring the state * or examining it might fail if we didn't clear exceptions. * ! * The error code chosen will be one of the FPE_... macros. It will be ! * sent as the second argument to old BSD-style signal handlers and as ! * "siginfo_t->si_code" (second argument) to SA_SIGINFO signal handlers. * * XXX the FP state is not preserved across signal handlers. So signal * handlers cannot afford to do FP unless they preserve the state or *************** *** 520,525 **** --- 700,706 ---- void *dummy; { int code; + u_long cw; struct intrframe *frame; if (npxproc == NULL || !npx_exists) { *************** *** 535,540 **** --- 716,722 ---- outb(0xf0, 0); fnstsw(&curpcb->pcb_savefpu.sv_ex_sw); + fnstcw(&cw); fnclex(); /* *************** *** 554,568 **** * just before it is used). */ curproc->p_md.md_regs = INTR_TO_TRAPFRAME(frame); - #ifdef notyet /* * Encode the appropriate code for detailed information on * this exception. */ ! code = XXX_ENCODE(curpcb->pcb_savefpu.sv_ex_sw); ! #else ! code = 0; /* XXX */ ! #endif trapsignal(curproc, SIGFPE, code); } else { /* --- 736,746 ---- * just before it is used). */ curproc->p_md.md_regs = INTR_TO_TRAPFRAME(frame); /* * Encode the appropriate code for detailed information on * this exception. */ ! code = ENCODE(curpcb->pcb_savefpu.sv_ex_sw, cw); trapsignal(curproc, SIGFPE, code); } else { /*