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.
-   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.
@@ -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.  */
 
-#include "sim-main.h"
+#include <errno.h>
+#include "dis-asm.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
@@ -50,6 +54,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #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
@@ -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;
-static CGEN_FIELDS insn_fields;
 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.  */
   {
-    const CGEN_OPERAND_INSTANCE *opinst = CGEN_INSN_OPERANDS (current_insn);
+    const CGEN_OPINST *opinst = CGEN_INSN_OPERANDS (current_insn);
 
     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.  */
-       /* 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;
-            CGEN_OPERAND_INSTANCE_TYPE (opinst) != CGEN_OPERAND_INSTANCE_END;
+            CGEN_OPINST_TYPE (opinst) != CGEN_OPINST_END;
             ++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]);
          }
       }
@@ -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,
-           const struct argbuf *abuf, PCADDR pc)
+           const struct argbuf *abuf, IADDR pc)
 {
   char disasm_buf[50];
 
@@ -170,7 +177,7 @@ trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode,
       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",
@@ -179,7 +186,7 @@ trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode,
 }
 
 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;
@@ -276,3 +283,132 @@ cgen_trace_printf (SIM_CPU *cpu, char *fmt, ...)
 
   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.0267 seconds and 4 git commands to generate.