2013-02-04 Andreas Tobler <andreast@fgznet.ch>

* Makefile.in (ALL_TARGET_OBS): Add powerpc FreeBSD files.
	* configure.host: Add powerpc*-*-freebsd* target.
	* configure.tgt: Add target info for powerpc*-*-freebsd*.
	* ppcfbsd-nat.c, ppcfbsd-tdep.h, ppcfbsd-tdep.c: New files.
	* config/powerpc/fbsd.mh: New file.
This commit is contained in:
Andreas Tobler 2013-02-04 20:48:53 +00:00
parent ace9af6f59
commit dc18f110f2
8 changed files with 649 additions and 2 deletions

View File

@ -1,3 +1,11 @@
2013-02-04 Andreas Tobler <andreast@fgznet.ch>
* Makefile.in (ALL_TARGET_OBS): Add powerpc FreeBSD files.
* configure.host: Add powerpc*-*-freebsd* target.
* configure.tgt: Add target info for powerpc*-*-freebsd*.
* ppcfbsd-nat.c, ppcfbsd-tdep.h, ppcfbsd-tdep.c: New files.
* config/powerpc/fbsd.mh: New file.
2013-02-04 Sergio Durigan Junior <sergiodj@redhat.com>
Denys Vlasenko <dvlasenk@redhat.com>
Pedro Alves <palves@redhat.com>

View File

@ -772,8 +772,8 @@ LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
HFILES_NO_SRCDIR = \
common/gdb_signals.h common/gdb_thread_db.h common/gdb_vecs.h \
common/i386-xstate.h common/linux-ptrace.h \
proc-utils.h aarch64-tdep.h arm-tdep.h ax-gdb.h ppcnbsd-tdep.h \
cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \
proc-utils.h aarch64-tdep.h arm-tdep.h ax-gdb.h ppcfbsd-tdep.h \
ppcnbsd-tdep.h cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \
exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h amd64bsd-nat.h \
i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \
ia64-tdep.h ada-lang.h ada-varobj.h varobj.h frv-tdep.h nto-tdep.h serial.h \

View File

@ -0,0 +1,23 @@
# Native config information for GDB on PowerPC systems running FreeBSD.
#
# Copyright (C) 2013 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 3 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, see <http://www.gnu.org/licenses/>. */
NATDEPFILES= fbsd-nat.o fork-child.o inf-ptrace.o ppcfbsd-nat.o bsd-kvm.o
LOADLIBES= -lkvm

View File

@ -125,6 +125,7 @@ mips64*-*-openbsd*) gdb_host=obsd64 ;;
powerpc-*-aix* | rs6000-*-*)
gdb_host=aix ;;
powerpc*-*-freebsd*) gdb_host=fbsd ;;
powerpc-*-linux*) gdb_host=linux ;;
powerpc-*-netbsd* | powerpc-*-knetbsd*-gnu)
gdb_host=nbsd ;;

View File

@ -395,6 +395,13 @@ mt-*-*)
gdb_target_obs="mt-tdep.o"
;;
powerpc*-*-freebsd*)
# Target: FreeBSD/powerpc
gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppc64-tdep.o \
ppcfbsd-tdep.o solib-svr4.o \
ravenscar-thread.o ppc-ravenscar-thread.o"
;;
powerpc-*-netbsd* | powerpc-*-knetbsd*-gnu)
# Target: NetBSD/powerpc
gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppcnbsd-tdep.o \

224
gdb/ppcfbsd-nat.c Normal file
View File

