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