Add support for Intel TDX instructions.
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index be894782a457a6e7902d86b5ed9142102c944e77..4891c45a1ab22a882ad6db116bf312ad9f96d2af 100644 (file)
@@ -290,8 +290,10 @@ enum i386_error
     unsupported_with_intel_mnemonic,
     unsupported_syntax,
     unsupported,
+    invalid_sib_address,
     invalid_vsib_address,
     invalid_vector_register_set,
+    invalid_tmm_register_set,
     unsupported_vector_index_register,
     unsupported_broadcast,
     broadcast_needed,
@@ -360,17 +362,20 @@ struct _i386_insn
     /* The operand to a branch insn indicates an absolute branch.  */
     bfd_boolean jumpabsolute;
 
-    /* Has MMX register operands.  */
-    bfd_boolean has_regmmx;
-
-    /* Has XMM register operands.  */
-    bfd_boolean has_regxmm;
-
-    /* Has YMM register operands.  */
-    bfd_boolean has_regymm;
-
-    /* Has ZMM register operands.  */
-    bfd_boolean has_regzmm;
+    /* Extended states.  */
+    enum
+      {
+       /* Use MMX state.  */
+       xstate_mmx = 1 << 0,
+       /* Use XMM state.  */
+       xstate_xmm = 1 << 1,
+       /* Use YMM state.  */
+       xstate_ymm = 1 << 2 | xstate_xmm,
+       /* Use ZMM state.  */
+       xstate_zmm = 1 << 3 | xstate_ymm,
+       /* Use TMM state.  */
+       xstate_tmm = 1 << 4
+      } xstate;
 
     /* Has GOTPC or TLS relocation.  */
     bfd_boolean has_gotpc_tls_reloc;
@@ -404,11 +409,12 @@ struct _i386_insn
        dir_encoding_swap
       } dir_encoding;
 
-    /* Prefer 8bit or 32bit displacement in encoding.  */
+    /* Prefer 8bit, 16bit, 32bit displacement in encoding.  */
     enum
       {
        disp_encoding_default = 0,
        disp_encoding_8bit,
+       disp_encoding_16bit,
        disp_encoding_32bit
       } disp_encoding;
 
@@ -475,14 +481,12 @@ const char extra_symbol_chars[] = "*%-([{}"
 #endif
        ;
 
-#if (defined (TE_I386AIX)                              \
-     || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))        \
-        && !defined (TE_GNU)                           \
-        && !defined (TE_LINUX)                         \
-        && !defined (TE_NACL)                          \
-        && !defined (TE_FreeBSD)                       \
-        && !defined (TE_DragonFly)                     \
-        && !defined (TE_NetBSD)))
+#if ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))    \
+     && !defined (TE_GNU)                              \
+     && !defined (TE_LINUX)                            \
+     && !defined (TE_FreeBSD)                          \
+     && !defined (TE_DragonFly)                                \
+     && !defined (TE_NetBSD))
 /* This array holds the chars that always start a comment.  If the
    pre-processor is disabled, these aren't very useful.  The option
    --divide will remove '/' from this list.  */
@@ -1202,6 +1206,12 @@ static const arch_entry cpu_arch[] =
     CPU_WAITPKG_FLAGS, 0 },
   { STRING_COMMA_LEN (".cldemote"), PROCESSOR_UNKNOWN,
     CPU_CLDEMOTE_FLAGS, 0 },
+  { STRING_COMMA_LEN (".amx_int8"), PROCESSOR_UNKNOWN,
+    CPU_AMX_INT8_FLAGS, 0 },
+  { STRING_COMMA_LEN (".amx_bf16"), PROCESSOR_UNKNOWN,
+    CPU_AMX_BF16_FLAGS, 0 },
+  { STRING_COMMA_LEN (".amx_tile"), PROCESSOR_UNKNOWN,
+    CPU_AMX_TILE_FLAGS, 0 },
   { STRING_COMMA_LEN (".movdiri"), PROCESSOR_UNKNOWN,
     CPU_MOVDIRI_FLAGS, 0 },
   { STRING_COMMA_LEN (".movdir64b"), PROCESSOR_UNKNOWN,
@@ -1210,6 +1220,8 @@ static const arch_entry cpu_arch[] =
     CPU_AVX512_BF16_FLAGS, 0 },
   { STRING_COMMA_LEN (".avx512_vp2intersect"), PROCESSOR_UNKNOWN,
     CPU_AVX512_VP2INTERSECT_FLAGS, 0 },
+  { STRING_COMMA_LEN (".tdx"), PROCESSOR_UNKNOWN,
+    CPU_TDX_FLAGS, 0 },
   { STRING_COMMA_LEN (".enqcmd"), PROCESSOR_UNKNOWN,
     CPU_ENQCMD_FLAGS, 0 },
   { STRING_COMMA_LEN (".serialize"), PROCESSOR_UNKNOWN,
@@ -1222,6 +1234,10 @@ static const arch_entry cpu_arch[] =
     CPU_SEV_ES_FLAGS, 0 },
   { STRING_COMMA_LEN (".tsxldtrk"), PROCESSOR_UNKNOWN,
     CPU_TSXLDTRK_FLAGS, 0 },
+  { STRING_COMMA_LEN (".kl"), PROCESSOR_UNKNOWN,
+    CPU_KL_FLAGS, 0 },
+  { STRING_COMMA_LEN (".widekl"), PROCESSOR_UNKNOWN,
+    CPU_WIDEKL_FLAGS, 0 },
 };
 
 static const noarch_entry cpu_noarch[] =
