Externals: update Bochs to newer version

Should resolve the disassembler not handling all the opcodes Dolphin generates.
This commit is contained in:
Fiora 2014-08-15 00:43:46 -07:00
parent 001c9a18fa
commit 290643ad25
21 changed files with 12016 additions and 7493 deletions

View File

@ -50,14 +50,18 @@
<ClInclude Include="dis_tables.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dis_decode.cpp" />
<ClCompile Include="dis_groups.cpp" />
<ClCompile Include="resolve.cpp" />
<ClCompile Include="syntax.cpp" />
<ClCompile Include="dis_decode.cc" />
<ClCompile Include="dis_groups.cc" />
<ClCompile Include="resolve.cc" />
<ClCompile Include="syntax.cc" />
</ItemGroup>
<ItemGroup>
<None Include="dis_tables.inl" />
<None Include="opcodes.inl" />
<None Include="opcodes.inc" />
<None Include="dis_tables.inc" />
<None Include="dis_tables_avx.inc" />
<None Include="dis_tables_sse.inc" />
<None Include="dis_tables_x87.inc" />
<None Include="dis_tables_xop.inc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -1,7 +1,7 @@
set(SRCS dis_decode.cpp
dis_groups.cpp
resolve.cpp
syntax.cpp)
set(SRCS dis_decode.cc
dis_groups.cc
resolve.cc
syntax.cc)
if(WIN32)
set(SRCS ${SRCS} stdafx.cpp)

82
Externals/Bochs_disasm/Makefile.in vendored Normal file
View File

@ -0,0 +1,82 @@
# Copyright (C) 2001 The Bochs Project
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
@SUFFIX_LINE@
srcdir = @srcdir@
VPATH = @srcdir@
top_builddir = ..
top_srcdir = @top_srcdir@
SHELL = @SHELL@
@SET_MAKE@
CXX = @CXX@
CXXFLAGS = @CXXFLAGS@ @GUI_CXXFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
RANLIB = @RANLIB@
# ===========================================================
# end of configurable options
# ===========================================================
BX_OBJS = \
dis_decode.o \
dis_groups.o \
resolve.o \
syntax.o
BX_INCLUDES = disasm.h
BX_INCDIRS = -I.. -I$(srcdir)/.. -I../@INSTRUMENT_DIR@ -I$(srcdir)/../@INSTRUMENT_DIR@
all: libdisasm.a
.@CPP_SUFFIX@.o:
$(CXX) @DASH@c $(BX_INCDIRS) $(CXXFLAGS) @CXXFP@$< @OFP@$@
libdisasm.a: $(BX_OBJS)
@RMCOMMAND@ libdisasm.a
@MAKELIB@ $(BX_OBJS)
$(RANLIB) libdisasm.a
$(BX_OBJS): $(BX_INCLUDES)
clean:
@RMCOMMAND@ *.o
@RMCOMMAND@ *.a
dist-clean: clean
@RMCOMMAND@ Makefile
###########################################
# dependencies generated by
# gcc -MM -I.. -I../instrument/stubs *.cc | sed 's/\.cc/.@CPP_SUFFIX@/g'
###########################################
dis_decode.o: dis_decode.@CPP_SUFFIX@ disasm.h ../config.h dis_tables.h opcodes.inc \
dis_tables.inc dis_tables_x87.inc dis_tables_sse.inc dis_tables_avx.inc dis_tables_xop.inc
dis_groups.o: dis_groups.@CPP_SUFFIX@ disasm.h ../config.h
resolve.o: resolve.@CPP_SUFFIX@ disasm.h ../config.h
syntax.o: syntax.@CPP_SUFFIX@ disasm.h ../config.h

View File

@ -38,4 +38,8 @@ typedef Bit64u bx_address;
#endif
#define BX_CONST64(x) (x##LL)
#define GET32L(val64) ((Bit32u)(((Bit64u)(val64)) & 0xFFFFFFFF))
#define GET32H(val64) ((Bit32u)(((Bit64u)(val64)) >> 32))
#endif

557
Externals/Bochs_disasm/dis_decode.cc vendored Normal file
View File

@ -0,0 +1,557 @@
/////////////////////////////////////////////////////////////////////////
// $Id: dis_decode.cc 11873 2013-10-10 21:00:26Z sshwarts $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2005-2012 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "disasm.h"
#include "dis_tables.h"
#define OPCODE(entry) ((BxDisasmOpcodeInfo_t*) entry->OpcodeInfo)
#define OPCODE_TABLE(entry) ((BxDisasmOpcodeTable_t*) entry->OpcodeInfo)
static const unsigned char instruction_has_modrm[512] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* ------------------------------- */
/* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
/* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
/* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
/* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
/* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,
/* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
/* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* A0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* B0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* C0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
/* D0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,
/* E0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* F0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* ------------------------------- */
1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0F 00 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 10 */
1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 0F 20 */
0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 0F 30 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 40 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 50 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 60 */
1,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1, /* 0F 70 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0F 80 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 90 */
0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1, /* 0F A0 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F B0 */
1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* 0F C0 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F D0 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F E0 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* 0F F0 */
/* ------------------------------- */
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
};
unsigned disassembler::disasm(bx_bool is_32, bx_bool is_64, bx_address cs_base, bx_address ip, const Bit8u *instr, char *disbuf)
{
x86_insn insn = decode(is_32, is_64, cs_base, ip, instr, disbuf);
return insn.ilen;
}
x86_insn disassembler::decode(bx_bool is_32, bx_bool is_64, bx_address cs_base, bx_address ip, const Bit8u *instr, char *disbuf)
{
if (is_64) is_32 = 1;
x86_insn insn(is_32, is_64);
const Bit8u *instruction_begin = instruction = instr;
resolve_modrm = NULL;
db_eip = ip;
db_cs_base = cs_base; // cs linear base (cs_base for PM & cs<<4 for RM & VM)
disbufptr = disbuf; // start sprintf()'ing into beginning of buffer
#define SSE_PREFIX_NONE 0
#define SSE_PREFIX_66 1
#define SSE_PREFIX_F3 2
#define SSE_PREFIX_F2 3 /* only one SSE prefix could be used */
unsigned sse_prefix = SSE_PREFIX_NONE, sse_opcode = 0;
unsigned rex_prefix = 0, prefixes = 0;
for(;;)
{
insn.b1 = fetch_byte();
prefixes++;
switch(insn.b1) {
case 0x40: // rex
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47:
case 0x48:
case 0x49:
case 0x4A:
case 0x4B:
case 0x4C:
case 0x4D:
case 0x4E:
case 0x4F:
if (! is_64) break;
rex_prefix = insn.b1;
continue;
case 0x26: // ES:
case 0x2e: // CS:
case 0x36: // SS:
case 0x3e: // DS:
if (! is_64) insn.seg_override = (insn.b1 >> 3) & 3;
rex_prefix = 0;
continue;
case 0x64: // FS:
case 0x65: // GS:
insn.seg_override = insn.b1 & 0xf;
rex_prefix = 0;
continue;
case 0x66: // operand size override
if (!insn.os_64) insn.os_32 = !is_32;
if (!sse_prefix) sse_prefix = SSE_PREFIX_66;
rex_prefix = 0;
continue;
case 0x67: // address size override
if (!is_64) insn.as_32 = !is_32;
insn.as_64 = 0;
rex_prefix = 0;
continue;
case 0xf0: // lock
rex_prefix = 0;
continue;
case 0xf2: // repne
case 0xf3: // rep
sse_prefix = (insn.b1 & 0xf) ^ 1;
rex_prefix = 0;
continue;
// no more prefixes
default:
break;
}
break;
}
if (insn.b1 == 0x0f)
{
insn.b1 = 0x100 | fetch_byte();
}
if (rex_prefix) {
insn.extend8b = 1;
if (rex_prefix & 0x8) {
insn.os_64 = 1;
insn.os_32 = 1;
}
if (rex_prefix & 0x4) insn.rex_r = 8;
if (rex_prefix & 0x2) insn.rex_x = 8;
if (rex_prefix & 0x1) insn.rex_b = 8;
}
const BxDisasmOpcodeTable_t *opcode_table, *entry;
if (is_64) {
if (insn.os_64)
opcode_table = BxDisasmOpcodes64q;
else if (insn.os_32)
opcode_table = BxDisasmOpcodes64d;
else
opcode_table = BxDisasmOpcodes64w;
} else {
if (insn.os_32)
opcode_table = BxDisasmOpcodes32;
else
opcode_table = BxDisasmOpcodes16;
}
entry = opcode_table + insn.b1;
if ((insn.b1 & ~1) == 0xc4 && (is_64 || (peek_byte() & 0xc0) == 0xc0))
{
if (sse_prefix)
dis_sprintf("(bad vex+rex prefix) ");
if (rex_prefix)
dis_sprintf("(bad vex+sse prefix) ");
// decode 0xC4 or 0xC5 VEX prefix
sse_prefix = decode_vex(&insn);
if (insn.b1 < 256 || insn.b1 >= 1024)
entry = &BxDisasmGroupSSE_ERR[0];
else
entry = BxDisasmOpcodesAVX + (insn.b1 - 256);
}
/*
if (insn.b1== 0x62 && (is_64 || (peek_byte() & 0xc0) == 0xc0))
{
if (sse_prefix)
dis_sprintf("(bad evex+rex prefix) ");
if (rex_prefix)
dis_sprintf("(bad evex+sse prefix) ");
// decode 0x62 EVEX prefix
sse_prefix = decode_evex(&insn);
if (insn.b1 < 256 || insn.b1 >= 1024)
entry = &BxDisasmGroupSSE_ERR[0];
// else
// entry = BxDisasmOpcodesEVEX + (insn.b1 - 256);
}
*/
else if (insn.b1 == 0x8f && (is_64 || (peek_byte() & 0xc0) == 0xc0) && (peek_byte() & 0x8) == 0x8)
{
if (sse_prefix)
dis_sprintf("(bad xop+rex prefix) ");
if (rex_prefix)
dis_sprintf("(bad xop+sse prefix) ");
// decode 0x8F XOP prefix
sse_prefix = decode_xop(&insn);
if (insn.b1 >= 768 || sse_prefix != 0)
entry = &BxDisasmGroupSSE_ERR[0];
else
entry = BxDisasmOpcodesXOP + insn.b1;
}
if (insn.b1 >= 512 || instruction_has_modrm[insn.b1] || insn.is_xop > 0)
{
// take 3rd byte for 3-byte opcode
if (entry->Attr == _GRP3BOP) {
entry = &(OPCODE_TABLE(entry)[fetch_byte()]);
}
decode_modrm(&insn);
}
int attr = entry->Attr;
while(attr)
{
switch(attr) {
case _GROUPN:
entry = &(OPCODE_TABLE(entry)[insn.nnn & 7]);
break;
case _GRPSSE66:
/* SSE opcode group with only prefix 0x66 allowed */
sse_opcode = 1;
if (sse_prefix != SSE_PREFIX_66)
entry = &(BxDisasmGroupSSE_ERR[sse_prefix]);
attr = 0;
continue;
case _GRPSSEF2:
/* SSE opcode group with only prefix 0xF2 allowed */
sse_opcode = 1;
if (sse_prefix != SSE_PREFIX_F2)
entry = &(BxDisasmGroupSSE_ERR[sse_prefix]);
attr = 0;
continue;
case _GRPSSEF3:
/* SSE opcode group with only prefix 0xF3 allowed */
sse_opcode = 1;
if (sse_prefix != SSE_PREFIX_F3)
entry = &(BxDisasmGroupSSE_ERR[sse_prefix]);
attr = 0;
continue;
case _GRPSSENONE:
/* SSE opcode group with no prefix only allowed */
sse_opcode = 1;
if (sse_prefix != SSE_PREFIX_NONE)
entry = &(BxDisasmGroupSSE_ERR[sse_prefix]);
attr = 0;
continue;
case _GRPSSE:
sse_opcode = 1;
/* For SSE opcodes, look into another 4 entries table
with the opcode prefixes (NONE, 0x66, 0xF2, 0xF3) */
entry = &(OPCODE_TABLE(entry)[sse_prefix]);
break;
case _GRPSSE2:
sse_opcode = 1;
/* For SSE opcodes, look into another 2 entries table
with the opcode prefixes (NONE, 0x66)
SSE prefixes 0xF2 and 0xF3 are not allowed */
if (sse_prefix > SSE_PREFIX_66)
entry = &(BxDisasmGroupSSE_ERR[sse_prefix]);
else
entry = &(OPCODE_TABLE(entry)[sse_prefix]);
break;
case _SPLIT11B:
entry = &(OPCODE_TABLE(entry)[insn.mod != 3]); /* REG/MEM */
break;
case _GRPRM:
entry = &(OPCODE_TABLE(entry)[insn.rm & 7]);
break;
case _GRPFP:
if(insn.mod != 3)
{
entry = &(OPCODE_TABLE(entry)[insn.nnn & 7]);
} else {
int index = (insn.b1-0xD8)*64 + (insn.modrm & 0x3f);
entry = &(BxDisasmOpcodeInfoFP[index]);
}
break;
case _GRP3DNOW:
entry = &(BxDisasm3DNowGroup[fetch_byte()]);
break;
case _GRP64B:
entry = &(OPCODE_TABLE(entry)[insn.os_64 ? 2 : insn.os_32]);
if (sse_prefix == SSE_PREFIX_66)
sse_prefix = 0;
break;
case _GRPVEXW:
entry = &(OPCODE_TABLE(entry)[insn.vex_w]);
break;
default:
printf("Internal disassembler error - unknown attribute !\n");
return x86_insn(is_32, is_64);
}
/* get additional attributes from group table */
attr = entry->Attr;
}
#define BRANCH_NOT_TAKEN 0x2E
#define BRANCH_TAKEN 0x3E
unsigned branch_hint = 0;
// print prefixes
for(unsigned i=0;i<prefixes;i++)
{
Bit8u prefix_byte = *(instr+i);
if (prefix_byte == 0xF0) dis_sprintf("lock ");
if (! insn.is_xop && ! insn.is_vex) {
if (insn.b1 == 0x90 && !insn.rex_b && prefix_byte == 0xF3)
continue;
if (prefix_byte == 0xF3 || prefix_byte == 0xF2) {
if (! sse_opcode) {
const BxDisasmOpcodeTable_t *prefix = &(opcode_table[prefix_byte]);
dis_sprintf("%s ", OPCODE(prefix)->IntelOpcode);
}
}
// branch hint for jcc instructions
if ((insn.b1 >= 0x070 && insn.b1 <= 0x07F) ||
(insn.b1 >= 0x180 && insn.b1 <= 0x18F))
{
if (prefix_byte == BRANCH_NOT_TAKEN || prefix_byte == BRANCH_TAKEN)
branch_hint = prefix_byte;
}
}
}
const BxDisasmOpcodeInfo_t *opcode = OPCODE(entry);
if (! insn.is_xop && ! insn.is_vex) {
// patch jecx opcode
if (insn.b1 == 0xE3 && insn.as_32 && !insn.as_64)
opcode = &Ia_jecxz_Jb;
// fix nop opcode
if (insn.b1 == 0x90) {
if (sse_prefix == SSE_PREFIX_F3)
opcode = &Ia_pause;
else if (!insn.rex_b)
opcode = &Ia_nop;
}
}
// print instruction disassembly
if (intel_mode)
print_disassembly_intel(&insn, opcode);
else
print_disassembly_att (&insn, opcode);
if (branch_hint == BRANCH_NOT_TAKEN)
{
dis_sprintf(", not taken");
}
else if (branch_hint == BRANCH_TAKEN)
{
dis_sprintf(", taken");
}
if (insn.is_vex < 0)
dis_sprintf(" (bad vex)");
else if (insn.is_evex < 0)
dis_sprintf(" (bad evex)");
else if (insn.is_xop < 0)
dis_sprintf(" (bad xop)");
insn.ilen = (unsigned)(instruction - instruction_begin);
return insn;
}
unsigned disassembler::decode_vex(x86_insn *insn)
{
insn->is_vex = 1;
unsigned b2 = fetch_byte(), vex_opcode_extension = 1;
insn->rex_r = (b2 & 0x80) ? 0 : 0x8;
if (insn->b1 == 0xc4) {
// decode 3-byte VEX prefix
insn->rex_x = (b2 & 0x40) ? 0 : 0x8;
if (insn->is_64)
insn->rex_b = (b2 & 0x20) ? 0 : 0x8;
vex_opcode_extension = b2 & 0x1f;
if (! vex_opcode_extension || vex_opcode_extension > 3)
insn->is_vex = -1;
b2 = fetch_byte(); // fetch VEX3 byte
if (b2 & 0x80) {
insn->os_64 = 1;
insn->os_32 = 1;
insn->vex_w = 1;
}
}
insn->vex_vvv = 15 - ((b2 >> 3) & 0xf);
if (! insn->is_64) insn->vex_vvv &= 7;
insn->vex_l = (b2 >> 2) & 0x1;
insn->b1 = fetch_byte() + 256 * vex_opcode_extension;
return b2 & 0x3;
}
unsigned disassembler::decode_evex(x86_insn *insn)
{
insn->is_evex = 1;
Bit32u evex = fetch_dword();
// check for reserved EVEX bits
if ((evex & 0x0c) != 0 || (evex & 0x400) == 0) {
insn->is_evex = -1;
}
unsigned evex_opcext = evex & 0x3;
if (evex_opcext == 0) {
insn->is_evex = -1;
}
if (insn->is_64) {
insn->rex_r = ((evex >> 4) & 0x8) ^ 0x8;
insn->rex_r |= (evex & 0x10) ^ 0x10;
insn->rex_x = ((evex >> 3) & 0x8) ^ 0x8;
insn->rex_b = ((evex >> 2) & 0x8) ^ 0x8;
insn->rex_b |= (insn->rex_x << 1);
}
unsigned sse_prefix = (evex >> 8) & 0x3;
insn->vex_vvv = 15 - ((evex >> 11) & 0xf);
unsigned evex_v = ((evex >> 15) & 0x10) ^ 0x10;
insn->vex_vvv |= evex_v;
if (! insn->is_64) insn->vex_vvv &= 7;
insn->vex_w = (evex >> 15) & 0x1;
if (insn->vex_w) {
insn->os_64 = 1;
insn->os_32 = 1;
}
insn->evex_b = (evex >> 20) & 0x1;
insn->evex_ll_rc = (evex >> 21) & 0x3;
insn->evex_z = (evex >> 23) & 0x1;
insn->b1 = (evex >> 24);
insn->b1 += 256 * (evex_opcext-1);
return sse_prefix;
}
unsigned disassembler::decode_xop(x86_insn *insn)
{
insn->is_xop = 1;
unsigned b2 = fetch_byte();
insn->rex_r = (b2 & 0x80) ? 0 : 0x8;
insn->rex_x = (b2 & 0x40) ? 0 : 0x8;
if (insn->is_64)
insn->rex_b = (b2 & 0x20) ? 0 : 0x8;
unsigned xop_opcode_extension = (b2 & 0x1f) - 8;
if (xop_opcode_extension >= 3)
insn->is_xop = -1;
b2 = fetch_byte(); // fetch VEX3 byte
if (b2 & 0x80) {
insn->os_64 = 1;
insn->os_32 = 1;
insn->vex_w = 1;
}
insn->vex_vvv = 15 - ((b2 >> 3) & 0xf);
if (! insn->is_64) insn->vex_vvv &= 7;
insn->vex_l = (b2 >> 2) & 0x1;
insn->b1 = fetch_byte() + 256 * xop_opcode_extension;
return b2 & 0x3;
}
void disassembler::dis_sprintf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsprintf(disbufptr, fmt, ap);
va_end(ap);
disbufptr += strlen(disbufptr);
}
void disassembler::dis_putc(char symbol)
{
*disbufptr++ = symbol;
*disbufptr = 0;
}

View File

@ -1,328 +0,0 @@
/////////////////////////////////////////////////////////////////////////
// $Id: dis_decode.cc,v 1.32 2006/05/12 17:04:19 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "disasm.h"
#include "dis_tables.h"
#define OPCODE(entry) ((BxDisasmOpcodeInfo_t*) entry->OpcodeInfo)
#define OPCODE_TABLE(entry) ((BxDisasmOpcodeTable_t*) entry->OpcodeInfo)
#ifndef NULL
#define NULL 0
#endif
static const unsigned char instruction_has_modrm[512] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* ------------------------------- */
/* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
/* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
/* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
/* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
/* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,
/* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
/* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* A0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* B0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* C0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
/* D0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,
/* E0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* F0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* ------------------------------- */
1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0F 00 */
1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1, /* 0F 10 */
1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 0F 20 */
0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 0F 30 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 40 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 50 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 60 */
1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1, /* 0F 70 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0F 80 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 90 */
0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1, /* 0F A0 */
1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* 0F B0 */
1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* 0F C0 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F D0 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F E0 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* 0F F0 */
/* ------------------------------- */
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
};
unsigned disassembler::disasm(bx_bool is_32, bx_bool is_64, bx_address base, bx_address ip, const Bit8u *instr, char *disbuf)
{
x86_insn insn = decode(is_32, is_64, base, ip, instr, disbuf);
return insn.ilen;
}
x86_insn disassembler::decode(bx_bool is_32, bx_bool is_64, bx_address base, bx_address ip, const Bit8u *instr, char *disbuf)
{
x86_insn insn(is_32, is_64);
const Bit8u *instruction_begin = instruction = instr;
resolve_modrm = NULL;
unsigned b3 = 0;
db_eip = ip;
db_base = base; // cs linear base (base for PM & cs<<4 for RM & VM)
disbufptr = disbuf; // start sprintf()'ing into beginning of buffer
#define SSE_PREFIX_NONE 0
#define SSE_PREFIX_66 1
#define SSE_PREFIX_F2 2
#define SSE_PREFIX_F3 3 /* only one SSE prefix could be used */
unsigned sse_prefix = SSE_PREFIX_NONE;
for(;;)
{
insn.b1 = fetch_byte();
insn.prefixes++;
switch(insn.b1) {
case 0x40: // rex
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47:
case 0x48:
case 0x49:
case 0x4A:
case 0x4B:
case 0x4C:
case 0x4D:
case 0x4E:
case 0x4F:
if (! is_64) break;
insn.extend8b = 1;
if (insn.b1 & 0x8) {
insn.os_64 = 1;
insn.os_32 = 1;
}
if (insn.b1 & 0x4) insn.rex_r = 8;
if (insn.b1 & 0x2) insn.rex_x = 8;
if (insn.b1 & 0x1) insn.rex_b = 8;
continue;
case 0x26: // ES:
if (! is_64) insn.seg_override = ES_REG;
continue;
case 0x2e: // CS:
if (! is_64) insn.seg_override = CS_REG;
continue;
case 0x36: // SS:
if (! is_64) insn.seg_override = SS_REG;
continue;
case 0x3e: // DS:
if (! is_64) insn.seg_override = DS_REG;
continue;
case 0x64: // FS:
insn.seg_override = FS_REG;
continue;
case 0x65: // GS:
insn.seg_override = GS_REG;
continue;
case 0x66: // operand size override
if (!insn.os_64) insn.os_32 = !is_32;
if (!sse_prefix) sse_prefix = SSE_PREFIX_66;
continue;
case 0x67: // address size override
if (!is_64) insn.as_32 = !is_32;
insn.as_64 = 0;
continue;
case 0xf0: // lock
continue;
case 0xf2: // repne
if (!sse_prefix) sse_prefix = SSE_PREFIX_F2;
continue;
case 0xf3: // rep
if (!sse_prefix) sse_prefix = SSE_PREFIX_F3;
continue;
// no more prefixes
default:
break;
}
insn.prefixes--;
break;
}
if (insn.b1 == 0x0f)
{
insn.b1 = 0x100 | fetch_byte();
}
const BxDisasmOpcodeTable_t *opcode_table, *entry;
if (is_64) {
if (insn.os_64)
opcode_table = BxDisasmOpcodes64q;
else if (insn.os_32)
opcode_table = BxDisasmOpcodes64d;
else
opcode_table = BxDisasmOpcodes64w;
} else {
if (insn.os_32)
opcode_table = BxDisasmOpcodes32;
else
opcode_table = BxDisasmOpcodes16;
}
entry = opcode_table + insn.b1;
// will require 3rd byte for 3-byte opcode
if (entry->Attr & _GRP3BTAB) b3 = fetch_byte();
if (instruction_has_modrm[insn.b1])
{
decode_modrm(&insn);
}
int attr = entry->Attr;
while(attr)
{
switch(attr) {
case _GROUPN:
entry = &(OPCODE_TABLE(entry)[insn.nnn]);
break;
case _GRPSSE:
if(sse_prefix) insn.prefixes--;
/* For SSE opcodes, look into another 4 entries table
with the opcode prefixes (NONE, 0x66, 0xF2, 0xF3) */
entry = &(OPCODE_TABLE(entry)[sse_prefix]);
break;
case _SPLIT11B:
entry = &(OPCODE_TABLE(entry)[insn.mod != 3]); /* REG/MEM */
break;
case _GRPRM:
entry = &(OPCODE_TABLE(entry)[insn.rm]);
break;
case _GRPFP:
if(insn.mod != 3)
{
entry = &(OPCODE_TABLE(entry)[insn.nnn]);
} else {
int index = (insn.b1-0xD8)*64 + (insn.modrm & 0x3f);
entry = &(BxDisasmOpcodeInfoFP[index]);
}
break;
case _GRP3DNOW:
entry = &(BxDisasm3DNowGroup[peek_byte()]);
break;
case _GRP3BTAB:
entry = &(OPCODE_TABLE(entry)[b3 >> 4]);
break;
case _GRP3BOP:
entry = &(OPCODE_TABLE(entry)[b3 & 15]);
break;
default:
printf("Internal disassembler error - unknown attribute !\n");
return x86_insn(is_32, is_64);
}
/* get additional attributes from group table */
attr = entry->Attr;
}
#define BRANCH_NOT_TAKEN 0x2E
#define BRANCH_TAKEN 0x3E
unsigned branch_hint = 0;
// print prefixes
for(unsigned i=0;i<insn.prefixes;i++)
{
Bit8u prefix_byte = *(instr+i);
if (prefix_byte == 0xF3 || prefix_byte == 0xF2 || prefix_byte == 0xF0)
{
const BxDisasmOpcodeTable_t *prefix = &(opcode_table[prefix_byte]);
dis_sprintf("%s ", OPCODE(prefix)->IntelOpcode);
}
// branch hint for jcc instructions
if ((insn.b1 >= 0x070 && insn.b1 <= 0x07F) ||
(insn.b1 >= 0x180 && insn.b1 <= 0x18F))
{
if (prefix_byte == BRANCH_NOT_TAKEN || prefix_byte == BRANCH_TAKEN)
branch_hint = prefix_byte;
}
}
const BxDisasmOpcodeInfo_t *opcode = OPCODE(entry);
// patch jecx opcode
if (insn.b1 == 0xE3 && insn.as_32 && !insn.as_64)
opcode = &Ia_jecxz_Jb;
// fix nop opcode
if (insn.b1 == 0x90 && !insn.rex_b) {
opcode = &Ia_nop;
}
// print instruction disassembly
if (intel_mode)
print_disassembly_intel(&insn, opcode);
else
print_disassembly_att (&insn, opcode);
if (branch_hint == BRANCH_NOT_TAKEN)
{
dis_sprintf(", not taken");
}
else if (branch_hint == BRANCH_TAKEN)
{
dis_sprintf(", taken");
}
insn.ilen = (unsigned)(instruction - instruction_begin);
return insn;
}
void disassembler::dis_sprintf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsprintf(disbufptr, fmt, ap);
va_end(ap);
disbufptr += strlen(disbufptr);
}
void disassembler::dis_putc(char symbol)
{
*disbufptr++ = symbol;
*disbufptr = 0;
}

View File

