fbsd-powerpc-low.c revision 303975
1230479Snetchild/* FreeBSD/PowerPC specific low level interface, for the remote server for
2230479Snetchild   GDB.
3230479Snetchild   Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002
4230479Snetchild   Free Software Foundation, Inc.
5230479Snetchild
6230479Snetchild   This file is part of GDB.
7230479Snetchild
8230479Snetchild   This program is free software; you can redistribute it and/or modify
9230479Snetchild   it under the terms of the GNU General Public License as published by
10230479Snetchild   the Free Software Foundation; either version 2 of the License, or
11230479Snetchild   (at your option) any later version.
12230479Snetchild
13230479Snetchild   This program is distributed in the hope that it will be useful,
14230479Snetchild   but WITHOUT ANY WARRANTY; without even the implied warranty of
15230479Snetchild   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16230479Snetchild   GNU General Public License for more details.
17230479Snetchild
18230479Snetchild   You should have received a copy of the GNU General Public License
19230479Snetchild   along with this program; if not, write to the Free Software
20230479Snetchild   Foundation, Inc., 59 Temple Place - Suite 330,
21230479Snetchild   Boston, MA 02111-1307, USA.  */
22
23#include <sys/cdefs.h>
24__FBSDID("$FreeBSD: releng/11.0/gnu/usr.bin/gdb/gdbserver/fbsd-powerpc-low.c 206624 2010-04-14 20:31:06Z imp $");
25
26#include "server.h"
27#include "fbsd-low.h"
28
29#include <sys/procfs.h>
30#include <sys/ptrace.h>
31
32#define ppc_num_regs 71
33
34/* Currently, don't check/send MQ.  */
35static int ppc_regmap[] =
36 { 0, 4, 8, 12, 16, 20, 24, 28,
37   32, 36, 40, 44, 48, 52, 56, 60,
38   64, 68, 72, 76, 80, 84, 88, 92,
39   96, 100, 104, 108, 112, 116, 120, 124,
40#if 0
41  /*
42   * XXX on FreeBSD the gdbserver for PowerPC was only tested with FPU-less
43   * cores i.e. e500. Let's leave the original FPR references around in case
44   * someone picks up and brings support for AIM-like FPU machines.
45   */
46  PT_FPR0*4,     PT_FPR0*4 + 8, PT_FPR0*4+16,  PT_FPR0*4+24,
47  PT_FPR0*4+32,  PT_FPR0*4+40,  PT_FPR0*4+48,  PT_FPR0*4+56,
48  PT_FPR0*4+64,  PT_FPR0*4+72,  PT_FPR0*4+80,  PT_FPR0*4+88,
49  PT_FPR0*4+96,  PT_FPR0*4+104,  PT_FPR0*4+112,  PT_FPR0*4+120,
50  PT_FPR0*4+128, PT_FPR0*4+136,  PT_FPR0*4+144,  PT_FPR0*4+152,
51  PT_FPR0*4+160,  PT_FPR0*4+168,  PT_FPR0*4+176,  PT_FPR0*4+184,
52  PT_FPR0*4+192,  PT_FPR0*4+200,  PT_FPR0*4+208,  PT_FPR0*4+216,
53  PT_FPR0*4+224,  PT_FPR0*4+232,  PT_FPR0*4+240,  PT_FPR0*4+248,
54#endif
55   -1, -1, -1, -1, -1, -1, -1, -1,
56   -1, -1, -1, -1, -1, -1, -1, -1,
57   -1, -1, -1, -1, -1, -1, -1, -1,
58   -1, -1, -1, -1, -1, -1, -1, -1,
59   144, -1, 132, 128, 140, 136, -1
60 };
61
62static int
63ppc_cannot_store_register (int regno)
64{
65  /* Some kernels do not allow us to store fpscr.  */
66  if (regno == find_regno ("fpscr"))
67    return 2;
68
69  return 0;
70}
71
72static int
73ppc_cannot_fetch_register (int regno)
74{
75  return 0;
76}
77
78static CORE_ADDR
79ppc_get_pc (void)
80{
81  unsigned long pc;
82
83  collect_register_by_name ("pc", &pc);
84  return (CORE_ADDR) pc;
85}
86
87static void
88ppc_set_pc (CORE_ADDR pc)
89{
90  unsigned long newpc = pc;
91
92  supply_register_by_name ("pc", &newpc);
93}
94
95/* Correct in either endianness.  Note that this file is
96   for PowerPC only, not PowerPC64.
97   This instruction is "twge r2, r2", which GDB uses as a software
98   breakpoint.  */
99static const unsigned long ppc_breakpoint = 0x7d821008;
100#define ppc_breakpoint_len 4
101
102static int
103ppc_breakpoint_at (CORE_ADDR where)
104{
105  unsigned long insn;
106
107  (*the_target->read_memory) (where, (char *) &insn, 4);
108  if (insn == ppc_breakpoint)
109    return 1;
110  /* If necessary, recognize more trap instructions here.  GDB only uses the
111     one.  */
112  return 0;
113}
114
115static void
116ppc_fill_gregset (void *buf)
117{
118  int i;
119
120  for (i = 0; i < ppc_num_regs; i++)
121	if (ppc_regmap[i] != -1)
122		collect_register (i, ((char *) buf) + ppc_regmap[i]);
123
124}
125
126static void
127ppc_store_gregset (const void *buf)
128{
129  int i;
130
131  for (i = 0; i < ppc_num_regs; i++)
132	if (ppc_regmap[i] != -1)
133		supply_register (i, ((char *) buf) + ppc_regmap[i]);
134
135}
136
137struct regset_info target_regsets[] = {
138  { PT_GETREGS, PT_SETREGS, sizeof (struct reg),
139    GENERAL_REGS,
140    ppc_fill_gregset, ppc_store_gregset },
141  { 0, 0, -1, -1, NULL, NULL }
142};
143
144struct fbsd_target_ops the_low_target = {
145  ppc_num_regs,
146  ppc_regmap,
147  ppc_cannot_fetch_register,
148  ppc_cannot_store_register,
149  ppc_get_pc,
150  ppc_set_pc,
151  (const char *) &ppc_breakpoint,
152  ppc_breakpoint_len,
153  NULL,
154  0,
155  ppc_breakpoint_at,
156};
157