Change regcache list to be an hash map
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index 0dc44a89a2e734f0c1640287ca1cf5b72c8260c7..2c087e42e0de4486ce1b89d6c2d1b1d36ded1a9e 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-i386.c -- Assemble code for the Intel 80386
-   Copyright (C) 1989-2019 Free Software Foundation, Inc.
+   Copyright (C) 1989-2020 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -182,6 +182,7 @@ static char *parse_insn (char *, char *);
 static char *parse_operands (char *, const char *);
 static void swap_operands (void);
 static void swap_2_operands (int, int);
+static enum flag_code i386_addressing_mode (void);
 static void optimize_imm (void);
 static void optimize_disp (void);
 static const insn_template *match_template (char);
@@ -3989,13 +3990,13 @@ optimize_encoding (void)
   unsigned int j;
 
   if (optimize_for_space
+      && !is_any_vex_encoding (&i.tm)
       && i.reg_operands == 1
       && i.imm_operands == 1
       && !i.types[1].bitfield.byte
       && i.op[0].imms->X_op == O_constant
       && fits_in_imm7 (i.op[0].imms->X_add_number)
-      && ((i.tm.base_opcode == 0xa8
-          && i.tm.extension_opcode == None)
+      && (i.tm.base_opcode == 0xa8
          || (i.tm.base_opcode == 0xf6
              && i.tm.extension_opcode == 0x0)))
     {
@@ -4008,20 +4009,20 @@ optimize_encoding (void)
          i.types[1].bitfield.byte = 1;
          /* Ignore the suffix.  */
          i.suffix = 0;
-         if (base_regnum >= 4)
-           {
-             /* Handle SP, BP, SI, DI and R12-R15 registers.  */
-             if (i.types[1].bitfield.word)
-               j = 16;
-             else if (i.types[1].bitfield.dword)
-               j = 32;
-             else
-               j = 48;
-             i.op[1].regs -= j;
-           }
+         /* Convert to byte registers.  */
+         if (i.types[1].bitfield.word)
+           j = 16;
+         else if (i.types[1].bitfield.dword)
+           j = 32;
+         else
+           j = 48;
+         if (!(i.op[1].regs->reg_flags & RegRex) && base_regnum < 4)
+           j += 8;
+         i.op[1].regs -= j;
        }
     }
   else if (flag_code == CODE_64BIT
+          && !is_any_vex_encoding (&i.tm)
           && ((i.types[1].bitfield.qword
                && i.reg_operands == 1
                && i.imm_operands == 1
@@ -4030,9 +4031,8 @@ optimize_encoding (void)
                     && i.tm.extension_opcode == None
                     && fits_in_unsigned_long (i.op[0].imms->X_add_number))
                    || (fits_in_imm31 (i.op[0].imms->X_add_number)
-                       && (((i.tm.base_opcode == 0x24
-                             || i.tm.base_opcode == 0xa8)
-                            && i.tm.extension_opcode == None)
+                       && ((i.tm.base_opcode == 0x24
+                            || i.tm.base_opcode == 0xa8)
                            || (i.tm.base_opcode == 0x80
                                && i.tm.extension_opcode == 0x4)
                            || ((i.tm.base_opcode == 0xf6
@@ -4044,13 +4044,11 @@ optimize_encoding (void)
               || (i.types[0].bitfield.qword
                   && ((i.reg_operands == 2
                        && i.op[0].regs == i.op[1].regs
-                       && ((i.tm.base_opcode == 0x30
-                            || i.tm.base_opcode == 0x28)
-                           && i.tm.extension_opcode == None))
+                       && (i.tm.base_opcode == 0x30
+                           || i.tm.base_opcode == 0x28))
                       || (i.reg_operands == 1
                           && i.operands == 1
-                          && i.tm.base_opcode == 0x30
-                          && i.tm.extension_opcode == None)))))
+                          && i.tm.base_opcode == 0x30)))))
     {
       /* Optimize: -O:
           andq $imm31, %r64   -> andl $imm31, %r32
@@ -4091,6 +4089,7 @@ optimize_encoding (void)
     }
   else if (optimize > 1
           && !optimize_for_space
+          && !is_any_vex_encoding (&i.tm)
           && i.reg_operands == 2
           && i.op[0].regs == i.op[1].regs
           && ((i.tm.base_opcode & ~(Opcode_D | 1)) == 0x8
@@ -4574,6 +4573,7 @@ md_assemble (char *line)
          if (i.types[x].bitfield.class == Reg && i.types[x].bitfield.byte
              && (i.op[x].regs->reg_flags & RegRex64) == 0)
            {
+             gas_assert (!(i.op[x].regs->reg_flags & RegRex));
              /* In case it is "hi" register, give up.  */
              if (i.op[x].regs->reg_num > 3)
                as_bad (_("can't encode register '%s%s' in an "
@@ -4592,7 +4592,7 @@ md_assemble (char *line)
   if (i.rex == 0 && i.rex_encoding)
     {
       /* Check if we can add a REX_OPCODE byte.  Look for 8 bit operand
-         that uses legacy register.  If it is "hi" register, don't add
+        that uses legacy register.  If it is "hi" register, don't add
         the REX_OPCODE byte.  */
       int x;
       for (x = 0; x < 2; x++)
@@ -4601,6 +4601,7 @@ md_assemble (char *line)
            && (i.op[x].regs->reg_flags & RegRex64) == 0
            && i.op[x].regs->reg_num > 3)
          {
+           gas_assert (!(i.op[x].regs->reg_flags & RegRex));
            i.rex_encoding = FALSE;
            break;
          }
@@ -5883,51 +5884,50 @@ match_template (char mnem_suffix)
            break;
        }
 
-      /* Address size prefix will turn Disp64/Disp32/Disp16 operand
-        into Disp32/Disp16/Disp32 operand.  */
-      if (i.prefix[ADDR_PREFIX] != 0)
-         {
-           /* There should be only one Disp operand.  */
-           switch (flag_code)
-           {
-           case CODE_16BIT:
-             for (j = 0; j < MAX_OPERANDS; j++)
-               {
-                 if (operand_types[j].bitfield.disp16)
-                   {
-                     addr_prefix_disp = j;
-                     operand_types[j].bitfield.disp32 = 1;
-                     operand_types[j].bitfield.disp16 = 0;
-                     break;
-                   }
-               }
+      if (!t->opcode_modifier.jump
+         || t->opcode_modifier.jump == JUMP_ABSOLUTE)
+       {
+         /* There should be only one Disp operand.  */
+         for (j = 0; j < MAX_OPERANDS; j++)
+           if (operand_type_check (operand_types[j], disp))
              break;
-           case CODE_32BIT:
-             for (j = 0; j < MAX_OPERANDS; j++)
+         if (j < MAX_OPERANDS)
+           {
+             bfd_boolean override = (i.prefix[ADDR_PREFIX] != 0);
+
+             addr_prefix_disp = j;
+
+             /* Address size prefix will turn Disp64/Disp32S/Disp32/Disp16
+                operand into Disp32/Disp32/Disp16/Disp32 operand.  */
+             switch (flag_code)
                {
-                 if (operand_types[j].bitfield.disp32)
+               case CODE_16BIT:
+                 override = !override;
+                 /* Fall through.  */
+               case CODE_32BIT:
+                 if (operand_types[j].bitfield.disp32
+                     && operand_types[j].bitfield.disp16)
                    {
-                     addr_prefix_disp = j;
-                     operand_types[j].bitfield.disp32 = 0;
-                     operand_types[j].bitfield.disp16 = 1;
-                     break;
+                     operand_types[j].bitfield.disp16 = override;
+                     operand_types[j].bitfield.disp32 = !override;
                    }
-               }
-             break;
-           case CODE_64BIT:
-             for (j = 0; j < MAX_OPERANDS; j++)
-               {
-                 if (operand_types[j].bitfield.disp64)
+                 operand_types[j].bitfield.disp32s = 0;
+                 operand_types[j].bitfield.disp64 = 0;
+                 break;
+
+               case CODE_64BIT:
+                 if (operand_types[j].bitfield.disp32s
+                     || operand_types[j].bitfield.disp64)
                    {
-                     addr_prefix_disp = j;
-                     operand_types[j].bitfield.disp64 = 0;
-                     operand_types[j].bitfield.disp32 = 1;
-                     break;
+                     operand_types[j].bitfield.disp64 &= !override;
+                     operand_types[j].bitfield.disp32s &= !override;
+                     operand_types[j].bitfield.disp32 = override;
                    }
+                 operand_types[j].bitfield.disp16 = 0;
+                 break;
                }
-             break;
            }
-         }
+       }
 
       /* Force 0x8b encoding for "mov foo@GOT, %eax".  */
       if (i.reloc[0] == BFD_RELOC_386_GOT32 && t->base_opcode == 0xa0)
@@ -7861,6 +7861,18 @@ build_modrm_byte (void)
   return default_seg;
 }
 
+static unsigned int
+flip_code16 (unsigned int code16)
+{
+  gas_assert (i.tm.operands == 1);
+
+  return !(i.prefix[REX_PREFIX] & REX_W)
+        && (code16 ? i.tm.operand_types[0].bitfield.disp32
+                     || i.tm.operand_types[0].bitfield.disp32s
+                   : i.tm.operand_types[0].bitfield.disp16)
+        ? CODE16 : 0;
+}
+
 static void
 output_branch (void)
 {
@@ -7880,7 +7892,7 @@ output_branch (void)
     {
       prefix = 1;
       i.prefixes -= 1;
-      code16 ^= CODE16;
+      code16 ^= flip_code16(code16);
     }
   /* Pentium4 branch hints.  */
   if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */
@@ -7898,12 +7910,12 @@ output_branch (void)
   /* BND prefixed jump.  */
   if (i.prefix[BND_PREFIX] != 0)
     {
-      FRAG_APPEND_1_CHAR (i.prefix[BND_PREFIX]);
-      i.prefixes -= 1;
+      prefix++;
+      i.prefixes--;
     }
 
-  if (i.prefixes != 0 && !intel_syntax)
-    as_warn (_("skipping prefixes on this instruction"));
+  if (i.prefixes != 0)
+    as_warn (_("skipping prefixes on `%s'"), i.tm.name);
 
   /* It's always a symbol;  End frag & setup for relax.
      Make sure there is enough room in this frag for the largest
@@ -7918,6 +7930,8 @@ output_branch (void)
   if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE
       || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE)
     *p++ = i.prefix[SEG_PREFIX];
+  if (i.prefix[BND_PREFIX] != 0)
+    *p++ = BND_PREFIX_OPCODE;
   if (i.prefix[REX_PREFIX] != 0)
     *p++ = i.prefix[REX_PREFIX];
   *p = i.tm.base_opcode;
@@ -8022,7 +8036,7 @@ output_jump (void)
        {
          FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
          i.prefixes -= 1;
-         code16 ^= CODE16;
+         code16 ^= flip_code16(code16);
        }
 
       size = 4;
@@ -8030,21 +8044,21 @@ output_jump (void)
        size = 2;
     }
 
-  if (i.prefix[REX_PREFIX] != 0)
+  /* BND prefixed jump.  */
+  if (i.prefix[BND_PREFIX] != 0)
     {
-      FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]);
+      FRAG_APPEND_1_CHAR (i.prefix[BND_PREFIX]);
       i.prefixes -= 1;
     }
 
-  /* BND prefixed jump.  */
-  if (i.prefix[BND_PREFIX] != 0)
+  if (i.prefix[REX_PREFIX] != 0)
     {
-      FRAG_APPEND_1_CHAR (i.prefix[BND_PREFIX]);
+      FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]);
       i.prefixes -= 1;
     }
 
