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