binutils-gdb/gdb/m88k-nat.c

286 lines
8.3 KiB
C
Raw Normal View History

1992-10-17 04:53:46 +08:00
/* Native-dependent Motorola 88xxx support for GDB, the GNU Debugger.
Copyright 1988, 1990, 1991, 1992 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
1995-08-02 11:41:12 +08:00
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
1992-10-17 04:53:46 +08:00
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include "gdbcore.h"
#include <sys/user.h>
#ifndef USER /* added to support BCS ptrace_user */
#define USER ptrace_user
#endif
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/file.h>
* configure.in: Check for working mmap, ansi headers, string.h, strings.h, and memory.h. * configure: Regenerated. * gdb_stat.h: New file, "portable" <sys/stat.h>. * gdb_string.h: New file, "portable" <string.h>. * altos-xdep.c, arm-tdep.c, arm-xdep.c, convex-tdep.c, convex-xdep.c, coredep.c, cxux-nat.c, dbxread.c, exec.c, gould-xdep.c, hppa-tdep.c, i386aix-nat.c, i386b-nat.c, i386mach-nat.c, i386v-nat.c, infptrace.c, m88k-nat.c, main.c, mdebugread.c, objfiles.c, os9kread.c, procfs.c, pyr-xdep.c, rs6000-nat.c, source.c, standalone.c, stuff.c, sun386-nat.c, symfile.c, symm-nat.c, symm-tdep.c, symtab.c, top.c, ultra3-nat.c, ultra3-xdep.c, umax-xdep.c, xcoffread.c: Include "gdb_stat.h" instead of <sys/stat.h>. * alpha-tdep.c, breakpoint.c, buildsym.c, c-typeprint.c, ch-typeprint.c, coffread.c, command.c, core-sol2.c, core-svr4.c, core.c, corelow.c, cp-valprint.c, dbxread.c, dcache.c, demangle.c, dpx2-nat.c, dstread.c, dwarfread.c, elfread.c, environ.c, eval.c, exec.c, f-lang.c, f-typeprint.c, f-valprint.c, findvar.c, fork-child.c, gdbtypes.c, hpread.c, i386-tdep.c, infcmd.c, inflow.c, infptrace.c, infrun.c, irix5-nat.c, language.c, m2-typeprint.c, main.c, mdebugread.c, minsyms.c, mipsread.c, monitor.c, nlmread.c, objfiles.c, os9kread.c, osfsolib.c, parse.c, printcmd.c, procfs.c, regex.c, remote-adapt.c, remote-arc.c, remote-array.c, remote-bug.c, remote-e7000.c, remote-eb.c, remote-es.c, remote-hms.c, remote-mm.c, remote-os9k.c, remote-pa.c, remote-sim.c, remote-st.c, remote-udi.c, remote-utils.c, remote-vx.c, remote-vx29k.c, remote-vx68.c, remote-vx960.c, remote-vxmips.c, remote-vxsparc.c, remote.c, solib.c, somread.c, source.c, stabsread.c, stack.c, symfile.c, symmisc.c, symtab.c, target.c, top.c, typeprint.c, utils.c, valarith.c, valops.c, valprint.c, values.c, xcoffread.c: Include "gdb_string.h" instead of <string.h>. * gdbtk.c: Likewise. * config/xm-sysv4.h, i386/xm-ptx.h, m68k/xm-sun3os4.h, sparc/xm-sun4os4.h (HAVE_MMAP): Removed. * config/xm-lynx.h, config/i386/xm-ptx.h, config/m68k/nm-apollo68b.h, config/m68k/xm-hp300hpux.h, config/mips/xm-irix3.h, config/mips/xm-mips.h, config/mips/xm-news-mips.h, config/mips/xm-riscos.h, config/pa/hppah.h, config/rs6000/xm-rs6000.h, config/sparc/xm-sun4os4.h, config/sparc/xm-sun4sol2.h, config/vax/xm-vaxbsd.h, config/vax/xm-vaxult.h, config/vax/xm-vaxult2.h (MEM_FNS_DECLARED): Removed. * config/mips/xm-irix3.h, config/mips/xm-mips.h, config/pa/xm-hppah.h (memcpy, memset): Removed declarations.
1995-08-02 04:14:27 +08:00
#include "gdb_stat.h"
1992-10-17 04:53:46 +08:00
#include "symtab.h"
#include "setjmp.h"
#include "value.h"
#ifdef DELTA88
#include <sys/ptrace.h>
1992-10-17 04:53:46 +08:00
/* define offsets to the pc instruction offsets in ptrace_user struct */
#define SXIP_OFFSET ((char *)&u.pt_sigframe.sig_sxip - (char *)&u)
#define SNIP_OFFSET ((char *)&u.pt_sigframe.sig_snip - (char *)&u)
#define SFIP_OFFSET ((char *)&u.pt_sigframe.sig_sfip - (char *)&u)
1992-10-17 04:53:46 +08:00
#else
/* define offsets to the pc instruction offsets in ptrace_user struct */
#define SXIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_sxip - (char *)&u)
#define SNIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_snip - (char *)&u)
#define SFIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_sfip - (char *)&u)
1992-10-17 04:53:46 +08:00
#endif
extern int have_symbol_file_p();
extern jmp_buf stack_jmp;
extern int errno;
extern char registers[REGISTER_BYTES];
void
fetch_inferior_registers (regno)
int regno; /* Original value discarded */
{
register unsigned int regaddr;
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
struct USER u;
unsigned int offset;
offset = (char *) &u.pt_r0 - (char *) &u;
regaddr = offset; /* byte offset to r0;*/
/* offset = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) - KERNEL_U_ADDR; */
for (regno = 0; regno < NUM_REGS; regno++)
{
/*regaddr = register_addr (regno, offset);*/
/* 88k enhancement */
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
*(int *) &buf[i] = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, 0);
regaddr += sizeof (int);
}
supply_register (regno, buf);
}
/* now load up registers 36 - 38; special pc registers */
*(int *) &buf[0] = ptrace (3,inferior_pid,
(PTRACE_ARG3_TYPE) SXIP_OFFSET ,0);
supply_register (SXIP_REGNUM, buf);
*(int *) &buf[0] = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) SNIP_OFFSET,0);
supply_register (SNIP_REGNUM, buf);
*(int *) &buf[0] = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) SFIP_OFFSET,0);
supply_register (SFIP_REGNUM, buf);
}
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
void
store_inferior_registers (regno)
int regno;
{
register unsigned int regaddr;
char buf[80];
struct USER u;
unsigned int offset = (char *) &u.pt_r0 - (char *) &u;
regaddr = offset;
/* Don't try to deal with EXIP_REGNUM or ENIP_REGNUM, because I think either
svr3 doesn't run on an 88110, or the kernel isolates the different (not
completely sure this is true, but seems to be. */
1992-10-17 04:53:46 +08:00
if (regno >= 0)
{
/* regaddr = register_addr (regno, offset); */
if (regno < PC_REGNUM)
{
regaddr = offset + regno * sizeof (int);
errno = 0;
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
else if (regno == SXIP_REGNUM)
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) SXIP_OFFSET, read_register(regno));
else if (regno == SNIP_REGNUM)
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) SNIP_OFFSET, read_register(regno));
else if (regno == SFIP_REGNUM)
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) SFIP_OFFSET, read_register(regno));
else
printf_unfiltered ("Bad register number for store_inferior routine\n");
}
else
{
for (regno = 0; regno < PC_REGNUM; regno++)
{
/* regaddr = register_addr (regno, offset); */
errno = 0;
regaddr = offset + regno * sizeof (int);
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
ptrace (6,inferior_pid,
(PTRACE_ARG3_TYPE) SXIP_OFFSET,read_register(SXIP_REGNUM));
ptrace (6,inferior_pid,
(PTRACE_ARG3_TYPE) SNIP_OFFSET,read_register(SNIP_REGNUM));
ptrace (6,inferior_pid,
(PTRACE_ARG3_TYPE) SFIP_OFFSET,read_register(SFIP_REGNUM));
}
1992-10-17 04:53:46 +08:00
}
/* blockend is the address of the end of the user structure */
m88k_register_u_addr (blockend, regnum)
{
struct USER u;
int ustart = blockend - sizeof (struct USER);
switch (regnum)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
return (ustart + ((int) &u.pt_r0 - (int) &u) + REGISTER_SIZE * regnum);
1992-10-17 04:53:46 +08:00
case PSR_REGNUM: return (ustart + ((int) &u.pt_psr - (int) &u));
case FPSR_REGNUM: return (ustart + ((int) &u.pt_fpsr - (int) &u));
case FPCR_REGNUM: return (ustart + ((int) &u.pt_fpcr - (int) &u));
case SXIP_REGNUM: return (ustart + SXIP_OFFSET);
case SNIP_REGNUM: return (ustart + SNIP_OFFSET);
case SFIP_REGNUM: return (ustart + SFIP_OFFSET);
default:
if (regnum < NUM_REGS)
/* The register is one of those which is not defined...
give it zero */
return (ustart + ((int) &u.pt_r0 - (int) &u));
else
return (blockend + REGISTER_SIZE * regnum);
1992-10-17 04:53:46 +08:00
}
}
#ifdef USE_PROC_FS
#include <sys/procfs.h>
/* Given a pointer to a general register set in /proc format (gregset_t *),
unpack the register contents and supply them as gdb's idea of the current
register values. */
void
supply_gregset (gregsetp)
gregset_t *gregsetp;
{
register int regi;
register greg_t *regp = (greg_t *) gregsetp;
for (regi=0; regi <= SP_REGNUM; regi++)
supply_register (regi, (char *) (regp + regi));
supply_register (SXIP_REGNUM, (char *) (regp + R_XIP));
supply_register (SNIP_REGNUM, (char *) (regp + R_NIP));
supply_register (SFIP_REGNUM, (char *) (regp + R_FIP));
supply_register (PSR_REGNUM, (char *) (regp + R_PSR));
supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
}
void
fill_gregset (gregsetp, regno)
gregset_t *gregsetp;
int regno;
{
int regi;
register greg_t *regp = (greg_t *) gregsetp;
extern char registers[];
for (regi = 0 ; regi <= R_R31 ; regi++)
if ((regno == -1) || (regno == regi))
*(regp + regi) = *(int *) &registers[REGISTER_BYTE(regi)];
if ((regno == -1) || (regno == SXIP_REGNUM))
*(regp + R_XIP) = *(int *) &registers[REGISTER_BYTE(SXIP_REGNUM)];
if ((regno == -1) || (regno == SNIP_REGNUM))
*(regp + R_NIP) = *(int *) &registers[REGISTER_BYTE(SNIP_REGNUM)];
if ((regno == -1) || (regno == SFIP_REGNUM))
*(regp + R_FIP) = *(int *) &registers[REGISTER_BYTE(SFIP_REGNUM)];
if ((regno == -1) || (regno == PSR_REGNUM))
*(regp + R_PSR) = *(int *) &registers[REGISTER_BYTE(PSR_REGNUM)];
if ((regno == -1) || (regno == FPSR_REGNUM))
*(regp + R_FPSR) = *(int *) &registers[REGISTER_BYTE(FPSR_REGNUM)];
if ((regno == -1) || (regno == FPCR_REGNUM))
*(regp + R_FPCR) = *(int *) &registers[REGISTER_BYTE(FPCR_REGNUM)];
}
#endif /* USE_PROC_FS */