Преглед изворни кода

* fixed ppc fpu exception mask stuff in math unit
+ added test for this functionality

git-svn-id: trunk@3136 -

Jonas Maebe пре 19 година
родитељ
комит
0517ce08e2
3 измењених фајлова са 81 додато и 9 уклоњено
  1. 1 0
      .gitattributes
  2. 10 9
      rtl/powerpc/mathu.inc
  3. 70 0
      tests/test/units/math/tmask.pp

+ 1 - 0
.gitattributes

@@ -5771,6 +5771,7 @@ tests/test/units/dos/tidos.pp svneol=native#text/plain
 tests/test/units/dos/tidos2.pp svneol=native#text/plain
 tests/test/units/dos/tidos2.pp svneol=native#text/plain
 tests/test/units/dos/tverify.pp svneol=native#text/plain
 tests/test/units/dos/tverify.pp svneol=native#text/plain
 tests/test/units/dos/tversion.pp svneol=native#text/plain
 tests/test/units/dos/tversion.pp svneol=native#text/plain
+tests/test/units/math/tmask.pp svneol=native#text/plain
 tests/test/units/math/tnaninf.pp svneol=native#text/plain
 tests/test/units/math/tnaninf.pp svneol=native#text/plain
 tests/test/units/math/ttrig1.pp svneol=native#text/plain
 tests/test/units/math/ttrig1.pp svneol=native#text/plain
 tests/test/units/objects/testobj.pp svneol=native#text/plain
 tests/test/units/objects/testobj.pp svneol=native#text/plain

+ 10 - 9
rtl/powerpc/mathu.inc

@@ -21,6 +21,7 @@ const
   UnderflowMask        = %00100000;
   UnderflowMask        = %00100000;
   ZeroDivideMask       = %00010000;
   ZeroDivideMask       = %00010000;
   InexactMask          = %00001000;
   InexactMask          = %00001000;
+  ExceptionsPendingMask = %11111111111111100000011100000000;
 
 
   ExceptionMask        = InvalidOperationMask or OverflowMask or UnderflowMask or ZeroDivideMask or InexactMask;
   ExceptionMask        = InvalidOperationMask or OverflowMask or UnderflowMask or ZeroDivideMask or InexactMask;
 
 
@@ -29,14 +30,14 @@ const
 function getFPSCR : DWord; assembler; nostackframe;
 function getFPSCR : DWord; assembler; nostackframe;
 asm
 asm
   mffs f0
   mffs f0
-  stfd f0, -8(r1)
-  lwz r3, -12(r1)
+  stfd f0, -12(r1)
+  lwz r3, -8(r1)
 end;
 end;
 
 
 procedure setFPSCR(newFPSCR : DWord); assembler; nostackframe;
 procedure setFPSCR(newFPSCR : DWord); assembler; nostackframe;
 asm
 asm
-  stw r3, -12(r1)
-  lfd f0, -8(r1)
+  stw r3, -8(r1)
+  lfd f0, -12(r1)
   mtfsf 255, f0
   mtfsf 255, f0
 end;
 end;
 
 
@@ -82,13 +83,13 @@ begin
   result := [];
   result := [];
   if ((getFPSCR and InvalidOperationMask) <> 0) then 
   if ((getFPSCR and InvalidOperationMask) <> 0) then 
     result := result + [exInvalidOp];
     result := result + [exInvalidOp];
-  if ((getFPSCR and OverflowMask) <> 0) then 
+  if ((getFPSCR and OverflowMask) = 0) then 
     result := result + [exOverflow];
     result := result + [exOverflow];
-  if ((getFPSCR and UnderflowMask) <> 0) then 
+  if ((getFPSCR and UnderflowMask) = 0) then 
     result := result + [exUnderflow];
     result := result + [exUnderflow];
-  if ((getFPSCR and ZeroDivideMask) <> 0) then 
+  if ((getFPSCR and ZeroDivideMask) = 0) then 
     result := result + [exZeroDivide];
     result := result + [exZeroDivide];
-  if ((getFPSCR and InexactMask) <> 0) then 
+  if ((getFPSCR and InexactMask) = 0) then 
     result := result + [exPrecision];
     result := result + [exPrecision];
 end;
 end;
 
 
@@ -108,7 +109,7 @@ begin
   if (exPrecision in Mask) then
   if (exPrecision in Mask) then
     mode := mode or InexactMask;
     mode := mode or InexactMask;
   
   
-  setFPSCR((getFPSCR and (not ExceptionMask)) or mode);
+  setFPSCR((getFPSCR or ExceptionMask) and not mode and not ExceptionsPendingMask);
   result := Mask - [exDenormalized];
   result := Mask - [exDenormalized];
 end;
 end;
 
 

+ 70 - 0
tests/test/units/math/tmask.pp

@@ -0,0 +1,70 @@
+program fpu;
+
+{$mode delphi}
+
+uses SysUtils,Math;
+
+var
+  f1,f2 : double;
+  caught: boolean;
+
+begin
+f1:=1.0;
+f2:=0.0;
+caught := false;
+try
+  writeln('dividing by zero without having disabled FPU Exceptions...');
+  writeln(f1/f2);
+  writeln('no exception was raised');
+except on E:Exception do
+  begin
+    writeln('Exception occured:',E.Message);
+    caught := true;
+  end;
+end;
+
+if not caught then
+  halt(1);
+
+writeln('Masking exceptions');
+
+writeln(integer(SetExceptionMask([exDenormalized,exInvalidOp,exOverflow,exPrecision,exUnderflow,exZeroDivide])));  //Returns 61, as expected
+writeln(integer(GetExceptionMask));  //Returns 4 - unexpected???
+writeln(integer([exZeroDivide]));    //Returns 4
+
+caught := false;
+try
+  writeln('dividing by zero with FPU Exceptions disabled...');
+  writeln(f1/f2);
+  writeln('no exception was raised');
+except on E:Exception do
+  begin
+    writeln('Exception occured:',E.Message);
+    caught := true;
+  end;
+end;
+
+if caught then
+  halt(2);
+
+writeln(integer(SetExceptionMask([exDenormalized,exInvalidOp,exOverflow,exPrecision,exUnderflow])));  //Returns 61, as expected
+writeln(integer(GetExceptionMask));  //Returns 4 - unexpected???
+writeln(integer([exZeroDivide]));    //Returns 4
+
+caught := false;
+
+try
+  writeln('dividing by zero without having disabled FPU Exceptions...');
+  writeln(f1/f2);
+  writeln('no exception was raised');
+except on E:Exception do
+  begin
+    writeln('Exception occured:',E.Message);
+    caught := true;
+  end;
+end;
+
+if not caught then
+  halt(0);
+
+end.