Source-Changes-HG archive

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

[src/trunk]: src/lib/libc/arch/alpha/gen Use excb before and after the mt_fpc...



details:   https://anonhg.NetBSD.org/src/rev/307aac1c6cfc
branches:  trunk
changeset: 765979:307aac1c6cfc
user:      matt <matt%NetBSD.org@localhost>
date:      Sun Jun 12 05:44:36 2011 +0000

description:
Use excb before and after the mt_fpcr/mf_fpcr instructions as specified
in the alpha ARM 4.7.8.1 (Accessing the FPCR):

        Because Alpha floating-point hardware can overlap the execution of
        a number of floating-point instructions, accessing the FPCR must
        be synchronized with other floating-point instructions. An EXCB
        instruction must be issued both prior to and after accessing the
        FPCR to ensure that the FPCR access is synchronized with the
        execution of previous and subsequent floating-point instructions;
        otherwise synchronization is not ensured.

Use unions to convert between double and uint64_t to avoid casting.

diffstat:

 lib/libc/arch/alpha/gen/__setjmp14.S |   4 +++-
 lib/libc/arch/alpha/gen/flt_rounds.c |  36 ++++++++++++++++++++----------------
 lib/libc/arch/alpha/gen/fpgetround.c |  17 +++++++++--------
 lib/libc/arch/alpha/gen/fpsetround.c |  32 ++++++++++++++++----------------
 4 files changed, 48 insertions(+), 41 deletions(-)

diffs (171 lines):

diff -r 69e2e126edb3 -r 307aac1c6cfc lib/libc/arch/alpha/gen/__setjmp14.S
--- a/lib/libc/arch/alpha/gen/__setjmp14.S      Sun Jun 12 05:39:57 2011 +0000
+++ b/lib/libc/arch/alpha/gen/__setjmp14.S      Sun Jun 12 05:44:36 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: __setjmp14.S,v 1.4 2004/03/21 18:04:27 matt Exp $ */
+/* $NetBSD: __setjmp14.S,v 1.5 2011/06/12 05:44:36 matt Exp $ */
 
 /*
  * Copyright (c) 1994, 1995 Carnegie-Mellon University.
@@ -96,7 +96,9 @@
        stt     fs5, (7*8 + SC_FPREGS)(a0)
        stt     fs6, (8*8 + SC_FPREGS)(a0)
        stt     fs7, (9*8 + SC_FPREGS)(a0)
+       excb                                    /* required 4.7.8.1 Alpha ARM */
        mf_fpcr ft0                             /* get FP control reg */
+       excb                                    /* required 4.7.8.1 Alpha ARM */
        stt     ft0, SC_FPCR(a0)                /* and store it in sc_fpcr */
        stq     zero, SC_FP_CONTROL(a0)         /* FP software control XXX */
        stq     zero, (SC_RESERVED + 0*8)(a0)   /* sc_reserved[0] */
diff -r 69e2e126edb3 -r 307aac1c6cfc lib/libc/arch/alpha/gen/flt_rounds.c
--- a/lib/libc/arch/alpha/gen/flt_rounds.c      Sun Jun 12 05:39:57 2011 +0000
+++ b/lib/libc/arch/alpha/gen/flt_rounds.c      Sun Jun 12 05:44:36 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: flt_rounds.c,v 1.8 2005/12/24 23:10:08 perry Exp $ */
+/* $NetBSD: flt_rounds.c,v 1.9 2011/06/12 05:44:36 matt Exp $ */
 
 /*
  * Copyright (c) 1995 Christopher G. Demetriou
@@ -36,29 +36,33 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: flt_rounds.c,v 1.8 2005/12/24 23:10:08 perry Exp $");
+__RCSID("$NetBSD: flt_rounds.c,v 1.9 2011/06/12 05:44:36 matt Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/types.h>
+#include <machine/ieeefp.h>
 #include <machine/float.h>
 
-static const int map[] = {
-       0,      /* round to zero */
-       3,      /* round to negative infinity */
-       1,      /* round to nearest */
-       2       /* round to positive infinity */
-};
+/*
+ * These come from <float.h> defintion
+ */
+#define        FLT_ROUND_MAP \
+       ( (0 << (FP_RZ*2))      /* round to zero */                     \
+       | (1 << (FP_RN*2))      /* round to nearest */                  \
+       | (3 << (FP_RM*2))      /* round to negative infinity */        \
+       | (2 << (FP_RP*2)))     /* round to positive infinity */
 
 int
