 |
How to Resolve StrictMath TCK Failures
There are many possible causes of StrictMath TCK failures. This page will attempt to cover most known causes of failures and provide solutions.
Strict aliasing compilers and fdlibm
In the past there have been many strict aliasing problems in the fdlibm source found in the cdc/src/share/native/java/lang/fdlibm/ directory. These bugs result in wrong results in java.loang.Math and java.lang.StrictMath. Each time they are fixed, the next major release of gcc seems to uncover more problems. For this reason, it is recommened to always compile fdlibm with gcc strict aliasing disable. This can be accomplished with the following line in your GNUmakefile:
CC_ARCH_FLAGS_FDLIB += -fno-strict-aliasing
Strict aliasing has also been a repeated thorn in the side of other CDC source, so as of MR1 and MR2, -fno-strict-aliasing has been made the default for all gcc compiled source on all platforms, making the above setting for CC_ARCH_FLAGS_FDLIB unecessary. If you are using an older version of CDC, you may want to add -fno-strict-aliasing to either
CC_ARCH_FLAGS_FDLIB or CC_ARCH_FLAGS
PowerPC "Fused Mulitiply/Add"
The PowerPC instruction set includes the fmadd instruction, which combines multiplying two registers and adding the result to a 3rd register. This results in extra precission in the result, and will cause "off by one" StrictMath TCK failures. It is easily disabled by adding the following to your GNUmakefile
CC_ARCH_FLAGS_FDLIB += -mno-fused-madd
Incorrect double word endianness
If the double word endianess is set incorrectly, this will result in incorrect results in some Math and StrictMath TCK tests. However, it will also result in many other problems, so if you are only seeing problems with Math and StrictMath, it is not the result of having the endianness set incorrect. The double word endianness is set in cdc/src/<os>-<cpu>/javavm/include/endianness_arch.h. It is normally set correctly automatically, and therefore does not require any user changes.
Extra precission in floating point hardware
Some platforms have floating point hardware that provides more precision than you would normally get when doing 32-bit or 64-bit floating point arithmetic. The PowerPC fmadd instruction mentioned above is one example of this. More commonly, there are floating point registers that contain more than 32 or 64 bits. This results in extra precission in floating point results, which results in "off by one" errors in the StrictMath TCK tests (Math TCK tests should be fine).
For builds using gcc on x86 and MIPS, the extra precission problem was solved with the following in the GNUmakefile:
CC_ARCH_FLAGS_FDLIB = -ffloat-store
For builds using Visual Studio on x86 and MIPS, the extra precission problem was solved with the following in the GNUmakefile:
CC_ARCH_FLAGS_FDLIB = /Op
Visual Studio optimizations cause Math and StrictMath TCK failures
See bug 6255783. The following TCK tests failed:
api/java_lang/StrictMath/desc.html#asin
api/java_lang/StrictMath/desc.html#cos
api/java_lang/StrictMath/desc.html#pow
api/java_lang/StrictMath/desc.html#sin
api/java_lang/StrictMath/desc.html#tan
api/java_lang/Math/cos.html#cos4
api/java_lang/Math/sin.html#sin4
api/java_lang/Math/tan.html#tan4
api/java_lang/Math/cos.html#cos6
api/java_lang/Math/sin.html#sin6
api/java_lang/Math/pow.html#pow1
api/java_lang/Math/cos.html#cos3
api/java_lang/Math/sin.html#sin3
api/java_lang/Math/tan.html#tan3
api/java_lang/Math/cos.html#cos5
api/java_lang/Math/sin.html#sin5
The exact cause is unkown, and possibly does not occur with more recent versions of Visual Studio. To fix the problem, the following is added to the GNUmakefile to disable optimizations in fdlibm when using Visual Studio to compile for an x86 target. It is also added for ARM targets, but it is unclear whether or not it is needed.
CC_ARCH_FLAGS_FDLIB += /Od
Note that this flag results in the fdlibm library not being compiled optimzed.
StrictMath failures on Linux/ARM
If you are seeing StrictMath failures on Linux/ARM, chances are you have a buggy version of the libgcc softfloat support. There are a few approaches to fixing this, depending on the version of gcc you are using.
***In all cases, make sure your gcc is using the version of libgcc.a you build after applying the patch, and if necessary, the patched libgcc_s.so is installed on your device.
Patch for gcc 3.4.x
The simplest solution is to apply the following patch. You can also download a patched copy of ieee754-df.S for gcc 3.4.2.
+++ gcc-3.4.6/gcc/config/arm/ieee754-df.S 2007-03-23 04:25:40.000000000
-0800
@@ -572,6 +572,7 @@
@ Apply exponent bias, check range for underflow.
sub r4, r4, #0x00f80000
subs r4, r4, #0x1f000000
+ movle lr, lr, lsl #12
ble LSYM(Lml_u)
@ Round the result.
Patch for gcc 3.3.x
Patching for gcc 3.3.x is a bit more difficult, since a patch is required just to get ARM softfloat support, and then additional patches are required to fix bugs in this softfloat support. The easiest solution is to just grab this patched copy of ieee754-df.S for gcc 3.3.4, and then rebuild libgcc with it.
Patch to use the C version of the libgcc softfloat support
It is also possible to use the C version of the libgcc softfloat support, which appears to be less buggy than the ARM assembler version. However, there was a problem reported with the 3.4.6 C version that caused the fpl03804m1 TCK test to fail. It is unclear if this failure also exists in earlier versions of gcc.
If you want to use the C version of the libgcc softfloat support, apply the following patch and rebuild (and install) libgcc.
Step 1. Change the LIB1ASMFUNCS? in gcc/config/arm/t-linux to disable the ASM soft float library functions.
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx \
- _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
- _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
- _fixsfsi _fixunssfsi
+LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx
Step 2. Add the following lines in gcc/config/arm/t-linux to enable C soft float library functions.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+fp-bit.c:$(srcdir)/config/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+dp-bit.c:$(srcdir)/config/fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc -fno-inline
-- ChrisPlummer - 08 May 2007
|