gdb/
[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 23
b6430ec3 24#include <elf.h>
0a30fbc4
DJ
25#include <asm/ptrace.h>
26
b6430ec3 27/* These are in <asm/cputable.h> in current kernels. */
677c5bb1 28#define PPC_FEATURE_HAS_VSX 0x00000080
b6430ec3
UW
29#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
30#define PPC_FEATURE_HAS_SPE 0x00800000
31
32static unsigned long ppc_hwcap;
33
34
7284e1be
UW
35/* Defined in auto-generated file powerpc-32l.c. */
36void init_registers_powerpc_32l (void);
37/* Defined in auto-generated file powerpc-altivec32l.c. */
38void init_registers_powerpc_altivec32l (void);
677c5bb1
LM
39/* Defined in auto-generated file powerpc-vsx32l.c. */
40void init_registers_powerpc_vsx32l (void);
7284e1be
UW
41/* Defined in auto-generated file powerpc-e500l.c. */
42void init_registers_powerpc_e500l (void);
43/* Defined in auto-generated file powerpc-64l.c. */
44void init_registers_powerpc_64l (void);
45/* Defined in auto-generated file powerpc-altivec64l.c. */
46void init_registers_powerpc_altivec64l (void);
677c5bb1
LM
47/* Defined in auto-generated file powerpc-vsx64l.c. */
48void init_registers_powerpc_vsx64l (void);
7284e1be
UW
49
50#define ppc_num_regs 73
51
52/* This sometimes isn't defined. */
53#ifndef PT_ORIG_R3
54#define PT_ORIG_R3 34
55#endif
56#ifndef PT_TRAP
57#define PT_TRAP 40
58#endif
0a30fbc4 59
5b0a002e
UW
60#ifdef __powerpc64__
61/* We use a constant for FPSCR instead of PT_FPSCR, because
62 many shipped PPC64 kernels had the wrong value in ptrace.h. */
63static int ppc_regmap[] =
64 {PT_R0 * 8, PT_R1 * 8, PT_R2 * 8, PT_R3 * 8,
65 PT_R4 * 8, PT_R5 * 8, PT_R6 * 8, PT_R7 * 8,
66 PT_R8 * 8, PT_R9 * 8, PT_R10 * 8, PT_R11 * 8,
67 PT_R12 * 8, PT_R13 * 8, PT_R14 * 8, PT_R15 * 8,
68 PT_R16 * 8, PT_R17 * 8, PT_R18 * 8, PT_R19 * 8,
69 PT_R20 * 8, PT_R21 * 8, PT_R22 * 8, PT_R23 * 8,
70 PT_R24 * 8, PT_R25 * 8, PT_R26 * 8, PT_R27 * 8,
71 PT_R28 * 8, PT_R29 * 8, PT_R30 * 8, PT_R31 * 8,
72 PT_FPR0*8, PT_FPR0*8 + 8, PT_FPR0*8+16, PT_FPR0*8+24,
73 PT_FPR0*8+32, PT_FPR0*8+40, PT_FPR0*8+48, PT_FPR0*8+56,
74 PT_FPR0*8+64, PT_FPR0*8+72, PT_FPR0*8+80, PT_FPR0*8+88,
75 PT_FPR0*8+96, PT_FPR0*8+104, PT_FPR0*8+112, PT_FPR0*8+120,
76 PT_FPR0*8+128, PT_FPR0*8+136, PT_FPR0*8+144, PT_FPR0*8+152,
77 PT_FPR0*8+160, PT_FPR0*8+168, PT_FPR0*8+176, PT_FPR0*8+184,
78 PT_FPR0*8+192, PT_FPR0*8+200, PT_FPR0*8+208, PT_FPR0*8+216,
79 PT_FPR0*8+224, PT_FPR0*8+232, PT_FPR0*8+240, PT_FPR0*8+248,
80 PT_NIP * 8, PT_MSR * 8, PT_CCR * 8, PT_LNK * 8,
7284e1be
UW
81 PT_CTR * 8, PT_XER * 8, PT_FPR0*8 + 256,
82 PT_ORIG_R3 * 8, PT_TRAP * 8 };
5b0a002e 83#else
0a30fbc4 84/* Currently, don't check/send MQ. */
2ec06d2e 85static int ppc_regmap[] =
0a30fbc4
DJ
86 {PT_R0 * 4, PT_R1 * 4, PT_R2 * 4, PT_R3 * 4,
87 PT_R4 * 4, PT_R5 * 4, PT_R6 * 4, PT_R7 * 4,
88 PT_R8 * 4, PT_R9 * 4, PT_R10 * 4, PT_R11 * 4,
89 PT_R12 * 4, PT_R13 * 4, PT_R14 * 4, PT_R15 * 4,
90 PT_R16 * 4, PT_R17 * 4, PT_R18 * 4, PT_R19 * 4,
91 PT_R20 * 4, PT_R21 * 4, PT_R22 * 4, PT_R23 * 4,
92 PT_R24 * 4, PT_R25 * 4, PT_R26 * 4, PT_R27 * 4,
93 PT_R28 * 4, PT_R29 * 4, PT_R30 * 4, PT_R31 * 4,
94 PT_FPR0*4, PT_FPR0*4 + 8, PT_FPR0*4+16, PT_FPR0*4+24,
95 PT_FPR0*4+32, PT_FPR0*4+40, PT_FPR0*4+48, PT_FPR0*4+56,
96 PT_FPR0*4+64, PT_FPR0*4+72, PT_FPR0*4+80, PT_FPR0*4+88,
97 PT_FPR0*4+96, PT_FPR0*4+104, PT_FPR0*4+112, PT_FPR0*4+120,
98 PT_FPR0*4+128, PT_FPR0*4+136, PT_FPR0*4+144, PT_FPR0*4+152,
99 PT_FPR0*4+160, PT_FPR0*4+168, PT_FPR0*4+176, PT_FPR0*4+184,
100 PT_FPR0*4+192, PT_FPR0*4+200, PT_FPR0*4+208, PT_FPR0*4+216,
101 PT_FPR0*4+224, PT_FPR0*4+232, PT_FPR0*4+240, PT_FPR0*4+248,
102 PT_NIP * 4, PT_MSR * 4, PT_CCR * 4, PT_LNK * 4,
7284e1be
UW
103 PT_CTR * 4, PT_XER * 4, PT_FPSCR * 4,
104 PT_ORIG_R3 * 4, PT_TRAP * 4
b6430ec3
UW
105 };
106
107static int ppc_regmap_e500[] =
108 {PT_R0 * 4, PT_R1 * 4, PT_R2 * 4, PT_R3 * 4,
109 PT_R4 * 4, PT_R5 * 4, PT_R6 * 4, PT_R7 * 4,
110 PT_R8 * 4, PT_R9 * 4, PT_R10 * 4, PT_R11 * 4,
111 PT_R12 * 4, PT_R13 * 4, PT_R14 * 4, PT_R15 * 4,
112 PT_R16 * 4, PT_R17 * 4, PT_R18 * 4, PT_R19 * 4,
113 PT_R20 * 4, PT_R21 * 4, PT_R22 * 4, PT_R23 * 4,
114 PT_R24 * 4, PT_R25 * 4, PT_R26 * 4, PT_R27 * 4,
115 PT_R28 * 4, PT_R29 * 4, PT_R30 * 4, PT_R31 * 4,
116 -1, -1, -1, -1,
117 -1, -1, -1, -1,
118 -1, -1, -1, -1,
119 -1, -1, -1, -1,
120 -1, -1, -1, -1,
121 -1, -1, -1, -1,
122 -1, -1, -1, -1,
123 -1, -1, -1, -1,
124 PT_NIP * 4, PT_MSR * 4, PT_CCR * 4, PT_LNK * 4,
7284e1be
UW
125 PT_CTR * 4, PT_XER * 4, -1,
126 PT_ORIG_R3 * 4, PT_TRAP * 4
30ed0a8f 127 };
5b0a002e 128#endif
0a30fbc4 129
2ec06d2e
DJ
130static int
131ppc_cannot_store_register (int regno)
0a30fbc4 132{
b6430ec3 133#ifndef __powerpc64__
bc1e36ca 134 /* Some kernels do not allow us to store fpscr. */
b6430ec3 135 if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE) && regno == find_regno ("fpscr"))
bc1e36ca 136 return 2;
30ed0a8f 137#endif
bc1e36ca 138
7284e1be
UW
139 /* Some kernels do not allow us to store orig_r3 or trap. */
140 if (regno == find_regno ("orig_r3")
141 || regno == find_regno ("trap"))
142 return 2;
143
0a30fbc4
DJ
144 return 0;
145}
146
2ec06d2e
DJ
147static int
148ppc_cannot_fetch_register (int regno)
0a30fbc4
DJ
149{
150 return 0;
151}
152
5b0a002e
UW
153static void
154ppc_collect_ptrace_register (int regno, char *buf)
155{
156 int size = register_size (regno);
76b233dd
UW
157
158 memset (buf, 0, sizeof (long));
159
5b0a002e
UW
160 if (size < sizeof (long))
161 collect_register (regno, buf + sizeof (long) - size);
162 else
163 collect_register (regno, buf);
164}
165
166static void
167ppc_supply_ptrace_register (int regno, const char *buf)
168{
169 int size = register_size (regno);
170 if (size < sizeof (long))
171 supply_register (regno, buf + sizeof (long) - size);
172 else
173 supply_register (regno, buf);
174}
175
0d62e5e8
DJ
176static CORE_ADDR
177ppc_get_pc (void)
178{
6fe305f7
UW
179 if (register_size (0) == 4)
180 {
181 unsigned int pc;
182 collect_register_by_name ("pc", &pc);
183 return (CORE_ADDR) pc;
184 }
185 else
186 {
187 unsigned long pc;
188 collect_register_by_name ("pc", &pc);
189 return (CORE_ADDR) pc;
190 }
0d62e5e8
DJ
191}
192
193static void
194ppc_set_pc (CORE_ADDR pc)
195{
6fe305f7
UW
196 if (register_size (0) == 4)
197 {
198 unsigned int newpc = pc;
199 supply_register_by_name ("pc", &newpc);
200 }
201 else
202 {
203 unsigned long newpc = pc;
204 supply_register_by_name ("pc", &newpc);
205 }
206}
207
b6430ec3
UW
208
209static int
210ppc_get_hwcap (unsigned long *valp)
211{
212 int wordsize = register_size (0);
213 unsigned char *data = alloca (2 * wordsize);
214 int offset = 0;
215
216 while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
217 {
218 if (wordsize == 4)
219 {
220 unsigned int *data_p = (unsigned int *)data;
221 if (data_p[0] == AT_HWCAP)
222 {
223 *valp = data_p[1];
224 return 1;
225 }
226 }
227 else
228 {
229 unsigned long *data_p = (unsigned long *)data;
230 if (data_p[0] == AT_HWCAP)
231 {
232 *valp = data_p[1];
233 return 1;
234 }
235 }
236
237 offset += 2 * wordsize;
238 }
239
240 *valp = 0;
241 return 0;
242}
243
6fe305f7
UW
244static void
245ppc_arch_setup (void)
246{
247#ifdef __powerpc64__
248 long msr;
0d62e5e8 249
c9b2f845
UW
250 /* On a 64-bit host, assume 64-bit inferior process with no
251 AltiVec registers. Reset ppc_hwcap to ensure that the
252 collect_register call below does not fail. */
7284e1be 253 init_registers_powerpc_64l ();
c9b2f845 254 ppc_hwcap = 0;
6fe305f7
UW
255
256 /* Only if the high bit of the MSR is set, we actually have
257 a 64-bit inferior. */
258 collect_register_by_name ("msr", &msr);
259 if (msr < 0)
b6430ec3
UW
260 {
261 ppc_get_hwcap (&ppc_hwcap);
677c5bb1
LM
262 if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
263 init_registers_powerpc_vsx64l ();
264 else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
7284e1be 265 init_registers_powerpc_altivec64l ();
b6430ec3
UW
266 return;
267 }
6fe305f7
UW
268#endif
269
270 /* OK, we have a 32-bit inferior. */
7284e1be 271 init_registers_powerpc_32l ();
b6430ec3
UW
272
273 ppc_get_hwcap (&ppc_hwcap);
677c5bb1
LM
274 if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
275 init_registers_powerpc_vsx32l ();
276 else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
7284e1be 277 init_registers_powerpc_altivec32l ();
b6430ec3 278
677c5bb1 279
b6430ec3
UW
280 /* On 32-bit machines, check for SPE registers.
281 Set the low target's regmap field as appropriately. */
282#ifndef __powerpc64__
283 the_low_target.regmap = ppc_regmap;
284 if (ppc_hwcap & PPC_FEATURE_HAS_SPE)
285 {
7284e1be 286 init_registers_powerpc_e500l ();
b6430ec3
UW
287 the_low_target.regmap = ppc_regmap_e500;
288 }
6fe305f7 289#endif
0d62e5e8
DJ
290}
291
5b0a002e 292/* Correct in either endianness.
0d62e5e8
DJ
293 This instruction is "twge r2, r2", which GDB uses as a software
294 breakpoint. */
5b0a002e 295static const unsigned int ppc_breakpoint = 0x7d821008;
0d62e5e8
DJ
296#define ppc_breakpoint_len 4
297
298static int
299ppc_breakpoint_at (CORE_ADDR where)
300{
5b0a002e 301 unsigned int insn;
0d62e5e8 302
f450004a 303 (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
0d62e5e8
DJ
304 if (insn == ppc_breakpoint)
305 return 1;
306 /* If necessary, recognize more trap instructions here. GDB only uses the
307 one. */
308 return 0;
309}
310
e9d25b98
DJ
311/* Provide only a fill function for the general register set. ps_lgetregs
312 will use this for NPTL support. */
313
314static void ppc_fill_gregset (void *buf)
315{
316 int i;
317
318 for (i = 0; i < 32; i++)
6fe305f7 319 ppc_collect_ptrace_register (i, (char *) buf + ppc_regmap[i]);
e9d25b98
DJ
320
321 for (i = 64; i < 70; i++)
6fe305f7 322 ppc_collect_ptrace_register (i, (char *) buf + ppc_regmap[i]);
7284e1be
UW
323
324 for (i = 71; i < 73; i++)
325 ppc_collect_ptrace_register (i, (char *) buf + ppc_regmap[i]);
e9d25b98
DJ
326}
327
677c5bb1
LM
328#ifndef PTRACE_GETVSXREGS
329#define PTRACE_GETVSXREGS 27
330#define PTRACE_SETVSXREGS 28
331#endif
332
333#define SIZEOF_VSXREGS 32*8
334
335static void
336ppc_fill_vsxregset (void *buf)
337{
338 int i, base;
339 char *regset = buf;
340
341 if (!(ppc_hwcap & PPC_FEATURE_HAS_VSX))
342 return;
343
344 base = find_regno ("vs0h");
345 for (i = 0; i < 32; i++)
346 collect_register (base + i, &regset[i * 8]);
347}
348
349static void
350ppc_store_vsxregset (const void *buf)
351{
352 int i, base;
353 const char *regset = buf;
354
355 if (!(ppc_hwcap & PPC_FEATURE_HAS_VSX))
356 return;
357
358 base = find_regno ("vs0h");
359 for (i = 0; i < 32; i++)
360 supply_register (base + i, &regset[i * 8]);
361}
362
30ed0a8f
DJ
363#ifndef PTRACE_GETVRREGS
364#define PTRACE_GETVRREGS 18
365#define PTRACE_SETVRREGS 19
366#endif
367
368#define SIZEOF_VRREGS 33*16+4
369
370static void
371ppc_fill_vrregset (void *buf)
372{
373 int i, base;
374 char *regset = buf;
375
b6430ec3
UW
376 if (!(ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC))
377 return;
378
30ed0a8f
DJ
379 base = find_regno ("vr0");
380 for (i = 0; i < 32; i++)
381 collect_register (base + i, &regset[i * 16]);
382
383 collect_register_by_name ("vscr", &regset[32 * 16 + 12]);
384 collect_register_by_name ("vrsave", &regset[33 * 16]);
385}
386
387static void
388ppc_store_vrregset (const void *buf)
389{
390 int i, base;
391 const char *regset = buf;
392
b6430ec3
UW
393 if (!(ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC))
394 return;
395
30ed0a8f
DJ
396 base = find_regno ("vr0");
397 for (i = 0; i < 32; i++)
398 supply_register (base + i, &regset[i * 16]);
399
400 supply_register_by_name ("vscr", &regset[32 * 16 + 12]);
401 supply_register_by_name ("vrsave", &regset[33 * 16]);
402}
403
30ed0a8f
DJ
404#ifndef PTRACE_GETEVRREGS
405#define PTRACE_GETEVRREGS 20
406#define PTRACE_SETEVRREGS 21
407#endif
408
409struct gdb_evrregset_t
410{
411 unsigned long evr[32];
412 unsigned long long acc;
413 unsigned long spefscr;
414};
415
416static void
417ppc_fill_evrregset (void *buf)
418{
419 int i, ev0;
420 struct gdb_evrregset_t *regset = buf;
421
b6430ec3
UW
422 if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE))
423 return;
424
30ed0a8f
DJ
425 ev0 = find_regno ("ev0h");
426 for (i = 0; i < 32; i++)
427 collect_register (ev0 + i, &regset->evr[i]);
428
429 collect_register_by_name ("acc", &regset->acc);
430 collect_register_by_name ("spefscr", &regset->spefscr);
431}
432
433static void
434ppc_store_evrregset (const void *buf)
435{
436 int i, ev0;
437 const struct gdb_evrregset_t *regset = buf;
438
b6430ec3
UW
439 if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE))
440 return;
441
30ed0a8f
DJ
442 ev0 = find_regno ("ev0h");
443 for (i = 0; i < 32; i++)
444 supply_register (ev0 + i, &regset->evr[i]);
445
446 supply_register_by_name ("acc", &regset->acc);
447 supply_register_by_name ("spefscr", &regset->spefscr);
448}
30ed0a8f 449
e9d25b98 450struct regset_info target_regsets[] = {
30ed0a8f
DJ
451 /* List the extra register sets before GENERAL_REGS. That way we will
452 fetch them every time, but still fall back to PTRACE_PEEKUSER for the
453 general registers. Some kernels support these, but not the newer
454 PPC_PTRACE_GETREGS. */
677c5bb1
LM
455 { PTRACE_GETVSXREGS, PTRACE_SETVSXREGS, SIZEOF_VSXREGS, EXTENDED_REGS,
456 ppc_fill_vsxregset, ppc_store_vsxregset },
30ed0a8f
DJ
457 { PTRACE_GETVRREGS, PTRACE_SETVRREGS, SIZEOF_VRREGS, EXTENDED_REGS,
458 ppc_fill_vrregset, ppc_store_vrregset },
30ed0a8f
DJ
459 { PTRACE_GETEVRREGS, PTRACE_SETEVRREGS, 32 * 4 + 8 + 4, EXTENDED_REGS,
460 ppc_fill_evrregset, ppc_store_evrregset },
e9d25b98
DJ
461 { 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
462 { 0, 0, -1, -1, NULL, NULL }
463};
464
2ec06d2e 465struct linux_target_ops the_low_target = {
6fe305f7 466 ppc_arch_setup,
2ec06d2e
DJ
467 ppc_num_regs,
468 ppc_regmap,
469 ppc_cannot_fetch_register,
470 ppc_cannot_store_register,
0d62e5e8
DJ
471 ppc_get_pc,
472 ppc_set_pc,
f450004a 473 (const unsigned char *) &ppc_breakpoint,
0d62e5e8
DJ
474 ppc_breakpoint_len,
475 NULL,
476 0,
477 ppc_breakpoint_at,
5b0a002e
UW
478 NULL,
479 NULL,
480 NULL,
481 NULL,
482 ppc_collect_ptrace_register,
483 ppc_supply_ptrace_register,
2ec06d2e 484};
This page took 0.66393 seconds and 4 git commands to generate.