aboutsummaryrefslogtreecommitdiff
path: root/src/protected_mode
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2026-06-08 07:20:41 +0000
committeriximeow <me@iximeow.net>2026-07-05 00:09:22 +0000
commit15b8817b2eda4c2f58fc098591677f77c34c454d (patch)
treea80541deccd81c4791a45a20bd62dedcac612a21 /src/protected_mode
parent9b24ada2c3a7afa42448fff7ee441ad983530d88 (diff)
fix vpbroadcast* memory size and source register bank
Diffstat (limited to 'src/protected_mode')
-rw-r--r--src/protected_mode/vex.rs38
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() {