Change GDB over to GNU General Public License version 2.
[deliverable/binutils-gdb.git] / gdb / i386-xdep.c
CommitLineData
dd3b648e
RP
1/* Intel 386 stuff.
2 Copyright (C) 1988, 1989 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
99a7de40 6This program is free software; you can redistribute it and/or modify
dd3b648e 7it under the terms of the GNU General Public License as published by
99a7de40
JG
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
dd3b648e 10
99a7de40 11This program is distributed in the hope that it will be useful,
dd3b648e
RP
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
99a7de40
JG
17along with this program; if not, write to the Free Software
18Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
dd3b648e
RP
19
20#include <stdio.h>
21#include "defs.h"
22#include "param.h"
23#include "frame.h"
24#include "inferior.h"
25#include "gdbcore.h"
26
27#ifdef USG
28#include <sys/types.h>
29#endif
30
31#include <sys/param.h>
32#include <sys/dir.h>
33#include <signal.h>
34#include <sys/user.h>
35#include <sys/ioctl.h>
36#include <fcntl.h>
37
38#include <sys/file.h>
39#include <sys/stat.h>
40
41#include <sys/reg.h>
42\f
43/* this table must line up with REGISTER_NAMES in m-i386.h */
44/* symbols like 'EAX' come from <sys/reg.h> */
45static int regmap[] =
46{
47 EAX, ECX, EDX, EBX,
48 UESP, EBP, ESI, EDI,
49 EIP, EFL, CS, SS,
50 DS, ES, FS, GS,
51};
52
53/* blockend is the value of u.u_ar0, and points to the
54 * place where GS is stored
55 */
56i386_register_u_addr (blockend, regnum)
57{
58#if 0
59 /* this will be needed if fp registers are reinstated */
60 /* for now, you can look at them with 'info float'
61 * sys5 wont let you change them with ptrace anyway
62 */
63 if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM)
64 {
65 int ubase, fpstate;
66 struct user u;
67 ubase = blockend + 4 * (SS + 1) - KSTKSZ;
68 fpstate = ubase + ((char *)&u.u_fpstate - (char *)&u);
69 return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
70 }
71 else
72#endif
73 return (blockend + 4 * regmap[regnum]);
74
75}
76
77/* This is broken for cross debugging. Possible solutions are:
78
791. Don't worry about whether the thing compiles for cross-debugging.
80Go ahead and call them from i386-tdep.c.
811a. Same thing but use some macros in xm-i386.h so that gdb will
82compile for cross-debugging but just give an error (or some such behavior)
83when you attempt to convert floats.
84
852. Write a portable (in the sense of running on any machine; it would
86always be for i387 floating-point formats) extended<->double converter
87(which just deals with the values as arrays of char).
88
893. Assume the host machine has *some* IEEE chip. However, IEEE does
90not standardize formats for extended floats (387 is 10 bytes, 68881 is
9112 bytes), so this won't work. */
92
93i387_to_double (from, to)
94 char *from;
95 char *to;
96{
97 long *lp;
98 /* push extended mode on 387 stack, then pop in double mode
99 *
100 * first, set exception masks so no error is generated -
101 * number will be rounded to inf or 0, if necessary
102 */
103 asm ("pushl %eax"); /* grab a stack slot */
104 asm ("fstcw (%esp)"); /* get 387 control word */
105 asm ("movl (%esp),%eax"); /* save old value */
106 asm ("orl $0x3f,%eax"); /* mask all exceptions */
107 asm ("pushl %eax");
108 asm ("fldcw (%esp)"); /* load new value into 387 */
109
110 asm ("movl 8(%ebp),%eax");
111 asm ("fldt (%eax)"); /* push extended number on 387 stack */
112 asm ("fwait");
113 asm ("movl 12(%ebp),%eax");
114 asm ("fstpl (%eax)"); /* pop double */
115 asm ("fwait");
116
117 asm ("popl %eax"); /* flush modified control word */
118 asm ("fnclex"); /* clear exceptions */
119 asm ("fldcw (%esp)"); /* restore original control word */
120 asm ("popl %eax"); /* flush saved copy */
121}
122
123double_to_i387 (from, to)
124 char *from;
125 char *to;
126{
127 /* push double mode on 387 stack, then pop in extended mode
128 * no errors are possible because every 64-bit pattern
129 * can be converted to an extended
130 */
131 asm ("movl 8(%ebp),%eax");
132 asm ("fldl (%eax)");
133 asm ("fwait");
134 asm ("movl 12(%ebp),%eax");
135 asm ("fstpt (%eax)");
136 asm ("fwait");
137}
138
139struct env387
140{
141 unsigned short control;
142 unsigned short r0;
143 unsigned short status;
144 unsigned short r1;
145 unsigned short tag;
146 unsigned short r2;
147 unsigned long eip;
148 unsigned short code_seg;
149 unsigned short opcode;
150 unsigned long operand;
151 unsigned short operand_seg;
152 unsigned short r3;
153 unsigned char regs[8][10];
154};
155
156static
157print_387_control_word (control)
158unsigned short control;
159{
160 printf ("control 0x%04x: ", control);
161 printf ("compute to ");
162 switch ((control >> 8) & 3)
163 {
164 case 0: printf ("24 bits; "); break;
165 case 1: printf ("(bad); "); break;
166 case 2: printf ("53 bits; "); break;
167 case 3: printf ("64 bits; "); break;
168 }
169 printf ("round ");
170 switch ((control >> 10) & 3)
171 {
172 case 0: printf ("NEAREST; "); break;
173 case 1: printf ("DOWN; "); break;
174 case 2: printf ("UP; "); break;
175 case 3: printf ("CHOP; "); break;
176 }
177 if (control & 0x3f)
178 {
179 printf ("mask:");
180 if (control & 0x0001) printf (" INVALID");
181 if (control & 0x0002) printf (" DENORM");
182 if (control & 0x0004) printf (" DIVZ");
183 if (control & 0x0008) printf (" OVERF");
184 if (control & 0x0010) printf (" UNDERF");
185 if (control & 0x0020) printf (" LOS");
186 printf (";");
187 }
188 printf ("\n");
189 if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n",
190 control & 0xe080);
191}
192
193static
194print_387_status_word (status)
195 unsigned short status;
196{
197 printf ("status 0x%04x: ", status);
198 if (status & 0xff)
199 {
200 printf ("exceptions:");
201 if (status & 0x0001) printf (" INVALID");
202 if (status & 0x0002) printf (" DENORM");
203 if (status & 0x0004) printf (" DIVZ");
204 if (status & 0x0008) printf (" OVERF");
205 if (status & 0x0010) printf (" UNDERF");
206 if (status & 0x0020) printf (" LOS");
207 if (status & 0x0040) printf (" FPSTACK");
208 printf ("; ");
209 }
210 printf ("flags: %d%d%d%d; ",
211 (status & 0x4000) != 0,
212 (status & 0x0400) != 0,
213 (status & 0x0200) != 0,
214 (status & 0x0100) != 0);
215
216 printf ("top %d\n", (status >> 11) & 7);
217}
218
219static
220print_387_status (status, ep)
221 unsigned short status;
222 struct env387 *ep;
223{
224 int i;
225 int bothstatus;
226 int top;
227 int fpreg;
228 unsigned char *p;
229
230 bothstatus = ((status != 0) && (ep->status != 0));
231 if (status != 0)
232 {
233 if (bothstatus)
234 printf ("u: ");
235 print_387_status_word (status);
236 }
237
238 if (ep->status != 0)
239 {
240 if (bothstatus)
241 printf ("e: ");
242 print_387_status_word (ep->status);
243 }
244
245 print_387_control_word (ep->control);
246 printf ("last exception: ");
247 printf ("opcode 0x%x; ", ep->opcode);
248 printf ("pc 0x%x:0x%x; ", ep->code_seg, ep->eip);
249 printf ("operand 0x%x:0x%x\n", ep->operand_seg, ep->operand);
250
251 top = (ep->status >> 11) & 7;
252
253 printf ("regno tag msb lsb value\n");
254 for (fpreg = 7; fpreg >= 0; fpreg--)
255 {
256 double val;
257
258 printf ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
259
260 switch ((ep->tag >> (fpreg * 2)) & 3)
261 {
262 case 0: printf ("valid "); break;
263 case 1: printf ("zero "); break;
264 case 2: printf ("trap "); break;
265 case 3: printf ("empty "); break;
266 }
267 for (i = 9; i >= 0; i--)
268 printf ("%02x", ep->regs[fpreg][i]);
269
270 i387_to_double (ep->regs[fpreg], (char *)&val);
271 printf (" %g\n", val);
272 }
273 if (ep->r0)
274 printf ("warning: reserved0 is 0x%x\n", ep->r0);
275 if (ep->r1)
276 printf ("warning: reserved1 is 0x%x\n", ep->r1);
277 if (ep->r2)
278 printf ("warning: reserved2 is 0x%x\n", ep->r2);
279 if (ep->r3)
280 printf ("warning: reserved3 is 0x%x\n", ep->r3);
281}
282
283#ifndef U_FPSTATE
284#define U_FPSTATE(u) u.u_fpstate
285#endif
286
287i386_float_info ()
288{
289 struct user u; /* just for address computations */
290 int i;
291 /* fpstate defined in <sys/user.h> */
292 struct fpstate *fpstatep;
293 char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
294 unsigned int uaddr;
295 char fpvalid;
296 unsigned int rounded_addr;
297 unsigned int rounded_size;
298 extern int corechan;
299 int skip;
300
301 uaddr = (char *)&u.u_fpvalid - (char *)&u;
302 if (have_inferior_p())
303 {
304 unsigned int data;
305 unsigned int mask;
306
307 rounded_addr = uaddr & -sizeof (int);
308 data = ptrace (3, inferior_pid, rounded_addr, 0);
309 mask = 0xff << ((uaddr - rounded_addr) * 8);
310
311 fpvalid = ((data & mask) != 0);
312 }
313 else
314 {
315 if (lseek (corechan, uaddr, 0) < 0)
316 perror ("seek on core file");
317 if (myread (corechan, &fpvalid, 1) < 0)
318 perror ("read on core file");
319
320 }
321
322 if (fpvalid == 0)
323 {
324 printf ("no floating point status saved\n");
325 return;
326 }
327
328 uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
329 if (have_inferior_p ())
330 {
331 int *ip;
332
333 rounded_addr = uaddr & -sizeof (int);
334 rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) +
335 sizeof (int) - 1) / sizeof (int);
336 skip = uaddr - rounded_addr;
337
338 ip = (int *)buf;
339 for (i = 0; i < rounded_size; i++)
340 {
341 *ip++ = ptrace (3, inferior_pid, rounded_addr, 0);
342 rounded_addr += sizeof (int);
343 }
344 }
345 else
346 {
347 if (lseek (corechan, uaddr, 0) < 0)
348 perror_with_name ("seek on core file");
349 if (myread (corechan, buf, sizeof (struct fpstate)) < 0)
350 perror_with_name ("read from core file");
351 skip = 0;
352 }
353
354 fpstatep = (struct fpstate *)(buf + skip);
355 print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
356}
357
This page took 0.04018 seconds and 4 git commands to generate.