Browse Source

Patched an important bug with pop on double
Set rounding mode for ENTIER to round to minus infinity


git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6797 8c9fc860-2736-0410-a75d-ab315db34111

felixf 9 years ago
parent
commit
07d0ab5616
1 changed files with 31 additions and 4 deletions
  1. 31 4
      source/FoxARMBackend.Mod

+ 31 - 4
source/FoxARMBackend.Mod

@@ -508,7 +508,7 @@ TYPE
 		runtimeModuleName: SyntaxTree.IdentifierString;
 		runtimeModuleName: SyntaxTree.IdentifierString;
 		backend: BackendARM;
 		backend: BackendARM;
 
 
-		opSP, opFP, opPC, opLR, opRES, opRESHI, opRESFS, opRESFD: InstructionSet.Operand;
+		opSP, opFP, opPC, opLR, opRES, opRESHI, opRESFS, opRESFD, fpscr: InstructionSet.Operand;
 
 
 		listOfReferences: ListOfReferences;
 		listOfReferences: ListOfReferences;
 
 
@@ -546,6 +546,7 @@ TYPE
 			opRESFS := InstructionSet.NewRegister(InstructionSet.RESFS, None, None, 0);
 			opRESFS := InstructionSet.NewRegister(InstructionSet.RESFS, None, None, 0);
 			opRESFD := InstructionSet.NewRegister(InstructionSet.RESFD, None, None, 0);
 			opRESFD := InstructionSet.NewRegister(InstructionSet.RESFD, None, None, 0);
 
 
+			fpscr := InstructionSet.NewRegister(InstructionSet.FPSCR, None, None, 0);
 			dump := NIL;
 			dump := NIL;
 
 
 			NEW(listOfReferences);
 			NEW(listOfReferences);
@@ -1879,10 +1880,9 @@ TYPE
 			register: Operand; partType: IntermediateCode.Type;
 			register: Operand; partType: IntermediateCode.Type;
 		BEGIN
 		BEGIN
 			register := AcquireDestinationRegister(irOperand, part, emptyOperand);
 			register := AcquireDestinationRegister(irOperand, part, emptyOperand);
-			IF ~IsRegisterForType(register.register, IntermediateCode.FloatType(32)) THEN
+			IF ~IsRegisterForType(register.register, IntermediateCode.FloatType(32)) & ~IsRegisterForType(register.register, IntermediateCode.FloatType(64)) THEN
 				(*Emit2(opLDR, register, InstructionSet.NewImmediateOffsetMemory(InstructionSet.SP, 4, {InstructionSet.Increment, InstructionSet.PostIndexed}));*)
 				(*Emit2(opLDR, register, InstructionSet.NewImmediateOffsetMemory(InstructionSet.SP, 4, {InstructionSet.Increment, InstructionSet.PostIndexed}));*)
 				Load(register, InstructionSet.NewImmediateOffsetMemory(InstructionSet.SP, 4, {InstructionSet.Increment, InstructionSet.PostIndexed}), PartType(irOperand.type, part));
 				Load(register, InstructionSet.NewImmediateOffsetMemory(InstructionSet.SP, 4, {InstructionSet.Increment, InstructionSet.PostIndexed}), PartType(irOperand.type, part));
-
 			ELSE
 			ELSE
 				Load(register, InstructionSet.NewImmediateOffsetMemory(InstructionSet.SP, 0, {InstructionSet.Increment}), PartType(irOperand.type, part));
 				Load(register, InstructionSet.NewImmediateOffsetMemory(InstructionSet.SP, 0, {InstructionSet.Increment}), PartType(irOperand.type, part));
 				partType := PartType(irOperand.type, part);
 				partType := PartType(irOperand.type, part);
@@ -2937,8 +2937,26 @@ TYPE
 		VAR
 		VAR
 			irDestination, irSource: IntermediateCode.Operand;
 			irDestination, irSource: IntermediateCode.Operand;
 			destination, source: ARRAY 2 OF Operand;
 			destination, source: ARRAY 2 OF Operand;
