OSDN Git Service

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