From 99a6378389b99784187058adbea6cfca26963d98 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 22 Feb 2026 23:10:09 +0000 Subject: correct push-immediate memory access size --- src/long_mode/mod.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'src/long_mode') diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 5163ba6..1e1d387 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -3852,7 +3852,8 @@ enum OperandCase { G_E_xmm_Ib, AL_Ibs, AX_Ivd, - Ivs, + PushIbs, + PushIvs, ModRM_0x83, Ed_G_xmm, G_Ed_xmm, @@ -4029,11 +4030,16 @@ enum OperandCase { #[repr(u16)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum OperandCode { - Ivs = OperandCodeBuilder::new().operand_case(OperandCase::Ivs).bits(), I_3 = OperandCodeBuilder::new().operand_case(OperandCase::I_3).bits(), Nothing = OperandCodeBuilder::new().operand_case(OperandCase::Nothing).bits(), Ib = OperandCodeBuilder::new().operand_case(OperandCase::Ib).bits(), Ibs = OperandCodeBuilder::new().only_imm().operand_case(OperandCase::Ibs).bits(), + // `push` of an immediate means we have to set a memory size, but `Ibs` is also the operand + // form for short relative (conditional) branches. to avoid the conditional in that relatively + // hot path, push is a different operand code so we can shove a `mem_size = 8` into the + // instruction later. + PushIbs = OperandCodeBuilder::new().operand_case(OperandCase::PushIbs).bits(), + PushIvs = OperandCodeBuilder::new().operand_case(OperandCase::PushIvs).bits(), Jvds = OperandCodeBuilder::new().only_imm().operand_case(OperandCase::Jvds).bits(), Yv_Xv = OperandCodeBuilder::new().operand_case(OperandCase::Yv_Xv).bits(), @@ -4500,9 +4506,9 @@ const OPCODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::Ivs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::PushIvs), OpcodeRecord::new(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gv_Ev_Iv), - OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::PushIbs), OpcodeRecord::new(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gv_Ev_Ib), OpcodeRecord::new(Interpretation::Instruction(Opcode::INS), OperandCode::Yb_DX), OpcodeRecord::new(Interpretation::Instruction(Opcode::INS), OperandCode::Yv_DX), @@ -5942,6 +5948,18 @@ fn read_operands< OperandCase::Internal | OperandCase::Gv_M | OperandCase::Ibs | OperandCase::Jvds => { } + OperandCase::PushIbs => { + instruction.mem_size = 8; + instruction.imm = read_imm_signed(words, 1)? as u64; + instruction.operands[0] = OperandSpec::ImmI8; + 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.operand_count = 1; + } OperandCase::SingleMMMOper => { instruction.operands[0] = mem_oper; instruction.operand_count = 1; @@ -6484,7 +6502,9 @@ fn read_operands< .with_id(words.offset() as u32 * 8 - numwidth as u32 * 8 + 1) ); } - OperandCase::Ivs => { + OperandCase::PushIvs => { + instruction.mem_size = 8; + if instruction.prefixes.rex_unchecked().w() || !instruction.prefixes.operand_size() { instruction.imm = read_imm_unsigned(words, 4)?; instruction.operands[0] = OperandSpec::ImmI32; -- cgit v1.1