From owner-svn-src-all@FreeBSD.ORG Wed Aug 29 19:34:47 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 460CA1065670; Wed, 29 Aug 2012 19:34:47 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2E3CB8FC1A; Wed, 29 Aug 2012 19:34:47 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q7TJYkcJ002041; Wed, 29 Aug 2012 19:34:46 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q7TJYkff002035; Wed, 29 Aug 2012 19:34:46 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201208291934.q7TJYkff002035@svn.freebsd.org> From: John Baldwin Date: Wed, 29 Aug 2012 19:34:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r239878 - in stable/9/contrib/binutils: gas/config opcodes X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 29 Aug 2012 19:34:47 -0000 Author: jhb Date: Wed Aug 29 19:34:46 2012 New Revision: 239878 URL: http://svn.freebsd.org/changeset/base/239878 Log: MFC 238123,238167: - 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. - Add support for the 'invept' and 'invvpid' instructions. Beyond simply adding appropriate table entries, the assembler had to be adjusted as these are the first non-SSE instructions to use a 3-byte opcode (and a mandatory prefix to boot). Modified: stable/9/contrib/binutils/gas/config/tc-i386.c stable/9/contrib/binutils/opcodes/i386-dis.c stable/9/contrib/binutils/opcodes/i386-opc.h stable/9/contrib/binutils/opcodes/i386-opc.tbl stable/9/contrib/binutils/opcodes/i386-tbl.h Directory Properties: stable/9/contrib/binutils/ (props changed) Modified: stable/9/contrib/binutils/gas/config/tc-i386.c ============================================================================== --- stable/9/contrib/binutils/gas/config/tc-i386.c Wed Aug 29 19:17:35 2012 (r239877) +++ stable/9/contrib/binutils/gas/config/tc-i386.c Wed Aug 29 19:34:46 2012 (r239878) @@ -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[] = @@ -3988,6 +3990,16 @@ output_insn (void) goto check_prefix; } } + else if (i.tm.base_opcode == 0x660f3880 || i.tm.base_opcode == 0x660f3881) + { + /* invept and invvpid are 3 byte instructions with a + mandatory prefix. */ + if (i.tm.base_opcode & 0xff000000) + { + prefix = (i.tm.base_opcode >> 24) & 0xff; + add_prefix (prefix); + } + } else if ((i.tm.base_opcode & 0xff0000) != 0) { prefix = (i.tm.base_opcode >> 16) & 0xff; @@ -4027,6 +4039,12 @@ output_insn (void) p = frag_more (3); *p++ = (i.tm.base_opcode >> 16) & 0xff; } + else if (i.tm.base_opcode == 0x660f3880 || + i.tm.base_opcode == 0x660f3881) + { + p = frag_more (3); + *p++ = (i.tm.base_opcode >> 16) & 0xff; + } else p = frag_more (2); Modified: stable/9/contrib/binutils/opcodes/i386-dis.c ============================================================================== --- stable/9/contrib/binutils/opcodes/i386-dis.c Wed Aug 29 19:17:35 2012 (r239877) +++ stable/9/contrib/binutils/opcodes/i386-dis.c Wed Aug 29 19:34:46 2012 (r239878) @@ -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); @@ -212,6 +213,7 @@ fetch_data (struct disassemble_info *inf #define Ew { OP_E, w_mode } #define M { OP_M, 0 } /* lea, lgdt, etc. */ #define Ma { OP_M, v_mode } +#define Mo { OP_M, o_mode } #define Mp { OP_M, f_mode } /* 32 or 48 bit memory operand for LDS, LES etc */ #define Mq { OP_M, q_mode } #define Gb { OP_G, b_mode } @@ -539,6 +541,8 @@ fetch_data (struct disassemble_info *inf #define PREGRP95 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 95 } } #define PREGRP96 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 96 } } #define PREGRP97 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 97 } } +#define PREGRP98 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 98 } } +#define PREGRP99 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 99 } } #define X86_64_0 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 0 } } @@ -1693,7 +1697,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 +1787,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 */ @@ -2585,6 +2589,22 @@ static const struct dis386 prefix_user_t { "punpckldq",{ MX, EMq } }, { "(bad)", { XX } }, }, + + /* PREGRP98 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "invept", { Gm, Mo } }, + { "(bad)", { XX } }, + }, + + /* PREGRP99 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "invvpid",{ Gm, Mo } }, + { "(bad)", { XX } }, + }, }; static const struct dis386 x86_64_table[][2] = { @@ -2754,8 +2774,8 @@ static const struct dis386 three_byte_ta { "(bad)", { XX } }, { "(bad)", { XX } }, /* 80 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP98 }, + { PREGRP99 }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, @@ -5883,7 +5903,7 @@ static void OP_M (int bytemode, int sizeflag) { if (modrm.mod == 3) - /* bad bound,lea,lds,les,lfs,lgs,lss,cmpxchg8b,vmptrst modrm */ + /* bad bound,lea,lds,les,lfs,lgs,lss,cmpxchg8b,vmptrst,invept,invvpid modrm */ BadOp (); else OP_E (bytemode, sizeflag); @@ -5905,17 +5925,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 +6190,43 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE } 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; Modified: stable/9/contrib/binutils/opcodes/i386-opc.h ============================================================================== --- stable/9/contrib/binutils/opcodes/i386-opc.h Wed Aug 29 19:17:35 2012 (r239877) +++ stable/9/contrib/binutils/opcodes/i386-opc.h Wed Aug 29 19:34:46 2012 (r239878) @@ -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 Modified: stable/9/contrib/binutils/opcodes/i386-opc.tbl ============================================================================== --- stable/9/contrib/binutils/opcodes/i386-opc.tbl Wed Aug 29 19:17:35 2012 (r239877) +++ stable/9/contrib/binutils/opcodes/i386-opc.tbl Wed Aug 29 19:34:46 2012 (r239878) @@ -1289,6 +1289,10 @@ mwait, 2, 0xf01, 0xc9, CpuSSE3|CpuNo64, mwait, 2, 0xf01, 0xc9, CpuSSE3|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|ImmExt|NoRex64, { Reg64, Reg64 } // VMX instructions. +invept, 2, 0x660f3880, None, CpuVMX|CpuNo64, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_xSuf|NoRex64, { BaseIndex|Disp8|Disp16|Disp32|Disp32S, Reg32 } +invept, 2, 0x660f3880, None, CpuVMX|Cpu64, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_xSuf|NoRex64, { BaseIndex|Disp8|Disp16|Disp32|Disp32S, Reg64 } +invvpid, 2, 0x660f3881, None, CpuVMX|CpuNo64, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_xSuf|NoRex64, { BaseIndex|Disp8|Disp16|Disp32|Disp32S, Reg32 } +invvpid, 2, 0x660f3881, None, CpuVMX|Cpu64, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_xSuf|NoRex64, { BaseIndex|Disp8|Disp16|Disp32|Disp32S, Reg64 } vmcall, 0, 0xf01, 0xc1, CpuVMX, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|ImmExt, { 0 } vmclear, 1, 0x660fc7, 0x6, CpuVMX, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|NoRex64, { BaseIndex|Disp8|Disp16|Disp32|Disp32S } vmlaunch, 0, 0xf01, 0xc2, CpuVMX, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|ImmExt, { 0 } @@ -1487,3 +1491,10 @@ xcryptcfb, 0, 0xf30fa7, 0xe0, Cpu686|Cpu 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 } Modified: stable/9/contrib/binutils/opcodes/i386-tbl.h ============================================================================== --- stable/9/contrib/binutils/opcodes/i386-tbl.h Wed Aug 29 19:17:35 2012 (r239877) +++ stable/9/contrib/binutils/opcodes/i386-tbl.h Wed Aug 29 19:34:46 2012 (r239878) @@ -3625,6 +3625,22 @@ const template i386_optab[] = No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|ImmExt|NoRex64, { Reg64, Reg64 } }, + { "invept", 2, 0x660f3880, None, CpuVMX|CpuNo64, + Modrm|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_xSuf|NoRex64, + { BaseIndex|Disp8|Disp16|Disp32|Disp32S, + Reg32 } }, + { "invept", 2, 0x660f3880, None, CpuVMX|Cpu64, + Modrm|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_xSuf|NoRex64, + { BaseIndex|Disp8|Disp16|Disp32|Disp32S, + Reg64 } }, + { "invvpid", 2, 0x660f3881, None, CpuVMX|CpuNo64, + Modrm|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_xSuf|NoRex64, + { BaseIndex|Disp8|Disp16|Disp32|Disp32S, + Reg32 } }, + { "invvpid", 2, 0x660f3881, None, CpuVMX|Cpu64, + Modrm|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_xSuf|NoRex64, + { BaseIndex|Disp8|Disp16|Disp32|Disp32S, + Reg64 } }, { "vmcall", 0, 0xf01, 0xc1, CpuVMX, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf|ImmExt, { 0 } }, @@ -4288,6 +4304,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 } } };