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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [i387-tdep.c] - Blame information for rev 1774

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

Line No. Rev Author Line
1 578 markom
/* Intel 387 floating point stuff.
2
   Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000, 2001
3
   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
 
32
 
33
/* FIXME: Eliminate the next two functions when we have the time to
34
   change all the callers.  */
35
 
36
void i387_to_double (char *from, char *to);
37
void double_to_i387 (char *from, char *to);
38
 
39
void
40
i387_to_double (char *from, char *to)
41
{
42
  floatformat_to_double (&floatformat_i387_ext, from, (double *) to);
43
}
44
 
45
void
46
double_to_i387 (char *from, char *to)
47
{
48
  floatformat_from_double (&floatformat_i387_ext, (double *) from, to);
49
}
50
 
51
 
52
/* FIXME: The functions on this page are used by the old `info float'
53
   implementations that a few of the i386 targets provide.  These
54
   functions should be removed if all of these have been converted to
55
   use the generic implementation based on the new register file
56
   layout.  */
57
 
58
static void print_387_control_bits (unsigned int control);
59
static void print_387_status_bits (unsigned int status);
60
 
61
static void
62
print_387_control_bits (unsigned int control)
63
{
64
  switch ((control >> 8) & 3)
65
    {
66
    case 0:
67
      puts_unfiltered (" 24 bit; ");
68
      break;
69
    case 1:
70
      puts_unfiltered (" (bad); ");
71
      break;
72
    case 2:
73
      puts_unfiltered (" 53 bit; ");
74
      break;
75
    case 3:
76
      puts_unfiltered (" 64 bit; ");
77
      break;
78
    }
79
  switch ((control >> 10) & 3)
80
    {
81
    case 0:
82
      puts_unfiltered ("NEAR; ");
83
      break;
84
    case 1:
85
      puts_unfiltered ("DOWN; ");
86
      break;
87
    case 2:
88
      puts_unfiltered ("UP; ");
89
      break;
90
    case 3:
91
      puts_unfiltered ("CHOP; ");
92
      break;
93
    }
94
  if (control & 0x3f)
95
    {
96
      puts_unfiltered ("mask");
97
      if (control & 0x0001)
98
        puts_unfiltered (" INVAL");
99
      if (control & 0x0002)
100
        puts_unfiltered (" DENOR");
101
      if (control & 0x0004)
102
        puts_unfiltered (" DIVZ");
103
      if (control & 0x0008)
104
        puts_unfiltered (" OVERF");
105
      if (control & 0x0010)
106
        puts_unfiltered (" UNDER");
107
      if (control & 0x0020)
108
        puts_unfiltered (" LOS");
109
      puts_unfiltered (";");
110
    }
111
 
112
  if (control & 0xe080)
113
    warning ("\nreserved bits on: %s",
114
             local_hex_string (control & 0xe080));
115
}
116
 
117
void
118
print_387_control_word (unsigned int control)
119
{
120
  printf_filtered ("control %s:", local_hex_string(control & 0xffff));
121
  print_387_control_bits (control);
122
  puts_unfiltered ("\n");
123
}
124
 
125
static void
126
print_387_status_bits (unsigned int status)
127
{
128
  printf_unfiltered (" flags %d%d%d%d; ",
129
                     (status & 0x4000) != 0,
130
                     (status & 0x0400) != 0,
131
                     (status & 0x0200) != 0,
132
                     (status & 0x0100) != 0);
133
  printf_unfiltered ("top %d; ", (status >> 11) & 7);
134
  if (status & 0xff)
135
    {
136
      puts_unfiltered ("excep");
137
      if (status & 0x0001) puts_unfiltered (" INVAL");
138
      if (status & 0x0002) puts_unfiltered (" DENOR");
139
      if (status & 0x0004) puts_unfiltered (" DIVZ");
140
      if (status & 0x0008) puts_unfiltered (" OVERF");
141
      if (status & 0x0010) puts_unfiltered (" UNDER");
142
      if (status & 0x0020) puts_unfiltered (" LOS");
143
      if (status & 0x0040) puts_unfiltered (" STACK");
144
    }
145
}
146
 
147
void
148
print_387_status_word (unsigned int status)
149
{
150
  printf_filtered ("status %s:", local_hex_string (status & 0xffff));
151
  print_387_status_bits (status);
152
  puts_unfiltered ("\n");
153
}
154
 
155
 
156
/* Implement the `info float' layout based on the register definitions
157
   in `tm-i386.h'.  */
158
 