@@ -1260,14 +1276,20 @@ static const noarch_entry cpu_noarch[] =
   { STRING_COMMA_LEN ("noavx512_bitalg"), CPU_ANY_AVX512_BITALG_FLAGS },
   { STRING_COMMA_LEN ("noibt"), CPU_ANY_IBT_FLAGS },
   { STRING_COMMA_LEN ("noshstk"), CPU_ANY_SHSTK_FLAGS },
+  { STRING_COMMA_LEN ("noamx_int8"), CPU_ANY_AMX_INT8_FLAGS },
+  { STRING_COMMA_LEN ("noamx_bf16"), CPU_ANY_AMX_BF16_FLAGS },
+  { STRING_COMMA_LEN ("noamx_tile"), CPU_ANY_AMX_TILE_FLAGS },
   { STRING_COMMA_LEN ("nomovdiri"), CPU_ANY_MOVDIRI_FLAGS },
   { STRING_COMMA_LEN ("nomovdir64b"), CPU_ANY_MOVDIR64B_FLAGS },
   { STRING_COMMA_LEN ("noavx512_bf16"), CPU_ANY_AVX512_BF16_FLAGS },
   { STRING_COMMA_LEN ("noavx512_vp2intersect"),
     CPU_ANY_AVX512_VP2INTERSECT_FLAGS },
+  { STRING_COMMA_LEN ("notdx"), CPU_ANY_TDX_FLAGS },
   { STRING_COMMA_LEN ("noenqcmd"), CPU_ANY_ENQCMD_FLAGS },
   { STRING_COMMA_LEN ("noserialize"), CPU_ANY_SERIALIZE_FLAGS },
   { STRING_COMMA_LEN ("notsxldtrk"), CPU_ANY_TSXLDTRK_FLAGS },
+  { STRING_COMMA_LEN ("nokl"), CPU_ANY_KL_FLAGS },
+  { STRING_COMMA_LEN ("nowidekl"), CPU_ANY_WIDEKL_FLAGS },
 };
 
 #ifdef I386COFF
@@ -1363,10 +1385,10 @@ const pseudo_typeS md_pseudo_table[] =
 extern char *input_line_pointer;
 
 /* Hash table for instruction mnemonic lookup.  */
-static struct hash_control *op_hash;
+static htab_t op_hash;
 
 /* Hash table for register lookup.  */
-static struct hash_control *reg_hash;
+static htab_t reg_hash;
 \f
   /* Various efficient no-op patterns for aligning code labels.
      Note: Don't try to assemble the instructions in the comments.
@@ -2160,7 +2182,9 @@ match_simd_size (const insn_template *t, unsigned int wanted,
           || (i.types[given].bitfield.ymmword
               && !t->operand_types[wanted].bitfield.ymmword)
           || (i.types[given].bitfield.zmmword
-              && !t->operand_types[wanted].bitfield.zmmword));
+              && !t->operand_types[wanted].bitfield.zmmword)
+          || (i.types[given].bitfield.tmmword
+              && !t->operand_types[wanted].bitfield.tmmword));
 }
 
 /* Return 1 if there is no conflict in any size between operand GIVEN
@@ -2297,6 +2321,7 @@ operand_type_match (i386_operand_type overlap,
   temp.bitfield.xmmword = 0;
   temp.bitfield.ymmword = 0;
   temp.bitfield.zmmword = 0;
+  temp.bitfield.tmmword = 0;
   if (operand_type_all_zero (&temp))
     goto mismatch;
 
@@ -2523,14 +2548,6 @@ offset_in_range (offsetT val, int size)
     default: abort ();
     }
 
-#ifdef BFD64
-  /* If BFD64, sign extend val for 32bit address mode.  */
-  if (flag_code != CODE_64BIT
-      || i.prefix[ADDR_PREFIX])
-    if ((val & ~(((addressT) 2 << 31) - 1)) == 0)
-      val = (val ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31);
-#endif
-
   if ((val & ~mask) != 0 && (val & ~mask) != ~mask)
     {
       char buf1[40], buf2[40];
@@ -3018,13 +3035,11 @@ i386_mach (void)
 void
 md_begin (void)
 {
-  const char *hash_err;
-
   /* Support pseudo prefixes like {disp32}.  */
   lex_type ['{'] = LEX_BEGIN_NAME;
 
   /* Initialize op_hash hash table.  */
-  op_hash = hash_new ();
+  op_hash = str_htab_create ();
 
   {
     const insn_template *optab;
@@ -3044,15 +3059,9 @@ md_begin (void)
            /* different name --> ship out current template list;
               add to hash table; & begin anew.  */
            core_optab->end = optab;
-           hash_err = hash_insert (op_hash,
-                                   (optab - 1)->name,
-                                   (void *) core_optab);
-           if (hash_err)
-             {
-               as_fatal (_("can't hash %s: %s"),
-                         (optab - 1)->name,
-                         hash_err);
-             }
+           if (str_hash_insert (op_hash, (optab - 1)->name, core_optab, 0))
+             as_fatal (_("duplicate %s"), (optab - 1)->name);
+
            if (optab->name == NULL)
              break;
            core_optab = XNEW (templates);
@@ -3062,19 +3071,14 @@ md_begin (void)
   }
 
   /* Initialize reg_hash hash table.  */
-  reg_hash = hash_new ();
+  reg_hash = str_htab_create ();
   {
     const reg_entry *regtab;
     unsigned int regtab_size = i386_regtab_size;
 
     for (regtab = i386_regtab; regtab_size--; regtab++)
-      {
-       hash_err = hash_insert (reg_hash, regtab->reg_name, (void *) regtab);
-       if (hash_err)
-         as_fatal (_("can't hash %s: %s"),
-                   regtab->reg_name,
-                   hash_err);
-      }
+      if (str_hash_insert (reg_hash, regtab->reg_name, regtab, 0) != NULL)
+       as_fatal (_("duplicate %s"), regtab->reg_name);
   }
 
   /* Fill in lexical tables:  mnemonic_chars, operand_chars.  */
@@ -3108,6 +3112,10 @@ md_begin (void)
            mnemonic_chars[c] = c;
            operand_chars[c] = c;
          }
+#ifdef SVR4_COMMENT_CHARS
+       else if (c == '\\' && strchr (i386_comment_chars, '/'))
+         operand_chars[c] = c;
+#endif
 
        if (ISALPHA (c) || ISDIGIT (c))
          identifier_chars[c] = c;
@@ -3161,8 +3169,8 @@ md_begin (void)
 void
 i386_print_statistics (FILE *file)
 {
-  hash_print_statistics (file, "i386 opcode", op_hash);
-  hash_print_statistics (file, "i386 register", reg_hash);
+  htab_print_statistics (file, "i386 opcode", op_hash);
+  htab_print_statistics (file, "i386 register", reg_hash);
 }
 \f
 #ifdef DEBUG386
@@ -3305,6 +3313,7 @@ const type_names[] =
   { OPERAND_TYPE_REGXMM, "rXMM" },
   { OPERAND_TYPE_REGYMM, "rYMM" },
   { OPERAND_TYPE_REGZMM, "rZMM" },
+  { OPERAND_TYPE_REGTMM, "rTMM" },
   { OPERAND_TYPE_REGMASK, "Mask reg" },
 };
 
