* sim-main.h (phys_to_virt): Use memory bank parameters to translate
[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->bank_start = 0;
468   cpu->bank_end   = 0;
469   cpu->bank_shift = 0;
470   cpu->cpu_config        = M6811_NOSEC | M6811_NOCOP | M6811_ROMON |
471     M6811_EEON;
472   interrupts_initialize (sd, cpu);
473
474   cpu->cpu_is_initialized = 1;
475   return 0;
476 }
477
478
479 /* Reinitialize the processor after a reset.  */
480 int
481 cpu_reset (sim_cpu *cpu)
482 {
483   /* Initialize the config register.
484      It is only initialized at reset time.  */
485   memset (cpu->ios, 0, sizeof (cpu->ios));
486   if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
487     cpu->ios[M6811_INIT] = 0x1;
488   else
489     cpu->ios[M6811_INIT] = 0;
490
491   /* Output compare registers set to 0xFFFF.  */
492   cpu->ios[M6811_TOC1_H] = 0xFF;
493   cpu->ios[M6811_TOC1_L] = 0xFF;
494   cpu->ios[M6811_TOC2_H] = 0xFF;
495   cpu->ios[M6811_TOC2_L] = 0xFF;
496   cpu->ios[M6811_TOC3_H] = 0xFF;
497   cpu->ios[M6811_TOC4_L] = 0xFF;
498   cpu->ios[M6811_TOC5_H] = 0xFF;
499   cpu->ios[M6811_TOC5_L] = 0xFF;
500
501   /* Setup the processor registers.  */
502   memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
503   cpu->cpu_absolute_cycle = 0;
504   cpu->cpu_current_cycle  = 0;
505   cpu->cpu_is_initialized = 0;
506
507   /* Reset interrupts.  */
508   interrupts_reset (&cpu->cpu_interrupts);
509
510   /* Reinitialize the CPU operating mode.  */
511   cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
512   return 0;
513 }
514
515 /* Reinitialize the processor after a reset.  */
516 int
517 cpu_restart (sim_cpu *cpu)
518 {
519   uint16 addr;
520
521   /* Get CPU starting address depending on the CPU mode.  */
522   if (cpu->cpu_use_elf_start == 0)
523     {
524       switch ((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA))
525         {
526           /* Single Chip  */
527         default:
528         case 0 :
529           addr = memory_read16 (cpu, 0xFFFE);
530           break;
531
532           /* Expanded Multiplexed  */
533         case M6811_MDA:
534           addr = memory_read16 (cpu, 0xFFFE);
535           break;
536
537           /* Special Bootstrap  */
538         case M6811_SMOD:
539           addr = 0;
540           break;
541
542           /* Factory Test  */
543         case M6811_MDA | M6811_SMOD:
544           addr = memory_read16 (cpu, 0xFFFE);
545           break;
546         }
547     }
548   else
549     {
550       addr = cpu->cpu_elf_start;
551     }
552   
553   /* Setup the processor registers.  */
554   cpu->cpu_insn_pc  = addr;
555   cpu->cpu_regs.pc  = addr;
556   cpu->cpu_regs.ccr = M6811_X_BIT | M6811_I_BIT | M6811_S_BIT;
557   cpu->cpu_absolute_cycle = 0;
558   cpu->cpu_is_initialized = 1;
559   cpu->cpu_current_cycle  = 0;
560
561   cpu_call (cpu, addr);
562   
563   return 0;
564 }
565
566 void
567 print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val, int mode)
568 {
569   while (desc->mask)
570     {
571       if (val & desc->mask)
572         sim_io_printf (sd, "%s",
573                        mode == 0 ? desc->short_name : desc->long_name);
574       desc++;
575     }
576 }
577
578 void
579 print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
580                uint8 val, uint16 addr)
581 {
582   sim_io_printf (sd, "  %-9.9s @ 0x%04x 0x%02x ", name, addr, val);
583   if (desc)
584     print_io_reg_desc (sd, desc, val, 0);
585 }
586
587 void
588 print_io_word (SIM_DESC sd, const char *name, io_reg_desc *desc,
589                uint16 val, uint16 addr)
590 {
591   sim_io_printf (sd, "  %-9.9s @ 0x%04x 0x%04x ", name, addr, val);
592   if (desc)
593     print_io_reg_desc (sd, desc, val, 0);
594 }
595
596 void
597 cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val)
598 {
599   cpu_set_ccr_V (proc, 0);
600   cpu_set_ccr_N (proc, val & 0x80 ? 1 : 0);
601   cpu_set_ccr_Z (proc, val == 0 ? 1 : 0);
602 }
603
604
605 uint16
606 cpu_fetch_relbranch (sim_cpu *cpu)
607 {
608   uint16 addr = (uint16) cpu_fetch8 (cpu);
609
610   if (addr & 0x0080)
611     {
612       addr |= 0xFF00;
613     }
614   addr += cpu->cpu_regs.pc;
615   return addr;
616 }
617
618 uint16
619 cpu_fetch_relbranch16 (sim_cpu *cpu)
620 {
621   uint16 addr = cpu_fetch16 (cpu);
622
623   addr += cpu->cpu_regs.pc;
624   return addr;
625 }
626
627 /* Push all the CPU registers (when an interruption occurs).  */
628 void
629 cpu_push_all (sim_cpu *cpu)
630 {
631   if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
632     {
633       cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.pc);
634       cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.iy);
635       cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.ix);
636       cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.d);
637       cpu_m68hc11_push_uint8 (cpu, cpu->cpu_regs.ccr);
638     }
639   else
640     {
641       cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.pc);
642       cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.iy);
643       cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.ix);
644       cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.d);
645       cpu_m68hc12_push_uint8 (cpu, cpu->cpu_regs.ccr);
646     }
647 }
648
649 /* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations.  */
650 void
651 cpu_dbcc (sim_cpu* cpu)
652 {
653   uint8 code;
654   uint16 addr;
655   uint16 inc;
656   uint16 reg;
657   
658   code = cpu_fetch8 (cpu);
659   switch (code & 0xc0)
660     {
661     case 0x80: /* ibcc */
662       inc = 1;
663       break;
664     case 0x40: /* tbcc */
665       inc = 0;
666       break;
667     case 0:    /* dbcc */
668       inc = -1;
669       break;
670     default:
671       abort ();
672       break;
673     }
674
675   addr = cpu_fetch8 (cpu);
676   if (code & 0x10)
677     addr |= 0xff00;
678
679   addr += cpu_get_pc (cpu);
680   reg = cpu_get_src_reg (cpu, code & 0x07);
681   reg += inc;
682
683   /* Branch according to register value.  */
684   if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
685     {
686       cpu_set_pc (cpu, addr);
687     }
688   cpu_set_dst_reg (cpu, code & 0x07, reg);
689 }
690
691 void
692 cpu_exg (sim_cpu* cpu, uint8 code)
693 {
694   uint8 r1, r2;
695   uint16 src1;
696   uint16 src2;
697
698   r1 = (code >> 4) & 0x07;
699   r2 = code & 0x07;
700   if (code & 0x80)
701     {
702       src1 = cpu_get_src_reg (cpu, r1);
703       src2 = cpu_get_src_reg (cpu, r2);
704       if (r2 == 1 || r2 == 2)
705         src2 |= 0xff00;
706       
707       cpu_set_dst_reg (cpu, r2, src1);
708       cpu_set_dst_reg (cpu, r1, src2);
709     }
710   else
711     {
712       src1 = cpu_get_src_reg (cpu, r1);
713
714       /* Sign extend the 8-bit registers (A, B, CCR).  */
715       if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
716         src1 |= 0xff00;
717
718       cpu_set_dst_reg (cpu, r2, src1);
719     }
720 }
721
722 /* Handle special instructions.  */
723 void
724 cpu_special (sim_cpu *cpu, enum M6811_Special special)
725 {
726   switch (special)
727     {
728     case M6811_RTI:
729       {
730         uint8 ccr;
731
732         ccr = cpu_m68hc11_pop_uint8 (cpu);
733         cpu_set_ccr (cpu, ccr);
734         cpu_set_d (cpu, cpu_m68hc11_pop_uint16 (cpu));
735         cpu_set_x (cpu, cpu_m68hc11_pop_uint16 (cpu));
736         cpu_set_y (cpu, cpu_m68hc11_pop_uint16 (cpu));
737         cpu_set_pc (cpu, cpu_m68hc11_pop_uint16 (cpu));
738         cpu_return (cpu);
739         break;
740       }
741
742     case M6812_RTI:
743       {
744         uint8 ccr;
745
746         ccr = cpu_m68hc12_pop_uint8 (cpu);
747         cpu_set_ccr (cpu, ccr);
748         cpu_set_d (cpu, cpu_m68hc12_pop_uint16 (cpu));
749         cpu_set_x (cpu, cpu_m68hc12_pop_uint16 (cpu));
750         cpu_set_y (cpu, cpu_m68hc12_pop_uint16 (cpu));
751         cpu_set_pc (cpu, cpu_m68hc12_pop_uint16 (cpu));
752         cpu_return (cpu);
753         break;
754       }
755       
756     case M6811_WAI:
757       /* In the ELF-start mode, we are in a special mode where
758          the WAI corresponds to an exit.  */
759       if (cpu->cpu_use_elf_start)
760         {
761           cpu_set_pc (cpu, cpu->cpu_insn_pc);
762           sim_engine_halt (CPU_STATE (cpu), cpu,
763                            NULL, NULL_CIA, sim_exited,
764                            cpu_get_d (cpu));
765           return;
766         }
767       /* SCz: not correct... */
768       cpu_push_all (cpu);
769       break;
770       
771     case M6811_SWI:
772       interrupts_raise (&cpu->cpu_interrupts, M6811_INT_SWI);
773       interrupts_process (&cpu->cpu_interrupts);
774       break;
775       
776     case M6811_EMUL_SYSCALL:
777     case M6811_ILLEGAL:
778       if (cpu->cpu_emul_syscall)
779         {
780           uint8 op = memory_read8 (cpu,
781                                    cpu_get_pc (cpu) - 1);
782           if (op == 0x41)
783             {
784               cpu_set_pc (cpu, cpu->cpu_insn_pc);
785               sim_engine_halt (CPU_STATE (cpu), cpu,
786                                NULL, NULL_CIA, sim_exited,
787                                cpu_get_d (cpu));
788               return;
789             }
790           else
791             {
792               emul_os (op, cpu);
793             }
794           return;
795         }
796       
797       interrupts_raise (&cpu->cpu_interrupts, M6811_INT_ILLEGAL);
798       interrupts_process (&cpu->cpu_interrupts);
799       break;
800
801     case M6811_TEST:
802     case M6812_BGND:
803       {
804         SIM_DESC sd;
805
806         sd = CPU_STATE (cpu);
807
808         /* Breakpoint instruction if we are under gdb.  */
809         if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
810           {
811             cpu->cpu_regs.pc --;
812             sim_engine_halt (CPU_STATE (cpu), cpu,
813                              0, cpu_get_pc (cpu), sim_stopped,
814                              SIM_SIGTRAP);
815           }
816         /* else this is a nop but not in test factory mode.  */
817         break;
818       }
819
820     case M6812_IDIVS:
821       {
822         int32 src1 = (int16) cpu_get_d (cpu);
823         int32 src2 = (int16) cpu_get_x (cpu);
824
825         if (src2 == 0)
826           {
827             cpu_set_ccr_C (cpu, 1);
828           }
829         else
830           {
831             cpu_set_d (cpu, src1 % src2);
832             src1 = src1 / src2;
833             cpu_set_x (cpu, src1);
834             cpu_set_ccr_C (cpu, 0);
835             cpu_set_ccr_Z (cpu, src1 == 0);
836             cpu_set_ccr_N (cpu, src1 & 0x8000);
837             cpu_set_ccr_V (cpu, src1 >= 32768 || src1 < -32768);
838           }
839       }
840       break;
841       
842     case M6812_EDIV:
843       {
844         uint32 src1 = (uint32) cpu_get_x (cpu);
845         uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
846           | (uint32) (cpu_get_d (cpu));
847
848         if (src1 == 0)
849           {
850             cpu_set_ccr_C (cpu, 1);
851           }
852         else
853           {
854             cpu_set_ccr_C (cpu, 0);
855             cpu_set_d (cpu, src2 % src1);
856             src2 = src2 / src1;
857             cpu_set_y (cpu, src2);
858             cpu_set_ccr_Z (cpu, src2 == 0);
859             cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
860             cpu_set_ccr_V (cpu, (src2 & 0xffff0000) != 0);
861           }
862       }
863       break;
864       
865     case M6812_EDIVS:
866       {
867         int32 src1 = (int16) cpu_get_x (cpu);
868         int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
869           | (uint32) (cpu_get_d (cpu));
870
871         if (src1 == 0)
872           {
873             cpu_set_ccr_C (cpu, 1);
874           }
875         else
876           {
877             cpu_set_ccr_C (cpu, 0);
878             cpu_set_d (cpu, src2 % src1);
879             src2 = src2 / src1;
880             cpu_set_y (cpu, src2);
881             cpu_set_ccr_Z (cpu, src2 == 0);
882             cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
883             cpu_set_ccr_V (cpu, src2 > 32767 || src2 < -32768);
884           }
885       }
886       break;      
887
888     case M6812_EMULS:
889       {
890         int32 src1, src2;
891
892         src1 = (int16) cpu_get_d (cpu);
893         src2 = (int16) cpu_get_y (cpu);
894         src1 = src1 * src2;
895         cpu_set_d (cpu, src1 & 0x0ffff);
896         cpu_set_y (cpu, src1 >> 16);
897         cpu_set_ccr_Z (cpu, src1 == 0);
898         cpu_set_ccr_N (cpu, (src1 & 0x80000000) != 0);
899         cpu_set_ccr_C (cpu, (src1 & 0x00008000) != 0);
900       }
901       break;
902       
903     case M6812_EMACS:
904       {
905         int32 src1, src2;
906         uint16 addr;
907         
908         addr = cpu_fetch16 (cpu);
909         src1 = (int16) memory_read16 (cpu, cpu_get_x (cpu));
910         src2 = (int16) memory_read16 (cpu, cpu_get_y (cpu));
911         src1 = src1 * src2;
912         src2 = (((uint32) memory_read16 (cpu, addr)) << 16)
913           | (uint32) memory_read16 (cpu, addr + 2);
914
915         memory_write16 (cpu, addr, (src1 + src2) >> 16);
916         memory_write16 (cpu, addr + 2, (src1 + src2));
917
918         
919       }
920       break;
921
922     case M6812_CALL:
923       {
924         uint8 page;
925         uint16 addr;
926
927         addr = cpu_fetch16 (cpu);
928         page = cpu_fetch8 (cpu);
929
930         cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
931         cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
932
933         cpu_set_page (cpu, page);
934         cpu_set_pc (cpu, addr);
935       }
936       break;
937
938     case M6812_CALL_INDIRECT:
939       {
940         uint8 code;
941         uint16 addr;
942         uint8 page;
943
944         code = memory_read8 (cpu, cpu_get_pc (cpu));
945         /* Indirect addressing call has the page specified in the
946            memory location pointed to by the address.  */
947         if ((code & 0xE3) == 0xE3)
948           {
949             addr = cpu_get_indexed_operand_addr (cpu, 0);
950             page = memory_read8 (cpu, addr + 2);
951             addr = memory_read16 (cpu, addr);
952           }
953         else
954           {
955             /* Otherwise, page is in the opcode.  */
956             addr = cpu_get_indexed_operand16 (cpu, 0);
957             page = cpu_fetch8 (cpu);
958           }
959         cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
960         cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
961         cpu_set_page (cpu, page);
962         cpu_set_pc (cpu, addr);
963       }
964       break;
965
966     case M6812_RTC:
967       {
968         uint8 page = cpu_m68hc12_pop_uint8 (cpu);
969         uint16 addr = cpu_m68hc12_pop_uint16 (cpu);
970
971         cpu_set_page (cpu, page);
972         cpu_set_pc (cpu, addr);
973       }
974       break;
975       
976     case M6812_ETBL:
977     default:
978       sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
979                        cpu_get_pc (cpu), sim_stopped,
980                        SIM_SIGILL);
981       break;
982     }
983 }
984
985
986 void
987 cpu_single_step (sim_cpu *cpu)
988 {
989   cpu->cpu_current_cycle = 0;
990   cpu->cpu_insn_pc = cpu_get_pc (cpu);
991
992   /* Handle the pending interrupts.  If an interrupt is handled,
993      treat this as an single step.  */
994   if (interrupts_process (&cpu->cpu_interrupts))
995     {
996       cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
997       return;
998     }
999   
1000   /*  printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
1001   cpu->cpu_interpretor (cpu);
1002   cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
1003 }
1004
1005 /* VARARGS */
1006 void
1007 sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
1008                   uint16 addr, const char *message, ...)
1009 {
1010   char buf[1024];
1011   va_list args;
1012
1013   va_start (args, message);
1014   vsprintf (buf, message, args);
1015   va_end (args);
1016
1017   sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
1018   cpu_memory_exception (cpu, excep, addr, buf);
1019 }
1020
1021
1022 void
1023 cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep,
1024                       uint16 addr, const char *message)
1025 {
1026   if (cpu->cpu_running == 0)
1027     return;
1028
1029   cpu_set_pc (cpu, cpu->cpu_insn_pc);
1030   sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
1031                    cpu_get_pc (cpu), sim_stopped, excep);
1032   
1033 #if 0
1034   cpu->mem_exception = excep;
1035   cpu->fault_addr    = addr;
1036   cpu->fault_msg     = strdup (message);
1037
1038   if (cpu->cpu_use_handler)
1039     {
1040       longjmp (&cpu->cpu_exception_handler, 1);
1041     }
1042   (* cpu->callback->printf_filtered)
1043     (cpu->callback, "Fault at 0x%04x: %s\n", addr, message);
1044 #endif
1045 }
1046
1047 void
1048 cpu_info (SIM_DESC sd, sim_cpu *cpu)
1049 {
1050   sim_io_printf (sd, "CPU info:\n");
1051   sim_io_printf (sd, "  Absolute cycle: %s\n",
1052                  cycle_to_string (cpu, cpu->cpu_absolute_cycle));
1053   
1054   sim_io_printf (sd, "  Syscall emulation: %s\n",
1055                  cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");
1056   sim_io_printf (sd, "  Memory errors detection: %s\n",
1057                  cpu->cpu_check_memory ? "yes" : "no");
1058   sim_io_printf (sd, "  Stop on interrupt: %s\n",
1059                  cpu->cpu_stop_on_interrupt ? "yes" : "no");
1060 }
1061