-__flt_rounds()
+__flt_rounds(void)
 {
-       double fpcrval;
-       u_int64_t old;
+       union {
+               double d;
+               uint64_t u64;
+       } fpcrval;
+       uint64_t old;
 
-       __asm("trapb");
-       __asm("mf_fpcr %0" : "=f" (fpcrval));
-       __asm("trapb");
-       old = *(u_int64_t *)(void *)&fpcrval;
+       __asm("excb; mf_fpcr %0; excb" : "=f" (fpcrval.d));
+       old = (fpcrval.u64 >> 58) & 3;
 
-       return map[(old >> 58) & 0x3];
+       return (FLT_ROUND_MAP >> (old << 1)) & 3;
 }
diff -r 69e2e126edb3 -r 307aac1c6cfc lib/libc/arch/alpha/gen/fpgetround.c
--- a/lib/libc/arch/alpha/gen/fpgetround.c      Sun Jun 12 05:39:57 2011 +0000
+++ b/lib/libc/arch/alpha/gen/fpgetround.c      Sun Jun 12 05:44:36 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fpgetround.c,v 1.9 2005/12/24 23:10:08 perry Exp $ */
+/* $NetBSD: fpgetround.c,v 1.10 2011/06/12 05:44:36 matt Exp $ */
 
 /*
  * Copyright (c) 1995 Christopher G. Demetriou
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: fpgetround.c,v 1.9 2005/12/24 23:10:08 perry Exp $");
+__RCSID("$NetBSD: fpgetround.c,v 1.10 2011/06/12 05:44:36 matt Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include "namespace.h"
@@ -49,13 +49,14 @@
 #endif
 
 fp_rnd
-fpgetround()
+fpgetround(void)
 {
-       double fpcrval;
-       u_int64_t old;
+       union {
+               double d;
+               uint64_t u64;
+       } fpcrval;
 
-       __asm("mf_fpcr %0" : "=f" (fpcrval));
-       old = *(u_int64_t *)(void *)&fpcrval;
+       __asm("excb; mf_fpcr %0; excb" : "=f" (fpcrval.d));
 
-       return ((old >> 58) & 0x3);
+       return ((fpcrval.u64 >> 58) & 0x3);
 }
diff -r 69e2e126edb3 -r 307aac1c6cfc lib/libc/arch/alpha/gen/fpsetround.c
--- a/lib/libc/arch/alpha/gen/fpsetround.c      Sun Jun 12 05:39:57 2011 +0000
+++ b/lib/libc/arch/alpha/gen/fpsetround.c      Sun Jun 12 05:44:36 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fpsetround.c,v 1.10 2005/12/24 23:10:08 perry Exp $ */
+/* $NetBSD: fpsetround.c,v 1.11 2011/06/12 05:44:36 matt Exp $ */
 
 /*
  * Copyright (c) 1995 Christopher G. Demetriou
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: fpsetround.c,v 1.10 2005/12/24 23:10:08 perry Exp $");
+__RCSID("$NetBSD: fpsetround.c,v 1.11 2011/06/12 05:44:36 matt Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include "namespace.h"
@@ -49,22 +49,22 @@
 #endif
 
 fp_rnd
-fpsetround(rnd_dir)
-       fp_rnd rnd_dir;
+fpsetround(fp_rnd rnd_dir)
 {
-       double fpcrval;
-       u_int64_t old, new;
-
-       __asm("excb");
-       __asm("mf_fpcr %0" : "=f" (fpcrval));
-       old = *(u_int64_t *)(void *)&fpcrval;
+       union {
+               double d;
+               uint64_t u64;
+       } fpcrval;
+       fp_rnd old;
 
-       new = old & ~(long)0x0c00000000000000;
-       new = (long)rnd_dir << 58;
-       *(u_int64_t *)(void *)&fpcrval = new;
+       __asm("excb; mf_fpcr %0; excb" : "=f" (fpcrval.d));
+       old = (fpcrval.u64 >> 58) & 0x3;
+
+       rnd_dir ^= old;
 
-       __asm("mt_fpcr %0" : : "f" (fpcrval));
-       __asm("excb");
+       fpcrval.u64 ^= (long)rnd_dir << 58;
 
-       return ((old >> 58) & 0x3);
+       __asm("excb; mt_fpcr %0; excb" : : "f" (fpcrval.d));
+
+       return old;
 }



Home | Main Index | Thread Index | Old Index