]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/linux-ppc-low.c
* configure.srv [powerpc64-*-linux*]: Use linux-ppc-low.o
[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);
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{
141 unsigned long pc;
142
143 collect_register_by_name ("pc", &pc);
144 return (CORE_ADDR) pc;
145}
146
147static void
148ppc_set_pc (CORE_ADDR pc)
149{
150 unsigned long newpc = pc;
151
152 supply_register_by_name ("pc", &newpc);
153}
154
5b0a002e 155/* Correct in either endianness.
0d62e5e8
DJ
156 This instruction is "twge r2, r2", which GDB uses as a software
157 breakpoint. */
5b0a002e 158static const unsigned int ppc_breakpoint = 0x7d821008;
0d62e5e8
DJ
159#define ppc_breakpoint_len 4
160
161static int
162ppc_breakpoint_at (CORE_ADDR where)
163{
5b0a002e 164 unsigned int insn;
0d62e5e8 165
f450004a 166 (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
0d62e5e8
DJ
167 if (insn == ppc_breakpoint)
168 return 1;
169 /* If necessary, recognize more trap instructions here. GDB only uses the
170 one. */
171 return 0;
172}
173
e9d25b98
DJ
174/* Provide only a fill function for the general register set. ps_lgetregs
175 will use this for NPTL support. */
176
177static void ppc_fill_gregset (void *buf)
178{
179 int i;
180
181 for (i = 0; i < 32; i++)
182 collect_register (i, (char *) buf + ppc_regmap[i]);
183
184 for (i = 64; i < 70; i++)
185 collect_register (i, (char *) buf + ppc_regmap[i]);
186}
187
30ed0a8f
DJ
188#ifdef __ALTIVEC__
189
190#ifndef PTRACE_GETVRREGS
191#define PTRACE_GETVRREGS 18
192#define PTRACE_SETVRREGS 19
193#endif
194
195#define SIZEOF_VRREGS 33*16+4
196
197static void
198ppc_fill_vrregset (void *buf)
199{
200 int i, base;
201 char *regset = buf;
202
203 base = find_regno ("vr0");
204 for (i = 0; i < 32; i++)
205 collect_register (base + i, &regset[i * 16]);
206
207 collect_register_by_name ("vscr", &regset[32 * 16 + 12]);
208 collect_register_by_name ("vrsave", &regset[33 * 16]);
209}
210
211static void
212ppc_store_vrregset (const void *buf)
213{
214 int i, base;
215 const char *regset = buf;
216
217 base = find_regno ("vr0");
218 for (i = 0; i < 32; i++)
219 supply_register (base + i, &regset[i * 16]);
220
221 supply_register_by_name ("vscr", &regset[32 * 16 + 12]);
222 supply_register_by_name ("vrsave", &regset[33 * 16]);
223}
224
225#endif /* __ALTIVEC__ */
226
227#ifdef __SPE__
228
229#ifndef PTRACE_GETEVRREGS
230#define PTRACE_GETEVRREGS 20
231#define PTRACE_SETEVRREGS 21
232#endif
233
234struct gdb_evrregset_t
235{
236 unsigned long evr[32];
237 unsigned long long acc;
238 unsigned long spefscr;
239};
240
241static void
242ppc_fill_evrregset (void *buf)
243{
244 int i, ev0;
245 struct gdb_evrregset_t *regset = buf;
246
247 ev0 = find_regno ("ev0h");
248 for (i = 0; i < 32; i++)
249 collect_register (ev0 + i, &regset->evr[i]);
250
251 collect_register_by_name ("acc", &regset->acc);
252 collect_register_by_name ("spefscr", &regset->spefscr);
253}
254
255static void
256ppc_store_evrregset (const void *buf)
257{
258 int i, ev0;
259 const struct gdb_evrregset_t *regset = buf;
260
261 ev0 = find_regno ("ev0h");
262 for (i = 0; i < 32; i++)
263 supply_register (ev0 + i, &regset->evr[i]);
264
265 supply_register_by_name ("acc", &regset->acc);
266 supply_register_by_name ("spefscr", &regset->spefscr);
267}
268#endif /* __SPE__ */
269
e9d25b98 270struct regset_info target_regsets[] = {
30ed0a8f
DJ
271 /* List the extra register sets before GENERAL_REGS. That way we will
272 fetch them every time, but still fall back to PTRACE_PEEKUSER for the
273 general registers. Some kernels support these, but not the newer
274 PPC_PTRACE_GETREGS. */
275#ifdef __ALTIVEC__
276 { PTRACE_GETVRREGS, PTRACE_SETVRREGS, SIZEOF_VRREGS, EXTENDED_REGS,
277 ppc_fill_vrregset, ppc_store_vrregset },
278#endif
279#ifdef __SPE__
280 { PTRACE_GETEVRREGS, PTRACE_SETEVRREGS, 32 * 4 + 8 + 4, EXTENDED_REGS,
281 ppc_fill_evrregset, ppc_store_evrregset },
282#endif
e9d25b98
DJ
283 { 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
284 { 0, 0, -1, -1, NULL, NULL }
285};
286
2ec06d2e 287struct linux_target_ops the_low_target = {
5b0a002e
UW
288#ifdef __powerpc64__
289#ifdef __ALTIVEC__
290 init_registers_powerpc_64,
291#else
292 init_registers_ppc64,
293#endif
294#else
d05b4ac3
UW
295#ifdef __ALTIVEC__
296 init_registers_powerpc_32,
297#else
298#ifdef __SPE__
299 init_registers_powerpc_e500,
300#else
301 init_registers_ppc,
302#endif
5b0a002e 303#endif
d05b4ac3 304#endif
2ec06d2e
DJ
305 ppc_num_regs,
306 ppc_regmap,
307 ppc_cannot_fetch_register,
308 ppc_cannot_store_register,
0d62e5e8
DJ
309 ppc_get_pc,
310 ppc_set_pc,
f450004a 311 (const unsigned char *) &ppc_breakpoint,
0d62e5e8
DJ
312 ppc_breakpoint_len,
313 NULL,
314 0,
315 ppc_breakpoint_at,
5b0a002e
UW
316 NULL,
317 NULL,
318 NULL,
319 NULL,
320 ppc_collect_ptrace_register,
321 ppc_supply_ptrace_register,
2ec06d2e 322};