@instruction<EOL><INDENT>def IMUL(cpu, *operands):<DEDENT>
dest = operands[<NUM_LIT:0>]<EOL>OperandSize = dest.size<EOL>reg_name_h = {<NUM_LIT:8>: '<STR_LIT>', <NUM_LIT:16>: '<STR_LIT>', <NUM_LIT:32>: '<STR_LIT>', <NUM_LIT:64>: '<STR_LIT>'}[OperandSize]<EOL>reg_name_l = {<NUM_LIT:8>: '<STR_LIT>', <NUM_LIT:16>: '<STR_LIT>', <NUM_LIT:32>: '<STR_LIT>', <NUM_LIT:64>: '<STR_LIT>'}[OperandSize]<EOL>arg0 = dest.read()<EOL>arg1 = None<EOL>arg2 = None<EOL>res = None<EOL>if len(operands) == <NUM_LIT:1>:<EOL><INDENT>arg1 = cpu.read_register(reg_name_l)<EOL>temp = (Operators.SEXTEND(arg0, OperandSize, OperandSize * <NUM_LIT:2>) *<EOL>Operators.SEXTEND(arg1, OperandSize, OperandSize * <NUM_LIT:2>))<EOL>temp = temp & ((<NUM_LIT:1> << (OperandSize * <NUM_LIT:2>)) - <NUM_LIT:1>)<EOL>cpu.write_register(reg_name_l,<EOL>Operators.EXTRACT(temp, <NUM_LIT:0>, OperandSize))<EOL>cpu.write_register(reg_name_h,<EOL>Operators.EXTRACT(temp, OperandSize, OperandSize))<EOL>res = Operators.EXTRACT(temp, <NUM_LIT:0>, OperandSize)<EOL><DEDENT>elif len(operands) == <NUM_LIT:2>:<EOL><INDENT>arg1 = operands[<NUM_LIT:1>].read()<EOL>arg1 = Operators.SEXTEND(arg1, OperandSize, OperandSize * <NUM_LIT:2>)<EOL>temp = Operators.SEXTEND(arg0, OperandSize, OperandSize * <NUM_LIT:2>) * arg1<EOL>temp = temp & ((<NUM_LIT:1> << (OperandSize * <NUM_LIT:2>)) - <NUM_LIT:1>)<EOL>res = dest.write(Operators.EXTRACT(temp, <NUM_LIT:0>, OperandSize))<EOL><DEDENT>else:<EOL><INDENT>arg1 = operands[<NUM_LIT:1>].read()<EOL>arg2 = operands[<NUM_LIT:2>].read()<EOL>temp = (Operators.SEXTEND(arg1, OperandSize, OperandSize * <NUM_LIT:2>) *<EOL>Operators.SEXTEND(arg2, operands[<NUM_LIT:2>].size, OperandSize * <NUM_LIT:2>))<EOL>temp = temp & ((<NUM_LIT:1> << (OperandSize * <NUM_LIT:2>)) - <NUM_LIT:1>)<EOL>res = dest.write(Operators.EXTRACT(temp, <NUM_LIT:0>, OperandSize))<EOL><DEDENT>cpu.CF = (Operators.SEXTEND(res, OperandSize, OperandSize * <NUM_LIT:2>) != temp)<EOL>cpu.OF = cpu.CF<EOL>
Signed multiply.

Performs a signed multiplication of two operands. This instruction has
three forms, depending on the number of operands.
    - One-operand form. This form is identical to that used by the MUL
    instruction. Here, the source operand (in a general-purpose
    register or memory location) is multiplied by the value in the AL,
    AX, or EAX register (depending on the operand size) and the product
    is stored in the AX, DX:AX, or EDX:EAX registers, respectively.
    - Two-operand form. With this form the destination operand (the
    first operand) is multiplied by the source operand (second
    operand). The destination operand is a general-purpose register and
    the source operand is an immediate value, a general-purpose
    register, or a memory location. The product is then stored in the
    destination operand location.
    - Three-operand form. This form requires a destination operand (the
    first operand) and two source operands (the second and the third
    operands). Here, the first source operand (which can be a
    general-purpose register or a memory location) is multiplied by the
    second source operand (an immediate value). The product is then
    stored in the destination operand (a general-purpose register).

When an immediate value is used as an operand, it is sign-extended to
the length of the destination operand format. The CF and OF flags are
set when significant bits are carried into the upper half of the
result. The CF and OF flags are cleared when the result fits exactly in
the lower half of the result. The three forms of the IMUL instruction
are similar in that the length of the product is calculated to twice
the length of the operands. With the one-operand form, the product is
stored exactly in the destination. With the two- and three- operand
forms, however, result is truncated to the length of the destination
before it is stored in the destination register. Because of this
truncation, the CF or OF flag should be tested to ensure that no
significant bits are lost. The two- and three-operand forms may also be
used with unsigned operands because the lower half of the product is
the same regardless if the operands are signed or unsigned. The CF and
OF flags, however, cannot be used to determine if the upper half of the
result is non-zero::

IF (NumberOfOperands == 1)
THEN
    IF (OperandSize == 8)
    THEN
        AX = AL * SRC (* Signed multiplication *)
        IF AL == AX
        THEN
            CF = 0; OF = 0;
        ELSE
            CF = 1; OF = 1;
        FI;
    ELSE
        IF OperandSize == 16
        THEN
            DX:AX = AX * SRC (* Signed multiplication *)
            IF sign_extend_to_32 (AX) == DX:AX
            THEN
                CF = 0; OF = 0;
            ELSE
                CF = 1; OF = 1;
            FI;
        ELSE
            IF OperandSize == 32
            THEN
                EDX:EAX = EAX * SRC (* Signed multiplication *)
                IF EAX == EDX:EAX
                THEN
                    CF = 0; OF = 0;
                ELSE
                    CF = 1; OF = 1;
                FI;
            ELSE (* OperandSize = 64 *)
                RDX:RAX = RAX * SRC (* Signed multiplication *)
                IF RAX == RDX:RAX
                THEN
                    CF = 0; OF = 0;
                ELSE
                   CF = 1; OF = 1;
                FI;
            FI;
        FI;
ELSE
    IF (NumberOfOperands = 2)
    THEN
        temp = DEST * SRC (* Signed multiplication; temp is double DEST size *)
        DEST = DEST * SRC (* Signed multiplication *)
        IF temp != DEST
        THEN
            CF = 1; OF = 1;
        ELSE
            CF = 0; OF = 0;
        FI;
    ELSE (* NumberOfOperands = 3 *)
        DEST = SRC1 * SRC2 (* Signed multiplication *)
        temp = SRC1 * SRC2 (* Signed multiplication; temp is double SRC1 size *)
        IF temp != DEST
        THEN
            CF = 1; OF = 1;
        ELSE
            CF = 0; OF = 0;
        FI;
    FI;
FI;

:param cpu: current CPU.
:param operands: variable list of operands.