浏览代码

- disabled fpc_qword_to_double() assembler version for AIX/ppc64 like for
AIX/ppc32
+ AIX/ppc64 support in powerpc64/mathu.inc (file is the same as
powerpc/mathu.inc, should be unified)
* fixed macos assembler code in powerpc64/strings.inc and enabled
for AIX/ppc64

git-svn-id: trunk@20980 -

Jonas Maebe 13 年之前
父节点
当前提交
bbdf9fca73
共有 3 个文件被更改,包括 103 次插入41 次删除
  1. 3 0
      rtl/powerpc64/math.inc
  2. 94 29
      rtl/powerpc64/mathu.inc
  3. 6 12
      rtl/powerpc64/strings.inc

+ 3 - 0
rtl/powerpc64/math.inc

@@ -82,6 +82,8 @@ asm
   fcfid f0,f0     // convert to fpu int
 end;
 
+{$ifndef aix}
+
 {$define FPC_SYSTEM_HAS_QWORD_TO_DOUBLE}
 function fpc_qword_to_double(q: qword): double; compilerproc;assembler;
 const
@@ -125,3 +127,4 @@ asm
   fmadd f0,f4,f2,f0   // (2**32)*high+low (only add can rnd)
 end;
 
+{$endif ndef aix}

+ 94 - 29
rtl/powerpc64/mathu.inc

@@ -21,6 +21,7 @@ const
   UnderflowMask        = %00100000;
   ZeroDivideMask       = %00010000;
   InexactMask          = %00001000;
+  AllExceptionsMask    = %11111000;
   ExceptionsPendingMask = %11111111111111100000011100000000;
 
   ExceptionMask        = InvalidOperationMask or OverflowMask or UnderflowMask or ZeroDivideMask or InexactMask;
@@ -41,13 +42,39 @@ asm
   mtfsf 255, f0
 end;
 
+{$ifdef aix}
+const
+  FP_RND_RZ = 0;
+  FP_RND_RN = 1;
+  FP_RND_RP = 2;
+  FP_RND_RM = 3;
+
+function fp_is_enabled(Mask: DWord): boolean;cdecl;external;
+procedure fp_enable(Mask: DWord);cdecl;external;
+function feclearexcept(Mask: DWord):DWord;cdecl;external;
+procedure fp_disable(Mask: DWord);cdecl;external;
+function fp_read_rnd: word;cdecl;external;
+function fp_swap_rnd(RoundMode: word): word;cdecl;external;
+
+{$else aix}
+const
+  FP_RND_RZ = 1;
+  FP_RND_RN = 0;
+  FP_RND_RP = 2;
+  FP_RND_RM = 3;
+{$endif aix}
+
 function GetRoundMode: TFPURoundingMode;
 begin
+{$ifndef aix}
   case (getFPSCR and RoundModeMask) of
-    0 : result := rmNearest;
-    1 : result := rmTruncate;
-    2 : result := rmUp;
-    3 : result := rmDown;
+{$else not aix}
+  case fp_read_rnd of
+{$endif not aix}
+    FP_RND_RN : result := rmNearest;
+    FP_RND_RZ : result := rmTruncate;
+    FP_RND_RP : result := rmUp;
+    FP_RND_RM : result := rmDown;
   end;
 end;
 
@@ -58,36 +85,30 @@ begin
   case (RoundMode) of
     rmNearest :
       begin
-        mode := 0;
-{ 2.3.x has internal rounding support, which does the right thing }
-{ automatically                                                   }
-{$ifdef VER2_2}
+        mode := FP_RND_RN;
         softfloat_rounding_mode := float_round_nearest_even;
-{$endif}
       end;
     rmTruncate :
       begin
-        mode := 1;
-{$ifdef VER2_2}
+        mode := FP_RND_RZ;
         softfloat_rounding_mode := float_round_to_zero;
-{$endif}
       end;
     rmUp :
       begin
-        mode := 2;
-{$ifdef VER2_2}
+        mode := FP_RND_RP;
         softfloat_rounding_mode := float_round_up;
-{$endif}
       end;
     rmDown :
       begin
-        mode := 3;
-{$ifdef VER2_2}
+        mode := FP_RND_RM;
         softfloat_rounding_mode := float_round_down;
-{$endif}
       end;
   end;
+{$ifndef aix}
   setFPSCR((getFPSCR and (not RoundModeMask)) or mode);
+{$else not aix}
+  fp_swap_rnd(mode);
+{$endif not aix}
   result := RoundMode;
 end;
 
@@ -107,16 +128,29 @@ end;
 function GetExceptionMask: TFPUExceptionMask;
 begin
   result := [];
-  if ((getFPSCR and InvalidOperationMask) = 0) then 
+{$ifndef aix}
+  if ((getFPSCR and InvalidOperationMask) = 0) then
     result := result + [exInvalidOp];
-  if ((getFPSCR and OverflowMask) = 0) then 
+  if ((getFPSCR and OverflowMask) = 0) then
     result := result + [exOverflow];
