]> Git Repo - binutils.git/blob - gdb/rs6000-xdep.c
*** empty log message ***
[binutils.git] / gdb / rs6000-xdep.c
1 /* IBM RS/6000 host-dependent code for GDB, the GNU debugger.
2    Copyright 1986, 1987, 1989, 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include "defs.h"
21 #include "frame.h"
22 #include "inferior.h"
23 #include "symtab.h"
24 #include "target.h"
25
26 #ifdef RS6000_TARGET
27
28 #include <sys/param.h>
29 #include <sys/dir.h>
30 #include <sys/user.h>
31 #include <signal.h>
32 #include <sys/ioctl.h>
33 #include <fcntl.h>
34
35 #include <sys/ptrace.h>
36 #include <sys/reg.h>
37
38 #include <a.out.h>
39 #include <sys/file.h>
40 #include <sys/stat.h>
41 #include <sys/core.h>
42
43 extern int errno;
44
45 static void
46 exec_one_dummy_insn PARAMS ((void));
47
48 /* Conversion from gdb-to-system special purpose register numbers.. */
49
50 static int special_regs[] = {
51   IAR,                          /* PC_REGNUM    */
52   MSR,                          /* PS_REGNUM    */
53   CR,                           /* CR_REGNUM    */
54   LR,                           /* LR_REGNUM    */
55   CTR,                          /* CTR_REGNUM   */
56   XER,                          /* XER_REGNUM   */
57   MQ                            /* MQ_REGNUM    */
58 };
59 \f
60 void
61 fetch_inferior_registers (regno)
62   int regno;
63 {
64   int ii;
65   extern char registers[];
66
67   if (regno < 0) {                      /* for all registers */
68
69     /* read 32 general purpose registers. */
70
71     for (ii=0; ii < 32; ++ii)
72       *(int*)&registers[REGISTER_BYTE (ii)] = 
73         ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii, 0, 0);
74
75     /* read general purpose floating point registers. */
76
77     for (ii=0; ii < 32; ++ii)
78       ptrace (PT_READ_FPR, inferior_pid, 
79         (PTRACE_ARG3_TYPE) &registers [REGISTER_BYTE (FP0_REGNUM+ii)],
80               FPR0+ii, 0);
81
82     /* read special registers. */
83     for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii)
84       *(int*)&registers[REGISTER_BYTE (FIRST_SP_REGNUM+ii)] = 
85         ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) special_regs[ii],
86                 0, 0);
87
88     registers_fetched ();
89     return;
90   }
91
92   /* else an individual register is addressed. */
93
94   else if (regno < FP0_REGNUM) {                /* a GPR */
95     *(int*)&registers[REGISTER_BYTE (regno)] =
96         ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno, 0, 0);
97   }
98   else if (regno <= FPLAST_REGNUM) {            /* a FPR */
99     ptrace (PT_READ_FPR, inferior_pid,
100         (PTRACE_ARG3_TYPE) &registers [REGISTER_BYTE (regno)],
101             (regno-FP0_REGNUM+FPR0), 0);
102   }
103   else if (regno <= LAST_SP_REGNUM) {           /* a special register */
104     *(int*)&registers[REGISTER_BYTE (regno)] =
105         ptrace (PT_READ_GPR, inferior_pid,
106                 (PTRACE_ARG3_TYPE) special_regs[regno-FIRST_SP_REGNUM], 0, 0);
107   }
108   else
109     fprintf (stderr, "gdb error: register no %d not implemented.\n", regno);
110
111   register_valid [regno] = 1;
112 }
113
114 /* Store our register values back into the inferior.
115    If REGNO is -1, do this for all registers.
116    Otherwise, REGNO specifies which register (so we can save time).  */
117
118 void
119 store_inferior_registers (regno)
120      int regno;
121 {
122   extern char registers[];
123
124   errno = 0;
125
126   if (regno == -1) {                    /* for all registers..  */
127       int ii;
128
129        /* execute one dummy instruction (which is a breakpoint) in inferior
130           process. So give kernel a chance to do internal house keeping.
131           Otherwise the following ptrace(2) calls will mess up user stack
132           since kernel will get confused about the bottom of the stack (%sp) */
133
134        exec_one_dummy_insn ();
135
136       /* write general purpose registers first! */
137       for ( ii=GPR0; ii<=GPR31; ++ii) {
138         ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii,
139                 *(int*)&registers[REGISTER_BYTE (ii)], 0);
140         if ( errno ) { 
141           perror ("ptrace write_gpr"); errno = 0;
142         }
143       }
144
145       /* write floating point registers now. */
146       for ( ii=0; ii < 32; ++ii) {
147         ptrace (PT_WRITE_FPR, inferior_pid, 
148                   (PTRACE_ARG3_TYPE) &registers[REGISTER_BYTE (FP0_REGNUM+ii)],
149                 FPR0+ii, 0);
150         if ( errno ) {
151           perror ("ptrace write_fpr"); errno = 0;
152         }
153       }
154
155       /* write special registers. */
156       for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii) {
157         ptrace (PT_WRITE_GPR, inferior_pid,
158                 (PTRACE_ARG3_TYPE) special_regs[ii],
159                 *(int*)&registers[REGISTER_BYTE (FIRST_SP_REGNUM+ii)], 0);
160         if ( errno ) {
161           perror ("ptrace write_gpr"); errno = 0;
162         }
163       }
164   }
165
166   /* else, a specific register number is given... */
167
168   else if (regno < FP0_REGNUM) {                /* a GPR */
169
170     ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno,
171                 *(int*)&registers[REGISTER_BYTE (regno)], 0);
172   }
173
174   else if (regno <= FPLAST_REGNUM) {            /* a FPR */
175     ptrace (PT_WRITE_FPR, inferior_pid, 
176             (PTRACE_ARG3_TYPE) &registers[REGISTER_BYTE (regno)],
177             regno-FP0_REGNUM+FPR0, 0);
178   }
179
180   else if (regno <= LAST_SP_REGNUM) {           /* a special register */
181
182     ptrace (PT_WRITE_GPR, inferior_pid,
183             (PTRACE_ARG3_TYPE) special_regs [regno-FIRST_SP_REGNUM],
184             *(int*)&registers[REGISTER_BYTE (regno)], 0);
185   }
186
187   else
188     fprintf (stderr, "Gdb error: register no %d not implemented.\n", regno);
189
190   if ( errno ) {
191     perror ("ptrace write");  errno = 0;
192   }
193 }
194
195 void
196 fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
197      char *core_reg_sect;
198      unsigned core_reg_size;
199      int which;
200      unsigned int reg_addr;     /* Unused in this version */
201 {
202   /* fetch GPRs and special registers from the first register section
203      in core bfd. */
204   if (which == 0) {
205
206     /* copy GPRs first. */
207     bcopy (core_reg_sect, registers, 32 * 4);
208
209     /* gdb's internal register template and bfd's register section layout
210        should share a common include file. FIXMEmgo */
211     /* then comes special registes. They are supposed to be in the same
212        order in gdb template and bfd `.reg' section. */
213     core_reg_sect += (32 * 4);
214     bcopy (core_reg_sect, &registers [REGISTER_BYTE (FIRST_SP_REGNUM)],
215                         (LAST_SP_REGNUM - FIRST_SP_REGNUM + 1) * 4);
216   }
217
218   /* fetch floating point registers from register section 2 in core bfd. */
219   else if (which == 2)
220     bcopy (core_reg_sect, &registers [REGISTER_BYTE (FP0_REGNUM)], 32 * 8);
221
222   else
223     fprintf (stderr, "Gdb error: unknown parameter to fetch_core_registers().\n");
224 }
225
226
227 /* Execute one dummy breakpoint instruction.  This way we give the kernel
228    a chance to do some housekeeping and update inferior's internal data,
229    including u_area. */
230 static void
231 exec_one_dummy_insn ()
232 {
233 #define DUMMY_INSN_ADDR (TEXT_SEGMENT_BASE)+0x200
234
235   unsigned long shadow;
236   unsigned int status, pid;
237
238   /* We plant one dummy breakpoint into DUMMY_INSN_ADDR address. We assume that
239      this address will never be executed again by the real code. */
240
241   target_insert_breakpoint (DUMMY_INSN_ADDR, &shadow);
242
243   errno = 0;
244   ptrace (PT_CONTINUE, inferior_pid, (PTRACE_ARG3_TYPE) DUMMY_INSN_ADDR, 0, 0);
245   if (errno)
246     perror ("pt_continue");
247
248   do {
249     pid = wait (&status);
250   } while (pid != inferior_pid);
251     
252   target_remove_breakpoint (DUMMY_INSN_ADDR, &shadow);
253 }
254
255
256 #else /* RS6000_TARGET */
257
258 /* FIXME: Kludge this til we separate host vs. target vs. native code. */
259
260 void
261 fetch_inferior_registers (regno)
262   int regno;
263 {
264 }
265
266 void
267 store_inferior_registers (regno)
268      int regno;
269 {
270 }
271
272 void
273 fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
274      char *core_reg_sect;
275      unsigned core_reg_size;
276      int which;
277      unsigned int reg_addr;     /* Unused in this version */
278 {
279 }
280
281 #endif /* RS6000_TARGET */
This page took 0.038353 seconds and 4 git commands to generate.