1 /* interp.c -- Simulator for Motorola 68HC11/68HC12 2 Copyright (C) 1999-2024 Free Software Foundation, Inc. 3 Written by Stephane Carrez (stcarrez@nerim.fr) 4 5 This file is part of GDB, the GNU debugger. 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 "bfd.h" 24 25 #include "sim-main.h" 26 #include "sim-assert.h" 27 #include "sim-hw.h" 28 #include "sim-options.h" 29 #include "hw-tree.h" 30 #include "hw-device.h" 31 #include "hw-ports.h" 32 #include "bfd/elf32-m68hc1x.h" 33 34 #include "m68hc11-sim.h" 35 36 #ifndef MONITOR_BASE 37 # define MONITOR_BASE (0x0C000) 38 # define MONITOR_SIZE (0x04000) 39 #endif 40 41 static void sim_get_info (SIM_DESC sd, char *cmd); 42 43 struct sim_info_list 44 { 45 const char *name; 46 const char *device; 47 }; 48 49 struct sim_info_list dev_list_68hc11[] = { 50 {"cpu", "/m68hc11"}, 51 {"timer", "/m68hc11/m68hc11tim"}, 52 {"sio", "/m68hc11/m68hc11sio"}, 53 {"spi", "/m68hc11/m68hc11spi"}, 54 {"eeprom", "/m68hc11/m68hc11eepr"}, 55 {0, 0} 56 }; 57 58 struct sim_info_list dev_list_68hc12[] = { 59 {"cpu", "/m68hc12"}, 60 {"timer", "/m68hc12/m68hc12tim"}, 61 {"sio", "/m68hc12/m68hc12sio"}, 62 {"spi", "/m68hc12/m68hc12spi"}, 63 {"eeprom", "/m68hc12/m68hc12eepr"}, 64 {0, 0} 65 }; 66 67 /* Cover function of sim_state_free to free the cpu buffers as well. */ 68 69 static void 70 free_state (SIM_DESC sd) 71 { 72 if (STATE_MODULES (sd) != NULL) 73 sim_module_uninstall (sd); 74 75 sim_state_free (sd); 76 } 77 78 /* Give some information about the simulator. */ 79 static void 80 sim_get_info (SIM_DESC sd, char *cmd) 81 { 82 sim_cpu *cpu; 83 84 cpu = STATE_CPU (sd, 0); 85 if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-')) 86 { 87 int i; 88 struct hw *hw_dev; 89 struct sim_info_list *dev_list; 90 const struct bfd_arch_info *arch; 91 92 arch = STATE_ARCHITECTURE (sd); 93 cmd++; 94 95 if (arch->arch == bfd_arch_m68hc11) 96 dev_list = dev_list_68hc11; 97 else 98 dev_list = dev_list_68hc12; 99 100 for (i = 0; dev_list[i].name; i++) 101 if (strcmp (cmd, dev_list[i].name) == 0) 102 break; 103 104 if (dev_list[i].name == 0) 105 { 106 sim_io_eprintf (sd, "Device '%s' not found.\n", cmd); 107 sim_io_eprintf (sd, "Valid devices: cpu timer sio eeprom\n"); 108 return; 109 } 110 hw_dev = sim_hw_parse (sd, "%s", dev_list[i].device); 111 if (hw_dev == 0) 112 { 113 sim_io_eprintf (sd, "Device '%s' not found\n", dev_list[i].device); 114 return; 115 } 116 hw_ioctl (hw_dev, 23, 0); 117 return; 118 } 119 120 cpu_info (sd, cpu); 121 interrupts_info (sd, &M68HC11_SIM_CPU (cpu)->cpu_interrupts); 122 } 123 124 125 void 126 sim_board_reset (SIM_DESC sd) 127 { 128 struct hw *hw_cpu; 129 sim_cpu *cpu; 130 struct m68hc11_sim_cpu *m68hc11_cpu; 131 const struct bfd_arch_info *arch; 132 const char *cpu_type; 133 134 cpu = STATE_CPU (sd, 0); 135 m68hc11_cpu = M68HC11_SIM_CPU (cpu); 136 arch = STATE_ARCHITECTURE (sd); 137 138 /* hw_cpu = sim_hw_parse (sd, "/"); */ 139 if (arch->arch == bfd_arch_m68hc11) 140 { 141 m68hc11_cpu->cpu_type = CPU_M6811; 142 cpu_type = "/m68hc11"; 143 } 144 else 145 { 146 m68hc11_cpu->cpu_type = CPU_M6812; 147 cpu_type = "/m68hc12"; 148 } 149 150 hw_cpu = sim_hw_parse (sd, "%s", cpu_type); 151 if (hw_cpu == 0) 152 { 153 sim_io_eprintf (sd, "%s cpu not found in device tree.", cpu_type); 154 return; 155 } 156 157 cpu_reset (cpu); 158 hw_port_event (hw_cpu, 3, 0); 159 cpu_restart (cpu); 160 } 161 162 static int 163 sim_hw_configure (SIM_DESC sd) 164 { 165 const struct bfd_arch_info *arch; 166 struct hw *device_tree; 167 sim_cpu *cpu; 168 struct m68hc11_sim_cpu *m68hc11_cpu; 169 170 arch = STATE_ARCHITECTURE (sd); 171 if (arch == 0) 172 return 0; 173 174 cpu = STATE_CPU (sd, 0); 175 m68hc11_cpu = M68HC11_SIM_CPU (cpu); 176 m68hc11_cpu->cpu_configured_arch = arch; 177 device_tree = sim_hw_parse (sd, "/"); 178 if (arch->arch == bfd_arch_m68hc11) 179 { 180 m68hc11_cpu->cpu_interpretor = cpu_interp_m6811; 181 if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0) 182 { 183 /* Allocate core managed memory */ 184 185 /* the monitor */ 186 sim_do_commandf (sd, "memory region 0x%x@%d,0x%x", 187 /* MONITOR_BASE, MONITOR_SIZE */ 188 0x8000, M6811_RAM_LEVEL, 0x8000); 189 sim_do_commandf (sd, "memory region 0x000@%d,0x8000", 190 M6811_RAM_LEVEL); 191 sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F"); 192 if (m68hc11_cpu->bank_start < m68hc11_cpu->bank_end) 193 { 194 sim_do_commandf (sd, "memory region 0x%x@%d,0x100000", 195 m68hc11_cpu->bank_virtual, M6811_RAM_LEVEL); 196 sim_hw_parse (sd, "/m68hc11/use_bank 1"); 197 } 198 } 199 if (m68hc11_cpu->cpu_start_mode) 200 { 201 sim_hw_parse (sd, "/m68hc11/mode %s", m68hc11_cpu->cpu_start_mode); 202 } 203 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0) 204 { 205 sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5"); 206 sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio"); 207 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio"); 208 } 209 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0) 210 { 211 /* M68hc11 Timer configuration. */ 212 sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5"); 213 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim"); 214 sim_hw_parse (sd, "/m68hc11 > capture capture /m68hc11/m68hc11tim"); 215 } 216 217 /* Create the SPI device. */ 218 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0) 219 { 220 sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3"); 221 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi"); 222 } 223 if (hw_tree_find_property (device_tree, "/m68hc11/nvram/reg") == 0) 224 { 225 /* M68hc11 persistent ram configuration. */ 226 sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256"); 227 sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram"); 228 sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified"); 229 /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */ 230 } 231 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0) 232 { 233 sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512"); 234 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr"); 235 } 236 sim_hw_parse (sd, "/m68hc11 > port-a cpu-write-port /m68hc11"); 237 sim_hw_parse (sd, "/m68hc11 > port-b cpu-write-port /m68hc11"); 238 sim_hw_parse (sd, "/m68hc11 > port-c cpu-write-port /m68hc11"); 239 sim_hw_parse (sd, "/m68hc11 > port-d cpu-write-port /m68hc11"); 240 m68hc11_cpu->hw_cpu = sim_hw_parse (sd, "/m68hc11"); 241 } 242 else 243 { 244 m68hc11_cpu->cpu_interpretor = cpu_interp_m6812; 245 if (hw_tree_find_property (device_tree, "/m68hc12/reg") == 0) 246 { 247 /* Allocate core external memory. */ 248 sim_do_commandf (sd, "memory region 0x%x@%d,0x%x", 249 0x8000, M6811_RAM_LEVEL, 0x8000); 250 sim_do_commandf (sd, "memory region 0x000@%d,0x8000", 251 M6811_RAM_LEVEL); 252 if (m68hc11_cpu->bank_start < m68hc11_cpu->bank_end) 253 { 254 sim_do_commandf (sd, "memory region 0x%x@%d,0x100000", 255 m68hc11_cpu->bank_virtual, M6811_RAM_LEVEL); 256 sim_hw_parse (sd, "/m68hc12/use_bank 1"); 257 } 258 sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF"); 259 } 260 261 if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg")) 262 { 263 sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8"); 264 sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/backend stdio"); 265 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1"); 266 } 267 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12tim/reg") == 0) 268 { 269 /* M68hc11 Timer configuration. */ 270 sim_hw_parse (sd, "/m68hc12/m68hc12tim/reg 0x1b 0x5"); 271 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim"); 272 sim_hw_parse (sd, "/m68hc12 > capture capture /m68hc12/m68hc12tim"); 273 } 274 275 /* Create the SPI device. */ 276 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12spi/reg") == 0) 277 { 278 sim_hw_parse (sd, "/m68hc12/m68hc12spi/reg 0x28 0x3"); 279 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi"); 280 } 281 if (hw_tree_find_property (device_tree, "/m68hc12/nvram/reg") == 0) 282 { 283 /* M68hc11 persistent ram configuration. */ 284 sim_hw_parse (sd, "/m68hc12/nvram/reg 0x2000 8192"); 285 sim_hw_parse (sd, "/m68hc12/nvram/file m68hc12.ram"); 286 sim_hw_parse (sd, "/m68hc12/nvram/mode save-modified"); 287 } 288 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12eepr/reg") == 0) 289 { 290 sim_hw_parse (sd, "/m68hc12/m68hc12eepr/reg 0x0800 2048"); 291 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr"); 292 } 293 294 sim_hw_parse (sd, "/m68hc12 > port-a cpu-write-port /m68hc12"); 295 sim_hw_parse (sd, "/m68hc12 > port-b cpu-write-port /m68hc12"); 296 sim_hw_parse (sd, "/m68hc12 > port-c cpu-write-port /m68hc12"); 297 sim_hw_parse (sd, "/m68hc12 > port-d cpu-write-port /m68hc12"); 298 m68hc11_cpu->hw_cpu = sim_hw_parse (sd, "/m68hc12"); 299 } 300 return 1; 301 } 302 303 /* Get the memory bank parameters by looking at the global symbols 304 defined by the linker. */ 305 static int 306 sim_get_bank_parameters (SIM_DESC sd) 307 { 308 sim_cpu *cpu; 309 struct m68hc11_sim_cpu *m68hc11_cpu; 310 unsigned size; 311 bfd_vma addr; 312 313 cpu = STATE_CPU (sd, 0); 314 m68hc11_cpu = M68HC11_SIM_CPU (cpu); 315 316 addr = trace_sym_value (sd, BFD_M68HC11_BANK_START_NAME); 317 if (addr != -1) 318 m68hc11_cpu->bank_start = addr; 319 320 size = trace_sym_value (sd, BFD_M68HC11_BANK_SIZE_NAME); 321 if (size == -1) 322 size = 0; 323 324 addr = trace_sym_value (sd, BFD_M68HC11_BANK_VIRTUAL_NAME); 325 if (addr != -1) 326 m68hc11_cpu->bank_virtual = addr; 327 328 m68hc11_cpu->bank_end = m68hc11_cpu->bank_start + size; 329 m68hc11_cpu->bank_shift = 0; 330 for (; size > 1; size >>= 1) 331 m68hc11_cpu->bank_shift++; 332 333 return 0; 334 } 335 336 static int 337 sim_prepare_for_program (SIM_DESC sd, bfd* abfd) 338 { 339 sim_cpu *cpu; 340 struct m68hc11_sim_cpu *m68hc11_cpu; 341 int elf_flags = 0; 342 343 cpu = STATE_CPU (sd, 0); 344 m68hc11_cpu = M68HC11_SIM_CPU (cpu); 345 346 if (abfd != NULL) 347 { 348 asection *s; 349 350 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) 351 elf_flags = elf_elfheader (abfd)->e_flags; 352 353 m68hc11_cpu->cpu_elf_start = bfd_get_start_address (abfd); 354 /* See if any section sets the reset address */ 355 m68hc11_cpu->cpu_use_elf_start = 1; 356 for (s = abfd->sections; s && m68hc11_cpu->cpu_use_elf_start; s = s->next) 357 { 358 if (s->flags & SEC_LOAD) 359 { 360 bfd_size_type size; 361 362 size = bfd_section_size (s); 363 if (size > 0) 364 { 365 bfd_vma lma; 366 367 if (STATE_LOAD_AT_LMA_P (sd)) 368 lma = bfd_section_lma (s); 369 else 370 lma = bfd_section_vma (s); 371 372 if (lma <= 0xFFFE && lma+size >= 0x10000) 373 m68hc11_cpu->cpu_use_elf_start = 0; 374 } 375 } 376 } 377 378 if (elf_flags & E_M68HC12_BANKS) 379 { 380 if (sim_get_bank_parameters (sd) != 0) 381 sim_io_eprintf (sd, "Memory bank parameters are not initialized\n"); 382 } 383 } 384 385 if (!sim_hw_configure (sd)) 386 return SIM_RC_FAIL; 387 388 /* reset all state information */ 389 sim_board_reset (sd); 390 391 return SIM_RC_OK; 392 } 393 394 static sim_cia 395 m68hc11_pc_get (sim_cpu *cpu) 396 { 397 return cpu_get_pc (cpu); 398 } 399 400 static void 401 m68hc11_pc_set (sim_cpu *cpu, sim_cia pc) 402 { 403 cpu_set_pc (cpu, pc); 404 } 405 406 static int m68hc11_reg_fetch (SIM_CPU *, int, void *, int); 407 static int m68hc11_reg_store (SIM_CPU *, int, const void *, int); 408 409 SIM_DESC 410 sim_open (SIM_OPEN_KIND kind, host_callback *callback, 411 bfd *abfd, char * const *argv) 412 { 413 int i; 414 SIM_DESC sd; 415 sim_cpu *cpu; 416 417 sd = sim_state_alloc (kind, callback); 418 419 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 420 421 /* Set default options before parsing user options. */ 422 current_target_byte_order = BFD_ENDIAN_BIG; 423 424 /* The cpu data is kept in a separately allocated chunk of memory. */ 425 if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct m68hc11_sim_cpu)) 426 != SIM_RC_OK) 427 { 428 free_state (sd); 429 return 0; 430 } 431 432 cpu = STATE_CPU (sd, 0); 433 434 cpu_initialize (sd, cpu); 435 436 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) 437 { 438 free_state (sd); 439 return 0; 440 } 441 442 /* The parser will print an error message for us, so we silently return. */ 443 if (sim_parse_args (sd, argv) != SIM_RC_OK) 444 { 445 /* Uninstall the modules to avoid memory leaks, 446 file descriptor leaks, etc. */ 447 free_state (sd); 448 return 0; 449 } 450 451 /* Check for/establish the a reference program image. */ 452 if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK) 453 { 454 free_state (sd); 455 return 0; 456 } 457 458 /* Establish any remaining configuration options. */ 459 if (sim_config (sd) != SIM_RC_OK) 460 { 461 free_state (sd); 462 return 0; 463 } 464 465 if (sim_post_argv_init (sd) != SIM_RC_OK) 466 { 467 /* Uninstall the modules to avoid memory leaks, 468 file descriptor leaks, etc. */ 469 free_state (sd); 470 return 0; 471 } 472 if (sim_prepare_for_program (sd, abfd) != SIM_RC_OK) 473 { 474 free_state (sd); 475 return 0; 476 } 477 478 /* CPU specific initialization. */ 479 for (i = 0; i < MAX_NR_PROCESSORS; ++i) 480 { 481 cpu = STATE_CPU (sd, i); 482 483 CPU_REG_FETCH (cpu) = m68hc11_reg_fetch; 484 CPU_REG_STORE (cpu) = m68hc11_reg_store; 485 CPU_PC_FETCH (cpu) = m68hc11_pc_get; 486 CPU_PC_STORE (cpu) = m68hc11_pc_set; 487 } 488 489 return sd; 490 } 491 492 /* Generic implementation of sim_engine_run that works within the 493 sim_engine setjmp/longjmp framework. */ 494 495 void 496 sim_engine_run (SIM_DESC sd, 497 int next_cpu_nr, /* ignore */ 498 int nr_cpus, /* ignore */ 499 int siggnal) /* ignore */ 500 { 501 sim_cpu *cpu; 502 503 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 504 cpu = STATE_CPU (sd, 0); 505 while (1) 506 { 507 cpu_single_step (cpu); 508 509 /* process any events */ 510 if (sim_events_tickn (sd, M68HC11_SIM_CPU (cpu)->cpu_current_cycle)) 511 { 512 sim_events_process (sd); 513 } 514 } 515 } 516 517 void 518 sim_info (SIM_DESC sd, bool verbose) 519 { 520 const char *cpu_type; 521 const struct bfd_arch_info *arch; 522 523 /* Nothing to do if there is no verbose flag set. */ 524 if (verbose == 0 && STATE_VERBOSE_P (sd) == 0) 525 return; 526 527 arch = STATE_ARCHITECTURE (sd); 528 if (arch->arch == bfd_arch_m68hc11) 529 cpu_type = "68HC11"; 530 else 531 cpu_type = "68HC12"; 532 533 sim_io_eprintf (sd, "Simulator info:\n"); 534 sim_io_eprintf (sd, " CPU Motorola %s\n", cpu_type); 535 sim_get_info (sd, 0); 536 sim_module_info (sd, verbose || STATE_VERBOSE_P (sd)); 537 } 538 539 SIM_RC 540 sim_create_inferior (SIM_DESC sd, struct bfd *abfd, 541 char * const *argv, char * const *env) 542 { 543 return sim_prepare_for_program (sd, abfd); 544 } 545 546 static int 547 m68hc11_reg_fetch (SIM_CPU *cpu, int rn, void *buf, int length) 548 { 549 unsigned char *memory = buf; 550 uint16_t val; 551 int size = 2; 552 553 switch (rn) 554 { 555 case A_REGNUM: 556 val = cpu_get_a (cpu); 557 size = 1; 558 break; 559 560 case B_REGNUM: 561 val = cpu_get_b (cpu); 562 size = 1; 563 break; 564 565 case D_REGNUM: 566 val = cpu_get_d (cpu); 567 break; 568 569 case X_REGNUM: 570 val = cpu_get_x (cpu); 571 break; 572 573 case Y_REGNUM: 574 val = cpu_get_y (cpu); 575 break; 576 577 case SP_REGNUM: 578 val = cpu_get_sp (cpu); 579 break; 580 581 case PC_REGNUM: 582 val = cpu_get_pc (cpu); 583 break; 584 585 case PSW_REGNUM: 586 val = cpu_get_ccr (cpu); 587 size = 1; 588 break; 589 590 case PAGE_REGNUM: 591 val = cpu_get_page (cpu); 592 size = 1; 593 break; 594 595 default: 596 val = 0; 597 break; 598 } 599 if (size == 1) 600 { 601 memory[0] = val; 602 } 603 else 604 { 605 memory[0] = val >> 8; 606 memory[1] = val & 0x0FF; 607 } 608 return size; 609 } 610 611 static int 612 m68hc11_reg_store (SIM_CPU *cpu, int rn, const void *buf, int length) 613 { 614 const unsigned char *memory = buf; 615 uint16_t val; 616 617 val = *memory++; 618 if (length == 2) 619 val = (val << 8) | *memory; 620 621 switch (rn) 622 { 623 case D_REGNUM: 624 cpu_set_d (cpu, val); 625 break; 626 627 case A_REGNUM: 628 cpu_set_a (cpu, val); 629 return 1; 630 631 case B_REGNUM: 632 cpu_set_b (cpu, val); 633 return 1; 634 635 case X_REGNUM: 636 cpu_set_x (cpu, val); 637 break; 638 639 case Y_REGNUM: 640 cpu_set_y (cpu, val); 641 break; 642 643 case SP_REGNUM: 644 cpu_set_sp (cpu, val); 645 break; 646 647 case PC_REGNUM: 648 cpu_set_pc (cpu, val); 649 break; 650 651 case PSW_REGNUM: 652 cpu_set_ccr (cpu, val); 653 return 1; 654 655 case PAGE_REGNUM: 656 cpu_set_page (cpu, val); 657 return 1; 658 659 default: 660 break; 661 } 662 663 return 2; 664 } 665