-/* Functions specific to running gdb native on a Sun 4 running sunos4.
- Copyright (C) 1989, 1992, Free Software Foundation, Inc.
+/* Native-dependent code for SPARC.
-This file is part of GDB.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
-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 file is part of GDB.
-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.
+ 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.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ 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
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "inferior.h"
+#include "regcache.h"
#include "target.h"
+#include "gdb_assert.h"
#include <signal.h>
+#include "gdb_string.h"
#include <sys/ptrace.h>
-#include <sys/wait.h>
+#include "gdb_wait.h"
+#ifdef HAVE_MACHINE_REG_H
#include <machine/reg.h>
+#endif
+
+#include "sparc-tdep.h"
+#include "sparc-nat.h"
+#include "inf-ptrace.h"
+
+/* With some trickery we can use the code in this file for most (if
+ not all) ptrace(2) based SPARC systems, which includes SunOS 4,
+ GNU/Linux and the various SPARC BSD's.
+
+ First, we need a data structure for use with ptrace(2). SunOS has
+ `struct regs' and `struct fp_status' in <machine/reg.h>. BSD's
+ have `struct reg' and `struct fpreg' in <machine/reg.h>. GNU/Linux
+ has the same structures as SunOS 4, but they're in <asm/reg.h>,
+ which is a kernel header. As a general rule we avoid including
+ GNU/Linux kernel headers. Fortunately GNU/Linux has a `gregset_t'
+ and a `fpregset_t' that are equivalent to `struct regs' and `struct
+ fp_status' in <sys/ucontext.h>, which is automatically included by
+ <signal.h>. Settling on using the `gregset_t' and `fpregset_t'
+ typedefs, providing them for the other systems, therefore solves
+ the puzzle. */
+
+#ifdef HAVE_MACHINE_REG_H
+#ifdef HAVE_STRUCT_REG
+typedef struct reg gregset_t;
+typedef struct fpreg fpregset_t;
+#else
+typedef struct regs gregset_t;
+typedef struct fp_status fpregset_t;
+#endif
+#endif
+
+/* Second, we need to remap the BSD ptrace(2) requests to their SunOS
+ equivalents. GNU/Linux already follows SunOS here. */
+
+#ifndef PTRACE_GETREGS
+#define PTRACE_GETREGS PT_GETREGS
+#endif
+
+#ifndef PTRACE_SETREGS
+#define PTRACE_SETREGS PT_SETREGS
+#endif
+
+#ifndef PTRACE_GETFPREGS
+#define PTRACE_GETFPREGS PT_GETFPREGS
+#endif
+
+#ifndef PTRACE_SETFPREGS
+#define PTRACE_SETFPREGS PT_SETFPREGS
+#endif
+
+/* Register set description. */
+const struct sparc_gregset *sparc_gregset;
+void (*sparc_supply_gregset) (const struct sparc_gregset *,
+ struct regcache *, int , const void *);
+void (*sparc_collect_gregset) (const struct sparc_gregset *,
+ const struct regcache *, int, void *);
+void (*sparc_supply_fpregset) (struct regcache *, int , const void *);
+void (*sparc_collect_fpregset) (const struct regcache *, int , void *);
+int (*sparc_gregset_supplies_p) (int);
+int (*sparc_fpregset_supplies_p) (int);
+
+/* Determine whether `gregset_t' contains register REGNUM. */
+
+int
+sparc32_gregset_supplies_p (int regnum)
+{
+ /* Integer registers. */
+ if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM)
+ || (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
+ || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM)
+ || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM))
+ return 1;
+
+ /* Control registers. */
+ if (regnum == SPARC32_PC_REGNUM
+ || regnum == SPARC32_NPC_REGNUM
+ || regnum == SPARC32_PSR_REGNUM
+ || regnum == SPARC32_Y_REGNUM)
+ return 1;
+
+ return 0;
+}
+
+/* Determine whether `fpregset_t' contains register REGNUM. */
-/* We don't store all registers immediately when requested, since they
- get sent over in large chunks anyway. Instead, we accumulate most
- of the changes and send them over once. "deferred_stores" keeps
- track of which sets of registers we have locally-changed copies of,
- so we only need send the groups that have changed. */
+int
+sparc32_fpregset_supplies_p (int regnum)
+{
+ /* Floating-point registers. */
+ if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
+ return 1;
+
+ /* Control registers. */
+ if (regnum == SPARC32_FSR_REGNUM)
+ return 1;
-#define INT_REGS 1
-#define STACK_REGS 2
-#define FP_REGS 4
+ return 0;
+}
-/* Fetch one or more registers from the inferior. REGNO == -1 to get
- them all. We actually fetch more than requested, when convenient,
- marking them as valid so we won't fetch them again. */
+/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
+ for all registers (including the floating-point registers). */
void
-fetch_inferior_registers (regno)
- int regno;
+fetch_inferior_registers (int regnum)
{
- struct regs inferior_registers;
- struct fp_status inferior_fp_registers;
- int i;
-
- /* We should never be called with deferred stores, because a prerequisite
- for writing regs is to have fetched them all (PREPARE_TO_STORE), sigh. */
- if (deferred_stores) abort();
-
- DO_DEFERRED_STORES;
-
- /* Global and Out regs are fetched directly, as well as the control
- registers. If we're getting one of the in or local regs,
- and the stack pointer has not yet been fetched,
- we have to do that first, since they're found in memory relative
- to the stack pointer. */
- if (regno < O7_REGNUM /* including -1 */
- || regno >= Y_REGNUM
- || (!register_valid[SP_REGNUM] && regno < I7_REGNUM))
+ struct regcache *regcache = current_regcache;
+ int pid;
+
+ /* NOTE: cagney/2002-12-03: This code assumes that the currently
+ selected light weight processes' registers can be written
+ directly into the selected thread's register cache. This works
+ fine when given an 1:1 LWP:thread model (such as found on
+ GNU/Linux) but will, likely, have problems when used on an N:1
+ (userland threads) or N:M (userland multiple LWP) model. In the
+ case of the latter two, the LWP's registers do not necessarily
+ belong to the selected thread (the LWP could be in the middle of
+ executing the thread switch code).
+
+ These functions should instead be paramaterized with an explicit
+ object (struct regcache, struct thread_info?) into which the LWPs
+ registers can be written. */
+ pid = TIDGET (inferior_ptid);
+ if (pid == 0)
+ pid = PIDGET (inferior_ptid);
+
+ if (regnum == SPARC_G0_REGNUM)
{
- if (0 != ptrace (PTRACE_GETREGS, inferior_pid,
- (PTRACE_ARG3_TYPE) &inferior_registers, 0))
- perror("ptrace_getregs");
-
- registers[REGISTER_BYTE (0)] = 0;
- memcpy (®isters[REGISTER_BYTE (1)], &inferior_registers.r_g1,
- 15 * REGISTER_RAW_SIZE (G0_REGNUM));
- *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
- *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
- *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
- *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
-
- for (i = G0_REGNUM; i <= O7_REGNUM; i++)
- register_valid[i] = 1;
- register_valid[Y_REGNUM] = 1;
- register_valid[PS_REGNUM] = 1;
- register_valid[PC_REGNUM] = 1;
- register_valid[NPC_REGNUM] = 1;
- /* If we don't set these valid, read_register_bytes() rereads
- all the regs every time it is called! FIXME. */
- register_valid[WIM_REGNUM] = 1; /* Not true yet, FIXME */
- register_valid[TBR_REGNUM] = 1; /* Not true yet, FIXME */
- register_valid[FPS_REGNUM] = 1; /* Not true yet, FIXME */
- register_valid[CPS_REGNUM] = 1; /* Not true yet, FIXME */
+ regcache_raw_supply (regcache, SPARC_G0_REGNUM, NULL);
+ return;
}
- /* Floating point registers */
- if (regno == -1 || (regno >= FP0_REGNUM && regno <= FP0_REGNUM + 31))
+ if (regnum == -1 || sparc_gregset_supplies_p (regnum))
{
- if (0 != ptrace (PTRACE_GETFPREGS, inferior_pid,
- (PTRACE_ARG3_TYPE) &inferior_fp_registers,
- 0))
- perror("ptrace_getfpregs");
- memcpy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
- sizeof inferior_fp_registers.fpu_fr);
- /* memcpy (®isters[REGISTER_BYTE (FPS_REGNUM)],
- &inferior_fp_registers.Fpu_fsr,
- sizeof (FPU_FSR_TYPE)); FIXME??? -- gnu@cyg */
- for (i = FP0_REGNUM; i <= FP0_REGNUM+31; i++)
- register_valid[i] = 1;
- register_valid[FPS_REGNUM] = 1;
- }
+ gregset_t regs;
- /* These regs are saved on the stack by the kernel. Only read them
- all (16 ptrace calls!) if we really need them. */
- if (regno == -1)
- {
- target_xfer_memory (*(CORE_ADDR*)®isters[REGISTER_BYTE (SP_REGNUM)],
- ®isters[REGISTER_BYTE (L0_REGNUM)],
- 16*REGISTER_RAW_SIZE (L0_REGNUM), 0);
- for (i = L0_REGNUM; i <= I7_REGNUM; i++)
- register_valid[i] = 1;
+ if (ptrace (PTRACE_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
+ perror_with_name (_("Couldn't get registers"));
+
+ sparc_supply_gregset (sparc_gregset, regcache, -1, ®s);
+ if (regnum != -1)
+ return;
}
- else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+
+ if (regnum == -1 || sparc_fpregset_supplies_p (regnum))
{
- CORE_ADDR sp = *(CORE_ADDR*)®isters[REGISTER_BYTE (SP_REGNUM)];
- i = REGISTER_BYTE (regno);
- if (register_valid[regno])
- printf("register %d valid and read\n", regno);
- target_xfer_memory (sp + i - REGISTER_BYTE (L0_REGNUM),
- ®isters[i], REGISTER_RAW_SIZE (regno), 0);
- register_valid[regno] = 1;
+ fpregset_t fpregs;
+
+ if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
+ perror_with_name (_("Couldn't get floating point status"));
+
+ sparc_supply_fpregset (regcache, -1, &fpregs);
}
}
-/* 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;
+store_inferior_registers (int regnum)
{
- struct regs inferior_registers;
- struct fp_status inferior_fp_registers;
- int wanna_store = INT_REGS + STACK_REGS + FP_REGS;
-
- /* First decide which pieces of machine-state we need to modify.
- Default for regno == -1 case is all pieces. */
- if (regno >= 0)
- if (FP0_REGNUM <= regno && regno < FP0_REGNUM + 32)
- {
- wanna_store = FP_REGS;
- }
- else
- {
- if (regno == SP_REGNUM)
- wanna_store = INT_REGS + STACK_REGS;
- else if (regno < L0_REGNUM || regno > I7_REGNUM)
- wanna_store = INT_REGS;
- else
- wanna_store = STACK_REGS;
- }
+ struct regcache *regcache = current_regcache;
+ int pid;
- /* See if we're forcing the stores to happen now, or deferring. */
- if (regno == -2)
- {
- wanna_store = deferred_stores;
- deferred_stores = 0;
- }
- else
+ /* NOTE: cagney/2002-12-02: See comment in fetch_inferior_registers
+ about threaded assumptions. */
+ pid = TIDGET (inferior_ptid);
+ if (pid == 0)
+ pid = PIDGET (inferior_ptid);
+
+ if (regnum == -1 || sparc_gregset_supplies_p (regnum))
{
- if (wanna_store == STACK_REGS)
- {
- /* Fall through and just store one stack reg. If we deferred
- it, we'd have to store them all, or remember more info. */
- }
- else
+ gregset_t regs;
+
+ if (ptrace (PTRACE_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
+ perror_with_name (_("Couldn't get registers"));
+
+ sparc_collect_gregset (sparc_gregset, regcache, regnum, ®s);
+
+ if (ptrace (PTRACE_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
+ perror_with_name (_("Couldn't write registers"));
+
+ /* Deal with the stack regs. */
+ if (regnum == -1 || regnum == SPARC_SP_REGNUM
+ || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM))
{
- deferred_stores |= wanna_store;
- return;
+ ULONGEST sp;
+
+ regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
+ sparc_collect_rwindow (regcache, sp, regnum);
}
+
+ if (regnum != -1)
+ return;
}
- if (wanna_store & STACK_REGS)
+ if (regnum == -1 || sparc_fpregset_supplies_p (regnum))
{
- CORE_ADDR sp = *(CORE_ADDR *)®isters[REGISTER_BYTE (SP_REGNUM)];
+ fpregset_t fpregs, saved_fpregs;
- if (regno < 0 || regno == SP_REGNUM)
- {
- if (!register_valid[L0_REGNUM+5]) abort();
- target_xfer_memory (sp,
- ®isters[REGISTER_BYTE (L0_REGNUM)],
- 16*REGISTER_RAW_SIZE (L0_REGNUM), 1);
- }
- else
+ if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
+ perror_with_name (_("Couldn't get floating-point registers"));
+
+ memcpy (&saved_fpregs, &fpregs, sizeof (fpregs));
+ sparc_collect_fpregset (regcache, regnum, &fpregs);
+
+ /* Writing the floating-point registers will fail on NetBSD with
+ EINVAL if the inferior process doesn't have an FPU state
+ (i.e. if it didn't use the FPU yet). Therefore we don't try
+ to write the registers if nothing changed. */
+ if (memcmp (&saved_fpregs, &fpregs, sizeof (fpregs)) != 0)
{
- if (!register_valid[regno]) abort();
- target_xfer_memory (sp + REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM),
- ®isters[REGISTER_BYTE (regno)],
- REGISTER_RAW_SIZE (regno), 1);
+ if (ptrace (PTRACE_SETFPREGS, pid,
+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
+ perror_with_name (_("Couldn't write floating-point registers"));
}
-
- }
-
- if (wanna_store & INT_REGS)
- {
- if (!register_valid[G1_REGNUM]) abort();
-
- memcpy (&inferior_registers.r_g1, ®isters[REGISTER_BYTE (G1_REGNUM)],
- 15 * REGISTER_RAW_SIZE (G1_REGNUM));
-
- inferior_registers.r_ps =
- *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
- inferior_registers.r_pc =
- *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
- inferior_registers.r_npc =
- *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)];
- inferior_registers.r_y =
- *(int *)®isters[REGISTER_BYTE (Y_REGNUM)];
-
- if (0 != ptrace (PTRACE_SETREGS, inferior_pid,
- (PTRACE_ARG3_TYPE) &inferior_registers, 0))
- perror("ptrace_setregs");
- }
- if (wanna_store & FP_REGS)
- {
- if (!register_valid[FP0_REGNUM+9]) abort();
- /* Initialize inferior_fp_registers members that gdb doesn't set
- by reading them from the inferior. */
- if (0 !=
- ptrace (PTRACE_GETFPREGS, inferior_pid,
- (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0))
- perror("ptrace_getfpregs");
- memcpy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)],
- sizeof inferior_fp_registers.fpu_fr);
-
-/* memcpy (&inferior_fp_registers.Fpu_fsr,
- ®isters[REGISTER_BYTE (FPS_REGNUM)], sizeof (FPU_FSR_TYPE));
-****/
- if (0 !=
- ptrace (PTRACE_SETFPREGS, inferior_pid,
- (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0))
- perror("ptrace_setfpregs");
+ if (regnum != -1)
+ return;
}
}
+\f
+/* Fetch StackGhost Per-Process XOR cookie. */
-void
-fetch_core_registers (core_reg_sect, core_reg_size, which, ignore)
- char *core_reg_sect;
- unsigned core_reg_size;
- int which;
- unsigned int ignore; /* reg addr, unused in this version */
+LONGEST
+sparc_xfer_wcookie (struct target_ops *ops, enum target_object object,
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
{
+ unsigned long wcookie = 0;
+ char *buf = (char *)&wcookie;
+
+ gdb_assert (object == TARGET_OBJECT_WCOOKIE);
+ gdb_assert (readbuf && writebuf == NULL);
+
+ if (offset >= sizeof (unsigned long))
+ return -1;
+
+#ifdef PT_WCOOKIE
+ /* If PT_WCOOKIE is defined (by <sys/ptrace.h>), assume we're
+ running on an OpenBSD release that uses StackGhost (3.1 or
+ later). As of release 3.4, OpenBSD doesn't use a randomized
+ cookie yet, but a future release probably will. */
+ {
+ int pid;
+
+ pid = TIDGET (inferior_ptid);
+ if (pid == 0)
+ pid = PIDGET (inferior_ptid);
+
+ /* Sanity check. The proper type for a cookie is register_t, but
+ we can't assume that this type exists on all systems supported
+ by the code in this file. */
+ gdb_assert (sizeof (wcookie) == sizeof (register_t));
+
+ /* Fetch the cookie. */
+ if (ptrace (PT_WCOOKIE, pid, (PTRACE_TYPE_ARG3) &wcookie, 0) == -1)
+ {
+ if (errno != EINVAL)
+ perror_with_name (_("Couldn't get StackGhost cookie"));
+
+ /* Although PT_WCOOKIE is defined on OpenBSD 3.1 and later,
+ the request wasn't implemented until after OpenBSD 3.4. If
+ the kernel doesn't support the PT_WCOOKIE request, assume
+ we're running on a kernel that uses non-randomized cookies. */
+ wcookie = 0x3;
+ }
+ }
+#endif /* PT_WCOOKIE */
- if (which == 0) {
+ if (len > sizeof (unsigned long) - offset)
+ len = sizeof (unsigned long) - offset;
- /* Integer registers */
+ memcpy (readbuf, buf + offset, len);
+ return len;
+}
-#define gregs ((struct regs *)core_reg_sect)
- /* G0 *always* holds 0. */
- *(int *)®isters[REGISTER_BYTE (0)] = 0;
+LONGEST (*inf_ptrace_xfer_partial) (struct target_ops *, enum target_object,
+ const char *, gdb_byte *, const gdb_byte *,
+ ULONGEST, LONGEST);
- /* The globals and output registers. */
- memcpy (®isters[REGISTER_BYTE (G1_REGNUM)], &gregs->r_g1,
- 15 * REGISTER_RAW_SIZE (G1_REGNUM));
- *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = gregs->r_ps;
- *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = gregs->r_pc;
- *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = gregs->r_npc;
- *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = gregs->r_y;
+static LONGEST
+sparc_xfer_partial (struct target_ops *ops, enum target_object object,
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+{
+ if (object == TARGET_OBJECT_WCOOKIE)
+ return sparc_xfer_wcookie (ops, object, annex, readbuf, writebuf,
+ offset, len);
- /* My best guess at where to get the locals and input
- registers is exactly where they usually are, right above
- the stack pointer. If the core dump was caused by a bus error
- from blowing away the stack pointer (as is possible) then this
- won't work, but it's worth the try. */
- {
- int sp;
+ return inf_ptrace_xfer_partial (ops, object, annex, readbuf, writebuf,
+ offset, len);
+}
+\f
+/* Create a prototype generic SPARC target. The client can override
+ it with local methods. */
- sp = *(int *)®isters[REGISTER_BYTE (SP_REGNUM)];
- if (0 != target_read_memory (sp, ®isters[REGISTER_BYTE (L0_REGNUM)],
- 16 * REGISTER_RAW_SIZE (L0_REGNUM)))
- {
- /* fprintf so user can still use gdb */
- fprintf (stderr,
- "Couldn't read input and local registers from core file\n");
- }
- }
- } else if (which == 2) {
+struct target_ops *
+sparc_target (void)
+{
+ struct target_ops *t;
+
+ t = inf_ptrace_target ();
+ t->to_fetch_registers = fetch_inferior_registers;
+ t->to_store_registers = store_inferior_registers;
+ inf_ptrace_xfer_partial = t->to_xfer_partial;
+ t->to_xfer_partial = sparc_xfer_partial;
+ return t;
+}
- /* Floating point registers */
+\f
+/* Provide a prototype to silence -Wmissing-prototypes. */
+void _initialize_sparc_nat (void);
-#define fpuregs ((struct fpu *) core_reg_sect)
- if (core_reg_size >= sizeof (struct fpu))
- {
- memcpy (®isters[REGISTER_BYTE (FP0_REGNUM)], fpuregs->fpu_regs,
- sizeof (fpuregs->fpu_regs));
- memcpy (®isters[REGISTER_BYTE (FPS_REGNUM)], &fpuregs->fpu_fsr,
- sizeof (FPU_FSR_TYPE));
- }
- else
- fprintf (stderr, "Couldn't read float regs from core file\n");
- }
+void
+_initialize_sparc_nat (void)
+{
+ /* Deafult to using SunOS 4 register sets. */
+ if (sparc_gregset == NULL)
+ sparc_gregset = &sparc32_sunos4_gregset;
+ if (sparc_supply_gregset == NULL)
+ sparc_supply_gregset = sparc32_supply_gregset;
+ if (sparc_collect_gregset == NULL)
+ sparc_collect_gregset = sparc32_collect_gregset;
+ if (sparc_supply_fpregset == NULL)
+ sparc_supply_fpregset = sparc32_supply_fpregset;
+ if (sparc_collect_fpregset == NULL)
+ sparc_collect_fpregset = sparc32_collect_fpregset;
+ if (sparc_gregset_supplies_p == NULL)
+ sparc_gregset_supplies_p = sparc32_gregset_supplies_p;
+ if (sparc_fpregset_supplies_p == NULL)
+ sparc_fpregset_supplies_p = sparc32_fpregset_supplies_p;
}
-