]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - sim/m68hc11/m68hc11_sim.c
sim: m68hc11: fix gcc-5 build error w/restrict keyword
[thirdparty/binutils-gdb.git] / sim / m68hc11 / m68hc11_sim.c
index 1beef6d4115f8e0f4946c59bb79c76eeb8c6d235..8a0464871e603f877ece85a414d4ccdca0f81843 100644 (file)
@@ -1,34 +1,32 @@
 /* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
-   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
-   Written by Stephane Carrez (stcarrez@worldnet.fr)
+   Copyright 1999-2015 Free Software Foundation, Inc.
+   Written by Stephane Carrez (stcarrez@nerim.fr)
 
 This file is part of GDB, GAS, and the GNU binutils.
 
-GDB, GAS, and the GNU binutils are free software; you can redistribute
-them and/or modify them under the terms of the GNU General Public
-License as published by the Free Software Foundation; either version
-1, or (at your option) any later version.
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
 
-GDB, GAS, and the GNU binutils are distributed in the hope that they
-will be useful, but WITHOUT ANY WARRANTY; without even the implied
-warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
-the GNU General Public License for more details.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this file; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "sim-main.h"
 #include "sim-assert.h"
 #include "sim-module.h"
 #include "sim-options.h"
 
-void cpu_free_frame (sim_cpu* cpu, struct cpu_frame *frame);
-
 enum {
   OPTION_CPU_RESET = OPTION_START,
   OPTION_EMUL_OS,
   OPTION_CPU_CONFIG,
+  OPTION_CPU_BOOTSTRAP,
   OPTION_CPU_MODE
 };
 
@@ -48,6 +46,10 @@ static const OPTION cpu_options[] =
       '\0', NULL, "Specify the initial CPU configuration register",
       cpu_option_handler },
 
+  { {"bootstrap", no_argument, NULL, OPTION_CPU_BOOTSTRAP },
+      '\0', NULL, "Start the processing in bootstrap mode",
+      cpu_option_handler },
+
   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
 };
 
@@ -56,7 +58,6 @@ static SIM_RC
 cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
                     int opt, char *arg, int is_command)
 {
-  sim_cpu *cpu;
   int val;
   
   cpu = STATE_CPU (sd, 0);
@@ -80,7 +81,11 @@ cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
       else
         cpu->cpu_use_local_config = 0;
       break;
-      
+
+    case OPTION_CPU_BOOTSTRAP:
+       cpu->cpu_start_mode = "bootstrap";
+       break;
+
     case OPTION_CPU_MODE:
       break;
     }
@@ -88,213 +93,17 @@ cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
   return SIM_RC_OK;
 }
 
-/* Tentative to keep track of the cpu frame.  */
-struct cpu_frame*
-cpu_find_frame (sim_cpu *cpu, uint16 sp)
-{
-  struct cpu_frame_list *flist;
-
-  flist = cpu->cpu_frames;
-  while (flist)
-    {
-      struct cpu_frame *frame;
-
-      frame = flist->frame;
-      while (frame)
-       {
-         if (frame->sp_low <= sp && frame->sp_high >= sp)
-           {
-             cpu->cpu_current_frame = flist;
-             return frame;
-           }
-
-         frame = frame->up;
-       }
-      flist = flist->next;
-    }
-  return 0;
-}
-
-struct cpu_frame_list*
-cpu_create_frame_list (sim_cpu *cpu)
-{
-  struct cpu_frame_list *flist;
-
-  flist = (struct cpu_frame_list*) malloc (sizeof (struct cpu_frame_list));
-  flist->frame = 0;
-  flist->next  = cpu->cpu_frames;
-  flist->prev  = 0;
-  if (flist->next)
-    flist->next->prev = flist;
-  cpu->cpu_frames = flist;
-  cpu->cpu_current_frame = flist;
-  return flist;
-}
-
-void
-cpu_remove_frame_list (sim_cpu *cpu, struct cpu_frame_list *flist)
-{
-  struct cpu_frame *frame;
-  
-  if (flist->prev == 0)
-    cpu->cpu_frames = flist->next;
-  else
-    flist->prev->next = flist->next;
-  if (flist->next)
-    flist->next->prev = flist->prev;
-
-  frame = flist->frame;
-  while (frame)
-    {
-      struct cpu_frame* up = frame->up;
-      cpu_free_frame (cpu, frame);
-      frame = up;
-    }
-  free (flist);
-}
-  
     
