diff options
| author | iximeow <me@iximeow.net> | 2026-06-08 07:20:41 +0000 |
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2026-07-05 00:09:22 +0000 |
| commit | 15b8817b2eda4c2f58fc098591677f77c34c454d (patch) | |
| tree | a80541deccd81c4791a45a20bd62dedcac612a21 /src/protected_mode | |
| parent | 9b24ada2c3a7afa42448fff7ee441ad983530d88 (diff) | |
fix vpbroadcast* memory size and source register bank
Diffstat (limited to 'src/protected_mode')
| -rw-r--r-- | src/protected_mode/vex.rs | 38 |
1 files changed, 34 insertions, 4 deletions
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() { |
