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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [i387-tdep.c] - Blame information for rev 833

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

Line No. Rev Author Line
1 227 jeremybenn
/* Intel 387 floating point stuff.
2
 
3
   Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000, 2001,
4
   2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
5
   Free Software Foundation, Inc.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
 
22
#include "defs.h"
23
#include "doublest.h"
24
#include "floatformat.h"
25
#include "frame.h"
26
#include "gdbcore.h"
27
#include "inferior.h"
28
#include "language.h"
29
#include "regcache.h"
30
#include "value.h"
31
 
32
#include "gdb_assert.h"
33
#include "gdb_string.h"
34
 
35
#include "i386-tdep.h"
36
#include "i387-tdep.h"
37
 
38
/* Print the floating point number specified by RAW.  */
39
 
40
static void
41
print_i387_value (struct gdbarch *gdbarch,
42
                  const gdb_byte *raw, struct ui_file *file)
43
{
44
  DOUBLEST value;
45
 
46
  /* Using extract_typed_floating here might affect the representation
47
     of certain numbers such as NaNs, even if GDB is running natively.
48
     This is fine since our caller already detects such special
49
     numbers and we print the hexadecimal representation anyway.  */
50
  value = extract_typed_floating (raw, i387_ext_type (gdbarch));
51
 
52
  /* We try to print 19 digits.  The last digit may or may not contain
53
     garbage, but we'd better print one too many.  We need enough room
54
     to print the value, 1 position for the sign, 1 for the decimal
55
     point, 19 for the digits and 6 for the exponent adds up to 27.  */
56
#ifdef PRINTF_HAS_LONG_DOUBLE
57
  fprintf_filtered (file, " %-+27.19Lg", (long double) value);
58
#else
59
  fprintf_filtered (file, " %-+27.19g", (double) value);
60
#endif
61
}
62
 
63
/* Print the classification for the register contents RAW.  */
64
 
65
static void
66
print_i387_ext (struct gdbarch *gdbarch,
67
                const gdb_byte *raw, struct ui_file *file)
68
{
69
  int sign;
70
  int integer;
71
  unsigned int exponent;
72
  unsigned long fraction[2];
73
 
74
  sign = raw[9] & 0x80;
75
  integer = raw[7] & 0x80;
76
  exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
77
  fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
78
  fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
79
                 | (raw[5] << 8) | raw[4]);
80
 
81
  if (exponent == 0x7fff && integer)
82
    {
83
      if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
84
        /* Infinity.  */
85
        fprintf_filtered (file, " %cInf", (sign ? '-' : '+'));
86
      else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
87
        /* Real Indefinite (QNaN).  */
88
        fputs_unfiltered (" Real Indefinite (QNaN)", file);
89
      else if (fraction[1] & 0x40000000)
90
        /* QNaN.  */
91
        fputs_filtered (" QNaN", file);
92
      else
93
        /* SNaN.  */
94
        fputs_filtered (" SNaN", file);
95
    }
96
  else if (exponent < 0x7fff && exponent > 0x0000 && integer)
97
    /* Normal.  */
98
    print_i387_value (gdbarch, raw, file);
99
  else if (exponent == 0x0000)
100
    {
101
      /* Denormal or zero.  */
102
      print_i387_value (gdbarch, raw, file);
103
 
104
      if (integer)
105
        /* Pseudo-denormal.  */
106
        fputs_filtered (" Pseudo-denormal", file);
107
      else if (fraction[0] || fraction[1])
108
        /* Denormal.  */
109
        fputs_filtered (" Denormal", file);
110
    }
111
  else
112
    /* Unsupported.  */
113
    fputs_filtered (" Unsupported", file);
114
}
115
 
116
/* Print the status word STATUS.  */
117
 
