]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/m68hc11/interp.c
sim: m68hc11: switch to common sim_resume
[thirdparty/binutils-gdb.git] / sim / m68hc11 / interp.c
1 /* interp.c -- Simulator for Motorola 68HC11/68HC12
2 Copyright (C) 1999-2015 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 3 of the License, or
10 (at your option) 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
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
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"
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 struct sim_info_list
45 {
46 const char *name;
47 const char *device;
48 };
49
50 struct sim_info_list dev_list_68hc11[] = {
51 {"cpu", "/m68hc11"},
52 {"timer", "/m68hc11/m68hc11tim"},
53 {"sio", "/m68hc11/m68hc11sio"},
54 {"spi", "/m68hc11/m68hc11spi"},
55 {"eeprom", "/m68hc11/m68hc11eepr"},
56 {0, 0}
57 };
58
59 struct sim_info_list dev_list_68hc12[] = {
60 {"cpu", "/m68hc12"},
61 {"timer", "/m68hc12/m68hc12tim"},
62 {"sio", "/m68hc12/m68hc12sio"},
63 {"spi", "/m68hc12/m68hc12spi"},
64 {"eeprom", "/m68hc12/m68hc12eepr"},
65 {0, 0}
66 };
67
68 /* Cover function of sim_state_free to free the cpu buffers as well. */
69
70 static void
71 free_state (SIM_DESC sd)
72 {
73 if (STATE_MODULES (sd) != NULL)
74 sim_module_uninstall (sd);
75
76 sim_state_free (sd);
77 }
78
79 /* Give some information about the simulator. */
80 static void
81 sim_get_info (SIM_DESC sd, char *cmd)
82 {
83 sim_cpu *cpu;
84
85 cpu = STATE_CPU (sd, 0);
86 if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-'))
87 {
88 int i;
89 struct hw *hw_dev;
90 struct sim_info_list *dev_list;
91 const struct bfd_arch_info *arch;
92
93 arch = STATE_ARCHITECTURE (sd);
94 cmd++;
95
96 if (arch->arch == bfd_arch_m68hc11)
97 dev_list = dev_list_68hc11;
98 else
99 dev_list = dev_list_68hc12;
100
101 for (i = 0; dev_list[i].name; i++)
102 if (strcmp (cmd, dev_list[i].name) == 0)
103 break;
104
105 if (dev_list[i].name == 0)
106 {
107 sim_io_eprintf (sd, "Device '%s' not found.\n", cmd);
108 sim_io_eprintf (sd, "Valid devices: cpu timer sio eeprom\n");
109 return;
110 }
111 hw_dev = sim_hw_parse (sd, dev_list[i].device);
112 if (hw_dev == 0)
113 {
114 sim_io_eprintf (sd, "Device '%s' not found\n", dev_list[i].device);
115 return;
116 }
117 hw_ioctl (hw_dev, 23, 0);
118 return;
119 }
120
121 cpu_info (sd, cpu);
122 interrupts_info (sd, &cpu->cpu_interrupts);
123 }
124
125
126 void
127 sim_board_reset (SIM_DESC sd)
128 {
129 struct hw *hw_cpu;
130 sim_cpu *cpu;
131 const struct bfd_arch_info *arch;
132 const char *cpu_type;
133
134 cpu = STATE_CPU (sd, 0);
135 arch = STATE_ARCHITECTURE (sd);
136
137 /* hw_cpu = sim_hw_parse (sd, "/"); */
138 if (arch->arch == bfd_arch_m68hc11)
139 {
140 cpu->cpu_type = CPU_M6811;
141 cpu_type = "/m68hc11";
142 }
143 else
144 {
145 cpu->cpu_type = CPU_M6812;
146 cpu_type = "/m68hc12";
147 }
148
149 hw_cpu = sim_hw_parse (sd, cpu_type);
150 if (hw_cpu == 0)
151 {
152 sim_io_eprintf (sd, "%s cpu not found in device tree.", cpu_type);
153 return;
154 }
155
156 cpu_reset (cpu);
157 hw_port_event (hw_cpu, 3, 0);
158 cpu_restart (cpu);
159 }
160
161 static int
162 sim_hw_configure (SIM_DESC sd)
163 {
164 const struct bfd_arch_info *arch;
165 struct hw *device_tree;
166 sim_cpu *cpu;
167
168 arch = STATE_ARCHITECTURE (sd);
169 if (arch == 0)
170 return 0;
171
172 cpu = STATE_CPU (sd, 0);
173 cpu->cpu_configured_arch = arch;
174 device_tree = sim_hw_parse (sd, "/");
175 if (arch->arch == bfd_arch_m68hc11)
176 {
177 cpu->cpu_interpretor = cpu_interp_m6811;
178 if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0)
179 {
180 /* Allocate core managed memory */
181
182 /* the monitor */
183 sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
184 /* MONITOR_BASE, MONITOR_SIZE */
185 0x8000, M6811_RAM_LEVEL, 0x8000);
186 sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
187 M6811_RAM_LEVEL);
188 sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F");
189 if (cpu->bank_start < cpu->bank_end)
190 {
191 sim_do_commandf (sd, "memory region 0x%lx@%d,0x100000",
192 cpu->bank_virtual, M6811_RAM_LEVEL);
193 sim_hw_parse (sd, "/m68hc11/use_bank 1");
194 }
195 }
196 if (cpu->cpu_start_mode)
197 {
198 sim_hw_parse (sd, "/m68hc11/mode %s", cpu->cpu_start_mode);
199 }
200 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0)
201 {
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");
205 }
206 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0)
207 {
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");
211 sim_hw_parse (sd, "/m68hc11 > capture capture /m68hc11/m68hc11tim");
212 }
213
214 /* Create the SPI device. */
215 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0)
216 {
217 sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3");
218 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
219 }
220 if (hw_tree_find_property (device_tree, "/m68hc11/nvram/reg") == 0)
221 {
222 /* M68hc11 persistent ram configuration. */
223 sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256");
224 sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram");
225 sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified");
226 /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */
227 }
228 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0)
229 {
230 sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512");
231 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
232 }
233 sim_hw_parse (sd, "/m68hc11 > port-a cpu-write-port /m68hc11");
234 sim_hw_parse (sd, "/m68hc11 > port-b cpu-write-port /m68hc11");
235 sim_hw_parse (sd, "/m68hc11 > port-c cpu-write-port /m68hc11");
236 sim_hw_parse (sd, "/m68hc11 > port-d cpu-write-port /m68hc11");
237 cpu->hw_cpu = sim_hw_parse (sd, "/m68hc11");
238 }
239 else
240 {
241 cpu->cpu_interpretor = cpu_interp_m6812;
242 if (hw_tree_find_property (device_tree, "/m68hc12/reg") == 0)
243 {
244 /* Allocate core external memory. */
245 sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
246 0x8000, M6811_RAM_LEVEL, 0x8000);
247 sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
248 M6811_RAM_LEVEL);
249 if (cpu->bank_start < cpu->bank_end)
250 {
251 sim_do_commandf (sd, "memory region 0x%lx@%d,0x100000",
252 cpu->bank_virtual, M6811_RAM_LEVEL);
253 sim_hw_parse (sd, "/m68hc12/use_bank 1");
254 }
255 sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF");
256 }
257
258 if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg"))
259 {
260 sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8");
261 sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/backend stdio");
262 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1");
263 }
264 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12tim/reg") == 0)
265 {
266 /* M68hc11 Timer configuration. */
267 sim_hw_parse (sd, "/m68hc12/m68hc12tim/reg 0x1b 0x5");
268 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim");
269 sim_hw_parse (sd, "/m68hc12 > capture capture /m68hc12/m68hc12tim");
270 }
271
272 /* Create the SPI device. */
273 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12spi/reg") == 0)
274 {
275 sim_hw_parse (sd, "/m68hc12/m68hc12spi/reg 0x28 0x3");
276 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi");
277 }
278 if (hw_tree_find_property (device_tree, "/m68hc12/nvram/reg") == 0)
279 {
280 /* M68hc11 persistent ram configuration. */
281 sim_hw_parse (sd, "/m68hc12/nvram/reg 0x2000 8192");
282 sim_hw_parse (sd, "/m68hc12/nvram/file m68hc12.ram");
283 sim_hw_parse (sd, "/m68hc12/nvram/mode save-modified");
284 }
285 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12eepr/reg") == 0)
286 {
287 sim_hw_parse (sd, "/m68hc12/m68hc12eepr/reg 0x0800 2048");
288 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr");
289 }
290
291 sim_hw_parse (sd, "/m68hc12 > port-a cpu-write-port /m68hc12");
292 sim_hw_parse (sd, "/m68hc12 > port-b cpu-write-port /m68hc12");
293 sim_hw_parse (sd, "/m68hc12 > port-c cpu-write-port /m68hc12");
294 sim_hw_parse (sd, "/m68hc12 > port-d cpu-write-port /m68hc12");
295 cpu->hw_cpu = sim_hw_parse (sd, "/m68hc12");
296 }
297 return 1;
298 }
299
300 /* Get the memory bank parameters by looking at the global symbols
301 defined by the linker. */
302 static int
303 sim_get_bank_parameters (SIM_DESC sd, bfd* abfd)
304 {
305 sim_cpu *cpu;
306 long symsize;
307 long symbol_count, i;
308 unsigned size;
309 asymbol** asymbols;
310 asymbol** current;
311
312 cpu = STATE_CPU (sd, 0);
313
314 symsize = bfd_get_symtab_upper_bound (abfd);
315 if (symsize < 0)
316 {
317 sim_io_eprintf (sd, "Cannot read symbols of program");
318 return 0;
319 }
320 asymbols = (asymbol **) xmalloc (symsize);
321 symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
322 if (symbol_count < 0)
323 {
324 sim_io_eprintf (sd, "Cannot read symbols of program");
325 return 0;
326 }
327
328 size = 0;
329 for (i = 0, current = asymbols; i < symbol_count; i++, current++)
330 {
331 const char* name = bfd_asymbol_name (*current);
332
333 if (strcmp (name, BFD_M68HC11_BANK_START_NAME) == 0)
334 {
335 cpu->bank_start = bfd_asymbol_value (*current);
336 }
337 else if (strcmp (name, BFD_M68HC11_BANK_SIZE_NAME) == 0)
338 {
339 size = bfd_asymbol_value (*current);
340 }
341 else if (strcmp (name, BFD_M68HC11_BANK_VIRTUAL_NAME) == 0)
342 {
343 cpu->bank_virtual = bfd_asymbol_value (*current);
344 }
345 }
346 free (asymbols);
347
348 cpu->bank_end = cpu->bank_start + size;
349 cpu->bank_shift = 0;
350 for (; size > 1; size >>= 1)
351 cpu->bank_shift++;
352
353 return 0;
354 }
355
356 static int
357 sim_prepare_for_program (SIM_DESC sd, bfd* abfd)
358 {
359 sim_cpu *cpu;
360 int elf_flags = 0;
361
362 cpu = STATE_CPU (sd, 0);
363
364 if (abfd != NULL)
365 {
366 asection *s;
367
368 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
369 elf_flags = elf_elfheader (abfd)->e_flags;
370
371 cpu->cpu_elf_start = bfd_get_start_address (abfd);
372 /* See if any section sets the reset address */
373 cpu->cpu_use_elf_start = 1;
374 for (s = abfd->sections; s && cpu->cpu_use_elf_start; s = s->next)
375 {
376 if (s->flags & SEC_LOAD)
377 {
378 bfd_size_type size;
379
380 size = bfd_get_section_size (s);
381 if (size > 0)
382 {
383 bfd_vma lma;
384
385 if (STATE_LOAD_AT_LMA_P (sd))
386 lma = bfd_section_lma (abfd, s);
387 else
388 lma = bfd_section_vma (abfd, s);
389
390 if (lma <= 0xFFFE && lma+size >= 0x10000)
391 cpu->cpu_use_elf_start = 0;
392 }
393 }
394 }
395
396 if (elf_flags & E_M68HC12_BANKS)
397 {
398 if (sim_get_bank_parameters (sd, abfd) != 0)
399 sim_io_eprintf (sd, "Memory bank parameters are not initialized\n");
400 }
401 }
402
403 if (!sim_hw_configure (sd))
404 return SIM_RC_FAIL;
405
406 /* reset all state information */
407 sim_board_reset (sd);
408
409 return SIM_RC_OK;
410 }
411
412 static sim_cia
413 m68hc11_pc_get (sim_cpu *cpu)
414 {
415 return cpu_get_pc (cpu);
416 }
417
418 static void
419 m68hc11_pc_set (sim_cpu *cpu, sim_cia pc)
420 {
421 cpu_set_pc (cpu, pc);
422 }
423
424 SIM_DESC
425 sim_open (SIM_OPEN_KIND kind, host_callback *callback,
426 bfd *abfd, char **argv)
427 {
428 int i;
429 SIM_DESC sd;
430 sim_cpu *cpu;
431
432 sd = sim_state_alloc (kind, callback);
433
434 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
435
436 /* The cpu data is kept in a separately allocated chunk of memory. */
437 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
438 {
439 free_state (sd);
440 return 0;
441 }
442
443 cpu = STATE_CPU (sd, 0);
444
445 /* for compatibility */
446 current_alignment = NONSTRICT_ALIGNMENT;
447 current_target_byte_order = BIG_ENDIAN;
448
449 cpu_initialize (sd, cpu);
450
451 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
452 {
453 free_state (sd);
454 return 0;
455 }
456
457 /* getopt will print the error message so we just have to exit if this fails.
458 FIXME: Hmmm... in the case of gdb we need getopt to call
459 print_filtered. */
460 if (sim_parse_args (sd, argv) != SIM_RC_OK)
461 {
462 /* Uninstall the modules to avoid memory leaks,
463 file descriptor leaks, etc. */
464 free_state (sd);
465 return 0;
466 }
467
468 /* Check for/establish the a reference program image. */
469 if (sim_analyze_program (sd,
470 (STATE_PROG_ARGV (sd) != NULL
471 ? *STATE_PROG_ARGV (sd)
472 : NULL), abfd) != SIM_RC_OK)
473 {
474 free_state (sd);
475 return 0;
476 }
477
478 /* Establish any remaining configuration options. */
479 if (sim_config (sd) != SIM_RC_OK)
480 {
481 free_state (sd);
482 return 0;
483 }
484
485 if (sim_post_argv_init (sd) != SIM_RC_OK)
486 {
487 /* Uninstall the modules to avoid memory leaks,
488 file descriptor leaks, etc. */
489 free_state (sd);
490 return 0;
491 }
492 if (sim_prepare_for_program (sd, abfd) != SIM_RC_OK)
493 {
494 free_state (sd);
495 return 0;
496 }
497
498 /* CPU specific initialization. */
499 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
500 {
501 SIM_CPU *cpu = STATE_CPU (sd, i);
502
503 CPU_PC_FETCH (cpu) = m68hc11_pc_get;
504 CPU_PC_STORE (cpu) = m68hc11_pc_set;
505 }
506
507 return sd;
508 }
509
510
511 void
512 sim_close (SIM_DESC sd, int quitting)
513 {
514 /* shut down modules */
515 sim_module_uninstall (sd);
516
517 /* Ensure that any resources allocated through the callback
518 mechanism are released: */
519 sim_io_shutdown (sd);
520
521 /* FIXME - free SD */
522 sim_state_free (sd);
523 return;
524 }
525
526 /* Generic implementation of sim_engine_run that works within the
527 sim_engine setjmp/longjmp framework. */
528
529 void
530 sim_engine_run (SIM_DESC sd,
531 int next_cpu_nr, /* ignore */
532 int nr_cpus, /* ignore */
533 int siggnal) /* ignore */
534 {
535 sim_cpu *cpu;
536
537 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
538 cpu = STATE_CPU (sd, 0);
539 while (1)
540 {
541 cpu_single_step (cpu);
542
543 /* process any events */
544 if (sim_events_tickn (sd, cpu->cpu_current_cycle))
545 {
546 sim_events_process (sd);
547 }
548 }
549 }
550
551 void
552 sim_info (SIM_DESC sd, int verbose)
553 {
554 const char *cpu_type;
555 const struct bfd_arch_info *arch;
556
557 /* Nothing to do if there is no verbose flag set. */
558 if (verbose == 0 && STATE_VERBOSE_P (sd) == 0)
559 return;
560
561 arch = STATE_ARCHITECTURE (sd);
562 if (arch->arch == bfd_arch_m68hc11)
563 cpu_type = "68HC11";
564 else
565 cpu_type = "68HC12";
566
567 sim_io_eprintf (sd, "Simulator info:\n");
568 sim_io_eprintf (sd, " CPU Motorola %s\n", cpu_type);
569 sim_get_info (sd, 0);
570 sim_module_info (sd, verbose || STATE_VERBOSE_P (sd));
571 }
572
573 SIM_RC
574 sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
575 char **argv, char **env)
576 {
577 return sim_prepare_for_program (sd, abfd);
578 }
579
580 int
581 sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
582 {
583 sim_cpu *cpu;
584 uint16 val;
585 int size = 2;
586
587 cpu = STATE_CPU (sd, 0);
588 switch (rn)
589 {
590 case A_REGNUM:
591 val = cpu_get_a (cpu);
592 size = 1;
593 break;
594
595 case B_REGNUM:
596 val = cpu_get_b (cpu);
597 size = 1;
598 break;
599
600 case D_REGNUM:
601 val = cpu_get_d (cpu);
602 break;
603
604 case X_REGNUM:
605 val = cpu_get_x (cpu);
606 break;
607
608 case Y_REGNUM:
609 val = cpu_get_y (cpu);
610 break;
611
612 case SP_REGNUM:
613 val = cpu_get_sp (cpu);
614 break;
615
616 case PC_REGNUM:
617 val = cpu_get_pc (cpu);
618 break;
619
620 case PSW_REGNUM:
621 val = cpu_get_ccr (cpu);
622 size = 1;
623 break;
624
625 case PAGE_REGNUM:
626 val = cpu_get_page (cpu);
627 size = 1;
628 break;
629
630 default:
631 val = 0;
632 break;
633 }
634 if (size == 1)
635 {
636 memory[0] = val;
637 }
638 else
639 {
640 memory[0] = val >> 8;
641 memory[1] = val & 0x0FF;
642 }
643 return size;
644 }
645
646 int
647 sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
648 {
649 uint16 val;
650 sim_cpu *cpu;
651
652 cpu = STATE_CPU (sd, 0);
653
654 val = *memory++;
655 if (length == 2)
656 val = (val << 8) | *memory;
657
658 switch (rn)
659 {
660 case D_REGNUM:
661 cpu_set_d (cpu, val);
662 break;
663
664 case A_REGNUM:
665 cpu_set_a (cpu, val);
666 return 1;
667
668 case B_REGNUM:
669 cpu_set_b (cpu, val);
670 return 1;
671
672 case X_REGNUM:
673 cpu_set_x (cpu, val);
674 break;
675
676 case Y_REGNUM:
677 cpu_set_y (cpu, val);
678 break;
679
680 case SP_REGNUM:
681 cpu_set_sp (cpu, val);
682 break;
683
684 case PC_REGNUM:
685 cpu_set_pc (cpu, val);
686 break;
687
688 case PSW_REGNUM:
689 cpu_set_ccr (cpu, val);
690 return 1;
691
692 case PAGE_REGNUM:
693 cpu_set_page (cpu, val);
694 return 1;
695
696 default:
697 break;
698 }
699
700 return 2;
701 }