1/* run front end support for arm
2   Copyright (C) 1995-2020 Free Software Foundation, Inc.
3
4   This file is part of ARM SIM.
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 3 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19/* This file provides the interface between the simulator and
20   run.c and gdb (when the simulator is linked with gdb).
21   All simulator interaction should go through this file.  */
22
23#include "config.h"
24#include <stdio.h>
25#include <stdarg.h>
26#include <string.h>
27#include <bfd.h>
28#include <signal.h>
29#include "gdb/callback.h"
30#include "gdb/remote-sim.h"
31#include "sim-main.h"
32#include "sim-options.h"
33#include "armemu.h"
34#include "dbg_rdi.h"
35#include "ansidecl.h"
36#include "gdb/sim-arm.h"
37#include "gdb/signals.h"
38#include "libiberty.h"
39#include "iwmmxt.h"
40#include "maverick.h"
41
42/* TODO: This should get pulled from the SIM_DESC.  */
43host_callback *sim_callback;
44
45/* TODO: This should get merged into sim_cpu.  */
46struct ARMul_State *state;
47
48/* Memory size in bytes.  */
49/* TODO: Memory should be converted to the common memory module.  */
50static int mem_size = (1 << 21);
51
52int stop_simulator;
53
54#include "dis-asm.h"
55
56/* TODO: Tracing should be converted to common tracing module.  */
57int trace = 0;
58int disas = 0;
59int trace_funcs = 0;
60
61static struct disassemble_info  info;
62static char opbuf[1000];
63
64static int
65op_printf (char *buf, char *fmt, ...)
66{
67  int ret;
68  va_list ap;
69
70  va_start (ap, fmt);
71  ret = vsprintf (opbuf + strlen (opbuf), fmt, ap);
72  va_end (ap);
73  return ret;
74}
75
76static int
77sim_dis_read (bfd_vma                     memaddr ATTRIBUTE_UNUSED,
78	      bfd_byte *                  ptr,
79	      unsigned int                length,
80	      struct disassemble_info *   info)
81{
82  ARMword val = (ARMword) *((ARMword *) info->application_data);
83
84  while (length--)
85    {
86      * ptr ++ = val & 0xFF;
87      val >>= 8;
88    }
89  return 0;
90}
91
92void
93print_insn (ARMword instr)
94{
95  int size;
96  disassembler_ftype disassemble_fn;
97
98  opbuf[0] = 0;
99  info.application_data = & instr;
100  disassemble_fn = disassembler (bfd_arch_arm, 0, 0, NULL);
101  size = disassemble_fn (0, & info);
102  fprintf (stderr, " %*s\n", size, opbuf);
103}
104
105static void
106init (void)
107{
108  static int done;
109
110  if (!done)
111    {
112      ARMul_EmulateInit ();
113      state = ARMul_NewState ();
114      state->bigendSig = (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? HIGH : LOW);
115      ARMul_MemoryInit (state, mem_size);
116      ARMul_OSInit (state);
117      state->verbose = 0;
118      done = 1;
119    }
120}
121
122void
123ARMul_ConsolePrint (ARMul_State * state,
124		    const char * format,
125		    ...)
126{
127  va_list ap;
128
129  if (state->verbose)
130    {
131      va_start (ap, format);
132      vprintf (format, ap);
133      va_end (ap);
134    }
135}
136
137int
138sim_write (SIM_DESC sd ATTRIBUTE_UNUSED,
139	   SIM_ADDR addr,
140	   const unsigned char * buffer,
141	   int size)
142{
143  int i;
144
145  init ();
146
147  for (i = 0; i < size; i++)
148    ARMul_SafeWriteByte (state, addr + i, buffer[i]);
149
150  return size;
151}
152
153int
154sim_read (SIM_DESC sd ATTRIBUTE_UNUSED,
155	  SIM_ADDR addr,
156	  unsigned char * buffer,
157	  int size)
158{
159  int i;
160
161  init ();
162
163  for (i = 0; i < size; i++)
164    buffer[i] = ARMul_SafeReadByte (state, addr + i);
165
166  return size;
167}
168
169int
170sim_stop (SIM_DESC sd ATTRIBUTE_UNUSED)
171{
172  state->Emulate = STOP;
173  stop_simulator = 1;
174  return 1;
175}
176
177void
178sim_resume (SIM_DESC sd ATTRIBUTE_UNUSED,
179	    int step,
180	    int siggnal ATTRIBUTE_UNUSED)
181{
182  state->EndCondition = 0;
183  stop_simulator = 0;
184
185  if (step)
186    {
187      state->Reg[15] = ARMul_DoInstr (state);
188      if (state->EndCondition == 0)
189	state->EndCondition = RDIError_BreakpointReached;
190    }
191  else
192    {
193      state->NextInstr = RESUME;	/* treat as PC change */
194      state->Reg[15] = ARMul_DoProg (state);
195    }
196
197  FLUSHPIPE;
198}
199
200SIM_RC
201sim_create_inferior (SIM_DESC sd ATTRIBUTE_UNUSED,
202		     struct bfd * abfd,
203		     char * const *argv,
204		     char * const *env)
205{
206  int argvlen = 0;
207  int mach;
208  char * const *arg;
209
210  init ();
211
212  if (abfd != NULL)
213    {
214      ARMul_SetPC (state, bfd_get_start_address (abfd));
215      mach = bfd_get_mach (abfd);
216    }
217  else
218    {
219      ARMul_SetPC (state, 0);	/* ??? */
220      mach = 0;
221    }
222
223#ifdef MODET
224  if (abfd != NULL && (bfd_get_start_address (abfd) & 1))
225    SETT;
226#endif
227
228  switch (mach)
229    {
230    default:
231      (*sim_callback->printf_filtered)
232	(sim_callback,
233	 "Unknown machine type '%d'; please update sim_create_inferior.\n",
234	 mach);
235      /* fall through */
236
237    case 0:
238      /* We wouldn't set the machine type with earlier toolchains, so we
239	 explicitly select a processor capable of supporting all ARMs in
240	 32bit mode.  */
241      ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_v6_Prop);
242      break;
243
244    case bfd_mach_arm_XScale:
245      ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop | ARM_v6_Prop);
246      break;
247
248    case bfd_mach_arm_iWMMXt2:
249    case bfd_mach_arm_iWMMXt:
250      {
251	extern int SWI_vector_installed;
252	ARMword i;
253
254	if (! SWI_vector_installed)
255	  {
256	    /* Intialise the hardware vectors to zero.  */
257	    if (! SWI_vector_installed)
258	      for (i = ARMul_ResetV; i <= ARMFIQV; i += 4)
259		ARMul_WriteWord (state, i, 0);
260
261	    /* ARM_WriteWord will have detected the write to the SWI vector,
262	       but we want SWI_vector_installed to remain at 0 so that thumb
263	       mode breakpoints will work.  */
264	    SWI_vector_installed = 0;
265	  }
266      }
267      ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop | ARM_iWMMXt_Prop);
268      break;
269
270    case bfd_mach_arm_ep9312:
271      ARMul_SelectProcessor (state, ARM_v4_Prop | ARM_ep9312_Prop);
272      break;
273
274    case bfd_mach_arm_5:
275      if (bfd_family_coff (abfd))
276	{
277	  /* This is a special case in order to support COFF based ARM toolchains.
278	     The COFF header does not have enough room to store all the different
279	     kinds of ARM cpu, so the XScale, v5T and v5TE architectures all default
280	     to v5.  (See coff_set_flags() in bdf/coffcode.h).  So if we see a v5
281	     machine type here, we assume it could be any of the above architectures
282	     and so select the most feature-full.  */
283	  ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
284	  break;
285	}
286      /* Otherwise drop through.  */
287
288    case bfd_mach_arm_5T:
289      ARMul_SelectProcessor (state, ARM_v5_Prop);
290      break;
291
292    case bfd_mach_arm_5TE:
293      ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop);
294      break;
295
296    case bfd_mach_arm_4:
297    case bfd_mach_arm_4T:
298      ARMul_SelectProcessor (state, ARM_v4_Prop);
299      break;
300
301    case bfd_mach_arm_3:
302    case bfd_mach_arm_3M:
303      ARMul_SelectProcessor (state, ARM_Lock_Prop);
304      break;
305
306    case bfd_mach_arm_2:
307    case bfd_mach_arm_2a:
308      ARMul_SelectProcessor (state, ARM_Fix26_Prop);
309      break;
310    }
311
312  memset (& info, 0, sizeof (info));
313  INIT_DISASSEMBLE_INFO (info, stdout, op_printf);
314  info.read_memory_func = sim_dis_read;
315  info.arch = bfd_get_arch (abfd);
316  info.mach = bfd_get_mach (abfd);
317  info.endian_code = BFD_ENDIAN_LITTLE;
318  if (info.mach == 0)
319    info.arch = bfd_arch_arm;
320  disassemble_init_for_target (& info);
321
322  if (argv != NULL)
323    {
324      /* Set up the command line by laboriously stringing together
325	 the environment carefully picked apart by our caller.  */
326
327      /* Free any old stuff.  */
328      if (state->CommandLine != NULL)
329	{
330	  free (state->CommandLine);
331	  state->CommandLine = NULL;
332	}
333
334      /* See how much we need.  */
335      for (arg = argv; *arg != NULL; arg++)
336	argvlen += strlen (*arg) + 1;
337
338      /* Allocate it.  */
339      state->CommandLine = malloc (argvlen + 1);
340      if (state->CommandLine != NULL)
341	{
342	  arg = argv;
343	  state->CommandLine[0] = '\0';
344
345	  for (arg = argv; *arg != NULL; arg++)
346	    {
347	      strcat (state->CommandLine, *arg);
348	      strcat (state->CommandLine, " ");
349	    }
350	}
351    }
352
353  if (env != NULL)
354    {
355      /* Now see if there's a MEMSIZE spec in the environment.  */
356      while (*env)
357	{
358	  if (strncmp (*env, "MEMSIZE=", sizeof ("MEMSIZE=") - 1) == 0)
359	    {
360	      char *end_of_num;
361
362	      /* Set up memory limit.  */
363	      state->MemSize =
364		strtoul (*env + sizeof ("MEMSIZE=") - 1, &end_of_num, 0);
365	    }
366	  env++;
367	}
368    }
369
370  return SIM_RC_OK;
371}
372
373static int
374frommem (struct ARMul_State *state, unsigned char *memory)
375{
376  if (state->bigendSig == HIGH)
377    return (memory[0] << 24) | (memory[1] << 16)
378      | (memory[2] << 8) | (memory[3] << 0);
379  else
380    return (memory[3] << 24) | (memory[2] << 16)
381      | (memory[1] << 8) | (memory[0] << 0);
382}
383
384static void
385tomem (struct ARMul_State *state,
386       unsigned char *memory,
387       int val)
388{
389  if (state->bigendSig == HIGH)
390    {
391      memory[0] = val >> 24;
392      memory[1] = val >> 16;
393      memory[2] = val >> 8;
394      memory[3] = val >> 0;
395    }
396  else
397    {
398      memory[3] = val >> 24;
399      memory[2] = val >> 16;
400      memory[1] = val >> 8;
401      memory[0] = val >> 0;
402    }
403}
404
405static int
406arm_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
407{
408  init ();
409
410  switch ((enum sim_arm_regs) rn)
411    {
412    case SIM_ARM_R0_REGNUM:
413    case SIM_ARM_R1_REGNUM:
414    case SIM_ARM_R2_REGNUM:
415    case SIM_ARM_R3_REGNUM:
416    case SIM_ARM_R4_REGNUM:
417    case SIM_ARM_R5_REGNUM:
418    case SIM_ARM_R6_REGNUM:
419    case SIM_ARM_R7_REGNUM:
420    case SIM_ARM_R8_REGNUM:
421    case SIM_ARM_R9_REGNUM:
422    case SIM_ARM_R10_REGNUM:
423    case SIM_ARM_R11_REGNUM:
424    case SIM_ARM_R12_REGNUM:
425    case SIM_ARM_R13_REGNUM:
426    case SIM_ARM_R14_REGNUM:
427    case SIM_ARM_R15_REGNUM: /* PC */
428    case SIM_ARM_FP0_REGNUM:
429    case SIM_ARM_FP1_REGNUM:
430    case SIM_ARM_FP2_REGNUM:
431    case SIM_ARM_FP3_REGNUM:
432    case SIM_ARM_FP4_REGNUM:
433    case SIM_ARM_FP5_REGNUM:
434    case SIM_ARM_FP6_REGNUM:
435    case SIM_ARM_FP7_REGNUM:
436    case SIM_ARM_FPS_REGNUM:
437      ARMul_SetReg (state, state->Mode, rn, frommem (state, memory));
438      break;
439
440    case SIM_ARM_PS_REGNUM:
441      state->Cpsr = frommem (state, memory);
442      ARMul_CPSRAltered (state);
443      break;
444
445    case SIM_ARM_MAVERIC_COP0R0_REGNUM:
446    case SIM_ARM_MAVERIC_COP0R1_REGNUM:
447    case SIM_ARM_MAVERIC_COP0R2_REGNUM:
448    case SIM_ARM_MAVERIC_COP0R3_REGNUM:
449    case SIM_ARM_MAVERIC_COP0R4_REGNUM:
450    case SIM_ARM_MAVERIC_COP0R5_REGNUM:
451    case SIM_ARM_MAVERIC_COP0R6_REGNUM:
452    case SIM_ARM_MAVERIC_COP0R7_REGNUM:
453    case SIM_ARM_MAVERIC_COP0R8_REGNUM:
454    case SIM_ARM_MAVERIC_COP0R9_REGNUM:
455    case SIM_ARM_MAVERIC_COP0R10_REGNUM:
456    case SIM_ARM_MAVERIC_COP0R11_REGNUM:
457    case SIM_ARM_MAVERIC_COP0R12_REGNUM:
458    case SIM_ARM_MAVERIC_COP0R13_REGNUM:
459    case SIM_ARM_MAVERIC_COP0R14_REGNUM:
460    case SIM_ARM_MAVERIC_COP0R15_REGNUM:
461      memcpy (& DSPregs [rn - SIM_ARM_MAVERIC_COP0R0_REGNUM],
462	      memory, sizeof (struct maverick_regs));
463      return sizeof (struct maverick_regs);
464
465    case SIM_ARM_MAVERIC_DSPSC_REGNUM:
466      memcpy (&DSPsc, memory, sizeof DSPsc);
467      return sizeof DSPsc;
468
469    case SIM_ARM_IWMMXT_COP0R0_REGNUM:
470    case SIM_ARM_IWMMXT_COP0R1_REGNUM:
471    case SIM_ARM_IWMMXT_COP0R2_REGNUM:
472    case SIM_ARM_IWMMXT_COP0R3_REGNUM:
473    case SIM_ARM_IWMMXT_COP0R4_REGNUM:
474    case SIM_ARM_IWMMXT_COP0R5_REGNUM:
475    case SIM_ARM_IWMMXT_COP0R6_REGNUM:
476    case SIM_ARM_IWMMXT_COP0R7_REGNUM:
477    case SIM_ARM_IWMMXT_COP0R8_REGNUM:
478    case SIM_ARM_IWMMXT_COP0R9_REGNUM:
479    case SIM_ARM_IWMMXT_COP0R10_REGNUM:
480    case SIM_ARM_IWMMXT_COP0R11_REGNUM:
481    case SIM_ARM_IWMMXT_COP0R12_REGNUM:
482    case SIM_ARM_IWMMXT_COP0R13_REGNUM:
483    case SIM_ARM_IWMMXT_COP0R14_REGNUM:
484    case SIM_ARM_IWMMXT_COP0R15_REGNUM:
485    case SIM_ARM_IWMMXT_COP1R0_REGNUM:
486    case SIM_ARM_IWMMXT_COP1R1_REGNUM:
487    case SIM_ARM_IWMMXT_COP1R2_REGNUM:
488    case SIM_ARM_IWMMXT_COP1R3_REGNUM:
489    case SIM_ARM_IWMMXT_COP1R4_REGNUM:
490    case SIM_ARM_IWMMXT_COP1R5_REGNUM:
491    case SIM_ARM_IWMMXT_COP1R6_REGNUM:
492    case SIM_ARM_IWMMXT_COP1R7_REGNUM:
493    case SIM_ARM_IWMMXT_COP1R8_REGNUM:
494    case SIM_ARM_IWMMXT_COP1R9_REGNUM:
495    case SIM_ARM_IWMMXT_COP1R10_REGNUM:
496    case SIM_ARM_IWMMXT_COP1R11_REGNUM:
497    case SIM_ARM_IWMMXT_COP1R12_REGNUM:
498    case SIM_ARM_IWMMXT_COP1R13_REGNUM:
499    case SIM_ARM_IWMMXT_COP1R14_REGNUM:
500    case SIM_ARM_IWMMXT_COP1R15_REGNUM:
501      return Store_Iwmmxt_Register (rn - SIM_ARM_IWMMXT_COP0R0_REGNUM, memory);
502
503    default:
504      return 0;
505    }
506
507  return length;
508}
509
510static int
511arm_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
512{
513  ARMword regval;
514  int len = length;
515
516  init ();
517
518  switch ((enum sim_arm_regs) rn)
519    {
520    case SIM_ARM_R0_REGNUM:
521    case SIM_ARM_R1_REGNUM:
522    case SIM_ARM_R2_REGNUM:
523    case SIM_ARM_R3_REGNUM:
524    case SIM_ARM_R4_REGNUM:
525    case SIM_ARM_R5_REGNUM:
526    case SIM_ARM_R6_REGNUM:
527    case SIM_ARM_R7_REGNUM:
528    case SIM_ARM_R8_REGNUM:
529    case SIM_ARM_R9_REGNUM:
530    case SIM_ARM_R10_REGNUM:
531    case SIM_ARM_R11_REGNUM:
532    case SIM_ARM_R12_REGNUM:
533    case SIM_ARM_R13_REGNUM:
534    case SIM_ARM_R14_REGNUM:
535    case SIM_ARM_R15_REGNUM: /* PC */
536      regval = ARMul_GetReg (state, state->Mode, rn);
537      break;
538
539    case SIM_ARM_FP0_REGNUM:
540    case SIM_ARM_FP1_REGNUM:
541    case SIM_ARM_FP2_REGNUM:
542    case SIM_ARM_FP3_REGNUM:
543    case SIM_ARM_FP4_REGNUM:
544    case SIM_ARM_FP5_REGNUM:
545    case SIM_ARM_FP6_REGNUM:
546    case SIM_ARM_FP7_REGNUM:
547    case SIM_ARM_FPS_REGNUM:
548      memset (memory, 0, length);
549      return 0;
550
551    case SIM_ARM_PS_REGNUM:
552      regval = ARMul_GetCPSR (state);
553      break;
554
555    case SIM_ARM_MAVERIC_COP0R0_REGNUM:
556    case SIM_ARM_MAVERIC_COP0R1_REGNUM:
557    case SIM_ARM_MAVERIC_COP0R2_REGNUM:
558    case SIM_ARM_MAVERIC_COP0R3_REGNUM:
559    case SIM_ARM_MAVERIC_COP0R4_REGNUM:
560    case SIM_ARM_MAVERIC_COP0R5_REGNUM:
561    case SIM_ARM_MAVERIC_COP0R6_REGNUM:
562    case SIM_ARM_MAVERIC_COP0R7_REGNUM:
563    case SIM_ARM_MAVERIC_COP0R8_REGNUM:
564    case SIM_ARM_MAVERIC_COP0R9_REGNUM:
565    case SIM_ARM_MAVERIC_COP0R10_REGNUM:
566    case SIM_ARM_MAVERIC_COP0R11_REGNUM:
567    case SIM_ARM_MAVERIC_COP0R12_REGNUM:
568    case SIM_ARM_MAVERIC_COP0R13_REGNUM:
569    case SIM_ARM_MAVERIC_COP0R14_REGNUM:
570    case SIM_ARM_MAVERIC_COP0R15_REGNUM:
571      memcpy (memory, & DSPregs [rn - SIM_ARM_MAVERIC_COP0R0_REGNUM],
572	      sizeof (struct maverick_regs));
573      return sizeof (struct maverick_regs);
574
575    case SIM_ARM_MAVERIC_DSPSC_REGNUM:
576      memcpy (memory, & DSPsc, sizeof DSPsc);
577      return sizeof DSPsc;
578
579    case SIM_ARM_IWMMXT_COP0R0_REGNUM:
580    case SIM_ARM_IWMMXT_COP0R1_REGNUM:
581    case SIM_ARM_IWMMXT_COP0R2_REGNUM:
582    case SIM_ARM_IWMMXT_COP0R3_REGNUM:
583    case SIM_ARM_IWMMXT_COP0R4_REGNUM:
584    case SIM_ARM_IWMMXT_COP0R5_REGNUM:
585    case SIM_ARM_IWMMXT_COP0R6_REGNUM:
586    case SIM_ARM_IWMMXT_COP0R7_REGNUM:
587    case SIM_ARM_IWMMXT_COP0R8_REGNUM:
588    case SIM_ARM_IWMMXT_COP0R9_REGNUM:
589    case SIM_ARM_IWMMXT_COP0R10_REGNUM:
590    case SIM_ARM_IWMMXT_COP0R11_REGNUM:
591    case SIM_ARM_IWMMXT_COP0R12_REGNUM:
592    case SIM_ARM_IWMMXT_COP0R13_REGNUM:
593    case SIM_ARM_IWMMXT_COP0R14_REGNUM:
594    case SIM_ARM_IWMMXT_COP0R15_REGNUM:
595    case SIM_ARM_IWMMXT_COP1R0_REGNUM:
596    case SIM_ARM_IWMMXT_COP1R1_REGNUM:
597    case SIM_ARM_IWMMXT_COP1R2_REGNUM:
598    case SIM_ARM_IWMMXT_COP1R3_REGNUM:
599    case SIM_ARM_IWMMXT_COP1R4_REGNUM:
600    case SIM_ARM_IWMMXT_COP1R5_REGNUM:
601    case SIM_ARM_IWMMXT_COP1R6_REGNUM:
602    case SIM_ARM_IWMMXT_COP1R7_REGNUM:
603    case SIM_ARM_IWMMXT_COP1R8_REGNUM:
604    case SIM_ARM_IWMMXT_COP1R9_REGNUM:
605    case SIM_ARM_IWMMXT_COP1R10_REGNUM:
606    case SIM_ARM_IWMMXT_COP1R11_REGNUM:
607    case SIM_ARM_IWMMXT_COP1R12_REGNUM:
608    case SIM_ARM_IWMMXT_COP1R13_REGNUM:
609    case SIM_ARM_IWMMXT_COP1R14_REGNUM:
610    case SIM_ARM_IWMMXT_COP1R15_REGNUM:
611      return Fetch_Iwmmxt_Register (rn - SIM_ARM_IWMMXT_COP0R0_REGNUM, memory);
612
613    default:
614      return 0;
615    }
616
617  while (len)
618    {
619      tomem (state, memory, regval);
620
621      len -= 4;
622      memory += 4;
623      regval = 0;
624    }
625
626  return length;
627}
628
629typedef struct
630{
631  char * 	swi_option;
632  unsigned int	swi_mask;
633} swi_options;
634
635#define SWI_SWITCH	"--swi-support"
636
637static swi_options options[] =
638  {
639    { "none",    0 },
640    { "demon",   SWI_MASK_DEMON },
641    { "angel",   SWI_MASK_ANGEL },
642    { "redboot", SWI_MASK_REDBOOT },
643    { "all",     -1 },
644    { "NONE",    0 },
645    { "DEMON",   SWI_MASK_DEMON },
646    { "ANGEL",   SWI_MASK_ANGEL },
647    { "REDBOOT", SWI_MASK_REDBOOT },
648    { "ALL",     -1 }
649  };
650
651
652static int
653sim_target_parse_command_line (int argc, char ** argv)
654{
655  int i;
656
657  for (i = 1; i < argc; i++)
658    {
659      char * ptr = argv[i];
660      int arg;
661
662      if ((ptr == NULL) || (* ptr != '-'))
663	break;
664
665      if (strcmp (ptr, "-t") == 0)
666	{
667	  trace = 1;
668	  continue;
669	}
670
671      if (strcmp (ptr, "-z") == 0)
672	{
673	  /* Remove this option from the argv array.  */
674	  for (arg = i; arg < argc; arg ++)
675	    {
676	      free (argv[arg]);
677	      argv[arg] = argv[arg + 1];
678	    }
679	  argc --;
680	  i --;
681	  trace_funcs = 1;
682	  continue;
683	}
684
685      if (strcmp (ptr, "-d") == 0)
686	{
687	  /* Remove this option from the argv array.  */
688	  for (arg = i; arg < argc; arg ++)
689	    {
690	      free (argv[arg]);
691	      argv[arg] = argv[arg + 1];
692	    }
693	  argc --;
694	  i --;
695	  disas = 1;
696	  continue;
697	}
698
699      if (strncmp (ptr, SWI_SWITCH, sizeof SWI_SWITCH - 1) != 0)
700	continue;
701
702      if (ptr[sizeof SWI_SWITCH - 1] == 0)
703	{
704	  /* Remove this option from the argv array.  */
705	  for (arg = i; arg < argc; arg ++)
706	    {
707	      free (argv[arg]);
708	      argv[arg] = argv[arg + 1];
709	    }
710	  argc --;
711
712	  ptr = argv[i];
713	}
714      else
715	ptr += sizeof SWI_SWITCH;
716
717      swi_mask = 0;
718
719      while (* ptr)
720	{
721	  int i;
722
723	  for (i = ARRAY_SIZE (options); i--;)
724	    if (strncmp (ptr, options[i].swi_option,
725			 strlen (options[i].swi_option)) == 0)
726	      {
727		swi_mask |= options[i].swi_mask;
728		ptr += strlen (options[i].swi_option);
729
730		if (* ptr == ',')
731		  ++ ptr;
732
733		break;
734	      }
735
736	  if (i < 0)
737	    break;
738	}
739
740      if (* ptr != 0)
741	fprintf (stderr, "Ignoring swi options: %s\n", ptr);
742
743      /* Remove this option from the argv array.  */
744      for (arg = i; arg < argc; arg ++)
745	{
746	  free (argv[arg]);
747	  argv[arg] = argv[arg + 1];
748	}
749      argc --;
750      i --;
751    }
752  return argc;
753}
754
755static void
756sim_target_parse_arg_array (char ** argv)
757{
758  sim_target_parse_command_line (countargv (argv), argv);
759}
760
761static sim_cia
762arm_pc_get (sim_cpu *cpu)
763{
764  return PC;
765}
766
767static void
768arm_pc_set (sim_cpu *cpu, sim_cia pc)
769{
770  ARMul_SetPC (state, pc);
771}
772
773static void
774free_state (SIM_DESC sd)
775{
776  if (STATE_MODULES (sd) != NULL)
777    sim_module_uninstall (sd);
778  sim_cpu_free_all (sd);
779  sim_state_free (sd);
780}
781
782SIM_DESC
783sim_open (SIM_OPEN_KIND kind,
784	  host_callback *cb,
785	  struct bfd *abfd,
786	  char * const *argv)
787{
788  int i;
789  char **argv_copy;
790  SIM_DESC sd = sim_state_alloc (kind, cb);
791  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
792
793  /* The cpu data is kept in a separately allocated chunk of memory.  */
794  if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
795    {
796      free_state (sd);
797      return 0;
798    }
799
800  if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
801    {
802      free_state (sd);
803      return 0;
804    }
805
806  /* The parser will print an error message for us, so we silently return.  */
807  if (sim_parse_args (sd, argv) != SIM_RC_OK)
808    {
809      free_state (sd);
810      return 0;
811    }
812
813  /* Check for/establish the a reference program image.  */
814  if (sim_analyze_program (sd,
815			   (STATE_PROG_ARGV (sd) != NULL
816			    ? *STATE_PROG_ARGV (sd)
817			    : NULL), abfd) != SIM_RC_OK)
818    {
819      free_state (sd);
820      return 0;
821    }
822
823  /* Configure/verify the target byte order and other runtime
824     configuration options.  */
825  if (sim_config (sd) != SIM_RC_OK)
826    {
827      sim_module_uninstall (sd);
828      return 0;
829    }
830
831  if (sim_post_argv_init (sd) != SIM_RC_OK)
832    {
833      /* Uninstall the modules to avoid memory leaks,
834	 file descriptor leaks, etc.  */
835      sim_module_uninstall (sd);
836      return 0;
837    }
838
839  /* CPU specific initialization.  */
840  for (i = 0; i < MAX_NR_PROCESSORS; ++i)
841    {
842      SIM_CPU *cpu = STATE_CPU (sd, i);
843
844      CPU_REG_FETCH (cpu) = arm_reg_fetch;
845      CPU_REG_STORE (cpu) = arm_reg_store;
846      CPU_PC_FETCH (cpu) = arm_pc_get;
847      CPU_PC_STORE (cpu) = arm_pc_set;
848    }
849
850  sim_callback = cb;
851
852  /* Copy over the argv contents so we can modify them.  */
853  argv_copy = dupargv (argv);
854
855  sim_target_parse_arg_array (argv_copy);
856
857  if (argv_copy[1] != NULL)
858    {
859      int i;
860
861      /* Scan for memory-size switches.  */
862      for (i = 0; (argv_copy[i] != NULL) && (argv_copy[i][0] != 0); i++)
863	if (argv_copy[i][0] == '-' && argv_copy[i][1] == 'm')
864	  {
865	    if (argv_copy[i][2] != '\0')
866	      mem_size = atoi (&argv_copy[i][2]);
867	    else if (argv_copy[i + 1] != NULL)
868	      {
869		mem_size = atoi (argv_copy[i + 1]);
870		i++;
871	      }
872	    else
873	      {
874		sim_callback->printf_filtered (sim_callback,
875					       "Missing argument to -m option\n");
876		return NULL;
877	      }
878	  }
879    }
880
881  freeargv (argv_copy);
882
883  return sd;
884}
885
886void
887sim_stop_reason (SIM_DESC sd ATTRIBUTE_UNUSED,
888		 enum sim_stop *reason,
889		 int *sigrc)
890{
891  if (stop_simulator)
892    {
893      *reason = sim_stopped;
894      *sigrc = GDB_SIGNAL_INT;
895    }
896  else if (state->EndCondition == 0)
897    {
898      *reason = sim_exited;
899      *sigrc = state->Reg[0] & 255;
900    }
901  else
902    {
903      *reason = sim_stopped;
904      if (state->EndCondition == RDIError_BreakpointReached)
905	*sigrc = GDB_SIGNAL_TRAP;
906      else if (   state->EndCondition == RDIError_DataAbort
907	       || state->EndCondition == RDIError_AddressException)
908	*sigrc = GDB_SIGNAL_BUS;
909      else
910	*sigrc = 0;
911    }
912}
913