1 /* interp.c -- Simulator for Motorola 68HC11
2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@worldnet.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
;
177 arch
= STATE_ARCHITECTURE (sd
);
181 cpu
= STATE_CPU (sd
, 0);
182 cpu
->cpu_configured_arch
= arch
;
183 device_tree
= sim_hw_parse (sd
, "/");
184 if (arch
->arch
== bfd_arch_m68hc11
)
186 cpu
->cpu_interpretor
= cpu_interp_m6811
;
187 if (hw_tree_find_property (device_tree
, "/m68hc11/reg") == 0)
189 /* Allocate core managed memory */
192 sim_do_commandf (sd
, "memory region 0x%lx@%d,0x%lx",
193 /* MONITOR_BASE, MONITOR_SIZE */
194 0x8000, M6811_RAM_LEVEL
, 0x8000);
195 sim_do_commandf (sd
, "memory region 0x000@%d,0x8000",
197 sim_hw_parse (sd
, "/m68hc11/reg 0x1000 0x03F");
200 if (hw_tree_find_property (device_tree
, "/m68hc11/m68hc11sio/reg") == 0)
202 sim_hw_parse (sd
, "/m68hc11/m68hc11sio/reg 0x2b 0x5");
203 sim_hw_parse (sd
, "/m68hc11/m68hc11sio/backend stdio");
204 sim_hw_parse (sd
, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio");
206 if (hw_tree_find_property (device_tree
, "/m68hc11/m68hc11tim/reg") == 0)
208 /* M68hc11 Timer configuration. */
209 sim_hw_parse (sd
, "/m68hc11/m68hc11tim/reg 0x1b 0x5");
210 sim_hw_parse (sd
, "/m68hc11 > cpu-reset reset /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");
235 cpu
->cpu_interpretor
= cpu_interp_m6812
;
236 if (hw_tree_find_property (device_tree
, "/m68hc12/reg") == 0)
238 /* Allocate core external memory. */
239 sim_do_commandf (sd
, "memory region 0x%lx@%d,0x%lx",
240 0x8000, M6811_RAM_LEVEL
, 0x8000);
241 sim_do_commandf (sd
, "memory region 0x000@%d,0x8000",
244 sim_hw_parse (sd
, "/m68hc12/reg 0x0 0x3FF");
247 if (!hw_tree_find_property (device_tree
, "/m68hc12/m68hc12sio@1/reg"))
249 sim_hw_parse (sd
, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8");
250 sim_hw_parse (sd
, "/m68hc12/m68hc12sio@1/backend stdio");
251 sim_hw_parse (sd
, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1");
253 if (!hw_tree_find_property (device_tree
, "/m68hc12/m68hc12sio@2/reg"))
255 sim_hw_parse (sd
, "/m68hc12/m68hc12sio@2/reg 0xC8 0x8");
256 sim_hw_parse (sd
, "/m68hc12/m68hc12sio@2/backend tcp");
257 sim_hw_parse (sd
, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@2");
259 if (hw_tree_find_property (device_tree
, "/m68hc12/m68hc12tim/reg") == 0)
261 /* M68hc11 Timer configuration. */
262 sim_hw_parse (sd
, "/m68hc12/m68hc12tim/reg 0x1b 0x5");
263 sim_hw_parse (sd
, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim");
266 /* Create the SPI device. */
267 if (hw_tree_find_property (device_tree
, "/m68hc12/m68hc12spi/reg") == 0)
269 sim_hw_parse (sd
, "/m68hc12/m68hc12spi/reg 0x28 0x3");
270 sim_hw_parse (sd
, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi");
272 if (hw_tree_find_property (device_tree
, "/m68hc12/nvram/reg") == 0)
274 /* M68hc11 persistent ram configuration. */
275 sim_hw_parse (sd
, "/m68hc12/nvram/reg 0x2000 8192");
276 sim_hw_parse (sd
, "/m68hc12/nvram/file m68hc12.ram");
277 sim_hw_parse (sd
, "/m68hc12/nvram/mode save-modified");
279 if (hw_tree_find_property (device_tree
, "/m68hc12/m68hc12eepr/reg") == 0)
281 sim_hw_parse (sd
, "/m68hc12/m68hc12eepr/reg 0x0800 2048");
282 sim_hw_parse (sd
, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr");
289 sim_prepare_for_program (SIM_DESC sd
, struct _bfd
* abfd
)
293 cpu
= STATE_CPU (sd
, 0);
295 sim_hw_configure (sd
);
298 cpu
->cpu_elf_start
= bfd_get_start_address (abfd
);
301 /* reset all state information */
302 sim_board_reset (sd
);
308 sim_open (SIM_OPEN_KIND kind
, host_callback
*callback
,
309 struct _bfd
*abfd
, char **argv
)
314 struct hw
*device_tree
;
316 sd
= sim_state_alloc (kind
, callback
);
317 cpu
= STATE_CPU (sd
, 0);
319 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
321 /* for compatibility */
322 current_alignment
= NONSTRICT_ALIGNMENT
;
323 current_target_byte_order
= BIG_ENDIAN
;
325 cpu_initialize (sd
, cpu
);
327 cpu
->cpu_use_elf_start
= 1;
328 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
334 /* getopt will print the error message so we just have to exit if this fails.
335 FIXME: Hmmm... in the case of gdb we need getopt to call
337 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
339 /* Uninstall the modules to avoid memory leaks,
340 file descriptor leaks, etc. */
345 /* Check for/establish the a reference program image. */
346 if (sim_analyze_program (sd
,
347 (STATE_PROG_ARGV (sd
) != NULL
348 ? *STATE_PROG_ARGV (sd
)
349 : NULL
), abfd
) != SIM_RC_OK
)
355 /* Establish any remaining configuration options. */
356 if (sim_config (sd
) != SIM_RC_OK
)
362 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
364 /* Uninstall the modules to avoid memory leaks,
365 file descriptor leaks, etc. */
370 sim_hw_configure (sd
);
372 /* Fudge our descriptor. */
378 sim_close (SIM_DESC sd
, int quitting
)
380 /* shut down modules */
381 sim_module_uninstall (sd
);
383 /* Ensure that any resources allocated through the callback
384 mechanism are released: */
385 sim_io_shutdown (sd
);
387 /* FIXME - free SD */
393 sim_set_profile (int n
)
398 sim_set_profile_size (int n
)
402 /* Generic implementation of sim_engine_run that works within the
403 sim_engine setjmp/longjmp framework. */
406 sim_engine_run (SIM_DESC sd
,
407 int next_cpu_nr
, /* ignore */
408 int nr_cpus
, /* ignore */
409 int siggnal
) /* ignore */
413 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
414 cpu
= STATE_CPU (sd
, 0);
417 cpu_single_step (cpu
);
419 /* process any events */
420 if (sim_events_tickn (sd
, cpu
->cpu_current_cycle
))
422 sim_events_process (sd
);
428 sim_trace (SIM_DESC sd
)
430 sim_resume (sd
, 0, 0);
435 sim_info (SIM_DESC sd
, int verbose
)
437 const char *cpu_type
;
438 const struct bfd_arch_info
*arch
;
440 /* Nothing to do if there is no verbose flag set. */
441 if (verbose
== 0 && STATE_VERBOSE_P (sd
) == 0)
444 arch
= STATE_ARCHITECTURE (sd
);
445 if (arch
->arch
== bfd_arch_m68hc11
)
450 sim_io_eprintf (sd
, "Simulator info:\n");
451 sim_io_eprintf (sd
, " CPU Motorola %s\n", cpu_type
);
452 sim_get_info (sd
, 0);
453 sim_module_info (sd
, verbose
|| STATE_VERBOSE_P (sd
));
457 sim_create_inferior (SIM_DESC sd
, struct _bfd
*abfd
,
458 char **argv
, char **env
)
460 return sim_prepare_for_program (sd
, abfd
);
465 sim_set_callbacks (host_callback
*p
)
467 /* m6811_callback = p; */
472 sim_fetch_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
477 cpu
= STATE_CPU (sd
, 0);
481 val
= cpu_get_a (cpu
);
485 val
= cpu_get_b (cpu
);
489 val
= cpu_get_d (cpu
);
493 val
= cpu_get_x (cpu
);
497 val
= cpu_get_y (cpu
);
501 val
= cpu_get_sp (cpu
);
505 val
= cpu_get_pc (cpu
);
509 val
= cpu_get_ccr (cpu
);
516 memory
[0] = val
>> 8;
517 memory
[1] = val
& 0x0FF;
522 sim_store_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
527 cpu
= STATE_CPU (sd
, 0);
531 val
= (val
<< 8) | *memory
;
536 cpu_set_d (cpu
, val
);
540 cpu_set_a (cpu
, val
);
544 cpu_set_b (cpu
, val
);
548 cpu_set_x (cpu
, val
);
552 cpu_set_y (cpu
, val
);
556 cpu_set_sp (cpu
, val
);
560 cpu_set_pc (cpu
, val
);
564 cpu_set_ccr (cpu
, val
);
581 sim_do_command (SIM_DESC sd
, char *cmd
)
583 char *mm_cmd
= "memory-map";
584 char *int_cmd
= "interrupt";
587 cpu
= STATE_CPU (sd
, 0);
588 /* Commands available from GDB: */
589 if (sim_args_command (sd
, cmd
) != SIM_RC_OK
)
591 if (strncmp (cmd
, "info", sizeof ("info") - 1) == 0)
592 sim_get_info (sd
, &cmd
[4]);
593 else if (strncmp (cmd
, "frame", sizeof ("frame") - 1) == 0)
594 cpu_print_frame (sd
, STATE_CPU (sd
, 0));
595 else if (strncmp (cmd
, mm_cmd
, strlen (mm_cmd
) == 0))
597 "`memory-map' command replaced by `sim memory'\n");
598 else if (strncmp (cmd
, int_cmd
, strlen (int_cmd
)) == 0)
599 sim_io_eprintf (sd
, "`interrupt' command replaced by `sim watch'\n");
601 sim_io_eprintf (sd
, "Unknown command `%s'\n", cmd
);
604 /* If the architecture changed, re-configure. */
605 if (STATE_ARCHITECTURE (sd
) != cpu
->cpu_configured_arch
)
606 sim_hw_configure (sd
);
609 /* Halt the simulator after just one instruction */
612 has_stepped (SIM_DESC sd
,
615 ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
616 sim_engine_halt (sd
, NULL
, NULL
, NULL_CIA
, sim_stopped
, SIM_SIGTRAP
);
620 /* Generic resume - assumes the existance of sim_engine_run */
623 sim_resume (SIM_DESC sd
,
627 sim_engine
*engine
= STATE_ENGINE (sd
);
631 ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
633 /* we only want to be single stepping the simulator once */
634 if (engine
->stepper
!= NULL
)
636 sim_events_deschedule (sd
, engine
->stepper
);
637 engine
->stepper
= NULL
;
639 sim_module_resume (sd
);
641 /* run/resume the simulator */
642 engine
->jmpbuf
= &buf
;
643 jmpval
= setjmp (buf
);
644 if (jmpval
== sim_engine_start_jmpval
645 || jmpval
== sim_engine_restart_jmpval
)
647 int last_cpu_nr
= sim_engine_last_cpu_nr (sd
);
648 int next_cpu_nr
= sim_engine_next_cpu_nr (sd
);
649 int nr_cpus
= sim_engine_nr_cpus (sd
);
651 sim_events_preprocess (sd
, last_cpu_nr
>= nr_cpus
, next_cpu_nr
>= nr_cpus
);
652 if (next_cpu_nr
>= nr_cpus
)
655 /* Only deliver the siggnal ]sic] the first time through - don't
656 re-deliver any siggnal during a restart. */
657 if (jmpval
== sim_engine_restart_jmpval
)
660 /* Install the stepping event after having processed some
661 pending events. This is necessary for HC11/HC12 simulator
662 because the tick counter is incremented by the number of cycles
663 the instruction took. Some pending ticks to process can still
664 be recorded internally by the simulator and sim_events_preprocess
665 will handle them. If the stepping event is inserted before,
666 these pending ticks will raise the event and the simulator will
667 stop without having executed any instruction. */
669 engine
->stepper
= sim_events_schedule (sd
, 0, has_stepped
, sd
);
671 #ifdef SIM_CPU_EXCEPTION_RESUME
673 sim_cpu
* cpu
= STATE_CPU (sd
, next_cpu_nr
);
674 SIM_CPU_EXCEPTION_RESUME(sd
, cpu
, siggnal
);
678 sim_engine_run (sd
, next_cpu_nr
, nr_cpus
, siggnal
);
680 engine
->jmpbuf
= NULL
;
682 sim_module_suspend (sd
);