]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/m68hc11/m68hc11_sim.c
* sim-main.h (phys_to_virt): Use memory bank parameters to translate
[thirdparty/binutils-gdb.git] / sim / m68hc11 / m68hc11_sim.c
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)
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->bank_start = 0;
468 cpu->bank_end = 0;
469 cpu->bank_shift = 0;
470 cpu->cpu_config = M6811_NOSEC | M6811_NOCOP | M6811_ROMON |
471 M6811_EEON;
472 interrupts_initialize (sd, cpu);
473
474 cpu->cpu_is_initialized = 1;
475 return 0;
476 }
477
478
479 /* Reinitialize the processor after a reset. */
480 int
481 cpu_reset (sim_cpu *cpu)
482 {
483 /* Initialize the config register.
484 It is only initialized at reset time. */
485 memset (cpu->ios, 0, sizeof (cpu->ios));
486 if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
487 cpu->ios[M6811_INIT] = 0x1;
488 else
489 cpu->ios[M6811_INIT] = 0;
490
491 /* Output compare registers set to 0xFFFF. */
492 cpu->ios[M6811_TOC1_H] = 0xFF;
493 cpu->ios[M6811_TOC1_L] = 0xFF;
494 cpu->ios[M6811_TOC2_H] = 0xFF;
495 cpu->ios[M6811_TOC2_L] = 0xFF;
496 cpu->ios[M6811_TOC3_H] = 0xFF;
497 cpu->ios[M6811_TOC4_L] = 0xFF;
498 cpu->ios[M6811_TOC5_H] = 0xFF;
499 cpu->ios[M6811_TOC5_L] = 0xFF;
500
501 /* Setup the processor registers. */
502 memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
503 cpu->cpu_absolute_cycle = 0;
504 cpu->cpu_current_cycle = 0;
505 cpu->cpu_is_initialized = 0;
506
507 /* Reset interrupts. */
508 interrupts_reset (&cpu->cpu_interrupts);
509
510 /* Reinitialize the CPU operating mode. */
511 cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
512 return 0;
513 }
514
515 /* Reinitialize the processor after a reset. */
516 int
517 cpu_restart (sim_cpu *cpu)
518 {
519 uint16 addr;
520
521 /* Get CPU starting address depending on the CPU mode. */
522 if (cpu->cpu_use_elf_start == 0)
523 {
524 switch ((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA))
525 {
526 /* Single Chip */
527 default:
528 case 0 :
529 addr = memory_read16 (cpu, 0xFFFE);
530 break;
531
532 /* Expanded Multiplexed */
533 case M6811_MDA:
534 addr = memory_read16 (cpu, 0xFFFE);
535 break;
536
537 /* Special Bootstrap */
538 case M6811_SMOD:
539 addr = 0;
540 break;
541
542 /* Factory Test */
543 case M6811_MDA | M6811_SMOD:
544 addr = memory_read16 (cpu, 0xFFFE);
545 break;
546 }
547 }
548 else
549 {
550 addr = cpu->cpu_elf_start;
551 }
552
553 /* Setup the processor registers. */
554 cpu->cpu_insn_pc = addr;
555 cpu->cpu_regs.pc = addr;
556 cpu->cpu_regs.ccr = M6811_X_BIT | M6811_I_BIT | M6811_S_BIT;
557 cpu->cpu_absolute_cycle = 0;
558 cpu->cpu_is_initialized = 1;
559 cpu->cpu_current_cycle = 0;
560
561 cpu_call (cpu, addr);
562
563 return 0;
564 }
565
566 void
567 print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val, int mode)
568 {
569 while (desc->mask)
570 {
571 if (val & desc->mask)
572 sim_io_printf (sd, "%s",
573 mode == 0 ? desc->short_name : desc->long_name);
574 desc++;
575 }
576 }
577
578 void
579 print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
580 uint8 val, uint16 addr)
581 {
582 sim_io_printf (sd, " %-9.9s @ 0x%04x 0x%02x ", name, addr, val);
583 if (desc)
584 print_io_reg_desc (sd, desc, val, 0);
585 }
586
587 void
588 print_io_word (SIM_DESC sd, const char *name, io_reg_desc *desc,
589 uint16 val, uint16 addr)
590 {
591 sim_io_printf (sd, " %-9.9s @ 0x%04x 0x%04x ", name, addr, val);
592 if (desc)
593 print_io_reg_desc (sd, desc, val, 0);
594 }
595
596 void
597 cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val)
598 {
599 cpu_set_ccr_V (proc, 0);
600 cpu_set_ccr_N (proc, val & 0x80 ? 1 : 0);
601 cpu_set_ccr_Z (proc, val == 0 ? 1 : 0);
602 }
603
604
605 uint16
606 cpu_fetch_relbranch (sim_cpu *cpu)
607 {
608 uint16 addr = (uint16) cpu_fetch8 (cpu);
609
610 if (addr & 0x0080)
611 {
612 addr |= 0xFF00;
613 }
614 addr += cpu->cpu_regs.pc;
615 return addr;
616 }
617
618 uint16
619 cpu_fetch_relbranch16 (sim_cpu *cpu)
620 {
621 uint16 addr = cpu_fetch16 (cpu);
622
623 addr += cpu->cpu_regs.pc;
624 return addr;
625 }
626
627 /* Push all the CPU registers (when an interruption occurs). */
628 void
629 cpu_push_all (sim_cpu *cpu)
630 {
631 if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
632 {
633 cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.pc);
634 cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.iy);
635 cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.ix);
636 cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.d);
637 cpu_m68hc11_push_uint8 (cpu, cpu->cpu_regs.ccr);
638 }
639 else
640 {
641 cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.pc);
642 cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.iy);
643 cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.ix);
644 cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.d);
645 cpu_m68hc12_push_uint8 (cpu, cpu->cpu_regs.ccr);
646 }
647 }
648
649 /* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations. */
650 void
651 cpu_dbcc (sim_cpu* cpu)
652 {
653 uint8 code;
654 uint16 addr;
655 uint16 inc;
656 uint16 reg;
657
658 code = cpu_fetch8 (cpu);
659 switch (code & 0xc0)
660 {
661 case 0x80: /* ibcc */
662 inc = 1;
663 break;
664 case 0x40: /* tbcc */
665 inc = 0;
666 break;
667 case 0: /* dbcc */
668 inc = -1;
669 break;
670 default:
671 abort ();
672 break;
673 }
674
675 addr = cpu_fetch8 (cpu);
676 if (code & 0x10)
677 addr |= 0xff00;
678
679 addr += cpu_get_pc (cpu);
680 reg = cpu_get_src_reg (cpu, code & 0x07);
681 reg += inc;
682
683 /* Branch according to register value. */
684 if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
685 {
686 cpu_set_pc (cpu, addr);
687 }
688 cpu_set_dst_reg (cpu, code & 0x07, reg);
689 }
690
691 void
692 cpu_exg (sim_cpu* cpu, uint8 code)
693 {
694 uint8 r1, r2;
695 uint16 src1;
696 uint16 src2;
697
698 r1 = (code >> 4) & 0x07;
699 r2 = code & 0x07;
700 if (code & 0x80)
701 {
702 src1 = cpu_get_src_reg (cpu, r1);
703 src2 = cpu_get_src_reg (cpu, r2);
704 if (r2 == 1 || r2 == 2)
705 src2 |= 0xff00;
706
707 cpu_set_dst_reg (cpu, r2, src1);
708 cpu_set_dst_reg (cpu, r1, src2);
709 }
710 else
711 {
712 src1 = cpu_get_src_reg (cpu, r1);
713
714 /* Sign extend the 8-bit registers (A, B, CCR). */
715 if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
716 src1 |= 0xff00;
717
718 cpu_set_dst_reg (cpu, r2, src1);
719 }
720 }
721
722 /* Handle special instructions. */
723 void
724 cpu_special (sim_cpu *cpu, enum M6811_Special special)
725 {
726 switch (special)
727 {
728 case M6811_RTI:
729 {
730 uint8 ccr;
731
732 ccr = cpu_m68hc11_pop_uint8 (cpu);
733 cpu_set_ccr (cpu, ccr);
734 cpu_set_d (cpu, cpu_m68hc11_pop_uint16 (cpu));
735 cpu_set_x (cpu, cpu_m68hc11_pop_uint16 (cpu));
736 cpu_set_y (cpu, cpu_m68hc11_pop_uint16 (cpu));
737 cpu_set_pc (cpu, cpu_m68hc11_pop_uint16 (cpu));
738 cpu_return (cpu);
739 break;
740 }
741
742 case M6812_RTI:
743 {
744 uint8 ccr;
745
746 ccr = cpu_m68hc12_pop_uint8 (cpu);
747 cpu_set_ccr (cpu, ccr);
748 cpu_set_d (cpu, cpu_m68hc12_pop_uint16 (cpu));
749 cpu_set_x (cpu, cpu_m68hc12_pop_uint16 (cpu));
750 cpu_set_y (cpu, cpu_m68hc12_pop_uint16 (cpu));
751 cpu_set_pc (cpu, cpu_m68hc12_pop_uint16 (cpu));
752 cpu_return (cpu);
753 break;
754 }
755
756 case M6811_WAI:
757 /* In the ELF-start mode, we are in a special mode where
758 the WAI corresponds to an exit. */
759 if (cpu->cpu_use_elf_start)
760 {
761 cpu_set_pc (cpu, cpu->cpu_insn_pc);
762 sim_engine_halt (CPU_STATE (cpu), cpu,
763 NULL, NULL_CIA, sim_exited,
764 cpu_get_d (cpu));
765 return;
766 }
767 /* SCz: not correct... */
768 cpu_push_all (cpu);
769 break;
770
771 case M6811_SWI:
772 interrupts_raise (&cpu->cpu_interrupts, M6811_INT_SWI);
773 interrupts_process (&cpu->cpu_interrupts);
774 break;
775
776 case M6811_EMUL_SYSCALL:
777 case M6811_ILLEGAL:
778 if (cpu->cpu_emul_syscall)
779 {
780 uint8 op = memory_read8 (cpu,
781 cpu_get_pc (cpu) - 1);
782 if (op == 0x41)
783 {
784 cpu_set_pc (cpu, cpu->cpu_insn_pc);
785 sim_engine_halt (CPU_STATE (cpu), cpu,
786 NULL, NULL_CIA, sim_exited,
787 cpu_get_d (cpu));
788 return;
789 }
790 else
791 {
792 emul_os (op, cpu);
793 }
794 return;
795 }
796
797 interrupts_raise (&cpu->cpu_interrupts, M6811_INT_ILLEGAL);
798 interrupts_process (&cpu->cpu_interrupts);
799 break;
800
801 case M6811_TEST:
802 case M6812_BGND:
803 {
804 SIM_DESC sd;
805
806 sd = CPU_STATE (cpu);
807
808 /* Breakpoint instruction if we are under gdb. */
809 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
810 {
811 cpu->cpu_regs.pc --;
812 sim_engine_halt (CPU_STATE (cpu), cpu,
813 0, cpu_get_pc (cpu), sim_stopped,
814 SIM_SIGTRAP);
815 }
816 /* else this is a nop but not in test factory mode. */
817 break;
818 }
819
820 case M6812_IDIVS:
821 {
822 int32 src1 = (int16) cpu_get_d (cpu);
823 int32 src2 = (int16) cpu_get_x (cpu);
824
825 if (src2 == 0)
826 {
827 cpu_set_ccr_C (cpu, 1);
828 }
829 else
830 {
831 cpu_set_d (cpu, src1 % src2);
832 src1 = src1 / src2;
833 cpu_set_x (cpu, src1);
834 cpu_set_ccr_C (cpu, 0);
835 cpu_set_ccr_Z (cpu, src1 == 0);
836 cpu_set_ccr_N (cpu, src1 & 0x8000);
837 cpu_set_ccr_V (cpu, src1 >= 32768 || src1 < -32768);
838 }
839 }
840 break;
841
842 case M6812_EDIV:
843 {
844 uint32 src1 = (uint32) cpu_get_x (cpu);
845 uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
846 | (uint32) (cpu_get_d (cpu));
847
848 if (src1 == 0)
849 {
850 cpu_set_ccr_C (cpu, 1);
851 }
852 else
853 {
854 cpu_set_ccr_C (cpu, 0);
855 cpu_set_d (cpu, src2 % src1);
856 src2 = src2 / src1;
857 cpu_set_y (cpu, src2);
858 cpu_set_ccr_Z (cpu, src2 == 0);
859 cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
860 cpu_set_ccr_V (cpu, (src2 & 0xffff0000) != 0);
861 }
862 }
863 break;
864
865 case M6812_EDIVS:
866 {
867 int32 src1 = (int16) cpu_get_x (cpu);
868 int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
869 | (uint32) (cpu_get_d (cpu));
870
871 if (src1 == 0)
872 {
873 cpu_set_ccr_C (cpu, 1);
874 }
875 else
876 {
877 cpu_set_ccr_C (cpu, 0);
878 cpu_set_d (cpu, src2 % src1);
879 src2 = src2 / src1;
880 cpu_set_y (cpu, src2);
881 cpu_set_ccr_Z (cpu, src2 == 0);
882 cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
883 cpu_set_ccr_V (cpu, src2 > 32767 || src2 < -32768);
884 }
885 }
886 break;
887
888 case M6812_EMULS:
889 {
890 int32 src1, src2;
891
892 src1 = (int16) cpu_get_d (cpu);
893 src2 = (int16) cpu_get_y (cpu);
894 src1 = src1 * src2;
895 cpu_set_d (cpu, src1 & 0x0ffff);
896 cpu_set_y (cpu, src1 >> 16);
897 cpu_set_ccr_Z (cpu, src1 == 0);
898 cpu_set_ccr_N (cpu, (src1 & 0x80000000) != 0);
899 cpu_set_ccr_C (cpu, (src1 & 0x00008000) != 0);
900 }
901 break;
902
903 case M6812_EMACS:
904 {
905 int32 src1, src2;
906 uint16 addr;
907
908 addr = cpu_fetch16 (cpu);
909 src1 = (int16) memory_read16 (cpu, cpu_get_x (cpu));
910 src2 = (int16) memory_read16 (cpu, cpu_get_y (cpu));
911 src1 = src1 * src2;
912 src2 = (((uint32) memory_read16 (cpu, addr)) << 16)
913 | (uint32) memory_read16 (cpu, addr + 2);
914
915 memory_write16 (cpu, addr, (src1 + src2) >> 16);
916 memory_write16 (cpu, addr + 2, (src1 + src2));
917
918
919 }
920 break;
921
922 case M6812_CALL:
923 {
924 uint8 page;
925 uint16 addr;
926
927 addr = cpu_fetch16 (cpu);
928 page = cpu_fetch8 (cpu);
929
930 cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
931 cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
932
933 cpu_set_page (cpu, page);
934 cpu_set_pc (cpu, addr);
935 }
936 break;
937
938 case M6812_CALL_INDIRECT:
939 {
940 uint8 code;
941 uint16 addr;
942 uint8 page;
943
944 code = memory_read8 (cpu, cpu_get_pc (cpu));
945 /* Indirect addressing call has the page specified in the
946 memory location pointed to by the address. */
947 if ((code & 0xE3) == 0xE3)
948 {
949 addr = cpu_get_indexed_operand_addr (cpu, 0);
950 page = memory_read8 (cpu, addr + 2);
951 addr = memory_read16 (cpu, addr);
952 }
953 else
954 {
955 /* Otherwise, page is in the opcode. */
956 addr = cpu_get_indexed_operand16 (cpu, 0);
957 page = cpu_fetch8 (cpu);
958 }
959 cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
960 cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
961 cpu_set_page (cpu, page);
962 cpu_set_pc (cpu, addr);
963 }
964 break;
965
966 case M6812_RTC:
967 {
968 uint8 page = cpu_m68hc12_pop_uint8 (cpu);
969 uint16 addr = cpu_m68hc12_pop_uint16 (cpu);
970
971 cpu_set_page (cpu, page);
972 cpu_set_pc (cpu, addr);
973 }
974 break;
975
976 case M6812_ETBL:
977 default:
978 sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
979 cpu_get_pc (cpu), sim_stopped,
980 SIM_SIGILL);
981 break;
982 }
983 }
984
985
986 void
987 cpu_single_step (sim_cpu *cpu)
988 {
989 cpu->cpu_current_cycle = 0;
990 cpu->cpu_insn_pc = cpu_get_pc (cpu);
991
992 /* Handle the pending interrupts. If an interrupt is handled,
993 treat this as an single step. */
994 if (interrupts_process (&cpu->cpu_interrupts))
995 {
996 cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
997 return;
998 }
999
1000 /* printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
1001 cpu->cpu_interpretor (cpu);
1002 cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
1003 }
1004
1005 /* VARARGS */
1006 void
1007 sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
1008 uint16 addr, const char *message, ...)
1009 {
1010 char buf[1024];
1011 va_list args;
1012
1013 va_start (args, message);
1014 vsprintf (buf, message, args);
1015 va_end (args);
1016
1017 sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
1018 cpu_memory_exception (cpu, excep, addr, buf);
1019 }
1020
1021
1022 void
1023 cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep,
1024 uint16 addr, const char *message)
1025 {
1026 if (cpu->cpu_running == 0)
1027 return;
1028
1029 cpu_set_pc (cpu, cpu->cpu_insn_pc);
1030 sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
1031 cpu_get_pc (cpu), sim_stopped, excep);
1032
1033 #if 0
1034 cpu->mem_exception = excep;
1035 cpu->fault_addr = addr;
1036 cpu->fault_msg = strdup (message);
1037
1038 if (cpu->cpu_use_handler)
1039 {
1040 longjmp (&cpu->cpu_exception_handler, 1);
1041 }
1042 (* cpu->callback->printf_filtered)
1043 (cpu->callback, "Fault at 0x%04x: %s\n", addr, message);
1044 #endif
1045 }
1046
1047 void
1048 cpu_info (SIM_DESC sd, sim_cpu *cpu)
1049 {
1050 sim_io_printf (sd, "CPU info:\n");
1051 sim_io_printf (sd, " Absolute cycle: %s\n",
1052 cycle_to_string (cpu, cpu->cpu_absolute_cycle));
1053
1054 sim_io_printf (sd, " Syscall emulation: %s\n",
1055 cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");
1056 sim_io_printf (sd, " Memory errors detection: %s\n",
1057 cpu->cpu_check_memory ? "yes" : "no");
1058 sim_io_printf (sd, " Stop on interrupt: %s\n",
1059 cpu->cpu_stop_on_interrupt ? "yes" : "no");
1060 }
1061