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