xref: /netbsd-src/external/gpl3/gdb/dist/sim/m68hc11/interp.c (revision 9b2a9e00295c5af9c57a466f299054d5910e47d6)
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