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