OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [i387-tdep.c] - Blame information for rev 1773

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.