Last change was actually made by Matthew Green.
[binutils-gdb.git] / opcodes / m32r-dis.c
index 48c591a6941cc7f299eef643a0d23b09514370d4..9b0397f3b7cb5f2147cb0c57b6ca40ced20217b5 100644 (file)
@@ -164,6 +164,15 @@ m32r_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
 
   switch (opindex)
     {
+    case M32R_OPERAND_ACC :
+      print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_acc, 0);
+      break;
+    case M32R_OPERAND_ACCD :
+      print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accd, 0);
+      break;
+    case M32R_OPERAND_ACCS :
+      print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accs, 0);
+      break;
     case M32R_OPERAND_DCR :
       print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r1, 0);
       break;
@@ -180,11 +189,14 @@ m32r_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
       print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0);
       break;
     case M32R_OPERAND_HASH :
-      print_hash (cd, info, fields->f_nil, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
+      print_hash (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
       break;
     case M32R_OPERAND_HI16 :
       print_normal (cd, info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
       break;
+    case M32R_OPERAND_IMM1 :
+      print_normal (cd, info, fields->f_imm1, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
+      break;
     case M32R_OPERAND_SCR :
       print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r2, 0);
       break;
@@ -251,12 +263,21 @@ m32r_cgen_init_dis (cd)
 
 static void
 print_normal (cd, dis_info, value, attrs, pc, length)
+#ifdef CGEN_PRINT_NORMAL
      CGEN_CPU_DESC cd;
+#else
+     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
+#endif
      PTR dis_info;
      long value;
      unsigned int attrs;
+#ifdef CGEN_PRINT_NORMAL
      bfd_vma pc;
      int length;
+#else
+     bfd_vma pc ATTRIBUTE_UNUSED;
+     int length ATTRIBUTE_UNUSED;
+#endif
 {
   disassemble_info *info = (disassemble_info *) dis_info;
 
@@ -277,12 +298,21 @@ print_normal (cd, dis_info, value, attrs, pc, length)
 
 static void
 print_address (cd, dis_info, value, attrs, pc, length)
+#ifdef CGEN_PRINT_NORMAL
      CGEN_CPU_DESC cd;
+#else
+     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
+#endif
      PTR dis_info;
      bfd_vma value;
      unsigned int attrs;
+#ifdef CGEN_PRINT_NORMAL
      bfd_vma pc;
      int length;
+#else
+     bfd_vma pc ATTRIBUTE_UNUSED;
+     int length ATTRIBUTE_UNUSED;
+#endif
 {
   disassemble_info *info = (disassemble_info *) dis_info;
 
@@ -307,11 +337,11 @@ print_address (cd, dis_info, value, attrs, pc, length)
 
 static void
 print_keyword (cd, dis_info, keyword_table, value, attrs)
-     CGEN_CPU_DESC cd;
+     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
      PTR dis_info;
      CGEN_KEYWORD *keyword_table;
      long value;
-     unsigned int attrs;
+     unsigned int attrs ATTRIBUTE_UNUSED;
 {
   disassemble_info *info = (disassemble_info *) dis_info;
   const CGEN_KEYWORD_ENTRY *ke;
@@ -362,43 +392,70 @@ print_insn_normal (cd, dis_info, insn, fields, pc, length)
     }
 }
 \f
-/* Utility to print 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).  */
-
+/* Subroutine of print_insn. Reads an insn into the given buffers and updates
+   the extract info.
+   Returns 0 if all is well, non-zero otherwise.  */
 static int
-print_insn (cd, pc, info, buf, buflen)
+read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
      CGEN_CPU_DESC cd;
      bfd_vma pc;
      disassemble_info *info;
      char *buf;
      int buflen;
+     CGEN_EXTRACT_INFO *ex_info;
+     unsigned long *insn_value;
 {
-  unsigned long insn_value;
-  const CGEN_INSN_LIST *insn_list;
-  CGEN_EXTRACT_INFO ex_info;
+  int status = (*info->read_memory_func) (pc, buf, buflen, info);
+  if (status != 0)
+    {
+      (*info->memory_error_func) (status, pc, info);
+      return -1;
+    }
 
-  ex_info.dis_info = info;
-  ex_info.valid = (1 << (cd->base_insn_bitsize / 8)) - 1;
-  ex_info.insn_bytes = buf;
+  ex_info->dis_info = info;
+  ex_info->valid = (1 << buflen) - 1;
+  ex_info->insn_bytes = buf;
 
   switch (buflen)
     {
     case 1:
-      insn_value = buf[0];
+      *insn_value = buf[0];
       break;
     case 2:
-      insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
+      *insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
       break;
     case 4:
-      insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
+      *insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
       break;
     default:
       abort ();
     }
 
+  return 0;
+}
+
+/* Utility to print 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).  */
+
+static int
+print_insn (cd, pc, info, buf, buflen)
+     CGEN_CPU_DESC cd;
+     bfd_vma pc;
+     disassemble_info *info;
+     char *buf;
+     int buflen;
+{
+  unsigned long insn_value;
+  const CGEN_INSN_LIST *insn_list;
+  CGEN_EXTRACT_INFO ex_info;
+
+  int rc = read_insn (cd, pc, info, buf, buflen, & ex_info, & insn_value);
+  if (rc != 0)
+    return rc;
+
   /* The instructions are stored in hash lists.
      Pick the first one and keep trying until we find the right one.  */
 
@@ -409,10 +466,14 @@ print_insn (cd, pc, info, buf, buflen)
       CGEN_FIELDS fields;
       int length;
 
-#if 0 /* not needed as insn shouldn't be in hash lists if not supported */
+#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
+      /* not needed as insn shouldn't be in hash lists if not supported */
       /* Supported by this cpu?  */
       if (! m32r_cgen_insn_supported (cd, insn))
-       continue;
+        {
+          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
+         continue;
+        }
 #endif
 
       /* Basic bit mask must be correct.  */
@@ -425,6 +486,22 @@ print_insn (cd, pc, info, buf, buflen)
             machine insn and extracts the fields.  The second pass prints
             them.  */
 
+#if CGEN_INT_INSN_P
+         /* Make sure the entire insn is loaded into insn_value.  */
+         if (CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize)
+           {
+             unsigned long full_insn_value;
+             int rc = read_insn (cd, pc, info, buf,
+                                 CGEN_INSN_BITSIZE (insn) / 8,
+                                 & ex_info, & full_insn_value);
+             if (rc != 0)
+               return rc;
+             length = CGEN_EXTRACT_FN (cd, insn)
+               (cd, insn, &ex_info, full_insn_value, &fields, pc);
+           }
+         else
+#endif
+
          length = CGEN_EXTRACT_FN (cd, insn)
            (cd, insn, &ex_info, insn_value, &fields, pc);
          /* length < 0 -> error */
@@ -483,7 +560,9 @@ print_insn_m32r (pc, info)
      disassemble_info *info;
 {
   static CGEN_CPU_DESC cd = 0;
-  static prev_isa,prev_mach,prev_endian;
+  static int prev_isa;
+  static int prev_mach;
+  static int prev_endian;
   int length;
   int isa,mach;
   int endian = (info->endian == BFD_ENDIAN_BIG