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