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)
5 This file is part of GDB, the GNU debugger.
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)
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.
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. */
22 #include "sim-assert.h"
24 #include "sim-options.h"
26 #include "hw-device.h"
30 # define MONITOR_BASE (0x0C000)
31 # define MONITOR_SIZE (0x04000)
34 static void sim_get_info (SIM_DESC sd
, char *cmd
);
37 char *interrupt_names
[] = {
45 #if defined(__GNUC__) && defined(__OPTIMIZE__)
46 #define INLINE __inline__
58 struct sim_info_list dev_list_68hc11
[] = {
60 {"timer", "/m68hc11/m68hc11tim"},
61 {"sio", "/m68hc11/m68hc11sio"},
62 {"spi", "/m68hc11/m68hc11spi"},
63 {"eeprom", "/m68hc11/m68hc11eepr"},
67 struct sim_info_list dev_list_68hc12
[] = {
69 {"timer", "/m68hc12/m68hc12tim"},
70 {"sio", "/m68hc12/m68hc12sio"},
71 {"spi", "/m68hc12/m68hc12spi"},
72 {"eeprom", "/m68hc12/m68hc12eepr"},
76 /* Cover function of sim_state_free to free the cpu buffers as well. */
79 free_state (SIM_DESC sd
)
81 if (STATE_MODULES (sd
) != NULL
)
82 sim_module_uninstall (sd
);
87 /* Give some information about the simulator. */
89 sim_get_info (SIM_DESC sd
, char *cmd
)
93 cpu
= STATE_CPU (sd
, 0);
94 if (cmd
!= 0 && (cmd
[0] == ' ' || cmd
[0] == '-'))
98 struct sim_info_list
*dev_list
;
99 const struct bfd_arch_info
*arch
;
101 arch
= STATE_ARCHITECTURE (sd
);
104 if (arch
->arch
== bfd_arch_m68hc11
)
105 dev_list
= dev_list_68hc11
;
107 dev_list
= dev_list_68hc12
;
109 for (i
= 0; dev_list
[i
].name
; i
++)
110 if (strcmp (cmd
, dev_list
[i
].name
) == 0)
113 if (dev_list
[i
].name
== 0)
115 sim_io_eprintf (sd
, "Device '%s' not found.\n", cmd
);
116 sim_io_eprintf (sd
, "Valid devices: cpu timer sio eeprom\n");
119 hw_dev
= sim_hw_parse (sd
, dev_list
[i
].device
);
122 sim_io_eprintf (sd
, "Device '%s' not found\n", dev_list
[i
].device
);
125 hw_ioctl (hw_dev
, 23, 0);
130 interrupts_info (sd
, &cpu
->cpu_interrupts
);
135 sim_board_reset (SIM_DESC sd
)
139 const struct bfd_arch_info
*arch
;
140 const char *cpu_type
;
142 cpu
= STATE_CPU (sd
, 0);
143 arch
= STATE_ARCHITECTURE (sd
);
145 /* hw_cpu = sim_hw_parse (sd, "/"); */
146 if (arch
->arch
== bfd_arch_m68hc11
)
148 cpu
->cpu_type
= CPU_M6811
;
149 cpu_type
= "/m68hc11";
153 cpu
->cpu_type
= CPU_M6812
;
154 cpu_type
= "/m68hc12";
157 hw_cpu
= sim_hw_parse (sd
, cpu_type
);
160 sim_io_eprintf (sd
, "%s cpu not found in device tree.", cpu_type
);
165 hw_port_event (hw_cpu
, 3, 0);
170 sim_hw_configure (SIM_DESC sd
)
172 const struct bfd_arch_info
*arch
;
173 struct hw
*device_tree
;
176 arch
= STATE_ARCHITECTURE (sd
);
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
)
185 cpu
->cpu_interpretor
= cpu_interp_m6811
;
186 if (hw_tree_find_property (device_tree
, "/m68hc11/reg") == 0)
188 /* Allocate core managed memory */
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",
196 sim_hw_parse (sd
, "/m68hc11/reg 0x1000 0x03F");
199 if (hw_tree_find_property (device_tree
, "/m68hc11/m68hc11sio/reg") == 0)
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");
205 if (hw_tree_find_property (device_tree
, "/m68hc11/m68hc11tim/reg") == 0)
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");
213 /* Create the SPI device. */
214 if (hw_tree_find_property (device_tree
, "/m68hc11/m68hc11spi/reg") == 0)
216 sim_hw_parse (sd
, "/m68hc11/m68hc11spi/reg 0x28 0x3");
217 sim_hw_parse (sd
, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
219 if (hw_tree_find_property (device_tree
, "/m68hc11/nvram/reg") == 0)
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"); */
227 if (hw_tree_find_property (device_tree
, "/m68hc11/m68hc11eepr/reg") == 0)
229 sim_hw_parse (sd
, "/m68hc11/m68hc11eepr/reg 0xb000 512");
230 sim_hw_parse (sd
, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
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");
240 cpu
->cpu_interpretor
= cpu_interp_m6812
;
241 if (hw_tree_find_property (device_tree
, "/m68hc12/reg") == 0)
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",
248 sim_do_commandf (sd
, "memory region 0x01000000@%d,0x100000",
251 sim_hw_parse (sd
, "/m68hc12/reg 0x0 0x3FF");
252 sim_hw_parse (sd
, "/m68hc12/use_bank 1");
255 if (!hw_tree_find_property (device_tree
, "/m68hc12/m68hc12sio@1/reg"))
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");
261 if (hw_tree_find_property (device_tree
, "/m68hc12/m68hc12tim/reg") == 0)
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");
269 /* Create the SPI device. */
270 if (hw_tree_find_property (device_tree
, "/m68hc12/m68hc12spi/reg") == 0)
272 sim_hw_parse (sd
, "/m68hc12/m68hc12spi/reg 0x28 0x3");
273 sim_hw_parse (sd
, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi");
275 if (hw_tree_find_property (device_tree
, "/m68hc12/nvram/reg") == 0)
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");
282 if (hw_tree_find_property (device_tree
, "/m68hc12/m68hc12eepr/reg") == 0)
284 sim_hw_parse (sd
, "/m68hc12/m68hc12eepr/reg 0x0800 2048");
285 sim_hw_parse (sd
, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr");
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");
298 sim_prepare_for_program (SIM_DESC sd
, struct _bfd
* abfd
)
302 cpu
= STATE_CPU (sd
, 0);
304 if (!sim_hw_configure (sd
))
310 cpu
->cpu_elf_start
= bfd_get_start_address (abfd
);
311 /* See if any section sets the reset address */
312 cpu
->cpu_use_elf_start
= 1;
313 for (s
= abfd
->sections
; s
&& cpu
->cpu_use_elf_start
; s
= s
->next
)
315 if (s
->flags
& SEC_LOAD
)
319 size
= bfd_get_section_size_before_reloc (s
);
324 if (STATE_LOAD_AT_LMA_P (sd
))
325 lma
= bfd_section_lma (abfd
, s
);
327 lma
= bfd_section_vma (abfd
, s
);
329 if (lma
<= 0xFFFE && lma
+size
>= 0x10000)
330 cpu
->cpu_use_elf_start
= 0;
336 /* reset all state information */
337 sim_board_reset (sd
);
343 sim_open (SIM_OPEN_KIND kind
, host_callback
*callback
,
344 struct _bfd
*abfd
, char **argv
)
349 sd
= sim_state_alloc (kind
, callback
);
350 cpu
= STATE_CPU (sd
, 0);
352 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
354 /* for compatibility */
355 current_alignment
= NONSTRICT_ALIGNMENT
;
356 current_target_byte_order
= BIG_ENDIAN
;
358 cpu_initialize (sd
, cpu
);
360 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
366 /* getopt will print the error message so we just have to exit if this fails.
367 FIXME: Hmmm... in the case of gdb we need getopt to call
369 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
371 /* Uninstall the modules to avoid memory leaks,
372 file descriptor leaks, etc. */
377 /* Check for/establish the a reference program image. */
378 if (sim_analyze_program (sd
,
379 (STATE_PROG_ARGV (sd
) != NULL
380 ? *STATE_PROG_ARGV (sd
)
381 : NULL
), abfd
) != SIM_RC_OK
)
387 /* Establish any remaining configuration options. */
388 if (sim_config (sd
) != SIM_RC_OK
)
394 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
396 /* Uninstall the modules to avoid memory leaks,
397 file descriptor leaks, etc. */
402 sim_hw_configure (sd
);
404 /* Fudge our descriptor. */
410 sim_close (SIM_DESC sd
, int quitting
)
412 /* shut down modules */
413 sim_module_uninstall (sd
);
415 /* Ensure that any resources allocated through the callback
416 mechanism are released: */
417 sim_io_shutdown (sd
);
419 /* FIXME - free SD */
425 sim_set_profile (int n
)
430 sim_set_profile_size (int n
)
434 /* Generic implementation of sim_engine_run that works within the
435 sim_engine setjmp/longjmp framework. */
438 sim_engine_run (SIM_DESC sd
,
439 int next_cpu_nr
, /* ignore */
440 int nr_cpus
, /* ignore */
441 int siggnal
) /* ignore */
445 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
446 cpu
= STATE_CPU (sd
, 0);
449 cpu_single_step (cpu
);
451 /* process any events */
452 if (sim_events_tickn (sd
, cpu
->cpu_current_cycle
))
454 sim_events_process (sd
);
460 sim_trace (SIM_DESC sd
)
462 sim_resume (sd
, 0, 0);
467 sim_info (SIM_DESC sd
, int verbose
)
469 const char *cpu_type
;
470 const struct bfd_arch_info
*arch
;
472 /* Nothing to do if there is no verbose flag set. */
473 if (verbose
== 0 && STATE_VERBOSE_P (sd
) == 0)
476 arch
= STATE_ARCHITECTURE (sd
);
477 if (arch
->arch
== bfd_arch_m68hc11
)
482 sim_io_eprintf (sd
, "Simulator info:\n");
483 sim_io_eprintf (sd
, " CPU Motorola %s\n", cpu_type
);
484 sim_get_info (sd
, 0);
485 sim_module_info (sd
, verbose
|| STATE_VERBOSE_P (sd
));
489 sim_create_inferior (SIM_DESC sd
, struct _bfd
*abfd
,
490 char **argv
, char **env
)
492 return sim_prepare_for_program (sd
, abfd
);
497 sim_set_callbacks (host_callback
*p
)
499 /* m6811_callback = p; */
504 sim_fetch_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
510 cpu
= STATE_CPU (sd
, 0);
514 val
= cpu_get_a (cpu
);
519 val
= cpu_get_b (cpu
);
524 val
= cpu_get_d (cpu
);
528 val
= cpu_get_x (cpu
);
532 val
= cpu_get_y (cpu
);
536 val
= cpu_get_sp (cpu
);
540 val
= cpu_get_pc (cpu
);
544 val
= cpu_get_ccr (cpu
);
549 val
= cpu_get_page (cpu
);
557 memory
[0] = val
>> 8;
558 memory
[1] = val
& 0x0FF;
563 sim_store_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
568 cpu
= STATE_CPU (sd
, 0);
572 val
= (val
<< 8) | *memory
;
577 cpu_set_d (cpu
, val
);
581 cpu_set_a (cpu
, val
);
585 cpu_set_b (cpu
, val
);
589 cpu_set_x (cpu
, val
);
593 cpu_set_y (cpu
, val
);
597 cpu_set_sp (cpu
, val
);
601 cpu_set_pc (cpu
, val
);
605 cpu_set_ccr (cpu
, val
);
609 cpu_set_page (cpu
, val
);
626 sim_do_command (SIM_DESC sd
, char *cmd
)
628 char *mm_cmd
= "memory-map";
629 char *int_cmd
= "interrupt";
632 cpu
= STATE_CPU (sd
, 0);
633 /* Commands available from GDB: */
634 if (sim_args_command (sd
, cmd
) != SIM_RC_OK
)
636 if (strncmp (cmd
, "info", sizeof ("info") - 1) == 0)
637 sim_get_info (sd
, &cmd
[4]);
638 else if (strncmp (cmd
, mm_cmd
, strlen (mm_cmd
) == 0))
640 "`memory-map' command replaced by `sim memory'\n");
641 else if (strncmp (cmd
, int_cmd
, strlen (int_cmd
)) == 0)
642 sim_io_eprintf (sd
, "`interrupt' command replaced by `sim watch'\n");
644 sim_io_eprintf (sd
, "Unknown command `%s'\n", cmd
);
647 /* If the architecture changed, re-configure. */
648 if (STATE_ARCHITECTURE (sd
) != cpu
->cpu_configured_arch
)
649 sim_hw_configure (sd
);
652 /* Halt the simulator after just one instruction */
655 has_stepped (SIM_DESC sd
,
658 ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
659 sim_engine_halt (sd
, NULL
, NULL
, NULL_CIA
, sim_stopped
, SIM_SIGTRAP
);
663 /* Generic resume - assumes the existance of sim_engine_run */
666 sim_resume (SIM_DESC sd
,
670 sim_engine
*engine
= STATE_ENGINE (sd
);
674 ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
676 /* we only want to be single stepping the simulator once */
677 if (engine
->stepper
!= NULL
)
679 sim_events_deschedule (sd
, engine
->stepper
);
680 engine
->stepper
= NULL
;
682 sim_module_resume (sd
);
684 /* run/resume the simulator */
685 engine
->jmpbuf
= &buf
;
686 jmpval
= setjmp (buf
);
687 if (jmpval
== sim_engine_start_jmpval
688 || jmpval
== sim_engine_restart_jmpval
)
690 int last_cpu_nr
= sim_engine_last_cpu_nr (sd
);
691 int next_cpu_nr
= sim_engine_next_cpu_nr (sd
);
692 int nr_cpus
= sim_engine_nr_cpus (sd
);
694 sim_events_preprocess (sd
, last_cpu_nr
>= nr_cpus
, next_cpu_nr
>= nr_cpus
);
695 if (next_cpu_nr
>= nr_cpus
)
698 /* Only deliver the siggnal ]sic] the first time through - don't
699 re-deliver any siggnal during a restart. */
700 if (jmpval
== sim_engine_restart_jmpval
)
703 /* Install the stepping event after having processed some
704 pending events. This is necessary for HC11/HC12 simulator
705 because the tick counter is incremented by the number of cycles
706 the instruction took. Some pending ticks to process can still
707 be recorded internally by the simulator and sim_events_preprocess
708 will handle them. If the stepping event is inserted before,
709 these pending ticks will raise the event and the simulator will
710 stop without having executed any instruction. */
712 engine
->stepper
= sim_events_schedule (sd
, 0, has_stepped
, sd
);
714 #ifdef SIM_CPU_EXCEPTION_RESUME
716 sim_cpu
* cpu
= STATE_CPU (sd
, next_cpu_nr
);
717 SIM_CPU_EXCEPTION_RESUME(sd
, cpu
, siggnal
);
721 sim_engine_run (sd
, next_cpu_nr
, nr_cpus
, siggnal
);
723 engine
->jmpbuf
= NULL
;
725 sim_module_suspend (sd
);