@@ -4847,9 +4856,32 @@ md_assemble (char *line)
   if (!process_suffix ())
     return;
 
-  /* Update operand types.  */
+  /* Update operand types and check extended states.  */
   for (j = 0; j < i.operands; j++)
-    i.types[j] = operand_type_and (i.types[j], i.tm.operand_types[j]);
+    {
+      i.types[j] = operand_type_and (i.types[j], i.tm.operand_types[j]);
+      switch (i.tm.operand_types[j].bitfield.class)
+       {
+       default:
+         break;
+       case RegMMX:
+         i.xstate |= xstate_mmx;
+         break;
+       case RegMask:
+         i.xstate |= xstate_zmm;
+         break;
+       case RegSIMD:
+         if (i.tm.operand_types[j].bitfield.tmmword)
+           i.xstate |= xstate_tmm;
+         else if (i.tm.operand_types[j].bitfield.zmmword)
+           i.xstate |= xstate_zmm;
+         else if (i.tm.operand_types[j].bitfield.ymmword)
+           i.xstate |= xstate_ymm;
+         else if (i.tm.operand_types[j].bitfield.xmmword)
+           i.xstate |= xstate_xmm;
+         break;
+       }
+    }
 
   /* Make still unresolved immediate matches conform to size of immediate
      given in i.suffix.  */
@@ -5052,7 +5084,7 @@ parse_insn (char *line, char *mnemonic)
        }
 
       /* Look up instruction (or prefix) via hash table.  */
-      current_templates = (const templates *) hash_find (op_hash, mnemonic);
+      current_templates = (const templates *) str_hash_find (op_hash, mnemonic);
 
       if (*l != END_OF_INSN
          && (!is_space_char (*l) || l[1] != END_OF_INSN)
@@ -5084,39 +5116,43 @@ parse_insn (char *line, char *mnemonic)
              /* Handle pseudo prefixes.  */
              switch (current_templates->start->base_opcode)
                {
-               case 0x0:
+               case Prefix_Disp8:
                  /* {disp8} */
                  i.disp_encoding = disp_encoding_8bit;
                  break;
-               case 0x1:
+               case Prefix_Disp16:
+                 /* {disp16} */
+                 i.disp_encoding = disp_encoding_16bit;
+                 break;
+               case Prefix_Disp32:
                  /* {disp32} */
                  i.disp_encoding = disp_encoding_32bit;
                  break;
-               case 0x2:
+               case Prefix_Load:
                  /* {load} */
                  i.dir_encoding = dir_encoding_load;
                  break;
-               case 0x3:
+               case Prefix_Store:
                  /* {store} */
                  i.dir_encoding = dir_encoding_store;
                  break;
-               case 0x4:
+               case Prefix_VEX:
                  /* {vex} */
                  i.vec_encoding = vex_encoding_vex;
                  break;
-               case 0x5:
+               case Prefix_VEX3:
                  /* {vex3} */
                  i.vec_encoding = vex_encoding_vex3;
                  break;
-               case 0x6:
+               case Prefix_EVEX:
                  /* {evex} */
                  i.vec_encoding = vex_encoding_evex;
                  break;
-               case 0x7:
+               case Prefix_REX:
                  /* {rex} */
                  i.rex_encoding = TRUE;
                  break;
-               case 0x8:
+               case Prefix_NoOptimize:
                  /* {nooptimize} */
                  i.no_optimize = TRUE;
                  break;
@@ -5174,7 +5210,7 @@ parse_insn (char *line, char *mnemonic)
        goto check_suffix;
       mnem_p = dot_p;
       *dot_p = '\0';
-      current_templates = (const templates *) hash_find (op_hash, mnemonic);
+      current_templates = (const templates *) str_hash_find (op_hash, mnemonic);
     }
 
   if (!current_templates)
@@ -5194,8 +5230,8 @@ parse_insn (char *line, char *mnemonic)
              case QWORD_MNEM_SUFFIX:
                i.suffix = mnem_p[-1];
              mnem_p[-1] = '\0';
-             current_templates = (const templates *) hash_find (op_hash,
-                                                                mnemonic);
+             current_templates
+               = (const templates *) str_hash_find (op_hash, mnemonic);
              break;
            case SHORT_MNEM_SUFFIX:
            case LONG_MNEM_SUFFIX:
@@ -5203,8 +5239,8 @@ parse_insn (char *line, char *mnemonic)
                {
                  i.suffix = mnem_p[-1];
                  mnem_p[-1] = '\0';
-                 current_templates = (const templates *) hash_find (op_hash,
-                                                                    mnemonic);
+                 current_templates
+                   = (const templates *) str_hash_find (op_hash, mnemonic);
                }
              break;
 
@@ -5217,8 +5253,8 @@ parse_insn (char *line, char *mnemonic)
                  else
                    i.suffix = LONG_MNEM_SUFFIX;
                  mnem_p[-1] = '\0';
-                 current_templates = (const templates *) hash_find (op_hash,
-                                                                    mnemonic);
+                 current_templates
+                   = (const templates *) str_hash_find (op_hash, mnemonic);
                }
              break;
            }
