1 /* m6811_cpu.c -- 68HC11 CPU Emulation
2 Copyright 1999, 2000 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@worldnet.fr)
5 This file is part of GDB, GAS, and the GNU binutils.
7 GDB, GAS, and the GNU binutils are free software; you can redistribute
8 them and/or modify them under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either version
10 1, or (at your option) any later version.
12 GDB, GAS, and the GNU binutils are distributed in the hope that they
13 will be useful, but WITHOUT ANY WARRANTY; without even the implied
14 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 the GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this file; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #include "sim-assert.h"
23 #include "sim-module.h"
24 #include "sim-options.h"
26 void cpu_free_frame (sim_cpu
* cpu
, struct cpu_frame
*frame
);
29 OPTION_CPU_RESET
= OPTION_START
,
35 static DECLARE_OPTION_HANDLER (cpu_option_handler
);
37 static const OPTION cpu_options
[] =
39 { {"cpu-reset", no_argument
, NULL
, OPTION_CPU_RESET
},
40 '\0', NULL
, "Reset the CPU",
43 { {"emulos", no_argument
, NULL
, OPTION_EMUL_OS
},
44 '\0', NULL
, "Emulate some OS system calls (read, write, ...)",
47 { {"cpu-config", required_argument
, NULL
, OPTION_CPU_CONFIG
},
48 '\0', NULL
, "Specify the initial CPU configuration register",
51 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
56 cpu_option_handler (SIM_DESC sd
, sim_cpu
*cpu
,
57 int opt
, char *arg
, int is_command
)
62 cpu
= STATE_CPU (sd
, 0);
65 case OPTION_CPU_RESET
:
70 cpu
->cpu_emul_syscall
= 1;
73 case OPTION_CPU_CONFIG
:
74 if (sscanf(arg
, "0x%x", &val
) == 1
75 || sscanf(arg
, "%d", &val
) == 1)
77 cpu
->cpu_config
= val
;
78 cpu
->cpu_use_local_config
= 1;
81 cpu
->cpu_use_local_config
= 0;
91 /* Tentative to keep track of the cpu frame. */
93 cpu_find_frame (sim_cpu
*cpu
, uint16 sp
)
95 struct cpu_frame_list
*flist
;
97 flist
= cpu
->cpu_frames
;
100 struct cpu_frame
*frame
;
102 frame
= flist
->frame
;
105 if (frame
->sp_low
<= sp
&& frame
->sp_high
>= sp
)
107 cpu
->cpu_current_frame
= flist
;
118 struct cpu_frame_list
*
119 cpu_create_frame_list (sim_cpu
*cpu
)
121 struct cpu_frame_list
*flist
;
123 flist
= (struct cpu_frame_list
*) malloc (sizeof (struct cpu_frame_list
));
125 flist
->next
= cpu
->cpu_frames
;
128 flist
->next
->prev
= flist
;
129 cpu
->cpu_frames
= flist
;
130 cpu
->cpu_current_frame
= flist
;
135 cpu_remove_frame_list (sim_cpu
*cpu
, struct cpu_frame_list
*flist
)
137 struct cpu_frame
*frame
;
139 if (flist
->prev
== 0)
140 cpu
->cpu_frames
= flist
->next
;
142 flist
->prev
->next
= flist
->next
;
144 flist
->next
->prev
= flist
->prev
;
146 frame
= flist
->frame
;
149 struct cpu_frame
* up
= frame
->up
;
150 cpu_free_frame (cpu
, frame
);
158 cpu_create_frame (sim_cpu
*cpu
, uint16 pc
, uint16 sp
)
160 struct cpu_frame
*frame
;
162 frame
= (struct cpu_frame
*) malloc (sizeof(struct cpu_frame
));
171 cpu_free_frame (sim_cpu
*cpu
, struct cpu_frame
*frame
)
177 cpu_frame_reg (sim_cpu
*cpu
, uint16 rn
)
179 struct cpu_frame
*frame
;
181 if (cpu
->cpu_current_frame
== 0)
184 frame
= cpu
->cpu_current_frame
->frame
;
188 return frame
->sp_high
;
196 cpu_call (sim_cpu
*cpu
, uint16 addr
)
199 uint16 pc
= cpu
->cpu_insn_pc
;
201 struct cpu_frame_list
*flist
;
202 struct cpu_frame
* frame
;
203 struct cpu_frame
* new_frame
;
206 cpu_set_pc (cpu
, addr
);
208 sp
= cpu_get_sp (cpu
);
210 cpu
->cpu_need_update_frame
= 0;
211 flist
= cpu
->cpu_current_frame
;
213 flist
= cpu_create_frame_list (cpu
);
215 frame
= flist
->frame
;
216 if (frame
&& frame
->sp_low
> sp
)
219 new_frame
= cpu_create_frame (cpu
, pc
, sp
);
220 new_frame
->up
= frame
;
221 flist
->frame
= new_frame
;
226 cpu_update_frame (sim_cpu
*cpu
, int do_create
)
229 struct cpu_frame
*frame
;
231 frame
= cpu_find_frame (cpu
, cpu_get_sp (cpu
));
234 while (frame
!= cpu
->cpu_current_frame
->frame
)
236 struct cpu_frame
* up
;
238 up
= cpu
->cpu_current_frame
->frame
->up
;
239 cpu_free_frame (cpu
, cpu
->cpu_current_frame
->frame
);
240 cpu
->cpu_current_frame
->frame
= up
;
247 cpu_create_frame_list (cpu
);
248 frame
= cpu_create_frame (cpu
, cpu_get_pc (cpu
), cpu_get_sp (cpu
));
249 cpu
->cpu_current_frame
->frame
= frame
;
255 cpu_return (sim_cpu
*cpu
)
258 uint16 sp
= cpu_get_sp (cpu
);
259 struct cpu_frame
*frame
;
260 struct cpu_frame_list
*flist
;
262 cpu
->cpu_need_update_frame
= 0;
263 flist
= cpu
->cpu_current_frame
;
264 if (flist
&& flist
->frame
&& flist
->frame
->up
)
266 frame
= flist
->frame
->up
;
267 if (frame
->sp_low
<= sp
&& frame
->sp_high
>= sp
)
269 cpu_free_frame (cpu
, flist
->frame
);
270 flist
->frame
= frame
;
274 cpu_update_frame (cpu
, 1);
279 cpu_print_frame (SIM_DESC sd
, sim_cpu
*cpu
)
281 struct cpu_frame
* frame
;
284 if (cpu
->cpu_current_frame
== 0 || cpu
->cpu_current_frame
->frame
== 0)
286 sim_io_printf (sd
, "No frame.\n");
289 sim_io_printf (sd
, " # PC SP-L SP-H\n");
290 frame
= cpu
->cpu_current_frame
->frame
;
293 sim_io_printf (sd
, "%3d 0x%04x 0x%04x 0x%04x\n",
294 level
, frame
->pc
, frame
->sp_low
, frame
->sp_high
);
300 /* Set the stack pointer and re-compute the current frame. */
302 cpu_set_sp (sim_cpu
*cpu
, uint16 val
)
304 cpu
->cpu_regs
.sp
= val
;
305 cpu_update_frame (cpu
, 0);
309 cpu_initialize (SIM_DESC sd
, sim_cpu
*cpu
)
313 sim_add_option_table (sd
, 0, cpu_options
);
315 memset (&cpu
->cpu_regs
, 0, sizeof(cpu
->cpu_regs
));
317 cpu
->cpu_absolute_cycle
= 0;
318 cpu
->cpu_current_cycle
= 0;
319 cpu
->cpu_emul_syscall
= 1;
320 cpu
->cpu_running
= 1;
321 cpu
->cpu_stop_on_interrupt
= 0;
322 cpu
->cpu_frequency
= 8 * 1000 * 1000;
324 cpu
->cpu_current_frame
= 0;
325 cpu
->cpu_use_elf_start
= 0;
326 cpu
->cpu_elf_start
= 0;
327 cpu
->cpu_use_local_config
= 0;
328 cpu
->cpu_config
= M6811_NOSEC
| M6811_NOCOP
| M6811_ROMON
|
330 result
= interrupts_initialize (cpu
);
332 cpu
->cpu_is_initialized
= 1;
337 /* Reinitialize the processor after a reset. */
339 cpu_reset (sim_cpu
*cpu
)
341 cpu
->cpu_need_update_frame
= 0;
342 cpu
->cpu_current_frame
= 0;
343 while (cpu
->cpu_frames
)
344 cpu_remove_frame_list (cpu
, cpu
->cpu_frames
);
346 /* Initialize the config register.
347 It is only initialized at reset time. */
348 memset (cpu
->ios
, 0, sizeof (cpu
->ios
));
349 cpu
->ios
[M6811_INIT
] = 0x1;
351 /* Output compare registers set to 0xFFFF. */
352 cpu
->ios
[M6811_TOC1_H
] = 0xFF;
353 cpu
->ios
[M6811_TOC1_L
] = 0xFF;
354 cpu
->ios
[M6811_TOC2_H
] = 0xFF;
355 cpu
->ios
[M6811_TOC2_L
] = 0xFF;
356 cpu
->ios
[M6811_TOC3_H
] = 0xFF;
357 cpu
->ios
[M6811_TOC4_L
] = 0xFF;
358 cpu
->ios
[M6811_TOC5_H
] = 0xFF;
359 cpu
->ios
[M6811_TOC5_L
] = 0xFF;
361 /* Setup the processor registers. */
362 memset (&cpu
->cpu_regs
, 0, sizeof(cpu
->cpu_regs
));
363 cpu
->cpu_absolute_cycle
= 0;
364 cpu
->cpu_current_cycle
= 0;
365 cpu
->cpu_is_initialized
= 0;
367 /* Reinitialize the CPU operating mode. */
368 cpu
->ios
[M6811_HPRIO
] = cpu
->cpu_mode
;
372 /* Reinitialize the processor after a reset. */
374 cpu_restart (sim_cpu
*cpu
)
378 /* Get CPU starting address depending on the CPU mode. */
379 if (cpu
->cpu_use_elf_start
== 0)
381 switch ((cpu
->ios
[M6811_HPRIO
]) & (M6811_SMOD
| M6811_MDA
))
386 addr
= memory_read16 (cpu
, 0xFFFE);
389 /* Expanded Multiplexed */
391 addr
= memory_read16 (cpu
, 0xFFFE);
394 /* Special Bootstrap */
400 case M6811_MDA
| M6811_SMOD
:
401 addr
= memory_read16 (cpu
, 0xFFFE);
407 addr
= cpu
->cpu_elf_start
;
410 /* Setup the processor registers. */
411 cpu
->cpu_insn_pc
= addr
;
412 cpu
->cpu_regs
.pc
= addr
;
413 cpu
->cpu_regs
.ccr
= M6811_X_BIT
| M6811_I_BIT
| M6811_S_BIT
;
414 cpu
->cpu_absolute_cycle
= 0;
415 cpu
->cpu_is_initialized
= 1;
416 cpu
->cpu_current_cycle
= 0;
418 cpu_call (cpu
, addr
);
424 print_io_reg_desc (SIM_DESC sd
, io_reg_desc
*desc
, int val
, int mode
)
428 if (val
& desc
->mask
)
429 sim_io_printf (sd
, "%s",
430 mode
== 0 ? desc
->short_name
: desc
->long_name
);
436 print_io_byte (SIM_DESC sd
, const char *name
, io_reg_desc
*desc
,
437 uint8 val
, uint16 addr
)
439 sim_io_printf (sd
, " %-9.9s @ 0x%04x 0x%02x ", name
, addr
, val
);
441 print_io_reg_desc (sd
, desc
, val
, 0);
445 cpu_ccr_update_tst8 (sim_cpu
*proc
, uint8 val
)
447 cpu_set_ccr_V (proc
, 0);
448 cpu_set_ccr_N (proc
, val
& 0x80 ? 1 : 0);
449 cpu_set_ccr_Z (proc
, val
== 0 ? 1 : 0);
454 cpu_fetch_relbranch (sim_cpu
*cpu
)
456 uint16 addr
= (uint16
) cpu_fetch8 (cpu
);
462 addr
+= cpu
->cpu_regs
.pc
;
467 /* Push all the CPU registers (when an interruption occurs). */
469 cpu_push_all (sim_cpu
*cpu
)
471 cpu_push_uint16 (cpu
, cpu
->cpu_regs
.pc
);
472 cpu_push_uint16 (cpu
, cpu
->cpu_regs
.iy
);
473 cpu_push_uint16 (cpu
, cpu
->cpu_regs
.ix
);
474 cpu_push_uint16 (cpu
, cpu
->cpu_regs
.d
);
475 cpu_push_uint8 (cpu
, cpu
->cpu_regs
.ccr
);
479 /* Handle special instructions. */
481 cpu_special (sim_cpu
*cpu
, enum M6811_Special special
)
489 ccr
= cpu_pop_uint8 (cpu
);
490 cpu_set_ccr (cpu
, ccr
);
491 cpu_set_d (cpu
, cpu_pop_uint16 (cpu
));
492 cpu_set_x (cpu
, cpu_pop_uint16 (cpu
));
493 cpu_set_y (cpu
, cpu_pop_uint16 (cpu
));
494 cpu_set_pc (cpu
, cpu_pop_uint16 (cpu
));
500 /* In the ELF-start mode, we are in a special mode where
501 the WAI corresponds to an exit. */
502 if (cpu
->cpu_use_elf_start
)
504 cpu_set_pc (cpu
, cpu
->cpu_insn_pc
);
505 sim_engine_halt (CPU_STATE (cpu
), cpu
,
506 NULL
, NULL_CIA
, sim_exited
,
510 /* SCz: not correct... */
515 interrupts_raise (&cpu
->cpu_interrupts
, M6811_INT_SWI
);
516 interrupts_process (&cpu
->cpu_interrupts
);
519 case M6811_EMUL_SYSCALL
:
521 if (cpu
->cpu_emul_syscall
)
523 uint8 op
= memory_read8 (cpu
,
524 cpu_get_pc (cpu
) - 1);
527 cpu_set_pc (cpu
, cpu
->cpu_insn_pc
);
528 sim_engine_halt (CPU_STATE (cpu
), cpu
,
529 NULL
, NULL_CIA
, sim_exited
,
540 interrupts_raise (&cpu
->cpu_interrupts
, M6811_INT_ILLEGAL
);
541 interrupts_process (&cpu
->cpu_interrupts
);
548 sd
= CPU_STATE (cpu
);
550 /* Breakpoint instruction if we are under gdb. */
551 if (STATE_OPEN_KIND (sd
) == SIM_OPEN_DEBUG
)
554 sim_engine_halt (CPU_STATE (cpu
), cpu
,
555 0, cpu_get_pc (cpu
), sim_stopped
,
558 /* else this is a nop but not in test factory mode. */
566 cpu_single_step (sim_cpu
*cpu
)
568 cpu
->cpu_current_cycle
= 0;
569 cpu
->cpu_insn_pc
= cpu_get_pc (cpu
);
571 /* Handle the pending interrupts. If an interrupt is handled,
572 treat this as an single step. */
573 if (interrupts_process (&cpu
->cpu_interrupts
))
575 cpu
->cpu_absolute_cycle
+= cpu
->cpu_current_cycle
;
579 /* printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
581 cpu
->cpu_absolute_cycle
+= cpu
->cpu_current_cycle
;
586 sim_memory_error (sim_cpu
*cpu
, SIM_SIGNAL excep
,
587 uint16 addr
, const char *message
, ...)
592 va_start (args
, message
);
593 vsprintf (buf
, message
, args
);
597 cpu_memory_exception (cpu
, excep
, addr
, buf
);
602 cpu_memory_exception (sim_cpu
*cpu
, SIM_SIGNAL excep
,
603 uint16 addr
, const char *message
)
605 if (cpu
->cpu_running
== 0)
608 cpu_set_pc (cpu
, cpu
->cpu_insn_pc
);
609 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
,
610 cpu_get_pc (cpu
), sim_stopped
, excep
);
613 cpu
->mem_exception
= excep
;
614 cpu
->fault_addr
= addr
;
615 cpu
->fault_msg
= strdup (message
);
617 if (cpu
->cpu_use_handler
)
619 longjmp (&cpu
->cpu_exception_handler
, 1);
621 (* cpu
->callback
->printf_filtered
)
622 (cpu
->callback
, "Fault at 0x%04x: %s\n", addr
, message
);
627 cpu_info (SIM_DESC sd
, sim_cpu
*cpu
)
629 sim_io_printf (sd
, "CPU info:\n");
630 sim_io_printf (sd
, " Absolute cycle: %llu\n",
631 cpu
->cpu_absolute_cycle
);
632 sim_io_printf (sd
, " Syscall emulation: %s\n",
633 cpu
->cpu_emul_syscall
? "yes, via 0xcd <n>" : "no");
634 sim_io_printf (sd
, " Memory errors detection: %s\n",
635 cpu
->cpu_check_memory
? "yes" : "no");
636 sim_io_printf (sd
, " Stop on interrupt: %s\n",
637 cpu
->cpu_stop_on_interrupt
? "yes" : "no");
This page took 0.042965 seconds and 4 git commands to generate.