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) ®s, lwp) == -1) 130 perror_with_name (_("Couldn't get registers")); 131 132 m68kbsd_supply_gregset (regcache, ®s); 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) ®s, lwp) == -1) 160 perror_with_name (_("Couldn't get registers")); 161 162 m68kbsd_collect_gregset (regcache, ®s, regnum); 163 164 if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 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