@@ -5791,7 +5827,7 @@ check_VecOperands (const insn_template *t)
 
   /* For VSIB byte, we need a vector register for index, and all vector
      registers must be distinct.  */
-  if (t->opcode_modifier.sib)
+  if (t->opcode_modifier.sib && t->opcode_modifier.sib != SIBMEM)
     {
       if (!i.index_reg
          || !((t->opcode_modifier.sib == VECSIB128
@@ -5850,6 +5886,23 @@ check_VecOperands (const insn_template *t)
        }
     }
 
+  /* For AMX instructions with three tmmword operands, all tmmword operand must be
+     distinct */
+  if (t->operand_types[0].bitfield.tmmword
+      && i.reg_operands == 3)
+    {
+      if (register_number (i.op[0].regs)
+          == register_number (i.op[1].regs)
+          || register_number (i.op[0].regs)
+             == register_number (i.op[2].regs)
+          || register_number (i.op[1].regs)
+             == register_number (i.op[2].regs))
+       {
+         i.error = invalid_tmm_register_set;
+         return 1;
+       }
+    }
+
   /* Check if broadcast is supported by the instruction and is applied
      to the memory operand.  */
   if (i.broadcast)
@@ -6585,12 +6638,18 @@ match_template (char mnem_suffix)
          as_bad (_("unsupported instruction `%s'"),
                  current_templates->start->name);
          return NULL;
+       case invalid_sib_address:
+         err_msg = _("invalid SIB address");
+         break;
        case invalid_vsib_address:
          err_msg = _("invalid VSIB address");
          break;
        case invalid_vector_register_set:
          err_msg = _("mask, index, and destination registers must be distinct");
          break;
+       case invalid_tmm_register_set:
+         err_msg = _("all tmm registers must be distinct");
+         break;
        case unsupported_vector_index_register:
          err_msg = _("unsupported vector index register");
          break;
@@ -7501,7 +7560,7 @@ process_operands (void)
              i.flags[j] = i.flags[j - 1];
            }
          i.op[0].regs
-           = (const reg_entry *) hash_find (reg_hash, "xmm0");
+           = (const reg_entry *) str_hash_find (reg_hash, "xmm0");
          i.types[0] = regxmm;
          i.tm.operand_types[0] = regxmm;
 
@@ -7885,10 +7944,8 @@ build_modrm_byte (void)
              i386_operand_type op;
              unsigned int vvvv;
 
-             /* Check register-only source operand when two source
-                operands are swapped.  */
-             if (!i.tm.operand_types[source].bitfield.baseindex
-                 && i.tm.operand_types[dest].bitfield.baseindex)
+             /* Swap two source operands if needed.  */
+             if (i.tm.opcode_modifier.swapsources)
                {
                  vvvv = source;
                  source = dest;
@@ -7920,21 +7977,6 @@ build_modrm_byte (void)
        {
          i.rm.reg = i.op[dest].regs->reg_num;
          i.rm.regmem = i.op[source].regs->reg_num;
-         if (i.op[dest].regs->reg_type.bitfield.class == RegMMX
-              || i.op[source].regs->reg_type.bitfield.class == RegMMX)
-           i.has_regmmx = TRUE;
-         else if (i.op[dest].regs->reg_type.bitfield.class == RegSIMD
-                  || i.op[source].regs->reg_type.bitfield.class == RegSIMD)
-           {
-             if (i.types[dest].bitfield.zmmword
-                 || i.types[source].bitfield.zmmword)
-               i.has_regzmm = TRUE;
-             else if (i.types[dest].bitfield.ymmword
-                      || i.types[source].bitfield.ymmword)
-               i.has_regymm = TRUE;
-             else
-               i.has_regxmm = TRUE;
-           }
          set_rex_vrex (i.op[dest].regs, REX_R, i.tm.opcode_modifier.sse2avx);
          set_rex_vrex (i.op[source].regs, REX_B, FALSE);
        }
@@ -7969,7 +8011,9 @@ build_modrm_byte (void)
 
          if (i.tm.opcode_modifier.sib)
            {
-             if (i.index_reg->reg_num == RegIZ)
+             /* The index register of VSIB shouldn't be RegIZ.  */
+             if (i.tm.opcode_modifier.sib != SIBMEM
+                 && i.index_reg->reg_num == RegIZ)
                abort ();
 
              i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
@@ -7992,8 +8036,19 @@ build_modrm_byte (void)
                      i.types[op].bitfield.disp32s = 1;
                    }
                }
-             i.sib.index = i.index_reg->reg_num;
-             set_rex_vrex (i.index_reg, REX_X, FALSE);
+
+             /* Since the mandatory SIB always has index register, so
+                the code logic remains unchanged. The non-mandatory SIB
+                without index register is allowed and will be handled
+                later.  */
+             if (i.index_reg)
+               {
+                 if (i.index_reg->reg_num == RegIZ)
+                   i.sib.index = NO_INDEX_REGISTER;
+                 else
+                   i.sib.index = i.index_reg->reg_num;
+                 set_rex_vrex (i.index_reg, REX_X, FALSE);
+               }
            }
 
          default_seg = &ds;
