Fix bug with FP stur instructions.
[external/binutils.git] / sim / aarch64 / interp.c
1 /* interp.c -- AArch64 sim interface to GDB.
2
3    Copyright (C) 2015-2016 Free Software Foundation, Inc.
4
5    Contributed by Red Hat.
6
7    This file is part of GDB.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23 #include <stdio.h>
24 #include <assert.h>
25 #include <signal.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <stdlib.h>
29
30 #include "ansidecl.h"
31 #include "bfd.h"
32 #include "gdb/callback.h"
33 #include "gdb/remote-sim.h"
34 #include "gdb/signals.h"
35 #include "gdb/sim-aarch64.h"
36
37 #include "sim-main.h"
38 #include "sim-options.h"
39 #include "memory.h"
40 #include "simulator.h"
41
42 /* Filter out (in place) symbols that are useless for disassembly.
43    COUNT is the number of elements in SYMBOLS.
44    Return the number of useful symbols. */
45
46 static long
47 remove_useless_symbols (asymbol **symbols, long count)
48 {
49   asymbol **in_ptr  = symbols;
50   asymbol **out_ptr = symbols;
51
52   while (count-- > 0)
53     {
54       asymbol *sym = *in_ptr++;
55
56       if (strstr (sym->name, "gcc2_compiled"))
57         continue;
58       if (sym->name == NULL || sym->name[0] == '\0')
59         continue;
60       if (sym->flags & (BSF_DEBUGGING))
61         continue;
62       if (   bfd_is_und_section (sym->section)
63           || bfd_is_com_section (sym->section))
64         continue;
65       if (sym->name[0] == '$')
66         continue;
67
68       *out_ptr++ = sym;
69     }
70   return out_ptr - symbols;
71 }
72
73 static signed int
74 compare_symbols (const void *ap, const void *bp)
75 {
76   const asymbol *a = * (const asymbol **) ap;
77   const asymbol *b = * (const asymbol **) bp;
78
79   if (bfd_asymbol_value (a) > bfd_asymbol_value (b))
80     return 1;
81   if (bfd_asymbol_value (a) < bfd_asymbol_value (b))
82     return -1;
83   return 0;
84 }
85
86 /* Find the name of the function at ADDR.  */
87 const char *
88 aarch64_get_func (SIM_DESC sd, uint64_t addr)
89 {
90   long symcount = STATE_PROG_SYMS_COUNT (sd);
91   asymbol **symtab = STATE_PROG_SYMS (sd);
92   int  min, max;
93
94   min = -1;
95   max = symcount;
96   while (min < max - 1)
97     {
98       int sym;
99       bfd_vma sa;
100
101       sym = (min + max) / 2;
102       sa = bfd_asymbol_value (symtab[sym]);
103
104       if (sa > addr)
105         max = sym;
106       else if (sa < addr)
107         min = sym;
108       else
109         {
110           min = sym;
111           break;
112         }
113     }
114
115   if (min != -1)
116     return bfd_asymbol_name (symtab [min]);
117
118   return "";
119 }
120
121 SIM_RC
122 sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
123                      char * const *argv, char * const *env)
124 {
125   sim_cpu *cpu = STATE_CPU (sd, 0);
126   bfd_vma addr = 0;
127
128   if (abfd != NULL)
129     addr = bfd_get_start_address (abfd);
130
131   aarch64_set_next_PC (cpu, addr);
132   aarch64_update_PC (cpu);
133
134   /* Standalone mode (i.e. `run`) will take care of the argv for us in
135      sim_open() -> sim_parse_args().  But in debug mode (i.e. 'target sim'
136      with `gdb`), we need to handle it because the user can change the
137      argv on the fly via gdb's 'run'.  */
138   if (STATE_PROG_ARGV (sd) != argv)
139     {
140       freeargv (STATE_PROG_ARGV (sd));
141       STATE_PROG_ARGV (sd) = dupargv (argv);
142     }
143
144   if (trace_load_symbols (sd))
145     {
146       STATE_PROG_SYMS_COUNT (sd) =
147         remove_useless_symbols (STATE_PROG_SYMS (sd),
148                                 STATE_PROG_SYMS_COUNT (sd));
149       qsort (STATE_PROG_SYMS (sd), STATE_PROG_SYMS_COUNT (sd),
150              sizeof (asymbol *), compare_symbols);
151     }
152
153   aarch64_init (cpu, addr);
154
155   return SIM_RC_OK;
156 }
157
158 /* Read the LENGTH bytes at BUF as a little-endian value.  */
159
160 static bfd_vma
161 get_le (unsigned char *buf, unsigned int length)
162 {
163   bfd_vma acc = 0;
164
165   while (length -- > 0)
166     acc = (acc << 8) + buf[length];
167
168   return acc;
169 }
170
171 /* Store VAL as a little-endian value in the LENGTH bytes at BUF.  */
172
173 static void
174 put_le (unsigned char *buf, unsigned int length, bfd_vma val)
175 {
176   int i;
177
178   for (i = 0; i < length; i++)
179     {
180       buf[i] = val & 0xff;
181       val >>= 8;
182     }
183 }
184
185 static int
186 check_regno (int regno)
187 {
188   return 0 <= regno && regno < AARCH64_MAX_REGNO;
189 }
190
191 static size_t
192 reg_size (int regno)
193 {
194   if (regno == AARCH64_CPSR_REGNO || regno == AARCH64_FPSR_REGNO)
195     return 32;
196   return 64;
197 }
198
199 static int
200 aarch64_reg_get (SIM_CPU *cpu, int regno, unsigned char *buf, int length)
201 {
202   size_t size;
203   bfd_vma val;
204
205   if (!check_regno (regno))
206     return 0;
207
208   size = reg_size (regno);
209
210   if (length != size)
211     return 0;
212
213   switch (regno)
214     {
215     case AARCH64_MIN_GR ... AARCH64_MAX_GR:
216       val = aarch64_get_reg_u64 (cpu, regno, 0);
217       break;
218
219     case AARCH64_MIN_FR ... AARCH64_MAX_FR:
220       val = aarch64_get_FP_double (cpu, regno - 32);
221       break;
222
223     case AARCH64_PC_REGNO:
224       val = aarch64_get_PC (cpu);
225       break;
226
227     case AARCH64_CPSR_REGNO:
228       val = aarch64_get_CPSR (cpu);
229       break;
230
231     case AARCH64_FPSR_REGNO:
232       val = aarch64_get_FPSR (cpu);
233       break;
234
235     default:
236       sim_io_eprintf (CPU_STATE (cpu),
237                       "sim: unrecognized register number: %d\n", regno);
238       return -1;
239     }
240
241   put_le (buf, length, val);
242
243   return size;
244 }
245
246 static int
247 aarch64_reg_set (SIM_CPU *cpu, int regno, unsigned char *buf, int length)
248 {
249   size_t size;
250   bfd_vma val;
251
252   if (!check_regno (regno))
253     return -1;
254
255   size = reg_size (regno);
256
257   if (length != size)
258     return -1;
259
260   val = get_le (buf, length);
261
262   switch (regno)
263     {
264     case AARCH64_MIN_GR ... AARCH64_MAX_GR:
265       aarch64_set_reg_u64 (cpu, regno, 1, val);
266       break;
267
268     case AARCH64_MIN_FR ... AARCH64_MAX_FR:
269       aarch64_set_FP_double (cpu, regno - 32, (double) val);
270       break;
271
272     case AARCH64_PC_REGNO:
273       aarch64_set_next_PC (cpu, val);
274       aarch64_update_PC (cpu);
275       break;
276
277     case AARCH64_CPSR_REGNO:
278       aarch64_set_CPSR (cpu, val);
279       break;
280
281     case AARCH64_FPSR_REGNO:
282       aarch64_set_FPSR (cpu, val);
283       break;
284
285     default:
286       sim_io_eprintf (CPU_STATE (cpu),
287                       "sim: unrecognized register number: %d\n", regno);
288       return 0;
289     }
290
291   return size;
292 }
293
294 static sim_cia
295 aarch64_pc_get (sim_cpu *cpu)
296 {
297   return aarch64_get_PC (cpu);
298 }
299
300 static void
301 aarch64_pc_set (sim_cpu *cpu, sim_cia pc)
302 {
303   aarch64_set_next_PC (cpu, pc);
304   aarch64_update_PC (cpu);
305 }
306
307 static void
308 free_state (SIM_DESC sd)
309 {
310   if (STATE_MODULES (sd) != NULL)
311     sim_module_uninstall (sd);
312   sim_cpu_free_all (sd);
313   sim_state_free (sd);
314 }
315
316 SIM_DESC
317 sim_open (SIM_OPEN_KIND                  kind,
318           struct host_callback_struct *  callback,
319           struct bfd *                   abfd,
320           char * const *                 argv)
321 {
322   sim_cpu *cpu;
323   SIM_DESC sd = sim_state_alloc (kind, callback);
324
325   if (sd == NULL)
326     return sd;
327
328   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
329
330   /* Perform the initialization steps one by one.  */
331   if (sim_cpu_alloc_all (sd, 1, 0) != SIM_RC_OK
332       || sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK
333       || sim_parse_args (sd, argv) != SIM_RC_OK
334       || sim_analyze_program (sd,
335                               (STATE_PROG_ARGV (sd) != NULL
336                                ? *STATE_PROG_ARGV (sd)
337                                : NULL), abfd) != SIM_RC_OK
338       || sim_config (sd) != SIM_RC_OK
339       || sim_post_argv_init (sd) != SIM_RC_OK)
340     {
341       free_state (sd);
342       return NULL;
343     }
344
345   aarch64_init_LIT_table ();
346
347   assert (MAX_NR_PROCESSORS == 1);
348   cpu = STATE_CPU (sd, 0);
349   CPU_PC_FETCH (cpu) = aarch64_pc_get;
350   CPU_PC_STORE (cpu) = aarch64_pc_set;
351   CPU_REG_FETCH (cpu) = aarch64_reg_get;
352   CPU_REG_STORE (cpu) = aarch64_reg_set;
353
354   /* Set SP, FP and PC to 0 and set LR to -1
355      so we can detect a top-level return.  */
356   aarch64_set_reg_u64 (cpu, SP, 1, 0);
357   aarch64_set_reg_u64 (cpu, FP, 1, 0);
358   aarch64_set_reg_u64 (cpu, LR, 1, TOP_LEVEL_RETURN_PC);
359   aarch64_set_next_PC (cpu, 0);
360   aarch64_update_PC (cpu);
361
362   /* Default to a 128 Mbyte (== 2^27) memory space.  */
363   sim_do_commandf (sd, "memory-size 0x8000000");
364
365   return sd;
366 }
367
368 void
369 sim_engine_run (SIM_DESC sd,
370                 int next_cpu_nr ATTRIBUTE_UNUSED,
371                 int nr_cpus ATTRIBUTE_UNUSED,
372                 int siggnal ATTRIBUTE_UNUSED)
373 {
374   aarch64_run (sd);
375 }