On Fri, Jul 02, 2004 at 03:50:17PM -0700, Marcel Moolenaar wrote: > On Sat, Jul 03, 2004 at 12:19:36AM +0300, Ruslan Ermilov wrote: > > > > > > No. It's a compiler bug on sparc64. I think the old binutils just > > > didn't complain about the invalid instruction. I compared the > > > output of the native cc and the cross cc and they are different. > > > Not much, but fataly so. > > > > > Yes, I produced that diff as well (by using -save-temps). > > Unfortunately, I don't know sparc64 assembler at all... > > [context: the faulty instruction is the fstox in the following snippet] > > fmuls %f8, %f9, %f8 > fstox %f8, %f7 > st %f8, [%fp+2031] > > As far as I can tell, the fstox is faulty because the target > FP register is a double extended FP, which therefore has to be > an even numbered FP register. The native cc uses %f12, while > the cross cc uses %f7. > > Simply replacing %f7 with %f6 or %f8 resolves the problem. Note > that %f8 should have been the register, because it's used by > the subsequent st instruction. > > I have no idea why a cross cc would trigger this. Maybe there's > a flags field with more than 32 flags and defined as long. On 64-bit > machines this works out well, on 32-bit machines this breaks. > I dunno... > I hit this bug also with a native compilation on sparc64 trying to build nmap. The patch below fixes both the cross-buildworlds and the nmap build. It's taken from the GCC gcc-3_3-branch branch (sparc.h revision 1.215.4.4) so it can be committed to the FSF branch in FreeBSD. It's also part of GCC 3.4 and 3.4.1. I have no idea why GNU tar trigged the bug only when cross building for sparc64. Index: sparc.h =================================================================== RCS file: /usr/data/bsd/cvs/fbsd/src/contrib/gcc/config/sparc/sparc.h,v retrieving revision 1.1.1.6 diff -u -r1.1.1.6 sparc.h --- sparc.h 11 Jul 2003 03:40:53 -0000 1.1.1.6 +++ sparc.h 7 Jul 2004 13:02:48 -0000 _at__at_ -1233,6 +1233,20 _at__at_ {-1, -1, -1, 0x20}, /* GENERAL_OR_EXTRA_FP_REGS */ \ {-1, -1, -1, 0x3f}} /* ALL_REGS */ +/* Defines invalid mode changes. Borrowed from pa64-regs.h. + + SImode loads to floating-point registers are not zero-extended. + The definition for LOAD_EXTEND_OP specifies that integer loads + narrower than BITS_PER_WORD will be zero-extended. As a result, + we inhibit changes from SImode unless they are to a mode that is + identical in size. */ + +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + (TARGET_ARCH64 \ + && (FROM) == SImode \ + && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ + ? reg_classes_intersect_p (CLASS, FP_REGS) : 0) + /* The same information, inverted: Return the class number of the smallest class containing reg number REGNO. This could be a conditional expressionReceived on Wed Jul 07 2004 - 18:05:44 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:00 UTC