@@ -8007,7 +8062,9 @@ build_modrm_byte (void)
                {
                  i386_operand_type newdisp;
 
-                 gas_assert (!i.tm.opcode_modifier.sib);
+                 /* Both check for VSIB and mandatory non-vector SIB. */
+                 gas_assert (!i.tm.opcode_modifier.sib
+                             || i.tm.opcode_modifier.sib == SIBMEM);
                  /* Operand is just <disp>  */
                  if (flag_code == CODE_64BIT)
                    {
@@ -8095,7 +8152,10 @@ build_modrm_byte (void)
                      if (operand_type_check (i.types[op], disp) == 0)
                        {
                          /* fake (%bp) into 0(%bp)  */
-                         i.types[op].bitfield.disp8 = 1;
+                         if (i.disp_encoding == disp_encoding_16bit)
+                           i.types[op].bitfield.disp16 = 1;
+                         else
+                           i.types[op].bitfield.disp8 = 1;
                          fake_zero_displacement = 1;
                        }
                    }
@@ -8105,6 +8165,16 @@ build_modrm_byte (void)
                default: /* (%si) -> 4 or (%di) -> 5  */
                  i.rm.regmem = i.base_reg->reg_num - 6 + 4;
                }
+             if (!fake_zero_displacement
+                 && !i.disp_operands
+                 && i.disp_encoding)
+               {
+                 fake_zero_displacement = 1;
+                 if (i.disp_encoding == disp_encoding_8bit)
+                   i.types[op].bitfield.disp8 = 1;
+                 else
+                   i.types[op].bitfield.disp16 = 1;
+               }
              i.rm.mode = mode_from_disp_size (i.types[op]);
            }
          else /* i.base_reg and 32/64 bit mode  */
@@ -8140,12 +8210,19 @@ build_modrm_byte (void)
              if (i.base_reg->reg_num == 5 && i.disp_operands == 0)
                {
                  fake_zero_displacement = 1;
-                 i.types[op].bitfield.disp8 = 1;
+                 if (i.disp_encoding == disp_encoding_32bit)
+                   i.types[op].bitfield.disp32 = 1;
+                 else
+                   i.types[op].bitfield.disp8 = 1;
                }
              i.sib.scale = i.log2_scale_factor;
              if (i.index_reg == 0)
                {
-                 gas_assert (!i.tm.opcode_modifier.sib);
+                 /* Only check for VSIB. */
+                 gas_assert (i.tm.opcode_modifier.sib != VECSIB128
+                             && i.tm.opcode_modifier.sib != VECSIB256
+                             && i.tm.opcode_modifier.sib != VECSIB512);
+
                  /* <disp>(%esp) becomes two byte modrm with no index
                     register.  We've already stored the code for esp
                     in i.rm.regmem ie. ESCAPE_TO_TWO_BYTE_ADDRESSING.
@@ -8259,31 +8336,16 @@ build_modrm_byte (void)
          unsigned int vex_reg = ~0;
 
          for (op = 0; op < i.operands; op++)
-           {
-             if (i.types[op].bitfield.class == Reg
-                 || i.types[op].bitfield.class == RegBND
-                 || i.types[op].bitfield.class == RegMask
-                 || i.types[op].bitfield.class == SReg
-                 || i.types[op].bitfield.class == RegCR
-                 || i.types[op].bitfield.class == RegDR
-                 || i.types[op].bitfield.class == RegTR)
-               break;
-             if (i.types[op].bitfield.class == RegSIMD)
-               {
-                 if (i.types[op].bitfield.zmmword)
-                   i.has_regzmm = TRUE;
-                 else if (i.types[op].bitfield.ymmword)
-                   i.has_regymm = TRUE;
-                 else
-                   i.has_regxmm = TRUE;
-                 break;
-               }
-             if (i.types[op].bitfield.class == RegMMX)
-               {
-                 i.has_regmmx = TRUE;
-                 break;
-               }
-           }
+           if (i.types[op].bitfield.class == Reg
+               || i.types[op].bitfield.class == RegBND
+               || i.types[op].bitfield.class == RegMask
+               || i.types[op].bitfield.class == SReg
+               || i.types[op].bitfield.class == RegCR
+               || i.types[op].bitfield.class == RegDR
+               || i.types[op].bitfield.class == RegTR
+               || i.types[op].bitfield.class == RegSIMD
+               || i.types[op].bitfield.class == RegMMX)
+             break;
 
          if (vex_3_sources)
            op = dest;
@@ -8384,6 +8446,15 @@ build_modrm_byte (void)
   return default_seg;
 }
 
+static INLINE void
+frag_opcode_byte (unsigned char byte)
+{
+  if (now_seg != absolute_section)
+    FRAG_APPEND_1_CHAR (byte);
+  else
+    ++abs_section_offset;
+}
+
 static unsigned int
 flip_code16 (unsigned int code16)
 {
@@ -8407,6 +8478,12 @@ output_branch (void)
   symbolS *sym;
   offsetT off;
 
+  if (now_seg == absolute_section)
+    {
+      as_bad (_("relaxable branches not supported in absolute section"));
+      return;
+    }
+
   code16 = flag_code == CODE_16BIT ? CODE16 : 0;
   size = i.disp_encoding == disp_encoding_32bit ? BIG : SMALL;
 
@@ -8536,14 +8613,14 @@ output_jump (void)
       size = 1;
       if (i.prefix[ADDR_PREFIX] != 0)
        {
-         FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE);
+         frag_opcode_byte (ADDR_PREFIX_OPCODE);
          i.prefixes -= 1;
        }
       /* Pentium4 branch hints.  */
       if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */
          || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */)
        {
-         FRAG_APPEND_1_CHAR (i.prefix[SEG_PREFIX]);
+         frag_opcode_byte (i.prefix[SEG_PREFIX]);
          i.prefixes--;
        }
     }
