]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/m68hc11/interp.c
* interrupts.c (interrupts_reset): New function, setup interrupt
[thirdparty/binutils-gdb.git] / sim / m68hc11 / interp.c
CommitLineData
e0709f50 1/* interp.c -- Simulator for Motorola 68HC11
81e09ed8 2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
e0709f50
AC
3 Written by Stephane Carrez (stcarrez@worldnet.fr)
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License along
18with this program; if not, write to the Free Software Foundation, Inc.,
1959 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
34static void sim_get_info (SIM_DESC sd, char *cmd);
35
36
37char *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
52struct sim_info_list
53{
54 const char *name;
55 const char *device;
56};
57
81e09ed8 58struct sim_info_list dev_list_68hc11[] = {
e0709f50
AC
59 {"cpu", "/m68hc11"},
60 {"timer", "/m68hc11/m68hc11tim"},
61 {"sio", "/m68hc11/m68hc11sio"},
62 {"spi", "/m68hc11/m68hc11spi"},
63 {"eeprom", "/m68hc11/m68hc11eepr"},
64 {0, 0}
65};
66
81e09ed8
SC
67struct 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
78static void
79free_state (SIM_DESC sd)
80{
81 if (STATE_MODULES (sd) != NULL)
82 sim_module_uninstall (sd);
83
84 sim_state_free (sd);
85}
86
e0709f50
AC
87/* Give some information about the simulator. */
88static void
89sim_get_info (SIM_DESC sd, char *cmd)
90{
91 sim_cpu *cpu;
92
81e09ed8 93 cpu = STATE_CPU (sd, 0);
e0709f50
AC
94 if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-'))
95 {
96 int i;
97 struct hw *hw_dev;
81e09ed8
SC
98 struct sim_info_list *dev_list;
99 const struct bfd_arch_info *arch;
100
101 arch = STATE_ARCHITECTURE (sd);
e0709f50
AC
102 cmd++;
103
81e09ed8
SC
104 if (arch->arch == bfd_arch_m68hc11)
105 dev_list = dev_list_68hc11;
106 else
107 dev_list = dev_list_68hc12;
108
e0709f50
AC
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
e0709f50
AC
129 cpu_info (sd, cpu);
130 interrupts_info (sd, &cpu->cpu_interrupts);
131}
132
133
134void
135sim_board_reset (SIM_DESC sd)
136{
137 struct hw *hw_cpu;
138 sim_cpu *cpu;
81e09ed8
SC
139 const struct bfd_arch_info *arch;
140 const char *cpu_type;
e0709f50
AC
141
142 cpu = STATE_CPU (sd, 0);
81e09ed8
SC
143 arch = STATE_ARCHITECTURE (sd);
144
e0709f50 145 /* hw_cpu = sim_hw_parse (sd, "/"); */
81e09ed8
SC
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);
e0709f50
AC
158 if (hw_cpu == 0)
159 {
81e09ed8 160 sim_io_eprintf (sd, "%s cpu not found in device tree.", cpu_type);
e0709f50
AC
161 return;
162 }
163
164 cpu_reset (cpu);
165 hw_port_event (hw_cpu, 3, 0);
166 cpu_restart (cpu);
167}
168
81e09ed8
SC
169int
170sim_hw_configure (SIM_DESC sd)
171{
172 const struct bfd_arch_info *arch;
173 struct hw *device_tree;
174 int m6811_mode;
175 sim_cpu *cpu;
176
177 arch = STATE_ARCHITECTURE (sd);
178 if (arch == 0)
179 return 0;
180
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)
185 {
186 cpu->cpu_interpretor = cpu_interp_m6811;
187 if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0)
188 {
189 /* Allocate core managed memory */
190
191 /* the monitor */
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",
196 M6811_RAM_LEVEL);
197 sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F");
198 }
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 }
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 }
233 else
234 {
235 cpu->cpu_interpretor = cpu_interp_m6812;
236 if (hw_tree_find_property (device_tree, "/m68hc12/reg") == 0)
237 {
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",
242 M6811_RAM_LEVEL);
243
244 sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF");
245 }
246
247 if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg"))
248 {
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");
252 }
253 if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@2/reg"))
254 {
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");
258 }
259 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12tim/reg") == 0)
260 {
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");
264 }
265
266 /* Create the SPI device. */
267 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12spi/reg") == 0)
268 {
269 sim_hw_parse (sd, "/m68hc12/m68hc12spi/reg 0x28 0x3");
270 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi");
271 }
272 if (hw_tree_find_property (device_tree, "/m68hc12/nvram/reg") == 0)
273 {
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");
278 }
279 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12eepr/reg") == 0)
280 {
281 sim_hw_parse (sd, "/m68hc12/m68hc12eepr/reg 0x0800 2048");
282 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr");
283 }
284 }
285 return 0;
286}
287
288static int
289sim_prepare_for_program (SIM_DESC sd, struct _bfd* abfd)
290{
291 sim_cpu *cpu;
292
293 cpu = STATE_CPU (sd, 0);
294
295 sim_hw_configure (sd);
296 if (abfd != NULL)
297 {
298 cpu->cpu_elf_start = bfd_get_start_address (abfd);
299 }
300
301 /* reset all state information */
302 sim_board_reset (sd);
303
304 return SIM_RC_OK;
305}
306
e0709f50
AC
307SIM_DESC
308sim_open (SIM_OPEN_KIND kind, host_callback *callback,
309 struct _bfd *abfd, char **argv)
310{
311 char **p;
312 SIM_DESC sd;
313 sim_cpu *cpu;
314 struct hw *device_tree;
315
316 sd = sim_state_alloc (kind, callback);
317 cpu = STATE_CPU (sd, 0);
318
319 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
320
321 /* for compatibility */
322 current_alignment = NONSTRICT_ALIGNMENT;
323 current_target_byte_order = BIG_ENDIAN;
324
325 cpu_initialize (sd, cpu);
326
327 cpu->cpu_use_elf_start = 1;
328 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
81e09ed8
SC
329 {
330 free_state (sd);
331 return 0;
332 }
e0709f50
AC
333
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
336 print_filtered. */
337 if (sim_parse_args (sd, argv) != SIM_RC_OK)
338 {
339 /* Uninstall the modules to avoid memory leaks,
340 file descriptor leaks, etc. */
81e09ed8 341 free_state (sd);
e0709f50
AC
342 return 0;
343 }
344
e0709f50
AC
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)
350 {
81e09ed8 351 free_state (sd);
e0709f50
AC
352 return 0;
353 }
354
355 /* Establish any remaining configuration options. */
356 if (sim_config (sd) != SIM_RC_OK)
357 {
81e09ed8 358 free_state (sd);
e0709f50
AC
359 return 0;
360 }
361
362 if (sim_post_argv_init (sd) != SIM_RC_OK)
363 {
364 /* Uninstall the modules to avoid memory leaks,
365 file descriptor leaks, etc. */
81e09ed8 366 free_state (sd);
e0709f50
AC
367 return 0;
368 }
369
81e09ed8 370 sim_hw_configure (sd);
e0709f50
AC
371
372 /* Fudge our descriptor. */
373 return sd;
374}
375
376
377void
378sim_close (SIM_DESC sd, int quitting)
379{
380 /* shut down modules */
381 sim_module_uninstall (sd);
382
383 /* Ensure that any resources allocated through the callback
384 mechanism are released: */
385 sim_io_shutdown (sd);
386
387 /* FIXME - free SD */
81e09ed8 388 sim_state_free (sd);
e0709f50
AC
389 return;
390}
391
392void
393sim_set_profile (int n)
394{
395}
396
397void
398sim_set_profile_size (int n)
399{
400}
401
402/* Generic implementation of sim_engine_run that works within the
403 sim_engine setjmp/longjmp framework. */
404
405void
406sim_engine_run (SIM_DESC sd,
407 int next_cpu_nr, /* ignore */
408 int nr_cpus, /* ignore */
409 int siggnal) /* ignore */
410{
411 sim_cpu *cpu;
412
413 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
414 cpu = STATE_CPU (sd, 0);
415 while (1)
416 {
417 cpu_single_step (cpu);
418
419 /* process any events */
420 if (sim_events_tickn (sd, cpu->cpu_current_cycle))
421 {
422 sim_events_process (sd);
423 }
424 }
425}
426
427int
428sim_trace (SIM_DESC sd)
429{
430 sim_resume (sd, 0, 0);
431 return 1;
432}
433
434void
435sim_info (SIM_DESC sd, int verbose)
436{
81e09ed8
SC
437 const char *cpu_type;
438 const struct bfd_arch_info *arch;
439
00d0c012
SC
440 /* Nothing to do if there is no verbose flag set. */
441 if (verbose == 0 && STATE_VERBOSE_P (sd) == 0)
442 return;
443
81e09ed8
SC
444 arch = STATE_ARCHITECTURE (sd);
445 if (arch->arch == bfd_arch_m68hc11)
446 cpu_type = "68HC11";
447 else
448 cpu_type = "68HC12";
449
e0709f50 450 sim_io_eprintf (sd, "Simulator info:\n");
81e09ed8 451 sim_io_eprintf (sd, " CPU Motorola %s\n", cpu_type);
e0709f50
AC
452 sim_get_info (sd, 0);
453 sim_module_info (sd, verbose || STATE_VERBOSE_P (sd));
454}
455
456SIM_RC
457sim_create_inferior (SIM_DESC sd, struct _bfd *abfd,
458 char **argv, char **env)
459{
81e09ed8 460 return sim_prepare_for_program (sd, abfd);
e0709f50
AC
461}
462
463
464void
465sim_set_callbacks (host_callback *p)
466{
467 /* m6811_callback = p; */
468}
469
470
471int
472sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
473{
474 sim_cpu *cpu;
475 uint16 val;
476
477 cpu = STATE_CPU (sd, 0);
478 switch (rn)
479 {
480 case A_REGNUM:
481 val = cpu_get_a (cpu);
482 break;
483
484 case B_REGNUM:
485 val = cpu_get_b (cpu);
486 break;
487
488 case D_REGNUM:
489 val = cpu_get_d (cpu);
490 break;
491
492 case X_REGNUM:
493 val = cpu_get_x (cpu);
494 break;
495
496 case Y_REGNUM:
497 val = cpu_get_y (cpu);
498 break;
499
500 case SP_REGNUM:
501 val = cpu_get_sp (cpu);
502 break;
503
504 case PC_REGNUM:
505 val = cpu_get_pc (cpu);
506 break;
507
508 case PSW_REGNUM:
509 val = cpu_get_ccr (cpu);
510 break;
511
e0709f50 512 default:
9830501b 513 val = 0;
e0709f50
AC
514 break;
515 }
516 memory[0] = val >> 8;
517 memory[1] = val & 0x0FF;
518 return 2;
519}
520
521int
522sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
523{
524 uint16 val;
525 sim_cpu *cpu;
526
527 cpu = STATE_CPU (sd, 0);
528
529 val = *memory++;
530 if (length == 2)
531 val = (val << 8) | *memory;
532
533 switch (rn)
534 {
535 case D_REGNUM:
536 cpu_set_d (cpu, val);
537 break;
538
539 case A_REGNUM:
540 cpu_set_a (cpu, val);
541 break;
542
543 case B_REGNUM:
544 cpu_set_b (cpu, val);
545 break;
546
547 case X_REGNUM:
548 cpu_set_x (cpu, val);
549 break;
550
551 case Y_REGNUM:
552 cpu_set_y (cpu, val);
553 break;
554
555 case SP_REGNUM:
556 cpu_set_sp (cpu, val);
557 break;
558
559 case PC_REGNUM:
560 cpu_set_pc (cpu, val);
561 break;
562
563 case PSW_REGNUM:
564 cpu_set_ccr (cpu, val);
565 break;
566
e0709f50 567 default:
e0709f50
AC
568 break;
569 }
570
571 return 2;
572}
573
574void
575sim_size (int s)
576{
577 ;
578}
579
580void
581sim_do_command (SIM_DESC sd, char *cmd)
582{
583 char *mm_cmd = "memory-map";
584 char *int_cmd = "interrupt";
81e09ed8 585 sim_cpu *cpu;
e0709f50 586
81e09ed8 587 cpu = STATE_CPU (sd, 0);
e0709f50
AC
588 /* Commands available from GDB: */
589 if (sim_args_command (sd, cmd) != SIM_RC_OK)
590 {
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))
596 sim_io_eprintf (sd,
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");
600 else
601 sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
602 }
81e09ed8
SC
603
604 /* If the architecture changed, re-configure. */
605 if (STATE_ARCHITECTURE (sd) != cpu->cpu_configured_arch)
606 sim_hw_configure (sd);
e0709f50 607}
00d0c012
SC
608
609/* Halt the simulator after just one instruction */
610
611static void
612has_stepped (SIM_DESC sd,
613 void *data)
614{
615 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
616 sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
617}
618
619
620/* Generic resume - assumes the existance of sim_engine_run */
621
622void
623sim_resume (SIM_DESC sd,
624 int step,
625 int siggnal)
626{
627 sim_engine *engine = STATE_ENGINE (sd);
628 jmp_buf buf;
629 int jmpval;
630
631 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
632
633 /* we only want to be single stepping the simulator once */
634 if (engine->stepper != NULL)
635 {
636 sim_events_deschedule (sd, engine->stepper);
637 engine->stepper = NULL;
638 }
639 sim_module_resume (sd);
640
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)
646 {
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);
650
651 sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus);
652 if (next_cpu_nr >= nr_cpus)
653 next_cpu_nr = 0;
654
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)
658 siggnal = 0;
659
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. */
668 if (step)
669 engine->stepper = sim_events_schedule (sd, 0, has_stepped, sd);
670
671#ifdef SIM_CPU_EXCEPTION_RESUME
672 {
673 sim_cpu* cpu = STATE_CPU (sd, next_cpu_nr);
674 SIM_CPU_EXCEPTION_RESUME(sd, cpu, siggnal);
675 }
676#endif
677
678 sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal);
679 }
680 engine->jmpbuf = NULL;
681
682 sim_module_suspend (sd);
683}