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