binutils-gdb/gdb/gdbserver/lynx-ppc-low.c

189 lines
5.8 KiB
C

/* Copyright (C) 2009-2014 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 "server.h"
#include "lynx-low.h"
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
#include <sys/ptrace.h>
/* The following two typedefs are defined in a .h file which is not
in the standard include path (/sys/include/family/ppc/ucontext.h),
so we just duplicate them here. */
/* General register context */
typedef struct usr_econtext_s
{
uint32_t uec_iregs[32];
uint32_t uec_inum;
uint32_t uec_srr0;
uint32_t uec_srr1;
uint32_t uec_lr;
uint32_t uec_ctr;
uint32_t uec_cr;
uint32_t uec_xer;
uint32_t uec_dar;
uint32_t uec_mq;
uint32_t uec_msr;
uint32_t uec_sregs[16];
uint32_t uec_ss_count;
uint32_t uec_ss_addr1;
uint32_t uec_ss_addr2;
uint32_t uec_ss_code1;
uint32_t uec_ss_code2;
} usr_econtext_t;
/* Floating point register context */
typedef struct usr_fcontext_s
{
uint64_t ufc_freg[32];
uint32_t ufc_fpscr[2];
} usr_fcontext_t;
/* Index of for various registers inside the regcache. */
#define R0_REGNUM 0
#define F0_REGNUM 32
#define PC_REGNUM 64
#define MSR_REGNUM 65
#define CR_REGNUM 66
#define LR_REGNUM 67
#define CTR_REGNUM 68
#define XER_REGNUM 69
#define FPSCR_REGNUM 70
/* Defined in auto-generated file powerpc-32.c. */
extern void init_registers_powerpc_32 (void);
extern const struct target_desc *tdesc_powerpc_32;
/* The fill_function for the general-purpose register set. */
static void
lynx_ppc_fill_gregset (struct regcache *regcache, char *buf)
{
int i;
/* r0 - r31 */
for (i = 0; i < 32; i++)
collect_register (regcache, R0_REGNUM + i,
buf + offsetof (usr_econtext_t, uec_iregs[i]));
/* The other registers provided in the GP register context. */
collect_register (regcache, PC_REGNUM,
buf + offsetof (usr_econtext_t, uec_srr0));
collect_register (regcache, MSR_REGNUM,
buf + offsetof (usr_econtext_t, uec_srr1));
collect_register (regcache, CR_REGNUM,
buf + offsetof (usr_econtext_t, uec_cr));
collect_register (regcache, LR_REGNUM,
buf + offsetof (usr_econtext_t, uec_lr));
collect_register (regcache, CTR_REGNUM,
buf + offsetof (usr_econtext_t, uec_ctr));
collect_register (regcache, XER_REGNUM,
buf + offsetof (usr_econtext_t, uec_xer));
}
/* The store_function for the general-purpose register set. */
static void
lynx_ppc_store_gregset (struct regcache *regcache, const char *buf)
{
int i;
/* r0 - r31 */
for (i = 0; i < 32; i++)
supply_register (regcache, R0_REGNUM + i,
buf + offsetof (usr_econtext_t, uec_iregs[i]));
/* The other registers provided in the GP register context. */
supply_register (regcache, PC_REGNUM,
buf + offsetof (usr_econtext_t, uec_srr0));
supply_register (regcache, MSR_REGNUM,
buf + offsetof (usr_econtext_t, uec_srr1));
supply_register (regcache, CR_REGNUM,
buf + offsetof (usr_econtext_t, uec_cr));
supply_register (regcache, LR_REGNUM,
buf + offsetof (usr_econtext_t, uec_lr));
supply_register (regcache, CTR_REGNUM,
buf + offsetof (usr_econtext_t, uec_ctr));
supply_register (regcache, XER_REGNUM,
buf + offsetof (usr_econtext_t, uec_xer));
}
/* The fill_function for the floating-point register set. */
static void
lynx_ppc_fill_fpregset (struct regcache *regcache, char *buf)
{
int i;
/* f0 - f31 */
for (i = 0; i < 32; i++)
collect_register (regcache, F0_REGNUM + i,
buf + offsetof (usr_fcontext_t, ufc_freg[i]));
/* fpscr */
collect_register (regcache, FPSCR_REGNUM,
buf + offsetof (usr_fcontext_t, ufc_fpscr));
}
/* The store_function for the floating-point register set. */
static void
lynx_ppc_store_fpregset (struct regcache *regcache, const char *buf)
{
int i;
/* f0 - f31 */
for (i = 0; i < 32; i++)
supply_register (regcache, F0_REGNUM + i,
buf + offsetof (usr_fcontext_t, ufc_freg[i]));
/* fpscr */
supply_register (regcache, FPSCR_REGNUM,
buf + offsetof (usr_fcontext_t, ufc_fpscr));
}
/* Implements the lynx_target_ops.arch_setup routine. */
static void
lynx_ppc_arch_setup (void)
{
init_registers_powerpc_32 ();
lynx_tdesc = tdesc_powerpc_32;
}
/* Description of all the powerpc-lynx register sets. */
struct lynx_regset_info lynx_target_regsets[] = {
/* General Purpose Registers. */
{PTRACE_GETREGS, PTRACE_SETREGS, sizeof(usr_econtext_t),
lynx_ppc_fill_gregset, lynx_ppc_store_gregset},
/* Floating Point Registers. */
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof(usr_fcontext_t),
lynx_ppc_fill_fpregset, lynx_ppc_store_fpregset },
/* End of list marker. */
{0, 0, -1, NULL, NULL }
};
/* The lynx_target_ops vector for powerpc-lynxos. */
struct lynx_target_ops the_low_target = {
lynx_ppc_arch_setup,
};