]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - opcodes/m68k-dis.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / opcodes / m68k-dis.c
index 62612b274419fc325c428768dc48c5c28d07a132..5396a0ce1325fd21027626798bc0da226ca522bb 100644 (file)
@@ -1,5 +1,5 @@
 /* Print Motorola 68k instructions.
-   Copyright (C) 1986-2015 Free Software Foundation, Inc.
+   Copyright (C) 1986-2021 Free Software Foundation, Inc.
 
    This file is part of the GNU opcodes library.
 
    MA 02110-1301, USA.  */
 
 #include "sysdep.h"
-#include "dis-asm.h"
+#include "disassemble.h"
 #include "floatformat.h"
 #include "libiberty.h"
 #include "opintl.h"
-
+#include "cpu-m68k.h"
 #include "opcode/m68k.h"
 
 /* Local function prototypes.  */
@@ -57,13 +57,27 @@ static char *const reg_half_names[] =
 #define COERCE_SIGNED_CHAR(ch) ((int) (((ch) ^ 0x80) & 0xFF) - 128)
 #endif
 
+/* Error code of print_insn_arg's return value.  */
+
+enum print_insn_arg_error
+  {
+    /* An invalid operand is found.  */
+    PRINT_INSN_ARG_INVALID_OPERAND = -1,
+
+    /* An opcode table error.  */
+    PRINT_INSN_ARG_INVALID_OP_TABLE = -2,
+
+    /* A memory error.  */
+    PRINT_INSN_ARG_MEMORY_ERROR = -3,
+  };
+
 /* Get a 1 byte signed integer.  */
 #define NEXTBYTE(p, val)                       \
   do                                           \
     {                                          \
       p += 2;                                  \
       if (!FETCH_DATA (info, p))               \
-       return -3;                              \
+       return PRINT_INSN_ARG_MEMORY_ERROR;     \
       val = COERCE_SIGNED_CHAR (p[-1]);                \
     }                                          \
   while (0)
@@ -82,7 +96,7 @@ static char *const reg_half_names[] =
   while (0)
 
 /* Get a 4 byte signed integer.  */
-#define COERCE32(x) ((bfd_signed_vma) ((x) ^ 0x80000000) - 0x80000000)
+#define COERCE32(x) (((bfd_vma) (x) ^ 0x80000000) - 0x80000000)
 
 #define NEXTLONG(p, val, ret_val)                                      \
   do                                                                   \
@@ -90,7 +104,8 @@ static char *const reg_half_names[] =
       p += 4;                                                          \
       if (!FETCH_DATA (info, p))                                       \
        return ret_val;                                                 \
-      val = COERCE32 ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]); \
+      val = COERCE32 (((((((unsigned) p[-4] << 8) + p[-3]) << 8)       \
+                       + p[-2]) << 8) + p[-1]);                        \
     }                                                                  \
   while (0)
 
@@ -100,8 +115,9 @@ static char *const reg_half_names[] =
     {                                                                  \
       p += 4;                                                          \
       if (!FETCH_DATA (info, p))                                       \
-       return -3;                                                      \
-      val = (unsigned int) ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]); \
+       return PRINT_INSN_ARG_MEMORY_ERROR;                             \
+      val = (((((((unsigned) p[-4] << 8) + p[-3]) << 8)                        \
+              + p[-2]) << 8) + p[-1]);                                 \
     }                                                                  \
   while (0)
 
@@ -111,7 +127,7 @@ static char *const reg_half_names[] =
     {                                                          \
       p += 4;                                                  \
       if (!FETCH_DATA (info, p))                               \
-       return -3;                                              \
+       return PRINT_INSN_ARG_MEMORY_ERROR;                     \
       floatformat_to_double (& floatformat_ieee_single_big,    \
                             (char *) p - 4, & val);            \
     }                                                          \
@@ -123,7 +139,7 @@ static char *const reg_half_names[] =
     {                                                          \
       p += 8;                                                  \
       if (!FETCH_DATA (info, p))                               \
-       return -3;                                              \
+       return PRINT_INSN_ARG_MEMORY_ERROR;                     \
       floatformat_to_double (& floatformat_ieee_double_big,    \
                             (char *) p - 8, & val);            \
     }                                                          \
