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