gas/testsuite/
[external/binutils.git] / gdb / ppcnbsd-nat.c
1 /* Native-dependent code for NetBSD/powerpc.
2
3    Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008, 2009
4    Free Software Foundation, Inc.
5
6    Contributed by Wasabi Systems, Inc.
7
8    This file is part of GDB.
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
23 #include <sys/types.h>
24 #include <sys/ptrace.h>
25 #include <machine/reg.h>
26 #include <machine/frame.h>
27 #include <machine/pcb.h>
28
29 #include "defs.h"
30 #include "gdbcore.h"
31 #include "inferior.h"
32 #include "regcache.h"
33
34 #include "gdb_assert.h"
35
36 #include "ppc-tdep.h"
37 #include "ppcnbsd-tdep.h"
38 #include "bsd-kvm.h"
39 #include "inf-ptrace.h"
40
41 /* Returns true if PT_GETREGS fetches this register.  */
42
43 static int
44 getregs_supplies (struct gdbarch *gdbarch, int regnum)
45 {
46   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
47
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
54           || regnum == gdbarch_pc_regnum (gdbarch));
55 }
56
57 /* Like above, but for PT_GETFPREGS.  */
58
59 static int
60 getfpregs_supplies (struct gdbarch *gdbarch, int regnum)
61 {
62   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
63
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.  */
74   gdb_assert (ppc_floating_point_unit_p (gdbarch));
75
76   return ((regnum >= tdep->ppc_fp0_regnum
77            && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs)
78           || regnum == tdep->ppc_fpscr_regnum);
79 }
80
81 static void
82 ppcnbsd_fetch_inferior_registers (struct target_ops *ops,
83                                   struct regcache *regcache, int regnum)
84 {
85   struct gdbarch *gdbarch = get_regcache_arch (regcache);
86
87   if (regnum == -1 || getregs_supplies (gdbarch, regnum))
88     {
89       struct reg regs;
90
91       if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
92                   (PTRACE_TYPE_ARG3) &regs, 0) == -1)
93         perror_with_name (_("Couldn't get registers"));
94
95       ppc_supply_gregset (&ppcnbsd_gregset, regcache,
96                           regnum, &regs, sizeof regs);
97     }
98
99   if (regnum == -1 || getfpregs_supplies (gdbarch, regnum))
100     {
101       struct fpreg fpregs;
102
103       if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
104                   (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
105         perror_with_name (_("Couldn't get FP registers"));
106
107       ppc_supply_fpregset (&ppcnbsd_fpregset, regcache,
108                            regnum, &fpregs, sizeof fpregs);
109     }
110 }
111
112 static void
113 ppcnbsd_store_inferior_registers (struct target_ops *ops,
114                                   struct regcache *regcache, int regnum)
115 {
116   struct gdbarch *gdbarch = get_regcache_arch (regcache);
117
118   if (regnum == -1 || getregs_supplies (gdbarch, regnum))
119     {
120       struct reg regs;
121
122       if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
123                   (PTRACE_TYPE_ARG3) &regs, 0) == -1)
124         perror_with_name (_("Couldn't get registers"));
125
126       ppc_collect_gregset (&ppcnbsd_gregset, regcache,
127                            regnum, &regs, sizeof regs);
128
129       if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
130                   (PTRACE_TYPE_ARG3) &regs, 0) == -1)
131         perror_with_name (_("Couldn't write registers"));
132     }
133
134   if (regnum == -1 || getfpregs_supplies (gdbarch, regnum))
135     {
136       struct fpreg fpregs;
137
138       if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
139                   (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
140         perror_with_name (_("Couldn't get FP registers"));
141
142       ppc_collect_fpregset (&ppcnbsd_fpregset, regcache,
143                             regnum, &fpregs, sizeof fpregs);
144
145       if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
146                   (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
147         perror_with_name (_("Couldn't set FP registers"));
148     }
149 }
150
151 static int
152 ppcnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
153 {
154   struct switchframe sf;
155   struct callframe cf;
156   struct gdbarch *gdbarch = get_regcache_arch (regcache);
157   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
158   int i;
159
160   /* The stack pointer shouldn't be zero.  */
161   if (pcb->pcb_sp == 0)
162     return 0;
163
164   read_memory (pcb->pcb_sp, (gdb_byte *)&sf, sizeof sf);
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
171   read_memory(sf.sp, (gdb_byte *)&cf, sizeof(cf));
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
176   read_memory(cf.sp, (gdb_byte *)&cf, sizeof(cf));
177   regcache_raw_supply (regcache, tdep->ppc_lr_regnum, &cf.lr);
178   regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch), &cf.lr);
179
180   return 1;
181 }
182
183 /* Provide a prototype to silence -Wmissing-prototypes.  */
184 void _initialize_ppcnbsd_nat (void);
185
186 void
187 _initialize_ppcnbsd_nat (void)
188 {
189   struct target_ops *t;
190
191   /* Support debugging kernel virtual memory images.  */
192   bsd_kvm_add_target (ppcnbsd_supply_pcb);
193
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);
199 }