General format tidy ups
[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     case bfd_mach_arm_5T:
238       ARMul_SelectProcessor (state, ARM_v5_Prop);
239       break;
240
241     case bfd_mach_arm_5TE:
242       ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop);
243       break;
244
245     case bfd_mach_arm_4:
246     case bfd_mach_arm_4T:
247       ARMul_SelectProcessor (state, ARM_v4_Prop);
248       break;
249
250     case bfd_mach_arm_3:
251     case bfd_mach_arm_3M:
252       ARMul_SelectProcessor (state, ARM_Lock_Prop);
253       break;
254
255     case bfd_mach_arm_2:
256     case bfd_mach_arm_2a:
257       ARMul_SelectProcessor (state, ARM_Fix26_Prop);
258       break;
259     }
260
261   if (   mach != bfd_mach_arm_3
262       && mach != bfd_mach_arm_3M
263       && mach != bfd_mach_arm_2
264       && mach != bfd_mach_arm_2a)
265     {
266       /* Reset mode to ARM.  A gdb user may rerun a program that had entered
267          THUMB mode from the start and cause the ARM-mode startup code to be
268          executed in THUMB mode.  */
269       ARMul_SetCPSR (state, SVC32MODE);
270     }
271   
272   if (argv != NULL)
273     {
274       /* Set up the command line by laboriously stringing together
275          the environment carefully picked apart by our caller.  */
276
277       /* Free any old stuff.  */
278       if (state->CommandLine != NULL)
279         {
280           free (state->CommandLine);
281           state->CommandLine = NULL;
282         }
283
284       /* See how much we need.  */
285       for (arg = argv; *arg != NULL; arg++)
286         argvlen += strlen (*arg) + 1;
287
288       /* Allocate it.  */
289       state->CommandLine = malloc (argvlen + 1);
290       if (state->CommandLine != NULL)
291         {
292           arg = argv;
293           state->CommandLine[0] = '\0';
294
295           for (arg = argv; *arg != NULL; arg++)
296             {
297               strcat (state->CommandLine, *arg);
298               strcat (state->CommandLine, " ");
299             }
300         }
301     }
302
303   if (env != NULL)
304     {
305       /* Now see if there's a MEMSIZE spec in the environment.  */
306       while (*env)
307         {
308           if (strncmp (*env, "MEMSIZE=", sizeof ("MEMSIZE=") - 1) == 0)
309             {
310               char *end_of_num;
311
312               /* Set up memory limit.  */
313               state->MemSize =
314                 strtoul (*env + sizeof ("MEMSIZE=") - 1, &end_of_num, 0);
315             }
316           env++;
317         }
318     }
319
320   return SIM_RC_OK;
321 }
322
323 void
324 sim_info (sd, verbose)
325      SIM_DESC sd ATTRIBUTE_UNUSED;
326      int verbose ATTRIBUTE_UNUSED;
327 {
328 }
329
330 static int
331 frommem (state, memory)
332      struct ARMul_State *state;
333      unsigned char *memory;
334 {
335   if (state->bigendSig == HIGH)
336     return (memory[0] << 24) | (memory[1] << 16)
337       | (memory[2] << 8) | (memory[3] << 0);
338   else
339     return (memory[3] << 24) | (memory[2] << 16)
340       | (memory[1] << 8) | (memory[0] << 0);
341 }
342
343 static void
344 tomem (state, memory, val)
345      struct ARMul_State *state;
346      unsigned char *memory;
347      int val;
348 {
349   if (state->bigendSig == HIGH)
350     {
351       memory[0] = val >> 24;
352       memory[1] = val >> 16;
353       memory[2] = val >> 8;
354       memory[3] = val >> 0;
355     }
356   else
357     {
358       memory[3] = val >> 24;
359       memory[2] = val >> 16;
360       memory[1] = val >> 8;
361       memory[0] = val >> 0;
362     }
363 }
364
365 int
366 sim_store_register (sd, rn, memory, length)
367      SIM_DESC sd ATTRIBUTE_UNUSED;
368      int rn;
369      unsigned char *memory;
370      int length ATTRIBUTE_UNUSED;
371 {
372   init ();
373
374   if (rn == 25)
375     {
376       state->Cpsr = frommem (state, memory);
377       ARMul_CPSRAltered (state);             
378     }
379   else
380     ARMul_SetReg (state, state->Mode, rn, frommem (state, memory));
381   return -1;
382 }
383
384 int
385 sim_fetch_register (sd, rn, memory, length)
386      SIM_DESC sd ATTRIBUTE_UNUSED;
387      int rn;
388      unsigned char *memory;
389      int length ATTRIBUTE_UNUSED;
390 {
391   ARMword regval;
392
393   init ();
394
395   if (rn < 16)
396     regval = ARMul_GetReg (state, state->Mode, rn);
397   else if (rn == 25)
398     /* FIXME: use PS_REGNUM from gdb/config/arm/tm-arm.h.  */
399     regval = ARMul_GetCPSR (state);
400   else
401     /* FIXME: should report an error.  */
402     regval = 0;
403
404   while (length)
405     {
406       tomem (state, memory, regval);
407
408       length -= 4;
409       memory += 4;
410       regval = 0;
411     }  
412
413   return -1;
414 }
415
416 SIM_DESC
417 sim_open (kind, ptr, abfd, argv)
418      SIM_OPEN_KIND kind;
419      host_callback *ptr;
420      struct _bfd *abfd;
421      char **argv;
422 {
423   sim_kind = kind;
424   if (myname) free (myname);
425   myname = (char *) xstrdup (argv[0]);
426   sim_callback = ptr;
427
428   /* Decide upon the endian-ness of the processor.
429      If we can, get the information from the bfd itself.
430      Otherwise look to see if we have been given a command
431      line switch that tells us.  Otherwise default to little endian.  */
432   if (abfd != NULL)
433     big_endian = bfd_big_endian (abfd);
434   else if (argv[1] != NULL)
435     {
436       int i;
437
438       /* Scan for endian-ness switch.  */
439       for (i = 0; (argv[i] != NULL) && (argv[i][0] != 0); i++)
440         if (argv[i][0] == '-' && argv[i][1] == 'E')
441           {
442             char c;
443
444             if ((c = argv[i][2]) == 0)
445               {
446                 ++i;
447                 c = argv[i][0];
448               }
449
450             switch (c)
451               {
452               case 0:
453                 sim_callback->printf_filtered
454                   (sim_callback, "No argument to -E option provided\n");
455                 break;
456
457               case 'b':
458               case 'B':
459                 big_endian = 1;
460                 break;
461
462               case 'l':
463               case 'L':
464                 big_endian = 0;
465                 break;
466
467               default:
468                 sim_callback->printf_filtered
469                   (sim_callback, "Unrecognised argument to -E option\n");
470                 break;
471               }
472           }
473     }
474
475   return (SIM_DESC) 1;
476 }
477
478 void
479 sim_close (sd, quitting)
480      SIM_DESC sd ATTRIBUTE_UNUSED;
481      int quitting ATTRIBUTE_UNUSED;
482 {
483   if (myname)
484     free (myname);
485   myname = NULL;
486 }
487
488 SIM_RC
489 sim_load (sd, prog, abfd, from_tty)
490      SIM_DESC sd;
491      char *prog;
492      bfd *abfd;
493      int from_tty ATTRIBUTE_UNUSED;
494 {
495   bfd *prog_bfd;
496
497   prog_bfd = sim_load_file (sd, myname, sim_callback, prog, abfd,
498                             sim_kind == SIM_OPEN_DEBUG, 0, sim_write);
499   if (prog_bfd == NULL)
500     return SIM_RC_FAIL;
501   ARMul_SetPC (state, bfd_get_start_address (prog_bfd));
502   if (abfd == NULL)
503     bfd_close (prog_bfd);
504   return SIM_RC_OK;
505 }
506
507 void
508 sim_stop_reason (sd, reason, sigrc)
509      SIM_DESC sd ATTRIBUTE_UNUSED;
510      enum sim_stop *reason;
511      int *sigrc;
512 {
513   if (stop_simulator)
514     {
515       *reason = sim_stopped;
516       *sigrc = SIGINT;
517     }
518   else if (state->EndCondition == 0)
519     {
520       *reason = sim_exited;
521       *sigrc = state->Reg[0] & 255;
522     }
523   else
524     {
525       *reason = sim_stopped;
526       if (state->EndCondition == RDIError_BreakpointReached)
527         *sigrc = SIGTRAP;
528       else
529         *sigrc = 0;
530     }
531 }
532
533 void
534 sim_do_command (sd, cmd)
535      SIM_DESC sd ATTRIBUTE_UNUSED;
536      char *cmd ATTRIBUTE_UNUSED;
537 {  
538   (*sim_callback->printf_filtered)
539     (sim_callback,
540      "This simulator does not accept any commands.\n");
541 }
542
543 void
544 sim_set_callbacks (ptr)
545      host_callback *ptr;
546 {
547   sim_callback = ptr;
548 }