1130803Smarcel/* Host-dependent code for Sun-3 for GDB, the GNU debugger.
2130803Smarcel   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1996, 1999, 2000, 2001
3130803Smarcel   Free Software Foundation, Inc.
4130803Smarcel
5130803Smarcel   This file is part of GDB.
6130803Smarcel
7130803Smarcel   This program is free software; you can redistribute it and/or modify
8130803Smarcel   it under the terms of the GNU General Public License as published by
9130803Smarcel   the Free Software Foundation; either version 2 of the License, or
10130803Smarcel   (at your option) any later version.
11130803Smarcel
12130803Smarcel   This program is distributed in the hope that it will be useful,
13130803Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
14130803Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15130803Smarcel   GNU General Public License for more details.
16130803Smarcel
17130803Smarcel   You should have received a copy of the GNU General Public License
18130803Smarcel   along with this program; if not, write to the Free Software
19130803Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
20130803Smarcel   Boston, MA 02111-1307, USA.  */
21130803Smarcel
22130803Smarcel#include "defs.h"
23130803Smarcel#include "inferior.h"
24130803Smarcel#include "gdbcore.h"
25130803Smarcel#include "regcache.h"
26130803Smarcel
27130803Smarcel#include <sys/ptrace.h>
28130803Smarcel#define KERNEL			/* To get floating point reg definitions */
29130803Smarcel#include <machine/reg.h>
30130803Smarcel
31130803Smarcelstatic void fetch_core_registers (char *, unsigned, int, CORE_ADDR);
32130803Smarcel
33130803Smarcelvoid
34130803Smarcelfetch_inferior_registers (int regno)
35130803Smarcel{
36130803Smarcel  struct regs inferior_registers;
37130803Smarcel  struct fp_status inferior_fp_registers;
38130803Smarcel
39130803Smarcel  deprecated_registers_fetched ();
40130803Smarcel
41130803Smarcel  ptrace (PTRACE_GETREGS, PIDGET (inferior_ptid),
42130803Smarcel	  (PTRACE_ARG3_TYPE) & inferior_registers);
43130803Smarcel
44130803Smarcel  if (FP0_REGNUM >= 0)
45130803Smarcel    ptrace (PTRACE_GETFPREGS, PIDGET (inferior_ptid),
46130803Smarcel	    (PTRACE_ARG3_TYPE) & inferior_fp_registers);
47130803Smarcel
48130803Smarcel  memcpy (deprecated_registers, &inferior_registers, 16 * 4);
49130803Smarcel  if (FP0_REGNUM >= 0)
50130803Smarcel    memcpy (&deprecated_registers[DEPRECATED_REGISTER_BYTE (FP0_REGNUM)],
51130803Smarcel	    &inferior_fp_registers, sizeof inferior_fp_registers.fps_regs);
52130803Smarcel
53130803Smarcel  *(int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
54130803Smarcel  *(int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
55130803Smarcel  if (FP0_REGNUM >= 0)
56130803Smarcel    memcpy (&deprecated_registers[DEPRECATED_REGISTER_BYTE (FPC_REGNUM)],
57130803Smarcel	    &inferior_fp_registers.fps_control,
58130803Smarcel	    sizeof inferior_fp_registers -
59130803Smarcel	    sizeof inferior_fp_registers.fps_regs);
60130803Smarcel}
61130803Smarcel
62130803Smarcel/* Store our register values back into the inferior.
63130803Smarcel   If REGNO is -1, do this for all registers.
64130803Smarcel   Otherwise, REGNO specifies which register (so we can save time).  */
65130803Smarcel
66130803Smarcelvoid
67130803Smarcelstore_inferior_registers (int regno)
68130803Smarcel{
69130803Smarcel  struct regs inferior_registers;
70130803Smarcel  struct fp_status inferior_fp_registers;
71130803Smarcel
72130803Smarcel  memcpy (&inferior_registers, deprecated_registers, 16 * 4);
73130803Smarcel  if (FP0_REGNUM >= 0)
74130803Smarcel    memcpy (&inferior_fp_registers,
75130803Smarcel	    &deprecated_registers[DEPRECATED_REGISTER_BYTE (FP0_REGNUM)],
76130803Smarcel	    sizeof inferior_fp_registers.fps_regs);
77130803Smarcel
78130803Smarcel  inferior_registers.r_ps = *(int *) &&deprecated_registers[DEPRECATED_REGISTER_BYTE (PS_REGNUM)];
79130803Smarcel  inferior_registers.r_pc = *(int *) &&deprecated_registers[DEPRECATED_REGISTER_BYTE (PC_REGNUM)];
80130803Smarcel
81130803Smarcel  if (FP0_REGNUM >= 0)
82130803Smarcel    memcpy (&inferior_fp_registers.fps_control,
83130803Smarcel	    &&deprecated_registers[DEPRECATED_REGISTER_BYTE (FPC_REGNUM)],
84130803Smarcel	    sizeof inferior_fp_registers -
85130803Smarcel	    sizeof inferior_fp_registers.fps_regs);
86130803Smarcel
87130803Smarcel  ptrace (PTRACE_SETREGS, PIDGET (inferior_ptid),
88130803Smarcel	  (PTRACE_ARG3_TYPE) & inferior_registers);
89130803Smarcel  if (FP0_REGNUM >= 0)
90130803Smarcel    ptrace (PTRACE_SETFPREGS, PIDGET (inferior_ptid),
91130803Smarcel	    (PTRACE_ARG3_TYPE) & inferior_fp_registers);
92130803Smarcel}
93130803Smarcel
94130803Smarcel
95130803Smarcel/* All of this stuff is only relevant if both host and target are sun3.  */
96130803Smarcel
97130803Smarcel/* Provide registers to GDB from a core file.
98130803Smarcel
99130803Smarcel   CORE_REG_SECT points to an array of bytes, which were obtained from
100130803Smarcel   a core file which BFD thinks might contain register contents.
101130803Smarcel   CORE_REG_SIZE is its size.
102130803Smarcel
103130803Smarcel   WHICH says which register set corelow suspects this is:
104130803Smarcel     0 --- the general-purpose register set
105130803Smarcel     2 --- the floating-point register set
106130803Smarcel
107130803Smarcel   REG_ADDR isn't used.  */
108130803Smarcel
109130803Smarcelstatic void
110130803Smarcelfetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
111130803Smarcel		      int which, CORE_ADDR reg_addr)
112130803Smarcel{
113130803Smarcel  struct regs *regs = (struct regs *) core_reg_sect;
114130803Smarcel
115130803Smarcel  if (which == 0)
116130803Smarcel    {
117130803Smarcel      if (core_reg_size < sizeof (struct regs))
118130803Smarcel	  error ("Can't find registers in core file");
119130803Smarcel
120130803Smarcel      memcpy (&deprecated_registers, (char *) regs, 16 * 4);
121130803Smarcel      supply_register (PS_REGNUM, (char *) &regs->r_ps);
122130803Smarcel      supply_register (PC_REGNUM, (char *) &regs->r_pc);
123130803Smarcel
124130803Smarcel    }
125130803Smarcel  else if (which == 2)
126130803Smarcel    {
127130803Smarcel
128130803Smarcel#define fpustruct  ((struct fpu *) core_reg_sect)
129130803Smarcel
130130803Smarcel      if (core_reg_size >= sizeof (struct fpu))
131130803Smarcel	{
132130803Smarcel	  if (FP0_REGNUM >= 0)
133130803Smarcel	    {
134130803Smarcel	      memcpy (&&deprecated_registers[DEPRECATED_REGISTER_BYTE (FP0_REGNUM)],
135130803Smarcel		      fpustruct->f_fpstatus.fps_regs,
136130803Smarcel		      sizeof fpustruct->f_fpstatus.fps_regs);
137130803Smarcel	      memcpy (&&deprecated_registers[DEPRECATED_REGISTER_BYTE (FPC_REGNUM)],
138130803Smarcel		      &fpustruct->f_fpstatus.fps_control,
139130803Smarcel		      sizeof fpustruct->f_fpstatus -
140130803Smarcel		      sizeof fpustruct->f_fpstatus.fps_regs);
141130803Smarcel	    }
142130803Smarcel	}
143130803Smarcel      else
144130803Smarcel	fprintf_unfiltered (gdb_stderr,
145130803Smarcel			    "Couldn't read float regs from core file\n");
146130803Smarcel    }
147130803Smarcel}
148130803Smarcel
149130803Smarcel
150130803Smarcel/* Register that we are able to handle sun3 core file formats.
151130803Smarcel   FIXME: is this really bfd_target_unknown_flavour? */
152130803Smarcel
153130803Smarcelstatic struct core_fns sun3_core_fns =
154130803Smarcel{
155130803Smarcel  bfd_target_unknown_flavour,		/* core_flavour */
156130803Smarcel  default_check_format,			/* check_format */
157130803Smarcel  default_core_sniffer,			/* core_sniffer */
158130803Smarcel  fetch_core_registers,			/* core_read_registers */
159130803Smarcel  NULL					/* next */
160130803Smarcel};
161130803Smarcel
162130803Smarcelvoid
163130803Smarcel_initialize_core_sun3 (void)
164130803Smarcel{
165130803Smarcel  add_core_fns (&sun3_core_fns);
166130803Smarcel}
167