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