152ba75afSkettenis /* Native-dependent code for Motorola 68000 BSD's.
252ba75afSkettenis
352ba75afSkettenis Copyright 2004 Free Software Foundation, Inc.
452ba75afSkettenis
552ba75afSkettenis This file is part of GDB.
652ba75afSkettenis
752ba75afSkettenis This program is free software; you can redistribute it and/or modify
852ba75afSkettenis it under the terms of the GNU General Public License as published by
952ba75afSkettenis the Free Software Foundation; either version 2 of the License, or
1052ba75afSkettenis (at your option) any later version.
1152ba75afSkettenis
1252ba75afSkettenis This program is distributed in the hope that it will be useful,
1352ba75afSkettenis but WITHOUT ANY WARRANTY; without even the implied warranty of
1452ba75afSkettenis MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1552ba75afSkettenis GNU General Public License for more details.
1652ba75afSkettenis
1752ba75afSkettenis You should have received a copy of the GNU General Public License
1852ba75afSkettenis along with this program; if not, write to the Free Software
1952ba75afSkettenis Foundation, Inc., 59 Temple Place - Suite 330,
2052ba75afSkettenis Boston, MA 02111-1307, USA. */
2152ba75afSkettenis
2252ba75afSkettenis #include "defs.h"
2352ba75afSkettenis #include "gdbcore.h"
2452ba75afSkettenis #include "inferior.h"
2552ba75afSkettenis #include "regcache.h"
2652ba75afSkettenis
2752ba75afSkettenis #include "gdb_assert.h"
2852ba75afSkettenis #include <sys/types.h>
2952ba75afSkettenis #include <sys/ptrace.h>
3052ba75afSkettenis #include <machine/reg.h>
3152ba75afSkettenis
3252ba75afSkettenis #include "m68k-tdep.h"
33*28dc8cddSkettenis #include "inf-ptrace.h"
3452ba75afSkettenis
3552ba75afSkettenis static int
m68kbsd_gregset_supplies_p(int regnum)3652ba75afSkettenis m68kbsd_gregset_supplies_p (int regnum)
3752ba75afSkettenis {
3852ba75afSkettenis return (regnum >= M68K_D0_REGNUM && regnum <= M68K_PC_REGNUM);
3952ba75afSkettenis }
4052ba75afSkettenis
4152ba75afSkettenis static int
m68kbsd_fpregset_supplies_p(int regnum)4252ba75afSkettenis m68kbsd_fpregset_supplies_p (int regnum)
4352ba75afSkettenis {
4452ba75afSkettenis return (regnum >= M68K_FP0_REGNUM && regnum <= M68K_FPI_REGNUM);
4552ba75afSkettenis }
4652ba75afSkettenis
4752ba75afSkettenis /* Supply the general-purpose registers stored in GREGS to REGCACHE. */
4852ba75afSkettenis
4952ba75afSkettenis static void
m68kbsd_supply_gregset(struct regcache * regcache,const void * gregs)5052ba75afSkettenis m68kbsd_supply_gregset (struct regcache *regcache, const void *gregs)
5152ba75afSkettenis {
5252ba75afSkettenis const char *regs = gregs;
5352ba75afSkettenis int regnum;
5452ba75afSkettenis
5552ba75afSkettenis for (regnum = M68K_D0_REGNUM; regnum <= M68K_PC_REGNUM; regnum++)
5652ba75afSkettenis regcache_raw_supply (regcache, regnum, regs + regnum * 4);
5752ba75afSkettenis }
5852ba75afSkettenis
5952ba75afSkettenis /* Supply the floating-point registers stored in FPREGS to REGCACHE. */
6052ba75afSkettenis
6152ba75afSkettenis static void
m68kbsd_supply_fpregset(struct regcache * regcache,const void * fpregs)6252ba75afSkettenis m68kbsd_supply_fpregset (struct regcache *regcache, const void *fpregs)
6352ba75afSkettenis {
6452ba75afSkettenis const char *regs = fpregs;
6552ba75afSkettenis int regnum;
6652ba75afSkettenis
6752ba75afSkettenis for (regnum = M68K_FP0_REGNUM; regnum <= M68K_FPI_REGNUM; regnum++)
6852ba75afSkettenis regcache_raw_supply (regcache, regnum,
6952ba75afSkettenis regs + m68kbsd_fpreg_offset (regnum));
7052ba75afSkettenis }
7152ba75afSkettenis
7252ba75afSkettenis /* Collect the general-purpose registers from REGCACHE and store them
7352ba75afSkettenis in GREGS. */
7452ba75afSkettenis
7552ba75afSkettenis static void
m68kbsd_collect_gregset(const struct regcache * regcache,void * gregs,int regnum)7652ba75afSkettenis m68kbsd_collect_gregset (const struct regcache *regcache,
7752ba75afSkettenis void *gregs, int regnum)
7852ba75afSkettenis {
7952ba75afSkettenis char *regs = gregs;
8052ba75afSkettenis int i;
8152ba75afSkettenis
8252ba75afSkettenis for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++)
8352ba75afSkettenis {
8452ba75afSkettenis if (regnum == -1 || regnum == i)
851505a8a8Skettenis regcache_raw_collect (regcache, i, regs + i * 4);
8652ba75afSkettenis }
8752ba75afSkettenis }
8852ba75afSkettenis
8952ba75afSkettenis /* Collect the floating-point registers from REGCACHE and store them
9052ba75afSkettenis in FPREGS. */
9152ba75afSkettenis
9252ba75afSkettenis static void
m68kbsd_collect_fpregset(struct regcache * regcache,void * fpregs,int regnum)9352ba75afSkettenis m68kbsd_collect_fpregset (struct regcache *regcache,
9452ba75afSkettenis void *fpregs, int regnum)
9552ba75afSkettenis {
9652ba75afSkettenis char *regs = fpregs;
9752ba75afSkettenis int i;
9852ba75afSkettenis
9952ba75afSkettenis for (i = M68K_FP0_REGNUM; i <= M68K_FPI_REGNUM; i++)
10052ba75afSkettenis {
10152ba75afSkettenis if (regnum == -1 || regnum == i)
1021505a8a8Skettenis regcache_raw_collect (regcache, i, regs + m68kbsd_fpreg_offset (i));
10352ba75afSkettenis }
10452ba75afSkettenis }
10552ba75afSkettenis
10652ba75afSkettenis
10752ba75afSkettenis /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
10852ba75afSkettenis for all registers (including the floating-point registers). */
10952ba75afSkettenis
110*28dc8cddSkettenis static void
m68kbsd_fetch_inferior_registers(int regnum)111*28dc8cddSkettenis m68kbsd_fetch_inferior_registers (int regnum)
11252ba75afSkettenis {
11352ba75afSkettenis if (regnum == -1 || m68kbsd_gregset_supplies_p (regnum))
11452ba75afSkettenis {
11552ba75afSkettenis struct reg regs;
11652ba75afSkettenis
11752ba75afSkettenis if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
11863addd46Skettenis (PTRACE_TYPE_ARG3) ®s, 0) == -1)
119*28dc8cddSkettenis perror_with_name (_("Couldn't get registers"));
12052ba75afSkettenis
12152ba75afSkettenis m68kbsd_supply_gregset (current_regcache, ®s);
12252ba75afSkettenis }
12352ba75afSkettenis
12452ba75afSkettenis if (regnum == -1 || m68kbsd_fpregset_supplies_p (regnum))
12552ba75afSkettenis {
12652ba75afSkettenis struct fpreg fpregs;
12752ba75afSkettenis
12852ba75afSkettenis if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
12963addd46Skettenis (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
130*28dc8cddSkettenis perror_with_name (_("Couldn't get floating point status"));
13152ba75afSkettenis
13252ba75afSkettenis m68kbsd_supply_fpregset (current_regcache, &fpregs);
13352ba75afSkettenis }
13452ba75afSkettenis }
13552ba75afSkettenis
13652ba75afSkettenis /* Store register REGNUM back into the inferior. If REGNUM is -1, do
13752ba75afSkettenis this for all registers (including the floating-point registers). */
13852ba75afSkettenis
139*28dc8cddSkettenis static void
m68kbsd_store_inferior_registers(int regnum)140*28dc8cddSkettenis m68kbsd_store_inferior_registers (int regnum)
14152ba75afSkettenis {
14252ba75afSkettenis if (regnum == -1 || m68kbsd_gregset_supplies_p (regnum))
14352ba75afSkettenis {
14452ba75afSkettenis struct reg regs;
14552ba75afSkettenis
14652ba75afSkettenis if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
14763addd46Skettenis (PTRACE_TYPE_ARG3) ®s, 0) == -1)
148*28dc8cddSkettenis perror_with_name (_("Couldn't get registers"));
14952ba75afSkettenis
15052ba75afSkettenis m68kbsd_collect_gregset (current_regcache, ®s, regnum);
15152ba75afSkettenis
15252ba75afSkettenis if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
15363addd46Skettenis (PTRACE_TYPE_ARG3) ®s, 0) == -1)
154*28dc8cddSkettenis perror_with_name (_("Couldn't write registers"));
15552ba75afSkettenis }
15652ba75afSkettenis
15752ba75afSkettenis if (regnum == -1 || m68kbsd_fpregset_supplies_p (regnum))
15852ba75afSkettenis {
15952ba75afSkettenis struct fpreg fpregs;
16052ba75afSkettenis
16152ba75afSkettenis if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
16263addd46Skettenis (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
163*28dc8cddSkettenis perror_with_name (_("Couldn't get floating point status"));
16452ba75afSkettenis
16552ba75afSkettenis m68kbsd_collect_fpregset (current_regcache, &fpregs, regnum);
16652ba75afSkettenis
16752ba75afSkettenis if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
16863addd46Skettenis (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
169*28dc8cddSkettenis perror_with_name (_("Couldn't write floating point status"));
17052ba75afSkettenis }
17152ba75afSkettenis }
17252ba75afSkettenis
17352ba75afSkettenis
17452ba75afSkettenis /* Support for debugging kernel virtual memory images. */
17552ba75afSkettenis
17652ba75afSkettenis #include <sys/types.h>
17752ba75afSkettenis #include <machine/pcb.h>
17852ba75afSkettenis
17952ba75afSkettenis #include "bsd-kvm.h"
18052ba75afSkettenis
18152ba75afSkettenis /* OpenBSD doesn't have these. */
18252ba75afSkettenis #ifndef PCB_REGS_FP
18352ba75afSkettenis #define PCB_REGS_FP 10
18452ba75afSkettenis #endif
18552ba75afSkettenis #ifndef PCB_REGS_SP
18652ba75afSkettenis #define PCB_REGS_SP 11
18752ba75afSkettenis #endif
18852ba75afSkettenis
1891505a8a8Skettenis static int
m68kbsd_supply_pcb(struct regcache * regcache,struct pcb * pcb)1901505a8a8Skettenis m68kbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
19152ba75afSkettenis {
19252ba75afSkettenis int regnum, tmp;
19352ba75afSkettenis int i = 0;
19452ba75afSkettenis
19552ba75afSkettenis /* The following is true for NetBSD 1.6.2:
19652ba75afSkettenis
19752ba75afSkettenis The pcb contains %d2...%d7, %a2...%a7 and %ps. This accounts for
19852ba75afSkettenis all callee-saved registers. From this information we reconstruct
19952ba75afSkettenis the register state as it would look when we just returned from
20052ba75afSkettenis cpu_switch(). */
20152ba75afSkettenis
20252ba75afSkettenis /* The stack pointer shouldn't be zero. */
20352ba75afSkettenis if (pcb->pcb_regs[PCB_REGS_SP] == 0)
20452ba75afSkettenis return 0;
20552ba75afSkettenis
20652ba75afSkettenis for (regnum = M68K_D2_REGNUM; regnum <= M68K_D7_REGNUM; regnum++)
20752ba75afSkettenis regcache_raw_supply (regcache, regnum, &pcb->pcb_regs[i++]);
20852ba75afSkettenis for (regnum = M68K_A2_REGNUM; regnum <= M68K_SP_REGNUM; regnum++)
20952ba75afSkettenis regcache_raw_supply (regcache, regnum, &pcb->pcb_regs[i++]);
21052ba75afSkettenis
21152ba75afSkettenis tmp = pcb->pcb_ps & 0xffff;
21252ba75afSkettenis regcache_raw_supply (regcache, M68K_PS_REGNUM, &tmp);
21352ba75afSkettenis
21452ba75afSkettenis read_memory (pcb->pcb_regs[PCB_REGS_FP] + 4, (char *) &tmp, sizeof tmp);
21552ba75afSkettenis regcache_raw_supply (regcache, M68K_PC_REGNUM, &tmp);
21652ba75afSkettenis
21752ba75afSkettenis return 1;
21852ba75afSkettenis }
2191505a8a8Skettenis
2201505a8a8Skettenis
2211505a8a8Skettenis /* Provide a prototype to silence -Wmissing-prototypes. */
2221505a8a8Skettenis void _initialize_m68kbsd_nat (void);
2231505a8a8Skettenis
2241505a8a8Skettenis void
_initialize_m68kbsd_nat(void)2251505a8a8Skettenis _initialize_m68kbsd_nat (void)
2261505a8a8Skettenis {
227*28dc8cddSkettenis struct target_ops *t;
228*28dc8cddSkettenis
229*28dc8cddSkettenis t = inf_ptrace_target ();
230*28dc8cddSkettenis t->to_fetch_registers = m68kbsd_fetch_inferior_registers;
231*28dc8cddSkettenis t->to_store_registers = m68kbsd_store_inferior_registers;
232*28dc8cddSkettenis add_target (t);
233*28dc8cddSkettenis
2341505a8a8Skettenis /* Support debugging kernel virtual memory images. */
2351505a8a8Skettenis bsd_kvm_add_target (m68kbsd_supply_pcb);
2361505a8a8Skettenis }
237