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