* config/tc-i386.c (lex_got): Match lower case relocation tokens.
[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"
d0df8472 30#include "gdb_assert.h"
c906108c 31
c906108c 32
de57eccd
JM
33/* FIXME: Eliminate the next two functions when we have the time to
34 change all the callers. */
d4f3574e 35
a14ed312
KB
36void i387_to_double (char *from, char *to);
37void double_to_i387 (char *from, char *to);
c906108c
SS
38
39void
fba45db2 40i387_to_double (char *from, char *to)
c906108c 41{
c5aa993b 42 floatformat_to_double (&floatformat_i387_ext, from, (double *) to);
c906108c
SS
43}
44
45void
fba45db2 46double_to_i387 (char *from, char *to)
c906108c 47{
c5aa993b 48 floatformat_from_double (&floatformat_i387_ext, (double *) from, to);
c906108c
SS
49}
50
de57eccd
JM
51\f
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
a14ed312
KB
58static void print_387_control_bits (unsigned int control);
59static void print_387_status_bits (unsigned int status);
de57eccd 60
d4f3574e 61static void
fba45db2 62print_387_control_bits (unsigned int control)
c906108c 63{
c5aa993b 64 switch ((control >> 8) & 3)
c906108c 65 {
c5aa993b 66 case 0:
d4f3574e 67 puts_unfiltered (" 24 bit; ");
c5aa993b
JM
68 break;
69 case 1:
d4f3574e 70 puts_unfiltered (" (bad); ");
c5aa993b
JM
71 break;
72 case 2:
d4f3574e 73 puts_unfiltered (" 53 bit; ");
c5aa993b
JM
74 break;
75 case 3:
d4f3574e 76 puts_unfiltered (" 64 bit; ");
c5aa993b 77 break;
c906108c 78 }
c5aa993b 79 switch ((control >> 10) & 3)
c906108c 80 {
c5aa993b 81 case 0:
d4f3574e 82 puts_unfiltered ("NEAR; ");
c5aa993b
JM
83 break;
84 case 1:
d4f3574e 85 puts_unfiltered ("DOWN; ");
c5aa993b
JM
86 break;
87 case 2:
d4f3574e 88 puts_unfiltered ("UP; ");
c5aa993b
JM
89 break;
90 case 3:
d4f3574e 91 puts_unfiltered ("CHOP; ");
c5aa993b 92 break;
c906108c 93 }
c5aa993b 94 if (control & 0x3f)
c906108c 95 {
d4f3574e 96 puts_unfiltered ("mask");
c5aa993b 97 if (control & 0x0001)
d4f3574e 98 puts_unfiltered (" INVAL");
c5aa993b 99 if (control & 0x0002)
d4f3574e 100 puts_unfiltered (" DENOR");
c5aa993b 101 if (control & 0x0004)
d4f3574e 102 puts_unfiltered (" DIVZ");
c5aa993b 103 if (control & 0x0008)
d4f3574e 104 puts_unfiltered (" OVERF");
c5aa993b 105 if (control & 0x0010)
d4f3574e 106 puts_unfiltered (" UNDER");
c5aa993b 107 if (control & 0x0020)
d4f3574e
SS
108 puts_unfiltered (" LOS");
109 puts_unfiltered (";");
c906108c 110 }
cff3e48b 111
c5aa993b 112 if (control & 0xe080)
d4f3574e 113 warning ("\nreserved bits on: %s",
c5aa993b 114 local_hex_string (control & 0xe080));
c906108c
SS
115}
116
117void
fba45db2 118print_387_control_word (unsigned int control)
d4f3574e
SS
119{
120 printf_filtered ("control %s:", local_hex_string(control & 0xffff));
121 print_387_control_bits (control);
122 puts_unfiltered ("\n");
123}
124
125static void
fba45db2 126print_387_status_bits (unsigned int status)
c906108c 127{
d4f3574e 128 printf_unfiltered (" flags %d%d%d%d; ",
c5aa993b
JM
129 (status & 0x4000) != 0,
130 (status & 0x0400) != 0,
131 (status & 0x0200) != 0,
132 (status & 0x0100) != 0);
d4f3574e
SS
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
147void
fba45db2 148print_387_status_word (unsigned int status)
d4f3574e
SS
149{
150 printf_filtered ("status %s:", local_hex_string (status & 0xffff));
151 print_387_status_bits (status);
152 puts_unfiltered ("\n");
153}
154
de57eccd
JM
155\f
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. */
160static void
161print_i387_value (char *raw)
162{
163 DOUBLEST value;
d0df8472
AC
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
c96646d0 171 memory is 96 bits. */
d0df8472 172 gdb_assert (FPU_REG_RAW_SIZE < len);
7f1659e6
MC
173 memcpy (tmp, raw, FPU_REG_RAW_SIZE);
174 memset (tmp + FPU_REG_RAW_SIZE, 0, len - FPU_REG_RAW_SIZE);
d0df8472
AC
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);
de57eccd
JM
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. */
196static void
197print_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. */
247static void
248print_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 (" ");
96836138 262 printf_filtered (" %s", (status & 0x0040) ? "SF" : " ");
de57eccd
JM
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. */
275static void
276print_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. */
326void
327i387_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}
This page took 0.126159 seconds and 4 git commands to generate.