This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [RFA] Provide cgen_disn and cgen_fields in disassemble_info


On 16-Jul-2001, Doug Evans wrote:

>Nit: there's a way to be typesafe here without requiring the inclusion
>of cgen.h.  Just declare the structs.

Yes, good point.  Here's the modified patch.

Nick

Index: include/dis-asm.h
===================================================================
diff -up include/dis-asm.h include/dis-asm.h
--- include/dis-asm.h	Mon Jul 16 14:24:47 2001
+++ include/dis-asm.h	Mon Jul 16 14:24:39 2001
@@ -47,6 +47,11 @@ enum dis_insn_type {
   dis_dref2			/* Two data references in instruction */
 };
 
+/* Forward declarations.  */
+
+struct cgen_insn;
+struct cgen_fields;
+
 /* This struct is passed into the instruction decoding routine, 
    and is passed back out into each callback.  The various fields are used
    for conveying information from your main routine into your callbacks,
@@ -164,6 +169,13 @@ typedef struct disassemble_info {
   bfd_vma target;		/* Target address of branch or dref, if known;
 				   zero if unknown.  */
   bfd_vma target2;		/* Second target address for dref2 */
+
+  /* Results from CGEN instruction decoders.  */
+
+  struct cgen_insn *cgen_insn;	/* If non-null, pointer to CGEN_INSN
+				   instruction descriptor.  */
+  struct cgen_fields *cgen_fields; /* If caller sets to non-null, receives
+				   CGEN_FIELDS operand descriptor.  */
 
   /* Command line options specific to the target disassembler.  */
   char * disassembler_options;
Index: opcodes/cgen-dis.in
===================================================================
diff -up opcodes/cgen-dis.in opcodes/cgen-dis.in
--- opcodes/cgen-dis.in	Mon Jul 16 14:24:49 2001
+++ opcodes/cgen-dis.in	Mon Jul 16 12:24:05 2001
@@ -47,10 +47,15 @@ static void print_keyword
 static void print_insn_normal
      PARAMS ((CGEN_CPU_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
 	      bfd_vma, int));
-static int print_insn PARAMS ((CGEN_CPU_DESC, bfd_vma,
-			       disassemble_info *, char *, int));
+static int decode_insn PARAMS ((CGEN_CPU_DESC, bfd_vma,
+				disassemble_info *, char *, int,
+				CGEN_FIELDS *));
+static int default_decode_insn
+     PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, CGEN_FIELDS *));
 static int default_print_insn
      PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
+static CGEN_CPU_DESC decode_init
+     PARAMS ((disassemble_info *));
 
 /* -- disassembler routines inserted here */
 
@@ -187,7 +192,7 @@ print_insn_normal (cd, dis_info, insn, f
     }
 }
 
-/* Subroutine of print_insn. Reads an insn into the given buffers and updates
+/* Subroutine of decode_insn. Reads an insn into the given buffers and updates
    the extract info.
    Returns 0 if all is well, non-zero otherwise.  */
 static int
@@ -215,19 +220,23 @@ read_insn (cd, pc, info, buf, buflen, ex
   return 0;
 }
 
-/* Utility to print an insn.
+/* Utility to decode an insn.
+
    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
    The result is the size of the insn in bytes or zero for an unknown insn
    or -1 if an error occurs fetching data (memory_error_func will have
-   been called).  */
+   been called).
+
+   FIELDS points to storage for the insn's extracted fields.  */
 
 static int
-print_insn (cd, pc, info, buf, buflen)
+decode_insn (cd, pc, info, buf, buflen, fields)
      CGEN_CPU_DESC cd;
      bfd_vma pc;
      disassemble_info *info;
      char *buf;
      int buflen;
