x86: replace Reg8, Reg16, Reg32, and Reg64
[deliverable/binutils-gdb.git] / gas / config / tc-sparc.c
index f0a100555d358e4eb386b419b535bb9023ef85be..6d1b038daa23c8cd1485871f7649c7c9e4bfe110 100644 (file)
@@ -36,6 +36,7 @@
 #define U0x80000000 ((((unsigned long) 1 << 16) << 15))
 
 static int sparc_ip (char *, const struct sparc_opcode **);
+static int parse_sparc_asi (char **, const sparc_asi **);
 static int parse_keyword_arg (int (*) (const char *), char **, int *);
 static int parse_const_expr_arg (char **, int *);
 static int get_expression (char *);
@@ -255,6 +256,7 @@ static struct sparc_arch {
 
   { "sparc4",     "v9v", v9,  0, 1, 0, 0 },
   { "sparc5",     "v9m", v9,  0, 1, 0, 0 },
+  { "sparc6",     "m8",  v9,  0, 1, 0, 0 },
 
   { "leon",      "leon",      leon,      32, 1, 0, 0 },
   { "sparclet",  "sparclet",  sparclet,  32, 1, 0, 0 },
@@ -269,7 +271,8 @@ static struct sparc_arch {
   { "v8pluse", "v9e", v9,  0, 1, HWCAP_V8PLUS, 0 },
   { "v8plusv", "v9v", v9,  0, 1, HWCAP_V8PLUS, 0 },
   { "v8plusm", "v9m", v9,  0, 1, HWCAP_V8PLUS, 0 },
-
+  { "v8plusm8", "m8", v9,  0, 1, HWCAP_V8PLUS, 0 },
+  
   { "v9",      "v9",  v9,  0, 1, 0, 0 },
   { "v9a",     "v9a", v9,  0, 1, 0, 0 },
   { "v9b",     "v9b", v9,  0, 1, 0, 0 },
@@ -278,6 +281,7 @@ static struct sparc_arch {
   { "v9e",     "v9e", v9,  0, 1, 0, 0 },
   { "v9v",     "v9v", v9,  0, 1, 0, 0 },
   { "v9m",     "v9m", v9,  0, 1, 0, 0 },
+  { "v9m8",     "m8", v9,  0, 1, 0, 0 },
 
   /* This exists to allow configure.tgt to pass one
      value to specify both the default machine and default word size.  */
@@ -1130,7 +1134,7 @@ md_begin (void)
        p->pop = &pop_table[i];
       }
 
-    /* Last entry is the centinel.  */
+    /* Last entry is the sentinel.  */
     perc_table[entry].type = perc_entry_none;
 
     qsort (perc_table, sizeof (perc_table) / sizeof (perc_table[0]),
@@ -1159,6 +1163,7 @@ sparc_md_end (void)
       case SPARC_OPCODE_ARCH_V9E: mach = bfd_mach_sparc_v9e; break;
       case SPARC_OPCODE_ARCH_V9V: mach = bfd_mach_sparc_v9v; break;
       case SPARC_OPCODE_ARCH_V9M: mach = bfd_mach_sparc_v9m; break;
+      case SPARC_OPCODE_ARCH_M8:  mach = bfd_mach_sparc_v9m8; break;
       default: mach = bfd_mach_sparc_v9; break;
       }
   else
@@ -1173,6 +1178,7 @@ sparc_md_end (void)
       case SPARC_OPCODE_ARCH_V9E: mach = bfd_mach_sparc_v8pluse; break;
       case SPARC_OPCODE_ARCH_V9V: mach = bfd_mach_sparc_v8plusv; break;
       case SPARC_OPCODE_ARCH_V9M: mach = bfd_mach_sparc_v8plusm; break;
+      case SPARC_OPCODE_ARCH_M8:  mach = bfd_mach_sparc_v8plusm8; break;
       /* The sparclite is treated like a normal sparc.  Perhaps it shouldn't
         be but for now it is (since that's the way it's always been
         treated).  */
@@ -1743,6 +1749,22 @@ get_hwcap_name (bfd_uint64_t mask)
     return "xmont";
   if (mask & HWCAP2_NSEC)
     return "nsec";
+  if (mask & HWCAP2_SPARC6)
+    return "sparc6";
+  if (mask & HWCAP2_ONADDSUB)
+    return "onaddsub";
+  if (mask & HWCAP2_ONMUL)
+    return "onmul";
+  if (mask & HWCAP2_ONDIV)
+    return "ondiv";
+  if (mask & HWCAP2_DICTUNP)
+    return "dictunp";
+  if (mask & HWCAP2_FPCMPSHL)
+    return "fpcmpshl";
+  if (mask & HWCAP2_RLE)
+    return "rle";
+  if (mask & HWCAP2_SHA3)
+    return "sha3";
 
   return "UNKNOWN";
 }
@@ -1764,6 +1786,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
   int comma = 0;
   int v9_arg_p;
   int special_case = SPECIAL_CASE_NONE;
+  const sparc_asi *sasi = NULL;
 
   s = str;
   if (ISLOWER (*s))
@@ -2530,10 +2553,13 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
            case 'e':           /* next operand is a floating point register */
            case 'v':
            case 'V':
+            case ';':
 
            case 'f':
            case 'B':
            case 'R':
+            case ':':
+            case '\'':
 
            case '4':
            case '5':
@@ -2542,6 +2568,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
            case 'H':
            case 'J':
            case '}':
+            case '^':
              {
                char format;
 
@@ -2560,6 +2587,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
                         || *args == 'B'
                         || *args == '5'
                         || *args == 'H'
+                         || *args == '\''
                         || format == 'd')
                        && (mask & 1))
                      {
@@ -2577,6 +2605,21 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
                        break;
                      }
 
