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