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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [gdb/] [i387-tdep.c] - Blame information for rev 294

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

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

powered by: WebSVN 2.1.0

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