gdb/ChangeLog:
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-ppc64-low.c
CommitLineData
eee84df1
DJ
1/* GNU/Linux/PowerPC64 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
eee84df1
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
eee84df1
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/>. */
eee84df1
DJ
20
21#include "server.h"
22#include "linux-low.h"
23
d05b4ac3
UW
24/* Defined in auto-generated file reg-ppc64.c. */
25void init_registers_ppc64 (void);
26/* Defined in auto-generated file powerpc-64.c. */
27void init_registers_powerpc_64 (void);
28
eee84df1
DJ
29#include <asm/ptrace.h>
30
31#define ppc_num_regs 71
32
33/* We use a constant for FPSCR instead of PT_FPSCR, because
34 many shipped PPC64 kernels had the wrong value in ptrace.h. */
35static int ppc_regmap[] =
36 {PT_R0 * 8, PT_R1 * 8, PT_R2 * 8, PT_R3 * 8,
37 PT_R4 * 8, PT_R5 * 8, PT_R6 * 8, PT_R7 * 8,
38 PT_R8 * 8, PT_R9 * 8, PT_R10 * 8, PT_R11 * 8,
39 PT_R12 * 8, PT_R13 * 8, PT_R14 * 8, PT_R15 * 8,
40 PT_R16 * 8, PT_R17 * 8, PT_R18 * 8, PT_R19 * 8,
41 PT_R20 * 8, PT_R21 * 8, PT_R22 * 8, PT_R23 * 8,
42 PT_R24 * 8, PT_R25 * 8, PT_R26 * 8, PT_R27 * 8,
43 PT_R28 * 8, PT_R29 * 8, PT_R30 * 8, PT_R31 * 8,
44 PT_FPR0*8, PT_FPR0*8 + 8, PT_FPR0*8+16, PT_FPR0*8+24,
45 PT_FPR0*8+32, PT_FPR0*8+40, PT_FPR0*8+48, PT_FPR0*8+56,
46 PT_FPR0*8+64, PT_FPR0*8+72, PT_FPR0*8+80, PT_FPR0*8+88,
47 PT_FPR0*8+96, PT_FPR0*8+104, PT_FPR0*8+112, PT_FPR0*8+120,
48 PT_FPR0*8+128, PT_FPR0*8+136, PT_FPR0*8+144, PT_FPR0*8+152,
49 PT_FPR0*8+160, PT_FPR0*8+168, PT_FPR0*8+176, PT_FPR0*8+184,
50 PT_FPR0*8+192, PT_FPR0*8+200, PT_FPR0*8+208, PT_FPR0*8+216,
51 PT_FPR0*8+224, PT_FPR0*8+232, PT_FPR0*8+240, PT_FPR0*8+248,
52 PT_NIP * 8, PT_MSR * 8, PT_CCR * 8, PT_LNK * 8,
53 PT_CTR * 8, PT_XER * 8, PT_FPR0*8 + 256 };
54
55static int
56ppc_cannot_store_register (int regno)
57{
58 return 0;
59}
60
61static int
62ppc_cannot_fetch_register (int regno)
63{
64 return 0;
65}
66
67static CORE_ADDR
68ppc_get_pc (void)
69{
70 unsigned long pc;
71
72 collect_register_by_name ("pc", &pc);
73 return (CORE_ADDR) pc;
74}
75
76static void
77ppc_set_pc (CORE_ADDR pc)
78{
79 unsigned long newpc = pc;
80
81 supply_register_by_name ("pc", &newpc);
82}
83
84/* Correct in either endianness.
85 This instruction is "twge r2, r2", which GDB uses as a software
86 breakpoint. */
87static const unsigned int ppc_breakpoint = 0x7d821008;
88#define ppc_breakpoint_len 4
89
90static int
91ppc_breakpoint_at (CORE_ADDR where)
92{
93 unsigned int insn;
94
f450004a 95 (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
eee84df1
DJ
96 if (insn == ppc_breakpoint)
97 return 1;
98 /* If necessary, recognize more trap instructions here. GDB only uses the
99 one. */
100 return 0;
101}
102
e9d25b98
DJ
103/* Provide only a fill function for the general register set. ps_lgetregs
104 will use this for NPTL support. */
105
106static void ppc_fill_gregset (void *buf)
107{
108 int i;
109
110 for (i = 0; i < 32; i++)
111 collect_register (i, (char *) buf + ppc_regmap[i]);
112
113 for (i = 64; i < 70; i++)
114 collect_register (i, (char *) buf + ppc_regmap[i]);
115}
116
30ed0a8f
DJ
117#ifdef __ALTIVEC__
118
119#ifndef PTRACE_GETVRREGS
120#define PTRACE_GETVRREGS 18
121#define PTRACE_SETVRREGS 19
122#endif
123
124#define SIZEOF_VRREGS 33*16+4
125
126static void
127ppc_fill_vrregset (void *buf)
128{
129 int i, base;
130 char *regset = buf;
131
132 base = find_regno ("vr0");
133 for (i = 0; i < 32; i++)
134 collect_register (base + i, &regset[i * 16]);
135
136 collect_register_by_name ("vscr", &regset[32 * 16 + 12]);
137 collect_register_by_name ("vrsave", &regset[33 * 16]);
138}
139
140static void
141ppc_store_vrregset (const void *buf)
142{
143 int i, base;
144 const char *regset = buf;
145
146 base = find_regno ("vr0");
147 for (i = 0; i < 32; i++)
148 supply_register (base + i, &regset[i * 16]);
149
150 supply_register_by_name ("vscr", &regset[32 * 16 + 12]);
151 supply_register_by_name ("vrsave", &regset[33 * 16]);
152}
153
154#endif /* __ALTIVEC__ */
155
e9d25b98 156struct regset_info target_regsets[] = {
30ed0a8f
DJ
157 /* List the extra register sets before GENERAL_REGS. That way we will
158 fetch them every time, but still fall back to PTRACE_PEEKUSER for the
159 general registers. Some kernels support these, but not the newer
160 PPC_PTRACE_GETREGS. */
161#ifdef __ALTIVEC__
162 { PTRACE_GETVRREGS, PTRACE_SETVRREGS, SIZEOF_VRREGS, EXTENDED_REGS,
163 ppc_fill_vrregset, ppc_store_vrregset },
164#endif
e9d25b98
DJ
165 { 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
166 { 0, 0, -1, -1, NULL, NULL }
167};
168
eee84df1 169struct linux_target_ops the_low_target = {
d05b4ac3
UW
170#ifdef __ALTIVEC__
171 init_registers_powerpc_64,
172#else
173 init_registers_ppc64,
174#endif
eee84df1
DJ
175 ppc_num_regs,
176 ppc_regmap,
177 ppc_cannot_fetch_register,
178 ppc_cannot_store_register,
179 ppc_get_pc,
180 ppc_set_pc,
f450004a 181 (const unsigned char *) &ppc_breakpoint,
eee84df1
DJ
182 ppc_breakpoint_len,
183 NULL,
184 0,
185 ppc_breakpoint_at,
5a1f5858
DJ
186 NULL,
187 NULL,
188 NULL,
189 NULL,
190 1
eee84df1 191};
This page took 0.188687 seconds and 4 git commands to generate.