-  if (i.prefixes != 0 && !intel_syntax)
-    as_warn (_("skipping prefixes on this instruction"));
+  if (i.prefixes != 0)
+    as_warn (_("skipping prefixes on `%s'"), i.tm.name);
 
   p = frag_more (i.tm.opcode_length + size);
   switch (i.tm.opcode_length)
@@ -8097,18 +8111,15 @@ output_interseg_jump (void)
       i.prefixes -= 1;
       code16 ^= CODE16;
     }
-  if (i.prefix[REX_PREFIX] != 0)
-    {
-      prefix++;
-      i.prefixes -= 1;
-    }
+
+  gas_assert (!i.prefix[REX_PREFIX]);
 
   size = 4;
   if (code16)
     size = 2;
 
-  if (i.prefixes != 0 && !intel_syntax)
-    as_warn (_("skipping prefixes on this instruction"));
+  if (i.prefixes != 0)
+    as_warn (_("skipping prefixes on `%s'"), i.tm.name);
 
   /* 1 opcode; 2 segment; offset  */
   p = frag_more (prefix + 1 + 2 + size);
@@ -9937,10 +9948,11 @@ i386_displacement (char *disp_start, char *disp_end)
 
   operand_type_set (&bigdisp, 0);
   if (i.jumpabsolute
+      || i.types[this_operand].bitfield.baseindex
       || (current_templates->start->opcode_modifier.jump != JUMP
          && current_templates->start->opcode_modifier.jump != JUMP_DWORD))
     {
-      bigdisp.bitfield.disp32 = 1;
+      i386_addressing_mode ();
       override = (i.prefix[ADDR_PREFIX] != 0);
       if (flag_code == CODE_64BIT)
        {
@@ -9949,27 +9961,47 @@ i386_displacement (char *disp_start, char *disp_end)
              bigdisp.bitfield.disp32s = 1;
              bigdisp.bitfield.disp64 = 1;
            }
+         else
+           bigdisp.bitfield.disp32 = 1;
        }
       else if ((flag_code == CODE_16BIT) ^ override)
