OSDN Git Service

- fixup asm. No object-code changes
[uclinux-h8/uClibc.git] / libm / powerpc / classic / s_trunc.c
1 #include <limits.h>
2 #include <math.h>
3 #include <endian.h>
4
5 typedef union
6       {
7       struct {
8 #if (__BYTE_ORDER == __BIG_ENDIAN)
9         unsigned long int hi;
10         unsigned long int lo;
11 #else
12         unsigned long int lo;
13         unsigned long int hi;
14 #endif
15       } words;
16       double dbl;
17       } DblInHex;
18
19 static const unsigned long int signMask = 0x80000000ul;
20 static const double twoTo52      = 4503599627370496.0;
21
22 /*******************************************************************************
23 *                                                                              *
24 *     The function trunc truncates its double argument to integral value       *
25 *     and returns the result in double format.  This function signals          *
26 *     inexact if an ordered return value is not equal to the operand.          *
27 *                                                                              *
28 *******************************************************************************/
29
30 libm_hidden_proto(trunc)
31 double trunc ( double x )
32       {
33         DblInHex argument,OldEnvironment;
34         register double y;
35         register unsigned long int xhi;
36         register long int target;
37
38         argument.dbl = x;
39         xhi = argument.words.hi & 0x7fffffffUL;         // xhi <- high half of |x|
40         target = ( argument.words.hi < signMask );              // flag positive sign
41
42         if ( xhi < 0x43300000ul )
43 /*******************************************************************************
44 *     Is |x| < 2.0^53?                                                         *
45 *******************************************************************************/
46                 {
47                 if ( xhi < 0x3ff00000ul )
48 /*******************************************************************************
49 *     Is |x| < 1.0?                                                            *
50 *******************************************************************************/
51                         {
52                         if ( ( xhi | argument.words.lo ) != 0ul )
53                                 {                               // raise deserved INEXACT
54                                 __asm__ ("mffs %0" : "=f" (OldEnvironment.dbl));
55                                 OldEnvironment.words.lo |= 0x02000000ul;
56                                 __asm__ ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
57                                 }
58                         if ( target )                           // return properly signed zero
59                                 return ( 0.0 );
60                         else
61                                 return ( -0.0 );
62                         }
63 /*******************************************************************************
64 *     Is 1.0 < |x| < 2.0^52?                                                   *
65 *******************************************************************************/
66                 if ( target )
67                         {
68                         y = ( x + twoTo52 ) - twoTo52;          // round at binary point
69                         if ( y > x )
70                                 return ( y - 1.0 );
71                         else
72                                 return ( y );
73                         }
74
75                 else
76                         {
77                         y = ( x - twoTo52 ) + twoTo52;          // round at binary point.
78                         if ( y < x )
79                                 return ( y + 1.0 );
80                         else
81                                 return ( y );
82                         }
83                 }
84 /*******************************************************************************
85 *      Is |x| >= 2.0^52 or x is a NaN.                                         *
86 *******************************************************************************/
87         return ( x );
88         }
89 libm_hidden_def(trunc)