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