import gdb-19990422 snapshot
[deliverable/binutils-gdb.git] / sim / common / cgen-trace.c
index 82a20a5fd62803cd87cfebf6124c2c8108fddb30..db852d5306c60c5b2339f7a2c02456a96b1766d9 100644 (file)
@@ -1,5 +1,5 @@
 /* Tracing support for CGEN-based simulators.
 /* Tracing support for CGEN-based simulators.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    Contributed by Cygnus Support.
 
 This file is part of GDB, the GNU debugger.
    Contributed by Cygnus Support.
 
 This file is part of GDB, the GNU debugger.
@@ -18,9 +18,13 @@ 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.  */
 
 with this program; if not, write to the Free Software Foundation, Inc.,
 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-#include "sim-main.h"
+#include <errno.h>
+#include "dis-asm.h"
 #include "bfd.h"
 #include "bfd.h"
-#include "cpu-opc.h"
+#include "sim-main.h"
+
+#undef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
 
 #ifndef SIZE_INSTRUCTION
 #define SIZE_INSTRUCTION 16
 
 #ifndef SIZE_INSTRUCTION
 #define SIZE_INSTRUCTION 16
@@ -50,6 +54,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define SIZE_TRACE_BUF 256
 #endif
 
 #define SIZE_TRACE_BUF 256
 #endif
 
+static void
+disassemble_insn (SIM_CPU *, const CGEN_INSN *,
+                 const struct argbuf *, IADDR, char *);
+
 /* Text is queued in TRACE_BUF because we want to output the insn's cycle
    count first but that isn't known until after the insn has executed.
    This also handles the queueing of trace results, TRACE_RESULT may be
 /* Text is queued in TRACE_BUF because we want to output the insn's cycle
    count first but that isn't known until after the insn has executed.
    This also handles the queueing of trace results, TRACE_RESULT may be
@@ -68,7 +76,6 @@ static int printed_result_p;
    Set by trace_insn, used by trace_insn_fini.
    ??? Move to SIM_CPU to support heterogeneous multi-cpu case.  */
 static const struct cgen_insn *current_insn;
    Set by trace_insn, used by trace_insn_fini.
    ??? Move to SIM_CPU to support heterogeneous multi-cpu case.  */
 static const struct cgen_insn *current_insn;
-static CGEN_FIELDS insn_fields;
 static const struct argbuf *current_abuf;
 
 void
 static const struct argbuf *current_abuf;
 
 void
@@ -121,7 +128,7 @@ trace_insn_fini (SIM_CPU *cpu, const struct argbuf *abuf, int last_p)
 #if 0
   /* Print insn results.  */
   {
 #if 0
   /* Print insn results.  */
   {
-    const CGEN_OPERAND_INSTANCE *opinst = CGEN_INSN_OPERANDS (current_insn);
+    const CGEN_OPINST *opinst = CGEN_INSN_OPERANDS (current_insn);
 
     if (opinst)
       {
 
     if (opinst)
       {
@@ -129,16 +136,16 @@ trace_insn_fini (SIM_CPU *cpu, const struct argbuf *abuf, int last_p)
        int indices[MAX_OPERAND_INSTANCES];
 
        /* Fetch the operands used by the insn.  */
        int indices[MAX_OPERAND_INSTANCES];
 
        /* Fetch the operands used by the insn.  */
-       /* FIXME: Add fn ptr to CGEN_OPCODE_DESC.  */
-       CGEN_SYM (get_insn_operands) (STATE_OPCODE_TABLE (sd), current_insn,
+       /* FIXME: Add fn ptr to CGEN_CPU_DESC.  */
+       CGEN_SYM (get_insn_operands) (CPU_CPU_DESC (cpu), current_insn,
                                      0, CGEN_FIELDS_BITSIZE (&insn_fields),
                                      indices);
 
        for (i = 0;
                                      0, CGEN_FIELDS_BITSIZE (&insn_fields),
                                      indices);
 
        for (i = 0;
-            CGEN_OPERAND_INSTANCE_TYPE (opinst) != CGEN_OPERAND_INSTANCE_END;
+            CGEN_OPINST_TYPE (opinst) != CGEN_OPINST_END;
             ++i, ++opinst)
          {
             ++i, ++opinst)
          {
-           if (CGEN_OPERAND_INSTANCE_TYPE (opinst) == CGEN_OPERAND_INSTANCE_OUTPUT)
+           if (CGEN_OPINST_TYPE (opinst) == CGEN_OPINST_OUTPUT)
              trace_result (cpu, current_insn, opinst, indices[i]);
          }
       }
              trace_result (cpu, current_insn, opinst, indices[i]);
          }
       }
@@ -155,7 +162,7 @@ trace_insn_fini (SIM_CPU *cpu, const struct argbuf *abuf, int last_p)
 
 void
 trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode,
 
 void
 trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode,
-           const struct argbuf *abuf, PCADDR pc)
+           const struct argbuf *abuf, IADDR pc)
 {
   char disasm_buf[50];
 
 {
   char disasm_buf[50];
 
@@ -170,7 +177,7 @@ trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode,
       return;
     }
 
       return;
     }
 
