1 /* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation 2 Copyright 1999-2014 Free Software Foundation, Inc. 3 Written by Stephane Carrez (stcarrez@nerim.fr) 4 5 This file is part of GDB, GAS, and the GNU binutils. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "sim-main.h" 21 #include "sim-assert.h" 22 #include "sim-module.h" 23 #include "sim-options.h" 24 25 enum { 26 OPTION_CPU_RESET = OPTION_START, 27 OPTION_EMUL_OS, 28 OPTION_CPU_CONFIG, 29 OPTION_CPU_BOOTSTRAP, 30 OPTION_CPU_MODE 31 }; 32 33 static DECLARE_OPTION_HANDLER (cpu_option_handler); 34 35 static 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 49 { {"bootstrap", no_argument, NULL, OPTION_CPU_BOOTSTRAP }, 50 '\0', NULL, "Start the processing in bootstrap mode", 51 cpu_option_handler }, 52 53 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } 54 }; 55 56 57 static SIM_RC 58 cpu_option_handler (SIM_DESC sd, sim_cpu *cpu, 59 int opt, char *arg, int is_command) 60 { 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; 84 85 case OPTION_CPU_BOOTSTRAP: 86 cpu->cpu_start_mode = "bootstrap"; 87 break; 88 89 case OPTION_CPU_MODE: 90 break; 91 } 92 93 return SIM_RC_OK; 94 } 95 96 97 void 98 cpu_call (sim_cpu *cpu, uint16 addr) 99 { 100 101 cpu_set_pc (cpu, addr); 102 } 103 104 void 105 cpu_return (sim_cpu *cpu) 106 { 107 } 108 109 /* Set the stack pointer and re-compute the current frame. */ 110 void 111 cpu_set_sp (sim_cpu *cpu, uint16 val) 112 { 113 cpu->cpu_regs.sp = val; 114 } 115 116 uint16 117 cpu_get_reg (sim_cpu* cpu, uint8 reg) 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 138 uint16 139 cpu_get_src_reg (sim_cpu* cpu, uint8 reg) 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 172 void 173 cpu_set_dst_reg (sim_cpu* cpu, uint8 reg, uint16 val) 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 214 void 215 cpu_set_reg (sim_cpu* cpu, uint8 reg, uint16 val) 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. */ 242 uint16 243 cpu_get_indexed_operand_addr (sim_cpu* cpu, int restrict) 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 { 288 if (restrict) 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 { 300 if (restrict) 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 347 uint8 348 cpu_get_indexed_operand8 (sim_cpu* cpu, int restrict) 349 { 350 uint16 addr; 351 352 addr = cpu_get_indexed_operand_addr (cpu, restrict); 353 return memory_read8 (cpu, addr); 354 } 355 356 uint16 357 cpu_get_indexed_operand16 (sim_cpu* cpu, int restrict) 358 { 359 uint16 addr; 360 361 addr = cpu_get_indexed_operand_addr (cpu, restrict); 362 return memory_read16 (cpu, addr); 363 } 364 365 void 366 cpu_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; 403 404 default: 405 sim_engine_abort (CPU_STATE (cpu), cpu, 0, 406 "Invalid code 0x%0x -- internal error?", code); 407 return; 408 } 409 memory_write8 (cpu, addr, src); 410 } 411 412 void 413 cpu_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; 450 451 default: 452 sim_engine_abort (CPU_STATE (cpu), cpu, 0, 453 "Invalid code 0x%0x -- internal error?", code); 454 return; 455 } 456 memory_write16 (cpu, addr, src); 457 } 458 459 int 460 cpu_initialize (SIM_DESC sd, sim_cpu *cpu) 461 { 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; 472 cpu->cpu_use_elf_start = 0; 473 cpu->cpu_elf_start = 0; 474 cpu->cpu_use_local_config = 0; 475 cpu->bank_start = 0; 476 cpu->bank_end = 0; 477 cpu->bank_shift = 0; 478 cpu->cpu_config = M6811_NOSEC | M6811_NOCOP | M6811_ROMON | 479 M6811_EEON; 480 interrupts_initialize (sd, cpu); 481 482 cpu->cpu_is_initialized = 1; 483 return 0; 484 } 485 486 487 /* Reinitialize the processor after a reset. */ 488 int 489 cpu_reset (sim_cpu *cpu) 490 { 491 /* Initialize the config register. 492 It is only initialized at reset time. */ 493 memset (cpu->ios, 0, sizeof (cpu->ios)); 494 if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11) 495 cpu->ios[M6811_INIT] = 0x1; 496 else 497 cpu->ios[M6811_INIT] = 0; 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 515 /* Reset interrupts. */ 516 interrupts_reset (&cpu->cpu_interrupts); 517 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. */ 524 int 525 cpu_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 574 void 575 print_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 586 void 587 print_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 595 void 596 print_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 604 void 605 cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val) 606 { 607 cpu_set_ccr_V (proc, 0); 608 cpu_set_ccr_N (proc, val & 0x80 ? 1 : 0); 609 cpu_set_ccr_Z (proc, val == 0 ? 1 : 0); 610 } 611 612 613 uint16 614 cpu_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 626 uint16 627 cpu_fetch_relbranch16 (sim_cpu *cpu) 628 { 629 uint16 addr = cpu_fetch16 (cpu); 630 631 addr += cpu->cpu_regs.pc; 632 return addr; 633 } 634 635 /* Push all the CPU registers (when an interruption occurs). */ 636 void 637 cpu_push_all (sim_cpu *cpu) 638 { 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 } 655 } 656 657 /* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations. */ 658 void 659 cpu_dbcc (sim_cpu* cpu) 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 699 void 700 cpu_exg (sim_cpu* cpu, uint8 code) 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 } 729 730 /* Handle special instructions. */ 731 void 732 cpu_special (sim_cpu *cpu, enum M6811_Special special) 733 { 734 switch (special) 735 { 736 case M6811_RTI: 737 { 738 uint8 ccr; 739 740 ccr = cpu_m68hc11_pop_uint8 (cpu); 741 cpu_set_ccr (cpu, ccr); 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)); 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: 810 case M6812_BGND: 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 } 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 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 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; 990 } 991 } 992 993 994 void 995 cpu_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));*/ 1009 cpu->cpu_interpretor (cpu); 1010 cpu->cpu_absolute_cycle += cpu->cpu_current_cycle; 1011 } 1012 1013 /* VARARGS */ 1014 void 1015 sim_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 1025 sim_io_printf (CPU_STATE (cpu), "%s\n", buf); 1026 cpu_memory_exception (cpu, excep, addr, buf); 1027 } 1028 1029 1030 void 1031 cpu_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 1055 void 1056 cpu_info (SIM_DESC sd, sim_cpu *cpu) 1057 { 1058 sim_io_printf (sd, "CPU info:\n"); 1059 sim_io_printf (sd, " Absolute cycle: %s\n", 1060 cycle_to_string (cpu, cpu->cpu_absolute_cycle, 1061 PRINT_TIME | PRINT_CYCLE)); 1062 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 1071