Back to home page

OSCL-LXR

 
 

    


0001 /* Software floating-point emulation.
0002    Basic one-word fraction declaration and manipulation.
0003    Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
0004    This file is part of the GNU C Library.
0005    Contributed by Richard Henderson (rth@cygnus.com),
0006           Jakub Jelinek (jj@ultra.linux.cz),
0007           David S. Miller (davem@redhat.com) and
0008           Peter Maydell (pmaydell@chiark.greenend.org.uk).
0009 
0010    The GNU C Library is free software; you can redistribute it and/or
0011    modify it under the terms of the GNU Library General Public License as
0012    published by the Free Software Foundation; either version 2 of the
0013    License, or (at your option) any later version.
0014 
0015    The GNU C Library is distributed in the hope that it will be useful,
0016    but WITHOUT ANY WARRANTY; without even the implied warranty of
0017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0018    Library General Public License for more details.
0019 
0020    You should have received a copy of the GNU Library General Public
0021    License along with the GNU C Library; see the file COPYING.LIB.  If
0022    not, write to the Free Software Foundation, Inc.,
0023    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
0024 
0025 #ifndef    __MATH_EMU_OP_1_H__
0026 #define    __MATH_EMU_OP_1_H__
0027 
0028 #define _FP_FRAC_DECL_1(X)  _FP_W_TYPE X##_f=0
0029 #define _FP_FRAC_COPY_1(D,S)    (D##_f = S##_f)
0030 #define _FP_FRAC_SET_1(X,I) (X##_f = I)
0031 #define _FP_FRAC_HIGH_1(X)  (X##_f)
0032 #define _FP_FRAC_LOW_1(X)   (X##_f)
0033 #define _FP_FRAC_WORD_1(X,w)    (X##_f)
0034 
0035 #define _FP_FRAC_ADDI_1(X,I)    (X##_f += I)
0036 #define _FP_FRAC_SLL_1(X,N)         \
0037   do {                      \
0038     if (__builtin_constant_p(N) && (N) == 1)    \
0039       X##_f += X##_f;               \
0040     else                    \
0041       X##_f <<= (N);                \
0042   } while (0)
0043 #define _FP_FRAC_SRL_1(X,N) (X##_f >>= N)
0044 
0045 /* Right shift with sticky-lsb.  */
0046 #define _FP_FRAC_SRS_1(X,N,sz)  __FP_FRAC_SRS_1(X##_f, N, sz)
0047 
0048 #define __FP_FRAC_SRS_1(X,N,sz)                     \
0049    (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1        \
0050              ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
0051 
0052 #define _FP_FRAC_ADD_1(R,X,Y)   (R##_f = X##_f + Y##_f)
0053 #define _FP_FRAC_SUB_1(R,X,Y)   (R##_f = X##_f - Y##_f)
0054 #define _FP_FRAC_DEC_1(X,Y) (X##_f -= Y##_f)
0055 #define _FP_FRAC_CLZ_1(z, X)    __FP_CLZ(z, X##_f)
0056 
0057 /* Predicates */
0058 #define _FP_FRAC_NEGP_1(X)  ((_FP_WS_TYPE)X##_f < 0)
0059 #define _FP_FRAC_ZEROP_1(X) (X##_f == 0)
0060 #define _FP_FRAC_OVERP_1(fs,X)  (X##_f & _FP_OVERFLOW_##fs)
0061 #define _FP_FRAC_CLEAR_OVERP_1(fs,X)    (X##_f &= ~_FP_OVERFLOW_##fs)
0062 #define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f)
0063 #define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f)
0064 #define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f)
0065 
0066 #define _FP_ZEROFRAC_1      0
0067 #define _FP_MINFRAC_1       1
0068 #define _FP_MAXFRAC_1       (~(_FP_WS_TYPE)0)
0069 
0070 /*
0071  * Unpack the raw bits of a native fp value.  Do not classify or
0072  * normalize the data.
0073  */
0074 
0075 #define _FP_UNPACK_RAW_1(fs, X, val)                \
0076   do {                              \
0077     union _FP_UNION_##fs _flo; _flo.flt = (val);        \
0078                                 \
0079     X##_f = _flo.bits.frac;                 \
0080     X##_e = _flo.bits.exp;                  \
0081     X##_s = _flo.bits.sign;                 \
0082   } while (0)
0083 
0084 #define _FP_UNPACK_RAW_1_P(fs, X, val)              \
0085   do {                              \
0086     union _FP_UNION_##fs *_flo =                \
0087       (union _FP_UNION_##fs *)(val);                \
0088                                 \
0089     X##_f = _flo->bits.frac;                    \
0090     X##_e = _flo->bits.exp;                 \
0091     X##_s = _flo->bits.sign;                    \
0092   } while (0)
0093 
0094 /*
0095  * Repack the raw bits of a native fp value.
0096  */
0097 
0098 #define _FP_PACK_RAW_1(fs, val, X)              \
0099   do {                              \
0100     union _FP_UNION_##fs _flo;                  \
0101                                 \
0102     _flo.bits.frac = X##_f;                 \
0103     _flo.bits.exp  = X##_e;                 \
0104     _flo.bits.sign = X##_s;                 \
0105                                 \
0106     (val) = _flo.flt;                       \
0107   } while (0)
0108 
0109 #define _FP_PACK_RAW_1_P(fs, val, X)                \
0110   do {                              \
0111     union _FP_UNION_##fs *_flo =                \
0112       (union _FP_UNION_##fs *)(val);                \
0113                                 \
0114     _flo->bits.frac = X##_f;                    \
0115     _flo->bits.exp  = X##_e;                    \
0116     _flo->bits.sign = X##_s;                    \
0117   } while (0)
0118 
0119 
0120 /*
0121  * Multiplication algorithms:
0122  */
0123 
0124 /* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
0125    multiplication immediately.  */
0126 
0127 #define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y)              \
0128   do {                                  \
0129     R##_f = X##_f * Y##_f;                      \
0130     /* Normalize since we know where the msb of the multiplicands   \
0131        were (bit B), we know that the msb of the of the product is  \
0132        at either 2B or 2B-1.  */                    \
0133     _FP_FRAC_SRS_1(R, wfracbits-1, 2*wfracbits);            \
0134   } while (0)
0135 
0136 /* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
0137 
0138 #define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit)           \
0139   do {                                  \
0140     _FP_W_TYPE _Z_f0, _Z_f1;                        \
0141     doit(_Z_f1, _Z_f0, X##_f, Y##_f);                   \
0142     /* Normalize since we know where the msb of the multiplicands   \
0143        were (bit B), we know that the msb of the of the product is  \
0144        at either 2B or 2B-1.  */                    \
0145     _FP_FRAC_SRS_2(_Z, wfracbits-1, 2*wfracbits);           \
0146     R##_f = _Z_f0;                          \
0147   } while (0)
0148 
0149 /* Finally, a simple widening multiply algorithm.  What fun!  */
0150 
0151 #define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y)             \
0152   do {                                  \
0153     _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1;      \
0154                                     \
0155     /* split the words in half */                   \
0156     _xh = X##_f >> (_FP_W_TYPE_SIZE/2);                 \
0157     _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1);     \
0158     _yh = Y##_f >> (_FP_W_TYPE_SIZE/2);                 \
0159     _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1);     \
0160                                     \
0161     /* multiply the pieces */                       \
0162     _z_f0 = _xl * _yl;                          \
0163     _a_f0 = _xh * _yl;                          \
0164     _a_f1 = _xl * _yh;                          \
0165     _z_f1 = _xh * _yh;                          \
0166                                     \
0167     /* reassemble into two full words */                \
0168     if ((_a_f0 += _a_f1) < _a_f1)                   \
0169       _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2);            \
0170     _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2);               \
0171     _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2);               \
0172     _FP_FRAC_ADD_2(_z, _z, _a);                     \
0173                                     \
0174     /* normalize */                         \
0175     _FP_FRAC_SRS_2(_z, wfracbits - 1, 2*wfracbits);         \
0176     R##_f = _z_f0;                          \
0177   } while (0)
0178 
0179 
0180 /*
0181  * Division algorithms:
0182  */
0183 
0184 /* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
0185    division immediately.  Give this macro either _FP_DIV_HELP_imm for
0186    C primitives or _FP_DIV_HELP_ldiv for the ISO function.  Which you
0187    choose will depend on what the compiler does with divrem4.  */
0188 
0189 #define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit)       \
0190   do {                          \
0191     _FP_W_TYPE _q, _r;                  \
0192     X##_f <<= (X##_f < Y##_f                \
0193            ? R##_e--, _FP_WFRACBITS_##fs        \
0194            : _FP_WFRACBITS_##fs - 1);       \
0195     doit(_q, _r, X##_f, Y##_f);             \
0196     R##_f = _q | (_r != 0);             \
0197   } while (0)
0198 
0199 /* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
0200    that may be useful in this situation.  This first is for a primitive
0201    that requires normalization, the second for one that does not.  Look
0202    for UDIV_NEEDS_NORMALIZATION to tell which your machine needs.  */
0203 
0204 #define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y)               \
0205   do {                                  \
0206     _FP_W_TYPE _nh, _nl, _q, _r, _y;                    \
0207                                     \
0208     /* Normalize Y -- i.e. make the most significant bit set.  */   \
0209     _y = Y##_f << _FP_WFRACXBITS_##fs;                  \
0210                                     \
0211     /* Shift X op correspondingly high, that is, up one full word.  */  \
0212     if (X##_f < Y##_f)                          \
0213       {                                 \
0214     R##_e--;                            \
0215     _nl = 0;                            \
0216     _nh = X##_f;                            \
0217       }                                 \
0218     else                                \
0219       {                                 \
0220     _nl = X##_f << (_FP_W_TYPE_SIZE - 1);               \
0221     _nh = X##_f >> 1;                       \
0222       }                                 \
0223                                         \
0224     udiv_qrnnd(_q, _r, _nh, _nl, _y);                   \
0225     R##_f = _q | (_r != 0);                     \
0226   } while (0)
0227 
0228 #define _FP_DIV_MEAT_1_udiv(fs, R, X, Y)        \
0229   do {                          \
0230     _FP_W_TYPE _nh, _nl, _q, _r;            \
0231     if (X##_f < Y##_f)                  \
0232       {                         \
0233     R##_e--;                    \
0234     _nl = X##_f << _FP_WFRACBITS_##fs;      \
0235     _nh = X##_f >> _FP_WFRACXBITS_##fs;     \
0236       }                         \
0237     else                        \
0238       {                         \
0239     _nl = X##_f << (_FP_WFRACBITS_##fs - 1);    \
0240     _nh = X##_f >> (_FP_WFRACXBITS_##fs + 1);   \
0241       }                         \
0242     udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);        \
0243     R##_f = _q | (_r != 0);             \
0244   } while (0)
0245   
0246   
0247 /*
0248  * Square root algorithms:
0249  * We have just one right now, maybe Newton approximation
0250  * should be added for those machines where division is fast.
0251  */
0252  
0253 #define _FP_SQRT_MEAT_1(R, S, T, X, q)          \
0254   do {                          \
0255     while (q != _FP_WORK_ROUND)             \
0256       {                         \
0257         T##_f = S##_f + q;              \
0258         if (T##_f <= X##_f)             \
0259           {                     \
0260             S##_f = T##_f + q;              \
0261             X##_f -= T##_f;             \
0262             R##_f += q;                 \
0263           }                     \
0264         _FP_FRAC_SLL_1(X, 1);               \
0265         q >>= 1;                    \
0266       }                         \
0267     if (X##_f)                      \
0268       {                         \
0269     if (S##_f < X##_f)              \
0270       R##_f |= _FP_WORK_ROUND;          \
0271     R##_f |= _FP_WORK_STICKY;           \
0272       }                         \
0273   } while (0)
0274 
0275 /*
0276  * Assembly/disassembly for converting to/from integral types.  
0277  * No shifting or overflow handled here.
0278  */
0279 
0280 #define _FP_FRAC_ASSEMBLE_1(r, X, rsize)    (r = X##_f)
0281 #define _FP_FRAC_DISASSEMBLE_1(X, r, rsize) (X##_f = r)
0282 
0283 
0284 /*
0285  * Convert FP values between word sizes
0286  */
0287 
0288 #define _FP_FRAC_CONV_1_1(dfs, sfs, D, S)               \
0289   do {                                  \
0290     D##_f = S##_f;                          \
0291     if (_FP_WFRACBITS_##sfs > _FP_WFRACBITS_##dfs)          \
0292       {                                 \
0293     if (S##_c != FP_CLS_NAN)                    \
0294       _FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs),  \
0295              _FP_WFRACBITS_##sfs);              \
0296     else                                \
0297       _FP_FRAC_SRL_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs)); \
0298       }                                 \
0299     else                                \
0300       D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs;      \
0301   } while (0)
0302 
0303 #endif /* __MATH_EMU_OP_1_H__ */