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