]> Git Repo - binutils.git/blobdiff - opcodes/mn10300-dis.c
* ppc-opc.c: Add PPC 403 instructions and extended opcodes. From
[binutils.git] / opcodes / mn10300-dis.c
index 707940aa803c5857baedbe96ad000de347f0a7dd..cf5d321c91af9f522a0a64a1bb91e8a09ba096a5 100644 (file)
@@ -1,5 +1,5 @@
 /* Disassemble MN10300 instructions.
-   Copyright (C) 1996 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997 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
@@ -23,11 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "dis-asm.h"
 
 static void disassemble PARAMS ((bfd_vma, struct disassemble_info *,
-                                unsigned long insn, unsigned long,
-                                unsigned int));
-
-static const char *const mn10300_reg_names[] =
-{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", };
+                                unsigned long insn, unsigned int));
 
 int 
 print_insn_mn10300 (memaddr, info)
@@ -37,7 +33,6 @@ print_insn_mn10300 (memaddr, info)
   int status;
   bfd_byte buffer[4];
   unsigned long insn;
-  unsigned long extension;
   unsigned int consume;
 
   /* First figure out how big the opcode is.  */
@@ -49,7 +44,7 @@ print_insn_mn10300 (memaddr, info)
     }
   insn = *(unsigned char *) buffer;
 
-  /* These are one byte insns XXX imm8 versions of mov, cmp.  */
+  /* These are one byte insns.  */
   if ((insn & 0xf3) == 0x00
       || (insn & 0xf0) == 0x10
       || (insn & 0xfc) == 0x3c
@@ -73,7 +68,6 @@ print_insn_mn10300 (memaddr, info)
       || (insn & 0xfc) == 0xd8
       || (insn & 0xf0) == 0xe0)
     {
-      extension = 0;
       consume = 1;
     }
 
@@ -107,7 +101,6 @@ print_insn_mn10300 (memaddr, info)
           return -1;
        }
       insn = bfd_getb16 (buffer);
-      extension = 0;
       consume = 2;
     }
 
@@ -135,8 +128,13 @@ print_insn_mn10300 (memaddr, info)
        }
       insn = bfd_getb16 (buffer);
       insn <<= 8;
-      insn |= *(unsigned char *)buffer + 2;
-      extension = 0;
+      status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      insn |= *(unsigned char *)buffer;
       consume = 3;
     }
 
@@ -151,7 +149,6 @@ print_insn_mn10300 (memaddr, info)
          return -1;
        }
       insn = bfd_getb32 (buffer);
-      extension = 0;
       consume = 4;
     }
 
@@ -166,14 +163,6 @@ print_insn_mn10300 (memaddr, info)
          return -1;
        }
       insn = bfd_getb32 (buffer);
-
-      status = (*info->read_memory_func) (memaddr, buffer, 1, info);
-      if (status != 0)
-       {
-         (*info->memory_error_func) (status, memaddr, info);
-         return -1;
-       }
-      extension = *(unsigned char *) buffer + 4;
       consume = 5;
     }
 
@@ -189,13 +178,6 @@ print_insn_mn10300 (memaddr, info)
        }
 
       insn = bfd_getb32 (buffer);
-      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
-      if (status != 0)
-       {
-         (*info->memory_error_func) (status, memaddr, info);
-         return -1;
-       }
-      extension = bfd_getb16 (buffer + 4);
       consume = 6;
     }
 
@@ -210,39 +192,31 @@ print_insn_mn10300 (memaddr, info)
        }
 
       insn = bfd_getb32 (buffer);
-      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
-      if (status != 0)
-       {
-         (*info->memory_error_func) (status, memaddr, info);
-         return -1;
-       }
-      extension = bfd_getb16 (buffer);
-      extension <<= 8;
-      extension |= *(unsigned char *)buffer + 2;
       consume = 7;
     }
 
-  disassemble (memaddr, info, insn, extension, consume);
+  disassemble (memaddr, info, insn, consume);
 
   return consume;
 }
 
 static void
-disassemble (memaddr, info, insn, extension, size)
+disassemble (memaddr, info, insn, size)
      bfd_vma memaddr;
      struct disassemble_info *info;
      unsigned long insn;