+                    if ((*args == ':'
+                         || *args == ';'
+                         || *args == '^')
+                        && (mask & 7))
+                      {
+                        /* register must be multiple of 8 */
+                        break;
+                      }
+
+                    if (*args == '\'' && mask < 48)
+                      {
+                        /* register must be higher or equal than %f48 */
+                        break;
+                      }
+
                    if (mask >= 64)
                      {
                        if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
@@ -2622,15 +2665,21 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
                  case 'v':
                  case 'V':
                  case 'e':
+                  case ';':
                    opcode |= RS1 (mask);
                    continue;
 
                  case 'f':
                  case 'B':
                  case 'R':
+                  case ':':
                    opcode |= RS2 (mask);
                    continue;
 
+                  case '\'':
+                    opcode |= RS2 (mask & 0xe);
+                    continue;
+                    
                  case '4':
                  case '5':
                    opcode |= RS3 (mask);
@@ -2640,6 +2689,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
                  case 'H':
                  case 'J':
                  case '}':
+                  case '^':
                    opcode |= RD (mask);
                    continue;
                  }             /* Pack it in.  */
@@ -2969,11 +3019,12 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
                /* Parse an asi.  */
                if (*s == '#')
                  {
-                   if (! parse_keyword_arg (sparc_encode_asi, &s, &asi))
+                   if (! parse_sparc_asi (&s, &sasi))
                      {
                        error_message = _(": invalid ASI name");
                        goto error;
                      }
+                   asi = sasi->value;
                  }
                else
                  {
@@ -3058,6 +3109,12 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
              s += 7;
              continue;
 
+            case '&':
+              if (strncmp (s, "%entropy", 8) != 0)
+                break;
+              s += 8;
+              continue;
+
            case 'E':
              if (strncmp (s, "%ccr", 4) != 0)
                break;
@@ -3076,6 +3133,26 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
              s += 4;
              continue;
 
+            case '|':
+              {
+                int imm2 = 0;
+
+                /* Parse a 2-bit immediate.  */
+                if (! parse_const_expr_arg (&s, &imm2))
+                  {
+                    error_message = _(": non-immdiate imm2 operand");
+                    goto error;
+                  }
+                if ((imm2 & ~0x3) != 0)
+                  {
+                    error_message = _(": imm2 immediate operand out of range (0-3)");
+                    goto error;
+                  }
+
+                opcode |= ((imm2 & 0x2) << 3) | (imm2 & 0x1);
+                continue;
+              }
+              
            case 'x':
              {
                char *push = input_line_pointer;
@@ -3147,8 +3224,18 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
       else
        {
          /* We have a match.  Now see if the architecture is OK.  */
+         /* String to use in case of architecture warning.  */
+         const char *msg_str = str;
          int needed_arch_mask = insn->architecture;
-         bfd_uint64_t hwcaps
+
+          /* Include the ASI architecture needed as well */
+          if (sasi && needed_arch_mask > sasi->architecture)
+            {
+              needed_arch_mask = sasi->architecture;
+              msg_str = sasi->name;
+            }
+
+          bfd_uint64_t hwcaps
            = (((bfd_uint64_t) insn->hwcaps2) << 32) | insn->hwcaps;
 
 #if defined(OBJ_ELF) && !defined(TE_SOLARIS)
@@ -3183,7 +3270,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
                  as_warn (_("architecture bumped from \"%s\" to \"%s\" on \"%s\""),
                           sparc_opcode_archs[current_architecture].name,
                           sparc_opcode_archs[needed_architecture].name,
-                          str);
+                          msg_str);
                  warn_after_architecture = needed_architecture;
                }
              current_architecture = needed_architecture;
@@ -3222,7 +3309,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
                }
 
              as_bad (_("Architecture mismatch on \"%s %s\"."), str, argsStart);
