Improve HC11 simulator to support HC12
[deliverable/binutils-gdb.git] / sim / m68hc11 / interp.c
index f9de86575ba753a2fbb9fec92969d5cbc5c63c86..e04399236fab09e0c0c3de709fcddda1d4c3a7cd 100644 (file)
@@ -1,5 +1,5 @@
 /* interp.c -- Simulator for Motorola 68HC11
-   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
    Written by Stephane Carrez (stcarrez@worldnet.fr)
 
 This file is part of GDB, the GNU debugger.
@@ -55,7 +55,7 @@ struct sim_info_list
   const char *device;
 };
 
-struct sim_info_list dev_list[] = {
+struct sim_info_list dev_list_68hc11[] = {
   {"cpu", "/m68hc11"},
   {"timer", "/m68hc11/m68hc11tim"},
   {"sio", "/m68hc11/m68hc11sio"},
@@ -64,18 +64,48 @@ struct sim_info_list dev_list[] = {
   {0, 0}
 };
 
+struct sim_info_list dev_list_68hc12[] = {
+  {"cpu", "/m68hc12"},
+  {"timer", "/m68hc12/m68hc12tim"},
+  {"sio", "/m68hc12/m68hc12sio"},
+  {"spi", "/m68hc12/m68hc12spi"},
+  {"eeprom", "/m68hc12/m68hc12eepr"},
+  {0, 0}
+};
+
+/* Cover function of sim_state_free to free the cpu buffers as well.  */
+
+static void
+free_state (SIM_DESC sd)
+{
+  if (STATE_MODULES (sd) != NULL)
+    sim_module_uninstall (sd);
+
+  sim_state_free (sd);
+}
+
 /* Give some information about the simulator.  */
 static void
 sim_get_info (SIM_DESC sd, char *cmd)
 {
   sim_cpu *cpu;
 
+  cpu = STATE_CPU (sd, 0);
   if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-'))
     {
       int i;
       struct hw *hw_dev;
+      struct sim_info_list *dev_list;
+      const struct bfd_arch_info *arch;
+
+      arch = STATE_ARCHITECTURE (sd);
       cmd++;
 
+      if (arch->arch == bfd_arch_m68hc11)
+        dev_list = dev_list_68hc11;
+      else
+        dev_list = dev_list_68hc12;
+
       for (i = 0; dev_list[i].name; i++)
        if (strcmp (cmd, dev_list[i].name) == 0)
          break;
@@ -96,7 +126,6 @@ sim_get_info (SIM_DESC sd, char *cmd)
       return;
     }
 
-  cpu = STATE_CPU (sd, 0);
   cpu_info (sd, cpu);
   interrupts_info (sd, &cpu->cpu_interrupts);
 }
@@ -107,13 +136,28 @@ sim_board_reset (SIM_DESC sd)
 {
   struct hw *hw_cpu;
   sim_cpu *cpu;
+  const struct bfd_arch_info *arch;
+  const char *cpu_type;
 
   cpu = STATE_CPU (sd, 0);
+  arch = STATE_ARCHITECTURE (sd);
+
   /*  hw_cpu = sim_hw_parse (sd, "/"); */
-  hw_cpu = sim_hw_parse (sd, "/m68hc11");
+  if (arch->arch == bfd_arch_m68hc11)
+    {
+      cpu->cpu_type = CPU_M6811;
+      cpu_type = "/m68hc11";
+    }
+  else
+    {
+      cpu->cpu_type = CPU_M6812;
+      cpu_type = "/m68hc12";
+    }
+  
+  hw_cpu = sim_hw_parse (sd, cpu_type);
   if (hw_cpu == 0)
     {
-      sim_io_eprintf (sd, "m68hc11 cpu not found in device tree.");
+      sim_io_eprintf (sd, "%s cpu not found in device tree.", cpu_type);
       return;
     }
 
@@ -122,6 +166,144 @@ sim_board_reset (SIM_DESC sd)
   cpu_restart (cpu);
 }
 
