14e98e3e1Schristos /* interp.c -- Simulator for Motorola 68HC11/68HC12 2*9b2a9e00Schristos Copyright (C) 1999-2024 Free Software Foundation, Inc. 34e98e3e1Schristos Written by Stephane Carrez (stcarrez@nerim.fr) 44e98e3e1Schristos 54e98e3e1Schristos This file is part of GDB, the GNU debugger. 64e98e3e1Schristos 74e98e3e1Schristos This program is free software; you can redistribute it and/or modify 84e98e3e1Schristos it under the terms of the GNU General Public License as published by 94e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 104e98e3e1Schristos (at your option) any later version. 114e98e3e1Schristos 124e98e3e1Schristos This program is distributed in the hope that it will be useful, 134e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 144e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 154e98e3e1Schristos GNU General Public License for more details. 164e98e3e1Schristos 174e98e3e1Schristos You should have received a copy of the GNU General Public License 184e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 194e98e3e1Schristos 204b169a6bSchristos /* This must come before any other includes. */ 214b169a6bSchristos #include "defs.h" 224b169a6bSchristos 23*9b2a9e00Schristos #include "bfd.h" 24*9b2a9e00Schristos 254e98e3e1Schristos #include "sim-main.h" 264e98e3e1Schristos #include "sim-assert.h" 274e98e3e1Schristos #include "sim-hw.h" 284e98e3e1Schristos #include "sim-options.h" 294e98e3e1Schristos #include "hw-tree.h" 304e98e3e1Schristos #include "hw-device.h" 314e98e3e1Schristos #include "hw-ports.h" 32*9b2a9e00Schristos #include "bfd/elf32-m68hc1x.h" 33*9b2a9e00Schristos 34*9b2a9e00Schristos #include "m68hc11-sim.h" 354e98e3e1Schristos 364e98e3e1Schristos #ifndef MONITOR_BASE 374e98e3e1Schristos # define MONITOR_BASE (0x0C000) 384e98e3e1Schristos # define MONITOR_SIZE (0x04000) 394e98e3e1Schristos #endif 404e98e3e1Schristos 414e98e3e1Schristos static void sim_get_info (SIM_DESC sd, char *cmd); 424e98e3e1Schristos 434e98e3e1Schristos struct sim_info_list 444e98e3e1Schristos { 454e98e3e1Schristos const char *name; 464e98e3e1Schristos const char *device; 474e98e3e1Schristos }; 484e98e3e1Schristos 494e98e3e1Schristos struct sim_info_list dev_list_68hc11[] = { 504e98e3e1Schristos {"cpu", "/m68hc11"}, 514e98e3e1Schristos {"timer", "/m68hc11/m68hc11tim"}, 524e98e3e1Schristos {"sio", "/m68hc11/m68hc11sio"}, 534e98e3e1Schristos {"spi", "/m68hc11/m68hc11spi"}, 544e98e3e1Schristos {"eeprom", "/m68hc11/m68hc11eepr"}, 554e98e3e1Schristos {0, 0} 564e98e3e1Schristos }; 574e98e3e1Schristos 584e98e3e1Schristos struct sim_info_list dev_list_68hc12[] = { 594e98e3e1Schristos {"cpu", "/m68hc12"}, 604e98e3e1Schristos {"timer", "/m68hc12/m68hc12tim"}, 614e98e3e1Schristos {"sio", "/m68hc12/m68hc12sio"}, 624e98e3e1Schristos {"spi", "/m68hc12/m68hc12spi"}, 634e98e3e1Schristos {"eeprom", "/m68hc12/m68hc12eepr"}, 644e98e3e1Schristos {0, 0} 654e98e3e1Schristos }; 664e98e3e1Schristos 674e98e3e1Schristos /* Cover function of sim_state_free to free the cpu buffers as well. */ 684e98e3e1Schristos 694e98e3e1Schristos static void 704e98e3e1Schristos free_state (SIM_DESC sd) 714e98e3e1Schristos { 724e98e3e1Schristos if (STATE_MODULES (sd) != NULL) 734e98e3e1Schristos sim_module_uninstall (sd); 744e98e3e1Schristos 754e98e3e1Schristos sim_state_free (sd); 764e98e3e1Schristos } 774e98e3e1Schristos 784e98e3e1Schristos /* Give some information about the simulator. */ 794e98e3e1Schristos static void 804e98e3e1Schristos sim_get_info (SIM_DESC sd, char *cmd) 814e98e3e1Schristos { 824e98e3e1Schristos sim_cpu *cpu; 834e98e3e1Schristos 844e98e3e1Schristos cpu = STATE_CPU (sd, 0); 854e98e3e1Schristos if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-')) 864e98e3e1Schristos { 874e98e3e1Schristos int i; 884e98e3e1Schristos struct hw *hw_dev; 894e98e3e1Schristos struct sim_info_list *dev_list; 904e98e3e1Schristos const struct bfd_arch_info *arch; 914e98e3e1Schristos 924e98e3e1Schristos arch = STATE_ARCHITECTURE (sd); 934e98e3e1Schristos cmd++; 944e98e3e1Schristos 954e98e3e1Schristos if (arch->arch == bfd_arch_m68hc11) 964e98e3e1Schristos dev_list = dev_list_68hc11; 974e98e3e1Schristos else 984e98e3e1Schristos dev_list = dev_list_68hc12; 994e98e3e1Schristos 1004e98e3e1Schristos for (i = 0; dev_list[i].name; i++) 1014e98e3e1Schristos if (strcmp (cmd, dev_list[i].name) == 0) 1024e98e3e1Schristos break; 1034e98e3e1Schristos 1044e98e3e1Schristos if (dev_list[i].name == 0) 1054e98e3e1Schristos { 1064e98e3e1Schristos sim_io_eprintf (sd, "Device '%s' not found.\n", cmd); 1074e98e3e1Schristos sim_io_eprintf (sd, "Valid devices: cpu timer sio eeprom\n"); 1084e98e3e1Schristos return; 1094e98e3e1Schristos } 1104b169a6bSchristos hw_dev = sim_hw_parse (sd, "%s", dev_list[i].device); 1114e98e3e1Schristos if (hw_dev == 0) 1124e98e3e1Schristos { 1134e98e3e1Schristos sim_io_eprintf (sd, "Device '%s' not found\n", dev_list[i].device); 1144e98e3e1Schristos return; 1154e98e3e1Schristos } 1164e98e3e1Schristos hw_ioctl (hw_dev, 23, 0); 1174e98e3e1Schristos return; 1184e98e3e1Schristos } 1194e98e3e1Schristos 1204e98e3e1Schristos cpu_info (sd, cpu); 121*9b2a9e00Schristos interrupts_info (sd, &M68HC11_SIM_CPU (cpu)->cpu_interrupts); 1224e98e3e1Schristos } 1234e98e3e1Schristos 1244e98e3e1Schristos 1254e98e3e1Schristos void 1264e98e3e1Schristos sim_board_reset (SIM_DESC sd) 1274e98e3e1Schristos { 1284e98e3e1Schristos struct hw *hw_cpu; 1294e98e3e1Schristos sim_cpu *cpu; 130*9b2a9e00Schristos struct m68hc11_sim_cpu *m68hc11_cpu; 1314e98e3e1Schristos const struct bfd_arch_info *arch; 1324e98e3e1Schristos const char *cpu_type; 1334e98e3e1Schristos 1344e98e3e1Schristos cpu = STATE_CPU (sd, 0); 135*9b2a9e00Schristos m68hc11_cpu = M68HC11_SIM_CPU (cpu); 1364e98e3e1Schristos arch = STATE_ARCHITECTURE (sd); 1374e98e3e1Schristos 1384e98e3e1Schristos /* hw_cpu = sim_hw_parse (sd, "/"); */ 1394e98e3e1Schristos if (arch->arch == bfd_arch_m68hc11) 1404e98e3e1Schristos { 141*9b2a9e00Schristos m68hc11_cpu->cpu_type = CPU_M6811; 1424e98e3e1Schristos cpu_type = "/m68hc11"; 1434e98e3e1Schristos } 1444e98e3e1Schristos else 1454e98e3e1Schristos { 146*9b2a9e00Schristos m68hc11_cpu->cpu_type = CPU_M6812; 1474e98e3e1Schristos cpu_type = "/m68hc12"; 1484e98e3e1Schristos } 1494e98e3e1Schristos 1504b169a6bSchristos hw_cpu = sim_hw_parse (sd, "%s", cpu_type); 1514e98e3e1Schristos if (hw_cpu == 0) 1524e98e3e1Schristos { 1534e98e3e1Schristos sim_io_eprintf (sd, "%s cpu not found in device tree.", cpu_type); 1544e98e3e1Schristos return; 1554e98e3e1Schristos } 1564e98e3e1Schristos 1574e98e3e1Schristos cpu_reset (cpu); 1584e98e3e1Schristos hw_port_event (hw_cpu, 3, 0); 1594e98e3e1Schristos cpu_restart (cpu); 1604e98e3e1Schristos } 1614e98e3e1Schristos 1624e98e3e1Schristos static int 1634e98e3e1Schristos sim_hw_configure (SIM_DESC sd) 1644e98e3e1Schristos { 1654e98e3e1Schristos const struct bfd_arch_info *arch; 1664e98e3e1Schristos struct hw *device_tree; 1674e98e3e1Schristos sim_cpu *cpu; 168*9b2a9e00Schristos struct m68hc11_sim_cpu *m68hc11_cpu; 1694e98e3e1Schristos 1704e98e3e1Schristos arch = STATE_ARCHITECTURE (sd); 1714e98e3e1Schristos if (arch == 0) 1724e98e3e1Schristos return 0; 1734e98e3e1Schristos 1744e98e3e1Schristos cpu = STATE_CPU (sd, 0); 175*9b2a9e00Schristos m68hc11_cpu = M68HC11_SIM_CPU (cpu); 176*9b2a9e00Schristos m68hc11_cpu->cpu_configured_arch = arch; 1774e98e3e1Schristos device_tree = sim_hw_parse (sd, "/"); 1784e98e3e1Schristos if (arch->arch == bfd_arch_m68hc11) 1794e98e3e1Schristos { 180*9b2a9e00Schristos m68hc11_cpu->cpu_interpretor = cpu_interp_m6811; 1814e98e3e1Schristos if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0) 1824e98e3e1Schristos { 1834e98e3e1Schristos /* Allocate core managed memory */ 1844e98e3e1Schristos 1854e98e3e1Schristos /* the monitor */ 1864b169a6bSchristos sim_do_commandf (sd, "memory region 0x%x@%d,0x%x", 1874e98e3e1Schristos /* MONITOR_BASE, MONITOR_SIZE */ 1884e98e3e1Schristos 0x8000, M6811_RAM_LEVEL, 0x8000); 1894e98e3e1Schristos sim_do_commandf (sd, "memory region 0x000@%d,0x8000", 1904e98e3e1Schristos M6811_RAM_LEVEL); 1914e98e3e1Schristos sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F"); 192*9b2a9e00Schristos if (m68hc11_cpu->bank_start < m68hc11_cpu->bank_end) 1934e98e3e1Schristos { 1944b169a6bSchristos sim_do_commandf (sd, "memory region 0x%x@%d,0x100000", 195*9b2a9e00Schristos m68hc11_cpu->bank_virtual, M6811_RAM_LEVEL); 1964e98e3e1Schristos sim_hw_parse (sd, "/m68hc11/use_bank 1"); 1974e98e3e1Schristos } 1984e98e3e1Schristos } 199*9b2a9e00Schristos if (m68hc11_cpu->cpu_start_mode) 2004e98e3e1Schristos { 201*9b2a9e00Schristos sim_hw_parse (sd, "/m68hc11/mode %s", m68hc11_cpu->cpu_start_mode); 2024e98e3e1Schristos } 2034e98e3e1Schristos if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0) 2044e98e3e1Schristos { 2054e98e3e1Schristos sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5"); 2064e98e3e1Schristos sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio"); 2074e98e3e1Schristos sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio"); 2084e98e3e1Schristos } 2094e98e3e1Schristos if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0) 2104e98e3e1Schristos { 2114e98e3e1Schristos /* M68hc11 Timer configuration. */ 2124e98e3e1Schristos sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5"); 2134e98e3e1Schristos sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim"); 2144e98e3e1Schristos sim_hw_parse (sd, "/m68hc11 > capture capture /m68hc11/m68hc11tim"); 2154e98e3e1Schristos } 2164e98e3e1Schristos 2174e98e3e1Schristos /* Create the SPI device. */ 2184e98e3e1Schristos if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0) 2194e98e3e1Schristos { 2204e98e3e1Schristos sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3"); 2214e98e3e1Schristos sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi"); 2224e98e3e1Schristos } 2234e98e3e1Schristos if (hw_tree_find_property (device_tree, "/m68hc11/nvram/reg") == 0) 2244e98e3e1Schristos { 2254e98e3e1Schristos /* M68hc11 persistent ram configuration. */ 2264e98e3e1Schristos sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256"); 2274e98e3e1Schristos sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram"); 2284e98e3e1Schristos sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified"); 2294e98e3e1Schristos /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */ 2304e98e3e1Schristos } 2314e98e3e1Schristos if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0) 2324e98e3e1Schristos { 2334e98e3e1Schristos sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512"); 2344e98e3e1Schristos sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr"); 2354e98e3e1Schristos } 2364e98e3e1Schristos sim_hw_parse (sd, "/m68hc11 > port-a cpu-write-port /m68hc11"); 2374e98e3e1Schristos sim_hw_parse (sd, "/m68hc11 > port-b cpu-write-port /m68hc11"); 2384e98e3e1Schristos sim_hw_parse (sd, "/m68hc11 > port-c cpu-write-port /m68hc11"); 2394e98e3e1Schristos sim_hw_parse (sd, "/m68hc11 > port-d cpu-write-port /m68hc11"); 240*9b2a9e00Schristos m68hc11_cpu->hw_cpu = sim_hw_parse (sd, "/m68hc11"); 2414e98e3e1Schristos } 2424e98e3e1Schristos else 2434e98e3e1Schristos { 244*9b2a9e00Schristos m68hc11_cpu->cpu_interpretor = cpu_interp_m6812; 2454e98e3e1Schristos if (hw_tree_find_property (device_tree, "/m68hc12/reg") == 0) 2464e98e3e1Schristos { 2474e98e3e1Schristos /* Allocate core external memory. */ 2484b169a6bSchristos sim_do_commandf (sd, "memory region 0x%x@%d,0x%x", 2494e98e3e1Schristos 0x8000, M6811_RAM_LEVEL, 0x8000); 2504e98e3e1Schristos sim_do_commandf (sd, "memory region 0x000@%d,0x8000", 2514e98e3e1Schristos M6811_RAM_LEVEL); 252*9b2a9e00Schristos if (m68hc11_cpu->bank_start < m68hc11_cpu->bank_end) 2534e98e3e1Schristos { 2544b169a6bSchristos sim_do_commandf (sd, "memory region 0x%x@%d,0x100000", 255*9b2a9e00Schristos m68hc11_cpu->bank_virtual, M6811_RAM_LEVEL); 2564e98e3e1Schristos sim_hw_parse (sd, "/m68hc12/use_bank 1"); 2574e98e3e1Schristos } 2584e98e3e1Schristos sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF"); 2594e98e3e1Schristos } 2604e98e3e1Schristos 2614e98e3e1Schristos if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg")) 2624e98e3e1Schristos { 2634e98e3e1Schristos sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8"); 2644e98e3e1Schristos sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/backend stdio"); 2654e98e3e1Schristos sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1"); 2664e98e3e1Schristos } 2674e98e3e1Schristos if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12tim/reg") == 0) 2684e98e3e1Schristos { 2694e98e3e1Schristos /* M68hc11 Timer configuration. */ 2704e98e3e1Schristos sim_hw_parse (sd, "/m68hc12/m68hc12tim/reg 0x1b 0x5"); 2714e98e3e1Schristos sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim"); 2724e98e3e1Schristos sim_hw_parse (sd, "/m68hc12 > capture capture /m68hc12/m68hc12tim"); 2734e98e3e1Schristos } 2744e98e3e1Schristos 2754e98e3e1Schristos /* Create the SPI device. */ 2764e98e3e1Schristos if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12spi/reg") == 0) 2774e98e3e1Schristos { 2784e98e3e1Schristos sim_hw_parse (sd, "/m68hc12/m68hc12spi/reg 0x28 0x3"); 2794e98e3e1Schristos sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi"); 2804e98e3e1Schristos } 2814e98e3e1Schristos if (hw_tree_find_property (device_tree, "/m68hc12/nvram/reg") == 0) 2824e98e3e1Schristos { 2834e98e3e1Schristos /* M68hc11 persistent ram configuration. */ 2844e98e3e1Schristos sim_hw_parse (sd, "/m68hc12/nvram/reg 0x2000 8192"); 2854e98e3e1Schristos sim_hw_parse (sd, "/m68hc12/nvram/file m68hc12.ram"); 2864e98e3e1Schristos sim_hw_parse (sd, "/m68hc12/nvram/mode save-modified"); 2874e98e3e1Schristos } 2884e98e3e1Schristos if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12eepr/reg") == 0) 2894e98e3e1Schristos { 2904e98e3e1Schristos sim_hw_parse (sd, "/m68hc12/m68hc12eepr/reg 0x0800 2048"); 2914e98e3e1Schristos sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr"); 2924e98e3e1Schristos } 2934e98e3e1Schristos 2944e98e3e1Schristos sim_hw_parse (sd, "/m68hc12 > port-a cpu-write-port /m68hc12"); 2954e98e3e1Schristos sim_hw_parse (sd, "/m68hc12 > port-b cpu-write-port /m68hc12"); 2964e98e3e1Schristos sim_hw_parse (sd, "/m68hc12 > port-c cpu-write-port /m68hc12"); 2974e98e3e1Schristos sim_hw_parse (sd, "/m68hc12 > port-d cpu-write-port /m68hc12"); 298*9b2a9e00Schristos m68hc11_cpu->hw_cpu = sim_hw_parse (sd, "/m68hc12"); 2994e98e3e1Schristos } 3004e98e3e1Schristos return 1; 3014e98e3e1Schristos } 3024e98e3e1Schristos 3034e98e3e1Schristos /* Get the memory bank parameters by looking at the global symbols 3044e98e3e1Schristos defined by the linker. */ 3054e98e3e1Schristos static int 306796c32c9Schristos sim_get_bank_parameters (SIM_DESC sd) 3074e98e3e1Schristos { 3084e98e3e1Schristos sim_cpu *cpu; 309*9b2a9e00Schristos struct m68hc11_sim_cpu *m68hc11_cpu; 3104e98e3e1Schristos unsigned size; 311796c32c9Schristos bfd_vma addr; 3124e98e3e1Schristos 3134e98e3e1Schristos cpu = STATE_CPU (sd, 0); 314*9b2a9e00Schristos m68hc11_cpu = M68HC11_SIM_CPU (cpu); 3154e98e3e1Schristos 316796c32c9Schristos addr = trace_sym_value (sd, BFD_M68HC11_BANK_START_NAME); 317796c32c9Schristos if (addr != -1) 318*9b2a9e00Schristos m68hc11_cpu->bank_start = addr; 3194e98e3e1Schristos 320796c32c9Schristos size = trace_sym_value (sd, BFD_M68HC11_BANK_SIZE_NAME); 321796c32c9Schristos if (size == -1) 3224e98e3e1Schristos size = 0; 3234e98e3e1Schristos 324796c32c9Schristos addr = trace_sym_value (sd, BFD_M68HC11_BANK_VIRTUAL_NAME); 325796c32c9Schristos if (addr != -1) 326*9b2a9e00Schristos m68hc11_cpu->bank_virtual = addr; 3274e98e3e1Schristos 328*9b2a9e00Schristos m68hc11_cpu->bank_end = m68hc11_cpu->bank_start + size; 329*9b2a9e00Schristos m68hc11_cpu->bank_shift = 0; 3304e98e3e1Schristos for (; size > 1; size >>= 1) 331*9b2a9e00Schristos m68hc11_cpu->bank_shift++; 3324e98e3e1Schristos 3334e98e3e1Schristos return 0; 3344e98e3e1Schristos } 3354e98e3e1Schristos 3364e98e3e1Schristos static int 3374e98e3e1Schristos sim_prepare_for_program (SIM_DESC sd, bfd* abfd) 3384e98e3e1Schristos { 3394e98e3e1Schristos sim_cpu *cpu; 340*9b2a9e00Schristos struct m68hc11_sim_cpu *m68hc11_cpu; 3414e98e3e1Schristos int elf_flags = 0; 3424e98e3e1Schristos 3434e98e3e1Schristos cpu = STATE_CPU (sd, 0); 344*9b2a9e00Schristos m68hc11_cpu = M68HC11_SIM_CPU (cpu); 3454e98e3e1Schristos 3464e98e3e1Schristos if (abfd != NULL) 3474e98e3e1Schristos { 3484e98e3e1Schristos asection *s; 3494e98e3e1Schristos 3504e98e3e1Schristos if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) 3514e98e3e1Schristos elf_flags = elf_elfheader (abfd)->e_flags; 3524e98e3e1Schristos 353*9b2a9e00Schristos m68hc11_cpu->cpu_elf_start = bfd_get_start_address (abfd); 3544e98e3e1Schristos /* See if any section sets the reset address */ 355*9b2a9e00Schristos m68hc11_cpu->cpu_use_elf_start = 1; 356*9b2a9e00Schristos for (s = abfd->sections; s && m68hc11_cpu->cpu_use_elf_start; s = s->next) 3574e98e3e1Schristos { 3584e98e3e1Schristos if (s->flags & SEC_LOAD) 3594e98e3e1Schristos { 3604e98e3e1Schristos bfd_size_type size; 3614e98e3e1Schristos 3628dffb485Schristos size = bfd_section_size (s); 3634e98e3e1Schristos if (size > 0) 3644e98e3e1Schristos { 3654e98e3e1Schristos bfd_vma lma; 3664e98e3e1Schristos 3674e98e3e1Schristos if (STATE_LOAD_AT_LMA_P (sd)) 3688dffb485Schristos lma = bfd_section_lma (s); 3694e98e3e1Schristos else 3708dffb485Schristos lma = bfd_section_vma (s); 3714e98e3e1Schristos 3724e98e3e1Schristos if (lma <= 0xFFFE && lma+size >= 0x10000) 373*9b2a9e00Schristos m68hc11_cpu->cpu_use_elf_start = 0; 3744e98e3e1Schristos } 3754e98e3e1Schristos } 3764e98e3e1Schristos } 3774e98e3e1Schristos 3784e98e3e1Schristos if (elf_flags & E_M68HC12_BANKS) 3794e98e3e1Schristos { 380796c32c9Schristos if (sim_get_bank_parameters (sd) != 0) 3814e98e3e1Schristos sim_io_eprintf (sd, "Memory bank parameters are not initialized\n"); 3824e98e3e1Schristos } 3834e98e3e1Schristos } 3844e98e3e1Schristos 3854e98e3e1Schristos if (!sim_hw_configure (sd)) 3864e98e3e1Schristos return SIM_RC_FAIL; 3874e98e3e1Schristos 3884e98e3e1Schristos /* reset all state information */ 3894e98e3e1Schristos sim_board_reset (sd); 3904e98e3e1Schristos 3914e98e3e1Schristos return SIM_RC_OK; 3924e98e3e1Schristos } 3934e98e3e1Schristos 394212397c6Schristos static sim_cia 395212397c6Schristos m68hc11_pc_get (sim_cpu *cpu) 396212397c6Schristos { 397212397c6Schristos return cpu_get_pc (cpu); 398212397c6Schristos } 399212397c6Schristos 400212397c6Schristos static void 401212397c6Schristos m68hc11_pc_set (sim_cpu *cpu, sim_cia pc) 402212397c6Schristos { 403212397c6Schristos cpu_set_pc (cpu, pc); 404212397c6Schristos } 405212397c6Schristos 4064b169a6bSchristos static int m68hc11_reg_fetch (SIM_CPU *, int, void *, int); 4074b169a6bSchristos static int m68hc11_reg_store (SIM_CPU *, int, const void *, int); 408ba340e45Schristos 4094e98e3e1Schristos SIM_DESC 4104e98e3e1Schristos sim_open (SIM_OPEN_KIND kind, host_callback *callback, 411ba340e45Schristos bfd *abfd, char * const *argv) 4124e98e3e1Schristos { 413212397c6Schristos int i; 4144e98e3e1Schristos SIM_DESC sd; 4154e98e3e1Schristos sim_cpu *cpu; 4164e98e3e1Schristos 4174e98e3e1Schristos sd = sim_state_alloc (kind, callback); 4184e98e3e1Schristos 4194e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 4204e98e3e1Schristos 4214b169a6bSchristos /* Set default options before parsing user options. */ 4224b169a6bSchristos current_target_byte_order = BFD_ENDIAN_BIG; 4234b169a6bSchristos 424212397c6Schristos /* The cpu data is kept in a separately allocated chunk of memory. */ 425*9b2a9e00Schristos if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct m68hc11_sim_cpu)) 426*9b2a9e00Schristos != SIM_RC_OK) 427212397c6Schristos { 428212397c6Schristos free_state (sd); 429212397c6Schristos return 0; 430212397c6Schristos } 431212397c6Schristos 432212397c6Schristos cpu = STATE_CPU (sd, 0); 433212397c6Schristos 4344e98e3e1Schristos cpu_initialize (sd, cpu); 4354e98e3e1Schristos 4364e98e3e1Schristos if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) 4374e98e3e1Schristos { 4384e98e3e1Schristos free_state (sd); 4394e98e3e1Schristos return 0; 4404e98e3e1Schristos } 4414e98e3e1Schristos 442ba340e45Schristos /* The parser will print an error message for us, so we silently return. */ 4434e98e3e1Schristos if (sim_parse_args (sd, argv) != SIM_RC_OK) 4444e98e3e1Schristos { 4454e98e3e1Schristos /* Uninstall the modules to avoid memory leaks, 4464e98e3e1Schristos file descriptor leaks, etc. */ 4474e98e3e1Schristos free_state (sd); 4484e98e3e1Schristos return 0; 4494e98e3e1Schristos } 4504e98e3e1Schristos 4514e98e3e1Schristos /* Check for/establish the a reference program image. */ 4524b169a6bSchristos if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK) 4534e98e3e1Schristos { 4544e98e3e1Schristos free_state (sd); 4554e98e3e1Schristos return 0; 4564e98e3e1Schristos } 4574e98e3e1Schristos 4584e98e3e1Schristos /* Establish any remaining configuration options. */ 4594e98e3e1Schristos if (sim_config (sd) != SIM_RC_OK) 4604e98e3e1Schristos { 4614e98e3e1Schristos free_state (sd); 4624e98e3e1Schristos return 0; 4634e98e3e1Schristos } 4644e98e3e1Schristos 4654e98e3e1Schristos if (sim_post_argv_init (sd) != SIM_RC_OK) 4664e98e3e1Schristos { 4674e98e3e1Schristos /* Uninstall the modules to avoid memory leaks, 4684e98e3e1Schristos file descriptor leaks, etc. */ 4694e98e3e1Schristos free_state (sd); 4704e98e3e1Schristos return 0; 4714e98e3e1Schristos } 4724e98e3e1Schristos if (sim_prepare_for_program (sd, abfd) != SIM_RC_OK) 4734e98e3e1Schristos { 4744e98e3e1Schristos free_state (sd); 4754e98e3e1Schristos return 0; 4764e98e3e1Schristos } 4774e98e3e1Schristos 478212397c6Schristos /* CPU specific initialization. */ 479212397c6Schristos for (i = 0; i < MAX_NR_PROCESSORS; ++i) 480212397c6Schristos { 481*9b2a9e00Schristos cpu = STATE_CPU (sd, i); 482212397c6Schristos 483ba340e45Schristos CPU_REG_FETCH (cpu) = m68hc11_reg_fetch; 484ba340e45Schristos CPU_REG_STORE (cpu) = m68hc11_reg_store; 485212397c6Schristos CPU_PC_FETCH (cpu) = m68hc11_pc_get; 486212397c6Schristos CPU_PC_STORE (cpu) = m68hc11_pc_set; 487212397c6Schristos } 488212397c6Schristos 4894e98e3e1Schristos return sd; 4904e98e3e1Schristos } 4914e98e3e1Schristos 4924e98e3e1Schristos /* Generic implementation of sim_engine_run that works within the 4934e98e3e1Schristos sim_engine setjmp/longjmp framework. */ 4944e98e3e1Schristos 4954e98e3e1Schristos void 4964e98e3e1Schristos sim_engine_run (SIM_DESC sd, 4974e98e3e1Schristos int next_cpu_nr, /* ignore */ 4984e98e3e1Schristos int nr_cpus, /* ignore */ 4994e98e3e1Schristos int siggnal) /* ignore */ 5004e98e3e1Schristos { 5014e98e3e1Schristos sim_cpu *cpu; 5024e98e3e1Schristos 5034e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 5044e98e3e1Schristos cpu = STATE_CPU (sd, 0); 5054e98e3e1Schristos while (1) 5064e98e3e1Schristos { 5074e98e3e1Schristos cpu_single_step (cpu); 5084e98e3e1Schristos 5094e98e3e1Schristos /* process any events */ 510*9b2a9e00Schristos if (sim_events_tickn (sd, M68HC11_SIM_CPU (cpu)->cpu_current_cycle)) 5114e98e3e1Schristos { 5124e98e3e1Schristos sim_events_process (sd); 5134e98e3e1Schristos } 5144e98e3e1Schristos } 5154e98e3e1Schristos } 5164e98e3e1Schristos 5174e98e3e1Schristos void 518*9b2a9e00Schristos sim_info (SIM_DESC sd, bool verbose) 5194e98e3e1Schristos { 5204e98e3e1Schristos const char *cpu_type; 5214e98e3e1Schristos const struct bfd_arch_info *arch; 5224e98e3e1Schristos 5234e98e3e1Schristos /* Nothing to do if there is no verbose flag set. */ 5244e98e3e1Schristos if (verbose == 0 && STATE_VERBOSE_P (sd) == 0) 5254e98e3e1Schristos return; 5264e98e3e1Schristos 5274e98e3e1Schristos arch = STATE_ARCHITECTURE (sd); 5284e98e3e1Schristos if (arch->arch == bfd_arch_m68hc11) 5294e98e3e1Schristos cpu_type = "68HC11"; 5304e98e3e1Schristos else 5314e98e3e1Schristos cpu_type = "68HC12"; 5324e98e3e1Schristos 5334e98e3e1Schristos sim_io_eprintf (sd, "Simulator info:\n"); 5344e98e3e1Schristos sim_io_eprintf (sd, " CPU Motorola %s\n", cpu_type); 5354e98e3e1Schristos sim_get_info (sd, 0); 5364e98e3e1Schristos sim_module_info (sd, verbose || STATE_VERBOSE_P (sd)); 5374e98e3e1Schristos } 5384e98e3e1Schristos 5394e98e3e1Schristos SIM_RC 5404e98e3e1Schristos sim_create_inferior (SIM_DESC sd, struct bfd *abfd, 541ba340e45Schristos char * const *argv, char * const *env) 5424e98e3e1Schristos { 5434e98e3e1Schristos return sim_prepare_for_program (sd, abfd); 5444e98e3e1Schristos } 5454e98e3e1Schristos 546ba340e45Schristos static int 5474b169a6bSchristos m68hc11_reg_fetch (SIM_CPU *cpu, int rn, void *buf, int length) 5484e98e3e1Schristos { 5494b169a6bSchristos unsigned char *memory = buf; 5504b169a6bSchristos uint16_t val; 5514e98e3e1Schristos int size = 2; 5524e98e3e1Schristos 5534e98e3e1Schristos switch (rn) 5544e98e3e1Schristos { 5554e98e3e1Schristos case A_REGNUM: 5564e98e3e1Schristos val = cpu_get_a (cpu); 5574e98e3e1Schristos size = 1; 5584e98e3e1Schristos break; 5594e98e3e1Schristos 5604e98e3e1Schristos case B_REGNUM: 5614e98e3e1Schristos val = cpu_get_b (cpu); 5624e98e3e1Schristos size = 1; 5634e98e3e1Schristos break; 5644e98e3e1Schristos 5654e98e3e1Schristos case D_REGNUM: 5664e98e3e1Schristos val = cpu_get_d (cpu); 5674e98e3e1Schristos break; 5684e98e3e1Schristos 5694e98e3e1Schristos case X_REGNUM: 5704e98e3e1Schristos val = cpu_get_x (cpu); 5714e98e3e1Schristos break; 5724e98e3e1Schristos 5734e98e3e1Schristos case Y_REGNUM: 5744e98e3e1Schristos val = cpu_get_y (cpu); 5754e98e3e1Schristos break; 5764e98e3e1Schristos 5774e98e3e1Schristos case SP_REGNUM: 5784e98e3e1Schristos val = cpu_get_sp (cpu); 5794e98e3e1Schristos break; 5804e98e3e1Schristos 5814e98e3e1Schristos case PC_REGNUM: 5824e98e3e1Schristos val = cpu_get_pc (cpu); 5834e98e3e1Schristos break; 5844e98e3e1Schristos 5854e98e3e1Schristos case PSW_REGNUM: 5864e98e3e1Schristos val = cpu_get_ccr (cpu); 5874e98e3e1Schristos size = 1; 5884e98e3e1Schristos break; 5894e98e3e1Schristos 5904e98e3e1Schristos case PAGE_REGNUM: 5914e98e3e1Schristos val = cpu_get_page (cpu); 5924e98e3e1Schristos size = 1; 5934e98e3e1Schristos break; 5944e98e3e1Schristos 5954e98e3e1Schristos default: 5964e98e3e1Schristos val = 0; 5974e98e3e1Schristos break; 5984e98e3e1Schristos } 5994e98e3e1Schristos if (size == 1) 6004e98e3e1Schristos { 6014e98e3e1Schristos memory[0] = val; 6024e98e3e1Schristos } 6034e98e3e1Schristos else 6044e98e3e1Schristos { 6054e98e3e1Schristos memory[0] = val >> 8; 6064e98e3e1Schristos memory[1] = val & 0x0FF; 6074e98e3e1Schristos } 6084e98e3e1Schristos return size; 6094e98e3e1Schristos } 6104e98e3e1Schristos 611ba340e45Schristos static int 6124b169a6bSchristos m68hc11_reg_store (SIM_CPU *cpu, int rn, const void *buf, int length) 6134e98e3e1Schristos { 6144b169a6bSchristos const unsigned char *memory = buf; 6154b169a6bSchristos uint16_t val; 6164e98e3e1Schristos 6174e98e3e1Schristos val = *memory++; 6184e98e3e1Schristos if (length == 2) 6194e98e3e1Schristos val = (val << 8) | *memory; 6204e98e3e1Schristos 6214e98e3e1Schristos switch (rn) 6224e98e3e1Schristos { 6234e98e3e1Schristos case D_REGNUM: 6244e98e3e1Schristos cpu_set_d (cpu, val); 6254e98e3e1Schristos break; 6264e98e3e1Schristos 6274e98e3e1Schristos case A_REGNUM: 6284e98e3e1Schristos cpu_set_a (cpu, val); 6294e98e3e1Schristos return 1; 6304e98e3e1Schristos 6314e98e3e1Schristos case B_REGNUM: 6324e98e3e1Schristos cpu_set_b (cpu, val); 6334e98e3e1Schristos return 1; 6344e98e3e1Schristos 6354e98e3e1Schristos case X_REGNUM: 6364e98e3e1Schristos cpu_set_x (cpu, val); 6374e98e3e1Schristos break; 6384e98e3e1Schristos 6394e98e3e1Schristos case Y_REGNUM: 6404e98e3e1Schristos cpu_set_y (cpu, val); 6414e98e3e1Schristos break; 6424e98e3e1Schristos 6434e98e3e1Schristos case SP_REGNUM: 6444e98e3e1Schristos cpu_set_sp (cpu, val); 6454e98e3e1Schristos break; 6464e98e3e1Schristos 6474e98e3e1Schristos case PC_REGNUM: 6484e98e3e1Schristos cpu_set_pc (cpu, val); 6494e98e3e1Schristos break; 6504e98e3e1Schristos 6514e98e3e1Schristos case PSW_REGNUM: 6524e98e3e1Schristos cpu_set_ccr (cpu, val); 6534e98e3e1Schristos return 1; 6544e98e3e1Schristos 6554e98e3e1Schristos case PAGE_REGNUM: 6564e98e3e1Schristos cpu_set_page (cpu, val); 6574e98e3e1Schristos return 1; 6584e98e3e1Schristos 6594e98e3e1Schristos default: 6604e98e3e1Schristos break; 6614e98e3e1Schristos } 6624e98e3e1Schristos 6634e98e3e1Schristos return 2; 6644e98e3e1Schristos } 665