Remove displaced_step_inferior_state::next
[external/binutils.git] / gdb / aarch64-ravenscar-thread.c
1 /* Ravenscar Aarch64 target support.
2
3    Copyright (C) 2017-2018 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 "aarch64-tdep.h"
24 #include "inferior.h"
25 #include "ravenscar-thread.h"
26 #include "aarch64-ravenscar-thread.h"
27
28 #define NO_OFFSET -1
29
30 /* See aarch64-tdep.h for register numbers.  */
31
32 static const int aarch64_context_offsets[] =
33 {
34   /* X0 - X28 */
35   NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
36   NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
37   NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
38   NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
39   NO_OFFSET, NO_OFFSET, NO_OFFSET, 0,
40   8,         16,        24,        32,
41   40,        48,        56,        64,
42   72,
43
44   /* FP, LR, SP, PC, CPSR */
45   /* Note that as task switch is synchronous, PC is in fact the LR here */
46   80,        88,        96,        88,
47   NO_OFFSET,
48
49   /* Q0 - Q31 */
50   112,       128,       144,       160,
51   176,       192,       208,       224,
52   240,       256,       272,       288,
53   304,       320,       336,       352,
54   368,       384,       400,       416,
55   432,       448,       464,       480,
56   496,       512,       528,       544,
57   560,       576,       592,       608,
58
59   /* FPSR, FPCR */
60   104,       108,
61
62   /* FPU Saved field */
63   624
64 };
65
66 /* The register layout info.  */
67
68 struct ravenscar_reg_info
69 {
70   /* A table providing the offset relative to the context structure
71      where each register is saved.  */
72   const int *context_offsets;
73
74   /* The number of elements in the context_offsets table above.  */
75   int context_offsets_size;
76 };
77
78 /* supply register REGNUM, which has been saved on REGISTER_ADDR, to the
79    regcache.  */
80
81 static void
82 supply_register_at_address (struct regcache *regcache, int regnum,
83                             CORE_ADDR register_addr)
84 {
85   struct gdbarch *gdbarch = regcache->arch ();
86   int buf_size = register_size (gdbarch, regnum);
87   gdb_byte *buf;
88
89   buf = (gdb_byte *) alloca (buf_size);
90   read_memory (register_addr, buf, buf_size);
91   regcache->raw_supply (regnum, buf);
92 }
93
94 /* Return true if, for a non-running thread, REGNUM has been saved on the
95    Thread_Descriptor.  */
96
97 static int
98 register_in_thread_descriptor_p (const struct ravenscar_reg_info *reg_info,
99                                  int regnum)
100 {
101   /* Check FPU registers */
102   return (regnum < reg_info->context_offsets_size
103           && reg_info->context_offsets[regnum] != NO_OFFSET);
104 }
105
106 /* to_fetch_registers when inferior_ptid is different from the running
107    thread.  */
108
109 static void
110 aarch64_ravenscar_generic_fetch_registers
111   (const struct ravenscar_reg_info *reg_info,
112    struct regcache *regcache, int regnum)
113 {
114   struct gdbarch *gdbarch = regcache->arch ();
115   const int num_regs = gdbarch_num_regs (gdbarch);
116   int current_regnum;
117   CORE_ADDR current_address;
118   CORE_ADDR thread_descriptor_address;
119
120   /* The tid is the thread_id field, which is a pointer to the thread.  */
121   thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid ();
122
123   /* Read registers.  */
124   for (current_regnum = 0; current_regnum < num_regs; current_regnum++)
125     {
126       if (register_in_thread_descriptor_p (reg_info, current_regnum))
127         {
128           current_address = thread_descriptor_address
129             + reg_info->context_offsets[current_regnum];
130           supply_register_at_address (regcache, current_regnum,
131                                       current_address);
132         }
133     }
134 }
135
136 /* to_prepare_to_store when inferior_ptid is different from the running
137    thread.  */
138
139 static void
140 aarch64_ravenscar_generic_prepare_to_store (struct regcache *regcache)
141 {
142   /* Nothing to do.  */
143 }
144
145 /* to_store_registers when inferior_ptid is different from the running
146    thread.  */
147
148 static void
149 aarch64_ravenscar_generic_store_registers
150   (const struct ravenscar_reg_info *reg_info,
151    struct regcache *regcache, int regnum)
152 {
153   struct gdbarch *gdbarch = regcache->arch ();
154   int buf_size = register_size (gdbarch, regnum);
155   gdb_byte buf[buf_size];
156   ULONGEST register_address;
157
158   if (register_in_thread_descriptor_p (reg_info, regnum))
159     register_address
160       = inferior_ptid.tid () + reg_info->context_offsets [regnum];
161   else
162     return;
163
164   regcache->raw_collect (regnum, buf);
165   write_memory (register_address,
166                 buf,
167                 buf_size);
168 }
169
170 /* The ravenscar_reg_info for most Aarch64 targets.  */
171
172 static const struct ravenscar_reg_info aarch64_reg_info =
173 {
174   aarch64_context_offsets,
175   ARRAY_SIZE (aarch64_context_offsets),
176 };
177
178 /* Implement the to_fetch_registers ravenscar_arch_ops method
179    for most Aarch64 targets.  */
180
181 static void
182 aarch64_ravenscar_fetch_registers (struct regcache *regcache, int regnum)
183 {
184   aarch64_ravenscar_generic_fetch_registers
185     (&aarch64_reg_info, regcache, regnum);
186 }
187
188 /* Implement the to_store_registers ravenscar_arch_ops method
189    for most Aarch64 targets.  */
190
191 static void
192 aarch64_ravenscar_store_registers (struct regcache *regcache, int regnum)
193 {
194   aarch64_ravenscar_generic_store_registers
195     (&aarch64_reg_info, regcache, regnum);
196 }
197
198 /* The ravenscar_arch_ops vector for most Aarch64 targets.  */
199
200 static struct ravenscar_arch_ops aarch64_ravenscar_ops =
201 {
202   aarch64_ravenscar_fetch_registers,
203   aarch64_ravenscar_store_registers,
204   aarch64_ravenscar_generic_prepare_to_store
205 };
206
207 /* Register aarch64_ravenscar_ops in GDBARCH.  */
208
209 void
210 register_aarch64_ravenscar_ops (struct gdbarch *gdbarch)
211 {
212   set_gdbarch_ravenscar_ops (gdbarch, &aarch64_ravenscar_ops);
213 }