Back to index

glibc  2.9
sfp-machine.h
Go to the documentation of this file.
00001 /* Machine-dependent software floating-point definitions.
00002    Sparc userland (_Q_*) version.
00003    Copyright (C) 1997,1998,1999, 2002, 2006 Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Contributed by Richard Henderson (rth@cygnus.com),
00006                 Jakub Jelinek (jj@ultra.linux.cz) and
00007                 David S. Miller (davem@redhat.com).
00008 
00009    The GNU C Library is free software; you can redistribute it and/or
00010    modify it under the terms of the GNU Lesser General Public
00011    License as published by the Free Software Foundation; either
00012    version 2.1 of the License, or (at your option) any later version.
00013 
00014    The GNU C Library is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017    Lesser General Public License for more details.
00018 
00019    You should have received a copy of the GNU Lesser General Public
00020    License along with the GNU C Library; if not, write to the Free
00021    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00022    02111-1307 USA.  */
00023 
00024 #include <fpu_control.h>
00025 #include <stdlib.h>
00026 
00027 #define _FP_W_TYPE_SIZE            32
00028 #define _FP_W_TYPE          unsigned long
00029 #define _FP_WS_TYPE         signed long
00030 #define _FP_I_TYPE          long
00031 
00032 #define _FP_MUL_MEAT_S(R,X,Y)                           \
00033   _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
00034 #define _FP_MUL_MEAT_D(R,X,Y)                           \
00035   _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
00036 #define _FP_MUL_MEAT_Q(R,X,Y)                           \
00037   _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
00038 
00039 #define _FP_DIV_MEAT_S(R,X,Y)      _FP_DIV_MEAT_1_udiv(S,R,X,Y)
00040 #define _FP_DIV_MEAT_D(R,X,Y)      _FP_DIV_MEAT_2_udiv(D,R,X,Y)
00041 #define _FP_DIV_MEAT_Q(R,X,Y)      _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
00042 
00043 #define _FP_NANFRAC_S              ((_FP_QNANBIT_S << 1) - 1)
00044 #define _FP_NANFRAC_D              ((_FP_QNANBIT_D << 1) - 1), -1
00045 #define _FP_NANFRAC_Q              ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
00046 #define _FP_NANSIGN_S              0
00047 #define _FP_NANSIGN_D              0
00048 #define _FP_NANSIGN_Q              0
00049 
00050 #define _FP_KEEPNANFRACP 1
00051 
00052 /* If one NaN is signaling and the other is not,
00053  * we choose that one, otherwise we choose X.
00054  */
00055 /* For _Qp_* and _Q_*, this should prefer X, for
00056  * CPU instruction emulation this should prefer Y.
00057  * (see SPAMv9 B.2.2 section).
00058  */
00059 #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)                     \
00060   do {                                                  \
00061     if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)         \
00062        && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs))     \
00063       {                                                        \
00064        R##_s = Y##_s;                                          \
00065        _FP_FRAC_COPY_##wc(R,Y);                         \
00066       }                                                        \
00067     else                                                \
00068       {                                                        \
00069        R##_s = X##_s;                                          \
00070        _FP_FRAC_COPY_##wc(R,X);                         \
00071       }                                                        \
00072     R##_c = FP_CLS_NAN;                                        \
00073   } while (0)
00074 
00075 /* Some assembly to speed things up. */
00076 #define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)                   \
00077   __asm__ ("addcc %r7,%8,%2\n\
00078            addxcc %r5,%6,%1\n\
00079            addx %r3,%4,%0"                                     \
00080           : "=r" ((USItype)(r2)),                              \
00081             "=&r" ((USItype)(r1)),                             \
00082             "=&r" ((USItype)(r0))                              \
00083           : "%rJ" ((USItype)(x2)),                             \
00084             "rI" ((USItype)(y2)),                              \
00085             "%rJ" ((USItype)(x1)),                             \
00086             "rI" ((USItype)(y1)),                              \
00087             "%rJ" ((USItype)(x0)),                             \
00088             "rI" ((USItype)(y0))                               \
00089           : "cc")
00090 
00091 #define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)                   \
00092   __asm__ ("subcc %r7,%8,%2\n\
00093            subxcc %r5,%6,%1\n\
00094            subx %r3,%4,%0"                                     \
00095           : "=r" ((USItype)(r2)),                              \
00096             "=&r" ((USItype)(r1)),                             \
00097             "=&r" ((USItype)(r0))                              \
00098           : "%rJ" ((USItype)(x2)),                             \
00099             "rI" ((USItype)(y2)),                              \
00100             "%rJ" ((USItype)(x1)),                             \
00101             "rI" ((USItype)(y1)),                              \
00102             "%rJ" ((USItype)(x0)),                             \
00103             "rI" ((USItype)(y0))                               \
00104           : "cc")
00105 
00106 #define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)          \
00107   do {                                                         \
00108     /* We need to fool gcc,  as we need to pass more than 10          \
00109        input/outputs.  */                                      \
00110     register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2");          \
00111     __asm__ __volatile__ ("\
00112            addcc %r8,%9,%1\n\
00113            addxcc %r6,%7,%0\n\
00114            addxcc %r4,%5,%%g2\n\
00115            addx %r2,%3,%%g1"                                          \
00116           : "=&r" ((USItype)(r1)),                             \
00117             "=&r" ((USItype)(r0))                              \
00118           : "%rJ" ((USItype)(x3)),                             \
00119             "rI" ((USItype)(y3)),                              \
00120             "%rJ" ((USItype)(x2)),                             \
00121             "rI" ((USItype)(y2)),                              \
00122             "%rJ" ((USItype)(x1)),                             \
00123             "rI" ((USItype)(y1)),                              \
00124             "%rJ" ((USItype)(x0)),                             \
00125             "rI" ((USItype)(y0))                               \
00126           : "cc", "g1", "g2");                                        \
00127     __asm__ __volatile__ ("" : "=r" (_t1), "=r" (_t2));               \
00128     r3 = _t1; r2 = _t2;                                               \
00129   } while (0)
00130 
00131 #define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)          \
00132   do {                                                         \
00133     /* We need to fool gcc,  as we need to pass more than 10          \
00134        input/outputs.  */                                      \
00135     register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2");          \
00136     __asm__ __volatile__ ("\
00137            subcc %r8,%9,%1\n\
00138            subxcc %r6,%7,%0\n\
00139            subxcc %r4,%5,%%g2\n\
00140            subx %r2,%3,%%g1"                                          \
00141           : "=&r" ((USItype)(r1)),                             \
00142             "=&r" ((USItype)(r0))                              \
00143           : "%rJ" ((USItype)(x3)),                             \
00144             "rI" ((USItype)(y3)),                              \
00145             "%rJ" ((USItype)(x2)),                             \
00146             "rI" ((USItype)(y2)),                              \
00147             "%rJ" ((USItype)(x1)),                             \
00148             "rI" ((USItype)(y1)),                              \
00149             "%rJ" ((USItype)(x0)),                             \
00150             "rI" ((USItype)(y0))                               \
00151           : "cc", "g1", "g2");                                        \
00152     __asm__ __volatile__ ("" : "=r" (_t1), "=r" (_t2));               \
00153     r3 = _t1; r2 = _t2;                                               \
00154   } while (0)
00155 
00156 #define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) __FP_FRAC_SUB_3(x2,x1,x0,x2,x1,x0,y2,y1,y0)
00157 
00158 #define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) __FP_FRAC_SUB_4(x3,x2,x1,x0,x3,x2,x1,x0,y3,y2,y1,y0)
00159 
00160 #define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i)                               \
00161   __asm__ ("addcc %3,%4,%3\n\
00162            addxcc %2,%%g0,%2\n\
00163            addxcc %1,%%g0,%1\n\
00164            addx %0,%%g0,%0"                                    \
00165           : "=&r" ((USItype)(x3)),                             \
00166             "=&r" ((USItype)(x2)),                             \
00167             "=&r" ((USItype)(x1)),                             \
00168             "=&r" ((USItype)(x0))                              \
00169           : "rI" ((USItype)(i)),                               \
00170             "0" ((USItype)(x3)),                               \
00171             "1" ((USItype)(x2)),                               \
00172             "2" ((USItype)(x1)),                               \
00173             "3" ((USItype)(x0))                                \
00174           : "cc")
00175 
00176 /* Obtain the current rounding mode. */
00177 #ifndef FP_ROUNDMODE
00178 #define FP_ROUNDMODE ((_fcw >> 30) & 0x3)
00179 #endif
00180 
00181 /* Exception flags. */
00182 #define FP_EX_INVALID              (1 << 4)
00183 #define FP_EX_OVERFLOW             (1 << 3)
00184 #define FP_EX_UNDERFLOW            (1 << 2)
00185 #define FP_EX_DIVZERO              (1 << 1)
00186 #define FP_EX_INEXACT              (1 << 0)
00187 
00188 #define _FP_DECL_EX  fpu_control_t _fcw
00189 
00190 #define FP_INIT_ROUNDMODE                               \
00191 do {                                                    \
00192   _FPU_GETCW(_fcw);                                     \
00193 } while (0)
00194 
00195 /* Simulate exceptions using double arithmetics. */
00196 extern double ___Q_simulate_exceptions(int exc);
00197 
00198 #define FP_HANDLE_EXCEPTIONS                                   \
00199 do {                                                    \
00200   if (!_fex)                                            \
00201     {                                                   \
00202       /* This is the common case, so we do it inline.          \
00203        * We need to clear cexc bits if any.                    \
00204        */                                               \
00205       extern unsigned long long ___Q_numbers[];                \
00206       __asm__ __volatile__("\
00207        ldd [%0], %%f30\n\
00208        faddd %%f30, %%f30, %%f30\
00209        " : : "r" (___Q_numbers) : "f30");               \
00210     }                                                   \
00211   else                                                  \
00212     ___Q_simulate_exceptions (_fex);                            \
00213 } while (0)