@ -1,6 +1,23 @@
/////////////////////////////////////////////////////////////////////////
// $Id: dis_groups.cc,v 1.33 2006/08/13 09:40:07 sshwarts Exp $
// $Id: dis_groups.cc 11885 2013-10-15 17:19:18Z sshwarts $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2005-2011 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <stdio.h>
#include <assert.h>
@ -16,41 +33,46 @@ void disassembler::Apw(const x86_insn *insn)
{
Bit16u imm16 = fetch_word();
Bit16u cs_selector = fetch_word();
dis_sprintf("%04x:%04x", (unsigned) cs_selector, (unsigned) imm16);
dis_sprintf("0x%04x:%04x", (unsigned) cs_selector, (unsigned) imm16);
}
void disassembler::Apd(const x86_insn *insn)
{
Bit32u imm32 = fetch_dword();
Bit16u cs_selector = fetch_word();
dis_sprintf("%04x:%08x", (unsigned) cs_selector, (unsigned) imm32);
dis_sprintf("0x%04x:%08x", (unsigned) cs_selector, (unsigned) imm32);
}
// 8-bit general purpose registers
void disassembler::AL(const x86_insn *insn) { dis_sprintf("%s", general_8bit_regname[rAX_REG]); }
void disassembler::CL(const x86_insn *insn) { dis_sprintf("%s", general_8bit_regname[rCX_REG]); }
void disassembler::AL_Reg(const x86_insn *insn) { dis_sprintf("%s", general_8bit_regname[rAX_REG]); }
void disassembler::CL_Reg(const x86_insn *insn) { dis_sprintf("%s", general_8bit_regname[rCX_REG]); }
// 16-bit general purpose registers
void disassembler::AX(const x86_insn *insn) {
void disassembler::AX_Reg(const x86_insn *insn) {
dis_sprintf("%s", general_16bit_regname[rAX_REG]);
}
void disassembler::DX(const x86_insn *insn) {
void disassembler::DX_Reg(const x86_insn *insn) {
dis_sprintf("%s", general_16bit_regname[rDX_REG]);
}
// 32-bit general purpose registers
void disassembler::EAX(const x86_insn *insn)
void disassembler::EAX_Reg(const x86_insn *insn)
{
dis_sprintf("%s", general_32bit_regname[rAX_REG]);
}
// 64-bit general purpose registers
void disassembler::RAX(const x86_insn *insn)
void disassembler::RAX_Reg(const x86_insn *insn)
{
dis_sprintf("%s", general_64bit_regname[rAX_REG]);
}
void disassembler::RCX_Reg(const x86_insn *insn)
{
dis_sprintf("%s", general_64bit_regname[rCX_REG]);
}
// segment registers
void disassembler::CS(const x86_insn *insn) { dis_sprintf("%s", segment_name[CS_REG]); }
void disassembler::DS(const x86_insn *insn) { dis_sprintf("%s", segment_name[DS_REG]); }
@ -61,18 +83,9 @@ void disassembler::GS(const x86_insn *insn) { dis_sprintf("%s", segment_name[GS_
void disassembler::Sw(const x86_insn *insn) { dis_sprintf("%s", segment_name[insn->nnn]); }
// test registers
void disassembler::Td(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("tr%d", insn->nnn);
else
dis_sprintf("%%tr%d", insn->nnn);
}
// control register
void disassembler::Cd(const x86_insn *insn)
{
void disassembler::Cd(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("cr%d", insn->nnn);
else
@ -82,21 +95,21 @@ void disassembler::Cd(const x86_insn *insn)
void disassembler::Cq(const x86_insn *insn) { Cd(insn); }
// debug register
void disassembler::Dd(const x86_insn *insn)
void disassembler::Dd(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("db%d", insn->nnn);
dis_sprintf ("dr%d", insn->nnn);
else
dis_sprintf("%%db%d", insn->nnn);
dis_sprintf("%%dr%d", insn->nnn);
}
void disassembler::Dq(const x86_insn *insn) { Dd(insn); }
// 8-bit general purpose register
void disassembler::R8(const x86_insn *insn)
{
void disassembler::Reg8(const x86_insn *insn)
{
unsigned reg = (insn->b1 & 7) | insn->rex_b;
if (reg < 4 || insn->extend8b)
dis_sprintf("%s", general_8bit_regname_rex[reg]);
else
@ -105,24 +118,24 @@ void disassembler::R8(const x86_insn *insn)
// 16-bit general purpose register
void disassembler::RX(const x86_insn *insn)
{
{
dis_sprintf("%s", general_16bit_regname[(insn->b1 & 7) | insn->rex_b]);
}
// 32-bit general purpose register
void disassembler::ERX(const x86_insn *insn)
{
{
dis_sprintf("%s", general_32bit_regname[(insn->b1 & 7) | insn->rex_b]);
}
// 64-bit general purpose register
void disassembler::RRX(const x86_insn *insn)
{
{
dis_sprintf("%s", general_64bit_regname[(insn->b1 & 7) | insn->rex_b]);
}
// general purpose register or memory operand
void disassembler::Eb(const x86_insn *insn)
void disassembler::Eb(const x86_insn *insn)
{
if (insn->mod == 3) {
if (insn->rm < 4 || insn->extend8b)
@ -134,7 +147,7 @@ void disassembler::Eb(const x86_insn *insn)
(this->*resolve_modrm)(insn, B_SIZE);
}
void disassembler::Ew(const x86_insn *insn)
void disassembler::Ew(const x86_insn *insn)
{
if (insn->mod == 3)
dis_sprintf("%s", general_16bit_regname[insn->rm]);
@ -142,7 +155,7 @@ void disassembler::Ew(const x86_insn *insn)
(this->*resolve_modrm)(insn, W_SIZE);
}
void disassembler::Ed(const x86_insn *insn)
void disassembler::Ed(const x86_insn *insn)
{
if (insn->mod == 3)
dis_sprintf("%s", general_32bit_regname[insn->rm]);
@ -150,7 +163,7 @@ void disassembler::Ed(const x86_insn *insn)
(this->*resolve_modrm)(insn, D_SIZE);
}
void disassembler::Eq(const x86_insn *insn)
void disassembler::Eq(const x86_insn *insn)
{
if (insn->mod == 3)
dis_sprintf("%s", general_64bit_regname[insn->rm]);
@ -158,8 +171,30 @@ void disassembler::Eq(const x86_insn *insn)
(this->*resolve_modrm)(insn, Q_SIZE);
}
void disassembler::Ey(const x86_insn *insn)
{
if (insn->os_64) Eq(insn);
else Ed(insn);
}
void disassembler::Ebd(const x86_insn *insn)
{
if (insn->mod == 3)
dis_sprintf("%s", general_32bit_regname[insn->rm]);
else
(this->*resolve_modrm)(insn, B_SIZE);
}
void disassembler::Ewd(const x86_insn *insn)
{
if (insn->mod == 3)
dis_sprintf("%s", general_32bit_regname[insn->rm]);
else
(this->*resolve_modrm)(insn, W_SIZE);
}
// general purpose register
void disassembler::Gb(const x86_insn *insn)
void disassembler::Gb(const x86_insn *insn)
{
if (insn->nnn < 4 || insn->extend8b)
dis_sprintf("%s", general_8bit_regname_rex[insn->nnn]);
@ -167,41 +202,69 @@ void disassembler::Gb(const x86_insn *insn)
dis_sprintf("%s", general_8bit_regname[insn->nnn]);
}
void disassembler::Gw(const x86_insn *insn)
void disassembler::Gw(const x86_insn *insn)
{
dis_sprintf("%s", general_16bit_regname[insn->nnn]);
}
void disassembler::Gd(const x86_insn *insn)
void disassembler::Gd(const x86_insn *insn)
{
dis_sprintf("%s", general_32bit_regname[insn->nnn]);
}
void disassembler::Gq(const x86_insn *insn)
void disassembler::Gq(const x86_insn *insn)
{
dis_sprintf("%s", general_64bit_regname[insn->nnn]);
}
void disassembler::Gy(const x86_insn *insn)
{
if (insn->os_64) Gq(insn);
else Gd(insn);
}
// vex encoded general purpose register
void disassembler::By(const x86_insn *insn)
{
if (insn->os_64)
dis_sprintf("%s", general_64bit_regname[insn->vex_vvv]);
else
dis_sprintf("%s", general_32bit_regname[insn->vex_vvv]);
}
// immediate
void disassembler::I1(const x86_insn *insn)
{
void disassembler::I1(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
dis_putc ('1');
}
void disassembler::Ib(const x86_insn *insn)
void disassembler::Ib(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
dis_sprintf("0x%02x", (unsigned) fetch_byte());
}
void disassembler::Iw(const x86_insn *insn)
void disassembler::Iw(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
dis_sprintf("0x%04x", (unsigned) fetch_word());
}
void disassembler::IwIb(const x86_insn *insn)
void disassembler::IbIb(const x86_insn *insn)
{
Bit8u ib1 = fetch_byte();
Bit8u ib2 = fetch_byte();
if (intel_mode) {
dis_sprintf("0x%02x, 0x%02x", ib1, ib2);
}
else {
dis_sprintf("$0x%02x, $0x%02x", ib2, ib1);
}
}
void disassembler::IwIb(const x86_insn *insn)
{
Bit16u iw = fetch_word();
Bit8u ib = fetch_byte();
@ -214,23 +277,22 @@ void disassembler::IwIb(const x86_insn *insn)
}
}
void disassembler::Id(const x86_insn *insn)
void disassembler::Id(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
dis_sprintf("0x%08x", (unsigned) fetch_dword());
}
void disassembler::Iq(const x86_insn *insn)
void disassembler::Iq(const x86_insn *insn)
{
Bit64u value = fetch_qword();
if (! intel_mode) dis_putc('$');
dis_sprintf("0x%08x%08x",
(unsigned)(value>>32), (unsigned)(value & 0xffffffff));
dis_sprintf("0x%08x%08x", GET32H(value), GET32L(value));
}
// sign extended immediate
void disassembler::sIbw(const x86_insn *insn)
void disassembler::sIbw(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
Bit16u imm16 = (Bit8s) fetch_byte();
@ -238,7 +300,7 @@ void disassembler::sIbw(const x86_insn *insn)
}
// sign extended immediate
void disassembler::sIbd(const x86_insn *insn)
void disassembler::sIbd(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
Bit32u imm32 = (Bit8s) fetch_byte();
@ -246,38 +308,36 @@ void disassembler::sIbd(const x86_insn *insn)
}
// sign extended immediate
void disassembler::sIbq(const x86_insn *insn)
void disassembler::sIbq(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
Bit64u imm64 = (Bit8s) fetch_byte();
dis_sprintf ("0x%08x%08x",
(unsigned)(imm64>>32), (unsigned)(imm64 & 0xffffffff));
dis_sprintf ("0x%08x%08x", GET32H(imm64), GET32L(imm64));
}
// sign extended immediate
void disassembler::sIdq(const x86_insn *insn)
void disassembler::sIdq(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
Bit64u imm64 = (Bit32s) fetch_dword();
dis_sprintf ("0x%08x%08x",
(unsigned)(imm64>>32), (unsigned)(imm64 & 0xffffffff));
dis_sprintf ("0x%08x%08x", GET32H(imm64), GET32L(imm64));
}
// floating point
void disassembler::ST0(const x86_insn *insn)
{
{
if (intel_mode)
dis_sprintf ("st(0)");
else
dis_sprintf("%%st(0)");
}
void disassembler::STi(const x86_insn *insn)
{
void disassembler::STi(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("st(%d)", insn->rm);
dis_sprintf ("st(%d)", insn->rm & 7);
else
dis_sprintf("%%st(%d)", insn->rm);
dis_sprintf("%%st(%d)", insn->rm & 7);
}
// 16-bit general purpose register
@ -298,21 +358,27 @@ void disassembler::Rq(const x86_insn *insn)
dis_sprintf("%s", general_64bit_regname[insn->rm]);
}
void disassembler::Ry(const x86_insn *insn)
{
if (insn->os_64) Rq(insn);
else Rd(insn);
}
// mmx register
void disassembler::Pq(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("mm%d", insn->nnn);
dis_sprintf ("mm%d", insn->nnn & 0x7);
else
dis_sprintf("%%mm%d", insn->nnn);
dis_sprintf("%%mm%d", insn->nnn & 0x7);
}
void disassembler::Nq(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("mm%d", insn->rm);
dis_sprintf ("mm%d", insn->rm & 0x7);
else
dis_sprintf("%%mm%d", insn->rm);
dis_sprintf("%%mm%d", insn->rm & 0x7);
}
void disassembler::Qd(const x86_insn *insn)
@ -320,9 +386,9 @@ void disassembler::Qd(const x86_insn *insn)
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf ("mm%d", insn->rm);
dis_sprintf ("mm%d", insn->rm & 0x7);
else
dis_sprintf("%%mm%d", insn->rm);
dis_sprintf("%%mm%d", insn->rm & 0x7);
}
else
(this->*resolve_modrm)(insn, D_SIZE);
@ -333,29 +399,27 @@ void disassembler::Qq(const x86_insn *insn)
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf ("mm%d", insn->rm);
dis_sprintf ("mm%d", insn->rm & 0x7);
else
dis_sprintf("%%mm%d", insn->rm);
dis_sprintf("%%mm%d", insn->rm & 0x7);
}
else
(this->*resolve_modrm)(insn, Q_SIZE);
}
// xmm register
// xmm/ymm register
void disassembler::Udq(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("xmm%d", insn->rm);
else
dis_sprintf("%%xmm%d", insn->rm);
dis_sprintf("%s%d", vector_reg_name[insn->vex_l], insn->rm);
}
void disassembler::Ups(const x86_insn *insn) { Udq(insn); }
void disassembler::Upd(const x86_insn *insn) { Udq(insn); }
void disassembler::Uq(const x86_insn *insn) { Udq(insn); }
void disassembler::Vq(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("xmm%d", insn->nnn);
else
dis_sprintf("%%xmm%d", insn->nnn);
dis_sprintf("%s%d", vector_reg_name[insn->vex_l], insn->nnn);
}
void disassembler::Vdq(const x86_insn *insn) { Vq(insn); }
@ -364,47 +428,60 @@ void disassembler::Vsd(const x86_insn *insn) { Vq(insn); }
void disassembler::Vps(const x86_insn *insn) { Vq(insn); }
void disassembler::Vpd(const x86_insn *insn) { Vq(insn); }
void disassembler::VIb(const x86_insn *insn)
{
unsigned vreg = fetch_byte() >> 4;
if (! insn->is_64) vreg &= 7;
dis_sprintf("%s%d", vector_reg_name[insn->vex_l], vreg);
}
void disassembler::Hdq(const x86_insn *insn)
{
dis_sprintf("%s%d", vector_reg_name[insn->vex_l], insn->vex_vvv);
}
void disassembler::Hps(const x86_insn *insn) { Hdq(insn); }
void disassembler::Hpd(const x86_insn *insn) { Hdq(insn); }
void disassembler::Hss(const x86_insn *insn) { Hdq(insn); }
void disassembler::Hsd(const x86_insn *insn) { Hdq(insn); }
void disassembler::Wb(const x86_insn *insn)
{
if (insn->mod == 3) Udq(insn);
else
(this->*resolve_modrm)(insn, B_SIZE);
}
void disassembler::Ww(const x86_insn *insn)
{
if (insn->mod == 3) Udq(insn);
else
(this->*resolve_modrm)(insn, W_SIZE);
}
void disassembler::Wd(const x86_insn *insn)
{
if (insn->mod == 3) Udq(insn);
else
(this->*resolve_modrm)(insn, D_SIZE);
}
void disassembler::Wq(const x86_insn *insn)
{
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf ("xmm%d", insn->rm);
else
dis_sprintf("%%xmm%d", insn->rm);
}
if (insn->mod == 3) Udq(insn);
else
(this->*resolve_modrm)(insn, Q_SIZE);
}
void disassembler::Wdq(const x86_insn *insn)
{
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf ("xmm%d", insn->rm);
else
dis_sprintf("%%xmm%d", insn->rm);
}
if (insn->mod == 3) Udq(insn);
else
(this->*resolve_modrm)(insn, O_SIZE);
(this->*resolve_modrm)(insn, XMM_SIZE + insn->vex_l);
}
void disassembler::Wsd(const x86_insn *insn) { Wq(insn); }
void disassembler::Wss(const x86_insn *insn)
{
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf ("xmm%d", insn->rm);
else
dis_sprintf("%%xmm%d", insn->rm);
}
else
(this->*resolve_modrm)(insn, D_SIZE);
}
void disassembler::Wss(const x86_insn *insn) { Wd(insn); }
void disassembler::Wpd(const x86_insn *insn) { Wdq(insn); }
void disassembler::Wps(const x86_insn *insn) { Wdq(insn); }
@ -422,16 +499,15 @@ void disassembler::OP_O(const x86_insn *insn, unsigned size)
if (insn->as_64) {
Bit64u imm64 = fetch_qword();
dis_sprintf("%s:0x%08x%08x", seg,
(unsigned)(imm64>>32), (unsigned)(imm64 & 0xffffffff));
dis_sprintf("%s:0x%08x%08x", seg, GET32H(imm64), GET32L(imm64));
}
else if (insn->as_32) {
Bit32u imm32 = fetch_dword();
dis_sprintf("%s:0x%x", seg, (unsigned) imm32);
dis_sprintf("%s:0x%08x", seg, (unsigned) imm32);
}
else {
Bit16u imm16 = fetch_word();
dis_sprintf("%s:0x%x", seg, (unsigned) imm16);
dis_sprintf("%s:0x%04x", seg, (unsigned) imm16);
}
}
@ -460,9 +536,20 @@ void disassembler::Md(const x86_insn *insn) { OP_M(insn, D_SIZE); }
void disassembler::Mq(const x86_insn *insn) { OP_M(insn, Q_SIZE); }
void disassembler::Mt(const x86_insn *insn) { OP_M(insn, T_SIZE); }
void disassembler::Mdq(const x86_insn *insn) { OP_M(insn, O_SIZE); }
void disassembler::Mps(const x86_insn *insn) { OP_M(insn, O_SIZE); }
void disassembler::Mpd(const x86_insn *insn) { OP_M(insn, O_SIZE); }
void disassembler::Mdq(const x86_insn *insn) { OP_M(insn, XMM_SIZE + insn->vex_l); }
void disassembler::Mps(const x86_insn *insn) { OP_M(insn, XMM_SIZE + insn->vex_l); }
void disassembler::Mpd(const x86_insn *insn) { OP_M(insn, XMM_SIZE + insn->vex_l); }
void disassembler::Mss(const x86_insn *insn) { OP_M(insn, D_SIZE); }
void disassembler::Msd(const x86_insn *insn) { OP_M(insn, Q_SIZE); }
// gather VSib
void disassembler::VSib(const x86_insn *insn)
{
if(insn->mod == 3)
dis_sprintf("(bad)");
else
(this->*resolve_modrm)(insn, (XMM_SIZE + insn->vex_l) | VSIB_Index);
}
// string instructions
void disassembler::OP_X(const x86_insn *insn, unsigned size)
@ -478,7 +565,7 @@ void disassembler::OP_X(const x86_insn *insn, unsigned size)
else
rsi = general_16bit_regname[rSI_REG];
}
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
@ -510,7 +597,7 @@ void disassembler::OP_Y(const x86_insn *insn, unsigned size)
else
rdi = general_16bit_regname[rDI_REG];
}
print_datasize(size);
if (intel_mode)
@ -524,6 +611,36 @@ void disassembler::Yw(const x86_insn *insn) { OP_Y(insn, W_SIZE); }
void disassembler::Yd(const x86_insn *insn) { OP_Y(insn, D_SIZE); }
void disassembler::Yq(const x86_insn *insn) { OP_Y(insn, Q_SIZE); }
void disassembler::OP_sY(const x86_insn *insn, unsigned size)
{
const char *rdi, *seg;
if (insn->as_64) {
rdi = general_64bit_regname[rDI_REG];
}
else {
if (insn->as_32)
rdi = general_32bit_regname[rDI_REG];
else
rdi = general_16bit_regname[rDI_REG];
}
print_datasize(size);
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = segment_name[DS_REG];
if (intel_mode)
dis_sprintf("%s:[%s]", seg, rdi);
else
dis_sprintf("%s:(%s)", seg, rdi);
}
void disassembler::sYq(const x86_insn *insn) { OP_sY(insn, Q_SIZE); }
void disassembler::sYdq(const x86_insn *insn) { OP_sY(insn, XMM_SIZE + insn->vex_l); }
#define BX_JUMP_TARGET_NOT_REQ ((bx_address)(-1))
// jump offset
@ -532,35 +649,52 @@ void disassembler::Jb(const x86_insn *insn)
Bit8s imm8 = (Bit8s) fetch_byte();
if (insn->is_64) {
Bit64u imm64 = (Bit64s) imm8;
dis_sprintf(".+0x%08x%08x",
(unsigned)(imm64>>32), (unsigned)(imm64 & 0xffffffff));
Bit64u imm64 = (Bit8s) imm8;
if (db_base != BX_JUMP_TARGET_NOT_REQ) {
Bit64u target = db_eip + (Bit64s) imm64; target += db_base;
dis_sprintf(" (0x%08x%08x)",
(unsigned)(target>>32), (unsigned)(target & 0xffffffff));
if (offset_mode_hex) {
dis_sprintf(".+0x%08x%08x", GET32H(imm64), GET32L(imm64));
}
else {
dis_sprintf(".%+d", (int) imm8);
}
if (db_cs_base != BX_JUMP_TARGET_NOT_REQ) {
Bit64u target = db_eip + imm64;
target += db_cs_base;
dis_sprintf(" (0x%08x%08x)", GET32H(target), GET32L(target));
}
return;
}
if (insn->os_32) {
Bit32u imm32 = (Bit32s) imm8;
dis_sprintf(".+0x%08x", (unsigned) imm32);
Bit32u imm32 = (Bit8s) imm8;
if (db_base != BX_JUMP_TARGET_NOT_REQ) {
Bit32u target = (Bit32u)(db_eip + (Bit32s) imm32); target += (Bit32u)db_base;
if (offset_mode_hex) {
dis_sprintf(".+0x%08x", (unsigned) imm32);
}
else {
dis_sprintf(".%+d", (int) imm8);
}
if (db_cs_base != BX_JUMP_TARGET_NOT_REQ) {
Bit32u target = (Bit32u)(db_cs_base + db_eip + (Bit32s) imm32);
dis_sprintf(" (0x%08x)", target);
}
}
else {
Bit16u imm16 = (Bit16s) imm8;
dis_sprintf(".+0x%04x", (unsigned) imm16);
Bit16u imm16 = (Bit8s) imm8;
if (db_base != BX_JUMP_TARGET_NOT_REQ) {
Bit16u target = (Bit32u)(db_eip + (Bit16s) imm16) & 0xffff;
dis_sprintf(" (0x%08x)", target + db_base);
if (offset_mode_hex) {
dis_sprintf(".+0x%04x", (unsigned) imm16);
}
else {
dis_sprintf(".%+d", (int) imm8);
}
if (db_cs_base != BX_JUMP_TARGET_NOT_REQ) {
Bit16u target = (Bit16u)((db_eip + (Bit16s) imm16) & 0xffff);
dis_sprintf(" (0x%08x)", target + db_cs_base);
}
}
}
@ -569,14 +703,19 @@ void disassembler::Jw(const x86_insn *insn)
{
// Jw supported in 16-bit mode only
assert(! insn->is_64);
assert(! insn->is_32);
Bit16u imm16 = (Bit16s) fetch_word();
dis_sprintf(".+0x%04x", (unsigned) imm16);
Bit16s imm16 = (Bit16s) fetch_word();
if (db_base != BX_JUMP_TARGET_NOT_REQ) {
Bit16u target = (Bit32u)(db_eip + (Bit16s) imm16) & 0xffff;
dis_sprintf(" (0x%08x)", target + db_base);
if (offset_mode_hex) {
dis_sprintf(".+0x%04x", (unsigned) (Bit16u) imm16);
}
else {
dis_sprintf(".%+d", (int) imm16);
}
if (db_cs_base != BX_JUMP_TARGET_NOT_REQ) {
Bit16u target = (db_eip + imm16) & 0xffff;
dis_sprintf(" (0x%08x)", target + db_cs_base);
}
}
@ -585,23 +724,32 @@ void disassembler::Jd(const x86_insn *insn)
Bit32s imm32 = (Bit32s) fetch_dword();
if (insn->is_64) {
Bit64u imm64 = (Bit64s) imm32;
dis_sprintf(".+0x%08x%08x",
(unsigned)(imm64>>32), (unsigned)(imm64 & 0xffffffff));
Bit64u imm64 = (Bit32s) imm32;
if (db_base != BX_JUMP_TARGET_NOT_REQ) {
Bit64u target = db_eip + (Bit64s) imm64; target += db_base;
dis_sprintf(" (0x%08x%08x)",
(unsigned)(target>>32), (unsigned)(target & 0xffffffff));
if (offset_mode_hex) {
dis_sprintf(".+0x%08x%08x", GET32H(imm64), GET32L(imm64));
}
else {
dis_sprintf(".%+d", (int) imm32);
}
if (db_cs_base != BX_JUMP_TARGET_NOT_REQ) {
Bit64u target = db_cs_base + db_eip + (Bit64s) imm64;
dis_sprintf(" (0x%08x%08x)", GET32H(target), GET32L(target));
}
return;
}
dis_sprintf(".+0x%08x", (unsigned) imm32);
if (offset_mode_hex) {
dis_sprintf(".+0x%08x", (unsigned) imm32);
}
else {
dis_sprintf(".%+d", (int) imm32);
}
if (db_base != BX_JUMP_TARGET_NOT_REQ) {
Bit32u target = (Bit32u)(db_eip + (Bit32s) imm32); target += (Bit32u)db_base;
if (db_cs_base != BX_JUMP_TARGET_NOT_REQ) {
Bit32u target = (Bit32u)(db_cs_base + db_eip + (Bit32s) imm32);
dis_sprintf(" (0x%08x)", target);
}
}

View File

@ -1,6 +1,23 @@
/////////////////////////////////////////////////////////////////////////
// $Id: dis_tables.h,v 1.29 2006/04/27 15:11:45 sshwarts Exp $
// $Id: dis_tables.h 11878 2013-10-11 20:09:51Z sshwarts $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2005-2012 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef _BX_DISASM_TABLES_
#define _BX_DISASM_TABLES_
@ -11,70 +28,93 @@
#define _GRPFP 3
#define _GRP3DNOW 4
#define _GRPSSE 5
#define _GRPRM 6
#define _GRP3BOP 7
#define _GRP3BTAB 8
#define _GRPSSE66 6
#define _GRPSSEF2 7
#define _GRPSSEF3 8
#define _GRPSSENONE 9
#define _GRPSSE2 10
#define _GRPRM 11
#define _GRP3BOP 12
#define _GRP64B 13
#define _GRPVEXW 14
/* ************************************************************************ */
#define GRPSSE(n) _GRPSSE, BxDisasmGroupSSE_##n
#define GRPSSE2(n) _GRPSSE2, BxDisasmGroupSSE_##n
#define GRPAVX(n) _GRPSSE, BxDisasmGroupAVX_##n
#define GRPAVX2(n) _GRPSSE2, BxDisasmGroupAVX_##n
#define GRPN(n) _GROUPN, BxDisasmGroup##n
#define GRPRM(n) _GRPRM, BxDisasmGroupRm##n
#define GRPMOD(n) _SPLIT11B, BxDisasmGroupMod##n
#define GRPFP(n) _GRPFP, BxDisasmFPGroup##n
#define GRP3DNOW _GRP3DNOW, BxDisasm3DNowGroup
#define GR3BOP(n) _GRP3BOP, BxDisasm3ByteOp##n
#define GR3BTAB(n) _GRP3BTAB, BxDisasm3ByteTable##n
#define GR3BTAB(n) _GRP3BOP, BxDisasm3ByteOpTable##n
#define GR64BIT(n) _GRP64B, BxDisasmGrpOs64B_##n
#define GRPVEXW(n) _GRPVEXW, BxDisasmGrpVexW_##n
/* ************************************************************************ */
/* ************************************************************************ */
#define GRPSSE66(n) _GRPSSE66, &n
#define GRPSSEF2(n) _GRPSSEF2, &n
#define GRPSSEF3(n) _GRPSSEF3, &n
#define GRPSSENONE(n) _GRPSSENONE, &n
/* ************************************************************************ */
#define Apw &disassembler::Apw
#define Apd &disassembler::Apd
#define AL &disassembler::AL
#define CL &disassembler::CL
#define AX &disassembler::AX
#define DX &disassembler::DX
#define AL_Reg &disassembler::AL_Reg
#define CL_Reg &disassembler::CL_Reg
#define AX_Reg &disassembler::AX_Reg
#define DX_Reg &disassembler::DX_Reg
#define EAX &disassembler::EAX
#define RAX &disassembler::RAX
#define EAX_Reg &disassembler::EAX_Reg
#define RAX_Reg &disassembler::RAX_Reg
#define RCX_Reg &disassembler::RCX_Reg
#define CS &disassembler::CS
#define DS &disassembler::DS
#define ES &disassembler::ES
#define SS &disassembler::SS
#define FS &disassembler::FS
#define GS &disassembler::GS
#define CS &disassembler::CS
#define DS &disassembler::DS
#define ES &disassembler::ES
#define SS &disassembler::SS
#define FS &disassembler::FS
#define GS &disassembler::GS
#define Sw &disassembler::Sw
#define Sw &disassembler::Sw
#define Td &disassembler::Td
#define Cd &disassembler::Cd
#define Cq &disassembler::Cq
#define Cd &disassembler::Cd
#define Cq &disassembler::Cq
#define Dd &disassembler::Dd
#define Dq &disassembler::Dq
#define Dd &disassembler::Dd
#define Dq &disassembler::Dq
#define Reg8 &disassembler::Reg8
#define RX &disassembler::RX
#define ERX &disassembler::ERX
#define RRX &disassembler::RRX
#define R8 &disassembler::R8
#define RX &disassembler::RX
#define ERX &disassembler::ERX
#define RRX &disassembler::RRX
#define Eb &disassembler::Eb
#define Ew &disassembler::Ew
#define Ed &disassembler::Ed
#define Eq &disassembler::Eq
#define Ey &disassembler::Ey
#define Ebd &disassembler::Ebd
#define Ewd &disassembler::Ewd
#define Eb &disassembler::Eb
#define Ew &disassembler::Ew
#define Ed &disassembler::Ed
#define Eq &disassembler::Eq
#define Gb &disassembler::Gb
#define Gw &disassembler::Gw
#define Gd &disassembler::Gd
#define Gq &disassembler::Gq
#define Gy &disassembler::Gy
#define Gb &disassembler::Gb
#define Gw &disassembler::Gw
#define Gd &disassembler::Gd
#define Gq &disassembler::Gq
#define By &disassembler::By
#define I1 &disassembler::I1
#define Ib &disassembler::Ib
#define Iw &disassembler::Iw
#define Id &disassembler::Id
#define Iq &disassembler::Iq
#define I1 &disassembler::I1
#define Ib &disassembler::Ib
#define Iw &disassembler::Iw
#define Id &disassembler::Id
#define Iq &disassembler::Iq
#define IbIb &disassembler::IbIb
#define IwIb &disassembler::IwIb
#define sIbw &disassembler::sIbw
@ -85,14 +125,15 @@
#define ST0 &disassembler::ST0
#define STi &disassembler::STi
#define Rw &disassembler::Rw
#define Rd &disassembler::Rd
#define Rq &disassembler::Rq
#define Rw &disassembler::Rw
#define Rd &disassembler::Rd
#define Rq &disassembler::Rq
#define Ry &disassembler::Ry
#define Pq &disassembler::Pq
#define Qd &disassembler::Qd
#define Qq &disassembler::Qq
#define Nq &disassembler::Nq
#define Pq &disassembler::Pq
#define Qd &disassembler::Qd
#define Qq &disassembler::Qq
#define Nq &disassembler::Nq
#define Vq &disassembler::Vq
#define Vdq &disassembler::Vdq
@ -100,8 +141,16 @@
#define Vsd &disassembler::Vsd
#define Vps &disassembler::Vps
#define Vpd &disassembler::Vpd
#define Udq &disassembler::Udq
#define VIb &disassembler::VIb
#define Ups &disassembler::Ups
#define Upd &disassembler::Upd
#define Udq &disassembler::Udq
#define Uq &disassembler::Uq
#define Wb &disassembler::Wb
#define Ww &disassembler::Ww
#define Wd &disassembler::Wd
#define Wq &disassembler::Wq
#define Wdq &disassembler::Wdq
#define Wss &disassembler::Wss
@ -109,10 +158,16 @@
#define Wps &disassembler::Wps
#define Wpd &disassembler::Wpd
#define Ob &disassembler::Ob
#define Ow &disassembler::Ow
#define Od &disassembler::Od
#define Oq &disassembler::Oq
#define Hdq &disassembler::Hdq
#define Hps &disassembler::Hps
#define Hpd &disassembler::Hpd
#define Hss &disassembler::Hss
#define Hsd &disassembler::Hsd
#define Ob &disassembler::Ob
#define Ow &disassembler::Ow
#define Od &disassembler::Od
#define Oq &disassembler::Oq
#define Ma &disassembler::Ma
#define Mp &disassembler::Mp
@ -126,26 +181,37 @@
#define Mdq &disassembler::Mdq
#define Mps &disassembler::Mps
#define Mpd &disassembler::Mpd
#define Mss &disassembler::Mss
#define Msd &disassembler::Msd
#define Xb &disassembler::Xb
#define Xw &disassembler::Xw
#define Xd &disassembler::Xd
#define Xq &disassembler::Xq
#define VSib &disassembler::VSib
#define Yb &disassembler::Yb
#define Yw &disassembler::Yw
#define Yd &disassembler::Yd
#define Yq &disassembler::Yq
#define Xb &disassembler::Xb
#define Xw &disassembler::Xw
#define Xd &disassembler::Xd
#define Xq &disassembler::Xq
#define Jb &disassembler::Jb
#define Jw &disassembler::Jw
#define Jd &disassembler::Jd
#define Yb &disassembler::Yb
#define Yw &disassembler::Yw
#define Yd &disassembler::Yd
#define Yq &disassembler::Yq
#define XX 0
#define sYq &disassembler::sYq
#define sYdq &disassembler::sYdq
#define Jb &disassembler::Jb
#define Jw &disassembler::Jw
#define Jd &disassembler::Jd
#define XX 0
const struct BxDisasmOpcodeInfo_t
#include "opcodes.inl"
#include "dis_tables.inl"
#include "opcodes.inc"
#include "dis_tables_x87.inc"
#include "dis_tables_sse.inc"
#include "dis_tables_avx.inc"
#include "dis_tables_xop.inc"
#include "dis_tables.inc"
#undef XX

3282
Externals/Bochs_disasm/dis_tables.inc vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1478
Externals/Bochs_disasm/dis_tables_avx.inc vendored Normal file

File diff suppressed because it is too large Load Diff

1452
Externals/Bochs_disasm/dis_tables_sse.inc vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,919 @@
/////////////////////////////////////////////////////////////////////////
// $Id: dis_tables_x87.inc 10298 2011-04-03 10:29:19Z vruppert $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2005-2010 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
/////////////////////////////////////////////////////////////////////////
/* ************************************************************************ */
/* 3DNow! opcodes */
static BxDisasmOpcodeTable_t BxDisasm3DNowGroup[256] = {
// 256 entries for 3DNow opcodes_by suffix
/* 00 */ { 0, &Ia_Invalid },
/* 01 */ { 0, &Ia_Invalid },
/* 02 */ { 0, &Ia_Invalid },
/* 03 */ { 0, &Ia_Invalid },
/* 04 */ { 0, &Ia_Invalid },
/* 05 */ { 0, &Ia_Invalid },
/* 06 */ { 0, &Ia_Invalid },
/* 07 */ { 0, &Ia_Invalid },
/* 08 */ { 0, &Ia_Invalid },
/* 09 */ { 0, &Ia_Invalid },
/* 0A */ { 0, &Ia_Invalid },
/* 0B */ { 0, &Ia_Invalid },
/* 0C */ { 0, &Ia_pi2fw_Pq_Qq },
/* 0D */ { 0, &Ia_pi2fd_Pq_Qq },
/* 0E */ { 0, &Ia_Invalid },
/* 0F */ { 0, &Ia_Invalid },
/* 10 */ { 0, &Ia_Invalid },
/* 11 */ { 0, &Ia_Invalid },
/* 12 */ { 0, &Ia_Invalid },
/* 13 */ { 0, &Ia_Invalid },
/* 14 */ { 0, &Ia_Invalid },
/* 15 */ { 0, &Ia_Invalid },
/* 16 */ { 0, &Ia_Invalid },
/* 17 */ { 0, &Ia_Invalid },
/* 18 */ { 0, &Ia_Invalid },
/* 19 */ { 0, &Ia_Invalid },
/* 1A */ { 0, &Ia_Invalid },
/* 1B */ { 0, &Ia_Invalid },
/* 1C */ { 0, &Ia_pf2iw_Pq_Qq },
/* 1D */ { 0, &Ia_pf2id_Pq_Qq },
/* 1E */ { 0, &Ia_Invalid },
/* 1F */ { 0, &Ia_Invalid },
/* 20 */ { 0, &Ia_Invalid },
/* 21 */ { 0, &Ia_Invalid },
/* 22 */ { 0, &Ia_Invalid },
/* 23 */ { 0, &Ia_Invalid },
/* 24 */ { 0, &Ia_Invalid },
/* 25 */ { 0, &Ia_Invalid },
/* 26 */ { 0, &Ia_Invalid },
/* 27 */ { 0, &Ia_Invalid },
/* 28 */ { 0, &Ia_Invalid },
/* 29 */ { 0, &Ia_Invalid },
/* 2A */ { 0, &Ia_Invalid },
/* 2B */ { 0, &Ia_Invalid },
/* 2C */ { 0, &Ia_Invalid },
/* 2D */ { 0, &Ia_Invalid },
/* 2E */ { 0, &Ia_Invalid },
/* 2F */ { 0, &Ia_Invalid },
/* 30 */ { 0, &Ia_Invalid },
/* 31 */ { 0, &Ia_Invalid },
/* 32 */ { 0, &Ia_Invalid },
/* 33 */ { 0, &Ia_Invalid },
/* 34 */ { 0, &Ia_Invalid },
/* 35 */ { 0, &Ia_Invalid },
/* 36 */ { 0, &Ia_Invalid },
/* 37 */ { 0, &Ia_Invalid },
/* 38 */ { 0, &Ia_Invalid },
/* 39 */ { 0, &Ia_Invalid },
/* 3A */ { 0, &Ia_Invalid },
/* 3B */ { 0, &Ia_Invalid },
/* 3C */ { 0, &Ia_Invalid },
/* 3D */ { 0, &Ia_Invalid },
/* 3E */ { 0, &Ia_Invalid },
/* 3F */ { 0, &Ia_Invalid },
/* 40 */ { 0, &Ia_Invalid },
/* 41 */ { 0, &Ia_Invalid },
/* 42 */ { 0, &Ia_Invalid },
/* 43 */ { 0, &Ia_Invalid },
/* 44 */ { 0, &Ia_Invalid },
/* 45 */ { 0, &Ia_Invalid },
/* 46 */ { 0, &Ia_Invalid },
/* 47 */ { 0, &Ia_Invalid },
/* 48 */ { 0, &Ia_Invalid },
/* 49 */ { 0, &Ia_Invalid },
/* 4A */ { 0, &Ia_Invalid },
/* 4B */ { 0, &Ia_Invalid },
/* 4C */ { 0, &Ia_Invalid },
/* 4D */ { 0, &Ia_Invalid },
/* 4E */ { 0, &Ia_Invalid },
/* 4F */ { 0, &Ia_Invalid },
/* 50 */ { 0, &Ia_Invalid },
/* 51 */ { 0, &Ia_Invalid },
/* 52 */ { 0, &Ia_Invalid },
/* 53 */ { 0, &Ia_Invalid },
/* 54 */ { 0, &Ia_Invalid },
/* 55 */ { 0, &Ia_Invalid },
/* 56 */ { 0, &Ia_Invalid },
/* 57 */ { 0, &Ia_Invalid },
/* 58 */ { 0, &Ia_Invalid },
/* 59 */ { 0, &Ia_Invalid },
/* 5A */ { 0, &Ia_Invalid },
/* 5B */ { 0, &Ia_Invalid },
/* 5C */ { 0, &Ia_Invalid },
/* 5D */ { 0, &Ia_Invalid },
/* 5E */ { 0, &Ia_Invalid },
/* 5F */ { 0, &Ia_Invalid },
/* 60 */ { 0, &Ia_Invalid },
/* 61 */ { 0, &Ia_Invalid },
/* 62 */ { 0, &Ia_Invalid },
/* 63 */ { 0, &Ia_Invalid },
/* 64 */ { 0, &Ia_Invalid },
/* 65 */ { 0, &Ia_Invalid },
/* 66 */ { 0, &Ia_Invalid },
/* 67 */ { 0, &Ia_Invalid },
/* 68 */ { 0, &Ia_Invalid },
/* 69 */ { 0, &Ia_Invalid },
/* 6A */ { 0, &Ia_Invalid },
/* 6B */ { 0, &Ia_Invalid },
/* 6C */ { 0, &Ia_Invalid },
/* 6D */ { 0, &Ia_Invalid },
/* 6E */ { 0, &Ia_Invalid },
/* 6F */ { 0, &Ia_Invalid },
/* 70 */ { 0, &Ia_Invalid },
/* 71 */ { 0, &Ia_Invalid },
/* 72 */ { 0, &Ia_Invalid },
/* 73 */ { 0, &Ia_Invalid },
/* 74 */ { 0, &Ia_Invalid },
/* 75 */ { 0, &Ia_Invalid },
/* 76 */ { 0, &Ia_Invalid },
/* 77 */ { 0, &Ia_Invalid },
/* 78 */ { 0, &Ia_Invalid },
/* 79 */ { 0, &Ia_Invalid },
/* 7A */ { 0, &Ia_Invalid },
/* 7B */ { 0, &Ia_Invalid },
/* 7C */ { 0, &Ia_Invalid },
/* 7D */ { 0, &Ia_Invalid },
/* 7E */ { 0, &Ia_Invalid },
/* 7F */ { 0, &Ia_Invalid },
/* 80 */ { 0, &Ia_Invalid },
/* 81 */ { 0, &Ia_Invalid },
/* 82 */ { 0, &Ia_Invalid },
/* 83 */ { 0, &Ia_Invalid },
/* 84 */ { 0, &Ia_Invalid },
/* 85 */ { 0, &Ia_Invalid },
/* 86 */ { 0, &Ia_Invalid },
/* 87 */ { 0, &Ia_Invalid },
/* 88 */ { 0, &Ia_Invalid },
/* 89 */ { 0, &Ia_Invalid },
/* 8A */ { 0, &Ia_pfnacc_Pq_Qq },
/* 8B */ { 0, &Ia_Invalid },
/* 8C */ { 0, &Ia_Invalid },
/* 8D */ { 0, &Ia_Invalid },
/* 8E */ { 0, &Ia_pfpnacc_Pq_Qq },
/* 8F */ { 0, &Ia_Invalid },
/* 90 */ { 0, &Ia_pfcmpge_Pq_Qq },
/* 91 */ { 0, &Ia_Invalid },
/* 92 */ { 0, &Ia_Invalid },
/* 93 */ { 0, &Ia_Invalid },
/* 94 */ { 0, &Ia_pfmin_Pq_Qq },
/* 95 */ { 0, &Ia_Invalid },
/* 96 */ { 0, &Ia_pfrcp_Pq_Qq },
/* 97 */ { 0, &Ia_pfrsqrt_Pq_Qq },
/* 98 */ { 0, &Ia_Invalid },
/* 99 */ { 0, &Ia_Invalid },
/* 9A */ { 0, &Ia_pfsub_Pq_Qq },
/* 9B */ { 0, &Ia_Invalid },
/* 9C */ { 0, &Ia_Invalid },
/* 9D */ { 0, &Ia_Invalid },
/* 9E */ { 0, &Ia_pfadd_Pq_Qq },
/* 9F */ { 0, &Ia_Invalid },
/* A0 */ { 0, &Ia_pfcmpgt_Pq_Qq },
/* A1 */ { 0, &Ia_Invalid },
/* A2 */ { 0, &Ia_Invalid },
/* A3 */ { 0, &Ia_Invalid },
/* A4 */ { 0, &Ia_pfmax_Pq_Qq },
/* A5 */ { 0, &Ia_Invalid },
/* A6 */ { 0, &Ia_pfrcpit1_Pq_Qq },
/* A7 */ { 0, &Ia_pfrsqit1_Pq_Qq },
/* A8 */ { 0, &Ia_Invalid },
/* A9 */ { 0, &Ia_Invalid },
/* AA */ { 0, &Ia_pfsubr_Pq_Qq },
/* AB */ { 0, &Ia_Invalid },
/* AC */ { 0, &Ia_Invalid },
/* AD */ { 0, &Ia_Invalid },
/* AE */ { 0, &Ia_pfacc_Pq_Qq },
/* AF */ { 0, &Ia_Invalid },
/* B0 */ { 0, &Ia_pfcmpeq_Pq_Qq },
/* B1 */ { 0, &Ia_Invalid },
/* B2 */ { 0, &Ia_Invalid },
/* B3 */ { 0, &Ia_Invalid },
/* B4 */ { 0, &Ia_pfmul_Pq_Qq },
/* B5 */ { 0, &Ia_Invalid },
/* B6 */ { 0, &Ia_pfrcpit2_Pq_Qq },
/* B7 */ { 0, &Ia_pmulhrw_Pq_Qq },
/* B8 */ { 0, &Ia_Invalid },
/* B9 */ { 0, &Ia_Invalid },
/* BA */ { 0, &Ia_Invalid },
/* BB */ { 0, &Ia_pswapd_Pq_Qq },
/* BC */ { 0, &Ia_Invalid },
/* BD */ { 0, &Ia_Invalid },
/* BE */ { 0, &Ia_Invalid },
/* BF */ { 0, &Ia_pavgb_Pq_Qq },
/* C0 */ { 0, &Ia_Invalid },
/* C1 */ { 0, &Ia_Invalid },
/* C2 */ { 0, &Ia_Invalid },
/* C3 */ { 0, &Ia_Invalid },
/* C4 */ { 0, &Ia_Invalid },
/* C5 */ { 0, &Ia_Invalid },
/* C6 */ { 0, &Ia_Invalid },
/* C7 */ { 0, &Ia_Invalid },
/* C8 */ { 0, &Ia_Invalid },
/* C9 */ { 0, &Ia_Invalid },
/* CA */ { 0, &Ia_Invalid },
/* CB */ { 0, &Ia_Invalid },
/* CC */ { 0, &Ia_Invalid },
/* CD */ { 0, &Ia_Invalid },
/* CE */ { 0, &Ia_Invalid },
/* CF */ { 0, &Ia_Invalid },
/* D0 */ { 0, &Ia_Invalid },
/* D1 */ { 0, &Ia_Invalid },
/* D2 */ { 0, &Ia_Invalid },
/* D3 */ { 0, &Ia_Invalid },
/* D4 */ { 0, &Ia_Invalid },
/* D5 */ { 0, &Ia_Invalid },
/* D6 */ { 0, &Ia_Invalid },
/* D7 */ { 0, &Ia_Invalid },
/* D8 */ { 0, &Ia_Invalid },
/* D9 */ { 0, &Ia_Invalid },
/* DA */ { 0, &Ia_Invalid },
/* DB */ { 0, &Ia_Invalid },
/* DC */ { 0, &Ia_Invalid },
/* DD */ { 0, &Ia_Invalid },
/* DE */ { 0, &Ia_Invalid },
/* DF */ { 0, &Ia_Invalid },
/* E0 */ { 0, &Ia_Invalid },
/* E1 */ { 0, &Ia_Invalid },
/* E2 */ { 0, &Ia_Invalid },
/* E3 */ { 0, &Ia_Invalid },
/* E4 */ { 0, &Ia_Invalid },
/* E5 */ { 0, &Ia_Invalid },
/* E6 */ { 0, &Ia_Invalid },
/* E7 */ { 0, &Ia_Invalid },
/* E8 */ { 0, &Ia_Invalid },
/* E9 */ { 0, &Ia_Invalid },
/* EA */ { 0, &Ia_Invalid },
/* EB */ { 0, &Ia_Invalid },
/* EC */ { 0, &Ia_Invalid },
/* ED */ { 0, &Ia_Invalid },
/* EE */ { 0, &Ia_Invalid },
/* EF */ { 0, &Ia_Invalid },
/* F0 */ { 0, &Ia_Invalid },
/* F1 */ { 0, &Ia_Invalid },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid },
/* F4 */ { 0, &Ia_Invalid },
/* F5 */ { 0, &Ia_Invalid },
/* F6 */ { 0, &Ia_Invalid },
/* F7 */ { 0, &Ia_Invalid },
/* F8 */ { 0, &Ia_Invalid },
/* F9 */ { 0, &Ia_Invalid },
/* FA */ { 0, &Ia_Invalid },
/* FB */ { 0, &Ia_Invalid },
/* FC */ { 0, &Ia_Invalid },
/* FD */ { 0, &Ia_Invalid },
/* FE */ { 0, &Ia_Invalid },
/* FF */ { 0, &Ia_Invalid }
};
/* ************************************************************************ */
/* FPU Opcodes */
// floating point instructions when mod!=11b.
// the following tables will be accessed like groups using the nnn (reg) field of
// the modrm byte. (the first byte is D8-DF)
// D8 (modrm is outside 00h - BFh) (mod != 11)
static BxDisasmOpcodeTable_t BxDisasmFPGroupD8[8] = {
/* 0 */ { 0, &Ia_fadds_Md },
/* 1 */ { 0, &Ia_fmuls_Md },
/* 2 */ { 0, &Ia_fcoms_Md },
/* 3 */ { 0, &Ia_fcomps_Md },
/* 4 */ { 0, &Ia_fsubs_Md },
/* 5 */ { 0, &Ia_fsubrs_Md },
/* 6 */ { 0, &Ia_fdivs_Md },
/* 7 */ { 0, &Ia_fdivrs_Md }
};
// D9 (modrm is outside 00h - BFh) (mod != 11)
static BxDisasmOpcodeTable_t BxDisasmFPGroupD9[8] = {
/* 0 */ { 0, &Ia_flds_Md },
/* 1 */ { 0, &Ia_Invalid },
/* 2 */ { 0, &Ia_fsts_Md },
/* 3 */ { 0, &Ia_fstps_Md },
/* 4 */ { 0, &Ia_fldenv },
/* 5 */ { 0, &Ia_fldcw },
/* 6 */ { 0, &Ia_fnstenv },
/* 7 */ { 0, &Ia_fnstcw }
};
// DA (modrm is outside 00h - BFh) (mod != 11)
static BxDisasmOpcodeTable_t BxDisasmFPGroupDA[8] = {
/* 0 */ { 0, &Ia_fiaddl_Md },
/* 1 */ { 0, &Ia_fimull_Md },
/* 2 */ { 0, &Ia_ficoml_Md },
/* 3 */ { 0, &Ia_ficompl_Md },
/* 4 */ { 0, &Ia_fisubl_Md },
/* 5 */ { 0, &Ia_fisubrl_Md },
/* 6 */ { 0, &Ia_fidivl_Md },
/* 7 */ { 0, &Ia_fidivrl_Md }
};
// DB (modrm is outside 00h - BFh) (mod != 11)
static BxDisasmOpcodeTable_t BxDisasmFPGroupDB[8] = {
/* 0 */ { 0, &Ia_fildl_Md },
/* 1 */ { 0, &Ia_fisttpl_Md },
/* 2 */ { 0, &Ia_fistl_Md },
/* 3 */ { 0, &Ia_fistpl_Md },
/* 4 */ { 0, &Ia_Invalid },
/* 5 */ { 0, &Ia_fldt_Mt },
/* 6 */ { 0, &Ia_Invalid },
/* 7 */ { 0, &Ia_fstpt_Mt }
};
// DC (modrm is outside 00h - BFh) (mod != 11)
static BxDisasmOpcodeTable_t BxDisasmFPGroupDC[8] = {
/* 0 */ { 0, &Ia_faddl_Mq },
/* 1 */ { 0, &Ia_fmull_Mq },
/* 2 */ { 0, &Ia_fcoml_Mq },
/* 3 */ { 0, &Ia_fcompl_Mq },
/* 4 */ { 0, &Ia_fsubl_Mq },
/* 5 */ { 0, &Ia_fsubrl_Mq },
/* 6 */ { 0, &Ia_fdivl_Mq },
/* 7 */ { 0, &Ia_fdivrl_Mq }
};
// DD (modrm is outside 00h - BFh) (mod != 11)
static BxDisasmOpcodeTable_t BxDisasmFPGroupDD[8] = {
/* 0 */ { 0, &Ia_fldl_Mq },
/* 1 */ { 0, &Ia_fisttpq_Mq },
/* 2 */ { 0, &Ia_fstl_Mq },
/* 3 */ { 0, &Ia_fstpl_Mq },
/* 4 */ { 0, &Ia_frstor },
/* 5 */ { 0, &Ia_Invalid },
/* 6 */ { 0, &Ia_fnsave },
/* 7 */ { 0, &Ia_fnstsw }
};
// DE (modrm is outside 00h - BFh) (mod != 11)
static BxDisasmOpcodeTable_t BxDisasmFPGroupDE[8] = {
/* 0 */ { 0, &Ia_fiadds_Mw },
/* 1 */ { 0, &Ia_fimuls_Mw },
/* 2 */ { 0, &Ia_ficoms_Mw },
/* 3 */ { 0, &Ia_ficomps_Mw },
/* 4 */ { 0, &Ia_fisubs_Mw },
/* 5 */ { 0, &Ia_fisubrs_Mw },
/* 6 */ { 0, &Ia_fidivs_Mw },
/* 7 */ { 0, &Ia_fidivrs_Mw }
};
// DF (modrm is outside 00h - BFh) (mod != 11)
static BxDisasmOpcodeTable_t BxDisasmFPGroupDF[8] = {
/* 0 */ { 0, &Ia_filds_Mw },
/* 1 */ { 0, &Ia_fisttps_Mw },
/* 2 */ { 0, &Ia_fists_Mw },
/* 3 */ { 0, &Ia_fistps_Mw },
/* 4 */ { 0, &Ia_fbldt_Mt },
/* 5 */ { 0, &Ia_fildq_Mq },
/* 6 */ { 0, &Ia_fbstpt_Mt },
/* 7 */ { 0, &Ia_fistpq_Mq }
};
// 512 entries for second byte of floating point instructions. (when mod==11b)
static BxDisasmOpcodeTable_t BxDisasmOpcodeInfoFP[512] = {
// D8 (modrm is outside 00h - BFh) (mod == 11)
/* D8 C0 */ { 0, &Ia_fadd_ST0_STi },
/* D8 C1 */ { 0, &Ia_fadd_ST0_STi },
/* D8 C2 */ { 0, &Ia_fadd_ST0_STi },
/* D8 C3 */ { 0, &Ia_fadd_ST0_STi },
/* D8 C4 */ { 0, &Ia_fadd_ST0_STi },
/* D8 C5 */ { 0, &Ia_fadd_ST0_STi },
/* D8 C6 */ { 0, &Ia_fadd_ST0_STi },
/* D8 C7 */ { 0, &Ia_fadd_ST0_STi },
/* D8 C8 */ { 0, &Ia_fmul_ST0_STi },
/* D8 C9 */ { 0, &Ia_fmul_ST0_STi },
/* D8 CA */ { 0, &Ia_fmul_ST0_STi },
/* D8 CB */ { 0, &Ia_fmul_ST0_STi },
/* D8 CC */ { 0, &Ia_fmul_ST0_STi },
/* D8 CD */ { 0, &Ia_fmul_ST0_STi },
/* D8 CE */ { 0, &Ia_fmul_ST0_STi },
/* D8 CF */ { 0, &Ia_fmul_ST0_STi },
/* D8 D0 */ { 0, &Ia_fcom_STi },
/* D8 D1 */ { 0, &Ia_fcom_STi },
/* D8 D2 */ { 0, &Ia_fcom_STi },
/* D8 D3 */ { 0, &Ia_fcom_STi },
/* D8 D4 */ { 0, &Ia_fcom_STi },
/* D8 D5 */ { 0, &Ia_fcom_STi },
/* D8 D6 */ { 0, &Ia_fcom_STi },
/* D8 D7 */ { 0, &Ia_fcom_STi },
/* D8 D8 */ { 0, &Ia_fcomp_STi },
/* D8 D9 */ { 0, &Ia_fcomp_STi },
/* D8 DA */ { 0, &Ia_fcomp_STi },
/* D8 DB */ { 0, &Ia_fcomp_STi },
/* D8 DC */ { 0, &Ia_fcomp_STi },
/* D8 DD */ { 0, &Ia_fcomp_STi },
/* D8 DE */ { 0, &Ia_fcomp_STi },
/* D8 DF */ { 0, &Ia_fcomp_STi },
/* D8 E0 */ { 0, &Ia_fsub_ST0_STi },
/* D8 E1 */ { 0, &Ia_fsub_ST0_STi },
/* D8 E2 */ { 0, &Ia_fsub_ST0_STi },
/* D8 E3 */ { 0, &Ia_fsub_ST0_STi },
/* D8 E4 */ { 0, &Ia_fsub_ST0_STi },
/* D8 E5 */ { 0, &Ia_fsub_ST0_STi },
/* D8 E6 */ { 0, &Ia_fsub_ST0_STi },
/* D8 E7 */ { 0, &Ia_fsub_ST0_STi },
/* D8 E8 */ { 0, &Ia_fsubr_ST0_STi },
/* D8 E9 */ { 0, &Ia_fsubr_ST0_STi },
/* D8 EA */ { 0, &Ia_fsubr_ST0_STi },
/* D8 EB */ { 0, &Ia_fsubr_ST0_STi },
/* D8 EC */ { 0, &Ia_fsubr_ST0_STi },
/* D8 ED */ { 0, &Ia_fsubr_ST0_STi },
/* D8 EE */ { 0, &Ia_fsubr_ST0_STi },
/* D8 EF */ { 0, &Ia_fsubr_ST0_STi },
/* D8 F0 */ { 0, &Ia_fdiv_ST0_STi },
/* D8 F1 */ { 0, &Ia_fdiv_ST0_STi },
/* D8 F2 */ { 0, &Ia_fdiv_ST0_STi },
/* D8 F3 */ { 0, &Ia_fdiv_ST0_STi },
/* D8 F4 */ { 0, &Ia_fdiv_ST0_STi },
/* D8 F5 */ { 0, &Ia_fdiv_ST0_STi },
/* D8 F6 */ { 0, &Ia_fdiv_ST0_STi },
/* D8 F7 */ { 0, &Ia_fdiv_ST0_STi },
/* D8 F8 */ { 0, &Ia_fdivr_ST0_STi },
/* D8 F9 */ { 0, &Ia_fdivr_ST0_STi },
/* D8 FA */ { 0, &Ia_fdivr_ST0_STi },
/* D8 FB */ { 0, &Ia_fdivr_ST0_STi },
/* D8 FC */ { 0, &Ia_fdivr_ST0_STi },
/* D8 FD */ { 0, &Ia_fdivr_ST0_STi },
/* D8 FE */ { 0, &Ia_fdivr_ST0_STi },
/* D8 FF */ { 0, &Ia_fdivr_ST0_STi },
// D9 (modrm is outside 00h - BFh) (mod == 11)
/* D9 C0 */ { 0, &Ia_fld_STi },
/* D9 C1 */ { 0, &Ia_fld_STi },
/* D9 C2 */ { 0, &Ia_fld_STi },
/* D9 C3 */ { 0, &Ia_fld_STi },
/* D9 C4 */ { 0, &Ia_fld_STi },
/* D9 C5 */ { 0, &Ia_fld_STi },
/* D9 C6 */ { 0, &Ia_fld_STi },
/* D9 C7 */ { 0, &Ia_fld_STi },
/* D9 C8 */ { 0, &Ia_fxch },
/* D9 C9 */ { 0, &Ia_fxch },
/* D9 CA */ { 0, &Ia_fxch },
/* D9 CB */ { 0, &Ia_fxch },
/* D9 CC */ { 0, &Ia_fxch },
/* D9 CD */ { 0, &Ia_fxch },
/* D9 CE */ { 0, &Ia_fxch },
/* D9 CF */ { 0, &Ia_fxch },
/* D9 D0 */ { 0, &Ia_fnop },
/* D9 D1 */ { 0, &Ia_Invalid },
/* D9 D2 */ { 0, &Ia_Invalid },
/* D9 D3 */ { 0, &Ia_Invalid },
/* D9 D4 */ { 0, &Ia_Invalid },
/* D9 D5 */ { 0, &Ia_Invalid },
/* D9 D6 */ { 0, &Ia_Invalid },
/* D9 D7 */ { 0, &Ia_Invalid },
/* D9 D8 */ { 0, &Ia_fstp_STi }, // undocumented
/* D9 D9 */ { 0, &Ia_fstp_STi }, // undocumented
/* D9 DA */ { 0, &Ia_fstp_STi }, // undocumented
/* D9 DB */ { 0, &Ia_fstp_STi }, // undocumented
/* D9 DC */ { 0, &Ia_fstp_STi }, // undocumented
/* D9 DD */ { 0, &Ia_fstp_STi }, // undocumented
/* D9 DE */ { 0, &Ia_fstp_STi }, // undocumented
/* D9 DF */ { 0, &Ia_fstp_STi }, // undocumented
/* D9 E0 */ { 0, &Ia_fchs },
/* D9 E1 */ { 0, &Ia_fabs },
/* D9 E2 */ { 0, &Ia_Invalid },
/* D9 E3 */ { 0, &Ia_Invalid },
/* D9 E4 */ { 0, &Ia_ftst },
/* D9 E5 */ { 0, &Ia_fxam },
/* D9 E6 */ { 0, &Ia_Invalid },
/* D9 E7 */ { 0, &Ia_Invalid },
/* D9 E8 */ { 0, &Ia_fld1 },
/* D9 E9 */ { 0, &Ia_fldl2t },
/* D9 EA */ { 0, &Ia_fldl2e },
/* D9 EB */ { 0, &Ia_fldpi },
/* D9 EC */ { 0, &Ia_fldlg2 },
/* D9 ED */ { 0, &Ia_fldln2 },
/* D9 EE */ { 0, &Ia_fldz },
/* D9 EF */ { 0, &Ia_Invalid },
/* D9 F0 */ { 0, &Ia_f2xm1 },
/* D9 F1 */ { 0, &Ia_fyl2x },
/* D9 F2 */ { 0, &Ia_fptan },
/* D9 F3 */ { 0, &Ia_fpatan },
/* D9 F4 */ { 0, &Ia_fxtract },
/* D9 F5 */ { 0, &Ia_fprem1 },
/* D9 F6 */ { 0, &Ia_fdecstp },
/* D9 F7 */ { 0, &Ia_fincstp },
/* D9 F8 */ { 0, &Ia_fprem },
/* D9 F9 */ { 0, &Ia_fyl2xp1 },
/* D9 FA */ { 0, &Ia_fsqrt },
/* D9 FB */ { 0, &Ia_fsincos },
/* D9 FC */ { 0, &Ia_frndint },
/* D9 FD */ { 0, &Ia_fscale },
/* D9 FE */ { 0, &Ia_fsin },
/* D9 FF */ { 0, &Ia_fcos },
// DA (modrm is outside 00h - BFh) (mod == 11)
/* DA C0 */ { 0, &Ia_fcmovb_ST0_STi },
/* DA C1 */ { 0, &Ia_fcmovb_ST0_STi },
/* DA C2 */ { 0, &Ia_fcmovb_ST0_STi },
/* DA C3 */ { 0, &Ia_fcmovb_ST0_STi },
/* DA C4 */ { 0, &Ia_fcmovb_ST0_STi },
/* DA C5 */ { 0, &Ia_fcmovb_ST0_STi },
/* DA C6 */ { 0, &Ia_fcmovb_ST0_STi },
/* DA C7 */ { 0, &Ia_fcmovb_ST0_STi },
/* DA C8 */ { 0, &Ia_fcmove_ST0_STi },
/* DA C9 */ { 0, &Ia_fcmove_ST0_STi },
/* DA CA */ { 0, &Ia_fcmove_ST0_STi },
/* DA CB */ { 0, &Ia_fcmove_ST0_STi },
/* DA CC */ { 0, &Ia_fcmove_ST0_STi },
/* DA CD */ { 0, &Ia_fcmove_ST0_STi },
/* DA CE */ { 0, &Ia_fcmove_ST0_STi },
/* DA CF */ { 0, &Ia_fcmove_ST0_STi },
/* DA D0 */ { 0, &Ia_fcmovbe_ST0_STi },
/* DA D1 */ { 0, &Ia_fcmovbe_ST0_STi },
/* DA D2 */ { 0, &Ia_fcmovbe_ST0_STi },
/* DA D3 */ { 0, &Ia_fcmovbe_ST0_STi },
/* DA D4 */ { 0, &Ia_fcmovbe_ST0_STi },
/* DA D5 */ { 0, &Ia_fcmovbe_ST0_STi },
/* DA D6 */ { 0, &Ia_fcmovbe_ST0_STi },
/* DA D7 */ { 0, &Ia_fcmovbe_ST0_STi },
/* DA D8 */ { 0, &Ia_fcmovu_ST0_STi },
/* DA D9 */ { 0, &Ia_fcmovu_ST0_STi },
/* DA DA */ { 0, &Ia_fcmovu_ST0_STi },
/* DA DB */ { 0, &Ia_fcmovu_ST0_STi },
/* DA DC */ { 0, &Ia_fcmovu_ST0_STi },
/* DA DD */ { 0, &Ia_fcmovu_ST0_STi },
/* DA DE */ { 0, &Ia_fcmovu_ST0_STi },
/* DA DF */ { 0, &Ia_fcmovu_ST0_STi },
/* DA E0 */ { 0, &Ia_Invalid },
/* DA E1 */ { 0, &Ia_Invalid },
/* DA E2 */ { 0, &Ia_Invalid },
/* DA E3 */ { 0, &Ia_Invalid },
/* DA E4 */ { 0, &Ia_Invalid },
/* DA E5 */ { 0, &Ia_Invalid },
/* DA E6 */ { 0, &Ia_Invalid },
/* DA E7 */ { 0, &Ia_Invalid },
/* DA E8 */ { 0, &Ia_Invalid },
/* DA E9 */ { 0, &Ia_fucompp },
/* DA EA */ { 0, &Ia_Invalid },
/* DA EB */ { 0, &Ia_Invalid },
/* DA EC */ { 0, &Ia_Invalid },
/* DA ED */ { 0, &Ia_Invalid },
/* DA EE */ { 0, &Ia_Invalid },
/* DA EF */ { 0, &Ia_Invalid },
/* DA F0 */ { 0, &Ia_Invalid },
/* DA F1 */ { 0, &Ia_Invalid },
/* DA F2 */ { 0, &Ia_Invalid },
/* DA F3 */ { 0, &Ia_Invalid },
/* DA F4 */ { 0, &Ia_Invalid },
/* DA F5 */ { 0, &Ia_Invalid },
/* DA F6 */ { 0, &Ia_Invalid },
/* DA F7 */ { 0, &Ia_Invalid },
/* DA F8 */ { 0, &Ia_Invalid },
/* DA F9 */ { 0, &Ia_Invalid },
/* DA FA */ { 0, &Ia_Invalid },
/* DA FB */ { 0, &Ia_Invalid },
/* DA FC */ { 0, &Ia_Invalid },
/* DA FD */ { 0, &Ia_Invalid },
/* DA FE */ { 0, &Ia_Invalid },
/* DA FF */ { 0, &Ia_Invalid },
// DB (modrm is outside 00h - BFh) (mod == 11)
/* DB C0 */ { 0, &Ia_fcmovnb_ST0_STi },
/* DB C1 */ { 0, &Ia_fcmovnb_ST0_STi },
/* DB C2 */ { 0, &Ia_fcmovnb_ST0_STi },
/* DB C3 */ { 0, &Ia_fcmovnb_ST0_STi },
/* DB C4 */ { 0, &Ia_fcmovnb_ST0_STi },
/* DB C5 */ { 0, &Ia_fcmovnb_ST0_STi },
/* DB C6 */ { 0, &Ia_fcmovnb_ST0_STi },
/* DB C7 */ { 0, &Ia_fcmovnb_ST0_STi },
/* DB C8 */ { 0, &Ia_fcmovne_ST0_STi },
/* DB C9 */ { 0, &Ia_fcmovne_ST0_STi },
/* DB CA */ { 0, &Ia_fcmovne_ST0_STi },
/* DB CB */ { 0, &Ia_fcmovne_ST0_STi },
/* DB CC */ { 0, &Ia_fcmovne_ST0_STi },
/* DB CD */ { 0, &Ia_fcmovne_ST0_STi },
/* DB CE */ { 0, &Ia_fcmovne_ST0_STi },
/* DB CF */ { 0, &Ia_fcmovne_ST0_STi },
/* DB D0 */ { 0, &Ia_fcmovnbe_ST0_STi },
/* DB D1 */ { 0, &Ia_fcmovnbe_ST0_STi },
/* DB D2 */ { 0, &Ia_fcmovnbe_ST0_STi },
/* DB D3 */ { 0, &Ia_fcmovnbe_ST0_STi },
/* DB D4 */ { 0, &Ia_fcmovnbe_ST0_STi },
/* DB D5 */ { 0, &Ia_fcmovnbe_ST0_STi },
/* DB D6 */ { 0, &Ia_fcmovnbe_ST0_STi },
/* DB D7 */ { 0, &Ia_fcmovnbe_ST0_STi },
/* DB D8 */ { 0, &Ia_fcmovnu_ST0_STi },
/* DB D9 */ { 0, &Ia_fcmovnu_ST0_STi },
/* DB DA */ { 0, &Ia_fcmovnu_ST0_STi },
/* DB DB */ { 0, &Ia_fcmovnu_ST0_STi },
/* DB DC */ { 0, &Ia_fcmovnu_ST0_STi },
/* DB DD */ { 0, &Ia_fcmovnu_ST0_STi },
/* DB DE */ { 0, &Ia_fcmovnu_ST0_STi },
/* DB DF */ { 0, &Ia_fcmovnu_ST0_STi },
/* DB E0 */ { 0, &Ia_feni },
/* DB E1 */ { 0, &Ia_fdisi },
/* DB E2 */ { 0, &Ia_fnclex },
/* DB E3 */ { 0, &Ia_fninit },
/* DB E4 */ { 0, &Ia_fsetpm },
/* DB E5 */ { 0, &Ia_Invalid },
/* DB E6 */ { 0, &Ia_Invalid },
/* DB E7 */ { 0, &Ia_Invalid },
/* DB E8 */ { 0, &Ia_fucomi_ST0_STi },
/* DB E9 */ { 0, &Ia_fucomi_ST0_STi },
/* DB EA */ { 0, &Ia_fucomi_ST0_STi },
/* DB EB */ { 0, &Ia_fucomi_ST0_STi },
/* DB EC */ { 0, &Ia_fucomi_ST0_STi },
/* DB ED */ { 0, &Ia_fucomi_ST0_STi },
/* DB EE */ { 0, &Ia_fucomi_ST0_STi },
/* DB EF */ { 0, &Ia_fucomi_ST0_STi },
/* DB F0 */ { 0, &Ia_fcomi_ST0_STi },
/* DB F1 */ { 0, &Ia_fcomi_ST0_STi },
/* DB F2 */ { 0, &Ia_fcomi_ST0_STi },
/* DB F3 */ { 0, &Ia_fcomi_ST0_STi },
/* DB F4 */ { 0, &Ia_fcomi_ST0_STi },
/* DB F5 */ { 0, &Ia_fcomi_ST0_STi },
/* DB F6 */ { 0, &Ia_fcomi_ST0_STi },
/* DB F7 */ { 0, &Ia_fcomi_ST0_STi },
/* DB F8 */ { 0, &Ia_Invalid },
/* DB F9 */ { 0, &Ia_Invalid },
/* DB FA */ { 0, &Ia_Invalid },
/* DB FB */ { 0, &Ia_Invalid },
/* DB FC */ { 0, &Ia_Invalid },
/* DB FD */ { 0, &Ia_Invalid },
/* DB FE */ { 0, &Ia_Invalid },
/* DB FF */ { 0, &Ia_Invalid },
// DC (modrm is outside 00h - BFh) (mod == 11)
/* DC C0 */ { 0, &Ia_fadd_STi_ST0 },
/* DC C1 */ { 0, &Ia_fadd_STi_ST0 },
/* DC C2 */ { 0, &Ia_fadd_STi_ST0 },
/* DC C3 */ { 0, &Ia_fadd_STi_ST0 },
/* DC C4 */ { 0, &Ia_fadd_STi_ST0 },
/* DC C5 */ { 0, &Ia_fadd_STi_ST0 },
/* DC C6 */ { 0, &Ia_fadd_STi_ST0 },
/* DC C7 */ { 0, &Ia_fadd_STi_ST0 },
/* DC C8 */ { 0, &Ia_fmul_STi_ST0 },
/* DC C9 */ { 0, &Ia_fmul_STi_ST0 },
/* DC CA */ { 0, &Ia_fmul_STi_ST0 },
/* DC CB */ { 0, &Ia_fmul_STi_ST0 },
/* DC CC */ { 0, &Ia_fmul_STi_ST0 },
/* DC CD */ { 0, &Ia_fmul_STi_ST0 },
/* DC CE */ { 0, &Ia_fmul_STi_ST0 },
/* DC CF */ { 0, &Ia_fmul_STi_ST0 },
/* DC D0 */ { 0, &Ia_fcom_STi }, // undocumented
/* DC D1 */ { 0, &Ia_fcom_STi }, // undocumented
/* DC D2 */ { 0, &Ia_fcom_STi }, // undocumented
/* DC D3 */ { 0, &Ia_fcom_STi }, // undocumented
/* DC D4 */ { 0, &Ia_fcom_STi }, // undocumented
/* DC D5 */ { 0, &Ia_fcom_STi }, // undocumented
/* DC D6 */ { 0, &Ia_fcom_STi }, // undocumented
/* DC D7 */ { 0, &Ia_fcom_STi }, // undocumented
/* DC D8 */ { 0, &Ia_fcomp_STi }, // undocumented
/* DC D9 */ { 0, &Ia_fcomp_STi }, // undocumented
/* DC DA */ { 0, &Ia_fcomp_STi }, // undocumented
/* DC DB */ { 0, &Ia_fcomp_STi }, // undocumented
/* DC DC */ { 0, &Ia_fcomp_STi }, // undocumented
/* DC DD */ { 0, &Ia_fcomp_STi }, // undocumented
/* DC DE */ { 0, &Ia_fcomp_STi }, // undocumented
/* DC DF */ { 0, &Ia_fcomp_STi }, // undocumented
/* DC E0 */ { 0, &Ia_fsubr_STi_ST0 },
/* DC E1 */ { 0, &Ia_fsubr_STi_ST0 },
/* DC E2 */ { 0, &Ia_fsubr_STi_ST0 },
/* DC E3 */ { 0, &Ia_fsubr_STi_ST0 },
/* DC E4 */ { 0, &Ia_fsubr_STi_ST0 },
/* DC E5 */ { 0, &Ia_fsubr_STi_ST0 },
/* DC E6 */ { 0, &Ia_fsubr_STi_ST0 },
/* DC E7 */ { 0, &Ia_fsubr_STi_ST0 },
/* DC E8 */ { 0, &Ia_fsub_STi_ST0 },
/* DC E9 */ { 0, &Ia_fsub_STi_ST0 },
/* DC EA */ { 0, &Ia_fsub_STi_ST0 },
/* DC EB */ { 0, &Ia_fsub_STi_ST0 },
/* DC EC */ { 0, &Ia_fsub_STi_ST0 },
/* DC ED */ { 0, &Ia_fsub_STi_ST0 },
/* DC EE */ { 0, &Ia_fsub_STi_ST0 },
/* DC EF */ { 0, &Ia_fsub_STi_ST0 },
/* DC F0 */ { 0, &Ia_fdivr_STi_ST0 },
/* DC F1 */ { 0, &Ia_fdivr_STi_ST0 },
/* DC F2 */ { 0, &Ia_fdivr_STi_ST0 },
/* DC F3 */ { 0, &Ia_fdivr_STi_ST0 },
/* DC F4 */ { 0, &Ia_fdivr_STi_ST0 },
/* DC F5 */ { 0, &Ia_fdivr_STi_ST0 },
/* DC F6 */ { 0, &Ia_fdivr_STi_ST0 },
/* DC F7 */ { 0, &Ia_fdivr_STi_ST0 },
/* DC F8 */ { 0, &Ia_fdiv_STi_ST0 },
/* DC F9 */ { 0, &Ia_fdiv_STi_ST0 },
/* DC FA */ { 0, &Ia_fdiv_STi_ST0 },
/* DC FB */ { 0, &Ia_fdiv_STi_ST0 },
/* DC FC */ { 0, &Ia_fdiv_STi_ST0 },
/* DC FD */ { 0, &Ia_fdiv_STi_ST0 },
/* DC FE */ { 0, &Ia_fdiv_STi_ST0 },
/* DC FF */ { 0, &Ia_fdiv_STi_ST0 },
// DD (modrm is outside 00h - BFh) (mod == 11)
/* DD C0 */ { 0, &Ia_ffree_STi },
/* DD C1 */ { 0, &Ia_ffree_STi },
/* DD C2 */ { 0, &Ia_ffree_STi },
/* DD C3 */ { 0, &Ia_ffree_STi },
/* DD C4 */ { 0, &Ia_ffree_STi },
/* DD C5 */ { 0, &Ia_ffree_STi },
/* DD C6 */ { 0, &Ia_ffree_STi },
/* DD C7 */ { 0, &Ia_ffree_STi },
/* DD C8 */ { 0, &Ia_fxch }, // undocumented
/* DD C9 */ { 0, &Ia_fxch }, // undocumented
/* DD CA */ { 0, &Ia_fxch }, // undocumented
/* DD CB */ { 0, &Ia_fxch }, // undocumented
/* DD CC */ { 0, &Ia_fxch }, // undocumented
/* DD CD */ { 0, &Ia_fxch }, // undocumented
/* DD CE */ { 0, &Ia_fxch }, // undocumented
/* DD CF */ { 0, &Ia_fxch }, // undocumented
/* DD D0 */ { 0, &Ia_fst_STi },
/* DD D1 */ { 0, &Ia_fst_STi },
/* DD D2 */ { 0, &Ia_fst_STi },
/* DD D3 */ { 0, &Ia_fst_STi },
/* DD D4 */ { 0, &Ia_fst_STi },
/* DD D5 */ { 0, &Ia_fst_STi },
/* DD D6 */ { 0, &Ia_fst_STi },
/* DD D7 */ { 0, &Ia_fst_STi },
/* DD D8 */ { 0, &Ia_fstp_STi },
/* DD D9 */ { 0, &Ia_fstp_STi },
/* DD DA */ { 0, &Ia_fstp_STi },
/* DD DB */ { 0, &Ia_fstp_STi },
/* DD DC */ { 0, &Ia_fstp_STi },
/* DD DD */ { 0, &Ia_fstp_STi },
/* DD DE */ { 0, &Ia_fstp_STi },
/* DD DF */ { 0, &Ia_fstp_STi },
/* DD E0 */ { 0, &Ia_fucom_STi },
/* DD E1 */ { 0, &Ia_fucom_STi },
/* DD E2 */ { 0, &Ia_fucom_STi },
/* DD E3 */ { 0, &Ia_fucom_STi },
/* DD E4 */ { 0, &Ia_fucom_STi },
/* DD E5 */ { 0, &Ia_fucom_STi },
/* DD E6 */ { 0, &Ia_fucom_STi },
/* DD E7 */ { 0, &Ia_fucom_STi },
/* DD E8 */ { 0, &Ia_fucomp_STi },
/* DD E9 */ { 0, &Ia_fucomp_STi },
/* DD EA */ { 0, &Ia_fucomp_STi },
/* DD EB */ { 0, &Ia_fucomp_STi },
/* DD EC */ { 0, &Ia_fucomp_STi },
/* DD ED */ { 0, &Ia_fucomp_STi },
/* DD EE */ { 0, &Ia_fucomp_STi },
/* DD EF */ { 0, &Ia_fucomp_STi },
/* DD F0 */ { 0, &Ia_Invalid },
/* DD F1 */ { 0, &Ia_Invalid },
/* DD F2 */ { 0, &Ia_Invalid },
/* DD F3 */ { 0, &Ia_Invalid },
/* DD F4 */ { 0, &Ia_Invalid },
/* DD F5 */ { 0, &Ia_Invalid },
/* DD F6 */ { 0, &Ia_Invalid },
/* DD F7 */ { 0, &Ia_Invalid },
/* DD F8 */ { 0, &Ia_Invalid },
/* DD F9 */ { 0, &Ia_Invalid },
/* DD FA */ { 0, &Ia_Invalid },
/* DD FB */ { 0, &Ia_Invalid },
/* DD FC */ { 0, &Ia_Invalid },
/* DD FD */ { 0, &Ia_Invalid },
/* DD FE */ { 0, &Ia_Invalid },
/* DD FF */ { 0, &Ia_Invalid },
// DE (modrm is outside 00h - BFh) (mod == 11)
/* DE C0 */ { 0, &Ia_faddp_STi_ST0 },
/* DE C1 */ { 0, &Ia_faddp_STi_ST0 },
/* DE C2 */ { 0, &Ia_faddp_STi_ST0 },
/* DE C3 */ { 0, &Ia_faddp_STi_ST0 },
/* DE C4 */ { 0, &Ia_faddp_STi_ST0 },
/* DE C5 */ { 0, &Ia_faddp_STi_ST0 },
/* DE C6 */ { 0, &Ia_faddp_STi_ST0 },
/* DE C7 */ { 0, &Ia_faddp_STi_ST0 },
/* DE C8 */ { 0, &Ia_fmulp_STi_ST0 },
/* DE C9 */ { 0, &Ia_fmulp_STi_ST0 },
/* DE CA */ { 0, &Ia_fmulp_STi_ST0 },
/* DE CB */ { 0, &Ia_fmulp_STi_ST0 },
/* DE CC */ { 0, &Ia_fmulp_STi_ST0 },
/* DE CD */ { 0, &Ia_fmulp_STi_ST0 },
/* DE CE */ { 0, &Ia_fmulp_STi_ST0 },
/* DE CF */ { 0, &Ia_fmulp_STi_ST0 },
/* DE D0 */ { 0, &Ia_fcomp_STi }, // undocumented
/* DE D1 */ { 0, &Ia_fcomp_STi }, // undocumented
/* DE D2 */ { 0, &Ia_fcomp_STi }, // undocumented
/* DE D3 */ { 0, &Ia_fcomp_STi }, // undocumented
/* DE D4 */ { 0, &Ia_fcomp_STi }, // undocumented
/* DE D5 */ { 0, &Ia_fcomp_STi }, // undocumented
/* DE D6 */ { 0, &Ia_fcomp_STi }, // undocumented
/* DE D7 */ { 0, &Ia_fcomp_STi }, // undocumented
/* DE D8 */ { 0, &Ia_Invalid },
/* DE D9 */ { 0, &Ia_fcompp },
/* DE DA */ { 0, &Ia_Invalid },
/* DE DB */ { 0, &Ia_Invalid },
/* DE DC */ { 0, &Ia_Invalid },
/* DE DD */ { 0, &Ia_Invalid },
/* DE DE */ { 0, &Ia_Invalid },
/* DE DF */ { 0, &Ia_Invalid },
/* DE E0 */ { 0, &Ia_fsubrp_STi_ST0 },
/* DE E1 */ { 0, &Ia_fsubrp_STi_ST0 },
/* DE E2 */ { 0, &Ia_fsubrp_STi_ST0 },
/* DE E3 */ { 0, &Ia_fsubrp_STi_ST0 },
/* DE E4 */ { 0, &Ia_fsubrp_STi_ST0 },
/* DE E5 */ { 0, &Ia_fsubrp_STi_ST0 },
/* DE E6 */ { 0, &Ia_fsubrp_STi_ST0 },
/* DE E7 */ { 0, &Ia_fsubrp_STi_ST0 },
/* DE E8 */ { 0, &Ia_fsubp_STi_ST0 },
/* DE E9 */ { 0, &Ia_fsubp_STi_ST0 },
/* DE EA */ { 0, &Ia_fsubp_STi_ST0 },
/* DE EB */ { 0, &Ia_fsubp_STi_ST0 },
/* DE EC */ { 0, &Ia_fsubp_STi_ST0 },
/* DE ED */ { 0, &Ia_fsubp_STi_ST0 },
/* DE EE */ { 0, &Ia_fsubp_STi_ST0 },
/* DE EF */ { 0, &Ia_fsubp_STi_ST0 },
/* DE F0 */ { 0, &Ia_fdivrp_STi_ST0 },
/* DE F1 */ { 0, &Ia_fdivrp_STi_ST0 },
/* DE F2 */ { 0, &Ia_fdivrp_STi_ST0 },
/* DE F3 */ { 0, &Ia_fdivrp_STi_ST0 },
/* DE F4 */ { 0, &Ia_fdivrp_STi_ST0 },
/* DE F5 */ { 0, &Ia_fdivrp_STi_ST0 },
/* DE F6 */ { 0, &Ia_fdivrp_STi_ST0 },
/* DE F7 */ { 0, &Ia_fdivrp_STi_ST0 },
/* DE F8 */ { 0, &Ia_fdivp_STi_ST0 },
/* DE F9 */ { 0, &Ia_fdivp_STi_ST0 },
/* DE FA */ { 0, &Ia_fdivp_STi_ST0 },
/* DE FB */ { 0, &Ia_fdivp_STi_ST0 },
/* DE FC */ { 0, &Ia_fdivp_STi_ST0 },
/* DE FD */ { 0, &Ia_fdivp_STi_ST0 },
/* DE FE */ { 0, &Ia_fdivp_STi_ST0 },
/* DE FF */ { 0, &Ia_fdivp_STi_ST0 },
// DF (modrm is outside 00h - BFh) (mod == 11)
/* DF C0 */ { 0, &Ia_ffreep_STi }, // 287 compatibility opcode
/* DF C1 */ { 0, &Ia_ffreep_STi },
/* DF C2 */ { 0, &Ia_ffreep_STi },
/* DF C3 */ { 0, &Ia_ffreep_STi },
/* DF C4 */ { 0, &Ia_ffreep_STi },
/* DF C5 */ { 0, &Ia_ffreep_STi },
/* DF C6 */ { 0, &Ia_ffreep_STi },
/* DF C7 */ { 0, &Ia_ffreep_STi },
/* DF C8 */ { 0, &Ia_fxch }, // undocumented
/* DF C9 */ { 0, &Ia_fxch }, // undocumented
/* DF CA */ { 0, &Ia_fxch }, // undocumented
/* DF CB */ { 0, &Ia_fxch }, // undocumented
/* DF CC */ { 0, &Ia_fxch }, // undocumented
/* DF CD */ { 0, &Ia_fxch }, // undocumented
/* DF CE */ { 0, &Ia_fxch }, // undocumented
/* DF CF */ { 0, &Ia_fxch }, // undocumented
/* DF D0 */ { 0, &Ia_fstp_STi }, // undocumented
/* DF D1 */ { 0, &Ia_fstp_STi }, // undocumented
/* DF D2 */ { 0, &Ia_fstp_STi }, // undocumented
/* DF D3 */ { 0, &Ia_fstp_STi }, // undocumented
/* DF D4 */ { 0, &Ia_fstp_STi }, // undocumented
/* DF D5 */ { 0, &Ia_fstp_STi }, // undocumented
/* DF D6 */ { 0, &Ia_fstp_STi }, // undocumented
/* DF D7 */ { 0, &Ia_fstp_STi }, // undocumented
/* DF D8 */ { 0, &Ia_fstp_STi }, // undocumented
/* DF D9 */ { 0, &Ia_fstp_STi }, // undocumented
/* DF DA */ { 0, &Ia_fstp_STi }, // undocumented
/* DF DB */ { 0, &Ia_fstp_STi }, // undocumented
/* DF DC */ { 0, &Ia_fstp_STi }, // undocumented
/* DF DD */ { 0, &Ia_fstp_STi }, // undocumented
/* DF DE */ { 0, &Ia_fstp_STi }, // undocumented
/* DF DF */ { 0, &Ia_fstp_STi }, // undocumented
/* DF E0 */ { 0, &Ia_fnstsw_AX },
/* DF E1 */ { 0, &Ia_Invalid },
/* DF E2 */ { 0, &Ia_Invalid },
/* DF E3 */ { 0, &Ia_Invalid },
/* DF E4 */ { 0, &Ia_Invalid },
/* DF E5 */ { 0, &Ia_Invalid },
/* DF E6 */ { 0, &Ia_Invalid },
/* DF E7 */ { 0, &Ia_Invalid },
/* DF E8 */ { 0, &Ia_fucomip_ST0_STi },
/* DF E9 */ { 0, &Ia_fucomip_ST0_STi },
/* DF EA */ { 0, &Ia_fucomip_ST0_STi },
/* DF EB */ { 0, &Ia_fucomip_ST0_STi },
/* DF EC */ { 0, &Ia_fucomip_ST0_STi },
/* DF ED */ { 0, &Ia_fucomip_ST0_STi },
/* DF EE */ { 0, &Ia_fucomip_ST0_STi },
/* DF EF */ { 0, &Ia_fucomip_ST0_STi },
/* DF F0 */ { 0, &Ia_fcomip_ST0_STi },
/* DF F1 */ { 0, &Ia_fcomip_ST0_STi },
/* DF F2 */ { 0, &Ia_fcomip_ST0_STi },
/* DF F3 */ { 0, &Ia_fcomip_ST0_STi },
/* DF F4 */ { 0, &Ia_fcomip_ST0_STi },
/* DF F5 */ { 0, &Ia_fcomip_ST0_STi },
/* DF F6 */ { 0, &Ia_fcomip_ST0_STi },
/* DF F7 */ { 0, &Ia_fcomip_ST0_STi },
/* DF F8 */ { 0, &Ia_Invalid },
/* DF F9 */ { 0, &Ia_Invalid },
/* DF FA */ { 0, &Ia_Invalid },
/* DF FB */ { 0, &Ia_Invalid },
/* DF FC */ { 0, &Ia_Invalid },
/* DF FD */ { 0, &Ia_Invalid },
/* DF FE */ { 0, &Ia_Invalid },
/* DF FF */ { 0, &Ia_Invalid },
};

View File

@ -0,0 +1,890 @@
/////////////////////////////////////////////////////////////////////////
// $Id: dis_tables_xop.inc 11863 2013-10-07 19:23:19Z sshwarts $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2011-2013 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
/////////////////////////////////////////////////////////////////////////
static BxDisasmOpcodeTable_t BxDisasmGroupXOP_G1[8] = {
/* 0 */ { 0, &Ia_Invalid },
/* 1 */ { 0, &Ia_blcfill_By_Ey },
/* 2 */ { 0, &Ia_blsfill_By_Ey },
/* 3 */ { 0, &Ia_blcs_By_Ey },
/* 4 */ { 0, &Ia_tzmsk_By_Ey },
/* 5 */ { 0, &Ia_blcic_By_Ey },
/* 6 */ { 0, &Ia_blsic_By_Ey },
/* 7 */ { 0, &Ia_t1mskc_By_Ey }
};
static BxDisasmOpcodeTable_t BxDisasmGroupXOP_G2[8] = {
/* 0 */ { 0, &Ia_Invalid },
/* 1 */ { 0, &Ia_blcmsk_By_Ey },
/* 2 */ { 0, &Ia_Invalid },
/* 3 */ { 0, &Ia_Invalid },
/* 4 */ { 0, &Ia_Invalid },
/* 5 */ { 0, &Ia_Invalid },
/* 6 */ { 0, &Ia_blci_By_Ey },
/* 7 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop8_a2[2] = {
/* 0 */ { 0, &Ia_vpcmov_Vdq_Hdq_Wdq_VIb },
/* 1 */ { 0, &Ia_vpcmov_Vdq_Hdq_VIb_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop8_a3[2] = {
/* 0 */ { 0, &Ia_vpperm_Vdq_Hdq_Wdq_VIb },
/* 1 */ { 0, &Ia_vpperm_Vdq_Hdq_VIb_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop9_88[2] = {
/* 0 */ { 0, &Ia_vpshab_Vdq_Wdq_Hdq },
/* 1 */ { 0, &Ia_vpshab_Vdq_Hdq_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop9_89[2] = {
/* 0 */ { 0, &Ia_vpshaw_Vdq_Wdq_Hdq },
/* 1 */ { 0, &Ia_vpshaw_Vdq_Hdq_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop9_8a[2] = {
/* 0 */ { 0, &Ia_vpshad_Vdq_Wdq_Hdq },
/* 1 */ { 0, &Ia_vpshad_Vdq_Hdq_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop9_8b[2] = {
/* 0 */ { 0, &Ia_vpshaq_Vdq_Wdq_Hdq },
/* 1 */ { 0, &Ia_vpshaq_Vdq_Hdq_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop9_90[2] = {
/* 0 */ { 0, &Ia_vprotb_Vdq_Wdq_Hdq },
/* 1 */ { 0, &Ia_vprotb_Vdq_Hdq_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop9_91[2] = {
/* 0 */ { 0, &Ia_vprotw_Vdq_Wdq_Hdq },
/* 1 */ { 0, &Ia_vprotw_Vdq_Hdq_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop9_92[2] = {
/* 0 */ { 0, &Ia_vprotd_Vdq_Wdq_Hdq },
/* 1 */ { 0, &Ia_vprotd_Vdq_Hdq_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop9_93[2] = {
/* 0 */ { 0, &Ia_vprotq_Vdq_Wdq_Hdq },
/* 1 */ { 0, &Ia_vprotq_Vdq_Hdq_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop9_94[2] = {
/* 0 */ { 0, &Ia_vpshlb_Vdq_Wdq_Hdq },
/* 1 */ { 0, &Ia_vpshlb_Vdq_Hdq_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop9_95[2] = {
/* 0 */ { 0, &Ia_vpshlw_Vdq_Wdq_Hdq },
/* 1 */ { 0, &Ia_vpshlw_Vdq_Hdq_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop9_96[2] = {
/* 0 */ { 0, &Ia_vpshld_Vdq_Wdq_Hdq },
/* 1 */ { 0, &Ia_vpshld_Vdq_Hdq_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmGrpVexW_xop9_97[2] = {
/* 0 */ { 0, &Ia_vpshlq_Vdq_Wdq_Hdq },
/* 1 */ { 0, &Ia_vpshlq_Vdq_Hdq_Wdq }
};
static BxDisasmOpcodeTable_t BxDisasmOpcodesXOP[256*3] = {
// 256 entries for XOP map 0x8 opcodes
/* 00 */ { 0, &Ia_Invalid },
/* 01 */ { GRPN(XOP_G1) },
/* 02 */ { GRPN(XOP_G2) },
/* 03 */ { 0, &Ia_Invalid },
/* 04 */ { 0, &Ia_Invalid },
/* 05 */ { 0, &Ia_Invalid },
/* 06 */ { 0, &Ia_Invalid },
/* 07 */ { 0, &Ia_Invalid },
/* 08 */ { 0, &Ia_Invalid },
/* 09 */ { 0, &Ia_Invalid },
/* 0A */ { 0, &Ia_Invalid },
/* 0B */ { 0, &Ia_Invalid },
/* 0C */ { 0, &Ia_Invalid },
/* 0D */ { 0, &Ia_Invalid },
/* 0E */ { 0, &Ia_Invalid },
/* 0F */ { 0, &Ia_Invalid },
/* 10 */ { 0, &Ia_Invalid },
/* 11 */ { 0, &Ia_Invalid },
/* 12 */ { 0, &Ia_Invalid },
/* 13 */ { 0, &Ia_Invalid },
/* 14 */ { 0, &Ia_Invalid },
/* 15 */ { 0, &Ia_Invalid },
/* 16 */ { 0, &Ia_Invalid },
/* 17 */ { 0, &Ia_Invalid },
/* 18 */ { 0, &Ia_Invalid },
/* 19 */ { 0, &Ia_Invalid },
/* 1A */ { 0, &Ia_Invalid },
/* 1B */ { 0, &Ia_Invalid },
/* 1C */ { 0, &Ia_Invalid },
/* 1D */ { 0, &Ia_Invalid },
/* 1E */ { 0, &Ia_Invalid },
/* 1F */ { 0, &Ia_Invalid },
/* 20 */ { 0, &Ia_Invalid },
/* 21 */ { 0, &Ia_Invalid },
/* 22 */ { 0, &Ia_Invalid },
/* 23 */ { 0, &Ia_Invalid },
/* 24 */ { 0, &Ia_Invalid },
/* 25 */ { 0, &Ia_Invalid },
/* 26 */ { 0, &Ia_Invalid },
/* 27 */ { 0, &Ia_Invalid },
/* 28 */ { 0, &Ia_Invalid },
/* 29 */ { 0, &Ia_Invalid },
/* 2A */ { 0, &Ia_Invalid },
/* 2B */ { 0, &Ia_Invalid },
/* 2C */ { 0, &Ia_Invalid },
/* 2D */ { 0, &Ia_Invalid },
/* 2E */ { 0, &Ia_Invalid },
/* 2F */ { 0, &Ia_Invalid },
/* 30 */ { 0, &Ia_Invalid },
/* 31 */ { 0, &Ia_Invalid },
/* 32 */ { 0, &Ia_Invalid },
/* 33 */ { 0, &Ia_Invalid },
/* 34 */ { 0, &Ia_Invalid },
/* 35 */ { 0, &Ia_Invalid },
/* 36 */ { 0, &Ia_Invalid },
/* 37 */ { 0, &Ia_Invalid },
/* 38 */ { 0, &Ia_Invalid },
/* 39 */ { 0, &Ia_Invalid },
/* 3A */ { 0, &Ia_Invalid },
/* 3B */ { 0, &Ia_Invalid },
/* 3C */ { 0, &Ia_Invalid },
/* 3D */ { 0, &Ia_Invalid },
/* 3E */ { 0, &Ia_Invalid },
/* 3F */ { 0, &Ia_Invalid },
/* 40 */ { 0, &Ia_Invalid },
/* 41 */ { 0, &Ia_Invalid },
/* 42 */ { 0, &Ia_Invalid },
/* 43 */ { 0, &Ia_Invalid },
/* 44 */ { 0, &Ia_Invalid },
/* 45 */ { 0, &Ia_Invalid },
/* 46 */ { 0, &Ia_Invalid },
/* 47 */ { 0, &Ia_Invalid },
/* 48 */ { 0, &Ia_Invalid },
/* 49 */ { 0, &Ia_Invalid },
/* 4A */ { 0, &Ia_Invalid },
/* 4B */ { 0, &Ia_Invalid },
/* 4C */ { 0, &Ia_Invalid },
/* 4D */ { 0, &Ia_Invalid },
/* 4E */ { 0, &Ia_Invalid },
/* 4F */ { 0, &Ia_Invalid },
/* 50 */ { 0, &Ia_Invalid },
/* 51 */ { 0, &Ia_Invalid },
/* 52 */ { 0, &Ia_Invalid },
/* 53 */ { 0, &Ia_Invalid },
/* 54 */ { 0, &Ia_Invalid },
/* 55 */ { 0, &Ia_Invalid },
/* 56 */ { 0, &Ia_Invalid },
/* 57 */ { 0, &Ia_Invalid },
/* 58 */ { 0, &Ia_Invalid },
/* 59 */ { 0, &Ia_Invalid },
/* 5A */ { 0, &Ia_Invalid },
/* 5B */ { 0, &Ia_Invalid },
/* 5C */ { 0, &Ia_Invalid },
/* 5D */ { 0, &Ia_Invalid },
/* 5E */ { 0, &Ia_Invalid },
/* 5F */ { 0, &Ia_Invalid },
/* 60 */ { 0, &Ia_Invalid },
/* 61 */ { 0, &Ia_Invalid },
/* 62 */ { 0, &Ia_Invalid },
/* 63 */ { 0, &Ia_Invalid },
/* 64 */ { 0, &Ia_Invalid },
/* 65 */ { 0, &Ia_Invalid },
/* 66 */ { 0, &Ia_Invalid },
/* 67 */ { 0, &Ia_Invalid },
/* 68 */ { 0, &Ia_Invalid },
/* 69 */ { 0, &Ia_Invalid },
/* 6A */ { 0, &Ia_Invalid },
/* 6B */ { 0, &Ia_Invalid },
/* 6C */ { 0, &Ia_Invalid },
/* 6D */ { 0, &Ia_Invalid },
/* 6E */ { 0, &Ia_Invalid },
/* 6F */ { 0, &Ia_Invalid },
/* 70 */ { 0, &Ia_Invalid },
/* 71 */ { 0, &Ia_Invalid },
/* 72 */ { 0, &Ia_Invalid },
/* 73 */ { 0, &Ia_Invalid },
/* 74 */ { 0, &Ia_Invalid },
/* 75 */ { 0, &Ia_Invalid },
/* 76 */ { 0, &Ia_Invalid },
/* 77 */ { 0, &Ia_Invalid },
/* 78 */ { 0, &Ia_Invalid },
/* 79 */ { 0, &Ia_Invalid },
/* 7A */ { 0, &Ia_Invalid },
/* 7B */ { 0, &Ia_Invalid },
/* 7C */ { 0, &Ia_Invalid },
/* 7D */ { 0, &Ia_Invalid },
/* 7E */ { 0, &Ia_Invalid },
/* 7F */ { 0, &Ia_Invalid },
/* 80 */ { 0, &Ia_Invalid },
/* 81 */ { 0, &Ia_Invalid },
/* 82 */ { 0, &Ia_Invalid },
/* 83 */ { 0, &Ia_Invalid },
/* 84 */ { 0, &Ia_Invalid },
/* 85 */ { 0, &Ia_vpmacssww_Vdq_Hdq_Wdq_VIb },
/* 86 */ { 0, &Ia_vpmacsswd_Vdq_Hdq_Wdq_VIb },
/* 87 */ { 0, &Ia_vpmacssdql_Vdq_Hdq_Wdq_VIb },
/* 88 */ { 0, &Ia_Invalid },
/* 89 */ { 0, &Ia_Invalid },
/* 8A */ { 0, &Ia_Invalid },
/* 8B */ { 0, &Ia_Invalid },
/* 8C */ { 0, &Ia_Invalid },
/* 8D */ { 0, &Ia_Invalid },
/* 8E */ { 0, &Ia_vpmacssdd_Vdq_Hdq_Wdq_VIb },
/* 8F */ { 0, &Ia_vpmacssdqh_Vdq_Hdq_Wdq_VIb },
/* 90 */ { 0, &Ia_Invalid },
/* 91 */ { 0, &Ia_Invalid },
/* 92 */ { 0, &Ia_Invalid },
/* 93 */ { 0, &Ia_Invalid },
/* 94 */ { 0, &Ia_Invalid },
/* 95 */ { 0, &Ia_vpmacsww_Vdq_Hdq_Wdq_VIb },
/* 96 */ { 0, &Ia_vpmacswd_Vdq_Hdq_Wdq_VIb },
/* 97 */ { 0, &Ia_vpmacsdql_Vdq_Hdq_Wdq_VIb },
/* 98 */ { 0, &Ia_Invalid },
/* 99 */ { 0, &Ia_Invalid },
/* 9A */ { 0, &Ia_Invalid },
/* 9B */ { 0, &Ia_Invalid },
/* 9C */ { 0, &Ia_Invalid },
/* 9D */ { 0, &Ia_Invalid },
/* 9E */ { 0, &Ia_vpmacsdd_Vdq_Hdq_Wdq_VIb },
/* 9F */ { 0, &Ia_vpmacsdqh_Vdq_Hdq_Wdq_VIb },
/* A0 */ { 0, &Ia_Invalid },
/* A1 */ { 0, &Ia_Invalid },
/* A2 */ { GRPVEXW(xop8_a2) },
/* A3 */ { GRPVEXW(xop8_a3) },
/* A4 */ { 0, &Ia_Invalid },
/* A5 */ { 0, &Ia_Invalid },
/* A6 */ { 0, &Ia_vpmadcsswd_Vdq_Hdq_Wdq_VIb },
/* A7 */ { 0, &Ia_Invalid },
/* A8 */ { 0, &Ia_Invalid },
/* A9 */ { 0, &Ia_Invalid },
/* AA */ { 0, &Ia_Invalid },
/* AB */ { 0, &Ia_Invalid },
/* AC */ { 0, &Ia_Invalid },
/* AD */ { 0, &Ia_Invalid },
/* AE */ { 0, &Ia_Invalid },
/* AF */ { 0, &Ia_Invalid },
/* B0 */ { 0, &Ia_Invalid },
/* B1 */ { 0, &Ia_Invalid },
/* B2 */ { 0, &Ia_Invalid },
/* B3 */ { 0, &Ia_Invalid },
/* B4 */ { 0, &Ia_Invalid },
/* B5 */ { 0, &Ia_Invalid },
/* B6 */ { 0, &Ia_vpmadcswd_Vdq_Hdq_Wdq_VIb },
/* B7 */ { 0, &Ia_Invalid },
/* B8 */ { 0, &Ia_Invalid },
/* B9 */ { 0, &Ia_Invalid },
/* BA */ { 0, &Ia_Invalid },
/* BB */ { 0, &Ia_Invalid },
/* BC */ { 0, &Ia_Invalid },
/* BD */ { 0, &Ia_Invalid },
/* BE */ { 0, &Ia_Invalid },
/* BF */ { 0, &Ia_Invalid },
/* C0 */ { 0, &Ia_vprotb_Vdq_Wdq_Ib },
/* C1 */ { 0, &Ia_vprotw_Vdq_Wdq_Ib },
/* C2 */ { 0, &Ia_vprotd_Vdq_Wdq_Ib },
/* C3 */ { 0, &Ia_vprotq_Vdq_Wdq_Ib },
/* C4 */ { 0, &Ia_Invalid },
/* C5 */ { 0, &Ia_Invalid },
/* C6 */ { 0, &Ia_Invalid },
/* C7 */ { 0, &Ia_Invalid },
/* C8 */ { 0, &Ia_Invalid },
/* C9 */ { 0, &Ia_Invalid },
/* CA */ { 0, &Ia_Invalid },
/* CB */ { 0, &Ia_Invalid },
/* CC */ { 0, &Ia_vpcomb_Vdq_Hdq_Wdq_Ib },
/* CD */ { 0, &Ia_vpcomw_Vdq_Hdq_Wdq_Ib },
/* CE */ { 0, &Ia_vpcomd_Vdq_Hdq_Wdq_Ib },
/* CF */ { 0, &Ia_vpcomq_Vdq_Hdq_Wdq_Ib },
/* D0 */ { 0, &Ia_Invalid },
/* D1 */ { 0, &Ia_Invalid },
/* D2 */ { 0, &Ia_Invalid },
/* D3 */ { 0, &Ia_Invalid },
/* D4 */ { 0, &Ia_Invalid },
/* D5 */ { 0, &Ia_Invalid },
/* D6 */ { 0, &Ia_Invalid },
/* D7 */ { 0, &Ia_Invalid },
/* D8 */ { 0, &Ia_Invalid },
/* D9 */ { 0, &Ia_Invalid },
/* DA */ { 0, &Ia_Invalid },
/* DB */ { 0, &Ia_Invalid },
/* DC */ { 0, &Ia_Invalid },
/* DD */ { 0, &Ia_Invalid },
/* DE */ { 0, &Ia_Invalid },
/* DF */ { 0, &Ia_Invalid },
/* E0 */ { 0, &Ia_Invalid },
/* E1 */ { 0, &Ia_Invalid },
/* E2 */ { 0, &Ia_Invalid },
/* E3 */ { 0, &Ia_Invalid },
/* E4 */ { 0, &Ia_Invalid },
/* E5 */ { 0, &Ia_Invalid },
/* E6 */ { 0, &Ia_Invalid },
/* E7 */ { 0, &Ia_Invalid },
/* E8 */ { 0, &Ia_Invalid },
/* E9 */ { 0, &Ia_Invalid },
/* EA */ { 0, &Ia_Invalid },
/* EB */ { 0, &Ia_Invalid },
/* EC */ { 0, &Ia_vpcomub_Vdq_Hdq_Wdq_Ib },
/* ED */ { 0, &Ia_vpcomuw_Vdq_Hdq_Wdq_Ib },
/* EE */ { 0, &Ia_vpcomud_Vdq_Hdq_Wdq_Ib },
/* EF */ { 0, &Ia_vpcomuq_Vdq_Hdq_Wdq_Ib },
/* F0 */ { 0, &Ia_Invalid },
/* F1 */ { 0, &Ia_Invalid },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid },
/* F4 */ { 0, &Ia_Invalid },
/* F5 */ { 0, &Ia_Invalid },
/* F6 */ { 0, &Ia_Invalid },
/* F7 */ { 0, &Ia_Invalid },
/* F8 */ { 0, &Ia_Invalid },
/* F9 */ { 0, &Ia_Invalid },
/* FA */ { 0, &Ia_Invalid },
/* FB */ { 0, &Ia_Invalid },
/* FC */ { 0, &Ia_Invalid },
/* FD */ { 0, &Ia_Invalid },
/* FE */ { 0, &Ia_Invalid },
/* FF */ { 0, &Ia_Invalid },
// 256 entries for XOP map 0x9 opcodes
/* 00 */ { 0, &Ia_Invalid },
/* 01 */ { 0, &Ia_Invalid },
/* 02 */ { 0, &Ia_Invalid },
/* 03 */ { 0, &Ia_Invalid },
/* 04 */ { 0, &Ia_Invalid },
/* 05 */ { 0, &Ia_Invalid },
/* 06 */ { 0, &Ia_Invalid },
/* 07 */ { 0, &Ia_Invalid },
/* 08 */ { 0, &Ia_Invalid },
/* 09 */ { 0, &Ia_Invalid },
/* 0A */ { 0, &Ia_Invalid },
/* 0B */ { 0, &Ia_Invalid },
/* 0C */ { 0, &Ia_Invalid },
/* 0D */ { 0, &Ia_Invalid },
/* 0E */ { 0, &Ia_Invalid },
/* 0F */ { 0, &Ia_Invalid },
/* 10 */ { 0, &Ia_Invalid },
/* 11 */ { 0, &Ia_Invalid },
/* 12 */ { 0, &Ia_Invalid },
/* 13 */ { 0, &Ia_Invalid },
/* 14 */ { 0, &Ia_Invalid },
/* 15 */ { 0, &Ia_Invalid },
/* 16 */ { 0, &Ia_Invalid },
/* 17 */ { 0, &Ia_Invalid },
/* 18 */ { 0, &Ia_Invalid },
/* 19 */ { 0, &Ia_Invalid },
/* 1A */ { 0, &Ia_Invalid },
/* 1B */ { 0, &Ia_Invalid },
/* 1C */ { 0, &Ia_Invalid },
/* 1D */ { 0, &Ia_Invalid },
/* 1E */ { 0, &Ia_Invalid },
/* 1F */ { 0, &Ia_Invalid },
/* 20 */ { 0, &Ia_Invalid },
/* 21 */ { 0, &Ia_Invalid },
/* 22 */ { 0, &Ia_Invalid },
/* 23 */ { 0, &Ia_Invalid },
/* 24 */ { 0, &Ia_Invalid },
/* 25 */ { 0, &Ia_Invalid },
/* 26 */ { 0, &Ia_Invalid },
/* 27 */ { 0, &Ia_Invalid },
/* 28 */ { 0, &Ia_Invalid },
/* 29 */ { 0, &Ia_Invalid },
/* 2A */ { 0, &Ia_Invalid },
/* 2B */ { 0, &Ia_Invalid },
/* 2C */ { 0, &Ia_Invalid },
/* 2D */ { 0, &Ia_Invalid },
/* 2E */ { 0, &Ia_Invalid },
/* 2F */ { 0, &Ia_Invalid },
/* 30 */ { 0, &Ia_Invalid },
/* 31 */ { 0, &Ia_Invalid },
/* 32 */ { 0, &Ia_Invalid },
/* 33 */ { 0, &Ia_Invalid },
/* 34 */ { 0, &Ia_Invalid },
/* 35 */ { 0, &Ia_Invalid },
/* 36 */ { 0, &Ia_Invalid },
/* 37 */ { 0, &Ia_Invalid },
/* 38 */ { 0, &Ia_Invalid },
/* 39 */ { 0, &Ia_Invalid },
/* 3A */ { 0, &Ia_Invalid },
/* 3B */ { 0, &Ia_Invalid },
/* 3C */ { 0, &Ia_Invalid },
/* 3D */ { 0, &Ia_Invalid },
/* 3E */ { 0, &Ia_Invalid },
/* 3F */ { 0, &Ia_Invalid },
/* 40 */ { 0, &Ia_Invalid },
/* 41 */ { 0, &Ia_Invalid },
/* 42 */ { 0, &Ia_Invalid },
/* 43 */ { 0, &Ia_Invalid },
/* 44 */ { 0, &Ia_Invalid },
/* 45 */ { 0, &Ia_Invalid },
/* 46 */ { 0, &Ia_Invalid },
/* 47 */ { 0, &Ia_Invalid },
/* 48 */ { 0, &Ia_Invalid },
/* 49 */ { 0, &Ia_Invalid },
/* 4A */ { 0, &Ia_Invalid },
/* 4B */ { 0, &Ia_Invalid },
/* 4C */ { 0, &Ia_Invalid },
/* 4D */ { 0, &Ia_Invalid },
/* 4E */ { 0, &Ia_Invalid },
/* 4F */ { 0, &Ia_Invalid },
/* 50 */ { 0, &Ia_Invalid },
/* 51 */ { 0, &Ia_Invalid },
/* 52 */ { 0, &Ia_Invalid },
/* 53 */ { 0, &Ia_Invalid },
/* 54 */ { 0, &Ia_Invalid },
/* 55 */ { 0, &Ia_Invalid },
/* 56 */ { 0, &Ia_Invalid },
/* 57 */ { 0, &Ia_Invalid },
/* 58 */ { 0, &Ia_Invalid },
/* 59 */ { 0, &Ia_Invalid },
/* 5A */ { 0, &Ia_Invalid },
/* 5B */ { 0, &Ia_Invalid },
/* 5C */ { 0, &Ia_Invalid },
/* 5D */ { 0, &Ia_Invalid },
/* 5E */ { 0, &Ia_Invalid },
/* 5F */ { 0, &Ia_Invalid },
/* 60 */ { 0, &Ia_Invalid },
/* 61 */ { 0, &Ia_Invalid },
/* 62 */ { 0, &Ia_Invalid },
/* 63 */ { 0, &Ia_Invalid },
/* 64 */ { 0, &Ia_Invalid },
/* 65 */ { 0, &Ia_Invalid },
/* 66 */ { 0, &Ia_Invalid },
/* 67 */ { 0, &Ia_Invalid },
/* 68 */ { 0, &Ia_Invalid },
/* 69 */ { 0, &Ia_Invalid },
/* 6A */ { 0, &Ia_Invalid },
/* 6B */ { 0, &Ia_Invalid },
/* 6C */ { 0, &Ia_Invalid },
/* 6D */ { 0, &Ia_Invalid },
/* 6E */ { 0, &Ia_Invalid },
/* 6F */ { 0, &Ia_Invalid },
/* 70 */ { 0, &Ia_Invalid },
/* 71 */ { 0, &Ia_Invalid },
/* 72 */ { 0, &Ia_Invalid },
/* 73 */ { 0, &Ia_Invalid },
/* 74 */ { 0, &Ia_Invalid },
/* 75 */ { 0, &Ia_Invalid },
/* 76 */ { 0, &Ia_Invalid },
/* 77 */ { 0, &Ia_Invalid },
/* 78 */ { 0, &Ia_Invalid },
/* 79 */ { 0, &Ia_Invalid },
/* 7A */ { 0, &Ia_Invalid },
/* 7B */ { 0, &Ia_Invalid },
/* 7C */ { 0, &Ia_Invalid },
/* 7D */ { 0, &Ia_Invalid },
/* 7E */ { 0, &Ia_Invalid },
/* 7F */ { 0, &Ia_Invalid },
/* 80 */ { 0, &Ia_frczps_Vps_Wps },
/* 81 */ { 0, &Ia_frczpd_Vpd_Wpd },
/* 82 */ { 0, &Ia_frczss_Vss_Wss },
/* 83 */ { 0, &Ia_frczsd_Vsd_Wsd },
/* 84 */ { 0, &Ia_Invalid },
/* 85 */ { 0, &Ia_Invalid },
/* 86 */ { 0, &Ia_Invalid },
/* 87 */ { 0, &Ia_Invalid },
/* 88 */ { GRPVEXW(xop9_88) },
/* 89 */ { GRPVEXW(xop9_89) },
/* 8A */ { GRPVEXW(xop9_8a) },
/* 8B */ { GRPVEXW(xop9_8b) },
/* 8C */ { 0, &Ia_Invalid },
/* 8D */ { 0, &Ia_Invalid },
/* 8E */ { 0, &Ia_Invalid },
/* 8F */ { 0, &Ia_Invalid },
/* 90 */ { GRPVEXW(xop9_90) },
/* 91 */ { GRPVEXW(xop9_91) },
/* 92 */ { GRPVEXW(xop9_92) },
/* 93 */ { GRPVEXW(xop9_93) },
/* 94 */ { GRPVEXW(xop9_94) },
/* 95 */ { GRPVEXW(xop9_95) },
/* 96 */ { GRPVEXW(xop9_96) },
/* 97 */ { GRPVEXW(xop9_97) },
/* 98 */ { 0, &Ia_Invalid },
/* 99 */ { 0, &Ia_Invalid },
/* 9A */ { 0, &Ia_Invalid },
/* 9B */ { 0, &Ia_Invalid },
/* 9C */ { 0, &Ia_Invalid },
/* 9D */ { 0, &Ia_Invalid },
/* 9E */ { 0, &Ia_Invalid },
/* 9F */ { 0, &Ia_Invalid },
/* A0 */ { 0, &Ia_Invalid },
/* A1 */ { 0, &Ia_Invalid },
/* A2 */ { 0, &Ia_Invalid },
/* A3 */ { 0, &Ia_Invalid },
/* A4 */ { 0, &Ia_Invalid },
/* A5 */ { 0, &Ia_Invalid },
/* A6 */ { 0, &Ia_Invalid },
/* A7 */ { 0, &Ia_Invalid },
/* A8 */ { 0, &Ia_Invalid },
/* A9 */ { 0, &Ia_Invalid },
/* AA */ { 0, &Ia_Invalid },
/* AB */ { 0, &Ia_Invalid },
/* AC */ { 0, &Ia_Invalid },
/* AD */ { 0, &Ia_Invalid },
/* AE */ { 0, &Ia_Invalid },
/* AF */ { 0, &Ia_Invalid },
/* B0 */ { 0, &Ia_Invalid },
/* B1 */ { 0, &Ia_Invalid },
/* B2 */ { 0, &Ia_Invalid },
/* B3 */ { 0, &Ia_Invalid },
/* B4 */ { 0, &Ia_Invalid },
/* B5 */ { 0, &Ia_Invalid },
/* B6 */ { 0, &Ia_Invalid },
/* B7 */ { 0, &Ia_Invalid },
/* B8 */ { 0, &Ia_Invalid },
/* B9 */ { 0, &Ia_Invalid },
/* BA */ { 0, &Ia_Invalid },
/* BB */ { 0, &Ia_Invalid },
/* BC */ { 0, &Ia_Invalid },
/* BD */ { 0, &Ia_Invalid },
/* BE */ { 0, &Ia_Invalid },
/* BF */ { 0, &Ia_Invalid },
/* C0 */ { 0, &Ia_Invalid },
/* C1 */ { 0, &Ia_vphaddbw_Vdq_Wdq },
/* C2 */ { 0, &Ia_vphaddbd_Vdq_Wdq },
/* C3 */ { 0, &Ia_vphaddbq_Vdq_Wdq },
/* C4 */ { 0, &Ia_Invalid },
/* C5 */ { 0, &Ia_Invalid },
/* C6 */ { 0, &Ia_vphaddwd_Vdq_Wdq },
/* C7 */ { 0, &Ia_vphaddwq_Vdq_Wdq },
/* C8 */ { 0, &Ia_Invalid },
/* C9 */ { 0, &Ia_Invalid },
/* CA */ { 0, &Ia_Invalid },
/* CB */ { 0, &Ia_vphadddq_Vdq_Wdq },
/* CC */ { 0, &Ia_Invalid },
/* CD */ { 0, &Ia_Invalid },
/* CE */ { 0, &Ia_Invalid },
/* CF */ { 0, &Ia_Invalid },
/* D0 */ { 0, &Ia_Invalid },
/* D1 */ { 0, &Ia_vphaddubw_Vdq_Wdq },
/* D2 */ { 0, &Ia_vphaddubd_Vdq_Wdq },
/* D3 */ { 0, &Ia_vphaddubq_Vdq_Wdq },
/* D4 */ { 0, &Ia_Invalid },
/* D5 */ { 0, &Ia_Invalid },
/* D6 */ { 0, &Ia_vphadduwd_Vdq_Wdq },
/* D7 */ { 0, &Ia_vphadduwq_Vdq_Wdq },
/* D8 */ { 0, &Ia_Invalid },
/* D9 */ { 0, &Ia_Invalid },
/* DA */ { 0, &Ia_Invalid },
/* DB */ { 0, &Ia_vphaddudq_Vdq_Wdq },
/* DC */ { 0, &Ia_Invalid },
/* DD */ { 0, &Ia_Invalid },
/* DE */ { 0, &Ia_Invalid },
/* DF */ { 0, &Ia_Invalid },
/* E0 */ { 0, &Ia_Invalid },
/* E1 */ { 0, &Ia_vphsubbw_Vdq_Wdq },
/* E2 */ { 0, &Ia_vphsubwd_Vdq_Wdq },
/* E3 */ { 0, &Ia_vphsubdq_Vdq_Wdq },
/* E4 */ { 0, &Ia_Invalid },
/* E5 */ { 0, &Ia_Invalid },
/* E6 */ { 0, &Ia_Invalid },
/* E7 */ { 0, &Ia_Invalid },
/* E8 */ { 0, &Ia_Invalid },
/* E9 */ { 0, &Ia_Invalid },
/* EA */ { 0, &Ia_Invalid },
/* EB */ { 0, &Ia_Invalid },
/* EC */ { 0, &Ia_Invalid },
/* ED */ { 0, &Ia_Invalid },
/* EE */ { 0, &Ia_Invalid },
/* EF */ { 0, &Ia_Invalid },
/* F0 */ { 0, &Ia_Invalid },
/* F1 */ { 0, &Ia_Invalid },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid },
/* F4 */ { 0, &Ia_Invalid },
/* F5 */ { 0, &Ia_Invalid },
/* F6 */ { 0, &Ia_Invalid },
/* F7 */ { 0, &Ia_Invalid },
/* F8 */ { 0, &Ia_Invalid },
/* F9 */ { 0, &Ia_Invalid },
/* FA */ { 0, &Ia_Invalid },
/* FB */ { 0, &Ia_Invalid },
/* FC */ { 0, &Ia_Invalid },
/* FD */ { 0, &Ia_Invalid },
/* FE */ { 0, &Ia_Invalid },
/* FF */ { 0, &Ia_Invalid },
// 256 entries for XOP map 0xA opcodes
/* 00 */ { 0, &Ia_Invalid },
/* 01 */ { 0, &Ia_Invalid },
/* 02 */ { 0, &Ia_Invalid },
/* 03 */ { 0, &Ia_Invalid },
/* 04 */ { 0, &Ia_Invalid },
/* 05 */ { 0, &Ia_Invalid },
/* 06 */ { 0, &Ia_Invalid },
/* 07 */ { 0, &Ia_Invalid },
/* 08 */ { 0, &Ia_Invalid },
/* 09 */ { 0, &Ia_Invalid },
/* 0A */ { 0, &Ia_Invalid },
/* 0B */ { 0, &Ia_Invalid },
/* 0C */ { 0, &Ia_Invalid },
/* 0D */ { 0, &Ia_Invalid },
/* 0E */ { 0, &Ia_Invalid },
/* 0F */ { 0, &Ia_Invalid },
/* 10 */ { 0, &Ia_bextr_Gy_Ey_Id },
/* 11 */ { 0, &Ia_Invalid },
/* 12 */ { 0, &Ia_Invalid },
/* 13 */ { 0, &Ia_Invalid },
/* 14 */ { 0, &Ia_Invalid },
/* 15 */ { 0, &Ia_Invalid },
/* 16 */ { 0, &Ia_Invalid },
/* 17 */ { 0, &Ia_Invalid },
/* 18 */ { 0, &Ia_Invalid },
/* 19 */ { 0, &Ia_Invalid },
/* 1A */ { 0, &Ia_Invalid },
/* 1B */ { 0, &Ia_Invalid },
/* 1C */ { 0, &Ia_Invalid },
/* 1D */ { 0, &Ia_Invalid },
/* 1E */ { 0, &Ia_Invalid },
/* 1F */ { 0, &Ia_Invalid },
/* 20 */ { 0, &Ia_Invalid },
/* 21 */ { 0, &Ia_Invalid },
/* 22 */ { 0, &Ia_Invalid },
/* 23 */ { 0, &Ia_Invalid },
/* 24 */ { 0, &Ia_Invalid },
/* 25 */ { 0, &Ia_Invalid },
/* 26 */ { 0, &Ia_Invalid },
/* 27 */ { 0, &Ia_Invalid },
/* 28 */ { 0, &Ia_Invalid },
/* 29 */ { 0, &Ia_Invalid },
/* 2A */ { 0, &Ia_Invalid },
/* 2B */ { 0, &Ia_Invalid },
/* 2C */ { 0, &Ia_Invalid },
/* 2D */ { 0, &Ia_Invalid },
/* 2E */ { 0, &Ia_Invalid },
/* 2F */ { 0, &Ia_Invalid },
/* 30 */ { 0, &Ia_Invalid },
/* 31 */ { 0, &Ia_Invalid },
/* 32 */ { 0, &Ia_Invalid },
/* 33 */ { 0, &Ia_Invalid },
/* 34 */ { 0, &Ia_Invalid },
/* 35 */ { 0, &Ia_Invalid },
/* 36 */ { 0, &Ia_Invalid },
/* 37 */ { 0, &Ia_Invalid },
/* 38 */ { 0, &Ia_Invalid },
/* 39 */ { 0, &Ia_Invalid },
/* 3A */ { 0, &Ia_Invalid },
/* 3B */ { 0, &Ia_Invalid },
/* 3C */ { 0, &Ia_Invalid },
/* 3D */ { 0, &Ia_Invalid },
/* 3E */ { 0, &Ia_Invalid },
/* 3F */ { 0, &Ia_Invalid },
/* 40 */ { 0, &Ia_Invalid },
/* 41 */ { 0, &Ia_Invalid },
/* 42 */ { 0, &Ia_Invalid },
/* 43 */ { 0, &Ia_Invalid },
/* 44 */ { 0, &Ia_Invalid },
/* 45 */ { 0, &Ia_Invalid },
/* 46 */ { 0, &Ia_Invalid },
/* 47 */ { 0, &Ia_Invalid },
/* 48 */ { 0, &Ia_Invalid },
/* 49 */ { 0, &Ia_Invalid },
/* 4A */ { 0, &Ia_Invalid },
/* 4B */ { 0, &Ia_Invalid },
/* 4C */ { 0, &Ia_Invalid },
/* 4D */ { 0, &Ia_Invalid },
/* 4E */ { 0, &Ia_Invalid },
/* 4F */ { 0, &Ia_Invalid },
/* 50 */ { 0, &Ia_Invalid },
/* 51 */ { 0, &Ia_Invalid },
/* 52 */ { 0, &Ia_Invalid },
/* 53 */ { 0, &Ia_Invalid },
/* 54 */ { 0, &Ia_Invalid },
/* 55 */ { 0, &Ia_Invalid },
/* 56 */ { 0, &Ia_Invalid },
/* 57 */ { 0, &Ia_Invalid },
/* 58 */ { 0, &Ia_Invalid },
/* 59 */ { 0, &Ia_Invalid },
/* 5A */ { 0, &Ia_Invalid },
/* 5B */ { 0, &Ia_Invalid },
/* 5C */ { 0, &Ia_Invalid },
/* 5D */ { 0, &Ia_Invalid },
/* 5E */ { 0, &Ia_Invalid },
/* 5F */ { 0, &Ia_Invalid },
/* 60 */ { 0, &Ia_Invalid },
/* 61 */ { 0, &Ia_Invalid },
/* 62 */ { 0, &Ia_Invalid },
/* 63 */ { 0, &Ia_Invalid },
/* 64 */ { 0, &Ia_Invalid },
/* 65 */ { 0, &Ia_Invalid },
/* 66 */ { 0, &Ia_Invalid },
/* 67 */ { 0, &Ia_Invalid },
/* 68 */ { 0, &Ia_Invalid },
/* 69 */ { 0, &Ia_Invalid },
/* 6A */ { 0, &Ia_Invalid },
/* 6B */ { 0, &Ia_Invalid },
/* 6C */ { 0, &Ia_Invalid },
/* 6D */ { 0, &Ia_Invalid },
/* 6E */ { 0, &Ia_Invalid },
/* 6F */ { 0, &Ia_Invalid },
/* 70 */ { 0, &Ia_Invalid },
/* 71 */ { 0, &Ia_Invalid },
/* 72 */ { 0, &Ia_Invalid },
/* 73 */ { 0, &Ia_Invalid },
/* 74 */ { 0, &Ia_Invalid },
/* 75 */ { 0, &Ia_Invalid },
/* 76 */ { 0, &Ia_Invalid },
/* 77 */ { 0, &Ia_Invalid },
/* 78 */ { 0, &Ia_Invalid },
/* 79 */ { 0, &Ia_Invalid },
/* 7A */ { 0, &Ia_Invalid },
/* 7B */ { 0, &Ia_Invalid },
/* 7C */ { 0, &Ia_Invalid },
/* 7D */ { 0, &Ia_Invalid },
/* 7E */ { 0, &Ia_Invalid },
/* 7F */ { 0, &Ia_Invalid },
/* 80 */ { 0, &Ia_Invalid },
/* 81 */ { 0, &Ia_Invalid },
/* 82 */ { 0, &Ia_Invalid },
/* 83 */ { 0, &Ia_Invalid },
/* 84 */ { 0, &Ia_Invalid },
/* 85 */ { 0, &Ia_Invalid },
/* 86 */ { 0, &Ia_Invalid },
/* 87 */ { 0, &Ia_Invalid },
/* 88 */ { 0, &Ia_Invalid },
/* 89 */ { 0, &Ia_Invalid },
/* 8A */ { 0, &Ia_Invalid },
/* 8B */ { 0, &Ia_Invalid },
/* 8C */ { 0, &Ia_Invalid },
/* 8D */ { 0, &Ia_Invalid },
/* 8E */ { 0, &Ia_Invalid },
/* 8F */ { 0, &Ia_Invalid },
/* 90 */ { 0, &Ia_Invalid },
/* 91 */ { 0, &Ia_Invalid },
/* 92 */ { 0, &Ia_Invalid },
/* 93 */ { 0, &Ia_Invalid },
/* 94 */ { 0, &Ia_Invalid },
/* 95 */ { 0, &Ia_Invalid },
/* 96 */ { 0, &Ia_Invalid },
/* 97 */ { 0, &Ia_Invalid },
/* 98 */ { 0, &Ia_Invalid },
/* 99 */ { 0, &Ia_Invalid },
/* 9A */ { 0, &Ia_Invalid },
/* 9B */ { 0, &Ia_Invalid },
/* 9C */ { 0, &Ia_Invalid },
/* 9D */ { 0, &Ia_Invalid },
/* 9E */ { 0, &Ia_Invalid },
/* 9F */ { 0, &Ia_Invalid },
/* A0 */ { 0, &Ia_Invalid },
/* A1 */ { 0, &Ia_Invalid },
/* A2 */ { 0, &Ia_Invalid },
/* A3 */ { 0, &Ia_Invalid },
/* A4 */ { 0, &Ia_Invalid },
/* A5 */ { 0, &Ia_Invalid },
/* A6 */ { 0, &Ia_Invalid },
/* A7 */ { 0, &Ia_Invalid },
/* A8 */ { 0, &Ia_Invalid },
/* A9 */ { 0, &Ia_Invalid },
/* AA */ { 0, &Ia_Invalid },
/* AB */ { 0, &Ia_Invalid },
/* AC */ { 0, &Ia_Invalid },
/* AD */ { 0, &Ia_Invalid },
/* AE */ { 0, &Ia_Invalid },
/* AF */ { 0, &Ia_Invalid },
/* B0 */ { 0, &Ia_Invalid },
/* B1 */ { 0, &Ia_Invalid },
/* B2 */ { 0, &Ia_Invalid },
/* B3 */ { 0, &Ia_Invalid },
/* B4 */ { 0, &Ia_Invalid },
/* B5 */ { 0, &Ia_Invalid },
/* B6 */ { 0, &Ia_Invalid },
/* B7 */ { 0, &Ia_Invalid },
/* B8 */ { 0, &Ia_Invalid },
/* B9 */ { 0, &Ia_Invalid },
/* BA */ { 0, &Ia_Invalid },
/* BB */ { 0, &Ia_Invalid },
/* BC */ { 0, &Ia_Invalid },
/* BD */ { 0, &Ia_Invalid },
/* BE */ { 0, &Ia_Invalid },
/* BF */ { 0, &Ia_Invalid },
/* C0 */ { 0, &Ia_Invalid },
/* C1 */ { 0, &Ia_Invalid },
/* C2 */ { 0, &Ia_Invalid },
/* C3 */ { 0, &Ia_Invalid },
/* C4 */ { 0, &Ia_Invalid },
/* C5 */ { 0, &Ia_Invalid },
/* C6 */ { 0, &Ia_Invalid },
/* C7 */ { 0, &Ia_Invalid },
/* C8 */ { 0, &Ia_Invalid },
/* C9 */ { 0, &Ia_Invalid },
/* CA */ { 0, &Ia_Invalid },
/* CB */ { 0, &Ia_Invalid },
/* CC */ { 0, &Ia_Invalid },
/* CD */ { 0, &Ia_Invalid },
/* CE */ { 0, &Ia_Invalid },
/* CF */ { 0, &Ia_Invalid },
/* D0 */ { 0, &Ia_Invalid },
/* D1 */ { 0, &Ia_Invalid },
/* D2 */ { 0, &Ia_Invalid },
/* D3 */ { 0, &Ia_Invalid },
/* D4 */ { 0, &Ia_Invalid },
/* D5 */ { 0, &Ia_Invalid },
/* D6 */ { 0, &Ia_Invalid },
/* D7 */ { 0, &Ia_Invalid },
/* D8 */ { 0, &Ia_Invalid },
/* D9 */ { 0, &Ia_Invalid },
/* DA */ { 0, &Ia_Invalid },
/* DB */ { 0, &Ia_Invalid },
/* DC */ { 0, &Ia_Invalid },
/* DD */ { 0, &Ia_Invalid },
/* DE */ { 0, &Ia_Invalid },
/* DF */ { 0, &Ia_Invalid },
/* E0 */ { 0, &Ia_Invalid },
/* E1 */ { 0, &Ia_Invalid },
/* E2 */ { 0, &Ia_Invalid },
/* E3 */ { 0, &Ia_Invalid },
/* E4 */ { 0, &Ia_Invalid },
/* E5 */ { 0, &Ia_Invalid },
/* E6 */ { 0, &Ia_Invalid },
/* E7 */ { 0, &Ia_Invalid },
/* E8 */ { 0, &Ia_Invalid },
/* E9 */ { 0, &Ia_Invalid },
/* EA */ { 0, &Ia_Invalid },
/* EB */ { 0, &Ia_Invalid },
/* EC */ { 0, &Ia_Invalid },
/* ED */ { 0, &Ia_Invalid },
/* EE */ { 0, &Ia_Invalid },
/* EF */ { 0, &Ia_Invalid },
/* F0 */ { 0, &Ia_Invalid },
/* F1 */ { 0, &Ia_Invalid },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid },
/* F4 */ { 0, &Ia_Invalid },
/* F5 */ { 0, &Ia_Invalid },
/* F6 */ { 0, &Ia_Invalid },
/* F7 */ { 0, &Ia_Invalid },
/* F8 */ { 0, &Ia_Invalid },
/* F9 */ { 0, &Ia_Invalid },
/* FA */ { 0, &Ia_Invalid },
/* FB */ { 0, &Ia_Invalid },
/* FC */ { 0, &Ia_Invalid },
/* FD */ { 0, &Ia_Invalid },
/* FE */ { 0, &Ia_Invalid },
/* FF */ { 0, &Ia_Invalid }
};

View File

@ -1,3 +1,26 @@
/////////////////////////////////////////////////////////////////////////
// $Id: disasm.h 12420 2014-07-18 11:14:25Z sshwarts $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2005-2014 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
/////////////////////////////////////////////////////////////////////////
#ifndef _BX_DISASM_H_
#define _BX_DISASM_H_
@ -15,23 +38,61 @@
base = sib_byte & 0x07; \
}
// will be used in future
#define IA_286 0x00000001 /* 286+ instruction */
#define IA_386 0x00000002 /* 386+ instruction */
#define IA_486 0x00000004 /* 486+ instruction */
#define IA_PENTIUM 0x00000008 /* Pentium+ instruction */
#define IA_P6 0x00000010 /* P6 new instruction */
#define IA_SYSTEM 0x00000020 /* system instruction (require CPL=0) */
#define IA_LEGACY 0x00000040 /* legacy instruction */
#define IA_X87 0x00000080 /* FPU (X87) instruction */
#define IA_MMX 0x00000100 /* MMX instruction */
#define IA_3DNOW 0x00000200 /* 3DNow! instruction */
#define IA_PREFETCH 0x00000400 /* Prefetch instruction */
#define IA_SSE 0x00000800 /* SSE instruction */
#define IA_SSE2 0x00001000 /* SSE2 instruction */
#define IA_SSE3 0x00002000 /* SSE3 instruction */
#define IA_SSE4 0x00004000 /* SSE4 instruction */
#define IA_X86_64 0x00008000 /* x86-64 instruction */
/* Instruction set attributes (duplicated in cpu.h) */
#define IA_X87 (BX_CONST64(1) << 0) /* FPU (X87) instruction */
#define IA_486 (BX_CONST64(1) << 1) /* 486 new instruction */
#define IA_PENTIUM (BX_CONST64(1) << 2) /* Pentium new instruction */
#define IA_P6 (BX_CONST64(1) << 3) /* P6 new instruction */
#define IA_MMX (BX_CONST64(1) << 4) /* MMX instruction */
#define IA_3DNOW (BX_CONST64(1) << 5) /* 3DNow! instruction (AMD) */
#define IA_SYSCALL_SYSRET (BX_CONST64(1) << 6) /* SYSCALL/SYSRET in legacy mode (AMD) */
#define IA_SYSENTER_SYSEXIT (BX_CONST64(1) << 7) /* SYSENTER/SYSEXIT instruction */
#define IA_CLFLUSH (BX_CONST64(1) << 8) /* CLFLUSH instruction */
#define IA_SSE (BX_CONST64(1) << 9) /* SSE instruction */
#define IA_SSE2 (BX_CONST64(1) << 10) /* SSE2 instruction */
#define IA_SSE3 (BX_CONST64(1) << 11) /* SSE3 instruction */
#define IA_SSSE3 (BX_CONST64(1) << 12) /* SSSE3 instruction */
#define IA_SSE4_1 (BX_CONST64(1) << 13) /* SSE4_1 instruction */
#define IA_SSE4_2 (BX_CONST64(1) << 14) /* SSE4_2 instruction */
#define IA_POPCNT (BX_CONST64(1) << 15) /* POPCNT instruction */
#define IA_MONITOR_MWAIT (BX_CONST64(1) << 16) /* MONITOR/MWAIT instruction */
#define IA_VMX (BX_CONST64(1) << 17) /* VMX instruction */
#define IA_SMX (BX_CONST64(1) << 18) /* SMX instruction */
#define IA_LM_LAHF_SAHF (BX_CONST64(1) << 19) /* Long Mode LAHF/SAHF instruction */
#define IA_CMPXCHG16B (BX_CONST64(1) << 20) /* CMPXCHG16B instruction */
#define IA_RDTSCP (BX_CONST64(1) << 21) /* RDTSCP instruction */
#define IA_XSAVE (BX_CONST64(1) << 22) /* XSAVE/XRSTOR extensions instruction */
#define IA_XSAVEOPT (BX_CONST64(1) << 23) /* XSAVEOPT instruction */
#define IA_AES_PCLMULQDQ (BX_CONST64(1) << 24) /* AES+PCLMULQDQ instruction */
#define IA_MOVBE (BX_CONST64(1) << 25) /* MOVBE Intel Atom(R) instruction */
#define IA_FSGSBASE (BX_CONST64(1) << 26) /* FS/GS BASE access instruction */
#define IA_INVPCID (BX_CONST64(1) << 27) /* INVPCID instruction */
#define IA_AVX (BX_CONST64(1) << 28) /* AVX instruction */
#define IA_AVX2 (BX_CONST64(1) << 29) /* AVX2 instruction */
#define IA_AVX_F16C (BX_CONST64(1) << 30) /* AVX F16 convert instruction */
#define IA_AVX_FMA (BX_CONST64(1) << 31) /* AVX FMA instruction */
#define IA_SSE4A (BX_CONST64(1) << 32) /* SSE4A instruction (AMD) */
#define IA_LZCNT (BX_CONST64(1) << 33) /* LZCNT instruction */
#define IA_BMI1 (BX_CONST64(1) << 34) /* BMI1 instruction */
#define IA_BMI2 (BX_CONST64(1) << 35) /* BMI2 instruction */
#define IA_FMA4 (BX_CONST64(1) << 36) /* FMA4 instruction (AMD) */
#define IA_XOP (BX_CONST64(1) << 37) /* XOP instruction (AMD) */
#define IA_TBM (BX_CONST64(1) << 38) /* TBM instruction (AMD) */
#define IA_SVM (BX_CONST64(1) << 39) /* SVM instruction (AMD) */
#define IA_RDRAND (BX_CONST64(1) << 40) /* RDRAND instruction */
#define IA_ADX (BX_CONST64(1) << 41) /* ADCX/ADOX instruction */
#define IA_SMAP (BX_CONST64(1) << 42) /* SMAP support */
#define IA_RDSEED (BX_CONST64(1) << 43) /* RDSEED instruction */
#define IA_SHA (BX_CONST64(1) << 44) /* SHA instruction */
#define IA_AVX512 (BX_CONST64(1) << 45) /* AVX-512 instruction */
#define IA_AVX512_CD (BX_CONST64(1) << 46) /* AVX-512 Conflict Detection instruction */
#define IA_AVX512_PF (BX_CONST64(1) << 47) /* AVX-512 Sparse Prefetch instruction */
#define IA_AVX512_ER (BX_CONST64(1) << 48) /* AVX-512 Exponential/Reciprocal instruction */
#define IA_AVX512_DQ (BX_CONST64(1) << 49) /* AVX-512DQ instruction */
#define IA_AVX512_BW (BX_CONST64(1) << 50) /* AVX-512 Byte/Word instruction */
#define IA_CLFLUSHOPT (BX_CONST64(1) << 51) /* CLFLUSHOPT instruction */
#define IA_XSAVEC (BX_CONST64(1) << 52) /* XSAVEC instruction */
#define IA_XSAVES (BX_CONST64(1) << 53) /* XSAVES instruction */
/* general purpose bit register */
enum {
@ -70,6 +131,8 @@ struct BxDisasmOpcodeInfo_t
BxDisasmPtr_t Operand1;
BxDisasmPtr_t Operand2;
BxDisasmPtr_t Operand3;
BxDisasmPtr_t Operand4;
Bit64u Feature;
};
struct BxDisasmOpcodeTable_t
@ -82,26 +145,27 @@ struct BxDisasmOpcodeTable_t
#define NO_SEG_OVERRIDE 0xFF
// datasize attributes
#define X_SIZE 0x0000
#define B_SIZE 0x0100
#define W_SIZE 0x0200
#define D_SIZE 0x0300
#define Q_SIZE 0x0400
#define Z_SIZE 0x0500
#define V_SIZE 0x0600
#define O_SIZE 0x0700
#define T_SIZE 0x0800
#define P_SIZE 0x0900
#define X_SIZE 0x00 /* no size */
#define B_SIZE 0x01 /* byte */
#define W_SIZE 0x02 /* word */
#define D_SIZE 0x03 /* double word */
#define Q_SIZE 0x04 /* quad word */
#define Z_SIZE 0x05 /* double word in 32-bit mode, quad word in 64-bit mode */
#define T_SIZE 0x06 /* 10-byte x87 floating point */
#define XMM_SIZE 0x07 /* double quad word (XMM) */
#define YMM_SIZE 0x08 /* quadruple quad word (YMM) */
#define VSIB_Index 0x80
// branch hint attribute
#define BRANCH_HINT 0x1000
struct x86_insn
struct x86_insn
{
public:
x86_insn(bx_bool is32, bx_bool is64);
bx_bool is_seg_override() const {
bx_bool is_seg_override() const {
return (seg_override != NO_SEG_OVERRIDE);
}
@ -113,15 +177,25 @@ public:
Bit8u extend8b;
Bit8u rex_r, rex_x, rex_b;
Bit8u seg_override;
unsigned b1, prefixes;
unsigned b1;
unsigned ilen;
#define BX_AVX_VL128 0
#define BX_AVX_VL256 1
Bit8u vex_vvv, vex_l, vex_w;
int is_vex; // 0 - no VEX used, 1 - VEX is used, -1 - invalid VEX
int is_evex; // 0 - no EVEX used, 1 - EVEX is used, -1 - invalid EVEX
int is_xop; // 0 - no XOP used, 1 - XOP is used, -1 - invalid XOP
Bit8u modrm, mod, nnn, rm;
Bit8u sib, scale, index, base;
union {
Bit16u displ16;
Bit32u displ32;
} displacement;
bx_bool evex_b;
bx_bool evex_z;
unsigned evex_ll_rc;
};
BX_CPP_INLINE x86_insn::x86_insn(bx_bool is32, bx_bool is64)
@ -145,48 +219,60 @@ BX_CPP_INLINE x86_insn::x86_insn(bx_bool is32, bx_bool is64)
extend8b = 0;
rex_r = rex_b = rex_x = 0;
seg_override = NO_SEG_OVERRIDE;
prefixes = 0;
ilen = 0;
b1 = 0;
is_vex = 0;
is_evex = 0;
is_xop = 0;
vex_vvv = 0;
vex_l = BX_AVX_VL128;
vex_w = 0;
modrm = mod = nnn = rm = 0;
sib = scale = index = base = 0;
displacement.displ32 = 0;
evex_b = 0;
evex_ll_rc = 0;
evex_z = 0;
}
class disassembler {
public:
disassembler() { set_syntax_intel(); }
disassembler(): offset_mode_hex(0), print_mem_datasize(1) { set_syntax_intel(); }
unsigned disasm(bx_bool is_32, bx_bool is_64, bx_address base, bx_address ip, const Bit8u *instr, char *disbuf);
unsigned disasm(bx_bool is_32, bx_bool is_64, bx_address cs_base, bx_address ip, const Bit8u *instr, char *disbuf);
unsigned disasm16(bx_address base, bx_address ip, const Bit8u *instr, char *disbuf)
{ return disasm(0, 0, base, ip, instr, disbuf); }
unsigned disasm16(bx_address cs_base, bx_address ip, const Bit8u *instr, char *disbuf)
{ return disasm(0, 0, cs_base, ip, instr, disbuf); }
unsigned disasm32(bx_address base, bx_address ip, const Bit8u *instr, char *disbuf)
{ return disasm(1, 0, base, ip, instr, disbuf); }
unsigned disasm32(bx_address cs_base, bx_address ip, const Bit8u *instr, char *disbuf)
{ return disasm(1, 0, cs_base, ip, instr, disbuf); }
unsigned disasm64(bx_address base, bx_address ip, const Bit8u *instr, char *disbuf)
{ return disasm(1, 1, base, ip, instr, disbuf); }
unsigned disasm64(bx_address cs_base, bx_address ip, const Bit8u *instr, char *disbuf)
{ return disasm(1, 1, cs_base, ip, instr, disbuf); }
x86_insn decode(bx_bool is_32, bx_bool is_64, bx_address base, bx_address ip, const Bit8u *instr, char *disbuf);
x86_insn decode(bx_bool is_32, bx_bool is_64, bx_address cs_base, bx_address ip, const Bit8u *instr, char *disbuf);
x86_insn decode16(bx_address base, bx_address ip, const Bit8u *instr, char *disbuf)
{ return decode(0, 0, base, ip, instr, disbuf); }
x86_insn decode16(bx_address cs_base, bx_address ip, const Bit8u *instr, char *disbuf)
{ return decode(0, 0, cs_base, ip, instr, disbuf); }
x86_insn decode32(bx_address base, bx_address ip, const Bit8u *instr, char *disbuf)
{ return decode(1, 0, base, ip, instr, disbuf); }
x86_insn decode32(bx_address cs_base, bx_address ip, const Bit8u *instr, char *disbuf)
{ return decode(1, 0, cs_base, ip, instr, disbuf); }
x86_insn decode64(bx_address base, bx_address ip, const Bit8u *instr, char *disbuf)
{ return decode(1, 1, base, ip, instr, disbuf); }
x86_insn decode64(bx_address cs_base, bx_address ip, const Bit8u *instr, char *disbuf)
{ return decode(1, 1, cs_base, ip, instr, disbuf); }
void set_syntax_intel();
void set_syntax_att ();
void set_syntax_att();
void set_offset_mode_hex(bx_bool mode) { offset_mode_hex = mode; }
void set_mem_datasize_print(bx_bool mode) { print_mem_datasize = mode; }
void toggle_syntax_mode();
private:
bx_bool intel_mode;
bx_bool intel_mode, offset_mode_hex, print_mem_datasize;
const char **general_16bit_regname;
const char **general_8bit_regname;
@ -196,16 +282,16 @@ private:
const char **segment_name;
const char **index16;
const char **vector_reg_name;
const char *sreg_mod01or10_rm32[8];
const char *sreg_mod00_base32[8];
const char *sreg_mod01or10_base32[8];
const char *sreg_mod00_base32[16];
const char *sreg_mod01or10_base32[16];
const char *sreg_mod00_rm16[8];
const char *sreg_mod01or10_rm16[8];
private:
bx_address db_eip, db_base;
bx_address db_eip, db_cs_base;
const Bit8u *instruction; // for fetching of next byte of instruction
@ -250,6 +336,9 @@ private:
void dis_putc(char symbol);
void dis_sprintf(const char *fmt, ...);
void decode_modrm(x86_insn *insn);
unsigned decode_vex(x86_insn *insn);
unsigned decode_evex(x86_insn *insn);
unsigned decode_xop(x86_insn *insn);
void resolve16_mod0 (const x86_insn *insn, unsigned mode);
void resolve16_mod1or2(const x86_insn *insn, unsigned mode);
@ -268,85 +357,88 @@ private:
void initialize_modrm_segregs();
void print_datasize (unsigned mode);
void print_datasize(unsigned mode);
void print_memory_access16(int datasize,
const char *seg, const char *index, Bit16u disp);
void print_memory_access (int datasize,
const char *seg, const char *base, const char *index, int scale, Bit32u disp);
void print_memory_access32(int datasize,
const char *seg, const char *base, const char *index, int scale, Bit32s disp);
void print_memory_access64(int datasize,
const char *seg, const char *base, const char *index, int scale, Bit32s disp);
void print_disassembly_intel(const x86_insn *insn, const BxDisasmOpcodeInfo_t *entry);
void print_disassembly_att (const x86_insn *insn, const BxDisasmOpcodeInfo_t *entry);
public:
/*
/*
* Codes for Addressing Method:
* ---------------------------
* A - Direct address. The instruction has no ModR/M byte; the address
* of the operand is encoded in the instruction; and no base register,
* A - Direct address. The instruction has no ModR/M byte; the address
* of the operand is encoded in the instruction; and no base register,
* index register, or scaling factor can be applied.
* C - The reg field of the ModR/M byte selects a control register.
* D - The reg field of the ModR/M byte selects a debug register.
* E - A ModR/M byte follows the opcode and specifies the operand. The
* operand is either a general-purpose register or a memory address.
* If it is a memory address, the address is computed from a segment
* register and any of the following values: a base register, an
* index register, a scaling factor, a displacement.
* E - A ModR/M byte follows the opcode and specifies the operand. The
* operand is either a general-purpose register or a memory address.
* In case of the register operand, the R/M field of the ModR/M byte
* selects a general register.
* F - Flags Register.
* G - The reg field of the ModR/M byte selects a general register.
* I - Immediate data. The operand value is encoded in subsequent bytes of
* I - Immediate data. The operand value is encoded in subsequent bytes of
* the instruction.
* J - The instruction contains a relative offset to be added to the
* J - The instruction contains a relative offset to be added to the
* instruction pointer register.
* M - The ModR/M byte may refer only to memory.
* N - The R/M field of the ModR/M byte selects a packed-quadword MMX
* N - The R/M field of the ModR/M byte selects a packed-quadword MMX
technology register.
* O - The instruction has no ModR/M byte; the offset of the operand is
* coded as a word or double word (depending on address size attribute)
* in the instruction. No base register, index register, or scaling
* O - The instruction has no ModR/M byte; the offset of the operand is
* coded as a word or double word (depending on address size attribute)
* in the instruction. No base register, index register, or scaling
* factor can be applied.
* P - The reg field of the ModR/M byte selects a packed quadword MMX
* P - The reg field of the ModR/M byte selects a packed quadword MMX
* technology register.
* Q - A ModR/M byte follows the opcode and specifies the operand. The
* operand is either an MMX technology register or a memory address.
* If it is a memory address, the address is computed from a segment
* register and any of the following values: a base register, an
* Q - A ModR/M byte follows the opcode and specifies the operand. The
* operand is either an MMX technology register or a memory address.
* If it is a memory address, the address is computed from a segment
* register and any of the following values: a base register, an
* index register, a scaling factor, and a displacement.
* R - The mod field of the ModR/M byte may refer only to a general register.
* S - The reg field of the ModR/M byte selects a segment register.
* U - The R/M field of the ModR/M byte selects a 128-bit XMM register.
* T - The reg field of the ModR/M byte selects a test register.
* V - The reg field of the ModR/M byte selects a 128-bit XMM register.
* W - A ModR/M byte follows the opcode and specifies the operand. The
* operand is either a 128-bit XMM register or a memory address. If
* it is a memory address, the address is computed from a segment
* U - The R/M field of the ModR/M byte selects a 128-bit XMM/256-bit YMM register.
* V - The reg field of the ModR/M byte selects a 128-bit XMM/256-bit YMM register.
* W - A ModR/M byte follows the opcode and specifies the operand. The
* operand is either a 128-bit XMM/256-bit YMM register or a memory address.
* If it is a memory address, the address is computed from a segment
* register and any of the following values: a base register, an
* index register, a scaling factor, and a displacement.
* X - Memory addressed by the DS:rSI register pair.
* Y - Memory addressed by the ES:rDI register pair.
*/
*/
/*
/*
* Codes for Operand Type:
* ----------------------
* a - Two one-word operands in memory or two double-word operands in
* a - Two one-word operands in memory or two double-word operands in
* memory, depending on operand-size attribute (used only by the BOUND
* instruction).
* b - Byte, regardless of operand-size attribute.
* d - Doubleword, regardless of operand-size attribute.
* dq - Double-quadword, regardless of operand-size attribute.
* p - 32-bit or 48-bit pointer, depending on operand-size attribute.
* pd - 128-bit packed double-precision floating-point data.
* pd - 128-bit/256-bit packed double-precision floating-point data.
* pi - Quadword MMX technology register (packed integer)
* ps - 128-bit packed single-precision floating-point data.
* ps - 128-bit/256-bit packed single-precision floating-point data.
* q - Quadword, regardless of operand-size attribute.
* s - 6-byte or 10-byte pseudo-descriptor.
* si - Doubleword integer register (scalar integer)
* ss - Scalar element of a 128-bit packed single-precision floating data.
* sd - Scalar element of a 128-bit packed double-precision floating data.
* ss - Scalar element of a packed single-precision floating data.
* sd - Scalar element of a packed double-precision floating data.
* v - Word, doubleword or quadword, depending on operand-size attribute.
* w - Word, regardless of operand-size attr.
* y - Doubleword or quadword (in 64-bit mode) depending on 32/64 bit
* operand size.
*/
// far call/jmp
@ -354,18 +446,19 @@ public:
void Apd(const x86_insn *insn);
// 8-bit general purpose registers
void AL(const x86_insn *insn);
void CL(const x86_insn *insn);
void AL_Reg(const x86_insn *insn);
void CL_Reg(const x86_insn *insn);
// 16-bit general purpose registers
void AX(const x86_insn *insn);
void DX(const x86_insn *insn);
void AX_Reg(const x86_insn *insn);
void DX_Reg(const x86_insn *insn);
// 32-bit general purpose registers
void EAX(const x86_insn *insn);
void EAX_Reg(const x86_insn *insn);
// 64-bit general purpose registers
void RAX(const x86_insn *insn);
void RAX_Reg(const x86_insn *insn);
void RCX_Reg(const x86_insn *insn);
// segment registers
void CS(const x86_insn *insn);
@ -378,9 +471,6 @@ public:
// segment registers
void Sw(const x86_insn *insn);
// test registers
void Td(const x86_insn *insn);
// control register
void Cd(const x86_insn *insn);
void Cq(const x86_insn *insn);
@ -390,7 +480,7 @@ public:
void Dq(const x86_insn *insn);
// 8-bit general purpose register
void R8(const x86_insn *insn);
void Reg8(const x86_insn *insn);
// 16-bit general purpose register
void RX(const x86_insn *insn);
@ -406,12 +496,20 @@ public:
void Ew(const x86_insn *insn);
void Ed(const x86_insn *insn);
void Eq(const x86_insn *insn);
void Ey(const x86_insn *insn);
void Ebd(const x86_insn *insn);
void Ewd(const x86_insn *insn);
void Edq(const x86_insn *insn);
// general purpose register
void Gb(const x86_insn *insn);
void Gw(const x86_insn *insn);
void Gd(const x86_insn *insn);
void Gq(const x86_insn *insn);
void Gy(const x86_insn *insn);
// vex encoded general purpose register
void By(const x86_insn *insn);
// immediate
void I1(const x86_insn *insn);
@ -420,7 +518,8 @@ public:
void Id(const x86_insn *insn);
void Iq(const x86_insn *insn);
// two immediates Iw/Ib
// double immediate
void IbIb(const x86_insn *insn);
void IwIb(const x86_insn *insn);
// sign extended immediate
@ -437,6 +536,7 @@ public:
void Rw(const x86_insn *insn);
void Rd(const x86_insn *insn);
void Rq(const x86_insn *insn);
void Ry(const x86_insn *insn);
// mmx register
void Pq(const x86_insn *insn);
@ -447,22 +547,39 @@ public:
void Vq(const x86_insn *insn);
void Nq(const x86_insn *insn);
// xmm register
// xmm/ymm register
void Ups(const x86_insn *insn);
void Upd(const x86_insn *insn);
void Udq(const x86_insn *insn);
void Uq(const x86_insn *insn);
void Vdq(const x86_insn *insn);
void Vss(const x86_insn *insn);
void Vsd(const x86_insn *insn);
void Vps(const x86_insn *insn);
void Vpd(const x86_insn *insn);
// xmm/ymm register through imm byte
void VIb(const x86_insn *insn);
// xmm register or memory operand
// xmm/ymm register or memory operand
void Wb(const x86_insn *insn);
void Ww(const x86_insn *insn);
void Wd(const x86_insn *insn);
void Wq(const x86_insn *insn);
void Wdq(const x86_insn *insn);
void Wss(const x86_insn *insn);
void Wsd(const x86_insn *insn);
void Wps(const x86_insn *insn);
void Wpd(const x86_insn *insn);
// vex encoded xmm/ymm register
void Hdq(const x86_insn *insn);
void Hps(const x86_insn *insn);
void Hpd(const x86_insn *insn);
void Hss(const x86_insn *insn);
void Hsd(const x86_insn *insn);
// direct memory access
void OP_O(const x86_insn *insn, unsigned size);
void Ob(const x86_insn *insn);
@ -484,6 +601,11 @@ public:
void Mdq(const x86_insn *insn);
void Mps(const x86_insn *insn);
void Mpd(const x86_insn *insn);
void Mss(const x86_insn *insn);
void Msd(const x86_insn *insn);
// gather VSib
void VSib(const x86_insn *insn);
// string instructions
void OP_X(const x86_insn *insn, unsigned size);
@ -499,6 +621,11 @@ public:
void Yd(const x86_insn *insn);
void Yq(const x86_insn *insn);
// maskmovdq/maskmovdqu
void OP_sY(const x86_insn *insn, unsigned size);
void sYq(const x86_insn *insn);
void sYdq(const x86_insn *insn);
// jump offset
void Jb(const x86_insn *insn);
void Jw(const x86_insn *insn);

1903
Externals/Bochs_disasm/opcodes.inc vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

696
Externals/Bochs_disasm/resolve.cc vendored Normal file
View File

@ -0,0 +1,696 @@
/////////////////////////////////////////////////////////////////////////
// $Id: resolve.cc 11863 2013-10-07 19:23:19Z sshwarts $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2005-2013 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
/////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <assert.h>
#include "disasm.h"
void disassembler::decode_modrm(x86_insn *insn)
{
insn->modrm = fetch_byte();
BX_DECODE_MODRM(insn->modrm, insn->mod, insn->nnn, insn->rm);
// MOVs with CRx and DRx always use register ops and ignore the mod field.
if ((insn->b1 & ~3) == 0x120) insn->mod = 3;
insn->nnn |= insn->rex_r;
insn->rm |= insn->rex_b;
if (insn->mod == 3) {
return; /* mod, reg, reg */
}
if (insn->as_64)
{
if ((insn->rm & 7) != 4) { /* rm != 100b, no s-i-b byte */
// one byte modrm
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve64_mod0;
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
insn->displacement.displ32 = fetch_dword();
break;
case 1:
/* reg, 8-bit displacement, sign extend */
resolve_modrm = &disassembler::resolve64_mod1or2;
insn->displacement.displ32 = (Bit8s) fetch_byte();
break;
case 2:
/* reg, 32-bit displacement */
resolve_modrm = &disassembler::resolve64_mod1or2;
insn->displacement.displ32 = fetch_dword();
break;
} /* switch (mod) */
} /* if (rm != 4) */
else { /* rm == 4, s-i-b byte follows */
insn->sib = fetch_byte();
BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
insn->base |= insn->rex_b;
insn->index |= insn->rex_x;
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve64_mod0_rm4;
if ((insn->base & 7) == 5)
insn->displacement.displ32 = fetch_dword();
break;
case 1:
resolve_modrm = &disassembler::resolve64_mod1or2_rm4;
insn->displacement.displ32 = (Bit8s) fetch_byte();
break;
case 2:
resolve_modrm = &disassembler::resolve64_mod1or2_rm4;
insn->displacement.displ32 = fetch_dword();
break;
}
} /* s-i-b byte follows */
}
else
{
if (insn->as_32)
{
if ((insn->rm & 7) != 4) { /* rm != 100b, no s-i-b byte */
// one byte modrm
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve32_mod0;
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
insn->displacement.displ32 = fetch_dword();
break;
case 1:
/* reg, 8-bit displacement, sign extend */
resolve_modrm = &disassembler::resolve32_mod1or2;
insn->displacement.displ32 = (Bit8s) fetch_byte();
break;
case 2:
/* reg, 32-bit displacement */
resolve_modrm = &disassembler::resolve32_mod1or2;
insn->displacement.displ32 = fetch_dword();
break;
} /* switch (mod) */
} /* if (rm != 4) */
else { /* rm == 4, s-i-b byte follows */
insn->sib = fetch_byte();
BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
insn->base |= insn->rex_b;
insn->index |= insn->rex_x;
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve32_mod0_rm4;
if ((insn->base & 7) == 5)
insn->displacement.displ32 = fetch_dword();
break;
case 1:
resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
insn->displacement.displ32 = (Bit8s) fetch_byte();
break;
case 2:
resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
insn->displacement.displ32 = fetch_dword();
break;
}
} /* s-i-b byte follows */
}
else {
assert(insn->rex_b == 0);
assert(insn->rex_x == 0);
assert(insn->rex_r == 0);
/* 16 bit addressing modes. */
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve16_mod0;
if(insn->rm == 6)
insn->displacement.displ16 = fetch_word();
break;
case 1:
/* reg, 8-bit displacement, sign extend */
resolve_modrm = &disassembler::resolve16_mod1or2;
insn->displacement.displ16 = (Bit8s) fetch_byte();
break;
case 2:
resolve_modrm = &disassembler::resolve16_mod1or2;
insn->displacement.displ16 = fetch_word();
break;
} /* switch (mod) ... */
}
}
}
void disassembler::resolve16_mod0(const x86_insn *insn, unsigned datasize)
{
const char *seg;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod00_rm16[insn->rm];
if(insn->rm == 6)
print_memory_access16(datasize, seg, NULL, insn->displacement.displ16);
else
print_memory_access16(datasize, seg, index16[insn->rm], 0);
}
void disassembler::resolve16_mod1or2(const x86_insn *insn, unsigned datasize)
{
const char *seg;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_rm16[insn->rm];
print_memory_access16(datasize, seg, index16[insn->rm], insn->displacement.displ16);
}
void disassembler::resolve32_mod0(const x86_insn *insn, unsigned datasize)
{
const char *seg, *eip_regname = NULL;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = segment_name[DS_REG];
if (insn->is_64) {
if (intel_mode) eip_regname = "eip";
else eip_regname = "%eip";
}
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
print_memory_access32(datasize, seg, eip_regname, NULL, 0, insn->displacement.displ32);
else
print_memory_access32(datasize, seg, general_32bit_regname[insn->rm], NULL, 0, 0);
}
void disassembler::resolve32_mod1or2(const x86_insn *insn, unsigned datasize)
{
const char *seg;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_base32[insn->rm];
print_memory_access32(datasize, seg,
general_32bit_regname[insn->rm], NULL, 0, insn->displacement.displ32);
}
void disassembler::resolve32_mod0_rm4(const x86_insn *insn, unsigned datasize)
{
char vsib_index[8];
const char *seg, *base = NULL, *index = NULL;
Bit32u disp32 = 0;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod00_base32[insn->base];
if ((insn->base & 7) != 5)
base = general_32bit_regname[insn->base];
else
disp32 = insn->displacement.displ32;
if (datasize & VSIB_Index) {
sprintf(vsib_index, "%s%d", vector_reg_name[insn->vex_l], insn->index);
index = vsib_index;
}
else {
if (insn->index != 4)
index = general_32bit_regname[insn->index];
}
print_memory_access32(datasize, seg, base, index, insn->scale, disp32);
}
void disassembler::resolve32_mod1or2_rm4(const x86_insn *insn, unsigned datasize)
{
char vsib_index[8];
const char *seg, *index = NULL;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_base32[insn->base];
if (datasize & VSIB_Index) {
sprintf(vsib_index, "%s%d", vector_reg_name[insn->vex_l], insn->index);
index = vsib_index;
}
else {
if (insn->index != 4)
index = general_32bit_regname[insn->index];
}
print_memory_access32(datasize, seg,
general_32bit_regname[insn->base], index, insn->scale, insn->displacement.displ32);
}
void disassembler::resolve64_mod0(const x86_insn *insn, unsigned datasize)
{
const char *seg, *rip_regname;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = segment_name[DS_REG];
if (intel_mode) rip_regname = "rip";
else rip_regname = "%rip";
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
print_memory_access64(datasize, seg, rip_regname, NULL, 0, (Bit32s) insn->displacement.displ32);
else
print_memory_access64(datasize, seg, general_64bit_regname[insn->rm], NULL, 0, 0);
}
void disassembler::resolve64_mod1or2(const x86_insn *insn, unsigned datasize)
{
const char *seg;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_base32[insn->rm];
print_memory_access64(datasize, seg,
general_64bit_regname[insn->rm], NULL, 0, (Bit32s) insn->displacement.displ32);
}
void disassembler::resolve64_mod0_rm4(const x86_insn *insn, unsigned datasize)
{
char vsib_index[8];
const char *seg, *base = NULL, *index = NULL;
Bit32s disp32 = 0;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod00_base32[insn->base];
if ((insn->base & 7) != 5)
base = general_64bit_regname[insn->base];
else
disp32 = (Bit32s) insn->displacement.displ32;
if (datasize & VSIB_Index) {
sprintf(vsib_index, "%s%d", vector_reg_name[insn->vex_l], insn->index);
index = vsib_index;
}
else {
if (insn->index != 4)
index = general_64bit_regname[insn->index];
}
print_memory_access64(datasize, seg, base, index, insn->scale, disp32);
}
void disassembler::resolve64_mod1or2_rm4(const x86_insn *insn, unsigned datasize)
{
char vsib_index[8];
const char *seg, *index = NULL;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_base32[insn->base];
if (datasize & VSIB_Index) {
sprintf(vsib_index, "%s%d", vector_reg_name[insn->vex_l], insn->index);
index = vsib_index;
}
else {
if (insn->index != 4)
index = general_64bit_regname[insn->index];
}
print_memory_access64(datasize, seg,
general_64bit_regname[insn->base], index, insn->scale, (Bit32s) insn->displacement.displ32);
}
void disassembler::print_datasize(unsigned size)
{
if (!intel_mode || !print_mem_datasize) return;
switch(size & 0xf)
{
case B_SIZE:
dis_sprintf("byte ptr ");
break;
case W_SIZE:
dis_sprintf("word ptr ");
break;
case D_SIZE:
dis_sprintf("dword ptr ");
break;
case Q_SIZE:
dis_sprintf("qword ptr ");
break;
case T_SIZE:
dis_sprintf("tbyte ptr ");
break;
case XMM_SIZE:
dis_sprintf("dqword ptr ");
break;
case YMM_SIZE:
dis_sprintf("qqword ptr ");
break;
case X_SIZE:
break;
};
}
void disassembler::print_memory_access16(int datasize,
const char *seg, const char *index, Bit16u disp)
{
print_datasize(datasize);
dis_sprintf("%s:", seg);
if (intel_mode)
{
if (index == NULL)
{
dis_sprintf("0x%04x", (unsigned) disp);
}
else
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("[%s+0x%04x]", index, (unsigned) disp);
else
dis_sprintf("[%s%+d]", index, (int) (Bit16s) disp);
}
else
dis_sprintf("[%s]", index);
}
}
else
{
if (index == NULL)
{
dis_sprintf("0x%04x", (unsigned) disp);
}
else
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("0x%04x(%s,1)", (unsigned) disp, index);
else
dis_sprintf("%d(%s,1)", (int) (Bit16s) disp, index);
}
else
dis_sprintf("(%s,1)", index);
}
}
}
void disassembler::print_memory_access32(int datasize,
const char *seg, const char *base, const char *index, int scale, Bit32s disp)
{
print_datasize(datasize);
dis_sprintf("%s:", seg);
scale = 1 << scale;
if (intel_mode)
{
if (base == NULL)
{
if (index == NULL)
{
dis_sprintf("0x%08x", (unsigned) disp);
}
else
{
if (scale != 1)
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("[%s*%d+0x%08x]", index, scale, (unsigned) disp);
else
dis_sprintf("[%s*%d%+d]", index, scale, (int) disp);
}
else
dis_sprintf("[%s*%d]", index, scale);
}
else
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("[%s+0x%08x]", index, (unsigned) disp);
else
dis_sprintf("[%s%+d]", index, (int) disp);
}
else {
dis_sprintf("[%s]", index);
}
}
}
}
else
{
if (index == NULL)
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("[%s+0x%08x]", base, (unsigned) disp);
else
dis_sprintf("[%s%+d]", base, (int) disp);
}
else {
dis_sprintf("[%s]", base);
}
}
else
{
if (scale != 1)
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("[%s+%s*%d+0x%08x]", base, index, scale, (unsigned) disp);
else
dis_sprintf("[%s+%s*%d%+d]", base, index, scale, (int) disp);
}
else {
dis_sprintf("[%s+%s*%d]", base, index, scale);
}
}
else
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("[%s+%s+0x%08x]", base, index, (unsigned) disp);
else
dis_sprintf("[%s+%s%+d]", base, index, (int) disp);
}
else
dis_sprintf("[%s+%s]", base, index);
}
}
}
}
else
{
if (base == NULL)
{
if (index == NULL)
{
dis_sprintf("0x%08x", (unsigned) disp);
}
else
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("0x%08x(,%s,%d)", (unsigned) disp, index, scale);
else
dis_sprintf("%d(,%s,%d)", (int) disp, index, scale);
}
else
dis_sprintf("(,%s,%d)", index, scale);
}
}
else
{
if (index == NULL)
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("0x%08x(%s)", (unsigned) disp, base);
else
dis_sprintf("%d(%s)", (int) disp, base);
}
else
dis_sprintf("(%s)", base);
}
else
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("0x%08x(%s,%s,%d)", (unsigned) disp, base, index, scale);
else
dis_sprintf("%d(%s,%s,%d)", (int) disp, base, index, scale);
}
else
dis_sprintf("(%s,%s,%d)", base, index, scale);
}
}
}
}
void disassembler::print_memory_access64(int datasize,
const char *seg, const char *base, const char *index, int scale, Bit32s disp)
{
Bit64u disp64 = (Bit64s) disp;
print_datasize(datasize);
dis_sprintf("%s:", seg);
scale = 1 << scale;
if (intel_mode)
{
if (base == NULL)
{
if (index == NULL)
{
dis_sprintf("0x%08x%08x", GET32H(disp64), GET32L(disp64));
}
else
{
if (scale != 1)
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("[%s*%d+0x%08x%08x]", index, scale, GET32H(disp64), GET32L(disp64));
else
dis_sprintf("[%s*%d%+d]", index, scale, (int) disp);
}
else
dis_sprintf("[%s*%d]", index, scale);
}
else
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("[%s+0x%08x%08x]", index, GET32H(disp64), GET32L(disp64));
else
dis_sprintf("[%s%+d]", index, (int) disp);
}
else {
dis_sprintf("[%s]", index);
}
}
}
}
else
{
if (index == NULL)
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("[%s+0x%08x%08x]", base, GET32H(disp64), GET32L(disp64));
else
dis_sprintf("[%s%+d]", base, (int) disp);
}
else {
dis_sprintf("[%s]", base);
}
}
else
{
if (scale != 1)
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("[%s+%s*%d+0x%08x%08x]", base, index, scale, GET32H(disp64), GET32L(disp64));
else
dis_sprintf("[%s+%s*%d%+d]", base, index, scale, (int) disp);
}
else {
dis_sprintf("[%s+%s*%d]", base, index, scale);
}
}
else
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("[%s+%s+0x%08x%08x]", base, index, GET32H(disp64), GET32L(disp64));
else
dis_sprintf("[%s+%s%+d]", base, index, (int) disp);
}
else
dis_sprintf("[%s+%s]", base, index);
}
}
}
}
else
{
if (base == NULL)
{
if (index == NULL)
{
dis_sprintf("0x%08x%08x", GET32H(disp64), GET32L(disp64));
}
else
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("0x%08x%08x(,%s,%d)", GET32H(disp64), GET32L(disp64), index, scale);
else
dis_sprintf("%d(,%s,%d)", (int) disp, index, scale);
}
else
dis_sprintf("(,%s,%d)", index, scale);
}
}
else
{
if (index == NULL)
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("0x%08x%08x(%s)", GET32H(disp64), GET32L(disp64), base);
else
dis_sprintf("%d(%s)", (int) disp, base);
}
else
dis_sprintf("(%s)", base);
}
else
{
if (disp != 0) {
if (offset_mode_hex)
dis_sprintf("0x%08x%08x(%s,%s,%d)", GET32H(disp64), GET32L(disp64), base, index, scale);
else
dis_sprintf("%d(%s,%s,%d)", (int) disp, base, index, scale);
}
else
dis_sprintf("(%s,%s,%d)", base, index, scale);
}
}
}
}