-struct cpu_frame*
-cpu_create_frame (sim_cpu *cpu, uint16 pc, uint16 sp)
-{
-  struct cpu_frame *frame;
-
-  frame = (struct cpu_frame*) malloc (sizeof(struct cpu_frame));
-  frame->up = 0;
-  frame->pc = pc;
-  frame->sp_low  = sp;
-  frame->sp_high = sp;
-  return frame;
-}
-
-void
-cpu_free_frame (sim_cpu *cpu, struct cpu_frame *frame)
-{
-  free (frame);
-}
-
-uint16
-cpu_frame_reg (sim_cpu *cpu, uint16 rn)
-{
-  struct cpu_frame *frame;
-
-  if (cpu->cpu_current_frame == 0)
-    return 0;
-  
-  frame = cpu->cpu_current_frame->frame;
-  while (frame)
-    {
-      if (rn == 0)
-       return frame->sp_high;
-      frame = frame->up;
-      rn--;
-    }
-  return 0;
-}
-  
 void
 cpu_call (sim_cpu *cpu, uint16 addr)
 {
-#if HAVE_FRAME
-  uint16 pc = cpu->cpu_insn_pc;
-  uint16 sp;
-  struct cpu_frame_list *flist;
-  struct cpu_frame* frame;
-  struct cpu_frame* new_frame;
-#endif
 
   cpu_set_pc (cpu, addr);
-#if HAVE_FRAME
-  sp = cpu_get_sp (cpu);
-
-  cpu->cpu_need_update_frame = 0;
-  flist = cpu->cpu_current_frame;
-  if (flist == 0)
-    flist = cpu_create_frame_list (cpu);
-
-  frame = flist->frame;
-  if (frame && frame->sp_low > sp)
-    frame->sp_low = sp;
-
-  new_frame = cpu_create_frame (cpu, pc, sp);
-  new_frame->up = frame;
-  flist->frame = new_frame;
-#endif
-}
-
-void
-cpu_update_frame (sim_cpu *cpu, int do_create)
-{
-#if HAVE_FRAME
-  struct cpu_frame *frame;
-
-  frame = cpu_find_frame (cpu, cpu_get_sp (cpu));
-  if (frame)
-    {
-      while (frame != cpu->cpu_current_frame->frame)
-       {
-         struct cpu_frame* up;
-         
-         up = cpu->cpu_current_frame->frame->up;
-         cpu_free_frame (cpu, cpu->cpu_current_frame->frame);
-         cpu->cpu_current_frame->frame = up;
-       }
-      return;
-    }
-
-  if (do_create)
-    {
-      cpu_create_frame_list (cpu);
-      frame = cpu_create_frame (cpu, cpu_get_pc (cpu), cpu_get_sp (cpu));
-      cpu->cpu_current_frame->frame = frame;
-    }
-#endif
 }
 
 void
 cpu_return (sim_cpu *cpu)
 {
-#if HAVE_FRAME
-  uint16 sp = cpu_get_sp (cpu);
-  struct cpu_frame *frame;
-  struct cpu_frame_list *flist;
-
-  cpu->cpu_need_update_frame = 0;
-  flist = cpu->cpu_current_frame;
-  if (flist && flist->frame && flist->frame->up)
-    {
-      frame = flist->frame->up;
-      if (frame->sp_low <= sp && frame->sp_high >= sp)
-       {
-         cpu_free_frame (cpu, flist->frame);
-         flist->frame = frame;
-         return;
-       }
-    }
-  cpu_update_frame (cpu, 1);
-#endif
-}
-
-void
-cpu_print_frame (SIM_DESC sd, sim_cpu *cpu)
-{
-  struct cpu_frame* frame;
-  int level = 0;
-  
-  if (cpu->cpu_current_frame == 0 || cpu->cpu_current_frame->frame == 0)
-    {
-      sim_io_printf (sd, "No frame.\n");
-      return;
-    }
-  sim_io_printf (sd, " #   PC   SP-L  SP-H\n");
-  frame = cpu->cpu_current_frame->frame;
-  while (frame)
-    {
-      sim_io_printf (sd, "%3d 0x%04x 0x%04x 0x%04x\n",
-                    level, frame->pc, frame->sp_low, frame->sp_high);
-      frame = frame->up;
-      level++;
-    }
 }
 
 /* Set the stack pointer and re-compute the current frame.  */
