From 15b8817b2eda4c2f58fc098591677f77c34c454d Mon Sep 17 00:00:00 2001 From: iximeow Date: Mon, 8 Jun 2026 07:20:41 +0000 Subject: fix vpbroadcast* memory size and source register bank --- src/long_mode/vex.rs | 38 ++++++++++++++++++++++++++++++++++---- src/protected_mode/vex.rs | 38 ++++++++++++++++++++++++++++++++++---- src/real_mode/vex.rs | 38 ++++++++++++++++++++++++++++++++++---- 3 files changed, 102 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs index 6ae12ad..b787598 100644 --- a/src/long_mode/vex.rs +++ b/src/long_mode/vex.rs @@ -76,6 +76,7 @@ enum VEXOperandCode { G_E_xyLmm, E_G_xyLmm, G_E_xyLmm_imm8, + G_Lmm_E_xmm, G_V_E_xyLmm_imm8, G_V_E_xmm, G_V_E_xmm_imm8, @@ -1200,6 +1201,35 @@ fn read_vex_operands< instruction.operand_count = 2; Ok(()) } + VEXOperandCode::G_Lmm_E_xmm => { + if instruction.regs[3].num != 0 { + return Err(DecodeError::InvalidOperand); + } + // the name of this bit is `L` in the documentation, so use the same name here. + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + let bank = if L { RegisterBank::Y } else { RegisterBank::X }; + + let modrm = read_modrm(words)?; + instruction.regs[0] = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), bank); + let mem_oper = read_E(words, instruction, modrm, RegisterBank::X, sink)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + if instruction.opcode == Opcode::VPBROADCASTB { + instruction.mem_size = 1; + } else if instruction.opcode == Opcode::VPBROADCASTW { + instruction.mem_size = 2; + } else if instruction.opcode == Opcode::VPBROADCASTD { + instruction.mem_size = 4; + } else if instruction.opcode == Opcode::VPBROADCASTQ { + instruction.mem_size = 8; + }; + } + instruction.operand_count = 2; + Ok(()) + } VEXOperandCode::G_V_E_xyLmm => { let modrm = read_modrm(words)?; // the name of this bit is `L` in the documentation, so use the same name here. @@ -2301,12 +2331,12 @@ fn read_vex_instruction< 0x58 => if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } else { - (Opcode::VPBROADCASTD, VEXOperandCode::G_E_xyLmm) + (Opcode::VPBROADCASTD, VEXOperandCode::G_Lmm_E_xmm) }, 0x59 => if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } else { - (Opcode::VPBROADCASTQ, VEXOperandCode::G_E_xyLmm) + (Opcode::VPBROADCASTQ, VEXOperandCode::G_Lmm_E_xmm) }, 0x5A => (Opcode::VBROADCASTI128, if L { if instruction.prefixes.vex_unchecked().w() { @@ -2319,12 +2349,12 @@ fn read_vex_instruction< 0x78 => if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } else { - (Opcode::VPBROADCASTB, VEXOperandCode::G_E_xyLmm) + (Opcode::VPBROADCASTB, VEXOperandCode::G_Lmm_E_xmm) }, 0x79 => if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } else { - (Opcode::VPBROADCASTW, VEXOperandCode::G_E_xyLmm) + (Opcode::VPBROADCASTW, VEXOperandCode::G_Lmm_E_xmm) }, 0x8C => { if instruction.prefixes.vex_unchecked().w() { diff --git a/src/protected_mode/vex.rs b/src/protected_mode/vex.rs index 875f010..429ad23 100644 --- a/src/protected_mode/vex.rs +++ b/src/protected_mode/vex.rs @@ -74,6 +74,7 @@ enum VEXOperandCode { G_V_E_xyLmm, G_E_xyLmm, E_G_xyLmm, + G_Lmm_E_xmm, G_E_xyLmm_imm8, G_V_E_xyLmm_imm8, G_V_E_xmm, @@ -1127,6 +1128,35 @@ fn read_vex_operands< instruction.operand_count = 2; Ok(()) } + VEXOperandCode::G_Lmm_E_xmm => { + if instruction.regs[3].num != 0 { + return Err(DecodeError::InvalidOperand); + } + // the name of this bit is `L` in the documentation, so use the same name here. + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + let bank = if L { RegisterBank::Y } else { RegisterBank::X }; + + let modrm = read_modrm(words)?; + instruction.regs[0] = + RegSpec::from_parts((modrm >> 3) & 7, bank); + let mem_oper = read_E(words, instruction, modrm, RegisterBank::X, sink)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + if instruction.opcode == Opcode::VPBROADCASTB { + instruction.mem_size = 1; + } else if instruction.opcode == Opcode::VPBROADCASTW { + instruction.mem_size = 2; + } else if instruction.opcode == Opcode::VPBROADCASTD { + instruction.mem_size = 4; + } else if instruction.opcode == Opcode::VPBROADCASTQ { + instruction.mem_size = 8; + }; + } + instruction.operand_count = 2; + Ok(()) + } VEXOperandCode::G_V_E_xyLmm => { let modrm = read_modrm(words)?; // the name of this bit is `L` in the documentation, so use the same name here. @@ -2172,12 +2202,12 @@ fn read_vex_instruction< 0x58 => if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } else { - (Opcode::VPBROADCASTD, VEXOperandCode::G_E_xyLmm) + (Opcode::VPBROADCASTD, VEXOperandCode::G_Lmm_E_xmm) }, 0x59 => if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } else { - (Opcode::VPBROADCASTQ, VEXOperandCode::G_E_xyLmm) + (Opcode::VPBROADCASTQ, VEXOperandCode::G_Lmm_E_xmm) }, 0x5A => (Opcode::VBROADCASTI128, if L { if instruction.prefixes.vex_unchecked().w() { @@ -2190,12 +2220,12 @@ fn read_vex_instruction< 0x78 => if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } else { - (Opcode::VPBROADCASTB, VEXOperandCode::G_E_xyLmm) + (Opcode::VPBROADCASTB, VEXOperandCode::G_Lmm_E_xmm) }, 0x79 => if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } else { - (Opcode::VPBROADCASTW, VEXOperandCode::G_E_xyLmm) + (Opcode::VPBROADCASTW, VEXOperandCode::G_Lmm_E_xmm) }, 0x8C => { if instruction.prefixes.vex_unchecked().w() { diff --git a/src/real_mode/vex.rs b/src/real_mode/vex.rs index 1c1470a..3a7fbe3 100644 --- a/src/real_mode/vex.rs +++ b/src/real_mode/vex.rs @@ -74,6 +74,7 @@ enum VEXOperandCode { G_V_E_xyLmm, G_E_xyLmm, E_G_xyLmm, + G_Lmm_E_xmm, G_E_xyLmm_imm8, G_V_E_xyLmm_imm8, G_V_E_xmm, @@ -1127,6 +1128,35 @@ fn read_vex_operands< instruction.operand_count = 2; Ok(()) } + VEXOperandCode::G_Lmm_E_xmm => { + if instruction.regs[3].num != 0 { + return Err(DecodeError::InvalidOperand); + } + // the name of this bit is `L` in the documentation, so use the same name here. + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + let bank = if L { RegisterBank::Y } else { RegisterBank::X }; + + let modrm = read_modrm(words)?; + instruction.regs[0] = + RegSpec::from_parts((modrm >> 3) & 7, bank); + let mem_oper = read_E(words, instruction, modrm, RegisterBank::X, sink)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + if instruction.opcode == Opcode::VPBROADCASTB { + instruction.mem_size = 1; + } else if instruction.opcode == Opcode::VPBROADCASTW { + instruction.mem_size = 2; + } else if instruction.opcode == Opcode::VPBROADCASTD { + instruction.mem_size = 4; + } else if instruction.opcode == Opcode::VPBROADCASTQ { + instruction.mem_size = 8; + }; + } + instruction.operand_count = 2; + Ok(()) + } VEXOperandCode::G_V_E_xyLmm => { let modrm = read_modrm(words)?; // the name of this bit is `L` in the documentation, so use the same name here. @@ -2172,12 +2202,12 @@ fn read_vex_instruction< 0x58 => if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } else { - (Opcode::VPBROADCASTD, VEXOperandCode::G_E_xyLmm) + (Opcode::VPBROADCASTD, VEXOperandCode::G_Lmm_E_xmm) }, 0x59 => if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } else { - (Opcode::VPBROADCASTQ, VEXOperandCode::G_E_xyLmm) + (Opcode::VPBROADCASTQ, VEXOperandCode::G_Lmm_E_xmm) }, 0x5A => (Opcode::VBROADCASTI128, if L { if instruction.prefixes.vex_unchecked().w() { @@ -2190,12 +2220,12 @@ fn read_vex_instruction< 0x78 => if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } else { - (Opcode::VPBROADCASTB, VEXOperandCode::G_E_xyLmm) + (Opcode::VPBROADCASTB, VEXOperandCode::G_Lmm_E_xmm) }, 0x79 => if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } else { - (Opcode::VPBROADCASTW, VEXOperandCode::G_E_xyLmm) + (Opcode::VPBROADCASTW, VEXOperandCode::G_Lmm_E_xmm) }, 0x8C => { if instruction.prefixes.vex_unchecked().w() { -- cgit v1.1