118
static void
119
print_i387_status_word (unsigned int status, struct ui_file *file)
120
{
121
  fprintf_filtered (file, "Status Word:         %s",
122
                    hex_string_custom (status, 4));
123
  fputs_filtered ("  ", file);
124
  fprintf_filtered (file, " %s", (status & 0x0001) ? "IE" : "  ");
125
  fprintf_filtered (file, " %s", (status & 0x0002) ? "DE" : "  ");
126
  fprintf_filtered (file, " %s", (status & 0x0004) ? "ZE" : "  ");
127
  fprintf_filtered (file, " %s", (status & 0x0008) ? "OE" : "  ");
128
  fprintf_filtered (file, " %s", (status & 0x0010) ? "UE" : "  ");
129
  fprintf_filtered (file, " %s", (status & 0x0020) ? "PE" : "  ");
130
  fputs_filtered ("  ", file);
131
  fprintf_filtered (file, " %s", (status & 0x0080) ? "ES" : "  ");
132
  fputs_filtered ("  ", file);
133
  fprintf_filtered (file, " %s", (status & 0x0040) ? "SF" : "  ");
134
  fputs_filtered ("  ", file);
135
  fprintf_filtered (file, " %s", (status & 0x0100) ? "C0" : "  ");
136
  fprintf_filtered (file, " %s", (status & 0x0200) ? "C1" : "  ");
137
  fprintf_filtered (file, " %s", (status & 0x0400) ? "C2" : "  ");
138
  fprintf_filtered (file, " %s", (status & 0x4000) ? "C3" : "  ");
139
 
140
  fputs_filtered ("\n", file);
141
 
142
  fprintf_filtered (file,
143
                    "                       TOP: %d\n", ((status >> 11) & 7));
144
}
145
 
146
/* Print the control word CONTROL.  */
147
 
148
static void
149
print_i387_control_word (unsigned int control, struct ui_file *file)
150
{
151
  fprintf_filtered (file, "Control Word:        %s",
152
                    hex_string_custom (control, 4));
153
  fputs_filtered ("  ", file);
154
  fprintf_filtered (file, " %s", (control & 0x0001) ? "IM" : "  ");
155
  fprintf_filtered (file, " %s", (control & 0x0002) ? "DM" : "  ");
156
  fprintf_filtered (file, " %s", (control & 0x0004) ? "ZM" : "  ");
157
  fprintf_filtered (file, " %s", (control & 0x0008) ? "OM" : "  ");
158
  fprintf_filtered (file, " %s", (control & 0x0010) ? "UM" : "  ");
159
  fprintf_filtered (file, " %s", (control & 0x0020) ? "PM" : "  ");
160
 
161
  fputs_filtered ("\n", file);
162
 
163
  fputs_filtered ("                       PC: ", file);
164
  switch ((control >> 8) & 3)
165
    {
166
    case 0:
167
      fputs_filtered ("Single Precision (24-bits)\n", file);
168
      break;
169
    case 1:
170
      fputs_filtered ("Reserved\n", file);
171
      break;
172
    case 2:
173
      fputs_filtered ("Double Precision (53-bits)\n", file);
174
      break;
175
    case 3:
176
      fputs_filtered ("Extended Precision (64-bits)\n", file);
177
      break;
178
    }
179
 
180
  fputs_filtered ("                       RC: ", file);
181
  switch ((control >> 10) & 3)
182
    {
183
    case 0:
184
      fputs_filtered ("Round to nearest\n", file);
185
      break;
186
    case 1:
187
      fputs_filtered ("Round down\n", file);
188
      break;
189
    case 2:
190
      fputs_filtered ("Round up\n", file);
191
      break;
192
    case 3:
193
      fputs_filtered ("Round toward zero\n", file);
194
      break;
195
    }
196
}
197
 
198
/* Print out the i387 floating point state.  Note that we ignore FRAME
199
   in the code below.  That's OK since floating-point registers are
200
   never saved on the stack.  */
201
 
202
void
203
i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
204
                       struct frame_info *frame, const char *args)