+int
+sim_hw_configure (SIM_DESC sd)
+{
+  const struct bfd_arch_info *arch;
+  struct hw *device_tree;
+  int m6811_mode;
+  sim_cpu *cpu;
+  
+  arch = STATE_ARCHITECTURE (sd);
+  if (arch == 0)
+    return 0;
+
+  cpu = STATE_CPU (sd, 0);
+  cpu->cpu_configured_arch = arch;
+  device_tree = sim_hw_parse (sd, "/");
+  if (arch->arch == bfd_arch_m68hc11)
+    {
+      cpu->cpu_interpretor = cpu_interp_m6811;
+      if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0)
+       {
+         /* Allocate core managed memory */
+
+         /* the monitor  */
+         sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
+                          /* MONITOR_BASE, MONITOR_SIZE */
+                          0x8000, M6811_RAM_LEVEL, 0x8000);
+         sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
+                          M6811_RAM_LEVEL);
+         sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F");
+       }
+
+      if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0)
+       {
+         sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5");
+         sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio");
+         sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio");
+       }
+      if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0)
+       {
+         /* M68hc11 Timer configuration. */
+         sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5");
+         sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim");
+       }
+
+      /* Create the SPI device.  */
+      if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0)
+       {
+         sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3");
+         sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
+       }
+      if (hw_tree_find_property (device_tree, "/m68hc11/nvram/reg") == 0)
+       {
+         /* M68hc11 persistent ram configuration. */
+         sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256");
+         sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram");
+         sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified");
+         /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */
+       }
+      if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0)
+       {
+         sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512");
+         sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
+       }
+    }
+  else
+    {
+      cpu->cpu_interpretor = cpu_interp_m6812;
+      if (hw_tree_find_property (device_tree, "/m68hc12/reg") == 0)
+       {
+         /* Allocate core external memory.  */
+         sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
+                          0x8000, M6811_RAM_LEVEL, 0x8000);
+         sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
+                          M6811_RAM_LEVEL);
+
+         sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF");
+       }
+
+      if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg"))
+       {
+         sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8");
+         sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/backend stdio");
+         sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1");
+       }
+      if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@2/reg"))
+       {
+         sim_hw_parse (sd, "/m68hc12/m68hc12sio@2/reg 0xC8 0x8");
+         sim_hw_parse (sd, "/m68hc12/m68hc12sio@2/backend tcp");
+         sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@2");
+       }
+      if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12tim/reg") == 0)
+       {
+         /* M68hc11 Timer configuration. */
+         sim_hw_parse (sd, "/m68hc12/m68hc12tim/reg 0x1b 0x5");
+         sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim");
+       }
+
+      /* Create the SPI device.  */
+      if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12spi/reg") == 0)
+       {
+         sim_hw_parse (sd, "/m68hc12/m68hc12spi/reg 0x28 0x3");
+         sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi");
+       }
+      if (hw_tree_find_property (device_tree, "/m68hc12/nvram/reg") == 0)
+       {
+         /* M68hc11 persistent ram configuration. */
+         sim_hw_parse (sd, "/m68hc12/nvram/reg 0x2000 8192");
+         sim_hw_parse (sd, "/m68hc12/nvram/file m68hc12.ram");
+         sim_hw_parse (sd, "/m68hc12/nvram/mode save-modified");
+       }
+      if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12eepr/reg") == 0)
+       {
+         sim_hw_parse (sd, "/m68hc12/m68hc12eepr/reg 0x0800 2048");
+         sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr");
+       }
+    }
+  return 0;
+}
+
+static int
+sim_prepare_for_program (SIM_DESC sd, struct _bfd* abfd)
+{
+  sim_cpu *cpu;
+
+  cpu = STATE_CPU (sd, 0);
+
+  sim_hw_configure (sd);
+  if (abfd != NULL)
+    {
+      cpu->cpu_elf_start = bfd_get_start_address (abfd);
+    }
+
+  /* reset all state information */
+  sim_board_reset (sd);
+
+  return SIM_RC_OK;
+}
+
 SIM_DESC
 sim_open (SIM_OPEN_KIND kind, host_callback *callback,
           struct _bfd *abfd, char **argv)
@@ -144,7 +326,10 @@ sim_open (SIM_OPEN_KIND kind, host_callback *callback,
 
   cpu->cpu_use_elf_start = 1;
   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
-    return 0;
+    {
+      free_state (sd);
+      return 0;
+    }
 
   /* getopt will print the error message so we just have to exit if this fails.
      FIXME: Hmmm...  in the case of gdb we need getopt to call
@@ -153,72 +338,24 @@ sim_open (SIM_OPEN_KIND kind, host_callback *callback,
     {
       /* Uninstall the modules to avoid memory leaks,
          file descriptor leaks, etc.  */
-      sim_module_uninstall (sd);
+      free_state (sd);
       return 0;
     }
 
