2003-06-14 H.J. Lu <hongjiu.lu@intel.com>
[deliverable/binutils-gdb.git] / gdb / i387-tdep.c
CommitLineData
c906108c 1/* Intel 387 floating point stuff.
38edeab8 2
dff95cc7 3 Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000,
38edeab8 4 2001, 2002, 2003 Free Software Foundation, Inc.
c906108c 5
c5aa993b 6 This file is part of GDB.
c906108c 7
c5aa993b
JM
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.
c906108c 12
c5aa993b
JM
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.
c906108c 17
c5aa993b
JM
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. */
c906108c
SS
22
23#include "defs.h"
24#include "frame.h"
25#include "inferior.h"
26#include "language.h"
d4f3574e 27#include "value.h"
c906108c
SS
28#include "gdbcore.h"
29#include "floatformat.h"
4e052eda 30#include "regcache.h"
d0df8472 31#include "gdb_assert.h"
309367d4 32#include "gdb_string.h"
d16aafd8 33#include "doublest.h"
c906108c 34
9a82579f 35#include "i386-tdep.h"
42c466d7 36#include "i387-tdep.h"
c906108c 37
de57eccd
JM
38/* Implement the `info float' layout based on the register definitions
39 in `tm-i386.h'. */
40
41/* Print the floating point number specified by RAW. */
42static void
61113f8b 43print_i387_value (char *raw, struct ui_file *file)
de57eccd
JM
44{
45 DOUBLEST value;
4583280c
MK
46
47 /* Using extract_typed_floating here might affect the representation
48 of certain numbers such as NaNs, even if GDB is running natively.
49 This is fine since our caller already detects such special
50 numbers and we print the hexadecimal representation anyway. */
51 value = extract_typed_floating (raw, builtin_type_i387_ext);
de57eccd
JM
52
53 /* We try to print 19 digits. The last digit may or may not contain
54 garbage, but we'd better print one too many. We need enough room
55 to print the value, 1 position for the sign, 1 for the decimal
56 point, 19 for the digits and 6 for the exponent adds up to 27. */
57#ifdef PRINTF_HAS_LONG_DOUBLE
61113f8b 58 fprintf_filtered (file, " %-+27.19Lg", (long double) value);
de57eccd 59#else
61113f8b 60 fprintf_filtered (file, " %-+27.19g", (double) value);
de57eccd
JM
61#endif
62}
63
64/* Print the classification for the register contents RAW. */
65static void
61113f8b 66print_i387_ext (unsigned char *raw, struct ui_file *file)
de57eccd
JM
67{
68 int sign;
69 int integer;
70 unsigned int exponent;
71 unsigned long fraction[2];
72
73 sign = raw[9] & 0x80;
74 integer = raw[7] & 0x80;
75 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
76 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
77 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
78 | (raw[5] << 8) | raw[4]);
79
80 if (exponent == 0x7fff && integer)
81 {
82 if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
83 /* Infinity. */
61113f8b 84 fprintf_filtered (file, " %cInf", (sign ? '-' : '+'));
de57eccd
JM
85 else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
86 /* Real Indefinite (QNaN). */
61113f8b 87 fputs_unfiltered (" Real Indefinite (QNaN)", file);
de57eccd
JM
88 else if (fraction[1] & 0x40000000)
89 /* QNaN. */
61113f8b 90 fputs_filtered (" QNaN", file);
de57eccd
JM
91 else
92 /* SNaN. */
61113f8b 93 fputs_filtered (" SNaN", file);
de57eccd
JM
94 }
95 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
96 /* Normal. */
61113f8b 97 print_i387_value (raw, file);
de57eccd
JM
98 else if (exponent == 0x0000)
99 {
100 /* Denormal or zero. */
61113f8b 101 print_i387_value (raw, file);
de57eccd
JM
102
103 if (integer)
104 /* Pseudo-denormal. */
61113f8b 105 fputs_filtered (" Pseudo-denormal", file);
de57eccd
JM
106 else if (fraction[0] || fraction[1])
107 /* Denormal. */
61113f8b 108 fputs_filtered (" Denormal", file);
de57eccd
JM
109 }
110 else
111 /* Unsupported. */
61113f8b 112 fputs_filtered (" Unsupported", file);
de57eccd
JM
113}
114
115/* Print the status word STATUS. */
116static void
61113f8b 117print_i387_status_word (unsigned int status, struct ui_file *file)
de57eccd 118{
61113f8b 119 fprintf_filtered (file, "Status Word: %s",
de57eccd 120 local_hex_string_custom (status, "04"));
61113f8b
MK
121 fputs_filtered (" ", file);
122 fprintf_filtered (file, " %s", (status & 0x0001) ? "IE" : " ");
123 fprintf_filtered (file, " %s", (status & 0x0002) ? "DE" : " ");
124 fprintf_filtered (file, " %s", (status & 0x0004) ? "ZE" : " ");
125 fprintf_filtered (file, " %s", (status & 0x0008) ? "OE" : " ");
126 fprintf_filtered (file, " %s", (status & 0x0010) ? "UE" : " ");
127 fprintf_filtered (file, " %s", (status & 0x0020) ? "PE" : " ");
128 fputs_filtered (" ", file);
129 fprintf_filtered (file, " %s", (status & 0x0080) ? "ES" : " ");
130 fputs_filtered (" ", file);
131 fprintf_filtered (file, " %s", (status & 0x0040) ? "SF" : " ");
132 fputs_filtered (" ", file);
133 fprintf_filtered (file, " %s", (status & 0x0100) ? "C0" : " ");
134 fprintf_filtered (file, " %s", (status & 0x0200) ? "C1" : " ");
135 fprintf_filtered (file, " %s", (status & 0x0400) ? "C2" : " ");
136 fprintf_filtered (file, " %s", (status & 0x4000) ? "C3" : " ");
137
138 fputs_filtered ("\n", file);
139
140 fprintf_filtered (file,
141 " TOP: %d\n", ((status >> 11) & 7));
de57eccd
JM
142}
143
144/* Print the control word CONTROL. */
145static void
61113f8b 146print_i387_control_word (unsigned int control, struct ui_file *file)
de57eccd 147{
61113f8b 148 fprintf_filtered (file, "Control Word: %s",
de57eccd 149 local_hex_string_custom (control, "04"));
61113f8b
MK
150 fputs_filtered (" ", file);
151 fprintf_filtered (file, " %s", (control & 0x0001) ? "IM" : " ");
152 fprintf_filtered (file, " %s", (control & 0x0002) ? "DM" : " ");
153 fprintf_filtered (file, " %s", (control & 0x0004) ? "ZM" : " ");
154 fprintf_filtered (file, " %s", (control & 0x0008) ? "OM" : " ");
155 fprintf_filtered (file, " %s", (control & 0x0010) ? "UM" : " ");
156 fprintf_filtered (file, " %s", (control & 0x0020) ? "PM" : " ");
de57eccd 157
61113f8b 158 fputs_filtered ("\n", file);
de57eccd 159
61113f8b 160 fputs_filtered (" PC: ", file);
de57eccd
JM
161 switch ((control >> 8) & 3)
162 {
163 case 0:
61113f8b 164 fputs_filtered ("Single Precision (24-bits)\n", file);
de57eccd
JM
165 break;
166 case 1:
61113f8b 167 fputs_filtered ("Reserved\n", file);
de57eccd
JM
168 break;
169 case 2:
61113f8b 170 fputs_filtered ("Double Precision (53-bits)\n", file);
de57eccd
JM
171 break;
172 case 3:
61113f8b 173 fputs_filtered ("Extended Precision (64-bits)\n", file);
de57eccd
JM
174 break;
175 }
176
61113f8b 177 fputs_filtered (" RC: ", file);
de57eccd
JM
178 switch ((control >> 10) & 3)
179 {
180 case 0:
61113f8b 181 fputs_filtered ("Round to nearest\n", file);
de57eccd
JM
182 break;
183 case 1:
61113f8b 184 fputs_filtered ("Round down\n", file);
de57eccd
JM
185 break;
186 case 2:
61113f8b 187 fputs_filtered ("Round up\n", file);
de57eccd
JM
188 break;
189 case 3:
61113f8b 190 fputs_filtered ("Round toward zero\n", file);
de57eccd
JM
191 break;
192 }
193}
194
9b949a49 195/* Print out the i387 floating point state. Note that we ignore FRAME
7d8d2918
MK
196 in the code below. That's OK since floating-point registers are
197 never saved on the stack. */
198
de57eccd 199void
61113f8b 200i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
8e186fd6 201 struct frame_info *frame, const char *args)
de57eccd 202{
1d70089a
MK
203 char buf[4];
204 ULONGEST fctrl;
205 ULONGEST fstat;
206 ULONGEST ftag;
207 ULONGEST fiseg;
208 ULONGEST fioff;
209 ULONGEST foseg;
210 ULONGEST fooff;
211 ULONGEST fop;
de57eccd
JM
212 int fpreg;
213 int top;
214
1d70089a
MK
215 frame_register_read (frame, FCTRL_REGNUM, buf);
216 fctrl = extract_unsigned_integer (buf, 4);
217 frame_register_read (frame, FSTAT_REGNUM, buf);
218 fstat = extract_unsigned_integer (buf, 4);
219 frame_register_read (frame, FTAG_REGNUM, buf);
220 ftag = extract_unsigned_integer (buf, 4);
221 frame_register_read (frame, FISEG_REGNUM, buf);
222 fiseg = extract_unsigned_integer (buf, 4);
223 frame_register_read (frame, FIOFF_REGNUM, buf);
224 fioff = extract_unsigned_integer (buf, 4);
225 frame_register_read (frame, FOSEG_REGNUM, buf);
226 foseg = extract_unsigned_integer (buf, 4);
227 frame_register_read (frame, FOOFF_REGNUM, buf);
228 fooff = extract_unsigned_integer (buf, 4);
229 frame_register_read (frame, FOP_REGNUM, buf);
230 fop = extract_unsigned_integer (buf, 4);
231
de57eccd
JM
232 top = ((fstat >> 11) & 7);
233
234 for (fpreg = 7; fpreg >= 0; fpreg--)
235 {
236 unsigned char raw[FPU_REG_RAW_SIZE];
237 int tag = (ftag >> (fpreg * 2)) & 3;
238 int i;
239
61113f8b 240 fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
de57eccd
JM
241
242 switch (tag)
243 {
244 case 0:
61113f8b 245 fputs_filtered ("Valid ", file);
de57eccd
JM
246 break;
247 case 1:
61113f8b 248 fputs_filtered ("Zero ", file);
de57eccd
JM
249 break;
250 case 2:
61113f8b 251 fputs_filtered ("Special ", file);
de57eccd
JM
252 break;
253 case 3:
61113f8b 254 fputs_filtered ("Empty ", file);
de57eccd
JM
255 break;
256 }
257
1d70089a 258 frame_register_read (frame, (fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
de57eccd 259
61113f8b 260 fputs_filtered ("0x", file);
de57eccd 261 for (i = 9; i >= 0; i--)
61113f8b 262 fprintf_filtered (file, "%02x", raw[i]);
de57eccd
JM
263
264 if (tag != 3)
61113f8b 265 print_i387_ext (raw, file);
de57eccd 266
61113f8b 267 fputs_filtered ("\n", file);
de57eccd
JM
268 }
269
f16a25ae 270 fputs_filtered ("\n", file);
de57eccd 271
61113f8b
MK
272 print_i387_status_word (fstat, file);
273 print_i387_control_word (fctrl, file);
274 fprintf_filtered (file, "Tag Word: %s\n",
275 local_hex_string_custom (ftag, "04"));
276 fprintf_filtered (file, "Instruction Pointer: %s:",
277 local_hex_string_custom (fiseg, "02"));
278 fprintf_filtered (file, "%s\n", local_hex_string_custom (fioff, "08"));
279 fprintf_filtered (file, "Operand Pointer: %s:",
280 local_hex_string_custom (foseg, "02"));
281 fprintf_filtered (file, "%s\n", local_hex_string_custom (fooff, "08"));
282 fprintf_filtered (file, "Opcode: %s\n",
283 local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
de57eccd 284}
e750d25e
JT
285
286/* FIXME: kettenis/2000-05-21: Right now more than a few i386 targets
287 define their own routines to manage the floating-point registers in
288 GDB's register array. Most (if not all) of these targets use the
289 format used by the "fsave" instruction in their communication with
290 the OS. They should all be converted to use the routines below. */
291
292/* At fsave_offset[REGNUM] you'll find the offset to the location in
293 the data structure used by the "fsave" instruction where GDB
294 register REGNUM is stored. */
295
296static int fsave_offset[] =
297{
298 28 + 0 * FPU_REG_RAW_SIZE, /* FP0_REGNUM through ... */
299 28 + 1 * FPU_REG_RAW_SIZE,
300 28 + 2 * FPU_REG_RAW_SIZE,
301 28 + 3 * FPU_REG_RAW_SIZE,
302 28 + 4 * FPU_REG_RAW_SIZE,
303 28 + 5 * FPU_REG_RAW_SIZE,
304 28 + 6 * FPU_REG_RAW_SIZE,
305 28 + 7 * FPU_REG_RAW_SIZE, /* ... FP7_REGNUM. */
306 0, /* FCTRL_REGNUM (16 bits). */
307 4, /* FSTAT_REGNUM (16 bits). */
308 8, /* FTAG_REGNUM (16 bits). */
309 16, /* FISEG_REGNUM (16 bits). */
310 12, /* FIOFF_REGNUM. */
311 24, /* FOSEG_REGNUM. */
312 20, /* FOOFF_REGNUM. */
313 18 /* FOP_REGNUM (bottom 11 bits). */
314};
315
316#define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
317\f
318
319/* Fill register REGNUM in GDB's register array with the appropriate
320 value from *FSAVE. This function masks off any of the reserved
321 bits in *FSAVE. */
322
323void
324i387_supply_register (int regnum, char *fsave)
325{
932bb524
KD
326 if (fsave == NULL)
327 {
328 supply_register (regnum, NULL);
329 return;
330 }
331
e750d25e
JT
332 /* Most of the FPU control registers occupy only 16 bits in
333 the fsave area. Give those a special treatment. */
334 if (regnum >= FPC_REGNUM
335 && regnum != FIOFF_REGNUM && regnum != FOOFF_REGNUM)
336 {
337 unsigned char val[4];
338
339 memcpy (val, FSAVE_ADDR (fsave, regnum), 2);
340 val[2] = val[3] = 0;
341 if (regnum == FOP_REGNUM)
342 val[1] &= ((1 << 3) - 1);
343 supply_register (regnum, val);
344 }
345 else
346 supply_register (regnum, FSAVE_ADDR (fsave, regnum));
347}
348
349/* Fill GDB's register array with the floating-point register values
350 in *FSAVE. This function masks off any of the reserved
351 bits in *FSAVE. */
352
353void
354i387_supply_fsave (char *fsave)
355{
356 int i;
357
358 for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
359 i387_supply_register (i, fsave);
360}
361
362/* Fill register REGNUM (if it is a floating-point register) in *FSAVE
363 with the value in GDB's register array. If REGNUM is -1, do this
364 for all registers. This function doesn't touch any of the reserved
365 bits in *FSAVE. */
366
367void
368i387_fill_fsave (char *fsave, int regnum)
369{
370 int i;
371
372 for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
373 if (regnum == -1 || regnum == i)
374 {
375 /* Most of the FPU control registers occupy only 16 bits in
376 the fsave area. Give those a special treatment. */
377 if (i >= FPC_REGNUM
378 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
379 {
380 unsigned char buf[4];
381
382 regcache_collect (i, buf);
383
384 if (i == FOP_REGNUM)
385 {
386 /* The opcode occupies only 11 bits. Make sure we
387 don't touch the other bits. */
388 buf[1] &= ((1 << 3) - 1);
389 buf[1] |= ((FSAVE_ADDR (fsave, i))[1] & ~((1 << 3) - 1));
390 }
391 memcpy (FSAVE_ADDR (fsave, i), buf, 2);
392 }
393 else
394 regcache_collect (i, FSAVE_ADDR (fsave, i));
395 }
396}
397\f
398
399/* At fxsave_offset[REGNUM] you'll find the offset to the location in
400 the data structure used by the "fxsave" instruction where GDB
401 register REGNUM is stored. */
402
403static int fxsave_offset[] =
404{
405 32, /* FP0_REGNUM through ... */
406 48,
407 64,
408 80,
409 96,
410 112,
411 128,
412 144, /* ... FP7_REGNUM (80 bits each). */
413 0, /* FCTRL_REGNUM (16 bits). */
414 2, /* FSTAT_REGNUM (16 bits). */
415 4, /* FTAG_REGNUM (16 bits). */
416 12, /* FISEG_REGNUM (16 bits). */
417 8, /* FIOFF_REGNUM. */
418 20, /* FOSEG_REGNUM (16 bits). */
419 16, /* FOOFF_REGNUM. */
420 6, /* FOP_REGNUM (bottom 11 bits). */
04c8243f
MK
421 160 + 0 * 16, /* XMM0_REGNUM through ... */
422 160 + 1 * 16,
423 160 + 2 * 16,
424 160 + 3 * 16,
425 160 + 4 * 16,
426 160 + 5 * 16,
427 160 + 6 * 16,
428 160 + 7 * 16,
429 160 + 8 * 16,
430 160 + 9 * 16,
431 160 + 10 * 16,
432 160 + 11 * 16,
433 160 + 12 * 16,
434 160 + 13 * 16,
435 160 + 14 * 16,
436 160 + 15 * 16, /* ... XMM15_REGNUM (128 bits each). */
437 24 /* MXCSR_REGNUM. */
e750d25e
JT
438};
439
04c8243f
MK
440/* FIXME: kettenis/20030430: We made an unfortunate choice in putting
441 %mxcsr after the SSE registers %xmm0-%xmm7 instead of before, since
442 it makes supporting the registers %xmm8-%xmm15 on x86-64 a bit
443 involved. Hack around it by explicitly overriding the offset for
444 %mxcsr here. */
445
e750d25e 446#define FXSAVE_ADDR(fxsave, regnum) \
04c8243f
MK
447 ((regnum == MXCSR_REGNUM) ? (fxsave + 24) : \
448 (fxsave + fxsave_offset[regnum - FP0_REGNUM]))
e750d25e
JT
449
450static int i387_tag (unsigned char *raw);
451\f
452
453/* Fill GDB's register array with the floating-point and SSE register
454 values in *FXSAVE. This function masks off any of the reserved
455 bits in *FXSAVE. */
456
457void
458i387_supply_fxsave (char *fxsave)
459{
dff95cc7
MK
460 int i, last_regnum = MXCSR_REGNUM;
461
462 if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
463 last_regnum = FOP_REGNUM;
e750d25e 464
dff95cc7 465 for (i = FP0_REGNUM; i <= last_regnum; i++)
e750d25e 466 {
932bb524
KD
467 if (fxsave == NULL)
468 {
469 supply_register (i, NULL);
470 continue;
471 }
472
e750d25e
JT
473 /* Most of the FPU control registers occupy only 16 bits in
474 the fxsave area. Give those a special treatment. */
475 if (i >= FPC_REGNUM && i < XMM0_REGNUM
476 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
477 {
478 unsigned char val[4];
479
480 memcpy (val, FXSAVE_ADDR (fxsave, i), 2);
481 val[2] = val[3] = 0;
482 if (i == FOP_REGNUM)
483 val[1] &= ((1 << 3) - 1);
484 else if (i== FTAG_REGNUM)
485 {
486 /* The fxsave area contains a simplified version of the
487 tag word. We have to look at the actual 80-bit FP
488 data to recreate the traditional i387 tag word. */
489
490 unsigned long ftag = 0;
491 int fpreg;
492 int top;
493
494 top = (((FXSAVE_ADDR (fxsave, FSTAT_REGNUM))[1] >> 3) & 0x7);
495
496 for (fpreg = 7; fpreg >= 0; fpreg--)
497 {
498 int tag;
499
500 if (val[0] & (1 << fpreg))
501 {
502 int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
503 tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
504 }
505 else
506 tag = 3; /* Empty */
507
508 ftag |= tag << (2 * fpreg);
509 }
510 val[0] = ftag & 0xff;
511 val[1] = (ftag >> 8) & 0xff;
512 }
513 supply_register (i, val);
514 }
515 else
516 supply_register (i, FXSAVE_ADDR (fxsave, i));
517 }
518}
519
520/* Fill register REGNUM (if it is a floating-point or SSE register) in
521 *FXSAVE with the value in GDB's register array. If REGNUM is -1, do
522 this for all registers. This function doesn't touch any of the
523 reserved bits in *FXSAVE. */
524
525void
526i387_fill_fxsave (char *fxsave, int regnum)
527{
dff95cc7
MK
528 int i, last_regnum = MXCSR_REGNUM;
529
530 if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
531 last_regnum = FOP_REGNUM;
e750d25e 532
dff95cc7 533 for (i = FP0_REGNUM; i <= last_regnum; i++)
e750d25e
JT
534 if (regnum == -1 || regnum == i)
535 {
536 /* Most of the FPU control registers occupy only 16 bits in
537 the fxsave area. Give those a special treatment. */
538 if (i >= FPC_REGNUM && i < XMM0_REGNUM
19e33363 539 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
e750d25e
JT
540 {
541 unsigned char buf[4];
542
543 regcache_collect (i, buf);
544
545 if (i == FOP_REGNUM)
546 {
547 /* The opcode occupies only 11 bits. Make sure we
548 don't touch the other bits. */
549 buf[1] &= ((1 << 3) - 1);
550 buf[1] |= ((FXSAVE_ADDR (fxsave, i))[1] & ~((1 << 3) - 1));
551 }
552 else if (i == FTAG_REGNUM)
553 {
554 /* Converting back is much easier. */
555
556 unsigned short ftag;
557 int fpreg;
558
559 ftag = (buf[1] << 8) | buf[0];
560 buf[0] = 0;
561 buf[1] = 0;
562
563 for (fpreg = 7; fpreg >= 0; fpreg--)
564 {
565 int tag = (ftag >> (fpreg * 2)) & 3;
566
567 if (tag != 3)
568 buf[0] |= (1 << fpreg);
569 }
570 }
571 memcpy (FXSAVE_ADDR (fxsave, i), buf, 2);
572 }
573 else
574 regcache_collect (i, FXSAVE_ADDR (fxsave, i));
575 }
576}
577
578/* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
579 *RAW. */
580
581static int
582i387_tag (unsigned char *raw)
583{
584 int integer;
585 unsigned int exponent;
586 unsigned long fraction[2];
587
588 integer = raw[7] & 0x80;
589 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
590 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
591 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
592 | (raw[5] << 8) | raw[4]);
593
594 if (exponent == 0x7fff)
595 {
596 /* Special. */
597 return (2);
598 }
599 else if (exponent == 0x0000)
600 {
601 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
602 {
603 /* Zero. */
604 return (1);
605 }
606 else
607 {
608 /* Special. */
609 return (2);
610 }
611 }
612 else
613 {
614 if (integer)
615 {
616 /* Valid. */
617 return (0);
618 }
619 else
620 {
621 /* Special. */
622 return (2);
623 }
624 }
625}
This page took 0.301989 seconds and 4 git commands to generate.