gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / opcodes / sparc-dis.c
index b0899a69ae9b7c303ce96a343f4f34cb92d4d1f2..c9667f172b40226905a9642508611e4701a75809 100644 (file)
@@ -1,7 +1,5 @@
 /* Print SPARC instructions.
-   Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 1989-2020 Free Software Foundation, Inc.
 
    This file is part of the GNU opcodes library.
 
@@ -20,9 +18,8 @@
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
    MA 02110-1301, USA.  */
 
-#include <stdio.h>
-
 #include "sysdep.h"
+#include <stdio.h>
 #include "opcode/sparc.h"
 #include "dis-asm.h"
 #include "libiberty.h"
 /* Bitmask of v9 architectures.  */
 #define MASK_V9 ((1 << SPARC_OPCODE_ARCH_V9) \
                 | (1 << SPARC_OPCODE_ARCH_V9A) \
-                | (1 << SPARC_OPCODE_ARCH_V9B))
+                | (1 << SPARC_OPCODE_ARCH_V9B) \
+                | (1 << SPARC_OPCODE_ARCH_V9C) \
+                | (1 << SPARC_OPCODE_ARCH_V9D) \
+                | (1 << SPARC_OPCODE_ARCH_V9E) \
+                | (1 << SPARC_OPCODE_ARCH_V9V) \
+                | (1 << SPARC_OPCODE_ARCH_V9M) \
+                | (1 << SPARC_OPCODE_ARCH_M8))
 /* 1 if INSN is for v9 only.  */
 #define V9_ONLY_P(insn) (! ((insn)->architecture & ~MASK_V9))
 /* 1 if INSN is for v9.  */
@@ -60,8 +63,8 @@ static sparc_opcode_hash *opcode_hash_table[HASH_SIZE];
 
 /* Sign-extend a value which is N bits long.  */
 #define        SEX(value, bits) \
-       ((((int)(value)) << ((8 * sizeof (int)) - bits))        \
-                        >> ((8 * sizeof (int)) - bits) )
+  ((int) (((value & ((1u << (bits - 1) << 1) - 1))     \
+          ^ (1u << (bits - 1))) - (1u << (bits - 1))))
 
 static  char *reg_names[] =
 { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
@@ -89,7 +92,7 @@ static char *v9_priv_reg_names[] =
   "tpc", "tnpc", "tstate", "tt", "tick", "tba", "pstate", "tl",
   "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin",
   "wstate", "fq", "gl"
-  /* "ver" - special cased */
+  /* "ver" and "pmcdper" - special cased */
 };
 
 /* These are ordered according to there register number in
@@ -97,19 +100,19 @@ static char *v9_priv_reg_names[] =
 static char *v9_hpriv_reg_names[] =
 {
   "hpstate", "htstate", "resv2", "hintp", "resv4", "htba", "hver",
-  "resv7", "resv8", "resv9", "resv10", "resv11", "resv12", "resv13", 
+  "resv7", "resv8", "resv9", "resv10", "resv11", "resv12", "resv13",
   "resv14", "resv15", "resv16", "resv17", "resv18", "resv19", "resv20",
-  "resv21", "resv22", "resv23", "resv24", "resv25", "resv26", "resv27",
-  "resv28", "resv29", "resv30", "hstick_cmpr"
+  "resv21", "resv22", "hmcdper", "hmcddfr", "resv25", "resv26", "hva_mask_nz",
+  "hstick_offset", "hstick_enable", "resv30", "hstick_cmpr"
 };
 
 /* These are ordered according to there register number in
    rd and wr insns (-16).  */
 static char *v9a_asr_reg_names[] =
 {
-  "pcr", "pic", "dcr", "gsr", "set_softint", "clear_softint",
+  "pcr", "pic", "dcr", "gsr", "softint_set", "softint_clear",
   "softint", "tick_cmpr", "stick", "stick_cmpr", "cfr",
-  "pause", "cps"
+  "pause", "mwait"
 };
 
 /* Macros used to extract instruction fields.  Not all fields have
@@ -126,6 +129,7 @@ static char *v9a_asr_reg_names[] =
 #define X_DISP22(i)  (((i) >> 0) & 0x3fffff)
 #define X_IMM22(i)   X_DISP22 (i)
 #define X_DISP30(i)  (((i) >> 0) & 0x3fffffff)
+#define X_IMM2(i)    (((i & 0x10) >> 3) | (i & 0x1))
 
 /* These are for v9.  */
 #define X_DISP16(i)  (((((i) >> 20) & 3) << 14) | (((i) >> 0) & 0x3fff))
