Teach binutils the {rd,wr}{fs,gs}base instructions.
authorguenther <guenther@openbsd.org>
Mon, 25 May 2015 00:12:59 +0000 (00:12 +0000)
committerguenther <guenther@openbsd.org>
Mon, 25 May 2015 00:12:59 +0000 (00:12 +0000)
Flag bits worked out with kettenis@
ok mlarkin@

gnu/usr.bin/binutils-2.17/gas/config/tc-i386.h
gnu/usr.bin/binutils-2.17/include/opcode/i386.h
gnu/usr.bin/binutils-2.17/opcodes/i386-dis.c

index 073f920..c77420d 100644 (file)
@@ -188,7 +188,7 @@ typedef struct
 #define CpuXSAVE     0x400000  /* XSAVE Instructions required */
 #define CpuAES      0x800000   /* Intel AES extensions required */
 #define CpuPCLMUL   0x1000000  /* Intel Carry-less Multiplication extensions */
-#define CpuRdRnd    0x2000000  /* Intel Random Number Generator extensions */
+#define CpuNEW      0x2000000  /* Generic "new" ops w/o encoding hacks */
 #define CpuSMAP     0x4000000  /* Intel Supervisor Mode Access Prevention */
 
   /* These flags are set by gas depending on the flag_code.  */
@@ -199,7 +199,7 @@ typedef struct
 #define CpuUnknownFlags (Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686 \
        |CpuP4|CpuSledgehammer|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuPNI|CpuVMX \
        |Cpu3dnow|Cpu3dnowA|CpuK6|CpuAthlon|CpuPadLock|CpuSVME|CpuMNI \
-       |CpuXSAVE|CpuAES|CpuPCLMUL|CpuRdRnd|CpuSMAP)
+       |CpuXSAVE|CpuAES|CpuPCLMUL|CpuNEW|CpuSMAP)
 
   /* the bits in opcode_modifier are used to generate the final opcode from
      the base_opcode.  These bits also are used to detect alternate forms of
index ccf6746..602187b 100644 (file)
@@ -992,6 +992,10 @@ static const template i386_optab[] =
 {"clflush",  1, 0x0fae,    7, CpuP4, NoSuf|Modrm|IgnoreSize,   { ByteMem, 0, 0 } },
 {"lfence",   0, 0x0fae, 0xe8, CpuP4, NoSuf|ImmExt,             { 0, 0, 0 } },
 {"mfence",   0, 0x0fae, 0xf0, CpuP4, NoSuf|ImmExt,             { 0, 0, 0 } },
+{"rdfsbase", 1, 0xf30fae,  0, CpuNEW, FP|Modrm,                { Reg32|Reg64, 0, 0 } },
+{"rdgsbase", 1, 0xf30fae,  1, CpuNEW, FP|Modrm,                { Reg32|Reg64, 0, 0 } },
+{"wrfsbase", 1, 0xf30fae,  2, CpuNEW, FP|Modrm,                { Reg32|Reg64, 0, 0 } },
+{"wrgsbase", 1, 0xf30fae,  3, CpuNEW, FP|Modrm,                { Reg32|Reg64, 0, 0 } },
 {"pause",    0, 0xf390,    X, CpuP4, NoSuf,            { 0, 0, 0 } },
 
 /* MMX/SSE2 instructions.  */
@@ -1504,7 +1508,7 @@ static const template i386_optab[] =
 {"pclmulhqhqdq", 2, 0x660f3a44, 0x11, CpuPCLMUL, FP|Modrm|IgnoreSize|NoSuf|ImmExt, { RegXMM|LLongMem, RegXMM } },
 
 /* Intel Random Number Generator extensions */
-{"rdrand", 1, 0x0fc7, 0x6, CpuRdRnd, Modrm|NoSuf, { Reg16|Reg32|Reg64 } },
+{"rdrand", 1, 0x0fc7, 0x6, CpuNEW, Modrm|NoSuf, { Reg16|Reg32|Reg64 } },
 
 /* Intel Supervisor Mode Access Prevention extensions */
 {"clac", 0, 0x0f01, 0xca, CpuSMAP, NoSuf|ImmExt, { 0, 0, 0 } },
index e3d1e7e..f7e8e5c 100644 (file)
@@ -316,6 +316,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define VM OP_VMX, q_mode
 #define OPSUF OP_3DNowSuffix, 0
 #define OPSIMD OP_SIMD_Suffix, 0
+#define OP0FAE OP_0fae, v_mode
 #define OP0F3A OP_0f3a, 0
 
 /* Used handle "rep" prefix for string instructions.  */
@@ -1469,14 +1470,14 @@ static const struct dis386 grps[][8] = {
   },
   /* GRP13 */
   {
-    { "fxsave", Ev, XX, XX },
-    { "fxrstor", Ev, XX, XX },
-    { "ldmxcsr", Ev, XX, XX },
-    { "stmxcsr", Ev, XX, XX },
-    { "xsave", Ev, XX, XX },
-    { "xrstor", OP_0fae, v_mode, XX, XX },
-    { "xsaveopt", OP_0fae, v_mode, XX, XX },
-    { "clflush", OP_0fae, v_mode, XX, XX },
+    { "fxsave",   OP0FAE, XX, XX },
+    { "fxrstor",  OP0FAE, XX, XX },
+    { "ldmxcsr",  OP0FAE, XX, XX },
+    { "stmxcsr",  OP0FAE, XX, XX },
+    { "xsave",   Ev, XX, XX },
+    { "xrstor",   OP0FAE, XX, XX },
+    { "xsaveopt", OP0FAE, XX, XX },
+    { "clflush",  OP0FAE, XX, XX },
   },
   /* GRP14 */
   {
@@ -4831,19 +4832,24 @@ OP_0fae (int bytemode, int sizeflag)
        strcpy (obuf + strlen (obuf) - sizeof ("xsaveopt") + 1, "mfence");
       else if (reg == 5)
        strcpy (obuf + strlen (obuf) - sizeof ("xrstor") + 1, "lfence");
-      bytemode = 0;
 
-      if (reg < 5 || rm != 0)
+      if (reg < 4 && prefixes == PREFIX_REPZ)
+        {
+         if (reg == 0)
+           strcpy (obuf, "rdfsbase");
+         else if (reg == 1)
+           strcpy (obuf, "rdgsbase");
+         else if (reg == 2)
+           strcpy (obuf, "wrfsbase");
+         else
+           strcpy (obuf, "wrgsbase");
+        }
+      else if (reg < 5 || rm != 0)
        {
          BadOp ();     /* bad sfence, mfence, or lfence */
          return;
        }
     }
-  else if (reg < 5)
-    {
-      BadOp ();                /* bad sfence, mfence, or lfence */
-      return;
-    }
 
   OP_E (bytemode, sizeflag);
 }