205
{
206
  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
207
  gdb_byte buf[4];
208
  ULONGEST fctrl;
209
  ULONGEST fstat;
210
  ULONGEST ftag;
211
  ULONGEST fiseg;
212
  ULONGEST fioff;
213
  ULONGEST foseg;
214
  ULONGEST fooff;
215
  ULONGEST fop;
216
  int fpreg;
217
  int top;
218
 
219
  gdb_assert (gdbarch == get_frame_arch (frame));
220
 
221
  fctrl = get_frame_register_unsigned (frame, I387_FCTRL_REGNUM (tdep));
222
  fstat = get_frame_register_unsigned (frame, I387_FSTAT_REGNUM (tdep));
223
  ftag = get_frame_register_unsigned (frame, I387_FTAG_REGNUM (tdep));
224
  fiseg = get_frame_register_unsigned (frame, I387_FISEG_REGNUM (tdep));
225
  fioff = get_frame_register_unsigned (frame, I387_FIOFF_REGNUM (tdep));
226
  foseg = get_frame_register_unsigned (frame, I387_FOSEG_REGNUM (tdep));
227
  fooff = get_frame_register_unsigned (frame, I387_FOOFF_REGNUM (tdep));
228
  fop = get_frame_register_unsigned (frame, I387_FOP_REGNUM (tdep));
229
 
230
  top = ((fstat >> 11) & 7);
231
 
232
  for (fpreg = 7; fpreg >= 0; fpreg--)
233
    {
234
      gdb_byte raw[I386_MAX_REGISTER_SIZE];
235
      int tag = (ftag >> (fpreg * 2)) & 3;
236
      int i;
237
 
238
      fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : "  ", fpreg);
239
 
240
      switch (tag)
241
        {
242
        case 0:
243
          fputs_filtered ("Valid   ", file);
244
          break;
245
        case 1:
246
          fputs_filtered ("Zero    ", file);
247
          break;
248
        case 2:
249
          fputs_filtered ("Special ", file);
250
          break;
251
        case 3:
252
          fputs_filtered ("Empty   ", file);
253
          break;
254
        }
255
 
256
      get_frame_register (frame, (fpreg + 8 - top) % 8 + I387_ST0_REGNUM (tdep),
257
                          raw);
258
 
259
      fputs_filtered ("0x", file);
260
      for (i = 9; i >= 0; i--)
261
        fprintf_filtered (file, "%02x", raw[i]);
262
 
263
      if (tag != 3)
264
        print_i387_ext (gdbarch, raw, file);
265
 
266
      fputs_filtered ("\n", file);
267
    }
268
 
269
  fputs_filtered ("\n", file);
270
 
271
  print_i387_status_word (fstat, file);
272
  print_i387_control_word (fctrl, file);
273
  fprintf_filtered (file, "Tag Word:            %s\n",
274
                    hex_string_custom (ftag, 4));
275
  fprintf_filtered (file, "Instruction Pointer: %s:",
276
                    hex_string_custom (fiseg, 2));
277
  fprintf_filtered (file, "%s\n", hex_string_custom (fioff, 8));
278
  fprintf_filtered (file, "Operand Pointer:     %s:",
279
                    hex_string_custom (foseg, 2));
280
  fprintf_filtered (file, "%s\n", hex_string_custom (fooff, 8));
281
  fprintf_filtered (file, "Opcode:              %s\n",
282
                    hex_string_custom (fop ? (fop | 0xd800) : 0, 4));
283
}
284
 
285
 
286
/* Return nonzero if a value of type TYPE stored in register REGNUM
287
   needs any special handling.  */
288
 
289
int
290
i387_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
291
{
292
  if (i386_fp_regnum_p (gdbarch, regnum))
293
    {
294
      /* Floating point registers must be converted unless we are
295
         accessing them in their hardware type.  */
296
      if (type == i387_ext_type (gdbarch))
297
        return 0;
298
      else
299
        return 1;
300
    }
301
 
302
  return 0;
303
}
304
 
305
/* Read a value of type TYPE from register REGNUM in frame FRAME, and
306
   return its contents in TO.  */
307
 
308
void
309
i387_register_to_value (struct frame_info *frame, int regnum,
310
                        struct type *type, gdb_byte *to)