-     unsigned long extension;
      unsigned int size;
 {
   struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes;
   const struct mn10300_operand *operand;
-  int match = 0;
+  bfd_byte buffer[4];
+  unsigned long extension = 0;
+  int status, match = 0;
 
   /* Find the opcode.  */
   while (op->name)
     {
-      int mysize;
+      int mysize, extra_shift;
 
       if (op->format == FMT_S0)
        mysize = 1;
@@ -265,26 +239,293 @@ disassemble (memaddr, info, insn, extension, size)
          && size == mysize)
        {
          const unsigned char *opindex_ptr;
-         unsigned int opnum, memop;
+         unsigned int nocomma;
+         int paren = 0;
          
+         if (op->format == FMT_D1 || op->format == FMT_S1)
+           extra_shift = 8;
+         else if (op->format == FMT_D2 || op->format == FMT_D4
+                  || op->format == FMT_S2 || op->format == FMT_S4
+                  || op->format == FMT_S6 || op->format == FMT_D5)
+           extra_shift = 16;
+         else
+           extra_shift = 0;
+
+         if (size == 1 || size == 2)
+           {
+             extension = 0;
+           }
+         else if (size == 3
+                  && (op->format == FMT_D1
+                      || op->opcode == 0xdf0000
+                      || op->opcode == 0xde0000))
+           {
+             extension = 0;
+           }
+         else if (size == 3)
+           {
+             insn &= 0xff0000;
+             status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
+             if (status != 0)
+               {
+                 (*info->memory_error_func) (status, memaddr, info);
+                 return;
+               }
+
+             insn |= bfd_getl16 (buffer);
+             extension = 0;
+           }
+         else if (size == 4
+                  && (op->opcode == 0xfaf80000
+                      || op->opcode == 0xfaf00000
+                      || op->opcode == 0xfaf40000))
+           {
+             extension = 0;
+           }
+         else if (size == 4)
+           {
+             insn &= 0xffff0000;
+             status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
+             if (status != 0)
+               {
+                 (*info->memory_error_func) (status, memaddr, info);
+                 return;
+               }
+
+             insn |= bfd_getl16 (buffer);
+             extension = 0;
+           }
+         else if (size == 5 && op->opcode == 0xdc000000)
+           {
+             unsigned long temp = 0;
+             status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
+             if (status != 0)
+               {
+                 (*info->memory_error_func) (status, memaddr, info);
+                 return;
+               }
+             temp |= bfd_getl32 (buffer);
+
+             insn &= 0xff000000;
+             insn |= (temp & 0xffffff00) >> 8;
+             extension = temp & 0xff;
+           }
+         else if (size == 5)
+           {
+             unsigned long temp = 0;
+             status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
+             if (status != 0)
+               {
+                 (*info->memory_error_func) (status, memaddr, info);
+                 return;
+               }
+             temp |= bfd_getl16 (buffer);
+
+             insn &= 0xff0000ff;
+             insn |= temp << 8;
+
+             status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
+             if (status != 0)
+               {
+                 (*info->memory_error_func) (status, memaddr, info);
+                 return;
+               }
+             extension = *(unsigned char *)buffer;
+           }
+         else if (size == 6)
+           {
+             unsigned long temp = 0;
+             status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
+             if (status != 0)
+               {
+                 (*info->memory_error_func) (status, memaddr, info);
+                 return;
+               }
+             temp |= bfd_getl32 (buffer);
+
+             insn &= 0xffff0000;
+             insn |= (temp >> 16) & 0xffff;
+             extension = temp & 0xffff;
+           }
+         else if (size == 7 && op->opcode == 0xdd000000)
+           {
+             unsigned long temp = 0;
+             status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
+             if (status != 0)
+               {
+                 (*info->memory_error_func) (status, memaddr, info);
+                 return;
+               }
+             temp |= bfd_getl32 (buffer);
+
+             insn &= 0xff000000;
+             insn |= (temp >> 8) & 0xffffff;
+             extension = (temp & 0xff) << 16;
+             
+             status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
+             if (status != 0)
+               {
+                 (*info->memory_error_func) (status, memaddr, info);
+                 return;
+               }
+             extension |= bfd_getb16 (buffer);
+           }
+         else if (size == 7)
+           {
+             unsigned long temp = 0;
+             status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
+             if (status != 0)
+               {
+                 (*info->memory_error_func) (status, memaddr, info);
+                 return;
+               }
+             temp |= bfd_getl32 (buffer);
+
+             insn &= 0xffff0000;
+             insn |= (temp >> 16) & 0xffff;
+             extension = (temp & 0xffff) << 8;
+             
+             status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
+             if (status != 0)
+               {
+                 (*info->memory_error_func) (status, memaddr, info);
+                 return;
+               }
+             extension |= *(unsigned char *)buffer;
+           }
+
          match = 1;
          (*info->fprintf_func) (info->stream, "%s\t", op->name);
 
          /* Now print the operands.  */
-         for (opindex_ptr = op->operands, opnum = 1;
+         for (opindex_ptr = op->operands, nocomma = 1;
               *opindex_ptr != 0;
-              opindex_ptr++, opnum++)
+              opindex_ptr++)
            {
              unsigned long value;
 
              operand = &mn10300_operands[*opindex_ptr];
 
-             value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+             if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
+               {
+                 unsigned long temp;
+                 value = insn & ((1 << operand->bits) - 1);
+                 value <<= (32 - operand->bits);
+                 temp = extension >> operand->shift;
+                 temp &= ((1 << (32 - operand->bits)) - 1);
+                 value |= temp;
+               }
+             else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
+               {
+                 value = ((extension >> (operand->shift))
+                          & ((1 << operand->bits) - 1));
+               }
+             else
+               {
+                 value = ((insn >> (operand->shift))
+                          & ((1 << operand->bits) - 1));
+               }
 
              if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
                value = ((long)(value << (32 - operand->bits))
                          >> (32 - operand->bits));
 
+             if (!nocomma
+                 && (!paren
+                     || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
+               (*info->fprintf_func) (info->stream, ",");
+
+             nocomma = 0;
+               
+             if ((operand->flags & MN10300_OPERAND_DREG) != 0)
+               {
+                 value = ((insn >> (operand->shift + extra_shift))
+                          & ((1 << operand->bits) - 1));
+                 (*info->fprintf_func) (info->stream, "d%d", value);
+               }
+
+             else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
+               {
+                 value = ((insn >> (operand->shift + extra_shift))
+                          & ((1 << operand->bits) - 1));
+                 (*info->fprintf_func) (info->stream, "a%d", value);
+               }
+
+             else if ((operand->flags & MN10300_OPERAND_SP) != 0)
+               (*info->fprintf_func) (info->stream, "sp");
+
+             else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
+               (*info->fprintf_func) (info->stream, "psw");
+
+             else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
+               (*info->fprintf_func) (info->stream, "mdr");
+
+             else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
+               {
+                 if (paren)
+                   (*info->fprintf_func) (info->stream, ")");
+                 else
+                   {
+                     (*info->fprintf_func) (info->stream, "(");
+                     nocomma = 1;
+                   }
+                 paren = !paren;
+               }
+
+             else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
+               (*info->print_address_func) (value + memaddr, info);
+
+             else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
+               (*info->print_address_func) (value, info);
+
+             else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
+               {
+                 int comma = 0;
+
+                 (*info->fprintf_func) (info->stream, "[");
+                 if (value & 0x80)
+                   {
+                     (*info->fprintf_func) (info->stream, "d2");
+                     comma = 1;
+                   }
+
+                 if (value & 0x40)
+                   {
+                     if (comma)
+                       (*info->fprintf_func) (info->stream, ",");
+                     (*info->fprintf_func) (info->stream, "d3");
+                     comma = 1;
+                   }
+
+                 if (value & 0x20)
+                   {
+                     if (comma)
+                       (*info->fprintf_func) (info->stream, ",");
+                     (*info->fprintf_func) (info->stream, "a2");
+                     comma = 1;
+                   }
+
+                 if (value & 0x10)
+                   {
+                     if (comma)
+                       (*info->fprintf_func) (info->stream, ",");
+                     (*info->fprintf_func) (info->stream, "a3");
+                     comma = 1;
+                   }
+
+                 if (value & 0x08)
+                   {
+                     if (comma)
+                       (*info->fprintf_func) (info->stream, ",");
+                     (*info->fprintf_func) (info->stream, "other");
+                     comma = 1;
+                   }
+                 (*info->fprintf_func) (info->stream, "]");
+               }
+
+             else 
+               (*info->fprintf_func) (info->stream, "%d", value);
+           }
          /* All done. */
          break;
        }
This page took 0.03651 seconds and 4 git commands to generate.