summaryrefslogtreecommitdiffstats
path: root/contrib/binutils
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2012-07-04 22:12:10 +0000
committerjhb <jhb@FreeBSD.org>2012-07-04 22:12:10 +0000
commit2ce653dc23b0936cbde96f33f880475b25dbdaba (patch)
tree8ee8e0ddd2e44400cf824846499bf22e3f69e664 /contrib/binutils
parent4f65fa236f2375697aae8a26e4208dd71aadf951 (diff)
downloadFreeBSD-src-2ce653dc23b0936cbde96f33f880475b25dbdaba.zip
FreeBSD-src-2ce653dc23b0936cbde96f33f880475b25dbdaba.tar.gz
Add support for the 'xsave', 'xrstor', 'xsaveopt', 'xgetbv', and 'xsetbv'
instructions. I reimplemented this from scratch based on the Intel manuals and the existing support for handling the fxsave and fxrstor instructions. This will let us use these instructions natively with GCC rather than hardcoding the opcodes in hex. Reviewed by: kib MFC after: 1 month
Diffstat (limited to 'contrib/binutils')
-rw-r--r--contrib/binutils/gas/config/tc-i386.c4
-rw-r--r--contrib/binutils/opcodes/i386-dis.c56
-rw-r--r--contrib/binutils/opcodes/i386-opc.h3
-rw-r--r--contrib/binutils/opcodes/i386-opc.tbl7
-rw-r--r--contrib/binutils/opcodes/i386-tbl.h15
5 files changed, 74 insertions, 11 deletions
diff --git a/contrib/binutils/gas/config/tc-i386.c b/contrib/binutils/gas/config/tc-i386.c
index 296fdcd..4c13a72 100644
--- a/contrib/binutils/gas/config/tc-i386.c
+++ b/contrib/binutils/gas/config/tc-i386.c
@@ -517,7 +517,9 @@ static const arch_entry cpu_arch[] =
{".sse4a", PROCESSOR_UNKNOWN,
CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a},
{".abm", PROCESSOR_UNKNOWN,
- CpuABM}
+ CpuABM},
+ {".xsave", PROCESSOR_UNKNOWN,
+ CpuXSAVE}
};
const pseudo_typeS md_pseudo_table[] =
diff --git a/contrib/binutils/opcodes/i386-dis.c b/contrib/binutils/opcodes/i386-dis.c
index 10de45b..35d3282 100644
--- a/contrib/binutils/opcodes/i386-dis.c
+++ b/contrib/binutils/opcodes/i386-dis.c
@@ -93,6 +93,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);
@@ -1693,7 +1694,7 @@ static const struct dis386 grps[][8] = {
{
{ "sgdt{Q|IQ||}", { { VMX_Fixup, 0 } } },
{ "sidt{Q|IQ||}", { { PNI_Fixup, 0 } } },
- { "lgdt{Q|Q||}", { M } },
+ { "lgdt{Q|Q||}", { { XCR_Fixup, 0 } } },
{ "lidt{Q|Q||}", { { SVME_Fixup, 0 } } },
{ "smswD", { Sv } },
{ "(bad)", { XX } },
@@ -1783,9 +1784,9 @@ static const struct dis386 grps[][8] = {
{ "fxrstor", { Ev } },
{ "ldmxcsr", { Ev } },
{ "stmxcsr", { Ev } },
- { "(bad)", { XX } },
- { "lfence", { { OP_0fae, 0 } } },
- { "mfence", { { OP_0fae, 0 } } },
+ { "xsave", { Ev } },
+ { "xrstor", { { OP_0fae, v_mode } } },
+ { "xsaveopt", { { OP_0fae, v_mode } } },
{ "clflush", { { OP_0fae, 0 } } },
},
/* GRP16 */
@@ -5905,17 +5906,17 @@ OP_0fae (int bytemode, int sizeflag)
{
if (modrm.reg == 7)
strcpy (obuf + strlen (obuf) - sizeof ("clflush") + 1, "sfence");
+ else if (modrm.reg == 6)
+ strcpy (obuf + strlen (obuf) - sizeof ("xsaveopt") + 1, "mfence");
+ else if (modrm.reg == 5)
+ strcpy (obuf + strlen (obuf) - sizeof ("xrstor") + 1, "lfence");
if (modrm.reg < 5 || modrm.rm != 0)
{
BadOp (); /* bad sfence, mfence, or lfence */
return;
}
- }
- else if (modrm.reg != 7)
- {
- BadOp (); /* bad clflush */
- return;
+ bytemode = 0;
}
OP_E (bytemode, sizeflag);
@@ -6170,6 +6171,43 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
}
static void
+XCR_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
+{
+ if (modrm.mod == 3 && modrm.reg == 2 && modrm.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) == ' '
+ && CONST_STRNEQ (p - 7, "addr")
+ && (CONST_STRNEQ (p - 3, "16")
+ || CONST_STRNEQ (p - 3, "32")))
+ p -= 7;
+
+ if (modrm.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/contrib/binutils/opcodes/i386-opc.h b/contrib/binutils/opcodes/i386-opc.h
index 5372d4a..7605b52 100644
--- a/contrib/binutils/opcodes/i386-opc.h
+++ b/contrib/binutils/opcodes/i386-opc.h
@@ -71,6 +71,7 @@ typedef struct template
#define CpuABM 0x200000 /* ABM New Instructions required */
#define CpuSSE4_1 0x400000 /* SSE4.1 Instructions required */
#define CpuSSE4_2 0x800000 /* SSE4.2 Instructions required */
+#define CpuXSAVE 0x1000000 /* XSAVE Instructions required */
/* SSE4.1/4.2 Instructions required */
#define CpuSSE4 (CpuSSE4_1|CpuSSE4_2)
@@ -83,7 +84,7 @@ typedef struct template
#define CpuUnknownFlags (Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686 \
|CpuP4|CpuSledgehammer|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuVMX \
|Cpu3dnow|Cpu3dnowA|CpuK6|CpuPadLock|CpuSVME|CpuSSSE3|CpuSSE4_1 \
- |CpuSSE4_2|CpuABM|CpuSSE4a)
+ |CpuSSE4_2|CpuABM|CpuSSE4a|CpuXSAVE)
/* 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/contrib/binutils/opcodes/i386-opc.tbl b/contrib/binutils/opcodes/i386-opc.tbl
index 5465608..bfe8d41 100644
--- a/contrib/binutils/opcodes/i386-opc.tbl
+++ b/contrib/binutils/opcodes/i386-opc.tbl
@@ -1487,3 +1487,10 @@ xcryptcfb, 0, 0xf30fa7, 0xe0, Cpu686|CpuPadLock, No_bSuf|No_wSuf|No_lSuf|No_sSuf
xcryptofb, 0, 0xf30fa7, 0xe8, Cpu686|CpuPadLock, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|IsString|ImmExt, { 0 }
// Alias for xstore-rng.
xstore, 0, 0xfa7, 0xc0, Cpu686|CpuPadLock, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|IsString|ImmExt, { 0 }
+
+// XSAVE/XRSTOR related instructions
+xgetbv, 0, 0xf01, 0xd0, CpuXSAVE, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|ImmExt, { 0 }
+xsetbv, 0, 0xf01, 0xd1, CpuXSAVE, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|ImmExt, { 0 }
+xsave, 1, 0xfae, 0x4, CpuXSAVE, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_xSuf, { BaseIndex|Disp8|Disp16|Disp32|Disp32S }
+xsaveopt, 1, 0xfae, 0x6, CpuXSAVE, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_xSuf, { BaseIndex|Disp8|Disp16|Disp32|Disp32S }
+xrstor, 1, 0xfae, 0x5, CpuXSAVE, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_xSuf, { BaseIndex|Disp8|Disp16|Disp32|Disp32S }
diff --git a/contrib/binutils/opcodes/i386-tbl.h b/contrib/binutils/opcodes/i386-tbl.h
index fa843b3..9df5762 100644
--- a/contrib/binutils/opcodes/i386-tbl.h
+++ b/contrib/binutils/opcodes/i386-tbl.h
@@ -4288,6 +4288,21 @@ const template i386_optab[] =
{ "xstore", 0, 0xfa7, 0xc0, Cpu686|CpuPadLock,
No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|IsString|ImmExt,
{ 0 } },
+ { "xgetbv", 0, 0xf01, 0xd0, CpuXSAVE,
+ No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|ImmExt,
+ { 0 } },
+ { "xsetbv", 0, 0xf01, 0xd1, CpuXSAVE,
+ No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|ImmExt,
+ { 0 } },
+ { "xsave", 1, 0xfae, 0x4, CpuXSAVE,
+ Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_xSuf,
+ { BaseIndex|Disp8|Disp16|Disp32|Disp32S } },
+ { "xsaveopt", 1, 0xfae, 0x6, CpuXSAVE,
+ Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_xSuf,
+ { BaseIndex|Disp8|Disp16|Disp32|Disp32S } },
+ { "xrstor", 1, 0xfae, 0x5, CpuXSAVE,
+ Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_xSuf,
+ { BaseIndex|Disp8|Disp16|Disp32|Disp32S } },
{ NULL, 0, 0, 0, 0, 0, { 0 } }
};
OpenPOWER on IntegriCloud