311
{
312
  struct gdbarch *gdbarch = get_frame_arch (frame);
313
  gdb_byte from[I386_MAX_REGISTER_SIZE];
314
 
315
  gdb_assert (i386_fp_regnum_p (gdbarch, regnum));
316
 
317
  /* We only support floating-point values.  */
318
  if (TYPE_CODE (type) != TYPE_CODE_FLT)
319
    {
320
      warning (_("Cannot convert floating-point register value "
321
               "to non-floating-point type."));
322
      return;
323
    }
324
 
325
  /* Convert to TYPE.  */
326
  get_frame_register (frame, regnum, from);
327
  convert_typed_floating (from, i387_ext_type (gdbarch), to, type);
328
}
329
 
330
/* Write the contents FROM of a value of type TYPE into register
331
   REGNUM in frame FRAME.  */
332
 
333
void
334
i387_value_to_register (struct frame_info *frame, int regnum,
335
                        struct type *type, const gdb_byte *from)
336
{
337
  struct gdbarch *gdbarch = get_frame_arch (frame);
338
  gdb_byte to[I386_MAX_REGISTER_SIZE];
339
 
340
  gdb_assert (i386_fp_regnum_p (gdbarch, regnum));
341
 
342
  /* We only support floating-point values.  */
343
  if (TYPE_CODE (type) != TYPE_CODE_FLT)
344
    {
345
      warning (_("Cannot convert non-floating-point type "
346
               "to floating-point register value."));
347
      return;
348
    }
349
 
350
  /* Convert from TYPE.  */
351
  convert_typed_floating (from, type, to, i387_ext_type (gdbarch));
352
  put_frame_register (frame, regnum, to);
353
}
354
 
355
 
356
/* Handle FSAVE and FXSAVE formats.  */
357
 
358
/* At fsave_offset[REGNUM] you'll find the offset to the location in
359
   the data structure used by the "fsave" instruction where GDB
360
   register REGNUM is stored.  */
361
 
362
static int fsave_offset[] =
363
{
364
  28 + 0 * 10,                   /* %st(0) ...  */
365
  28 + 1 * 10,
366
  28 + 2 * 10,
367
  28 + 3 * 10,
368
  28 + 4 * 10,
369
  28 + 5 * 10,
370
  28 + 6 * 10,
371
  28 + 7 * 10,                  /* ... %st(7).  */
372
  0,                             /* `fctrl' (16 bits).  */
373
  4,                            /* `fstat' (16 bits).  */
374
  8,                            /* `ftag' (16 bits).  */
375
  16,                           /* `fiseg' (16 bits).  */
376
  12,                           /* `fioff'.  */
377
  24,                           /* `foseg' (16 bits).  */
378
  20,                           /* `fooff'.  */
379
  18                            /* `fop' (bottom 11 bits).  */
380
};
381
 
382
#define FSAVE_ADDR(tdep, fsave, regnum) \
383
  (fsave + fsave_offset[regnum - I387_ST0_REGNUM (tdep)])
384
 
385
 
386
/* Fill register REGNUM in REGCACHE with the appropriate value from
387
   *FSAVE.  This function masks off any of the reserved bits in
388
   *FSAVE.  */
389
 
