1/* Native-dependent code for NetBSD/powerpc.
2
3   Copyright (C) 2002-2023 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/* We define this to get types like register_t.  */
23#include "defs.h"
24
25#include <sys/types.h>
26#include <sys/ptrace.h>
27#include <machine/reg.h>
28#include <machine/frame.h>
29#include <machine/pcb.h>
30
31#include "gdbcore.h"
32#include "inferior.h"
33#include "regcache.h"
34
35#include "ppc-tdep.h"
36#include "ppc-netbsd-tdep.h"
37#include "bsd-kvm.h"
38#include "inf-ptrace.h"
39#include "netbsd-nat.h"
40
41struct ppc_nbsd_nat_target final : public nbsd_nat_target
42{
43  void fetch_registers (struct regcache *, int) override;
44  void store_registers (struct regcache *, int) override;
45};
46
47static ppc_nbsd_nat_target the_ppc_nbsd_nat_target;
48
49/* Returns true if PT_GETREGS fetches this register.  */
50
51static int
52getregs_supplies (struct gdbarch *gdbarch, int regnum)
53{
54  ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
55
56  return ((regnum >= tdep->ppc_gp0_regnum
57	   && regnum < tdep->ppc_gp0_regnum + ppc_num_gprs)
58	  || regnum == tdep->ppc_lr_regnum
59	  || regnum == tdep->ppc_cr_regnum
60	  || regnum == tdep->ppc_xer_regnum
61	  || regnum == tdep->ppc_ctr_regnum
62	  || regnum == gdbarch_pc_regnum (gdbarch));
63}
64
65/* Like above, but for PT_GETFPREGS.  */
66
67static int
68getfpregs_supplies (struct gdbarch *gdbarch, int regnum)
69{
70  ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
71
72  /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
73     point registers.  Traditionally, GDB's register set has still
74     listed the floating point registers for such machines, so this
75     code is harmless.  However, the new E500 port actually omits the
76     floating point registers entirely from the register set --- they
77     don't even have register numbers assigned to them.
78
79     It's not clear to me how best to update this code, so this assert
80     will alert the first person to encounter the NetBSD/E500
81     combination to the problem.  */
82  gdb_assert (ppc_floating_point_unit_p (gdbarch));
83
84  return ((regnum >= tdep->ppc_fp0_regnum
85	   && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs)
86	  || regnum == tdep->ppc_fpscr_regnum);
87}
88
89void
90ppc_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
91{
92  struct gdbarch *gdbarch = regcache->arch ();
93  pid_t pid = regcache->ptid ().pid ();
94  int lwp = regcache->ptid ().lwp ();
95
96  if (regnum == -1 || getregs_supplies (gdbarch, regnum))
97    {
98      struct reg regs;
99
100      if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
101	perror_with_name (_("Couldn't get registers"));
102
103      ppc_supply_gregset (&ppcnbsd_gregset, regcache,
104			  regnum, &regs, sizeof regs);
105    }
106
107  if (regnum == -1 || getfpregs_supplies (gdbarch, regnum))
108    {
109      struct fpreg fpregs;
110
111      if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
112	perror_with_name (_("Couldn't get FP registers"));
113
114      ppc_supply_fpregset (&ppcnbsd_fpregset, regcache,
115			   regnum, &fpregs, sizeof fpregs);
116    }
117}
118
119void
120ppc_nbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
121{
122  struct gdbarch *gdbarch = regcache->arch ();
123  pid_t pid = regcache->ptid ().pid ();
124  int lwp = regcache->ptid ().lwp ();
125
126  if (regnum == -1 || getregs_supplies (gdbarch, regnum))
127    {
128      struct reg regs;
129
130      if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
131	perror_with_name (_("Couldn't get registers"));
132
133      ppc_collect_gregset (&ppcnbsd_gregset, regcache,
134			   regnum, &regs, sizeof regs);
135
136      if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
137	perror_with_name (_("Couldn't write registers"));
138    }
139
140  if (regnum == -1 || getfpregs_supplies (gdbarch, regnum))
141    {
142      struct fpreg fpregs;
143
144      if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
145	perror_with_name (_("Couldn't get FP registers"));
146
147      ppc_collect_fpregset (&ppcnbsd_fpregset, regcache,
148			    regnum, &fpregs, sizeof fpregs);
149
150      if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
151	perror_with_name (_("Couldn't set FP registers"));
152    }
153}
154
155static int
156ppcnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
157{
158  struct switchframe sf;
159  struct callframe cf;
160  struct gdbarch *gdbarch = regcache->arch ();
161  ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
162  int i;
163
164  /* The stack pointer shouldn't be zero.  */
165  if (pcb->pcb_sp == 0)
166    return 0;
167
168  read_memory (pcb->pcb_sp, (gdb_byte *)&sf, sizeof sf);
169  regcache->raw_supply (tdep->ppc_cr_regnum, &sf.sf_cr);
170  regcache->raw_supply (tdep->ppc_gp0_regnum + 2, &sf.sf_fixreg2);
171  for (i = 0 ; i < 19 ; i++)
172    regcache->raw_supply (tdep->ppc_gp0_regnum + 13 + i, &sf.sf_fixreg[i]);
173
174  read_memory(sf.sf_sp, (gdb_byte *)&cf, sizeof(cf));
175  regcache->raw_supply (tdep->ppc_gp0_regnum + 30, &cf.cf_r30);
176  regcache->raw_supply (tdep->ppc_gp0_regnum + 31, &cf.cf_r31);
177  regcache->raw_supply (tdep->ppc_gp0_regnum + 1, &cf.cf_sp);
178
179  read_memory(cf.cf_sp, (gdb_byte *)&cf, sizeof(cf));
180  regcache->raw_supply (tdep->ppc_lr_regnum, &cf.cf_lr);
181  regcache->raw_supply (gdbarch_pc_regnum (gdbarch), &cf.cf_lr);
182
183  return 1;
184}
185
186void _initialize_ppcnbsd_nat ();
187void
188_initialize_ppcnbsd_nat ()
189{
190  /* Support debugging kernel virtual memory images.  */
191  bsd_kvm_add_target (ppcnbsd_supply_pcb);
192
193  add_inf_child_target (&the_ppc_nbsd_nat_target);
194}
195