Browse Source

* assembly round and trunc routines for ppc64

git-svn-id: trunk@1601 -
tom_at_work 20 years ago
parent
commit
2198a6a44a
3 changed files with 51 additions and 225 deletions
  1. 2 1
      compiler/powerpc64/cpubase.pas
  2. 2 1
      compiler/powerpc64/itcpugas.pas
  3. 47 223
      rtl/powerpc64/math.inc

+ 2 - 1
compiler/powerpc64/cpubase.pas

@@ -101,7 +101,8 @@ type
     A_LDARX, A_STDCX_, A_CNTLZD,
     A_LVX, A_STVX,
     A_MULLDO, A_MULLDO_, A_MULHDU, A_MULHDU_,
-    A_MFXER);
+    A_MFXER,
+    A_FCTID, A_FCTID_, A_FCTIDZ, A_FCTIDZ_);
 
   {# This should define the array of instructions as string }
   op2strtable = array[tasmop] of string[8];

+ 2 - 1
compiler/powerpc64/itcpugas.pas

@@ -91,7 +91,8 @@ const
     'ldarx', 'stdcx.', 'cntlzd',
     'lvx', 'stvx',
     'mulldo', 'mulldo.', 'mulhdu', 'mulhdu.',
-    'mfxer');
+    'mfxer',
+    'fctid', 'fctid.', 'fctidz', 'fctidz.');
 
 function gas_regnum_search(const s: string): Tregister;
 function gas_regname(r: Tregister): string;

+ 47 - 223
rtl/powerpc64/math.inc

@@ -14,239 +14,65 @@
 
  **********************************************************************}
 
-
-const
-  longint_to_real_helper: int64 = $4330000080000000;
-  cardinal_to_real_helper: int64 = $4330000000000000;
-  int_to_real_factor: double = double(high(cardinal))+1.0;
-
-
 {****************************************************************************
                        EXTENDED data type routines
  ****************************************************************************}
 
