Fix up mix of man(7)/mdoc(7).
[netbsd-mini2440.git] / gnu / dist / gdb6 / sim / m68hc11 / m68hc11_sim.c
blob444147b9492bb1e036d0370c4a0173dbccd1a601
1 /* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
2 Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@nerim.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. */
21 #include "sim-main.h"
22 #include "sim-assert.h"
23 #include "sim-module.h"
24 #include "sim-options.h"
26 enum {
27 OPTION_CPU_RESET = OPTION_START,
28 OPTION_EMUL_OS,
29 OPTION_CPU_CONFIG,
30 OPTION_CPU_BOOTSTRAP,
31 OPTION_CPU_MODE
34 static DECLARE_OPTION_HANDLER (cpu_option_handler);
36 static const OPTION cpu_options[] =
38 { {"cpu-reset", no_argument, NULL, OPTION_CPU_RESET },
39 '\0', NULL, "Reset the CPU",
40 cpu_option_handler },
42 { {"emulos", no_argument, NULL, OPTION_EMUL_OS },
43 '\0', NULL, "Emulate some OS system calls (read, write, ...)",
44 cpu_option_handler },
46 { {"cpu-config", required_argument, NULL, OPTION_CPU_CONFIG },
47 '\0', NULL, "Specify the initial CPU configuration register",
48 cpu_option_handler },
50 { {"bootstrap", no_argument, NULL, OPTION_CPU_BOOTSTRAP },
51 '\0', NULL, "Start the processing in bootstrap mode",
52 cpu_option_handler },
54 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
58 static SIM_RC
59 cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
60 int opt, char *arg, int is_command)
62 int val;
64 cpu = STATE_CPU (sd, 0);
65 switch (opt)
67 case OPTION_CPU_RESET:
68 sim_board_reset (sd);
69 break;
71 case OPTION_EMUL_OS:
72 cpu->cpu_emul_syscall = 1;
73 break;
75 case OPTION_CPU_CONFIG:
76 if (sscanf(arg, "0x%x", &val) == 1
77 || sscanf(arg, "%d", &val) == 1)
79 cpu->cpu_config = val;
80 cpu->cpu_use_local_config = 1;
82 else
83 cpu->cpu_use_local_config = 0;
84 break;
86 case OPTION_CPU_BOOTSTRAP:
87 cpu->cpu_start_mode = "bootstrap";
88 break;
90 case OPTION_CPU_MODE:
91 break;
94 return SIM_RC_OK;
98 void
99 cpu_call (sim_cpu *cpu, uint16 addr)
102 cpu_set_pc (cpu, addr);
105 void
106 cpu_return (sim_cpu *cpu)
110 /* Set the stack pointer and re-compute the current frame. */
111 void
112 cpu_set_sp (sim_cpu *cpu, uint16 val)
114 cpu->cpu_regs.sp = val;
117 uint16
118 cpu_get_reg (sim_cpu* cpu, uint8 reg)
120 switch (reg)
122 case 0:
123 return cpu_get_x (cpu);
125 case 1:
126 return cpu_get_y (cpu);
128 case 2:
129 return cpu_get_sp (cpu);
131 case 3:
132 return cpu_get_pc (cpu);
134 default:
135 return 0;
139 uint16
140 cpu_get_src_reg (sim_cpu* cpu, uint8 reg)
142 switch (reg)
144 case 0:
145 return cpu_get_a (cpu);
147 case 1:
148 return cpu_get_b (cpu);
150 case 2:
151 return cpu_get_ccr (cpu);
153 case 3:
154 return cpu_get_tmp3 (cpu);
156 case 4:
157 return cpu_get_d (cpu);
159 case 5:
160 return cpu_get_x (cpu);
162 case 6:
163 return cpu_get_y (cpu);
165 case 7:
166 return cpu_get_sp (cpu);
168 default:
169 return 0;
173 void
174 cpu_set_dst_reg (sim_cpu* cpu, uint8 reg, uint16 val)
176 switch (reg)
178 case 0:
179 cpu_set_a (cpu, val);
180 break;
182 case 1:
183 cpu_set_b (cpu, val);
184 break;
186 case 2:
187 cpu_set_ccr (cpu, val);
188 break;
190 case 3:
191 cpu_set_tmp2 (cpu, val);
192 break;
194 case 4:
195 cpu_set_d (cpu, val);
196 break;
198 case 5:
199 cpu_set_x (cpu, val);
200 break;
202 case 6:
203 cpu_set_y (cpu, val);
204 break;
206 case 7:
207 cpu_set_sp (cpu, val);
208 break;
210 default:
211 break;
215 void
216 cpu_set_reg (sim_cpu* cpu, uint8 reg, uint16 val)
218 switch (reg)
220 case 0:
221 cpu_set_x (cpu, val);
222 break;
224 case 1:
225 cpu_set_y (cpu, val);
226 break;
228 case 2:
229 cpu_set_sp (cpu, val);
230 break;
232 case 3:
233 cpu_set_pc (cpu, val);
234 break;
236 default:
237 break;
241 /* Returns the address of a 68HC12 indexed operand.
242 Pre and post modifications are handled on the source register. */
243 uint16
244 cpu_get_indexed_operand_addr (sim_cpu* cpu, int restrict)
246 uint8 reg;
247 uint16 sval;
248 uint16 addr;
249 uint8 code;
251 code = cpu_fetch8 (cpu);
253 /* n,r with 5-bit signed constant. */
254 if ((code & 0x20) == 0)
256 reg = (code >> 6) & 3;
257 sval = (code & 0x1f);
258 if (code & 0x10)
259 sval |= 0xfff0;
261 addr = cpu_get_reg (cpu, reg);
262 addr += sval;
265 /* Auto pre/post increment/decrement. */
266 else if ((code & 0xc0) != 0xc0)
268 reg = (code >> 6) & 3;
269 sval = (code & 0x0f);
270 if (sval & 0x8)
272 sval |= 0xfff0;
274 else
276 sval = sval + 1;
278 addr = cpu_get_reg (cpu, reg);
279 cpu_set_reg (cpu, reg, addr + sval);
280 if ((code & 0x10) == 0)
282 addr += sval;
286 /* [n,r] 16-bits offset indexed indirect. */
287 else if ((code & 0x07) == 3)
289 if (restrict)
291 return 0;
293 reg = (code >> 3) & 0x03;
294 addr = cpu_get_reg (cpu, reg);
295 addr += cpu_fetch16 (cpu);
296 addr = memory_read16 (cpu, addr);
297 cpu_add_cycles (cpu, 1);
299 else if ((code & 0x4) == 0)
301 if (restrict)
303 return 0;
305 reg = (code >> 3) & 0x03;
306 addr = cpu_get_reg (cpu, reg);
307 if (code & 0x2)
309 sval = cpu_fetch16 (cpu);
310 cpu_add_cycles (cpu, 1);
312 else
314 sval = cpu_fetch8 (cpu);
315 if (code & 0x1)
316 sval |= 0xff00;
317 cpu_add_cycles (cpu, 1);
319 addr += sval;
321 else
323 reg = (code >> 3) & 0x03;
324 addr = cpu_get_reg (cpu, reg);
325 switch (code & 3)
327 case 0:
328 addr += cpu_get_a (cpu);
329 break;
330 case 1:
331 addr += cpu_get_b (cpu);
332 break;
333 case 2:
334 addr += cpu_get_d (cpu);
335 break;
336 case 3:
337 default:
338 addr += cpu_get_d (cpu);
339 addr = memory_read16 (cpu, addr);
340 cpu_add_cycles (cpu, 1);
341 break;
345 return addr;
348 uint8
349 cpu_get_indexed_operand8 (sim_cpu* cpu, int restrict)
351 uint16 addr;
353 addr = cpu_get_indexed_operand_addr (cpu, restrict);
354 return memory_read8 (cpu, addr);
357 uint16
358 cpu_get_indexed_operand16 (sim_cpu* cpu, int restrict)
360 uint16 addr;
362 addr = cpu_get_indexed_operand_addr (cpu, restrict);
363 return memory_read16 (cpu, addr);
366 void
367 cpu_move8 (sim_cpu *cpu, uint8 code)
369 uint8 src;
370 uint16 addr;
372 switch (code)
374 case 0x0b:
375 src = cpu_fetch8 (cpu);
376 addr = cpu_fetch16 (cpu);
377 break;
379 case 0x08:
380 addr = cpu_get_indexed_operand_addr (cpu, 1);
381 src = cpu_fetch8 (cpu);
382 break;
384 case 0x0c:
385 addr = cpu_fetch16 (cpu);
386 src = memory_read8 (cpu, addr);
387 addr = cpu_fetch16 (cpu);
388 break;
390 case 0x09:
391 addr = cpu_get_indexed_operand_addr (cpu, 1);
392 src = memory_read8 (cpu, cpu_fetch16 (cpu));
393 break;
395 case 0x0d:
396 src = cpu_get_indexed_operand8 (cpu, 1);
397 addr = cpu_fetch16 (cpu);
398 break;
400 case 0x0a:
401 src = cpu_get_indexed_operand8 (cpu, 1);
402 addr = cpu_get_indexed_operand_addr (cpu, 1);
403 break;
405 default:
406 sim_engine_abort (CPU_STATE (cpu), cpu, 0,
407 "Invalid code 0x%0x -- internal error?", code);
408 return;
410 memory_write8 (cpu, addr, src);
413 void
414 cpu_move16 (sim_cpu *cpu, uint8 code)
416 uint16 src;
417 uint16 addr;
419 switch (code)
421 case 0x03:
422 src = cpu_fetch16 (cpu);
423 addr = cpu_fetch16 (cpu);
424 break;
426 case 0x00:
427 addr = cpu_get_indexed_operand_addr (cpu, 1);
428 src = cpu_fetch16 (cpu);
429 break;
431 case 0x04:
432 addr = cpu_fetch16 (cpu);
433 src = memory_read16 (cpu, addr);
434 addr = cpu_fetch16 (cpu);
435 break;
437 case 0x01:
438 addr = cpu_get_indexed_operand_addr (cpu, 1);
439 src = memory_read16 (cpu, cpu_fetch16 (cpu));
440 break;
442 case 0x05:
443 src = cpu_get_indexed_operand16 (cpu, 1);
444 addr = cpu_fetch16 (cpu);
445 break;
447 case 0x02:
448 src = cpu_get_indexed_operand16 (cpu, 1);
449 addr = cpu_get_indexed_operand_addr (cpu, 1);
450 break;
452 default:
453 sim_engine_abort (CPU_STATE (cpu), cpu, 0,
454 "Invalid code 0x%0x -- internal error?", code);
455 return;
457 memory_write16 (cpu, addr, src);
461 cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
463 sim_add_option_table (sd, 0, cpu_options);
465 memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
467 cpu->cpu_absolute_cycle = 0;
468 cpu->cpu_current_cycle = 0;
469 cpu->cpu_emul_syscall = 1;
470 cpu->cpu_running = 1;
471 cpu->cpu_stop_on_interrupt = 0;
472 cpu->cpu_frequency = 8 * 1000 * 1000;
473 cpu->cpu_use_elf_start = 0;
474 cpu->cpu_elf_start = 0;
475 cpu->cpu_use_local_config = 0;
476 cpu->bank_start = 0;
477 cpu->bank_end = 0;
478 cpu->bank_shift = 0;
479 cpu->cpu_config = M6811_NOSEC | M6811_NOCOP | M6811_ROMON |
480 M6811_EEON;
481 interrupts_initialize (sd, cpu);
483 cpu->cpu_is_initialized = 1;
484 return 0;
488 /* Reinitialize the processor after a reset. */
490 cpu_reset (sim_cpu *cpu)
492 /* Initialize the config register.
493 It is only initialized at reset time. */
494 memset (cpu->ios, 0, sizeof (cpu->ios));
495 if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
496 cpu->ios[M6811_INIT] = 0x1;
497 else
498 cpu->ios[M6811_INIT] = 0;
500 /* Output compare registers set to 0xFFFF. */
501 cpu->ios[M6811_TOC1_H] = 0xFF;
502 cpu->ios[M6811_TOC1_L] = 0xFF;
503 cpu->ios[M6811_TOC2_H] = 0xFF;
504 cpu->ios[M6811_TOC2_L] = 0xFF;
505 cpu->ios[M6811_TOC3_H] = 0xFF;
506 cpu->ios[M6811_TOC4_L] = 0xFF;
507 cpu->ios[M6811_TOC5_H] = 0xFF;
508 cpu->ios[M6811_TOC5_L] = 0xFF;
510 /* Setup the processor registers. */
511 memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
512 cpu->cpu_absolute_cycle = 0;
513 cpu->cpu_current_cycle = 0;
514 cpu->cpu_is_initialized = 0;
516 /* Reset interrupts. */
517 interrupts_reset (&cpu->cpu_interrupts);
519 /* Reinitialize the CPU operating mode. */
520 cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
521 return 0;
524 /* Reinitialize the processor after a reset. */
526 cpu_restart (sim_cpu *cpu)
528 uint16 addr;
530 /* Get CPU starting address depending on the CPU mode. */
531 if (cpu->cpu_use_elf_start == 0)
533 switch ((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA))
535 /* Single Chip */
536 default:
537 case 0 :
538 addr = memory_read16 (cpu, 0xFFFE);
539 break;
541 /* Expanded Multiplexed */
542 case M6811_MDA:
543 addr = memory_read16 (cpu, 0xFFFE);
544 break;
546 /* Special Bootstrap */
547 case M6811_SMOD:
548 addr = 0;
549 break;
551 /* Factory Test */
552 case M6811_MDA | M6811_SMOD:
553 addr = memory_read16 (cpu, 0xFFFE);
554 break;
557 else
559 addr = cpu->cpu_elf_start;
562 /* Setup the processor registers. */
563 cpu->cpu_insn_pc = addr;
564 cpu->cpu_regs.pc = addr;
565 cpu->cpu_regs.ccr = M6811_X_BIT | M6811_I_BIT | M6811_S_BIT;
566 cpu->cpu_absolute_cycle = 0;
567 cpu->cpu_is_initialized = 1;
568 cpu->cpu_current_cycle = 0;
570 cpu_call (cpu, addr);
572 return 0;
575 void
576 print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val, int mode)
578 while (desc->mask)
580 if (val & desc->mask)
581 sim_io_printf (sd, "%s",
582 mode == 0 ? desc->short_name : desc->long_name);
583 desc++;
587 void
588 print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
589 uint8 val, uint16 addr)
591 sim_io_printf (sd, " %-9.9s @ 0x%04x 0x%02x ", name, addr, val);
592 if (desc)
593 print_io_reg_desc (sd, desc, val, 0);
596 void
597 print_io_word (SIM_DESC sd, const char *name, io_reg_desc *desc,
598 uint16 val, uint16 addr)
600 sim_io_printf (sd, " %-9.9s @ 0x%04x 0x%04x ", name, addr, val);
601 if (desc)
602 print_io_reg_desc (sd, desc, val, 0);
605 void
606 cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val)
608 cpu_set_ccr_V (proc, 0);
609 cpu_set_ccr_N (proc, val & 0x80 ? 1 : 0);
610 cpu_set_ccr_Z (proc, val == 0 ? 1 : 0);
614 uint16
615 cpu_fetch_relbranch (sim_cpu *cpu)
617 uint16 addr = (uint16) cpu_fetch8 (cpu);
619 if (addr & 0x0080)
621 addr |= 0xFF00;
623 addr += cpu->cpu_regs.pc;
624 return addr;
627 uint16
628 cpu_fetch_relbranch16 (sim_cpu *cpu)
630 uint16 addr = cpu_fetch16 (cpu);
632 addr += cpu->cpu_regs.pc;
633 return addr;
636 /* Push all the CPU registers (when an interruption occurs). */
637 void
638 cpu_push_all (sim_cpu *cpu)
640 if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
642 cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.pc);
643 cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.iy);
644 cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.ix);
645 cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.d);
646 cpu_m68hc11_push_uint8 (cpu, cpu->cpu_regs.ccr);
648 else
650 cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.pc);
651 cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.iy);
652 cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.ix);
653 cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.d);
654 cpu_m68hc12_push_uint8 (cpu, cpu->cpu_regs.ccr);
658 /* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations. */
659 void
660 cpu_dbcc (sim_cpu* cpu)
662 uint8 code;
663 uint16 addr;
664 uint16 inc;
665 uint16 reg;
667 code = cpu_fetch8 (cpu);
668 switch (code & 0xc0)
670 case 0x80: /* ibcc */
671 inc = 1;
672 break;
673 case 0x40: /* tbcc */
674 inc = 0;
675 break;
676 case 0: /* dbcc */
677 inc = -1;
678 break;
679 default:
680 abort ();
681 break;
684 addr = cpu_fetch8 (cpu);
685 if (code & 0x10)
686 addr |= 0xff00;
688 addr += cpu_get_pc (cpu);
689 reg = cpu_get_src_reg (cpu, code & 0x07);
690 reg += inc;
692 /* Branch according to register value. */
693 if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
695 cpu_set_pc (cpu, addr);
697 cpu_set_dst_reg (cpu, code & 0x07, reg);
700 void
701 cpu_exg (sim_cpu* cpu, uint8 code)
703 uint8 r1, r2;
704 uint16 src1;
705 uint16 src2;
707 r1 = (code >> 4) & 0x07;
708 r2 = code & 0x07;
709 if (code & 0x80)
711 src1 = cpu_get_src_reg (cpu, r1);
712 src2 = cpu_get_src_reg (cpu, r2);
713 if (r2 == 1 || r2 == 2)
714 src2 |= 0xff00;
716 cpu_set_dst_reg (cpu, r2, src1);
717 cpu_set_dst_reg (cpu, r1, src2);
719 else
721 src1 = cpu_get_src_reg (cpu, r1);
723 /* Sign extend the 8-bit registers (A, B, CCR). */
724 if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
725 src1 |= 0xff00;
727 cpu_set_dst_reg (cpu, r2, src1);
731 /* Handle special instructions. */
732 void
733 cpu_special (sim_cpu *cpu, enum M6811_Special special)
735 switch (special)
737 case M6811_RTI:
739 uint8 ccr;
741 ccr = cpu_m68hc11_pop_uint8 (cpu);
742 cpu_set_ccr (cpu, ccr);
743 cpu_set_d (cpu, cpu_m68hc11_pop_uint16 (cpu));
744 cpu_set_x (cpu, cpu_m68hc11_pop_uint16 (cpu));
745 cpu_set_y (cpu, cpu_m68hc11_pop_uint16 (cpu));
746 cpu_set_pc (cpu, cpu_m68hc11_pop_uint16 (cpu));
747 cpu_return (cpu);
748 break;
751 case M6812_RTI:
753 uint8 ccr;
755 ccr = cpu_m68hc12_pop_uint8 (cpu);
756 cpu_set_ccr (cpu, ccr);
757 cpu_set_d (cpu, cpu_m68hc12_pop_uint16 (cpu));
758 cpu_set_x (cpu, cpu_m68hc12_pop_uint16 (cpu));
759 cpu_set_y (cpu, cpu_m68hc12_pop_uint16 (cpu));
760 cpu_set_pc (cpu, cpu_m68hc12_pop_uint16 (cpu));
761 cpu_return (cpu);
762 break;
765 case M6811_WAI:
766 /* In the ELF-start mode, we are in a special mode where
767 the WAI corresponds to an exit. */
768 if (cpu->cpu_use_elf_start)
770 cpu_set_pc (cpu, cpu->cpu_insn_pc);
771 sim_engine_halt (CPU_STATE (cpu), cpu,
772 NULL, NULL_CIA, sim_exited,
773 cpu_get_d (cpu));
774 return;
776 /* SCz: not correct... */
777 cpu_push_all (cpu);
778 break;
780 case M6811_SWI:
781 interrupts_raise (&cpu->cpu_interrupts, M6811_INT_SWI);
782 interrupts_process (&cpu->cpu_interrupts);
783 break;
785 case M6811_EMUL_SYSCALL:
786 case M6811_ILLEGAL:
787 if (cpu->cpu_emul_syscall)
789 uint8 op = memory_read8 (cpu,
790 cpu_get_pc (cpu) - 1);
791 if (op == 0x41)
793 cpu_set_pc (cpu, cpu->cpu_insn_pc);
794 sim_engine_halt (CPU_STATE (cpu), cpu,
795 NULL, NULL_CIA, sim_exited,
796 cpu_get_d (cpu));
797 return;
799 else
801 emul_os (op, cpu);
803 return;
806 interrupts_raise (&cpu->cpu_interrupts, M6811_INT_ILLEGAL);
807 interrupts_process (&cpu->cpu_interrupts);
808 break;
810 case M6811_TEST:
811 case M6812_BGND:
813 SIM_DESC sd;
815 sd = CPU_STATE (cpu);
817 /* Breakpoint instruction if we are under gdb. */
818 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
820 cpu->cpu_regs.pc --;
821 sim_engine_halt (CPU_STATE (cpu), cpu,
822 0, cpu_get_pc (cpu), sim_stopped,
823 SIM_SIGTRAP);
825 /* else this is a nop but not in test factory mode. */
826 break;
829 case M6812_IDIVS:
831 int32 src1 = (int16) cpu_get_d (cpu);
832 int32 src2 = (int16) cpu_get_x (cpu);
834 if (src2 == 0)
836 cpu_set_ccr_C (cpu, 1);
838 else
840 cpu_set_d (cpu, src1 % src2);
841 src1 = src1 / src2;
842 cpu_set_x (cpu, src1);
843 cpu_set_ccr_C (cpu, 0);
844 cpu_set_ccr_Z (cpu, src1 == 0);
845 cpu_set_ccr_N (cpu, src1 & 0x8000);
846 cpu_set_ccr_V (cpu, src1 >= 32768 || src1 < -32768);
849 break;
851 case M6812_EDIV:
853 uint32 src1 = (uint32) cpu_get_x (cpu);
854 uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
855 | (uint32) (cpu_get_d (cpu));
857 if (src1 == 0)
859 cpu_set_ccr_C (cpu, 1);
861 else
863 cpu_set_ccr_C (cpu, 0);
864 cpu_set_d (cpu, src2 % src1);
865 src2 = src2 / src1;
866 cpu_set_y (cpu, src2);
867 cpu_set_ccr_Z (cpu, src2 == 0);
868 cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
869 cpu_set_ccr_V (cpu, (src2 & 0xffff0000) != 0);
872 break;
874 case M6812_EDIVS:
876 int32 src1 = (int16) cpu_get_x (cpu);
877 int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
878 | (uint32) (cpu_get_d (cpu));
880 if (src1 == 0)
882 cpu_set_ccr_C (cpu, 1);
884 else
886 cpu_set_ccr_C (cpu, 0);
887 cpu_set_d (cpu, src2 % src1);
888 src2 = src2 / src1;
889 cpu_set_y (cpu, src2);
890 cpu_set_ccr_Z (cpu, src2 == 0);
891 cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
892 cpu_set_ccr_V (cpu, src2 > 32767 || src2 < -32768);
895 break;
897 case M6812_EMULS:
899 int32 src1, src2;
901 src1 = (int16) cpu_get_d (cpu);
902 src2 = (int16) cpu_get_y (cpu);
903 src1 = src1 * src2;
904 cpu_set_d (cpu, src1 & 0x0ffff);
905 cpu_set_y (cpu, src1 >> 16);
906 cpu_set_ccr_Z (cpu, src1 == 0);
907 cpu_set_ccr_N (cpu, (src1 & 0x80000000) != 0);
908 cpu_set_ccr_C (cpu, (src1 & 0x00008000) != 0);
910 break;
912 case M6812_EMACS:
914 int32 src1, src2;
915 uint16 addr;
917 addr = cpu_fetch16 (cpu);
918 src1 = (int16) memory_read16 (cpu, cpu_get_x (cpu));
919 src2 = (int16) memory_read16 (cpu, cpu_get_y (cpu));
920 src1 = src1 * src2;
921 src2 = (((uint32) memory_read16 (cpu, addr)) << 16)
922 | (uint32) memory_read16 (cpu, addr + 2);
924 memory_write16 (cpu, addr, (src1 + src2) >> 16);
925 memory_write16 (cpu, addr + 2, (src1 + src2));
929 break;
931 case M6812_CALL:
933 uint8 page;
934 uint16 addr;
936 addr = cpu_fetch16 (cpu);
937 page = cpu_fetch8 (cpu);
939 cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
940 cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
942 cpu_set_page (cpu, page);
943 cpu_set_pc (cpu, addr);
945 break;
947 case M6812_CALL_INDIRECT:
949 uint8 code;
950 uint16 addr;
951 uint8 page;
953 code = memory_read8 (cpu, cpu_get_pc (cpu));
954 /* Indirect addressing call has the page specified in the
955 memory location pointed to by the address. */
956 if ((code & 0xE3) == 0xE3)
958 addr = cpu_get_indexed_operand_addr (cpu, 0);
959 page = memory_read8 (cpu, addr + 2);
960 addr = memory_read16 (cpu, addr);
962 else
964 /* Otherwise, page is in the opcode. */
965 addr = cpu_get_indexed_operand16 (cpu, 0);
966 page = cpu_fetch8 (cpu);
968 cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
969 cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
970 cpu_set_page (cpu, page);
971 cpu_set_pc (cpu, addr);
973 break;
975 case M6812_RTC:
977 uint8 page = cpu_m68hc12_pop_uint8 (cpu);
978 uint16 addr = cpu_m68hc12_pop_uint16 (cpu);
980 cpu_set_page (cpu, page);
981 cpu_set_pc (cpu, addr);
983 break;
985 case M6812_ETBL:
986 default:
987 sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
988 cpu_get_pc (cpu), sim_stopped,
989 SIM_SIGILL);
990 break;
995 void
996 cpu_single_step (sim_cpu *cpu)
998 cpu->cpu_current_cycle = 0;
999 cpu->cpu_insn_pc = cpu_get_pc (cpu);
1001 /* Handle the pending interrupts. If an interrupt is handled,
1002 treat this as an single step. */
1003 if (interrupts_process (&cpu->cpu_interrupts))
1005 cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
1006 return;
1009 /* printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
1010 cpu->cpu_interpretor (cpu);
1011 cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
1014 /* VARARGS */
1015 void
1016 sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
1017 uint16 addr, const char *message, ...)
1019 char buf[1024];
1020 va_list args;
1022 va_start (args, message);
1023 vsprintf (buf, message, args);
1024 va_end (args);
1026 sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
1027 cpu_memory_exception (cpu, excep, addr, buf);
1031 void
1032 cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep,
1033 uint16 addr, const char *message)
1035 if (cpu->cpu_running == 0)
1036 return;
1038 cpu_set_pc (cpu, cpu->cpu_insn_pc);
1039 sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
1040 cpu_get_pc (cpu), sim_stopped, excep);
1042 #if 0
1043 cpu->mem_exception = excep;
1044 cpu->fault_addr = addr;
1045 cpu->fault_msg = strdup (message);
1047 if (cpu->cpu_use_handler)
1049 longjmp (&cpu->cpu_exception_handler, 1);
1051 (* cpu->callback->printf_filtered)
1052 (cpu->callback, "Fault at 0x%04x: %s\n", addr, message);
1053 #endif
1056 void
1057 cpu_info (SIM_DESC sd, sim_cpu *cpu)
1059 sim_io_printf (sd, "CPU info:\n");
1060 sim_io_printf (sd, " Absolute cycle: %s\n",
1061 cycle_to_string (cpu, cpu->cpu_absolute_cycle,
1062 PRINT_TIME | PRINT_CYCLE));
1064 sim_io_printf (sd, " Syscall emulation: %s\n",
1065 cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");
1066 sim_io_printf (sd, " Memory errors detection: %s\n",
1067 cpu->cpu_check_memory ? "yes" : "no");
1068 sim_io_printf (sd, " Stop on interrupt: %s\n",
1069 cpu->cpu_stop_on_interrupt ? "yes" : "no");