]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/ppcnbsd-nat.c
gdb/
[thirdparty/binutils-gdb.git] / gdb / ppcnbsd-nat.c
CommitLineData
def18405
MK
1/* Native-dependent code for NetBSD/powerpc.
2
0b302171 3 Copyright (C) 2002, 2004-2012 Free Software Foundation, Inc.
def18405 4
485721b1 5 Contributed by Wasabi Systems, Inc.
e42180d7
C
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
e42180d7
C
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
e42180d7 21
0baeab03
PA
22#include "defs.h"
23
e42180d7
C
24#include <sys/types.h>
25#include <sys/ptrace.h>
26#include <machine/reg.h>
69e9e646
NW
27#include <machine/frame.h>
28#include <machine/pcb.h>
e42180d7 29
69e9e646 30#include "gdbcore.h"
def18405 31#include "inferior.h"
69e9e646 32#include "regcache.h"
def18405
MK
33
34#include "gdb_assert.h"
e42180d7 35
485721b1
JT
36#include "ppc-tdep.h"
37#include "ppcnbsd-tdep.h"
def18405 38#include "bsd-kvm.h"
5bf970f9
AC
39#include "inf-ptrace.h"
40
485721b1 41/* Returns true if PT_GETREGS fetches this register. */
def18405 42
485721b1 43static int
206988c4 44getregs_supplies (struct gdbarch *gdbarch, int regnum)
e42180d7 45{
206988c4 46 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
485721b1 47
def18405
MK
48 return ((regnum >= tdep->ppc_gp0_regnum
49 && regnum < tdep->ppc_gp0_regnum + ppc_num_gprs)
50 || regnum == tdep->ppc_lr_regnum
51 || regnum == tdep->ppc_cr_regnum
52 || regnum == tdep->ppc_xer_regnum
53 || regnum == tdep->ppc_ctr_regnum
206988c4 54 || regnum == gdbarch_pc_regnum (gdbarch));
e42180d7
C
55}
56
485721b1 57/* Like above, but for PT_GETFPREGS. */
def18405 58
485721b1 59static int
206988c4 60getfpregs_supplies (struct gdbarch *gdbarch, int regnum)
e42180d7 61{
206988c4 62 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
e42180d7 63
383f0f5b
JB
64 /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
65 point registers. Traditionally, GDB's register set has still
66 listed the floating point registers for such machines, so this
67 code is harmless. However, the new E500 port actually omits the
68 floating point registers entirely from the register set --- they
69 don't even have register numbers assigned to them.
70
71 It's not clear to me how best to update this code, so this assert
72 will alert the first person to encounter the NetBSD/E500
73 combination to the problem. */
206988c4 74 gdb_assert (ppc_floating_point_unit_p (gdbarch));
383f0f5b 75
def18405
MK
76 return ((regnum >= tdep->ppc_fp0_regnum
77 && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs)
78 || regnum == tdep->ppc_fpscr_regnum);
485721b1 79}
e42180d7 80
5bf970f9 81static void
28439f5e
PA
82ppcnbsd_fetch_inferior_registers (struct target_ops *ops,
83 struct regcache *regcache, int regnum)
e42180d7 84{
206988c4
MD
85 struct gdbarch *gdbarch = get_regcache_arch (regcache);
86
87 if (regnum == -1 || getregs_supplies (gdbarch, regnum))
485721b1
JT
88 {
89 struct reg regs;
90
91 if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 92 (PTRACE_TYPE_ARG3) &regs, 0) == -1)
e2e0b3e5 93 perror_with_name (_("Couldn't get registers"));
485721b1 94
56be3814 95 ppc_supply_gregset (&ppcnbsd_gregset, regcache,
def18405 96 regnum, &regs, sizeof regs);
485721b1
JT
97 }
98
206988c4 99 if (regnum == -1 || getfpregs_supplies (gdbarch, regnum))
485721b1
JT
100 {
101 struct fpreg fpregs;
102
103 if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 104 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
e2e0b3e5 105 perror_with_name (_("Couldn't get FP registers"));
485721b1 106
56be3814 107 ppc_supply_fpregset (&ppcnbsd_fpregset, regcache,
def18405 108 regnum, &fpregs, sizeof fpregs);
485721b1 109 }
e42180d7
C
110}
111
5bf970f9 112static void
28439f5e
PA
113ppcnbsd_store_inferior_registers (struct target_ops *ops,
114 struct regcache *regcache, int regnum)
e42180d7 115{
206988c4
MD
116 struct gdbarch *gdbarch = get_regcache_arch (regcache);
117
118 if (regnum == -1 || getregs_supplies (gdbarch, regnum))
485721b1
JT
119 {
120 struct reg regs;
121
122 if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 123 (PTRACE_TYPE_ARG3) &regs, 0) == -1)
e2e0b3e5 124 perror_with_name (_("Couldn't get registers"));
485721b1 125
56be3814 126 ppc_collect_gregset (&ppcnbsd_gregset, regcache,
def18405 127 regnum, &regs, sizeof regs);
485721b1
JT
128
129 if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
9f8e0089 130 (PTRACE_TYPE_ARG3) &regs, 0) == -1)
e2e0b3e5 131 perror_with_name (_("Couldn't write registers"));
485721b1
JT
132 }
133
206988c4 134 if (regnum == -1 || getfpregs_supplies (gdbarch, regnum))
485721b1
JT
135 {
136 struct fpreg fpregs;
137
138 if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 139 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
e2e0b3e5 140 perror_with_name (_("Couldn't get FP registers"));
485721b1 141
56be3814 142 ppc_collect_fpregset (&ppcnbsd_fpregset, regcache,
def18405
MK
143 regnum, &fpregs, sizeof fpregs);
144
485721b1 145 if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
9f8e0089 146 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
e2e0b3e5 147 perror_with_name (_("Couldn't set FP registers"));
485721b1 148 }
e42180d7 149}
69e9e646
NW
150
151static int
152ppcnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
153{
154 struct switchframe sf;
155 struct callframe cf;
40a6adc1
MD
156 struct gdbarch *gdbarch = get_regcache_arch (regcache);
157 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
69e9e646
NW
158 int i;
159
160 /* The stack pointer shouldn't be zero. */
161 if (pcb->pcb_sp == 0)
162 return 0;
163
def18405 164 read_memory (pcb->pcb_sp, (gdb_byte *)&sf, sizeof sf);
69e9e646
NW
165 regcache_raw_supply (regcache, tdep->ppc_cr_regnum, &sf.cr);
166 regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 2, &sf.fixreg2);
167 for (i = 0 ; i < 19 ; i++)
168 regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 13 + i,
169 &sf.fixreg[i]);
170
def18405 171 read_memory(sf.sp, (gdb_byte *)&cf, sizeof(cf));
69e9e646
NW
172 regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 30, &cf.r30);
173 regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 31, &cf.r31);
174 regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 1, &cf.sp);
175
def18405 176 read_memory(cf.sp, (gdb_byte *)&cf, sizeof(cf));
69e9e646 177 regcache_raw_supply (regcache, tdep->ppc_lr_regnum, &cf.lr);
40a6adc1 178 regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch), &cf.lr);
69e9e646
NW
179
180 return 1;
181}
182
183/* Provide a prototype to silence -Wmissing-prototypes. */
184void _initialize_ppcnbsd_nat (void);
185
186void
187_initialize_ppcnbsd_nat (void)
188{
5bf970f9 189 struct target_ops *t;
def18405 190
69e9e646
NW
191 /* Support debugging kernel virtual memory images. */
192 bsd_kvm_add_target (ppcnbsd_supply_pcb);
def18405 193
5bf970f9
AC
194 /* Add in local overrides. */
195 t = inf_ptrace_target ();
196 t->to_fetch_registers = ppcnbsd_fetch_inferior_registers;
197 t->to_store_registers = ppcnbsd_store_inferior_registers;
198 add_target (t);
69e9e646 199}