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