* configure.in: Use common simulator always. Don't subst sim_gen
[external/binutils.git] / sim / mn10300 / interp.c
1 #include <signal.h>
2
3 #include "sim-main.h"
4 #include "sim-options.h"
5 #include "sim-hw.h"
6
7 #include "sysdep.h"
8 #include "bfd.h"
9 #include "sim-assert.h"
10
11
12 #ifdef HAVE_STDLIB_H
13 #include <stdlib.h>
14 #endif
15
16 #ifdef HAVE_STRING_H
17 #include <string.h>
18 #else
19 #ifdef HAVE_STRINGS_H
20 #include <strings.h>
21 #endif
22 #endif
23
24 #include "bfd.h"
25
26 #ifndef INLINE
27 #ifdef __GNUC__
28 #define INLINE inline
29 #else
30 #define INLINE
31 #endif
32 #endif
33
34
35 host_callback *mn10300_callback;
36 int mn10300_debug;
37 struct _state State;
38
39
40 /* simulation target board.  NULL=default configuration */
41 static char* board = NULL;
42
43 static DECLARE_OPTION_HANDLER (mn10300_option_handler);
44
45 enum {
46   OPTION_BOARD = OPTION_START,
47 };
48
49 static SIM_RC
50 mn10300_option_handler (sd, cpu, opt, arg, is_command)
51      SIM_DESC sd;
52      sim_cpu *cpu;
53      int opt;
54      char *arg;
55      int is_command;
56 {
57   int cpu_nr;
58   switch (opt)
59     {
60     case OPTION_BOARD:
61       {
62         if (arg)
63           {
64             board = zalloc(strlen(arg) + 1);
65             strcpy(board, arg);
66           }
67         return SIM_RC_OK;
68       }
69     }
70   
71   return SIM_RC_OK;
72 }
73
74 static const OPTION mn10300_options[] = 
75 {
76 #define BOARD_AM32 "stdeval1"
77   { {"board", required_argument, NULL, OPTION_BOARD},
78      '\0', "none" /* rely on compile-time string concatenation for other options */
79            "|" BOARD_AM32
80     , "Customize simulation for a particular board.", mn10300_option_handler },
81
82   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
83 };
84
85 /* For compatibility */
86 SIM_DESC simulator;
87
88 /* These default values correspond to expected usage for the chip.  */
89
90 SIM_DESC
91 sim_open (kind, cb, abfd, argv)
92      SIM_OPEN_KIND kind;
93      host_callback *cb;
94      struct bfd *abfd;
95      char **argv;
96 {
97   SIM_DESC sd = sim_state_alloc (kind, cb);
98   mn10300_callback = cb;
99
100   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
101
102   /* for compatibility */
103   simulator = sd;
104
105   /* FIXME: should be better way of setting up interrupts.  For
106      moment, only support watchpoints causing a breakpoint (gdb
107      halt). */
108   STATE_WATCHPOINTS (sd)->pc = &(PC);
109   STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
110   STATE_WATCHPOINTS (sd)->interrupt_handler = NULL;
111   STATE_WATCHPOINTS (sd)->interrupt_names = NULL;
112
113   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
114     return 0;
115   sim_add_option_table (sd, NULL, mn10300_options);
116
117   /* Allocate core managed memory */
118   sim_do_command (sd, "memory region 0,0x100000");
119   sim_do_command (sd, "memory region 0x40000000,0x200000");
120
121   /* getopt will print the error message so we just have to exit if this fails.
122      FIXME: Hmmm...  in the case of gdb we need getopt to call
123      print_filtered.  */
124   if (sim_parse_args (sd, argv) != SIM_RC_OK)
125     {
126       /* Uninstall the modules to avoid memory leaks,
127          file descriptor leaks, etc.  */
128       sim_module_uninstall (sd);
129       return 0;
130     }
131
132   if ( NULL != board
133        && (strcmp(board, BOARD_AM32) == 0 ) )
134     {
135       /* environment */
136       STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
137
138       sim_do_command (sd, "memory region 0x44000000,0x40000");
139       sim_do_command (sd, "memory region 0x48000000,0x400000");
140
141       /* device support for mn1030002 */
142       /* interrupt controller */
143
144       sim_hw_parse (sd, "/mn103int@0x34000100/reg 0x34000100 0x7C 0x34000200 0x8 0x34000280 0x8");
145
146       /* DEBUG: NMI input's */
147       sim_hw_parse (sd, "/glue@0x30000000/reg 0x30000000 12");
148       sim_hw_parse (sd, "/glue@0x30000000 > int0 nmirq /mn103int");
149       sim_hw_parse (sd, "/glue@0x30000000 > int1 watchdog /mn103int");
150       sim_hw_parse (sd, "/glue@0x30000000 > int2 syserr /mn103int");
151       
152       /* DEBUG: ACK input */
153       sim_hw_parse (sd, "/glue@0x30002000/reg 0x30002000 4");
154       sim_hw_parse (sd, "/glue@0x30002000 > int ack /mn103int");
155       
156       /* DEBUG: LEVEL output */
157       sim_hw_parse (sd, "/glue@0x30004000/reg 0x30004000 8");
158       sim_hw_parse (sd, "/mn103int > nmi int0 /glue@0x30004000");
159       sim_hw_parse (sd, "/mn103int > level int1 /glue@0x30004000");
160       
161       /* DEBUG: A bunch of interrupt inputs */
162       sim_hw_parse (sd, "/glue@0x30006000/reg 0x30006000 32");
163       sim_hw_parse (sd, "/glue@0x30006000 > int0 irq-0 /mn103int");
164       sim_hw_parse (sd, "/glue@0x30006000 > int1 irq-1 /mn103int");
165       sim_hw_parse (sd, "/glue@0x30006000 > int2 irq-2 /mn103int");
166       sim_hw_parse (sd, "/glue@0x30006000 > int3 irq-3 /mn103int");
167       sim_hw_parse (sd, "/glue@0x30006000 > int4 irq-4 /mn103int");
168       sim_hw_parse (sd, "/glue@0x30006000 > int5 irq-5 /mn103int");
169       sim_hw_parse (sd, "/glue@0x30006000 > int6 irq-6 /mn103int");
170       sim_hw_parse (sd, "/glue@0x30006000 > int7 irq-7 /mn103int");
171       
172       /* processor interrupt device */
173       
174       /* the device */
175       sim_hw_parse (sd, "/mn103cpu@0x20000000");
176       sim_hw_parse (sd, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
177       
178       /* DEBUG: ACK output wired upto a glue device */
179       sim_hw_parse (sd, "/glue@0x20002000");
180       sim_hw_parse (sd, "/glue@0x20002000/reg 0x20002000 4");
181       sim_hw_parse (sd, "/mn103cpu > ack int0 /glue@0x20002000");
182       
183       /* DEBUG: RESET/NMI/LEVEL wired up to a glue device */
184       sim_hw_parse (sd, "/glue@0x20004000");
185       sim_hw_parse (sd, "/glue@0x20004000/reg 0x20004000 12");
186       sim_hw_parse (sd, "/glue@0x20004000 > int0 reset /mn103cpu");
187       sim_hw_parse (sd, "/glue@0x20004000 > int1 nmi /mn103cpu");
188       sim_hw_parse (sd, "/glue@0x20004000 > int2 level /mn103cpu");
189       
190       /* REAL: The processor wired up to the real interrupt controller */
191       sim_hw_parse (sd, "/mn103cpu > ack ack /mn103int");
192       sim_hw_parse (sd, "/mn103int > level level /mn103cpu");
193       sim_hw_parse (sd, "/mn103int > nmi nmi /mn103cpu");
194       
195       
196       /* PAL */
197       
198       /* the device */
199       sim_hw_parse (sd, "/pal@0x31000000");
200       sim_hw_parse (sd, "/pal@0x31000000/reg 0x31000000 64");
201       sim_hw_parse (sd, "/pal@0x31000000/poll? true");
202       
203       /* DEBUG: PAL wired up to a glue device */
204       sim_hw_parse (sd, "/glue@0x31002000");
205       sim_hw_parse (sd, "/glue@0x31002000/reg 0x31002000 16");
206       sim_hw_parse (sd, "/pal@0x31000000 > countdown int0 /glue@0x31002000");
207       sim_hw_parse (sd, "/pal@0x31000000 > timer int1 /glue@0x31002000");
208       sim_hw_parse (sd, "/pal@0x31000000 > int int2 /glue@0x31002000");
209       sim_hw_parse (sd, "/glue@0x31002000 > int0 int3 /glue@0x31002000");
210       sim_hw_parse (sd, "/glue@0x31002000 > int1 int3 /glue@0x31002000");
211       sim_hw_parse (sd, "/glue@0x31002000 > int2 int3 /glue@0x31002000");
212       
213       /* REAL: The PAL wired up to the real interrupt controller */
214       sim_hw_parse (sd, "/pal@0x31000000 > countdown irq-0 /mn103int");
215       sim_hw_parse (sd, "/pal@0x31000000 > timer irq-1 /mn103int");
216       sim_hw_parse (sd, "/pal@0x31000000 > int irq-2 /mn103int");
217       
218       /* 8 and 16 bit timers */
219       sim_hw_parse (sd, "/mn103tim@0x34001000/reg 0x34001000 36 0x34001080 100 0x34004000 16");
220
221       /* Hook timer interrupts up to interrupt controller */
222       sim_hw_parse (sd, "/mn103tim > timer-0-underflow timer-0-underflow /mn103int");
223       sim_hw_parse (sd, "/mn103tim > timer-1-underflow timer-1-underflow /mn103int");
224       sim_hw_parse (sd, "/mn103tim > timer-2-underflow timer-2-underflow /mn103int");
225       sim_hw_parse (sd, "/mn103tim > timer-3-underflow timer-3-underflow /mn103int");
226       sim_hw_parse (sd, "/mn103tim > timer-4-underflow timer-4-underflow /mn103int");
227       sim_hw_parse (sd, "/mn103tim > timer-5-underflow timer-5-underflow /mn103int");
228       sim_hw_parse (sd, "/mn103tim > timer-6-underflow timer-6-underflow /mn103int");
229       sim_hw_parse (sd, "/mn103tim > timer-6-compare-a timer-6-compare-a /mn103int");
230       sim_hw_parse (sd, "/mn103tim > timer-6-compare-b timer-6-compare-b /mn103int");
231       
232       
233       /* Serial devices 0,1,2 */
234       sim_hw_parse (sd, "/mn103ser@0x34000800/reg 0x34000800 48");
235       sim_hw_parse (sd, "/mn103ser@0x34000800/poll? true");
236       
237       /* Hook serial interrupts up to interrupt controller */
238       sim_hw_parse (sd, "/mn103ser > serial-0-receive serial-0-receive /mn103int");
239       sim_hw_parse (sd, "/mn103ser > serial-0-transmit serial-0-transmit /mn103int");
240       sim_hw_parse (sd, "/mn103ser > serial-1-receive serial-1-receive /mn103int");
241       sim_hw_parse (sd, "/mn103ser > serial-1-transmit serial-1-transmit /mn103int");
242       sim_hw_parse (sd, "/mn103ser > serial-2-receive serial-2-receive /mn103int");
243       sim_hw_parse (sd, "/mn103ser > serial-2-transmit serial-2-transmit /mn103int");
244       
245       sim_hw_parse (sd, "/mn103iop@0x36008000/reg 0x36008000 8 0x36008020 8 0x36008040 0xc 0x36008060 8 0x36008080 8");
246
247       /* Memory control registers */
248       sim_do_command (sd, "memory region 0x32000020,0x30");
249       /* Cache control register */
250       sim_do_command (sd, "memory region 0x20000070,0x4");
251       /* Cache purge regions */
252       sim_do_command (sd, "memory region 0x28400000,0x800");
253       sim_do_command (sd, "memory region 0x28401000,0x800");
254       /* DMA registers */
255       sim_do_command (sd, "memory region 0x32000100,0xF");
256       sim_do_command (sd, "memory region 0x32000200,0xF");
257       sim_do_command (sd, "memory region 0x32000400,0xF");
258       sim_do_command (sd, "memory region 0x32000800,0xF");
259     }
260   else
261     {
262       if (board != NULL)
263         {
264           sim_io_eprintf (sd, "Error: Board `%s' unknown.\n", board);
265           return 0;
266         }
267     }
268   
269   
270
271   /* check for/establish the a reference program image */
272   if (sim_analyze_program (sd,
273                            (STATE_PROG_ARGV (sd) != NULL
274                             ? *STATE_PROG_ARGV (sd)
275                             : NULL),
276                            abfd) != SIM_RC_OK)
277     {
278       sim_module_uninstall (sd);
279       return 0;
280     }
281
282   /* establish any remaining configuration options */
283   if (sim_config (sd) != SIM_RC_OK)
284     {
285       sim_module_uninstall (sd);
286       return 0;
287     }
288
289   if (sim_post_argv_init (sd) != SIM_RC_OK)
290     {
291       /* Uninstall the modules to avoid memory leaks,
292          file descriptor leaks, etc.  */
293       sim_module_uninstall (sd);
294       return 0;
295     }
296
297
298   /* set machine specific configuration */
299 /*   STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */
300 /*                           | PSW_CY | PSW_OV | PSW_S | PSW_Z); */
301
302   return sd;
303 }
304
305
306 void
307 sim_close (sd, quitting)
308      SIM_DESC sd;
309      int quitting;
310 {
311   sim_module_uninstall (sd);
312 }
313
314
315 SIM_RC
316 sim_create_inferior (sd, prog_bfd, argv, env)
317      SIM_DESC sd;
318      struct bfd *prog_bfd;
319      char **argv;
320      char **env;
321 {
322   memset (&State, 0, sizeof (State));
323   if (prog_bfd != NULL) {
324     PC = bfd_get_start_address (prog_bfd);
325   } else {
326     PC = 0;
327   }
328   CIA_SET (STATE_CPU (sd, 0), (unsigned64) PC);
329
330   return SIM_RC_OK;
331 }
332
333 void
334 sim_do_command (sd, cmd)
335      SIM_DESC sd;
336      char *cmd;
337 {
338   char *mm_cmd = "memory-map";
339   char *int_cmd = "interrupt";
340
341   if (sim_args_command (sd, cmd) != SIM_RC_OK)
342     {
343       if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
344         sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n");
345       else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
346         sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
347       else
348         sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
349     }
350 }
351
352 /* FIXME These would more efficient to use than load_mem/store_mem,
353    but need to be changed to use the memory map.  */
354
355 uint8
356 get_byte (x)
357      uint8 *x;
358 {
359   return *x;
360 }
361
362 uint16
363 get_half (x)
364      uint8 *x;
365 {
366   uint8 *a = x;
367   return (a[1] << 8) + (a[0]);
368 }
369
370 uint32
371 get_word (x)
372       uint8 *x;
373 {
374   uint8 *a = x;
375   return (a[3]<<24) + (a[2]<<16) + (a[1]<<8) + (a[0]);
376 }
377
378 void
379 put_byte (addr, data)
380      uint8 *addr;
381      uint8 data;
382 {
383   uint8 *a = addr;
384   a[0] = data;
385 }
386
387 void
388 put_half (addr, data)
389      uint8 *addr;
390      uint16 data;
391 {
392   uint8 *a = addr;
393   a[0] = data & 0xff;
394   a[1] = (data >> 8) & 0xff;
395 }
396
397 void
398 put_word (addr, data)
399      uint8 *addr;
400      uint32 data;
401 {
402   uint8 *a = addr;
403   a[0] = data & 0xff;
404   a[1] = (data >> 8) & 0xff;
405   a[2] = (data >> 16) & 0xff;
406   a[3] = (data >> 24) & 0xff;
407 }
408
409 int
410 sim_fetch_register (sd, rn, memory, length)
411      SIM_DESC sd;
412      int rn;
413      unsigned char *memory;
414      int length;
415 {
416   put_word (memory, State.regs[rn]);
417   return -1;
418 }
419  
420 int
421 sim_store_register (sd, rn, memory, length)
422      SIM_DESC sd;
423      int rn;
424      unsigned char *memory;
425      int length;
426 {
427   State.regs[rn] = get_word (memory);
428   return -1;
429 }
430
431
432 void
433 mn10300_core_signal (SIM_DESC sd,
434                  sim_cpu *cpu,
435                  sim_cia cia,
436                  unsigned map,
437                  int nr_bytes,
438                  address_word addr,
439                  transfer_type transfer,
440                  sim_core_signals sig)
441 {
442   const char *copy = (transfer == read_transfer ? "read" : "write");
443   address_word ip = CIA_ADDR (cia);
444
445   switch (sig)
446     {
447     case sim_core_unmapped_signal:
448       sim_io_eprintf (sd, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
449                       nr_bytes, copy, 
450                       (unsigned long) addr, (unsigned long) ip);
451       program_interrupt(sd, cpu, cia, SIM_SIGSEGV);
452       break;
453
454     case sim_core_unaligned_signal:
455       sim_io_eprintf (sd, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
456                       nr_bytes, copy, 
457                       (unsigned long) addr, (unsigned long) ip);
458       program_interrupt(sd, cpu, cia, SIM_SIGBUS);
459       break;
460
461     default:
462       sim_engine_abort (sd, cpu, cia,
463                         "mn10300_core_signal - internal error - bad switch");
464     }
465 }
466
467
468 void
469 program_interrupt (SIM_DESC sd,
470                    sim_cpu *cpu,
471                    sim_cia cia,
472                    SIM_SIGNAL sig)
473 {
474   int status;
475   struct hw *device;
476   static int in_interrupt = 0;
477
478 #ifdef SIM_CPU_EXCEPTION_TRIGGER
479   SIM_CPU_EXCEPTION_TRIGGER(sd,cpu,cia);
480 #endif
481
482   /* avoid infinite recursion */
483   if (in_interrupt)
484     {
485       (*mn10300_callback->printf_filtered) (mn10300_callback, 
486                                             "ERROR: recursion in program_interrupt during software exception dispatch.");
487     }
488   else
489     {
490       in_interrupt = 1;
491       /* copy NMI handler code from dv-mn103cpu.c */
492       store_word (SP - 4, CIA_GET (cpu));
493       store_half (SP - 8, PSW);
494
495       /* Set the SYSEF flag in NMICR by backdoor method.  See
496          dv-mn103int.c:write_icr().  This is necessary because
497          software exceptions are not modelled by actually talking to
498          the interrupt controller, so it cannot set its own SYSEF
499          flag. */
500      if ((NULL != board) && (strcmp(board, BOARD_AM32) == 0))
501        store_byte (0x34000103, 0x04);
502     }
503
504   PSW &= ~PSW_IE;
505   SP = SP - 8;
506   CIA_SET (cpu, 0x40000008);
507
508   in_interrupt = 0;
509   sim_engine_halt(sd, cpu, NULL, cia, sim_stopped, sig);
510 }
511
512
513 void
514 mn10300_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word cia)
515 {
516   ASSERT(cpu != NULL);
517
518   if(State.exc_suspended > 0)
519     sim_io_eprintf(sd, "Warning, nested exception triggered (%d)\n", State.exc_suspended); 
520
521   CIA_SET (cpu, cia);
522   memcpy(State.exc_trigger_regs, State.regs, sizeof(State.exc_trigger_regs));
523   State.exc_suspended = 0;
524 }
525
526 void
527 mn10300_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception)
528 {
529   ASSERT(cpu != NULL);
530
531   if(State.exc_suspended > 0)
532     sim_io_eprintf(sd, "Warning, nested exception signal (%d then %d)\n", 
533                    State.exc_suspended, exception); 
534
535   memcpy(State.exc_suspend_regs, State.regs, sizeof(State.exc_suspend_regs));
536   memcpy(State.regs, State.exc_trigger_regs, sizeof(State.regs));
537   CIA_SET (cpu, PC); /* copy PC back from new State.regs */
538   State.exc_suspended = exception;
539 }
540
541 void
542 mn10300_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception)
543 {
544   ASSERT(cpu != NULL);
545
546   if(exception == 0 && State.exc_suspended > 0)
547     {
548       if(State.exc_suspended != SIGTRAP) /* warn not for breakpoints */
549          sim_io_eprintf(sd, "Warning, resuming but ignoring pending exception signal (%d)\n",
550                        State.exc_suspended); 
551     }
552   else if(exception != 0 && State.exc_suspended > 0)
553     {
554       if(exception != State.exc_suspended) 
555         sim_io_eprintf(sd, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
556                        State.exc_suspended, exception); 
557       
558       memcpy(State.regs, State.exc_suspend_regs, sizeof(State.regs)); 
559       CIA_SET (cpu, PC); /* copy PC back from new State.regs */
560     }
561   else if(exception != 0 && State.exc_suspended == 0)
562     {
563       sim_io_eprintf(sd, "Warning, ignoring spontanous exception signal (%d)\n", exception); 
564     }
565   State.exc_suspended = 0; 
566 }