* interp.c (sim_hw_configure): Return 1 for success.
[external/binutils.git] / sim / m68hc11 / interp.c
1 /* interp.c -- Simulator for Motorola 68HC11/68HC12
2    Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3    Written by Stephane Carrez (stcarrez@nerim.fr)
4
5 This file is part of GDB, the GNU debugger.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include "sim-main.h"
22 #include "sim-assert.h"
23 #include "sim-hw.h"
24 #include "sim-options.h"
25 #include "hw-tree.h"
26 #include "hw-device.h"
27 #include "hw-ports.h"
28
29 #ifndef MONITOR_BASE
30 # define MONITOR_BASE (0x0C000)
31 # define MONITOR_SIZE (0x04000)
32 #endif
33
34 static void sim_get_info (SIM_DESC sd, char *cmd);
35
36
37 char *interrupt_names[] = {
38   "reset",
39   "nmi",
40   "int",
41   NULL
42 };
43
44 #ifndef INLINE
45 #if defined(__GNUC__) && defined(__OPTIMIZE__)
46 #define INLINE __inline__
47 #else
48 #define INLINE
49 #endif
50 #endif
51
52 struct sim_info_list
53 {
54   const char *name;
55   const char *device;
56 };
57
58 struct sim_info_list dev_list_68hc11[] = {
59   {"cpu", "/m68hc11"},
60   {"timer", "/m68hc11/m68hc11tim"},
61   {"sio", "/m68hc11/m68hc11sio"},
62   {"spi", "/m68hc11/m68hc11spi"},
63   {"eeprom", "/m68hc11/m68hc11eepr"},
64   {0, 0}
65 };
66
67 struct sim_info_list dev_list_68hc12[] = {
68   {"cpu", "/m68hc12"},
69   {"timer", "/m68hc12/m68hc12tim"},
70   {"sio", "/m68hc12/m68hc12sio"},
71   {"spi", "/m68hc12/m68hc12spi"},
72   {"eeprom", "/m68hc12/m68hc12eepr"},
73   {0, 0}
74 };
75
76 /* Cover function of sim_state_free to free the cpu buffers as well.  */
77
78 static void
79 free_state (SIM_DESC sd)
80 {
81   if (STATE_MODULES (sd) != NULL)
82     sim_module_uninstall (sd);
83
84   sim_state_free (sd);
85 }
86
87 /* Give some information about the simulator.  */
88 static void
89 sim_get_info (SIM_DESC sd, char *cmd)
90 {
91   sim_cpu *cpu;
92
93   cpu = STATE_CPU (sd, 0);
94   if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-'))
95     {
96       int i;
97       struct hw *hw_dev;
98       struct sim_info_list *dev_list;
99       const struct bfd_arch_info *arch;
100
101       arch = STATE_ARCHITECTURE (sd);
102       cmd++;
103
104       if (arch->arch == bfd_arch_m68hc11)
105         dev_list = dev_list_68hc11;
106       else
107         dev_list = dev_list_68hc12;
108
109       for (i = 0; dev_list[i].name; i++)
110         if (strcmp (cmd, dev_list[i].name) == 0)
111           break;
112
113       if (dev_list[i].name == 0)
114         {
115           sim_io_eprintf (sd, "Device '%s' not found.\n", cmd);
116           sim_io_eprintf (sd, "Valid devices: cpu timer sio eeprom\n");
117           return;
118         }
119       hw_dev = sim_hw_parse (sd, dev_list[i].device);
120       if (hw_dev == 0)
121         {
122           sim_io_eprintf (sd, "Device '%s' not found\n", dev_list[i].device);
123           return;
124         }
125       hw_ioctl (hw_dev, 23, 0);
126       return;
127     }
128
129   cpu_info (sd, cpu);
130   interrupts_info (sd, &cpu->cpu_interrupts);
131 }
132
133
134 void
135 sim_board_reset (SIM_DESC sd)
136 {
137   struct hw *hw_cpu;
138   sim_cpu *cpu;
139   const struct bfd_arch_info *arch;
140   const char *cpu_type;
141
142   cpu = STATE_CPU (sd, 0);
143   arch = STATE_ARCHITECTURE (sd);
144
145   /*  hw_cpu = sim_hw_parse (sd, "/"); */
146   if (arch->arch == bfd_arch_m68hc11)
147     {
148       cpu->cpu_type = CPU_M6811;
149       cpu_type = "/m68hc11";
150     }
151   else
152     {
153       cpu->cpu_type = CPU_M6812;
154       cpu_type = "/m68hc12";
155     }
156   
157   hw_cpu = sim_hw_parse (sd, cpu_type);
158   if (hw_cpu == 0)
159     {
160       sim_io_eprintf (sd, "%s cpu not found in device tree.", cpu_type);
161       return;
162     }
163
164   cpu_reset (cpu);
165   hw_port_event (hw_cpu, 3, 0);
166   cpu_restart (cpu);
167 }
168
169 static int
170 sim_hw_configure (SIM_DESC sd)
171 {
172   const struct bfd_arch_info *arch;
173   struct hw *device_tree;
174   sim_cpu *cpu;
175   
176   arch = STATE_ARCHITECTURE (sd);
177   if (arch == 0)
178     return 0;
179
180   cpu = STATE_CPU (sd, 0);
181   cpu->cpu_configured_arch = arch;
182   device_tree = sim_hw_parse (sd, "/");
183   if (arch->arch == bfd_arch_m68hc11)
184     {
185       cpu->cpu_interpretor = cpu_interp_m6811;
186       if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0)
187         {
188           /* Allocate core managed memory */
189
190           /* the monitor  */
191           sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
192                            /* MONITOR_BASE, MONITOR_SIZE */
193                            0x8000, M6811_RAM_LEVEL, 0x8000);
194           sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
195                            M6811_RAM_LEVEL);
196           sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F");
197         }
198
199       if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0)
200         {
201           sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5");
202           sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio");
203           sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio");
204         }
205       if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0)
206         {
207           /* M68hc11 Timer configuration. */
208           sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5");
209           sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim");
210           sim_hw_parse (sd, "/m68hc11 > capture capture /m68hc11/m68hc11tim");
211         }
212
213       /* Create the SPI device.  */
214       if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0)
215         {
216           sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3");
217           sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
218         }
219       if (hw_tree_find_property (device_tree, "/m68hc11/nvram/reg") == 0)
220         {
221           /* M68hc11 persistent ram configuration. */
222           sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256");
223           sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram");
224           sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified");
225           /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */
226         }
227       if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0)
228         {
229           sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512");
230           sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
231         }
232       sim_hw_parse (sd, "/m68hc11 > port-a cpu-write-port /m68hc11");
233       sim_hw_parse (sd, "/m68hc11 > port-b cpu-write-port /m68hc11");
234       sim_hw_parse (sd, "/m68hc11 > port-c cpu-write-port /m68hc11");
235       sim_hw_parse (sd, "/m68hc11 > port-d cpu-write-port /m68hc11");
236       cpu->hw_cpu = sim_hw_parse (sd, "/m68hc11");
237     }
238   else
239     {
240       cpu->cpu_interpretor = cpu_interp_m6812;
241       if (hw_tree_find_property (device_tree, "/m68hc12/reg") == 0)
242         {
243           /* Allocate core external memory.  */
244           sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
245                            0xC000, M6811_RAM_LEVEL, 0x4000);
246           sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
247                            M6811_RAM_LEVEL);
248           sim_do_commandf (sd, "memory region 0x01000000@%d,0x100000",
249                            M6811_RAM_LEVEL);
250
251           sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF");
252           sim_hw_parse (sd, "/m68hc12/use_bank 1");
253         }
254
255       if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg"))
256         {
257           sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8");
258           sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/backend stdio");
259           sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1");
260         }
261       if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12tim/reg") == 0)
262         {
263           /* M68hc11 Timer configuration. */
264           sim_hw_parse (sd, "/m68hc12/m68hc12tim/reg 0x1b 0x5");
265           sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim");
266           sim_hw_parse (sd, "/m68hc12 > capture capture /m68hc12/m68hc12tim");
267         }
268
269       /* Create the SPI device.  */
270       if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12spi/reg") == 0)
271         {
272           sim_hw_parse (sd, "/m68hc12/m68hc12spi/reg 0x28 0x3");
273           sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi");
274         }
275       if (hw_tree_find_property (device_tree, "/m68hc12/nvram/reg") == 0)
276         {
277           /* M68hc11 persistent ram configuration. */
278           sim_hw_parse (sd, "/m68hc12/nvram/reg 0x2000 8192");
279           sim_hw_parse (sd, "/m68hc12/nvram/file m68hc12.ram");
280           sim_hw_parse (sd, "/m68hc12/nvram/mode save-modified");
281         }
282       if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12eepr/reg") == 0)
283         {
284           sim_hw_parse (sd, "/m68hc12/m68hc12eepr/reg 0x0800 2048");
285           sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr");
286         }
287
288       sim_hw_parse (sd, "/m68hc12 > port-a cpu-write-port /m68hc12");
289       sim_hw_parse (sd, "/m68hc12 > port-b cpu-write-port /m68hc12");
290       sim_hw_parse (sd, "/m68hc12 > port-c cpu-write-port /m68hc12");
291       sim_hw_parse (sd, "/m68hc12 > port-d cpu-write-port /m68hc12");
292       cpu->hw_cpu = sim_hw_parse (sd, "/m68hc12");
293     }
294   return 1;
295 }
296
297 static int
298 sim_prepare_for_program (SIM_DESC sd, struct _bfd* abfd)
299 {
300   sim_cpu *cpu;
301
302   cpu = STATE_CPU (sd, 0);
303
304   if (!sim_hw_configure (sd))
305     return SIM_RC_FAIL;
306
307   if (abfd != NULL)
308     {
309       cpu->cpu_elf_start = bfd_get_start_address (abfd);
310     }
311
312   /* reset all state information */
313   sim_board_reset (sd);
314
315   return SIM_RC_OK;
316 }
317
318 SIM_DESC
319 sim_open (SIM_OPEN_KIND kind, host_callback *callback,
320           struct _bfd *abfd, char **argv)
321 {
322   SIM_DESC sd;
323   sim_cpu *cpu;
324
325   sd = sim_state_alloc (kind, callback);
326   cpu = STATE_CPU (sd, 0);
327
328   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
329
330   /* for compatibility */
331   current_alignment = NONSTRICT_ALIGNMENT;
332   current_target_byte_order = BIG_ENDIAN;
333
334   cpu_initialize (sd, cpu);
335
336   cpu->cpu_use_elf_start = 1;
337   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
338     {
339       free_state (sd);
340       return 0;
341     }
342
343   /* getopt will print the error message so we just have to exit if this fails.
344      FIXME: Hmmm...  in the case of gdb we need getopt to call
345      print_filtered.  */
346   if (sim_parse_args (sd, argv) != SIM_RC_OK)
347     {
348       /* Uninstall the modules to avoid memory leaks,
349          file descriptor leaks, etc.  */
350       free_state (sd);
351       return 0;
352     }
353
354   /* Check for/establish the a reference program image.  */
355   if (sim_analyze_program (sd,
356                            (STATE_PROG_ARGV (sd) != NULL
357                             ? *STATE_PROG_ARGV (sd)
358                             : NULL), abfd) != SIM_RC_OK)
359     {
360       free_state (sd);
361       return 0;
362     }
363
364   /* Establish any remaining configuration options.  */
365   if (sim_config (sd) != SIM_RC_OK)
366     {
367       free_state (sd);
368       return 0;
369     }
370
371   if (sim_post_argv_init (sd) != SIM_RC_OK)
372     {
373       /* Uninstall the modules to avoid memory leaks,
374          file descriptor leaks, etc.  */
375       free_state (sd);
376       return 0;
377     }
378
379   sim_hw_configure (sd);
380
381   /* Fudge our descriptor.  */
382   return sd;
383 }
384
385
386 void
387 sim_close (SIM_DESC sd, int quitting)
388 {
389   /* shut down modules */
390   sim_module_uninstall (sd);
391
392   /* Ensure that any resources allocated through the callback
393      mechanism are released: */
394   sim_io_shutdown (sd);
395
396   /* FIXME - free SD */
397   sim_state_free (sd);
398   return;
399 }
400
401 void
402 sim_set_profile (int n)
403 {
404 }
405
406 void
407 sim_set_profile_size (int n)
408 {
409 }
410
411 /* Generic implementation of sim_engine_run that works within the
412    sim_engine setjmp/longjmp framework. */
413
414 void
415 sim_engine_run (SIM_DESC sd,
416                 int next_cpu_nr,        /* ignore */
417                 int nr_cpus,    /* ignore */
418                 int siggnal)    /* ignore */
419 {
420   sim_cpu *cpu;
421
422   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
423   cpu = STATE_CPU (sd, 0);
424   while (1)
425     {
426       cpu_single_step (cpu);
427
428       /* process any events */
429       if (sim_events_tickn (sd, cpu->cpu_current_cycle))
430         {
431           sim_events_process (sd);
432         }
433     }
434 }
435
436 int
437 sim_trace (SIM_DESC sd)
438 {
439   sim_resume (sd, 0, 0);
440   return 1;
441 }
442
443 void
444 sim_info (SIM_DESC sd, int verbose)
445 {
446   const char *cpu_type;
447   const struct bfd_arch_info *arch;
448
449   /* Nothing to do if there is no verbose flag set.  */
450   if (verbose == 0 && STATE_VERBOSE_P (sd) == 0)
451     return;
452
453   arch = STATE_ARCHITECTURE (sd);
454   if (arch->arch == bfd_arch_m68hc11)
455     cpu_type = "68HC11";
456   else
457     cpu_type = "68HC12";
458
459   sim_io_eprintf (sd, "Simulator info:\n");
460   sim_io_eprintf (sd, "  CPU Motorola %s\n", cpu_type);
461   sim_get_info (sd, 0);
462   sim_module_info (sd, verbose || STATE_VERBOSE_P (sd));
463 }
464
465 SIM_RC
466 sim_create_inferior (SIM_DESC sd, struct _bfd *abfd,
467                      char **argv, char **env)
468 {
469   return sim_prepare_for_program (sd, abfd);
470 }
471
472
473 void
474 sim_set_callbacks (host_callback *p)
475 {
476   /*  m6811_callback = p; */
477 }
478
479
480 int
481 sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
482 {
483   sim_cpu *cpu;
484   uint16 val;
485   int size = 2;
486
487   cpu = STATE_CPU (sd, 0);
488   switch (rn)
489     {
490     case A_REGNUM:
491       val = cpu_get_a (cpu);
492       size = 1;
493       break;
494
495     case B_REGNUM:
496       val = cpu_get_b (cpu);
497       size = 1;
498       break;
499
500     case D_REGNUM:
501       val = cpu_get_d (cpu);
502       break;
503
504     case X_REGNUM:
505       val = cpu_get_x (cpu);
506       break;
507
508     case Y_REGNUM:
509       val = cpu_get_y (cpu);
510       break;
511
512     case SP_REGNUM:
513       val = cpu_get_sp (cpu);
514       break;
515
516     case PC_REGNUM:
517       val = cpu_get_pc (cpu);
518       break;
519
520     case PSW_REGNUM:
521       val = cpu_get_ccr (cpu);
522       size = 1;
523       break;
524
525     case PAGE_REGNUM:
526       val = cpu_get_page (cpu);
527       size = 1;
528       break;
529
530     default:
531       val = 0;
532       break;
533     }
534   memory[0] = val >> 8;
535   memory[1] = val & 0x0FF;
536   return size;
537 }
538
539 int
540 sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
541 {
542   uint16 val;
543   sim_cpu *cpu;
544
545   cpu = STATE_CPU (sd, 0);
546
547   val = *memory++;
548   if (length == 2)
549     val = (val << 8) | *memory;
550
551   switch (rn)
552     {
553     case D_REGNUM:
554       cpu_set_d (cpu, val);
555       break;
556
557     case A_REGNUM:
558       cpu_set_a (cpu, val);
559       return 1;
560
561     case B_REGNUM:
562       cpu_set_b (cpu, val);
563       return 1;
564
565     case X_REGNUM:
566       cpu_set_x (cpu, val);
567       break;
568
569     case Y_REGNUM:
570       cpu_set_y (cpu, val);
571       break;
572
573     case SP_REGNUM:
574       cpu_set_sp (cpu, val);
575       break;
576
577     case PC_REGNUM:
578       cpu_set_pc (cpu, val);
579       break;
580
581     case PSW_REGNUM:
582       cpu_set_ccr (cpu, val);
583       return 1;
584
585     case PAGE_REGNUM:
586       cpu_set_page (cpu, val);
587       return 1;
588
589     default:
590       break;
591     }
592
593   return 2;
594 }
595
596 void
597 sim_size (int s)
598 {
599   ;
600 }
601
602 void
603 sim_do_command (SIM_DESC sd, char *cmd)
604 {
605   char *mm_cmd = "memory-map";
606   char *int_cmd = "interrupt";
607   sim_cpu *cpu;
608
609   cpu = STATE_CPU (sd, 0);
610   /* Commands available from GDB:   */
611   if (sim_args_command (sd, cmd) != SIM_RC_OK)
612     {
613       if (strncmp (cmd, "info", sizeof ("info") - 1) == 0)
614         sim_get_info (sd, &cmd[4]);
615       else if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
616         sim_io_eprintf (sd,
617                         "`memory-map' command replaced by `sim memory'\n");
618       else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
619         sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
620       else
621         sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
622     }
623
624   /* If the architecture changed, re-configure.  */
625   if (STATE_ARCHITECTURE (sd) != cpu->cpu_configured_arch)
626     sim_hw_configure (sd);
627 }
628
629 /* Halt the simulator after just one instruction */
630
631 static void
632 has_stepped (SIM_DESC sd,
633              void *data)
634 {
635   ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
636   sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
637 }
638
639
640 /* Generic resume - assumes the existance of sim_engine_run */
641
642 void
643 sim_resume (SIM_DESC sd,
644             int step,
645             int siggnal)
646 {
647   sim_engine *engine = STATE_ENGINE (sd);
648   jmp_buf buf;
649   int jmpval;
650
651   ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
652
653   /* we only want to be single stepping the simulator once */
654   if (engine->stepper != NULL)
655     {
656       sim_events_deschedule (sd, engine->stepper);
657       engine->stepper = NULL;
658     }
659   sim_module_resume (sd);
660
661   /* run/resume the simulator */
662   engine->jmpbuf = &buf;
663   jmpval = setjmp (buf);
664   if (jmpval == sim_engine_start_jmpval
665       || jmpval == sim_engine_restart_jmpval)
666     {
667       int last_cpu_nr = sim_engine_last_cpu_nr (sd);
668       int next_cpu_nr = sim_engine_next_cpu_nr (sd);
669       int nr_cpus = sim_engine_nr_cpus (sd);
670
671       sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus);
672       if (next_cpu_nr >= nr_cpus)
673         next_cpu_nr = 0;
674
675       /* Only deliver the siggnal ]sic] the first time through - don't
676          re-deliver any siggnal during a restart. */
677       if (jmpval == sim_engine_restart_jmpval)
678         siggnal = 0;
679
680       /* Install the stepping event after having processed some
681          pending events.  This is necessary for HC11/HC12 simulator
682          because the tick counter is incremented by the number of cycles
683          the instruction took.  Some pending ticks to process can still
684          be recorded internally by the simulator and sim_events_preprocess
685          will handle them.  If the stepping event is inserted before,
686          these pending ticks will raise the event and the simulator will
687          stop without having executed any instruction.  */
688       if (step)
689         engine->stepper = sim_events_schedule (sd, 0, has_stepped, sd);
690
691 #ifdef SIM_CPU_EXCEPTION_RESUME
692       {
693         sim_cpu* cpu = STATE_CPU (sd, next_cpu_nr);
694         SIM_CPU_EXCEPTION_RESUME(sd, cpu, siggnal);
695       }
696 #endif
697
698       sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal);
699     }
700   engine->jmpbuf = NULL;
701
702   sim_module_suspend (sd);
703 }