-             as_tsktsk (_(" (Requires %s; requested architecture is %s.)"),
+             as_tsktsk (_("(Requires %s; requested architecture is %s.)"),
                         required_archs,
                         sparc_opcode_archs[max_architecture].name);
              return special_case;
@@ -3247,6 +3334,35 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
   return special_case;
 }
 
+static char *
+skip_over_keyword (char *q)
+{
+  for (q = q + (*q == '#' || *q == '%');
+       ISALNUM (*q) || *q == '_';
+       ++q)
+    continue;
+  return q;
+}
+
+static int
+parse_sparc_asi (char **input_pointer_p, const sparc_asi **value_p)
+{
+  const sparc_asi *value;
+  char c, *p, *q;
+
+  p = *input_pointer_p;
+  q = skip_over_keyword(p);
+  c = *q;
+  *q = 0;
+  value = sparc_encode_asi (p);
+  *q = c;
+  if (value == NULL)
+    return 0;
+  *value_p = value;
+  *input_pointer_p = q;
+  return 1;
+}
+
 /* Parse an argument that can be expressed as a keyword.
    (eg: #StoreStore or %ccfr).
    The result is a boolean indicating success.
@@ -3261,10 +3377,7 @@ parse_keyword_arg (int (*lookup_fn) (const char *),
   char c, *p, *q;
 
   p = *input_pointerP;
-  for (q = p + (*p == '#' || *p == '%');
-       ISALNUM (*q) || *q == '_';
-       ++q)
-    continue;
+  q = skip_over_keyword(p);
   c = *q;
   *q = 0;
   value = (*lookup_fn) (p);
@@ -3545,8 +3658,13 @@ md_apply_fix (fixS *fixP, valueT *valP, segT segment ATTRIBUTE_UNUSED)
 
          insn |= val & 0x3fffffff;
 
-         /* See if we have a delay slot.  */
-         if (sparc_relax && fixP->fx_where + 8 <= fixP->fx_frag->fr_fix)
+         /* See if we have a delay slot.  In that case we attempt to
+             optimize several cases transforming CALL instructions
+             into branches.  But we can only do that if the relocation
+             can be completely resolved here, i.e. if no undefined
+             symbol is associated with it.  */
+         if (sparc_relax && fixP->fx_addsy == NULL
+             && fixP->fx_where + 8 <= fixP->fx_frag->fr_fix)
            {
 #define G0             0
 #define O7             15
@@ -3828,8 +3946,33 @@ tc_gen_reloc (asection *section, fixS *fixp)
 
   switch (fixp->fx_r_type)
     {
+    case BFD_RELOC_8:
     case BFD_RELOC_16:
     case BFD_RELOC_32:
+    case BFD_RELOC_64:
+      if (fixp->fx_pcrel)
+       {
+         switch (fixp->fx_size)
+           {
+           default:
+             as_bad_where (fixp->fx_file, fixp->fx_line,
+                           _("can not do %d byte pc-relative relocation"),
+                           fixp->fx_size);
+             code = fixp->fx_r_type;
+             fixp->fx_pcrel = 0;
+             break;
+           case 1: code = BFD_RELOC_8_PCREL;  break;
+           case 2: code = BFD_RELOC_16_PCREL; break;
+           case 4: code = BFD_RELOC_32_PCREL; break;
+#ifdef BFD64
+           case 8: code = BFD_RELOC_64_PCREL; break;
+#endif
+           }
+         if (fixp->fx_pcrel)
+           fixp->fx_addnumber = fixp->fx_offset;
+         break;
+       }
+      /* Fall through.  */
     case BFD_RELOC_HI22:
     case BFD_RELOC_LO10:
     case BFD_RELOC_32_PCREL_S2:
@@ -3842,7 +3985,6 @@ tc_gen_reloc (asection *section, fixS *fixp)
     case BFD_RELOC_SPARC_WDISP16:
     case BFD_RELOC_SPARC_WDISP19:
     case BFD_RELOC_SPARC_WDISP22:
-    case BFD_RELOC_64:
     case BFD_RELOC_SPARC_5:
     case BFD_RELOC_SPARC_6:
     case BFD_RELOC_SPARC_7:
This page took 0.031147 seconds and 4 git commands to generate.