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