aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/s390/fixdfdi.h
blob: 3e1ad496052dc00294b852f92ce58b76ef677e35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#ifdef L_fixunsdfdi
#define EXPD(fp)	(((fp.l.upper) >> 20) & 0x7FF)
#define EXCESSD		1022
#define SIGNBIT		0x80000000
#define SIGND(fp)	((fp.l.upper) & SIGNBIT)
#define MANTD_LL(fp)	((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
#define FRACD_LL(fp)	(fp.ll & (HIDDEND_LL-1))
#define HIDDEND_LL	((long long)1 << 52)

union double_long {
    double d;
    struct {
      long upper;
      unsigned long lower;
    } l;
    long long ll;
};


/* convert double to unsigned int */
unsigned long long
__fixunsdfdi (double a1)
{
    register union double_long dl1;
    register int exp;
    register long long l;

    dl1.d = a1;

    /* +/- 0, denormalized, negativ */

    if (!EXPD (dl1) || SIGND(dl1))
      return 0;

    exp = EXPD (dl1) - EXCESSD - 53;

    /* number < 1 */

    if (exp < -53)
      return 0;

    /* NaN */

    if ((EXPD(dl1) == 0x7ff) && (FRACD_LL(dl1) != 0)) /* NaN */
      return 0x0ULL;

    /* Number big number & + inf */

    if (exp >= 12) {
      return 0xFFFFFFFFFFFFFFFFULL;
    }

    l = MANTD_LL(dl1);

    /* shift down until exp < 12 or l = 0 */
    if (exp > 0)
      l <<= exp;
    else 
      l >>= -exp;

    return l;
}
#define __fixunsdfdi ___fixunsdfdi
#endif
#undef L_fixunsdfdi

#ifdef L_fixdfdi
#define EXPD(fp)	(((fp.l.upper) >> 20) & 0x7FF)
#define EXCESSD		1022
#define SIGNBIT		0x80000000
#define SIGND(fp)	((fp.l.upper) & SIGNBIT)
#define MANTD_LL(fp)	((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
#define FRACD_LL(fp)	(fp.ll & (HIDDEND_LL-1))
#define HIDDEND_LL	((long long)1 << 52)

union double_long {
    double d;
    struct {
      long upper;
      unsigned long lower;
    } l;
    long long ll;
};

/* convert double to int */
long long
__fixdfdi (double a1)
{
    register union double_long dl1;
    register int exp;
    register long long l;

    dl1.d = a1;

    /* +/- 0, denormalized */

    if (!EXPD (dl1))
      return 0;

    exp = EXPD (dl1) - EXCESSD - 53;

    /* number < 1 */

    if (exp < -53)
      return 0;

    /* NaN */

    if ((EXPD(dl1) == 0x7ff) && (FRACD_LL(dl1) != 0)) /* NaN */
      return 0x8000000000000000ULL;

    /* Number big number & +/- inf */

    if (exp >= 11) {
	l = (long long)1<<63;
	if (!SIGND(dl1))
	    l--;
	return l;
    }

    l = MANTD_LL(dl1);

    /* shift down until exp < 12 or l = 0 */
    if (exp > 0)
      l <<= exp;
    else 
      l >>= -exp;

    return (SIGND (dl1) ? -l : l);
}
#define __fixdfdi ___fixdfdi
#endif
#undef L_fixdfdi