*** empty log message ***
[deliverable/binutils-gdb.git] / opcodes / m10300-dis.c
index 7d7f74c947f7904428ea87b2ec0eddece7a9b24f..1d3637c704d0b534fc82783b4faf7536f02406dd 100644 (file)
@@ -1,5 +1,5 @@
 /* Disassemble MN10300 instructions.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001 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,15 +18,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include <stdio.h>
 
-#include "ansidecl.h"
-#include "opcode/mn10300.h" 
+#include "sysdep.h"
+#include "opcode/mn10300.h"
 #include "dis-asm.h"
 #include "opintl.h"
 
 static void disassemble PARAMS ((bfd_vma, struct disassemble_info *,
                                 unsigned long insn, unsigned int));
 
-int 
+#define HAVE_AM33_2 (info->mach == AM33_2)
+#define HAVE_AM33 (info->mach == AM33 || HAVE_AM33_2)
+#define HAVE_AM30 (info->mach == AM30)
+
+int
 print_insn_mn10300 (memaddr, info)
      bfd_vma memaddr;
      struct disassemble_info *info;
@@ -100,7 +104,7 @@ print_insn_mn10300 (memaddr, info)
       if (status != 0)
        {
          (*info->memory_error_func) (status, memaddr, info);
-          return -1;
+         return -1;
        }
       insn = bfd_getb16 (buffer);
       consume = 2;
@@ -108,7 +112,7 @@ print_insn_mn10300 (memaddr, info)
 
   /* These are three byte insns.  */
   else if ((insn & 0xff) == 0xf8
-          || (insn & 0xff) == 0xcc 
+          || (insn & 0xff) == 0xcc
           || (insn & 0xff) == 0xf9
           || (insn & 0xf3) == 0x01
           || (insn & 0xf3) == 0x02
@@ -137,7 +141,7 @@ print_insn_mn10300 (memaddr, info)
          (*info->memory_error_func) (status, memaddr, info);
          return -1;
        }
-      insn |= *(unsigned char *)buffer;
+      insn |= *(unsigned char *) buffer;
       consume = 3;
     }
 
@@ -197,6 +201,9 @@ print_insn_mn10300 (memaddr, info)
 
       insn = bfd_getb32 (buffer);
       consume = 7;
+      /* Handle the 5-byte extended instruction codes.  */
+      if ((insn & 0xfff80000) == 0xfe800000)
+       consume = 5;
     }
 
   disassemble (memaddr, info, insn, consume);
@@ -234,6 +241,8 @@ disassemble (memaddr, info, insn, size)
        mysize = 5;
       else if (op->format == FMT_D2)
        mysize = 4;
+      else if (op->format == FMT_D3)
+       mysize = 5;
       else if (op->format == FMT_D4)
        mysize = 6;
       else if (op->format == FMT_D6)
@@ -246,16 +255,18 @@ disassemble (memaddr, info, insn, size)
        mysize = 7;
       else
        mysize = 7;
-       
+
       if ((op->mask & insn) == op->opcode
          && size == (unsigned int) mysize
          && (op->machine == 0
-             || op->machine == info->mach))
+             || (op->machine == AM33_2 && HAVE_AM33_2)
+             || (op->machine == AM33 && HAVE_AM33)
+             || (op->machine == AM30 && HAVE_AM30)))
        {
          const unsigned char *opindex_ptr;
          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
@@ -339,6 +350,25 @@ disassemble (memaddr, info, insn, size)
              insn |= (temp & 0xffffff00) >> 8;
              extension = temp & 0xff;
            }
+         else if (size == 5 && op->format == FMT_D3)
+           {
+             status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
+             if (status != 0)
+               {
+                 (*info->memory_error_func) (status, memaddr, info);
+                 return;
+               }
+             insn &= 0xffff0000;
+             insn |= bfd_getl16 (buffer);
+
+             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 == 5)
            {
              unsigned long temp = 0;
@@ -359,7 +389,7 @@ disassemble (memaddr, info, insn, size)
                  (*info->memory_error_func) (status, memaddr, info);
                  return;
                }
-             extension = *(unsigned char *)buffer;
+             extension = *(unsigned char *) buffer;
            }
          else if (size == 6 && op->format == FMT_D8)
            {
@@ -370,7 +400,7 @@ disassemble (memaddr, info, insn, size)
                  (*info->memory_error_func) (status, memaddr, info);
                  return;
                }
-             insn |= *(unsigned char *)buffer;
+             insn |= *(unsigned char *) buffer;
 
              status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
              if (status != 0)
@@ -422,7 +452,7 @@ disassemble (memaddr, info, insn, size)
              insn &= 0xff000000;
              insn |= (temp >> 8) & 0xffffff;
              extension = (temp & 0xff) << 16;
-             
+
              status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
              if (status != 0)
                {
@@ -445,14 +475,14 @@ disassemble (memaddr, info, insn, size)
              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;
+             extension |= *(unsigned char *) buffer;
            }
 
          match = 1;
@@ -480,6 +510,8 @@ disassemble (memaddr, info, insn, size)
                  temp = extension >> operand->shift;
                  temp &= ((1 << (32 - operand->bits)) - 1);
                  value |= temp;
