daily update
[external/binutils.git] / sim / common / cgen-utils.c
index 6aa9107..2dc18fc 100644 (file)
@@ -1,43 +1,43 @@
 /* Support code for various pieces of CGEN simulators.
-   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2007, 2008
+   Free Software Foundation, Inc.
    Contributed by Cygnus Support.
 
 This file is part of GDB, the GNU debugger.
 
 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 2, or (at your option)
-any later version.
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
 
 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 program; if not, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
+#include "bfd.h"
 #include "sim-main.h"
-#include <signal.h>
 #include "dis-asm.h"
-#include "cpu-opc.h"
-#include "decode.h"
 
 #define MEMOPS_DEFINE_INLINE
-#include "mem-ops.h"
+#include "cgen-mem.h"
 
 #define SEMOPS_DEFINE_INLINE
-#include "sem-ops.h"
+#include "cgen-ops.h"
+
+#undef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
 
 const char *mode_names[] = {
-  "VM",
+  "VOID",
   "BI",
   "QI",
   "HI",
   "SI",
   "DI",
-  "UBI",
   "UQI",
   "UHI",
   "USI",
@@ -46,220 +46,108 @@ const char *mode_names[] = {
   "DF",
   "XF",
   "TF",
+  0, /* MODE_TARGET_MAX */
+  "INT",
+  "UINT",
+  "PTR"
 };
 
-/* Initialize cgen things.
-   This is called after sim_post_argv_init.  */
+/* Opcode table for virtual insns used by the simulator.  */
 
-void
-cgen_init (SIM_DESC sd)
-{
-  int i, c;
-  int run_fast_p = 1;
+#define V CGEN_ATTR_MASK (CGEN_INSN_VIRTUAL)
 
-  /* If no profiling or tracing has been enabled, run in fast mode.  */
-  for (c = 0; c < MAX_NR_PROCESSORS; ++c)
-    {
-      sim_cpu *cpu = STATE_CPU (sd, c);
-
-      for (i = 0; i < MAX_PROFILE_VALUES; ++i)
-       if (CPU_PROFILE_FLAGS (cpu) [i])
-         {
-           run_fast_p = 0;
-           break;
-         }
-      for (i = 0; i < MAX_TRACE_VALUES; ++i)
-       if (CPU_TRACE_FLAGS (cpu) [i])
-         {
-           run_fast_p = 0;
-           break;
-         }
-      if (! run_fast_p)
-       break;
-    }
-  STATE_RUN_FAST_P (sd) = run_fast_p;
-}
-\f
-void
-engine_halt (cpu, reason, sigrc)
-     sim_cpu *cpu;
-     enum exec_state reason;
-     int sigrc;
+static const CGEN_IBASE virtual_insn_entries[] =
 {
-  CPU_EXEC_STATE (cpu) = reason;
-  CPU_HALT_SIGRC (cpu) = sigrc;
+  {
+    VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, { V, { 0 } }
+  },
+  {
+    VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, { V, { 0 } }
+  },
+  {
+    VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, { V, { 0 } }
+  },
+  {
+    VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, { V, { 0 } }
+  },
+  {
+    VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, { V, { 0 } }
+  },
+  {
+    VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, { V, { 0 } }
+  }
+};
 
-  longjmp (STATE_HALT_JMP_BUF (CPU_STATE (cpu)), 1);
-}
+#undef V
 
-void
-engine_signal (cpu, sig)
-     sim_cpu *cpu;
-     enum sim_signal_type sig;
+const CGEN_INSN cgen_virtual_insn_table[] =
 {
-  engine_halt (cpu, EXEC_STATE_STOPPED, sig);
-}
-
-/* Convert SIM_SIGFOO to SIGFOO.  */
+  { & virtual_insn_entries[0] },
+  { & virtual_insn_entries[1] },
+  { & virtual_insn_entries[2] },
+  { & virtual_insn_entries[3] },
+  { & virtual_insn_entries[4] },
+  { & virtual_insn_entries[5] }
+};
 