-    {$define FPC_SYSTEM_HAS_PI}
-    function fpc_pi_real : valreal;compilerproc;
-    begin
-      { Function is handled internal in the compiler }
-      runerror(207);
-      result:=0;
-    end;
-
-    {$define FPC_SYSTEM_HAS_ABS}
-    function fpc_abs_real(d : valreal) : valreal;compilerproc;
-    begin
-      { Function is handled internal in the compiler }
-      runerror(207);
-      result:=0;
-    end;
-
-    {$define FPC_SYSTEM_HAS_SQR}
-    function fpc_sqr_real(d : valreal) : valreal;compilerproc;
-    begin
-      { Function is handled internal in the compiler }
-      runerror(207);
-      result:=0;
-    end;
-
-      const
-        factor: double = double(int64(1) shl 32);
-        factor2: double = double(int64(1) shl 31);
-(*
-{$ifndef FPC_SYSTEM_HAS_TRUNC}
-    {$define FPC_SYSTEM_HAS_TRUNC}
-    function fpc_trunc_real(d : valreal) : int64;assembler;compilerproc;
-      { input: d in fr1      }
-      { output: result in r3 }
-      assembler;
-      var
-        temp: packed record
-            case byte of
-              0: (l1,l2: longint);
-              1: (d: double);
-          end;
-      asm
-        // store d in temp
-        stfd    f1,temp
-        // extract sign bit (record in cr0)
-        lwz     r3,temp
-        rlwinm. r3,r3,1,31,31
-        // make d positive
-        fabs    f1,f1
-        // load 2^32 in f2
-        {$ifndef macos}
-        lis    r4,factor@ha
-        lfd    f2,factor@l(r4)
-        {$else}
-        lwz    r4,factor(r2)
-        lfd    f2,0(r4)
-        {$endif}
-        // check if value is < 0
-        // f3 := d / 2^32;
-        fdiv     f3,f1,f2
-        // round
-        fctiwz   f4,f3
-        // store
-        stfd     f4,temp
-        // and load into r4
-        lwz      r3,temp+4
-        // convert back to float
-        lis      r0,0x4330
-        stw      r0,temp
-        xoris    r0,r3,0x8000
-        stw      r0,temp+4
-        {$ifndef macos}
-        lis    r4,longint_to_real_helper@ha
-        lfd    f0,longint_to_real_helper@l(r4)
-        {$else}
-        lwz    r4,longint_to_real_helper(r2)
-        lfd    f0,0(r4)
-        {$endif}
-        lfd    f3,temp
-        fsub   f3,f3,f0
-
-
-        // f4 := d "mod" 2^32 ( = d - ((d / 2^32) * 2^32))
-        fnmsub   f4,f3,f2,f1
-
-        // now, convert to unsigned 32 bit
-
-        // load 2^31 in f2
-        {$ifndef macos}
-        lis    r4,factor2@ha
-        lfd    f2,factor2@l(r4)
-        {$else}
-        lwz    r4,factor2(r2)
-        lfd    f2,0(r4)
-        {$endif}
-
-        // subtract 2^31
-        fsub   f3,f4,f2
-        // was the value > 2^31?
-        fcmpu  cr1,f4,f2
-        // use diff if >= 2^31
-        fsel   f4,f3,f3,f4
-
-        // next part same as conversion to signed integer word
-        fctiwz f4,f4
-        stfd   f4,temp
-        lwz    r4,temp+4
-        // add 2^31 if value was >=2^31
-        blt    cr1, .LTruncNoAdd
-        xoris  r4,r4,0x8000
-.LTruncNoAdd:
-        // negate value if it was negative to start with
-        beq    cr0,.LTruncPositive
-        subfic r4,r4,0
-        subfze r3,r3
-.LTruncPositive:
-      end;
-{$endif not FPC_SYSTEM_HAS_TRUNC}
-*)
-
-(*
-{$ifndef FPC_SYSTEM_HAS_ROUND}
-    {$define FPC_SYSTEM_HAS_ROUND}
-    function round(d : extended) : int64;
-
-    function fpc_round(d : extended) : int64;assembler;[public, alias:'FPC_ROUND'];compilerproc;
-      { exactly the same as trunc, except that one fctiwz has become fctiw }
-      { input: d in fr1      }
-      { output: result in r3 }
-      assembler;
-      var
-        temp: packed record
-            case byte of
-              0: (l1,l2: longint);
-              1: (d: double);
-          end;
-      asm
-        // store d in temp
-        stfd    f1, temp
-        // extract sign bit (record in cr0)
-        lwz     r4,temp
-        rlwinm. r4,r4,1,31,31
-        // make d positive
-        fabs    f1,f1
-        // load 2^32 in f2
-        {$ifndef macos}
-        lis    r4,factor@ha
-        lfd    f2,factor@l(r4)
-        {$else}
-        lwz    r4,factor(r2)
-        lfd    f2,0(r4)
-        {$endif}
-        // check if value is < 0
-        // f3 := d / 2^32;
-        fdiv     f3,f1,f2
-        // round
-        fctiwz   f4,f3
-        // store
-        stfd     f4,temp
-        // and load into r4
-        lwz      r3,temp+4
-        // convert back to float
-        lis      r0,0x4330
-        stw      r0,temp
-        xoris    r0,r3,0x8000
-        stw      r0,temp+4
-        {$ifndef macos}
-        lis    r4,longint_to_real_helper@ha
-        lfd    f0,longint_to_real_helper@l(r4)
-        {$else}
-        lwz    r4,longint_to_real_helper(r2)
-        lfd    f0,0(r4)
-        {$endif}
-        lfd    f3,temp
-        fsub   f3,f3,f0
-
-
-        // f4 := d "mod" 2^32 ( = d - ((d / 2^32) * 2^32))
-        fnmsub   f4,f3,f2,f1
-
-        // now, convert to unsigned 32 bit
+{$define FPC_SYSTEM_HAS_PI}
+function fpc_pi_real : valreal;compilerproc;
+begin
+  { Function is handled internal in the compiler }
+  runerror(207);
+  result:=0;
+end;
 
-        // load 2^31 in f2
-        {$ifndef macos}
-        lis    r4,factor2@ha
-        lfd    f2,factor2@l(r4)
-        {$else}
-        lwz    r4,factor2(r2)
-        lfd    f2,0(r4)
-        {$endif}
+{$define FPC_SYSTEM_HAS_ABS}
+function fpc_abs_real(d : valreal) : valreal;compilerproc;
+begin
+  { Function is handled internal in the compiler }
+  runerror(207);
+  result:=0;
+end;
 
-        // subtract 2^31
-        fsub   f3,f4,f2
-        // was the value > 2^31?
-        fcmpu  cr1,f4,f2
-        // use diff if >= 2^31
-        fsel   f4,f3,f3,f4
+{$define FPC_SYSTEM_HAS_SQR}
+function fpc_sqr_real(d : valreal) : valreal;compilerproc;
+begin
+  { Function is handled internal in the compiler }
+  runerror(207);
+  result:=0;
+end;
 
-        // next part same as conversion to signed integer word
-        fctiw  f4,f4
-        stfd   f4,temp
-        lwz    r4,temp+4
-        // add 2^31 if value was >=2^31
-        blt    cr1, .LRoundNoAdd
-        xoris  r4,r4,0x8000
-.LRoundNoAdd:
-        // negate value if it was negative to start with
-        beq    cr0,.LRoundPositive
-        subfic r4,r4,0
-        subfze r3,r3
-.LRoundPositive:
-      end;
-{$endif not FPC_SYSTEM_HAS_ROUND}
-*)
+{$define FPC_SYSTEM_HAS_TRUNC}
+function fpc_trunc_real(d : valreal) : int64;compilerproc; assembler;
+{ input: d in fr1      }
+{ output: result in r3 }
+var
+  temp : int64;
+asm
+  fctidz f1, f1
+  stfd f1, temp
+  ld r3, temp
+end;
 
