This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
PATCH: Add Intel VMX instructions
- From: "H. J. Lu" <hjl at lucon dot org>
- To: binutils at sources dot redhat dot com
- Date: Thu, 14 Jul 2005 17:42:02 -0700
- Subject: PATCH: Add Intel VMX instructions
This patch adds Intel VMX instructions. I will check it in tomorrow.
H.J.
-----
gas/
2007-07-14 H.J. Lu <hongjiu.lu@intel.com>
* gas/config/tc-i386.h (CpuVMX): New.
(CpuUnknownFlags): Add CpuVMX.
gas/testsuite/
2007-07-14 H.J. Lu <hongjiu.lu@intel.com>
* gas/i386/i386.exp: Add vmx and x86-64-vmx.
* gas/i386/vmx.d: New file.
* gas/i386/vmx.s: Likewise.
* gas/i386/x86-64-vmx.d: Likewise.
* gas/i386/x86-64-vmx.s: Likewise.
include/opcode/
2007-07-14 H.J. Lu <hongjiu.lu@intel.com>
* i386.h (i386_optab): Support Intel VMX Instructions.
opcodes/
2007-07-14 H.J. Lu <hongjiu.lu@intel.com>
* i386-dis.c (OP_VMX): New. Handle Intel VMX Instructions.
(VMX_Fixup): New. Fix up Intel VMX Instructions.
(Em): New.
(Gm): New.
(VM): New.
(dis386_twobyte): Updated entries 0x78 and 0x79.
(twobyte_has_modrm): Likewise.
(grps): Use OP_VMX in the "sgdtIQ" entry. Updated GRP9.
(OP_G): Handle m_mode.
--- binutils/gas/config/tc-i386.h.vmx 2005-07-06 12:16:04.338368844 -0700
+++ binutils/gas/config/tc-i386.h 2005-07-06 12:19:30.108436457 -0700
@@ -186,6 +186,7 @@ typedef struct
#define CpuPNI CpuSSE3 /* Prescott New Instructions required */
#define CpuPadLock 0x40000 /* VIA PadLock required */
#define CpuSVME 0x80000 /* AMD Secure Virtual Machine Ext-s required */
+#define CpuVMX 0x100000 /* VMX Instructions required */
/* These flags are set by gas depending on the flag_code. */
#define Cpu64 0x4000000 /* 64bit support required */
@@ -193,7 +194,7 @@ 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 \
+ |CpuP4|CpuSledgehammer|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuPNI|CpuVMX \
|Cpu3dnow|Cpu3dnowA|CpuK6|CpuAthlon|CpuPadLock|CpuSVME)
/* the bits in opcode_modifier are used to generate the final opcode from
--- binutils/gas/testsuite/gas/i386/i386.exp.vmx 2005-07-06 08:45:43.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/i386.exp 2005-07-06 12:18:07.575046575 -0700
@@ -60,6 +60,7 @@ if [expr ([istarget "i*86-*-*"] || [ist
run_dump_test "sub"
run_dump_test "prescott"
run_dump_test "sib"
+ run_dump_test "vmx"
if {![istarget "*-*-aix*"]
&& (![is_elf_format] || [istarget "*-*-linux*"]
@@ -130,6 +131,7 @@ if [expr ([istarget "i*86-*-*"] || [ista
run_list_test "x86-64-inval-seg" "-al"
run_dump_test "x86-64-branch"
run_dump_test "svme64"
+ run_dump_test "x86-64-vmx"
# For ELF targets verify that @unwind works.
if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"]
--- binutils/gas/testsuite/gas/i386/vmx.d.vmx 2005-07-06 12:17:03.615593769 -0700
+++ binutils/gas/testsuite/gas/i386/vmx.d 2005-07-06 12:17:03.615593769 -0700
@@ -0,0 +1,25 @@
+#objdump: -dw
+#name: i386 VMX
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <foo>:
+ 0: 0f 01 c1 [ ]*vmcall
+ 3: 0f 01 c2 [ ]*vmlaunch
+ 6: 0f 01 c3 [ ]*vmresume
+ 9: 0f 01 c4 [ ]*vmxoff
+ c: 66 0f c7 30 [ ]*vmclear \(%eax\)
+ 10: 0f c7 30 [ ]*vmptrld \(%eax\)
+ 13: 0f c7 38 [ ]*vmptrst \(%eax\)
+ 16: f3 0f c7 30 [ ]*vmxon \(%eax\)
+ 1a: 0f 78 c3 [ ]*vmread %eax,%ebx
+ 1d: 0f 78 c3 [ ]*vmread %eax,%ebx
+ 20: 0f 78 03 [ ]*vmread %eax,\(%ebx\)
+ 23: 0f 78 03 [ ]*vmread %eax,\(%ebx\)
+ 26: 0f 79 d8 [ ]*vmwrite %eax,%ebx
+ 29: 0f 79 d8 [ ]*vmwrite %eax,%ebx
+ 2c: 0f 79 18 [ ]*vmwrite \(%eax\),%ebx
+ 2f: 0f 79 18 [ ]*vmwrite \(%eax\),%ebx
+ ...
--- binutils/gas/testsuite/gas/i386/vmx.s.vmx 2005-07-06 12:17:03.615593769 -0700
+++ binutils/gas/testsuite/gas/i386/vmx.s 2005-07-06 12:17:03.615593769 -0700
@@ -0,0 +1,21 @@
+# VMX Instructions
+
+ .text
+foo:
+ vmcall
+ vmlaunch
+ vmresume
+ vmxoff
+ vmclear (%eax)
+ vmptrld (%eax)
+ vmptrst (%eax)
+ vmxon (%eax)
+ vmread %eax,%ebx
+ vmreadl %eax,%ebx
+ vmread %eax,(%ebx)
+ vmreadl %eax,(%ebx)
+ vmwrite %eax,%ebx
+ vmwritel %eax,%ebx
+ vmwrite (%eax),%ebx
+ vmwritel (%eax),%ebx
+ .p2align 4,0
--- binutils/gas/testsuite/gas/i386/x86-64-vmx.d.vmx 2005-07-06 12:17:03.616593604 -0700
+++ binutils/gas/testsuite/gas/i386/x86-64-vmx.d 2005-07-06 12:17:03.616593604 -0700
@@ -0,0 +1,25 @@
+#objdump: -dw
+#name: 64bit VMX
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <foo>:
+ 0: 0f 01 c1 [ ]*vmcall
+ 3: 0f 01 c2 [ ]*vmlaunch
+ 6: 0f 01 c3 [ ]*vmresume
+ 9: 0f 01 c4 [ ]*vmxoff
+ c: 66 0f c7 30 [ ]*vmclear \(%rax\)
+ 10: 0f c7 30 [ ]*vmptrld \(%rax\)
+ 13: 0f c7 38 [ ]*vmptrst \(%rax\)
+ 16: f3 0f c7 30 [ ]*vmxon \(%rax\)
+ 1a: 0f 78 c3 [ ]*vmread %rax,%rbx
+ 1d: 0f 78 c3 [ ]*vmread %rax,%rbx
+ 20: 0f 78 03 [ ]*vmread %rax,\(%rbx\)
+ 23: 0f 78 03 [ ]*vmread %rax,\(%rbx\)
+ 26: 0f 79 d8 [ ]*vmwrite %rax,%rbx
+ 29: 0f 79 d8 [ ]*vmwrite %rax,%rbx
+ 2c: 0f 79 18 [ ]*vmwrite \(%rax\),%rbx
+ 2f: 0f 79 18 [ ]*vmwrite \(%rax\),%rbx
+ ...
--- binutils/gas/testsuite/gas/i386/x86-64-vmx.s.vmx 2005-07-06 12:17:03.616593604 -0700
+++ binutils/gas/testsuite/gas/i386/x86-64-vmx.s 2005-07-06 12:17:03.616593604 -0700
@@ -0,0 +1,21 @@
+# VMX Instructions
+
+ .text
+foo:
+ vmcall
+ vmlaunch
+ vmresume
+ vmxoff
+ vmclear (%rax)
+ vmptrld (%rax)
+ vmptrst (%rax)
+ vmxon (%rax)
+ vmread %rax,%rbx
+ vmreadq %rax,%rbx
+ vmread %rax,(%rbx)
+ vmreadq %rax,(%rbx)
+ vmwrite %rax,%rbx
+ vmwriteq %rax,%rbx
+ vmwrite (%rax),%rbx
+ vmwriteq (%rax),%rbx
+ .p2align 4,0
--- binutils/include/opcode/i386.h.vmx 2005-07-06 08:45:41.000000000 -0700
+++ binutils/include/opcode/i386.h 2005-07-06 12:17:03.627591791 -0700
@@ -1347,6 +1347,20 @@ static const template i386_optab[] =
/* Need to ensure only "mwait %eax,%ecx" is accepted. */
{"mwait", 2, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+/* VMX instructions. */
+{"vmcall", 0, 0x0f01, 0xc1, CpuVMX, NoSuf|ImmExt, { 0, 0, 0} },
+{"vmclear", 1, 0x660fc7, 6, CpuVMX, NoSuf|IgnoreSize|Modrm|NoRex64, { LLongMem, 0, 0} },
+{"vmlaunch", 0, 0x0f01, 0xc2, CpuVMX, NoSuf|ImmExt, { 0, 0, 0} },
+{"vmresume", 0, 0x0f01, 0xc3, CpuVMX, NoSuf|ImmExt, { 0, 0, 0} },
+{"vmptrld", 1, 0x0fc7, 6, CpuVMX, NoSuf|IgnoreSize|Modrm|NoRex64, { LLongMem, 0, 0} },
+{"vmptrst", 1, 0x0fc7, 7, CpuVMX, NoSuf|IgnoreSize|Modrm|NoRex64, { LLongMem, 0, 0} },
+{"vmread", 2, 0x0f78, X, CpuVMX|CpuNo64, l_Suf|Modrm,{ Reg32, Reg32|LongMem, 0} },
+{"vmread", 2, 0x0f78, X, CpuVMX|Cpu64, q_Suf|Modrm|NoRex64,{ Reg64, Reg64|LLongMem, 0} },
+{"vmwrite", 2, 0x0f79, X, CpuVMX|CpuNo64, l_Suf|Modrm,{ Reg32|LongMem, Reg32, 0} },
+{"vmwrite", 2, 0x0f79, X, CpuVMX|Cpu64, q_Suf|Modrm|NoRex64,{ Reg64|LLongMem, Reg64, 0} },
+{"vmxoff", 0, 0x0f01, 0xc4, CpuVMX, NoSuf|ImmExt, { 0, 0, 0} },
+{"vmxon", 1, 0xf30fc7, 6, CpuVMX, NoSuf|IgnoreSize|Modrm|NoRex64, { LLongMem, 0, 0} },
+
/* AMD 3DNow! instructions. */
{"prefetch", 1, 0x0f0d, 0, Cpu3dnow, NoSuf|IgnoreSize|Modrm, { ByteMem, 0, 0 } },
--- binutils/opcodes/i386-dis.c.vmx 2005-07-06 08:45:34.000000000 -0700
+++ binutils/opcodes/i386-dis.c 2005-07-06 12:17:03.632590966 -0700
@@ -88,6 +88,7 @@ static void OP_EX (int, int);
static void OP_MS (int, int);
static void OP_XS (int, int);
static void OP_M (int, int);
+static void OP_VMX (int, int);
static void OP_0fae (int, int);
static void OP_0f07 (int, int);
static void NOP_Fixup (int, int);
@@ -99,6 +100,7 @@ static void SVME_Fixup (int, int);
static void INVLPG_Fixup (int, int);
static void BadOp (void);
static void SEG_Fixup (int, int);
+static void VMX_Fixup (int, int);
struct dis_private {
/* Points to first byte not fetched. */
@@ -200,6 +202,7 @@ fetch_data (struct disassemble_info *inf
#define Edqw OP_E, dqw_mode
#define indirEv OP_indirE, branch_v_mode
#define indirEp OP_indirE, f_mode
+#define Em OP_E, m_mode
#define Ew OP_E, w_mode
#define Ma OP_E, v_mode
#define M OP_M, 0 /* lea, lgdt, etc. */
@@ -208,6 +211,7 @@ fetch_data (struct disassemble_info *inf
#define Gv OP_G, v_mode
#define Gd OP_G, d_mode
#define Gdq OP_G, dq_mode
+#define Gm OP_G, m_mode
#define Gw OP_G, w_mode
#define Rd OP_Rd, d_mode
#define Rm OP_Rd, m_mode
@@ -299,6 +303,7 @@ fetch_data (struct disassemble_info *inf
#define EX OP_EX, v_mode
#define MS OP_MS, v_mode
#define XS OP_XS, v_mode
+#define VM OP_VMX, q_mode
#define OPSUF OP_3DNowSuffix, 0
#define OPSIMD OP_SIMD_Suffix, 0
@@ -915,8 +920,8 @@ static const struct dis386 dis386_twobyt
{ "pcmpeqd", MX, EM, XX },
{ "emms", XX, XX, XX },
/* 78 */
- { "(bad)", XX, XX, XX },
- { "(bad)", XX, XX, XX },
+ { "vmread", Em, Gm, XX },
+ { "vmwrite", Gm, Em, XX },
{ "(bad)", XX, XX, XX },
{ "(bad)", XX, XX, XX },
{ PREGRP28 },
@@ -1102,7 +1107,7 @@ static const unsigned char twobyte_has_m
/* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
/* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */
/* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */
- /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1, /* 7f */
+ /* 70 */ 1,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1, /* 7f */
/* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
/* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
/* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */
@@ -1372,7 +1377,7 @@ static const struct dis386 grps[][8] = {
},
/* GRP7 */
{
- { "sgdtIQ", M, XX, XX },
+ { "sgdtIQ", VMX_Fixup, 0, XX, XX },
{ "sidtIQ", PNI_Fixup, 0, XX, XX },
{ "lgdt{Q|Q||}", M, XX, XX },
{ "lidt{Q|Q||}", SVME_Fixup, 0, XX, XX },
@@ -1400,8 +1405,8 @@ static const struct dis386 grps[][8] = {
{ "(bad)", XX, XX, XX },
{ "(bad)", XX, XX, XX },
{ "(bad)", XX, XX, XX },
- { "(bad)", XX, XX, XX },
- { "(bad)", XX, XX, XX },
+ { "", VM, XX, XX }, /* See OP_VMX. */
+ { "vmptrst", Eq, XX, XX },
},
/* GRP10 */
{
@@ -3487,6 +3492,12 @@ OP_G (int bytemode, int sizeflag)
oappend (names16[reg + add]);
used_prefixes |= (prefixes & PREFIX_DATA);
break;
+ case m_mode:
+ if (mode_64bit)
+ oappend (names64[reg + add]);
+ else
+ oappend (names32[reg + add]);
+ break;
default:
oappend (INTERNAL_DISASSEMBLER_ERROR);
break;
@@ -4597,3 +4608,50 @@ SEG_Fixup (int extrachar, int sizeflag)
OP_E (extrachar, sizeflag);
}
+
+static void
+VMX_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
+{
+ if (mod == 3 && reg == 0 && rm >=1 && rm <= 4)
+ {
+ /* Override "sgdt". */
+ char *p = obuf + strlen (obuf) - 4;
+
+ /* We might have a suffix. */
+ if (*p == 'i')
+ --p;
+
+ switch (rm)
+ {
+ case 1:
+ strcpy (p, "vmcall");
+ break;
+ case 2:
+ strcpy (p, "vmlaunch");
+ break;
+ case 3:
+ strcpy (p, "vmresume");
+ break;
+ case 4:
+ strcpy (p, "vmxoff");
+ break;
+ }
+
+ codep++;
+ }
+ else
+ OP_E (0, sizeflag);
+}
+
+static void
+OP_VMX (int bytemode, int sizeflag)
+{
+ used_prefixes |= (prefixes & (PREFIX_DATA | PREFIX_REPZ));
+ if (prefixes & PREFIX_DATA)
+ strcpy (obuf, "vmclear");
+ else if (prefixes & PREFIX_REPZ)
+ strcpy (obuf, "vmxon");
+ else
+ strcpy (obuf, "vmptrld");
+ OP_E (bytemode, sizeflag);
+}