aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2026-06-05 08:32:09 +0000
committeriximeow <me@iximeow.net>2026-06-21 16:44:21 +0000
commite38dbea8cb456758c50f3593287acdca3983889e (patch)
treee6abc5573a21ee8f6eb6754d83aab846b0f72e32
parenta38cba0c4a4ed9a1ed763618e5efe3f4487b1ad0 (diff)
fix several instructions' incorrect memory or op2 size
-rw-r--r--CHANGELOG5
-rw-r--r--src/long_mode/mod.rs35
-rw-r--r--src/protected_mode/mod.rs17
-rw-r--r--src/real_mode/mod.rs13
-rw-r--r--test/long_mode/mod.rs45
-rw-r--r--test/protected_mode/mod.rs37
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");
}