1*ef5ccd6cSJohn Marino /* Ravenscar PowerPC target support.
2*ef5ccd6cSJohn Marino
3*ef5ccd6cSJohn Marino Copyright (C) 2011-2013 Free Software Foundation, Inc.
4*ef5ccd6cSJohn Marino
5*ef5ccd6cSJohn Marino This file is part of GDB.
6*ef5ccd6cSJohn Marino
7*ef5ccd6cSJohn Marino This program is free software; you can redistribute it and/or modify
8*ef5ccd6cSJohn Marino it under the terms of the GNU General Public License as published by
9*ef5ccd6cSJohn Marino the Free Software Foundation; either version 3 of the License, or
10*ef5ccd6cSJohn Marino (at your option) any later version.
11*ef5ccd6cSJohn Marino
12*ef5ccd6cSJohn Marino This program is distributed in the hope that it will be useful,
13*ef5ccd6cSJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
14*ef5ccd6cSJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*ef5ccd6cSJohn Marino GNU General Public License for more details.
16*ef5ccd6cSJohn Marino
17*ef5ccd6cSJohn Marino You should have received a copy of the GNU General Public License
18*ef5ccd6cSJohn Marino along with this program. If not, see <http://www.gnu.org/licenses/>. */
19*ef5ccd6cSJohn Marino
20*ef5ccd6cSJohn Marino #include "defs.h"
21*ef5ccd6cSJohn Marino #include "gdbcore.h"
22*ef5ccd6cSJohn Marino #include "regcache.h"
23*ef5ccd6cSJohn Marino #include "ppc-tdep.h"
24*ef5ccd6cSJohn Marino #include "inferior.h"
25*ef5ccd6cSJohn Marino #include "ravenscar-thread.h"
26*ef5ccd6cSJohn Marino #include "ppc-ravenscar-thread.h"
27*ef5ccd6cSJohn Marino
28*ef5ccd6cSJohn Marino #define NO_OFFSET -1
29*ef5ccd6cSJohn Marino
30*ef5ccd6cSJohn Marino /* See ppc-tdep.h for register numbers. */
31*ef5ccd6cSJohn Marino
32*ef5ccd6cSJohn Marino static const int powerpc_context_offsets[] =
33*ef5ccd6cSJohn Marino {
34*ef5ccd6cSJohn Marino /* R0 - R32 */
35*ef5ccd6cSJohn Marino NO_OFFSET, 0, 4, NO_OFFSET,
36*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
37*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
38*ef5ccd6cSJohn Marino NO_OFFSET, 8, 12, 16,
39*ef5ccd6cSJohn Marino 20, 24, 28, 32,
40*ef5ccd6cSJohn Marino 36, 40, 44, 48,
41*ef5ccd6cSJohn Marino 52, 56, 60, 64,
42*ef5ccd6cSJohn Marino 68, 72, 76, 80,
43*ef5ccd6cSJohn Marino
44*ef5ccd6cSJohn Marino /* F0 - F31 */
45*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
46*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
47*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
48*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, 96, 104,
49*ef5ccd6cSJohn Marino 112, 120, 128, 136,
50*ef5ccd6cSJohn Marino 144, 152, 160, 168,
51*ef5ccd6cSJohn Marino 176, 184, 192, 200,
52*ef5ccd6cSJohn Marino 208, 216, 224, 232,
53*ef5ccd6cSJohn Marino
54*ef5ccd6cSJohn Marino /* PC, MSR, CR, LR */
55*ef5ccd6cSJohn Marino 88, NO_OFFSET, 84, NO_OFFSET,
56*ef5ccd6cSJohn Marino
57*ef5ccd6cSJohn Marino /* CTR, XER, FPSCR */
58*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, 240
59*ef5ccd6cSJohn Marino };
60*ef5ccd6cSJohn Marino
61*ef5ccd6cSJohn Marino static const int e500_context_offsets[] =
62*ef5ccd6cSJohn Marino {
63*ef5ccd6cSJohn Marino /* R0 - R32 */
64*ef5ccd6cSJohn Marino NO_OFFSET, 4, 12, NO_OFFSET,
65*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
66*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
67*ef5ccd6cSJohn Marino NO_OFFSET, 20, 28, 36,
68*ef5ccd6cSJohn Marino 44, 52, 60, 68,
69*ef5ccd6cSJohn Marino 76, 84, 92, 100,
70*ef5ccd6cSJohn Marino 108, 116, 124, 132,
71*ef5ccd6cSJohn Marino 140, 148, 156, 164,
72*ef5ccd6cSJohn Marino
73*ef5ccd6cSJohn Marino /* F0 - F31 */
74*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
75*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
76*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
77*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
78*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
79*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
80*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
81*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
82*ef5ccd6cSJohn Marino
83*ef5ccd6cSJohn Marino /* PC, MSR, CR, LR */
84*ef5ccd6cSJohn Marino 172, NO_OFFSET, 168, NO_OFFSET,
85*ef5ccd6cSJohn Marino
86*ef5ccd6cSJohn Marino /* CTR, XER, FPSCR, MQ */
87*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
88*ef5ccd6cSJohn Marino
89*ef5ccd6cSJohn Marino /* Upper R0-R32. */
90*ef5ccd6cSJohn Marino NO_OFFSET, 0, 8, NO_OFFSET,
91*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
92*ef5ccd6cSJohn Marino NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
93*ef5ccd6cSJohn Marino NO_OFFSET, 16, 24, 32,
94*ef5ccd6cSJohn Marino 40, 48, 56, 64,
95*ef5ccd6cSJohn Marino 72, 80, 88, 96,
96*ef5ccd6cSJohn Marino 104, 112, 120, 128,
97*ef5ccd6cSJohn Marino 136, 144, 152, 160,
98*ef5ccd6cSJohn Marino
99*ef5ccd6cSJohn Marino /* ACC, FSCR */
100*ef5ccd6cSJohn Marino NO_OFFSET, 176
101*ef5ccd6cSJohn Marino };
102*ef5ccd6cSJohn Marino
103*ef5ccd6cSJohn Marino /* The register layout info. */
104*ef5ccd6cSJohn Marino
105*ef5ccd6cSJohn Marino struct ravenscar_reg_info
106*ef5ccd6cSJohn Marino {
107*ef5ccd6cSJohn Marino /* A table providing the offset relative to the context structure
108*ef5ccd6cSJohn Marino where each register is saved. */
109*ef5ccd6cSJohn Marino const int *context_offsets;
110*ef5ccd6cSJohn Marino
111*ef5ccd6cSJohn Marino /* The number of elements in the context_offsets table above. */
112*ef5ccd6cSJohn Marino int context_offsets_size;
113*ef5ccd6cSJohn Marino };
114*ef5ccd6cSJohn Marino
115*ef5ccd6cSJohn Marino /* supply register REGNUM, which has been saved on REGISTER_ADDR, to the
116*ef5ccd6cSJohn Marino regcache. */
117*ef5ccd6cSJohn Marino
118*ef5ccd6cSJohn Marino static void
supply_register_at_address(struct regcache * regcache,int regnum,CORE_ADDR register_addr)119*ef5ccd6cSJohn Marino supply_register_at_address (struct regcache *regcache, int regnum,
120*ef5ccd6cSJohn Marino CORE_ADDR register_addr)
121*ef5ccd6cSJohn Marino {
122*ef5ccd6cSJohn Marino struct gdbarch *gdbarch = get_regcache_arch (regcache);
123*ef5ccd6cSJohn Marino int buf_size = register_size (gdbarch, regnum);
124*ef5ccd6cSJohn Marino char *buf;
125*ef5ccd6cSJohn Marino
126*ef5ccd6cSJohn Marino buf = (char *) alloca (buf_size);
127*ef5ccd6cSJohn Marino read_memory (register_addr, buf, buf_size);
128*ef5ccd6cSJohn Marino regcache_raw_supply (regcache, regnum, buf);
129*ef5ccd6cSJohn Marino }
130*ef5ccd6cSJohn Marino
131*ef5ccd6cSJohn Marino /* Return true if, for a non-running thread, REGNUM has been saved on the
132*ef5ccd6cSJohn Marino Thread_Descriptor. */
133*ef5ccd6cSJohn Marino
134*ef5ccd6cSJohn Marino static int
register_in_thread_descriptor_p(const struct ravenscar_reg_info * reg_info,int regnum)135*ef5ccd6cSJohn Marino register_in_thread_descriptor_p (const struct ravenscar_reg_info *reg_info,
136*ef5ccd6cSJohn Marino int regnum)
137*ef5ccd6cSJohn Marino {
138*ef5ccd6cSJohn Marino return (regnum < reg_info->context_offsets_size
139*ef5ccd6cSJohn Marino && reg_info->context_offsets[regnum] != NO_OFFSET);
140*ef5ccd6cSJohn Marino }
141*ef5ccd6cSJohn Marino
142*ef5ccd6cSJohn Marino /* to_fetch_registers when inferior_ptid is different from the running
143*ef5ccd6cSJohn Marino thread. */
144*ef5ccd6cSJohn Marino
145*ef5ccd6cSJohn Marino static void
ppc_ravenscar_generic_fetch_registers(const struct ravenscar_reg_info * reg_info,struct regcache * regcache,int regnum)146*ef5ccd6cSJohn Marino ppc_ravenscar_generic_fetch_registers
147*ef5ccd6cSJohn Marino (const struct ravenscar_reg_info *reg_info,
148*ef5ccd6cSJohn Marino struct regcache *regcache, int regnum)
149*ef5ccd6cSJohn Marino {
150*ef5ccd6cSJohn Marino struct gdbarch *gdbarch = get_regcache_arch (regcache);
151*ef5ccd6cSJohn Marino const int sp_regnum = gdbarch_sp_regnum (gdbarch);
152*ef5ccd6cSJohn Marino const int num_regs = gdbarch_num_regs (gdbarch);
153*ef5ccd6cSJohn Marino int current_regnum;
154*ef5ccd6cSJohn Marino CORE_ADDR current_address;
155*ef5ccd6cSJohn Marino CORE_ADDR thread_descriptor_address;
156*ef5ccd6cSJohn Marino
157*ef5ccd6cSJohn Marino /* The tid is the thread_id field, which is a pointer to the thread. */
158*ef5ccd6cSJohn Marino thread_descriptor_address = (CORE_ADDR) ptid_get_tid (inferior_ptid);
159*ef5ccd6cSJohn Marino
160*ef5ccd6cSJohn Marino /* Read registers. */
161*ef5ccd6cSJohn Marino for (current_regnum = 0; current_regnum < num_regs; current_regnum++)
162*ef5ccd6cSJohn Marino {
163*ef5ccd6cSJohn Marino if (register_in_thread_descriptor_p (reg_info, current_regnum))
164*ef5ccd6cSJohn Marino {
165*ef5ccd6cSJohn Marino current_address = thread_descriptor_address
166*ef5ccd6cSJohn Marino + reg_info->context_offsets[current_regnum];
167*ef5ccd6cSJohn Marino supply_register_at_address (regcache, current_regnum,
168*ef5ccd6cSJohn Marino current_address);
169*ef5ccd6cSJohn Marino }
170*ef5ccd6cSJohn Marino }
171*ef5ccd6cSJohn Marino }
172*ef5ccd6cSJohn Marino
173*ef5ccd6cSJohn Marino /* to_prepare_to_store when inferior_ptid is different from the running
174*ef5ccd6cSJohn Marino thread. */
175*ef5ccd6cSJohn Marino
176*ef5ccd6cSJohn Marino static void
ppc_ravenscar_generic_prepare_to_store(struct regcache * regcache)177*ef5ccd6cSJohn Marino ppc_ravenscar_generic_prepare_to_store (struct regcache *regcache)
178*ef5ccd6cSJohn Marino {
179*ef5ccd6cSJohn Marino /* Nothing to do. */
180*ef5ccd6cSJohn Marino }
181*ef5ccd6cSJohn Marino
182*ef5ccd6cSJohn Marino /* to_store_registers when inferior_ptid is different from the running
183*ef5ccd6cSJohn Marino thread. */
184*ef5ccd6cSJohn Marino
185*ef5ccd6cSJohn Marino static void
ppc_ravenscar_generic_store_registers(const struct ravenscar_reg_info * reg_info,struct regcache * regcache,int regnum)186*ef5ccd6cSJohn Marino ppc_ravenscar_generic_store_registers
187*ef5ccd6cSJohn Marino (const struct ravenscar_reg_info *reg_info,
188*ef5ccd6cSJohn Marino struct regcache *regcache, int regnum)
189*ef5ccd6cSJohn Marino {
190*ef5ccd6cSJohn Marino struct gdbarch *gdbarch = get_regcache_arch (regcache);
191*ef5ccd6cSJohn Marino int buf_size = register_size (gdbarch, regnum);
192*ef5ccd6cSJohn Marino char buf [buf_size];
193*ef5ccd6cSJohn Marino ULONGEST register_address;
194*ef5ccd6cSJohn Marino
195*ef5ccd6cSJohn Marino if (register_in_thread_descriptor_p (reg_info, regnum))
196*ef5ccd6cSJohn Marino register_address
197*ef5ccd6cSJohn Marino = ptid_get_tid (inferior_ptid) + reg_info->context_offsets [regnum];
198*ef5ccd6cSJohn Marino else
199*ef5ccd6cSJohn Marino return;
200*ef5ccd6cSJohn Marino
201*ef5ccd6cSJohn Marino regcache_raw_collect (regcache, regnum, buf);
202*ef5ccd6cSJohn Marino write_memory (register_address,
203*ef5ccd6cSJohn Marino buf,
204*ef5ccd6cSJohn Marino buf_size);
205*ef5ccd6cSJohn Marino }
206*ef5ccd6cSJohn Marino
207*ef5ccd6cSJohn Marino /* The ravenscar_reg_info for most PowerPC targets. */
208*ef5ccd6cSJohn Marino
209*ef5ccd6cSJohn Marino static const struct ravenscar_reg_info ppc_reg_info =
210*ef5ccd6cSJohn Marino {
211*ef5ccd6cSJohn Marino powerpc_context_offsets,
212*ef5ccd6cSJohn Marino ARRAY_SIZE (powerpc_context_offsets),
213*ef5ccd6cSJohn Marino };
214*ef5ccd6cSJohn Marino
215*ef5ccd6cSJohn Marino /* Implement the to_fetch_registers ravenscar_arch_ops method
216*ef5ccd6cSJohn Marino for most PowerPC targets. */
217*ef5ccd6cSJohn Marino
218*ef5ccd6cSJohn Marino static void
ppc_ravenscar_powerpc_fetch_registers(struct regcache * regcache,int regnum)219*ef5ccd6cSJohn Marino ppc_ravenscar_powerpc_fetch_registers (struct regcache *regcache, int regnum)
220*ef5ccd6cSJohn Marino {
221*ef5ccd6cSJohn Marino ppc_ravenscar_generic_fetch_registers (&ppc_reg_info, regcache, regnum);
222*ef5ccd6cSJohn Marino }
223*ef5ccd6cSJohn Marino
224*ef5ccd6cSJohn Marino /* Implement the to_store_registers ravenscar_arch_ops method
225*ef5ccd6cSJohn Marino for most PowerPC targets. */
226*ef5ccd6cSJohn Marino
227*ef5ccd6cSJohn Marino static void
ppc_ravenscar_powerpc_store_registers(struct regcache * regcache,int regnum)228*ef5ccd6cSJohn Marino ppc_ravenscar_powerpc_store_registers (struct regcache *regcache, int regnum)
229*ef5ccd6cSJohn Marino {
230*ef5ccd6cSJohn Marino ppc_ravenscar_generic_store_registers (&ppc_reg_info, regcache, regnum);
231*ef5ccd6cSJohn Marino }
232*ef5ccd6cSJohn Marino
233*ef5ccd6cSJohn Marino /* The ravenscar_arch_ops vector for most PowerPC targets. */
234*ef5ccd6cSJohn Marino
235*ef5ccd6cSJohn Marino static struct ravenscar_arch_ops ppc_ravenscar_powerpc_ops =
236*ef5ccd6cSJohn Marino {
237*ef5ccd6cSJohn Marino ppc_ravenscar_powerpc_fetch_registers,
238*ef5ccd6cSJohn Marino ppc_ravenscar_powerpc_store_registers,
239*ef5ccd6cSJohn Marino ppc_ravenscar_generic_prepare_to_store
240*ef5ccd6cSJohn Marino };
241*ef5ccd6cSJohn Marino
242*ef5ccd6cSJohn Marino /* Register ppc_ravenscar_powerpc_ops in GDBARCH. */
243*ef5ccd6cSJohn Marino
244*ef5ccd6cSJohn Marino void
register_ppc_ravenscar_ops(struct gdbarch * gdbarch)245*ef5ccd6cSJohn Marino register_ppc_ravenscar_ops (struct gdbarch *gdbarch)
246*ef5ccd6cSJohn Marino {
247*ef5ccd6cSJohn Marino set_gdbarch_ravenscar_ops (gdbarch, &ppc_ravenscar_powerpc_ops);
248*ef5ccd6cSJohn Marino }
249*ef5ccd6cSJohn Marino
250*ef5ccd6cSJohn Marino /* The ravenscar_reg_info for E500 targets. */
251*ef5ccd6cSJohn Marino
252*ef5ccd6cSJohn Marino static const struct ravenscar_reg_info e500_reg_info =
253*ef5ccd6cSJohn Marino {
254*ef5ccd6cSJohn Marino e500_context_offsets,
255*ef5ccd6cSJohn Marino ARRAY_SIZE (e500_context_offsets),
256*ef5ccd6cSJohn Marino };
257*ef5ccd6cSJohn Marino
258*ef5ccd6cSJohn Marino /* Implement the to_fetch_registers ravenscar_arch_ops method
259*ef5ccd6cSJohn Marino for E500 targets. */
260*ef5ccd6cSJohn Marino
261*ef5ccd6cSJohn Marino static void
ppc_ravenscar_e500_fetch_registers(struct regcache * regcache,int regnum)262*ef5ccd6cSJohn Marino ppc_ravenscar_e500_fetch_registers (struct regcache *regcache, int regnum)
263*ef5ccd6cSJohn Marino {
264*ef5ccd6cSJohn Marino ppc_ravenscar_generic_fetch_registers (&e500_reg_info, regcache, regnum);
265*ef5ccd6cSJohn Marino }
266*ef5ccd6cSJohn Marino
267*ef5ccd6cSJohn Marino /* Implement the to_store_registers ravenscar_arch_ops method
268*ef5ccd6cSJohn Marino for E500 targets. */
269*ef5ccd6cSJohn Marino
270*ef5ccd6cSJohn Marino static void
ppc_ravenscar_e500_store_registers(struct regcache * regcache,int regnum)271*ef5ccd6cSJohn Marino ppc_ravenscar_e500_store_registers (struct regcache *regcache, int regnum)
272*ef5ccd6cSJohn Marino {
273*ef5ccd6cSJohn Marino ppc_ravenscar_generic_store_registers (&e500_reg_info, regcache, regnum);
274*ef5ccd6cSJohn Marino }
275*ef5ccd6cSJohn Marino
276*ef5ccd6cSJohn Marino /* The ravenscar_arch_ops vector for E500 targets. */
277*ef5ccd6cSJohn Marino
278*ef5ccd6cSJohn Marino static struct ravenscar_arch_ops ppc_ravenscar_e500_ops =
279*ef5ccd6cSJohn Marino {
280*ef5ccd6cSJohn Marino ppc_ravenscar_e500_fetch_registers,
281*ef5ccd6cSJohn Marino ppc_ravenscar_e500_store_registers,
282*ef5ccd6cSJohn Marino ppc_ravenscar_generic_prepare_to_store
283*ef5ccd6cSJohn Marino };
284*ef5ccd6cSJohn Marino
285*ef5ccd6cSJohn Marino /* Register ppc_ravenscar_e500_ops in GDBARCH. */
286*ef5ccd6cSJohn Marino
287*ef5ccd6cSJohn Marino void
register_e500_ravenscar_ops(struct gdbarch * gdbarch)288*ef5ccd6cSJohn Marino register_e500_ravenscar_ops (struct gdbarch *gdbarch)
289*ef5ccd6cSJohn Marino {
290*ef5ccd6cSJohn Marino set_gdbarch_ravenscar_ops (gdbarch, &ppc_ravenscar_e500_ops);
291*ef5ccd6cSJohn Marino }
292