From e38dbea8cb456758c50f3593287acdca3983889e Mon Sep 17 00:00:00 2001 From: iximeow Date: Fri, 5 Jun 2026 08:32:09 +0000 Subject: fix several instructions' incorrect memory or op2 size --- CHANGELOG | 5 +++++ src/long_mode/mod.rs | 35 ++++++++++++++++++----------------- src/protected_mode/mod.rs | 17 +++++++++++------ src/real_mode/mod.rs | 13 +++++++++---- test/long_mode/mod.rs | 45 +++++++++++++++++++++++---------------------- test/protected_mode/mod.rs | 37 +++++++++++++++++++++++++------------ 6 files changed, 91 insertions(+), 61 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6cdb7e2..9494d72 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -18,6 +18,11 @@ AVX-512. everything else (including assemblers like nasm, masm, gas, ..) since standardized on "rn-sae", the spelling for the rounding mode in subsequent versions of the SDM and now APM. +* fix several instructions having incorrectly-large register or memory access sizes. + `roundss` and `roundsd` were overly-large, as were `pmovsxbd`, `pmovzxwq`, + `pmovsxwq`, and `cvtss2sd`. additionally, `lfs`, `lgs`, and `lss` in 64-bit + mode have 32-bit operand forms (yielding 32 + 16 == 48 bits of memory + accessed). ## 2.1.0 diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 3ba76a0..548aec3 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -6511,9 +6511,9 @@ fn read_operands< .with_id(words.offset() as u32 * 8 - 8 + 1) ); if instruction.operands[1] != OperandSpec::RegMMM { - if instruction.opcode == Opcode::CMPSS { + if instruction.opcode == Opcode::CMPSS || instruction.opcode == Opcode::ROUNDSS { instruction.mem_size = 4; - } else if instruction.opcode == Opcode::CMPSD { + } else if instruction.opcode == Opcode::CMPSD || instruction.opcode == Opcode::ROUNDSD { instruction.mem_size = 8; } else { instruction.mem_size = 16; @@ -6787,7 +6787,7 @@ fn read_operands< if instruction.operands[1] != OperandSpec::RegMMM { if [Opcode::PMOVSXBQ, Opcode::PMOVZXBQ].contains(&instruction.opcode) { instruction.mem_size = 2; - } else if [Opcode::PMOVZXBD, Opcode::UCOMISS, Opcode::COMISS].contains(&instruction.opcode) { + } else if [Opcode::PMOVZXBD, Opcode::PMOVSXBD, Opcode::PMOVZXWQ, Opcode::PMOVSXWQ, Opcode::UCOMISS, Opcode::COMISS, Opcode::CVTSS2SD].contains(&instruction.opcode) { instruction.mem_size = 4; } else { instruction.mem_size = 8; @@ -6806,9 +6806,13 @@ fn read_operands< if [Opcode::LFS, Opcode::LGS, Opcode::LSS].contains(&instruction.opcode) { if instruction.prefixes.rex_unchecked().w() { instruction.mem_size = 10; - } else { + } else if instruction.prefixes.operand_size() { + instruction.regs[0].bank = RegisterBank::W; instruction.mem_size = 4; - } + } else { + instruction.regs[0].bank = RegisterBank::D; + instruction.mem_size = 6; + } } else if [Opcode::ENQCMD, Opcode::ENQCMDS].contains(&instruction.opcode) { instruction.mem_size = 64; } else { @@ -7498,7 +7502,8 @@ fn read_operands< } 7 => { instruction.opcode = Opcode::RDPID; - instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; + // > "The value of CS.D and operand-size prefixes (66H and REX.W) do not affect the behavior of the RDPID instruction." + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::Q, sink)?; if instruction.operands[0] != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } @@ -7937,11 +7942,7 @@ fn read_operands< if op == OperandCase::G_xmm_U_mm { return Err(DecodeError::InvalidOperand); } else { - if instruction.prefixes.rex_unchecked().w() { - instruction.mem_size = 8; - } else { - instruction.mem_size = 4; - } + instruction.mem_size = 8; } } }, @@ -8447,12 +8448,11 @@ fn read_operands< instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; } } else if r == 4 { - // TODO: this permits storing only to word-size registers - // spec suggets this might do something different for f.ex rdi? + // TODO: note that this was incorrectly choosing 16-bit operands every time instruction.opcode = Opcode::SMSW; instruction.operand_count = 1; instruction.mem_size = 2; - instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::W, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, self.vqp_size(), sink)?; } else if r == 5 { let mod_bits = modrm >> 6; if mod_bits != 0b11 { @@ -8687,7 +8687,8 @@ fn read_operands< return Err(DecodeError::InvalidOpcode); } }; - let bank = if instruction.prefixes.rex_unchecked().w() { RegisterBank::Q } else { RegisterBank::D }; + // TPAUSE is always a 32-bit register. + let bank = RegisterBank::D; instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; instruction.operand_count = 1; } @@ -8701,8 +8702,8 @@ fn read_operands< 6 => { instruction.opcode = Opcode::UMWAIT; instruction.regs[0] = RegSpec { - bank: if instruction.prefixes.rex_unchecked().w() { RegisterBank::Q } else { RegisterBank::D }, - num: m + if instruction.prefixes.rex_unchecked().x() { 0b1000 } else { 0 }, + bank: RegisterBank::D, + num: m + if instruction.prefixes.rex_unchecked().b() { 0b1000 } else { 0 }, }; instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index f419197..0c33643 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -6362,9 +6362,9 @@ fn read_operands< .with_id(words.offset() as u32 * 8 - 8 + 1) ); if instruction.operands[1] != OperandSpec::RegMMM { - if instruction.opcode == Opcode::CMPSS { + if instruction.opcode == Opcode::CMPSS || instruction.opcode == Opcode::ROUNDSS { instruction.mem_size = 4; - } else if instruction.opcode == Opcode::CMPSD { + } else if instruction.opcode == Opcode::CMPSD || instruction.opcode == Opcode::ROUNDSD { instruction.mem_size = 8; } else { instruction.mem_size = 16; @@ -6646,7 +6646,7 @@ fn read_operands< if instruction.operands[1] != OperandSpec::RegMMM { if [Opcode::PMOVSXBQ, Opcode::PMOVZXBQ].contains(&instruction.opcode) { instruction.mem_size = 2; - } else if [Opcode::PMOVZXBD, Opcode::UCOMISS, Opcode::COMISS, Opcode::CVTSS2SD].contains(&instruction.opcode) { + } else if [Opcode::PMOVZXBD, Opcode::PMOVSXBD, Opcode::PMOVZXWQ, Opcode::PMOVSXWQ, Opcode::UCOMISS, Opcode::COMISS, Opcode::CVTSS2SD].contains(&instruction.opcode) { instruction.mem_size = 4; } else { instruction.mem_size = 8; @@ -7393,6 +7393,7 @@ fn read_operands< } 7 => { instruction.opcode = Opcode::RDPID; + // > "The value of CS.D and operand-size prefixes (66H and REX.W) do not affect the behavior of the RDPID instruction." instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if instruction.operands[0] != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); @@ -8291,12 +8292,16 @@ fn read_operands< instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; } } else if r == 4 { - // TODO: this permits storing only to word-size registers - // spec suggets this might do something different for f.ex rdi? + // TODO: note that this was incorrectly choosing 16-bit operands every time instruction.opcode = Opcode::SMSW; instruction.operand_count = 1; instruction.mem_size = 2; - instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::W, sink)?; + let bank = if instruction.prefixes.operand_size() { + RegisterBank::W + } else { + RegisterBank::D + }; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; } else if r == 5 { let mod_bits = modrm >> 6; if mod_bits != 0b11 { diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index 716148c..334c07a 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -6686,7 +6686,7 @@ fn read_operands< if instruction.operands[1] != OperandSpec::RegMMM { if [Opcode::PMOVSXBQ, Opcode::PMOVZXBQ].contains(&instruction.opcode) { instruction.mem_size = 2; - } else if [Opcode::PMOVZXBD, Opcode::UCOMISS, Opcode::COMISS, Opcode::CVTSS2SD].contains(&instruction.opcode) { + } else if [Opcode::PMOVZXBD, Opcode::PMOVSXBD, Opcode::PMOVZXWQ, Opcode::PMOVSXWQ, Opcode::UCOMISS, Opcode::COMISS, Opcode::CVTSS2SD].contains(&instruction.opcode) { instruction.mem_size = 4; } else { instruction.mem_size = 8; @@ -7435,6 +7435,7 @@ fn read_operands< } 7 => { instruction.opcode = Opcode::RDPID; + // > "The value of CS.D and operand-size prefixes (66H and REX.W) do not affect the behavior of the RDPID instruction." instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if instruction.operands[0] != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); @@ -8336,12 +8337,16 @@ fn read_operands< instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; } } else if r == 4 { - // TODO: this permits storing only to word-size registers - // spec suggets this might do something different for f.ex rdi? + // TODO: note that this was incorrectly choosing 16-bit operands every time instruction.opcode = Opcode::SMSW; instruction.operand_count = 1; instruction.mem_size = 2; - instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::W, sink)?; + let bank = if !instruction.prefixes.operand_size() { + RegisterBank::W + } else { + RegisterBank::D + }; + instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; } else if r == 5 { let mod_bits = modrm >> 6; if mod_bits != 0b11 { diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs index 50c4dc2..9c3039d 100644 --- a/test/long_mode/mod.rs +++ b/test/long_mode/mod.rs @@ -629,6 +629,7 @@ mod cvt { testcase!(&[0x4f, 0x0f, 0x2c, 0xcf], "cvttps2pi mm1, xmm15"), testcase!(&[0x4f, 0x0f, 0x2a, 0xcf], "cvtpi2ps xmm9, mm7"), testcase!(&[0x4f, 0x0f, 0x2a, 0x00], "cvtpi2ps xmm8, qword [r8]"), + testcase!(&[0x0f, 0x2a, 0x00], "cvtpi2ps xmm0, qword [rax]"), testcase!(&[0x4f, 0x66, 0x0f, 0x2a, 0xcf], "cvtpi2pd xmm1, mm7"), testcase!(&[0x66, 0x4f, 0x0f, 0x2a, 0xcf], "cvtpi2pd xmm9, mm7"), testcase!(&[0x4f, 0xf3, 0x0f, 0x2a, 0xcf], "cvtsi2ss xmm1, edi"), @@ -639,7 +640,7 @@ mod cvt { testcase!(&[0xf2, 0x4f, 0x0f, 0x2a, 0x00], "cvtsi2sd xmm8, qword [r8]"), testcase!(&[0x4f, 0xf3, 0x0f, 0x2a, 0x00], "cvtsi2ss xmm0, dword [rax]"), testcase!(&[0xf3, 0x4f, 0x0f, 0x2a, 0x00], "cvtsi2ss xmm8, qword [r8]"), - testcase!(&[0x4f, 0x66, 0x0f, 0x2a, 0x00], "cvtpi2pd xmm0, dword [rax]"), + testcase!(&[0x4f, 0x66, 0x0f, 0x2a, 0x00], "cvtpi2pd xmm0, qword [rax]"), testcase!(&[0x66, 0x4f, 0x0f, 0x2a, 0x00], "cvtpi2pd xmm8, qword [r8]"), ]; @@ -1098,13 +1099,13 @@ mod sse4_1 { testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x38, 0x20, 0x06], "pmovsxbw xmm0, qword [rsi]"), testcase!(invalid: &[0x0f, 0x38, 0x20, 0x06]), - testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x38, 0x21, 0x06], "pmovsxbd xmm0, qword [rsi]"), + testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x38, 0x21, 0x06], "pmovsxbd xmm0, dword [rsi]"), testcase!(invalid: &[0x0f, 0x38, 0x21, 0x06]), testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x38, 0x22, 0x06], "pmovsxbq xmm0, word [rsi]"), testcase!(invalid: &[0x0f, 0x38, 0x22, 0x06]), testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x38, 0x23, 0x06], "pmovsxwd xmm0, qword [rsi]"), testcase!(invalid: &[0x0f, 0x38, 0x23, 0x06]), - testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x38, 0x24, 0x06], "pmovsxwq xmm0, qword [rsi]"), + testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x38, 0x24, 0x06], "pmovsxwq xmm0, dword [rsi]"), testcase!(invalid: &[0x0f, 0x38, 0x24, 0x06]), testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x38, 0x25, 0x06], "pmovsxdq xmm0, qword [rsi]"), testcase!(invalid: &[0x0f, 0x38, 0x25, 0x06]), @@ -1127,7 +1128,7 @@ mod sse4_1 { testcase!(invalid: &[0x0f, 0x38, 0x32, 0x06]), testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x38, 0x33, 0x06], "pmovzxwd xmm0, qword [rsi]"), testcase!(invalid: &[0x0f, 0x38, 0x33, 0x06]), - testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x38, 0x34, 0x06], "pmovzxwq xmm0, qword [rsi]"), + testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x38, 0x34, 0x06], "pmovzxwq xmm0, dword [rsi]"), testcase!(invalid: &[0x0f, 0x38, 0x34, 0x06]), testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x38, 0x35, 0x06], "pmovzxdq xmm0, qword [rsi]"), testcase!(invalid: &[0x0f, 0x38, 0x35, 0x06]), @@ -1159,9 +1160,9 @@ mod sse4_1 { testcase!(invalid: &[0x0f, 0x3a, 0x08, 0x06]), testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x3a, 0x09, 0x06, 0x31], "roundpd xmm0, xmmword [rsi], 0x31"), testcase!(invalid: &[0x0f, 0x3a, 0x09, 0x06]), - testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x3a, 0x0a, 0x06, 0x31], "roundss xmm0, xmmword [rsi], 0x31"), + testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x3a, 0x0a, 0x06, 0x31], "roundss xmm0, dword [rsi], 0x31"), testcase!(invalid: &[0x0f, 0x3a, 0x0a, 0x06]), - testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x3a, 0x0b, 0x06, 0x31], "roundsd xmm0, xmmword [rsi], 0x31"), + testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x3a, 0x0b, 0x06, 0x31], "roundsd xmm0, qword [rsi], 0x31"), testcase!(invalid: &[0x0f, 0x3a, 0x0b, 0x06]), testcase!(features { SSE4_1: true, AVX: false } &[0x66, 0x0f, 0x3a, 0x0e, 0x06, 0x31], "pblendw xmm0, xmmword [rsi], 0x31"), @@ -1306,15 +1307,15 @@ mod _0f01 { testcase!(&[0x0f, 0x01, 0xfe], "invlpgb rax, edx, ecx"), testcase!(&[0x0f, 0x01, 0xff], "tlbsync"), testcase!(&[0x2e, 0x67, 0x65, 0x2e, 0x46, 0x0f, 0x01, 0xff], "tlbsync"), - testcase!(&[0x4f, 0x0f, 0x01, 0xe0], "smsw r8w"), - testcase!(&[0x0f, 0x01, 0xe0], "smsw ax"), - testcase!(&[0x0f, 0x01, 0xe1], "smsw cx"), - testcase!(&[0x0f, 0x01, 0xe2], "smsw dx"), - testcase!(&[0x0f, 0x01, 0xe3], "smsw bx"), - testcase!(&[0x0f, 0x01, 0xe4], "smsw sp"), - testcase!(&[0x0f, 0x01, 0xe5], "smsw bp"), - testcase!(&[0x0f, 0x01, 0xe6], "smsw si"), - testcase!(&[0x0f, 0x01, 0xe7], "smsw di"), + testcase!(&[0x4f, 0x0f, 0x01, 0xe0], "smsw r8"), + testcase!(&[0x0f, 0x01, 0xe0], "smsw eax"), + testcase!(&[0x0f, 0x01, 0xe1], "smsw ecx"), + testcase!(&[0x0f, 0x01, 0xe2], "smsw edx"), + testcase!(&[0x0f, 0x01, 0xe3], "smsw ebx"), + testcase!(&[0x0f, 0x01, 0xe4], "smsw esp"), + testcase!(&[0x0f, 0x01, 0xe5], "smsw ebp"), + testcase!(&[0x0f, 0x01, 0xe6], "smsw esi"), + testcase!(&[0x0f, 0x01, 0xe7], "smsw edi"), testcase!(invalid: &[0x0f, 0x01, 0xe8]), testcase!(invalid: &[0x0f, 0x01, 0xe8]), testcase!(invalid: &[0x0f, 0x01, 0xe9]), @@ -1425,7 +1426,8 @@ mod system { testcase!(&[0x66, 0x4f, 0x0f, 0xb2, 0x00], "lss r8, mword [r8]"), testcase!(&[0x67, 0x4f, 0x0f, 0xb2, 0x00], "lss r8, mword [r8d]"), testcase!(&[0x4f, 0x0f, 0xb2, 0x00], "lss r8, mword [r8]"), - testcase!(&[0x0f, 0xb2, 0x00], "lss rax, dword [rax]"), + testcase!(&[0x0f, 0xb2, 0x00], "lss eax, far [rax]"), + testcase!(&[0x66, 0x0f, 0xb2, 0x00], "lss ax, dword [rax]"), testcase!(invalid: &[0x45, 0x0f, 0x22, 0xc8]), testcase!(invalid: &[0x45, 0x0f, 0x20, 0xc8]), testcase!(&[0x40, 0x0f, 0x22, 0xd0], "mov cr2, rax"), @@ -1527,7 +1529,7 @@ mod sse { testcase!(&[0x4f, 0x0f, 0x59, 0x01], "mulps xmm8, xmmword [r9]"), testcase!(&[0xf3, 0x4f, 0x0f, 0x59, 0x01], "mulss xmm8, dword [r9]"), testcase!(&[0x4f, 0x0f, 0x5a, 0x01], "cvtps2pd xmm8, qword [r9]"), - testcase!(&[0xf3, 0x4f, 0x0f, 0x5a, 0x01], "cvtss2sd xmm8, qword [r9]"), + testcase!(&[0xf3, 0x4f, 0x0f, 0x5a, 0x01], "cvtss2sd xmm8, dword [r9]"), testcase!(&[0x4f, 0x0f, 0x5b, 0x01], "cvtdq2ps xmm8, xmmword [r9]"), testcase!(&[0xf3, 0x4f, 0x0f, 0x5b, 0x01], "cvttps2dq xmm8, xmmword [r9]"), testcase!(&[0x67, 0x4f, 0x0f, 0x5b, 0x01], "cvtdq2ps xmm8, xmmword [r9d]"), @@ -1557,7 +1559,7 @@ mod sse { ), testcase!(&[0xf3, 0x0f, 0x70, 0xc0, 0x4e], "pshufhw xmm0, xmm0, 0x4e"), testcase!(&[0xf3, 0x0f, 0x7e, 0xc1], "movq xmm0, xmm1"), - testcase!(&[0xf3, 0x4f, 0x0f, 0x7e, 0xc1], "movd r9, mm0"), // use of rex.w demotes to movd r/mm + testcase!(&[0xf3, 0x4f, 0x0f, 0x7e, 0xc1], "movd r9, mm0"), testcase!(&[0xf3, 0x40, 0x0f, 0x7e, 0xc1], "movq xmm0, xmm1"), testcase!(&[0xf3, 0x41, 0x0f, 0x7e, 0xc1], "movq xmm0, xmm9"), testcase!(&[0xf3, 0x42, 0x0f, 0x7e, 0xc1], "movq xmm0, xmm1"), @@ -1982,7 +1984,7 @@ mod misc { testcase!(&[0x66, 0x0f, 0xae, 0xf7], "tpause edi"), testcase!(&[0xf3, 0x0f, 0xae, 0xf1], "umonitor rcx"), testcase!(&[0xf2, 0x0f, 0xae, 0xf1], "umwait ecx"), - testcase!(&[0xf2, 0x4f, 0x0f, 0xae, 0xf1], "umwait r9"), + testcase!(&[0xf2, 0x4f, 0x0f, 0xae, 0xf1], "umwait r9d"), testcase!(&[0x66, 0x0f, 0x38, 0x80, 0x2f], "invept rbp, xmmword [rdi]"), testcase!(&[0x66, 0x49, 0x0f, 0x38, 0x80, 0x2f], "invept rbp, xmmword [r15]"), testcase!(invalid: &[0x0f, 0x38, 0x80, 0x2f]), @@ -1996,7 +1998,7 @@ mod misc { testcase!(invalid: &[0x0f, 0x38, 0x82, 0x2f]), testcase!(invalid: &[0x43, 0x0f, 0x38, 0x82, 0x2f]), testcase!(&[0x66, 0x0f, 0xae, 0xf1], "tpause ecx"), - testcase!(&[0x66, 0x4f, 0x0f, 0xae, 0xf1], "tpause r9"), + testcase!(&[0x66, 0x4f, 0x0f, 0xae, 0xf1], "tpause r9d"), testcase!(&[0xc4, 0b000_00011, 0b0_1111_101, 0x1d, 0b11_001_010, 0x77], "vcvtps2ph xmm10, ymm9, 0x77"), ]; @@ -2032,7 +2034,6 @@ mod evex { testcase!(&[0x62, 0x12, 0x7d, 0x06, 0xa0, 0x14, 0x0f], "vpscatterdd dword [r15 + xmm25 * 1], k6, xmm10"), testcase!(&[0x62, 0x12, 0x7d, 0x26, 0xa0, 0x14, 0x0f], "vpscatterdd dword [r15 + ymm25 * 1], k6, ymm10"), testcase!(&[0x62, 0x12, 0x7d, 0x46, 0xa0, 0x14, 0x0f], "vpscatterdd dword [r15 + zmm25 * 1], k6, zmm10"), - testcase!(&[0x62, 0x12, 0xfd, 0x46, 0xa0, 0x14, 0x0f], "vpscatterdq qword [r15 + zmm25 * 1], k6, zmm10"), testcase!(&[0x62, 0x12, 0x7d, 0x46, 0xa1, 0x14, 0x0f], "vpscatterqd dword [r15 + zmm25 * 1], k6, zmm10"), testcase!(&[0x62, 0x12, 0xfd, 0x46, 0xa1, 0x14, 0x0f], "vpscatterqq qword [r15 + zmm25 * 1], k6, zmm10"), @@ -3582,7 +3583,7 @@ mod rdpid { use crate::long_mode::{TestCase, run_test}; const CASES: &'static [TestCase] = &[ - testcase!(&[0xf3, 0x0f, 0xc7, 0xfd], "rdpid ebp"), + testcase!(&[0xf3, 0x0f, 0xc7, 0xfd], "rdpid rbp"), ]; #[test] diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs index f0450b1..a82c3bc 100644 --- a/test/protected_mode/mod.rs +++ b/test/protected_mode/mod.rs @@ -660,13 +660,13 @@ fn test_sse4_1() { test_instr(&[0x66, 0x0f, 0x38, 0x20, 0x06], "pmovsxbw xmm0, qword [esi]"); test_invalid(&[0x0f, 0x38, 0x20, 0x06]); - test_instr(&[0x66, 0x0f, 0x38, 0x21, 0x06], "pmovsxbd xmm0, qword [esi]"); + test_instr(&[0x66, 0x0f, 0x38, 0x21, 0x06], "pmovsxbd xmm0, dword [esi]"); test_invalid(&[0x0f, 0x38, 0x21, 0x06]); test_instr(&[0x66, 0x0f, 0x38, 0x22, 0x06], "pmovsxbq xmm0, word [esi]"); test_invalid(&[0x0f, 0x38, 0x22, 0x06]); test_instr(&[0x66, 0x0f, 0x38, 0x23, 0x06], "pmovsxwd xmm0, qword [esi]"); test_invalid(&[0x0f, 0x38, 0x23, 0x06]); - test_instr(&[0x66, 0x0f, 0x38, 0x24, 0x06], "pmovsxwq xmm0, qword [esi]"); + test_instr(&[0x66, 0x0f, 0x38, 0x24, 0x06], "pmovsxwq xmm0, dword [esi]"); test_invalid(&[0x0f, 0x38, 0x24, 0x06]); test_instr(&[0x66, 0x0f, 0x38, 0x25, 0x06], "pmovsxdq xmm0, qword [esi]"); test_invalid(&[0x0f, 0x38, 0x25, 0x06]); @@ -721,9 +721,9 @@ fn test_sse4_1() { test_invalid(&[0x0f, 0x3a, 0x08, 0x06]); test_instr(&[0x66, 0x0f, 0x3a, 0x09, 0x06, 0x31], "roundpd xmm0, xmmword [esi], 0x31"); test_invalid(&[0x0f, 0x3a, 0x09, 0x06]); - test_instr(&[0x66, 0x0f, 0x3a, 0x0a, 0x06, 0x31], "roundss xmm0, xmmword [esi], 0x31"); + test_instr(&[0x66, 0x0f, 0x3a, 0x0a, 0x06, 0x31], "roundss xmm0, dword [esi], 0x31"); test_invalid(&[0x0f, 0x3a, 0x0a, 0x06]); - test_instr(&[0x66, 0x0f, 0x3a, 0x0b, 0x06, 0x31], "roundsd xmm0, xmmword [esi], 0x31"); + test_instr(&[0x66, 0x0f, 0x3a, 0x0b, 0x06, 0x31], "roundsd xmm0, qword [esi], 0x31"); test_invalid(&[0x0f, 0x3a, 0x0b, 0x06]); test_instr(&[0x66, 0x0f, 0x3a, 0x0e, 0x06, 0x31], "pblendw xmm0, xmmword [esi], 0x31"); @@ -860,14 +860,14 @@ fn test_0f01() { // test_display(&[0x0f, 0x01, 0xfe], "invlpgb rax, edx, ecx"); // test_display(&[0x0f, 0x01, 0xff], "tlbsync"); // test_display(&[0x2e, 0x67, 0x65, 0x2e, 0x46, 0x0f, 0x01, 0xff], "tlbsync"); - test_display(&[0x0f, 0x01, 0xe0], "smsw ax"); - test_display(&[0x0f, 0x01, 0xe1], "smsw cx"); - test_display(&[0x0f, 0x01, 0xe2], "smsw dx"); - test_display(&[0x0f, 0x01, 0xe3], "smsw bx"); - test_display(&[0x0f, 0x01, 0xe4], "smsw sp"); - test_display(&[0x0f, 0x01, 0xe5], "smsw bp"); - test_display(&[0x0f, 0x01, 0xe6], "smsw si"); - test_display(&[0x0f, 0x01, 0xe7], "smsw di"); + test_display(&[0x0f, 0x01, 0xe0], "smsw eax"); + test_display(&[0x0f, 0x01, 0xe1], "smsw ecx"); + test_display(&[0x0f, 0x01, 0xe2], "smsw edx"); + test_display(&[0x0f, 0x01, 0xe3], "smsw ebx"); + test_display(&[0x0f, 0x01, 0xe4], "smsw esp"); + test_display(&[0x0f, 0x01, 0xe5], "smsw ebp"); + test_display(&[0x0f, 0x01, 0xe6], "smsw esi"); + test_display(&[0x0f, 0x01, 0xe7], "smsw edi"); test_invalid(&[0x0f, 0x01, 0xe8]); test_invalid(&[0x0f, 0x01, 0xe8]); test_invalid(&[0x0f, 0x01, 0xe9]); @@ -944,6 +944,19 @@ fn test_0fae() { fn test_system() { test_display(&[0x63, 0xc1], "arpl cx, ax"); test_display(&[0x63, 0x04, 0xba], "arpl word [edx + edi * 4], ax"); + test_display(&[0x66, 0x0f, 0xb2, 0x00], "lss ax, word [eax]"); + test_display(&[0x67, 0x0f, 0xb2, 0x00], "lss eax, far [bx + si * 1]"); + test_display(&[0x0f, 0xb2, 0x00], "lss eax, far [eax]"); + test_display(&[0x66, 0x0f, 0xb2, 0x00], "lss ax, word [eax]"); + test_invalid(&[0x0f, 0x22, 0xc8]); + test_invalid(&[0x0f, 0x20, 0xc8]); + test_display(&[0x0f, 0x22, 0xd0], "mov cr2, eax"); + test_invalid(&[0x0f, 0x22, 0xcf]); + test_display(&[0x0f, 0x22, 0xd7], "mov cr2, edi"); + test_display(&[0x0f, 0x20, 0xd0], "mov eax, cr2"); + + test_display(&[0x0f, 0x23, 0xc8], "mov dr1, eax"); + test_display(&[0x0f, 0x21, 0xc8], "mov eax, dr1"); test_display(&[0x0f, 0x06], "clts"); } -- cgit v1.1