xref: /dflybsd-src/contrib/gdb-7/gdb/ppc-ravenscar-thread.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
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