@@ -302,7 +111,6 @@ void
 cpu_set_sp (sim_cpu *cpu, uint16 val)
 {
   cpu->cpu_regs.sp = val;
-  cpu_update_frame (cpu, 0);
 }
 
 uint16
@@ -432,7 +240,7 @@ cpu_set_reg (sim_cpu* cpu, uint8 reg, uint16 val)
 /* Returns the address of a 68HC12 indexed operand.
    Pre and post modifications are handled on the source register.  */
 uint16
-cpu_get_indexed_operand_addr (sim_cpu* cpu, int restrict)
+cpu_get_indexed_operand_addr (sim_cpu* cpu, int restricted)
 {
   uint8 reg;
   uint16 sval;
@@ -477,7 +285,7 @@ cpu_get_indexed_operand_addr (sim_cpu* cpu, int restrict)
   /* [n,r] 16-bits offset indexed indirect.  */
   else if ((code & 0x07) == 3)
     {
-      if (restrict)
+      if (restricted)
        {
          return 0;
        }
@@ -489,7 +297,7 @@ cpu_get_indexed_operand_addr (sim_cpu* cpu, int restrict)
     }
   else if ((code & 0x4) == 0)
     {
-      if (restrict)
+      if (restricted)
        {
          return 0;
        }
@@ -537,20 +345,20 @@ cpu_get_indexed_operand_addr (sim_cpu* cpu, int restrict)
 }
 
 uint8
-cpu_get_indexed_operand8 (sim_cpu* cpu, int restrict)
+cpu_get_indexed_operand8 (sim_cpu* cpu, int restricted)
 {
   uint16 addr;
 
-  addr = cpu_get_indexed_operand_addr (cpu, restrict);
+  addr = cpu_get_indexed_operand_addr (cpu, restricted);
   return memory_read8 (cpu, addr);
 }
 
 uint16
-cpu_get_indexed_operand16 (sim_cpu* cpu, int restrict)
+cpu_get_indexed_operand16 (sim_cpu* cpu, int restricted)
 {
   uint16 addr;
 
-  addr = cpu_get_indexed_operand_addr (cpu, restrict);
+  addr = cpu_get_indexed_operand_addr (cpu, restricted);
   return memory_read16 (cpu, addr);
 }
 
@@ -592,7 +400,11 @@ cpu_move8 (sim_cpu *cpu, uint8 code)
       src = cpu_get_indexed_operand8 (cpu, 1);
       addr = cpu_get_indexed_operand_addr (cpu, 1);
       break;
-      
+
+    default:
+      sim_engine_abort (CPU_STATE (cpu), cpu, 0,
+                       "Invalid code 0x%0x -- internal error?", code);
+      return;
     }
   memory_write8 (cpu, addr, src);
 }
@@ -635,7 +447,11 @@ cpu_move16 (sim_cpu *cpu, uint8 code)
       src = cpu_get_indexed_operand16 (cpu, 1);
       addr = cpu_get_indexed_operand_addr (cpu, 1);
       break;
-      
+
+    default:
+      sim_engine_abort (CPU_STATE (cpu), cpu, 0,
+                       "Invalid code 0x%0x -- internal error?", code);
+      return;
     }
   memory_write16 (cpu, addr, src);
 }
@@ -643,8 +459,6 @@ cpu_move16 (sim_cpu *cpu, uint8 code)
 int
 cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
 {
-  int result;
-  
   sim_add_option_table (sd, 0, cpu_options);
 
   memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
@@ -655,17 +469,18 @@ cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
   cpu->cpu_running        = 1;
   cpu->cpu_stop_on_interrupt = 0;
   cpu->cpu_frequency = 8 * 1000 * 1000;
-  cpu->cpu_frames = 0;
-  cpu->cpu_current_frame = 0;
   cpu->cpu_use_elf_start = 0;
   cpu->cpu_elf_start     = 0;
   cpu->cpu_use_local_config = 0;
+  cpu->bank_start = 0;
+  cpu->bank_end   = 0;
+  cpu->bank_shift = 0;
   cpu->cpu_config        = M6811_NOSEC | M6811_NOCOP | M6811_ROMON |
     M6811_EEON;
-  result = interrupts_initialize (cpu);
+  interrupts_initialize (sd, cpu);
 
   cpu->cpu_is_initialized = 1;
-  return result;
+  return 0;
 }
 
 
