Port-i386 archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Changing x87 precision to full 63bit as default



Hi all,
as discussed a while ago, I would like to change the initial x87
configuration to the system default, aka long double precision.
This makes it possible to get working long double. A review of the libm
assembler routines will follow to make sure they do correct rounding.

The patch checks the version of the main binary, so that old binaries
will keep working. libm will update the global fenv.h environment to
match whatever the kernel is using. The mixing should be harmless as
long as only double routines are used, new long double routines will
naturally not give the full precision for old binaries.

Joerg
Index: external/gpl3/gcc/dist/gcc/config/i386/netbsd-elf.h
===================================================================
RCS file: 
/home/joerg/repo/netbsd/src/external/gpl3/gcc/dist/gcc/config/i386/netbsd-elf.h,v
retrieving revision 1.3
diff -u -p -r1.3 netbsd-elf.h
--- external/gpl3/gcc/dist/gcc/config/i386/netbsd-elf.h 14 Sep 2012 13:00:01 
-0000      1.3
+++ external/gpl3/gcc/dist/gcc/config/i386/netbsd-elf.h 30 Oct 2013 23:43:03 
-0000
@@ -123,10 +123,6 @@ along with GCC; see the file COPYING3.  
 
 #define TARGET_VERSION fprintf (stderr, " (NetBSD/i386 ELF)");
 
-#undef X87_ENABLE_ARITH
-#define X87_ENABLE_ARITH(MODE) \
-  (flag_excess_precision == EXCESS_PRECISION_FAST || (MODE) == DFmode)
-
 /* Preserve i386 psABI  */
 #undef PREFERRED_STACK_BOUNDARY_DEFAULT
 #define PREFERRED_STACK_BOUNDARY_DEFAULT MIN_STACK_BOUNDARY
