1 /* interp.c -- Simulator for Motorola 68HC11/68HC12
2 Copyright (C) 1999-2024 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 3 of the License, or
10 (at your option) any later version.
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
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 /* This must come before any other includes. */
26 #include "sim-assert.h"
28 #include "sim-options.h"
30 #include "hw-device.h"
32 #include "bfd/elf32-m68hc1x.h"
34 #include "m68hc11-sim.h"
37 # define MONITOR_BASE (0x0C000)
38 # define MONITOR_SIZE (0x04000)
41 static void sim_get_info (SIM_DESC sd
, char *cmd
);
49 struct sim_info_list dev_list_68hc11
[] = {
51 {"timer", "/m68hc11/m68hc11tim"},
52 {"sio", "/m68hc11/m68hc11sio"},
53 {"spi", "/m68hc11/m68hc11spi"},
54 {"eeprom", "/m68hc11/m68hc11eepr"},
58 struct sim_info_list dev_list_68hc12
[] = {
60 {"timer", "/m68hc12/m68hc12tim"},
61 {"sio", "/m68hc12/m68hc12sio"},
62 {"spi", "/m68hc12/m68hc12spi"},
63 {"eeprom", "/m68hc12/m68hc12eepr"},
67 /* Cover function of sim_state_free to free the cpu buffers as well. */
70 free_state (SIM_DESC sd
)
72 if (STATE_MODULES (sd
) != NULL
)
73 sim_module_uninstall (sd
);
78 /* Give some information about the simulator. */
80 sim_get_info (SIM_DESC sd
, char *cmd
)
84 cpu
= STATE_CPU (sd
, 0);
85 if (cmd
!= 0 && (cmd
[0] == ' ' || cmd
[0] == '-'))
89 struct sim_info_list
*dev_list
;
90 const struct bfd_arch_info
*arch
;
92 arch
= STATE_ARCHITECTURE (sd
);
95 if (arch
->arch
== bfd_arch_m68hc11
)
96 dev_list
= dev_list_68hc11
;
98 dev_list
= dev_list_68hc12
;
100 for (i
= 0; dev_list
[i
].name
; i
++)
101 if (strcmp (cmd
, dev_list
[i
].name
) == 0)
104 if (dev_list
[i
].name
== 0)
106 sim_io_eprintf (sd
, "Device '%s' not found.\n", cmd
);
107 sim_io_eprintf (sd
, "Valid devices: cpu timer sio eeprom\n");
110 hw_dev
= sim_hw_parse (sd
, "%s", dev_list
[i
].device
);
113 sim_io_eprintf (sd
, "Device '%s' not found\n", dev_list
[i
].device
);
116 hw_ioctl (hw_dev
, 23, 0);
121 interrupts_info (sd
, &M68HC11_SIM_CPU (cpu
)->cpu_interrupts
);
126 sim_board_reset (SIM_DESC sd
)
130 struct m68hc11_sim_cpu
*m68hc11_cpu
;
131 const struct bfd_arch_info
*arch
;
132 const char *cpu_type
;
134 cpu
= STATE_CPU (sd
, 0);
135 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
136 arch
= STATE_ARCHITECTURE (sd
);
138 /* hw_cpu = sim_hw_parse (sd, "/"); */
139 if (arch
->arch
== bfd_arch_m68hc11
)
141 m68hc11_cpu
->cpu_type
= CPU_M6811
;
142 cpu_type
= "/m68hc11";
146 m68hc11_cpu
->cpu_type
= CPU_M6812
;
147 cpu_type
= "/m68hc12";
150 hw_cpu
= sim_hw_parse (sd
, "%s", cpu_type
);
153 sim_io_eprintf (sd
, "%s cpu not found in device tree.", cpu_type
);
158 hw_port_event (hw_cpu
, 3, 0);
163 sim_hw_configure (SIM_DESC sd
)
165 const struct bfd_arch_info
*arch
;
166 struct hw
*device_tree
;
168 struct m68hc11_sim_cpu
*m68hc11_cpu
;
170 arch
= STATE_ARCHITECTURE (sd
);
174 cpu
= STATE_CPU (sd
, 0);
175 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
176 m68hc11_cpu
->cpu_configured_arch
= arch
;
177 device_tree
= sim_hw_parse (sd
, "/");
178 if (arch
->arch
== bfd_arch_m68hc11
)
180 m68hc11_cpu
->cpu_interpretor
= cpu_interp_m6811
;
181 if (hw_tree_find_property (device_tree
, "/m68hc11/reg") == 0)
183 /* Allocate core managed memory */
186 sim_do_commandf (sd
, "memory region 0x%x@%d,0x%x",
187 /* MONITOR_BASE, MONITOR_SIZE */
188 0x8000, M6811_RAM_LEVEL
, 0x8000);
189 sim_do_commandf (sd
, "memory region 0x000@%d,0x8000",
191 sim_hw_parse (sd
, "/m68hc11/reg 0x1000 0x03F");
192 if (m68hc11_cpu
->bank_start
< m68hc11_cpu
->bank_end
)
194 sim_do_commandf (sd
, "memory region 0x%x@%d,0x100000",
195 m68hc11_cpu
->bank_virtual
, M6811_RAM_LEVEL
);
196 sim_hw_parse (sd
, "/m68hc11/use_bank 1");
199 if (m68hc11_cpu
->cpu_start_mode
)
201 sim_hw_parse (sd
, "/m68hc11/mode %s", m68hc11_cpu
->cpu_start_mode
);
203 if (hw_tree_find_property (device_tree
, "/m68hc11/m68hc11sio/reg") == 0)
205 sim_hw_parse (sd
, "/m68hc11/m68hc11sio/reg 0x2b 0x5");
206 sim_hw_parse (sd
, "/m68hc11/m68hc11sio/backend stdio");
207 sim_hw_parse (sd
, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio");
209 if (hw_tree_find_property (device_tree
, "/m68hc11/m68hc11tim/reg") == 0)
211 /* M68hc11 Timer configuration. */
212 sim_hw_parse (sd
, "/m68hc11/m68hc11tim/reg 0x1b 0x5");
213 sim_hw_parse (sd
, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim");
214 sim_hw_parse (sd
, "/m68hc11 > capture capture /m68hc11/m68hc11tim");
217 /* Create the SPI device. */
218 if (hw_tree_find_property (device_tree
, "/m68hc11/m68hc11spi/reg") == 0)
220 sim_hw_parse (sd
, "/m68hc11/m68hc11spi/reg 0x28 0x3");
221 sim_hw_parse (sd
, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
223 if (hw_tree_find_property (device_tree
, "/m68hc11/nvram/reg") == 0)
225 /* M68hc11 persistent ram configuration. */
226 sim_hw_parse (sd
, "/m68hc11/nvram/reg 0x0 256");
227 sim_hw_parse (sd
, "/m68hc11/nvram/file m68hc11.ram");
228 sim_hw_parse (sd
, "/m68hc11/nvram/mode save-modified");
229 /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */
231 if (hw_tree_find_property (device_tree
, "/m68hc11/m68hc11eepr/reg") == 0)
233 sim_hw_parse (sd
, "/m68hc11/m68hc11eepr/reg 0xb000 512");
234 sim_hw_parse (sd
, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
236 sim_hw_parse (sd
, "/m68hc11 > port-a cpu-write-port /m68hc11");
237 sim_hw_parse (sd
, "/m68hc11 > port-b cpu-write-port /m68hc11");
238 sim_hw_parse (sd
, "/m68hc11 > port-c cpu-write-port /m68hc11");
239 sim_hw_parse (sd
, "/m68hc11 > port-d cpu-write-port /m68hc11");
240 m68hc11_cpu
->hw_cpu
= sim_hw_parse (sd
, "/m68hc11");
244 m68hc11_cpu
->cpu_interpretor
= cpu_interp_m6812
;
245 if (hw_tree_find_property (device_tree
, "/m68hc12/reg") == 0)
247 /* Allocate core external memory. */
248 sim_do_commandf (sd
, "memory region 0x%x@%d,0x%x",
249 0x8000, M6811_RAM_LEVEL
, 0x8000);
250 sim_do_commandf (sd
, "memory region 0x000@%d,0x8000",
252 if (m68hc11_cpu
->bank_start
< m68hc11_cpu
->bank_end
)
254 sim_do_commandf (sd
, "memory region 0x%x@%d,0x100000",
255 m68hc11_cpu
->bank_virtual
, M6811_RAM_LEVEL
);
256 sim_hw_parse (sd
, "/m68hc12/use_bank 1");
258 sim_hw_parse (sd
, "/m68hc12/reg 0x0 0x3FF");
261 if (!hw_tree_find_property (device_tree
, "/m68hc12/m68hc12sio@1/reg"))
263 sim_hw_parse (sd
, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8");
264 sim_hw_parse (sd
, "/m68hc12/m68hc12sio@1/backend stdio");
265 sim_hw_parse (sd
, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1");
267 if (hw_tree_find_property (device_tree
, "/m68hc12/m68hc12tim/reg") == 0)
269 /* M68hc11 Timer configuration. */
270 sim_hw_parse (sd
, "/m68hc12/m68hc12tim/reg 0x1b 0x5");
271 sim_hw_parse (sd
, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim");
272 sim_hw_parse (sd
, "/m68hc12 > capture capture /m68hc12/m68hc12tim");
275 /* Create the SPI device. */
276 if (hw_tree_find_property (device_tree
, "/m68hc12/m68hc12spi/reg") == 0)
278 sim_hw_parse (sd
, "/m68hc12/m68hc12spi/reg 0x28 0x3");
279 sim_hw_parse (sd
, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi");
281 if (hw_tree_find_property (device_tree
, "/m68hc12/nvram/reg") == 0)
283 /* M68hc11 persistent ram configuration. */
284 sim_hw_parse (sd
, "/m68hc12/nvram/reg 0x2000 8192");
285 sim_hw_parse (sd
, "/m68hc12/nvram/file m68hc12.ram");
286 sim_hw_parse (sd
, "/m68hc12/nvram/mode save-modified");
288 if (hw_tree_find_property (device_tree
, "/m68hc12/m68hc12eepr/reg") == 0)
290 sim_hw_parse (sd
, "/m68hc12/m68hc12eepr/reg 0x0800 2048");
291 sim_hw_parse (sd
, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr");
294 sim_hw_parse (sd
, "/m68hc12 > port-a cpu-write-port /m68hc12");
295 sim_hw_parse (sd
, "/m68hc12 > port-b cpu-write-port /m68hc12");
296 sim_hw_parse (sd
, "/m68hc12 > port-c cpu-write-port /m68hc12");
297 sim_hw_parse (sd
, "/m68hc12 > port-d cpu-write-port /m68hc12");
298 m68hc11_cpu
->hw_cpu
= sim_hw_parse (sd
, "/m68hc12");
303 /* Get the memory bank parameters by looking at the global symbols
304 defined by the linker. */
306 sim_get_bank_parameters (SIM_DESC sd
)
309 struct m68hc11_sim_cpu
*m68hc11_cpu
;
313 cpu
= STATE_CPU (sd
, 0);
314 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
316 addr
= trace_sym_value (sd
, BFD_M68HC11_BANK_START_NAME
);
318 m68hc11_cpu
->bank_start
= addr
;
320 size
= trace_sym_value (sd
, BFD_M68HC11_BANK_SIZE_NAME
);
324 addr
= trace_sym_value (sd
, BFD_M68HC11_BANK_VIRTUAL_NAME
);
326 m68hc11_cpu
->bank_virtual
= addr
;
328 m68hc11_cpu
->bank_end
= m68hc11_cpu
->bank_start
+ size
;
329 m68hc11_cpu
->bank_shift
= 0;
330 for (; size
> 1; size
>>= 1)
331 m68hc11_cpu
->bank_shift
++;
337 sim_prepare_for_program (SIM_DESC sd
, bfd
* abfd
)
340 struct m68hc11_sim_cpu
*m68hc11_cpu
;
343 cpu
= STATE_CPU (sd
, 0);
344 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
350 if (bfd_get_flavour (abfd
) == bfd_target_elf_flavour
)
351 elf_flags
= elf_elfheader (abfd
)->e_flags
;
353 m68hc11_cpu
->cpu_elf_start
= bfd_get_start_address (abfd
);
354 /* See if any section sets the reset address */
355 m68hc11_cpu
->cpu_use_elf_start
= 1;
356 for (s
= abfd
->sections
; s
&& m68hc11_cpu
->cpu_use_elf_start
; s
= s
->next
)
358 if (s
->flags
& SEC_LOAD
)
362 size
= bfd_section_size (s
);
367 if (STATE_LOAD_AT_LMA_P (sd
))
368 lma
= bfd_section_lma (s
);
370 lma
= bfd_section_vma (s
);
372 if (lma
<= 0xFFFE && lma
+size
>= 0x10000)
373 m68hc11_cpu
->cpu_use_elf_start
= 0;
378 if (elf_flags
& E_M68HC12_BANKS
)
380 if (sim_get_bank_parameters (sd
) != 0)
381 sim_io_eprintf (sd
, "Memory bank parameters are not initialized\n");
385 if (!sim_hw_configure (sd
))
388 /* reset all state information */
389 sim_board_reset (sd
);
395 m68hc11_pc_get (sim_cpu
*cpu
)
397 return cpu_get_pc (cpu
);
401 m68hc11_pc_set (sim_cpu
*cpu
, sim_cia pc
)
403 cpu_set_pc (cpu
, pc
);
406 static int m68hc11_reg_fetch (SIM_CPU
*, int, void *, int);
407 static int m68hc11_reg_store (SIM_CPU
*, int, const void *, int);
410 sim_open (SIM_OPEN_KIND kind
, host_callback
*callback
,
411 bfd
*abfd
, char * const *argv
)
417 sd
= sim_state_alloc (kind
, callback
);
419 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
421 /* Set default options before parsing user options. */
422 current_target_byte_order
= BFD_ENDIAN_BIG
;
424 /* The cpu data is kept in a separately allocated chunk of memory. */
425 if (sim_cpu_alloc_all_extra (sd
, 0, sizeof (struct m68hc11_sim_cpu
))
432 cpu
= STATE_CPU (sd
, 0);
434 cpu_initialize (sd
, cpu
);
436 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
442 /* The parser will print an error message for us, so we silently return. */
443 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
445 /* Uninstall the modules to avoid memory leaks,
446 file descriptor leaks, etc. */
451 /* Check for/establish the a reference program image. */
452 if (sim_analyze_program (sd
, STATE_PROG_FILE (sd
), abfd
) != SIM_RC_OK
)
458 /* Establish any remaining configuration options. */
459 if (sim_config (sd
) != SIM_RC_OK
)
465 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
467 /* Uninstall the modules to avoid memory leaks,
468 file descriptor leaks, etc. */
472 if (sim_prepare_for_program (sd
, abfd
) != SIM_RC_OK
)
478 /* CPU specific initialization. */
479 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
481 cpu
= STATE_CPU (sd
, i
);
483 CPU_REG_FETCH (cpu
) = m68hc11_reg_fetch
;
484 CPU_REG_STORE (cpu
) = m68hc11_reg_store
;
485 CPU_PC_FETCH (cpu
) = m68hc11_pc_get
;
486 CPU_PC_STORE (cpu
) = m68hc11_pc_set
;
492 /* Generic implementation of sim_engine_run that works within the
493 sim_engine setjmp/longjmp framework. */
496 sim_engine_run (SIM_DESC sd
,
497 int next_cpu_nr
, /* ignore */
498 int nr_cpus
, /* ignore */
499 int siggnal
) /* ignore */
503 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
504 cpu
= STATE_CPU (sd
, 0);
507 cpu_single_step (cpu
);
509 /* process any events */
510 if (sim_events_tickn (sd
, M68HC11_SIM_CPU (cpu
)->cpu_current_cycle
))
512 sim_events_process (sd
);
518 sim_info (SIM_DESC sd
, bool verbose
)
520 const char *cpu_type
;
521 const struct bfd_arch_info
*arch
;
523 /* Nothing to do if there is no verbose flag set. */
524 if (verbose
== 0 && STATE_VERBOSE_P (sd
) == 0)
527 arch
= STATE_ARCHITECTURE (sd
);
528 if (arch
->arch
== bfd_arch_m68hc11
)
533 sim_io_eprintf (sd
, "Simulator info:\n");
534 sim_io_eprintf (sd
, " CPU Motorola %s\n", cpu_type
);
535 sim_get_info (sd
, 0);
536 sim_module_info (sd
, verbose
|| STATE_VERBOSE_P (sd
));
540 sim_create_inferior (SIM_DESC sd
, struct bfd
*abfd
,
541 char * const *argv
, char * const *env
)
543 return sim_prepare_for_program (sd
, abfd
);
547 m68hc11_reg_fetch (SIM_CPU
*cpu
, int rn
, void *buf
, int length
)
549 unsigned char *memory
= buf
;
556 val
= cpu_get_a (cpu
);
561 val
= cpu_get_b (cpu
);
566 val
= cpu_get_d (cpu
);
570 val
= cpu_get_x (cpu
);
574 val
= cpu_get_y (cpu
);
578 val
= cpu_get_sp (cpu
);
582 val
= cpu_get_pc (cpu
);
586 val
= cpu_get_ccr (cpu
);
591 val
= cpu_get_page (cpu
);
605 memory
[0] = val
>> 8;
606 memory
[1] = val
& 0x0FF;
612 m68hc11_reg_store (SIM_CPU
*cpu
, int rn
, const void *buf
, int length
)
614 const unsigned char *memory
= buf
;
619 val
= (val
<< 8) | *memory
;
624 cpu_set_d (cpu
, val
);
628 cpu_set_a (cpu
, val
);
632 cpu_set_b (cpu
, val
);
636 cpu_set_x (cpu
, val
);
640 cpu_set_y (cpu
, val
);
644 cpu_set_sp (cpu
, val
);
648 cpu_set_pc (cpu
, val
);
652 cpu_set_ccr (cpu
, val
);
656 cpu_set_page (cpu
, val
);