瀏覽代碼

Patched some issues with 64-bit / 32-bit FPU on ARM

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6769 8c9fc860-2736-0410-a75d-ab315db34111
felixf 9 年之前
父節點
當前提交
7ec66430e0
共有 2 個文件被更改,包括 32 次插入11 次删除
  1. 7 4
      source/ARM.MathL.Mod
  2. 25 7
      source/FoxARMBackend.Mod

+ 7 - 4
source/ARM.MathL.Mod

@@ -11,14 +11,15 @@ CONST
 	NEON = FALSE;
 
 (** Returns the mantissa *)
-PROCEDURE Mantissa (x: LONGREAL): HUGEINT;
+PROCEDURE Mantissa (x: LONGREAL):HUGEINT;
 TYPE
 	Flt = ARRAY 2 OF LONGINT;
 VAR
-	y: Flt;
+	y: Flt; h: HUGEINT;
 BEGIN
 	y := SYSTEM.VAL(Flt, x);
-	RETURN y[0] + LSH(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, y[1]) * {0 .. 19}), 32)
+	h := y[0] + LSH(SYSTEM.VAL(HUGEINT, SYSTEM.VAL(SET, y[1])*{0..19}), 32); 
+	RETURN h;
 END Mantissa;
 
 PROCEDURE Equal (x, y: LONGREAL): BOOLEAN;
@@ -144,6 +145,7 @@ PROCEDURE ln*(x: LONGREAL): LONGREAL;
 VAR
 	res, y, yk: LONGREAL;
 	k: LONGINT;
+	mantissa: HUGEINT;
 BEGIN
 	IF x <= 0 THEN HALT(80)
 	ELSIF NEON THEN
@@ -157,7 +159,8 @@ BEGIN
 
 			ln(m * 2^e) = e ln(2) + ln(m)
 		*)
-		RETURN (Reals.ExpoL(x) - 1023) * ln2 + ln(SYSTEM.VAL(LONGREAL, Mantissa(x) + 3FF0000000000000H))
+		mantissa := Mantissa(x) + 3FF0000000000000H;
+		RETURN (Reals.ExpoL(x) - 1023) * ln2 + ln(SYSTEM.VAL(LONGREAL, mantissa))
 	ELSE
 		(* ln(x) = 2 * sum_k 1/(2 k + 1) y^k, where y = (x - 1) / (x + 1), x real *)
 		y := (x - 1) / (x + 1);

+ 25 - 7
source/FoxARMBackend.Mod

@@ -1362,7 +1362,8 @@ TYPE
 				END
 			ELSE
 				HALT(100)
-			END
+			END;
+			ASSERT(partType.form > IntermediateCode.Undefined);
 		END GetPartType;
 
 		(** the value of a 32 bit part **)
@@ -1693,8 +1694,21 @@ TYPE
 			IF ~IsSameRegister(a, b) THEN
 				ASSERT(a.mode = InstructionSet.modeRegister);
 
-				IF IsRegisterForType(a.register, IntermediateCode.FloatType(32)) THEN
-					IF IsRegisterForType(b.register, IntermediateCode.FloatType(32)) THEN
+				IF IsRegisterForType(a.register, IntermediateCode.FloatType(64)) THEN
+					IF IsRegisterForType(b.register, IntermediateCode.FloatType(64)) THEN
+						(* mov float, double: *)
+						Emit2(opFCPYD, a, b)
+					ELSIF IsRegisterForType(b.register, IntermediateCode.FloatType(32)) THEN
+						(* mov float, float: *)
+						Emit2(opFCVTSD, a, b)
+					ELSE
+						HALT(200);
+					END
+				ELSIF IsRegisterForType(a.register, IntermediateCode.FloatType(32)) THEN
+					IF IsRegisterForType(b.register, IntermediateCode.FloatType(64)) THEN
+						(* mov float, double: *)
+						Emit2(opFCVTSD, a, b)
+					ELSIF IsRegisterForType(b.register, IntermediateCode.FloatType(32)) THEN
 						(* mov float, float: *)
 						Emit2(opFCPYS, a, b)
 					ELSE
@@ -1705,6 +1719,8 @@ TYPE
 					IF IsRegisterForType(b.register, IntermediateCode.FloatType(32)) THEN
 						(* mov int, float: *)
 						Emit2(opFMRS, a, b)
+					ELSIF IsRegisterForType(b.register, IntermediateCode.FloatType(64)) THEN
+						HALT(200)
 					ELSE
 						(* mov int, int: *)
 						Emit2(opMOV, a, b)
@@ -2717,7 +2733,7 @@ TYPE
 			PROCEDURE Cmp(CONST left, right: InstructionSet.Operand; float: BOOLEAN);
 			BEGIN
 				IF float THEN
-					IF ~backend.useFPU32 OR IsComplex(irLeft) (* 64 bit *) THEN
+					IF ~backend.useFPU32 (* NO FPU *) OR IsComplex(irLeft) (* 64 bit but not DP FPU *) THEN
 						(* floating point comparisons without VFP unit *)
 						temp := GetFreeRegister(IntermediateCode.UnsignedIntegerType(32));
 						Emit3WithFlags(opAND, temp, left, right, {InstructionSet.flagS});
@@ -2726,9 +2742,12 @@ TYPE
 						Emit2(opCMP, left, right);
 						Emit1(opB, InstructionSet.NewImmediate(0)); (* skip one instructions  *)
 						Emit2(opCMP, right, left);
-					ELSE
+					ELSIF IsSinglePrecisionFloat(irLeft) THEN
 						Emit2(opFCMPS, left, right);
 						Emit0(opFMSTAT); (* transfer the VFP flags to the standard ARM flags *)
+					ELSIF IsDoublePrecisionFloat(irLeft) THEN
+						Emit2(opFCMPD, left, right);
+						Emit0(opFMSTAT); (* transfer the VFP flags to the standard ARM flags *)
 					END
 				ELSE
 					Emit2(opCMP, left, right);
@@ -2815,7 +2834,7 @@ TYPE
 						END
 					END
 
-				ELSIF IsSinglePrecisionFloat(irLeft) THEN
+				ELSIF IsSinglePrecisionFloat(irLeft) OR IsDoublePrecisionFloat(irLeft) & backend.useFPU64 THEN
 					left[Low] := RegisterFromIrOperand(irLeft, Low, emptyOperand);
 					right[Low] := RegisterFromIrOperand(irRight, Low, emptyOperand);
 					Cmp(left[Low], right[Low], TRUE);
@@ -2827,7 +2846,6 @@ TYPE
 					| IntermediateCode.brge: (* left >= right *) lowHit := InstructionSet.conditionGE
 					ELSE HALT(100)
 					END
-
 				ELSIF IsDoublePrecisionFloat(irLeft) THEN
 					CASE irInstruction.opcode OF
 					IntermediateCode.breq: