pub fn imul(&self, control_flow_graph: &mut ControlFlowGraph) -> Result<()> {
        let detail = self.details()?;

        let block_index = {
            let block = control_flow_graph.new_block()?;

            // Get multiplicand
            let multiplicand = match detail.op_count {
                1 => match detail.operands[0].size {
                    1 => self.get_register(x86_reg::X86_REG_AL)?.get()?,
                    2 => self.get_register(x86_reg::X86_REG_AX)?.get()?,
                    4 => self.get_register(x86_reg::X86_REG_EAX)?.get()?,
                    8 => self.get_register(x86_reg::X86_REG_RAX)?.get()?,
                    _ => bail!("invalid operand size for imul"),
                },
                2 => self.operand_load(block, &detail.operands[0])?,
                3 => self.operand_load(block, &detail.operands[1])?,
                _ => bail!(
                    "invalid number of operands for imul {} at 0x{:x}",
                    detail.op_count,
                    self.instruction().address
                ),
            };

            // Get multiplier
            let multiplier = match detail.op_count {
                1 => self.operand_load(block, &detail.operands[0])?,
                2 => {
                    let multiplier = self.operand_load(block, &detail.operands[1])?;
                    if multiplier.bits() < multiplicand.bits() {
                        Expr::sext(multiplicand.bits(), multiplier)?
                    } else {
                        multiplier
                    }
                }
                3 => {
                    let multiplier = self.operand_load(block, &detail.operands[2])?;
                    if multiplier.bits() < multiplicand.bits() {
                        Expr::sext(multiplicand.bits(), multiplier)?
                    } else {
                        multiplier
                    }
                }
                _ => bail!("invalid number of operands for imul"),
            };

            // Perform multiplication
            let bit_width = multiplicand.bits() * 2;

            let result = self.temp(0, bit_width);
            block.assign(
                result.clone(),
                Expr::mul(
                    Expr::zext(bit_width, multiplicand)?,
                    Expr::zext(bit_width, multiplier)?,
                )?,
            );

            // Set the result
            match detail.op_count {
                1 => match detail.operands[0].size {
                    1 => self
                        .get_register(x86_reg::X86_REG_AX)?
                        .set(block, result.clone().into())?,
                    2 => {
                        let dx = self.get_register(x86_reg::X86_REG_DX)?;
                        let ax = self.get_register(x86_reg::X86_REG_AX)?;
                        let expr = Expr::shr(result.clone().into(), expr_const(16, 32))?;
                        dx.set(block, Expr::trun(16, expr)?)?;
                        ax.set(block, Expr::trun(16, result.clone().into())?)?;
                    }
                    4 => {
                        let edx = self.get_register(x86_reg::X86_REG_EDX)?;
                        let eax = self.get_register(x86_reg::X86_REG_EAX)?;
                        let expr = Expr::shr(result.clone().into(), expr_const(32, 64))?;
                        edx.set(block, Expr::trun(32, expr)?)?;
                        eax.set(block, Expr::trun(32, result.clone().into())?)?;
                    }
                    8 => {
                        let rdx = self.get_register(x86_reg::X86_REG_RDX)?;
                        let rax = self.get_register(x86_reg::X86_REG_RAX)?;
                        let expr = Expr::shr(result.clone().into(), expr_const(64, 128))?;
                        rdx.set(block, Expr::trun(64, expr)?)?;
                        rax.set(block, Expr::trun(64, result.clone().into())?)?;
                    }
                    _ => bail!("Invalid operand size for imul"),
                },
                2 => {
                    let expr = Expr::trun(bit_width / 2, result.clone().into())?;
                    self.operand_store(block, &detail.operands[0], expr)?;
                }
                3 => {
                    let expr = Expr::trun(bit_width / 2, result.clone().into())?;
                    self.operand_store(block, &detail.operands[0], expr)?;
                }
                _ => bail!("invalid number of operands for imul"),
            }

            // Set flags
            block.assign(
                scalar("OF", 1),
                Expr::cmpneq(
                    Expr::trun(
                        bit_width / 2,
                        Expr::shr(result.into(), expr_const((bit_width / 2) as u64, bit_width))?,
                    )?,
                    expr_const(0, bit_width / 2),
                )?,
            );
            block.assign(scalar("CF", 1), expr_scalar("OF", 1));

            block.index()
        };

        control_flow_graph.set_entry(block_index)?;
        control_flow_graph.set_exit(block_index)?;

        Ok(())
    }
