diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2014-02-09 22:42:28 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2014-02-09 22:42:28 +0000 |
commit | 3d28e9ace295091b0d7b011e31f3f5344ef7a4e7 (patch) | |
tree | 682c2df4e4d999ba9289d9ea3df3ddd56969fbd1 | |
parent | 1479cfc9acfbc2f084be12b3af9c73435479da5d (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.c | 2 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/gas/config/tc-i386.h | 13 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/include/opcode/i386.h | 7 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/opcodes/i386-dis.c | 58 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gas/config/tc-i386.c | 2 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gas/config/tc-i386.h | 11 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/include/opcode/i386.h | 7 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/opcodes/i386-dis.c | 43 |
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) |