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;
 
 
 
© 2017 Turbo Pascal | Privacy Policy