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; |