From 2198a6a44a3456f435469864409cd7f3320e81d1 Mon Sep 17 00:00:00 2001 From: tom_at_work Date: Wed, 26 Oct 2005 21:43:54 +0000 Subject: [PATCH] * assembly round and trunc routines for ppc64 git-svn-id: trunk@1601 - --- compiler/powerpc64/cpubase.pas | 3 +- compiler/powerpc64/itcpugas.pas | 3 +- rtl/powerpc64/math.inc | 270 ++++++-------------------------- 3 files changed, 51 insertions(+), 225 deletions(-) diff --git a/compiler/powerpc64/cpubase.pas b/compiler/powerpc64/cpubase.pas index 2ca2860887..a35962ec3d 100644 --- a/compiler/powerpc64/cpubase.pas +++ b/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]; diff --git a/compiler/powerpc64/itcpugas.pas b/compiler/powerpc64/itcpugas.pas index 41b376b1dc..ce4ce4b5f3 100644 --- a/compiler/powerpc64/itcpugas.pas +++ b/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; diff --git a/rtl/powerpc64/math.inc b/rtl/powerpc64/math.inc index 8f09129455..59c4f95bd1 100644 --- a/rtl/powerpc64/math.inc +++ b/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_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_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; +{$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 - - // 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 - 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; - +