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