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) ®s, lwp) == -1) 65 perror_with_name (_("Couldn't get registers")); 66 67 mipsnbsd_supply_reg (regcache, (char *) ®s, 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) ®s, lwp) == -1) 96 perror_with_name (_("Couldn't get registers")); 97 98 mipsnbsd_fill_reg (regcache, (char *) ®s, regno); 99 100 if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 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