1 /* IBM RS/6000 native-dependent code for GDB, the GNU debugger.
2 Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
24 #include <sys/ptrace.h>
27 #include <sys/param.h>
31 #include <sys/ioctl.h>
42 exec_one_dummy_insn PARAMS ((void));
44 /* Conversion from gdb-to-system special purpose register numbers.. */
46 static int special_regs[] = {
57 fetch_inferior_registers (regno)
61 extern char registers[];
63 if (regno < 0) { /* for all registers */
65 /* read 32 general purpose registers. */
67 for (ii=0; ii < 32; ++ii)
68 *(int*)®isters[REGISTER_BYTE (ii)] =
69 ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii, 0, 0);
71 /* read general purpose floating point registers. */
73 for (ii=0; ii < 32; ++ii)
74 ptrace (PT_READ_FPR, inferior_pid,
75 (PTRACE_ARG3_TYPE) ®isters [REGISTER_BYTE (FP0_REGNUM+ii)],
78 /* read special registers. */
79 for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii)
80 *(int*)®isters[REGISTER_BYTE (FIRST_SP_REGNUM+ii)] =
81 ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) special_regs[ii],
88 /* else an individual register is addressed. */
90 else if (regno < FP0_REGNUM) { /* a GPR */
91 *(int*)®isters[REGISTER_BYTE (regno)] =
92 ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno, 0, 0);
94 else if (regno <= FPLAST_REGNUM) { /* a FPR */
95 ptrace (PT_READ_FPR, inferior_pid,
96 (PTRACE_ARG3_TYPE) ®isters [REGISTER_BYTE (regno)],
97 (regno-FP0_REGNUM+FPR0), 0);
99 else if (regno <= LAST_SP_REGNUM) { /* a special register */
100 *(int*)®isters[REGISTER_BYTE (regno)] =
101 ptrace (PT_READ_GPR, inferior_pid,
102 (PTRACE_ARG3_TYPE) special_regs[regno-FIRST_SP_REGNUM], 0, 0);
105 fprintf (stderr, "gdb error: register no %d not implemented.\n", regno);
107 register_valid [regno] = 1;
110 /* Store our register values back into the inferior.
111 If REGNO is -1, do this for all registers.
112 Otherwise, REGNO specifies which register (so we can save time). */
115 store_inferior_registers (regno)
118 extern char registers[];
122 if (regno == -1) { /* for all registers.. */
125 /* execute one dummy instruction (which is a breakpoint) in inferior
126 process. So give kernel a chance to do internal house keeping.
127 Otherwise the following ptrace(2) calls will mess up user stack
128 since kernel will get confused about the bottom of the stack (%sp) */
130 exec_one_dummy_insn ();
132 /* write general purpose registers first! */
133 for ( ii=GPR0; ii<=GPR31; ++ii) {
134 ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii,
135 *(int*)®isters[REGISTER_BYTE (ii)], 0);
137 perror ("ptrace write_gpr"); errno = 0;
141 /* write floating point registers now. */
142 for ( ii=0; ii < 32; ++ii) {
143 ptrace (PT_WRITE_FPR, inferior_pid,
144 (PTRACE_ARG3_TYPE) ®isters[REGISTER_BYTE (FP0_REGNUM+ii)],
147 perror ("ptrace write_fpr"); errno = 0;
151 /* write special registers. */
152 for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii) {
153 ptrace (PT_WRITE_GPR, inferior_pid,
154 (PTRACE_ARG3_TYPE) special_regs[ii],
155 *(int*)®isters[REGISTER_BYTE (FIRST_SP_REGNUM+ii)], 0);
157 perror ("ptrace write_gpr"); errno = 0;
162 /* else, a specific register number is given... */
164 else if (regno < FP0_REGNUM) { /* a GPR */
166 ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno,
167 *(int*)®isters[REGISTER_BYTE (regno)], 0);
170 else if (regno <= FPLAST_REGNUM) { /* a FPR */
171 ptrace (PT_WRITE_FPR, inferior_pid,
172 (PTRACE_ARG3_TYPE) ®isters[REGISTER_BYTE (regno)],
173 regno-FP0_REGNUM+FPR0, 0);
176 else if (regno <= LAST_SP_REGNUM) { /* a special register */
178 ptrace (PT_WRITE_GPR, inferior_pid,
179 (PTRACE_ARG3_TYPE) special_regs [regno-FIRST_SP_REGNUM],
180 *(int*)®isters[REGISTER_BYTE (regno)], 0);
184 fprintf (stderr, "Gdb error: register no %d not implemented.\n", regno);
187 perror ("ptrace write"); errno = 0;
191 /* Execute one dummy breakpoint instruction. This way we give the kernel
192 a chance to do some housekeeping and update inferior's internal data,
195 exec_one_dummy_insn ()
197 #define DUMMY_INSN_ADDR (TEXT_SEGMENT_BASE)+0x200
199 unsigned long shadow;
200 unsigned int status, pid;
202 /* We plant one dummy breakpoint into DUMMY_INSN_ADDR address. We assume that
203 this address will never be executed again by the real code. */
205 target_insert_breakpoint (DUMMY_INSN_ADDR, &shadow);
208 ptrace (PT_CONTINUE, inferior_pid, (PTRACE_ARG3_TYPE) DUMMY_INSN_ADDR, 0, 0);
210 perror ("pt_continue");
213 pid = wait (&status);
214 } while (pid != inferior_pid);
216 target_remove_breakpoint (DUMMY_INSN_ADDR, &shadow);
220 fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
222 unsigned core_reg_size;
224 unsigned int reg_addr; /* Unused in this version */
226 /* fetch GPRs and special registers from the first register section
230 /* copy GPRs first. */
231 memcpy (registers, core_reg_sect, 32 * 4);
233 /* gdb's internal register template and bfd's register section layout
234 should share a common include file. FIXMEmgo */
235 /* then comes special registes. They are supposed to be in the same
236 order in gdb template and bfd `.reg' section. */
237 core_reg_sect += (32 * 4);
238 memcpy (®isters [REGISTER_BYTE (FIRST_SP_REGNUM)], core_reg_sect,
239 (LAST_SP_REGNUM - FIRST_SP_REGNUM + 1) * 4);
242 /* fetch floating point registers from register section 2 in core bfd. */
244 memcpy (®isters [REGISTER_BYTE (FP0_REGNUM)], core_reg_sect, 32 * 8);
247 fprintf (stderr, "Gdb error: unknown parameter to fetch_core_registers().\n");