Processing Mathematical Operations
Turbo Pascal generates code for all mathemathical operations with two operands by the following procedure. The input of this procedure are left and right expression and the operation.
Type TCalcOperation = (
Calc_Add, { 00 }
Calc_Subtract, { 01 }
Calc_Multiply, { 02 }
Calc_DIV, { 03 }
Calc_MOD, { 04 }
Calc_SHL, { 05 }
Calc_SHR, { 06 }
Calc_AND, { 07 }
Calc_OR, { 08 }
Calc_XOR, { 09 }
Calc_IsEqual, { 0A }
Calc_IsNotEqual, { 0B }
Calc_IsGreater, { 0C }
Calc_IsLower, { 0D }
Calc_IsGreaterOrEqual, { 0E }
Calc_IsLowerOrEqual, { 0F }
Calc_Divide, { 10 }
Calc_IN); { 11 }
Table AllowedOperations
defines which operations are allowed. Conditional jump opcodes define which jump code will be generated for comparison operations. The procedure first checks for PChar operations, then it copies string-compatible character arrays to stack frame, next some type adjustments are made, type compatibility is checked and finally the methematical operation is performed. If both operands are constant then no code needs to be generated and special procedures are used. Finally, left expression holds the result (including the code) of the mathematical operation.
Procedure CalculateOperation (Operation: TCalcOperation; Var LeftExpression, RightExpression: TExpression);
Const AllowedOperations: Array [Calc_Add..Calc_Divide] of TBaseTypeSet = (
{ + } [ btChar, btInteger, btReal, btExtended, btString, btSet],
{ - } [ btInteger, btReal, btExtended, btPointer, btSet],
{ * } [ btInteger, btReal, btExtended, btSet],
{ DIV } [ btInteger],
{ MOD } [ btInteger],
{ SHL } [ btInteger],
{ SHR } [ btInteger],
{ AND } [ btBoolean, btInteger],
{ OR } [ btBoolean, btInteger],
{ XOR } [ btBoolean, btInteger],
{ = } [btEnumeration, btChar, btBoolean, btInteger, btReal, btExtended, btString, btPointer, btSet],
{ <> } [btEnumeration, btChar, btBoolean, btInteger, btReal, btExtended, btString, btPointer, btSet],
{ > } [btEnumeration, btChar, btBoolean, btInteger, btReal, btExtended, btString, btPointer],
{ < } [btEnumeration, btChar, btBoolean, btInteger, btReal, btExtended, btString, btPointer],
{ >= } [btEnumeration, btChar, btBoolean, btInteger, btReal, btExtended, btString, btPointer, btSet],
{ <= } [btEnumeration, btChar, btBoolean, btInteger, btReal, btExtended, btString, btPointer, btSet],
{ / } [ btInteger, btReal, btExtended]);
UnsignedConditionalJumpOpCode: Array [Calc_IsEqual..Calc_IsLowerOrEqual] of Byte = (
JE,
JNE,
JA,
JB,
JNB,
JBE);
SignedConditionalJumpOpCode: Array [Calc_IsEqual..Calc_IsLowerOrEqual] of Byte = (
JE,
JNE,
JG,
JL,
JNL,
JLE);
begin
If ExtendedSyntax in ModuleCompilerSwitches then If CharacterPointerOperations then Exit;
LeftExpression.CopyCharArrayCompatibleWithStringToStackFrameAsString;
RightExpression.CopyCharArrayCompatibleWithStringToStackFrameAsString;
If LeftExpression.TypeDefPtr^.BaseType = RightExpression.TypeDefPtr^.BaseType then
begin
If (LeftExpression.TypeDefPtr^.BaseType = btInteger) and (Operation = Calc_Divide) then ConvertToRealOrExtended else
If (LeftExpression.TypeDefPtr^.BaseType = btChar) and (Operation = Calc_Add) then
begin
LeftExpression.ConvertCharToString;
RightExpression.ConvertCharToString;
end;
end else begin
LeftExpression.ConvertCharToString;
RightExpression.ConvertCharToString;
ConvertToRealOrExtended;
end;
LeftExpression.CheckTypeCompatibility (RightExpression.TypeDefPtr);
If not (RightExpression.TypeDefPtr^.BaseType in AllowedOperations [Operation]) then
Error (OperandTypesDoNotMatchOperator);
If (LeftExpression.Location = elConstant) and (RightExpression.Location = elConstant) then
Case LeftExpression.TypeDefPtr^.BaseType of
btSet: ConstantSetOperations;
btPointer: ConstantPointerOperations;
btString: ConstantStringOperations;
btExtended: ConstantExtendedOperations;
btReal: GenerateCodeForRealOperations;
btInteger: ConstantIntegerOperations;
btBoolean: ConstantBooleanOperations;
btChar: ConstantIntegerOperations;
btEnumeration: ConstantIntegerOperations;
end else Case LeftExpression.TypeDefPtr^.BaseType of
btSet: GenerateCodeForSetOperations;
btPointer: GenerateCodeForPointerOperations;
btString: GenerateCodeForStringOperations;
btExtended: GenerateCodeForExtendedOperations;
btReal: GenerateCodeForRealOperations;
btInteger: GenerateCodeForIntegerOperations;
btBoolean: GenerateCodeForBooleanOperations;
btChar: GenerateCodeForIntegerOperations;
btEnumeration: GenerateCodeForIntegerOperations;
end;
end;
If both expressions are constant or 80×87 instructions are enabled then both expressions are converted to Extended, otherwise they are converted to Real.
Function ConvertToRealOrExtended: Boolean;
begin
If (LeftExpression.Location = elConstant) and (RightExpression.Location = elConstant) then
ConvertIntegerOrRealToExtended else If Instructions80x87 in StatementCompilerSwitches then
ConvertIntegerOrRealToExtended else ConvertIntegerOrExtendedToReal;
end;
Procedure ConvertIntegerOrRealToExtended;
begin
LeftExpression.ConvertIntegerToExtended;
LeftExpression.ConvertRealToExtended;
RightExpression.ConvertIntegerToExtended;
RightExpression.ConvertRealToExtended;
end;
Procedure ConvertIntegerOrExtendedToReal;
begin
LeftExpression.ConvertIntegerToReal;
LeftExpression.ConvertExtendedToReal;
RightExpression.ConvertIntegerToReal;
RightExpression.ConvertExtendedToReal;
end;