Add checks to catch invaliud XScale MIA, MIAPH and MIAxy instructions.
[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 #include "gdb/sim-arm.h"
40
41 host_callback *sim_callback;
42
43 static struct ARMul_State *state;
44
45 /* Who is using the simulator. */
46 static SIM_OPEN_KIND sim_kind;
47
48 /* argv[0] */
49 static char *myname;
50
51 /* Memory size in bytes. */
52 static int mem_size = (1 << 23);
53
54 /* Non-zero to display start up banner, and maybe other things. */
55 static int verbosity;
56
57 /* Non-zero to set big endian mode. */
58 static int big_endian;
59
60 int stop_simulator;
61
62 static void
63 init ()
64 {
65 static int done;
66
67 if (!done)
68 {
69 ARMul_EmulateInit ();
70 state = ARMul_NewState ();
71 state->bigendSig = (big_endian ? HIGH : LOW);
72 ARMul_MemoryInit (state, mem_size);
73 ARMul_OSInit (state);
74 ARMul_CoProInit (state);
75 state->verbose = verbosity;
76 done = 1;
77 }
78 }
79
80 /* Set verbosity level of simulator.
81 This is not intended to produce detailed tracing or debugging information.
82 Just summaries. */
83 /* FIXME: common/run.c doesn't do this yet. */
84
85 void
86 sim_set_verbose (v)
87 int v;
88 {
89 verbosity = v;
90 }
91
92 /* Set the memory size to SIZE bytes.
93 Must be called before initializing simulator. */
94 /* FIXME: Rename to sim_set_mem_size. */
95
96 void
97 sim_size (size)
98 int size;
99 {
100 mem_size = size;
101 }
102
103 void
104 ARMul_ConsolePrint VPARAMS ((ARMul_State * state,
105 const char * format,
106 ...))
107 {
108 va_list ap;
109
110 if (state->verbose)
111 {
112 va_start (ap, format);
113 vprintf (format, ap);
114 va_end (ap);
115 }
116 }
117
118 ARMword
119 ARMul_Debug (state, pc, instr)
120 ARMul_State * state ATTRIBUTE_UNUSED;
121 ARMword pc ATTRIBUTE_UNUSED;
122 ARMword instr ATTRIBUTE_UNUSED;
123 {
124 return 0;
125 }
126
127 int
128 sim_write (sd, addr, buffer, size)
129 SIM_DESC sd ATTRIBUTE_UNUSED;
130 SIM_ADDR addr;
131 unsigned char * buffer;
132 int size;
133 {
134 int i;
135
136 init ();
137
138 for (i = 0; i < size; i++)
139 ARMul_SafeWriteByte (state, addr + i, buffer[i]);
140
141 return size;
142 }
143
144 int
145 sim_read (sd, addr, buffer, size)
146 SIM_DESC sd ATTRIBUTE_UNUSED;
147 SIM_ADDR addr;
148 unsigned char * buffer;
149 int size;
150 {
151 int i;
152
153 init ();
154
155 for (i = 0; i < size; i++)
156 buffer[i] = ARMul_SafeReadByte (state, addr + i);
157
158 return size;
159 }
160
161 int
162 sim_trace (sd)
163 SIM_DESC sd ATTRIBUTE_UNUSED;
164 {
165 (*sim_callback->printf_filtered)
166 (sim_callback,
167 "This simulator does not support tracing\n");
168 return 1;
169 }
170
171 int
172 sim_stop (sd)
173 SIM_DESC sd ATTRIBUTE_UNUSED;
174 {
175 state->Emulate = STOP;
176 stop_simulator = 1;
177 return 1;
178 }
179
180 void
181 sim_resume (sd, step, siggnal)
182 SIM_DESC sd ATTRIBUTE_UNUSED;
183 int step;
184 int siggnal ATTRIBUTE_UNUSED;
185 {
186 state->EndCondition = 0;
187 stop_simulator = 0;
188
189 if (step)
190 {
191 state->Reg[15] = ARMul_DoInstr (state);
192 if (state->EndCondition == 0)
193 state->EndCondition = RDIError_BreakpointReached;
194 }
195 else
196 {
197 state->NextInstr = RESUME; /* treat as PC change */
198 state->Reg[15] = ARMul_DoProg (state);
199 }
200
201 FLUSHPIPE;
202 }
203
204 SIM_RC
205 sim_create_inferior (sd, abfd, argv, env)
206 SIM_DESC sd ATTRIBUTE_UNUSED;
207 struct _bfd * abfd;
208 char ** argv;
209 char ** env;
210 {
211 int argvlen = 0;
212 int mach;
213 char **arg;
214
215 if (abfd != NULL)
216 ARMul_SetPC (state, bfd_get_start_address (abfd));
217 else
218 ARMul_SetPC (state, 0); /* ??? */
219
220 mach = bfd_get_mach (abfd);
221
222 switch (mach)
223 {
224 default:
225 (*sim_callback->printf_filtered)
226 (sim_callback,
227 "Unknown machine type '%d'; please update sim_create_inferior.\n",
228 mach);
229 /* fall through */
230
231 case 0:
232 /* We wouldn't set the machine type with earlier toolchains, so we
233 explicitly select a processor capable of supporting all ARMs in
234 32bit mode. */
235 case bfd_mach_arm_XScale:
236 ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
237 break;
238
239 case bfd_mach_arm_5:
240 if (bfd_family_coff (abfd))
241 {
242 /* This is a special case in order to support COFF based ARM toolchains.
243 The COFF header does not have enough room to store all the different
244 kinds of ARM cpu, so the XScale, v5T and v5TE architectures all default
245 to v5. (See coff_set_flags() in bdf/coffcode.h). So if we see a v5
246 machine type here, we assume it could be any of the above architectures
247 and so select the most feature-full. */
248 ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
249 break;
250 }
251 /* Otherwise drop through. */
252
253 case bfd_mach_arm_5T:
254 ARMul_SelectProcessor (state, ARM_v5_Prop);
255 break;
256
257 case bfd_mach_arm_5TE:
258 ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop);
259 break;
260
261 case bfd_mach_arm_4:
262 case bfd_mach_arm_4T:
263 ARMul_SelectProcessor (state, ARM_v4_Prop);
264 break;
265
266 case bfd_mach_arm_3:
267 case bfd_mach_arm_3M:
268 ARMul_SelectProcessor (state, ARM_Lock_Prop);
269 break;
270
271 case bfd_mach_arm_2:
272 case bfd_mach_arm_2a:
273 ARMul_SelectProcessor (state, ARM_Fix26_Prop);
274 break;
275 }
276
277 if ( mach != bfd_mach_arm_3
278 && mach != bfd_mach_arm_3M
279 && mach != bfd_mach_arm_2
280 && mach != bfd_mach_arm_2a)
281 {
282 /* Reset mode to ARM. A gdb user may rerun a program that had entered
283 THUMB mode from the start and cause the ARM-mode startup code to be
284 executed in THUMB mode. */
285 ARMul_SetCPSR (state, SVC32MODE);
286 }
287
288 if (argv != NULL)
289 {
290 /* Set up the command line by laboriously stringing together
291 the environment carefully picked apart by our caller. */
292
293 /* Free any old stuff. */
294 if (state->CommandLine != NULL)
295 {
296 free (state->CommandLine);
297 state->CommandLine = NULL;
298 }
299
300 /* See how much we need. */
301 for (arg = argv; *arg != NULL; arg++)
302 argvlen += strlen (*arg) + 1;
303
304 /* Allocate it. */
305 state->CommandLine = malloc (argvlen + 1);
306 if (state->CommandLine != NULL)
307 {
308 arg = argv;
309 state->CommandLine[0] = '\0';
310
311 for (arg = argv; *arg != NULL; arg++)
312 {
313 strcat (state->CommandLine, *arg);
314 strcat (state->CommandLine, " ");
315 }
316 }
317 }
318
319 if (env != NULL)
320 {
321 /* Now see if there's a MEMSIZE spec in the environment. */
322 while (*env)
323 {
324 if (strncmp (*env, "MEMSIZE=", sizeof ("MEMSIZE=") - 1) == 0)
325 {
326 char *end_of_num;
327
328 /* Set up memory limit. */
329 state->MemSize =
330 strtoul (*env + sizeof ("MEMSIZE=") - 1, &end_of_num, 0);
331 }
332 env++;
333 }
334 }
335
336 return SIM_RC_OK;
337 }
338
339 void
340 sim_info (sd, verbose)
341 SIM_DESC sd ATTRIBUTE_UNUSED;
342 int verbose ATTRIBUTE_UNUSED;
343 {
344 }
345
346 static int
347 frommem (state, memory)
348 struct ARMul_State *state;
349 unsigned char *memory;
350 {
351 if (state->bigendSig == HIGH)
352 return (memory[0] << 24) | (memory[1] << 16)
353 | (memory[2] << 8) | (memory[3] << 0);
354 else
355 return (memory[3] << 24) | (memory[2] << 16)
356 | (memory[1] << 8) | (memory[0] << 0);
357 }
358
359 static void
360 tomem (state, memory, val)
361 struct ARMul_State *state;
362 unsigned char *memory;
363 int val;
364 {
365 if (state->bigendSig == HIGH)
366 {
367 memory[0] = val >> 24;
368 memory[1] = val >> 16;
369 memory[2] = val >> 8;
370 memory[3] = val >> 0;
371 }
372 else
373 {
374 memory[3] = val >> 24;
375 memory[2] = val >> 16;
376 memory[1] = val >> 8;
377 memory[0] = val >> 0;
378 }
379 }
380
381 int
382 sim_store_register (sd, rn, memory, length)
383 SIM_DESC sd ATTRIBUTE_UNUSED;
384 int rn;
385 unsigned char *memory;
386 int length ATTRIBUTE_UNUSED;
387 {
388 init ();
389
390 switch ((enum sim_arm_regs) rn)
391 {
392 case SIM_ARM_R0_REGNUM:
393 case SIM_ARM_R1_REGNUM:
394 case SIM_ARM_R2_REGNUM:
395 case SIM_ARM_R3_REGNUM:
396 case SIM_ARM_R4_REGNUM:
397 case SIM_ARM_R5_REGNUM:
398 case SIM_ARM_R6_REGNUM:
399 case SIM_ARM_R7_REGNUM:
400 case SIM_ARM_R8_REGNUM:
401 case SIM_ARM_R9_REGNUM:
402 case SIM_ARM_R10_REGNUM:
403 case SIM_ARM_R11_REGNUM:
404 case SIM_ARM_R12_REGNUM:
405 case SIM_ARM_R13_REGNUM:
406 case SIM_ARM_R14_REGNUM:
407 case SIM_ARM_R15_REGNUM: /* PC */
408 case SIM_ARM_FP0_REGNUM:
409 case SIM_ARM_FP1_REGNUM:
410 case SIM_ARM_FP2_REGNUM:
411 case SIM_ARM_FP3_REGNUM:
412 case SIM_ARM_FP4_REGNUM:
413 case SIM_ARM_FP5_REGNUM:
414 case SIM_ARM_FP6_REGNUM:
415 case SIM_ARM_FP7_REGNUM:
416 case SIM_ARM_FPS_REGNUM:
417 ARMul_SetReg (state, state->Mode, rn, frommem (state, memory));
418 break;
419
420 case SIM_ARM_PS_REGNUM:
421 state->Cpsr = frommem (state, memory);
422 ARMul_CPSRAltered (state);
423 break;
424
425 default:
426 return 0;
427 }
428
429 return -1;
430 }
431
432 int
433 sim_fetch_register (sd, rn, memory, length)
434 SIM_DESC sd ATTRIBUTE_UNUSED;
435 int rn;
436 unsigned char *memory;
437 int length ATTRIBUTE_UNUSED;
438 {
439 ARMword regval;
440
441 init ();
442
443 switch ((enum sim_arm_regs) rn)
444 {
445 case SIM_ARM_R0_REGNUM:
446 case SIM_ARM_R1_REGNUM:
447 case SIM_ARM_R2_REGNUM:
448 case SIM_ARM_R3_REGNUM:
449 case SIM_ARM_R4_REGNUM:
450 case SIM_ARM_R5_REGNUM:
451 case SIM_ARM_R6_REGNUM:
452 case SIM_ARM_R7_REGNUM:
453 case SIM_ARM_R8_REGNUM:
454 case SIM_ARM_R9_REGNUM:
455 case SIM_ARM_R10_REGNUM:
456 case SIM_ARM_R11_REGNUM:
457 case SIM_ARM_R12_REGNUM:
458 case SIM_ARM_R13_REGNUM:
459 case SIM_ARM_R14_REGNUM:
460 case SIM_ARM_R15_REGNUM: /* PC */
461 regval = ARMul_GetReg (state, state->Mode, rn);
462 break;
463
464 case SIM_ARM_FP0_REGNUM:
465 case SIM_ARM_FP1_REGNUM:
466 case SIM_ARM_FP2_REGNUM:
467 case SIM_ARM_FP3_REGNUM:
468 case SIM_ARM_FP4_REGNUM:
469 case SIM_ARM_FP5_REGNUM:
470 case SIM_ARM_FP6_REGNUM:
471 case SIM_ARM_FP7_REGNUM:
472 case SIM_ARM_FPS_REGNUM:
473 memset (memory, 0, length);
474 return 0;
475
476 case SIM_ARM_PS_REGNUM:
477 regval = ARMul_GetCPSR (state);
478 break;
479
480 default:
481 return 0;
482 }
483
484 while (length)
485 {
486 tomem (state, memory, regval);
487
488 length -= 4;
489 memory += 4;
490 regval = 0;
491 }
492
493 return -1;
494 }
495
496 #ifdef SIM_TARGET_SWITCHES
497
498 static void sim_target_parse_arg_array PARAMS ((char **));
499
500 typedef struct
501 {
502 char * swi_option;
503 unsigned int swi_mask;
504 } swi_options;
505
506 #define SWI_SWITCH "--swi-support"
507
508 static swi_options options[] =
509 {
510 { "none", 0 },
511 { "demon", SWI_MASK_DEMON },
512 { "angel", SWI_MASK_ANGEL },
513 { "redboot", SWI_MASK_REDBOOT },
514 { "all", -1 },
515 { "NONE", 0 },
516 { "DEMON", SWI_MASK_DEMON },
517 { "ANGEL", SWI_MASK_ANGEL },
518 { "REDBOOT", SWI_MASK_REDBOOT },
519 { "ALL", -1 }
520 };
521
522
523 int
524 sim_target_parse_command_line (argc, argv)
525 int argc;
526 char ** argv;
527 {
528 int i;
529
530 for (i = 1; i < argc; i++)
531 {
532 char * ptr = argv[i];
533 int arg;
534
535 if ((ptr == NULL) || (* ptr != '-'))
536 break;
537
538 if (strncmp (ptr, SWI_SWITCH, sizeof SWI_SWITCH - 1) != 0)
539 continue;
540
541 if (ptr[sizeof SWI_SWITCH - 1] == 0)
542 {
543 /* Remove this option from the argv array. */
544 for (arg = i; arg < argc; arg ++)
545 argv[arg] = argv[arg + 1];
546 argc --;
547
548 ptr = argv[i];
549 }
550 else
551 ptr += sizeof SWI_SWITCH;
552
553 swi_mask = 0;
554
555 while (* ptr)
556 {
557 int i;
558
559 for (i = sizeof options / sizeof options[0]; i--;)
560 if (strncmp (ptr, options[i].swi_option,
561 strlen (options[i].swi_option)) == 0)
562 {
563 swi_mask |= options[i].swi_mask;
564 ptr += strlen (options[i].swi_option);
565
566 if (* ptr == ',')
567 ++ ptr;
568
569 break;
570 }
571
572 if (i < 0)
573 break;
574 }
575
576 if (* ptr != 0)
577 fprintf (stderr, "Ignoring swi options: %s\n", ptr);
578
579 /* Remove this option from the argv array. */
580 for (arg = i; arg < argc; arg ++)
581 argv[arg] = argv[arg + 1];
582 argc --;
583 i --;
584 }
585 return argc;
586 }
587
588 static void
589 sim_target_parse_arg_array (argv)
590 char ** argv;
591 {
592 int i;
593
594 for (i = 0; argv[i]; i++)
595 ;
596
597 return (void) sim_target_parse_command_line (i, argv);
598 }
599
600 void
601 sim_target_display_usage ()
602 {
603 fprintf (stderr, "%s=<list> Comma seperated list of SWI protocols to supoport.\n\
604 This list can contain: NONE, DEMON, ANGEL, REDBOOT and/or ALL.\n",
605 SWI_SWITCH);
606 }
607 #endif
608
609 SIM_DESC
610 sim_open (kind, ptr, abfd, argv)
611 SIM_OPEN_KIND kind;
612 host_callback *ptr;
613 struct _bfd *abfd;
614 char **argv;
615 {
616 sim_kind = kind;
617 if (myname) free (myname);
618 myname = (char *) xstrdup (argv[0]);
619 sim_callback = ptr;
620
621 #ifdef SIM_TARGET_SWITCHES
622 sim_target_parse_arg_array (argv);
623 #endif
624
625 /* Decide upon the endian-ness of the processor.
626 If we can, get the information from the bfd itself.
627 Otherwise look to see if we have been given a command
628 line switch that tells us. Otherwise default to little endian. */
629 if (abfd != NULL)
630 big_endian = bfd_big_endian (abfd);
631 else if (argv[1] != NULL)
632 {
633 int i;
634
635 /* Scan for endian-ness switch. */
636 for (i = 0; (argv[i] != NULL) && (argv[i][0] != 0); i++)
637 if (argv[i][0] == '-' && argv[i][1] == 'E')
638 {
639 char c;
640
641 if ((c = argv[i][2]) == 0)
642 {
643 ++i;
644 c = argv[i][0];
645 }
646
647 switch (c)
648 {
649 case 0:
650 sim_callback->printf_filtered
651 (sim_callback, "No argument to -E option provided\n");
652 break;
653
654 case 'b':
655 case 'B':
656 big_endian = 1;
657 break;
658
659 case 'l':
660 case 'L':
661 big_endian = 0;
662 break;
663
664 default:
665 sim_callback->printf_filtered
666 (sim_callback, "Unrecognised argument to -E option\n");
667 break;
668 }
669 }
670 }
671
672 return (SIM_DESC) 1;
673 }
674
675 void
676 sim_close (sd, quitting)
677 SIM_DESC sd ATTRIBUTE_UNUSED;
678 int quitting ATTRIBUTE_UNUSED;
679 {
680 if (myname)
681 free (myname);
682 myname = NULL;
683 }
684
685 SIM_RC
686 sim_load (sd, prog, abfd, from_tty)
687 SIM_DESC sd;
688 char *prog;
689 bfd *abfd;
690 int from_tty ATTRIBUTE_UNUSED;
691 {
692 bfd *prog_bfd;
693
694 prog_bfd = sim_load_file (sd, myname, sim_callback, prog, abfd,
695 sim_kind == SIM_OPEN_DEBUG, 0, sim_write);
696 if (prog_bfd == NULL)
697 return SIM_RC_FAIL;
698 ARMul_SetPC (state, bfd_get_start_address (prog_bfd));
699 if (abfd == NULL)
700 bfd_close (prog_bfd);
701 return SIM_RC_OK;
702 }
703
704 void
705 sim_stop_reason (sd, reason, sigrc)
706 SIM_DESC sd ATTRIBUTE_UNUSED;
707 enum sim_stop *reason;
708 int *sigrc;
709 {
710 if (stop_simulator)
711 {
712 *reason = sim_stopped;
713 *sigrc = SIGINT;
714 }
715 else if (state->EndCondition == 0)
716 {
717 *reason = sim_exited;
718 *sigrc = state->Reg[0] & 255;
719 }
720 else
721 {
722 *reason = sim_stopped;
723 if (state->EndCondition == RDIError_BreakpointReached)
724 *sigrc = SIGTRAP;
725 else
726 *sigrc = 0;
727 }
728 }
729
730 void
731 sim_do_command (sd, cmd)
732 SIM_DESC sd ATTRIBUTE_UNUSED;
733 char *cmd ATTRIBUTE_UNUSED;
734 {
735 (*sim_callback->printf_filtered)
736 (sim_callback,
737 "This simulator does not accept any commands.\n");
738 }
739
740 void
741 sim_set_callbacks (ptr)
742 host_callback *ptr;
743 {
744 sim_callback = ptr;
745 }
This page took 0.045202 seconds and 4 git commands to generate.