390
void
391
i387_supply_fsave (struct regcache *regcache, int regnum, const void *fsave)
392
{
393
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
394
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
395
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
396
  const gdb_byte *regs = fsave;
397
  int i;
398
 
399
  gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
400
 
401
  for (i = I387_ST0_REGNUM (tdep); i < I387_XMM0_REGNUM (tdep); i++)
402
    if (regnum == -1 || regnum == i)
403
      {
404
        if (fsave == NULL)
405
          {
406
            regcache_raw_supply (regcache, i, NULL);
407
            continue;
408
          }
409
 
410
        /* Most of the FPU control registers occupy only 16 bits in the
411
           fsave area.  Give those a special treatment.  */
412
        if (i >= I387_FCTRL_REGNUM (tdep)
413
            && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
414
          {
415
            gdb_byte val[4];
416
 
417
            memcpy (val, FSAVE_ADDR (tdep, regs, i), 2);
418
            val[2] = val[3] = 0;
419
            if (i == I387_FOP_REGNUM (tdep))
420
              val[1] &= ((1 << 3) - 1);
421
            regcache_raw_supply (regcache, i, val);
422
          }
423
        else
424
          regcache_raw_supply (regcache, i, FSAVE_ADDR (tdep, regs, i));
425
      }
426
 
427
  /* Provide dummy values for the SSE registers.  */
428
  for (i = I387_XMM0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
429
    if (regnum == -1 || regnum == i)
430
      regcache_raw_supply (regcache, i, NULL);
431
  if (regnum == -1 || regnum == I387_MXCSR_REGNUM (tdep))
432
    {
433
      gdb_byte buf[4];
434
 
435
      store_unsigned_integer (buf, 4, byte_order, 0x1f80);
436
      regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep), buf);
437
    }
438
}
439
 
440
/* Fill register REGNUM (if it is a floating-point register) in *FSAVE
441
   with the value from REGCACHE.  If REGNUM is -1, do this for all
442
   registers.  This function doesn't touch any of the reserved bits in
443
   *FSAVE.  */
444
 
