2008-04-17 Daniel Jacobowitz <dan@codesourcery.com>
[deliverable/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);
5b0a002e
UW
32/* Defined in auto-generated file reg-ppc64.c. */
33void init_registers_ppc64 (void);
34/* Defined in auto-generated file powerpc-64.c. */
35void init_registers_powerpc_64 (void);
d05b4ac3 36
2ec06d2e 37#define ppc_num_regs 71
0a30fbc4 38
5b0a002e
UW
39#ifdef __powerpc64__
40/* We use a constant for FPSCR instead of PT_FPSCR, because
41 many shipped PPC64 kernels had the wrong value in ptrace.h. */
42static int ppc_regmap[] =
43 {PT_R0 * 8, PT_R1 * 8, PT_R2 * 8, PT_R3 * 8,
44 PT_R4 * 8, PT_R5 * 8, PT_R6 * 8, PT_R7 * 8,
45 PT_R8 * 8, PT_R9 * 8, PT_R10 * 8, PT_R11 * 8,
46 PT_R12 * 8, PT_R13 * 8, PT_R14 * 8, PT_R15 * 8,
47 PT_R16 * 8, PT_R17 * 8, PT_R18 * 8, PT_R19 * 8,
48 PT_R20 * 8, PT_R21 * 8, PT_R22 * 8, PT_R23 * 8,
49 PT_R24 * 8, PT_R25 * 8, PT_R26 * 8, PT_R27 * 8,
50 PT_R28 * 8, PT_R29 * 8, PT_R30 * 8, PT_R31 * 8,
51 PT_FPR0*8, PT_FPR0*8 + 8, PT_FPR0*8+16, PT_FPR0*8+24,
52 PT_FPR0*8+32, PT_FPR0*8+40, PT_FPR0*8+48, PT_FPR0*8+56,
53 PT_FPR0*8+64, PT_FPR0*8+72, PT_FPR0*8+80, PT_FPR0*8+88,
54 PT_FPR0*8+96, PT_FPR0*8+104, PT_FPR0*8+112, PT_FPR0*8+120,
55 PT_FPR0*8+128, PT_FPR0*8+136, PT_FPR0*8+144, PT_FPR0*8+152,
56 PT_FPR0*8+160, PT_FPR0*8+168, PT_FPR0*8+176, PT_FPR0*8+184,
57 PT_FPR0*8+192, PT_FPR0*8+200, PT_FPR0*8+208, PT_FPR0*8+216,
58 PT_FPR0*8+224, PT_FPR0*8+232, PT_FPR0*8+240, PT_FPR0*8+248,
59 PT_NIP * 8, PT_MSR * 8, PT_CCR * 8, PT_LNK * 8,
60 PT_CTR * 8, PT_XER * 8, PT_FPR0*8 + 256 };
61#else
0a30fbc4 62/* Currently, don't check/send MQ. */
2ec06d2e 63static int ppc_regmap[] =
0a30fbc4
DJ
64 {PT_R0 * 4, PT_R1 * 4, PT_R2 * 4, PT_R3 * 4,
65 PT_R4 * 4, PT_R5 * 4, PT_R6 * 4, PT_R7 * 4,
66 PT_R8 * 4, PT_R9 * 4, PT_R10 * 4, PT_R11 * 4,
67 PT_R12 * 4, PT_R13 * 4, PT_R14 * 4, PT_R15 * 4,
68 PT_R16 * 4, PT_R17 * 4, PT_R18 * 4, PT_R19 * 4,
69 PT_R20 * 4, PT_R21 * 4, PT_R22 * 4, PT_R23 * 4,
70 PT_R24 * 4, PT_R25 * 4, PT_R26 * 4, PT_R27 * 4,
71 PT_R28 * 4, PT_R29 * 4, PT_R30 * 4, PT_R31 * 4,
30ed0a8f
DJ
72#ifdef __SPE__
73 -1, -1, -1, -1,
74 -1, -1, -1, -1,
75 -1, -1, -1, -1,
76 -1, -1, -1, -1,
77 -1, -1, -1, -1,
78 -1, -1, -1, -1,
79 -1, -1, -1, -1,
80 -1, -1, -1, -1,
81#else
0a30fbc4
DJ
82 PT_FPR0*4, PT_FPR0*4 + 8, PT_FPR0*4+16, PT_FPR0*4+24,
83 PT_FPR0*4+32, PT_FPR0*4+40, PT_FPR0*4+48, PT_FPR0*4+56,
84 PT_FPR0*4+64, PT_FPR0*4+72, PT_FPR0*4+80, PT_FPR0*4+88,
85 PT_FPR0*4+96, PT_FPR0*4+104, PT_FPR0*4+112, PT_FPR0*4+120,
86 PT_FPR0*4+128, PT_FPR0*4+136, PT_FPR0*4+144, PT_FPR0*4+152,
87 PT_FPR0*4+160, PT_FPR0*4+168, PT_FPR0*4+176, PT_FPR0*4+184,
88 PT_FPR0*4+192, PT_FPR0*4+200, PT_FPR0*4+208, PT_FPR0*4+216,
89 PT_FPR0*4+224, PT_FPR0*4+232, PT_FPR0*4+240, PT_FPR0*4+248,
30ed0a8f 90#endif
0a30fbc4 91 PT_NIP * 4, PT_MSR * 4, PT_CCR * 4, PT_LNK * 4,
30ed0a8f
DJ
92#ifdef __SPE__
93 PT_CTR * 4, PT_XER * 4, -1
94#else
95 PT_CTR * 4, PT_XER * 4, PT_FPSCR * 4
96#endif
97 };
5b0a002e 98#endif
0a30fbc4 99
2ec06d2e
DJ
100static int
101ppc_cannot_store_register (int regno)
0a30fbc4 102{
5b0a002e 103#if !defined (__powerpc64__) && !defined (__SPE__)
bc1e36ca
DJ
104 /* Some kernels do not allow us to store fpscr. */
105 if (regno == find_regno ("fpscr"))
106 return 2;
30ed0a8f 107#endif
bc1e36ca 108
0a30fbc4
DJ
109 return 0;
110}
111
2ec06d2e
DJ
112static int
113ppc_cannot_fetch_register (int regno)
0a30fbc4
DJ
114{
115 return 0;
116}
117
5b0a002e
UW
118static void
119ppc_collect_ptrace_register (int regno, char *buf)
120{
121 int size = register_size (regno);
122 if (size < sizeof (long))
123 collect_register (regno, buf + sizeof (long) - size);
124 else
125 collect_register (regno, buf);
126}
127
128static void
129ppc_supply_ptrace_register (int regno, const char *buf)
130{
131 int size = register_size (regno);
132 if (size < sizeof (long))
133 supply_register (regno, buf + sizeof (long) - size);
134 else
135 supply_register (regno, buf);
136}
137
0d62e5e8
DJ
138static CORE_ADDR
139ppc_get_pc (void)
140{
6fe305f7
UW
141 if (register_size (0) == 4)
142 {
143 unsigned int pc;
144 collect_register_by_name ("pc", &pc);
145 return (CORE_ADDR) pc;
146 }
147 else
148 {
149 unsigned long pc;
150 collect_register_by_name ("pc", &pc);
151 return (CORE_ADDR) pc;
152 }
0d62e5e8
DJ
153}
154
155static void
156ppc_set_pc (CORE_ADDR pc)
157{
6fe305f7
UW
158 if (register_size (0) == 4)
159 {
160 unsigned int newpc = pc;
161 supply_register_by_name ("pc", &newpc);
162 }
163 else
164 {
165 unsigned long newpc = pc;
166 supply_register_by_name ("pc", &newpc);
167 }
168}
169
170static void
171ppc_arch_setup (void)
172{
173#ifdef __powerpc64__
174 long msr;
0d62e5e8 175
6fe305f7
UW
176 /* On a 64-bit host, assume 64-bit inferior process. */
177#ifdef __ALTIVEC__
178 init_registers_powerpc_64 ();
179#else
180 init_registers_ppc64 ();
181#endif
182
183 /* Only if the high bit of the MSR is set, we actually have
184 a 64-bit inferior. */
185 collect_register_by_name ("msr", &msr);
186 if (msr < 0)
187 return;
188#endif
189
190 /* OK, we have a 32-bit inferior. */
191#ifdef __ALTIVEC__
192 init_registers_powerpc_32 ();
193#else
194#ifdef __SPE__
195 init_registers_powerpc_e500 ();
196#else
197 init_registers_ppc ();
198#endif
199#endif
0d62e5e8
DJ
200}
201
5b0a002e 202/* Correct in either endianness.
0d62e5e8
DJ
203 This instruction is "twge r2, r2", which GDB uses as a software
204 breakpoint. */
5b0a002e 205static const unsigned int ppc_breakpoint = 0x7d821008;
0d62e5e8
DJ
206#define ppc_breakpoint_len 4
207
208static int
209ppc_breakpoint_at (CORE_ADDR where)
210{
5b0a002e 211 unsigned int insn;
0d62e5e8 212
f450004a 213 (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
0d62e5e8
DJ
214 if (insn == ppc_breakpoint)
215 return 1;
216 /* If necessary, recognize more trap instructions here. GDB only uses the
217 one. */
218 return 0;
219}
220
e9d25b98
DJ
221/* Provide only a fill function for the general register set. ps_lgetregs
222 will use this for NPTL support. */
223
224static void ppc_fill_gregset (void *buf)
225{
226 int i;
227
228 for (i = 0; i < 32; i++)
6fe305f7 229 ppc_collect_ptrace_register (i, (char *) buf + ppc_regmap[i]);
e9d25b98
DJ
230
231 for (i = 64; i < 70; i++)
6fe305f7 232 ppc_collect_ptrace_register (i, (char *) buf + ppc_regmap[i]);
e9d25b98
DJ
233}
234
30ed0a8f
DJ
235#ifdef __ALTIVEC__
236
237#ifndef PTRACE_GETVRREGS
238#define PTRACE_GETVRREGS 18
239#define PTRACE_SETVRREGS 19
240#endif
241
242#define SIZEOF_VRREGS 33*16+4
243
244static void
245ppc_fill_vrregset (void *buf)
246{
247 int i, base;
248 char *regset = buf;
249
250 base = find_regno ("vr0");
251 for (i = 0; i < 32; i++)
252 collect_register (base + i, &regset[i * 16]);
253
254 collect_register_by_name ("vscr", &regset[32 * 16 + 12]);
255 collect_register_by_name ("vrsave", &regset[33 * 16]);
256}
257
258static void
259ppc_store_vrregset (const void *buf)
260{
261 int i, base;
262 const char *regset = buf;
263
264 base = find_regno ("vr0");
265 for (i = 0; i < 32; i++)
266 supply_register (base + i, &regset[i * 16]);
267
268 supply_register_by_name ("vscr", &regset[32 * 16 + 12]);
269 supply_register_by_name ("vrsave", &regset[33 * 16]);
270}
271
272#endif /* __ALTIVEC__ */
273
274#ifdef __SPE__
275
276#ifndef PTRACE_GETEVRREGS
277#define PTRACE_GETEVRREGS 20
278#define PTRACE_SETEVRREGS 21
279#endif
280
281struct gdb_evrregset_t
282{
283 unsigned long evr[32];
284 unsigned long long acc;
285 unsigned long spefscr;
286};
287
288static void
289ppc_fill_evrregset (void *buf)
290{
291 int i, ev0;
292 struct gdb_evrregset_t *regset = buf;
293
294 ev0 = find_regno ("ev0h");
295 for (i = 0; i < 32; i++)
296 collect_register (ev0 + i, &regset->evr[i]);
297
298 collect_register_by_name ("acc", &regset->acc);
299 collect_register_by_name ("spefscr", &regset->spefscr);
300}
301
302static void
303ppc_store_evrregset (const void *buf)
304{
305 int i, ev0;
306 const struct gdb_evrregset_t *regset = buf;
307
308 ev0 = find_regno ("ev0h");
309 for (i = 0; i < 32; i++)
310 supply_register (ev0 + i, &regset->evr[i]);
311
312 supply_register_by_name ("acc", &regset->acc);
313 supply_register_by_name ("spefscr", &regset->spefscr);
314}
315#endif /* __SPE__ */
316
e9d25b98 317struct regset_info target_regsets[] = {
30ed0a8f
DJ
318 /* List the extra register sets before GENERAL_REGS. That way we will
319 fetch them every time, but still fall back to PTRACE_PEEKUSER for the
320 general registers. Some kernels support these, but not the newer
321 PPC_PTRACE_GETREGS. */
322#ifdef __ALTIVEC__
323 { PTRACE_GETVRREGS, PTRACE_SETVRREGS, SIZEOF_VRREGS, EXTENDED_REGS,
324 ppc_fill_vrregset, ppc_store_vrregset },
325#endif
326#ifdef __SPE__
327 { PTRACE_GETEVRREGS, PTRACE_SETEVRREGS, 32 * 4 + 8 + 4, EXTENDED_REGS,
328 ppc_fill_evrregset, ppc_store_evrregset },
329#endif
e9d25b98
DJ
330 { 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
331 { 0, 0, -1, -1, NULL, NULL }
332};
333
2ec06d2e 334struct linux_target_ops the_low_target = {
6fe305f7 335 ppc_arch_setup,
2ec06d2e
DJ
336 ppc_num_regs,
337 ppc_regmap,
338 ppc_cannot_fetch_register,
339 ppc_cannot_store_register,
0d62e5e8
DJ
340 ppc_get_pc,
341 ppc_set_pc,
f450004a 342 (const unsigned char *) &ppc_breakpoint,
0d62e5e8
DJ
343 ppc_breakpoint_len,
344 NULL,
345 0,
346 ppc_breakpoint_at,
5b0a002e
UW
347 NULL,
348 NULL,
349 NULL,
350 NULL,
351 ppc_collect_ptrace_register,
352 ppc_supply_ptrace_register,
2ec06d2e 353};
This page took 0.479465 seconds and 4 git commands to generate.