]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/m68hc11/m68hc11_sim.c
* m68hc11_sim.c (cpu_special): Handle call and rtc instructions.
[thirdparty/binutils-gdb.git] / sim / m68hc11 / m68hc11_sim.c
1 /* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
2 Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@nerim.fr)
4
5 This file is part of GDB, GAS, and the GNU binutils.
6
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.
11
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.
16
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. */
20
21 #include "sim-main.h"
22 #include "sim-assert.h"
23 #include "sim-module.h"
24 #include "sim-options.h"
25
26 enum {
27 OPTION_CPU_RESET = OPTION_START,
28 OPTION_EMUL_OS,
29 OPTION_CPU_CONFIG,
30 OPTION_CPU_MODE
31 };
32
33 static DECLARE_OPTION_HANDLER (cpu_option_handler);
34
35 static const OPTION cpu_options[] =
36 {
37 { {"cpu-reset", no_argument, NULL, OPTION_CPU_RESET },
38 '\0', NULL, "Reset the CPU",
39 cpu_option_handler },
40
41 { {"emulos", no_argument, NULL, OPTION_EMUL_OS },
42 '\0', NULL, "Emulate some OS system calls (read, write, ...)",
43 cpu_option_handler },
44
45 { {"cpu-config", required_argument, NULL, OPTION_CPU_CONFIG },
46 '\0', NULL, "Specify the initial CPU configuration register",
47 cpu_option_handler },
48
49 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
50 };
51
52
53 static SIM_RC
54 cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
55 int opt, char *arg, int is_command)
56 {
57 int val;
58
59 cpu = STATE_CPU (sd, 0);
60 switch (opt)
61 {
62 case OPTION_CPU_RESET:
63 sim_board_reset (sd);
64 break;
65
66 case OPTION_EMUL_OS:
67 cpu->cpu_emul_syscall = 1;
68 break;
69
70 case OPTION_CPU_CONFIG:
71 if (sscanf(arg, "0x%x", &val) == 1
72 || sscanf(arg, "%d", &val) == 1)
73 {
74 cpu->cpu_config = val;
75 cpu->cpu_use_local_config = 1;
76 }
77 else
78 cpu->cpu_use_local_config = 0;
79 break;
80
81 case OPTION_CPU_MODE:
82 break;
83 }
84
85 return SIM_RC_OK;
86 }
87
88
89 void
90 cpu_call (sim_cpu *cpu, uint16 addr)
91 {
92
93 cpu_set_pc (cpu, addr);
94 }
95
96 void
97 cpu_return (sim_cpu *cpu)
98 {
99 }
100
101 /* Set the stack pointer and re-compute the current frame. */
102 void
103 cpu_set_sp (sim_cpu *cpu, uint16 val)
104 {
105 cpu->cpu_regs.sp = val;
106 }
107
108 uint16
109 cpu_get_reg (sim_cpu* cpu, uint8 reg)
110 {
111 switch (reg)
112 {
113 case 0:
114 return cpu_get_x (cpu);
115
116 case 1:
117 return cpu_get_y (cpu);
118
119 case 2:
120 return cpu_get_sp (cpu);
121
122 case 3:
123 return cpu_get_pc (cpu);
124
125 default:
126 return 0;
127 }
128 }
129
130 uint16
131 cpu_get_src_reg (sim_cpu* cpu, uint8 reg)
132 {
133 switch (reg)
134 {
135 case 0:
136 return cpu_get_a (cpu);
137
138 case 1:
139 return cpu_get_b (cpu);
140
141 case 2:
142 return cpu_get_ccr (cpu);
143
144 case 3:
145 return cpu_get_tmp3 (cpu);
146
147 case 4:
148 return cpu_get_d (cpu);
149
150 case 5:
151 return cpu_get_x (cpu);
152
153 case 6:
154 return cpu_get_y (cpu);
155
156 case 7:
157 return cpu_get_sp (cpu);
158
159 default:
160 return 0;
161 }
162 }
163
164 void
165 cpu_set_dst_reg (sim_cpu* cpu, uint8 reg, uint16 val)
166 {
167 switch (reg)
168 {
169 case 0:
170 cpu_set_a (cpu, val);
171 break;
172
173 case 1:
174 cpu_set_b (cpu, val);
175 break;
176
177 case 2:
178 cpu_set_ccr (cpu, val);
179 break;
180
181 case 3:
182 cpu_set_tmp2 (cpu, val);
183 break;
184
185 case 4:
186 cpu_set_d (cpu, val);
187 break;
188
189 case 5:
190 cpu_set_x (cpu, val);
191 break;
192
193 case 6:
194 cpu_set_y (cpu, val);
195 break;
196
197 case 7:
198 cpu_set_sp (cpu, val);
199 break;
200
201 default:
202 break;
203 }
204 }
205
206 void
207 cpu_set_reg (sim_cpu* cpu, uint8 reg, uint16 val)
208 {
209 switch (reg)
210 {
211 case 0:
212 cpu_set_x (cpu, val);
213 break;
214
215 case 1:
216 cpu_set_y (cpu, val);
217 break;
218
219 case 2:
220 cpu_set_sp (cpu, val);
221 break;
222
223 case 3:
224 cpu_set_pc (cpu, val);
225 break;
226
227 default:
228 break;
229 }
230 }
231
232 /* Returns the address of a 68HC12 indexed operand.
233 Pre and post modifications are handled on the source register. */
234 uint16
235 cpu_get_indexed_operand_addr (sim_cpu* cpu, int restrict)
236 {
237 uint8 reg;
238 uint16 sval;
239 uint16 addr;
240 uint8 code;
241
242 code = cpu_fetch8 (cpu);
243
244 /* n,r with 5-bit signed constant. */
245 if ((code & 0x20) == 0)
246 {
247 reg = (code >> 6) & 3;
248 sval = (code & 0x1f);
249 if (code & 0x10)
250 sval |= 0xfff0;
251
252 addr = cpu_get_reg (cpu, reg);
253 addr += sval;
254 }
255
256 /* Auto pre/post increment/decrement. */
257 else if ((code & 0xc0) != 0xc0)
258 {
259 reg = (code >> 6) & 3;
260 sval = (code & 0x0f);
261 if (sval & 0x8)
262 {
263 sval |= 0xfff0;
264 }
265 else
266 {
267 sval = sval + 1;
268 }
269 addr = cpu_get_reg (cpu, reg);
270 cpu_set_reg (cpu, reg, addr + sval);
271 if ((code & 0x10) == 0)
272 {
273 addr += sval;
274 }
275 }
276
277 /* [n,r] 16-bits offset indexed indirect. */
278 else if ((code & 0x07) == 3)
279 {
280 if (restrict)
281 {
282 return 0;
283 }
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);
289 }
290 else if ((code & 0x4) == 0)
291 {
292 if (restrict)
293 {
294 return 0;
295 }
296 reg = (code >> 3) & 0x03;
297 addr = cpu_get_reg (cpu, reg);
298 if (code & 0x2)
299 {
300 sval = cpu_fetch16 (cpu);
301 cpu_add_cycles (cpu, 1);
302 }
303 else
304 {
305 sval = cpu_fetch8 (cpu);
306 if (code & 0x1)
307 sval |= 0xff00;
308 cpu_add_cycles (cpu, 1);
309 }
310 addr += sval;
311 }
312 else
313 {
314 reg = (code >> 3) & 0x03;
315 addr = cpu_get_reg (cpu, reg);
316 switch (code & 3)
317 {
318 case 0:
319 addr += cpu_get_a (cpu);
320 break;
321 case 1:
322 addr += cpu_get_b (cpu);
323 break;
324 case 2:
325 addr += cpu_get_d (cpu);
326 break;
327 case 3:
328 default:
329 addr += cpu_get_d (cpu);
330 addr = memory_read16 (cpu, addr);
331 cpu_add_cycles (cpu, 1);
332 break;
333 }
334 }
335
336 return addr;
337 }
338
339 uint8
340 cpu_get_indexed_operand8 (sim_cpu* cpu, int restrict)
341 {
342 uint16 addr;
343
344 addr = cpu_get_indexed_operand_addr (cpu, restrict);
345 return memory_read8 (cpu, addr);
346 }
347
348 uint16
349 cpu_get_indexed_operand16 (sim_cpu* cpu, int restrict)
350 {
351 uint16 addr;
352
353 addr = cpu_get_indexed_operand_addr (cpu, restrict);
354 return memory_read16 (cpu, addr);
355 }
356
357 void
358 cpu_move8 (sim_cpu *cpu, uint8 code)
359 {
360 uint8 src;
361 uint16 addr;
362
363 switch (code)
364 {
365 case 0x0b:
366 src = cpu_fetch8 (cpu);
367 addr = cpu_fetch16 (cpu);
368 break;
369
370 case 0x08:
371 addr = cpu_get_indexed_operand_addr (cpu, 1);
372 src = cpu_fetch8 (cpu);
373 break;
374
375 case 0x0c:
376 addr = cpu_fetch16 (cpu);
377 src = memory_read8 (cpu, addr);
378 addr = cpu_fetch16 (cpu);
379 break;
380
381 case 0x09:
382 addr = cpu_get_indexed_operand_addr (cpu, 1);
383 src = memory_read8 (cpu, cpu_fetch16 (cpu));
384 break;
385
386 case 0x0d:
387 src = cpu_get_indexed_operand8 (cpu, 1);
388 addr = cpu_fetch16 (cpu);
389 break;
390
391 case 0x0a:
392 src = cpu_get_indexed_operand8 (cpu, 1);
393 addr = cpu_get_indexed_operand_addr (cpu, 1);
394 break;
395
396 default:
397 sim_engine_abort (CPU_STATE (cpu), cpu, 0,
398 "Invalid code 0x%0x -- internal error?", code);
399 return;
400 }
401 memory_write8 (cpu, addr, src);
402 }
403
404 void
405 cpu_move16 (sim_cpu *cpu, uint8 code)
406 {
407 uint16 src;
408 uint16 addr;
409
410 switch (code)
411 {
412 case 0x03:
413 src = cpu_fetch16 (cpu);
414 addr = cpu_fetch16 (cpu);
415 break;
416
417 case 0x00:
418 addr = cpu_get_indexed_operand_addr (cpu, 1);
419 src = cpu_fetch16 (cpu);
420 break;
421
422 case 0x04:
423 addr = cpu_fetch16 (cpu);
424 src = memory_read16 (cpu, addr);
425 addr = cpu_fetch16 (cpu);
426 break;
427
428 case 0x01:
429 addr = cpu_get_indexed_operand_addr (cpu, 1);
430 src = memory_read16 (cpu, cpu_fetch16 (cpu));
431 break;
432
433 case 0x05:
434 src = cpu_get_indexed_operand16 (cpu, 1);
435 addr = cpu_fetch16 (cpu);
436 break;
437
438 case 0x02:
439 src = cpu_get_indexed_operand16 (cpu, 1);
440 addr = cpu_get_indexed_operand_addr (cpu, 1);
441 break;
442
443 default:
444 sim_engine_abort (CPU_STATE (cpu), cpu, 0,
445 "Invalid code 0x%0x -- internal error?", code);
446 return;
447 }
448 memory_write16 (cpu, addr, src);
449 }
450
451 int
452 cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
453 {
454 sim_add_option_table (sd, 0, cpu_options);
455
456 memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
457
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 |
468 M6811_EEON;
469 interrupts_initialize (sd, cpu);
470
471 cpu->cpu_is_initialized = 1;
472 return 0;
473 }
474
475
476 /* Reinitialize the processor after a reset. */
477 int
478 cpu_reset (sim_cpu *cpu)
479 {
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;
485 else
486 cpu->ios[M6811_INIT] = 0;
487
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;
497
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;
503
504 /* Reset interrupts. */
505 interrupts_reset (&cpu->cpu_interrupts);
506
507 /* Reinitialize the CPU operating mode. */
508 cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
509 return 0;
510 }
511
512 /* Reinitialize the processor after a reset. */
513 int
514 cpu_restart (sim_cpu *cpu)
515 {
516 uint16 addr;
517
518 /* Get CPU starting address depending on the CPU mode. */
519 if (cpu->cpu_use_elf_start == 0)
520 {
521 switch ((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA))
522 {
523 /* Single Chip */
524 default:
525 case 0 :
526 addr = memory_read16 (cpu, 0xFFFE);
527 break;
528
529 /* Expanded Multiplexed */
530 case M6811_MDA:
531 addr = memory_read16 (cpu, 0xFFFE);
532 break;
533
534 /* Special Bootstrap */
535 case M6811_SMOD:
536 addr = 0;
537 break;
538
539 /* Factory Test */
540 case M6811_MDA | M6811_SMOD:
541 addr = memory_read16 (cpu, 0xFFFE);
542 break;
543 }
544 }
545 else
546 {
547 addr = cpu->cpu_elf_start;
548 }
549
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;
557
558 cpu_call (cpu, addr);
559
560 return 0;
561 }
562
563 void
564 print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val, int mode)
565 {
566 while (desc->mask)
567 {
568 if (val & desc->mask)
569 sim_io_printf (sd, "%s",
570 mode == 0 ? desc->short_name : desc->long_name);
571 desc++;
572 }
573 }
574
575 void
576 print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
577 uint8 val, uint16 addr)
578 {
579 sim_io_printf (sd, " %-9.9s @ 0x%04x 0x%02x ", name, addr, val);
580 if (desc)
581 print_io_reg_desc (sd, desc, val, 0);
582 }
583
584 void
585 cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val)
586 {
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);
590 }
591
592
593 uint16
594 cpu_fetch_relbranch (sim_cpu *cpu)
595 {
596 uint16 addr = (uint16) cpu_fetch8 (cpu);
597
598 if (addr & 0x0080)
599 {
600 addr |= 0xFF00;
601 }
602 addr += cpu->cpu_regs.pc;
603 return addr;
604 }
605
606 uint16
607 cpu_fetch_relbranch16 (sim_cpu *cpu)
608 {
609 uint16 addr = cpu_fetch16 (cpu);
610
611 addr += cpu->cpu_regs.pc;
612 return addr;
613 }
614
615 /* Push all the CPU registers (when an interruption occurs). */
616 void
617 cpu_push_all (sim_cpu *cpu)
618 {
619 if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
620 {
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);
626 }
627 else
628 {
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);
634 }
635 }
636
637 /* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations. */
638 void
639 cpu_dbcc (sim_cpu* cpu)
640 {
641 uint8 code;
642 uint16 addr;
643 uint16 inc;
644 uint16 reg;
645
646 code = cpu_fetch8 (cpu);
647 switch (code & 0xc0)
648 {
649 case 0x80: /* ibcc */
650 inc = 1;
651 break;
652 case 0x40: /* tbcc */
653 inc = 0;
654 break;
655 case 0: /* dbcc */
656 inc = -1;
657 break;
658 default:
659 abort ();
660 break;
661 }
662
663 addr = cpu_fetch8 (cpu);
664 if (code & 0x10)
665 addr |= 0xff00;
666
667 addr += cpu_get_pc (cpu);
668 reg = cpu_get_src_reg (cpu, code & 0x07);
669 reg += inc;
670
671 /* Branch according to register value. */
672 if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
673 {
674 cpu_set_pc (cpu, addr);
675 }
676 cpu_set_dst_reg (cpu, code & 0x07, reg);
677 }
678
679 void
680 cpu_exg (sim_cpu* cpu, uint8 code)
681 {
682 uint8 r1, r2;
683 uint16 src1;
684 uint16 src2;
685
686 r1 = (code >> 4) & 0x07;
687 r2 = code & 0x07;
688 if (code & 0x80)
689 {
690 src1 = cpu_get_src_reg (cpu, r1);
691 src2 = cpu_get_src_reg (cpu, r2);
692 if (r2 == 1 || r2 == 2)
693 src2 |= 0xff00;
694
695 cpu_set_dst_reg (cpu, r2, src1);
696 cpu_set_dst_reg (cpu, r1, src2);
697 }
698 else
699 {
700 src1 = cpu_get_src_reg (cpu, r1);
701
702 /* Sign extend the 8-bit registers (A, B, CCR). */
703 if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
704 src1 |= 0xff00;
705
706 cpu_set_dst_reg (cpu, r2, src1);
707 }
708 }
709
710 /* Handle special instructions. */
711 void
712 cpu_special (sim_cpu *cpu, enum M6811_Special special)
713 {
714 switch (special)
715 {
716 case M6811_RTI:
717 {
718 uint8 ccr;
719
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));
726 cpu_return (cpu);
727 break;
728 }
729
730 case M6812_RTI:
731 {
732 uint8 ccr;
733
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));
740 cpu_return (cpu);
741 break;
742 }
743
744 case M6811_WAI:
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)
748 {
749 cpu_set_pc (cpu, cpu->cpu_insn_pc);
750 sim_engine_halt (CPU_STATE (cpu), cpu,
751 NULL, NULL_CIA, sim_exited,
752 cpu_get_d (cpu));
753 return;
754 }
755 /* SCz: not correct... */
756 cpu_push_all (cpu);
757 break;
758
759 case M6811_SWI:
760 interrupts_raise (&cpu->cpu_interrupts, M6811_INT_SWI);
761 interrupts_process (&cpu->cpu_interrupts);
762 break;
763
764 case M6811_EMUL_SYSCALL:
765 case M6811_ILLEGAL:
766 if (cpu->cpu_emul_syscall)
767 {
768 uint8 op = memory_read8 (cpu,
769 cpu_get_pc (cpu) - 1);
770 if (op == 0x41)
771 {
772 cpu_set_pc (cpu, cpu->cpu_insn_pc);
773 sim_engine_halt (CPU_STATE (cpu), cpu,
774 NULL, NULL_CIA, sim_exited,
775 cpu_get_d (cpu));
776 return;
777 }
778 else
779 {
780 emul_os (op, cpu);
781 }
782 return;
783 }
784
785 interrupts_raise (&cpu->cpu_interrupts, M6811_INT_ILLEGAL);
786 interrupts_process (&cpu->cpu_interrupts);
787 break;
788
789 case M6811_TEST:
790 case M6812_BGND:
791 {
792 SIM_DESC sd;
793
794 sd = CPU_STATE (cpu);
795
796 /* Breakpoint instruction if we are under gdb. */
797 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
798 {
799 cpu->cpu_regs.pc --;
800 sim_engine_halt (CPU_STATE (cpu), cpu,
801 0, cpu_get_pc (cpu), sim_stopped,
802 SIM_SIGTRAP);
803 }
804 /* else this is a nop but not in test factory mode. */
805 break;
806 }
807
808 case M6812_IDIVS:
809 {
810 int32 src1 = (int16) cpu_get_d (cpu);
811 int32 src2 = (int16) cpu_get_x (cpu);
812
813 if (src2 == 0)
814 {
815 cpu_set_ccr_C (cpu, 1);
816 }
817 else
818 {
819 cpu_set_d (cpu, src1 % src2);
820 src1 = 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);
826 }
827 }
828 break;
829
830 case M6812_EDIV:
831 {
832 uint32 src1 = (uint32) cpu_get_x (cpu);
833 uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
834 | (uint32) (cpu_get_d (cpu));
835
836 if (src1 == 0)
837 {
838 cpu_set_ccr_C (cpu, 1);
839 }
840 else
841 {
842 cpu_set_ccr_C (cpu, 0);
843 cpu_set_d (cpu, src2 % src1);
844 src2 = 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);
849 }
850 }
851 break;
852
853 case M6812_EDIVS:
854 {
855 int32 src1 = (int16) cpu_get_x (cpu);
856 int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
857 | (uint32) (cpu_get_d (cpu));
858
859 if (src1 == 0)
860 {
861 cpu_set_ccr_C (cpu, 1);
862 }
863 else
864 {
865 cpu_set_ccr_C (cpu, 0);
866 cpu_set_d (cpu, src2 % src1);
867 src2 = 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);
872 }
873 }
874 break;
875
876 case M6812_EMULS:
877 {
878 int32 src1, src2;
879
880 src1 = (int16) cpu_get_d (cpu);
881 src2 = (int16) cpu_get_y (cpu);
882 src1 = src1 * src2;
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);
888 }
889 break;
890
891 case M6812_EMACS:
892 {
893 int32 src1, src2;
894 uint16 addr;
895
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));
899 src1 = src1 * src2;
900 src2 = (((uint32) memory_read16 (cpu, addr)) << 16)
901 | (uint32) memory_read16 (cpu, addr + 2);
902
903 memory_write16 (cpu, addr, (src1 + src2) >> 16);
904 memory_write16 (cpu, addr + 2, (src1 + src2));
905
906
907 }
908 break;
909
910 case M6812_CALL:
911 {
912 uint8 page;
913 uint16 addr;
914
915 addr = cpu_fetch16 (cpu);
916 page = cpu_fetch8 (cpu);
917
918 cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
919 cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
920
921 cpu_set_page (cpu, page);
922 cpu_set_pc (cpu, addr);
923 }
924 break;
925
926 case M6812_CALL_INDIRECT:
927 {
928 uint8 code;
929 uint16 addr;
930 uint8 page;
931
932 code = memory_read8 (cpu, cpu_get_pc (cpu));
933 /* Indirect addressing call has the page specified in the
934 memory location pointed to by the address. */
935 if ((code & 0xE3) == 0xE3)
936 {
937 addr = cpu_get_indexed_operand_addr (cpu, 0);
938 page = memory_read8 (cpu, addr + 2);
939 addr = memory_read16 (cpu, addr);
940 }
941 else
942 {
943 /* Otherwise, page is in the opcode. */
944 addr = cpu_get_indexed_operand16 (cpu, 0);
945 page = cpu_fetch8 (cpu);
946 }
947 cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
948 cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
949 cpu_set_page (cpu, page);
950 cpu_set_pc (cpu, addr);
951 }
952 break;
953
954 case M6812_RTC:
955 {
956 uint8 page = cpu_m68hc12_pop_uint8 (cpu);
957 uint16 addr = cpu_m68hc12_pop_uint16 (cpu);
958
959 cpu_set_page (cpu, page);
960 cpu_set_pc (cpu, addr);
961 }
962 break;
963
964 case M6812_ETBL:
965 default:
966 sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
967 cpu_get_pc (cpu), sim_stopped,
968 SIM_SIGILL);
969 break;
970 }
971 }
972
973
974 void
975 cpu_single_step (sim_cpu *cpu)
976 {
977 cpu->cpu_current_cycle = 0;
978 cpu->cpu_insn_pc = cpu_get_pc (cpu);
979
980 /* Handle the pending interrupts. If an interrupt is handled,
981 treat this as an single step. */
982 if (interrupts_process (&cpu->cpu_interrupts))
983 {
984 cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
985 return;
986 }
987
988 /* printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
989 cpu->cpu_interpretor (cpu);
990 cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
991 }
992
993 /* VARARGS */
994 void
995 sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
996 uint16 addr, const char *message, ...)
997 {
998 char buf[1024];
999 va_list args;
1000
1001 va_start (args, message);
1002 vsprintf (buf, message, args);
1003 va_end (args);
1004
1005 sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
1006 cpu_memory_exception (cpu, excep, addr, buf);
1007 }
1008
1009
1010 void
1011 cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep,
1012 uint16 addr, const char *message)
1013 {
1014 if (cpu->cpu_running == 0)
1015 return;
1016
1017 cpu_set_pc (cpu, cpu->cpu_insn_pc);
1018 sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
1019 cpu_get_pc (cpu), sim_stopped, excep);
1020
1021 #if 0
1022 cpu->mem_exception = excep;
1023 cpu->fault_addr = addr;
1024 cpu->fault_msg = strdup (message);
1025
1026 if (cpu->cpu_use_handler)
1027 {
1028 longjmp (&cpu->cpu_exception_handler, 1);
1029 }
1030 (* cpu->callback->printf_filtered)
1031 (cpu->callback, "Fault at 0x%04x: %s\n", addr, message);
1032 #endif
1033 }
1034
1035 void
1036 cpu_info (SIM_DESC sd, sim_cpu *cpu)
1037 {
1038 sim_io_printf (sd, "CPU info:\n");
1039 sim_io_printf (sd, " Absolute cycle: %s\n",
1040 cycle_to_string (cpu, cpu->cpu_absolute_cycle));
1041
1042 sim_io_printf (sd, " Syscall emulation: %s\n",
1043 cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");
1044 sim_io_printf (sd, " Memory errors detection: %s\n",
1045 cpu->cpu_check_memory ? "yes" : "no");
1046 sim_io_printf (sd, " Stop on interrupt: %s\n",
1047 cpu->cpu_stop_on_interrupt ? "yes" : "no");
1048 }
1049