Updated from specs in HDD-tool-0611 document.
authorNick Clifton <nickc@redhat.com>
Fri, 22 Aug 1997 17:35:24 +0000 (17:35 +0000)
committerNick Clifton <nickc@redhat.com>
Fri, 22 Aug 1997 17:35:24 +0000 (17:35 +0000)
opcodes/ChangeLog
opcodes/v850-dis.c
opcodes/v850-opc.c

index 8e2962de726cd1d0d23a02b3b3e7cffa9cc681ba..fef7e514f2a65229a8eec49360290edded1965a2 100644 (file)
@@ -1,3 +1,11 @@
+Fri Aug 22 10:35:15 1997  Nick Clifton  <nickc@cygnus.com>
+
+       * v850-dis.c (disassemble): Use curly brace syntax for register
+       lists.
+
+       * v850-opc.c (v850_opcodes[]): Add NOT_R0 flag to decect cases
+       where r0 is being used as a destination register.
+
 start-sanitize-v850e
 Thu Aug 21 11:09:09 1997  Nick Clifton  <nickc@cygnus.com>
 
index 2970ab913b94d5cf7da84a9f157e82b7761581b7..77bf51d11cc5e72483f1925a5014273c95444d39 100644 (file)
@@ -38,54 +38,27 @@ static const char *const v850_cc_names[] =
 { "v", "c/l", "z", "nh", "s/n", "t", "lt", "le", 
   "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" };
 
-int 
-print_insn_v850 (memaddr, info)
+static int
+disassemble (memaddr, info, insn)
      bfd_vma memaddr;
      struct disassemble_info *info;
+     unsigned long insn;
 {
-  int status;
-  bfd_byte buffer[4];
-  unsigned long insn;
-
-  /* First figure out how big the opcode is.  */
-  status = (*info->read_memory_func) (memaddr, buffer, 2, info);
-  if (status != 0)
-    {
-      (*info->memory_error_func) (status, memaddr, info);
-      return -1;
-    }
-  insn = bfd_getl16 (buffer);
-
-  /* If this is a 4 byte insn, read 4 bytes of stuff.  */
-  if ((insn & 0x0600) == 0x0600)
-    {
-      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
-      if (status != 0)
-       {
-         (*info->memory_error_func) (status, memaddr, info);
-         return -1;
-       }
-      insn = bfd_getl32 (buffer);
-    }
-
-  disassemble (insn, info);
+  struct v850_opcode *          op = (struct v850_opcode *)v850_opcodes;
+  const struct v850_operand *   operand;
+  int                           match = 0;
+  int                          short_op = ((insn & 0x0600) != 0x0600);
+  int                          bytes_read;
 
-  /* Make sure we tell our caller how many bytes we consumed.  */
-  if ((insn & 0x0600) == 0x0600)
-    return 4;
-  else
-    return 2;
-}
 
