From 685e0091b4f4b6c21a251fb3c5c0847b413a7580 Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Thu, 27 Dec 2012 19:31:21 +0000 Subject: [PATCH] fixed decoding of RDRAND/RDSEED with 0x66 prefix --- bochs/cpu/cpu.h | 25 +++++++++++++------------ bochs/cpu/fetchdecode.cc | 8 ++++++-- bochs/cpu/fetchdecode.h | 12 ++++++------ bochs/cpu/fetchdecode64.cc | 8 ++++++-- bochs/cpu/fetchdecode_sse.h | 12 ++++++------ 5 files changed, 37 insertions(+), 28 deletions(-) diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index 05908a0c1..7e48f172b 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -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. diff --git a/bochs/cpu/fetchdecode.cc b/bochs/cpu/fetchdecode.cc index 4af95787d..d78ad321b 100644 --- a/bochs/cpu/fetchdecode.cc +++ b/bochs/cpu/fetchdecode.cc @@ -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 diff --git a/bochs/cpu/fetchdecode.h b/bochs/cpu/fetchdecode.h index 8d8777da3..273d611aa 100644 --- a/bochs/cpu/fetchdecode.h +++ b/bochs/cpu/fetchdecode.h @@ -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 }, diff --git a/bochs/cpu/fetchdecode64.cc b/bochs/cpu/fetchdecode64.cc index 1ce667258..d844ec59f 100644 --- a/bochs/cpu/fetchdecode64.cc +++ b/bochs/cpu/fetchdecode64.cc @@ -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 diff --git a/bochs/cpu/fetchdecode_sse.h b/bochs/cpu/fetchdecode_sse.h index 642ce879e..74fe8026e 100644 --- a/bochs/cpu/fetchdecode_sse.h +++ b/bochs/cpu/fetchdecode_sse.h @@ -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 };