1/* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation 2 Copyright 1999-2023 Free Software Foundation, Inc. 3 Written by Stephane Carrez (stcarrez@nerim.fr) 4 5This file is part of GDB, GAS, and the GNU binutils. 6 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. 11 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. 16 17You should have received a copy of the GNU General Public License 18along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20/* This must come before any other includes. */ 21#include "defs.h" 22 23#include "sim-main.h" 24#include "sim-assert.h" 25#include "sim-module.h" 26#include "sim-options.h" 27#include "sim-signal.h" 28 29#include <stdlib.h> 30 31enum { 32 OPTION_CPU_RESET = OPTION_START, 33 OPTION_EMUL_OS, 34 OPTION_CPU_CONFIG, 35 OPTION_CPU_BOOTSTRAP, 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 55 { {"bootstrap", no_argument, NULL, OPTION_CPU_BOOTSTRAP }, 56 '\0', NULL, "Start the processing in bootstrap mode", 57 cpu_option_handler }, 58 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{ 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; 90 91 case OPTION_CPU_BOOTSTRAP: 92 cpu->cpu_start_mode = "bootstrap"; 93 break; 94 95 case OPTION_CPU_MODE: 96 break; 97 } 98 99 return SIM_RC_OK; 100} 101 102 103void 104cpu_call (sim_cpu *cpu, uint16_t addr) 105{ 106 107 cpu_set_pc (cpu, addr); 108} 109 110void 111cpu_return (sim_cpu *cpu) 112{ 113} 114 115/* Set the stack pointer and re-compute the current frame. */ 116void 117cpu_set_sp (sim_cpu *cpu, uint16_t val) 118{ 119 cpu->cpu_regs.sp = val; 120} 121 122static uint16_t 123cpu_get_reg (sim_cpu *cpu, uint8_t reg) 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 144static uint16_t 145cpu_get_src_reg (sim_cpu *cpu, uint8_t reg) 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 178static void 179cpu_set_dst_reg (sim_cpu *cpu, uint8_t reg, uint16_t val) 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 220static void 221cpu_set_reg (sim_cpu *cpu, uint8_t reg, uint16_t val) 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_t 249cpu_get_indexed_operand_addr (sim_cpu *cpu, int restricted) 250{ 251 uint8_t reg; 252 uint16_t sval; 253 uint16_t addr; 254 uint8_t 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 { 294 if (restricted) 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 { 306 if (restricted) 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 353static uint8_t 354cpu_get_indexed_operand8 (sim_cpu *cpu, int restricted) 355{ 356 uint16_t addr; 357 358 addr = cpu_get_indexed_operand_addr (cpu, restricted); 359 return memory_read8 (cpu, addr); 360} 361 362static uint16_t 363cpu_get_indexed_operand16 (sim_cpu *cpu, int restricted) 364{ 365 uint16_t addr; 366 367 addr = cpu_get_indexed_operand_addr (cpu, restricted); 368 return memory_read16 (cpu, addr); 369} 370 371void 372cpu_move8 (sim_cpu *cpu, uint8_t code) 373{ 374 uint8_t src; 375 uint16_t 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; 409 410 default: 411 sim_engine_abort (CPU_STATE (cpu), cpu, 0, 412 "Invalid code 0x%0x -- internal error?", code); 413 return; 414 } 415 memory_write8 (cpu, addr, src); 416} 417 418void 419cpu_move16 (sim_cpu *cpu, uint8_t code) 420{ 421 uint16_t src; 422 uint16_t 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; 456 457 default: 458 sim_engine_abort (CPU_STATE (cpu), cpu, 0, 459 "Invalid code 0x%0x -- internal error?", code); 460 return; 461 } 462 memory_write16 (cpu, addr, src); 463} 464 465int 466cpu_initialize (SIM_DESC sd, sim_cpu *cpu) 467{ 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; 478 cpu->cpu_use_elf_start = 0; 479 cpu->cpu_elf_start = 0; 480 cpu->cpu_use_local_config = 0; 481 cpu->bank_start = 0; 482 cpu->bank_end = 0; 483 cpu->bank_shift = 0; 484 cpu->cpu_config = M6811_NOSEC | M6811_NOCOP | M6811_ROMON | 485 M6811_EEON; 486 interrupts_initialize (sd, cpu); 487 488 cpu->cpu_is_initialized = 1; 489 return 0; 490} 491 492 493/* Reinitialize the processor after a reset. */ 494int 495cpu_reset (sim_cpu *cpu) 496{ 497 /* Initialize the config register. 498 It is only initialized at reset time. */ 499 memset (cpu->ios, 0, sizeof (cpu->ios)); 500 if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11) 501 cpu->ios[M6811_INIT] = 0x1; 502 else 503 cpu->ios[M6811_INIT] = 0; 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 521 /* Reset interrupts. */ 522 interrupts_reset (&cpu->cpu_interrupts); 523 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_t 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_t val, uint16_t 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 601void 602print_io_word (SIM_DESC sd, const char *name, io_reg_desc *desc, 603 uint16_t val, uint16_t 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 610void 611cpu_ccr_update_tst8 (sim_cpu *cpu, uint8_t val) 612{ 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); 616} 617 618 619uint16_t 620cpu_fetch_relbranch (sim_cpu *cpu) 621{ 622 uint16_t addr = (uint16_t) cpu_fetch8 (cpu); 623 624 if (addr & 0x0080) 625 { 626 addr |= 0xFF00; 627 } 628 addr += cpu->cpu_regs.pc; 629 return addr; 630} 631 632uint16_t 633cpu_fetch_relbranch16 (sim_cpu *cpu) 634{ 635 uint16_t addr = cpu_fetch16 (cpu); 636 637 addr += cpu->cpu_regs.pc; 638 return addr; 639} 640 641/* Push all the CPU registers (when an interruption occurs). */ 642void 643cpu_push_all (sim_cpu *cpu) 644{ 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 } 661} 662 663/* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations. */ 664void 665cpu_dbcc (sim_cpu *cpu) 666{ 667 uint8_t code; 668 uint16_t addr; 669 uint16_t inc; 670 uint16_t 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 706cpu_exg (sim_cpu *cpu, uint8_t code) 707{ 708 uint8_t r1, r2; 709 uint16_t src1; 710 uint16_t 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} 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_t ccr; 745 746 ccr = cpu_m68hc11_pop_uint8 (cpu); 747 cpu_set_ccr (cpu, ccr); 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_t 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)); 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_t 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: 816 case M6812_BGND: 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 } 833 834 case M6812_IDIVS: 835 { 836 int32_t src1 = (int16_t) cpu_get_d (cpu); 837 int32_t src2 = (int16_t) 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_t src1 = (uint32_t) cpu_get_x (cpu); 859 uint32_t src2 = (uint32_t) (cpu_get_y (cpu) << 16) 860 | (uint32_t) (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_t src1 = (int16_t) cpu_get_x (cpu); 882 int32_t src2 = (uint32_t) (cpu_get_y (cpu) << 16) 883 | (uint32_t) (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_t src1, src2; 905 906 src1 = (int16_t) cpu_get_d (cpu); 907 src2 = (int16_t) 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_t src1, src2; 920 uint16_t addr; 921 922 addr = cpu_fetch16 (cpu); 923 src1 = (int16_t) memory_read16 (cpu, cpu_get_x (cpu)); 924 src2 = (int16_t) memory_read16 (cpu, cpu_get_y (cpu)); 925 src1 = src1 * src2; 926 src2 = (((uint32_t) memory_read16 (cpu, addr)) << 16) 927 | (uint32_t) 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 936 case M6812_CALL: 937 { 938 uint8_t page; 939 uint16_t 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_t code; 955 uint16_t addr; 956 uint8_t 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_t page = cpu_m68hc12_pop_uint8 (cpu); 983 uint16_t addr = cpu_m68hc12_pop_uint16 (cpu); 984 985 cpu_set_page (cpu, page); 986 cpu_set_pc (cpu, addr); 987 } 988 break; 989 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; 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));*/ 1015 cpu->cpu_interpretor (cpu); 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_t 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 1031 sim_io_printf (CPU_STATE (cpu), "%s\n", buf); 1032 cpu_memory_exception (cpu, excep, addr, buf); 1033} 1034 1035 1036void 1037cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep, 1038 uint16_t 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"); 1065 sim_io_printf (sd, " Absolute cycle: %s\n", 1066 cycle_to_string (cpu, cpu->cpu_absolute_cycle, 1067 PRINT_TIME | PRINT_CYCLE)); 1068 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 1077