]>
Commit | Line | Data |
---|---|---|
d16aafd8 AC |
1 | /* Floating point routines for GDB, the GNU debugger. |
2 | Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, | |
3 | 1997, 1998, 1999, 2000, 2001 | |
4 | Free Software Foundation, Inc. | |
5 | ||
6 | This file is part of GDB. | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, Inc., 59 Temple Place - Suite 330, | |
21 | Boston, MA 02111-1307, USA. */ | |
22 | ||
23 | /* Support for converting target fp numbers into host DOUBLEST format. */ | |
24 | ||
25 | /* XXX - This code should really be in libiberty/floatformat.c, | |
26 | however configuration issues with libiberty made this very | |
27 | difficult to do in the available time. */ | |
28 | ||
29 | #include "defs.h" | |
30 | #include "doublest.h" | |
31 | #include "floatformat.h" | |
32 | #include "gdb_assert.h" | |
33 | #include "gdb_string.h" | |
34 | #include <math.h> /* ldexp */ | |
35 | ||
36 | /* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not | |
37 | going to bother with trying to muck around with whether it is defined in | |
38 | a system header, what we do if not, etc. */ | |
39 | #define FLOATFORMAT_CHAR_BIT 8 | |
40 | ||
41 | static unsigned long get_field (unsigned char *, | |
42 | enum floatformat_byteorders, | |
43 | unsigned int, unsigned int, unsigned int); | |
44 | ||
45 | /* Extract a field which starts at START and is LEN bytes long. DATA and | |
46 | TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ | |
47 | static unsigned long | |
48 | get_field (unsigned char *data, enum floatformat_byteorders order, | |
49 | unsigned int total_len, unsigned int start, unsigned int len) | |
50 | { | |
51 | unsigned long result; | |
52 | unsigned int cur_byte; | |
53 | int cur_bitshift; | |
54 | ||
55 | /* Start at the least significant part of the field. */ | |
56 | if (order == floatformat_little || order == floatformat_littlebyte_bigword) | |
57 | { | |
58 | /* We start counting from the other end (i.e, from the high bytes | |
59 | rather than the low bytes). As such, we need to be concerned | |
60 | with what happens if bit 0 doesn't start on a byte boundary. | |
61 | I.e, we need to properly handle the case where total_len is | |
62 | not evenly divisible by 8. So we compute ``excess'' which | |
63 | represents the number of bits from the end of our starting | |
64 | byte needed to get to bit 0. */ | |
65 | int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT); | |
66 | cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) | |
67 | - ((start + len + excess) / FLOATFORMAT_CHAR_BIT); | |
68 | cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT) | |
69 | - FLOATFORMAT_CHAR_BIT; | |
70 | } | |
71 | else | |
72 | { | |
73 | cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT; | |
74 | cur_bitshift = | |
75 | ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT; | |
76 | } | |
77 | if (cur_bitshift > -FLOATFORMAT_CHAR_BIT) | |
78 | result = *(data + cur_byte) >> (-cur_bitshift); | |
79 | else | |
80 | result = 0; | |
81 | cur_bitshift += FLOATFORMAT_CHAR_BIT; | |
82 | if (order == floatformat_little || order == floatformat_littlebyte_bigword) | |
83 | ++cur_byte; | |
84 | else | |
85 | --cur_byte; | |
86 | ||
87 | /* Move towards the most significant part of the field. */ | |
88 | while (cur_bitshift < len) | |
89 | { | |
90 | result |= (unsigned long)*(data + cur_byte) << cur_bitshift; | |
91 | cur_bitshift += FLOATFORMAT_CHAR_BIT; | |
92 | if (order == floatformat_little || order == floatformat_littlebyte_bigword) | |
93 | ++cur_byte; | |
94 | else | |
95 | --cur_byte; | |
96 | } | |
97 | if (len < sizeof(result) * FLOATFORMAT_CHAR_BIT) | |
98 | /* Mask out bits which are not part of the field */ | |
99 | result &= ((1UL << len) - 1); | |
100 | return result; | |
101 | } | |
102 | ||
103 | /* Convert from FMT to a DOUBLEST. | |
104 | FROM is the address of the extended float. | |
105 | Store the DOUBLEST in *TO. */ | |
106 | ||
107 | void | |
64f6fcad AC |
108 | floatformat_to_doublest (const struct floatformat *fmt, |
109 | const void *from, | |
d16aafd8 AC |
110 | DOUBLEST *to) |
111 | { | |
112 | unsigned char *ufrom = (unsigned char *) from; | |
113 | DOUBLEST dto; | |
114 | long exponent; | |
115 | unsigned long mant; | |
116 | unsigned int mant_bits, mant_off; | |
117 | int mant_bits_left; | |
118 | int special_exponent; /* It's a NaN, denorm or zero */ | |
119 | ||
120 | /* If the mantissa bits are not contiguous from one end of the | |
121 | mantissa to the other, we need to make a private copy of the | |
122 | source bytes that is in the right order since the unpacking | |
123 | algorithm assumes that the bits are contiguous. | |
124 | ||
125 | Swap the bytes individually rather than accessing them through | |
126 | "long *" since we have no guarantee that they start on a long | |
127 | alignment, and also sizeof(long) for the host could be different | |
128 | than sizeof(long) for the target. FIXME: Assumes sizeof(long) | |
129 | for the target is 4. */ | |
130 | ||
131 | if (fmt->byteorder == floatformat_littlebyte_bigword) | |
132 | { | |
133 | static unsigned char *newfrom; | |
134 | unsigned char *swapin, *swapout; | |
135 | int longswaps; | |
136 | ||
137 | longswaps = fmt->totalsize / FLOATFORMAT_CHAR_BIT; | |
138 | longswaps >>= 3; | |
139 | ||
140 | if (newfrom == NULL) | |
141 | { | |
142 | newfrom = (unsigned char *) xmalloc (fmt->totalsize); | |
143 | } | |
144 | swapout = newfrom; | |
145 | swapin = ufrom; | |
146 | ufrom = newfrom; | |
147 | while (longswaps-- > 0) | |
148 | { | |
149 | /* This is ugly, but efficient */ | |
150 | *swapout++ = swapin[4]; | |
151 | *swapout++ = swapin[5]; | |
152 | *swapout++ = swapin[6]; | |
153 | *swapout++ = swapin[7]; | |
154 | *swapout++ = swapin[0]; | |
155 | *swapout++ = swapin[1]; | |
156 | *swapout++ = swapin[2]; | |
157 | *swapout++ = swapin[3]; | |
158 | swapin += 8; | |
159 | } | |
160 | } | |
161 | ||
162 | exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, | |
163 | fmt->exp_start, fmt->exp_len); | |
164 | /* Note that if exponent indicates a NaN, we can't really do anything useful | |
165 | (not knowing if the host has NaN's, or how to build one). So it will | |
166 | end up as an infinity or something close; that is OK. */ | |
167 | ||
168 | mant_bits_left = fmt->man_len; | |
169 | mant_off = fmt->man_start; | |
170 | dto = 0.0; | |
171 | ||
172 | special_exponent = exponent == 0 || exponent == fmt->exp_nan; | |
173 | ||
174 | /* Don't bias NaNs. Use minimum exponent for denorms. For simplicity, | |
175 | we don't check for zero as the exponent doesn't matter. */ | |
176 | if (!special_exponent) | |
177 | exponent -= fmt->exp_bias; | |
178 | else if (exponent == 0) | |
179 | exponent = 1 - fmt->exp_bias; | |
180 | ||
181 | /* Build the result algebraically. Might go infinite, underflow, etc; | |
182 | who cares. */ | |
183 | ||
184 | /* If this format uses a hidden bit, explicitly add it in now. Otherwise, | |
185 | increment the exponent by one to account for the integer bit. */ | |
186 | ||
187 | if (!special_exponent) | |
188 | { | |
189 | if (fmt->intbit == floatformat_intbit_no) | |
190 | dto = ldexp (1.0, exponent); | |
191 | else | |
192 | exponent++; | |
193 | } | |
194 | ||
195 | while (mant_bits_left > 0) | |
196 | { | |
197 | mant_bits = min (mant_bits_left, 32); | |
198 | ||
199 | mant = get_field (ufrom, fmt->byteorder, fmt->totalsize, | |
200 | mant_off, mant_bits); | |
201 | ||
202 | dto += ldexp ((double) mant, exponent - mant_bits); | |
203 | exponent -= mant_bits; | |
204 | mant_off += mant_bits; | |
205 | mant_bits_left -= mant_bits; | |
206 | } | |
207 | ||
208 | /* Negate it if negative. */ | |
209 | if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1)) | |
210 | dto = -dto; | |
211 | *to = dto; | |
212 | } | |
213 | \f | |
214 | static void put_field (unsigned char *, enum floatformat_byteorders, | |
215 | unsigned int, | |
216 | unsigned int, unsigned int, unsigned long); | |
217 | ||
218 | /* Set a field which starts at START and is LEN bytes long. DATA and | |
219 | TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ | |
220 | static void | |
221 | put_field (unsigned char *data, enum floatformat_byteorders order, | |
222 | unsigned int total_len, unsigned int start, unsigned int len, | |
223 | unsigned long stuff_to_put) | |
224 | { | |
225 | unsigned int cur_byte; | |
226 | int cur_bitshift; | |
227 | ||
228 | /* Start at the least significant part of the field. */ | |
229 | if (order == floatformat_little || order == floatformat_littlebyte_bigword) | |
230 | { | |
231 | int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT); | |
232 | cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) | |
233 | - ((start + len + excess) / FLOATFORMAT_CHAR_BIT); | |
234 | cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT) | |
235 | - FLOATFORMAT_CHAR_BIT; | |
236 | } | |
237 | else | |
238 | { | |
239 | cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT; | |
240 | cur_bitshift = | |
241 | ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT; | |
242 | } | |
243 | if (cur_bitshift > -FLOATFORMAT_CHAR_BIT) | |
244 | { | |
245 | *(data + cur_byte) &= | |
246 | ~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1) | |
247 | << (-cur_bitshift)); | |
248 | *(data + cur_byte) |= | |
249 | (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift); | |
250 | } | |
251 | cur_bitshift += FLOATFORMAT_CHAR_BIT; | |
252 | if (order == floatformat_little || order == floatformat_littlebyte_bigword) | |
253 | ++cur_byte; | |
254 | else | |
255 | --cur_byte; | |
256 | ||
257 | /* Move towards the most significant part of the field. */ | |
258 | while (cur_bitshift < len) | |
259 | { | |
260 | if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT) | |
261 | { | |
262 | /* This is the last byte. */ | |
263 | *(data + cur_byte) &= | |
264 | ~((1 << (len - cur_bitshift)) - 1); | |
265 | *(data + cur_byte) |= (stuff_to_put >> cur_bitshift); | |
266 | } | |
267 | else | |
268 | *(data + cur_byte) = ((stuff_to_put >> cur_bitshift) | |
269 | & ((1 << FLOATFORMAT_CHAR_BIT) - 1)); | |
270 | cur_bitshift += FLOATFORMAT_CHAR_BIT; | |
271 | if (order == floatformat_little || order == floatformat_littlebyte_bigword) | |
272 | ++cur_byte; | |
273 | else | |
274 | --cur_byte; | |
275 | } | |
276 | } | |
277 | ||
278 | #ifdef HAVE_LONG_DOUBLE | |
279 | /* Return the fractional part of VALUE, and put the exponent of VALUE in *EPTR. | |
280 | The range of the returned value is >= 0.5 and < 1.0. This is equivalent to | |
281 | frexp, but operates on the long double data type. */ | |
282 | ||
283 | static long double ldfrexp (long double value, int *eptr); | |
284 | ||
285 | static long double | |
286 | ldfrexp (long double value, int *eptr) | |
287 | { | |
288 | long double tmp; | |
289 | int exp; | |
290 | ||
291 | /* Unfortunately, there are no portable functions for extracting the exponent | |
292 | of a long double, so we have to do it iteratively by multiplying or dividing | |
293 | by two until the fraction is between 0.5 and 1.0. */ | |
294 | ||
295 | if (value < 0.0l) | |
296 | value = -value; | |
297 | ||
298 | tmp = 1.0l; | |
299 | exp = 0; | |
300 | ||
301 | if (value >= tmp) /* Value >= 1.0 */ | |
302 | while (value >= tmp) | |
303 | { | |
304 | tmp *= 2.0l; | |
305 | exp++; | |
306 | } | |
307 | else if (value != 0.0l) /* Value < 1.0 and > 0.0 */ | |
308 | { | |
309 | while (value < tmp) | |
310 | { | |
311 | tmp /= 2.0l; | |
312 | exp--; | |
313 | } | |
314 | tmp *= 2.0l; | |
315 | exp++; | |
316 | } | |
317 | ||
318 | *eptr = exp; | |
319 | return value / tmp; | |
320 | } | |
321 | #endif /* HAVE_LONG_DOUBLE */ | |
322 | ||
323 | ||
324 | /* The converse: convert the DOUBLEST *FROM to an extended float | |
325 | and store where TO points. Neither FROM nor TO have any alignment | |
326 | restrictions. */ | |
327 | ||
328 | void | |
64f6fcad AC |
329 | floatformat_from_doublest (CONST struct floatformat *fmt, |
330 | const DOUBLEST *from, | |
331 | void *to) | |
d16aafd8 AC |
332 | { |
333 | DOUBLEST dfrom; | |
334 | int exponent; | |
335 | DOUBLEST mant; | |
336 | unsigned int mant_bits, mant_off; | |
337 | int mant_bits_left; | |
338 | unsigned char *uto = (unsigned char *) to; | |
339 | ||
340 | memcpy (&dfrom, from, sizeof (dfrom)); | |
341 | memset (uto, 0, (fmt->totalsize + FLOATFORMAT_CHAR_BIT - 1) | |
342 | / FLOATFORMAT_CHAR_BIT); | |
343 | if (dfrom == 0) | |
344 | return; /* Result is zero */ | |
345 | if (dfrom != dfrom) /* Result is NaN */ | |
346 | { | |
347 | /* From is NaN */ | |
348 | put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, | |
349 | fmt->exp_len, fmt->exp_nan); | |
350 | /* Be sure it's not infinity, but NaN value is irrel */ | |
351 | put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, | |
352 | 32, 1); | |
353 | return; | |
354 | } | |
355 | ||
356 | /* If negative, set the sign bit. */ | |
357 | if (dfrom < 0) | |
358 | { | |
359 | put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1); | |
360 | dfrom = -dfrom; | |
361 | } | |
362 | ||
363 | if (dfrom + dfrom == dfrom && dfrom != 0.0) /* Result is Infinity */ | |
364 | { | |
365 | /* Infinity exponent is same as NaN's. */ | |
366 | put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, | |
367 | fmt->exp_len, fmt->exp_nan); | |
368 | /* Infinity mantissa is all zeroes. */ | |
369 | put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, | |
370 | fmt->man_len, 0); | |
371 | return; | |
372 | } | |
373 | ||
374 | #ifdef HAVE_LONG_DOUBLE | |
375 | mant = ldfrexp (dfrom, &exponent); | |
376 | #else | |
377 | mant = frexp (dfrom, &exponent); | |
378 | #endif | |
379 | ||
380 | put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len, | |
381 | exponent + fmt->exp_bias - 1); | |
382 | ||
383 | mant_bits_left = fmt->man_len; | |
384 | mant_off = fmt->man_start; | |
385 | while (mant_bits_left > 0) | |
386 | { | |
387 | unsigned long mant_long; | |
388 | mant_bits = mant_bits_left < 32 ? mant_bits_left : 32; | |
389 | ||
390 | mant *= 4294967296.0; | |
391 | mant_long = ((unsigned long) mant) & 0xffffffffL; | |
392 | mant -= mant_long; | |
393 | ||
394 | /* If the integer bit is implicit, then we need to discard it. | |
395 | If we are discarding a zero, we should be (but are not) creating | |
396 | a denormalized number which means adjusting the exponent | |
397 | (I think). */ | |
398 | if (mant_bits_left == fmt->man_len | |
399 | && fmt->intbit == floatformat_intbit_no) | |
400 | { | |
401 | mant_long <<= 1; | |
402 | mant_long &= 0xffffffffL; | |
403 | mant_bits -= 1; | |
404 | } | |
405 | ||
406 | if (mant_bits < 32) | |
407 | { | |
408 | /* The bits we want are in the most significant MANT_BITS bits of | |
409 | mant_long. Move them to the least significant. */ | |
410 | mant_long >>= 32 - mant_bits; | |
411 | } | |
412 | ||
413 | put_field (uto, fmt->byteorder, fmt->totalsize, | |
414 | mant_off, mant_bits, mant_long); | |
415 | mant_off += mant_bits; | |
416 | mant_bits_left -= mant_bits; | |
417 | } | |
418 | if (fmt->byteorder == floatformat_littlebyte_bigword) | |
419 | { | |
420 | int count; | |
421 | unsigned char *swaplow = uto; | |
422 | unsigned char *swaphigh = uto + 4; | |
423 | unsigned char tmp; | |
424 | ||
425 | for (count = 0; count < 4; count++) | |
426 | { | |
427 | tmp = *swaplow; | |
428 | *swaplow++ = *swaphigh; | |
429 | *swaphigh++ = tmp; | |
430 | } | |
431 | } | |
432 | } | |
433 | ||
434 | /* Check if VAL (which is assumed to be a floating point number whose | |
435 | format is described by FMT) is negative. */ | |
436 | ||
437 | int | |
438 | floatformat_is_negative (const struct floatformat *fmt, char *val) | |
439 | { | |
440 | unsigned char *uval = (unsigned char *) val; | |
441 | ||
442 | return get_field (uval, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1); | |
443 | } | |
444 | ||
445 | /* Check if VAL is "not a number" (NaN) for FMT. */ | |
446 | ||
447 | int | |
448 | floatformat_is_nan (const struct floatformat *fmt, char *val) | |
449 | { | |
450 | unsigned char *uval = (unsigned char *) val; | |
451 | long exponent; | |
452 | unsigned long mant; | |
453 | unsigned int mant_bits, mant_off; | |
454 | int mant_bits_left; | |
455 | ||
456 | if (! fmt->exp_nan) | |
457 | return 0; | |
458 | ||
459 | exponent = get_field (uval, fmt->byteorder, fmt->totalsize, | |
460 | fmt->exp_start, fmt->exp_len); | |
461 | ||
462 | if (exponent != fmt->exp_nan) | |
463 | return 0; | |
464 | ||
465 | mant_bits_left = fmt->man_len; | |
466 | mant_off = fmt->man_start; | |
467 | ||
468 | while (mant_bits_left > 0) | |
469 | { | |
470 | mant_bits = min (mant_bits_left, 32); | |
471 | ||
472 | mant = get_field (uval, fmt->byteorder, fmt->totalsize, | |
473 | mant_off, mant_bits); | |
474 | ||
475 | /* If there is an explicit integer bit, mask it off. */ | |
476 | if (mant_off == fmt->man_start | |
477 | && fmt->intbit == floatformat_intbit_yes) | |
478 | mant &= ~(1 << (mant_bits - 1)); | |
479 | ||
480 | if (mant) | |
481 | return 1; | |
482 | ||
483 | mant_off += mant_bits; | |
484 | mant_bits_left -= mant_bits; | |
485 | } | |
486 | ||
487 | return 0; | |
488 | } | |
489 | ||
490 | /* Convert the mantissa of VAL (which is assumed to be a floating | |
491 | point number whose format is described by FMT) into a hexadecimal | |
492 | and store it in a static string. Return a pointer to that string. */ | |
493 | ||
494 | char * | |
495 | floatformat_mantissa (const struct floatformat *fmt, char *val) | |
496 | { | |
497 | unsigned char *uval = (unsigned char *) val; | |
498 | unsigned long mant; | |
499 | unsigned int mant_bits, mant_off; | |
500 | int mant_bits_left; | |
501 | static char res[50]; | |
502 | char buf[9]; | |
503 | ||
504 | /* Make sure we have enough room to store the mantissa. */ | |
505 | gdb_assert (sizeof res > ((fmt->man_len + 7) / 8) * 2); | |
506 | ||
507 | mant_off = fmt->man_start; | |
508 | mant_bits_left = fmt->man_len; | |
509 | mant_bits = (mant_bits_left % 32) > 0 ? mant_bits_left % 32 : 32; | |
510 | ||
511 | mant = get_field (uval, fmt->byteorder, fmt->totalsize, | |
512 | mant_off, mant_bits); | |
513 | ||
514 | sprintf (res, "%lx", mant); | |
515 | ||
516 | mant_off += mant_bits; | |
517 | mant_bits_left -= mant_bits; | |
518 | ||
519 | while (mant_bits_left > 0) | |
520 | { | |
521 | mant = get_field (uval, fmt->byteorder, fmt->totalsize, | |
522 | mant_off, 32); | |
523 | ||
524 | sprintf (buf, "%08lx", mant); | |
525 | strcat (res, buf); | |
526 | ||
527 | mant_off += 32; | |
528 | mant_bits_left -= 32; | |
529 | } | |
530 | ||
531 | return res; | |
532 | } | |
533 | ||
534 | ||
535 | \f | |
536 | /* Extract a floating-point number from a target-order byte-stream at ADDR. | |
537 | Returns the value as type DOUBLEST. | |
538 | ||
539 | If the host and target formats agree, we just copy the raw data into the | |
540 | appropriate type of variable and return, letting the host increase precision | |
541 | as necessary. Otherwise, we call the conversion routine and let it do the | |
542 | dirty work. */ | |
543 | ||
544 | DOUBLEST | |
64f6fcad | 545 | extract_floating (const void *addr, int len) |
d16aafd8 AC |
546 | { |
547 | DOUBLEST dretval; | |
548 | ||
549 | if (len * TARGET_CHAR_BIT == TARGET_FLOAT_BIT) | |
550 | { | |
551 | if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT) | |
552 | { | |
553 | float retval; | |
554 | ||
555 | memcpy (&retval, addr, sizeof (retval)); | |
556 | return retval; | |
557 | } | |
558 | else | |
559 | floatformat_to_doublest (TARGET_FLOAT_FORMAT, addr, &dretval); | |
560 | } | |
561 | else if (len * TARGET_CHAR_BIT == TARGET_DOUBLE_BIT) | |
562 | { | |
563 | if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT) | |
564 | { | |
565 | double retval; | |
566 | ||
567 | memcpy (&retval, addr, sizeof (retval)); | |
568 | return retval; | |
569 | } | |
570 | else | |
571 | floatformat_to_doublest (TARGET_DOUBLE_FORMAT, addr, &dretval); | |
572 | } | |
573 | else if (len * TARGET_CHAR_BIT == TARGET_LONG_DOUBLE_BIT) | |
574 | { | |
575 | if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT) | |
576 | { | |
577 | DOUBLEST retval; | |
578 | ||
579 | memcpy (&retval, addr, sizeof (retval)); | |
580 | return retval; | |
581 | } | |
582 | else | |
583 | floatformat_to_doublest (TARGET_LONG_DOUBLE_FORMAT, addr, &dretval); | |
584 | } | |
585 | else | |
586 | { | |
587 | error ("Can't deal with a floating point number of %d bytes.", len); | |
588 | } | |
589 | ||
590 | return dretval; | |
591 | } | |
592 | ||
593 | void | |
594 | store_floating (void *addr, int len, DOUBLEST val) | |
595 | { | |
596 | if (len * TARGET_CHAR_BIT == TARGET_FLOAT_BIT) | |
597 | { | |
598 | if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT) | |
599 | { | |
600 | float floatval = val; | |
601 | ||
602 | memcpy (addr, &floatval, sizeof (floatval)); | |
603 | } | |
604 | else | |
605 | floatformat_from_doublest (TARGET_FLOAT_FORMAT, &val, addr); | |
606 | } | |
607 | else if (len * TARGET_CHAR_BIT == TARGET_DOUBLE_BIT) | |
608 | { | |
609 | if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT) | |
610 | { | |
611 | double doubleval = val; | |
612 | ||
613 | memcpy (addr, &doubleval, sizeof (doubleval)); | |
614 | } | |
615 | else | |
616 | floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &val, addr); | |
617 | } | |
618 | else if (len * TARGET_CHAR_BIT == TARGET_LONG_DOUBLE_BIT) | |
619 | { | |
620 | if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT) | |
621 | memcpy (addr, &val, sizeof (val)); | |
622 | else | |
623 | floatformat_from_doublest (TARGET_LONG_DOUBLE_FORMAT, &val, addr); | |
624 | } | |
625 | else | |
626 | { | |
627 | error ("Can't deal with a floating point number of %d bytes.", len); | |
628 | } | |
629 | } |