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;