@@ -135,7 +151,7 @@ static char *const reg_half_names[] =
     {                                                  \
       p += 12;                                         \
       if (!FETCH_DATA (info, p))                       \
-       return -3;                                      \
+       return PRINT_INSN_ARG_MEMORY_ERROR;             \
       floatformat_to_double (& floatformat_m68881_ext, \
                             (char *) p - 12, & val);   \
     }                                                  \
@@ -150,7 +166,7 @@ static char *const reg_half_names[] =
     {                                          \
       p += 12;                                 \
       if (!FETCH_DATA (info, p))               \
-       return -3;                              \
+       return PRINT_INSN_ARG_MEMORY_ERROR;     \
       val = 0.0;                               \
     }                                          \
   while (0)
@@ -168,7 +184,8 @@ struct private
 };
 
 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
-   to ADDR (exclusive) are valid.  Returns 1 for success, 0 on error.  */
+   to ADDR (exclusive) are valid.  Returns 1 for success, 0 on memory
+   error.  */
 #define FETCH_DATA(info, addr) \
   ((addr) <= ((struct private *) (info->private_data))->max_fetched \
    ? 1 : fetch_data ((info), (addr)))
@@ -617,14 +634,13 @@ print_indexed (int basereg,
     {                                                  \
       val = fetch_arg (buffer, place, size, info);     \
       if (val < 0)                                     \
-       return -3;                                      \
+       return PRINT_INSN_ARG_MEMORY_ERROR;             \
     }                                                  \
   while (0)
 
 /* Returns number of bytes "eaten" by the operand, or
-   return -1 if an invalid operand was found, or -2 if
-   an opcode tabe error was found or -3 to simply abort.
-   ADDR is the pc for this arg to be relative to.  */
+   return enum print_insn_arg_error.  ADDR is the pc for this arg to be
+   relative to.  */
 
 static int
 print_insn_arg (const char *d,
@@ -864,7 +880,7 @@ print_insn_arg (const char *d,
          (*info->fprintf_func) (info->stream, "{#%d}", val);
        }
       else
-       return -1;
+       return PRINT_INSN_ARG_INVALID_OPERAND;
       break;
 
     case '#':
@@ -881,11 +897,11 @@ print_insn_arg (const char *d,
       else if (place == 'b')
        NEXTBYTE (p1, val);
       else if (place == 'w' || place == 'W')
-       NEXTWORD (p1, val, -3);
+       NEXTWORD (p1, val, PRINT_INSN_ARG_MEMORY_ERROR);
       else if (place == 'l')
-       NEXTLONG (p1, val, -3);
+       NEXTLONG (p1, val, PRINT_INSN_ARG_MEMORY_ERROR);
       else
-       return -2;
+       return PRINT_INSN_ARG_INVALID_OP_TABLE;
 
       (*info->fprintf_func) (info->stream, "#%d", val);
       break;
@@ -896,26 +912,26 @@ print_insn_arg (const char *d,
       else if (place == 'B')
        disp = COERCE_SIGNED_CHAR (buffer[1]);
       else if (place == 'w' || place == 'W')
-       NEXTWORD (p, disp, -3);
+       NEXTWORD (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
       else if (place == 'l' || place == 'L' || place == 'C')
-       NEXTLONG (p, disp, -3);
+       NEXTLONG (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
       else if (place == 'g')
        {
          NEXTBYTE (buffer, disp);
          if (disp == 0)
-           NEXTWORD (p, disp, -3);
+           NEXTWORD (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
          else if (disp == -1)
-           NEXTLONG (p, disp, -3);
+           NEXTLONG (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
        }
       else if (place == 'c')
        {
          if (buffer[1] & 0x40)         /* If bit six is one, long offset.  */
-           NEXTLONG (p, disp, -3);
+           NEXTLONG (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
          else
-           NEXTWORD (p, disp, -3);
+           NEXTWORD (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
        }
       else
-       return -2;
+       return PRINT_INSN_ARG_INVALID_OP_TABLE;
 
       (*info->print_address_func) (addr + disp, info);
       break;
@@ -924,7 +940,7 @@ print_insn_arg (const char *d,
       {
        int val1;
 
-       NEXTWORD (p, val, -3);
+       NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
        FETCH_ARG (3, val1);
        (*info->fprintf_func) (info->stream, "%s@(%d)", reg_names[val1 + 8], val);
        break;
@@ -952,14 +968,14 @@ print_insn_arg (const char *d,
       else if (val == 3)
        (*info->fprintf_func) (info->stream, ">>");
       else
-       return -1;
+       return PRINT_INSN_ARG_INVALID_OPERAND;
       break;
 
     case 'I':
       /* Get coprocessor ID... */
       val = fetch_arg (buffer, 'd', 3, info);
       if (val < 0)
-       return -3;
+       return PRINT_INSN_ARG_MEMORY_ERROR;
       if (val != 1)                            /* Unusual coprocessor ID?  */
        (*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
       break;
@@ -992,19 +1008,19 @@ print_insn_arg (const char *d,
        {
          val = fetch_arg (buffer, 'x', 6, info);
          if (val < 0)
-           return -3;
+           return PRINT_INSN_ARG_MEMORY_ERROR;
          val = ((val & 7) << 3) + ((val >> 3) & 7);
        }
       else
        {
          val = fetch_arg (buffer, 's', 6, info);
          if (val < 0)
-           return -3;
+           return PRINT_INSN_ARG_MEMORY_ERROR;
        }
 
       /* If the <ea> is invalid for *d, then reject this match.  */
       if (!m68k_valid_ea (*d, val))
-       return -1;
+       return PRINT_INSN_ARG_INVALID_OPERAND;
 
       /* Get register number assuming address register.  */
       regno = (val & 7) + 8;
@@ -1032,21 +1048,21 @@ print_insn_arg (const char *d,
          break;
 
        case 5:
-         NEXTWORD (p, val, -3);
+         NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
          (*info->fprintf_func) (info->stream, "%s@(%d)", regname, val);
          break;
 
        case 6:
          p = print_indexed (regno, p, addr, info);
          if (p == NULL)
-           return -3;
+           return PRINT_INSN_ARG_MEMORY_ERROR;
          break;
 
        case 7:
          switch (val & 7)
            {
            case 0:
-             NEXTWORD (p, val, -3);
+             NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
              (*info->print_address_func) (val, info);
              break;
 
@@ -1056,7 +1072,7 @@ print_insn_arg (const char *d,
              break;
 
            case 2:
-             NEXTWORD (p, val, -3);
+             NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
              (*info->fprintf_func) (info->stream, "%%pc@(");
              (*info->print_address_func) (addr + val, info);
              (*info->fprintf_func) (info->stream, ")");
@@ -1065,7 +1081,7 @@ print_insn_arg (const char *d,
            case 3:
              p = print_indexed (-1, p, addr, info);
              if (p == NULL)
-               return -3;
+               return PRINT_INSN_ARG_MEMORY_ERROR;
              break;
 
            case 4:
@@ -1078,12 +1094,12 @@ print_insn_arg (const char *d,
                  break;
 
                case 'w':
-                 NEXTWORD (p, val, -3);
+                 NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
                  flt_p = 0;
                  break;
 
                case 'l':
-                 NEXTLONG (p, val, -3);
+                 NEXTLONG (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
                  flt_p = 0;
                  break;
 
@@ -1104,7 +1120,7 @@ print_insn_arg (const char *d,
                  break;
 
                default:
-                 return -1;
+                 return PRINT_INSN_ARG_INVALID_OPERAND;
              }
              if (flt_p)        /* Print a float? */
                (*info->fprintf_func) (info->stream, "#0e%g", flval);
@@ -1113,7 +1129,7 @@ print_insn_arg (const char *d,
              break;
 
            default:
-             return -1;
+             return PRINT_INSN_ARG_INVALID_OPERAND;
            }
        }
 
@@ -1134,7 +1150,7 @@ print_insn_arg (const char *d,
          {
            char doneany;
            p1 = buffer + 2;
-           NEXTWORD (p1, val, -3);
+           NEXTWORD (p1, val, PRINT_INSN_ARG_MEMORY_ERROR);
            /* Move the pointer ahead if this point is farther ahead
               than the last.  */
            p = p1 > p ? p1 : p;
@@ -1215,11 +1231,12 @@ print_insn_arg (const char *d,
            (*info->fprintf_func) (info->stream, "%s", fpcr_names[val]);
          }
        else
-         return -2;
+         return PRINT_INSN_ARG_INVALID_OP_TABLE;
       break;
 
     case 'X':
       place = '8';
+      /* Fall through.  */
     case 'Y':
     case 'Z':
     case 'W':
@@ -1309,14 +1326,15 @@ print_insn_arg (const char *d,
       break;
 
     default:
-      return -2;
+      return PRINT_INSN_ARG_INVALID_OP_TABLE;
     }
 
   return p - p0;
 }
 
 /* Try to match the current instruction to best and if so, return the
-   number of bytes consumed from the instruction stream, else zero.  */
+   number of bytes consumed from the instruction stream, else zero.
+   Return -1 on memory error.  */
 
 static int
 match_insn_m68k (bfd_vma memaddr,
@@ -1400,12 +1418,14 @@ match_insn_m68k (bfd_vma memaddr,
         this because we know exactly what the second word is, and we
         aren't going to print anything based on it.  */
       p = buffer + 6;
-      FETCH_DATA (info, p);
+      if (!FETCH_DATA (info, p))
+       return -1;
       buffer[2] = buffer[4];
       buffer[3] = buffer[5];
     }
 
-  FETCH_DATA (info, p);
+  if (!FETCH_DATA (info, p))
+    return -1;
 
   save_p = p;
   info->print_address_func = dummy_print_address;
@@ -1419,11 +1439,12 @@ match_insn_m68k (bfd_vma memaddr,
 
       if (eaten >= 0)
        p += eaten;
-      else if (eaten == -1 || eaten == -3)
+      else if (eaten == PRINT_INSN_ARG_INVALID_OPERAND
+              || eaten == PRINT_INSN_ARG_MEMORY_ERROR)
        {
          info->fprintf_func = save_printer;
          info->print_address_func = save_print_address;
-         return 0;
+         return eaten == PRINT_INSN_ARG_MEMORY_ERROR ? -1 : 0;
        }
       else
        {
@@ -1465,7 +1486,8 @@ match_insn_m68k (bfd_vma memaddr,
 /* Try to interpret the instruction at address MEMADDR as one that
    can execute on a processor with the features given by ARCH_MASK.
    If successful, print the instruction to INFO->STREAM and return
-   its length in bytes.  Return 0 otherwise.  */
+   its length in bytes.  Return 0 otherwise.  Return -1 on memory
+   error.  */
 
 static int
 m68k_scan_mask (bfd_vma memaddr, disassemble_info *info,
@@ -1507,7 +1529,8 @@ m68k_scan_mask (bfd_vma memaddr, disassemble_info *info,
        *opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i];
     }
 
-  FETCH_DATA (info, buffer + 2);
+  if (!FETCH_DATA (info, buffer + 2))
+    return -1;
   major_opcode = (buffer[0] >> 4) & 15;
 
   for (i = 0; i < numopcodes[major_opcode]; i++)
@@ -1612,7 +1635,7 @@ print_insn_m68k (bfd_vma memaddr, disassemble_info *info)
       /* First try printing an m680x0 instruction.  Try printing a Coldfire
         one if that fails.  */
       val = m68k_scan_mask (memaddr, info, m68k_mask);
-      if (val == 0)
+      if (val <= 0)
        val = m68k_scan_mask (memaddr, info, mcf_mask);
     }
   else