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