159
/* Print the floating point number specified by RAW.  */
160
static void
161
print_i387_value (char *raw)
162
{
163
  DOUBLEST value;
164
  int len = TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT;
165
  char *tmp = alloca (len);
166
 
167
  /* This code only works on targets where ... */
168
  gdb_assert (TARGET_LONG_DOUBLE_FORMAT == &floatformat_i387_ext);
169
 
170
  /* Take care of the padding.  FP reg is 80 bits.  The same value in
171
     memory is 96 bits.  */
172
  gdb_assert (FPU_REG_RAW_SIZE < len);
173
  memcpy (&tmp, raw, FPU_REG_RAW_SIZE);
174
  memset (&tmp + FPU_REG_RAW_SIZE, 0, len - FPU_REG_RAW_SIZE);
175
 
176
  /* Extract the value as a DOUBLEST.  */
177
  /* Use extract_floating() rather than floatformat_to_doublest().
178
     The latter is lossy in nature.  Once GDB gets a host/target
179
     independent and non-lossy FP it will become possible to bypass
180
     extract_floating() and call floatformat*() directly.  Note also
181
     the assumptions about TARGET_LONG_DOUBLE above.  */
182
  value = extract_floating (tmp, len);
183
 
184
  /* We try to print 19 digits.  The last digit may or may not contain
185
     garbage, but we'd better print one too many.  We need enough room
186
     to print the value, 1 position for the sign, 1 for the decimal
187
     point, 19 for the digits and 6 for the exponent adds up to 27.  */
188
#ifdef PRINTF_HAS_LONG_DOUBLE
189
  printf_filtered (" %-+27.19Lg", (long double) value);
190
#else
191
  printf_filtered (" %-+27.19g", (double) value);
192
#endif
193
}
194
 
195
/* Print the classification for the register contents RAW.  */
196
static void
197
print_i387_ext (unsigned char *raw)
198
{
199
  int sign;
200
  int integer;
201
  unsigned int exponent;
202
  unsigned long fraction[2];
203
 
204
  sign = raw[9] & 0x80;
205
  integer = raw[7] & 0x80;
206
  exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
207
  fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
208
  fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
209
                 | (raw[5] << 8) | raw[4]);
210
 
211
  if (exponent == 0x7fff && integer)
212
    {
213
      if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
214
        /* Infinity.  */
215
        printf_filtered (" %cInf", (sign ? '-' : '+'));
216
      else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
217
        /* Real Indefinite (QNaN).  */
218
        puts_unfiltered (" Real Indefinite (QNaN)");
219
      else if (fraction[1] & 0x40000000)
220
        /* QNaN.  */
221
        puts_filtered (" QNaN");
222
      else
223
        /* SNaN.  */
224
        puts_filtered (" SNaN");
225
    }
226
  else if (exponent < 0x7fff && exponent > 0x0000 && integer)
227
    /* Normal.  */
228
    print_i387_value (raw);
229
  else if (exponent == 0x0000)
230
    {
231
      /* Denormal or zero.  */
232
      print_i387_value (raw);
233
 
234
      if (integer)
235
        /* Pseudo-denormal.  */
236
        puts_filtered (" Pseudo-denormal");
237
      else if (fraction[0] || fraction[1])
238
        /* Denormal.  */
239
        puts_filtered (" Denormal");
240
    }
241
  else
242
    /* Unsupported.  */
243
    puts_filtered (" Unsupported");
244
}
245
 
246
/* Print the status word STATUS.  */
247
static void
248
print_i387_status_word (unsigned int status)
249
{
250
  printf_filtered ("Status Word:         %s",
251
                   local_hex_string_custom (status, "04"));
252
  puts_filtered ("  ");
253
  printf_filtered (" %s", (status & 0x0001) ? "IE" : "  ");
254
  printf_filtered (" %s", (status & 0x0002) ? "DE" : "  ");
255
  printf_filtered (" %s", (status & 0x0004) ? "ZE" : "  ");
256
  printf_filtered (" %s", (status & 0x0008) ? "OE" : "  ");
257
  printf_filtered (" %s", (status & 0x0010) ? "UE" : "  ");
258
  printf_filtered (" %s", (status & 0x0020) ? "PE" : "  ");
259
  puts_filtered ("  ");
260
  printf_filtered (" %s", (status & 0x0080) ? "ES" : "  ");
261
  puts_filtered ("  ");
262
  printf_filtered (" %s", (status & 0x0040) ? "SF" : "  ");
263
  puts_filtered ("  ");
264
  printf_filtered (" %s", (status & 0x0100) ? "C0" : "  ");
265
  printf_filtered (" %s", (status & 0x0200) ? "C1" : "  ");
266
  printf_filtered (" %s", (status & 0x0400) ? "C2" : "  ");
267
  printf_filtered (" %s", (status & 0x4000) ? "C3" : "  ");
268
 
269
  puts_filtered ("\n");
270
 
271
  printf_filtered ("                       TOP: %d\n", ((status >> 11) & 7));
272
}
273
 
