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