diff --git a/contrib/binutils/gas/config/tc-i386.c b/contrib/binutils/gas/config/tc-i386.c index 296fdcdde41..4c13a72a46e 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 10de45bcbc9..35d32827caa 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); @@ -6169,6 +6170,43 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag) OP_M (0, 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) { diff --git a/contrib/binutils/opcodes/i386-opc.h b/contrib/binutils/opcodes/i386-opc.h index 5372d4a65aa..7605b521f8a 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 5465608ebee..bfe8d4173da 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 fa843b33473..9df576224c8 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 } } };