xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/mips-netbsd-nat.c (revision 8e33eff89e26cf71871ead62f0d5063e1313c33a)
1 /* Native-dependent code for MIPS systems running NetBSD.
2 
3    Copyright (C) 2000-2023 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 "inferior.h"
23 #include "regcache.h"
24 #include "target.h"
25 
26 #include <sys/types.h>
27 #include <sys/ptrace.h>
28 #include <machine/reg.h>
29 #include <machine/pcb.h>
30 
31 #include "mips-tdep.h"
32 #include "mips-netbsd-tdep.h"
33 #include "netbsd-nat.h"
34 #include "inf-ptrace.h"
35 #include "bsd-kvm.h"
36 
37 class mips_nbsd_nat_target final : public nbsd_nat_target
38 {
39   void fetch_registers (struct regcache *, int) override;
40   void store_registers (struct regcache *, int) override;
41 };
42 
43 static mips_nbsd_nat_target the_mips_nbsd_nat_target;
44 
45 /* Determine if PT_GETREGS fetches this register.  */
46 static int
47 getregs_supplies (struct gdbarch *gdbarch, int regno)
48 {
49   return ((regno) >= MIPS_ZERO_REGNUM
50 	  && (regno) <= gdbarch_pc_regnum (gdbarch));
51 }
52 
53 void
54 mips_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
55 {
56   pid_t pid = regcache->ptid ().pid ();
57   int lwp = regcache->ptid ().lwp ();
58 
59   struct gdbarch *gdbarch = regcache->arch ();
60   if (regno == -1 || getregs_supplies (gdbarch, regno))
61     {
62       struct reg regs;
63 
64       if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
65 	perror_with_name (_("Couldn't get registers"));
66 
67       mipsnbsd_supply_reg (regcache, (char *) &regs, regno);
68       if (regno != -1)
69 	return;
70     }
71 
72   if (regno == -1
73       || regno >= gdbarch_fp0_regnum (regcache->arch ()))
74     {
75       struct fpreg fpregs;
76 
77       if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
78 	perror_with_name (_("Couldn't get floating point status"));
79 
80       mipsnbsd_supply_fpreg (regcache, (char *) &fpregs, regno);
81     }
82 }
83 
84 void
85 mips_nbsd_nat_target::store_registers (struct regcache *regcache, int regno)
86 {
87   pid_t pid = regcache->ptid ().pid ();
88   int lwp = regcache->ptid ().lwp ();
89 
90   struct gdbarch *gdbarch = regcache->arch ();
91   if (regno == -1 || getregs_supplies (gdbarch, regno))
92     {
93       struct reg regs;
94 
95       if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
96 	perror_with_name (_("Couldn't get registers"));
97 
98       mipsnbsd_fill_reg (regcache, (char *) &regs, regno);
99 
100       if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
101 	perror_with_name (_("Couldn't write registers"));
102 
103       if (regno != -1)
104 	return;
105     }
106 
107   if (regno == -1
108       || regno >= gdbarch_fp0_regnum (regcache->arch ()))
109     {
110       struct fpreg fpregs;
111 
112       if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
113 	perror_with_name (_("Couldn't get floating point status"));
114 
115       mipsnbsd_fill_fpreg (regcache, (char *) &fpregs, regno);
116 
117       if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
118 	perror_with_name (_("Couldn't write floating point status"));
119     }
120 }
121 
122 static int
123 mipsnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
124 {
125   struct label_t sf;
126 
127   sf = pcb->pcb_context;
128 
129   /* really should test for n{32,64} abi for this register
130      unless this is purely the "n" ABI */
131 
132   regcache->raw_supply (MIPS_S0_REGNUM, &sf.val[_L_S0]);
133   regcache->raw_supply (MIPS_S1_REGNUM, &sf.val[_L_S1]);
134   regcache->raw_supply (MIPS_S2_REGNUM, &sf.val[_L_S2]);
135   regcache->raw_supply (MIPS_S3_REGNUM, &sf.val[_L_S3]);
136   regcache->raw_supply (MIPS_S4_REGNUM, &sf.val[_L_S4]);
137   regcache->raw_supply (MIPS_S5_REGNUM, &sf.val[_L_S5]);
138   regcache->raw_supply (MIPS_S6_REGNUM, &sf.val[_L_S6]);
139   regcache->raw_supply (MIPS_S7_REGNUM, &sf.val[_L_S7]);
140 
141   regcache->raw_supply (MIPS_S8_REGNUM, &sf.val[_L_S8]);
142 
143   regcache->raw_supply (MIPS_T8_REGNUM, &sf.val[_L_T8]);
144 
145   regcache->raw_supply (MIPS_GP_REGNUM, &sf.val[_L_GP]);
146 
147   regcache->raw_supply (MIPS_SP_REGNUM, &sf.val[_L_SP]);
148   regcache->raw_supply (MIPS_RA_REGNUM, &sf.val[_L_RA]);
149   regcache->raw_supply (MIPS_PS_REGNUM, &sf.val[_L_SR]);
150 
151   /* provide the return address of the savectx as the current pc */
152   regcache->raw_supply (MIPS_EMBED_PC_REGNUM, &sf.val[_L_RA]);
153 
154   return 0;
155 }
156 
157 void _initialize_mipsnbsd_nat ();
158 void
159 _initialize_mipsnbsd_nat ()
160 {
161   add_inf_child_target (&the_mips_nbsd_nat_target);
162   bsd_kvm_add_target (mipsnbsd_supply_pcb);
163 }
164