If a v5 architecture is detected, assume it might be an XScale binary, since
[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 "callback.h"
32 #include "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
39 host_callback *sim_callback;
40
41 static struct ARMul_State *state;
42
43 /* Who is using the simulator.  */
44 static SIM_OPEN_KIND sim_kind;
45
46 /* argv[0] */
47 static char *myname;
48
49 /* Memory size in bytes.  */
50 static int mem_size = (1 << 21);
51
52 /* Non-zero to display start up banner, and maybe other things.  */
53 static int verbosity;
54
55 /* Non-zero to set big endian mode.  */
56 static int big_endian;
57
58 int stop_simulator;
59
60 static void
61 init ()
62 {
63   static int done;
64
65   if (!done)
66     {
67       ARMul_EmulateInit ();
68       state = ARMul_NewState ();
69       state->bigendSig = (big_endian ? HIGH : LOW);
70       ARMul_MemoryInit (state, mem_size);
71       ARMul_OSInit (state);
72       ARMul_CoProInit (state);
73       state->verbose = verbosity;
74       done = 1;
75     }
76 }
77
78 /* Set verbosity level of simulator.
79    This is not intended to produce detailed tracing or debugging information.
80    Just summaries.  */
81 /* FIXME: common/run.c doesn't do this yet.  */
82
83 void
84 sim_set_verbose (v)
85      int v;
86 {
87   verbosity = v;
88 }
89
90 /* Set the memory size to SIZE bytes.
91    Must be called before initializing simulator.  */
92 /* FIXME: Rename to sim_set_mem_size.  */
93
94 void
95 sim_size (size)
96      int size;
97 {
98   mem_size = size;
99 }
100
101 void
102 ARMul_ConsolePrint VPARAMS ((ARMul_State * state,
103                              const char * format,
104                              ...))
105 {
106   va_list ap;
107
108   if (state->verbose)
109     {
110       va_start (ap, format);
111       vprintf (format, ap);
112       va_end (ap);
113     }
114 }
115
116 ARMword
117 ARMul_Debug (state, pc, instr)
118      ARMul_State * state ATTRIBUTE_UNUSED;
119      ARMword       pc    ATTRIBUTE_UNUSED;
120      ARMword       instr ATTRIBUTE_UNUSED;
121 {
122   return 0;
123 }
124
125 int
126 sim_write (sd, addr, buffer, size)
127      SIM_DESC sd ATTRIBUTE_UNUSED;
128      SIM_ADDR addr;
129      unsigned char * buffer;
130      int size;
131 {
132   int i;
133
134   init ();
135
136   for (i = 0; i < size; i++)
137     ARMul_SafeWriteByte (state, addr + i, buffer[i]);
138
139   return size;
140 }
141
142 int
143 sim_read (sd, addr, buffer, size)
144      SIM_DESC sd ATTRIBUTE_UNUSED;
145      SIM_ADDR addr;
146      unsigned char * buffer;
147      int size;
148 {
149   int i;
150
151   init ();
152
153   for (i = 0; i < size; i++)
154     buffer[i] = ARMul_SafeReadByte (state, addr + i);
155
156   return size;
157 }
158
159 int
160 sim_trace (sd)
161      SIM_DESC sd ATTRIBUTE_UNUSED;
162 {  
163   (*sim_callback->printf_filtered)
164     (sim_callback,
165      "This simulator does not support tracing\n");
166   return 1;
167 }
168
169 int
170 sim_stop (sd)
171      SIM_DESC sd ATTRIBUTE_UNUSED;
172 {
173   state->Emulate = STOP;
174   stop_simulator = 1;
175   return 1;
176 }
177
178 void
179 sim_resume (sd, step, siggnal)
180      SIM_DESC sd ATTRIBUTE_UNUSED;
181      int step;
182      int siggnal ATTRIBUTE_UNUSED;
183 {
184   state->EndCondition = 0;
185   stop_simulator = 0;
186
187   if (step)
188     {
189       state->Reg[15] = ARMul_DoInstr (state);
190       if (state->EndCondition == 0)
191         state->EndCondition = RDIError_BreakpointReached;
192     }
193   else
194     {
195       state->NextInstr = RESUME;        /* treat as PC change */
196       state->Reg[15] = ARMul_DoProg (state);
197     }
198
199   FLUSHPIPE;
200 }
201
202 SIM_RC
203 sim_create_inferior (sd, abfd, argv, env)
204      SIM_DESC sd ATTRIBUTE_UNUSED;
205      struct _bfd * abfd;
206      char ** argv;
207      char ** env;
208 {
209   int argvlen = 0;
210   int mach;
211   char **arg;
212
213   if (abfd != NULL)
214     ARMul_SetPC (state, bfd_get_start_address (abfd));
215   else
216     ARMul_SetPC (state, 0);     /* ??? */
217
218   mach = bfd_get_mach (abfd);
219
220   switch (mach)
221     {
222     default:
223       (*sim_callback->printf_filtered)
224         (sim_callback,
225          "Unknown machine type; please update sim_create_inferior.\n");
226       /* fall through */
227
228     case 0:
229       /* We wouldn't set the machine type with earlier toolchains, so we
230          explicitly select a processor capable of supporting all ARMs in
231          32bit mode.  */
232     case bfd_mach_arm_XScale:
233       ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
234       break;
235
236     case bfd_mach_arm_5:
237       /* This is a special case in order to support COFF based ARM toolchains.
238          The COFF header does not have enough room to store all the different
239          kinds of ARM cpu, so the XScale, v5T and v5TE architectures all default
240          to v5.  (See coff_set_flags() in bdf/coffcode.h).  So if we see a v5
241          machine type here, we assume it could be any of the above architectures
242          and so select the most feature-full.  */
243       ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
244       break;
245
246     case bfd_mach_arm_5T:
247       ARMul_SelectProcessor (state, ARM_v5_Prop);
248       break;
249
250     case bfd_mach_arm_5TE:
251       ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop);
252       break;
253
254     case bfd_mach_arm_4:
255     case bfd_mach_arm_4T:
256       ARMul_SelectProcessor (state, ARM_v4_Prop);
257       break;
258
259     case bfd_mach_arm_3:
260     case bfd_mach_arm_3M:
261       ARMul_SelectProcessor (state, ARM_Lock_Prop);
262       break;
263
264     case bfd_mach_arm_2:
265     case bfd_mach_arm_2a:
266       ARMul_SelectProcessor (state, ARM_Fix26_Prop);
267       break;
268     }
269
270   if (   mach != bfd_mach_arm_3
271       && mach != bfd_mach_arm_3M
272       && mach != bfd_mach_arm_2
273       && mach != bfd_mach_arm_2a)
274     {
275       /* Reset mode to ARM.  A gdb user may rerun a program that had entered
276          THUMB mode from the start and cause the ARM-mode startup code to be
277          executed in THUMB mode.  */
278       ARMul_SetCPSR (state, SVC32MODE);
279     }
280   
281   if (argv != NULL)
282     {
283       /* Set up the command line by laboriously stringing together
284          the environment carefully picked apart by our caller.  */
285
286       /* Free any old stuff.  */
287       if (state->CommandLine != NULL)
288         {
289           free (state->CommandLine);
290           state->CommandLine = NULL;
291         }
292
293       /* See how much we need.  */
294       for (arg = argv; *arg != NULL; arg++)
295         argvlen += strlen (*arg) + 1;
296
297       /* Allocate it.  */
298       state->CommandLine = malloc (argvlen + 1);
299       if (state->CommandLine != NULL)
300         {
301           arg = argv;
302           state->CommandLine[0] = '\0';
303
304           for (arg = argv; *arg != NULL; arg++)
305             {
306               strcat (state->CommandLine, *arg);
307               strcat (state->CommandLine, " ");
308             }
309         }
310     }
311
312   if (env != NULL)
313     {
314       /* Now see if there's a MEMSIZE spec in the environment.  */
315       while (*env)
316         {
317           if (strncmp (*env, "MEMSIZE=", sizeof ("MEMSIZE=") - 1) == 0)
318             {
319               char *end_of_num;
320
321               /* Set up memory limit.  */
322               state->MemSize =
323                 strtoul (*env + sizeof ("MEMSIZE=") - 1, &end_of_num, 0);
324             }
325           env++;
326         }
327     }
328
329   return SIM_RC_OK;
330 }
331
332 void
333 sim_info (sd, verbose)
334      SIM_DESC sd ATTRIBUTE_UNUSED;
335      int verbose ATTRIBUTE_UNUSED;
336 {
337 }
338
339 static int
340 frommem (state, memory)
341      struct ARMul_State *state;
342      unsigned char *memory;
343 {
344   if (state->bigendSig == HIGH)
345     return (memory[0] << 24) | (memory[1] << 16)
346       | (memory[2] << 8) | (memory[3] << 0);
347   else
348     return (memory[3] << 24) | (memory[2] << 16)
349       | (memory[1] << 8) | (memory[0] << 0);
350 }
351
352 static void
353 tomem (state, memory, val)
354      struct ARMul_State *state;
355      unsigned char *memory;
356      int val;
357 {
358   if (state->bigendSig == HIGH)
359     {
360       memory[0] = val >> 24;
361       memory[1] = val >> 16;
362       memory[2] = val >> 8;
363       memory[3] = val >> 0;
364     }
365   else
366     {
367       memory[3] = val >> 24;
368       memory[2] = val >> 16;
369       memory[1] = val >> 8;
370       memory[0] = val >> 0;
371     }
372 }
373
374 int
375 sim_store_register (sd, rn, memory, length)
376      SIM_DESC sd ATTRIBUTE_UNUSED;
377      int rn;
378      unsigned char *memory;
379      int length ATTRIBUTE_UNUSED;
380 {
381   init ();
382
383   if (rn == 25)
384     {
385       state->Cpsr = frommem (state, memory);
386       ARMul_CPSRAltered (state);             
387     }
388   else
389     ARMul_SetReg (state, state->Mode, rn, frommem (state, memory));
390   return -1;
391 }
392
393 int
394 sim_fetch_register (sd, rn, memory, length)
395      SIM_DESC sd ATTRIBUTE_UNUSED;
396      int rn;
397      unsigned char *memory;
398      int length ATTRIBUTE_UNUSED;
399 {
400   ARMword regval;
401
402   init ();
403
404   if (rn < 16)
405     regval = ARMul_GetReg (state, state->Mode, rn);
406   else if (rn == 25)
407     /* FIXME: use PS_REGNUM from gdb/config/arm/tm-arm.h.  */
408     regval = ARMul_GetCPSR (state);
409   else
410     /* FIXME: should report an error.  */
411     regval = 0;
412
413   while (length)
414     {
415       tomem (state, memory, regval);
416
417       length -= 4;
418       memory += 4;
419       regval = 0;
420     }  
421
422   return -1;
423 }
424
425 SIM_DESC
426 sim_open (kind, ptr, abfd, argv)
427      SIM_OPEN_KIND kind;
428      host_callback *ptr;
429      struct _bfd *abfd;
430      char **argv;
431 {
432   sim_kind = kind;
433   if (myname) free (myname);
434   myname = (char *) xstrdup (argv[0]);
435   sim_callback = ptr;
436
437   /* Decide upon the endian-ness of the processor.
438      If we can, get the information from the bfd itself.
439      Otherwise look to see if we have been given a command
440      line switch that tells us.  Otherwise default to little endian.  */
441   if (abfd != NULL)
442     big_endian = bfd_big_endian (abfd);
443   else if (argv[1] != NULL)
444     {
445       int i;
446
447       /* Scan for endian-ness switch.  */
448       for (i = 0; (argv[i] != NULL) && (argv[i][0] != 0); i++)
449         if (argv[i][0] == '-' && argv[i][1] == 'E')
450           {
451             char c;
452
453             if ((c = argv[i][2]) == 0)
454               {
455                 ++i;
456                 c = argv[i][0];
457               }
458
459             switch (c)
460               {
461               case 0:
462                 sim_callback->printf_filtered
463                   (sim_callback, "No argument to -E option provided\n");
464                 break;
465
466               case 'b':
467               case 'B':
468                 big_endian = 1;
469                 break;
470
471               case 'l':
472               case 'L':
473                 big_endian = 0;
474                 break;
475
476               default:
477                 sim_callback->printf_filtered
478                   (sim_callback, "Unrecognised argument to -E option\n");
479                 break;
480               }
481           }
482     }
483
484   return (SIM_DESC) 1;
485 }
486
487 void
488 sim_close (sd, quitting)
489      SIM_DESC sd ATTRIBUTE_UNUSED;
490      int quitting ATTRIBUTE_UNUSED;
491 {
492   if (myname)
493     free (myname);
494   myname = NULL;
495 }
496
497 SIM_RC
498 sim_load (sd, prog, abfd, from_tty)
499      SIM_DESC sd;
500      char *prog;
501      bfd *abfd;
502      int from_tty ATTRIBUTE_UNUSED;
503 {
504   bfd *prog_bfd;
505
506   prog_bfd = sim_load_file (sd, myname, sim_callback, prog, abfd,
507                             sim_kind == SIM_OPEN_DEBUG, 0, sim_write);
508   if (prog_bfd == NULL)
509     return SIM_RC_FAIL;
510   ARMul_SetPC (state, bfd_get_start_address (prog_bfd));
511   if (abfd == NULL)
512     bfd_close (prog_bfd);
513   return SIM_RC_OK;
514 }
515
516 void
517 sim_stop_reason (sd, reason, sigrc)
518      SIM_DESC sd ATTRIBUTE_UNUSED;
519      enum sim_stop *reason;
520      int *sigrc;
521 {
522   if (stop_simulator)
523     {
524       *reason = sim_stopped;
525       *sigrc = SIGINT;
526     }
527   else if (state->EndCondition == 0)
528     {
529       *reason = sim_exited;
530       *sigrc = state->Reg[0] & 255;
531     }
532   else
533     {
534       *reason = sim_stopped;
535       if (state->EndCondition == RDIError_BreakpointReached)
536         *sigrc = SIGTRAP;
537       else
538         *sigrc = 0;
539     }
540 }
541
542 void
543 sim_do_command (sd, cmd)
544      SIM_DESC sd ATTRIBUTE_UNUSED;
545      char *cmd ATTRIBUTE_UNUSED;
546 {  
547   (*sim_callback->printf_filtered)
548     (sim_callback,
549      "This simulator does not accept any commands.\n");
550 }
551
552 void
553 sim_set_callbacks (ptr)
554      host_callback *ptr;
555 {
556   sim_callback = ptr;
557 }