@@ -8557,7 +8634,7 @@ output_jump (void)
 
       if (i.prefix[DATA_PREFIX] != 0)
        {
-         FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
+         frag_opcode_byte (DATA_PREFIX_OPCODE);
          i.prefixes -= 1;
          code16 ^= flip_code16(code16);
        }
@@ -8570,19 +8647,25 @@ output_jump (void)
   /* BND prefixed jump.  */
   if (i.prefix[BND_PREFIX] != 0)
     {
-      FRAG_APPEND_1_CHAR (i.prefix[BND_PREFIX]);
+      frag_opcode_byte (i.prefix[BND_PREFIX]);
       i.prefixes -= 1;
     }
 
   if (i.prefix[REX_PREFIX] != 0)
     {
-      FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]);
+      frag_opcode_byte (i.prefix[REX_PREFIX]);
       i.prefixes -= 1;
     }
 
   if (i.prefixes != 0)
     as_warn (_("skipping prefixes on `%s'"), i.tm.name);
 
+  if (now_seg == absolute_section)
+    {
+      abs_section_offset += i.tm.opcode_length + size;
+      return;
+    }
+
   p = frag_more (i.tm.opcode_length + size);
   switch (i.tm.opcode_length)
     {
@@ -8644,6 +8727,12 @@ output_interseg_jump (void)
   if (i.prefixes != 0)
     as_warn (_("skipping prefixes on `%s'"), i.tm.name);
 
+  if (now_seg == absolute_section)
+    {
+      abs_section_offset += prefix + 1 + 2 + size;
+      return;
+    }
+
   /* 1 opcode; 2 segment; offset  */
   p = frag_more (prefix + 1 + 2 + size);
 
@@ -9056,7 +9145,7 @@ output_insn (void)
   enum mf_jcc_kind mf_jcc = mf_jcc_jo;
 
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
-  if (IS_ELF && x86_used_note)
+  if (IS_ELF && x86_used_note && now_seg != absolute_section)
     {
       if (i.tm.cpu_flags.bitfield.cpucmov)
        x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_CMOV;
@@ -9115,17 +9204,17 @@ output_insn (void)
          || i.tm.cpu_flags.bitfield.cpu687
          || i.tm.cpu_flags.bitfield.cpufisttp)
        x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_X87;
-      if (i.has_regmmx
+      if ((i.xstate & xstate_mmx)
          || i.tm.base_opcode == 0xf77 /* emms */
-         || i.tm.base_opcode == 0xf0e /* femms */
-         || i.tm.base_opcode == 0xf2a /* cvtpi2ps */
-         || i.tm.base_opcode == 0x660f2a /* cvtpi2pd */)
+         || i.tm.base_opcode == 0xf0e /* femms */)
        x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_MMX;
-      if (i.has_regxmm)
+      if ((i.xstate & xstate_xmm)
+         || i.tm.cpu_flags.bitfield.cpuwidekl
+         || i.tm.cpu_flags.bitfield.cpukl)
        x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_XMM;
-      if (i.has_regymm)
+      if ((i.xstate & xstate_ymm) == xstate_ymm)
        x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_YMM;
-      if (i.has_regzmm)
+      if ((i.xstate & xstate_zmm) == xstate_zmm)
        x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_ZMM;
       if (i.tm.cpu_flags.bitfield.cpufxsr)
        x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_FXSR;
@@ -9135,6 +9224,10 @@ output_insn (void)
        x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT;
       if (i.tm.cpu_flags.bitfield.cpuxsavec)
        x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_XSAVEC;
+
+      if ((i.xstate & xstate_tmm) == xstate_tmm
+         || i.tm.cpu_flags.bitfield.cpuamx_tile)
+       x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_TMM;
     }
 #endif
 
@@ -9193,14 +9286,20 @@ output_insn (void)
          && (i.tm.base_opcode == 0xfaee8
              || i.tm.base_opcode == 0xfaef0
              || i.tm.base_opcode == 0xfaef8))