@@ -224,7 +228,8 @@ compute_arch_mask (unsigned long mach)
     {
     case 0 :
     case bfd_mach_sparc :
-      return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8);
+      return (SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8)
+              | SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_LEON));
     case bfd_mach_sparc_sparclet :
       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLET);
     case bfd_mach_sparc_sparclite :
@@ -243,6 +248,24 @@ compute_arch_mask (unsigned long mach)
     case bfd_mach_sparc_v8plusb :
     case bfd_mach_sparc_v9b :
       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9B);
+    case bfd_mach_sparc_v8plusc :
+    case bfd_mach_sparc_v9c :
+      return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9C);
+    case bfd_mach_sparc_v8plusd :
+    case bfd_mach_sparc_v9d :
+      return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9D);
+    case bfd_mach_sparc_v8pluse :
+    case bfd_mach_sparc_v9e :
+      return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9E);
+    case bfd_mach_sparc_v8plusv :
+    case bfd_mach_sparc_v9v :
+      return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9V);
+    case bfd_mach_sparc_v8plusm :
+    case bfd_mach_sparc_v9m :
+      return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9M);
+    case bfd_mach_sparc_v8plusm8 :
+    case bfd_mach_sparc_v9m8 :
+      return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_M8);
     }
   abort ();
 }
