fixed decoding of RDRAND/RDSEED with 0x66 prefix

This commit is contained in:
Stanislav Shwartsman 2012-12-27 19:31:21 +00:00
parent 48d7fa3786
commit 685e0091b4
5 changed files with 37 additions and 28 deletions

View File

@ -4887,19 +4887,20 @@ enum {
// Lookup for opcode and attributes in another opcode tables
// Totally 15 opcode groups supported
#define BxGroupX 0x00f0 // bits 7..4: opcode groups definition
#define BxPrefixSSE66 0x0010 // Group encoding: 0001, SSE_PREFIX_66
#define BxPrefixSSEF3 0x0020 // Group encoding: 0010, SSE_PREFIX_F3
#define BxPrefixSSEF2 0x0030 // Group encoding: 0011, SSE_PREFIX_F2
#define BxPrefixSSE66 0x0010 // Group encoding: 0001, SSE_PREFIX_66 only
#define BxPrefixSSEF3 0x0020 // Group encoding: 0010, SSE_PREFIX_F3 only
#define BxPrefixSSEF2 0x0030 // Group encoding: 0011, SSE_PREFIX_F2 only
#define BxPrefixSSE 0x0040 // Group encoding: 0100
#define BxGroupN 0x0050 // Group encoding: 0101
#define BxSplitGroupN 0x0060 // Group encoding: 0110
#define BxFPEscape 0x0070 // Group encoding: 0111
#define Bx3ByteOp 0x0080 // Group encoding: 1000
#define BxOSizeGrp 0x0090 // Group encoding: 1001
#define BxPrefixVEX 0x00A0 // Group encoding: 1010
#define BxSplitVexW 0x00B0 // Group encoding: 1011
#define BxSplitVexW64 0x00C0 // Group encoding: 1100 - VexW ignored in 32-bit mode
#define BxSplitMod11B 0x00D0 // Group encoding: 1101
#define BxPrefixSSEF2F3 0x0050 // Group encoding: 0101, ignore SSE_PREFIX_66
#define BxGroupN 0x0060 // Group encoding: 0110
#define BxSplitGroupN 0x0070 // Group encoding: 0111
#define BxFPEscape 0x0080 // Group encoding: 1000
#define Bx3ByteOp 0x0090 // Group encoding: 1001
#define BxOSizeGrp 0x00A0 // Group encoding: 1010
#define BxPrefixVEX 0x00B0 // Group encoding: 1011
#define BxSplitVexW 0x00C0 // Group encoding: 1100
#define BxSplitVexW64 0x00D0 // Group encoding: 1101 - VexW ignored in 32-bit mode
#define BxSplitMod11B 0x00E0 // Group encoding: 1110
// The BxImmediate2 mask specifies kind of second immediate data
// required by instruction.

View File

@ -1654,6 +1654,12 @@ modrm_done:
Bit32u group = attr & BxGroupX;
attr &= ~BxGroupX;
// ignore 0x66 SSE prefix is required
if (group == BxPrefixSSEF2F3) {
if (sse_prefix == SSE_PREFIX_66) sse_prefix = SSE_PREFIX_NONE;
group = BxPrefixSSE;
}
if (group < BxPrefixSSE) {
/* For opcodes with only one allowed SSE prefix */
if (sse_prefix != (group >> 4)) {
@ -1691,8 +1697,6 @@ modrm_done:
#endif
case BxOSizeGrp:
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[os_32]);
if (sse_prefix == SSE_PREFIX_66)
sse_prefix = 0;
break;
case BxPrefixSSE:
/* For SSE opcodes look into another table

View File

@ -649,8 +649,8 @@ static const BxOpcodeInfo_t BxOpcodeInfoG9w[8*2] = {
/* 3 */ { 0, BX_IA_ERROR },
/* 4 */ { 0, BX_IA_ERROR },
/* 5 */ { 0, BX_IA_ERROR },
/* 6 */ { BxPrefixSSE, BX_IA_RDRAND_Ew, BxOpcodeGroupSSE_ERR },
/* 7 */ { BxPrefixSSE, BX_IA_RDSEED_Ew, BxOpcodeGroupSSE_ERR },
/* 6 */ { BxPrefixSSEF2F3, BX_IA_RDRAND_Ew, BxOpcodeGroupSSE_ERR },
/* 7 */ { BxPrefixSSEF2F3, BX_IA_RDSEED_Ew, BxOpcodeGroupSSE_ERR },
/* /m form */
/* 0 */ { 0, BX_IA_ERROR },
@ -671,8 +671,8 @@ static const BxOpcodeInfo_t BxOpcodeInfoG9d[8*2] = {
/* 3 */ { 0, BX_IA_ERROR },
/* 4 */ { 0, BX_IA_ERROR },
/* 5 */ { 0, BX_IA_ERROR },
/* 6 */ { BxPrefixSSE, BX_IA_RDRAND_Ed, BxOpcodeGroupSSE_ERR },
/* 7 */ { BxPrefixSSE, BX_IA_RDSEED_Ed, BxOpcodeGroupSSE_ERR },
/* 6 */ { BxPrefixSSEF2F3, BX_IA_RDRAND_Ed, BxOpcodeGroupSSE_ERR },
/* 7 */ { BxPrefixSSEF2F3, BX_IA_RDSEED_Ed, BxOpcodeGroupSSE_ERR },
/* /m form */
/* 0 */ { 0, BX_IA_ERROR },
@ -694,8 +694,8 @@ static const BxOpcodeInfo_t BxOpcodeInfo64G9q[8*2] = {
/* 3 */ { 0, BX_IA_ERROR },
/* 4 */ { 0, BX_IA_ERROR },
/* 5 */ { 0, BX_IA_ERROR },
/* 6 */ { BxPrefixSSE, BX_IA_RDRAND_Eq, BxOpcodeGroupSSE_ERR },
/* 7 */ { BxPrefixSSE, BX_IA_RDSEED_Eq, BxOpcodeGroupSSE_ERR },
/* 6 */ { BxPrefixSSEF2F3, BX_IA_RDRAND_Eq, BxOpcodeGroupSSE_ERR },
/* 7 */ { BxPrefixSSEF2F3, BX_IA_RDSEED_Eq, BxOpcodeGroupSSE_ERR },
/* /m form */
/* 0 */ { 0, BX_IA_ERROR },

View File

@ -2085,6 +2085,12 @@ modrm_done:
Bit32u group = attr & BxGroupX;
attr &= ~BxGroupX;
// ignore 0x66 SSE prefix is required
if (group == BxPrefixSSEF2F3) {
if (sse_prefix == SSE_PREFIX_66) sse_prefix = SSE_PREFIX_NONE;
group = BxPrefixSSE;
}
if (group < BxPrefixSSE) {
/* For opcodes with only one allowed SSE prefix */
if (sse_prefix != (group >> 4)) {
@ -2117,8 +2123,6 @@ modrm_done:
break;
case BxOSizeGrp:
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[offset >> 9]);
if (sse_prefix == SSE_PREFIX_66)
sse_prefix = 0;
break;
case BxPrefixSSE:
/* For SSE opcodes look into another table

View File

@ -920,10 +920,10 @@ static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f38f0[3] = {
};
static const BxOpcodeInfo_t BxOpcodeGroupOsize0f38f0[BX_SUPPORT_X86_64 + 2] = {
/* 16 */ { BxPrefixSSE, BX_IA_MOVBE_GwMw, BxOpcodeGroupSSE_0f38f0 },
/* 32 */ { BxPrefixSSE, BX_IA_MOVBE_GdMd, BxOpcodeGroupSSE_0f38f0 },
/* 16 */ { BxPrefixSSEF2F3, BX_IA_MOVBE_GwMw, BxOpcodeGroupSSE_0f38f0 },
/* 32 */ { BxPrefixSSEF2F3, BX_IA_MOVBE_GdMd, BxOpcodeGroupSSE_0f38f0 },
#if BX_SUPPORT_X86_64
/* 64 */ { BxPrefixSSE, BX_IA_MOVBE_GqMq, BxOpcodeGroupSSE_0f38f0 },
/* 64 */ { BxPrefixSSEF2F3, BX_IA_MOVBE_GqMq, BxOpcodeGroupSSE_0f38f0 },
#endif
};
@ -948,10 +948,10 @@ static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f38f1q[3] = {
#endif
static const BxOpcodeInfo_t BxOpcodeGroupOsize0f38f1[BX_SUPPORT_X86_64 + 2] = {
/* 16 */ { BxPrefixSSE, BX_IA_MOVBE_MwGw, BxOpcodeGroupSSE_0f38f1w },
/* 32 */ { BxPrefixSSE, BX_IA_MOVBE_MdGd, BxOpcodeGroupSSE_0f38f1d },
/* 16 */ { BxPrefixSSEF2F3, BX_IA_MOVBE_MwGw, BxOpcodeGroupSSE_0f38f1w },
/* 32 */ { BxPrefixSSEF2F3, BX_IA_MOVBE_MdGd, BxOpcodeGroupSSE_0f38f1d },
#if BX_SUPPORT_X86_64
/* 64 */ { BxPrefixSSE, BX_IA_MOVBE_MqGq, BxOpcodeGroupSSE_0f38f1q },
/* 64 */ { BxPrefixSSEF2F3, BX_IA_MOVBE_MqGq, BxOpcodeGroupSSE_0f38f1q },
#endif
};