Index: lib/libm/arch/i387/fenv.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libm/arch/i387/fenv.c,v
retrieving revision 1.5
diff -u -p -r1.5 fenv.c
--- lib/libm/arch/i387/fenv.c   29 May 2013 00:53:19 -0000      1.5
+++ lib/libm/arch/i387/fenv.c   30 Oct 2013 23:38:15 -0000
@@ -115,16 +115,20 @@ fenv_t __fe_dfl_env = {
  */
 static int __HAS_SSE = 0;
 
-static void __test_sse(void) __attribute__ ((constructor));
+static void __init_libm(void) __attribute__ ((constructor, used));
 
-static void __test_sse(void)
+static void __init_libm(void)
 {
        size_t oldlen = sizeof(__HAS_SSE);
        int rv;
+       uint16_t control;
 
        rv = sysctlbyname("machdep.sse", &__HAS_SSE, &oldlen, NULL, 0);
        if (rv == -1)
                __HAS_SSE = 0;
+
+       __fnstcw(&control);
+       __fe_dfl_env.x87.control = control;
 }
 
 /*
Index: lib/libm/arch/x86_64/fenv.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libm/arch/x86_64/fenv.c,v
retrieving revision 1.5
diff -u -p -r1.5 fenv.c
--- lib/libm/arch/x86_64/fenv.c 18 Oct 2013 17:03:02 -0000      1.5
+++ lib/libm/arch/x86_64/fenv.c 30 Oct 2013 23:38:23 -0000
@@ -100,6 +100,16 @@ fenv_t __fe_dfl_env = {
 };
 #define FE_DFL_ENV      ((const fenv_t *) &__fe_dfl_env)
 
+static void __init_libm(void) __attribute__ ((constructor, used));
+
+static void __init_libm(void)
+{
+       uint16_t control;
+
+       __fnstcw(&control);
+       __fe_dfl_env.x87.control = control;
+}
+
 
 /*
  * The feclearexcept() function clears the supported floating-point exceptions
Index: sys/arch/amd64/amd64/machdep.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/sys/arch/amd64/amd64/machdep.c,v
retrieving revision 1.198
diff -u -p -r1.198 machdep.c
--- sys/arch/amd64/amd64/machdep.c      6 Nov 2013 06:23:15 -0000       1.198
+++ sys/arch/amd64/amd64/machdep.c      6 Nov 2013 14:57:22 -0000
@@ -1324,7 +1324,10 @@ setregs(struct lwp *l, struct exec_packa
 
        pcu_discard(&fpu_ops, false);
        pcb->pcb_flags = 0;
-       pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_NPXCW__;
+       if (pack->ep_osversion >= 699002500)
+               pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_NPXCW__;
+       else
+               pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_COMPAT_NPXCW__;
        pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__;
        pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__;
 
Index: sys/arch/amd64/amd64/netbsd32_machdep.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/sys/arch/amd64/amd64/netbsd32_machdep.c,v
retrieving revision 1.83
diff -u -p -r1.83 netbsd32_machdep.c
--- sys/arch/amd64/amd64/netbsd32_machdep.c     2 Nov 2013 00:41:58 -0000       
1.83
+++ sys/arch/amd64/amd64/netbsd32_machdep.c     6 Nov 2013 14:57:22 -0000
@@ -141,7 +141,10 @@ netbsd32_setregs(struct lwp *l, struct e
 
        l->l_md.md_flags |= MDL_COMPAT32;       /* Force iret not sysret */
        pcb->pcb_flags = PCB_COMPAT32;
-        pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_NPXCW__;
+       if (pack->ep_osversion >= 699002500)
+               pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_NPXCW__;
+       else
+               pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_COMPAT_NPXCW__;
         pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__;  
        pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__;
 
Index: sys/arch/amd64/include/fpu.h
===================================================================
RCS file: /home/joerg/repo/netbsd/src/sys/arch/amd64/include/fpu.h,v
retrieving revision 1.8
diff -u -p -r1.8 fpu.h
--- sys/arch/amd64/include/fpu.h        23 Oct 2013 20:18:50 -0000      1.8
+++ sys/arch/amd64/include/fpu.h        7 Nov 2013 10:11:41 -0000
@@ -47,8 +47,10 @@ struct savefpu_i387 {
 #define __INITIAL_MXCSR__      0x1f80
 #define __INITIAL_MXCSR_MASK__ 0xffbf
 
-/* NetBSD uses IEEE double precision. */
-#define        __NetBSD_NPXCW__        0x127f
+/* Modern NetBSD uses the default control word.. */
+#define        __NetBSD_NPXCW__        0x037f
+/* NetBSD before 6.99.25 forced IEEE double precision. */
+#define        __NetBSD_COMPAT_NPXCW__ 0x127f
 /* Linux just uses the default control word. */
 #define        __Linux_NPXCW__         0x037f
 
Index: sys/arch/i386/i386/machdep.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.735
diff -u -p -r1.735 machdep.c
--- sys/arch/i386/i386/machdep.c        23 Oct 2013 20:18:50 -0000      1.735
+++ sys/arch/i386/i386/machdep.c        30 Oct 2013 23:42:09 -0000
@@ -862,17 +862,23 @@ setregs(struct lwp *l, struct exec_packa
        struct pmap *pmap = vm_map_pmap(&l->l_proc->p_vmspace->vm_map);
        struct pcb *pcb = lwp_getpcb(l);
        struct trapframe *tf;
+       uint16_t control;
 
 #ifdef USER_LDT
        pmap_ldt_cleanup(l);
 #endif
 
        pcu_discard(&fpu_ops, false);
+       if (pack->ep_osversion >= 699002500)
+               control = __INITIAL_NPXCW__;
+       else
+               control = __NetBSD_COMPAT_NPXCW__;
+
        if (i386_use_fxsave) {
-               pcb->pcb_savefpu.sv_xmm.sv_env.en_cw = __NetBSD_NPXCW__;
+               pcb->pcb_savefpu.sv_xmm.sv_env.en_cw = control;
                pcb->pcb_savefpu.sv_xmm.sv_env.en_mxcsr = __INITIAL_MXCSR__;
        } else
-               pcb->pcb_savefpu.sv_87.sv_env.en_cw = __NetBSD_NPXCW__;
+               pcb->pcb_savefpu.sv_87.sv_env.en_cw = control;
        memcpy(&pcb->pcb_fsd, &gdt[GUDATA_SEL], sizeof(pcb->pcb_fsd));
        memcpy(&pcb->pcb_gsd, &gdt[GUDATA_SEL], sizeof(pcb->pcb_gsd));
 
Index: sys/arch/i386/include/npx.h
===================================================================
RCS file: /home/joerg/repo/netbsd/src/sys/arch/i386/include/npx.h,v
retrieving revision 1.25
diff -u -p -r1.25 npx.h
--- sys/arch/i386/include/npx.h 31 Jul 2010 21:47:54 -0000      1.25
+++ sys/arch/i386/include/npx.h 7 Nov 2013 10:11:57 -0000
@@ -126,8 +126,10 @@ union savefpu {
  * with all exceptions masked.
  */
 #define        __INITIAL_NPXCW__       0x037f
-/* NetBSD uses IEEE double precision. */
-#define        __NetBSD_NPXCW__        0x127f
+/* Modern NetBSD uses the default control word.. */
+#define        __NetBSD_NPXCW__        0x037f
+/* NetBSD before 6.99.25 forced IEEE double precision. */
+#define        __NetBSD_COMPAT_NPXCW__ 0x127f
 /* FreeBSD leaves some exceptions unmasked as well. */
 #define        __FreeBSD_NPXCW__       0x1272
 /* iBCS2 goes a bit further and leaves the underflow exception unmasked. */
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp       (revision 193633)
+++ lib/Basic/Targets.cpp       (working copy)
@@ -2988,7 +2988,12 @@
       : NetBSDTargetInfo<X86_32TargetInfo>(Triple) {}
 
   virtual unsigned getFloatEvalMethod() const {
-    // NetBSD defaults to "double" rounding
+    unsigned Major, Minor, Micro;
+    getTriple().getOSVersion(Major, Minor, Micro);
+    // New NetBSD uses the default rounding mode.
+    if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 25) || Major == 0)
+      return X86_32TargetInfo::getFloatEvalMethod();
+    // NetBSD before 6.99.25 defaults to "double" rounding.
     return 1;
   }
 };


Home | Main Index | Thread Index | Old Index