aboutsummaryrefslogtreecommitdiff
path: root/src/real_mode/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/real_mode/mod.rs')
-rw-r--r--src/real_mode/mod.rs40
1 files changed, 37 insertions, 3 deletions
diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs
index f538fa5..8dd29b1 100644
--- a/src/real_mode/mod.rs
+++ b/src/real_mode/mod.rs
@@ -2508,6 +2508,13 @@ pub enum Opcode {
PVALIDATE,
RMPADJUST,
RMPUPDATE,
+
+ // these were part of the base (i386) ISA but were reported as distinct opcodes relatively late.
+ PUSHAD,
+ POPAD,
+
+ // likewise with alternate-size jecxz/jcxz..
+ JECXZ,
}
impl PartialEq for Instruction {
@@ -3992,6 +3999,7 @@ enum OperandCase {
ModRM_0xf30f38fa,
ModRM_0xf30f38fb,
ModRM_0xf30f3af0,
+ CXZ, // catch-all for "j*cxz and prefix handling"
}
#[allow(non_camel_case_types)]
@@ -4319,6 +4327,7 @@ enum OperandCode {
ModRM_0xc4 = OperandCodeBuilder::new().operand_case(OperandCase::ModRM_0xc4).bits(),
ModRM_0xc5 = OperandCodeBuilder::new().operand_case(OperandCase::ModRM_0xc5).bits(),
MASKMOVDQU = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::MASKMOVDQU).bits(),
+ CXZ = OperandCodeBuilder::new().operand_case(OperandCase::CXZ).bits(),
}
fn base_opcode_map(v: u8) -> Opcode {
@@ -4622,7 +4631,7 @@ const OPCODES: [OpcodeRecord; 256] = [
OpcodeRecord::new(Interpretation::Instruction(Opcode::LOOPNZ), OperandCode::Ibs),
OpcodeRecord::new(Interpretation::Instruction(Opcode::LOOPZ), OperandCode::Ibs),
OpcodeRecord::new(Interpretation::Instruction(Opcode::LOOP), OperandCode::Ibs),
- OpcodeRecord::new(Interpretation::Instruction(Opcode::JCXZ), OperandCode::Ibs),
+ OpcodeRecord::new(Interpretation::Instruction(Opcode::JCXZ), OperandCode::CXZ),
OpcodeRecord::new(Interpretation::Instruction(Opcode::IN), OperandCode::AL_Ib),
OpcodeRecord::new(Interpretation::Instruction(Opcode::IN), OperandCode::AX_Ib),
OpcodeRecord::new(Interpretation::Instruction(Opcode::OUT), OperandCode::Ib_AL),
@@ -6510,9 +6519,19 @@ fn read_operands<
} else if instruction.opcode == Opcode::XLAT {
instruction.mem_size = 1;
} else if instruction.opcode == Opcode::PUSHA {
- instruction.mem_size = 2 * 8;
+ if !instruction.prefixes.operand_size() {
+ instruction.mem_size = 2 * 8;
+ } else {
+ instruction.opcode = Opcode::PUSHAD;
+ instruction.mem_size = 4 * 8;
+ }
} else if instruction.opcode == Opcode::POPA {
- instruction.mem_size = 2 * 8;
+ if !instruction.prefixes.operand_size() {
+ instruction.mem_size = 2 * 8;
+ } else {
+ instruction.opcode = Opcode::POPAD;
+ instruction.mem_size = 4 * 8;
+ }
}
instruction.operands[0] = OperandSpec::Nothing;
instruction.operand_count = 0;
@@ -9050,6 +9069,21 @@ fn read_operands<
instruction.mem_size = 2;
instruction.operand_count = 2;
},
+ OperandCase::CXZ => {
+ if instruction.prefixes.address_size() {
+ // address-size overridden from 16-bit to 32-bit
+ instruction.opcode = Opcode::JECXZ;
+ }
+ instruction.imm =
+ read_imm_signed(words, 1)? as u32;
+ sink.record(
+ words.offset() as u32 * 8 - 8,
+ words.offset() as u32 * 8 - 1,
+ InnerDescription::Number("1-byte immediate", instruction.imm as i64)
+ .with_id(words.offset() as u32 * 8),
+ );
+ instruction.operands[0] = OperandSpec::ImmI8;
+ },
};
Ok(())
}