]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/linux-ppc-low.c
ChangeLog:
[thirdparty/binutils-gdb.git] / gdb / gdbserver / linux-ppc-low.c
CommitLineData
0a30fbc4
DJ
1/* GNU/Linux/PowerPC specific low level interface, for the remote server for
2 GDB.
9b254dd1 3 Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2005, 2007, 2008
0a30fbc4
DJ
4 Free Software Foundation, Inc.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
0a30fbc4
DJ
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
0a30fbc4
DJ
20
21#include "server.h"
58caa3dc 22#include "linux-low.h"
0a30fbc4
DJ
23
24#include <asm/ptrace.h>
25
d05b4ac3
UW
26/* Defined in auto-generated file reg-ppc.c. */
27void init_registers_ppc (void);
28/* Defined in auto-generated file powerpc-32.c. */
29void init_registers_powerpc_32 (void);
30/* Defined in auto-generated file powerpc-e500.c. */
31void init_registers_powerpc_e500 (void);
32
2ec06d2e 33#define ppc_num_regs 71
0a30fbc4
DJ
34
35/* Currently, don't check/send MQ. */
2ec06d2e 36static int ppc_regmap[] =
0a30fbc4
DJ
37 {PT_R0 * 4, PT_R1 * 4, PT_R2 * 4, PT_R3 * 4,
38 PT_R4 * 4, PT_R5 * 4, PT_R6 * 4, PT_R7 * 4,
39 PT_R8 * 4, PT_R9 * 4, PT_R10 * 4, PT_R11 * 4,
40 PT_R12 * 4, PT_R13 * 4, PT_R14 * 4, PT_R15 * 4,
41 PT_R16 * 4, PT_R17 * 4, PT_R18 * 4, PT_R19 * 4,
42 PT_R20 * 4, PT_R21 * 4, PT_R22 * 4, PT_R23 * 4,
43 PT_R24 * 4, PT_R25 * 4, PT_R26 * 4, PT_R27 * 4,
44 PT_R28 * 4, PT_R29 * 4, PT_R30 * 4, PT_R31 * 4,
30ed0a8f
DJ
45#ifdef __SPE__
46 -1, -1, -1, -1,
47 -1, -1, -1, -1,
48 -1, -1, -1, -1,
49 -1, -1, -1, -1,
50 -1, -1, -1, -1,
51 -1, -1, -1, -1,
52 -1, -1, -1, -1,
53 -1, -1, -1, -1,
54#else
0a30fbc4
DJ
55 PT_FPR0*4, PT_FPR0*4 + 8, PT_FPR0*4+16, PT_FPR0*4+24,
56 PT_FPR0*4+32, PT_FPR0*4+40, PT_FPR0*4+48, PT_FPR0*4+56,
57 PT_FPR0*4+64, PT_FPR0*4+72, PT_FPR0*4+80, PT_FPR0*4+88,
58 PT_FPR0*4+96, PT_FPR0*4+104, PT_FPR0*4+112, PT_FPR0*4+120,
59 PT_FPR0*4+128, PT_FPR0*4+136, PT_FPR0*4+144, PT_FPR0*4+152,
60 PT_FPR0*4+160, PT_FPR0*4+168, PT_FPR0*4+176, PT_FPR0*4+184,
61 PT_FPR0*4+192, PT_FPR0*4+200, PT_FPR0*4+208, PT_FPR0*4+216,
62 PT_FPR0*4+224, PT_FPR0*4+232, PT_FPR0*4+240, PT_FPR0*4+248,
30ed0a8f 63#endif
0a30fbc4 64 PT_NIP * 4, PT_MSR * 4, PT_CCR * 4, PT_LNK * 4,
30ed0a8f
DJ
65#ifdef __SPE__
66 PT_CTR * 4, PT_XER * 4, -1
67#else
68 PT_CTR * 4, PT_XER * 4, PT_FPSCR * 4
69#endif
70 };
0a30fbc4 71
2ec06d2e
DJ
72static int
73ppc_cannot_store_register (int regno)
0a30fbc4 74{
30ed0a8f 75#ifndef __SPE__
bc1e36ca
DJ
76 /* Some kernels do not allow us to store fpscr. */
77 if (regno == find_regno ("fpscr"))
78 return 2;
30ed0a8f 79#endif
bc1e36ca 80
0a30fbc4
DJ
81 return 0;
82}
83
2ec06d2e
DJ
84static int
85ppc_cannot_fetch_register (int regno)
0a30fbc4
DJ
86{
87 return 0;
88}
89
0d62e5e8
DJ
90static CORE_ADDR
91ppc_get_pc (void)
92{
93 unsigned long pc;
94
95 collect_register_by_name ("pc", &pc);
96 return (CORE_ADDR) pc;
97}
98
99static void
100ppc_set_pc (CORE_ADDR pc)
101{
102 unsigned long newpc = pc;
103
104 supply_register_by_name ("pc", &newpc);
105}
106
107/* Correct in either endianness. Note that this file is
108 for PowerPC only, not PowerPC64.
109 This instruction is "twge r2, r2", which GDB uses as a software
110 breakpoint. */
111static const unsigned long ppc_breakpoint = 0x7d821008;
112#define ppc_breakpoint_len 4
113
114static int
115ppc_breakpoint_at (CORE_ADDR where)
116{
117 unsigned long insn;
118
f450004a 119 (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
0d62e5e8
DJ
120 if (insn == ppc_breakpoint)
121 return 1;
122 /* If necessary, recognize more trap instructions here. GDB only uses the
123 one. */
124 return 0;
125}
126
e9d25b98
DJ
127/* Provide only a fill function for the general register set. ps_lgetregs
128 will use this for NPTL support. */
129
130static void ppc_fill_gregset (void *buf)
131{
132 int i;
133
134 for (i = 0; i < 32; i++)
135 collect_register (i, (char *) buf + ppc_regmap[i]);
136
137 for (i = 64; i < 70; i++)
138 collect_register (i, (char *) buf + ppc_regmap[i]);
139}
140
30ed0a8f
DJ
141#ifdef __ALTIVEC__
142
143#ifndef PTRACE_GETVRREGS
144#define PTRACE_GETVRREGS 18
145#define PTRACE_SETVRREGS 19
146#endif
147
148#define SIZEOF_VRREGS 33*16+4
149
150static void
151ppc_fill_vrregset (void *buf)
152{
153 int i, base;
154 char *regset = buf;
155
156 base = find_regno ("vr0");
157 for (i = 0; i < 32; i++)
158 collect_register (base + i, &regset[i * 16]);
159
160 collect_register_by_name ("vscr", &regset[32 * 16 + 12]);
161 collect_register_by_name ("vrsave", &regset[33 * 16]);
162}
163
164static void
165ppc_store_vrregset (const void *buf)
166{
167 int i, base;
168 const char *regset = buf;
169
170 base = find_regno ("vr0");
171 for (i = 0; i < 32; i++)
172 supply_register (base + i, &regset[i * 16]);
173
174 supply_register_by_name ("vscr", &regset[32 * 16 + 12]);
175 supply_register_by_name ("vrsave", &regset[33 * 16]);
176}
177
178#endif /* __ALTIVEC__ */
179
180#ifdef __SPE__
181
182#ifndef PTRACE_GETEVRREGS
183#define PTRACE_GETEVRREGS 20
184#define PTRACE_SETEVRREGS 21
185#endif
186
187struct gdb_evrregset_t
188{
189 unsigned long evr[32];
190 unsigned long long acc;
191 unsigned long spefscr;
192};
193
194static void
195ppc_fill_evrregset (void *buf)
196{
197 int i, ev0;
198 struct gdb_evrregset_t *regset = buf;
199
200 ev0 = find_regno ("ev0h");
201 for (i = 0; i < 32; i++)
202 collect_register (ev0 + i, &regset->evr[i]);
203
204 collect_register_by_name ("acc", &regset->acc);
205 collect_register_by_name ("spefscr", &regset->spefscr);
206}
207
208static void
209ppc_store_evrregset (const void *buf)
210{
211 int i, ev0;
212 const struct gdb_evrregset_t *regset = buf;
213
214 ev0 = find_regno ("ev0h");
215 for (i = 0; i < 32; i++)
216 supply_register (ev0 + i, &regset->evr[i]);
217
218 supply_register_by_name ("acc", &regset->acc);
219 supply_register_by_name ("spefscr", &regset->spefscr);
220}
221#endif /* __SPE__ */
222
e9d25b98 223struct regset_info target_regsets[] = {
30ed0a8f
DJ
224 /* List the extra register sets before GENERAL_REGS. That way we will
225 fetch them every time, but still fall back to PTRACE_PEEKUSER for the
226 general registers. Some kernels support these, but not the newer
227 PPC_PTRACE_GETREGS. */
228#ifdef __ALTIVEC__
229 { PTRACE_GETVRREGS, PTRACE_SETVRREGS, SIZEOF_VRREGS, EXTENDED_REGS,
230 ppc_fill_vrregset, ppc_store_vrregset },
231#endif
232#ifdef __SPE__
233 { PTRACE_GETEVRREGS, PTRACE_SETEVRREGS, 32 * 4 + 8 + 4, EXTENDED_REGS,
234 ppc_fill_evrregset, ppc_store_evrregset },
235#endif
e9d25b98
DJ
236 { 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
237 { 0, 0, -1, -1, NULL, NULL }
238};
239
2ec06d2e 240struct linux_target_ops the_low_target = {
d05b4ac3
UW
241#ifdef __ALTIVEC__
242 init_registers_powerpc_32,
243#else
244#ifdef __SPE__
245 init_registers_powerpc_e500,
246#else
247 init_registers_ppc,
248#endif
249#endif
2ec06d2e
DJ
250 ppc_num_regs,
251 ppc_regmap,
252 ppc_cannot_fetch_register,
253 ppc_cannot_store_register,
0d62e5e8
DJ
254 ppc_get_pc,
255 ppc_set_pc,
f450004a 256 (const unsigned char *) &ppc_breakpoint,
0d62e5e8
DJ
257 ppc_breakpoint_len,
258 NULL,
259 0,
260 ppc_breakpoint_at,
2ec06d2e 261};