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