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