]> Git Repo - binutils.git/blob - gdb/sun386-xdep.c
Change GDB over to GNU General Public License version 2.
[binutils.git] / gdb / sun386-xdep.c
1 /* Machine-dependent code for host Sun 386i's for GDB, the GNU debugger.
2    Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
3    Changes for sun386i by Jean Daniel Fekete ([email protected]),
4    C2V Paris, April 89.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
21
22 #if defined (GDB_TARGET_IS_SUN386)
23
24 #include <stdio.h>
25 #include "defs.h"
26 #include "param.h"
27 #include "frame.h"
28 #include "inferior.h"
29 #include "signame.h"
30 #include "gdbcore.h"
31
32 #include <sys/param.h>
33 #include <sys/dir.h>
34 #include <sys/user.h>
35 #include <signal.h>
36 #include <sys/ioctl.h>
37 #include <fcntl.h>
38
39 #include <sys/ptrace.h>
40 #include <machine/reg.h>
41
42 #include <sys/file.h>
43 #include <sys/stat.h>
44 #include <sys/core.h>
45 \f
46 void
47 fetch_inferior_registers ()
48 {
49   struct regs inferior_registers;
50   struct fp_state inferior_fp_registers;
51   extern char registers[];
52
53   registers_fetched ();
54
55   ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
56   ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
57
58   bcopy (&inferior_registers, registers, sizeof inferior_registers);
59
60   bcopy (inferior_fp_registers.f_st,&registers[REGISTER_BYTE (FP0_REGNUM)],
61          sizeof inferior_fp_registers.f_st);
62   bcopy (&inferior_fp_registers.f_ctrl,
63          &registers[REGISTER_BYTE (FPC_REGNUM)],
64          sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
65 }
66
67 /* Store our register values back into the inferior.
68    If REGNO is -1, do this for all registers.
69    Otherwise, REGNO specifies which register (so we can save time).  */
70
71 store_inferior_registers (regno)
72      int regno;
73 {
74   struct regs inferior_registers;
75   struct fp_state inferior_fp_registers;
76   extern char registers[];
77
78   bcopy (registers, &inferior_registers, 20 * 4);
79
80   bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],inferior_fp_registers.f_st,
81          sizeof inferior_fp_registers.f_st);
82   bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
83          &inferior_fp_registers.f_ctrl,
84          sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
85   
86 #ifdef PTRACE_FP_BUG
87   if (regno == FP_REGNUM || regno == -1)
88     /* Storing the frame pointer requires a gross hack, in which an
89        instruction that moves eax into ebp gets single-stepped.  */
90     {
91       int stack = inferior_registers.r_reg[SP_REGNUM];
92       int stuff = ptrace (PTRACE_PEEKDATA, inferior_pid, stack);
93       int reg = inferior_registers.r_reg[EAX];
94       inferior_registers.r_reg[EAX] =
95         inferior_registers.r_reg[FP_REGNUM];
96       ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
97       ptrace (PTRACE_POKEDATA, inferior_pid, stack, 0xc589);
98       ptrace (PTRACE_SINGLESTEP, inferior_pid, stack, 0);
99       wait (0);
100       ptrace (PTRACE_POKEDATA, inferior_pid, stack, stuff);
101       inferior_registers.r_reg[EAX] = reg;
102     }
103 #endif
104   ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
105   ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
106 }
107
108 /* Machine-dependent code which would otherwise be in core.c */
109 /* Work with core files, for GDB. */
110
111 \f
112 void
113 core_file_command (filename, from_tty)
114      char *filename;
115      int from_tty;
116 {
117   int val;
118   extern char registers[];
119
120   /* Discard all vestiges of any previous core file
121      and mark data and stack spaces as empty.  */
122
123   if (corefile)
124     free (corefile);
125   corefile = 0;
126
127   if (corechan >= 0)
128     close (corechan);
129   corechan = -1;
130
131   data_start = 0;
132   data_end = 0;
133   stack_start = STACK_END_ADDR;
134   stack_end = STACK_END_ADDR;
135
136   /* Now, if a new core file was specified, open it and digest it.  */
137
138   if (filename)
139     {
140       filename = tilde_expand (filename);
141       make_cleanup (free, filename);
142       
143       if (have_inferior_p ())
144         error ("To look at a core file, you must kill the inferior with \"kill\".");
145       corechan = open (filename, O_RDONLY, 0);
146       if (corechan < 0)
147         perror_with_name (filename);
148
149       {
150         struct core corestr;
151
152         val = myread (corechan, &corestr, sizeof corestr);
153         if (val < 0)
154           perror_with_name (filename);
155         if (corestr.c_magic != CORE_MAGIC)
156           error ("\"%s\" does not appear to be a core dump file (magic 0x%x, expected 0x%x)",
157                  filename, corestr.c_magic, (int) CORE_MAGIC);
158         else if (sizeof (struct core) != corestr.c_len)
159           error ("\"%s\" has an invalid struct core length (%d, expected %d)",
160                  filename, corestr.c_len, (int) sizeof (struct core));
161
162         data_start = exec_data_start;
163         data_end = data_start + corestr.c_dsize;
164         stack_start = stack_end - corestr.c_ssize;
165         data_offset = sizeof corestr;
166         stack_offset = sizeof corestr + corestr.c_dsize;
167
168         bcopy (&corestr.c_regs, registers, sizeof corestr.c_regs);
169
170         bcopy (corestr.c_fpu.f_fpstatus.f_st,
171                &registers[REGISTER_BYTE (FP0_REGNUM)],
172                sizeof corestr.c_fpu.f_fpstatus.f_st);
173         bcopy (&corestr.c_fpu.f_fpstatus.f_ctrl,
174                &registers[REGISTER_BYTE (FPC_REGNUM)],
175                sizeof corestr.c_fpu.f_fpstatus -
176                sizeof corestr.c_fpu.f_fpstatus.f_st);
177
178         /* the struct aouthdr of sun coff is not the struct exec stored
179            in the core file. */
180         bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec));
181 #ifndef COFF_ENCAPSULATE
182         core_aouthdr.magic = corestr.c_aouthdr.a_info;
183         core_aouthdr.vstamp = /*SUNVERSION*/ 31252;
184 #endif
185         printf ("Core file is from \"%s\".\n", corestr.c_cmdname);
186         if (corestr.c_signo > 0)
187           printf ("Program terminated with signal %d, %s.\n",
188                         corestr.c_signo,
189                         corestr.c_signo < NSIG
190                         ? sys_siglist[corestr.c_signo]
191                         : "(undocumented)");
192       }
193       if (filename[0] == '/')
194         corefile = savestring (filename, strlen (filename));
195       else
196         {
197           corefile = concat (current_directory, "/", filename);
198         }
199
200       set_current_frame ( create_new_frame (read_register (FP_REGNUM),
201                                             read_pc ()));
202       select_frame (get_current_frame (), 0);
203
204       validate_files ();
205     }
206   else if (from_tty)
207     printf ("No core file now.\n");
208 }
209
210 i387_to_double (from, to)
211      char *from;
212      char *to;
213 {
214   long *lp;
215   /* push extended mode on 387 stack, then pop in double mode
216    *
217    * first, set exception masks so no error is generated -
218    * number will be rounded to inf or 0, if necessary 
219    */
220   asm ("pushl %eax");           /* grab a stack slot */
221   asm ("fstcw (%esp)");         /* get 387 control word */
222   asm ("movl (%esp),%eax");     /* save old value */
223   asm ("orl $0x3f,%eax");               /* mask all exceptions */
224   asm ("pushl %eax");
225   asm ("fldcw (%esp)");         /* load new value into 387 */
226   
227   asm ("movl 8(%ebp),%eax");
228   asm ("fldt (%eax)");          /* push extended number on 387 stack */
229   asm ("fwait");
230   asm ("movl 12(%ebp),%eax");
231   asm ("fstpl (%eax)");         /* pop double */
232   asm ("fwait");
233   
234   asm ("popl %eax");            /* flush modified control word */
235   asm ("fnclex");                       /* clear exceptions */
236   asm ("fldcw (%esp)");         /* restore original control word */
237   asm ("popl %eax");            /* flush saved copy */
238 }
239
240 double_to_i387 (from, to)
241      char *from;
242      char *to;
243 {
244   /* push double mode on 387 stack, then pop in extended mode
245    * no errors are possible because every 64-bit pattern
246    * can be converted to an extended
247    */
248   asm ("movl 8(%ebp),%eax");
249   asm ("fldl (%eax)");
250   asm ("fwait");
251   asm ("movl 12(%ebp),%eax");
252   asm ("fstpt (%eax)");
253   asm ("fwait");
254 }
255 #else /* Not sun386 target.  */
256
257 /* These functions shouldn't be called when we're cross-debugging.  */
258
259 void
260 fetch_inferior_registers ()
261 {
262 }
263
264 /* ARGSUSED */
265 store_inferior_registers (regno)
266      int regno;
267 {
268 }
269
270 /* ARGSUSED */
271 void
272 fetch_core_registers (core_reg_sect, core_reg_size, which)
273      char *core_reg_sect;
274      unsigned core_reg_size;
275      int which;
276 {
277 }
278
279 #endif /* Not sun386 target.  */
This page took 0.03929 seconds and 4 git commands to generate.