+     CGEN_FIELDS *fields;
 {
   CGEN_INSN_INT insn_value;
   const CGEN_INSN_LIST *insn_list;
@@ -250,7 +259,6 @@ print_insn (cd, pc, info, buf, buflen)
   while (insn_list != NULL)
     {
       const CGEN_INSN *insn = insn_list->insn;
-      CGEN_FIELDS fields;
       int length;
       unsigned long insn_value_cropped;
 
@@ -296,18 +304,18 @@ print_insn (cd, pc, info, buf, buflen)
 	      if (rc != 0)
 		return rc;
 	      length = CGEN_EXTRACT_FN (cd, insn)
-		(cd, insn, &ex_info, full_insn_value, &fields, pc);
+		(cd, insn, &ex_info, full_insn_value, fields, pc);
 	    }
 	  else
 	    length = CGEN_EXTRACT_FN (cd, insn)
-	      (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
+	      (cd, insn, &ex_info, insn_value_cropped, fields, pc);
 
 	  /* length < 0 -> error */
 	  if (length < 0)
 	    return length;
 	  if (length > 0)
 	    {
-	      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
+	      info->cgen_insn = (void *) insn;
 	      /* length is in bits, result is in bytes */
 	      return length / 8;
 	    }
@@ -319,19 +327,20 @@ print_insn (cd, pc, info, buf, buflen)
   return 0;
 }
 
-/* Default value for CGEN_PRINT_INSN.
+/* Default value for CGEN_DECODE_INSN.
    The result is the size of the insn in bytes or zero for an unknown insn
    or -1 if an error occured fetching bytes.  */
 
-#ifndef CGEN_PRINT_INSN
-#define CGEN_PRINT_INSN default_print_insn
+#ifndef CGEN_DECODE_INSN
+#define CGEN_DECODE_INSN default_decode_insn
 #endif
 
 static int
-default_print_insn (cd, pc, info)
+default_decode_insn (cd, pc, info, fields)
      CGEN_CPU_DESC cd;
      bfd_vma pc;
      disassemble_info *info;
+     CGEN_FIELDS *fields;
 {
   char buf[CGEN_MAX_INSN_SIZE];
   int buflen;
@@ -354,23 +363,46 @@ default_print_insn (cd, pc, info)
       return -1;
     }
 
-  return print_insn (cd, pc, info, buf, buflen);
+  return decode_insn (cd, pc, info, buf, buflen, fields);
 }
 
-/* Main entry point.
-   Print one instruction from PC on INFO->STREAM.
-   Return the size of the instruction (in bytes).  */
+/* Default value for CGEN_PRINT_INSN.
+   The result is the size of the insn in bytes or zero for an unknown insn
+   or -1 if an error occured fetching bytes.  */
 
-int
-print_insn_@arch@ (pc, info)
+#ifndef CGEN_PRINT_INSN
+#define CGEN_PRINT_INSN default_print_insn
+#endif
+
+static int
+default_print_insn (cd, pc, info)
+     CGEN_CPU_DESC cd;
      bfd_vma pc;
      disassemble_info *info;
 {
+  CGEN_FIELDS fields;
+  int length;
+  const CGEN_INSN *insn;
+
+  length = CGEN_DECODE_INSN (cd, pc, info, &fields);
+  if (length > 0)
+    {
+      insn = info->cgen_insn;
+      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length * 8);
+    }
+  return length ;
+}
+
+/* Prepare to decode the instruction at PC.  */
+
+static CGEN_CPU_DESC
+decode_init (info)
+     disassemble_info *info;
+{
   static CGEN_CPU_DESC cd = 0;
   static int prev_isa;
   static int prev_mach;
   static int prev_endian;
-  int length;
   int isa,mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
@@ -430,6 +462,43 @@ print_insn_@arch@ (pc, info)
 	abort ();
       @arch@_cgen_init_dis (cd);
     }
+
+  return cd;
+}
+
+/* Main entry point for decoding.
+   Store in INFO information about the instruction at PC.
+   If successful, return the size of the instruction (in bytes).  Otherwise,
+   return 0 for an unknown insn and -1 if some other error occurred.  */
+
+int
+decode_insn_@arch@ (pc, info)
+     bfd_vma pc;
+     disassemble_info *info;
+{
+  CGEN_CPU_DESC cd = decode_init (info);
+
+  /* We try to have as much common code as possible.
+     But at this point some targets need to take over.  */
+  /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
+     but if not possible try to move this hook elsewhere rather than
+     have two hooks.  */
+  return CGEN_DECODE_INSN (cd, pc, info, info->cgen_fields);
+}
+
+/* Main entry point for printing.
+   Print one instruction from PC on INFO->STREAM.
+   Return the size of the instruction (in bytes).  */
+
+int
+print_insn_@arch@ (pc, info)
+     bfd_vma pc;
+     disassemble_info *info;
+{
+  CGEN_CPU_DESC cd;
+  int length;
+
+  cd = decode_init (info);
 
   /* We try to have as much common code as possible.
      But at this point some targets need to take over.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]