Improve HC11 simulator to support HC12
[external/binutils.git] / sim / m68hc11 / m68hc11_sim.c
1 /* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
2    Copyright 1999, 2000, 2001 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   int result;
647   
648   sim_add_option_table (sd, 0, cpu_options);
649
650   memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
651
652   cpu->cpu_absolute_cycle = 0;
653   cpu->cpu_current_cycle  = 0;
654   cpu->cpu_emul_syscall   = 1;
655   cpu->cpu_running        = 1;
656   cpu->cpu_stop_on_interrupt = 0;
657   cpu->cpu_frequency = 8 * 1000 * 1000;
658   cpu->cpu_frames = 0;
659   cpu->cpu_current_frame = 0;
660   cpu->cpu_use_elf_start = 0;
661   cpu->cpu_elf_start     = 0;
662   cpu->cpu_use_local_config = 0;
663   cpu->cpu_config        = M6811_NOSEC | M6811_NOCOP | M6811_ROMON |
664     M6811_EEON;
665   result = interrupts_initialize (cpu);
666
667   cpu->cpu_is_initialized = 1;
668   return result;
669 }
670
671
672 /* Reinitialize the processor after a reset.  */
673 int
674 cpu_reset (sim_cpu *cpu)
675 {
676   cpu->cpu_need_update_frame = 0;
677   cpu->cpu_current_frame = 0;
678   while (cpu->cpu_frames)
679     cpu_remove_frame_list (cpu, cpu->cpu_frames);
680
681   /* Initialize the config register.
682      It is only initialized at reset time.  */
683   memset (cpu->ios, 0, sizeof (cpu->ios));
684   if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
685     cpu->ios[M6811_INIT] = 0x1;
686   else
687     cpu->ios[M6811_INIT] = 0;
688
689   /* Output compare registers set to 0xFFFF.  */
690   cpu->ios[M6811_TOC1_H] = 0xFF;
691   cpu->ios[M6811_TOC1_L] = 0xFF;
692   cpu->ios[M6811_TOC2_H] = 0xFF;
693   cpu->ios[M6811_TOC2_L] = 0xFF;
694   cpu->ios[M6811_TOC3_H] = 0xFF;
695   cpu->ios[M6811_TOC4_L] = 0xFF;
696   cpu->ios[M6811_TOC5_H] = 0xFF;
697   cpu->ios[M6811_TOC5_L] = 0xFF;
698
699   /* Setup the processor registers.  */
700   memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
701   cpu->cpu_absolute_cycle = 0;
702   cpu->cpu_current_cycle  = 0;
703   cpu->cpu_is_initialized = 0;
704
705   /* Reinitialize the CPU operating mode.  */
706   cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
707   return 0;
708 }
709
710 /* Reinitialize the processor after a reset.  */
711 int
712 cpu_restart (sim_cpu *cpu)
713 {
714   uint16 addr;
715
716   /* Get CPU starting address depending on the CPU mode.  */
717   if (cpu->cpu_use_elf_start == 0)
718     {
719       switch ((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA))
720         {
721           /* Single Chip  */
722         default:
723         case 0 :
724           addr = memory_read16 (cpu, 0xFFFE);
725           break;
726
727           /* Expanded Multiplexed  */
728         case M6811_MDA:
729           addr = memory_read16 (cpu, 0xFFFE);
730           break;
731
732           /* Special Bootstrap  */
733         case M6811_SMOD:
734           addr = 0;
735           break;
736
737           /* Factory Test  */
738         case M6811_MDA | M6811_SMOD:
739           addr = memory_read16 (cpu, 0xFFFE);
740           break;
741         }
742     }
743   else
744     {
745       addr = cpu->cpu_elf_start;
746     }
747   
748   /* Setup the processor registers.  */
749   cpu->cpu_insn_pc  = addr;
750   cpu->cpu_regs.pc  = addr;
751   cpu->cpu_regs.ccr = M6811_X_BIT | M6811_I_BIT | M6811_S_BIT;
752   cpu->cpu_absolute_cycle = 0;
753   cpu->cpu_is_initialized = 1;
754   cpu->cpu_current_cycle  = 0;
755
756   cpu_call (cpu, addr);
757   
758   return 0;
759 }
760
761 void
762 print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val, int mode)
763 {
764   while (desc->mask)
765     {
766       if (val & desc->mask)
767         sim_io_printf (sd, "%s",
768                        mode == 0 ? desc->short_name : desc->long_name);
769       desc++;
770     }
771 }
772
773 void
774 print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
775                uint8 val, uint16 addr)
776 {
777   sim_io_printf (sd, "  %-9.9s @ 0x%04x 0x%02x ", name, addr, val);
778   if (desc)
779     print_io_reg_desc (sd, desc, val, 0);
780 }
781
782 void
783 cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val)
784 {
785   cpu_set_ccr_V (proc, 0);
786   cpu_set_ccr_N (proc, val & 0x80 ? 1 : 0);
787   cpu_set_ccr_Z (proc, val == 0 ? 1 : 0);
788 }
789
790
791 uint16
792 cpu_fetch_relbranch (sim_cpu *cpu)
793 {
794   uint16 addr = (uint16) cpu_fetch8 (cpu);
795
796   if (addr & 0x0080)
797     {
798       addr |= 0xFF00;
799     }
800   addr += cpu->cpu_regs.pc;
801   return addr;
802 }
803
804 uint16
805 cpu_fetch_relbranch16 (sim_cpu *cpu)
806 {
807   uint16 addr = cpu_fetch16 (cpu);
808
809   addr += cpu->cpu_regs.pc;
810   return addr;
811 }
812
813 /* Push all the CPU registers (when an interruption occurs).  */
814 void
815 cpu_push_all (sim_cpu *cpu)
816 {
817   if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
818     {
819       cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.pc);
820       cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.iy);
821       cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.ix);
822       cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.d);
823       cpu_m68hc11_push_uint8 (cpu, cpu->cpu_regs.ccr);
824     }
825   else
826     {
827       cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.pc);
828       cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.iy);
829       cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.ix);
830       cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.d);
831       cpu_m68hc12_push_uint8 (cpu, cpu->cpu_regs.ccr);
832     }
833 }
834
835 /* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations.  */
836 void
837 cpu_dbcc (sim_cpu* cpu)
838 {
839   uint8 code;
840   uint16 addr;
841   uint16 inc;
842   uint16 reg;
843   
844   code = cpu_fetch8 (cpu);
845   switch (code & 0xc0)
846     {
847     case 0x80: /* ibcc */
848       inc = 1;
849       break;
850     case 0x40: /* tbcc */
851       inc = 0;
852       break;
853     case 0:    /* dbcc */
854       inc = -1;
855       break;
856     default:
857       abort ();
858       break;
859     }
860
861   addr = cpu_fetch8 (cpu);
862   if (code & 0x10)
863     addr |= 0xff00;
864
865   addr += cpu_get_pc (cpu);
866   reg = cpu_get_src_reg (cpu, code & 0x07);
867   reg += inc;
868
869   /* Branch according to register value.  */
870   if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
871     {
872       cpu_set_pc (cpu, addr);
873     }
874   cpu_set_dst_reg (cpu, code & 0x07, reg);
875 }
876
877 void
878 cpu_exg (sim_cpu* cpu, uint8 code)
879 {
880   uint8 r1, r2;
881   uint16 src1;
882   uint16 src2;
883
884   r1 = (code >> 4) & 0x07;
885   r2 = code & 0x07;
886   if (code & 0x80)
887     {
888       src1 = cpu_get_src_reg (cpu, r1);
889       src2 = cpu_get_src_reg (cpu, r2);
890       if (r2 == 1 || r2 == 2)
891         src2 |= 0xff00;
892       
893       cpu_set_dst_reg (cpu, r2, src1);
894       cpu_set_dst_reg (cpu, r1, src2);
895     }
896   else
897     {
898       src1 = cpu_get_src_reg (cpu, r1);
899
900       /* Sign extend the 8-bit registers (A, B, CCR).  */
901       if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
902         src1 |= 0xff00;
903
904       cpu_set_dst_reg (cpu, r2, src1);
905     }
906 }
907
908 /* Handle special instructions.  */
909 void
910 cpu_special (sim_cpu *cpu, enum M6811_Special special)
911 {
912   switch (special)
913     {
914     case M6811_RTI:
915       {
916         uint8 ccr;
917
918         ccr = cpu_m68hc11_pop_uint8 (cpu);
919         cpu_set_ccr (cpu, ccr);
920         cpu_set_d (cpu, cpu_m68hc11_pop_uint16 (cpu));
921         cpu_set_x (cpu, cpu_m68hc11_pop_uint16 (cpu));
922         cpu_set_y (cpu, cpu_m68hc11_pop_uint16 (cpu));
923         cpu_set_pc (cpu, cpu_m68hc11_pop_uint16 (cpu));
924         cpu_return (cpu);
925         break;
926       }
927
928     case M6812_RTI:
929       {
930         uint8 ccr;
931
932         ccr = cpu_m68hc12_pop_uint8 (cpu);
933         cpu_set_ccr (cpu, ccr);
934         cpu_set_d (cpu, cpu_m68hc12_pop_uint16 (cpu));
935         cpu_set_x (cpu, cpu_m68hc12_pop_uint16 (cpu));
936         cpu_set_y (cpu, cpu_m68hc12_pop_uint16 (cpu));
937         cpu_set_pc (cpu, cpu_m68hc12_pop_uint16 (cpu));
938         cpu_return (cpu);
939         break;
940       }
941       
942     case M6811_WAI:
943       /* In the ELF-start mode, we are in a special mode where
944          the WAI corresponds to an exit.  */
945       if (cpu->cpu_use_elf_start)
946         {
947           cpu_set_pc (cpu, cpu->cpu_insn_pc);
948           sim_engine_halt (CPU_STATE (cpu), cpu,
949                            NULL, NULL_CIA, sim_exited,
950                            cpu_get_d (cpu));
951           return;
952         }
953       /* SCz: not correct... */
954       cpu_push_all (cpu);
955       break;
956       
957     case M6811_SWI:
958       interrupts_raise (&cpu->cpu_interrupts, M6811_INT_SWI);
959       interrupts_process (&cpu->cpu_interrupts);
960       break;
961       
962     case M6811_EMUL_SYSCALL:
963     case M6811_ILLEGAL:
964       if (cpu->cpu_emul_syscall)
965         {
966           uint8 op = memory_read8 (cpu,
967                                    cpu_get_pc (cpu) - 1);
968           if (op == 0x41)
969             {
970               cpu_set_pc (cpu, cpu->cpu_insn_pc);
971               sim_engine_halt (CPU_STATE (cpu), cpu,
972                                NULL, NULL_CIA, sim_exited,
973                                cpu_get_d (cpu));
974               return;
975             }
976           else
977             {
978               emul_os (op, cpu);
979             }
980           return;
981         }
982       
983       interrupts_raise (&cpu->cpu_interrupts, M6811_INT_ILLEGAL);
984       interrupts_process (&cpu->cpu_interrupts);
985       break;
986
987     case M6811_TEST:
988     case M6812_BGND:
989       {
990         SIM_DESC sd;
991
992         sd = CPU_STATE (cpu);
993
994         /* Breakpoint instruction if we are under gdb.  */
995         if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
996           {
997             cpu->cpu_regs.pc --;
998             sim_engine_halt (CPU_STATE (cpu), cpu,
999                              0, cpu_get_pc (cpu), sim_stopped,
1000                              SIM_SIGTRAP);
1001           }
1002         /* else this is a nop but not in test factory mode.  */
1003         break;
1004       }
1005
1006     case M6812_IDIVS:
1007       {
1008         int32 src1 = (int16) cpu_get_d (cpu);
1009         int32 src2 = (int16) cpu_get_x (cpu);
1010
1011         if (src2 == 0)
1012           {
1013             cpu_set_ccr_C (cpu, 1);
1014           }
1015         else
1016           {
1017             cpu_set_d (cpu, src1 % src2);
1018             src1 = src1 / src2;
1019             cpu_set_x (cpu, src1);
1020             cpu_set_ccr_C (cpu, 0);
1021             cpu_set_ccr_Z (cpu, src1 == 0);
1022             cpu_set_ccr_N (cpu, src1 & 0x8000);
1023             cpu_set_ccr_V (cpu, src1 >= 32768 || src1 < -32768);
1024           }
1025       }
1026       break;
1027       
1028     case M6812_EDIV:
1029       {
1030         uint32 src1 = (uint32) cpu_get_x (cpu);
1031         uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
1032           | (uint32) (cpu_get_d (cpu));
1033
1034         if (src1 == 0)
1035           {
1036             cpu_set_ccr_C (cpu, 1);
1037           }
1038         else
1039           {
1040             cpu_set_ccr_C (cpu, 0);
1041             cpu_set_d (cpu, src2 % src1);
1042             src2 = src2 / src1;
1043             cpu_set_y (cpu, src2);
1044             cpu_set_ccr_Z (cpu, src2 == 0);
1045             cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
1046             cpu_set_ccr_V (cpu, (src2 & 0xffff0000) != 0);
1047           }
1048       }
1049       break;
1050       
1051     case M6812_EDIVS:
1052       {
1053         int32 src1 = (int16) cpu_get_x (cpu);
1054         int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
1055           | (uint32) (cpu_get_d (cpu));
1056
1057         if (src1 == 0)
1058           {
1059             cpu_set_ccr_C (cpu, 1);
1060           }
1061         else
1062           {
1063             cpu_set_ccr_C (cpu, 0);
1064             cpu_set_d (cpu, src2 % src1);
1065             src2 = src2 / src1;
1066             cpu_set_y (cpu, src2);
1067             cpu_set_ccr_Z (cpu, src2 == 0);
1068             cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
1069             cpu_set_ccr_V (cpu, src2 > 32767 || src2 < -32768);
1070           }
1071       }
1072       break;      
1073
1074     case M6812_EMULS:
1075       {
1076         int32 src1, src2;
1077
1078         src1 = (int16) cpu_get_d (cpu);
1079         src2 = (int16) cpu_get_y (cpu);
1080         src1 = src1 * src2;
1081         cpu_set_d (cpu, src1 & 0x0ffff);
1082         cpu_set_y (cpu, src1 >> 16);
1083         cpu_set_ccr_Z (cpu, src1 == 0);
1084         cpu_set_ccr_N (cpu, (src1 & 0x80000000) != 0);
1085         cpu_set_ccr_C (cpu, (src1 & 0x00008000) != 0);
1086       }
1087       break;
1088       
1089     case M6812_EMACS:
1090       {
1091         int32 src1, src2;
1092         uint16 addr;
1093         
1094         addr = cpu_fetch16 (cpu);
1095         src1 = (int16) memory_read16 (cpu, cpu_get_x (cpu));
1096         src2 = (int16) memory_read16 (cpu, cpu_get_y (cpu));
1097         src1 = src1 * src2;
1098         src2 = (((uint32) memory_read16 (cpu, addr)) << 16)
1099           | (uint32) memory_read16 (cpu, addr + 2);
1100
1101         memory_write16 (cpu, addr, (src1 + src2) >> 16);
1102         memory_write16 (cpu, addr + 2, (src1 + src2));
1103
1104         
1105       }
1106       break;
1107
1108     case M6812_ETBL:
1109     default:
1110       sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
1111                        cpu_get_pc (cpu), sim_stopped,
1112                        SIM_SIGILL);
1113       break;
1114     }
1115 }
1116
1117
1118 void
1119 cpu_single_step (sim_cpu *cpu)
1120 {
1121   cpu->cpu_current_cycle = 0;
1122   cpu->cpu_insn_pc = cpu_get_pc (cpu);
1123
1124   /* Handle the pending interrupts.  If an interrupt is handled,
1125      treat this as an single step.  */
1126   if (interrupts_process (&cpu->cpu_interrupts))
1127     {
1128       cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
1129       return;
1130     }
1131   
1132   /*  printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
1133   cpu->cpu_interpretor (cpu);
1134   cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
1135 }
1136
1137 /* VARARGS */
1138 void
1139 sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
1140                   uint16 addr, const char *message, ...)
1141 {
1142   char buf[1024];
1143   va_list args;
1144
1145   va_start (args, message);
1146   vsprintf (buf, message, args);
1147   va_end (args);
1148
1149   printf("%s\n", buf);
1150   cpu_memory_exception (cpu, excep, addr, buf);
1151 }
1152
1153
1154 void
1155 cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep,
1156                       uint16 addr, const char *message)
1157 {
1158   if (cpu->cpu_running == 0)
1159     return;
1160
1161   cpu_set_pc (cpu, cpu->cpu_insn_pc);
1162   sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
1163                    cpu_get_pc (cpu), sim_stopped, excep);
1164   
1165 #if 0
1166   cpu->mem_exception = excep;
1167   cpu->fault_addr    = addr;
1168   cpu->fault_msg     = strdup (message);
1169
1170   if (cpu->cpu_use_handler)
1171     {
1172       longjmp (&cpu->cpu_exception_handler, 1);
1173     }
1174   (* cpu->callback->printf_filtered)
1175     (cpu->callback, "Fault at 0x%04x: %s\n", addr, message);
1176 #endif
1177 }
1178
1179 void
1180 cpu_info (SIM_DESC sd, sim_cpu *cpu)
1181 {
1182   sim_io_printf (sd, "CPU info:\n");
1183   sim_io_printf (sd, "  Absolute cycle: %s\n",
1184                  cycle_to_string (cpu, cpu->cpu_absolute_cycle));
1185   
1186   sim_io_printf (sd, "  Syscall emulation: %s\n",
1187                  cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");
1188   sim_io_printf (sd, "  Memory errors detection: %s\n",
1189                  cpu->cpu_check_memory ? "yes" : "no");
1190   sim_io_printf (sd, "  Stop on interrupt: %s\n",
1191                  cpu->cpu_stop_on_interrupt ? "yes" : "no");
1192 }
1193