// If we have one operand, we go in AX, DX:AX, EDX:EAX
// If we have two operands, sign-extend rhs if required, go in 0 operand
// If we have three operands, sign-extend rhs if required, go in 0 operand
If we have one operand, we go in AX, DX:AX, EDX:EAX
If we have two operands, sign-extend rhs if required, go in 0 operand
If we have three operands, sign-extend rhs if required, go in 0 operand
If we have one operand we go in AX DX : AX EDX : EAX If we have two operands sign - extend rhs if required go in 0 operand If we have three operands sign - extend rhs if required go in 0 operand
pub fn imul(&self, control_flow_graph: &mut ControlFlowGraph) -> Result<()> {
        let detail = self.details()?;
        let block_index = {
            let block = control_flow_graph.new_block()?;
            // Get multiplicand
            let multiplicand = match detail.op_count {
                1 => match detail.operands[0].size {
                    1 => self.get_register(x86_reg::X86_REG_AL)?.get()?,
                    2 => self.get_register(x86_reg::X86_REG_AX)?.get()?,
                    4 => self.get_register(x86_reg::X86_REG_EAX)?.get()?,
                    8 => self.get_register(x86_reg::X86_REG_RAX)?.get()?,
                    _ => bail!("invalid operand size for imul"),
                },
                2 => self.operand_load(block, &detail.operands[0])?,
                3 => self.operand_load(block, &detail.operands[1])?,
                _ => bail!(
                    "invalid number of operands for imul {} at 0x{:x}",
                    detail.op_count,
                    self.instruction().address
                ),
            };
            // Get multiplier
            let multiplier = match detail.op_count {
                1 => self.operand_load(block, &detail.operands[0])?,
                2 => {
                    let multiplier = self.operand_load(block, &detail.operands[1])?;
                    if multiplier.bits() < multiplicand.bits() {
                        Expr::sext(multiplicand.bits(), multiplier)?
                    } else {
                        multiplier
                    }
                }
                3 => {
                    let multiplier = self.operand_load(block, &detail.operands[2])?;
                    if multiplier.bits() < multiplicand.bits() {
                        Expr::sext(multiplicand.bits(), multiplier)?
                    } else {
                        multiplier
                    }
                }
                _ => bail!("invalid number of operands for imul"),
            };
            // Perform multiplication
            let bit_width = multiplicand.bits() * 2;
            let result = self.temp(0, bit_width);
            block.assign(
                result.clone(),
                Expr::mul(
                    Expr::zext(bit_width, multiplicand)?,
                    Expr::zext(bit_width, multiplier)?,
                )?,
            );
            // Set the result
            match detail.op_count {
                1 => match detail.operands[0].size {
                    1 => self
                        .get_register(x86_reg::X86_REG_AX)?
                        .set(block, result.clone().into())?,
                    2 => {
                        let dx = self.get_register(x86_reg::X86_REG_DX)?;
                        let ax = self.get_register(x86_reg::X86_REG_AX)?;
                        let expr = Expr::shr(result.clone().into(), expr_const(16, 32))?;
                        dx.set(block, Expr::trun(16, expr)?)?;
                        ax.set(block, Expr::trun(16, result.clone().into())?)?;
                    }
                    4 => {
                        let edx = self.get_register(x86_reg::X86_REG_EDX)?;
                        let eax = self.get_register(x86_reg::X86_REG_EAX)?;
                        let expr = Expr::shr(result.clone().into(), expr_const(32, 64))?;
                        edx.set(block, Expr::trun(32, expr)?)?;
                        eax.set(block, Expr::trun(32, result.clone().into())?)?;
                    }
                    8 => {
                        let rdx = self.get_register(x86_reg::X86_REG_RDX)?;
                        let rax = self.get_register(x86_reg::X86_REG_RAX)?;
                        let expr = Expr::shr(result.clone().into(), expr_const(64, 128))?;
                        rdx.set(block, Expr::trun(64, expr)?)?;
                        rax.set(block, Expr::trun(64, result.clone().into())?)?;
                    }
                    _ => bail!("Invalid operand size for imul"),
                },
                2 => {
                    let expr = Expr::trun(bit_width / 2, result.clone().into())?;
                    self.operand_store(block, &detail.operands[0], expr)?;
                }
                3 => {
                    let expr = Expr::trun(bit_width / 2, result.clone().into())?;
                    self.operand_store(block, &detail.operands[0], expr)?;
                }
                _ => bail!("invalid number of operands for imul"),
            }
            // Set flags
            block.assign(
                scalar("OF", 1),
                Expr::cmpneq(
                    Expr::trun(
                        bit_width / 2,
                        Expr::shr(result.into(), expr_const((bit_width / 2) as u64, bit_width))?,
                    )?,
                    expr_const(0, bit_width / 2),
                )?,
            );
            block.assign(scalar("CF", 1), expr_scalar("OF", 1));
            block.index()
        };
        control_flow_graph.set_entry(block_index)?;
        control_flow_graph.set_exit(block_index)?;
        Ok(())
    }