@@ -280,10 +303,9 @@ compare_opcodes (const void * a, const void * b)
      wrong with the opcode table.  */
   if (match0 & lose0)
     {
-      fprintf
-       (stderr,
-        /* xgettext:c-format */
-        _("Internal error:  bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
+      opcodes_error_handler
+       /* xgettext:c-format */
+       (_("internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
         op0->name, match0, lose0);
       op0->lose &= ~op0->match;
       lose0 = op0->lose;
@@ -291,10 +313,9 @@ compare_opcodes (const void * a, const void * b)
 
   if (match1 & lose1)
     {
-      fprintf
-       (stderr,
-        /* xgettext:c-format */
-        _("Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
+      opcodes_error_handler
+       /* xgettext:c-format */
+       (_("internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
         op1->name, match1, lose1);
       op1->lose &= ~op1->match;
       lose1 = op1->lose;
@@ -304,7 +325,7 @@ compare_opcodes (const void * a, const void * b)
      another, it is important to order the opcodes in the right order.  */
   for (i = 0; i < 32; ++i)
     {
-      unsigned long int x = 1 << i;
+      unsigned long int x = 1ul << i;
       int x0 = (match0 & x) != 0;
       int x1 = (match1 & x) != 0;
 
@@ -314,7 +335,7 @@ compare_opcodes (const void * a, const void * b)
 
   for (i = 0; i < 32; ++i)
     {
-      unsigned long int x = 1 << i;
+      unsigned long int x = 1ul << i;
       int x0 = (lose0 & x) != 0;
       int x1 = (lose1 & x) != 0;
 
@@ -339,13 +360,22 @@ compare_opcodes (const void * a, const void * b)
   i = strcmp (op0->name, op1->name);
   if (i)
     {
-      if (op0->flags & F_ALIAS) /* If they're both aliases, be arbitrary.  */
-       return i;
+      if (op0->flags & F_ALIAS)
+       {
+         if (op0->flags & F_PREFERRED)
+           return -1;
+         if (op1->flags & F_PREFERRED)
+           return 1;
+
+         /* If they're both aliases, and neither is marked as preferred,
+            be arbitrary.  */
+         return i;
+       }
       else
-       fprintf (stderr,
-                /* xgettext:c-format */
-                _("Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n"),
-                op0->name, op1->name);
+       opcodes_error_handler
+         /* xgettext:c-format */
+         (_("internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n"),
+          op0->name, op1->name);
     }
 
   /* Fewer arguments are preferred.  */
@@ -411,8 +441,7 @@ build_hash_table (const sparc_opcode **opcode_table,
 
   memset (hash_table, 0, HASH_SIZE * sizeof (hash_table[0]));
   memset (hash_count, 0, HASH_SIZE * sizeof (hash_count[0]));
-  if (hash_buf != NULL)
-    free (hash_buf);
+  free (hash_buf);
   hash_buf = xmalloc (sizeof (* hash_buf) * num_opcodes);
   for (i = num_opcodes - 1; i >= 0; --i)
     {
@@ -551,7 +580,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
              /* Can't do simple format if source and dest are different.  */
              continue;
 
-         (*info->fprintf_func) (stream, opcode->name);
+         (*info->fprintf_func) (stream, "%s", opcode->name);
 
          {
            const char *s;
@@ -626,6 +655,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
                    break;
                  case 'v':     /* Double/even.  */
                  case 'V':     /* Quad/multiple of 4.  */
+                  case ';':    /* Double/even multiple of 8 doubles.  */
                    fregx (X_RS1 (insn));
                    break;
 
@@ -634,6 +664,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
                    break;
                  case 'B':     /* Double/even.  */
                  case 'R':     /* Quad/multiple of 4.  */
+                  case ':':    /* Double/even multiple of 8 doubles.  */
                    fregx (X_RS2 (insn));
                    break;
 
@@ -649,8 +680,18 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
                    break;
                  case 'H':     /* Double/even.  */
                  case 'J':     /* Quad/multiple of 4.  */
+                 case '}':     /* Double/even.  */
                    fregx (X_RD (insn));
                    break;
+                    
+                  case '^':    /* Double/even multiple of 8 doubles.  */
+                    fregx (X_RD (insn) & ~0x6);
+                    break;
+                    
+                  case '\'':   /* Double/even in FPCMPSHL.  */
+                    fregx (X_RS2 (insn | 0x11));
+                    break;
+                    
 #undef freg
 #undef fregx
 
@@ -670,8 +711,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
 
                  case 'h':
                    (*info->fprintf_func) (stream, "%%hi(%#x)",
-                                          ((unsigned) 0xFFFFFFFF
-                                           & ((int) X_IMM22 (insn) << 10)));
+                                          (unsigned) X_IMM22 (insn) << 10);
                    break;
 
                  case 'i':     /* 13 bit immediate.  */
@@ -705,7 +745,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
                    break;
 
                  case ')':     /* 5 bit unsigned immediate from RS3.  */
-                   (info->fprintf_func) (stream, "%#x", X_RS3 (insn));
+                   (info->fprintf_func) (stream, "%#x", (unsigned int) X_RS3 (insn));
                    break;
 
                  case 'X':     /* 5 bit unsigned immediate.  */
@@ -786,6 +826,14 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
                    (*info->fprintf_func) (stream, "%%fprs");
                    break;
 
+                 case '{':
+                   (*info->fprintf_func) (stream, "%%mcdper");
+                   break;
+
+                  case '&':
+                    (*info->fprintf_func) (stream, "%%entropy");
+                    break;
+
                  case 'o':
                    (*info->fprintf_func) (stream, "%%asi");
                    break;
@@ -801,6 +849,8 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
                  case '?':
                    if (X_RS1 (insn) == 31)
                      (*info->fprintf_func) (stream, "%%ver");
+                   else if (X_RS1 (insn) == 23)
+                     (*info->fprintf_func) (stream, "%%pmcdper");
                    else if ((unsigned) X_RS1 (insn) < 17)
                      (*info->fprintf_func) (stream, "%%%s",
                                             v9_priv_reg_names[X_RS1 (insn)]);
@@ -809,7 +859,11 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
                    break;
 
                  case '!':
-                   if ((unsigned) X_RD (insn) < 17)
+                    if (X_RD (insn) == 31)
+                      (*info->fprintf_func) (stream, "%%ver");
+                   else if (X_RD (insn) == 23)
+                     (*info->fprintf_func) (stream, "%%pmcdper");
+                   else if ((unsigned) X_RD (insn) < 17)
                      (*info->fprintf_func) (stream, "%%%s",
                                             v9_priv_reg_names[X_RD (insn)]);
                    else
@@ -931,6 +985,10 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
                                            + X_ASI (insn)));
                    break;
 
+                  case '|': /* 2-bit immediate  */
+                    (*info->fprintf_func) (stream, "%ld", X_IMM2 (insn));
+                    break;
+
                  case 'y':
                    (*info->fprintf_func) (stream, "%%y");
                    break;
@@ -1002,9 +1060,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
                      && X_RD (prev_insn) == X_RS1 (insn))
                    {
                      (*info->fprintf_func) (stream, "\t! ");
-                     info->target =
-                       ((unsigned) 0xFFFFFFFF
-                        & ((int) X_IMM22 (prev_insn) << 10));
+                     info->target = (unsigned) X_IMM22 (prev_insn) << 10;
                      if (imm_added_to_rs1)
                        info->target += X_SIMM (insn, 13);
                      else
This page took 0.044941 seconds and 4 git commands to generate.