-  sim_disassemble_insn (cpu, opcode, abuf, pc, disasm_buf, &insn_fields);
+  CPU_DISASSEMBLER (cpu) (cpu, opcode, abuf, pc, disasm_buf);
   trace_prefix (CPU_STATE (cpu), cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
                NULL, 0,
                "%s%-*s",
   trace_prefix (CPU_STATE (cpu), cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
                NULL, 0,
                "%s%-*s",
@@ -179,7 +186,7 @@ trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode,
 }
 
 void
 }
 
 void
-trace_extract (SIM_CPU *cpu, PCADDR pc, char *name, ...)
+trace_extract (SIM_CPU *cpu, IADDR pc, char *name, ...)
 {
   va_list args;
   int printed_one_p = 0;
 {
   va_list args;
   int printed_one_p = 0;
@@ -276,3 +283,132 @@ cgen_trace_printf (SIM_CPU *cpu, char *fmt, ...)
 
   va_end (args);
 }
 
   va_end (args);
 }
+\f
+/* Disassembly support.  */
+
+/* sprintf to a "stream" */
+
+int
+sim_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;
+}
+
+/* Memory read support for an opcodes disassembler.  */
+
+int
+sim_disasm_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
+                       struct disassemble_info *info)
+{
+  SIM_CPU *cpu = (SIM_CPU *) info->application_data;
+  SIM_DESC sd = CPU_STATE (cpu);
+  int length_read;
+
+  length_read = sim_core_read_buffer (sd, cpu, read_map, myaddr, memaddr,
+                                     length);
+  if (length_read != length)
+    return EIO;
+  return 0;
+}
+
+/* Memory error support for an opcodes disassembler.  */
+
+void
+sim_disasm_perror_memory (int status, bfd_vma memaddr,
+                         struct disassemble_info *info)
+{
+  if (status != EIO)
+    /* Can't happen.  */
+    info->fprintf_func (info->stream, "Unknown error %d.", status);
+  else
+    /* Actually, address between memaddr and memaddr + len was
+       out of bounds.  */
+    info->fprintf_func (info->stream,
+                       "Address 0x%x is out of bounds.",
+                       (int) memaddr);
+}
+
+/* Disassemble using the CGEN opcode table.
+   ??? 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.  */
+
+void
+sim_cgen_disassemble_insn (SIM_CPU *cpu, const CGEN_INSN *insn,
+                          const ARGBUF *abuf, IADDR pc, char *buf)
+{
+  unsigned int length;
+  unsigned long insn_value;
+  struct disassemble_info disasm_info;
+  SFILE sfile;
+  union {
+    unsigned8 bytes[CGEN_MAX_INSN_SIZE];
+    unsigned16 shorts[8];
+    unsigned32 words[4];
+  } insn_buf;
+  SIM_DESC sd = CPU_STATE (cpu);
+  CGEN_CPU_DESC cd = CPU_CPU_DESC (cpu);
+  CGEN_EXTRACT_INFO ex_info;
+  CGEN_FIELDS *fields = alloca (CGEN_CPU_SIZEOF_FIELDS (cd));
+  int insn_bit_length = CGEN_INSN_BITSIZE (insn);
+  int insn_length = insn_bit_length / 8;
+
+  sfile.buffer = sfile.current = buf;
+  INIT_DISASSEMBLE_INFO (disasm_info, (FILE *) &sfile,
+                        (fprintf_ftype) sim_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);
+
+  length = sim_core_read_buffer (sd, cpu, read_map, &insn_buf, pc,
+                                insn_length);
+
+  switch (min (cd->base_insn_bitsize, insn_bit_length))
+    {
+    case 0 : return; /* fake insn, typically "compile" (aka "invalid") */
+    case 8 : insn_value = insn_buf.bytes[0]; break;
+    case 16 : insn_value = T2H_2 (insn_buf.shorts[0]); break;
+    case 32 : insn_value = T2H_4 (insn_buf.words[0]); break;
+    default: abort ();
+    }
+
+  disasm_info.buffer_vma = pc;
+  disasm_info.buffer = insn_buf.bytes;
+  disasm_info.buffer_length = length;
+
+  ex_info.dis_info = (PTR) &disasm_info;
+  ex_info.valid = (1 << length) - 1;
+  ex_info.insn_bytes = insn_buf.bytes;
+
+  length = (*CGEN_EXTRACT_FN (cd, insn)) (cd, insn, &ex_info, insn_value, fields, pc);
+  /* 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 == insn_bit_length)
+    {
+      (*CGEN_PRINT_FN (cd, insn)) (cd, &disasm_info, insn, fields, pc, length);
+    }
+  else
+    {
+      /* This shouldn't happen, but aborting is too drastic.  */
+      strcpy (buf, "***unknown***");
+    }
+}
This page took 0.028256 seconds and 4 git commands to generate.