* i387-tdep.c (i387_print_float_info): Add comment about ignoring
[deliverable/binutils-gdb.git] / gdb / i387-tdep.c
1 /* Intel 387 floating point stuff.
2 Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000,
3 2001, 2002 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include "defs.h"
23 #include "frame.h"
24 #include "inferior.h"
25 #include "language.h"
26 #include "value.h"
27 #include "gdbcore.h"
28 #include "floatformat.h"
29 #include "regcache.h"
30 #include "gdb_assert.h"
31 #include "doublest.h"
32
33 #include "i386-tdep.h"
34
35 /* FIXME: Eliminate the next two functions when we have the time to
36 change all the callers. */
37
38 void i387_to_double (char *from, char *to);
39 void double_to_i387 (char *from, char *to);
40
41 void
42 i387_to_double (char *from, char *to)
43 {
44 floatformat_to_double (&floatformat_i387_ext, from, (double *) to);
45 }
46
47 void
48 double_to_i387 (char *from, char *to)
49 {
50 floatformat_from_double (&floatformat_i387_ext, (double *) from, to);
51 }
52
53 \f
54 /* FIXME: The functions on this page are used by the old `info float'
55 implementations that a few of the i386 targets provide. These
56 functions should be removed if all of these have been converted to
57 use the generic implementation based on the new register file
58 layout. */
59
60 static void print_387_control_bits (unsigned int control);
61 static void print_387_status_bits (unsigned int status);
62
63 static void
64 print_387_control_bits (unsigned int control)
65 {
66 switch ((control >> 8) & 3)
67 {
68 case 0:
69 puts_unfiltered (" 24 bit; ");
70 break;
71 case 1:
72 puts_unfiltered (" (bad); ");
73 break;
74 case 2:
75 puts_unfiltered (" 53 bit; ");
76 break;
77 case 3:
78 puts_unfiltered (" 64 bit; ");
79 break;
80 }
81 switch ((control >> 10) & 3)
82 {
83 case 0:
84 puts_unfiltered ("NEAR; ");
85 break;
86 case 1:
87 puts_unfiltered ("DOWN; ");
88 break;
89 case 2:
90 puts_unfiltered ("UP; ");
91 break;
92 case 3:
93 puts_unfiltered ("CHOP; ");
94 break;
95 }
96 if (control & 0x3f)
97 {
98 puts_unfiltered ("mask");
99 if (control & 0x0001)
100 puts_unfiltered (" INVAL");
101 if (control & 0x0002)
102 puts_unfiltered (" DENOR");
103 if (control & 0x0004)
104 puts_unfiltered (" DIVZ");
105 if (control & 0x0008)
106 puts_unfiltered (" OVERF");
107 if (control & 0x0010)
108 puts_unfiltered (" UNDER");
109 if (control & 0x0020)
110 puts_unfiltered (" LOS");
111 puts_unfiltered (";");
112 }
113
114 if (control & 0xe080)
115 warning ("\nreserved bits on: %s",
116 local_hex_string (control & 0xe080));
117 }
118
119 void
120 print_387_control_word (unsigned int control)
121 {
122 printf_filtered ("control %s:", local_hex_string(control & 0xffff));
123 print_387_control_bits (control);
124 puts_unfiltered ("\n");
125 }
126
127 static void
128 print_387_status_bits (unsigned int status)
129 {
130 printf_unfiltered (" flags %d%d%d%d; ",
131 (status & 0x4000) != 0,
132 (status & 0x0400) != 0,
133 (status & 0x0200) != 0,
134 (status & 0x0100) != 0);
135 printf_unfiltered ("top %d; ", (status >> 11) & 7);
136 if (status & 0xff)
137 {
138 puts_unfiltered ("excep");
139 if (status & 0x0001) puts_unfiltered (" INVAL");
140 if (status & 0x0002) puts_unfiltered (" DENOR");
141 if (status & 0x0004) puts_unfiltered (" DIVZ");
142 if (status & 0x0008) puts_unfiltered (" OVERF");
143 if (status & 0x0010) puts_unfiltered (" UNDER");
144 if (status & 0x0020) puts_unfiltered (" LOS");
145 if (status & 0x0040) puts_unfiltered (" STACK");
146 }
147 }
148
149 void
150 print_387_status_word (unsigned int status)
151 {
152 printf_filtered ("status %s:", local_hex_string (status & 0xffff));
153 print_387_status_bits (status);
154 puts_unfiltered ("\n");
155 }
156
157 \f
158 /* Implement the `info float' layout based on the register definitions
159 in `tm-i386.h'. */
160
161 /* Print the floating point number specified by RAW. */
162 static void
163 print_i387_value (char *raw, struct ui_file *file)
164 {
165 DOUBLEST value;
166
167 /* Using extract_typed_floating here might affect the representation
168 of certain numbers such as NaNs, even if GDB is running natively.
169 This is fine since our caller already detects such special
170 numbers and we print the hexadecimal representation anyway. */
171 value = extract_typed_floating (raw, builtin_type_i387_ext);
172
173 /* We try to print 19 digits. The last digit may or may not contain
174 garbage, but we'd better print one too many. We need enough room
175 to print the value, 1 position for the sign, 1 for the decimal
176 point, 19 for the digits and 6 for the exponent adds up to 27. */
177 #ifdef PRINTF_HAS_LONG_DOUBLE
178 fprintf_filtered (file, " %-+27.19Lg", (long double) value);
179 #else
180 fprintf_filtered (file, " %-+27.19g", (double) value);
181 #endif
182 }
183
184 /* Print the classification for the register contents RAW. */
185 static void
186 print_i387_ext (unsigned char *raw, struct ui_file *file)
187 {
188 int sign;
189 int integer;
190 unsigned int exponent;
191 unsigned long fraction[2];
192
193 sign = raw[9] & 0x80;
194 integer = raw[7] & 0x80;
195 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
196 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
197 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
198 | (raw[5] << 8) | raw[4]);
199
200 if (exponent == 0x7fff && integer)
201 {
202 if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
203 /* Infinity. */
204 fprintf_filtered (file, " %cInf", (sign ? '-' : '+'));
205 else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
206 /* Real Indefinite (QNaN). */
207 fputs_unfiltered (" Real Indefinite (QNaN)", file);
208 else if (fraction[1] & 0x40000000)
209 /* QNaN. */
210 fputs_filtered (" QNaN", file);
211 else
212 /* SNaN. */
213 fputs_filtered (" SNaN", file);
214 }
215 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
216 /* Normal. */
217 print_i387_value (raw, file);
218 else if (exponent == 0x0000)
219 {
220 /* Denormal or zero. */
221 print_i387_value (raw, file);
222
223 if (integer)
224 /* Pseudo-denormal. */
225 fputs_filtered (" Pseudo-denormal", file);
226 else if (fraction[0] || fraction[1])
227 /* Denormal. */
228 fputs_filtered (" Denormal", file);
229 }
230 else
231 /* Unsupported. */
232 fputs_filtered (" Unsupported", file);
233 }
234
235 /* Print the status word STATUS. */
236 static void
237 print_i387_status_word (unsigned int status, struct ui_file *file)
238 {
239 fprintf_filtered (file, "Status Word: %s",
240 local_hex_string_custom (status, "04"));
241 fputs_filtered (" ", file);
242 fprintf_filtered (file, " %s", (status & 0x0001) ? "IE" : " ");
243 fprintf_filtered (file, " %s", (status & 0x0002) ? "DE" : " ");
244 fprintf_filtered (file, " %s", (status & 0x0004) ? "ZE" : " ");
245 fprintf_filtered (file, " %s", (status & 0x0008) ? "OE" : " ");
246 fprintf_filtered (file, " %s", (status & 0x0010) ? "UE" : " ");
247 fprintf_filtered (file, " %s", (status & 0x0020) ? "PE" : " ");
248 fputs_filtered (" ", file);
249 fprintf_filtered (file, " %s", (status & 0x0080) ? "ES" : " ");
250 fputs_filtered (" ", file);
251 fprintf_filtered (file, " %s", (status & 0x0040) ? "SF" : " ");
252 fputs_filtered (" ", file);
253 fprintf_filtered (file, " %s", (status & 0x0100) ? "C0" : " ");
254 fprintf_filtered (file, " %s", (status & 0x0200) ? "C1" : " ");
255 fprintf_filtered (file, " %s", (status & 0x0400) ? "C2" : " ");
256 fprintf_filtered (file, " %s", (status & 0x4000) ? "C3" : " ");
257
258 fputs_filtered ("\n", file);
259
260 fprintf_filtered (file,
261 " TOP: %d\n", ((status >> 11) & 7));
262 }
263
264 /* Print the control word CONTROL. */
265 static void
266 print_i387_control_word (unsigned int control, struct ui_file *file)
267 {
268 fprintf_filtered (file, "Control Word: %s",
269 local_hex_string_custom (control, "04"));
270 fputs_filtered (" ", file);
271 fprintf_filtered (file, " %s", (control & 0x0001) ? "IM" : " ");
272 fprintf_filtered (file, " %s", (control & 0x0002) ? "DM" : " ");
273 fprintf_filtered (file, " %s", (control & 0x0004) ? "ZM" : " ");
274 fprintf_filtered (file, " %s", (control & 0x0008) ? "OM" : " ");
275 fprintf_filtered (file, " %s", (control & 0x0010) ? "UM" : " ");
276 fprintf_filtered (file, " %s", (control & 0x0020) ? "PM" : " ");
277
278 fputs_filtered ("\n", file);
279
280 fputs_filtered (" PC: ", file);
281 switch ((control >> 8) & 3)
282 {
283 case 0:
284 fputs_filtered ("Single Precision (24-bits)\n", file);
285 break;
286 case 1:
287 fputs_filtered ("Reserved\n", file);
288 break;
289 case 2:
290 fputs_filtered ("Double Precision (53-bits)\n", file);
291 break;
292 case 3:
293 fputs_filtered ("Extended Precision (64-bits)\n", file);
294 break;
295 }
296
297 fputs_filtered (" RC: ", file);
298 switch ((control >> 10) & 3)
299 {
300 case 0:
301 fputs_filtered ("Round to nearest\n", file);
302 break;
303 case 1:
304 fputs_filtered ("Round down\n", file);
305 break;
306 case 2:
307 fputs_filtered ("Round up\n", file);
308 break;
309 case 3:
310 fputs_filtered ("Round toward zero\n", file);
311 break;
312 }
313 }
314
315 /* Print out the i387 floating poin state. Note that we ignore FRAME
316 in the code below. That's OK since floating-point registers are
317 never saved on the stack. */
318
319 void
320 i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
321 struct frame_info *frame)
322 {
323 unsigned int fctrl;
324 unsigned int fstat;
325 unsigned int ftag;
326 unsigned int fiseg;
327 unsigned int fioff;
328 unsigned int foseg;
329 unsigned int fooff;
330 unsigned int fop;
331 int fpreg;
332 int top;
333
334 fctrl = read_register (FCTRL_REGNUM);
335 fstat = read_register (FSTAT_REGNUM);
336 ftag = read_register (FTAG_REGNUM);
337 fiseg = read_register (FCS_REGNUM);
338 fioff = read_register (FCOFF_REGNUM);
339 foseg = read_register (FDS_REGNUM);
340 fooff = read_register (FDOFF_REGNUM);
341 fop = read_register (FOP_REGNUM);
342
343 top = ((fstat >> 11) & 7);
344
345 for (fpreg = 7; fpreg >= 0; fpreg--)
346 {
347 unsigned char raw[FPU_REG_RAW_SIZE];
348 int tag = (ftag >> (fpreg * 2)) & 3;
349 int i;
350
351 fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
352
353 switch (tag)
354 {
355 case 0:
356 fputs_filtered ("Valid ", file);
357 break;
358 case 1:
359 fputs_filtered ("Zero ", file);
360 break;
361 case 2:
362 fputs_filtered ("Special ", file);
363 break;
364 case 3:
365 fputs_filtered ("Empty ", file);
366 break;
367 }
368
369 read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
370
371 fputs_filtered ("0x", file);
372 for (i = 9; i >= 0; i--)
373 fprintf_filtered (file, "%02x", raw[i]);
374
375 if (tag != 3)
376 print_i387_ext (raw, file);
377
378 fputs_filtered ("\n", file);
379 }
380
381 puts_filtered ("\n");
382
383 print_i387_status_word (fstat, file);
384 print_i387_control_word (fctrl, file);
385 fprintf_filtered (file, "Tag Word: %s\n",
386 local_hex_string_custom (ftag, "04"));
387 fprintf_filtered (file, "Instruction Pointer: %s:",
388 local_hex_string_custom (fiseg, "02"));
389 fprintf_filtered (file, "%s\n", local_hex_string_custom (fioff, "08"));
390 fprintf_filtered (file, "Operand Pointer: %s:",
391 local_hex_string_custom (foseg, "02"));
392 fprintf_filtered (file, "%s\n", local_hex_string_custom (fooff, "08"));
393 fprintf_filtered (file, "Opcode: %s\n",
394 local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
395 }
396
397 /* FIXME: kettenis/2000-05-21: Right now more than a few i386 targets
398 define their own routines to manage the floating-point registers in
399 GDB's register array. Most (if not all) of these targets use the
400 format used by the "fsave" instruction in their communication with
401 the OS. They should all be converted to use the routines below. */
402
403 /* At fsave_offset[REGNUM] you'll find the offset to the location in
404 the data structure used by the "fsave" instruction where GDB
405 register REGNUM is stored. */
406
407 static int fsave_offset[] =
408 {
409 28 + 0 * FPU_REG_RAW_SIZE, /* FP0_REGNUM through ... */
410 28 + 1 * FPU_REG_RAW_SIZE,
411 28 + 2 * FPU_REG_RAW_SIZE,
412 28 + 3 * FPU_REG_RAW_SIZE,
413 28 + 4 * FPU_REG_RAW_SIZE,
414 28 + 5 * FPU_REG_RAW_SIZE,
415 28 + 6 * FPU_REG_RAW_SIZE,
416 28 + 7 * FPU_REG_RAW_SIZE, /* ... FP7_REGNUM. */
417 0, /* FCTRL_REGNUM (16 bits). */
418 4, /* FSTAT_REGNUM (16 bits). */
419 8, /* FTAG_REGNUM (16 bits). */
420 16, /* FISEG_REGNUM (16 bits). */
421 12, /* FIOFF_REGNUM. */
422 24, /* FOSEG_REGNUM. */
423 20, /* FOOFF_REGNUM. */
424 18 /* FOP_REGNUM (bottom 11 bits). */
425 };
426
427 #define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
428 \f
429
430 /* Fill register REGNUM in GDB's register array with the appropriate
431 value from *FSAVE. This function masks off any of the reserved
432 bits in *FSAVE. */
433
434 void
435 i387_supply_register (int regnum, char *fsave)
436 {
437 /* Most of the FPU control registers occupy only 16 bits in
438 the fsave area. Give those a special treatment. */
439 if (regnum >= FPC_REGNUM
440 && regnum != FIOFF_REGNUM && regnum != FOOFF_REGNUM)
441 {
442 unsigned char val[4];
443
444 memcpy (val, FSAVE_ADDR (fsave, regnum), 2);
445 val[2] = val[3] = 0;
446 if (regnum == FOP_REGNUM)
447 val[1] &= ((1 << 3) - 1);
448 supply_register (regnum, val);
449 }
450 else
451 supply_register (regnum, FSAVE_ADDR (fsave, regnum));
452 }
453
454 /* Fill GDB's register array with the floating-point register values
455 in *FSAVE. This function masks off any of the reserved
456 bits in *FSAVE. */
457
458 void
459 i387_supply_fsave (char *fsave)
460 {
461 int i;
462
463 for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
464 i387_supply_register (i, fsave);
465 }
466
467 /* Fill register REGNUM (if it is a floating-point register) in *FSAVE
468 with the value in GDB's register array. If REGNUM is -1, do this
469 for all registers. This function doesn't touch any of the reserved
470 bits in *FSAVE. */
471
472 void
473 i387_fill_fsave (char *fsave, int regnum)
474 {
475 int i;
476
477 for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
478 if (regnum == -1 || regnum == i)
479 {
480 /* Most of the FPU control registers occupy only 16 bits in
481 the fsave area. Give those a special treatment. */
482 if (i >= FPC_REGNUM
483 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
484 {
485 unsigned char buf[4];
486
487 regcache_collect (i, buf);
488
489 if (i == FOP_REGNUM)
490 {
491 /* The opcode occupies only 11 bits. Make sure we
492 don't touch the other bits. */
493 buf[1] &= ((1 << 3) - 1);
494 buf[1] |= ((FSAVE_ADDR (fsave, i))[1] & ~((1 << 3) - 1));
495 }
496 memcpy (FSAVE_ADDR (fsave, i), buf, 2);
497 }
498 else
499 regcache_collect (i, FSAVE_ADDR (fsave, i));
500 }
501 }
502 \f
503
504 /* At fxsave_offset[REGNUM] you'll find the offset to the location in
505 the data structure used by the "fxsave" instruction where GDB
506 register REGNUM is stored. */
507
508 static int fxsave_offset[] =
509 {
510 32, /* FP0_REGNUM through ... */
511 48,
512 64,
513 80,
514 96,
515 112,
516 128,
517 144, /* ... FP7_REGNUM (80 bits each). */
518 0, /* FCTRL_REGNUM (16 bits). */
519 2, /* FSTAT_REGNUM (16 bits). */
520 4, /* FTAG_REGNUM (16 bits). */
521 12, /* FISEG_REGNUM (16 bits). */
522 8, /* FIOFF_REGNUM. */
523 20, /* FOSEG_REGNUM (16 bits). */
524 16, /* FOOFF_REGNUM. */
525 6, /* FOP_REGNUM (bottom 11 bits). */
526 160, /* XMM0_REGNUM through ... */
527 176,
528 192,
529 208,
530 224,
531 240,
532 256,
533 272, /* ... XMM7_REGNUM (128 bits each). */
534 24, /* MXCSR_REGNUM. */
535 };
536
537 #define FXSAVE_ADDR(fxsave, regnum) \
538 (fxsave + fxsave_offset[regnum - FP0_REGNUM])
539
540 static int i387_tag (unsigned char *raw);
541 \f
542
543 /* Fill GDB's register array with the floating-point and SSE register
544 values in *FXSAVE. This function masks off any of the reserved
545 bits in *FXSAVE. */
546
547 void
548 i387_supply_fxsave (char *fxsave)
549 {
550 int i, last_regnum = MXCSR_REGNUM;
551
552 if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
553 last_regnum = FOP_REGNUM;
554
555 for (i = FP0_REGNUM; i <= last_regnum; i++)
556 {
557 /* Most of the FPU control registers occupy only 16 bits in
558 the fxsave area. Give those a special treatment. */
559 if (i >= FPC_REGNUM && i < XMM0_REGNUM
560 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
561 {
562 unsigned char val[4];
563
564 memcpy (val, FXSAVE_ADDR (fxsave, i), 2);
565 val[2] = val[3] = 0;
566 if (i == FOP_REGNUM)
567 val[1] &= ((1 << 3) - 1);
568 else if (i== FTAG_REGNUM)
569 {
570 /* The fxsave area contains a simplified version of the
571 tag word. We have to look at the actual 80-bit FP
572 data to recreate the traditional i387 tag word. */
573
574 unsigned long ftag = 0;
575 int fpreg;
576 int top;
577
578 top = (((FXSAVE_ADDR (fxsave, FSTAT_REGNUM))[1] >> 3) & 0x7);
579
580 for (fpreg = 7; fpreg >= 0; fpreg--)
581 {
582 int tag;
583
584 if (val[0] & (1 << fpreg))
585 {
586 int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
587 tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
588 }
589 else
590 tag = 3; /* Empty */
591
592 ftag |= tag << (2 * fpreg);
593 }
594 val[0] = ftag & 0xff;
595 val[1] = (ftag >> 8) & 0xff;
596 }
597 supply_register (i, val);
598 }
599 else
600 supply_register (i, FXSAVE_ADDR (fxsave, i));
601 }
602 }
603
604 /* Fill register REGNUM (if it is a floating-point or SSE register) in
605 *FXSAVE with the value in GDB's register array. If REGNUM is -1, do
606 this for all registers. This function doesn't touch any of the
607 reserved bits in *FXSAVE. */
608
609 void
610 i387_fill_fxsave (char *fxsave, int regnum)
611 {
612 int i, last_regnum = MXCSR_REGNUM;
613
614 if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
615 last_regnum = FOP_REGNUM;
616
617 for (i = FP0_REGNUM; i <= last_regnum; i++)
618 if (regnum == -1 || regnum == i)
619 {
620 /* Most of the FPU control registers occupy only 16 bits in
621 the fxsave area. Give those a special treatment. */
622 if (i >= FPC_REGNUM && i < XMM0_REGNUM
623 && i != FIOFF_REGNUM && i != FDOFF_REGNUM)
624 {
625 unsigned char buf[4];
626
627 regcache_collect (i, buf);
628
629 if (i == FOP_REGNUM)
630 {
631 /* The opcode occupies only 11 bits. Make sure we
632 don't touch the other bits. */
633 buf[1] &= ((1 << 3) - 1);
634 buf[1] |= ((FXSAVE_ADDR (fxsave, i))[1] & ~((1 << 3) - 1));
635 }
636 else if (i == FTAG_REGNUM)
637 {
638 /* Converting back is much easier. */
639
640 unsigned short ftag;
641 int fpreg;
642
643 ftag = (buf[1] << 8) | buf[0];
644 buf[0] = 0;
645 buf[1] = 0;
646
647 for (fpreg = 7; fpreg >= 0; fpreg--)
648 {
649 int tag = (ftag >> (fpreg * 2)) & 3;
650
651 if (tag != 3)
652 buf[0] |= (1 << fpreg);
653 }
654 }
655 memcpy (FXSAVE_ADDR (fxsave, i), buf, 2);
656 }
657 else
658 regcache_collect (i, FXSAVE_ADDR (fxsave, i));
659 }
660 }
661
662 /* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
663 *RAW. */
664
665 static int
666 i387_tag (unsigned char *raw)
667 {
668 int integer;
669 unsigned int exponent;
670 unsigned long fraction[2];
671
672 integer = raw[7] & 0x80;
673 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
674 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
675 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
676 | (raw[5] << 8) | raw[4]);
677
678 if (exponent == 0x7fff)
679 {
680 /* Special. */
681 return (2);
682 }
683 else if (exponent == 0x0000)
684 {
685 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
686 {
687 /* Zero. */
688 return (1);
689 }
690 else
691 {
692 /* Special. */
693 return (2);
694 }
695 }
696 else
697 {
698 if (integer)
699 {
700 /* Valid. */
701 return (0);
702 }
703 else
704 {
705 /* Special. */
706 return (2);
707 }
708 }
709 }
This page took 0.057053 seconds and 4 git commands to generate.