e00c21b4ca39cacd76b0c80b6e86bd45f586f941
[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
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 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 }
This page took 0.060183 seconds and 3 git commands to generate.