-disassemble (insn, info)
-     unsigned long insn;
-     struct disassemble_info *info;
-{
-  struct v850_opcode *op = (struct v850_opcode *)v850_opcodes;
-  const struct v850_operand *operand;
-  int match = 0;
+  /* Special case: 32 bit MOV */
+  if ((insn & 0xffe0) == 0x0620)
+    short_op = true;
+      
+  bytes_read = short_op ? 2 : 4;
+  
   /* If this is a two byte insn, then mask off the high bits. */
-  if ((insn & 0x0600) != 0x0600)
+  if (short_op)
     insn &= 0xffff;
 
   /* Find the opcode.  */
@@ -93,41 +66,188 @@ disassemble (insn, info)
     {
       if ((op->mask & insn) == op->opcode)
        {
-         const unsigned char *opindex_ptr;
+         const unsigned char * opindex_ptr;
+         unsigned int          opnum;
+         unsigned int          memop;
 
          match = 1;
          (*info->fprintf_func) (info->stream, "%s\t", op->name);
+//fprintf (stderr, "match: mask: %x insn: %x, opcode: %x, name: %s\n", op->mask, insn, op->opcode, op->name );
 
-         /* Now print the operands.  */
-         for (opindex_ptr = op->operands; *opindex_ptr != 0; opindex_ptr++)
-           {
-             unsigned long value;
+         memop = op->memop;
+         /* Now print the operands.
+
+            MEMOP is the operand number at which a memory
+            address specification starts, or zero if this
+            instruction has no memory addresses.
+
+            A memory address is always two arguments.
 
+            This information allows us to determine when to
+            insert commas into the output stream as well as
+            when to insert disp[reg] expressions onto the
+            output stream.  */
+         
+         for (opindex_ptr = op->operands, opnum = 1;
+              *opindex_ptr != 0;
+              opindex_ptr++, opnum++)
+           {
+             long      value;
+             int       flag;
+             int       status;
+             bfd_byte  buffer[ 4 ];
+             
              operand = &v850_operands[*opindex_ptr];
 
              if (operand->extract)
                value = (operand->extract) (insn, 0);
+             else if (operand->bits == -1)
+               value = (insn & operand->shift);
              else
                value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
 
-             if ((operand->flags & V850_OPERAND_SIGNED) != 0)
-               value = ((signed long)(value << (32 - operand->bits))
+             if (operand->flags & V850_OPERAND_SIGNED)
+               value = ((long)(value << (32 - operand->bits))
                          >> (32 - operand->bits));
-             if ((operand->flags & V850_OPERAND_REG) != 0)
-               (*info->fprintf_func) (info->stream, "%s",
-                                     v850_reg_names[value]);
-             else if ((operand->flags & V850_OPERAND_SRG) != 0)
-               (*info->fprintf_func) (info->stream, "%s",
-                                     v850_sreg_names[value]);
-             else if ((operand->flags & V850_OPERAND_CC) != 0)
-               (*info->fprintf_func) (info->stream, "%s",
-                                     v850_cc_names[value]);
-             else if ((operand->flags & V850_OPERAND_EP) != 0)
-               (*info->fprintf_func) (info->stream, "ep");
-             else
-               (*info->fprintf_func) (info->stream, "%d", value);
+
+             /* The first operand is always output without any
+                special handling.
+
+                For the following arguments:
+
+                  If memop && opnum == memop + 1, then we need '[' since
+                  we're about to output the register used in a memory
+                  reference.
+
+                  If memop && opnum == memop + 2, then we need ']' since
+                  we just finished the register in a memory reference.  We
+                  also need a ',' before this operand.
+
+                  Else we just need a comma.
+
+                  We may need to output a trailing ']' if the last operand
+                  in an instruction is the register for a memory address. 
+
+                  The exception (and there's always an exception) is the
+                  "jmp" insn which needs square brackets around it's only
+                  register argument.  */
+
+                  if (memop && opnum == memop + 1) info->fprintf_func (info->stream, "[");
+             else if (memop && opnum == memop + 2) info->fprintf_func (info->stream, "],");
+             else if (memop == 1 && opnum == 1
+                      && (operand->flags & V850_OPERAND_REG))
+                                                   info->fprintf_func (info->stream, "[");
+             else if (opnum > 1)                   info->fprintf_func (info->stream, ", ");
+
+             /* extract the flags, ignorng ones which do not effect disassembly output. */
+             flag = operand->flags;
+             flag &= ~ V850_OPERAND_SIGNED;
+             flag &= ~ V850_OPERAND_RELAX;
+             flag &= ~ V850_OPERAND_ADJUST_SHORT_MEMORY;
+             flag &= - flag;
+             
+             switch (flag)
+               {
+               case V850_OPERAND_REG:  info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
+               case V850_OPERAND_SRG:  info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
+               case V850_OPERAND_CC:   info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
+               case V850_OPERAND_EP:   info->fprintf_func (info->stream, "ep"); break;
+               case V850_OPERAND_DISP: info->print_address_func (value + memaddr, info); break;
+               default:                info->fprintf_func (info->stream, "%d", value); break;
+/* start-sanitize-v850e */
+               case V850E_PUSH_POP:
+                 {
+                   static int list12_regs[32] = { 30,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
+/* start-sanitize-v850eq */
+                   static int list18_h_regs[32] = { 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
+                   static int list18_l_regs[32] = {  3,  2,  1, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 14, 15, 13, 12,  7,  6,  5,  4, 11, 10,  9,  8 };
+/* end-sanitize-v850eq */
+                   int *      regs;
+                   int        i;
+                   int        shown_one = false;
+                   
+                   switch (operand->shift)
+                     {
+                     case 0xffe00001: regs = list12_regs; break;
+/* start-sanitize-v850eq */
+                     case 0xfff8000f: regs = list18_h_regs; break;
+                     case 0xfff8001f: regs = list18_l_regs; value &= ~0x10; break;  /* Do not include magic bit */
+/* end-sanitize-v850eq */
+                     default:
+                       fprintf (stderr, "unknown operand shift: %x\n", operand->shift );                   
+                       abort();
+                     }
+
+                   info->fprintf_func (info->stream, "{");
+                   for (i = 0; i < 32; i++)
+                     {
+                       if (value & (1 << i))
+                         {
+                           if (shown_one)
+                             info->fprintf_func (info->stream, ",");
+                           else
+                             shown_one = true;
+                             
+                           switch (regs[ i ])
+                             {
+                             default: info->fprintf_func (info->stream, "%s", v850_reg_names[regs[ i ]]); break;
+/* start-sanitize-v850eq */
+                             case 0:  fprintf (stderr, "unknown pop reg: %d\n", i ); abort();
+                             case -1: info->fprintf_func (info->stream, "PC "); break;
+                             case -2: info->fprintf_func (info->stream, "SR"); break;
+/* end-sanitize-v850eq */
+                             }
+                         }
+                     }
+                   info->fprintf_func (info->stream, "}");
+                 }
+               break;
+                 
+               case V850E_IMMEDIATE16:
+                 status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
+                 if (status == 0)
+                   {
+                     bytes_read += 2;
+                     value = bfd_getl16 (buffer);
+
+                     /* If this is a DISPOSE instruction with ff set to 0x10, then shift value up by 16.  */
+                     if ((insn & 0x001fffc0) == 0x00130780)
+                       value <<= 16;
+
+                     info->fprintf_func (info->stream, "0x%x", value);
+                   }
+                 else
+                   {
+                     info->memory_error_func (status, memaddr + bytes_read, info);
+                   }
+                 break;
+                 
+               case V850E_IMMEDIATE32:
+                 status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
+                 if (status == 0)
+                   {
+                     bytes_read += 4;
+                     value = bfd_getl32 (buffer);
+                     info->fprintf_func (info->stream, "0x%lx", value);
+                   }
+                 else
+                   {
+                     info->memory_error_func (status, memaddr + bytes_read, info);
+                   }
+                 break;
+/* end-sanitize-v850e */
+               }                 
+
+             /* Handle jmp correctly.  */
+             if (memop == 1 && opnum == 1
+                 && ((operand->flags & V850_OPERAND_REG) != 0))
+               (*info->fprintf_func) (info->stream, "]");
            }
 
+         /* Close any square bracket we left open.  */
+         if (memop && opnum == memop + 2)
+           (*info->fprintf_func) (info->stream, "]");
+
          /* All done. */
          break;
        }
@@ -136,9 +256,50 @@ disassemble (insn, info)
 
   if (!match)
     {
-      if ((insn & 0x0600) != 0x0600)
-       (*info->fprintf_func) (info->stream, ".short\t0x%04x", insn);
+      if (short_op)
+       info->fprintf_func (info->stream, ".short\t0x%04x", insn);
       else
-       (*info->fprintf_func) (info->stream, ".long\t0x%08x", insn);
+       info->fprintf_func (info->stream, ".long\t0x%08x", insn);
     }
+
+  return bytes_read;
 }
+
+int 
+print_insn_v850 (memaddr, info)
+     bfd_vma memaddr;
+     struct disassemble_info * info;
+{
+  int           status;
+  bfd_byte      buffer[ 4 ];
+  unsigned long insn;
+
+  /* First figure out how big the opcode is.  */
+  
+  status = info->read_memory_func (memaddr, buffer, 2, info);
+  if (status == 0)
+    {
+      insn = bfd_getl16 (buffer);
+      
+      if (   (insn & 0x0600) == 0x0600
+         && (insn & 0xffe0) != 0x0620)
+       {
+         /* If this is a 4 byte insn, read 4 bytes of stuff.  */
+         status = info->read_memory_func (memaddr, buffer, 4, info);
+
+         if (status == 0)
+           insn = bfd_getl32 (buffer);
+       }
+    }
+  
+  if (status != 0)
+    {
+      info->memory_error_func (status, memaddr, info);
+      return -1;
+    }
+
+  /* Make sure we tell our caller how many bytes we consumed.  */
+  return disassemble (memaddr, info, insn);
+}
+
+
index fa46f8211ac91474631dcd109663318534e71b72..5d0dce4a946763ec44062d00904ddf2cfee66752 100644 (file)
@@ -335,7 +335,8 @@ extract_i5div (insn, invalid)
 /* end-sanitize-v850eq */
 
 \f
-const struct v850_operand v850_operands[] = {
+const struct v850_operand v850_operands[] =
+{
 #define UNUSED 0
   { 0, 0, 0, 0, 0 }, 
 
@@ -343,12 +344,20 @@ const struct v850_operand v850_operands[] = {
 #define R1     (UNUSED+1)
   { 5, 0, 0, 0, V850_OPERAND_REG }, 
 
+/* The R1 field in a format 1, 6, 7, or 9 insn. */
+#define R1_NOTR0 (R1 + 1)
+  { 5, 0, 0, 0, V850_OPERAND_REG | V850_NOT_R0 }, 
+
 /* The R2 field in a format 1, 2, 4, 5, 6, 7, 9 insn. */
-#define R2     (R1+1)
+#define R2     (R1_NOTR0 + 1)
   { 5, 11, 0, 0, V850_OPERAND_REG },
 
+/* The R2 field in a format 1, 2, 4, 5, 6, 7, 9 insn. */
+#define R2_NOTR0 (R2 + 1)
+  { 5, 11, 0, 0, V850_OPERAND_REG | V850_NOT_R0 },
+
 /* The IMM5 field in a format 2 insn. */
-#define I5     (R2+1)
+#define I5     (R2_NOTR0 + 1)
   { 5, 0, 0, 0, V850_OPERAND_SIGNED }, 
 
 #define I5U    (I5+1)
@@ -465,7 +474,7 @@ const struct v850_operand v850_operands[] = {
 
 /* Reg2 in dispose instruction. */
 #define R2DISPOSE      (IMM5 + 1)
-  { 5, 16, 0, 0, V850_OPERAND_REG },
+  { 5, 16, 0, 0, V850_OPERAND_REG | V850_NOT_R0 },
 
 /* Stack pointer in prepare instruction. */
 #define SP     (R2DISPOSE + 1)
@@ -533,15 +542,15 @@ const struct v850_opcode v850_opcodes[] =
   
 /* load/store instructions */
 #ifdef ARCH_v850eq
-{ "sld.bu",    one (0x0300),           one (0x0780),           {D7,   EP,   R2},       1 },
-{ "sld.hu",    one (0x0400),           one (0x0780),           {D8_7, EP,   R2},       1 },
+{ "sld.bu",    one (0x0300),           one (0x0780),           {D7,   EP,   R2_NOTR0}, 1 },
+{ "sld.hu",    one (0x0400),           one (0x0780),           {D8_7, EP,   R2_NOTR0}, 1 },
 { "sld.b",      one (0x0060),          one (0x07f0),           {D4,   EP,   R2},       1 },
 { "sld.h",      one (0x0070),          one (0x07f0),           {D5_4, EP,   R2},       1 },
 #else
 { "sld.b",     one (0x0300),           one (0x0780),           {D7,   EP,   R2},       1 },
 { "sld.h",     one (0x0400),           one (0x0780),           {D8_7, EP,   R2},       1 },
-{ "sld.bu",     one (0x0060),          one (0x07f0),           {D4,   EP,   R2},       1 },
-{ "sld.hu",     one (0x0070),          one (0x07f0),           {D5_4, EP,   R2},       1 },
+{ "sld.bu",     one (0x0060),          one (0x07f0),           {D4,   EP,   R2_NOTR0}, 1 },
+{ "sld.hu",     one (0x0070),          one (0x07f0),           {D5_4, EP,   R2_NOTR0}, 1 },
 #endif
 { "sld.w",     one (0x0500),           one (0x0781),           {D8_6, EP,   R2},       1 },
 { "sst.b",     one (0x0380),           one (0x0780),           {R2,   D7,   EP},       2 },
@@ -569,8 +578,8 @@ const struct v850_opcode v850_opcodes[] =
 { "ld.h",      two (0x0720, 0x0000),   two (0x07e0, 0x0001),   {D16_15, R1, R2},       1 },
 { "ld.w",      two (0x0720, 0x0001),   two (0x07e0, 0x0001),   {D16_15, R1, R2},       1 },
 /* start-sanitize-v850e */
-{ "ld.bu",     two (0x0780, 0x0001),   two (0x07c0, 0x0001),   {D16_16, R1, R2},       1 },
-{ "ld.hu",     two (0x07e0, 0x0001),   two (0x07e0, 0x0001),   {D16_15, R1, R2},       1 },  
+{ "ld.bu",     two (0x0780, 0x0001),   two (0x07c0, 0x0001),   {D16_16, R1, R2_NOTR0}, 1 },
+{ "ld.hu",     two (0x07e0, 0x0001),   two (0x07e0, 0x0001),   {D16_15, R1, R2_NOTR0}, 1 },  
 /* end-sanitize-v850e */
 { "st.b",      two (0x0740, 0x0000),   two (0x07e0, 0x0000),   {R2, D16, R1},          2 },
 { "st.h",      two (0x0760, 0x0000),   two (0x07e0, 0x0001),   {R2, D16_15, R1},       2 },
@@ -578,10 +587,10 @@ const struct v850_opcode v850_opcodes[] =
 
 /* start-sanitize-v850e */
 /* byte swap/extend instructions */
-{ "zxb",       one (0x0080),           one (0xffe0),           {R1},                   0 },
-{ "zxh",       one (0x00c0),           one (0xffe0),           {R1},                   0 },
-{ "sxb",       one (0x00a0),           one (0xffe0),           {R1},                   0 },
-{ "sxh",       one (0x00e0),           one (0xffe0),           {R1},                   0 },
+{ "zxb",       one (0x0080),           one (0xffe0),           {R1_NOTR0},             0 },
+{ "zxh",       one (0x00c0),           one (0xffe0),           {R1_NOTR0},             0 },
+{ "sxb",       one (0x00a0),           one (0xffe0),           {R1_NOTR0},             0 },
+{ "sxh",       one (0x00e0),           one (0xffe0),           {R1_NOTR0},             0 },
 { "bsh",       two (0x07e0, 0x0342),   two (0x07ff, 0x07ff),   {R2, R3},               0 },
 { "bsw",       two (0x07e0, 0x0340),   two (0x07ff, 0x07ff),   {R2, R3},               0 },
 { "hsw",       two (0x07e0, 0x0344),   two (0x07ff, 0x07ff),   {R2, R3},               0 },
@@ -611,7 +620,7 @@ const struct v850_opcode v850_opcodes[] =
 { "divhu",     two (0x07e0, 0x0282),   two (0x07e0, 0x07ff),   {R1, R2, R3},           0 },
 { "divh",      two (0x07e0, 0x0280),   two (0x07e0, 0x07ff),   {R1, R2, R3},           0 },
 /* end-sanitize-v850e */
-{ "divh",      OP  (0x02),             OP_MASK,                IF1,                    0 },
+{ "divh",      OP  (0x02),             OP_MASK,                {R1, R2_NOTR0},         0 },
   
 /* start-sanitize-v850eq */
 { "divhn",     two (0x07e0, 0x0280),   two (0x07e0, 0x07c3),   {I5DIV, R1, R2, R3},    0 },
@@ -625,30 +634,30 @@ const struct v850_opcode v850_opcodes[] =
 /* end-sanitize-v850eq */
   
 { "nop",       one (0x00),             one (0xffff),           {0},                    0 },
-{ "mov",        OP  (0x00),            OP_MASK,                IF1,                    0 },
-{ "mov",       OP  (0x10),             OP_MASK,                IF2,                    0 },
+{ "mov",       OP  (0x10),             OP_MASK,                {I5, R2_NOTR0},         0 },
 /* start-sanitize-v850e */
-{ "mov",       one (0x0620),           one (0xffe0),           {IMM32, R1},            0 },
+{ "mov",       one (0x0620),           one (0xffe0),           {IMM32, R1_NOTR0},      0 },
 /* end-sanitize-v850e */
-{ "movea",     OP  (0x31),             OP_MASK,                IF6,                    0 },
-{ "movhi",     OP  (0x32),             OP_MASK,                IF6,                    0 },
+{ "mov",        OP  (0x00),            OP_MASK,                {R1, R2_NOTR0},         0 },
+{ "movea",     OP  (0x31),             OP_MASK,                {I16, R1, R2_NOTR0},    0 },
+{ "movhi",     OP  (0x32),             OP_MASK,                {I16, R1, R2_NOTR0},    0 },
 { "add",       OP  (0x0e),             OP_MASK,                IF1,                    0 },
 { "add",       OP  (0x12),             OP_MASK,                IF2,                    0 },
 { "addi",      OP  (0x30),             OP_MASK,                IF6,                    0 },
 { "sub",       OP  (0x0d),             OP_MASK,                IF1,                    0 },
 { "subr",      OP  (0x0c),             OP_MASK,                IF1,                    0 },
-{ "mulh",      OP  (0x07),             OP_MASK,                IF1,                    0 },
-{ "mulh",      OP  (0x17),             OP_MASK,                IF2,                    0 },
-{ "mulhi",     OP  (0x37),             OP_MASK,                IF6,                    0 },
+{ "mulh",      OP  (0x17),             OP_MASK,                {I5, R2_NOTR0},         0 },
+{ "mulh",      OP  (0x07),             OP_MASK,                {R1, R2_NOTR0},         0 },
+{ "mulhi",     OP  (0x37),             OP_MASK,                {I16, R1, R2_NOTR0},    0 },
 { "cmp",       OP  (0x0f),             OP_MASK,                IF1,                    0 },
 { "cmp",       OP  (0x13),             OP_MASK,                IF2,                    0 },
   
 /* saturated operation instructions */
-{ "satadd",    OP (0x06),              OP_MASK,                IF1,                    0 },
-{ "satadd",    OP (0x11),              OP_MASK,                IF2,                    0 },
-{ "satsub",    OP (0x05),              OP_MASK,                IF1,                    0 },
-{ "satsubi",   OP (0x33),              OP_MASK,                IF6,                    0 },
-{ "satsubr",   OP (0x04),              OP_MASK,                IF1,                    0 },
+{ "satadd",    OP (0x11),              OP_MASK,                {I5, R2_NOTR0},         0 },
+{ "satadd",    OP (0x06),              OP_MASK,                {R1, R2_NOTR0},         0 },
+{ "satsub",    OP (0x05),              OP_MASK,                {R1, R2_NOTR0},         0 },
+{ "satsubi",   OP (0x33),              OP_MASK,                {I16, R1, R2_NOTR0},    0 },
+{ "satsubr",   OP (0x04),              OP_MASK,                {R1, R2_NOTR0},         0 },
 
 /* logical operation instructions */
 { "tst",       OP (0x0b),              OP_MASK,                IF1,                    0 },
This page took 0.036225 seconds and 4 git commands to generate.