]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/m68hc11/m68hc11_sim.c
Copyright updates for 2007.
[thirdparty/binutils-gdb.git] / sim / m68hc11 / m68hc11_sim.c
CommitLineData
81e09ed8 1/* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
6aba47ca 2 Copyright 1999, 2000, 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
63f36def 3 Written by Stephane Carrez (stcarrez@nerim.fr)
e0709f50
AC
4
5This file is part of GDB, GAS, and the GNU binutils.
6
7GDB, GAS, and the GNU binutils are free software; you can redistribute
8them and/or modify them under the terms of the GNU General Public
9License as published by the Free Software Foundation; either version
101, or (at your option) any later version.
11
12GDB, GAS, and the GNU binutils are distributed in the hope that they
13will be useful, but WITHOUT ANY WARRANTY; without even the implied
14warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15the GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this file; see the file COPYING. If not, write to the Free
19Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include "sim-main.h"
22#include "sim-assert.h"
23#include "sim-module.h"
24#include "sim-options.h"
25
e0709f50
AC
26enum {
27 OPTION_CPU_RESET = OPTION_START,
28 OPTION_EMUL_OS,
29 OPTION_CPU_CONFIG,
a685700c 30 OPTION_CPU_BOOTSTRAP,
e0709f50
AC
31 OPTION_CPU_MODE
32};
33
34static DECLARE_OPTION_HANDLER (cpu_option_handler);
35
36static 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
a685700c
SC
50 { {"bootstrap", no_argument, NULL, OPTION_CPU_BOOTSTRAP },
51 '\0', NULL, "Start the processing in bootstrap mode",
52 cpu_option_handler },
53
e0709f50
AC
54 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
55};
56
57
58static SIM_RC
59cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
60 int opt, char *arg, int is_command)
61{
e0709f50
AC
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;
a685700c
SC
85
86 case OPTION_CPU_BOOTSTRAP:
87 cpu->cpu_start_mode = "bootstrap";
88 break;
89
e0709f50
AC
90 case OPTION_CPU_MODE:
91 break;
92 }
93
94 return SIM_RC_OK;
95}
96
e0709f50 97
e0709f50
AC
98void
99cpu_call (sim_cpu *cpu, uint16 addr)
100{
e0709f50
AC
101
102 cpu_set_pc (cpu, addr);
e0709f50
AC
103}
104
105void
106cpu_return (sim_cpu *cpu)
107{
e0709f50
AC
108}
109
110/* Set the stack pointer and re-compute the current frame. */
111void
112cpu_set_sp (sim_cpu *cpu, uint16 val)
113{
114 cpu->cpu_regs.sp = val;
e0709f50
AC
115}
116
81e09ed8
SC
117uint16
118cpu_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
139uint16
140cpu_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
173void
174cpu_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
215void
216cpu_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. */
243uint16
244cpu_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
348uint8
349cpu_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
357uint16
358cpu_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
366void
367cpu_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;
86596dc8
SC
404
405 default:
406 sim_engine_abort (CPU_STATE (cpu), cpu, 0,
407 "Invalid code 0x%0x -- internal error?", code);
408 return;
81e09ed8
SC
409 }
410 memory_write8 (cpu, addr, src);
411}
412
413void
414cpu_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;
86596dc8
SC
451
452 default:
453 sim_engine_abort (CPU_STATE (cpu), cpu, 0,
454 "Invalid code 0x%0x -- internal error?", code);
455 return;
81e09ed8
SC
456 }
457 memory_write16 (cpu, addr, src);
458}
459
e0709f50
AC
460int
461cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
462{
e0709f50
AC
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;
e0709f50
AC
473 cpu->cpu_use_elf_start = 0;
474 cpu->cpu_elf_start = 0;
475 cpu->cpu_use_local_config = 0;
77342e5e
SC
476 cpu->bank_start = 0;
477 cpu->bank_end = 0;
478 cpu->bank_shift = 0;
e0709f50
AC
479 cpu->cpu_config = M6811_NOSEC | M6811_NOCOP | M6811_ROMON |
480 M6811_EEON;
26128965 481 interrupts_initialize (sd, cpu);
e0709f50
AC
482
483 cpu->cpu_is_initialized = 1;
26128965 484 return 0;
e0709f50
AC
485}
486
487
488/* Reinitialize the processor after a reset. */
489int
490cpu_reset (sim_cpu *cpu)
491{
e0709f50
AC
492 /* Initialize the config register.
493 It is only initialized at reset time. */
494 memset (cpu->ios, 0, sizeof (cpu->ios));
81e09ed8
SC
495 if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
496 cpu->ios[M6811_INIT] = 0x1;
497 else
498 cpu->ios[M6811_INIT] = 0;
e0709f50
AC
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
26128965
SC
516 /* Reset interrupts. */
517 interrupts_reset (&cpu->cpu_interrupts);
518
e0709f50
AC
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. */
525int
526cpu_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
575void
576print_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
587void
588print_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
962e9d85
SC
596void
597print_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
e0709f50
AC
605void
606cpu_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
614uint16
615cpu_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
81e09ed8
SC
627uint16
628cpu_fetch_relbranch16 (sim_cpu *cpu)
629{
630 uint16 addr = cpu_fetch16 (cpu);
631
632 addr += cpu->cpu_regs.pc;
633 return addr;
634}
e0709f50
AC
635
636/* Push all the CPU registers (when an interruption occurs). */
637void
638cpu_push_all (sim_cpu *cpu)
639{
81e09ed8
SC
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 }
e0709f50
AC
656}
657
81e09ed8
SC
658/* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations. */
659void
660cpu_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
700void
701cpu_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}
e0709f50
AC
730
731/* Handle special instructions. */
732void
733cpu_special (sim_cpu *cpu, enum M6811_Special special)
734{
735 switch (special)
736 {
737 case M6811_RTI:
738 {
739 uint8 ccr;
740
81e09ed8 741 ccr = cpu_m68hc11_pop_uint8 (cpu);
e0709f50 742 cpu_set_ccr (cpu, ccr);
81e09ed8
SC
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));
e0709f50
AC
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:
81e09ed8 811 case M6812_BGND:
e0709f50
AC
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 }
81e09ed8
SC
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
63f36def
SC
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
81e09ed8
SC
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;
e0709f50
AC
991 }
992}
993
994
995void
996cpu_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));*/
81e09ed8 1010 cpu->cpu_interpretor (cpu);
e0709f50
AC
1011 cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
1012}
1013
1014/* VARARGS */
1015void
1016sim_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
86596dc8 1026 sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
e0709f50
AC
1027 cpu_memory_exception (cpu, excep, addr, buf);
1028}
1029
1030
1031void
1032cpu_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
1056void
1057cpu_info (SIM_DESC sd, sim_cpu *cpu)
1058{
1059 sim_io_printf (sd, "CPU info:\n");
2990a9f4 1060 sim_io_printf (sd, " Absolute cycle: %s\n",
a685700c
SC
1061 cycle_to_string (cpu, cpu->cpu_absolute_cycle,
1062 PRINT_TIME | PRINT_CYCLE));
2990a9f4 1063
e0709f50
AC
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