Просмотр исходного кода

Added support of Division via FPU unit

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6851 8c9fc860-2736-0410-a75d-ab315db34111
felixf 9 лет назад
Родитель
Сommit
c222e0e64c
1 измененных файлов с 38 добавлено и 2 удалено
  1. 38 2
      source/FoxARMBackend.Mod

+ 38 - 2
source/FoxARMBackend.Mod

@@ -647,7 +647,9 @@ TYPE
 				END;
 
 			| IntermediateCode.div:
-				result :=  backend.useFPU32 & IsSinglePrecisionFloat(irInstruction.op1) OR backend.useFPU64 & IsDoublePrecisionFloat(irInstruction.op1);
+				result :=  backend.useFPU32 & IsSinglePrecisionFloat(irInstruction.op1) 
+							OR backend.useFPU64 & IsDoublePrecisionFloat(irInstruction.op1)
+							OR backend.useFPU64 & IsInteger32(irInstruction.op1);
 				(*
 				result := result OR IntermediateCode.IsConstantInteger(irInstruction.op3,value) & PowerOf2(value,exp)
 				*)
@@ -1404,6 +1406,11 @@ TYPE
 		BEGIN RETURN irOperand.type.form IN IntermediateCode.Integer
 		END IsInteger;
 
+		(** whether an IR operand hold am integer value **)
+		PROCEDURE IsInteger32(CONST irOperand: IntermediateCode.Operand): BOOLEAN;
+		BEGIN RETURN (irOperand.type.form IN IntermediateCode.Integer) & (irOperand.type.sizeInBits = 32)
+		END IsInteger32;
+
 		(** whether an IR operand hold am integer value **)
 		PROCEDURE IsInteger64(CONST irOperand: IntermediateCode.Operand): BOOLEAN;
 		BEGIN RETURN (irOperand.type.form IN IntermediateCode.Integer) & (irOperand.type.sizeInBits = 64)
@@ -2237,7 +2244,7 @@ TYPE
 
 		PROCEDURE EmitDiv(VAR irInstruction: IntermediateCode.Instruction);
 		VAR
-			destination, left, right: Operand;
+			destination, left, right, float, leftd, rightd: Operand;
 		BEGIN
 			IF IsSinglePrecisionFloat(irInstruction.op1) THEN
 				ASSERT(backend.useFPU32);
@@ -2249,6 +2256,35 @@ TYPE
 				PrepareDoubleSourceOp(irInstruction, Low, destination, left, right);
 				Emit3(opFDIVD, destination, left, right);
 				WriteBack(irInstruction.op1, Low, destination)
+			ELSIF IsInteger32(irInstruction.op1) THEN
+				ASSERT(backend.useFPU64);
+				PrepareDoubleSourceOp(irInstruction, Low, destination, left, right);
+				(* left and right operands to double *)
+				float := GetFreeRegister(IntermediateCode.FloatType(32));
+		 		Emit2(opFMSR, float, left);
+				leftd := GetFreeRegister(IntermediateCode.FloatType(64));
+	 			IF irInstruction.op1.type.form = IntermediateCode.UnsignedInteger THEN
+					Emit2(opFUITOD, leftd, float)
+				ELSE
+					Emit2(opFSITOD,leftd, float)
+				END;
+		 		Emit2(opFMSR, float,right);
+				rightd := GetFreeRegister(IntermediateCode.FloatType(64));
+	 			IF irInstruction.op1.type.form = IntermediateCode.UnsignedInteger THEN
+					Emit2(opFUITOD, rightd, float)
+				ELSE
+					Emit2(opFSITOD,rightd, float)
+				END;
+				(* div *)
+				Emit3(opFDIVD, leftd, leftd, rightd);
+				(* result to destination *)
+	 			IF irInstruction.op1.type.form = IntermediateCode.UnsignedInteger THEN
+					Emit2(opFTOUID, float, leftd)
+				ELSE
+					Emit2(opFTOSID, float, leftd)
+				END;
+		 		Emit2(opFMRS, destination, float);
+				WriteBack(irInstruction.op1, Low, destination)
 			ELSE
 				HALT(200)
 			END