Implement Intel Transactional Synchronization Extensions
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index dbac2cef04f3b865d60bcf53dcd2b8afb317d816..97cb68e02acd458da3ea3af9de5f0ac829e0a41a 100644 (file)
    WAIT_PREFIX must be the first prefix since FWAIT is really is an
    instruction, and so must come before any prefixes.
    The preferred prefix order is SEG_PREFIX, ADDR_PREFIX, DATA_PREFIX,
-   REP_PREFIX, LOCK_PREFIX.  */
+   REP_PREFIX/HLE_PREFIX, LOCK_PREFIX.  */
 #define WAIT_PREFIX    0
 #define SEG_PREFIX     1
 #define ADDR_PREFIX    2
 #define DATA_PREFIX    3
 #define REP_PREFIX     4
+#define HLE_PREFIX     REP_PREFIX
 #define LOCK_PREFIX    5
 #define REX_PREFIX     6       /* must come last.  */
 #define MAX_PREFIXES   7       /* max prefixes per opcode */
@@ -288,6 +289,9 @@ struct _i386_insn
        disp_encoding_32bit
       } disp_encoding;
 
+    /* Have HLE prefix.  */
+    unsigned int have_hle;
+
     /* Error message.  */
     enum i386_error error;
   };
@@ -309,7 +313,8 @@ const char extra_symbol_chars[] = "*%-(["
      || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))        \
         && !defined (TE_GNU)                           \
         && !defined (TE_LINUX)                         \
-        && !defined (TE_NETWARE)                       \
+        && !defined (TE_NACL)                          \
+        && !defined (TE_NETWARE)                       \
         && !defined (TE_FreeBSD)                       \
         && !defined (TE_DragonFly)                     \
         && !defined (TE_NetBSD)))
@@ -730,6 +735,10 @@ static const arch_entry cpu_arch[] =
     CPU_EPT_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".lzcnt"), PROCESSOR_UNKNOWN,
     CPU_LZCNT_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN (".hle"), PROCESSOR_UNKNOWN,
+    CPU_HLE_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN (".rtm"), PROCESSOR_UNKNOWN,
+    CPU_RTM_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".invpcid"), PROCESSOR_UNKNOWN,
     CPU_INVPCID_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".clflush"), PROCESSOR_UNKNOWN,
@@ -2998,6 +3007,50 @@ process_immext (void)
   i.tm.extension_opcode = None;
 }
 
+
+static int
+check_hle (void)
+{
+  switch (i.tm.opcode_modifier.hleprefixok)
+    {
+    default:
+      abort ();
+    case 0:
+      if (i.prefix[HLE_PREFIX] == XACQUIRE_PREFIX_OPCODE)
+       as_bad (_("invalid instruction `%s' after `xacquire'"),
+               i.tm.name);
+      else
+       as_bad (_("invalid instruction `%s' after `xrelease'"),
+               i.tm.name);
+      return 0;
+    case 1:
+      if (i.prefix[LOCK_PREFIX])
+       return 1;
+      if (i.prefix[HLE_PREFIX] == XACQUIRE_PREFIX_OPCODE)
+       as_bad (_("missing `lock' with `xacquire'"));
+      else
+       as_bad (_("missing `lock' with `xrelease'"));
+      return 0;
+    case 2:
+      return 1;
+    case 3:
+      if (i.prefix[HLE_PREFIX] != XRELEASE_PREFIX_OPCODE)
+       {
+         as_bad (_("instruction `%s' after `xacquire' not allowed"),
+                 i.tm.name);
+         return 0;
+       }
+      if (i.mem_operands == 0
+         || !operand_type_check (i.types[i.operands - 1], anymem))
+       {
+         as_bad (_("memory destination needed for instruction `%s'"
+                   " after `xrelease'"), i.tm.name);
+         return 0;
+       }
+      return 1;
+    }
+}
+
 /* This is the guts of the machine-dependent assembler.  LINE points to a
    machine dependent instruction.  This function is supposed to emit
    the frags/bytes it assembles to.  */
@@ -3116,6 +3169,10 @@ md_assemble (char *line)
       return;
     }
 
+  /* Check if HLE prefix is OK.  */
+  if (i.have_hle && !check_hle ())
+    return;
+
   /* Check string instruction segment overrides.  */
   if (i.tm.opcode_modifier.isstring && i.mem_operands != 0)
     {
@@ -3319,7 +3376,10 @@ parse_insn (char *line, char *mnemonic)
            case PREFIX_EXIST:
              return NULL;
            case PREFIX_REP:
-             expecting_string_instruction = current_templates->start->name;
+             if (current_templates->start->cpu_flags.bitfield.cpuhle)
+               i.have_hle = 1;
+             else
+               expecting_string_instruction = current_templates->start->name;
              break;
            default:
              break;
@@ -3337,11 +3397,11 @@ parse_insn (char *line, char *mnemonic)
         encoding.  */
       if (mnem_p - 2 == dot_p && dot_p[1] == 's')
        i.swap_operand = 1;
-      else if (mnem_p - 3 == dot_p 
+      else if (mnem_p - 3 == dot_p
               && dot_p[1] == 'd'
               && dot_p[2] == '8')
        i.disp_encoding = disp_encoding_8bit;
-      else if (mnem_p - 4 == dot_p 
+      else if (mnem_p - 4 == dot_p
               && dot_p[1] == 'd'
               && dot_p[2] == '3'
               && dot_p[3] == '2')
@@ -5854,7 +5914,7 @@ build_modrm_byte (void)
                  vex_reg = op + 1;
                }
              else
-               { 
+               {
                  /* There are only 2 operands.  */
                  gas_assert (op < 2 && i.operands == 2);
                  vex_reg = 1;
@@ -6040,8 +6100,17 @@ output_jump (void)
   if (i.prefixes != 0 && !intel_syntax)
     as_warn (_("skipping prefixes on this instruction"));
 
-  p = frag_more (1 + size);
-  *p++ = i.tm.base_opcode;
+  p = frag_more (i.tm.opcode_length + size);
+  switch (i.tm.opcode_length)
+    {
+    case 2:
+      *p++ = i.tm.base_opcode >> 8;
+    case 1:
+      *p++ = i.tm.base_opcode;
+      break;
+    default:
+      abort ();
+    }
 
   fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
                      i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
@@ -8647,7 +8716,7 @@ show_arch (FILE *stream, int ext, int check)
          fprintf (stream, "%s\n", message);
          p = start;
          left = size - (start - message) - len - 2;
-         
+
          gas_assert (left >= 0);
 
          p = mempcpy (p, name, len);
This page took 0.028256 seconds and 4 git commands to generate.