Merge from vendor branch GCC:
[dragonfly.git] / contrib / gdb / gdb / i386b-nat.c
1 /* Native-dependent code for BSD Unix running on i386's, for GDB.
2    Copyright 1988, 1989, 1991, 1992, 1994, 1996 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
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.
10
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.
15
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, Boston, MA 02111-1307, USA.  */
19
20 #include "defs.h"
21
22 #ifdef FETCH_INFERIOR_REGISTERS
23 #include <sys/types.h>
24 #include <sys/ptrace.h>
25 #include <machine/reg.h>
26 #include <machine/frame.h>
27 #include "inferior.h"
28
29 void
30 fetch_inferior_registers(regno)
31      int regno;
32 {
33   struct reg inferior_registers;
34
35   ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &inferior_registers, 0);
36   memcpy (&registers[REGISTER_BYTE (0)], &inferior_registers, 4*NUM_REGS);
37   registers_fetched ();
38 }
39
40 void
41 store_inferior_registers(regno)
42      int regno;
43 {
44   struct reg inferior_registers;
45
46   memcpy (&inferior_registers, &registers[REGISTER_BYTE (0)], 4*NUM_REGS);
47   ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &inferior_registers, 0);
48 }
49
50 struct md_core {
51   struct reg intreg;
52   struct fpreg freg;
53 };
54
55 void
56 fetch_core_registers (core_reg_sect, core_reg_size, which, ignore)
57      char *core_reg_sect;
58      unsigned core_reg_size;
59      int which;
60      CORE_ADDR ignore;
61 {
62   struct md_core *core_reg = (struct md_core *)core_reg_sect;
63
64   /* integer registers */
65   memcpy(&registers[REGISTER_BYTE (0)], &core_reg->intreg,
66          sizeof(struct reg));
67   /* floating point registers */
68   /* XXX */
69 }
70
71 #else
72
73 #include <machine/reg.h>
74
75 /* Some systems don't provide all the registers on a trap.  Use SS as a
76    default if so.  */
77
78 #ifndef tDS
79 #define tDS tSS
80 #endif
81 #ifndef tES
82 #define tES tSS
83 #endif
84 #ifndef tFS
85 #define tFS tSS
86 #endif
87 #ifndef tGS
88 #define tGS tSS
89 #endif
90
91 /* These tables map between the registers on a trap frame, and the register
92    order used by the rest of GDB.  */
93 /* this table must line up with REGISTER_NAMES in tm-i386.h */
94 /* symbols like 'tEAX' come from <machine/reg.h> */
95 static int tregmap[] = 
96 {
97   tEAX, tECX, tEDX, tEBX,
98   tESP, tEBP, tESI, tEDI,
99   tEIP, tEFLAGS, tCS, tSS,
100   tDS, tES, tFS, tGS
101 };
102
103 #ifdef sEAX
104 static int sregmap[] = 
105 {
106   sEAX, sECX, sEDX, sEBX,
107   sESP, sEBP, sESI, sEDI,
108   sEIP, sEFLAGS, sCS, sSS
109 };
110 #else /* No sEAX */
111
112 /* FreeBSD has decided to collapse the s* and t* symbols.  So if the s*
113    ones aren't around, use the t* ones for sregmap too.  */
114
115 static int sregmap[] = 
116 {
117   tEAX, tECX, tEDX, tEBX,
118   tESP, tEBP, tESI, tEDI,
119   tEIP, tEFLAGS, tCS, tSS,
120   tDS, tES, tFS, tGS
121 };
122 #endif /* No sEAX */
123
124 /* blockend is the value of u.u_ar0, and points to the
125    place where ES is stored.  */
126
127 int
128 i386_register_u_addr (blockend, regnum)
129      int blockend;
130      int regnum;
131 {
132   /* The following condition is a kludge to get at the proper register map
133      depending upon the state of pcb_flag.
134      The proper condition would be
135      if (u.u_pcb.pcb_flag & FM_TRAP)
136      but that would require a ptrace call here and wouldn't work
137      for corefiles.  */
138
139   if (blockend < 0x1fcc)
140     return (blockend + 4 * tregmap[regnum]);
141   else
142     return (blockend + 4 * sregmap[regnum]);
143 }
144
145 #endif /* !FETCH_INFERIOR_REGISTERS */
146
147 #ifdef FLOAT_INFO
148 #include "expression.h"
149 #include "language.h"                   /* for local_hex_string */
150 #include "floatformat.h"
151
152 #include <sys/param.h>
153 #include <signal.h>
154 #include <sys/ioctl.h>
155 #include <fcntl.h>
156
157 #include <a.out.h>
158
159 #include <sys/time.h>
160 #include <sys/resource.h>
161 #include <sys/uio.h>
162 #define curpcb Xcurpcb  /* XXX avoid leaking declaration from pcb.h */
163 #include <sys/user.h>
164 #undef curpcb
165 #include <sys/file.h>
166 #include "gdb_stat.h"
167 #include <sys/ptrace.h>
168
169 extern void print_387_control_word ();          /* i387-tdep.h */
170 extern void print_387_status_word ();
171
172 #define fpstate         save87
173 #define U_FPSTATE(u)    u.u_pcb.pcb_savefpu
174
175 static void
176 i387_to_double (from, to)
177      char *from;
178      char *to;
179 {
180   long *lp;
181   /* push extended mode on 387 stack, then pop in double mode
182    *
183    * first, set exception masks so no error is generated -
184    * number will be rounded to inf or 0, if necessary
185    */
186   asm ("pushl %eax");           /* grab a stack slot */
187   asm ("fstcw (%esp)");         /* get 387 control word */
188   asm ("movl (%esp),%eax");     /* save old value */
189   asm ("orl $0x3f,%eax");               /* mask all exceptions */
190   asm ("pushl %eax");
191   asm ("fldcw (%esp)");         /* load new value into 387 */
192
193   asm ("movl 8(%ebp),%eax");
194   asm ("fldt (%eax)");          /* push extended number on 387 stack */
195   asm ("fwait");
196   asm ("movl 12(%ebp),%eax");
197   asm ("fstpl (%eax)");         /* pop double */
198   asm ("fwait");
199
200   asm ("popl %eax");            /* flush modified control word */
201   asm ("fnclex");                       /* clear exceptions */
202   asm ("fldcw (%esp)");         /* restore original control word */
203   asm ("popl %eax");            /* flush saved copy */
204 }
205
206 struct env387 
207 {
208   unsigned short control;
209   unsigned short r0;
210   unsigned short status;
211   unsigned short r1;
212   unsigned short tag;
213   unsigned short r2;
214   unsigned long eip;
215   unsigned short code_seg;
216   unsigned short opcode;
217   unsigned long operand;
218   unsigned short operand_seg;
219   unsigned short r3;
220   unsigned char regs[8][10];
221 };
222
223 static void
224 print_387_status (status, ep)
225      unsigned short status;
226      struct env387 *ep;
227 {
228   int i;
229   int bothstatus;
230   int top;
231   int fpreg;
232   
233   bothstatus = ((status != 0) && (ep->status != 0));
234   if (status != 0) 
235     {
236       if (bothstatus)
237         printf_unfiltered ("u: ");
238       print_387_status_word ((unsigned int)status);
239     }
240   
241   if (ep->status != 0) 
242     {
243       if (bothstatus)
244         printf_unfiltered ("e: ");
245       print_387_status_word ((unsigned int)ep->status);
246     }
247   
248   print_387_control_word ((unsigned int)ep->control);
249   printf_unfiltered ("last instruction: ");
250   printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
251   printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
252   printf_unfiltered ("%s; ", local_hex_string(ep->eip));
253   printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg));
254   printf_unfiltered (":%s\n", local_hex_string(ep->operand));
255
256   top = (ep->status >> 11) & 7;
257   
258   printf_unfiltered (" regno     tag  msb              lsb  value\n");
259   for (fpreg = 7; fpreg >= 0; fpreg--) 
260     {
261       int st_regno;
262       double val;
263       
264       /* The physical regno `fpreg' is only relevant as an index into the
265        * tag word.  Logical `%st' numbers are required for indexing ep->regs.
266        */
267       st_regno = (fpreg + 8 - top) & 7;
268
269       printf_unfiltered ("%%st(%d) %s ", st_regno, fpreg == top ? "=>" : "  ");
270
271       switch ((ep->tag >> (fpreg * 2)) & 3) 
272         {
273         case 0: printf_unfiltered ("valid "); break;
274         case 1: printf_unfiltered ("zero  "); break;
275         case 2: printf_unfiltered ("trap  "); break;
276         case 3: printf_unfiltered ("empty "); break;
277         }
278       for (i = 9; i >= 0; i--)
279         printf_unfiltered ("%02x", ep->regs[st_regno][i]);
280       
281       i387_to_double((char *) ep->regs[st_regno], (char *) &val);
282       printf_unfiltered ("  %g\n", val);
283     }
284 }
285
286 void
287 i386_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   extern int inferior_pid;
301   
302   uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
303   if (inferior_pid) 
304     {
305       int *ip;
306       
307       rounded_addr = uaddr & -sizeof (int);
308       rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) +
309                       sizeof (int) - 1) / sizeof (int);
310       skip = uaddr - rounded_addr;
311       
312       ip = (int *)buf;
313       for (i = 0; i < rounded_size; i++) 
314         {
315           *ip++ = ptrace (PT_READ_U, inferior_pid, (caddr_t)rounded_addr, 0);
316           rounded_addr += sizeof (int);
317         }
318     } 
319   else 
320     {
321       printf("float info: can't do a core file (yet)\n");
322       return;
323 #if 0
324       if (lseek (corechan, uaddr, 0) < 0)
325         perror_with_name ("seek on core file");
326       if (myread (corechan, buf, sizeof (struct fpstate)) < 0) 
327         perror_with_name ("read from core file");
328       skip = 0;
329 #endif
330     }
331
332 #ifdef  __FreeBSD__
333   fpstatep = (struct fpstate *)(buf + skip);
334   print_387_status (fpstatep->sv_ex_sw, (struct env387 *)fpstatep);
335 #else
336   print_387_status (0, (struct env387 *)buf);
337 #endif
338 }
339 #endif /* FLOAT_INFO */
340
341 int
342 kernel_u_size ()
343 {
344   return (sizeof (struct user));
345 }
346
347 #ifdef  SETUP_ARBITRARY_FRAME
348 #include "frame.h"
349 struct frame_info *
350 setup_arbitrary_frame (argc, argv)
351         int argc;
352         CORE_ADDR *argv;
353 {
354     if (argc != 2)
355         error ("i386 frame specifications require two arguments: sp and pc");
356
357     return create_new_frame (argv[0], argv[1]);
358 }
359 #endif  /* SETUP_ARBITRARY_FRAME */