Add linux_get_hwcap
[external/binutils.git] / gdb / aarch64-ravenscar-thread.c
1 /* Ravenscar Aarch64 target support.
2
3    Copyright (C) 2017-2019 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_store_registers when inferior_ptid is different from the running
137    thread.  */
138
139 static void
140 aarch64_ravenscar_generic_store_registers
141   (const struct ravenscar_reg_info *reg_info,
142    struct regcache *regcache, int regnum)
143 {
144   struct gdbarch *gdbarch = regcache->arch ();
145   int buf_size = register_size (gdbarch, regnum);
146   gdb_byte buf[buf_size];
147   ULONGEST register_address;
148
149   if (register_in_thread_descriptor_p (reg_info, regnum))
150     register_address
151       = inferior_ptid.tid () + reg_info->context_offsets [regnum];
152   else
153     return;
154
155   regcache->raw_collect (regnum, buf);
156   write_memory (register_address,
157                 buf,
158                 buf_size);
159 }
160
161 /* The ravenscar_reg_info for most Aarch64 targets.  */
162
163 static const struct ravenscar_reg_info aarch64_reg_info =
164 {
165   aarch64_context_offsets,
166   ARRAY_SIZE (aarch64_context_offsets),
167 };
168
169 struct aarch64_ravenscar_ops : public ravenscar_arch_ops
170 {
171   void fetch_registers (struct regcache *regcache, int regnum) override
172   {
173     aarch64_ravenscar_generic_fetch_registers
174       (&aarch64_reg_info, regcache, regnum);
175   }
176
177   void store_registers (struct regcache *regcache, int regnum) override
178   {
179     aarch64_ravenscar_generic_store_registers
180       (&aarch64_reg_info, regcache, regnum);
181   }
182 };
183
184 /* The ravenscar_arch_ops vector for most Aarch64 targets.  */
185
186 static struct aarch64_ravenscar_ops aarch64_ravenscar_ops;
187
188 /* Register aarch64_ravenscar_ops in GDBARCH.  */
189
190 void
191 register_aarch64_ravenscar_ops (struct gdbarch *gdbarch)
192 {
193   set_gdbarch_ravenscar_ops (gdbarch, &aarch64_ravenscar_ops);
194 }