pub fn i64_mul(&mut self) {
        let right = self.pop();
        let left = self.pop();

        if let Some(right) = right.immediate() {
            if let Some(left) = left.immediate() {
                self.push(ValueLocation::Immediate(
                    i64::wrapping_mul(right.as_i64().unwrap(), left.as_i64().unwrap()).into(),
                ));
                return;
            }
        }

        let (mut left, mut right) = match left {
            ValueLocation::Reg(_) => (left, right),
            _ => {
                if right.immediate().is_some() {
                    (left, right)
                } else {
                    (right, left)
                }
            }
        };

        let out = match right {
            ValueLocation::Reg(_) | ValueLocation::Cond(_) => {
                let rreg = self.into_reg(I64, &mut right).unwrap();
                let lreg = self.into_temp_reg(I64, &mut left).unwrap();
                dynasm!(self.asm
                    ; imul Rq(lreg.rq().unwrap()), Rq(rreg.rq().unwrap())
                );
                left
            }
            ValueLocation::Stack(offset) => {
                let offset = self.adjusted_offset(offset);

                let lreg = self.into_temp_reg(I64, &mut left).unwrap();
                dynasm!(self.asm
                    ; imul Rq(lreg.rq().unwrap()), [rsp + offset]
                );
                left
            }
            ValueLocation::Immediate(i) => {
                let i = i.as_i64().unwrap();
                if let Some(i) = i.try_into() {
                    let new_reg = self.take_reg(I64).unwrap();
                    let lreg = self.into_reg(I64, &mut left).unwrap();

                    dynasm!(self.asm
                        ; imul Rq(new_reg.rq().unwrap()), Rq(lreg.rq().unwrap()), i
                    );

                    self.free_value(left);

                    ValueLocation::Reg(new_reg)
                } else {
                    let rreg = self.into_reg(I64, &mut right).unwrap();
                    let lreg = self.into_temp_reg(I64, &mut left).unwrap();
                    dynasm!(self.asm
                        ; imul Rq(lreg.rq().unwrap()), Rq(rreg.rq().unwrap())
                    );
                    left
                }
            }
        };

        self.push(out);
        self.free_value(right);
    }
// `i64_mul` needs to be separate because the immediate form of the instruction
// has a different syntax to the immediate form of the other instructions.
`i64_mul` needs to be separate because the immediate form of the instruction
has a different syntax to the immediate form of the other instructions.
` i64_mul ` needs to be separate because the immediate form of the instruction has a different syntax to the immediate form of the other instructions .
pub fn i64_mul(&mut self) {
        let right = self.pop();
        let left = self.pop();
        if let Some(right) = right.immediate() {
            if let Some(left) = left.immediate() {
                self.push(ValueLocation::Immediate(
                    i64::wrapping_mul(right.as_i64().unwrap(), left.as_i64().unwrap()).into(),
                ));
                return;
            }
        }
        let (mut left, mut right) = match left {
            ValueLocation::Reg(_) => (left, right),
            _ => {
                if right.immediate().is_some() {
                    (left, right)
                } else {
                    (right, left)
                }
            }
        };
        let out = match right {
            ValueLocation::Reg(_) | ValueLocation::Cond(_) => {
                let rreg = self.into_reg(I64, &mut right).unwrap();
                let lreg = self.into_temp_reg(I64, &mut left).unwrap();
                dynasm!(self.asm
                    ; imul Rq(lreg.rq().unwrap()), Rq(rreg.rq().unwrap())
                );
                left
            }
            ValueLocation::Stack(offset) => {
                let offset = self.adjusted_offset(offset);
                let lreg = self.into_temp_reg(I64, &mut left).unwrap();
                dynasm!(self.asm
                    ; imul Rq(lreg.rq().unwrap()), [rsp + offset]
                );
                left
            }
            ValueLocation::Immediate(i) => {
                let i = i.as_i64().unwrap();
                if let Some(i) = i.try_into() {
                    let new_reg = self.take_reg(I64).unwrap();
                    let lreg = self.into_reg(I64, &mut left).unwrap();
                    dynasm!(self.asm
                        ; imul Rq(new_reg.rq().unwrap()), Rq(lreg.rq().unwrap()), i
                    );
                    self.free_value(left);
                    ValueLocation::Reg(new_reg)
                } else {
                    let rreg = self.into_reg(I64, &mut right).unwrap();
                    let lreg = self.into_temp_reg(I64, &mut left).unwrap();
                    dynasm!(self.asm
                        ; imul Rq(lreg.rq().unwrap()), Rq(rreg.rq().unwrap())
                    );
                    left
                }
            }
        };
        self.push(out);
        self.free_value(right);
    }
pub fn i64_mul ( & mut self ) { let right = self . pop ( ) ; let left = self . pop ( ) ; if let Some ( right ) = right . immediate ( ) { if let Some ( left ) = left . immediate ( ) { self . push ( ValueLocation :: Immediate ( i64 :: wrapping_mul ( right . as_i64 ( ) . unwrap ( ) , left . as_i64 ( ) . unwrap ( ) ) . into ( ) , ) ) ; return ; } } let ( mut left , mut right ) = match left { ValueLocation :: Reg ( _ ) => ( left , right ) , _ => { if right . immediate ( ) . is_some ( ) { ( left , right ) } else { ( right , left ) } } } ; let out = match right { ValueLocation :: Reg ( _ ) | ValueLocation :: Cond ( _ ) => { let rreg = self . into_reg ( I64 , & mut right ) . unwrap ( ) ; let lreg = self . into_temp_reg ( I64 , & mut left ) . unwrap ( ) ; dynasm ! ( self asm imul Rq ( lreg rq ( ) unwrap ( ) ) Rq ( rreg rq ( ) unwrap ( ) ) ) ; left } ValueLocation :: Stack ( offset ) => { let offset = self . adjusted_offset ( offset ) ; let lreg = self . into_temp_reg ( I64 , & mut left ) . unwrap ( ) ; dynasm ! ( self asm imul Rq ( lreg rq ( ) unwrap ( ) ) [ rsp offset ] ) ; left } ValueLocation :: Immediate ( i ) => { let i = i . as_i64 ( ) . unwrap ( ) ; if let Some ( i ) = i . try_into ( ) { let new_reg = self . take_reg ( I64 ) . unwrap ( ) ; let lreg = self . into_reg ( I64 , & mut left ) . unwrap ( ) ; dynasm ! ( self asm imul Rq ( new_reg rq ( ) unwrap ( ) ) Rq ( lreg rq ( ) unwrap ( ) ) i ) ; self . free_value ( left ) ; ValueLocation :: Reg ( new_reg ) } else { let rreg = self . into_reg ( I64 , & mut right ) . unwrap ( ) ; let lreg = self . into_temp_reg ( I64 , & mut left ) . unwrap ( ) ; dynasm ! ( self asm imul Rq ( lreg rq ( ) unwrap ( ) ) Rq ( rreg rq ( ) unwrap ( ) ) ) ; left } } } ; self . push ( out ) ; self . free_value ( right ) ; }
`i64_mul` needs to be separate because the immediate form of the instruction
has a different syntax to the immediate form of the other instructions.
` i64_mul ` needs to be separate because the immediate form of the instruction has a different syntax to the immediate form of the other instructions .
&mut self