View File

@ -1,460 +0,0 @@
/////////////////////////////////////////////////////////////////////////
// $Id: resolve.cc,v 1.13 2006/08/11 17:22:43 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <assert.h>
#include "disasm.h"
void disassembler::decode_modrm(x86_insn *insn)
{
insn->modrm = fetch_byte();
BX_DECODE_MODRM(insn->modrm, insn->mod, insn->nnn, insn->rm);
// MOVs with CRx and DRx always use register ops and ignore the mod field.
if ((insn->b1 & ~3) == 0x120) insn->mod = 3;
insn->nnn |= insn->rex_r;
if (insn->mod == 3) {
/* mod, reg, reg */
insn->rm |= insn->rex_b;
return;
}
if (insn->as_64)
{
if (insn->rm != 4) { /* rm != 100b, no s-i-b byte */
insn->rm |= insn->rex_b;
// one byte modrm
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve64_mod0;
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
insn->displacement.displ32 = fetch_dword();
break;
case 1:
/* reg, 8-bit displacement, sign extend */
resolve_modrm = &disassembler::resolve64_mod1or2;
insn->displacement.displ32 = (Bit8s) fetch_byte();
break;
case 2:
/* reg, 32-bit displacement */
resolve_modrm = &disassembler::resolve64_mod1or2;
insn->displacement.displ32 = fetch_dword();
break;
} /* switch (mod) */
} /* if (rm != 4) */
else { /* rm == 4, s-i-b byte follows */
insn->sib = fetch_byte();
BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
insn->base |= insn->rex_b;
insn->index |= insn->rex_x;
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve64_mod0_rm4;
if ((insn->base & 7) == 5)
insn->displacement.displ32 = fetch_dword();
break;
case 1:
resolve_modrm = &disassembler::resolve64_mod1or2_rm4;
insn->displacement.displ32 = (Bit8s) fetch_byte();
break;
case 2:
resolve_modrm = &disassembler::resolve64_mod1or2_rm4;
insn->displacement.displ32 = fetch_dword();
break;
}
} /* s-i-b byte follows */
}
else
{
if (insn->as_32)
{
if (insn->rm != 4) { /* rm != 100b, no s-i-b byte */
insn->rm |= insn->rex_b;
// one byte modrm
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve32_mod0;
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
insn->displacement.displ32 = fetch_dword();
break;
case 1:
/* reg, 8-bit displacement, sign extend */
resolve_modrm = &disassembler::resolve32_mod1or2;
insn->displacement.displ32 = (Bit8s) fetch_byte();
break;
case 2:
/* reg, 32-bit displacement */
resolve_modrm = &disassembler::resolve32_mod1or2;
insn->displacement.displ32 = fetch_dword();
break;
} /* switch (mod) */
} /* if (rm != 4) */
else { /* rm == 4, s-i-b byte follows */
insn->sib = fetch_byte();
BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
insn->base |= insn->rex_b;
insn->index |= insn->rex_x;
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve32_mod0_rm4;
if ((insn->base & 7) == 5)
insn->displacement.displ32 = fetch_dword();
break;
case 1:
resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
insn->displacement.displ32 = (Bit8s) fetch_byte();
break;
case 2:
resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
insn->displacement.displ32 = fetch_dword();
break;
}
} /* s-i-b byte follows */
}
else {
assert(insn->rex_b == 0);
assert(insn->rex_x == 0);
assert(insn->rex_r == 0);
/* 16 bit addressing modes. */
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve16_mod0;
if(insn->rm == 6)
insn->displacement.displ16 = fetch_word();
break;
case 1:
/* reg, 8-bit displacement, sign extend */
resolve_modrm = &disassembler::resolve16_mod1or2;
insn->displacement.displ16 = (Bit8s) fetch_byte();
break;
case 2:
resolve_modrm = &disassembler::resolve16_mod1or2;
insn->displacement.displ16 = fetch_word();
break;
} /* switch (mod) ... */
}
}
}
void disassembler::resolve16_mod0(const x86_insn *insn, unsigned mode)
{
const char *seg;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod00_rm16[insn->rm];
if(insn->rm == 6)
print_memory_access16(mode, seg, NULL, insn->displacement.displ16);
else
print_memory_access16(mode, seg, index16[insn->rm], 0);
}
void disassembler::resolve16_mod1or2(const x86_insn *insn, unsigned mode)
{
const char *seg;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_rm16[insn->rm];
print_memory_access16(mode, seg, index16[insn->rm], insn->displacement.displ16);
}
void disassembler::resolve32_mod0(const x86_insn *insn, unsigned mode)
{
const char *seg;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = segment_name[DS_REG];
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
print_memory_access(mode, seg, NULL, NULL, 0, insn->displacement.displ32);
else
print_memory_access(mode, seg, general_32bit_regname[insn->rm], NULL, 0, 0);
}
void disassembler::resolve32_mod1or2(const x86_insn *insn, unsigned mode)
{
const char *seg;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_rm32[insn->rm];
print_memory_access(mode, seg,
general_32bit_regname[insn->rm], NULL, 0, insn->displacement.displ32);
}
void disassembler::resolve32_mod0_rm4(const x86_insn *insn, unsigned mode)
{
const char *seg, *base = NULL, *index = NULL;
Bit32u disp32 = 0;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod00_base32[insn->base];
if ((insn->base & 7) != 5)
base = general_32bit_regname[insn->base];
else
disp32 = insn->displacement.displ32;
if (insn->index != 4)
index = general_32bit_regname[insn->index];
print_memory_access(mode, seg, base, index, insn->scale, disp32);
}
void disassembler::resolve32_mod1or2_rm4(const x86_insn *insn, unsigned mode)
{
const char *seg, *index = NULL;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_base32[insn->base];
if (insn->index != 4)
index = general_32bit_regname[insn->index];
print_memory_access(mode, seg,
general_32bit_regname[insn->base], index, insn->scale, insn->displacement.displ32);
}
void disassembler::resolve64_mod0(const x86_insn *insn, unsigned mode)
{
const char *seg, *rip_regname;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = segment_name[DS_REG];
if (intel_mode) rip_regname = "rip";
else rip_regname = "%rip";
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
print_memory_access(mode, seg, rip_regname, NULL, 0, insn->displacement.displ32);
else
print_memory_access(mode, seg, general_64bit_regname[insn->rm], NULL, 0, 0);
}
void disassembler::resolve64_mod1or2(const x86_insn *insn, unsigned mode)
{
const char *seg;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_rm32[insn->rm];
print_memory_access(mode, seg,
general_64bit_regname[insn->rm], NULL, 0, insn->displacement.displ32);
}
void disassembler::resolve64_mod0_rm4(const x86_insn *insn, unsigned mode)
{
const char *seg, *base = NULL, *index = NULL;
Bit32u disp32 = 0;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod00_base32[insn->base];
if ((insn->base & 7) != 5)
base = general_64bit_regname[insn->base];
else
disp32 = insn->displacement.displ32;
if (insn->index != 4)
index = general_64bit_regname[insn->index];
print_memory_access(mode, seg, base, index, insn->scale, disp32);
}
void disassembler::resolve64_mod1or2_rm4(const x86_insn *insn, unsigned mode)
{
const char *seg, *index = NULL;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_base32[insn->base];
if (insn->index != 4)
index = general_64bit_regname[insn->index];
print_memory_access(mode, seg,
general_64bit_regname[insn->base], index, insn->scale, insn->displacement.displ32);
}
void disassembler::print_datasize(unsigned size)
{
if (!intel_mode) return;
switch(size)
{
case B_SIZE:
dis_sprintf("byte ptr ");
break;
case W_SIZE:
dis_sprintf("word ptr ");
break;
case D_SIZE:
dis_sprintf("dword ptr ");
break;
case Q_SIZE:
dis_sprintf("qword ptr ");
break;
case O_SIZE:
dis_sprintf("dqword ptr ");
break;
case T_SIZE:
dis_sprintf("tbyte ptr ");
break;
case P_SIZE:
break;
case X_SIZE:
break;
};
}
void disassembler::print_memory_access16(int datasize,
const char *seg, const char *index, Bit16u disp)
{
print_datasize(datasize);
if (intel_mode)
{
if (index == NULL)
{
dis_sprintf("%s:0x%x", seg, (unsigned) disp);
}
else
{
if (disp != 0)
dis_sprintf("%s:[%s+0x%x]", seg, index, (unsigned) disp);
else
dis_sprintf("%s:[%s]", seg, index);
}
}
else
{
if (index == NULL)
{
dis_sprintf("%s:0x%x", seg, (unsigned) disp);
}
else
{
if (disp != 0)
dis_sprintf("%s:0x%x(%s,1)", seg, (unsigned) disp, index);
else
dis_sprintf("%s:(%s,1)", seg, index);
}
}
}
void disassembler::print_memory_access(int datasize,
const char *seg, const char *base, const char *index, int scale, Bit32u disp)
{
print_datasize(datasize);
if (intel_mode)
{
if (base == NULL)
{
if (index == NULL)
{
dis_sprintf("%s:0x%x", seg, (unsigned) disp);
}
else
{
if (scale != 0)
{
if (disp != 0)
dis_sprintf("%s:[%s*%d+0x%x]", seg, index, 1<<scale, (unsigned) disp);
else
dis_sprintf("%s:[%s*%d]", seg, index, 1<<scale);
}
else
{
if (disp != 0)
dis_sprintf("%s:[%s+0x%x]", seg, index, (unsigned) disp);
else
dis_sprintf("%s:[%s]", seg, index);
}
}
}
else
{
if (index == NULL)
{
if (disp != 0)
dis_sprintf("%s:[%s+0x%x]", seg, base, (unsigned) disp);
else
dis_sprintf("%s:[%s]", seg, base);
}
else
{
if (scale != 0)
{
if (disp != 0)
dis_sprintf("%s:[%s+%s*%d+0x%x]", seg, base, index, 1<<scale, (unsigned) disp);
else
dis_sprintf("%s:[%s+%s*%d]", seg, base, index, 1<<scale);
}
else
{
if (disp != 0)
dis_sprintf("%s:[%s+%s+0x%x]", seg, base, index, (unsigned) disp);
else
dis_sprintf("%s:[%s+%s]", seg, base, index);
}
}
}
}
else
{
if (base == NULL)
{
if (index == NULL)
{
dis_sprintf("%s:0x%x", seg, (unsigned) disp);
}
else
{
if (disp != 0)
dis_sprintf("%s:0x%x(,%s,%d)", seg, (unsigned) disp, index, 1<<scale);
else
dis_sprintf("%s:(,%s,%d)", seg, index, 1<<scale);
}
}
else
{
if (index == NULL)
{
if (disp != 0)
dis_sprintf("%s:0x%x(%s)", seg, (unsigned) disp, base);
else
dis_sprintf("%s:(%s)", seg, base);
}
else
{
if (disp != 0)
dis_sprintf("%s:0x%x(%s,%s,%d)", seg, (unsigned) disp, base, index, 1<<scale);
else
dis_sprintf("%s:(%s,%s,%d)", seg, base, index, 1<<scale);
}
}
}
}

