xref: /netbsd-src/external/gpl3/gdb/dist/sim/m68hc11/m68hc11_sim.c (revision 1897181a7231d5fc7ab48994d1447fcbc4e13a49)
1 /* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
2    Copyright 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010, 2011
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 
1072