* header.sed: Strip tabs.
[deliverable/binutils-gdb.git] / sim / m68hc11 / interp.c
CommitLineData
5abb9efa
SC
1/* interp.c -- Simulator for Motorola 68HC11/68HC12
2 Copyright (C) 1999, 2000, 2001, 2002 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;
81e09ed8
SC
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");
827ec39a 210 sim_hw_parse (sd, "/m68hc11 > capture capture /m68hc11/m68hc11tim");
81e09ed8
SC
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 }
827ec39a 232 cpu->hw_cpu = sim_hw_parse (sd, "/m68hc11");
81e09ed8
SC
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 }
81e09ed8
SC
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 }
827ec39a
SC
279
280 cpu->hw_cpu = sim_hw_parse (sd, "/m68hc12");
81e09ed8
SC
281 }
282 return 0;
283}
284
285static int
286sim_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
e0709f50
AC
304SIM_DESC
305sim_open (SIM_OPEN_KIND kind, host_callback *callback,
306 struct _bfd *abfd, char **argv)
307{
e0709f50
AC
308 SIM_DESC sd;
309 sim_cpu *cpu;
e0709f50
AC
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)
81e09ed8
SC
324 {
325 free_state (sd);
326 return 0;
327 }
e0709f50
AC
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. */
81e09ed8 336 free_state (sd);
e0709f50
AC
337 return 0;
338 }
339
e0709f50
AC
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 {
81e09ed8 346 free_state (sd);
e0709f50
AC
347 return 0;
348 }
349
350 /* Establish any remaining configuration options. */
351 if (sim_config (sd) != SIM_RC_OK)
352 {
81e09ed8 353 free_state (sd);
e0709f50
AC
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. */
81e09ed8 361 free_state (sd);
e0709f50
AC
362 return 0;
363 }
364
81e09ed8 365 sim_hw_configure (sd);
e0709f50
AC
366
367 /* Fudge our descriptor. */
368 return sd;
369}
370
371
372void
373sim_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 */
81e09ed8 383 sim_state_free (sd);
e0709f50
AC
384 return;
385}
386
387void
388sim_set_profile (int n)
389{
390}
391
392void
393sim_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
400void
401sim_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
422int
423sim_trace (SIM_DESC sd)
424{
425 sim_resume (sd, 0, 0);
426 return 1;
427}
428
429void
430sim_info (SIM_DESC sd, int verbose)
431{
81e09ed8
SC
432 const char *cpu_type;
433 const struct bfd_arch_info *arch;
434
00d0c012
SC
435 /* Nothing to do if there is no verbose flag set. */
436 if (verbose == 0 && STATE_VERBOSE_P (sd) == 0)
437 return;
438
81e09ed8
SC
439 arch = STATE_ARCHITECTURE (sd);
440 if (arch->arch == bfd_arch_m68hc11)
441 cpu_type = "68HC11";
442 else
443 cpu_type = "68HC12";
444
e0709f50 445 sim_io_eprintf (sd, "Simulator info:\n");
81e09ed8 446 sim_io_eprintf (sd, " CPU Motorola %s\n", cpu_type);
e0709f50
AC
447 sim_get_info (sd, 0);
448 sim_module_info (sd, verbose || STATE_VERBOSE_P (sd));
449}
450
451SIM_RC
452sim_create_inferior (SIM_DESC sd, struct _bfd *abfd,
453 char **argv, char **env)
454{
81e09ed8 455 return sim_prepare_for_program (sd, abfd);
e0709f50
AC
456}
457
458
459void
460sim_set_callbacks (host_callback *p)
461{
462 /* m6811_callback = p; */
463}
464
465
466int
467sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
468{
469 sim_cpu *cpu;
470 uint16 val;
471
472 cpu = STATE_CPU (sd, 0);
473 switch (rn)
474 {
475 case A_REGNUM:
476 val = cpu_get_a (cpu);
477 break;
478
479 case B_REGNUM:
480 val = cpu_get_b (cpu);
481 break;
482
483 case D_REGNUM:
484 val = cpu_get_d (cpu);
485 break;
486
487 case X_REGNUM:
488 val = cpu_get_x (cpu);
489 break;
490
491 case Y_REGNUM:
492 val = cpu_get_y (cpu);
493 break;
494
495 case SP_REGNUM:
496 val = cpu_get_sp (cpu);
497 break;
498
499 case PC_REGNUM:
500 val = cpu_get_pc (cpu);
501 break;
502
503 case PSW_REGNUM:
504 val = cpu_get_ccr (cpu);
505 break;
506
e0709f50 507 default:
9830501b 508 val = 0;
e0709f50
AC
509 break;
510 }
511 memory[0] = val >> 8;
512 memory[1] = val & 0x0FF;
513 return 2;
514}
515
516int
517sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
518{
519 uint16 val;
520 sim_cpu *cpu;
521
522 cpu = STATE_CPU (sd, 0);
523
524 val = *memory++;
525 if (length == 2)
526 val = (val << 8) | *memory;
527
528 switch (rn)
529 {
530 case D_REGNUM:
531 cpu_set_d (cpu, val);
532 break;
533
534 case A_REGNUM:
535 cpu_set_a (cpu, val);
536 break;
537
538 case B_REGNUM:
539 cpu_set_b (cpu, val);
540 break;
541
542 case X_REGNUM:
543 cpu_set_x (cpu, val);
544 break;
545
546 case Y_REGNUM:
547 cpu_set_y (cpu, val);
548 break;
549
550 case SP_REGNUM:
551 cpu_set_sp (cpu, val);
552 break;
553
554 case PC_REGNUM:
555 cpu_set_pc (cpu, val);
556 break;
557
558 case PSW_REGNUM:
559 cpu_set_ccr (cpu, val);
560 break;
561
e0709f50 562 default:
e0709f50
AC
563 break;
564 }
565
566 return 2;
567}
568
569void
570sim_size (int s)
571{
572 ;
573}
574
575void
576sim_do_command (SIM_DESC sd, char *cmd)
577{
578 char *mm_cmd = "memory-map";
579 char *int_cmd = "interrupt";
81e09ed8 580 sim_cpu *cpu;
e0709f50 581
81e09ed8 582 cpu = STATE_CPU (sd, 0);
e0709f50
AC
583 /* Commands available from GDB: */
584 if (sim_args_command (sd, cmd) != SIM_RC_OK)
585 {
586 if (strncmp (cmd, "info", sizeof ("info") - 1) == 0)
587 sim_get_info (sd, &cmd[4]);
e0709f50
AC
588 else if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
589 sim_io_eprintf (sd,
590 "`memory-map' command replaced by `sim memory'\n");
591 else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
592 sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
593 else
594 sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
595 }
81e09ed8
SC
596
597 /* If the architecture changed, re-configure. */
598 if (STATE_ARCHITECTURE (sd) != cpu->cpu_configured_arch)
599 sim_hw_configure (sd);
e0709f50 600}
00d0c012
SC
601
602/* Halt the simulator after just one instruction */
603
604static void
605has_stepped (SIM_DESC sd,
606 void *data)
607{
608 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
609 sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
610}
611
612
613/* Generic resume - assumes the existance of sim_engine_run */
614
615void
616sim_resume (SIM_DESC sd,
617 int step,
618 int siggnal)
619{
620 sim_engine *engine = STATE_ENGINE (sd);
621 jmp_buf buf;
622 int jmpval;
623
624 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
625
626 /* we only want to be single stepping the simulator once */
627 if (engine->stepper != NULL)
628 {
629 sim_events_deschedule (sd, engine->stepper);
630 engine->stepper = NULL;
631 }
632 sim_module_resume (sd);
633
634 /* run/resume the simulator */
635 engine->jmpbuf = &buf;
636 jmpval = setjmp (buf);
637 if (jmpval == sim_engine_start_jmpval
638 || jmpval == sim_engine_restart_jmpval)
639 {
640 int last_cpu_nr = sim_engine_last_cpu_nr (sd);
641 int next_cpu_nr = sim_engine_next_cpu_nr (sd);
642 int nr_cpus = sim_engine_nr_cpus (sd);
643
644 sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus);
645 if (next_cpu_nr >= nr_cpus)
646 next_cpu_nr = 0;
647
648 /* Only deliver the siggnal ]sic] the first time through - don't
649 re-deliver any siggnal during a restart. */
650 if (jmpval == sim_engine_restart_jmpval)
651 siggnal = 0;
652
653 /* Install the stepping event after having processed some
654 pending events. This is necessary for HC11/HC12 simulator
655 because the tick counter is incremented by the number of cycles
656 the instruction took. Some pending ticks to process can still
657 be recorded internally by the simulator and sim_events_preprocess
658 will handle them. If the stepping event is inserted before,
659 these pending ticks will raise the event and the simulator will
660 stop without having executed any instruction. */
661 if (step)
662 engine->stepper = sim_events_schedule (sd, 0, has_stepped, sd);
663
664#ifdef SIM_CPU_EXCEPTION_RESUME
665 {
666 sim_cpu* cpu = STATE_CPU (sd, next_cpu_nr);
667 SIM_CPU_EXCEPTION_RESUME(sd, cpu, siggnal);
668 }
669#endif
670
671 sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal);
672 }
673 engine->jmpbuf = NULL;
674
675 sim_module_suspend (sd);
676}
This page took 0.146328 seconds and 4 git commands to generate.