[binutils, ARM, 4/16] BF insns infrastructure with array of relocs in struct arm_it
[binutils-gdb.git] / sim / m68hc11 / interp.c
blob9e8ccab18078c69c20d757e6824fc017cee7198b
1 /* interp.c -- Simulator for Motorola 68HC11/68HC12
2 Copyright (C) 1999-2019 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 #include "sim-main.h"
21 #include "sim-assert.h"
22 #include "sim-hw.h"
23 #include "sim-options.h"
24 #include "hw-tree.h"
25 #include "hw-device.h"
26 #include "hw-ports.h"
27 #include "elf32-m68hc1x.h"
29 #ifndef MONITOR_BASE
30 # define MONITOR_BASE (0x0C000)
31 # define MONITOR_SIZE (0x04000)
32 #endif
34 static void sim_get_info (SIM_DESC sd, char *cmd);
36 struct sim_info_list
38 const char *name;
39 const char *device;
42 struct sim_info_list dev_list_68hc11[] = {
43 {"cpu", "/m68hc11"},
44 {"timer", "/m68hc11/m68hc11tim"},
45 {"sio", "/m68hc11/m68hc11sio"},
46 {"spi", "/m68hc11/m68hc11spi"},
47 {"eeprom", "/m68hc11/m68hc11eepr"},
48 {0, 0}
51 struct sim_info_list dev_list_68hc12[] = {
52 {"cpu", "/m68hc12"},
53 {"timer", "/m68hc12/m68hc12tim"},
54 {"sio", "/m68hc12/m68hc12sio"},
55 {"spi", "/m68hc12/m68hc12spi"},
56 {"eeprom", "/m68hc12/m68hc12eepr"},
57 {0, 0}
60 /* Cover function of sim_state_free to free the cpu buffers as well. */
62 static void
63 free_state (SIM_DESC sd)
65 if (STATE_MODULES (sd) != NULL)
66 sim_module_uninstall (sd);
68 sim_state_free (sd);
71 /* Give some information about the simulator. */
72 static void
73 sim_get_info (SIM_DESC sd, char *cmd)
75 sim_cpu *cpu;
77 cpu = STATE_CPU (sd, 0);
78 if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-'))
80 int i;
81 struct hw *hw_dev;
82 struct sim_info_list *dev_list;
83 const struct bfd_arch_info *arch;
85 arch = STATE_ARCHITECTURE (sd);
86 cmd++;
88 if (arch->arch == bfd_arch_m68hc11)
89 dev_list = dev_list_68hc11;
90 else
91 dev_list = dev_list_68hc12;
93 for (i = 0; dev_list[i].name; i++)
94 if (strcmp (cmd, dev_list[i].name) == 0)
95 break;
97 if (dev_list[i].name == 0)
99 sim_io_eprintf (sd, "Device '%s' not found.\n", cmd);
100 sim_io_eprintf (sd, "Valid devices: cpu timer sio eeprom\n");
101 return;
103 hw_dev = sim_hw_parse (sd, dev_list[i].device);
104 if (hw_dev == 0)
106 sim_io_eprintf (sd, "Device '%s' not found\n", dev_list[i].device);
107 return;
109 hw_ioctl (hw_dev, 23, 0);
110 return;
113 cpu_info (sd, cpu);
114 interrupts_info (sd, &cpu->cpu_interrupts);
118 void
119 sim_board_reset (SIM_DESC sd)
121 struct hw *hw_cpu;
122 sim_cpu *cpu;
123 const struct bfd_arch_info *arch;
124 const char *cpu_type;
126 cpu = STATE_CPU (sd, 0);
127 arch = STATE_ARCHITECTURE (sd);
129 /* hw_cpu = sim_hw_parse (sd, "/"); */
130 if (arch->arch == bfd_arch_m68hc11)
132 cpu->cpu_type = CPU_M6811;
133 cpu_type = "/m68hc11";
135 else
137 cpu->cpu_type = CPU_M6812;
138 cpu_type = "/m68hc12";
141 hw_cpu = sim_hw_parse (sd, cpu_type);
142 if (hw_cpu == 0)
144 sim_io_eprintf (sd, "%s cpu not found in device tree.", cpu_type);
145 return;
148 cpu_reset (cpu);
149 hw_port_event (hw_cpu, 3, 0);
150 cpu_restart (cpu);
153 static int
154 sim_hw_configure (SIM_DESC sd)
156 const struct bfd_arch_info *arch;
157 struct hw *device_tree;
158 sim_cpu *cpu;
160 arch = STATE_ARCHITECTURE (sd);
161 if (arch == 0)
162 return 0;
164 cpu = STATE_CPU (sd, 0);
165 cpu->cpu_configured_arch = arch;
166 device_tree = sim_hw_parse (sd, "/");
167 if (arch->arch == bfd_arch_m68hc11)
169 cpu->cpu_interpretor = cpu_interp_m6811;
170 if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0)
172 /* Allocate core managed memory */
174 /* the monitor */
175 sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
176 /* MONITOR_BASE, MONITOR_SIZE */
177 0x8000, M6811_RAM_LEVEL, 0x8000);
178 sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
179 M6811_RAM_LEVEL);
180 sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F");
181 if (cpu->bank_start < cpu->bank_end)
183 sim_do_commandf (sd, "memory region 0x%lx@%d,0x100000",
184 cpu->bank_virtual, M6811_RAM_LEVEL);
185 sim_hw_parse (sd, "/m68hc11/use_bank 1");
188 if (cpu->cpu_start_mode)
190 sim_hw_parse (sd, "/m68hc11/mode %s", cpu->cpu_start_mode);
192 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0)
194 sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5");
195 sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio");
196 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio");
198 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0)
200 /* M68hc11 Timer configuration. */
201 sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5");
202 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim");
203 sim_hw_parse (sd, "/m68hc11 > capture capture /m68hc11/m68hc11tim");
206 /* Create the SPI device. */
207 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0)
209 sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3");
210 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
212 if (hw_tree_find_property (device_tree, "/m68hc11/nvram/reg") == 0)
214 /* M68hc11 persistent ram configuration. */
215 sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256");
216 sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram");
217 sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified");
218 /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */
220 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0)
222 sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512");
223 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
225 sim_hw_parse (sd, "/m68hc11 > port-a cpu-write-port /m68hc11");
226 sim_hw_parse (sd, "/m68hc11 > port-b cpu-write-port /m68hc11");
227 sim_hw_parse (sd, "/m68hc11 > port-c cpu-write-port /m68hc11");
228 sim_hw_parse (sd, "/m68hc11 > port-d cpu-write-port /m68hc11");
229 cpu->hw_cpu = sim_hw_parse (sd, "/m68hc11");
231 else
233 cpu->cpu_interpretor = cpu_interp_m6812;
234 if (hw_tree_find_property (device_tree, "/m68hc12/reg") == 0)
236 /* Allocate core external memory. */
237 sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
238 0x8000, M6811_RAM_LEVEL, 0x8000);
239 sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
240 M6811_RAM_LEVEL);
241 if (cpu->bank_start < cpu->bank_end)
243 sim_do_commandf (sd, "memory region 0x%lx@%d,0x100000",
244 cpu->bank_virtual, M6811_RAM_LEVEL);
245 sim_hw_parse (sd, "/m68hc12/use_bank 1");
247 sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF");
250 if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg"))
252 sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8");
253 sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/backend stdio");
254 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1");
256 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12tim/reg") == 0)
258 /* M68hc11 Timer configuration. */
259 sim_hw_parse (sd, "/m68hc12/m68hc12tim/reg 0x1b 0x5");
260 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim");
261 sim_hw_parse (sd, "/m68hc12 > capture capture /m68hc12/m68hc12tim");
264 /* Create the SPI device. */
265 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12spi/reg") == 0)
267 sim_hw_parse (sd, "/m68hc12/m68hc12spi/reg 0x28 0x3");
268 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi");
270 if (hw_tree_find_property (device_tree, "/m68hc12/nvram/reg") == 0)
272 /* M68hc11 persistent ram configuration. */
273 sim_hw_parse (sd, "/m68hc12/nvram/reg 0x2000 8192");
274 sim_hw_parse (sd, "/m68hc12/nvram/file m68hc12.ram");
275 sim_hw_parse (sd, "/m68hc12/nvram/mode save-modified");
277 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12eepr/reg") == 0)
279 sim_hw_parse (sd, "/m68hc12/m68hc12eepr/reg 0x0800 2048");
280 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr");
283 sim_hw_parse (sd, "/m68hc12 > port-a cpu-write-port /m68hc12");
284 sim_hw_parse (sd, "/m68hc12 > port-b cpu-write-port /m68hc12");
285 sim_hw_parse (sd, "/m68hc12 > port-c cpu-write-port /m68hc12");
286 sim_hw_parse (sd, "/m68hc12 > port-d cpu-write-port /m68hc12");
287 cpu->hw_cpu = sim_hw_parse (sd, "/m68hc12");
289 return 1;
292 /* Get the memory bank parameters by looking at the global symbols
293 defined by the linker. */
294 static int
295 sim_get_bank_parameters (SIM_DESC sd)
297 sim_cpu *cpu;
298 unsigned size;
299 bfd_vma addr;
301 cpu = STATE_CPU (sd, 0);
303 addr = trace_sym_value (sd, BFD_M68HC11_BANK_START_NAME);
304 if (addr != -1)
305 cpu->bank_start = addr;
307 size = trace_sym_value (sd, BFD_M68HC11_BANK_SIZE_NAME);
308 if (size == -1)
309 size = 0;
311 addr = trace_sym_value (sd, BFD_M68HC11_BANK_VIRTUAL_NAME);
312 if (addr != -1)
313 cpu->bank_virtual = addr;
315 cpu->bank_end = cpu->bank_start + size;
316 cpu->bank_shift = 0;
317 for (; size > 1; size >>= 1)
318 cpu->bank_shift++;
320 return 0;
323 static int
324 sim_prepare_for_program (SIM_DESC sd, bfd* abfd)
326 sim_cpu *cpu;
327 int elf_flags = 0;
329 cpu = STATE_CPU (sd, 0);
331 if (abfd != NULL)
333 asection *s;
335 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
336 elf_flags = elf_elfheader (abfd)->e_flags;
338 cpu->cpu_elf_start = bfd_get_start_address (abfd);
339 /* See if any section sets the reset address */
340 cpu->cpu_use_elf_start = 1;
341 for (s = abfd->sections; s && cpu->cpu_use_elf_start; s = s->next)
343 if (s->flags & SEC_LOAD)
345 bfd_size_type size;
347 size = bfd_get_section_size (s);
348 if (size > 0)
350 bfd_vma lma;
352 if (STATE_LOAD_AT_LMA_P (sd))
353 lma = bfd_section_lma (abfd, s);
354 else
355 lma = bfd_section_vma (abfd, s);
357 if (lma <= 0xFFFE && lma+size >= 0x10000)
358 cpu->cpu_use_elf_start = 0;
363 if (elf_flags & E_M68HC12_BANKS)
365 if (sim_get_bank_parameters (sd) != 0)
366 sim_io_eprintf (sd, "Memory bank parameters are not initialized\n");
370 if (!sim_hw_configure (sd))
371 return SIM_RC_FAIL;
373 /* reset all state information */
374 sim_board_reset (sd);
376 return SIM_RC_OK;
379 static sim_cia
380 m68hc11_pc_get (sim_cpu *cpu)
382 return cpu_get_pc (cpu);
385 static void
386 m68hc11_pc_set (sim_cpu *cpu, sim_cia pc)
388 cpu_set_pc (cpu, pc);
391 static int m68hc11_reg_fetch (SIM_CPU *, int, unsigned char *, int);
392 static int m68hc11_reg_store (SIM_CPU *, int, unsigned char *, int);
394 SIM_DESC
395 sim_open (SIM_OPEN_KIND kind, host_callback *callback,
396 bfd *abfd, char * const *argv)
398 int i;
399 SIM_DESC sd;
400 sim_cpu *cpu;
402 sd = sim_state_alloc (kind, callback);
404 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
406 /* The cpu data is kept in a separately allocated chunk of memory. */
407 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
409 free_state (sd);
410 return 0;
413 cpu = STATE_CPU (sd, 0);
415 cpu_initialize (sd, cpu);
417 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
419 free_state (sd);
420 return 0;
423 /* The parser will print an error message for us, so we silently return. */
424 if (sim_parse_args (sd, argv) != SIM_RC_OK)
426 /* Uninstall the modules to avoid memory leaks,
427 file descriptor leaks, etc. */
428 free_state (sd);
429 return 0;
432 /* Check for/establish the a reference program image. */
433 if (sim_analyze_program (sd,
434 (STATE_PROG_ARGV (sd) != NULL
435 ? *STATE_PROG_ARGV (sd)
436 : NULL), abfd) != SIM_RC_OK)
438 free_state (sd);
439 return 0;
442 /* Establish any remaining configuration options. */
443 if (sim_config (sd) != SIM_RC_OK)
445 free_state (sd);
446 return 0;
449 if (sim_post_argv_init (sd) != SIM_RC_OK)
451 /* Uninstall the modules to avoid memory leaks,
452 file descriptor leaks, etc. */
453 free_state (sd);
454 return 0;
456 if (sim_prepare_for_program (sd, abfd) != SIM_RC_OK)
458 free_state (sd);
459 return 0;
462 /* CPU specific initialization. */
463 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
465 SIM_CPU *cpu = STATE_CPU (sd, i);
467 CPU_REG_FETCH (cpu) = m68hc11_reg_fetch;
468 CPU_REG_STORE (cpu) = m68hc11_reg_store;
469 CPU_PC_FETCH (cpu) = m68hc11_pc_get;
470 CPU_PC_STORE (cpu) = m68hc11_pc_set;
473 return sd;
476 /* Generic implementation of sim_engine_run that works within the
477 sim_engine setjmp/longjmp framework. */
479 void
480 sim_engine_run (SIM_DESC sd,
481 int next_cpu_nr, /* ignore */
482 int nr_cpus, /* ignore */
483 int siggnal) /* ignore */
485 sim_cpu *cpu;
487 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
488 cpu = STATE_CPU (sd, 0);
489 while (1)
491 cpu_single_step (cpu);
493 /* process any events */
494 if (sim_events_tickn (sd, cpu->cpu_current_cycle))
496 sim_events_process (sd);
501 void
502 sim_info (SIM_DESC sd, int verbose)
504 const char *cpu_type;
505 const struct bfd_arch_info *arch;
507 /* Nothing to do if there is no verbose flag set. */
508 if (verbose == 0 && STATE_VERBOSE_P (sd) == 0)
509 return;
511 arch = STATE_ARCHITECTURE (sd);
512 if (arch->arch == bfd_arch_m68hc11)
513 cpu_type = "68HC11";
514 else
515 cpu_type = "68HC12";
517 sim_io_eprintf (sd, "Simulator info:\n");
518 sim_io_eprintf (sd, " CPU Motorola %s\n", cpu_type);
519 sim_get_info (sd, 0);
520 sim_module_info (sd, verbose || STATE_VERBOSE_P (sd));
523 SIM_RC
524 sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
525 char * const *argv, char * const *env)
527 return sim_prepare_for_program (sd, abfd);
530 static int
531 m68hc11_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
533 uint16 val;
534 int size = 2;
536 switch (rn)
538 case A_REGNUM:
539 val = cpu_get_a (cpu);
540 size = 1;
541 break;
543 case B_REGNUM:
544 val = cpu_get_b (cpu);
545 size = 1;
546 break;
548 case D_REGNUM:
549 val = cpu_get_d (cpu);
550 break;
552 case X_REGNUM:
553 val = cpu_get_x (cpu);
554 break;
556 case Y_REGNUM:
557 val = cpu_get_y (cpu);
558 break;
560 case SP_REGNUM:
561 val = cpu_get_sp (cpu);
562 break;
564 case PC_REGNUM:
565 val = cpu_get_pc (cpu);
566 break;
568 case PSW_REGNUM:
569 val = cpu_get_ccr (cpu);
570 size = 1;
571 break;
573 case PAGE_REGNUM:
574 val = cpu_get_page (cpu);
575 size = 1;
576 break;
578 default:
579 val = 0;
580 break;
582 if (size == 1)
584 memory[0] = val;
586 else
588 memory[0] = val >> 8;
589 memory[1] = val & 0x0FF;
591 return size;
594 static int
595 m68hc11_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
597 uint16 val;
599 val = *memory++;
600 if (length == 2)
601 val = (val << 8) | *memory;
603 switch (rn)
605 case D_REGNUM:
606 cpu_set_d (cpu, val);
607 break;
609 case A_REGNUM:
610 cpu_set_a (cpu, val);
611 return 1;
613 case B_REGNUM:
614 cpu_set_b (cpu, val);
615 return 1;
617 case X_REGNUM:
618 cpu_set_x (cpu, val);
619 break;
621 case Y_REGNUM:
622 cpu_set_y (cpu, val);
623 break;
625 case SP_REGNUM:
626 cpu_set_sp (cpu, val);
627 break;
629 case PC_REGNUM:
630 cpu_set_pc (cpu, val);
631 break;
633 case PSW_REGNUM:
634 cpu_set_ccr (cpu, val);
635 return 1;
637 case PAGE_REGNUM:
638 cpu_set_page (cpu, val);
639 return 1;
641 default:
642 break;
645 return 2;