-        {
-          /* Encode lfence, mfence, and sfence as
-             f0 83 04 24 00   lock addl $0x0, (%{re}sp).  */
-          offsetT val = 0x240483f0ULL;
-          p = frag_more (5);
-          md_number_to_chars (p, val, 5);
-          return;
-        }
+       {
+         /* Encode lfence, mfence, and sfence as
+            f0 83 04 24 00   lock addl $0x0, (%{re}sp).  */
+         if (now_seg != absolute_section)
+           {
+             offsetT val = 0x240483f0ULL;
+
+             p = frag_more (5);
+             md_number_to_chars (p, val, 5);
+           }
+         else
+           abs_section_offset += 5;
+         return;
+       }
 
       /* Some processors fail on LOCK prefix. This options makes
         assembler ignore LOCK prefix and serves as a workaround.  */
@@ -9299,7 +9398,7 @@ output_insn (void)
          /* The prefix bytes.  */
          for (j = ARRAY_SIZE (i.prefix), q = i.prefix; j > 0; j--, q++)
            if (*q)
-             FRAG_APPEND_1_CHAR (*q);
+             frag_opcode_byte (*q);
        }
       else
        {
@@ -9309,7 +9408,7 @@ output_insn (void)
                {
                case SEG_PREFIX:
                case ADDR_PREFIX:
-                 FRAG_APPEND_1_CHAR (*q);
+                 frag_opcode_byte (*q);
                  break;
                default:
                  /* There should be no other prefixes for instructions
@@ -9323,13 +9422,20 @@ output_insn (void)
          if (i.vrex)
            abort ();
          /* Now the VEX prefix.  */
-         p = frag_more (i.vex.length);
-         for (j = 0; j < i.vex.length; j++)
-           p[j] = i.vex.bytes[j];
+         if (now_seg != absolute_section)
+           {
+             p = frag_more (i.vex.length);
+             for (j = 0; j < i.vex.length; j++)
+               p[j] = i.vex.bytes[j];
+           }
+         else
+           abs_section_offset += i.vex.length;
        }
 
       /* Now the opcode; be careful about word order here!  */
-      if (i.tm.opcode_length == 1)
+      if (now_seg == absolute_section)
+       abs_section_offset += i.tm.opcode_length;
+      else if (i.tm.opcode_length == 1)
        {
          FRAG_APPEND_1_CHAR (i.tm.base_opcode);
        }
@@ -9362,9 +9468,9 @@ output_insn (void)
       /* Now the modrm byte and sib byte (if present).  */
       if (i.tm.opcode_modifier.modrm)
        {
-         FRAG_APPEND_1_CHAR ((i.rm.regmem << 0
-                              | i.rm.reg << 3
-                              | i.rm.mode << 6));
+         frag_opcode_byte ((i.rm.regmem << 0)
+                            | (i.rm.reg << 3)
+                            | (i.rm.mode << 6));
          /* If i.rm.regmem == ESP (4)
             && i.rm.mode != (Register mode)
             && not 16 bit
@@ -9372,9 +9478,9 @@ output_insn (void)
          if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING
              && i.rm.mode != 3
              && !(i.base_reg && i.base_reg->reg_type.bitfield.word))
-           FRAG_APPEND_1_CHAR ((i.sib.base << 0
-                                | i.sib.index << 3
-                                | i.sib.scale << 6));
+           frag_opcode_byte ((i.sib.base << 0)
+                             | (i.sib.index << 3)
+                             | (i.sib.scale << 6));
        }
 
       if (i.disp_operands)
@@ -9542,9 +9648,12 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
     {
       if (operand_type_check (i.types[n], disp))
        {
-         if (i.op[n].disps->X_op == O_constant)
+         int size = disp_size (n);
+
+         if (now_seg == absolute_section)
+           abs_section_offset += size;
+         else if (i.op[n].disps->X_op == O_constant)
            {
-             int size = disp_size (n);
              offsetT val = i.op[n].disps->X_add_number;
 
              val = offset_in_range (val >> (size == 1 ? i.memshift : 0),
@@ -9555,7 +9664,6 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
          else
            {
              enum bfd_reloc_code_real reloc_type;
-             int size = disp_size (n);
              int sign = i.types[n].bitfield.disp32s;
              int pcrel = (i.flags[n] & Operand_PCrel) != 0;
              fixS *fixP;
@@ -9688,9 +9796,12 @@ output_imm (fragS *insn_start_frag, offsetT insn_start_off)
 
       if (operand_type_check (i.types[n], imm))
        {
-         if (i.op[n].imms->X_op == O_constant)
+         int size = imm_size (n);
+
+         if (now_seg == absolute_section)
+           abs_section_offset += size;
+         else if (i.op[n].imms->X_op == O_constant)
            {
-             int size = imm_size (n);
              offsetT val;
 
              val = offset_in_range (i.op[n].imms->X_add_number,
@@ -9705,7 +9816,6 @@ output_imm (fragS *insn_start_frag, offsetT insn_start_off)
                 non-absolute imms).  Try to support other
                 sizes ...  */
              enum bfd_reloc_code_real reloc_type;
-             int size = imm_size (n);
              int sign;
 
              if (i.types[n].bitfield.imm32s
@@ -10872,10 +10982,13 @@ i386_index_check (const char *operand_string)
                  && current_templates->end[-1].operand_types[1]
                     .bitfield.baseindex))
            op = 1;
-         expected_reg = hash_find (reg_hash, di_si[addr_mode][op == es_op]);
+         expected_reg
+           = (const reg_entry *) str_hash_find (reg_hash,
+                                                di_si[addr_mode][op == es_op]);
        }
       else
