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