Fix problem with going to automake 2.14
[deliverable/binutils-gdb.git] / opcodes / d30v-dis.c
index 91262adce805776316a4ad832c77406743d47a8c..9358b7532358fd50f845657414934522bb6468f5 100644 (file)
@@ -1,5 +1,5 @@
 /* Disassemble D30V instructions.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
 
 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
@@ -18,12 +18,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include <stdio.h>
 #include "opcode/d30v.h" 
 #include "dis-asm.h"
+#include "opintl.h"
 
 #define PC_MASK 0xFFFFFFFF
 
 static int lookup_opcode PARAMS (( struct d30v_insn *insn, long num, int is_long ));
 static void print_insn PARAMS (( struct disassemble_info *info, bfd_vma memaddr, long long num, 
-                                struct d30v_insn *insn, int is_long ));
+                                struct d30v_insn *insn, int is_long, int show_ext ));
 static int extract_value PARAMS (( long long num, struct d30v_operand *oper, int is_long ));
 
 int 
@@ -31,7 +32,7 @@ print_insn_d30v (memaddr, info)
      bfd_vma memaddr;
      struct disassemble_info *info;
 {
-  int status, i;
+  int status, result;
   bfd_byte buffer[12];
   unsigned long in1,in2;
   struct d30v_insn insn;
@@ -39,36 +40,48 @@ print_insn_d30v (memaddr, info)
 
   insn.form = (struct d30v_format *)NULL;
 
-  status = (*info->read_memory_func) (memaddr, buffer, 8, info);
+  info->bytes_per_line = 8;
+  info->bytes_per_chunk = 4;
+  info->display_endian = BFD_ENDIAN_BIG;
+
+  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
   if (status != 0)
     {
       (*info->memory_error_func) (status, memaddr, info);
       return -1;
     }
-  info->bytes_per_line = 8;
-  info->bytes_per_chunk = 4;
-  info->display_endian = BFD_ENDIAN_BIG;
   in1 = bfd_getb32 (buffer);
-  in2 = bfd_getb32 (buffer+4);
+
+  status = (*info->read_memory_func) (memaddr+4, buffer, 4, info);
+  if (status != 0)
+    {
+      info->bytes_per_line = 8;
+      if (!(result = lookup_opcode(&insn, in1, 0)))
+       (*info->fprintf_func) (info->stream, ".long\t0x%x",in1);
+      else
+       print_insn(info, memaddr, (long long) in1, &insn, 0, result);
+      return 4;      
+    }
+  in2 = bfd_getb32 (buffer);
   
   if (in1 & in2 & FM01)
     {
       /* LONG instruction */
-      if (!lookup_opcode(&insn, in1, 1))
+      if (!(result = lookup_opcode(&insn, in1, 1)))
        {
          (*info->fprintf_func) (info->stream, ".long\t0x%x,0x%x",in1,in2);
          return 8;
        }
       num = (long long)in1 << 32 | in2;
-      print_insn(info, memaddr, num, &insn, 1);
+      print_insn(info, memaddr, num, &insn, 1, result);
     }
   else
     {
       num = in1;
-      if (!lookup_opcode(&insn, in1, 0))
+      if (!(result = lookup_opcode(&insn, in1, 0)))
        (*info->fprintf_func) (info->stream, ".long\t0x%x",in1);
       else
-       print_insn(info, memaddr, num, &insn, 0);
+       print_insn(info, memaddr, num, &insn, 0, result);
       
       switch ( ((in1>>31)<<1) | (in2>>31) )
        {
@@ -86,16 +99,19 @@ print_insn_d30v (memaddr, info)
       
       insn.form = (struct d30v_format *)NULL;
       num = in2;
-      if (!lookup_opcode(&insn, in2, 0))
+      if (!(result = lookup_opcode(&insn, in2, 0)))
        (*info->fprintf_func) (info->stream, ".long\t0x%x",in2);
       else
-       print_insn(info, memaddr, num, &insn, 0);
+       print_insn(info, memaddr, num, &insn, 0, result);
 
     }
   return 8;
 }
 
 
+/* returns 0 if lookup fails */
+/* 1 if found and only one form */
+/* 2 if found and there are short and long forms */
 static int
 lookup_opcode (insn, num, is_long)
      struct d30v_insn *insn;
@@ -122,7 +138,8 @@ lookup_opcode (insn, num, is_long)
   while (op->op1 == op1 && op->op2 == op2)
     {
       /* scan through all the formats for the opcode  */
-      while (index = op->format[i++])
+      index = op->format[i++];
+      do 
        {
          f = (struct d30v_format *)&d30v_format_table[index];
          while (f->form == index)
@@ -136,7 +153,7 @@ lookup_opcode (insn, num, is_long)
            }
          if (insn->form)
            break;
-       }
+       } while ((index = op->format[i++]) != 0);
       if (insn->form)
        break;
       op++;
@@ -147,19 +164,22 @@ lookup_opcode (insn, num, is_long)
 
   insn->op = op;
   insn->ecc = (num >> 28) & 0x7;
-  return 1;
+  if (op->format[1])
+    return 2;
+  else
+    return 1;
 }
 
 
 static void 
