daily update
[external/binutils.git] / sim / common / cgen-utils.c
index c7919d5..2dc18fc 100644 (file)
@@ -1,26 +1,26 @@
 /* Support code for various pieces of CGEN simulators.
-   Copyright (C) 1996, 1997, 1998 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 "dis-asm.h"
-#include "cpu-opc.h"
 
 #define MEMOPS_DEFINE_INLINE
 #include "cgen-mem.h"
@@ -28,14 +28,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define SEMOPS_DEFINE_INLINE
 #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",
@@ -44,6 +46,48 @@ const char *mode_names[] = {
   "DF",
   "XF",
   "TF",
+  0, /* MODE_TARGET_MAX */
+  "INT",
+  "UINT",
+  "PTR"
+};
+
+/* Opcode table for virtual insns used by the simulator.  */
+
+#define V CGEN_ATTR_MASK (CGEN_INSN_VIRTUAL)
+
+static const CGEN_IBASE virtual_insn_entries[] =
+{
+  {
+    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 } }
+  }
+};
+
+#undef V
+
+const CGEN_INSN cgen_virtual_insn_table[] =
+{
+  { & virtual_insn_entries[0] },
+  { & virtual_insn_entries[1] },
+  { & virtual_insn_entries[2] },
+  { & virtual_insn_entries[3] },
+  { & virtual_insn_entries[4] },
+  { & virtual_insn_entries[5] }
 };
 
 /* Initialize cgen things.
@@ -53,115 +97,57 @@ void
 cgen_init (SIM_DESC sd)
 {
   int i, c;
-  int run_fast_p = 1;
 
   /* 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
-/* 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, ...))
-{
-#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;
+  {
+    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;
+  }
 }
 
-void
-sim_disassemble_insn (SIM_CPU *cpu, const struct cgen_insn *insn,
-                     const struct argbuf *abuf, PCADDR pc, char *buf)
-{
-  unsigned int length;
-  unsigned long insn_value;
-  struct disassemble_info disasm_info;
-  struct cgen_fields fields;
-  SFILE sfile;
-  union {
-    unsigned8 bytes[16];
-    unsigned16 shorts[8];
-    unsigned32 words[4];
-  } insn_buf;
-  SIM_DESC sd = CPU_STATE (cpu);
+/* Return the name of insn number I.  */
 
-  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);
+const char *
+cgen_insn_name (SIM_CPU *cpu, int i)
+{
+  return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i)));
+}
 
-  length = sim_core_read_buffer (sd, cpu, sim_core_read_map, &insn_buf, pc,
-                                CGEN_INSN_BITSIZE (insn) / 8);
+/* Return the maximum number of extra bytes required for a SIM_CPU struct.  */
 
-  switch (length)
-    {
-    case 1 : insn_value = insn_buf.bytes[0]; break;
-    case 2 : insn_value = T2H_2 (insn_buf.shorts[0]); break;
-    case 4 : insn_value = T2H_4 (insn_buf.words[0]); 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);
-  /* Result of extract fn is in bits.  */
-  /* ??? This assumes that each instruction has a fixed length (and thus
-     for insns with multiple versions of variable lengths they would each
-     have their own table entry).  */
-  if (length == CGEN_INSN_BITSIZE (insn))
+  for (i = 0; sim_machs[i] != 0; ++i)
     {
-      (*CGEN_PRINT_FN (insn)) (&disasm_info, insn, &fields, pc, length);
-    }
-  else
-    {
-      /* 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
@@ -334,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);
+}