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