-print_insn ( info, memaddr, num, insn, is_long )
+print_insn ( info, memaddr, num, insn, is_long, show_ext )
      struct disassemble_info *info;
      bfd_vma memaddr;
      long long num;
      struct d30v_insn *insn;
      int is_long;
+     int show_ext;
 {
-  char buffer[128];
   int val, opnum, need_comma=0;
   struct d30v_operand *oper;
   int i, match, opind=0, need_paren=0, found_control=0;
@@ -174,14 +194,27 @@ print_insn ( info, memaddr, num, insn, is_long )
       (*info->fprintf_func) (info->stream, "%s",d30v_cc_names[val]);
     }
 
+  /* add in ".s" or ".l" */
+  if (show_ext == 2)
+    {
+      if (is_long)
+       (*info->fprintf_func) (info->stream, ".l");
+      else
+       (*info->fprintf_func) (info->stream, ".s");
+    }
+
   if (insn->ecc)
     (*info->fprintf_func) (info->stream, "/%s",d30v_ecc_names[insn->ecc]);
 
   (*info->fprintf_func) (info->stream, "\t");
 
-  while (opnum = insn->form->operands[opind++])
+  while ((opnum = insn->form->operands[opind++]) != 0)
     {
+      int bits;
       oper = (struct d30v_operand *)&d30v_operand_table[opnum];
+      bits = oper->bits;
+      if (oper->flags & OPERAND_SHIFT)
+       bits += 3;
 
       if (need_comma && oper->flags != OPERAND_PLUS && oper->flags != OPERAND_MINUS)
        {
@@ -255,9 +288,11 @@ print_insn ( info, memaddr, num, insn, is_long )
              if (val == pre_defined_registers[i].value)
                {
                  if (pre_defined_registers[i].pname)
-                   (*info->fprintf_func) (info->stream, "%s",pre_defined_registers[i].pname);
+                   (*info->fprintf_func)
+                     (info->stream, "%s",pre_defined_registers[i].pname);
                  else
-                   (*info->fprintf_func) (info->stream, "%s",pre_defined_registers[i].name);
+                   (*info->fprintf_func)
+                     (info->stream, "%s",pre_defined_registers[i].name);
                  match=1;
                  break;
                }
@@ -266,26 +301,42 @@ print_insn ( info, memaddr, num, insn, is_long )
            {
              /* this would only get executed if a register was not in the 
                 register table */
-             (*info->fprintf_func) (info->stream, "<unknown register %d>",val & 0x3F);       
+             (*info->fprintf_func)
+               (info->stream, _("<unknown register %d>"), val & 0x3F);       
            }
        }
-      else if (insn->op->reloc_flag == RELOC_PCREL)
+      else if (insn->op->reloc_flag == RELOC_PCREL || 
+              (opind == 1 && (insn->form->form == SHORT_D2 || insn->form->form == LONG_D)))
        {
          long max;
          int neg=0;
-         max = (1 << (oper->bits - 1));
+         max = (1 << (bits - 1));
          if (val & max)
            {
-             if (oper->bits == 32)
+             if (bits == 32)
                val = -val;
              else
-               val = -val & ((1 << oper->bits)-1);
+               val = -val & ((1 << bits)-1);
              neg = 1;
            }
-         if (neg)
-           (*info->print_address_func) ((memaddr - val) & PC_MASK, info);
-         else
-           (*info->print_address_func) ((memaddr + val) & PC_MASK, info);
+         if (opind == 1 && (insn->form->form == SHORT_D2 || insn->form->form == LONG_D))
+           {
+             (*info->fprintf_func) (info->stream, "%x",val);
+           }
+         else {
+           if (neg)
+             {
+               (*info->fprintf_func) (info->stream, "-%x\t(",val);
+               (*info->print_address_func) ((memaddr - val) & PC_MASK, info);
+               (*info->fprintf_func) (info->stream, ")");
+             }
+           else
+             {
+               (*info->fprintf_func) (info->stream, "%x\t(",val);
+               (*info->print_address_func) ((memaddr + val) & PC_MASK, info);
+               (*info->fprintf_func) (info->stream, ")");
+             }
+         }
        }
       else if (insn->op->reloc_flag == RELOC_ABS)
        {
@@ -295,10 +346,12 @@ print_insn ( info, memaddr, num, insn, is_long )
        {
          if (oper->flags & OPERAND_SIGNED)
            {
-             int max = (1 << (oper->bits - 1));
+             int max = (1 << (bits - 1));
              if (val & max)
                {
-                 val = -val & ((1 << oper->bits) - 1);
+                 val = -val;
+                 if (bits < 32)
+                   val &= ((1 << bits) - 1);
                  (*info->fprintf_func) (info->stream, "-");
                }
            }
@@ -329,8 +382,9 @@ extract_value (num, oper, is_long)
       if (oper->bits == 32) 
        {
          /* piece together 32-bit constant */
-         val = num & 0x3FFFF | (num & 0xFF00000) >> 2 |
-           (num & 0x3F00000000LL) >> 6;
+         val = ((num & 0x3FFFF)
+                | ((num & 0xFF00000) >> 2)
+                | ((num & 0x3F00000000LL) >> 6));
        }
       else     
        val = (num >> (32 + shift)) & mask;     
This page took 0.026369 seconds and 4 git commands to generate.