@ -0,0 +1,224 @@
/* Native-dependent code for PowerPC's running FreeBSD, for GDB.
Copyright (C) 2013 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 3 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, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "gdbcore.h"
#include "inferior.h"
#include "regcache.h"
#include "gdb_assert.h"
#include <stddef.h>
#include <sys/types.h>
#include <sys/procfs.h>
#include <sys/ptrace.h>
#include <sys/signal.h>
#include <machine/frame.h>
#include <machine/pcb.h>
#include <machine/reg.h>
#include "fbsd-nat.h"
#include "gregset.h"
#include "ppc-tdep.h"
#include "ppcfbsd-tdep.h"
#include "inf-ptrace.h"
#include "bsd-kvm.h"
/* Fill GDB's register array with the general-purpose register values
in *GREGSETP. */
void
supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
{
const struct regset *regset = ppc_fbsd_gregset (sizeof (long));
ppc_supply_gregset (regset, regcache, -1, gregsetp, sizeof (*gregsetp));
}
/* Fill register REGNO (if a gpr) in *GREGSETP with the value in GDB's
register array. If REGNO is -1 do it for all registers. */
void
fill_gregset (const struct regcache *regcache,
gdb_gregset_t *gregsetp, int regno)
{
const struct regset *regset = ppc_fbsd_gregset (sizeof (long));
if (regno == -1)
memset (gregsetp, 0, sizeof (*gregsetp));
ppc_collect_gregset (regset, regcache, regno, gregsetp, sizeof (*gregsetp));
}
/* Fill GDB's register array with the floating-point register values
in *FPREGSETP. */
void
supply_fpregset (struct regcache *regcache, const gdb_fpregset_t * fpregsetp)
{
const struct regset *regset = ppc_fbsd_fpregset ();
ppc_supply_fpregset (regset, regcache, -1,
fpregsetp, sizeof (*fpregsetp));
}
/* Fill register REGNO in *FGREGSETP with the value in GDB's
register array. If REGNO is -1 do it for all registers. */
void
fill_fpregset (const struct regcache *regcache,
gdb_fpregset_t *fpregsetp, int regno)
{
const struct regset *regset = ppc_fbsd_fpregset ();
ppc_collect_fpregset (regset, regcache, regno,
fpregsetp, sizeof (*fpregsetp));
}
/* Returns true if PT_GETFPREGS fetches this register. */
static int
getfpregs_supplies (struct gdbarch *gdbarch, int regno)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
point registers. Traditionally, GDB's register set has still
listed the floating point registers for such machines, so this
code is harmless. However, the new E500 port actually omits the
floating point registers entirely from the register set --- they
don't even have register numbers assigned to them.
It's not clear to me how best to update this code, so this assert
will alert the first person to encounter the NetBSD/E500
combination to the problem. */
gdb_assert (ppc_floating_point_unit_p (gdbarch));
return ((regno >= tdep->ppc_fp0_regnum
&& regno < tdep->ppc_fp0_regnum + ppc_num_fprs)
|| regno == tdep->ppc_fpscr_regnum);
}
/* Fetch register REGNO from the child process. If REGNO is -1, do it
for all registers. */
static void
ppcfbsd_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
{
gdb_gregset_t regs;
if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
(PTRACE_TYPE_ARG3) &regs, 0) == -1)
perror_with_name (_("Couldn't get registers"));
supply_gregset (regcache, &regs);
if (regno == -1 || getfpregs_supplies (get_regcache_arch (regcache), regno))
{
const struct regset *fpregset = ppc_fbsd_fpregset ();
gdb_fpregset_t fpregs;
if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
(PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
perror_with_name (_("Couldn't get FP registers"));
ppc_supply_fpregset (fpregset, regcache, regno, &fpregs, sizeof fpregs);
}
}
/* Store register REGNO back into the child process. If REGNO is -1,
do this for all registers. */
static void
ppcfbsd_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
{
gdb_gregset_t regs;
if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
(PTRACE_TYPE_ARG3) &regs, 0) == -1)
perror_with_name (_("Couldn't get registers"));
fill_gregset (regcache, &regs, regno);
if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
(PTRACE_TYPE_ARG3) &regs, 0) == -1)
perror_with_name (_("Couldn't write registers"));
if (regno == -1 || getfpregs_supplies (get_regcache_arch (regcache), regno))
{
gdb_fpregset_t fpregs;
if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
(PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
perror_with_name (_("Couldn't get FP registers"));
fill_fpregset (regcache, &fpregs, regno);
if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
(PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
perror_with_name (_("Couldn't set FP registers"));
}
}
/* Architecture specific function that reconstructs the
register state from PCB (Process Control Block) and supplies it
to REGCACHE. */
static int
ppcfbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
int i, regnum;
/* The stack pointer shouldn't be zero. */
if (pcb->pcb_sp == 0)
return 0;
regcache_raw_supply (regcache, gdbarch_sp_regnum (gdbarch), &pcb->pcb_sp);
regcache_raw_supply (regcache, tdep->ppc_cr_regnum, &pcb->pcb_cr);
regcache_raw_supply (regcache, tdep->ppc_lr_regnum, &pcb->pcb_lr);
for (i = 0, regnum = tdep->ppc_gp0_regnum + 14; i < 20; i++, regnum++)
regcache_raw_supply (regcache, regnum, &pcb->pcb_context[i]);
return 1;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
void _initialize_ppcfbsd_nat (void);
void
_initialize_ppcfbsd_nat (void)
{
struct target_ops *t;
/* Add in local overrides. */
t = inf_ptrace_target ();
t->to_fetch_registers = ppcfbsd_fetch_inferior_registers;
t->to_store_registers = ppcfbsd_store_inferior_registers;
t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
t->to_find_memory_regions = fbsd_find_memory_regions;
t->to_make_corefile_notes = fbsd_make_corefile_notes;
add_target (t);
/* Support debugging kernel virtual memory images. */
bsd_kvm_add_target (ppcfbsd_supply_pcb);
}

355
gdb/ppcfbsd-tdep.c Normal file
View File

@ -0,0 +1,355 @@
/* Target-dependent code for PowerPC systems running FreeBSD.
Copyright (C) 2013 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 3 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, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "arch-utils.h"
#include "frame.h"
#include "gdbcore.h"
#include "frame-unwind.h"
#include "gdbtypes.h"
#include "osabi.h"
#include "regcache.h"
#include "regset.h"
#include "symtab.h"
#include "target.h"
#include "trad-frame.h"
#include "gdb_assert.h"
#include "gdb_string.h"
#include "ppc-tdep.h"
#include "ppc64-tdep.h"
#include "ppcfbsd-tdep.h"
#include "solib-svr4.h"
/* 32-bit regset descriptions. */
static const struct ppc_reg_offsets ppc32_fbsd_reg_offsets =
{
/* General-purpose registers. */
/* .r0_offset = */ 0,
/* .gpr_size = */ 4,
/* .xr_size = */ 4,
/* .pc_offset = */ 144,
/* .ps_offset = */ -1,
/* .cr_offset = */ 132,
/* .lr_offset = */ 128,
/* .ctr_offset = */ 140,
/* .xer_offset = */ 136,
/* .mq_offset = */ -1,
/* Floating-point registers. */
/* .f0_offset = */ 0,
/* .fpscr_offset = */ 256,
/* .fpscr_size = */ 8,
#ifdef NOTYET
/* AltiVec registers. */
/* .vr0_offset = */ 0,
/* .vscr_offset = */ 512 + 12,
/* .vrsave_offset = */ 512
#endif
};
/* 64-bit regset descriptions. */
static const struct ppc_reg_offsets ppc64_fbsd_reg_offsets =
{
/* General-purpose registers. */
/* .r0_offset = */ 0,
/* .gpr_size = */ 8,
/* .xr_size = */ 8,
/* .pc_offset = */ 288,
/* .ps_offset = */ -1,
/* .cr_offset = */ 264,
/* .lr_offset = */ 256,
/* .ctr_offset = */ 280,
/* .xer_offset = */ 272,
/* .mq_offset = */ -1,
/* Floating-point registers. */
/* .f0_offset = */ 0,
/* .fpscr_offset = */ 256,
/* .fpscr_size = */ 8,
#ifdef NOYET
/* AltiVec registers. */
/* .vr0_offset = */ 0,
/* .vscr_offset = */ 512 + 12,
/* .vrsave_offset = */ 528
#endif
};
/* 32-bit general-purpose register set. */
static const struct regset ppc32_fbsd_gregset = {
&ppc32_fbsd_reg_offsets,
ppc_supply_gregset,
ppc_collect_gregset,
NULL
};
/* 64-bit general-purpose register set. */
static const struct regset ppc64_fbsd_gregset = {
&ppc64_fbsd_reg_offsets,
ppc_supply_gregset,
ppc_collect_gregset,
NULL
};
/* 32-/64-bit floating-point register set. */
static struct regset ppc32_fbsd_fpregset = {
&ppc32_fbsd_reg_offsets,
ppc_supply_fpregset,
ppc_collect_fpregset
};
const struct regset *
ppc_fbsd_gregset (int wordsize)
{
return wordsize == 8 ? &ppc64_fbsd_gregset : &ppc32_fbsd_gregset;
}
const struct regset *
ppc_fbsd_fpregset (void)
{
return &ppc32_fbsd_fpregset;
}
/* Return the appropriate register set for the core section identified
by SECT_NAME and SECT_SIZE. */
static const struct regset *
ppcfbsd_regset_from_core_section (struct gdbarch *gdbarch,
const char *sect_name, size_t sect_size)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
if (strcmp (sect_name, ".reg") == 0 && sect_size >= 148)
{
if (tdep->wordsize == 4)
return &ppc32_fbsd_gregset;
else
return &ppc64_fbsd_gregset;
}
if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 264)
return &ppc32_fbsd_fpregset;
return NULL;
}
/* Default page size. */
static const int ppcfbsd_page_size = 4096;
/* Offset for sigreturn(2). */
static const int ppcfbsd_sigreturn_offset[] = {
0xc, /* FreeBSD 32-bit */
-1
};
/* Signal trampolines. */
static int
ppcfbsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
struct frame_info *this_frame,
void **this_cache)
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR pc = get_frame_pc (this_frame);
CORE_ADDR start_pc = (pc & ~(ppcfbsd_page_size - 1));
const int *offset;
const char *name;
/* A stack trampoline is detected if no name is associated
to the current pc and if it points inside a trampoline
sequence. */
find_pc_partial_function (pc, &name, NULL, NULL);
/* If we have a name, we have no trampoline, return. */
if (name)
return 0;
for (offset = ppcfbsd_sigreturn_offset; *offset != -1; offset++)
{
gdb_byte buf[2 * PPC_INSN_SIZE];
unsigned long insn;
if (!safe_frame_unwind_memory (this_frame, start_pc + *offset,
buf, sizeof buf))
continue;
/* Check for "li r0,SYS_sigreturn". */
insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order);
if (insn != 0x380001a1)
continue;
/* Check for "sc". */
insn = extract_unsigned_integer (buf + PPC_INSN_SIZE,
PPC_INSN_SIZE, byte_order);
if (insn != 0x44000002)
continue;
return 1;
}
return 0;
}
static struct trad_frame_cache *
ppcfbsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
struct trad_frame_cache *cache;
CORE_ADDR addr, base, func;
gdb_byte buf[PPC_INSN_SIZE];
int i;
if (*this_cache)
return *this_cache;
cache = trad_frame_cache_zalloc (this_frame);
*this_cache = cache;
func = get_frame_pc (this_frame);
func &= ~(ppcfbsd_page_size - 1);
if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf))
return cache;
base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
addr = base + 0x10 + 2 * tdep->wordsize;
for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
{
int regnum = i + tdep->ppc_gp0_regnum;
trad_frame_set_reg_addr (cache, regnum, addr);
}
trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr);
addr += tdep->wordsize;
trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr);
addr += tdep->wordsize;
trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr);
addr += tdep->wordsize;
trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr);
addr += tdep->wordsize;
trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr);
/* SRR0? */
addr += tdep->wordsize;
/* Construct the frame ID using the function start. */
trad_frame_set_id (cache, frame_id_build (base, func));
return cache;
}
static void
ppcfbsd_sigtramp_frame_this_id (struct frame_info *this_frame,
void **this_cache, struct frame_id *this_id)
{
struct trad_frame_cache *cache =
ppcfbsd_sigtramp_frame_cache (this_frame, this_cache);
trad_frame_get_id (cache, this_id);
}
static struct value *
ppcfbsd_sigtramp_frame_prev_register (struct frame_info *this_frame,
void **this_cache, int regnum)
{
struct trad_frame_cache *cache =
ppcfbsd_sigtramp_frame_cache (this_frame, this_cache);
return trad_frame_get_register (cache, this_frame, regnum);
}
static const struct frame_unwind ppcfbsd_sigtramp_frame_unwind = {
SIGTRAMP_FRAME,
default_frame_unwind_stop_reason,
ppcfbsd_sigtramp_frame_this_id,
ppcfbsd_sigtramp_frame_prev_register,
NULL,
ppcfbsd_sigtramp_frame_sniffer
};
static enum return_value_convention
ppcfbsd_return_value (struct gdbarch *gdbarch, struct value *function,
struct type *valtype, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype,
regcache, readbuf, writebuf);
}
static void
ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* FreeBSD doesn't support the 128-bit `long double' from the psABI. */
set_gdbarch_long_double_bit (gdbarch, 64);
set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
if (tdep->wordsize == 4)
{
set_gdbarch_return_value (gdbarch, ppcfbsd_return_value);
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
set_solib_svr4_fetch_link_map_offsets (gdbarch,
svr4_ilp32_fetch_link_map_offsets);
frame_unwind_append_unwinder (gdbarch, &ppcfbsd_sigtramp_frame_unwind);
set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc");
}
if (tdep->wordsize == 8)
{
set_gdbarch_convert_from_func_ptr_addr
(gdbarch, ppc64_convert_from_func_ptr_addr);
set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
set_solib_svr4_fetch_link_map_offsets (gdbarch,
svr4_lp64_fetch_link_map_offsets);
set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc");
}
set_gdbarch_regset_from_core_section
(gdbarch, ppcfbsd_regset_from_core_section);
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
}
/* Provide a prototype to silence -Wmissing-prototypes. */
void _initialize_ppcfbsd_tdep (void);
void
_initialize_ppcfbsd_tdep (void)
{
gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc, GDB_OSABI_FREEBSD_ELF,
ppcfbsd_init_abi);
gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc64,
GDB_OSABI_FREEBSD_ELF,
ppcfbsd_init_abi);
gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_FREEBSD_ELF,
ppcfbsd_init_abi);
}

29
gdb/ppcfbsd-tdep.h Normal file
View File

@ -0,0 +1,29 @@
/* Target-dependent code for GDB on PowerPC systems running FreeBSD.
Copyright (C) 2013 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 3 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, see <http://www.gnu.org/licenses/>. */
#ifndef PPCFBSD_TDEP_H
#define PPCFBSD_TDEP_H
struct regset;
/* From ppcfbsd-tdep.c ... */
const struct regset *ppc_fbsd_gregset (int);
const struct regset *ppc_fbsd_fpregset (void);
#endif /* PPCFBSD_TDEP_H */