+{$define FPC_SYSTEM_HAS_ROUND}
+function fpc_round_real(d : valreal) : int64; compilerproc;assembler;
+{ exactly the same as trunc, except that one fctiwz has become fctiw }
+{ input: d in fr1      }
+{ output: result in r3 }
+var
+  temp: int64;
+asm
+  fctid f1, f1
+  stfd  f1, temp
+  ld r3, temp
+end;
 
 {****************************************************************************
                          Int to real helpers
  ****************************************************************************}
 
 {$define FPC_SYSTEM_HAS_INT64_TO_DOUBLE}
-function fpc_int64_to_double(i: int64): double; compilerproc;
-assembler;
+function fpc_int64_to_double(i: int64): double; compilerproc;assembler;
 { input: i in r3 }
 { output: double(i) in f0            }
 {from "PowerPC Microprocessor Family: Programming Environments Manual for 64 and 32-Bit Microprocessors", v2.0, pg. 698 }
@@ -257,10 +83,8 @@ asm
         fcfid f0,f0     // convert to fpu int
 end;
 
-
 {$define FPC_SYSTEM_HAS_QWORD_TO_DOUBLE}
-function fpc_qword_to_double(q: qword): double; compilerproc;
-assembler;
+function fpc_qword_to_double(q: qword): double; compilerproc;assembler;
 const
   longint_to_real_helper: qword = $80000000;
 {from "PowerPC Microprocessor Family: Programming Environments Manual for
@@ -287,4 +111,4 @@ asm
         fcfid f0,f0         // fpu int (no rnd)
         fmadd f0,f4,f2,f0   // (2**32)*high+low (only add can rnd)
 end;
-
+