pub fn imul ( & self , control_flow_graph : & mut ControlFlowGraph ) -> Result < ( ) > { let detail = self . details ( ) ? ; let block_index = { let block = control_flow_graph . new_block ( ) ? ; // Get multiplicand let multiplicand = match detail . op_count { 1 => match detail . operands [ 0 ] . size { 1 => self . get_register ( x86_reg :: X86_REG_AL ) ? . get ( ) ? , 2 => self . get_register ( x86_reg :: X86_REG_AX ) ? . get ( ) ? , 4 => self . get_register ( x86_reg :: X86_REG_EAX ) ? . get ( ) ? , 8 => self . get_register ( x86_reg :: X86_REG_RAX ) ? . get ( ) ? , _ => bail ! ( " " ) , } , 2 => self . operand_load ( block , & detail . operands [ 0 ] ) ? , 3 => self . operand_load ( block , & detail . operands [ 1 ] ) ? , _ => bail ! ( " " detail op_count self instruction ( ) address ) , } ; // Get multiplier let multiplier = match detail . op_count { 1 => self . operand_load ( block , & detail . operands [ 0 ] ) ? , 2 => { let multiplier = self . operand_load ( block , & detail . operands [ 1 ] ) ? ; if multiplier . bits ( ) < multiplicand . bits ( ) { Expr :: sext ( multiplicand . bits ( ) , multiplier ) ? } else { multiplier } } 3 => { let multiplier = self . operand_load ( block , & detail . operands [ 2 ] ) ? ; if multiplier . bits ( ) < multiplicand . bits ( ) { Expr :: sext ( multiplicand . bits ( ) , multiplier ) ? } else { multiplier } } _ => bail ! ( " " ) , } ; // Perform multiplication let bit_width = multiplicand . bits ( ) * 2 ; let result = self . temp ( 0 , bit_width ) ; block . assign ( result . clone ( ) , Expr :: mul ( Expr :: zext ( bit_width , multiplicand ) ? , Expr :: zext ( bit_width , multiplier ) ? , ) ? , ) ; // Set the result match detail . op_count { 1 => match detail . operands [ 0 ] . size { 1 => self . get_register ( x86_reg :: X86_REG_AX ) ? . set ( block , result . clone ( ) . into ( ) ) ? , 2 => { let dx = self . get_register ( x86_reg :: X86_REG_DX ) ? ; let ax = self . get_register ( x86_reg :: X86_REG_AX ) ? ; let expr = Expr :: shr ( result . clone ( ) . into ( ) , expr_const ( 16 , 32 ) ) ? ; dx . set ( block , Expr :: trun ( 16 , expr ) ? ) ? ; ax . set ( block , Expr :: trun ( 16 , result . clone ( ) . into ( ) ) ? ) ? ; } 4 => { let edx = self . get_register ( x86_reg :: X86_REG_EDX ) ? ; let eax = self . get_register ( x86_reg :: X86_REG_EAX ) ? ; let expr = Expr :: shr ( result . clone ( ) . into ( ) , expr_const ( 32 , 64 ) ) ? ; edx . set ( block , Expr :: trun ( 32 , expr ) ? ) ? ; eax . set ( block , Expr :: trun ( 32 , result . clone ( ) . into ( ) ) ? ) ? ; } 8 => { let rdx = self . get_register ( x86_reg :: X86_REG_RDX ) ? ; let rax = self . get_register ( x86_reg :: X86_REG_RAX ) ? ; let expr = Expr :: shr ( result . clone ( ) . into ( ) , expr_const ( 64 , 128 ) ) ? ; rdx . set ( block , Expr :: trun ( 64 , expr ) ? ) ? ; rax . set ( block , Expr :: trun ( 64 , result . clone ( ) . into ( ) ) ? ) ? ; } _ => bail ! ( " " ) , } , 2 => { let expr = Expr :: trun ( bit_width / 2 , result . clone ( ) . into ( ) ) ? ; self . operand_store ( block , & detail . operands [ 0 ] , expr ) ? ; } 3 => { let expr = Expr :: trun ( bit_width / 2 , result . clone ( ) . into ( ) ) ? ; self . operand_store ( block , & detail . operands [ 0 ] , expr ) ? ; } _ => bail ! ( " " ) , } // Set flags block . assign ( scalar ( " " , 1 ) , Expr :: cmpneq ( Expr :: trun ( bit_width / 2 , Expr :: shr ( result . into ( ) , expr_const ( ( bit_width / 2 ) as u64 , bit_width ) ) ? , ) ? , expr_const ( 0 , bit_width / 2 ) , ) ? , ) ; block . assign ( scalar ( " " , 1 ) , expr_scalar ( " " , 1 ) ) ; block . index ( ) } ; control_flow_graph . set_entry ( block_index ) ? ; control_flow_graph . set_exit ( block_index ) ? ; Ok ( ( ) ) }
If we have one operand, we go in AX, DX:AX, EDX:EAX
If we have two operands, sign-extend rhs if required, go in 0 operand
If we have three operands, sign-extend rhs if required, go in 0 operand
If we have one operand we go in AX DX : AX EDX : EAX If we have two operands sign - extend rhs if required go in 0 operand If we have three operands sign - extend rhs if required go in 0 operand
&self
control_flow_graph
&mut ControlFlowGraph
&self
control_flow_graph
&mut ControlFlowGraph