]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/m68hc11/m68hc11_sim.c
Update copyright notices to add year 2010.
[thirdparty/binutils-gdb.git] / sim / m68hc11 / m68hc11_sim.c
1 /* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
2 Copyright 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
4 Written by Stephane Carrez (stcarrez@nerim.fr)
5
6 This file is part of GDB, GAS, and the GNU binutils.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
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_BOOTSTRAP,
31 OPTION_CPU_MODE
32 };
33
34 static DECLARE_OPTION_HANDLER (cpu_option_handler);
35
36 static const OPTION cpu_options[] =
37 {
38 { {"cpu-reset", no_argument, NULL, OPTION_CPU_RESET },
39 '\0', NULL, "Reset the CPU",
40 cpu_option_handler },
41
42 { {"emulos", no_argument, NULL, OPTION_EMUL_OS },
43 '\0', NULL, "Emulate some OS system calls (read, write, ...)",
44 cpu_option_handler },
45
46 { {"cpu-config", required_argument, NULL, OPTION_CPU_CONFIG },
47 '\0', NULL, "Specify the initial CPU configuration register",
48 cpu_option_handler },
49
50 { {"bootstrap", no_argument, NULL, OPTION_CPU_BOOTSTRAP },
51 '\0', NULL, "Start the processing in bootstrap mode",
52 cpu_option_handler },
53
54 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
55 };
56
57
58 static SIM_RC
59 cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
60 int opt, char *arg, int is_command)
61 {
62 int val;
63
64 cpu = STATE_CPU (sd, 0);
65 switch (opt)
66 {
67 case OPTION_CPU_RESET:
68 sim_board_reset (sd);
69 break;
70
71 case OPTION_EMUL_OS:
72 cpu->cpu_emul_syscall = 1;
73 break;
74
75 case OPTION_CPU_CONFIG:
76 if (sscanf(arg, "0x%x", &val) == 1
77 || sscanf(arg, "%d", &val) == 1)
78 {
79 cpu->cpu_config = val;
80 cpu->cpu_use_local_config = 1;
81 }
82 else
83 cpu->cpu_use_local_config = 0;
84 break;
85
86 case OPTION_CPU_BOOTSTRAP:
87 cpu->cpu_start_mode = "bootstrap";
88 break;
89
90 case OPTION_CPU_MODE:
91 break;
92 }
93
94 return SIM_RC_OK;
95 }
96
97
98 void
99 cpu_call (sim_cpu *cpu, uint16 addr)
100 {
101
102 cpu_set_pc (cpu, addr);
103 }
104
105 void
106 cpu_return (sim_cpu *cpu)
107 {
108 }
109
110 /* Set the stack pointer and re-compute the current frame. */
111 void
112 cpu_set_sp (sim_cpu *cpu, uint16 val)
113 {
114 cpu->cpu_regs.sp = val;
115 }
116
117 uint16
118 cpu_get_reg (sim_cpu* cpu, uint8 reg)
119 {
120 switch (reg)
121 {
122 case 0:
123 return cpu_get_x (cpu);
124
125 case 1:
126 return cpu_get_y (cpu);
127
128 case 2:
129 return cpu_get_sp (cpu);
130
131 case 3:
132 return cpu_get_pc (cpu);
133
134 default:
135 return 0;
136 }
137 }
138
139 uint16
140 cpu_get_src_reg (sim_cpu* cpu, uint8 reg)
141 {
142 switch (reg)
143 {
144 case 0:
145 return cpu_get_a (cpu);
146
147 case 1:
148 return cpu_get_b (cpu);
149
150 case 2:
151 return cpu_get_ccr (cpu);
152
153 case 3:
154 return cpu_get_tmp3 (cpu);
155
156 case 4:
157 return cpu_get_d (cpu);
158
159 case 5:
160 return cpu_get_x (cpu);
161
162 case 6:
163 return cpu_get_y (cpu);
164
165 case 7:
166 return cpu_get_sp (cpu);
167
168 default:
169 return 0;
170 }
171 }
172
173 void
174 cpu_set_dst_reg (sim_cpu* cpu, uint8 reg, uint16 val)
175 {
176 switch (reg)
177 {
178 case 0:
179 cpu_set_a (cpu, val);
180 break;
181
182 case 1:
183 cpu_set_b (cpu, val);
184 break;
185
186 case 2:
187 cpu_set_ccr (cpu, val);
188 break;
189
190 case 3:
191 cpu_set_tmp2 (cpu, val);
192 break;
193
194 case 4:
195 cpu_set_d (cpu, val);
196 break;
197
198 case 5:
199 cpu_set_x (cpu, val);
200 break;
201
202 case 6:
203 cpu_set_y (cpu, val);
204 break;
205
206 case 7:
207 cpu_set_sp (cpu, val);
208 break;
209
210 default:
211 break;
212 }
213 }
214
215 void
216 cpu_set_reg (sim_cpu* cpu, uint8 reg, uint16 val)
217 {
218 switch (reg)
219 {
220 case 0:
221 cpu_set_x (cpu, val);
222 break;
223
224 case 1:
225 cpu_set_y (cpu, val);
226 break;
227
228 case 2:
229 cpu_set_sp (cpu, val);
230 break;
231
232 case 3:
233 cpu_set_pc (cpu, val);
234 break;
235
236 default:
237 break;
238 }
239 }
240
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)
245 {
246 uint8 reg;
247 uint16 sval;
248 uint16 addr;
249 uint8 code;
250
251 code = cpu_fetch8 (cpu);
252
253 /* n,r with 5-bit signed constant. */
254 if ((code & 0x20) == 0)
255 {
256 reg = (code >> 6) & 3;
257 sval = (code & 0x1f);
258 if (code & 0x10)
259 sval |= 0xfff0;
260
261 addr = cpu_get_reg (cpu, reg);
262 addr += sval;
263 }
264
265 /* Auto pre/post increment/decrement. */
266 else if ((code & 0xc0) != 0xc0)
267 {
268 reg = (code >> 6) & 3;
269 sval = (code & 0x0f);
270 if (sval & 0x8)
271 {
272 sval |= 0xfff0;
273 }
274 else
275 {
276 sval = sval + 1;
277 }
278 addr = cpu_get_reg (cpu, reg);
279 cpu_set_reg (cpu, reg, addr + sval);
280 if ((code & 0x10) == 0)
281 {
282 addr += sval;
283 }
284 }
285
286 /* [n,r] 16-bits offset indexed indirect. */
287 else if ((code & 0x07) == 3)
288 {
289 if (restrict)
290 {
291 return 0;
292 }
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);
298 }
299 else if ((code & 0x4) == 0)
300 {
301 if (restrict)
302 {
303 return 0;
304 }
305 reg = (code >> 3) & 0x03;
306 addr = cpu_get_reg (cpu, reg);
307 if (code & 0x2)
308 {
309 sval = cpu_fetch16 (cpu);
310 cpu_add_cycles (cpu, 1);
311 }
312 else
313 {
314 sval = cpu_fetch8 (cpu);
315 if (code & 0x1)
316 sval |= 0xff00;
317 cpu_add_cycles (cpu, 1);
318 }
319 addr += sval;
320 }
321 else
322 {
323 reg = (code >> 3) & 0x03;
324 addr = cpu_get_reg (cpu, reg);
325 switch (code & 3)
326 {
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;
342 }
343 }
344
345 return addr;
346 }
347
348 uint8
349 cpu_get_indexed_operand8 (sim_cpu* cpu, int restrict)
350 {
351 uint16 addr;
352
353 addr = cpu_get_indexed_operand_addr (cpu, restrict);
354 return memory_read8 (cpu, addr);
355 }
356
357 uint16
358 cpu_get_indexed_operand16 (sim_cpu* cpu, int restrict)
359 {
360 uint16 addr;
361
362 addr = cpu_get_indexed_operand_addr (cpu, restrict);
363 return memory_read16 (cpu, addr);
364 }
365
366 void
367 cpu_move8 (sim_cpu *cpu, uint8 code)
368 {
369 uint8 src;
370 uint16 addr;
371
372 switch (code)
373 {
374 case 0x0b:
375 src = cpu_fetch8 (cpu);
376 addr = cpu_fetch16 (cpu);
377 break;
378
379 case 0x08:
380 addr = cpu_get_indexed_operand_addr (cpu, 1);
381 src = cpu_fetch8 (cpu);
382 break;
383
384 case 0x0c:
385 addr = cpu_fetch16 (cpu);
386 src = memory_read8 (cpu, addr);
387 addr = cpu_fetch16 (cpu);
388 break;
389
390 case 0x09:
391 addr = cpu_get_indexed_operand_addr (cpu, 1);
392 src = memory_read8 (cpu, cpu_fetch16 (cpu));
393 break;
394
395 case 0x0d:
396 src = cpu_get_indexed_operand8 (cpu, 1);
397 addr = cpu_fetch16 (cpu);
398 break;
399
400 case 0x0a:
401 src = cpu_get_indexed_operand8 (cpu, 1);
402 addr = cpu_get_indexed_operand_addr (cpu, 1);
403 break;
404
405 default:
406 sim_engine_abort (CPU_STATE (cpu), cpu, 0,
407 "Invalid code 0x%0x -- internal error?", code);
408 return;
409 }
410 memory_write8 (cpu, addr, src);
411 }
412
413 void
414 cpu_move16 (sim_cpu *cpu, uint8 code)
415 {
416 uint16 src;
417 uint16 addr;
418
419 switch (code)
420 {
421 case 0x03:
422 src = cpu_fetch16 (cpu);
423 addr = cpu_fetch16 (cpu);
424 break;
425
426 case 0x00:
427 addr = cpu_get_indexed_operand_addr (cpu, 1);
428 src = cpu_fetch16 (cpu);
429 break;
430
431 case 0x04:
432 addr = cpu_fetch16 (cpu);
433 src = memory_read16 (cpu, addr);
434 addr = cpu_fetch16 (cpu);
435 break;
436
437 case 0x01:
438 addr = cpu_get_indexed_operand_addr (cpu, 1);
439 src = memory_read16 (cpu, cpu_fetch16 (cpu));
440 break;
441
442 case 0x05:
443 src = cpu_get_indexed_operand16 (cpu, 1);
444 addr = cpu_fetch16 (cpu);
445 break;
446
447 case 0x02:
448 src = cpu_get_indexed_operand16 (cpu, 1);
449 addr = cpu_get_indexed_operand_addr (cpu, 1);
450 break;
451
452 default:
453 sim_engine_abort (CPU_STATE (cpu), cpu, 0,
454 "Invalid code 0x%0x -- internal error?", code);
455 return;
456 }
457 memory_write16 (cpu, addr, src);
458 }
459
460 int
461 cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
462 {
463 sim_add_option_table (sd, 0, cpu_options);
464
465 memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
466
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);
482
483 cpu->cpu_is_initialized = 1;
484 return 0;
485 }
486
487
488 /* Reinitialize the processor after a reset. */
489 int
490 cpu_reset (sim_cpu *cpu)
491 {
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;
499
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;
509
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;
515
516 /* Reset interrupts. */
517 interrupts_reset (&cpu->cpu_interrupts);
518
519 /* Reinitialize the CPU operating mode. */
520 cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
521 return 0;
522 }
523
524 /* Reinitialize the processor after a reset. */
525 int
526 cpu_restart (sim_cpu *cpu)
527 {
528 uint16 addr;
529
530 /* Get CPU starting address depending on the CPU mode. */
531 if (cpu->cpu_use_elf_start == 0)
532 {
533 switch ((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA))
534 {
535 /* Single Chip */
536 default:
537 case 0 :
538 addr = memory_read16 (cpu, 0xFFFE);
539 break;
540
541 /* Expanded Multiplexed */
542 case M6811_MDA:
543 addr = memory_read16 (cpu, 0xFFFE);
544 break;
545
546 /* Special Bootstrap */
547 case M6811_SMOD:
548 addr = 0;
549 break;
550
551 /* Factory Test */
552 case M6811_MDA | M6811_SMOD:
553 addr = memory_read16 (cpu, 0xFFFE);
554 break;
555 }
556 }
557 else
558 {
559 addr = cpu->cpu_elf_start;
560 }
561
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;
569
570 cpu_call (cpu, addr);
571
572 return 0;
573 }
574
575 void
576 print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val, int mode)
577 {
578 while (desc->mask)
579 {
580 if (val & desc->mask)
581 sim_io_printf (sd, "%s",
582 mode == 0 ? desc->short_name : desc->long_name);
583 desc++;
584 }
585 }
586
587 void
588 print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
589 uint8 val, uint16 addr)
590 {
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);
594 }
595
596 void
597 print_io_word (SIM_DESC sd, const char *name, io_reg_desc *desc,
598 uint16 val, uint16 addr)
599 {
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);
603 }
604
605 void
606 cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val)
607 {
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);
611 }
612
613
614 uint16
615 cpu_fetch_relbranch (sim_cpu *cpu)
616 {
617 uint16 addr = (uint16) cpu_fetch8 (cpu);
618
619 if (addr & 0x0080)
620 {
621 addr |= 0xFF00;
622 }
623 addr += cpu->cpu_regs.pc;
624 return addr;
625 }
626
627 uint16
628 cpu_fetch_relbranch16 (sim_cpu *cpu)
629 {
630 uint16 addr = cpu_fetch16 (cpu);
631
632 addr += cpu->cpu_regs.pc;
633 return addr;
634 }
635
636 /* Push all the CPU registers (when an interruption occurs). */
637 void
638 cpu_push_all (sim_cpu *cpu)
639 {
640 if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
641 {
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);
647 }
648 else
649 {
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);
655 }
656 }
657
658 /* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations. */
659 void
660 cpu_dbcc (sim_cpu* cpu)
661 {
662 uint8 code;
663 uint16 addr;
664 uint16 inc;
665 uint16 reg;
666
667 code = cpu_fetch8 (cpu);
668 switch (code & 0xc0)
669 {
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;
682 }
683
684 addr = cpu_fetch8 (cpu);
685 if (code & 0x10)
686 addr |= 0xff00;
687
688 addr += cpu_get_pc (cpu);
689 reg = cpu_get_src_reg (cpu, code & 0x07);
690 reg += inc;
691
692 /* Branch according to register value. */
693 if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
694 {
695 cpu_set_pc (cpu, addr);
696 }
697 cpu_set_dst_reg (cpu, code & 0x07, reg);
698 }
699
700 void
701 cpu_exg (sim_cpu* cpu, uint8 code)
702 {
703 uint8 r1, r2;
704 uint16 src1;
705 uint16 src2;
706
707 r1 = (code >> 4) & 0x07;
708 r2 = code & 0x07;
709 if (code & 0x80)
710 {
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;
715
716 cpu_set_dst_reg (cpu, r2, src1);
717 cpu_set_dst_reg (cpu, r1, src2);
718 }
719 else
720 {
721 src1 = cpu_get_src_reg (cpu, r1);
722
723 /* Sign extend the 8-bit registers (A, B, CCR). */
724 if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
725 src1 |= 0xff00;
726
727 cpu_set_dst_reg (cpu, r2, src1);
728 }
729 }
730
731 /* Handle special instructions. */
732 void
733 cpu_special (sim_cpu *cpu, enum M6811_Special special)
734 {
735 switch (special)
736 {
737 case M6811_RTI:
738 {
739 uint8 ccr;
740
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;
749 }
750
751 case M6812_RTI:
752 {
753 uint8 ccr;
754
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;
763 }
764
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)
769 {
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;
775 }
776 /* SCz: not correct... */
777 cpu_push_all (cpu);
778 break;
779
780 case M6811_SWI:
781 interrupts_raise (&cpu->cpu_interrupts, M6811_INT_SWI);
782 interrupts_process (&cpu->cpu_interrupts);
783 break;
784
785 case M6811_EMUL_SYSCALL:
786 case M6811_ILLEGAL:
787 if (cpu->cpu_emul_syscall)
788 {
789 uint8 op = memory_read8 (cpu,
790 cpu_get_pc (cpu) - 1);
791 if (op == 0x41)
792 {
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;
798 }
799 else
800 {
801 emul_os (op, cpu);
802 }
803 return;
804 }
805
806 interrupts_raise (&cpu->cpu_interrupts, M6811_INT_ILLEGAL);
807 interrupts_process (&cpu->cpu_interrupts);
808 break;
809
810 case M6811_TEST:
811 case M6812_BGND:
812 {
813 SIM_DESC sd;
814
815 sd = CPU_STATE (cpu);
816
817 /* Breakpoint instruction if we are under gdb. */
818 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
819 {
820 cpu->cpu_regs.pc --;
821 sim_engine_halt (CPU_STATE (cpu), cpu,
822 0, cpu_get_pc (cpu), sim_stopped,
823 SIM_SIGTRAP);
824 }
825 /* else this is a nop but not in test factory mode. */
826 break;
827 }
828
829 case M6812_IDIVS:
830 {
831 int32 src1 = (int16) cpu_get_d (cpu);
832 int32 src2 = (int16) cpu_get_x (cpu);
833
834 if (src2 == 0)
835 {
836 cpu_set_ccr_C (cpu, 1);
837 }
838 else
839 {
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);
847 }
848 }
849 break;
850
851 case M6812_EDIV:
852 {
853 uint32 src1 = (uint32) cpu_get_x (cpu);
854 uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
855 | (uint32) (cpu_get_d (cpu));
856
857 if (src1 == 0)
858 {
859 cpu_set_ccr_C (cpu, 1);
860 }
861 else
862 {
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);
870 }
871 }
872 break;
873
874 case M6812_EDIVS:
875 {
876 int32 src1 = (int16) cpu_get_x (cpu);
877 int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
878 | (uint32) (cpu_get_d (cpu));
879
880 if (src1 == 0)
881 {
882 cpu_set_ccr_C (cpu, 1);
883 }
884 else
885 {
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);
893 }
894 }
895 break;
896
897 case M6812_EMULS:
898 {
899 int32 src1, src2;
900
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);
909 }
910 break;
911
912 case M6812_EMACS:
913 {
914 int32 src1, src2;
915 uint16 addr;
916
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);
923
924 memory_write16 (cpu, addr, (src1 + src2) >> 16);
925 memory_write16 (cpu, addr + 2, (src1 + src2));
926
927
928 }
929 break;
930
931 case M6812_CALL:
932 {
933 uint8 page;
934 uint16 addr;
935
936 addr = cpu_fetch16 (cpu);
937 page = cpu_fetch8 (cpu);
938
939 cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
940 cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
941
942 cpu_set_page (cpu, page);
943 cpu_set_pc (cpu, addr);
944 }
945 break;
946
947 case M6812_CALL_INDIRECT:
948 {
949 uint8 code;
950 uint16 addr;
951 uint8 page;
952
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)
957 {
958 addr = cpu_get_indexed_operand_addr (cpu, 0);
959 page = memory_read8 (cpu, addr + 2);
960 addr = memory_read16 (cpu, addr);
961 }
962 else
963 {
964 /* Otherwise, page is in the opcode. */
965 addr = cpu_get_indexed_operand16 (cpu, 0);
966 page = cpu_fetch8 (cpu);
967 }
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);
972 }
973 break;
974
975 case M6812_RTC:
976 {
977 uint8 page = cpu_m68hc12_pop_uint8 (cpu);
978 uint16 addr = cpu_m68hc12_pop_uint16 (cpu);
979
980 cpu_set_page (cpu, page);
981 cpu_set_pc (cpu, addr);
982 }
983 break;
984
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;
991 }
992 }
993
994
995 void
996 cpu_single_step (sim_cpu *cpu)
997 {
998 cpu->cpu_current_cycle = 0;
999 cpu->cpu_insn_pc = cpu_get_pc (cpu);
1000
1001 /* Handle the pending interrupts. If an interrupt is handled,
1002 treat this as an single step. */
1003 if (interrupts_process (&cpu->cpu_interrupts))
1004 {
1005 cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
1006 return;
1007 }
1008
1009 /* printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
1010 cpu->cpu_interpretor (cpu);
1011 cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
1012 }
1013
1014 /* VARARGS */
1015 void
1016 sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
1017 uint16 addr, const char *message, ...)
1018 {
1019 char buf[1024];
1020 va_list args;
1021
1022 va_start (args, message);
1023 vsprintf (buf, message, args);
1024 va_end (args);
1025
1026 sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
1027 cpu_memory_exception (cpu, excep, addr, buf);
1028 }
1029
1030
1031 void
1032 cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep,
1033 uint16 addr, const char *message)
1034 {
1035 if (cpu->cpu_running == 0)
1036 return;
1037
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);
1041
1042 #if 0
1043 cpu->mem_exception = excep;
1044 cpu->fault_addr = addr;
1045 cpu->fault_msg = strdup (message);
1046
1047 if (cpu->cpu_use_handler)
1048 {
1049 longjmp (&cpu->cpu_exception_handler, 1);
1050 }
1051 (* cpu->callback->printf_filtered)
1052 (cpu->callback, "Fault at 0x%04x: %s\n", addr, message);
1053 #endif
1054 }
1055
1056 void
1057 cpu_info (SIM_DESC sd, sim_cpu *cpu)
1058 {
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));
1063
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");
1070 }
1071