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