aboutsummaryrefslogtreecommitdiff
path: root/src/long_mode
diff options
context:
space:
mode:
Diffstat (limited to 'src/long_mode')
-rw-r--r--src/long_mode/behavior.rs12
-rw-r--r--src/long_mode/display.rs12
-rw-r--r--src/long_mode/mod.rs22
3 files changed, 39 insertions, 7 deletions
diff --git a/src/long_mode/behavior.rs b/src/long_mode/behavior.rs
index 3e1b4a7..478c07a 100644
--- a/src/long_mode/behavior.rs
+++ b/src/long_mode/behavior.rs
@@ -229,8 +229,7 @@ impl Instruction {
}
} else if self.opcode() == Opcode::LOOPNZ
|| self.opcode() == Opcode::LOOPZ
- || self.opcode() == Opcode::LOOP
- || self.opcode() == Opcode::JRCXZ {
+ || self.opcode() == Opcode::LOOP {
if self.prefixes.rex_unchecked().w() {
behavior = behavior
.set_implicit_ops(RW_RCX_IDX);
@@ -3559,7 +3558,7 @@ fn behavior_table_size_is_right() {
}
/// this table MUST line up with Opcode declaration order in `mod.rs`.
-static TABLE: [BehaviorDigest; 1413] = [
+static TABLE: [BehaviorDigest; 1414] = [
/* ADD => */ GENERAL_RW_R_FLAGWRITE,
/* OR => */ GENERAL_RW_R_FLAGWRITE,
/* ADC => */ GENERAL_RW_R_FLAGRW,
@@ -5167,7 +5166,7 @@ static TABLE: [BehaviorDigest; 1413] = [
/* JRCXZ => */ BehaviorDigest::empty()
.set_pl_any()
.set_operand(0, Access::Read)
- .set_nontrivial(true),
+ .set_implicit_ops(RW_RCX_IDX),
// started shipping in Tremont, 2020 sept 23
// while this instruction is marked "write, read", the written first operand is a register
@@ -5871,4 +5870,9 @@ static TABLE: [BehaviorDigest; 1413] = [
.set_pl0()
.set_flags_access(Access::Write)
.set_complex(true),
+
+ /* JECXZ => */ BehaviorDigest::empty()
+ .set_pl_any()
+ .set_operand(0, Access::Read)
+ .set_implicit_ops(RW_ECX_IDX),
];
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs
index f215d07..a00dd22 100644
--- a/src/long_mode/display.rs
+++ b/src/long_mode/display.rs
@@ -2100,6 +2100,8 @@ const MNEMONICS: &[&'static str] = &[
"pvalidate",
"rmpadjust",
"rmpupdate",
+
+ "jecxz",
];
impl Opcode {
@@ -2699,6 +2701,7 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::LOOPZ |
Opcode::LOOP |
Opcode::JRCXZ |
+ Opcode::JECXZ |
Opcode::CALL |
Opcode::CALLF |
Opcode::JMP |
@@ -4018,6 +4021,10 @@ pub(crate) fn contextualize_c<T: DisplaySink>(instr: &Instruction, out: &mut T)
out.write_str("if rcx == 0 then jmp ")?;
write_jmp_operand(instr.operand(0), out)?;
},
+ Opcode::JECXZ => {
+ out.write_str("if ecx == 0 then jmp ")?;
+ write_jmp_operand(instr.operand(0), out)?;
+ },
Opcode::LOOP => {
out.write_str("rcx--; if rcx != 0 then jmp ")?;
write_jmp_operand(instr.operand(0), out)?;
@@ -4216,8 +4223,9 @@ impl <T: fmt::Write, Y: YaxColors> ShowContextual<u64, [Option<alloc::string::St
}
}
-static RELATIVE_BRANCHES: [Opcode; 22] = [
- Opcode::JMP, Opcode::CALL, Opcode::JRCXZ,
+static RELATIVE_BRANCHES: [Opcode; 23] = [
+ Opcode::JMP, Opcode::CALL,
+ Opcode::JRCXZ, Opcode::JECXZ,
Opcode::LOOP, Opcode::LOOPZ, Opcode::LOOPNZ,
Opcode::JO, Opcode::JNO,
Opcode::JB, Opcode::JNB,
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index c477b16..f2fac5b 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -2593,6 +2593,9 @@ pub enum Opcode {
PVALIDATE,
RMPADJUST,
RMPUPDATE,
+
+ // this was present since initial x86-64 but the library missed the prefix handling..
+ JECXZ,
}
impl PartialEq for Instruction {
@@ -4047,6 +4050,7 @@ enum OperandCase {
ModRM_0xf30f38fa,
ModRM_0xf30f38fb,
ModRM_0xf30f3af0,
+ CXZ,
}
#[allow(non_camel_case_types)]
@@ -4381,6 +4385,7 @@ enum OperandCode {
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(),
+ CXZ = OperandCodeBuilder::new().operand_case(OperandCase::CXZ).bits(),
}
fn base_opcode_map(v: u8) -> Opcode {
@@ -4684,7 +4689,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::JRCXZ), OperandCode::Ibs),
+ OpcodeRecord::new(Interpretation::Instruction(Opcode::JRCXZ), 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),
@@ -9117,6 +9122,21 @@ fn read_operands<
instruction.regs[0].bank = RegisterBank::Q;
};
}
+ OperandCase::CXZ => {
+ if instruction.prefixes.address_size() {
+ // address-size overridden from 64-bit to 32-bit
+ instruction.opcode = Opcode::JECXZ;
+ }
+ instruction.imm =
+ read_imm_signed(words, 1)? as u64;
+ 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(())
}