* dv-m68hc11tim.c (cycle_to_string): Add flags parameter to better
[external/binutils.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_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