1 /* GDC -- D front-end for GCC
2 Copyright (C) 2004 David Friedman
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "d-gcc-includes.h"
27 #include "d-gcc-real.h"
30 #include "d-codegen.h"
32 static enum machine_mode
35 return TYPE_MODE(long_double_type_node
);
38 static enum machine_mode
39 myMode_to_machineMode(real_t::MyMode mode
)
43 case real_t::Float: return SFmode;
44 case real_t::Double: return DFmode;
45 case real_t::LongDouble: return max_float_mode();
47 case real_t::Float
: return TYPE_MODE(float_type_node
);
48 case real_t::Double
: return TYPE_MODE(double_type_node
);
49 case real_t::LongDouble
: return TYPE_MODE(long_double_type_node
);
57 real_t_Properties real_t_properties
[real_t::NumModes
];
59 #define M_LOG10_2 0.30102999566398119521
64 assert(sizeof(real_t
) >= sizeof(REAL_VALUE_TYPE
));
65 for (int i
= (int) Float
; i
< (int) NumModes
; i
++) {
66 real_t_Properties
& p
= real_t_properties
[i
];
68 enum machine_mode mode
= myMode_to_machineMode((MyMode
) i
);
69 const struct real_format
& rf
= * REAL_MODE_FORMAT(mode
);
71 real_maxval(& p
.maxval
.rv(), 0, mode
);
72 real_ldexp(& p
.minval
.rv(), & dconst1
, rf
.emin
- 1); // %% correct for non-ieee754?
73 real_ldexp(& p
.epsilonval
.rv(), & dconst1
, 1 - rf
.p
); // %% correct for non-ieee754?
75 real_nan(& p.nanval.rv(), "", 1, mode);
76 real_inf(& p.infval.rv());
78 p
.dig
= (int)(rf
.p
* M_LOG10_2
); // %% not always the same as header values..
80 p
.max_10_exp
= (int)(rf
.emax
* M_LOG10_2
);
81 p
.min_10_exp
= (int)(rf
.emin
* M_LOG10_2
);
88 real_t::parse(const char * str
, MyMode mode
)
91 r
.rv() = REAL_VALUE_ATOF(str
, myMode_to_machineMode(mode
));
96 real_t::getnan(MyMode mode
)
99 real_nan(& r
.rv(), "", 1, myMode_to_machineMode(mode
));
104 real_t::getinfinity()
114 REAL_VALUE_FROM_INT(rv(), 0, 0, max_float_mode());
118 real_t::real_t(const real_t
& r
)
123 real_t::real_t(const struct real_value
& rv
)
128 // HOST_WIDE_INT is probably == d_uns64 this is probably zero, so this is probably zero...
129 real_t::real_t(int v
)
134 real_t::real_t(d_uns64 v
)
136 # if HOST_BITS_PER_WIDE_INT == 32
137 REAL_VALUE_FROM_UNSIGNED_INT(rv(),
138 v
& 0xffffffff, (v
>> 32) & 0xffffffff,
140 # elif HOST_BITS_PER_WIDE_INT == 64
141 REAL_VALUE_FROM_UNSIGNED_INT(rv(), v
, 0,
149 real_t::real_t(d_int64 v
)
151 # if HOST_BITS_PER_WIDE_INT == 32
152 REAL_VALUE_FROM_INT(rv(), v
& 0xffffffff,
153 (v
>> 32) & 0xffffffff, max_float_mode());
154 # elif HOST_BITS_PER_WIDE_INT == 64
155 REAL_VALUE_FROM_INT(rv(), v
,
156 (v
& 0x8000000000000000ULL
) ? ~(unsigned HOST_WIDE_INT
) 0 : 0,
163 real_t
& real_t::operator=(const real_t
& r
)
169 real_t
& real_t::operator=(int v
)
171 REAL_VALUE_FROM_UNSIGNED_INT(rv(), v
, 0, max_float_mode());
175 real_t
real_t::operator+ (const real_t
& r
)
178 REAL_ARITHMETIC(x
.rv(), PLUS_EXPR
, rv(), r
.rv());
182 real_t
real_t::operator- (const real_t
& r
)
185 REAL_ARITHMETIC(x
.rv(), MINUS_EXPR
, rv(), r
.rv());
189 real_t
real_t::operator- ()
192 x
.rv() = REAL_VALUE_NEGATE(rv());
196 real_t
real_t::operator* (const real_t
& r
)
199 REAL_ARITHMETIC(x
.rv(), MULT_EXPR
, rv(), r
.rv());
203 real_t
real_t::operator/ (const real_t
& r
)
206 REAL_ARITHMETIC(x
.rv(), RDIV_EXPR
, rv(), r
.rv());
210 // Using darwin fmodl man page for special cases
211 real_t
real_t::operator% (const real_t
& r
)
213 REAL_VALUE_TYPE quot
, tmp
, x
;
217 if (r
.rv().cl
== rvc_zero
|| REAL_VALUE_ISINF(rv())) {
219 real_nan(& rvt
, "", 1, max_float_mode());
223 if ( rv().cl
== rvc_zero
) {
227 if ( REAL_VALUE_ISINF(r
.rv()) ) {
231 // %% need to check for NaN?
232 REAL_ARITHMETIC(quot
, RDIV_EXPR
, rv(), r
.rv());
233 quot
= real_arithmetic2(FIX_TRUNC_EXPR
, & quot
, NULL
);
234 REAL_ARITHMETIC(tmp
, MULT_EXPR
, quot
, r
.rv());
235 REAL_ARITHMETIC(x
, MINUS_EXPR
, rv(), tmp
);
240 bool real_t::operator< (const real_t
& r
)
242 return real_compare(LT_EXPR
, & rv(), & r
.rv());
245 bool real_t::operator> (const real_t
& r
)
247 return real_compare(GT_EXPR
, & rv(), & r
.rv());
250 bool real_t::operator<= (const real_t
& r
)
252 return real_compare(LE_EXPR
, & rv(), & r
.rv());
255 bool real_t::operator>= (const real_t
& r
)
257 return real_compare(GE_EXPR
, & rv(), & r
.rv());
260 bool real_t::operator== (const real_t
& r
)
262 return real_compare(EQ_EXPR
, & rv(), & r
.rv());
265 bool real_t::operator!= (const real_t
& r
)
267 return real_compare(NE_EXPR
, & rv(), & r
.rv());
271 real_t::operator d_uns64()
273 // this may not be the same as native real->int
275 return real_to_integer(& rv());
280 real_t::toInt() const
282 HOST_WIDE_INT low
, high
;
283 real_to_integer2(& low
, & high
, & rv());
284 return gen
.hwi2toli(low
, high
);
288 real_t::toInt(Type
* real_type
, Type
* int_type
) const
290 tree t
= fold( build1(FIX_TRUNC_EXPR
, int_type
->toCtype(),
291 gen
.floatConstant(rv(), real_type
->toBasetype()->isTypeBasic())) );
292 // can't use tree_low_cst as it asserts !TREE_OVERFLOW
293 return gen
.hwi2toli(TREE_INT_CST_LOW(t
), TREE_INT_CST_HIGH(t
));
297 real_t::convert(MyMode to_mode
) const
300 real_convert(& result
.rv(), myMode_to_machineMode(to_mode
), & rv());
307 return rv().cl
== rvc_zero
;
313 return REAL_VALUE_NEGATIVE(rv());
317 real_t::floatCompare(int op
, const real_t
& r
)
321 switch ( (enum TOK
) op
) {
322 case TOKleg
: out
= ORDERED_EXPR
; break; //n = r1 <>= r2; break;
324 return *this < r
|| * this > r
;
325 // n = r1 <> r2; break;
326 case TOKunord
: out
= UNORDERED_EXPR
; break; // n = r1 !<>= r2; break;
327 case TOKue
: out
= UNEQ_EXPR
; break; // n = r1 !<> r2; break;
328 case TOKug
: out
= UNGT_EXPR
; break; // n = r1 !<= r2; break;
329 case TOKuge
: out
= UNGE_EXPR
; break; // n = r1 !< r2; break;
330 case TOKul
: out
= UNLT_EXPR
; break; // n = r1 !>= r2; break;
331 case TOKule
: out
= UNLE_EXPR
; break; // n = r1 !> r2; break;
335 return real_compare(out
, & rv(), & r
.rv());
339 real_t::isIdenticalTo(const real_t
& r
) const
341 return REAL_VALUES_IDENTICAL(rv(), r
.rv());
345 real_t::format(char * buf
, unsigned buf_size
) const
347 real_to_decimal(buf
, & rv(), buf_size
, 0, 1);
351 real_t::formatHex(char * buf
, unsigned buf_size
) const
353 real_to_hexadecimal(buf
, & rv(), buf_size
, 0, 1);
359 return REAL_VALUE_ISINF(rv());
365 return REAL_VALUE_ISNAN(rv());
369 real_t::isConversionExact(MyMode to_mode
) const
371 return exact_real_truncate(myMode_to_machineMode(to_mode
), & rv());
375 real_t::toBytes(unsigned char * buf
, unsigned buf_size
)
377 // See assemble_real in varasm.c
378 // This code assumes we are storing into 8-bit host bytes.
379 unsigned ld_size
= int_size_in_bytes(long_double_type_node
);
380 unsigned count
= ld_size
;
383 unsigned char *dest
= buf
;
385 // assert(ld_size == REALSIZE);
386 // assert(buf_size >= REALSIZE);
387 assert( ld_size
<= 16 );
389 real_to_target (data
, & rv(), TYPE_MODE(long_double_type_node
));
392 for (int i
= 4; i
&& count
; i
--) {
405 format(buf
, sizeof(buf
));
406 fprintf(stderr
, "%s\n", buf
);