Move include/callback.h and include/remote-sim.h to include/gdb/.
[external/binutils.git] / sim / arm / wrapper.c
1 /* run front end support for arm
2    Copyright (C) 1995, 1996, 1997, 2000, 2001, 2002
3    Free Software Foundation, Inc.
4
5    This file is part of ARM SIM.
6
7    GCC is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published
9    by the Free Software Foundation; either version 2, or (at your
10    option) any later version.
11
12    GCC is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See
15    the GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public
18    License along with this program; if not, write to the Free
19    Software Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 /* This file provides the interface between the simulator and
23    run.c and gdb (when the simulator is linked with gdb).
24    All simulator interaction should go through this file.  */
25
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <bfd.h>
30 #include <signal.h>
31 #include "gdb/callback.h"
32 #include "gdb/remote-sim.h"
33 #include "armdefs.h"
34 #include "armemu.h"
35 #include "dbg_rdi.h"
36 #include "ansidecl.h"
37 #include "sim-utils.h"
38 #include "run-sim.h"
39
40 host_callback *sim_callback;
41
42 static struct ARMul_State *state;
43
44 /* Who is using the simulator.  */
45 static SIM_OPEN_KIND sim_kind;
46
47 /* argv[0] */
48 static char *myname;
49
50 /* Memory size in bytes.  */
51 static int mem_size = (1 << 23);
52
53 /* Non-zero to display start up banner, and maybe other things.  */
54 static int verbosity;
55
56 /* Non-zero to set big endian mode.  */
57 static int big_endian;
58
59 int stop_simulator;
60
61 static void
62 init ()
63 {
64   static int done;
65
66   if (!done)
67     {
68       ARMul_EmulateInit ();
69       state = ARMul_NewState ();
70       state->bigendSig = (big_endian ? HIGH : LOW);
71       ARMul_MemoryInit (state, mem_size);
72       ARMul_OSInit (state);
73       ARMul_CoProInit (state);
74       state->verbose = verbosity;
75       done = 1;
76     }
77 }
78
79 /* Set verbosity level of simulator.
80    This is not intended to produce detailed tracing or debugging information.
81    Just summaries.  */
82 /* FIXME: common/run.c doesn't do this yet.  */
83
84 void
85 sim_set_verbose (v)
86      int v;
87 {
88   verbosity = v;
89 }
90
91 /* Set the memory size to SIZE bytes.
92    Must be called before initializing simulator.  */
93 /* FIXME: Rename to sim_set_mem_size.  */
94
95 void
96 sim_size (size)
97      int size;
98 {
99   mem_size = size;
100 }
101
102 void
103 ARMul_ConsolePrint VPARAMS ((ARMul_State * state,
104                              const char * format,
105                              ...))
106 {
107   va_list ap;
108
109   if (state->verbose)
110     {
111       va_start (ap, format);
112       vprintf (format, ap);
113       va_end (ap);
114     }
115 }
116
117 ARMword
118 ARMul_Debug (state, pc, instr)
119      ARMul_State * state ATTRIBUTE_UNUSED;
120      ARMword       pc    ATTRIBUTE_UNUSED;
121      ARMword       instr ATTRIBUTE_UNUSED;
122 {
123   return 0;
124 }
125
126 int
127 sim_write (sd, addr, buffer, size)
128      SIM_DESC sd ATTRIBUTE_UNUSED;
129      SIM_ADDR addr;
130      unsigned char * buffer;
131      int size;
132 {
133   int i;
134
135   init ();
136
137   for (i = 0; i < size; i++)
138     ARMul_SafeWriteByte (state, addr + i, buffer[i]);
139
140   return size;
141 }
142
143 int
144 sim_read (sd, addr, buffer, size)
145      SIM_DESC sd ATTRIBUTE_UNUSED;
146      SIM_ADDR addr;
147      unsigned char * buffer;
148      int size;
149 {
150   int i;
151
152   init ();
153
154   for (i = 0; i < size; i++)
155     buffer[i] = ARMul_SafeReadByte (state, addr + i);
156
157   return size;
158 }
159
160 int
161 sim_trace (sd)
162      SIM_DESC sd ATTRIBUTE_UNUSED;
163 {  
164   (*sim_callback->printf_filtered)
165     (sim_callback,
166      "This simulator does not support tracing\n");
167   return 1;
168 }
169
170 int
171 sim_stop (sd)
172      SIM_DESC sd ATTRIBUTE_UNUSED;
173 {
174   state->Emulate = STOP;
175   stop_simulator = 1;
176   return 1;
177 }
178
179 void
180 sim_resume (sd, step, siggnal)
181      SIM_DESC sd ATTRIBUTE_UNUSED;
182      int step;
183      int siggnal ATTRIBUTE_UNUSED;
184 {
185   state->EndCondition = 0;
186   stop_simulator = 0;
187
188   if (step)
189     {
190       state->Reg[15] = ARMul_DoInstr (state);
191       if (state->EndCondition == 0)
192         state->EndCondition = RDIError_BreakpointReached;
193     }
194   else
195     {
196       state->NextInstr = RESUME;        /* treat as PC change */
197       state->Reg[15] = ARMul_DoProg (state);
198     }
199
200   FLUSHPIPE;
201 }
202
203 SIM_RC
204 sim_create_inferior (sd, abfd, argv, env)
205      SIM_DESC sd ATTRIBUTE_UNUSED;
206      struct _bfd * abfd;
207      char ** argv;
208      char ** env;
209 {
210   int argvlen = 0;
211   int mach;
212   char **arg;
213
214   if (abfd != NULL)
215     ARMul_SetPC (state, bfd_get_start_address (abfd));
216   else
217     ARMul_SetPC (state, 0);     /* ??? */
218
219   mach = bfd_get_mach (abfd);
220
221   switch (mach)
222     {
223     default:
224       (*sim_callback->printf_filtered)
225         (sim_callback,
226          "Unknown machine type '%d'; please update sim_create_inferior.\n",
227          mach);
228       /* fall through */
229
230     case 0:
231       /* We wouldn't set the machine type with earlier toolchains, so we
232          explicitly select a processor capable of supporting all ARMs in
233          32bit mode.  */
234     case bfd_mach_arm_XScale:
235       ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
236       break;
237
238     case bfd_mach_arm_5:
239       if (bfd_family_coff (abfd))
240         {
241           /* This is a special case in order to support COFF based ARM toolchains.
242              The COFF header does not have enough room to store all the different
243              kinds of ARM cpu, so the XScale, v5T and v5TE architectures all default
244              to v5.  (See coff_set_flags() in bdf/coffcode.h).  So if we see a v5
245              machine type here, we assume it could be any of the above architectures
246              and so select the most feature-full.  */
247           ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
248           break;
249         }
250       /* Otherwise drop through.  */
251
252     case bfd_mach_arm_5T:
253       ARMul_SelectProcessor (state, ARM_v5_Prop);
254       break;
255
256     case bfd_mach_arm_5TE:
257       ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop);
258       break;
259
260     case bfd_mach_arm_4:
261     case bfd_mach_arm_4T:
262       ARMul_SelectProcessor (state, ARM_v4_Prop);
263       break;
264
265     case bfd_mach_arm_3:
266     case bfd_mach_arm_3M:
267       ARMul_SelectProcessor (state, ARM_Lock_Prop);
268       break;
269
270     case bfd_mach_arm_2:
271     case bfd_mach_arm_2a:
272       ARMul_SelectProcessor (state, ARM_Fix26_Prop);
273       break;
274     }
275
276   if (   mach != bfd_mach_arm_3
277       && mach != bfd_mach_arm_3M
278       && mach != bfd_mach_arm_2
279       && mach != bfd_mach_arm_2a)
280     {
281       /* Reset mode to ARM.  A gdb user may rerun a program that had entered
282          THUMB mode from the start and cause the ARM-mode startup code to be
283          executed in THUMB mode.  */
284       ARMul_SetCPSR (state, SVC32MODE);
285     }
286   
287   if (argv != NULL)
288     {
289       /* Set up the command line by laboriously stringing together
290          the environment carefully picked apart by our caller.  */
291
292       /* Free any old stuff.  */
293       if (state->CommandLine != NULL)
294         {
295           free (state->CommandLine);
296           state->CommandLine = NULL;
297         }
298
299       /* See how much we need.  */
300       for (arg = argv; *arg != NULL; arg++)
301         argvlen += strlen (*arg) + 1;
302
303       /* Allocate it.  */
304       state->CommandLine = malloc (argvlen + 1);
305       if (state->CommandLine != NULL)
306         {
307           arg = argv;
308           state->CommandLine[0] = '\0';
309
310           for (arg = argv; *arg != NULL; arg++)
311             {
312               strcat (state->CommandLine, *arg);
313               strcat (state->CommandLine, " ");
314             }
315         }
316     }
317
318   if (env != NULL)
319     {
320       /* Now see if there's a MEMSIZE spec in the environment.  */
321       while (*env)
322         {
323           if (strncmp (*env, "MEMSIZE=", sizeof ("MEMSIZE=") - 1) == 0)
324             {
325               char *end_of_num;
326
327               /* Set up memory limit.  */
328               state->MemSize =
329                 strtoul (*env + sizeof ("MEMSIZE=") - 1, &end_of_num, 0);
330             }
331           env++;
332         }
333     }
334
335   return SIM_RC_OK;
336 }
337
338 void
339 sim_info (sd, verbose)
340      SIM_DESC sd ATTRIBUTE_UNUSED;
341      int verbose ATTRIBUTE_UNUSED;
342 {
343 }
344
345 static int
346 frommem (state, memory)
347      struct ARMul_State *state;
348      unsigned char *memory;
349 {
350   if (state->bigendSig == HIGH)
351     return (memory[0] << 24) | (memory[1] << 16)
352       | (memory[2] << 8) | (memory[3] << 0);
353   else
354     return (memory[3] << 24) | (memory[2] << 16)
355       | (memory[1] << 8) | (memory[0] << 0);
356 }
357
358 static void
359 tomem (state, memory, val)
360      struct ARMul_State *state;
361      unsigned char *memory;
362      int val;
363 {
364   if (state->bigendSig == HIGH)
365     {
366       memory[0] = val >> 24;
367       memory[1] = val >> 16;
368       memory[2] = val >> 8;
369       memory[3] = val >> 0;
370     }
371   else
372     {
373       memory[3] = val >> 24;
374       memory[2] = val >> 16;
375       memory[1] = val >> 8;
376       memory[0] = val >> 0;
377     }
378 }
379
380 int
381 sim_store_register (sd, rn, memory, length)
382      SIM_DESC sd ATTRIBUTE_UNUSED;
383      int rn;
384      unsigned char *memory;
385      int length ATTRIBUTE_UNUSED;
386 {
387   init ();
388
389   if (rn == 25)
390     {
391       state->Cpsr = frommem (state, memory);
392       ARMul_CPSRAltered (state);
393     }
394   else
395     ARMul_SetReg (state, state->Mode, rn, frommem (state, memory));
396   return -1;
397 }
398
399 int
400 sim_fetch_register (sd, rn, memory, length)
401      SIM_DESC sd ATTRIBUTE_UNUSED;
402      int rn;
403      unsigned char *memory;
404      int length ATTRIBUTE_UNUSED;
405 {
406   ARMword regval;
407
408   init ();
409
410   if (rn < 16)
411     regval = ARMul_GetReg (state, state->Mode, rn);
412   else if (rn == 25)
413     /* FIXME: use PS_REGNUM from gdb/config/arm/tm-arm.h.  */
414     regval = ARMul_GetCPSR (state);
415   else
416     /* FIXME: should report an error.  */
417     regval = 0;
418
419   while (length)
420     {
421       tomem (state, memory, regval);
422
423       length -= 4;
424       memory += 4;
425       regval = 0;
426     }  
427
428   return -1;
429 }
430
431 #ifdef SIM_TARGET_SWITCHES
432
433 static void sim_target_parse_arg_array PARAMS ((char **));
434
435 typedef struct
436 {
437   char *        swi_option;
438   unsigned int  swi_mask;
439 } swi_options;
440
441 #define SWI_SWITCH      "--swi-support"
442
443 static swi_options options[] =
444   {
445     { "none",    0 },
446     { "demon",   SWI_MASK_DEMON },
447     { "angel",   SWI_MASK_ANGEL },
448     { "redboot", SWI_MASK_REDBOOT },
449     { "all",     -1 },
450     { "NONE",    0 },
451     { "DEMON",   SWI_MASK_DEMON },
452     { "ANGEL",   SWI_MASK_ANGEL },
453     { "REDBOOT", SWI_MASK_REDBOOT },
454     { "ALL",     -1 }
455   };
456
457
458 int
459 sim_target_parse_command_line (argc, argv)
460      int argc;
461      char ** argv;
462 {
463   int i;
464
465   for (i = 1; i < argc; i++)
466     {
467       char * ptr = argv[i];
468       int arg;
469
470       if ((ptr == NULL) || (* ptr != '-'))
471         break;
472
473       if (strncmp (ptr, SWI_SWITCH, sizeof SWI_SWITCH - 1) != 0)
474         continue;
475
476       if (ptr[sizeof SWI_SWITCH - 1] == 0)
477         {
478           /* Remove this option from the argv array.  */
479           for (arg = i; arg < argc; arg ++)
480             argv[arg] = argv[arg + 1];
481           argc --;
482           
483           ptr = argv[i];
484         }
485       else
486         ptr += sizeof SWI_SWITCH;
487
488       swi_mask = 0;
489       
490       while (* ptr)
491         {
492           int i;
493
494           for (i = sizeof options / sizeof options[0]; i--;)
495             if (strncmp (ptr, options[i].swi_option,
496                          strlen (options[i].swi_option)) == 0)
497               {
498                 swi_mask |= options[i].swi_mask;
499                 ptr += strlen (options[i].swi_option);
500
501                 if (* ptr == ',')
502                   ++ ptr;
503
504                 break;
505               }
506
507           if (i < 0)
508             break;
509         }
510
511       if (* ptr != 0)
512         fprintf (stderr, "Ignoring swi options: %s\n", ptr);
513       
514       /* Remove this option from the argv array.  */
515       for (arg = i; arg < argc; arg ++)
516         argv[arg] = argv[arg + 1];
517       argc --;
518       i --;
519     }
520   return argc;
521 }
522
523 static void
524 sim_target_parse_arg_array (argv)
525      char ** argv;
526 {
527   int i;
528
529   for (i = 0; argv[i]; i++)
530     ;
531
532   return (void) sim_target_parse_command_line (i, argv);
533 }
534
535 void
536 sim_target_display_usage ()
537 {
538   fprintf (stderr, "%s=<list>  Comma seperated list of SWI protocols to supoport.\n\
539                 This list can contain: NONE, DEMON, ANGEL, REDBOOT and/or ALL.\n",
540            SWI_SWITCH);
541 }
542 #endif
543
544 SIM_DESC
545 sim_open (kind, ptr, abfd, argv)
546      SIM_OPEN_KIND kind;
547      host_callback *ptr;
548      struct _bfd *abfd;
549      char **argv;
550 {
551   sim_kind = kind;
552   if (myname) free (myname);
553   myname = (char *) xstrdup (argv[0]);
554   sim_callback = ptr;
555
556 #ifdef SIM_TARGET_SWITCHES
557   sim_target_parse_arg_array (argv);
558 #endif
559   
560   /* Decide upon the endian-ness of the processor.
561      If we can, get the information from the bfd itself.
562      Otherwise look to see if we have been given a command
563      line switch that tells us.  Otherwise default to little endian.  */
564   if (abfd != NULL)
565     big_endian = bfd_big_endian (abfd);
566   else if (argv[1] != NULL)
567     {
568       int i;
569
570       /* Scan for endian-ness switch.  */
571       for (i = 0; (argv[i] != NULL) && (argv[i][0] != 0); i++)
572         if (argv[i][0] == '-' && argv[i][1] == 'E')
573           {
574             char c;
575
576             if ((c = argv[i][2]) == 0)
577               {
578                 ++i;
579                 c = argv[i][0];
580               }
581
582             switch (c)
583               {
584               case 0:
585                 sim_callback->printf_filtered
586                   (sim_callback, "No argument to -E option provided\n");
587                 break;
588
589               case 'b':
590               case 'B':
591                 big_endian = 1;
592                 break;
593
594               case 'l':
595               case 'L':
596                 big_endian = 0;
597                 break;
598
599               default:
600                 sim_callback->printf_filtered
601                   (sim_callback, "Unrecognised argument to -E option\n");
602                 break;
603               }
604           }
605     }
606
607   return (SIM_DESC) 1;
608 }
609
610 void
611 sim_close (sd, quitting)
612      SIM_DESC sd ATTRIBUTE_UNUSED;
613      int quitting ATTRIBUTE_UNUSED;
614 {
615   if (myname)
616     free (myname);
617   myname = NULL;
618 }
619
620 SIM_RC
621 sim_load (sd, prog, abfd, from_tty)
622      SIM_DESC sd;
623      char *prog;
624      bfd *abfd;
625      int from_tty ATTRIBUTE_UNUSED;
626 {
627   bfd *prog_bfd;
628
629   prog_bfd = sim_load_file (sd, myname, sim_callback, prog, abfd,
630                             sim_kind == SIM_OPEN_DEBUG, 0, sim_write);
631   if (prog_bfd == NULL)
632     return SIM_RC_FAIL;
633   ARMul_SetPC (state, bfd_get_start_address (prog_bfd));
634   if (abfd == NULL)
635     bfd_close (prog_bfd);
636   return SIM_RC_OK;
637 }
638
639 void
640 sim_stop_reason (sd, reason, sigrc)
641      SIM_DESC sd ATTRIBUTE_UNUSED;
642      enum sim_stop *reason;
643      int *sigrc;
644 {
645   if (stop_simulator)
646     {
647       *reason = sim_stopped;
648       *sigrc = SIGINT;
649     }
650   else if (state->EndCondition == 0)
651     {
652       *reason = sim_exited;
653       *sigrc = state->Reg[0] & 255;
654     }
655   else
656     {
657       *reason = sim_stopped;
658       if (state->EndCondition == RDIError_BreakpointReached)
659         *sigrc = SIGTRAP;
660       else
661         *sigrc = 0;
662     }
663 }
664
665 void
666 sim_do_command (sd, cmd)
667      SIM_DESC sd ATTRIBUTE_UNUSED;
668      char *cmd ATTRIBUTE_UNUSED;
669 {  
670   (*sim_callback->printf_filtered)
671     (sim_callback,
672      "This simulator does not accept any commands.\n");
673 }
674
675 void
676 sim_set_callbacks (ptr)
677      host_callback *ptr;
678 {
679   sim_callback = ptr;
680 }