1 /* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
2 Copyright 1999, 2000, 2001, 2002 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"
27 OPTION_CPU_RESET = OPTION_START,
33 static DECLARE_OPTION_HANDLER (cpu_option_handler);
35 static const OPTION cpu_options[] =
37 { {"cpu-reset", no_argument, NULL, OPTION_CPU_RESET },
38 '\0', NULL, "Reset the CPU",
41 { {"emulos", no_argument, NULL, OPTION_EMUL_OS },
42 '\0', NULL, "Emulate some OS system calls (read, write, ...)",
45 { {"cpu-config", required_argument, NULL, OPTION_CPU_CONFIG },
46 '\0', NULL, "Specify the initial CPU configuration register",
49 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
54 cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
55 int opt, char *arg, int is_command)
59 cpu = STATE_CPU (sd, 0);
62 case OPTION_CPU_RESET:
67 cpu->cpu_emul_syscall = 1;
70 case OPTION_CPU_CONFIG:
71 if (sscanf(arg, "0x%x", &val) == 1
72 || sscanf(arg, "%d", &val) == 1)
74 cpu->cpu_config = val;
75 cpu->cpu_use_local_config = 1;
78 cpu->cpu_use_local_config = 0;
90 cpu_call (sim_cpu *cpu, uint16 addr)
93 cpu_set_pc (cpu, addr);
97 cpu_return (sim_cpu *cpu)
101 /* Set the stack pointer and re-compute the current frame. */
103 cpu_set_sp (sim_cpu *cpu, uint16 val)
105 cpu->cpu_regs.sp = val;
109 cpu_get_reg (sim_cpu* cpu, uint8 reg)
114 return cpu_get_x (cpu);
117 return cpu_get_y (cpu);
120 return cpu_get_sp (cpu);
123 return cpu_get_pc (cpu);
131 cpu_get_src_reg (sim_cpu* cpu, uint8 reg)
136 return cpu_get_a (cpu);
139 return cpu_get_b (cpu);
142 return cpu_get_ccr (cpu);
145 return cpu_get_tmp3 (cpu);
148 return cpu_get_d (cpu);
151 return cpu_get_x (cpu);
154 return cpu_get_y (cpu);
157 return cpu_get_sp (cpu);
165 cpu_set_dst_reg (sim_cpu* cpu, uint8 reg, uint16 val)
170 cpu_set_a (cpu, val);
174 cpu_set_b (cpu, val);
178 cpu_set_ccr (cpu, val);
182 cpu_set_tmp2 (cpu, val);
186 cpu_set_d (cpu, val);
190 cpu_set_x (cpu, val);
194 cpu_set_y (cpu, val);
198 cpu_set_sp (cpu, val);
207 cpu_set_reg (sim_cpu* cpu, uint8 reg, uint16 val)
212 cpu_set_x (cpu, val);
216 cpu_set_y (cpu, val);
220 cpu_set_sp (cpu, val);
224 cpu_set_pc (cpu, val);
232 /* Returns the address of a 68HC12 indexed operand.
233 Pre and post modifications are handled on the source register. */
235 cpu_get_indexed_operand_addr (sim_cpu* cpu, int restrict)
242 code = cpu_fetch8 (cpu);
244 /* n,r with 5-bit signed constant. */
245 if ((code & 0x20) == 0)
247 reg = (code >> 6) & 3;
248 sval = (code & 0x1f);
252 addr = cpu_get_reg (cpu, reg);
256 /* Auto pre/post increment/decrement. */
257 else if ((code & 0xc0) != 0xc0)
259 reg = (code >> 6) & 3;
260 sval = (code & 0x0f);
269 addr = cpu_get_reg (cpu, reg);
270 cpu_set_reg (cpu, reg, addr + sval);
271 if ((code & 0x10) == 0)
277 /* [n,r] 16-bits offset indexed indirect. */
278 else if ((code & 0x07) == 3)
284 reg = (code >> 3) & 0x03;
285 addr = cpu_get_reg (cpu, reg);
286 addr += cpu_fetch16 (cpu);
287 addr = memory_read16 (cpu, addr);
288 cpu_add_cycles (cpu, 1);
290 else if ((code & 0x4) == 0)
296 reg = (code >> 3) & 0x03;
297 addr = cpu_get_reg (cpu, reg);
300 sval = cpu_fetch16 (cpu);
301 cpu_add_cycles (cpu, 1);
305 sval = cpu_fetch8 (cpu);
308 cpu_add_cycles (cpu, 1);
314 reg = (code >> 3) & 0x03;
315 addr = cpu_get_reg (cpu, reg);
319 addr += cpu_get_a (cpu);
322 addr += cpu_get_b (cpu);
325 addr += cpu_get_d (cpu);
329 addr += cpu_get_d (cpu);
330 addr = memory_read16 (cpu, addr);
331 cpu_add_cycles (cpu, 1);
340 cpu_get_indexed_operand8 (sim_cpu* cpu, int restrict)
344 addr = cpu_get_indexed_operand_addr (cpu, restrict);
345 return memory_read8 (cpu, addr);
349 cpu_get_indexed_operand16 (sim_cpu* cpu, int restrict)
353 addr = cpu_get_indexed_operand_addr (cpu, restrict);
354 return memory_read16 (cpu, addr);
358 cpu_move8 (sim_cpu *cpu, uint8 code)
366 src = cpu_fetch8 (cpu);
367 addr = cpu_fetch16 (cpu);
371 addr = cpu_get_indexed_operand_addr (cpu, 1);
372 src = cpu_fetch8 (cpu);
376 addr = cpu_fetch16 (cpu);
377 src = memory_read8 (cpu, addr);
378 addr = cpu_fetch16 (cpu);
382 addr = cpu_get_indexed_operand_addr (cpu, 1);
383 src = memory_read8 (cpu, cpu_fetch16 (cpu));
387 src = cpu_get_indexed_operand8 (cpu, 1);
388 addr = cpu_fetch16 (cpu);
392 src = cpu_get_indexed_operand8 (cpu, 1);
393 addr = cpu_get_indexed_operand_addr (cpu, 1);
397 sim_engine_abort (CPU_STATE (cpu), cpu, 0,
398 "Invalid code 0x%0x -- internal error?", code);
401 memory_write8 (cpu, addr, src);
405 cpu_move16 (sim_cpu *cpu, uint8 code)
413 src = cpu_fetch16 (cpu);
414 addr = cpu_fetch16 (cpu);
418 addr = cpu_get_indexed_operand_addr (cpu, 1);
419 src = cpu_fetch16 (cpu);
423 addr = cpu_fetch16 (cpu);
424 src = memory_read16 (cpu, addr);
425 addr = cpu_fetch16 (cpu);
429 addr = cpu_get_indexed_operand_addr (cpu, 1);
430 src = memory_read16 (cpu, cpu_fetch16 (cpu));
434 src = cpu_get_indexed_operand16 (cpu, 1);
435 addr = cpu_fetch16 (cpu);
439 src = cpu_get_indexed_operand16 (cpu, 1);
440 addr = cpu_get_indexed_operand_addr (cpu, 1);
444 sim_engine_abort (CPU_STATE (cpu), cpu, 0,
445 "Invalid code 0x%0x -- internal error?", code);
448 memory_write16 (cpu, addr, src);
452 cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
454 sim_add_option_table (sd, 0, cpu_options);
456 memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
458 cpu->cpu_absolute_cycle = 0;
459 cpu->cpu_current_cycle = 0;
460 cpu->cpu_emul_syscall = 1;
461 cpu->cpu_running = 1;
462 cpu->cpu_stop_on_interrupt = 0;
463 cpu->cpu_frequency = 8 * 1000 * 1000;
464 cpu->cpu_use_elf_start = 0;
465 cpu->cpu_elf_start = 0;
466 cpu->cpu_use_local_config = 0;
467 cpu->cpu_config = M6811_NOSEC | M6811_NOCOP | M6811_ROMON |
469 interrupts_initialize (sd, cpu);
471 cpu->cpu_is_initialized = 1;
476 /* Reinitialize the processor after a reset. */
478 cpu_reset (sim_cpu *cpu)
480 /* Initialize the config register.
481 It is only initialized at reset time. */
482 memset (cpu->ios, 0, sizeof (cpu->ios));
483 if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
484 cpu->ios[M6811_INIT] = 0x1;
486 cpu->ios[M6811_INIT] = 0;
488 /* Output compare registers set to 0xFFFF. */
489 cpu->ios[M6811_TOC1_H] = 0xFF;
490 cpu->ios[M6811_TOC1_L] = 0xFF;
491 cpu->ios[M6811_TOC2_H] = 0xFF;
492 cpu->ios[M6811_TOC2_L] = 0xFF;
493 cpu->ios[M6811_TOC3_H] = 0xFF;
494 cpu->ios[M6811_TOC4_L] = 0xFF;
495 cpu->ios[M6811_TOC5_H] = 0xFF;
496 cpu->ios[M6811_TOC5_L] = 0xFF;
498 /* Setup the processor registers. */
499 memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
500 cpu->cpu_absolute_cycle = 0;
501 cpu->cpu_current_cycle = 0;
502 cpu->cpu_is_initialized = 0;
504 /* Reset interrupts. */
505 interrupts_reset (&cpu->cpu_interrupts);
507 /* Reinitialize the CPU operating mode. */
508 cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
512 /* Reinitialize the processor after a reset. */
514 cpu_restart (sim_cpu *cpu)
518 /* Get CPU starting address depending on the CPU mode. */
519 if (cpu->cpu_use_elf_start == 0)
521 switch ((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA))
526 addr = memory_read16 (cpu, 0xFFFE);
529 /* Expanded Multiplexed */
531 addr = memory_read16 (cpu, 0xFFFE);
534 /* Special Bootstrap */
540 case M6811_MDA | M6811_SMOD:
541 addr = memory_read16 (cpu, 0xFFFE);
547 addr = cpu->cpu_elf_start;
550 /* Setup the processor registers. */
551 cpu->cpu_insn_pc = addr;
552 cpu->cpu_regs.pc = addr;
553 cpu->cpu_regs.ccr = M6811_X_BIT | M6811_I_BIT | M6811_S_BIT;
554 cpu->cpu_absolute_cycle = 0;
555 cpu->cpu_is_initialized = 1;
556 cpu->cpu_current_cycle = 0;
558 cpu_call (cpu, addr);
564 print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val, int mode)
568 if (val & desc->mask)
569 sim_io_printf (sd, "%s",
570 mode == 0 ? desc->short_name : desc->long_name);
576 print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
577 uint8 val, uint16 addr)
579 sim_io_printf (sd, " %-9.9s @ 0x%04x 0x%02x ", name, addr, val);
581 print_io_reg_desc (sd, desc, val, 0);
585 cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val)
587 cpu_set_ccr_V (proc, 0);
588 cpu_set_ccr_N (proc, val & 0x80 ? 1 : 0);
589 cpu_set_ccr_Z (proc, val == 0 ? 1 : 0);
594 cpu_fetch_relbranch (sim_cpu *cpu)
596 uint16 addr = (uint16) cpu_fetch8 (cpu);
602 addr += cpu->cpu_regs.pc;
607 cpu_fetch_relbranch16 (sim_cpu *cpu)
609 uint16 addr = cpu_fetch16 (cpu);
611 addr += cpu->cpu_regs.pc;
615 /* Push all the CPU registers (when an interruption occurs). */
617 cpu_push_all (sim_cpu *cpu)
619 if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
621 cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.pc);
622 cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.iy);
623 cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.ix);
624 cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.d);
625 cpu_m68hc11_push_uint8 (cpu, cpu->cpu_regs.ccr);
629 cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.pc);
630 cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.iy);
631 cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.ix);
632 cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.d);
633 cpu_m68hc12_push_uint8 (cpu, cpu->cpu_regs.ccr);
637 /* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations. */
639 cpu_dbcc (sim_cpu* cpu)
646 code = cpu_fetch8 (cpu);
649 case 0x80: /* ibcc */
652 case 0x40: /* tbcc */
663 addr = cpu_fetch8 (cpu);
667 addr += cpu_get_pc (cpu);
668 reg = cpu_get_src_reg (cpu, code & 0x07);
671 /* Branch according to register value. */
672 if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
674 cpu_set_pc (cpu, addr);
676 cpu_set_dst_reg (cpu, code & 0x07, reg);
680 cpu_exg (sim_cpu* cpu, uint8 code)
686 r1 = (code >> 4) & 0x07;
690 src1 = cpu_get_src_reg (cpu, r1);
691 src2 = cpu_get_src_reg (cpu, r2);
692 if (r2 == 1 || r2 == 2)
695 cpu_set_dst_reg (cpu, r2, src1);
696 cpu_set_dst_reg (cpu, r1, src2);
700 src1 = cpu_get_src_reg (cpu, r1);
702 /* Sign extend the 8-bit registers (A, B, CCR). */
703 if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
706 cpu_set_dst_reg (cpu, r2, src1);
710 /* Handle special instructions. */
712 cpu_special (sim_cpu *cpu, enum M6811_Special special)
720 ccr = cpu_m68hc11_pop_uint8 (cpu);
721 cpu_set_ccr (cpu, ccr);
722 cpu_set_d (cpu, cpu_m68hc11_pop_uint16 (cpu));
723 cpu_set_x (cpu, cpu_m68hc11_pop_uint16 (cpu));
724 cpu_set_y (cpu, cpu_m68hc11_pop_uint16 (cpu));
725 cpu_set_pc (cpu, cpu_m68hc11_pop_uint16 (cpu));
734 ccr = cpu_m68hc12_pop_uint8 (cpu);
735 cpu_set_ccr (cpu, ccr);
736 cpu_set_d (cpu, cpu_m68hc12_pop_uint16 (cpu));
737 cpu_set_x (cpu, cpu_m68hc12_pop_uint16 (cpu));
738 cpu_set_y (cpu, cpu_m68hc12_pop_uint16 (cpu));
739 cpu_set_pc (cpu, cpu_m68hc12_pop_uint16 (cpu));
745 /* In the ELF-start mode, we are in a special mode where
746 the WAI corresponds to an exit. */
747 if (cpu->cpu_use_elf_start)
749 cpu_set_pc (cpu, cpu->cpu_insn_pc);
750 sim_engine_halt (CPU_STATE (cpu), cpu,
751 NULL, NULL_CIA, sim_exited,
755 /* SCz: not correct... */
760 interrupts_raise (&cpu->cpu_interrupts, M6811_INT_SWI);
761 interrupts_process (&cpu->cpu_interrupts);
764 case M6811_EMUL_SYSCALL:
766 if (cpu->cpu_emul_syscall)
768 uint8 op = memory_read8 (cpu,
769 cpu_get_pc (cpu) - 1);
772 cpu_set_pc (cpu, cpu->cpu_insn_pc);
773 sim_engine_halt (CPU_STATE (cpu), cpu,
774 NULL, NULL_CIA, sim_exited,
785 interrupts_raise (&cpu->cpu_interrupts, M6811_INT_ILLEGAL);
786 interrupts_process (&cpu->cpu_interrupts);
794 sd = CPU_STATE (cpu);
796 /* Breakpoint instruction if we are under gdb. */
797 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
800 sim_engine_halt (CPU_STATE (cpu), cpu,
801 0, cpu_get_pc (cpu), sim_stopped,
804 /* else this is a nop but not in test factory mode. */
810 int32 src1 = (int16) cpu_get_d (cpu);
811 int32 src2 = (int16) cpu_get_x (cpu);
815 cpu_set_ccr_C (cpu, 1);
819 cpu_set_d (cpu, src1 % src2);
821 cpu_set_x (cpu, src1);
822 cpu_set_ccr_C (cpu, 0);
823 cpu_set_ccr_Z (cpu, src1 == 0);
824 cpu_set_ccr_N (cpu, src1 & 0x8000);
825 cpu_set_ccr_V (cpu, src1 >= 32768 || src1 < -32768);
832 uint32 src1 = (uint32) cpu_get_x (cpu);
833 uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
834 | (uint32) (cpu_get_d (cpu));
838 cpu_set_ccr_C (cpu, 1);
842 cpu_set_ccr_C (cpu, 0);
843 cpu_set_d (cpu, src2 % src1);
845 cpu_set_y (cpu, src2);
846 cpu_set_ccr_Z (cpu, src2 == 0);
847 cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
848 cpu_set_ccr_V (cpu, (src2 & 0xffff0000) != 0);
855 int32 src1 = (int16) cpu_get_x (cpu);
856 int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
857 | (uint32) (cpu_get_d (cpu));
861 cpu_set_ccr_C (cpu, 1);
865 cpu_set_ccr_C (cpu, 0);
866 cpu_set_d (cpu, src2 % src1);
868 cpu_set_y (cpu, src2);
869 cpu_set_ccr_Z (cpu, src2 == 0);
870 cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
871 cpu_set_ccr_V (cpu, src2 > 32767 || src2 < -32768);
880 src1 = (int16) cpu_get_d (cpu);
881 src2 = (int16) cpu_get_y (cpu);
883 cpu_set_d (cpu, src1 & 0x0ffff);
884 cpu_set_y (cpu, src1 >> 16);
885 cpu_set_ccr_Z (cpu, src1 == 0);
886 cpu_set_ccr_N (cpu, (src1 & 0x80000000) != 0);
887 cpu_set_ccr_C (cpu, (src1 & 0x00008000) != 0);
896 addr = cpu_fetch16 (cpu);
897 src1 = (int16) memory_read16 (cpu, cpu_get_x (cpu));
898 src2 = (int16) memory_read16 (cpu, cpu_get_y (cpu));
900 src2 = (((uint32) memory_read16 (cpu, addr)) << 16)
901 | (uint32) memory_read16 (cpu, addr + 2);
903 memory_write16 (cpu, addr, (src1 + src2) >> 16);
904 memory_write16 (cpu, addr + 2, (src1 + src2));
912 sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
913 cpu_get_pc (cpu), sim_stopped,
921 cpu_single_step (sim_cpu *cpu)
923 cpu->cpu_current_cycle = 0;
924 cpu->cpu_insn_pc = cpu_get_pc (cpu);
926 /* Handle the pending interrupts. If an interrupt is handled,
927 treat this as an single step. */
928 if (interrupts_process (&cpu->cpu_interrupts))
930 cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
934 /* printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
935 cpu->cpu_interpretor (cpu);
936 cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
941 sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
942 uint16 addr, const char *message, ...)
947 va_start (args, message);
948 vsprintf (buf, message, args);
951 sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
952 cpu_memory_exception (cpu, excep, addr, buf);
957 cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep,
958 uint16 addr, const char *message)
960 if (cpu->cpu_running == 0)
963 cpu_set_pc (cpu, cpu->cpu_insn_pc);
964 sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
965 cpu_get_pc (cpu), sim_stopped, excep);
968 cpu->mem_exception = excep;
969 cpu->fault_addr = addr;
970 cpu->fault_msg = strdup (message);
972 if (cpu->cpu_use_handler)
974 longjmp (&cpu->cpu_exception_handler, 1);
976 (* cpu->callback->printf_filtered)
977 (cpu->callback, "Fault at 0x%04x: %s\n", addr, message);
982 cpu_info (SIM_DESC sd, sim_cpu *cpu)
984 sim_io_printf (sd, "CPU info:\n");
985 sim_io_printf (sd, " Absolute cycle: %s\n",
986 cycle_to_string (cpu, cpu->cpu_absolute_cycle));
988 sim_io_printf (sd, " Syscall emulation: %s\n",
989 cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");
990 sim_io_printf (sd, " Memory errors detection: %s\n",
991 cpu->cpu_check_memory ? "yes" : "no");
992 sim_io_printf (sd, " Stop on interrupt: %s\n",
993 cpu->cpu_stop_on_interrupt ? "yes" : "no");