Extended Operations
Constant Extended
values are always stored in expression Value
, while for non-constant expressions numeric constants are stored in code block and FPU instructions are used for calculation. This procedure calculates operation between two constant Extended
values.
Procedure ConstantExtendedOperations;
Var BooleanValue: LongBool;
begin
Case Operation of
Calc_Add,
Calc_Subtract,
Calc_Multiply,
Calc_Divide: begin
Case Operation of
Calc_Add: LeftExpression.Value.Extended :=
LeftExpression.Value.Extended + RightExpression.Value.Extended;
Calc_Subtract: LeftExpression.Value.Extended :=
LeftExpression.Value.Extended - RightExpression.Value.Extended;
Calc_Multiply: LeftExpression.Value.Extended :=
LeftExpression.Value.Extended * RightExpression.Value.Extended;
Calc_Divide: LeftExpression.Value.Extended :=
LeftExpression.Value.Extended / RightExpression.Value.Extended;
end;
If LeftExpression.Value.W18 and $7FFF = $7FFF then Error (InvalidFloatingPointOperation);
end;
else begin
Case Operation of
Calc_IsEqual: BooleanValue := LeftExpression.Value.Extended = RightExpression.Value.Extended;
Calc_IsNotEqual: BooleanValue := LeftExpression.Value.Extended <> RightExpression.Value.Extended;
Calc_IsGreater: BooleanValue := LeftExpression.Value.Extended > RightExpression.Value.Extended;
Calc_IsLower: BooleanValue := LeftExpression.Value.Extended < RightExpression.Value.Extended;
Calc_IsGreaterOrEqual: BooleanValue := LeftExpression.Value.Extended >= RightExpression.Value.Extended;
Calc_IsLowerOrEqual: BooleanValue := LeftExpression.Value.Extended <= RightExpression.Value.Extended;
end;
SetLeftExpressionToConstantBooleanValue (BooleanValue);
end;
end;
end;
This procedure generates code for operations on Extended expressions. FPU instructions are used.
Procedure GenerateCodeForExtendedOperations;
Var OpCode: Word;
StackFrameOffset: Word;
Procedure ExchangeExpressionsAndInvertOperation;
begin
ExchangeLeftAndRightExpression;
If OpCode and $2000 <> 0 then OpCode := OpCode xor $0800;
end;
begin
LeftExpression.ConvertToLowestFPTypeAndStoreToCodeBlock;
RightExpression.ConvertToLowestFPTypeAndStoreToCodeBlock;
Case Operation of
Calc_Add: OpCode := FADDP;
Calc_Subtract: OpCode := FSUBRP;
Calc_Multiply: OpCode := FMULP;
Calc_Divide: OpCode := FDIVRP;
Calc_IsEqual..Calc_IsLowerOrEqual: OpCode := FCOMPP;
end;
If LeftExpression.Location <> elStackFrame then
begin
If RightExpression.Location = elStackFrame then ExchangeExpressionsAndInvertOperation else
If (fpExtended in LeftExpression.DataType) and not (fpExtended in RightExpression.DataType) then
ExchangeExpressionsAndInvertOperation;
end;
If fpExtended in RightExpression.DataType then
begin
ExchangeExpressionsAndInvertOperation;
LeftExpression.LoadExpressionToFPU;
RightExpression.LoadExpressionToFPU;
CalculateBothExpressions (RightExpression, LeftExpression);
ModifyAndSroreFPUInstructionForFixup (OpCode);
end else begin
LeftExpression.LoadExpressionToFPU;
CalculateBothExpressions (LeftExpression, RightExpression);
RightExpression.GenerateFPUInstructionWithExpressionInMemory (
ESC or Byte (RightExpression.DataType), Hi (OpCode) xor $C1);
end;
Case Operation of
Calc_Add,
Calc_Subtract,
Calc_Multiply,
Calc_Divide: begin
LeftExpression.UsedRegisters := LeftExpression.UsedRegisters + RightExpression.UsedRegisters;
LeftExpression.EndIntermediateCodeSubroutine;
Exit;
end;
end;
StackFrameOffset := CreateTempStackFrameSpace (2);
GenerateFPUInstructionForStackFrameDisplacement ($3EDD, StackFrameOffset);
GenerateInstruction_TwoBytes ($CD, $3D);
GenerateInstructionForStackFrameDisplacement ($8A, $26, StackFrameOffset + 1);
GenerateInstruction_Byte ($9E);
LeftExpression.EndIntermediateCodeSubroutine;
LeftExpression.UsedRegisters := LeftExpression.UsedRegisters + RightExpression.UsedRegisters + [urAX];
LeftExpression.SetExpressionToBooleanJump (UnsignedConditionalJumpOpCode [Operation]);
end;