+                 value = ((value ^ (((unsigned long) 1) << 31))
+                          - (((unsigned long) 1) << 31));
                }
              else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
                {
@@ -490,7 +522,53 @@ disassemble (memaddr, info, insn, size)
                  temp &= ((1 << (24 - operand->bits)) - 1);
                  value |= temp;
                  if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
-                   value = ((value & 0xffffff) ^ (~0x7fffff)) + 0x800000;
+                   value = ((value & 0xffffff) ^ 0x800000) - 0x800000;
+               }
+             else if ((operand->flags & (MN10300_OPERAND_FSREG
+                                         | MN10300_OPERAND_FDREG)))
+               {
+                 /* See m10300-opc.c just before #define FSM0 for an
+                    explanation of these variables.  Note that
+                    FMT-implied shifts are not taken into account for
+                    FP registers.  */
+                 unsigned long mask_low, mask_high;
+                 int shl_low, shr_high, shl_high;
+
+                 switch (operand->bits)
+                   {
+                   case 5:
+                     /* Handle regular FP registers.  */
+                     if (operand->shift >= 0)
+                       {
+                         /* This is an `m' register.  */
+                         shl_low = operand->shift;
+                         shl_high = 8 + (8 & shl_low) + (shl_low & 4) / 4;
+                       }
+                     else
+                       {
+                         /* This is an `n' register.  */
+                         shl_low = -operand->shift;
+                         shl_high = shl_low / 4;
+                       }
+                     mask_low = 0x0f;
+                     mask_high = 0x10;
+                     shr_high = 4;
+                     break;
+
+                   case 3:
+                     /* Handle accumulators.  */
+                     shl_low = -operand->shift;
+                     shl_high = 0;
+                     mask_low = 0x03;
+                     mask_high = 0x04;
+                     shr_high = 2;
+                     break;
+
+                   default:
+                     abort ();
+                   }
+                 value = ((((insn >> shl_high) << shr_high) & mask_high)
+                          | ((insn >> shl_low) & mask_low));
                }
              else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
                {
@@ -504,11 +582,10 @@ disassemble (memaddr, info, insn, size)
                }
 
              if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
-                  /* These are properly extended by the code above.  */
-                  && ((operand->flags & MN10300_OPERAND_24BIT) == 0)
-                 )
-               value = ((long)(value << (32 - operand->bits))
-                         >> (32 - operand->bits));
+                 /* These are properly extended by the code above.  */
+                 && ((operand->flags & MN10300_OPERAND_24BIT) == 0))
+               value = ((value ^ (((unsigned long) 1) << (operand->bits - 1)))
+                        - (((unsigned long) 1) << (operand->bits - 1)));
 
              if (!nocomma
                  && (!paren
@@ -516,19 +593,19 @@ disassemble (memaddr, info, insn, size)
                (*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);
+                 (*info->fprintf_func) (info->stream, "d%d", (int) 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);
+                 (*info->fprintf_func) (info->stream, "a%d", (int) value);
                }
 
              else if ((operand->flags & MN10300_OPERAND_SP) != 0)
@@ -545,11 +622,11 @@ disassemble (memaddr, info, insn, size)
                  value = ((insn >> (operand->shift + extra_shift))
                           & ((1 << operand->bits) - 1));
                  if (value < 8)
-                   (*info->fprintf_func) (info->stream, "r%d", value);
+                   (*info->fprintf_func) (info->stream, "r%d", (int) value);
                  else if (value < 12)
-                   (*info->fprintf_func) (info->stream, "a%d", value - 8);
+                   (*info->fprintf_func) (info->stream, "a%d", (int) value - 8);
                  else
-                   (*info->fprintf_func) (info->stream, "d%d", value - 12);
+                   (*info->fprintf_func) (info->stream, "d%d", (int) value - 12);
                }
 
              else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
@@ -559,9 +636,18 @@ disassemble (memaddr, info, insn, size)
                  if (value == 0)
                    (*info->fprintf_func) (info->stream, "sp", value);
                  else
-                 (*info->fprintf_func) (info->stream, "xr%d", value);
+                   (*info->fprintf_func) (info->stream, "xr%d", (int) value);
                }
 
+             else if ((operand->flags & MN10300_OPERAND_FSREG) != 0)
+               (*info->fprintf_func) (info->stream, "fs%d", (int) value);
+
+             else if ((operand->flags & MN10300_OPERAND_FDREG) != 0)
+               (*info->fprintf_func) (info->stream, "fd%d", (int) value);
+
+             else if ((operand->flags & MN10300_OPERAND_FPCR) != 0)
+               (*info->fprintf_func) (info->stream, "fpcr");
+
              else if ((operand->flags & MN10300_OPERAND_USP) != 0)
                (*info->fprintf_func) (info->stream, "usp");
 
@@ -665,8 +751,8 @@ disassemble (memaddr, info, insn, size)
                  (*info->fprintf_func) (info->stream, "]");
                }
 
-             else 
-               (*info->fprintf_func) (info->stream, "%d", value);
+             else
+               (*info->fprintf_func) (info->stream, "%ld", (long) value);
            }
          /* All done. */
          break;
This page took 0.030624 seconds and 4 git commands to generate.