-			temp: Operand;
+			temp, fpstatus: Operand;
 			partType: IntermediateCode.Type;
 			partType: IntermediateCode.Type;
+			
+			PROCEDURE RoundDown;
+			BEGIN
+				fpstatus := GetFreeRegister(IntermediateCode.UnsignedIntegerType(32));
+				(* round to minus infitinity *)
+				Emit2(InstructionSet.opVMRS, fpstatus, fpscr);
+				Emit3(opORR, fpstatus, fpstatus, InstructionSet.NewImmediate(0x800000));
+				Emit2(InstructionSet.opVMSR, fpscr, fpstatus);
+			END RoundDown;
+			
+			PROCEDURE ResetRounding;
+			BEGIN
+				(* reset rounding mode *)
+				Emit3(opBIC, fpstatus, fpstatus, InstructionSet.NewImmediate(0x800000));
+				Emit2(InstructionSet.opVMSR, fpscr, fpstatus);
+			END ResetRounding;
+			
+			
 		BEGIN
 		BEGIN
 			irDestination := irInstruction.op1; irSource := irInstruction.op2;
 			irDestination := irInstruction.op1; irSource := irInstruction.op2;
 
 
@@ -2988,12 +3006,17 @@ TYPE
 						ASSERT(backend.useFPU32);
 						ASSERT(backend.useFPU32);
 						(* single precision float to non-complex integer: *)
 						(* single precision float to non-complex integer: *)
 						temp := GetFreeRegister(IntermediateCode.FloatType(32));
 						temp := GetFreeRegister(IntermediateCode.FloatType(32));
+						
 						IF irDestination.type.form = IntermediateCode.UnsignedInteger THEN
 						IF irDestination.type.form = IntermediateCode.UnsignedInteger THEN
 							(* single precision float to non-complex unsigned integer: *)
 							(* single precision float to non-complex unsigned integer: *)
+							RoundDown;
 							Emit2(opFTOUIS, temp, source[Low]);
 							Emit2(opFTOUIS, temp, source[Low]);
+							ResetRounding;
 						ELSE
 						ELSE
 							(* single precision float to non-complex signed integer: *)
 							(* single precision float to non-complex signed integer: *)
+							RoundDown;
 							Emit2(opFTOSIS, temp, source[Low]);
 							Emit2(opFTOSIS, temp, source[Low]);
+							ResetRounding;
 						END;
 						END;
 						Emit2(opFMRS, destination[Low], temp)
 						Emit2(opFMRS, destination[Low], temp)
 					ELSIF IsDoublePrecisionFloat(irSource) THEN
 					ELSIF IsDoublePrecisionFloat(irSource) THEN
@@ -3003,10 +3026,14 @@ TYPE
 						temp := GetFreeRegister(IntermediateCode.FloatType(32));
 						temp := GetFreeRegister(IntermediateCode.FloatType(32));
 						IF irDestination.type.form = IntermediateCode.UnsignedInteger THEN
 						IF irDestination.type.form = IntermediateCode.UnsignedInteger THEN
 							(* single precision float to non-complex unsigned integer: *)
 							(* single precision float to non-complex unsigned integer: *)
+							RoundDown;
 							Emit2(opFTOUID, temp, source[Low]);
 							Emit2(opFTOUID, temp, source[Low]);
+							ResetRounding;
 						ELSE
 						ELSE
 							(* single precision float to non-complex signed integer: *)
 							(* single precision float to non-complex signed integer: *)
+							RoundDown;
 							Emit2(opFTOSID, temp, source[Low]);
 							Emit2(opFTOSID, temp, source[Low]);
+							ResetRounding;
 						END;
 						END;
 						Emit2(opFMRS, destination[Low], temp)
 						Emit2(opFMRS, destination[Low], temp)
 					ELSE
 					ELSE