-       expected_reg = hash_find (reg_hash, bx[addr_mode]);
+       expected_reg
+         = (const reg_entry *)str_hash_find (reg_hash, bx[addr_mode]);
 
       if (i.base_reg != expected_reg
          || i.index_reg
@@ -10913,6 +11026,14 @@ i386_index_check (const char *operand_string)
       if (addr_mode != CODE_16BIT)
        {
          /* 32-bit/64-bit checks.  */
+         if (i.disp_encoding == disp_encoding_16bit)
+           {
+           bad_disp:
+             as_bad (_("invalid `%s' prefix"),
+                     addr_mode == CODE_16BIT ? "{disp32}" : "{disp16}");
+             return 0;
+           }
+
          if ((i.base_reg
               && ((addr_mode == CODE_64BIT
                    ? !i.base_reg->reg_type.bitfield.qword
@@ -10929,9 +11050,10 @@ i386_index_check (const char *operand_string)
                      || !i.index_reg->reg_type.bitfield.baseindex)))
            goto bad_address;
 
-         /* bndmk, bndldx, and bndstx have special restrictions. */
+         /* bndmk, bndldx, bndstx and mandatory non-vector SIB have special restrictions. */
          if (current_templates->start->base_opcode == 0xf30f1b
-             || (current_templates->start->base_opcode & ~1) == 0x0f1a)
+             || (current_templates->start->base_opcode & ~1) == 0x0f1a
+             || current_templates->start->opcode_modifier.sib == SIBMEM)
            {
              /* They cannot use RIP-relative addressing. */
              if (i.base_reg && i.base_reg->reg_num == RegIP)
@@ -10941,7 +11063,7 @@ i386_index_check (const char *operand_string)
                }
 
              /* bndldx and bndstx ignore their scale factor. */
-             if (current_templates->start->base_opcode != 0xf30f1b
+             if ((current_templates->start->base_opcode & ~1) == 0x0f1a
                  && i.log2_scale_factor)
                as_warn (_("register scaling is being ignored here"));
            }
@@ -10949,6 +11071,9 @@ i386_index_check (const char *operand_string)
       else
        {
          /* 16-bit checks.  */
+         if (i.disp_encoding == disp_encoding_32bit)
+           goto bad_disp;
+
          if ((i.base_reg
               && (!i.base_reg->reg_type.bitfield.word
                   || !i.base_reg->reg_type.bitfield.baseindex))
@@ -12443,6 +12568,11 @@ static bfd_boolean check_register (const reg_entry *r)
        }
     }
 
+  if (r->reg_type.bitfield.tmmword
+      && (!cpu_arch_flags.bitfield.cpuamx_tile
+          || flag_code != CODE_64BIT))
+    return FALSE;
+
   if (r->reg_type.bitfield.class == RegBND && !cpu_arch_flags.bitfield.cpumpx)
     return FALSE;
 
@@ -12509,7 +12639,7 @@ parse_real_register (char *reg_string, char **end_op)
 
   *end_op = s;
 
-  r = (const reg_entry *) hash_find (reg_hash, reg_name_given);
+  r = (const reg_entry *) str_hash_find (reg_hash, reg_name_given);
 
   /* Handle floating point regs, allowing spaces in the (i) part.  */
   if (r == i386_regtab /* %st is first entry of table  */)
@@ -12536,7 +12666,7 @@ parse_real_register (char *reg_string, char **end_op)
              if (*s == ')')
                {
                  *end_op = s + 1;
-                 r = (const reg_entry *) hash_find (reg_hash, "st(0)");
+                 r = (const reg_entry *) str_hash_find (reg_hash, "st(0)");
                  know (r);
                  return r + fpr;
                }
@@ -13685,7 +13815,7 @@ md_undefined_symbol (char *name)
          if (symbol_find (name))
            as_bad (_("GOT already in symbol table"));
          GOT_symbol = symbol_new (name, undefined_section,
-                                  (valueT) 0, &zero_address_frag);
+                                  &zero_address_frag, 0);
        };
       return GOT_symbol;
     }
@@ -13799,11 +13929,22 @@ i386_validate_fix (fixS *fixp)
        }
     }
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
-  else if (!object_64bit)
+  else
     {
-      if (fixp->fx_r_type == BFD_RELOC_386_GOT32
-         && fixp->fx_tcbit2)
-       fixp->fx_r_type = BFD_RELOC_386_GOT32X;
+      /* NB: Commit 292676c1 resolved PLT32 reloc aganst local symbol
+        to section.  Since PLT32 relocation must be against symbols,
+        turn such PLT32 relocation into PC32 relocation.  */
+      if (fixp->fx_addsy
+         && (fixp->fx_r_type == BFD_RELOC_386_PLT32
+             || fixp->fx_r_type == BFD_RELOC_X86_64_PLT32)
+         && symbol_section_p (fixp->fx_addsy))
+       fixp->fx_r_type = BFD_RELOC_32_PCREL;
+      if (!object_64bit)
+       {
+         if (fixp->fx_r_type == BFD_RELOC_386_GOT32
+             && fixp->fx_tcbit2)
+           fixp->fx_r_type = BFD_RELOC_386_GOT32X;
+       }
     }
 #endif
 }
This page took 0.078279 seconds and 4 git commands to generate.