-int
-sim_signal_to_host (sig)
-     int sig;
-{
-  switch (sig)
-    {
-    case SIM_SIGILL :
-#ifdef SIGILL
-      return SIGILL;
-#endif
-      break;
-
-    case SIM_SIGTRAP :
-#ifdef SIGTRAP
-      return SIGTRAP;
-#else
-#ifdef _MSC_VER
-      /* Wingdb uses this value.  */
-      return 5;
-#endif
-#endif
-      break;
-
-    case SIM_SIGALIGN :
-    case SIM_SIGACCESS :
-#ifdef SIGSEGV
-      return SIGSEGV;
-#endif
-      break;
-
-    case SIM_SIGXCPU :
-#ifdef SIGXCPU
-      return SIGXCPU;
-#endif
-      break;
-    }
-  return 1;
-}
-\f
-/* FIXME: Add "no return" attribute to illegal insn handlers.
-   They all call longjmp.  */
-/* FIXME: May wish to call a target supplied routine which can then call
-   sim_halt if it wants: to allow target to gain control for moment.  */
+/* Initialize cgen things.
+   This is called after sim_post_argv_init.  */
 
 void
-ex_illegal (SIM_CPU *cpu, PCADDR pc, insn_t insn, ARGBUF *abuf)
+cgen_init (SIM_DESC sd)
 {
-  abuf->length = CGEN_BASE_INSN_SIZE;
-  abuf->addr = pc;
-  /* Leave signalling to semantic fn.  */
-}
+  int i, c;
 
-void
-exc_illegal (SIM_CPU *cpu, PCADDR pc, insn_t insn, ARGBUF *abuf)
-{
-  abuf->length = CGEN_BASE_INSN_SIZE;
-  abuf->addr = pc;
-  /* Leave signalling to semantic fn.  */
+  /* If no profiling or tracing has been enabled, run in fast mode.  */
+  {
+    int run_fast_p = 1;
+
+    for (c = 0; c < MAX_NR_PROCESSORS; ++c)
+      {
+       SIM_CPU *cpu = STATE_CPU (sd, c);
+
+       for (i = 0; i < MAX_PROFILE_VALUES; ++i)
+         if (CPU_PROFILE_FLAGS (cpu) [i])
+           {
+             run_fast_p = 0;
+             break;
+           }
+       for (i = 0; i < MAX_TRACE_VALUES; ++i)
+         if (CPU_TRACE_FLAGS (cpu) [i])
+           {
+             run_fast_p = 0;
+             break;
+           }
+       if (! run_fast_p)
+         break;
+      }
+    STATE_RUN_FAST_P (sd) = run_fast_p;
+  }
 }
 
-PCADDR
-sem_illegal (current_cpu, sem_arg)
-     SIM_CPU *current_cpu;
-     struct argbuf *sem_arg;
-{
-  engine_halt (current_cpu, EXEC_STATE_SIGNALLED, SIM_SIGILL);
-  return 0;
-}
+/* Return the name of insn number I.  */
 
-PCADDR
-semc_illegal (current_cpu, sem_arg)
-     SIM_CPU *current_cpu;
-     struct scache *sem_arg;
-{
-  engine_halt (current_cpu, EXEC_STATE_SIGNALLED, SIM_SIGILL);
-  return 0;
-}
-\f
-/* Disassembly support.
-   ??? While executing an instruction, the insn has been decoded and all its
-   fields have been extracted.  It is certainly possible to do the disassembly
-   with that data.  This seems simpler, but maybe in the future the already
-   extracted fields will be used.  */
-
-/* Pseudo FILE object for strings.  */
-typedef struct {
-  char *buffer;
-  char *current;
-} SFILE;
-
-/* sprintf to a "stream" */
-
-static int
-disasm_sprintf VPARAMS ((SFILE *f, const char *format, ...))
+const char *
+cgen_insn_name (SIM_CPU *cpu, int i)
 {
-#ifndef __STDC__
-  SFILE *f;
-  const char *format;
-#endif
-  int n;
-  va_list args;
-
-  VA_START (args, format);
-#ifndef __STDC__
-  f = va_arg (args, SFILE *);
-  format = va_arg (args, char *);
-#endif
-  vsprintf (f->current, format, args);
-  f->current += n = strlen (f->current);
-  va_end (args);
-  return n;
+  return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i)));
 }
 