@@ -673,11 +488,6 @@ cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
 int
 cpu_reset (sim_cpu *cpu)
 {
-  cpu->cpu_need_update_frame = 0;
-  cpu->cpu_current_frame = 0;
-  while (cpu->cpu_frames)
-    cpu_remove_frame_list (cpu, cpu->cpu_frames);
-
   /* Initialize the config register.
      It is only initialized at reset time.  */
   memset (cpu->ios, 0, sizeof (cpu->ios));
@@ -702,6 +512,9 @@ cpu_reset (sim_cpu *cpu)
   cpu->cpu_current_cycle  = 0;
   cpu->cpu_is_initialized = 0;
 
+  /* Reset interrupts.  */
+  interrupts_reset (&cpu->cpu_interrupts);
+
   /* Reinitialize the CPU operating mode.  */
   cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
   return 0;
@@ -779,6 +592,15 @@ print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
     print_io_reg_desc (sd, desc, val, 0);
 }
 
+void
+print_io_word (SIM_DESC sd, const char *name, io_reg_desc *desc,
+              uint16 val, uint16 addr)
+{
+  sim_io_printf (sd, "  %-9.9s @ 0x%04x 0x%04x ", name, addr, val);
+  if (desc)
+    print_io_reg_desc (sd, desc, val, 0);
+}
+
 void
 cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val)
 {
@@ -1105,6 +927,60 @@ cpu_special (sim_cpu *cpu, enum M6811_Special special)
       }
       break;
 
+    case M6812_CALL:
+      {
+        uint8 page;
+        uint16 addr;
+
+        addr = cpu_fetch16 (cpu);
+        page = cpu_fetch8 (cpu);
+
+        cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
+        cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
+
+        cpu_set_page (cpu, page);
+        cpu_set_pc (cpu, addr);
+      }
+      break;
+
+    case M6812_CALL_INDIRECT:
+      {
+        uint8 code;
+        uint16 addr;
+        uint8 page;
+
+        code = memory_read8 (cpu, cpu_get_pc (cpu));
+        /* Indirect addressing call has the page specified in the
+           memory location pointed to by the address.  */
+        if ((code & 0xE3) == 0xE3)
+          {
+            addr = cpu_get_indexed_operand_addr (cpu, 0);
+            page = memory_read8 (cpu, addr + 2);
+            addr = memory_read16 (cpu, addr);
+          }
+        else
+          {
+            /* Otherwise, page is in the opcode.  */
+            addr = cpu_get_indexed_operand16 (cpu, 0);
+            page = cpu_fetch8 (cpu);
+          }
+        cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
+        cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
+        cpu_set_page (cpu, page);
+        cpu_set_pc (cpu, addr);
+      }
+      break;
+
+    case M6812_RTC:
+      {
+        uint8 page = cpu_m68hc12_pop_uint8 (cpu);
+        uint16 addr = cpu_m68hc12_pop_uint16 (cpu);
+
+        cpu_set_page (cpu, page);
+        cpu_set_pc (cpu, addr);
+      }
+      break;
+      
     case M6812_ETBL:
     default:
       sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
@@ -1146,7 +1022,7 @@ sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
   vsprintf (buf, message, args);
   va_end (args);
 
-  printf("%s\n", buf);
+  sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
   cpu_memory_exception (cpu, excep, addr, buf);
 }
 
@@ -1181,7 +1057,8 @@ cpu_info (SIM_DESC sd, sim_cpu *cpu)
 {
   sim_io_printf (sd, "CPU info:\n");
   sim_io_printf (sd, "  Absolute cycle: %s\n",
-                 cycle_to_string (cpu, cpu->cpu_absolute_cycle));
+                 cycle_to_string (cpu, cpu->cpu_absolute_cycle,
+                                  PRINT_TIME | PRINT_CYCLE));
   
   sim_io_printf (sd, "  Syscall emulation: %s\n",
                  cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");