-       {
-         bigdisp.bitfield.disp32 = 0;
          bigdisp.bitfield.disp16 = 1;
-       }
+      else
+         bigdisp.bitfield.disp32 = 1;
     }
   else
     {
-      /* For PC-relative branches, the width of the displacement
-        is dependent upon data size, not address size.  */
+      /* For PC-relative branches, the width of the displacement may be
+        dependent upon data size, but is never dependent upon address size.
+        Also make sure to not unintentionally match against a non-PC-relative
+        branch template.  */
+      static templates aux_templates;
+      const insn_template *t = current_templates->start;
+      bfd_boolean has_intel64 = FALSE;
+
+      aux_templates.start = t;
+      while (++t < current_templates->end)
+       {
+         if (t->opcode_modifier.jump
+             != current_templates->start->opcode_modifier.jump)
+           break;
+         if (t->opcode_modifier.intel64)
+           has_intel64 = TRUE;
+       }
+      if (t < current_templates->end)
+       {
+         aux_templates.end = t;
+         current_templates = &aux_templates;
+       }
+
       override = (i.prefix[DATA_PREFIX] != 0);
       if (flag_code == CODE_64BIT)
        {
-         if (override || i.suffix == WORD_MNEM_SUFFIX)
+         if ((override || i.suffix == WORD_MNEM_SUFFIX)
+             && (!intel64 || !has_intel64))
            bigdisp.bitfield.disp16 = 1;
          else
-           {
-             bigdisp.bitfield.disp32 = 1;
-             bigdisp.bitfield.disp32s = 1;
-           }
+           bigdisp.bitfield.disp32s = 1;
        }
       else
        {
@@ -10142,6 +10174,11 @@ i386_finalize_displacement (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp,
     }
 #endif
 
+  if (current_templates->start->opcode_modifier.jump == JUMP_BYTE
+      /* Constants get taken care of by optimize_disp().  */
+      && exp->X_op != O_constant)
+    i.types[this_operand].bitfield.disp8 = 1;
+
   /* Check if this is a displacement only operand.  */
   bigdisp = i.types[this_operand];
   bigdisp.bitfield.disp8 = 0;
This page took 0.037214 seconds and 4 git commands to generate.