Add support for target specific command line switches to old-style simualtors.
[deliverable/binutils-gdb.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 #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; please update sim_create_inferior.\n");
227 /* fall through */
228
229 case 0:
230 /* We wouldn't set the machine type with earlier toolchains, so we
231 explicitly select a processor capable of supporting all ARMs in
232 32bit mode. */
233 case bfd_mach_arm_XScale:
234 ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
235 break;
236
237 case bfd_mach_arm_5:
238 if (bfd_family_coff (abfd))
239 {
240 /* This is a special case in order to support COFF based ARM toolchains.
241 The COFF header does not have enough room to store all the different
242 kinds of ARM cpu, so the XScale, v5T and v5TE architectures all default
243 to v5. (See coff_set_flags() in bdf/coffcode.h). So if we see a v5
244 machine type here, we assume it could be any of the above architectures
245 and so select the most feature-full. */
246 ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
247 break;
248 }
249 /* Otherwise drop through. */
250
251 case bfd_mach_arm_5T:
252 ARMul_SelectProcessor (state, ARM_v5_Prop);
253 break;
254
255 case bfd_mach_arm_5TE:
256 ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop);
257 break;
258
259 case bfd_mach_arm_4:
260 case bfd_mach_arm_4T:
261 ARMul_SelectProcessor (state, ARM_v4_Prop);
262 break;
263
264 case bfd_mach_arm_3:
265 case bfd_mach_arm_3M:
266 ARMul_SelectProcessor (state, ARM_Lock_Prop);
267 break;
268
269 case bfd_mach_arm_2:
270 case bfd_mach_arm_2a:
271 ARMul_SelectProcessor (state, ARM_Fix26_Prop);
272 break;
273 }
274
275 if ( mach != bfd_mach_arm_3
276 && mach != bfd_mach_arm_3M
277 && mach != bfd_mach_arm_2
278 && mach != bfd_mach_arm_2a)
279 {
280 /* Reset mode to ARM. A gdb user may rerun a program that had entered
281 THUMB mode from the start and cause the ARM-mode startup code to be
282 executed in THUMB mode. */
283 ARMul_SetCPSR (state, SVC32MODE);
284 }
285
286 if (argv != NULL)
287 {
288 /* Set up the command line by laboriously stringing together
289 the environment carefully picked apart by our caller. */
290
291 /* Free any old stuff. */
292 if (state->CommandLine != NULL)
293 {
294 free (state->CommandLine);
295 state->CommandLine = NULL;
296 }
297
298 /* See how much we need. */
299 for (arg = argv; *arg != NULL; arg++)
300 argvlen += strlen (*arg) + 1;
301
302 /* Allocate it. */
303 state->CommandLine = malloc (argvlen + 1);
304 if (state->CommandLine != NULL)
305 {
306 arg = argv;
307 state->CommandLine[0] = '\0';
308
309 for (arg = argv; *arg != NULL; arg++)
310 {
311 strcat (state->CommandLine, *arg);
312 strcat (state->CommandLine, " ");
313 }
314 }
315 }
316
317 if (env != NULL)
318 {
319 /* Now see if there's a MEMSIZE spec in the environment. */
320 while (*env)
321 {
322 if (strncmp (*env, "MEMSIZE=", sizeof ("MEMSIZE=") - 1) == 0)
323 {
324 char *end_of_num;
325
326 /* Set up memory limit. */
327 state->MemSize =
328 strtoul (*env + sizeof ("MEMSIZE=") - 1, &end_of_num, 0);
329 }
330 env++;
331 }
332 }
333
334 return SIM_RC_OK;
335 }
336
337 void
338 sim_info (sd, verbose)
339 SIM_DESC sd ATTRIBUTE_UNUSED;
340 int verbose ATTRIBUTE_UNUSED;
341 {
342 }
343
344 static int
345 frommem (state, memory)
346 struct ARMul_State *state;
347 unsigned char *memory;
348 {
349 if (state->bigendSig == HIGH)
350 return (memory[0] << 24) | (memory[1] << 16)
351 | (memory[2] << 8) | (memory[3] << 0);
352 else
353 return (memory[3] << 24) | (memory[2] << 16)
354 | (memory[1] << 8) | (memory[0] << 0);
355 }
356
357 static void
358 tomem (state, memory, val)
359 struct ARMul_State *state;
360 unsigned char *memory;
361 int val;
362 {
363 if (state->bigendSig == HIGH)
364 {
365 memory[0] = val >> 24;
366 memory[1] = val >> 16;
367 memory[2] = val >> 8;
368 memory[3] = val >> 0;
369 }
370 else
371 {
372 memory[3] = val >> 24;
373 memory[2] = val >> 16;
374 memory[1] = val >> 8;
375 memory[0] = val >> 0;
376 }
377 }
378
379 int
380 sim_store_register (sd, rn, memory, length)
381 SIM_DESC sd ATTRIBUTE_UNUSED;
382 int rn;
383 unsigned char *memory;
384 int length ATTRIBUTE_UNUSED;
385 {
386 init ();
387
388 if (rn == 25)
389 {
390 state->Cpsr = frommem (state, memory);
391 ARMul_CPSRAltered (state);
392 }
393 else
394 ARMul_SetReg (state, state->Mode, rn, frommem (state, memory));
395 return -1;
396 }
397
398 int
399 sim_fetch_register (sd, rn, memory, length)
400 SIM_DESC sd ATTRIBUTE_UNUSED;
401 int rn;
402 unsigned char *memory;
403 int length ATTRIBUTE_UNUSED;
404 {
405 ARMword regval;
406
407 init ();
408
409 if (rn < 16)
410 regval = ARMul_GetReg (state, state->Mode, rn);
411 else if (rn == 25)
412 /* FIXME: use PS_REGNUM from gdb/config/arm/tm-arm.h. */
413 regval = ARMul_GetCPSR (state);
414 else
415 /* FIXME: should report an error. */
416 regval = 0;
417
418 while (length)
419 {
420 tomem (state, memory, regval);
421
422 length -= 4;
423 memory += 4;
424 regval = 0;
425 }
426
427 return -1;
428 }
429
430 #ifdef SIM_TARGET_SWITCHES
431
432 static void sim_target_parse_arg_array PARAMS ((char **));
433
434 typedef struct
435 {
436 char * swi_option;
437 unsigned int swi_mask;
438 } swi_options;
439
440 #define SWI_SWITCH "--swi-support"
441
442 static swi_options options[] =
443 {
444 { "none", 0 },
445 { "demon", SWI_MASK_DEMON },
446 { "angel", SWI_MASK_ANGEL },
447 { "redboot", SWI_MASK_REDBOOT },
448 { "all", -1 },
449 { "NONE", 0 },
450 { "DEMON", SWI_MASK_DEMON },
451 { "ANGEL", SWI_MASK_ANGEL },
452 { "REDBOOT", SWI_MASK_REDBOOT },
453 { "ALL", -1 }
454 };
455
456
457 int
458 sim_target_parse_command_line (argc, argv)
459 int argc;
460 char ** argv;
461 {
462 int i;
463
464 for (i = 1; i < argc; i++)
465 {
466 char * ptr = argv[i];
467 int arg;
468
469 if ((ptr == NULL) || (* ptr != '-'))
470 break;
471
472 if (strncmp (ptr, SWI_SWITCH, sizeof SWI_SWITCH - 1) != 0)
473 continue;
474
475 if (ptr[sizeof SWI_SWITCH - 1] == 0)
476 {
477 /* Remove this option from the argv array. */
478 for (arg = i; arg < argc; arg ++)
479 argv[arg] = argv[arg + 1];
480 argc --;
481
482 ptr = argv[i];
483 }
484 else
485 ptr += sizeof SWI_SWITCH;
486
487 swi_mask = 0;
488
489 while (* ptr)
490 {
491 int i;
492
493 for (i = sizeof options / sizeof options[0]; i--;)
494 if (strncmp (ptr, options[i].swi_option,
495 strlen (options[i].swi_option)) == 0)
496 {
497 swi_mask |= options[i].swi_mask;
498 ptr += strlen (options[i].swi_option);
499
500 if (* ptr == ',')
501 ++ ptr;
502
503 break;
504 }
505
506 if (i < 0)
507 break;
508 }
509
510 if (* ptr != 0)
511 fprintf (stderr, "Ignoring swi options: %s\n", ptr);
512
513 /* Remove this option from the argv array. */
514 for (arg = i; arg < argc; arg ++)
515 argv[arg] = argv[arg + 1];
516 argc --;
517 i --;
518 }
519 return argc;
520 }
521
522 static void
523 sim_target_parse_arg_array (argv)
524 char ** argv;
525 {
526 int i;
527
528 for (i = 0; argv[i]; i++)
529 ;
530
531 return (void) sim_target_parse_command_line (i, argv);
532 }
533
534 void
535 sim_target_display_usage ()
536 {
537 fprintf (stderr, "%s=<list> Comma seperated list of SWI protocols to supoport.\n\
538 This list can contain: NONE, DEMON, ANGEL, REDBOOT and/or ALL.\n",
539 SWI_SWITCH);
540 }
541 #endif
542
543 SIM_DESC
544 sim_open (kind, ptr, abfd, argv)
545 SIM_OPEN_KIND kind;
546 host_callback *ptr;
547 struct _bfd *abfd;
548 char **argv;
549 {
550 sim_kind = kind;
551 if (myname) free (myname);
552 myname = (char *) xstrdup (argv[0]);
553 sim_callback = ptr;
554
555 #ifdef SIM_TARGET_SWITCHES
556 sim_target_parse_arg_array (argv);
557 #endif
558
559 /* Decide upon the endian-ness of the processor.
560 If we can, get the information from the bfd itself.
561 Otherwise look to see if we have been given a command
562 line switch that tells us. Otherwise default to little endian. */
563 if (abfd != NULL)
564 big_endian = bfd_big_endian (abfd);
565 else if (argv[1] != NULL)
566 {
567 int i;
568
569 /* Scan for endian-ness switch. */
570 for (i = 0; (argv[i] != NULL) && (argv[i][0] != 0); i++)
571 if (argv[i][0] == '-' && argv[i][1] == 'E')
572 {
573 char c;
574
575 if ((c = argv[i][2]) == 0)
576 {
577 ++i;
578 c = argv[i][0];
579 }
580
581 switch (c)
582 {
583 case 0:
584 sim_callback->printf_filtered
585 (sim_callback, "No argument to -E option provided\n");
586 break;
587
588 case 'b':
589 case 'B':
590 big_endian = 1;
591 break;
592
593 case 'l':
594 case 'L':
595 big_endian = 0;
596 break;
597
598 default:
599 sim_callback->printf_filtered
600 (sim_callback, "Unrecognised argument to -E option\n");
601 break;
602 }
603 }
604 }
605
606 return (SIM_DESC) 1;
607 }
608
609 void
610 sim_close (sd, quitting)
611 SIM_DESC sd ATTRIBUTE_UNUSED;
612 int quitting ATTRIBUTE_UNUSED;
613 {
614 if (myname)
615 free (myname);
616 myname = NULL;
617 }
618
619 SIM_RC
620 sim_load (sd, prog, abfd, from_tty)
621 SIM_DESC sd;
622 char *prog;
623 bfd *abfd;
624 int from_tty ATTRIBUTE_UNUSED;
625 {
626 bfd *prog_bfd;
627
628 prog_bfd = sim_load_file (sd, myname, sim_callback, prog, abfd,
629 sim_kind == SIM_OPEN_DEBUG, 0, sim_write);
630 if (prog_bfd == NULL)
631 return SIM_RC_FAIL;
632 ARMul_SetPC (state, bfd_get_start_address (prog_bfd));
633 if (abfd == NULL)
634 bfd_close (prog_bfd);
635 return SIM_RC_OK;
636 }
637
638 void
639 sim_stop_reason (sd, reason, sigrc)
640 SIM_DESC sd ATTRIBUTE_UNUSED;
641 enum sim_stop *reason;
642 int *sigrc;
643 {
644 if (stop_simulator)
645 {
646 *reason = sim_stopped;
647 *sigrc = SIGINT;
648 }
649 else if (state->EndCondition == 0)
650 {
651 *reason = sim_exited;
652 *sigrc = state->Reg[0] & 255;
653 }
654 else
655 {
656 *reason = sim_stopped;
657 if (state->EndCondition == RDIError_BreakpointReached)
658 *sigrc = SIGTRAP;
659 else
660 *sigrc = 0;
661 }
662 }
663
664 void
665 sim_do_command (sd, cmd)
666 SIM_DESC sd ATTRIBUTE_UNUSED;
667 char *cmd ATTRIBUTE_UNUSED;
668 {
669 (*sim_callback->printf_filtered)
670 (sim_callback,
671 "This simulator does not accept any commands.\n");
672 }
673
674 void
675 sim_set_callbacks (ptr)
676 host_callback *ptr;
677 {
678 sim_callback = ptr;
679 }
This page took 0.044054 seconds and 4 git commands to generate.