-void
-sim_disassemble_insn (SIM_CPU *cpu, const struct cgen_insn *insn,
-                     const struct argbuf *abuf, PCADDR pc, char *buf)
-{
-  int length;
-  unsigned long insn_value;
-  struct disassemble_info disasm_info;
-  struct cgen_fields fields;
-  SFILE sfile;
-  char insn_buf[20];
-  SIM_DESC sd = CPU_STATE (cpu);
-
-  sfile.buffer = sfile.current = buf;
-  INIT_DISASSEMBLE_INFO (disasm_info, (FILE *) &sfile,
-                        (fprintf_ftype) disasm_sprintf);
-  disasm_info.endian =
-    (bfd_big_endian (STATE_PROG_BFD (sd)) ? BFD_ENDIAN_BIG
-     : bfd_little_endian (STATE_PROG_BFD (sd)) ? BFD_ENDIAN_LITTLE
-     : BFD_ENDIAN_UNKNOWN);
+/* Return the maximum number of extra bytes required for a SIM_CPU struct.  */
 
-  switch (abuf->length)
-    {
-    case 1 :
-      insn_value = sim_core_read_1 (CPU_STATE (cpu), sim_core_read_map, pc, NULL, NULL_CIA);
-      break;
-    case 2 :
-      insn_value = sim_core_read_2 (CPU_STATE (cpu), sim_core_read_map, pc, NULL, NULL_CIA);
-      break;
-    case 4 :
-      insn_value = sim_core_read_4 (CPU_STATE (cpu), sim_core_read_map, pc, NULL, NULL_CIA);
-      break;
-    default:
-      abort ();
-    }
+int
+cgen_cpu_max_extra_bytes (void)
+{
+  int i;
+  int extra = 0;
 
-  length = (*CGEN_EXTRACT_FN (insn)) (insn, NULL, insn_value, &fields);
-  if (length != abuf->length)
-    {
-      (*CGEN_PRINT_FN (insn)) (&disasm_info, insn, &fields, pc, length);
-    }
-  else
+  for (i = 0; sim_machs[i] != 0; ++i)
     {
-      /* This shouldn't happen, but aborting is too drastic.  */
-      strcpy (buf, "***unknown***");
+      int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (sim_machs[i]));
+      if (size > extra)
+       extra = size;
     }
+  return extra;
 }
 \f
 #ifdef DI_FN_SUPPORT
@@ -432,3 +320,119 @@ CONVDISI (val)
 }
 
 #endif /* DI_FN_SUPPORT */
+\f
+QI
+RORQI (val, shift)
+     QI  val;
+     int shift;
+{
+  if (shift != 0)
+    {
+      int remain = 8 - shift;
+      int mask = (1 << shift) - 1;
+      QI result = (val & mask) << remain;
+      mask = (1 << remain) - 1;
+      result |= (val >> shift) & mask;
+      return result;
+    }
+  return val;
+}
+
+QI
+ROLQI (val, shift)
+     QI  val;
+     int shift;
+{
+  if (shift != 0)
+    {
+      int remain = 8 - shift;
+      int mask = (1 << remain) - 1;
+      QI result = (val & mask) << shift;
+      mask = (1 << shift) - 1;
+      result |= (val >> remain) & mask;
+      return result;
+    }
+  return val;
+}
+
+HI
+RORHI (val, shift)
+     HI  val;
+     int shift;
+{
+  if (shift != 0)
+    {
+      int remain = 16 - shift;
+      int mask = (1 << shift) - 1;
+      HI result = (val & mask) << remain;
+      mask = (1 << remain) - 1;
+      result |= (val >> shift) & mask;
+      return result;
+    }
+  return val;
+}
+
+HI
+ROLHI (val, shift)
+     HI  val;
+     int shift;
+{
+  if (shift != 0)
+    {
+      int remain = 16 - shift;
+      int mask = (1 << remain) - 1;
+      HI result = (val & mask) << shift;
+      mask = (1 << shift) - 1;
+      result |= (val >> remain) & mask;
+      return result;
+    }
+  return val;
+}
+
+SI
+RORSI (val, shift)
+     SI  val;
+     int shift;
+{
+  if (shift != 0)
+    {
+      int remain = 32 - shift;
+      int mask = (1 << shift) - 1;
+      SI result = (val & mask) << remain;
+      mask = (1 << remain) - 1;
+      result |= (val >> shift) & mask;
+      return result;
+    }
+  return val;
+}
+
+SI
+ROLSI (val, shift)
+     SI  val;
+     int shift;
+{
+  if (shift != 0)
+    {
+      int remain = 32 - shift;
+      int mask = (1 << remain) - 1;
+      SI result = (val & mask) << shift;
+      mask = (1 << shift) - 1;
+      result |= (val >> remain) & mask;
+      return result;
+    }
+
+  return val;
+}
+
+/* Emit an error message from CGEN RTL.  */
+
+void
+cgen_rtx_error (SIM_CPU *cpu, const char * msg)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+
+  sim_io_printf (sd, msg);
+  sim_io_printf (sd, "\n");
+
+  sim_engine_halt (sd, cpu, NULL, CIA_GET (cpu), sim_stopped, SIM_SIGTRAP);
+}