]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/m68hc11/interp.c
* m68hc11_sim.c (cpu_special): Handle call and rtc instructions.
[thirdparty/binutils-gdb.git] / sim / m68hc11 / interp.c
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)
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 2, or (at your option)
10 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 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. */
20
21 #include "sim-main.h"
22 #include "sim-assert.h"
23 #include "sim-hw.h"
24 #include "sim-options.h"
25 #include "hw-tree.h"
26 #include "hw-device.h"
27 #include "hw-ports.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 #ifndef INLINE
45 #if defined(__GNUC__) && defined(__OPTIMIZE__)
46 #define INLINE __inline__
47 #else
48 #define INLINE
49 #endif
50 #endif
51
52 struct sim_info_list
53 {
54 const char *name;
55 const char *device;
56 };
57
58 struct sim_info_list dev_list_68hc11[] = {
59 {"cpu", "/m68hc11"},
60 {"timer", "/m68hc11/m68hc11tim"},
61 {"sio", "/m68hc11/m68hc11sio"},
62 {"spi", "/m68hc11/m68hc11spi"},
63 {"eeprom", "/m68hc11/m68hc11eepr"},
64 {0, 0}
65 };
66
67 struct sim_info_list dev_list_68hc12[] = {
68 {"cpu", "/m68hc12"},
69 {"timer", "/m68hc12/m68hc12tim"},
70 {"sio", "/m68hc12/m68hc12sio"},
71 {"spi", "/m68hc12/m68hc12spi"},
72 {"eeprom", "/m68hc12/m68hc12eepr"},
73 {0, 0}
74 };
75
76 /* Cover function of sim_state_free to free the cpu buffers as well. */
77
78 static void
79 free_state (SIM_DESC sd)
80 {
81 if (STATE_MODULES (sd) != NULL)
82 sim_module_uninstall (sd);
83
84 sim_state_free (sd);
85 }
86
87 /* Give some information about the simulator. */
88 static void
89 sim_get_info (SIM_DESC sd, char *cmd)
90 {
91 sim_cpu *cpu;
92
93 cpu = STATE_CPU (sd, 0);
94 if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-'))
95 {
96 int i;
97 struct hw *hw_dev;
98 struct sim_info_list *dev_list;
99 const struct bfd_arch_info *arch;
100
101 arch = STATE_ARCHITECTURE (sd);
102 cmd++;
103
104 if (arch->arch == bfd_arch_m68hc11)
105 dev_list = dev_list_68hc11;
106 else
107 dev_list = dev_list_68hc12;
108
109 for (i = 0; dev_list[i].name; i++)
110 if (strcmp (cmd, dev_list[i].name) == 0)
111 break;
112
113 if (dev_list[i].name == 0)
114 {
115 sim_io_eprintf (sd, "Device '%s' not found.\n", cmd);
116 sim_io_eprintf (sd, "Valid devices: cpu timer sio eeprom\n");
117 return;
118 }
119 hw_dev = sim_hw_parse (sd, dev_list[i].device);
120 if (hw_dev == 0)
121 {
122 sim_io_eprintf (sd, "Device '%s' not found\n", dev_list[i].device);
123 return;
124 }
125 hw_ioctl (hw_dev, 23, 0);
126 return;
127 }
128
129 cpu_info (sd, cpu);
130 interrupts_info (sd, &cpu->cpu_interrupts);
131 }
132
133
134 void
135 sim_board_reset (SIM_DESC sd)
136 {
137 struct hw *hw_cpu;
138 sim_cpu *cpu;
139 const struct bfd_arch_info *arch;
140 const char *cpu_type;
141
142 cpu = STATE_CPU (sd, 0);
143 arch = STATE_ARCHITECTURE (sd);
144
145 /* hw_cpu = sim_hw_parse (sd, "/"); */
146 if (arch->arch == bfd_arch_m68hc11)
147 {
148 cpu->cpu_type = CPU_M6811;
149 cpu_type = "/m68hc11";
150 }
151 else
152 {
153 cpu->cpu_type = CPU_M6812;
154 cpu_type = "/m68hc12";
155 }
156
157 hw_cpu = sim_hw_parse (sd, cpu_type);
158 if (hw_cpu == 0)
159 {
160 sim_io_eprintf (sd, "%s cpu not found in device tree.", cpu_type);
161 return;
162 }
163
164 cpu_reset (cpu);
165 hw_port_event (hw_cpu, 3, 0);
166 cpu_restart (cpu);
167 }
168
169 int
170 sim_hw_configure (SIM_DESC sd)
171 {
172 const struct bfd_arch_info *arch;
173 struct hw *device_tree;
174 sim_cpu *cpu;
175
176 arch = STATE_ARCHITECTURE (sd);
177 if (arch == 0)
178 return 0;
179
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)
184 {
185 cpu->cpu_interpretor = cpu_interp_m6811;
186 if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0)
187 {
188 /* Allocate core managed memory */
189
190 /* the monitor */
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",
195 M6811_RAM_LEVEL);
196 sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F");
197 }
198
199 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0)
200 {
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");
204 }
205 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0)
206 {
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");
211 }
212
213 /* Create the SPI device. */
214 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0)
215 {
216 sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3");
217 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
218 }
219 if (hw_tree_find_property (device_tree, "/m68hc11/nvram/reg") == 0)
220 {
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"); */
226 }
227 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0)
228 {
229 sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512");
230 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
231 }
232 cpu->hw_cpu = sim_hw_parse (sd, "/m68hc11");
233 }
234 else
235 {
236 cpu->cpu_interpretor = cpu_interp_m6812;
237 if (hw_tree_find_property (device_tree, "/m68hc12/reg") == 0)
238 {
239 /* Allocate core external memory. */
240 sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
241 0x8000, M6811_RAM_LEVEL, 0x8000);
242 sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
243 M6811_RAM_LEVEL);
244
245 sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF");
246 }
247
248 if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg"))
249 {
250 sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8");
251 sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/backend stdio");
252 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1");
253 }
254 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12tim/reg") == 0)
255 {
256 /* M68hc11 Timer configuration. */
257 sim_hw_parse (sd, "/m68hc12/m68hc12tim/reg 0x1b 0x5");
258 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim");
259 }
260
261 /* Create the SPI device. */
262 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12spi/reg") == 0)
263 {
264 sim_hw_parse (sd, "/m68hc12/m68hc12spi/reg 0x28 0x3");
265 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi");
266 }
267 if (hw_tree_find_property (device_tree, "/m68hc12/nvram/reg") == 0)
268 {
269 /* M68hc11 persistent ram configuration. */
270 sim_hw_parse (sd, "/m68hc12/nvram/reg 0x2000 8192");
271 sim_hw_parse (sd, "/m68hc12/nvram/file m68hc12.ram");
272 sim_hw_parse (sd, "/m68hc12/nvram/mode save-modified");
273 }
274 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12eepr/reg") == 0)
275 {
276 sim_hw_parse (sd, "/m68hc12/m68hc12eepr/reg 0x0800 2048");
277 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr");
278 }
279
280 cpu->hw_cpu = sim_hw_parse (sd, "/m68hc12");
281 }
282 return 0;
283 }
284
285 static int
286 sim_prepare_for_program (SIM_DESC sd, struct _bfd* abfd)
287 {
288 sim_cpu *cpu;
289
290 cpu = STATE_CPU (sd, 0);
291
292 sim_hw_configure (sd);
293 if (abfd != NULL)
294 {
295 cpu->cpu_elf_start = bfd_get_start_address (abfd);
296 }
297
298 /* reset all state information */
299 sim_board_reset (sd);
300
301 return SIM_RC_OK;
302 }
303
304 SIM_DESC
305 sim_open (SIM_OPEN_KIND kind, host_callback *callback,
306 struct _bfd *abfd, char **argv)
307 {
308 SIM_DESC sd;
309 sim_cpu *cpu;
310
311 sd = sim_state_alloc (kind, callback);
312 cpu = STATE_CPU (sd, 0);
313
314 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
315
316 /* for compatibility */
317 current_alignment = NONSTRICT_ALIGNMENT;
318 current_target_byte_order = BIG_ENDIAN;
319
320 cpu_initialize (sd, cpu);
321
322 cpu->cpu_use_elf_start = 1;
323 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
324 {
325 free_state (sd);
326 return 0;
327 }
328
329 /* getopt will print the error message so we just have to exit if this fails.
330 FIXME: Hmmm... in the case of gdb we need getopt to call
331 print_filtered. */
332 if (sim_parse_args (sd, argv) != SIM_RC_OK)
333 {
334 /* Uninstall the modules to avoid memory leaks,
335 file descriptor leaks, etc. */
336 free_state (sd);
337 return 0;
338 }
339
340 /* Check for/establish the a reference program image. */
341 if (sim_analyze_program (sd,
342 (STATE_PROG_ARGV (sd) != NULL
343 ? *STATE_PROG_ARGV (sd)
344 : NULL), abfd) != SIM_RC_OK)
345 {
346 free_state (sd);
347 return 0;
348 }
349
350 /* Establish any remaining configuration options. */
351 if (sim_config (sd) != SIM_RC_OK)
352 {
353 free_state (sd);
354 return 0;
355 }
356
357 if (sim_post_argv_init (sd) != SIM_RC_OK)
358 {
359 /* Uninstall the modules to avoid memory leaks,
360 file descriptor leaks, etc. */
361 free_state (sd);
362 return 0;
363 }
364
365 sim_hw_configure (sd);
366
367 /* Fudge our descriptor. */
368 return sd;
369 }
370
371
372 void
373 sim_close (SIM_DESC sd, int quitting)
374 {
375 /* shut down modules */
376 sim_module_uninstall (sd);
377
378 /* Ensure that any resources allocated through the callback
379 mechanism are released: */
380 sim_io_shutdown (sd);
381
382 /* FIXME - free SD */
383 sim_state_free (sd);
384 return;
385 }
386
387 void
388 sim_set_profile (int n)
389 {
390 }
391
392 void
393 sim_set_profile_size (int n)
394 {
395 }
396
397 /* Generic implementation of sim_engine_run that works within the
398 sim_engine setjmp/longjmp framework. */
399
400 void
401 sim_engine_run (SIM_DESC sd,
402 int next_cpu_nr, /* ignore */
403 int nr_cpus, /* ignore */
404 int siggnal) /* ignore */
405 {
406 sim_cpu *cpu;
407
408 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
409 cpu = STATE_CPU (sd, 0);
410 while (1)
411 {
412 cpu_single_step (cpu);
413
414 /* process any events */
415 if (sim_events_tickn (sd, cpu->cpu_current_cycle))
416 {
417 sim_events_process (sd);
418 }
419 }
420 }
421
422 int
423 sim_trace (SIM_DESC sd)
424 {
425 sim_resume (sd, 0, 0);
426 return 1;
427 }
428
429 void
430 sim_info (SIM_DESC sd, int verbose)
431 {
432 const char *cpu_type;
433 const struct bfd_arch_info *arch;
434
435 /* Nothing to do if there is no verbose flag set. */
436 if (verbose == 0 && STATE_VERBOSE_P (sd) == 0)
437 return;
438
439 arch = STATE_ARCHITECTURE (sd);
440 if (arch->arch == bfd_arch_m68hc11)
441 cpu_type = "68HC11";
442 else
443 cpu_type = "68HC12";
444
445 sim_io_eprintf (sd, "Simulator info:\n");
446 sim_io_eprintf (sd, " CPU Motorola %s\n", cpu_type);
447 sim_get_info (sd, 0);
448 sim_module_info (sd, verbose || STATE_VERBOSE_P (sd));
449 }
450
451 SIM_RC
452 sim_create_inferior (SIM_DESC sd, struct _bfd *abfd,
453 char **argv, char **env)
454 {
455 return sim_prepare_for_program (sd, abfd);
456 }
457
458
459 void
460 sim_set_callbacks (host_callback *p)
461 {
462 /* m6811_callback = p; */
463 }
464
465
466 int
467 sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
468 {
469 sim_cpu *cpu;
470 uint16 val;
471 int size = 2;
472
473 cpu = STATE_CPU (sd, 0);
474 switch (rn)
475 {
476 case A_REGNUM:
477 val = cpu_get_a (cpu);
478 size = 1;
479 break;
480
481 case B_REGNUM:
482 val = cpu_get_b (cpu);
483 size = 1;
484 break;
485
486 case D_REGNUM:
487 val = cpu_get_d (cpu);
488 break;
489
490 case X_REGNUM:
491 val = cpu_get_x (cpu);
492 break;
493
494 case Y_REGNUM:
495 val = cpu_get_y (cpu);
496 break;
497
498 case SP_REGNUM:
499 val = cpu_get_sp (cpu);
500 break;
501
502 case PC_REGNUM:
503 val = cpu_get_pc (cpu);
504 break;
505
506 case PSW_REGNUM:
507 val = cpu_get_ccr (cpu);
508 size = 1;
509 break;
510
511 case PAGE_REGNUM:
512 val = cpu_get_page (cpu);
513 size = 1;
514 break;
515
516 default:
517 val = 0;
518 break;
519 }
520 memory[0] = val >> 8;
521 memory[1] = val & 0x0FF;
522 return size;
523 }
524
525 int
526 sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
527 {
528 uint16 val;
529 sim_cpu *cpu;
530
531 cpu = STATE_CPU (sd, 0);
532
533 val = *memory++;
534 if (length == 2)
535 val = (val << 8) | *memory;
536
537 switch (rn)
538 {
539 case D_REGNUM:
540 cpu_set_d (cpu, val);
541 break;
542
543 case A_REGNUM:
544 cpu_set_a (cpu, val);
545 return 1;
546
547 case B_REGNUM:
548 cpu_set_b (cpu, val);
549 return 1;
550
551 case X_REGNUM:
552 cpu_set_x (cpu, val);
553 break;
554
555 case Y_REGNUM:
556 cpu_set_y (cpu, val);
557 break;
558
559 case SP_REGNUM:
560 cpu_set_sp (cpu, val);
561 break;
562
563 case PC_REGNUM:
564 cpu_set_pc (cpu, val);
565 break;
566
567 case PSW_REGNUM:
568 cpu_set_ccr (cpu, val);
569 return 1;
570
571 case PAGE_REGNUM:
572 cpu_set_page (cpu, val);
573 return 1;
574
575 default:
576 break;
577 }
578
579 return 2;
580 }
581
582 void
583 sim_size (int s)
584 {
585 ;
586 }
587
588 void
589 sim_do_command (SIM_DESC sd, char *cmd)
590 {
591 char *mm_cmd = "memory-map";
592 char *int_cmd = "interrupt";
593 sim_cpu *cpu;
594
595 cpu = STATE_CPU (sd, 0);
596 /* Commands available from GDB: */
597 if (sim_args_command (sd, cmd) != SIM_RC_OK)
598 {
599 if (strncmp (cmd, "info", sizeof ("info") - 1) == 0)
600 sim_get_info (sd, &cmd[4]);
601 else if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
602 sim_io_eprintf (sd,
603 "`memory-map' command replaced by `sim memory'\n");
604 else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
605 sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
606 else
607 sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
608 }
609
610 /* If the architecture changed, re-configure. */
611 if (STATE_ARCHITECTURE (sd) != cpu->cpu_configured_arch)
612 sim_hw_configure (sd);
613 }
614
615 /* Halt the simulator after just one instruction */
616
617 static void
618 has_stepped (SIM_DESC sd,
619 void *data)
620 {
621 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
622 sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
623 }
624
625
626 /* Generic resume - assumes the existance of sim_engine_run */
627
628 void
629 sim_resume (SIM_DESC sd,
630 int step,
631 int siggnal)
632 {
633 sim_engine *engine = STATE_ENGINE (sd);
634 jmp_buf buf;
635 int jmpval;
636
637 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
638
639 /* we only want to be single stepping the simulator once */
640 if (engine->stepper != NULL)
641 {
642 sim_events_deschedule (sd, engine->stepper);
643 engine->stepper = NULL;
644 }
645 sim_module_resume (sd);
646
647 /* run/resume the simulator */
648 engine->jmpbuf = &buf;
649 jmpval = setjmp (buf);
650 if (jmpval == sim_engine_start_jmpval
651 || jmpval == sim_engine_restart_jmpval)
652 {
653 int last_cpu_nr = sim_engine_last_cpu_nr (sd);
654 int next_cpu_nr = sim_engine_next_cpu_nr (sd);
655 int nr_cpus = sim_engine_nr_cpus (sd);
656
657 sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus);
658 if (next_cpu_nr >= nr_cpus)
659 next_cpu_nr = 0;
660
661 /* Only deliver the siggnal ]sic] the first time through - don't
662 re-deliver any siggnal during a restart. */
663 if (jmpval == sim_engine_restart_jmpval)
664 siggnal = 0;
665
666 /* Install the stepping event after having processed some
667 pending events. This is necessary for HC11/HC12 simulator
668 because the tick counter is incremented by the number of cycles
669 the instruction took. Some pending ticks to process can still
670 be recorded internally by the simulator and sim_events_preprocess
671 will handle them. If the stepping event is inserted before,
672 these pending ticks will raise the event and the simulator will
673 stop without having executed any instruction. */
674 if (step)
675 engine->stepper = sim_events_schedule (sd, 0, has_stepped, sd);
676
677 #ifdef SIM_CPU_EXCEPTION_RESUME
678 {
679 sim_cpu* cpu = STATE_CPU (sd, next_cpu_nr);
680 SIM_CPU_EXCEPTION_RESUME(sd, cpu, siggnal);
681 }
682 #endif
683
684 sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal);
685 }
686 engine->jmpbuf = NULL;
687
688 sim_module_suspend (sd);
689 }