445
void
446
i387_collect_fsave (const struct regcache *regcache, int regnum, void *fsave)
447
{
448
  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
449
  gdb_byte *regs = fsave;
450
  int i;
451
 
452
  gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
453
 
454
  for (i = I387_ST0_REGNUM (tdep); i < I387_XMM0_REGNUM (tdep); i++)
455
    if (regnum == -1 || regnum == i)
456
      {
457
        /* Most of the FPU control registers occupy only 16 bits in
458
           the fsave area.  Give those a special treatment.  */
459
        if (i >= I387_FCTRL_REGNUM (tdep)
460
            && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
461
          {
462
            gdb_byte buf[4];
463
 
464
            regcache_raw_collect (regcache, i, buf);
465
 
466
            if (i == I387_FOP_REGNUM (tdep))
467
              {
468
                /* The opcode occupies only 11 bits.  Make sure we
469
                   don't touch the other bits.  */
470
                buf[1] &= ((1 << 3) - 1);
471
                buf[1] |= ((FSAVE_ADDR (tdep, regs, i))[1] & ~((1 << 3) - 1));
472
              }
473
            memcpy (FSAVE_ADDR (tdep, regs, i), buf, 2);
474
          }
475
        else
476
          regcache_raw_collect (regcache, i, FSAVE_ADDR (tdep, regs, i));
477
      }
478
}
479
 
480
 
481
/* At fxsave_offset[REGNUM] you'll find the offset to the location in
482
   the data structure used by the "fxsave" instruction where GDB
483
   register REGNUM is stored.  */
484
 
485
static int fxsave_offset[] =
486
{
487
  32,                           /* %st(0) through ...  */
488
  48,
489
  64,
490
  80,
491
  96,
492
  112,
493
  128,
494
  144,                          /* ... %st(7) (80 bits each).  */
495
  0,                             /* `fctrl' (16 bits).  */
496
  2,                            /* `fstat' (16 bits).  */
497
  4,                            /* `ftag' (16 bits).  */
498
  12,                           /* `fiseg' (16 bits).  */
499
  8,                            /* `fioff'.  */
500
  20,                           /* `foseg' (16 bits).  */
501
  16,                           /* `fooff'.  */
502
  6,                            /* `fop' (bottom 11 bits).  */
503
  160 + 0 * 16,                  /* %xmm0 through ...  */
504
  160 + 1 * 16,
505
  160 + 2 * 16,
506
  160 + 3 * 16,
507
  160 + 4 * 16,
508
  160 + 5 * 16,
509
  160 + 6 * 16,
510
  160 + 7 * 16,
511
  160 + 8 * 16,
512
  160 + 9 * 16,
513
  160 + 10 * 16,
514
  160 + 11 * 16,
515
  160 + 12 * 16,
516
  160 + 13 * 16,
517
  160 + 14 * 16,
518
  160 + 15 * 16,                /* ... %xmm15 (128 bits each).  */
519
};
520
 
521
#define FXSAVE_ADDR(tdep, fxsave, regnum) \
522
  (fxsave + fxsave_offset[regnum - I387_ST0_REGNUM (tdep)])
523
 
524
/* We made an unfortunate choice in putting %mxcsr after the SSE
525
   registers %xmm0-%xmm7 instead of before, since it makes supporting
526
   the registers %xmm8-%xmm15 on AMD64 a bit involved.  Therefore we
527
   don't include the offset for %mxcsr here above.  */
528
 
529
#define FXSAVE_MXCSR_ADDR(fxsave) (fxsave + 24)
530
 
531
static int i387_tag (const gdb_byte *raw);
532
 
533
 
534
/* Fill register REGNUM in REGCACHE with the appropriate
535
   floating-point or SSE register value from *FXSAVE.  This function
536
   masks off any of the reserved bits in *FXSAVE.  */
537
 
538
void
539
i387_supply_fxsave (struct regcache *regcache, int regnum, const void *fxsave)
540
{
541
  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
542
  const gdb_byte *regs = fxsave;
543
  int i;
544
 
545
  gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
546
  gdb_assert (tdep->num_xmm_regs > 0);
547
 
548
  for (i = I387_ST0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
549
    if (regnum == -1 || regnum == i)
550
      {
551
        if (regs == NULL)
552
          {
553
            regcache_raw_supply (regcache, i, NULL);
554
            continue;
555
          }
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 >= I387_FCTRL_REGNUM (tdep) && i < I387_XMM0_REGNUM (tdep)
560
            && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
561
          {
562
            gdb_byte val[4];
563
 
564
            memcpy (val, FXSAVE_ADDR (tdep, regs, i), 2);
565
            val[2] = val[3] = 0;
566
            if (i == I387_FOP_REGNUM (tdep))
567
              val[1] &= ((1 << 3) - 1);
568
            else if (i== I387_FTAG_REGNUM (tdep))
569
              {
570
                /* The fxsave area contains a simplified version of
571
                   the tag word.  We have to look at the actual 80-bit
572
                   FP 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 (tdep, regs,
579
                                     I387_FSTAT_REGNUM (tdep)))[1] >> 3);
580
                top &= 0x7;
581
 
582
                for (fpreg = 7; fpreg >= 0; fpreg--)
583
                  {
584
                    int tag;
585
 
586
                    if (val[0] & (1 << fpreg))
587
                      {
588
                        int regnum = (fpreg + 8 - top) % 8
589
                                       + I387_ST0_REGNUM (tdep);
590
                        tag = i387_tag (FXSAVE_ADDR (tdep, regs, regnum));
591
                      }
592
                    else
593
                      tag = 3;          /* Empty */
594
 
595
                    ftag |= tag << (2 * fpreg);
596
                  }
597
                val[0] = ftag & 0xff;
598
                val[1] = (ftag >> 8) & 0xff;
599
              }
600
            regcache_raw_supply (regcache, i, val);
601
          }
602
        else
603
          regcache_raw_supply (regcache, i, FXSAVE_ADDR (tdep, regs, i));
604
      }
605
 
606
  if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
607
    {
608
      if (regs == NULL)
609
        regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep), NULL);
610
      else
611
        regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep),
612
                             FXSAVE_MXCSR_ADDR (regs));
613
    }
614
}
615
 
616
/* Fill register REGNUM (if it is a floating-point or SSE register) in
617
   *FXSAVE with the value from REGCACHE.  If REGNUM is -1, do this for
618
   all registers.  This function doesn't touch any of the reserved
619
   bits in *FXSAVE.  */
620
 