274
/* Print the control word CONTROL.  */
275
static void
276
print_i387_control_word (unsigned int control)
277
{
278
  printf_filtered ("Control Word:        %s",
279
                   local_hex_string_custom (control, "04"));
280
  puts_filtered ("  ");
281
  printf_filtered (" %s", (control & 0x0001) ? "IM" : "  ");
282
  printf_filtered (" %s", (control & 0x0002) ? "DM" : "  ");
283
  printf_filtered (" %s", (control & 0x0004) ? "ZM" : "  ");
284
  printf_filtered (" %s", (control & 0x0008) ? "OM" : "  ");
285
  printf_filtered (" %s", (control & 0x0010) ? "UM" : "  ");
286
  printf_filtered (" %s", (control & 0x0020) ? "PM" : "  ");
287
 
288
  puts_filtered ("\n");
289
 
290
  puts_filtered ("                       PC: ");
291
  switch ((control >> 8) & 3)
292
    {
293
    case 0:
294
      puts_filtered ("Single Precision (24-bits)\n");
295
      break;
296
    case 1:
297
      puts_filtered ("Reserved\n");
298
      break;
299
    case 2:
300
      puts_filtered ("Double Precision (53-bits)\n");
301
      break;
302
    case 3:
303
      puts_filtered ("Extended Precision (64-bits)\n");
304
      break;
305
    }
306
 
307
  puts_filtered ("                       RC: ");
308
  switch ((control >> 10) & 3)
309
    {
310
    case 0:
311
      puts_filtered ("Round to nearest\n");
312
      break;
313
    case 1:
314
      puts_filtered ("Round down\n");
315
      break;
316
    case 2:
317
      puts_filtered ("Round up\n");
318
      break;
319
    case 3:
320
      puts_filtered ("Round toward zero\n");
321
      break;
322
    }
323
}
324
 
325
/* Print out the i387 floating poin state.  */
326
void
327
i387_float_info (void)
328
{
329
  unsigned int fctrl;
330
  unsigned int fstat;
331
  unsigned int ftag;
332
  unsigned int fiseg;
333
  unsigned int fioff;
334
  unsigned int foseg;
335
  unsigned int fooff;
336
  unsigned int fop;
337
  int fpreg;
338
  int top;
339
 
340
  fctrl = read_register (FCTRL_REGNUM);
341
  fstat = read_register (FSTAT_REGNUM);
342
  ftag  = read_register (FTAG_REGNUM);
343
  fiseg = read_register (FCS_REGNUM);
344
  fioff = read_register (FCOFF_REGNUM);
345
  foseg = read_register (FDS_REGNUM);
346
  fooff = read_register (FDOFF_REGNUM);
347
  fop   = read_register (FOP_REGNUM);
348
 
349
  top = ((fstat >> 11) & 7);
350
 
351
  for (fpreg = 7; fpreg >= 0; fpreg--)
352
    {
353
      unsigned char raw[FPU_REG_RAW_SIZE];
354
      int tag = (ftag >> (fpreg * 2)) & 3;
355
      int i;
356
 
357
      printf_filtered ("%sR%d: ", fpreg == top ? "=>" : "  ", fpreg);
358
 
359
      switch (tag)
360
        {
361
        case 0:
362
          puts_filtered ("Valid   ");
363
          break;
364
        case 1:
365
          puts_filtered ("Zero    ");
366
          break;
367
        case 2:
368
          puts_filtered ("Special ");
369
          break;
370
        case 3:
371
          puts_filtered ("Empty   ");
372
          break;
373
        }
374
 
375
      read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
376
 
377
      puts_filtered ("0x");
378
      for (i = 9; i >= 0; i--)
379
        printf_filtered ("%02x", raw[i]);
380
 
381
      if (tag != 3)
382
        print_i387_ext (raw);
383
 
384
      puts_filtered ("\n");
385
    }
386
 
387
  puts_filtered ("\n");
388
 
389
  print_i387_status_word (fstat);
390
  print_i387_control_word (fctrl);
391
  printf_filtered ("Tag Word:            %s\n",
392
                   local_hex_string_custom (ftag, "04"));
393
  printf_filtered ("Instruction Pointer: %s:",
394
                   local_hex_string_custom (fiseg, "02"));
395
  printf_filtered ("%s\n", local_hex_string_custom (fioff, "08"));
396
  printf_filtered ("Operand Pointer:     %s:",
397
                   local_hex_string_custom (foseg, "02"));
398
  printf_filtered ("%s\n", local_hex_string_custom (fooff, "08"));
399
  printf_filtered ("Opcode:              %s\n",
400
                   local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
401
}

powered by: WebSVN 2.1.0

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