-  if ((getFPSCR and UnderflowMask) = 0) then 
+  if ((getFPSCR and UnderflowMask) = 0) then
     result := result + [exUnderflow];
-  if ((getFPSCR and ZeroDivideMask) = 0) then 
+  if ((getFPSCR and ZeroDivideMask) = 0) then
     result := result + [exZeroDivide];
-  if ((getFPSCR and InexactMask) = 0) then 
+  if ((getFPSCR and InexactMask) = 0) then
     result := result + [exPrecision];
+{$else not aix}
+  if not fp_is_enabled(InvalidOperationMask) then
+    result := result + [exInvalidOp];
+  if not fp_is_enabled(OverflowMask) then
+    result := result + [exOverflow];
+  if not fp_is_enabled(UnderflowMask) then
+    result := result + [exUnderflow];
+  if not fp_is_enabled(ZeroDivideMask) then
+    result := result + [exZeroDivide];
+  if not fp_is_enabled(InexactMask) then
+    result := result + [exPrecision];
+{$endif not aix}
 end;
 
 function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
@@ -124,24 +158,55 @@ var
   mode : DWord;
 begin
   mode := 0;
+  softfloat_exception_mask := 0;
   if (exInvalidOp in Mask) then
-    mode := mode or InvalidOperationMask;
+    begin
+      mode := mode or InvalidOperationMask;
+      softfloat_exception_mask := softfloat_exception_mask or float_flag_invalid;
+    end;
   if (exOverflow in Mask) then
-    mode := mode or OverflowMask;
+    begin
+      mode := mode or OverflowMask;
+      softfloat_exception_mask := softfloat_exception_mask or float_flag_overflow;
+    end;
   if (exUnderflow in Mask) then
-    mode := mode or UnderflowMask;
+    begin
+      mode := mode or UnderflowMask;
+      softfloat_exception_mask := softfloat_exception_mask or float_flag_underflow;
+    end;
   if (exZeroDivide in Mask) then
-    mode := mode or ZeroDivideMask;
+    begin
+      mode := mode or ZeroDivideMask;
+      softfloat_exception_mask := softfloat_exception_mask or float_flag_divbyzero;
+    end;
   if (exPrecision in Mask) then
-    mode := mode or InexactMask;
-  
+    begin
+      mode := mode or InexactMask;
+      softfloat_exception_mask := softfloat_exception_mask or float_flag_inexact;
+    end;
+
   setFPSCR((getFPSCR or ExceptionMask) and not mode and not ExceptionsPendingMask);
+  softfloat_exception_flags := 0;;
+  { also clear out pending exceptions on AIX }
+{$ifdef aix}
+  { clear pending exceptions }
+  feclearexcept(AllExceptionsMask);
+  { enable the exceptions that are not disabled }
+  fp_enable(mode xor AllExceptionsMask);
+  { and disable the rest }
+  fp_disable(mode);
+{$endif}
   result := Mask - [exDenormalized];
 end;
 
 
 procedure ClearExceptions(RaisePending: Boolean = true);
 begin
+{$ifdef aix}
+  { clear pending exceptions }
+  feclearexcept(AllExceptionsMask);
+{$endif}
+  softfloat_exception_flags := 0;
   { RaisePending has no effect on PPC, always raises them at the correct location }
   setFPSCR(getFPSCR and (not ExceptionsPendingMask));
 end;

+ 6 - 12
rtl/powerpc64/strings.inc

@@ -50,13 +50,13 @@ asm
         subi    r4,r4,3
         subi    r9,r9,3
         { setup magic constants }
-        {$ifdef macos}
+        {$if defined(macos) or defined(aix)}
         {  load constant 0xfefefeff }
         lis     r8,0xfefe
-        addi    r8,r8,0xfeff
+        ori     r8,r8,0xfeff
         {  load constant 0x80808080}
         lis     r7,0x8080
-        addi    r7,r7,0x8080
+        ori     r7,r7,0x8080
         {$else}
         lis     r8,(0xfefefeff)@ha
         addi    r8,r8,(0xfefefeff)@l
@@ -124,25 +124,19 @@ asm
         subi    r4,r4,3
         subi    r3,r3,3
         { setup magic constants }
-        {$ifdef macos}
+        {$if defined(macos) or defined(aix)}
         {  load constant 0xfefefeff }
         lis     r8,0xfefe
-        addi    r8,r8,0xfeff
+        ori     r8,r8,0xfeff
         {  load constant 0x80808080}
         lis     r7,0x8080
-        addi    r7,r7,0x8080
+        ori     r7,r7,0x8080
         {$else}
         lis     r8,(0xfefefeff)@ha
         addi    r8,r8,(0xfefefeff)@l
         lis     r7,(0x80808080)@ha
         addi    r7,r7,(0x80808080)@l
         {$endif}
-{
-        li      r8,-257        { 0x0feff }
-        andis.  r8,r8,0x0fefe
-        li      r9,-32640      { 0x08080 }
-        andis.  r9,r9,0x08080
-}
 .LStrECopyAlignedLoop:
 
         {  load next 4 bytes  }