diff --git a/tests/test/cg/obj/darwin/i386/tcext6.o b/tests/test/cg/obj/darwin/i386/tcext6.o index 378a5f6d99..6dfe166c55 100644 Binary files a/tests/test/cg/obj/darwin/i386/tcext6.o and b/tests/test/cg/obj/darwin/i386/tcext6.o differ diff --git a/tests/test/cg/obj/darwin/powerpc/tcext6.o b/tests/test/cg/obj/darwin/powerpc/tcext6.o index 9bae1dc37c..87f87ddd34 100644 Binary files a/tests/test/cg/obj/darwin/powerpc/tcext6.o and b/tests/test/cg/obj/darwin/powerpc/tcext6.o differ diff --git a/tests/test/cg/obj/darwin/powerpc64/tcext6.o b/tests/test/cg/obj/darwin/powerpc64/tcext6.o index daf4019a36..a19cb31607 100644 Binary files a/tests/test/cg/obj/darwin/powerpc64/tcext6.o and b/tests/test/cg/obj/darwin/powerpc64/tcext6.o differ diff --git a/tests/test/cg/obj/darwin/x86_64/tcext6.o b/tests/test/cg/obj/darwin/x86_64/tcext6.o index 9881345375..a20875292e 100644 Binary files a/tests/test/cg/obj/darwin/x86_64/tcext6.o and b/tests/test/cg/obj/darwin/x86_64/tcext6.o differ diff --git a/tests/test/cg/obj/linux/arm-eabi/tcext6.o b/tests/test/cg/obj/linux/arm-eabi/tcext6.o index de78ea4df4..dffff0b522 100644 Binary files a/tests/test/cg/obj/linux/arm-eabi/tcext6.o and b/tests/test/cg/obj/linux/arm-eabi/tcext6.o differ diff --git a/tests/test/cg/obj/linux/i386/tcext6.o b/tests/test/cg/obj/linux/i386/tcext6.o index bd2dd5a8ae..13ef2d7c2e 100644 Binary files a/tests/test/cg/obj/linux/i386/tcext6.o and b/tests/test/cg/obj/linux/i386/tcext6.o differ diff --git a/tests/test/cg/obj/linux/x86_64/tcext6.o b/tests/test/cg/obj/linux/x86_64/tcext6.o index 4ba7ddeba6..2f1c082c23 100644 Binary files a/tests/test/cg/obj/linux/x86_64/tcext6.o and b/tests/test/cg/obj/linux/x86_64/tcext6.o differ diff --git a/tests/test/cg/obj/tcext6.c b/tests/test/cg/obj/tcext6.c index 848248f702..ea2716d9a6 100644 --- a/tests/test/cg/obj/tcext6.c +++ b/tests/test/cg/obj/tcext6.c @@ -99,6 +99,134 @@ struct struct31 { float v2; }; + +/* to avoid depending on libc for double->int64 conversions + +License/credit: + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + + +*/ + +#define LIT64( a ) a##LL + +#define double2float64( a ) (*(float64*)&(a)) + +typedef char flag; + +typedef int64_t float64; +typedef uint64_t bits64; +typedef int64_t sbits64; + +bits64 extractFloat64Frac( float64 a ) +{ + return a & LIT64( 0x000FFFFFFFFFFFFF ); +} + +int16_t extractFloat64Exp( float64 a ) +{ + return ( a>>52 ) & 0x7FF; +} + +flag extractFloat64Sign( float64 a ) +{ + return a>>63; +} + +int32_t int64_is_zero(bits64 a0) +{ + return (((uint32_t)(a0 >> 32)) == 0) && ((((uint32_t)(a0 & LIT64(0xFFFFFFFF)))) == 0); +} + +void shift64ExtraRightJamming(bits64 a0, bits64 a1, int16_t count, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits64 z0, z1; + int8_t negCount = ( - count ) & 63; + + if ( count == 0 ) { + z1 = a1; + z0 = a0; + } + else if ( count < 64 ) { + z1 = ( a0<>count; + } + else { + if ( count == 64 ) { + z1 = a0 | ( !int64_is_zero(a1) ); + } + else { + z1 = ( !int64_is_zero( a0 | a1 ) ); + } + z0 = 0; + } + *z1Ptr = z1; + *z0Ptr = z0; +} + +static int64_t roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 ) +{ + int64_t z; + + z = absZ0; + if ( zSign ) z = - z; + return z; + +} + +int64_t float64_to_int64( float64 a ) +{ + flag aSign; + int16_t aExp, shiftCount; + bits64 aSig, aSigExtra; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); + shiftCount = 0x433 - aExp; + if ( shiftCount <= 0 ) { + if ( 0x43E < aExp ) { + if ( ! aSign + || ( ( aExp == 0x7FF ) + && ( aSig != LIT64( 0x0010000000000000 ) ) ) + ) { + return LIT64( 0x7FFFFFFFFFFFFFFF ); + } + return (sbits64) LIT64( 0x8000000000000000 ); + } + aSigExtra = 0; + aSig <<= - shiftCount; + } + else { + shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra ); + } + return roundAndPackInt64( aSign, aSig, aSigExtra ); +} + float pass1(struct struct1 s) { return s.v; } @@ -132,31 +260,31 @@ double pass8(struct struct8 s) { } int64_t pass9(struct struct9 s) { - return s.v1 + (int64_t)s.v2; + return s.v1 + double2float64(s.v2); } int64_t pass10(struct struct10 s) { - return s.v1 + s.v2 + (int64_t)s.v3; + return s.v1 + s.v2 + double2float64(s.v3); } int64_t pass11(struct struct11 s) { - return s.v1 + (int64_t)s.v2; + return s.v1 + double2float64(s.v2); } int64_t pass12(struct struct12 s) { - return s.v1 + (int64_t)s.v2 + (int64_t)s.v3; + return s.v1 + double2float64(s.v2) + double2float64(s.v3); } int64_t pass13(struct struct13 s) { - return (int64_t)s.v1 + s.v2; + return double2float64(s.v1) + s.v2; } int64_t pass14(struct struct14 s) { - return (int64_t)s.v1 + s.v2 + s.v3; + return double2float64(s.v1) + s.v2 + s.v3; } int64_t pass15(struct struct15 s) { - return (int64_t)s.v1 + s.v2 + (int64_t)s.v3; + return double2float64(s.v1) + s.v2 + double2float64(s.v3); } float pass16(struct struct16 s) { @@ -167,8 +295,9 @@ float pass17(struct struct17 s) { return s.v1 + s.v2; } -long double pass31(struct struct31 s) { - return s.v1 + s.v2; +long double pass31(struct struct31 s, float *v2) { + *v2 = s.v2; + return s.v1; } diff --git a/tests/test/cg/tcalext6.pp b/tests/test/cg/tcalext6.pp index 1a8f0bf22e..2dc04130dd 100644 --- a/tests/test/cg/tcalext6.pp +++ b/tests/test/cg/tcalext6.pp @@ -14,6 +14,11 @@ program calext6; {$define NO_FLOAT} {$endif} +{$ifdef CPUARMEL} +{ for softfloat calls in the C code } +{$linklib gcc} +{$endif} + type int8_t = shortint; pint8_t = ^int8_t; @@ -156,6 +161,7 @@ begin WriteLn('Failed'); end; +{$ifdef FPC_HAS_TYPE_EXTENDED} procedure verify(val1, val2 : cextended; nr : Integer); overload; begin success := success and (val1 = val2); @@ -165,6 +171,7 @@ begin else WriteLn('Failed'); end; +{$endif FPC_HAS_TYPE_EXTENDED} function check1(s : struct1) : single; begin @@ -253,7 +260,9 @@ end; function check31(s : struct31) : cextended; begin - result := s.v1 + s.v2; + {Ędon't perform an addition, because that causes the C code to depend on + libgcc } + result := s.v1; end; @@ -277,7 +286,7 @@ function pass15(s : struct15; b: byte) : int64_t; cdecl; external; function pass16(s : struct16; b: byte) : single; cdecl; external; function pass17(s : struct17; b: byte) : single; cdecl; external; {$ifdef FPC_HAS_TYPE_EXTENDED} -function pass31(s : struct31; b: byte) : cextended; cdecl; external; +function pass31(s : struct31; b: byte; var ss: single) : cextended; cdecl; external; {$endif} function pass1a(b: byte; s : struct1) : struct1; cdecl; external; @@ -298,7 +307,7 @@ function pass15a(b: byte; s : struct15) : struct15; cdecl; external; function pass16a(b: byte; s : struct16) : struct16; cdecl; external; function pass17a(b: byte; s : struct17) : struct17; cdecl; external; {$ifdef FPC_HAS_TYPE_EXTENDED} -function pass31a(b: byte; s : struct31) : struct31; cdecl; external; +function pass31a(b: byte; s : struct31; var ss: single) : struct31; cdecl; external; {$endif} procedure dotest; @@ -321,6 +330,8 @@ var s16 : struct16; s17 : struct17; s31 : struct31; + + ss: single; begin success := true; @@ -403,7 +414,8 @@ begin verify(pass16(s16,16), check16(s16), 16); verify(pass17(s17,17), check17(s17), 17); {$ifdef FPC_HAS_TYPE_EXTENDED} - verify(pass31(s31,31), check31(s31), 31); + verify(pass31(s31,31,ss), check31(s31), 31); + verify(ss,s31.v2,32); {$endif} verify(check1(pass1a(1,s1)), check1(s1), 41); @@ -424,7 +436,8 @@ begin verify(check16(pass16a(16,s16)), check16(s16), 56); verify(check17(pass17a(17,s17)), check17(s17), 57); {$ifdef FPC_HAS_TYPE_EXTENDED} - verify(check31(pass31a(31,s31)), check31(s31), 71); + verify(check31(pass31a(31,s31,ss)), check31(s31), 71); + verify(ss,s31.v2,72); {$endif} verify(pass1a(1,s1).v, s1.v, 81); @@ -448,7 +461,8 @@ begin verify(pass16a(16,s16).v1, s16.v1, 96); verify(pass17a(17,s17).v1, s17.v1, 97); {$ifdef FPC_HAS_TYPE_EXTENDED} - verify(pass31a(31,s31).v1, s31.v1, 101); + verify(pass31a(31,s31,ss).v1, s31.v1, 101); + verify(ss,s31.v2,102); {$endif} {$endif ndef nofloat}