diff options
| author | iximeow <me@iximeow.net> | 2026-05-04 03:48:02 +0000 |
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2026-05-25 01:41:55 +0000 |
| commit | 307d39dedfabaa0a0400ba62cd9a418d3f94a582 (patch) | |
| tree | d1c2b0c3cd635eb4f4d20c8d6d8c511b9d5f2095 | |
| parent | 298c3348a6258c877c534aee7b4ce7a45622b6d1 (diff) | |
pextr*/extractps
| -rw-r--r-- | CHANGELOG | 1 | ||||
| -rw-r--r-- | src/long_mode/mod.rs | 32 | ||||
| -rw-r--r-- | src/protected_mode/mod.rs | 30 | ||||
| -rw-r--r-- | src/real_mode/mod.rs | 30 | ||||
| -rw-r--r-- | test/long_mode/mod.rs | 10 | ||||
| -rw-r--r-- | test/protected_mode/mod.rs | 8 | ||||
| -rw-r--r-- | test/real_mode/mod.rs | 8 |
7 files changed, 91 insertions, 28 deletions
@@ -20,6 +20,7 @@ zero-extended to 64 bits for storage. writing to "eax" in this way implies the 32->64 bit zero-extend, whereas writing to "ax" does not imply any zero-extension. mov reg-to-seg is unchanged and uses a 16-bit form for source GPR. +* fix pextr{b,w,d,q} and extractps first and second operands being backwards. * reject 0f0d prefetch/nop with a register operand, which was incorrectly decoded before. * maskmovq and maskmovdqu now have their implicit memory access size reported correctly. * monitor now reports a 1-byte memory access size. the monitored range in practice depends on CPUID. diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 5123ff5..b262308 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -4026,6 +4026,7 @@ enum OperandCase { PMOVX_G_E_xmm, PMOVX_E_G_xmm, G_Ev_xmm_Ib, + Ev_G_xmm_Ib, G_E_mm_Ib, MOVDIR64B, MASKMOVDQU, @@ -4384,6 +4385,7 @@ enum OperandCode { PMOVX_G_E_xmm = OperandCodeBuilder::new().read_E().operand_case(OperandCase::PMOVX_G_E_xmm).bits(), PMOVX_E_G_xmm = OperandCodeBuilder::new().read_E().operand_case(OperandCase::PMOVX_E_G_xmm).bits(), G_Ev_xmm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_Ev_xmm_Ib).bits(), + Ev_G_xmm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Ev_G_xmm_Ib).bits(), G_E_mm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_E_mm_Ib).bits(), MASKMOVDQU = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::MASKMOVDQU).bits(), } @@ -6713,8 +6715,9 @@ fn read_operands< instruction.operands[2] = OperandSpec::ImmI8; instruction.operand_count = 3; } - OperandCase::G_Ev_xmm_Ib => { - instruction.operands[1] = mem_oper; + OperandCase::Ev_G_xmm_Ib => { + instruction.operands[1] = instruction.operands[0]; + instruction.operands[0] = mem_oper; instruction.regs[0].bank = RegisterBank::X; instruction.imm = read_num(words, 1)? as u8 as u64; @@ -6724,6 +6727,21 @@ fn read_operands< Opcode::PEXTRW => 2, Opcode::PEXTRD => 4, Opcode::EXTRACTPS => 4, + _ => 8, + }; + } else { + instruction.regs[1].bank = RegisterBank::X; + } + instruction.operands[2] = OperandSpec::ImmI8; + instruction.operand_count = 3; + } + OperandCase::G_Ev_xmm_Ib => { + instruction.operands[1] = mem_oper; + instruction.regs[0].bank = RegisterBank::X; + instruction.imm = + read_num(words, 1)? as u8 as u64; + if instruction.operands[1] != OperandSpec::RegMMM { + instruction.mem_size = match instruction.opcode { Opcode::INSERTPS => 4, Opcode::PINSRB => 1, Opcode::PINSRW => 2, @@ -9270,7 +9288,7 @@ fn read_0f3a_opcode(&mut self, opcode: u8, prefixes: &mut Prefixes) -> Result<Op if prefixes.operand_size() { if opcode == 0x16 && prefixes.rex_unchecked().w() { - return Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRQ), OperandCode::G_Ev_xmm_Ib)); + return Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRQ), OperandCode::Ev_G_xmm_Ib)); } else if opcode == 0x22 && prefixes.rex_unchecked().w() { return Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PINSRQ), OperandCode::G_Ev_xmm_Ib)); } @@ -9284,10 +9302,10 @@ fn read_0f3a_opcode(&mut self, opcode: u8, prefixes: &mut Prefixes) -> Result<Op 0x0d => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::BLENDPD), OperandCode::G_E_xmm_Ib)), 0x0e => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PBLENDW), OperandCode::G_E_xmm_Ib)), 0x0f => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PALIGNR), OperandCode::G_E_xmm_Ib)), - 0x14 => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRB), OperandCode::G_Ev_xmm_Ib)), - 0x15 => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRW), OperandCode::G_Ev_xmm_Ib)), - 0x16 => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRD), OperandCode::G_Ev_xmm_Ib)), - 0x17 => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::EXTRACTPS), OperandCode::G_Ev_xmm_Ib)), + 0x14 => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRB), OperandCode::Ev_G_xmm_Ib)), + 0x15 => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRW), OperandCode::Ev_G_xmm_Ib)), + 0x16 => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRD), OperandCode::Ev_G_xmm_Ib)), + 0x17 => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::EXTRACTPS), OperandCode::Ev_G_xmm_Ib)), 0x20 => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PINSRB), OperandCode::G_Ev_xmm_Ib)), 0x21 => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::INSERTPS), OperandCode::G_Ev_xmm_Ib)), 0x22 => Ok(OpcodeRecord::new(Interpretation::Instruction(Opcode::PINSRD), OperandCode::G_Ev_xmm_Ib)), diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 4581485..a59216f 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -3940,6 +3940,7 @@ enum OperandCase { PMOVX_G_E_xmm, PMOVX_E_G_xmm, G_Ev_xmm_Ib, + Ev_G_xmm_Ib, G_E_mm_Ib, AbsFar, MOVDIR64B, @@ -4284,6 +4285,7 @@ enum OperandCode { PMOVX_G_E_xmm = OperandCodeBuilder::new().read_E().operand_case(OperandCase::PMOVX_G_E_xmm).bits(), PMOVX_E_G_xmm = OperandCodeBuilder::new().read_E().operand_case(OperandCase::PMOVX_E_G_xmm).bits(), G_Ev_xmm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_Ev_xmm_Ib).bits(), + Ev_G_xmm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Ev_G_xmm_Ib).bits(), G_E_mm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_E_mm_Ib).bits(), AbsFar = OperandCodeBuilder::new().operand_case(OperandCase::AbsFar).bits(), ModRM_0xc4 = OperandCodeBuilder::new().operand_case(OperandCase::ModRM_0xc4).bits(), @@ -6531,8 +6533,9 @@ fn read_operands< instruction.operands[2] = OperandSpec::ImmI8; instruction.operand_count = 3; } - OperandCase::G_Ev_xmm_Ib => { - instruction.operands[1] = mem_oper; + OperandCase::Ev_G_xmm_Ib => { + instruction.operands[1] = instruction.operands[0]; + instruction.operands[0] = mem_oper; instruction.regs[0].bank = RegisterBank::X; instruction.imm = read_num(words, 1)? as u8 as u32; @@ -6542,6 +6545,21 @@ fn read_operands< Opcode::PEXTRW => 2, Opcode::PEXTRD => 4, Opcode::EXTRACTPS => 4, + _ => 8, + }; + } else { + instruction.regs[1].bank = RegisterBank::X; + } + instruction.operands[2] = OperandSpec::ImmI8; + instruction.operand_count = 3; + } + OperandCase::G_Ev_xmm_Ib => { + instruction.operands[1] = mem_oper; + instruction.regs[0].bank = RegisterBank::X; + instruction.imm = + read_num(words, 1)? as u8 as u32; + if instruction.operands[1] != OperandSpec::RegMMM { + instruction.mem_size = match instruction.opcode { Opcode::INSERTPS => 4, Opcode::PINSRB => 1, Opcode::PINSRW => 2, @@ -9152,10 +9170,10 @@ fn read_0f3a_opcode(&mut self, opcode: u8, prefixes: &mut Prefixes) -> OpcodeRec 0x0d => OpcodeRecord::new(Interpretation::Instruction(Opcode::BLENDPD), OperandCode::G_E_xmm_Ib), 0x0e => OpcodeRecord::new(Interpretation::Instruction(Opcode::PBLENDW), OperandCode::G_E_xmm_Ib), 0x0f => OpcodeRecord::new(Interpretation::Instruction(Opcode::PALIGNR), OperandCode::G_E_xmm_Ib), - 0x14 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRB), OperandCode::G_Ev_xmm_Ib), - 0x15 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRW), OperandCode::G_Ev_xmm_Ib), - 0x16 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRD), OperandCode::G_Ev_xmm_Ib), - 0x17 => OpcodeRecord::new(Interpretation::Instruction(Opcode::EXTRACTPS), OperandCode::G_Ev_xmm_Ib), + 0x14 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRB), OperandCode::Ev_G_xmm_Ib), + 0x15 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRW), OperandCode::Ev_G_xmm_Ib), + 0x16 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRD), OperandCode::Ev_G_xmm_Ib), + 0x17 => OpcodeRecord::new(Interpretation::Instruction(Opcode::EXTRACTPS), OperandCode::Ev_G_xmm_Ib), 0x20 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PINSRB), OperandCode::G_Ev_xmm_Ib), 0x21 => OpcodeRecord::new(Interpretation::Instruction(Opcode::INSERTPS), OperandCode::G_Ev_xmm_Ib), 0x22 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PINSRD), OperandCode::G_Ev_xmm_Ib), diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index 3fbb99a..2530c1d 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -3970,6 +3970,7 @@ enum OperandCase { PMOVX_G_E_xmm, PMOVX_E_G_xmm, G_Ev_xmm_Ib, + Ev_G_xmm_Ib, G_E_mm_Ib, AbsFar, MOVDIR64B, @@ -4314,6 +4315,7 @@ enum OperandCode { PMOVX_G_E_xmm = OperandCodeBuilder::new().read_E().operand_case(OperandCase::PMOVX_G_E_xmm).bits(), PMOVX_E_G_xmm = OperandCodeBuilder::new().read_E().operand_case(OperandCase::PMOVX_E_G_xmm).bits(), G_Ev_xmm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_Ev_xmm_Ib).bits(), + Ev_G_xmm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Ev_G_xmm_Ib).bits(), G_E_mm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_E_mm_Ib).bits(), AbsFar = OperandCodeBuilder::new().operand_case(OperandCase::AbsFar).bits(), ModRM_0xc4 = OperandCodeBuilder::new().operand_case(OperandCase::ModRM_0xc4).bits(), @@ -6568,8 +6570,9 @@ fn read_operands< instruction.operands[2] = OperandSpec::ImmI8; instruction.operand_count = 3; } - OperandCase::G_Ev_xmm_Ib => { - instruction.operands[1] = mem_oper; + OperandCase::Ev_G_xmm_Ib => { + instruction.operands[1] = instruction.operands[0]; + instruction.operands[0] = mem_oper; instruction.regs[0].bank = RegisterBank::X; instruction.imm = read_num(words, 1)? as u8 as u32; @@ -6579,6 +6582,21 @@ fn read_operands< Opcode::PEXTRW => 2, Opcode::PEXTRD => 4, Opcode::EXTRACTPS => 4, + _ => 8, + }; + } else { + instruction.regs[1].bank = RegisterBank::X; + } + instruction.operands[2] = OperandSpec::ImmI8; + instruction.operand_count = 3; + } + OperandCase::G_Ev_xmm_Ib => { + instruction.operands[1] = mem_oper; + instruction.regs[0].bank = RegisterBank::X; + instruction.imm = + read_num(words, 1)? as u8 as u32; + if instruction.operands[1] != OperandSpec::RegMMM { + instruction.mem_size = match instruction.opcode { Opcode::INSERTPS => 4, Opcode::PINSRB => 1, Opcode::PINSRW => 2, @@ -9194,10 +9212,10 @@ fn read_0f3a_opcode(&mut self, opcode: u8, prefixes: &mut Prefixes) -> OpcodeRec 0x0d => OpcodeRecord::new(Interpretation::Instruction(Opcode::BLENDPD), OperandCode::G_E_xmm_Ib), 0x0e => OpcodeRecord::new(Interpretation::Instruction(Opcode::PBLENDW), OperandCode::G_E_xmm_Ib), 0x0f => OpcodeRecord::new(Interpretation::Instruction(Opcode::PALIGNR), OperandCode::G_E_xmm_Ib), - 0x14 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRB), OperandCode::G_Ev_xmm_Ib), - 0x15 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRW), OperandCode::G_Ev_xmm_Ib), - 0x16 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRD), OperandCode::G_Ev_xmm_Ib), - 0x17 => OpcodeRecord::new(Interpretation::Instruction(Opcode::EXTRACTPS), OperandCode::G_Ev_xmm_Ib), + 0x14 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRB), OperandCode::Ev_G_xmm_Ib), + 0x15 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRW), OperandCode::Ev_G_xmm_Ib), + 0x16 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRD), OperandCode::Ev_G_xmm_Ib), + 0x17 => OpcodeRecord::new(Interpretation::Instruction(Opcode::EXTRACTPS), OperandCode::Ev_G_xmm_Ib), 0x20 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PINSRB), OperandCode::G_Ev_xmm_Ib), 0x21 => OpcodeRecord::new(Interpretation::Instruction(Opcode::INSERTPS), OperandCode::G_Ev_xmm_Ib), 0x22 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PINSRD), OperandCode::G_Ev_xmm_Ib), diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs index 649d979..f803692 100644 --- a/test/long_mode/mod.rs +++ b/test/long_mode/mod.rs @@ -866,14 +866,14 @@ fn test_sse4_1() { test_instr(&[0x66, 0x0f, 0x3a, 0x0e, 0x06, 0x31], "pblendw xmm0, xmmword [rsi], 0x31"); test_invalid(&[0x0f, 0x3a, 0x0e, 0x06]); - test_instr(&[0x66, 0x0f, 0x3a, 0x14, 0x06, 0x31], "pextrb xmm0, byte [rsi], 0x31"); + test_instr(&[0x66, 0x0f, 0x3a, 0x14, 0x06, 0x31], "pextrb byte [rsi], xmm0, 0x31"); test_invalid(&[0x0f, 0x3a, 0x14, 0x06]); - test_instr(&[0x66, 0x0f, 0x3a, 0x15, 0x06, 0x31], "pextrw xmm0, word [rsi], 0x31"); + test_instr(&[0x66, 0x0f, 0x3a, 0x15, 0x06, 0x31], "pextrw word [rsi], xmm0, 0x31"); test_invalid(&[0x0f, 0x3a, 0x15, 0x06]); - test_instr(&[0x66, 0x0f, 0x3a, 0x16, 0x06, 0x31], "pextrd xmm0, dword [rsi], 0x31"); + test_instr(&[0x66, 0x0f, 0x3a, 0x16, 0x06, 0x31], "pextrd dword [rsi], xmm0, 0x31"); test_invalid(&[0x0f, 0x3a, 0x16, 0x06]); - test_instr(&[0x66, 0x48, 0x0f, 0x3a, 0x16, 0x06, 0x31], "pextrq xmm0, qword [rsi], 0x31"); - test_instr(&[0x66, 0x0f, 0x3a, 0x17, 0x06, 0x31], "extractps xmm0, dword [rsi], 0x31"); + test_instr(&[0x66, 0x48, 0x0f, 0x3a, 0x16, 0x06, 0x31], "pextrq qword [rsi], xmm0, 0x31"); + test_instr(&[0x66, 0x0f, 0x3a, 0x17, 0x06, 0x31], "extractps dword [rsi], xmm0, 0x31"); test_invalid(&[0x0f, 0x3a, 0x17, 0x06]); test_instr(&[0x66, 0x0f, 0x3a, 0x20, 0x06, 0x31], "pinsrb xmm0, byte [rsi], 0x31"); diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs index 0ee8696..7f6ebf7 100644 --- a/test/protected_mode/mod.rs +++ b/test/protected_mode/mod.rs @@ -727,13 +727,13 @@ fn test_sse4_1() { test_instr(&[0x66, 0x0f, 0x3a, 0x0e, 0x06, 0x31], "pblendw xmm0, xmmword [esi], 0x31"); test_invalid(&[0x0f, 0x3a, 0x0e, 0x06]); - test_instr(&[0x66, 0x0f, 0x3a, 0x14, 0x06, 0x31], "pextrb xmm0, byte [esi], 0x31"); + test_instr(&[0x66, 0x0f, 0x3a, 0x14, 0x06, 0x31], "pextrb byte [esi], xmm0, 0x31"); test_invalid(&[0x0f, 0x3a, 0x14, 0x06]); - test_instr(&[0x66, 0x0f, 0x3a, 0x15, 0x06, 0x31], "pextrw xmm0, word [esi], 0x31"); + test_instr(&[0x66, 0x0f, 0x3a, 0x15, 0x06, 0x31], "pextrw word [esi], xmm0, 0x31"); test_invalid(&[0x0f, 0x3a, 0x15, 0x06]); - test_instr(&[0x66, 0x0f, 0x3a, 0x16, 0x06, 0x31], "pextrd xmm0, dword [esi], 0x31"); + test_instr(&[0x66, 0x0f, 0x3a, 0x16, 0x06, 0x31], "pextrd dword [esi], xmm0, 0x31"); test_invalid(&[0x0f, 0x3a, 0x16, 0x06]); - test_instr(&[0x66, 0x0f, 0x3a, 0x17, 0x06, 0x31], "extractps xmm0, dword [esi], 0x31"); + test_instr(&[0x66, 0x0f, 0x3a, 0x17, 0x06, 0x31], "extractps dword [esi], xmm0, 0x31"); test_invalid(&[0x0f, 0x3a, 0x17, 0x06]); test_instr(&[0x66, 0x0f, 0x3a, 0x20, 0x06, 0x31], "pinsrb xmm0, byte [esi], 0x31"); diff --git a/test/real_mode/mod.rs b/test/real_mode/mod.rs index d29cda4..af5a315 100644 --- a/test/real_mode/mod.rs +++ b/test/real_mode/mod.rs @@ -16774,6 +16774,10 @@ fn test_real_mode() { test_display(&[0x66, 0x0f, 0x3a, 0x0c, 0xc1, 0x22], "blendps xmm0, xmm1, 0x22"); test_display(&[0x66, 0x0f, 0x3a, 0x0d, 0x11, 0x22], "blendpd xmm2, xmmword [bx + di * 1], 0x22"); test_display(&[0x66, 0x0f, 0x3a, 0x0d, 0xc1, 0x22], "blendpd xmm0, xmm1, 0x22"); + test_display(&[0x66, 0x0f, 0x3a, 0x14, 0x01, 0x31], "pextrb byte [bx + di * 1], xmm0, 0x31"); + test_display(&[0x66, 0x0f, 0x3a, 0x15, 0x01, 0x31], "pextrw word [bx + di * 1], xmm0, 0x31"); + test_display(&[0x66, 0x0f, 0x3a, 0x16, 0x01, 0x31], "pextrd dword [bx + di * 1], xmm0, 0x31"); + test_display(&[0x66, 0x0f, 0x3a, 0x17, 0x01, 0x31], "extractps dword [bx + di * 1], xmm0, 0x31"); test_display(&[0x66, 0x0f, 0x3a, 0x60, 0xc6, 0x54], "pcmpestrm xmm0, xmm6, 0x54"); test_display(&[0x66, 0x0f, 0x3a, 0x61, 0xc6, 0x54], "pcmpestri xmm0, xmm6, 0x54"); test_display(&[0x66, 0x0f, 0x3a, 0x62, 0xc6, 0x54], "pcmpistrm xmm0, xmm6, 0x54"); @@ -18040,8 +18044,12 @@ fn test_invalid_sequences() { test_invalid(&[0x0f, 0x3a, 0x0b, 0x06]); test_invalid(&[0x0f, 0x3a, 0x0e, 0x06]); test_invalid(&[0x0f, 0x3a, 0x14, 0x06]); + test_invalid(&[0x0f, 0x3a, 0x14, 0x06]); + test_invalid(&[0x0f, 0x3a, 0x15, 0x06]); test_invalid(&[0x0f, 0x3a, 0x15, 0x06]); test_invalid(&[0x0f, 0x3a, 0x16, 0x06]); + test_invalid(&[0x0f, 0x3a, 0x16, 0x06]); + test_invalid(&[0x0f, 0x3a, 0x17, 0x06]); test_invalid(&[0x0f, 0x3a, 0x17, 0x06]); test_invalid(&[0x0f, 0x3a, 0x20, 0x06]); test_invalid(&[0x0f, 0x3a, 0x21, 0x06]); |