621
void
622
i387_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave)
623
{
624
  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
625
  gdb_byte *regs = fxsave;
626
  int i;
627
 
628
  gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
629
  gdb_assert (tdep->num_xmm_regs > 0);
630
 
631
  for (i = I387_ST0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
632
    if (regnum == -1 || regnum == i)
633
      {
634
        /* Most of the FPU control registers occupy only 16 bits in
635
           the fxsave area.  Give those a special treatment.  */
636
        if (i >= I387_FCTRL_REGNUM (tdep) && i < I387_XMM0_REGNUM (tdep)
637
            && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
638
          {
639
            gdb_byte buf[4];
640
 
641
            regcache_raw_collect (regcache, i, buf);
642
 
643
            if (i == I387_FOP_REGNUM (tdep))
644
              {
645
                /* The opcode occupies only 11 bits.  Make sure we
646
                   don't touch the other bits.  */
647
                buf[1] &= ((1 << 3) - 1);
648
                buf[1] |= ((FXSAVE_ADDR (tdep, regs, i))[1] & ~((1 << 3) - 1));
649
              }
650
            else if (i == I387_FTAG_REGNUM (tdep))
651
              {
652
                /* Converting back is much easier.  */
653
 
654
                unsigned short ftag;
655
                int fpreg;
656
 
657
                ftag = (buf[1] << 8) | buf[0];
658
                buf[0] = 0;
659
                buf[1] = 0;
660
 
661
                for (fpreg = 7; fpreg >= 0; fpreg--)
662
                  {
663
                    int tag = (ftag >> (fpreg * 2)) & 3;
664
 
665
                    if (tag != 3)
666
                      buf[0] |= (1 << fpreg);
667
                  }
668
              }
669
            memcpy (FXSAVE_ADDR (tdep, regs, i), buf, 2);
670
          }
671
        else
672
          regcache_raw_collect (regcache, i, FXSAVE_ADDR (tdep, regs, i));
673
      }
674
 
675
  if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
676
    regcache_raw_collect (regcache, I387_MXCSR_REGNUM (tdep),
677
                          FXSAVE_MXCSR_ADDR (regs));
678
}
679
 
680
/* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
681
   *RAW.  */
682
 
683
static int
684
i387_tag (const gdb_byte *raw)
685
{
686
  int integer;
687
  unsigned int exponent;
688
  unsigned long fraction[2];
689
 
690
  integer = raw[7] & 0x80;
691
  exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
692
  fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
693
  fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
694
                 | (raw[5] << 8) | raw[4]);
695
 
696
  if (exponent == 0x7fff)
697
    {
698
      /* Special.  */
699
      return (2);
700
    }
701
  else if (exponent == 0x0000)
702
    {
703
      if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
704
        {
705
          /* Zero.  */
706
          return (1);
707
        }
708
      else
709
        {
710
          /* Special.  */
711
          return (2);
712
        }
713
    }
714
  else
715
    {
716
      if (integer)
717
        {
718
          /* Valid.  */
719
          return (0);
720
        }
721
      else
722
        {
723
          /* Special.  */
724
          return (2);
725
        }
726
    }
727
}
728
 
729
/* Prepare the FPU stack in REGCACHE for a function return.  */
730
 
731
void
732
i387_return_value (struct gdbarch *gdbarch, struct regcache *regcache)
733
{
734
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
735
  ULONGEST fstat;
736
 
737
  /* Set the top of the floating-point register stack to 7.  The
738
     actual value doesn't really matter, but 7 is what a normal
739
     function return would end up with if the program started out with
740
     a freshly initialized FPU.  */
741
  regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM (tdep), &fstat);
742
  fstat |= (7 << 11);
743
  regcache_raw_write_unsigned (regcache, I387_FSTAT_REGNUM (tdep), fstat);
744
 
745
  /* Mark %st(1) through %st(7) as empty.  Since we set the top of the
746
     floating-point register stack to 7, the appropriate value for the
747
     tag word is 0x3fff.  */
748
  regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM (tdep), 0x3fff);
749
 
750
}

powered by: WebSVN 2.1.0

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