Checkin gdb.arch/i386-avx.exp.
[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.
0fb0cc75 3 Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2005, 2007, 2008,
4c38e0a4 4 2009, 2010 Free Software Foundation, Inc.
0a30fbc4
DJ
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
f4d9bade 31#define PPC_FEATURE_CELL 0x00010000
f04c6d38 32#define PPC_FEATURE_HAS_DFP 0x00000400
b6430ec3
UW
33
34static unsigned long ppc_hwcap;
35
36
7284e1be
UW
37/* Defined in auto-generated file powerpc-32l.c. */
38void init_registers_powerpc_32l (void);
39/* Defined in auto-generated file powerpc-altivec32l.c. */
40void init_registers_powerpc_altivec32l (void);
f4d9bade
UW
41/* Defined in auto-generated file powerpc-cell32l.c. */
42void init_registers_powerpc_cell32l (void);
677c5bb1
LM
43/* Defined in auto-generated file powerpc-vsx32l.c. */
44void init_registers_powerpc_vsx32l (void);
2c4ad781
TJB
45/* Defined in auto-generated file powerpc-isa205-32l.c. */
46void init_registers_powerpc_isa205_32l (void);
47/* Defined in auto-generated file powerpc-isa205-altivec32l.c. */
48void init_registers_powerpc_isa205_altivec32l (void);
49/* Defined in auto-generated file powerpc-isa205-vsx32l.c. */
50void init_registers_powerpc_isa205_vsx32l (void);
7284e1be
UW
51/* Defined in auto-generated file powerpc-e500l.c. */
52void init_registers_powerpc_e500l (void);
53/* Defined in auto-generated file powerpc-64l.c. */
54void init_registers_powerpc_64l (void);
55/* Defined in auto-generated file powerpc-altivec64l.c. */
56void init_registers_powerpc_altivec64l (void);
f4d9bade
UW
57/* Defined in auto-generated file powerpc-cell64l.c. */
58void init_registers_powerpc_cell64l (void);
677c5bb1
LM
59/* Defined in auto-generated file powerpc-vsx64l.c. */
60void init_registers_powerpc_vsx64l (void);
2c4ad781
TJB
61/* Defined in auto-generated file powerpc-isa205-64l.c. */
62void init_registers_powerpc_isa205_64l (void);
63/* Defined in auto-generated file powerpc-isa205-altivec64l.c. */
64void init_registers_powerpc_isa205_altivec64l (void);
65/* Defined in auto-generated file powerpc-isa205-vsx64l.c. */
66void init_registers_powerpc_isa205_vsx64l (void);
7284e1be
UW
67
68#define ppc_num_regs 73
69
70/* This sometimes isn't defined. */
71#ifndef PT_ORIG_R3
72#define PT_ORIG_R3 34
73#endif
74#ifndef PT_TRAP
75#define PT_TRAP 40
76#endif
0a30fbc4 77
5b0a002e
UW
78#ifdef __powerpc64__
79/* We use a constant for FPSCR instead of PT_FPSCR, because
80 many shipped PPC64 kernels had the wrong value in ptrace.h. */
81static int ppc_regmap[] =
82 {PT_R0 * 8, PT_R1 * 8, PT_R2 * 8, PT_R3 * 8,
83 PT_R4 * 8, PT_R5 * 8, PT_R6 * 8, PT_R7 * 8,
84 PT_R8 * 8, PT_R9 * 8, PT_R10 * 8, PT_R11 * 8,
85 PT_R12 * 8, PT_R13 * 8, PT_R14 * 8, PT_R15 * 8,
86 PT_R16 * 8, PT_R17 * 8, PT_R18 * 8, PT_R19 * 8,
87 PT_R20 * 8, PT_R21 * 8, PT_R22 * 8, PT_R23 * 8,
88 PT_R24 * 8, PT_R25 * 8, PT_R26 * 8, PT_R27 * 8,
89 PT_R28 * 8, PT_R29 * 8, PT_R30 * 8, PT_R31 * 8,
90 PT_FPR0*8, PT_FPR0*8 + 8, PT_FPR0*8+16, PT_FPR0*8+24,
91 PT_FPR0*8+32, PT_FPR0*8+40, PT_FPR0*8+48, PT_FPR0*8+56,
92 PT_FPR0*8+64, PT_FPR0*8+72, PT_FPR0*8+80, PT_FPR0*8+88,
93 PT_FPR0*8+96, PT_FPR0*8+104, PT_FPR0*8+112, PT_FPR0*8+120,
94 PT_FPR0*8+128, PT_FPR0*8+136, PT_FPR0*8+144, PT_FPR0*8+152,
95 PT_FPR0*8+160, PT_FPR0*8+168, PT_FPR0*8+176, PT_FPR0*8+184,
96 PT_FPR0*8+192, PT_FPR0*8+200, PT_FPR0*8+208, PT_FPR0*8+216,
97 PT_FPR0*8+224, PT_FPR0*8+232, PT_FPR0*8+240, PT_FPR0*8+248,
98 PT_NIP * 8, PT_MSR * 8, PT_CCR * 8, PT_LNK * 8,
7284e1be
UW
99 PT_CTR * 8, PT_XER * 8, PT_FPR0*8 + 256,
100 PT_ORIG_R3 * 8, PT_TRAP * 8 };
5b0a002e 101#else
0a30fbc4 102/* Currently, don't check/send MQ. */
2ec06d2e 103static int ppc_regmap[] =
0a30fbc4
DJ
104 {PT_R0 * 4, PT_R1 * 4, PT_R2 * 4, PT_R3 * 4,
105 PT_R4 * 4, PT_R5 * 4, PT_R6 * 4, PT_R7 * 4,
106 PT_R8 * 4, PT_R9 * 4, PT_R10 * 4, PT_R11 * 4,
107 PT_R12 * 4, PT_R13 * 4, PT_R14 * 4, PT_R15 * 4,
108 PT_R16 * 4, PT_R17 * 4, PT_R18 * 4, PT_R19 * 4,
109 PT_R20 * 4, PT_R21 * 4, PT_R22 * 4, PT_R23 * 4,
110 PT_R24 * 4, PT_R25 * 4, PT_R26 * 4, PT_R27 * 4,
111 PT_R28 * 4, PT_R29 * 4, PT_R30 * 4, PT_R31 * 4,
112 PT_FPR0*4, PT_FPR0*4 + 8, PT_FPR0*4+16, PT_FPR0*4+24,
113 PT_FPR0*4+32, PT_FPR0*4+40, PT_FPR0*4+48, PT_FPR0*4+56,
114 PT_FPR0*4+64, PT_FPR0*4+72, PT_FPR0*4+80, PT_FPR0*4+88,
115 PT_FPR0*4+96, PT_FPR0*4+104, PT_FPR0*4+112, PT_FPR0*4+120,
116 PT_FPR0*4+128, PT_FPR0*4+136, PT_FPR0*4+144, PT_FPR0*4+152,
117 PT_FPR0*4+160, PT_FPR0*4+168, PT_FPR0*4+176, PT_FPR0*4+184,
118 PT_FPR0*4+192, PT_FPR0*4+200, PT_FPR0*4+208, PT_FPR0*4+216,
119 PT_FPR0*4+224, PT_FPR0*4+232, PT_FPR0*4+240, PT_FPR0*4+248,
120 PT_NIP * 4, PT_MSR * 4, PT_CCR * 4, PT_LNK * 4,
7284e1be
UW
121 PT_CTR * 4, PT_XER * 4, PT_FPSCR * 4,
122 PT_ORIG_R3 * 4, PT_TRAP * 4
b6430ec3
UW
123 };
124
125static int ppc_regmap_e500[] =
126 {PT_R0 * 4, PT_R1 * 4, PT_R2 * 4, PT_R3 * 4,
127 PT_R4 * 4, PT_R5 * 4, PT_R6 * 4, PT_R7 * 4,
128 PT_R8 * 4, PT_R9 * 4, PT_R10 * 4, PT_R11 * 4,
129 PT_R12 * 4, PT_R13 * 4, PT_R14 * 4, PT_R15 * 4,
130 PT_R16 * 4, PT_R17 * 4, PT_R18 * 4, PT_R19 * 4,
131 PT_R20 * 4, PT_R21 * 4, PT_R22 * 4, PT_R23 * 4,
132 PT_R24 * 4, PT_R25 * 4, PT_R26 * 4, PT_R27 * 4,
133 PT_R28 * 4, PT_R29 * 4, PT_R30 * 4, PT_R31 * 4,
134 -1, -1, -1, -1,
135 -1, -1, -1, -1,
136 -1, -1, -1, -1,
137 -1, -1, -1, -1,
138 -1, -1, -1, -1,
139 -1, -1, -1, -1,
140 -1, -1, -1, -1,
141 -1, -1, -1, -1,
142 PT_NIP * 4, PT_MSR * 4, PT_CCR * 4, PT_LNK * 4,
7284e1be
UW
143 PT_CTR * 4, PT_XER * 4, -1,
144 PT_ORIG_R3 * 4, PT_TRAP * 4
30ed0a8f 145 };
5b0a002e 146#endif
0a30fbc4 147
2ec06d2e
DJ
148static int
149ppc_cannot_store_register (int regno)
0a30fbc4 150{
b6430ec3 151#ifndef __powerpc64__
bc1e36ca 152 /* Some kernels do not allow us to store fpscr. */
b6430ec3 153 if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE) && regno == find_regno ("fpscr"))
bc1e36ca 154 return 2;
30ed0a8f 155#endif
bc1e36ca 156
7284e1be
UW
157 /* Some kernels do not allow us to store orig_r3 or trap. */
158 if (regno == find_regno ("orig_r3")
159 || regno == find_regno ("trap"))
160 return 2;
161
0a30fbc4
DJ
162 return 0;
163}
164
2ec06d2e
DJ
165static int
166ppc_cannot_fetch_register (int regno)
0a30fbc4
DJ
167{
168 return 0;
169}
170
5b0a002e 171static void
442ea881 172ppc_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
5b0a002e
UW
173{
174 int size = register_size (regno);
76b233dd
UW
175
176 memset (buf, 0, sizeof (long));
177
5b0a002e 178 if (size < sizeof (long))
442ea881 179 collect_register (regcache, regno, buf + sizeof (long) - size);
5b0a002e 180 else
442ea881 181 collect_register (regcache, regno, buf);
5b0a002e
UW
182}
183
184static void
442ea881
PA
185ppc_supply_ptrace_register (struct regcache *regcache,
186 int regno, const char *buf)
5b0a002e
UW
187{
188 int size = register_size (regno);
189 if (size < sizeof (long))
442ea881 190 supply_register (regcache, regno, buf + sizeof (long) - size);
5b0a002e 191 else
442ea881 192 supply_register (regcache, regno, buf);
5b0a002e
UW
193}
194
0b9ff2c0
UW
195
196#define INSTR_SC 0x44000002
197#define NR_spu_run 0x0116
198
199/* If the PPU thread is currently stopped on a spu_run system call,
200 return to FD and ADDR the file handle and NPC parameter address
201 used with the system call. Return non-zero if successful. */
202static int
442ea881 203parse_spufs_run (struct regcache *regcache, int *fd, CORE_ADDR *addr)
0b9ff2c0
UW
204{
205 CORE_ADDR curr_pc;
206 int curr_insn;
207 int curr_r0;
208
209 if (register_size (0) == 4)
210 {
211 unsigned int pc, r0, r3, r4;
442ea881
PA
212 collect_register_by_name (regcache, "pc", &pc);
213 collect_register_by_name (regcache, "r0", &r0);
214 collect_register_by_name (regcache, "orig_r3", &r3);
215 collect_register_by_name (regcache, "r4", &r4);
0b9ff2c0
UW
216 curr_pc = (CORE_ADDR) pc;
217 curr_r0 = (int) r0;
218 *fd = (int) r3;
219 *addr = (CORE_ADDR) r4;
220 }
221 else
222 {
223 unsigned long pc, r0, r3, r4;
442ea881
PA
224 collect_register_by_name (regcache, "pc", &pc);
225 collect_register_by_name (regcache, "r0", &r0);
226 collect_register_by_name (regcache, "orig_r3", &r3);
227 collect_register_by_name (regcache, "r4", &r4);
0b9ff2c0
UW
228 curr_pc = (CORE_ADDR) pc;
229 curr_r0 = (int) r0;
230 *fd = (int) r3;
231 *addr = (CORE_ADDR) r4;
232 }
233
234 /* Fetch instruction preceding current NIP. */
235 if ((*the_target->read_memory) (curr_pc - 4,
236 (unsigned char *) &curr_insn, 4) != 0)
237 return 0;
238 /* It should be a "sc" instruction. */
239 if (curr_insn != INSTR_SC)
240 return 0;
241 /* System call number should be NR_spu_run. */
242 if (curr_r0 != NR_spu_run)
243 return 0;
244
245 return 1;
246}
247
0d62e5e8 248static CORE_ADDR
442ea881 249ppc_get_pc (struct regcache *regcache)
0d62e5e8 250{
0b9ff2c0
UW
251 CORE_ADDR addr;
252 int fd;
253
442ea881 254 if (parse_spufs_run (regcache, &fd, &addr))
0b9ff2c0
UW
255 {
256 unsigned int pc;
257 (*the_target->read_memory) (addr, (unsigned char *) &pc, 4);
258 return ((CORE_ADDR)1 << 63) | ((CORE_ADDR)fd << 32) | (CORE_ADDR) (pc - 4);
259 }
260 else if (register_size (0) == 4)
6fe305f7
UW
261 {
262 unsigned int pc;
442ea881 263 collect_register_by_name (regcache, "pc", &pc);
6fe305f7
UW
264 return (CORE_ADDR) pc;
265 }
266 else
267 {
268 unsigned long pc;
442ea881 269 collect_register_by_name (regcache, "pc", &pc);
6fe305f7
UW
270 return (CORE_ADDR) pc;
271 }
0d62e5e8
DJ
272}
273
274static void
442ea881 275ppc_set_pc (struct regcache *regcache, CORE_ADDR pc)
0d62e5e8 276{
0b9ff2c0
UW
277 CORE_ADDR addr;
278 int fd;
279
442ea881 280 if (parse_spufs_run (regcache, &fd, &addr))
0b9ff2c0
UW
281 {
282 unsigned int newpc = pc;
283 (*the_target->write_memory) (addr, (unsigned char *) &newpc, 4);
284 }
285 else if (register_size (0) == 4)
6fe305f7
UW
286 {
287 unsigned int newpc = pc;
442ea881 288 supply_register_by_name (regcache, "pc", &newpc);
6fe305f7
UW
289 }
290 else
291 {
292 unsigned long newpc = pc;
442ea881 293 supply_register_by_name (regcache, "pc", &newpc);
6fe305f7
UW
294 }
295}
296
b6430ec3
UW
297
298static int
299ppc_get_hwcap (unsigned long *valp)
300{
301 int wordsize = register_size (0);
302 unsigned char *data = alloca (2 * wordsize);
303 int offset = 0;
304
305 while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
306 {
307 if (wordsize == 4)
308 {
309 unsigned int *data_p = (unsigned int *)data;
310 if (data_p[0] == AT_HWCAP)
311 {
312 *valp = data_p[1];
313 return 1;
314 }
315 }
316 else
317 {
318 unsigned long *data_p = (unsigned long *)data;
319 if (data_p[0] == AT_HWCAP)
320 {
321 *valp = data_p[1];
322 return 1;
323 }
324 }
325
326 offset += 2 * wordsize;
327 }
328
329 *valp = 0;
330 return 0;
331}
332
6fe305f7
UW
333static void
334ppc_arch_setup (void)
335{
336#ifdef __powerpc64__
337 long msr;
3be029c7 338 struct regcache *regcache;
0d62e5e8 339
c9b2f845
UW
340 /* On a 64-bit host, assume 64-bit inferior process with no
341 AltiVec registers. Reset ppc_hwcap to ensure that the
342 collect_register call below does not fail. */
7284e1be 343 init_registers_powerpc_64l ();
c9b2f845 344 ppc_hwcap = 0;
6fe305f7
UW
345
346 /* Only if the high bit of the MSR is set, we actually have
347 a 64-bit inferior. */
3be029c7
PA
348 regcache = get_thread_regcache (current_inferior, 1);
349 collect_register_by_name (regcache, "msr", &msr);
6fe305f7 350 if (msr < 0)
b6430ec3
UW
351 {
352 ppc_get_hwcap (&ppc_hwcap);
f4d9bade
UW
353 if (ppc_hwcap & PPC_FEATURE_CELL)
354 init_registers_powerpc_cell64l ();
355 else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
2c4ad781 356 {
f04c6d38
TJB
357 /* Power ISA 2.05 (implemented by Power 6 and newer processors)
358 increases the FPSCR from 32 bits to 64 bits. Even though Power 7
359 supports this ISA version, it doesn't have PPC_FEATURE_ARCH_2_05
360 set, only PPC_FEATURE_ARCH_2_06. Since for now the only bits
361 used in the higher half of the register are for Decimal Floating
362 Point, we check if that feature is available to decide the size
363 of the FPSCR. */
364 if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
2c4ad781
TJB
365 init_registers_powerpc_isa205_vsx64l ();
366 else
367 init_registers_powerpc_vsx64l ();
368 }
677c5bb1 369 else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
2c4ad781 370 {
f04c6d38 371 if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
2c4ad781
TJB
372 init_registers_powerpc_isa205_altivec64l ();
373 else
374 init_registers_powerpc_altivec64l ();
375 }
376
b6430ec3
UW
377 return;
378 }
6fe305f7
UW
379#endif
380
381 /* OK, we have a 32-bit inferior. */
7284e1be 382 init_registers_powerpc_32l ();
b6430ec3
UW
383
384 ppc_get_hwcap (&ppc_hwcap);
f4d9bade
UW
385 if (ppc_hwcap & PPC_FEATURE_CELL)
386 init_registers_powerpc_cell32l ();
387 else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
2c4ad781 388 {
f04c6d38 389 if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
2c4ad781
TJB
390 init_registers_powerpc_isa205_vsx32l ();
391 else
392 init_registers_powerpc_vsx32l ();
393 }
677c5bb1 394 else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
2c4ad781 395 {
f04c6d38 396 if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
2c4ad781
TJB
397 init_registers_powerpc_isa205_altivec32l ();
398 else
399 init_registers_powerpc_altivec32l ();
400 }
677c5bb1 401
b6430ec3
UW
402 /* On 32-bit machines, check for SPE registers.
403 Set the low target's regmap field as appropriately. */
404#ifndef __powerpc64__
405 the_low_target.regmap = ppc_regmap;
406 if (ppc_hwcap & PPC_FEATURE_HAS_SPE)
407 {
7284e1be 408 init_registers_powerpc_e500l ();
b6430ec3
UW
409 the_low_target.regmap = ppc_regmap_e500;
410 }
2c4ad781
TJB
411
412 /* If the FPSCR is 64-bit wide, we need to fetch the whole 64-bit
413 slot and not just its second word. The PT_FPSCR supplied in a
414 32-bit GDB compilation doesn't reflect this. */
415 if (register_size (70) == 8)
416 ppc_regmap[70] = (48 + 2*32) * sizeof (long);
6fe305f7 417#endif
0d62e5e8
DJ
418}
419
5b0a002e 420/* Correct in either endianness.
0d62e5e8
DJ
421 This instruction is "twge r2, r2", which GDB uses as a software
422 breakpoint. */
5b0a002e 423static const unsigned int ppc_breakpoint = 0x7d821008;
0d62e5e8
DJ
424#define ppc_breakpoint_len 4
425
426static int
427ppc_breakpoint_at (CORE_ADDR where)
428{
5b0a002e 429 unsigned int insn;
0d62e5e8 430
0b9ff2c0
UW
431 if (where & ((CORE_ADDR)1 << 63))
432 {
433 char mem_annex[32];
434 sprintf (mem_annex, "%d/mem", (int)((where >> 32) & 0x7fffffff));
435 (*the_target->qxfer_spu) (mem_annex, (unsigned char *) &insn,
436 NULL, where & 0xffffffff, 4);
437 if (insn == 0x3fff)
438 return 1;
439 }
440 else
441 {
442 (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
443 if (insn == ppc_breakpoint)
444 return 1;
445 /* If necessary, recognize more trap instructions here. GDB only uses
446 the one. */
447 }
448
0d62e5e8
DJ
449 return 0;
450}
451
e9d25b98
DJ
452/* Provide only a fill function for the general register set. ps_lgetregs
453 will use this for NPTL support. */
454
442ea881 455static void ppc_fill_gregset (struct regcache *regcache, void *buf)
e9d25b98
DJ
456{
457 int i;
458
459 for (i = 0; i < 32; i++)
442ea881 460 ppc_collect_ptrace_register (regcache, i, (char *) buf + ppc_regmap[i]);
e9d25b98
DJ
461
462 for (i = 64; i < 70; i++)
442ea881 463 ppc_collect_ptrace_register (regcache, i, (char *) buf + ppc_regmap[i]);
7284e1be
UW
464
465 for (i = 71; i < 73; i++)
442ea881 466 ppc_collect_ptrace_register (regcache, i, (char *) buf + ppc_regmap[i]);
e9d25b98
DJ
467}
468
677c5bb1
LM
469#ifndef PTRACE_GETVSXREGS
470#define PTRACE_GETVSXREGS 27
471#define PTRACE_SETVSXREGS 28
472#endif
473
474#define SIZEOF_VSXREGS 32*8
475
476static void
442ea881 477ppc_fill_vsxregset (struct regcache *regcache, void *buf)
677c5bb1
LM
478{
479 int i, base;
480 char *regset = buf;
481
482 if (!(ppc_hwcap & PPC_FEATURE_HAS_VSX))
483 return;
484
485 base = find_regno ("vs0h");
486 for (i = 0; i < 32; i++)
442ea881 487 collect_register (regcache, base + i, &regset[i * 8]);
677c5bb1
LM
488}
489
490static void
442ea881 491ppc_store_vsxregset (struct regcache *regcache, const void *buf)
677c5bb1
LM
492{
493 int i, base;
494 const char *regset = buf;
495
496 if (!(ppc_hwcap & PPC_FEATURE_HAS_VSX))
497 return;
498
499 base = find_regno ("vs0h");
500 for (i = 0; i < 32; i++)
442ea881 501 supply_register (regcache, base + i, &regset[i * 8]);
677c5bb1
LM
502}
503
30ed0a8f
DJ
504#ifndef PTRACE_GETVRREGS
505#define PTRACE_GETVRREGS 18
506#define PTRACE_SETVRREGS 19
507#endif
508
509#define SIZEOF_VRREGS 33*16+4
510
511static void
442ea881 512ppc_fill_vrregset (struct regcache *regcache, void *buf)
30ed0a8f
DJ
513{
514 int i, base;
515 char *regset = buf;
516
b6430ec3
UW
517 if (!(ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC))
518 return;
519
30ed0a8f
DJ
520 base = find_regno ("vr0");
521 for (i = 0; i < 32; i++)
442ea881 522 collect_register (regcache, base + i, &regset[i * 16]);
30ed0a8f 523
442ea881
PA
524 collect_register_by_name (regcache, "vscr", &regset[32 * 16 + 12]);
525 collect_register_by_name (regcache, "vrsave", &regset[33 * 16]);
30ed0a8f
DJ
526}
527
528static void
442ea881 529ppc_store_vrregset (struct regcache *regcache, const void *buf)
30ed0a8f
DJ
530{
531 int i, base;
532 const char *regset = buf;
533
b6430ec3
UW
534 if (!(ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC))
535 return;
536
30ed0a8f
DJ
537 base = find_regno ("vr0");
538 for (i = 0; i < 32; i++)
442ea881 539 supply_register (regcache, base + i, &regset[i * 16]);
30ed0a8f 540
442ea881
PA
541 supply_register_by_name (regcache, "vscr", &regset[32 * 16 + 12]);
542 supply_register_by_name (regcache, "vrsave", &regset[33 * 16]);
30ed0a8f
DJ
543}
544
30ed0a8f
DJ
545#ifndef PTRACE_GETEVRREGS
546#define PTRACE_GETEVRREGS 20
547#define PTRACE_SETEVRREGS 21
548#endif
549
550struct gdb_evrregset_t
551{
552 unsigned long evr[32];
553 unsigned long long acc;
554 unsigned long spefscr;
555};
556
557static void
442ea881 558ppc_fill_evrregset (struct regcache *regcache, void *buf)
30ed0a8f
DJ
559{
560 int i, ev0;
561 struct gdb_evrregset_t *regset = buf;
562
b6430ec3
UW
563 if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE))
564 return;
565
30ed0a8f
DJ
566 ev0 = find_regno ("ev0h");
567 for (i = 0; i < 32; i++)
442ea881 568 collect_register (regcache, ev0 + i, &regset->evr[i]);
30ed0a8f 569
442ea881
PA
570 collect_register_by_name (regcache, "acc", &regset->acc);
571 collect_register_by_name (regcache, "spefscr", &regset->spefscr);
30ed0a8f
DJ
572}
573
574static void
442ea881 575ppc_store_evrregset (struct regcache *regcache, const void *buf)
30ed0a8f
DJ
576{
577 int i, ev0;
578 const struct gdb_evrregset_t *regset = buf;
579
b6430ec3
UW
580 if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE))
581 return;
582
30ed0a8f
DJ
583 ev0 = find_regno ("ev0h");
584 for (i = 0; i < 32; i++)
442ea881 585 supply_register (regcache, ev0 + i, &regset->evr[i]);
30ed0a8f 586
442ea881
PA
587 supply_register_by_name (regcache, "acc", &regset->acc);
588 supply_register_by_name (regcache, "spefscr", &regset->spefscr);
30ed0a8f 589}
30ed0a8f 590
e9d25b98 591struct regset_info target_regsets[] = {
30ed0a8f
DJ
592 /* List the extra register sets before GENERAL_REGS. That way we will
593 fetch them every time, but still fall back to PTRACE_PEEKUSER for the
594 general registers. Some kernels support these, but not the newer
595 PPC_PTRACE_GETREGS. */
677c5bb1
LM
596 { PTRACE_GETVSXREGS, PTRACE_SETVSXREGS, SIZEOF_VSXREGS, EXTENDED_REGS,
597 ppc_fill_vsxregset, ppc_store_vsxregset },
30ed0a8f
DJ
598 { PTRACE_GETVRREGS, PTRACE_SETVRREGS, SIZEOF_VRREGS, EXTENDED_REGS,
599 ppc_fill_vrregset, ppc_store_vrregset },
30ed0a8f
DJ
600 { PTRACE_GETEVRREGS, PTRACE_SETEVRREGS, 32 * 4 + 8 + 4, EXTENDED_REGS,
601 ppc_fill_evrregset, ppc_store_evrregset },
e9d25b98
DJ
602 { 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
603 { 0, 0, -1, -1, NULL, NULL }
604};
605
2ec06d2e 606struct linux_target_ops the_low_target = {
6fe305f7 607 ppc_arch_setup,
2ec06d2e
DJ
608 ppc_num_regs,
609 ppc_regmap,
610 ppc_cannot_fetch_register,
611 ppc_cannot_store_register,
0d62e5e8
DJ
612 ppc_get_pc,
613 ppc_set_pc,
f450004a 614 (const unsigned char *) &ppc_breakpoint,
0d62e5e8
DJ
615 ppc_breakpoint_len,
616 NULL,
617 0,
618 ppc_breakpoint_at,
5b0a002e
UW
619 NULL,
620 NULL,
621 NULL,
622 NULL,
623 ppc_collect_ptrace_register,
624 ppc_supply_ptrace_register,
2ec06d2e 625};
This page took 0.932011 seconds and 4 git commands to generate.