-  device_tree = sim_hw_parse (sd, "/");
-  if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0)
-    {
-      /* Allocate core managed memory */
-
-      /* the monitor  */
-      sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
-                      /* MONITOR_BASE, MONITOR_SIZE */
-                      0x8000, M6811_RAM_LEVEL, 0x8000);
-      sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
-                       M6811_RAM_LEVEL);
-      sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F");
-    }
-
-  if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0)
-    {
-      sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5");
-      sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio");
-      sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio");
-    }
-  if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0)
-    {
-      /* M68hc11 Timer configuration. */
-      sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5");
-      sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim");
-    }
-
-  /* Create the SPI device.  */
-  if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0)
-    {
-      sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3");
-      sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
-    }
-  if (hw_tree_find_property (device_tree, "/m68hc11/pram/reg") == 0)
-    {
-      /* M68hc11 persistent ram configuration. */
-      sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256");
-      sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram");
-      sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified");
-      /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */
-    }
-  if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0)
-    {
-      sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512");
-      /* Connect the CPU reset to all devices. */
-      sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
-    }
-
   /* Check for/establish the a reference program image.  */
   if (sim_analyze_program (sd,
                           (STATE_PROG_ARGV (sd) != NULL
                            ? *STATE_PROG_ARGV (sd)
                            : NULL), abfd) != SIM_RC_OK)
     {
-      sim_module_uninstall (sd);
+      free_state (sd);
       return 0;
     }
 
   /* Establish any remaining configuration options.  */
   if (sim_config (sd) != SIM_RC_OK)
     {
-      sim_module_uninstall (sd);
+      free_state (sd);
       return 0;
     }
 
@@ -226,16 +363,11 @@ sim_open (SIM_OPEN_KIND kind, host_callback *callback,
     {
       /* Uninstall the modules to avoid memory leaks,
          file descriptor leaks, etc.  */
-      sim_module_uninstall (sd);
+      free_state (sd);
       return 0;
     }
 
-  if (abfd != NULL)
-    {
-      cpu->cpu_elf_start = bfd_get_start_address (abfd);
-    }
-
-  sim_board_reset (sd);
+  sim_hw_configure (sd);
 
   /* Fudge our descriptor.  */
   return sd;
@@ -253,7 +385,7 @@ sim_close (SIM_DESC sd, int quitting)
   sim_io_shutdown (sd);
 
   /* FIXME - free SD */
-
+  sim_state_free (sd);
   return;
 }
 
@@ -302,8 +434,17 @@ sim_trace (SIM_DESC sd)
 void
 sim_info (SIM_DESC sd, int verbose)
 {
+  const char *cpu_type;
+  const struct bfd_arch_info *arch;
+
+  arch = STATE_ARCHITECTURE (sd);
+  if (arch->arch == bfd_arch_m68hc11)
+    cpu_type = "68HC11";
+  else
+    cpu_type = "68HC12";
+
   sim_io_eprintf (sd, "Simulator info:\n");
-  sim_io_eprintf (sd, "  CPU Motorola 68HC11\n");
+  sim_io_eprintf (sd, "  CPU Motorola %s\n", cpu_type);
   sim_get_info (sd, 0);
   sim_module_info (sd, verbose || STATE_VERBOSE_P (sd));
 }
@@ -312,20 +453,7 @@ SIM_RC
 sim_create_inferior (SIM_DESC sd, struct _bfd *abfd,
                      char **argv, char **env)
 {
-  sim_cpu *cpu;
-  int i;
-
-  cpu = STATE_CPU (sd, 0);
-
-  if (abfd != NULL)
-    {
-      cpu->cpu_elf_start = bfd_get_start_address (abfd);
-    }
-
-  /* reset all state information */
-  sim_board_reset (sd);
-
-  return SIM_RC_OK;
+  return sim_prepare_for_program (sd, abfd);
 }
 
 
@@ -450,7 +578,9 @@ sim_do_command (SIM_DESC sd, char *cmd)
 {
   char *mm_cmd = "memory-map";
   char *int_cmd = "interrupt";
+  sim_cpu *cpu;
 
+  cpu = STATE_CPU (sd, 0);
   /* Commands available from GDB:   */
   if (sim_args_command (sd, cmd) != SIM_RC_OK)
     {
@@ -466,4 +596,8 @@ sim_do_command (SIM_DESC sd, char *cmd)
       else
        sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
     }
+
+  /* If the architecture changed, re-configure.  */
+  if (STATE_ARCHITECTURE (sd) != cpu->cpu_configured_arch)
+    sim_hw_configure (sd);
 }
This page took 0.027398 seconds and 4 git commands to generate.