Press enter to see results or esc to cancel.

Integer Multiplication

This procedure generates code to multiply integer with integer. Multiplication with power of 2 is translated to shift, other special cases (0, 1, 3, 5, 6) are also treated separately. Result is stored in specified Register if possible.

Procedure TExpression.IntegerMultiplicationWithConstant (Register: Byte; Factor: Integer);
Var ShiftCount: ShortInt;
    TempFactor: Word;

  Procedure GeneralIntegerMultiplicationWithConstant;
  begin
    Case Instructions80286 in StatementCompilerSwitches of
      True: If Factor = ShortInt (Factor) then
              begin
                GenerateInstructionWithExpressionInMemOrReg (IMUL_Reg_SignExtendImmediateByte, Register shl 3);
                GenerateInstruction_Byte (Factor);
              end else begin
                         GenerateInstructionWithExpressionInMemOrReg (IMUL_Reg_Opearations, Register shl 3);
                         GenerateInstruction_Word (Factor);
                       end;
      else begin
             Include (Usedregisters, urDX);
             If (Location = elRegister) and (LocationData.Register = rAX) then
               begin
                 GenerateInstruction_Byte (MOV_DX_Immediate);
                 GenerateInstruction_Word (Factor);
                 GenerateInstruction_Word (MUL_DX);
                 Exit;
               end else begin
                          GenerateInstruction_Byte (MOV_AX_Immediate);
                          GenerateInstruction_Word (Factor);
                          GenerateInstructionWithExpressionInMemOrReg (Unary_16Bit_Operations, mod_MUL_rm);
                          Register := rAX;
                        end;
           end;
    end;
    Location := elRegister;
    LocationData.Register := Register;
    Include (Usedregisters, TUsedRegister (Register));
  end;

begin
  If Factor <= 0 then GeneralIntegerMultiplicationWithConstant else
    If Factor > 1 then
      begin
        ShiftCount := 0;
        TempFactor := Factor;
        While (TempFactor and $01) = 0 do
          begin
            Inc (ShiftCount);
            TempFactor := TempFactor shr 1;
          end;
        If TempFactor  = 1 then
          begin
            LoadExpressionToRegisters (TUsedRegister (Register));
            Case ShiftCount of
              1: GenerateInstruction_TwoBytes (ShiftRotateOperationsBy1_16Bit, SHL_Reg or Register);
              else Case Instructions80286 in StatementCompilerSwitches of
                     True: begin
                             GenerateInstruction_TwoBytes (ShiftRotateOperationsByValue_16Bit, SHL_Reg or Register);
                             GenerateInstruction_Byte (ShiftCount);
                           end;
                     else Case ShiftCount of
                            2: begin
                                 GenerateInstruction_TwoBytes (ShiftRotateOperationsBy1_16Bit, SHL_Reg or Register);
                                 GenerateInstruction_TwoBytes (ShiftRotateOperationsBy1_16Bit, SHL_Reg or Register);
                               end;
                            else begin
                                   Include (UsedRegisters, urCX);
                                   GenerateInstruction_TwoBytes (MOV_8BitReg_Immediate or rCL, ShiftCount);
                                   GenerateInstruction_TwoBytes (ShiftRotateOperationsByCL_16Bit, SHL_Reg or Register);
                                 end;
                          end;
                   end;
            end;
          end else If Factor > 6 then GeneralIntegerMultiplicationWithConstant else
                     begin                          { Factor = 3, 5, 6 }
                       LoadExpressionToRegisters (TUsedRegister (Register));
                       If Factor = 6 then
                         GenerateInstruction_TwoBytes (ShiftRotateOperationsBy1_16Bit, SHL_Reg or Register);
                       GenerateInstruction_TwoBytes (MOV_16Bit_Reg_Source, SI__Reg or Register);
                       GenerateInstruction_TwoBytes (ShiftRotateOperationsBy1_16Bit, SHL_Reg or Register);
                       If Factor = 5 then
                         GenerateInstruction_TwoBytes (ShiftRotateOperationsBy1_16Bit, SHL_Reg or Register);
                       GenerateInstruction_TwoBytes (ADD_16Bit_Dest_Reg, Register or Reg__SI);
                     end;
      end;
end;