xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/m68k-bsd-nat.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /* Native-dependent code for Motorola 68000 BSD's.
2 
3    Copyright (C) 2004-2020 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 /* We define this to get types like register_t.  */
21 #include "defs.h"
22 #include "gdbcore.h"
23 #include "inferior.h"
24 #include "regcache.h"
25 
26 #include <sys/types.h>
27 #include <sys/ptrace.h>
28 #include <machine/reg.h>
29 
30 #include "m68k-tdep.h"
31 #include "inf-ptrace.h"
32 #include "nbsd-nat.h"
33 
34 struct m68k_bsd_nat_target final : public nbsd_nat_target
35 {
36   void fetch_registers (struct regcache *, int) override;
37   void store_registers (struct regcache *, int) override;
38 };
39 
40 static m68k_bsd_nat_target the_m68k_bsd_nat_target;
41 
42 static int
43 m68kbsd_gregset_supplies_p (int regnum)
44 {
45   return (regnum >= M68K_D0_REGNUM && regnum <= M68K_PC_REGNUM);
46 }
47 
48 static int
49 m68kbsd_fpregset_supplies_p (int regnum)
50 {
51   return (regnum >= M68K_FP0_REGNUM && regnum <= M68K_FPI_REGNUM);
52 }
53 
54 /* Supply the general-purpose registers stored in GREGS to REGCACHE.  */
55 
56 static void
57 m68kbsd_supply_gregset (struct regcache *regcache, const void *gregs)
58 {
59   const gdb_byte *regs = (const gdb_byte *) gregs;
60   int regnum;
61 
62   for (regnum = M68K_D0_REGNUM; regnum <= M68K_PC_REGNUM; regnum++)
63     regcache->raw_supply (regnum, regs + regnum * 4);
64 }
65 
66 /* Supply the floating-point registers stored in FPREGS to REGCACHE.  */
67 
68 static void
69 m68kbsd_supply_fpregset (struct regcache *regcache, const void *fpregs)
70 {
71   struct gdbarch *gdbarch = regcache->arch ();
72   const gdb_byte *regs = (const gdb_byte *) fpregs;
73   int regnum;
74 
75   for (regnum = M68K_FP0_REGNUM; regnum <= M68K_FPI_REGNUM; regnum++)
76     regcache->raw_supply (regnum,
77 			  regs + m68kbsd_fpreg_offset (gdbarch, regnum));
78 }
79 
80 /* Collect the general-purpose registers from REGCACHE and store them
81    in GREGS.  */
82 
83 static void
84 m68kbsd_collect_gregset (const struct regcache *regcache,
85 			 void *gregs, int regnum)
86 {
87   gdb_byte *regs = (gdb_byte *) gregs;
88   int i;
89 
90   for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++)
91     {
92       if (regnum == -1 || regnum == i)
93 	regcache->raw_collect (i, regs + i * 4);
94     }
95 }
96 
97 /* Collect the floating-point registers from REGCACHE and store them
98    in FPREGS.  */
99 
100 static void
101 m68kbsd_collect_fpregset (struct regcache *regcache,
102 			  void *fpregs, int regnum)
103 {
104   struct gdbarch *gdbarch = regcache->arch ();
105   gdb_byte *regs = (gdb_byte *)fpregs;
106   int i;
107 
108   for (i = M68K_FP0_REGNUM; i <= M68K_FPI_REGNUM; i++)
109     {
110       if (regnum == -1 || regnum == i)
111 	regcache->raw_collect (i, regs + m68kbsd_fpreg_offset (gdbarch, i));
112     }
113 }
114 
115 
116 /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
117    for all registers (including the floating-point registers).  */
118 
119 void
120 m68k_bsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
121 {
122   pid_t pid = regcache->ptid ().pid ();
123   int lwp = regcache->ptid ().lwp ();
124 
125   if (regnum == -1 || m68kbsd_gregset_supplies_p (regnum))
126     {
127       struct reg regs;
128 
129       if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
130 	perror_with_name (_("Couldn't get registers"));
131 
132       m68kbsd_supply_gregset (regcache, &regs);
133     }
134 
135   if (regnum == -1 || m68kbsd_fpregset_supplies_p (regnum))
136     {
137       struct fpreg fpregs;
138 
139       if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
140 	perror_with_name (_("Couldn't get floating point status"));
141 
142       m68kbsd_supply_fpregset (regcache, &fpregs);
143     }
144 }
145 
146 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
147    this for all registers (including the floating-point registers).  */
148 
149 void
150 m68k_bsd_nat_target::store_registers (struct regcache *regcache, int regnum)
151 {
152   pid_t pid = regcache->ptid ().pid ();
153   int lwp = regcache->ptid ().lwp ();
154 
155   if (regnum == -1 || m68kbsd_gregset_supplies_p (regnum))
156     {
157       struct reg regs;
158 
159       if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
160         perror_with_name (_("Couldn't get registers"));
161 
162       m68kbsd_collect_gregset (regcache, &regs, regnum);
163 
164       if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
165         perror_with_name (_("Couldn't write registers"));
166     }
167 
168   if (regnum == -1 || m68kbsd_fpregset_supplies_p (regnum))
169     {
170       struct fpreg fpregs;
171 
172       if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
173 	perror_with_name (_("Couldn't get floating point status"));
174 
175       m68kbsd_collect_fpregset (regcache, &fpregs, regnum);
176 
177       if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
178 	perror_with_name (_("Couldn't write floating point status"));
179     }
180 }
181 
182 
183 /* Support for debugging kernel virtual memory images.  */
184 
185 #include <machine/pcb.h>
186 
187 #include "bsd-kvm.h"
188 
189 /* OpenBSD doesn't have these.  */
190 #ifndef PCB_REGS_FP
191 #define PCB_REGS_FP 10
192 #endif
193 #ifndef PCB_REGS_SP
194 #define PCB_REGS_SP 11
195 #endif
196 
197 static int
198 m68kbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
199 {
200   int regnum, tmp;
201   int i = 0;
202 
203   /* The following is true for NetBSD 1.6.2:
204 
205      The pcb contains %d2...%d7, %a2...%a7 and %ps.  This accounts for
206      all callee-saved registers.  From this information we reconstruct
207      the register state as it would look when we just returned from
208      cpu_switch().  */
209 
210   /* The stack pointer shouldn't be zero.  */
211   if (pcb->pcb_regs[PCB_REGS_SP] == 0)
212     return 0;
213 
214   for (regnum = M68K_D2_REGNUM; regnum <= M68K_D7_REGNUM; regnum++)
215     regcache->raw_supply (regnum, &pcb->pcb_regs[i++]);
216   for (regnum = M68K_A2_REGNUM; regnum <= M68K_SP_REGNUM; regnum++)
217     regcache->raw_supply (regnum, &pcb->pcb_regs[i++]);
218 
219   tmp = pcb->pcb_ps & 0xffff;
220   regcache->raw_supply (M68K_PS_REGNUM, &tmp);
221 
222   read_memory (pcb->pcb_regs[PCB_REGS_FP] + 4, (gdb_byte *) &tmp, sizeof tmp);
223   regcache->raw_supply (M68K_PC_REGNUM, &tmp);
224 
225   return 1;
226 }
227 
228 void _initialize_m68kbsd_nat ();
229 void
230 _initialize_m68kbsd_nat ()
231 {
232   add_inf_child_target (&the_m68k_bsd_nat_target);
233 
234   /* Support debugging kernel virtual memory images.  */
235   bsd_kvm_add_target (m68kbsd_supply_pcb);
236 }
237