summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2014-02-09 22:42:28 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2014-02-09 22:42:28 +0000
commit3d28e9ace295091b0d7b011e31f3f5344ef7a4e7 (patch)
tree682c2df4e4d999ba9289d9ea3df3ddd56969fbd1
parent1479cfc9acfbc2f084be12b3af9c73435479da5d (diff)
Add support for i386 XSAVE family of instructions: xgetbv, xsetbv, xsave,
xrstor, and xsaveopt. based on kettenis's original that did xgetbv and xsetbv ok kettenis@
-rw-r--r--gnu/usr.bin/binutils-2.17/gas/config/tc-i386.c2
-rw-r--r--gnu/usr.bin/binutils-2.17/gas/config/tc-i386.h13
-rw-r--r--gnu/usr.bin/binutils-2.17/include/opcode/i386.h7
-rw-r--r--gnu/usr.bin/binutils-2.17/opcodes/i386-dis.c58
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-i386.c2
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-i386.h11
-rw-r--r--gnu/usr.bin/binutils/include/opcode/i386.h7
-rw-r--r--gnu/usr.bin/binutils/opcodes/i386-dis.c43
8 files changed, 116 insertions, 27 deletions
diff --git a/gnu/usr.bin/binutils-2.17/gas/config/tc-i386.c b/gnu/usr.bin/binutils-2.17/gas/config/tc-i386.c
index 0967efaca43..ff255afafb9 100644
--- a/gnu/usr.bin/binutils-2.17/gas/config/tc-i386.c
+++ b/gnu/usr.bin/binutils-2.17/gas/config/tc-i386.c
@@ -1557,7 +1557,7 @@ md_assemble (line)
{
expressionS *exp;
- if ((i.tm.cpu_flags & (CpuPNI|CpuSMAP)) && i.operands > 0)
+ if ((i.tm.cpu_flags & (CpuPNI|CpuXSAVE|CpuSMAP)) && i.operands > 0)
{
/* These Intel Prescott New Instructions have the fixed
operands with an opcode suffix which is coded in the same
diff --git a/gnu/usr.bin/binutils-2.17/gas/config/tc-i386.h b/gnu/usr.bin/binutils-2.17/gas/config/tc-i386.h
index 5856e07ec83..330c8f0f600 100644
--- a/gnu/usr.bin/binutils-2.17/gas/config/tc-i386.h
+++ b/gnu/usr.bin/binutils-2.17/gas/config/tc-i386.h
@@ -185,10 +185,11 @@ typedef struct
#define CpuSVME 0x80000 /* AMD Secure Virtual Machine Ext-s required */
#define CpuVMX 0x100000 /* VMX Instructions required */
#define CpuMNI 0x200000 /* Merom New Instructions required */
-#define CpuAES 0x400000 /* Intel AES extensions required */
-#define CpuPCLMUL 0x800000 /* Intel Carry-less Multiplication extensions */
-#define CpuRdRnd 0x1000000 /* Intel Random Number Generator extensions */
-#define CpuSMAP 0x2000000 /* Intel Supervisor Mode Access Prevention */
+#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 CpuSMAP 0x4000000 /* Intel Supervisor Mode Access Prevention */
/* These flags are set by gas depending on the flag_code. */
#define Cpu64 0x4000000 /* 64bit support required */
@@ -197,8 +198,8 @@ typedef struct
/* The default value for unknown CPUs - enable all features to avoid problems. */
#define CpuUnknownFlags (Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686 \
|CpuP4|CpuSledgehammer|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuPNI|CpuVMX \
- |Cpu3dnow|Cpu3dnowA|CpuK6|CpuAthlon|CpuPadLock|CpuSVME|CpuMNI|CpuAES \
- |CpuPCLMUL|CpuRdRnd|CpuSMAP)
+ |Cpu3dnow|Cpu3dnowA|CpuK6|CpuAthlon|CpuPadLock|CpuSVME|CpuMNI \
+ |CpuXSAVE|CpuAES|CpuPCLMUL|CpuRdRnd|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
diff --git a/gnu/usr.bin/binutils-2.17/include/opcode/i386.h b/gnu/usr.bin/binutils-2.17/include/opcode/i386.h
index a367b6bd5e2..242190a3c57 100644
--- a/gnu/usr.bin/binutils-2.17/include/opcode/i386.h
+++ b/gnu/usr.bin/binutils-2.17/include/opcode/i386.h
@@ -1508,6 +1508,13 @@ static const template i386_optab[] =
{"clac", 0, 0x0f01, 0xca, CpuSMAP, NoSuf|ImmExt, { 0, 0, 0 } },
{"stac", 0, 0x0f01, 0xcb, CpuSMAP, NoSuf|ImmExt, { 0, 0, 0 } },
+/* Intel XSAVE extensions */
+{"xgetbv", 0, 0x0f01, 0xd0, CpuXSAVE, NoSuf|ImmExt, { 0, 0, 0 } },
+{"xsetbv", 0, 0x0f01, 0xd1, CpuXSAVE, NoSuf|ImmExt, { 0, 0, 0 } },
+{"xsave", 1, 0x0fae, 4, CpuXSAVE, q_Suf|Modrm, { LLongMem, 0, 0 } },
+{"xrstor", 1, 0x0fae, 5, CpuXSAVE, q_Suf|Modrm, { LLongMem, 0, 0 } },
+{"xsaveopt", 1, 0x0fae, 6, CpuXSAVE, q_Suf|Modrm, { LLongMem, 0, 0 } },
+
/* sentinel */
{NULL, 0, 0, 0, 0, 0, { 0, 0, 0} }
};
diff --git a/gnu/usr.bin/binutils-2.17/opcodes/i386-dis.c b/gnu/usr.bin/binutils-2.17/opcodes/i386-dis.c
index 03fa624070a..e3d1e7e1a1b 100644
--- a/gnu/usr.bin/binutils-2.17/opcodes/i386-dis.c
+++ b/gnu/usr.bin/binutils-2.17/opcodes/i386-dis.c
@@ -96,6 +96,7 @@ static void OP_3DNowSuffix (int, int);
static void OP_SIMD_Suffix (int, int);
static void SIMD_Fixup (int, int);
static void PNI_Fixup (int, int);
+static void XCR_Fixup (int, int);
static void SVME_Fixup (int, int);
static void INVLPG_Fixup (int, int);
static void BadOp (void);
@@ -1404,7 +1405,7 @@ static const struct dis386 grps[][8] = {
{
{ "sgdtIQ", VMX_Fixup, 0, XX, XX },
{ "sidtIQ", PNI_Fixup, 0, XX, XX },
- { "lgdt{Q|Q||}", M, XX, XX },
+ { "lgdt{Q|Q||}", XCR_Fixup, 0, XX, XX },
{ "lidt{Q|Q||}", SVME_Fixup, 0, XX, XX },
{ "smswQ", Ev, XX, XX },
{ "(bad)", XX, XX, XX },
@@ -1472,10 +1473,10 @@ static const struct dis386 grps[][8] = {
{ "fxrstor", Ev, XX, XX },
{ "ldmxcsr", Ev, XX, XX },
{ "stmxcsr", Ev, XX, XX },
- { "(bad)", XX, XX, XX },
- { "lfence", OP_0fae, 0, XX, XX },
- { "mfence", OP_0fae, 0, XX, XX },
- { "clflush", OP_0fae, 0, 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 },
},
/* GRP14 */
{
@@ -4826,6 +4827,11 @@ OP_0fae (int bytemode, int sizeflag)
{
if (reg == 7)
strcpy (obuf + strlen (obuf) - sizeof ("clflush") + 1, "sfence");
+ else if (reg == 6)
+ 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)
{
@@ -4833,9 +4839,9 @@ OP_0fae (int bytemode, int sizeflag)
return;
}
}
- else if (reg != 7)
+ else if (reg < 5)
{
- BadOp (); /* bad clflush */
+ BadOp (); /* bad sfence, mfence, or lfence */
return;
}
@@ -5084,6 +5090,44 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
}
static void
+XCR_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
+{
+ if (mod == 3 && reg == 2 && rm <= 1)
+ {
+ /* Override "lgdt". */
+ size_t olen = strlen (obuf);
+ char *p = obuf + olen - 4;
+
+ /* We might have a suffix when disassembling with -Msuffix. */
+ if (*p == 'i')
+ --p;
+
+ /* Remove "addr16/addr32" if we aren't in Intel mode. */
+ if (!intel_syntax
+ && (prefixes & PREFIX_ADDR)
+ && olen >= (4 + 7)
+ && *(p - 1) == ' '
+ && strncmp (p - 7, "addr", 4) == 0
+ && (strncmp (p - 3, "16", 2) == 0
+ || strncmp (p - 3, "32", 2) == 0))
+ p -= 7;
+
+ if (rm)
+ {
+ strcpy (p, "xsetbv");
+ }
+ else
+ {
+ strcpy (p, "xgetbv");
+ }
+
+ codep++;
+ }
+ else
+ OP_M (0, sizeflag);
+}
+
+static void
SVME_Fixup (int bytemode, int sizeflag)
{
const char *alt;
diff --git a/gnu/usr.bin/binutils/gas/config/tc-i386.c b/gnu/usr.bin/binutils/gas/config/tc-i386.c
index c6fb483417e..a3128a083c7 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-i386.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-i386.c
@@ -1380,7 +1380,7 @@ md_assemble (line)
{
expressionS *exp;
- if ((i.tm.cpu_flags & (CpuPNI|CpuSMAP)) && i.operands > 0)
+ if ((i.tm.cpu_flags & (CpuPNI|CpuXSAVE|CpuSMAP)) && i.operands > 0)
{
/* These Intel Prescott New Instructions have the fixed
operands with an opcode suffix which is coded in the same
diff --git a/gnu/usr.bin/binutils/gas/config/tc-i386.h b/gnu/usr.bin/binutils/gas/config/tc-i386.h
index 601010acd6c..6747b6ce58f 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-i386.h
+++ b/gnu/usr.bin/binutils/gas/config/tc-i386.h
@@ -196,17 +196,18 @@ typedef struct
#define CpuPNI 0x8000 /* Prescott New Instructions required */
#define CpuPadLock 0x10000 /* VIA PadLock required */
#define CpuSSSE3 0x20000 /* Supplementary SSE3 required */
-#define CpuAES 0x40000 /* Intel AES extensions required */
-#define CpuPCLMUL 0x80000 /* Intel Carry-less Multiplication extensions */
-#define CpuRdRnd 0x100000 /* Intel Random Number Generator extensions */
-#define CpuSMAP 0x200000 /* Intel Supervisor Mode Access Prevention */
+#define CpuXSAVE 0x40000 /* XSAVE extensions required */
+#define CpuAES 0x80000 /* Intel AES extensions required */
+#define CpuPCLMUL 0x100000 /* Intel Carry-less Multiplication extensions */
+#define CpuRdRnd 0x200000 /* Intel Random Number Generator extensions */
+#define CpuSMAP 0x400000 /* Intel Supervisor Mode Access Prevention */
/* These flags are set by gas depending on the flag_code. */
#define Cpu64 0x4000000 /* 64bit support required */
#define CpuNo64 0x8000000 /* Not supported in the 64bit mode */
/* The default value for unknown CPUs - enable all features to avoid problems. */
-#define CpuUnknownFlags (Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuSledgehammer|CpuMMX|CpuSSE|CpuSSE2|CpuPNI|Cpu3dnow|CpuK6|CpuAthlon|CpuPadLock|CpuSSSE3|CpuAES|CpuPCLMUL|CpuRdRnd|CpuSMAP)
+#define CpuUnknownFlags (Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuSledgehammer|CpuMMX|CpuSSE|CpuSSE2|CpuPNI|Cpu3dnow|CpuK6|CpuAthlon|CpuPadLock|CpuSSSE3|CpuXSAVE|CpuAES|CpuPCLMUL|CpuRdRnd|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
diff --git a/gnu/usr.bin/binutils/include/opcode/i386.h b/gnu/usr.bin/binutils/include/opcode/i386.h
index 9d811b325ab..4c4005cb83d 100644
--- a/gnu/usr.bin/binutils/include/opcode/i386.h
+++ b/gnu/usr.bin/binutils/include/opcode/i386.h
@@ -1409,6 +1409,13 @@ static const template i386_optab[] = {
{"clac", 0, 0x0f01, 0xca, CpuSMAP, NoSuf|ImmExt, { 0, 0, 0 } },
{"stac", 0, 0x0f01, 0xcb, CpuSMAP, NoSuf|ImmExt, { 0, 0, 0 } },
+/* Intel XSAVE extensions */
+{"xgetbv", 0, 0x0f01, 0xd0, CpuXSAVE, NoSuf|ImmExt, { 0, 0, 0 } },
+{"xsetbv", 0, 0x0f01, 0xd1, CpuXSAVE, NoSuf|ImmExt, { 0, 0, 0 } },
+{"xsave", 1, 0x0fae, 4, CpuXSAVE, NoSuf|Modrm, { LLongMem, 0, 0 } },
+{"xrstor", 1, 0x0fae, 5, CpuXSAVE, NoSuf|Modrm, { LLongMem, 0, 0 } },
+{"xsaveopt", 1, 0x0fae, 6, CpuXSAVE, NoSuf|Modrm, { LLongMem, 0, 0 } },
+
/* sentinel */
{NULL, 0, 0, 0, 0, 0, { 0, 0, 0} }
};
diff --git a/gnu/usr.bin/binutils/opcodes/i386-dis.c b/gnu/usr.bin/binutils/opcodes/i386-dis.c
index f33929fd8f8..cbdd567b226 100644
--- a/gnu/usr.bin/binutils/opcodes/i386-dis.c
+++ b/gnu/usr.bin/binutils/opcodes/i386-dis.c
@@ -100,6 +100,7 @@ static void OP_xcrypt (int, int);
static void OP_SIMD_Suffix (int, int);
static void SIMD_Fixup (int, int);
static void PNI_Fixup (int, int);
+static void XCR_Fixup (int, int);
static void INVLPG_Fixup (int, int);
static void OP_0f38 (int, int);
static void OP_0f3a (int, int);
@@ -1366,7 +1367,7 @@ static const struct dis386 grps[][8] = {
{
{ "sgdtQ", M, XX, XX },
{ "sidtQ", PNI_Fixup, 0, XX, XX },
- { "lgdtQ", M, XX, XX },
+ { "lgdtQ", XCR_Fixup, 0, XX, XX },
{ "lidtQ", M, XX, XX },
{ "smswQ", Ev, XX, XX },
{ "(bad)", XX, XX, XX },
@@ -1434,10 +1435,10 @@ static const struct dis386 grps[][8] = {
{ "fxrstor", Ev, XX, XX },
{ "ldmxcsr", Ev, XX, XX },
{ "stmxcsr", Ev, XX, XX },
- { "(bad)", XX, XX, XX },
- { "lfence", OP_0fae, 0, XX, XX },
- { "mfence", OP_0fae, 0, XX, XX },
- { "clflush", OP_0fae, 0, 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 },
},
/* GRP14 */
{
@@ -3962,6 +3963,11 @@ OP_0fae (int bytemode, int sizeflag)
{
if (reg == 7)
strcpy (obuf + strlen (obuf) - sizeof ("clflush") + 1, "sfence");
+ else if (reg == 6)
+ 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)
{
@@ -3969,9 +3975,9 @@ OP_0fae (int bytemode, int sizeflag)
return;
}
}
- else if (reg != 7)
+ else if (reg < 5)
{
- BadOp (); /* bad clflush */
+ BadOp (); /* bad sfence, mfence, or lfence */
return;
}
@@ -4181,6 +4187,29 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
}
static void
+XCR_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
+{
+ if (mod == 3 && reg == 2 && rm <= 1)
+ {
+ char *p = obuf + strlen (obuf);
+
+ /* Override "lgdt". */
+ if (rm)
+ {
+ strcpy (p - 4, "xsetbv");
+ }
+ else
+ {
+ strcpy (p - 4, "xgetbv");
+ }
+
+ codep++;
+ }
+ else
+ OP_M (0, sizeflag);
+}
+
+static void
INVLPG_Fixup (int bytemode, int sizeflag)
{
if (*codep == 0xf8)