View File

@ -1,6 +1,26 @@
/////////////////////////////////////////////////////////////////////////
// $Id: syntax.cc,v 1.10 2006/04/27 15:11:45 sshwarts Exp $
// $Id: syntax.cc 11968 2013-11-29 20:49:20Z sshwarts $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2005-2011 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
/////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "disasm.h"
@ -8,10 +28,6 @@
// Intel STYLE
//////////////////
#define BX_DISASM_SUPPORT_X86_64
#ifdef BX_DISASM_SUPPORT_X86_64
static const char *intel_general_16bit_regname[16] = {
"ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
"r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
@ -32,18 +48,6 @@ static const char *intel_general_8bit_regname_rex[16] = {
"r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
};
#else
static const char *intel_general_16bit_regname[8] = {
"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"
};
static const char *intel_general_32bit_regname[8] = {
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
};
#endif
static const char *intel_general_8bit_regname[8] = {
"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
};
@ -53,23 +57,24 @@ static const char *intel_segment_name[8] = {
};
static const char *intel_index16[8] = {
"bx+si",
"bx+di",
"bp+si",
"bp+di",
"si",
"di",
"bp",
"bx+si",
"bx+di",
"bp+si",
"bp+di",
"si",
"di",
"bp",
"bx"
};
static const char *intel_vector_reg_name[4] = {
"xmm", "ymm", "???", "zmm"
};
//////////////////
// AT&T STYLE
//////////////////
#ifdef BX_DISASM_SUPPORT_X86_64
static const char *att_general_16bit_regname[16] = {
"%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
"%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
@ -90,18 +95,6 @@ static const char *att_general_8bit_regname_rex[16] = {
"%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
};
#else
static const char *att_general_16bit_regname[8] = {
"%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di"
};
static const char *att_general_32bit_regname[8] = {
"%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi"
};
#endif
static const char *att_general_8bit_regname[8] = {
"%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh"
};
@ -111,16 +104,20 @@ static const char *att_segment_name[8] = {
};
static const char *att_index16[8] = {
"%bx, %si",
"%bx, %di",
"%bp, %si",
"%bp, %di",
"%si",
"%di",
"%bp",
"%bx,%si",
"%bx,%di",
"%bp,%si",
"%bp,%di",
"%si",
"%di",
"%bp",
"%bx"
};
static const char *att_vector_reg_name[4] = {
"%xmm", "%ymm", "%???", "%zmm"
};
#define NULL_SEGMENT_REGISTER 7
void disassembler::initialize_modrm_segregs()
@ -143,32 +140,39 @@ void disassembler::initialize_modrm_segregs()
sreg_mod01or10_rm16[6] = segment_name[SS_REG];
sreg_mod01or10_rm16[7] = segment_name[DS_REG];
sreg_mod01or10_rm32[0] = segment_name[DS_REG];
sreg_mod01or10_rm32[1] = segment_name[DS_REG];
sreg_mod01or10_rm32[2] = segment_name[DS_REG];
sreg_mod01or10_rm32[3] = segment_name[DS_REG];
sreg_mod01or10_rm32[4] = segment_name[NULL_SEGMENT_REGISTER];
sreg_mod01or10_rm32[5] = segment_name[SS_REG];
sreg_mod01or10_rm32[6] = segment_name[DS_REG];
sreg_mod01or10_rm32[7] = segment_name[DS_REG];
sreg_mod00_base32[0] = segment_name[DS_REG];
sreg_mod00_base32[1] = segment_name[DS_REG];
sreg_mod00_base32[2] = segment_name[DS_REG];
sreg_mod00_base32[3] = segment_name[DS_REG];
sreg_mod00_base32[4] = segment_name[SS_REG];
sreg_mod00_base32[5] = segment_name[DS_REG];
sreg_mod00_base32[6] = segment_name[DS_REG];
sreg_mod00_base32[7] = segment_name[DS_REG];
sreg_mod00_base32[8] = segment_name[DS_REG];
sreg_mod00_base32[9] = segment_name[DS_REG];
sreg_mod00_base32[10] = segment_name[DS_REG];
sreg_mod00_base32[11] = segment_name[DS_REG];
sreg_mod00_base32[12] = segment_name[DS_REG];
sreg_mod00_base32[13] = segment_name[DS_REG];
sreg_mod00_base32[14] = segment_name[DS_REG];
sreg_mod00_base32[15] = segment_name[DS_REG];
sreg_mod00_base32[0] = segment_name[DS_REG];
sreg_mod00_base32[1] = segment_name[DS_REG];
sreg_mod00_base32[2] = segment_name[DS_REG];
sreg_mod00_base32[3] = segment_name[DS_REG];
sreg_mod00_base32[4] = segment_name[SS_REG];
sreg_mod00_base32[5] = segment_name[DS_REG];
sreg_mod00_base32[6] = segment_name[DS_REG];
sreg_mod00_base32[7] = segment_name[DS_REG];
sreg_mod01or10_base32[0] = segment_name[DS_REG];
sreg_mod01or10_base32[1] = segment_name[DS_REG];
sreg_mod01or10_base32[2] = segment_name[DS_REG];
sreg_mod01or10_base32[3] = segment_name[DS_REG];
sreg_mod01or10_base32[4] = segment_name[SS_REG];
sreg_mod01or10_base32[5] = segment_name[SS_REG];
sreg_mod01or10_base32[6] = segment_name[DS_REG];
sreg_mod01or10_base32[7] = segment_name[DS_REG];
sreg_mod01or10_base32[0] = segment_name[DS_REG];
sreg_mod01or10_base32[1] = segment_name[DS_REG];
sreg_mod01or10_base32[2] = segment_name[DS_REG];
sreg_mod01or10_base32[3] = segment_name[DS_REG];
sreg_mod01or10_base32[4] = segment_name[SS_REG];
sreg_mod01or10_base32[5] = segment_name[SS_REG];
sreg_mod01or10_base32[6] = segment_name[DS_REG];
sreg_mod01or10_base32[7] = segment_name[DS_REG];
sreg_mod01or10_base32[8] = segment_name[DS_REG];
sreg_mod01or10_base32[9] = segment_name[DS_REG];
sreg_mod01or10_base32[10] = segment_name[DS_REG];
sreg_mod01or10_base32[11] = segment_name[DS_REG];
sreg_mod01or10_base32[12] = segment_name[DS_REG];
sreg_mod01or10_base32[13] = segment_name[DS_REG];
sreg_mod01or10_base32[14] = segment_name[DS_REG];
sreg_mod01or10_base32[15] = segment_name[DS_REG];
}
//////////////////
@ -187,6 +191,7 @@ void disassembler::set_syntax_intel()
segment_name = intel_segment_name;
index16 = intel_index16;
vector_reg_name = intel_vector_reg_name;
initialize_modrm_segregs();
}
@ -207,12 +212,16 @@ void disassembler::print_disassembly_intel(const x86_insn *insn, const BxDisasmO
dis_sprintf(", ");
(this->*entry->Operand3)(insn);
}
if (entry->Operand4) {
dis_sprintf(", ");
(this->*entry->Operand4)(insn);
}
}
//////////////////
// AT&T STYLE
//////////////////
void disassembler::set_syntax_att()
{
intel_mode = 0;
@ -225,6 +234,7 @@ void disassembler::set_syntax_att()
segment_name = att_segment_name;
index16 = att_index16;
vector_reg_name = att_vector_reg_name;
initialize_modrm_segregs();
}
@ -240,7 +250,11 @@ void disassembler::print_disassembly_att(const x86_insn *insn, const BxDisasmOpc
// print opcode
dis_sprintf("%s ", entry->AttOpcode);
if (entry->Operand3) {
if (entry->Operand4) {
(this->*entry->Operand4)(insn);
dis_sprintf(", ");
}
if (entry->Operand3) {
(this->*entry->Operand3)(insn);
dis_sprintf(", ");
}