NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

port-m68k/45857: undefined ref to __fixxfsi in code compiled with -m68040



>Number:         45857
>Category:       port-m68k
>Synopsis:       undefined ref to __fixxfsi in code compiled with -m68040
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    port-m68k-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jan 19 05:00:01 +0000 2012
>Originator:     Jake Hamby
>Release:        5.99.60
>Organization:
Google
>Environment:
NetBSD amiga1 5.99.60 NetBSD 5.99.60 (WARP3000) #0: Sun Jan 15 02:23:14 PST 
2012  
jhamby%fast1.alpha1bbs.org@localhost:/home/jhamby/NetBSD-current/obj/sys/arch/amiga/compile/WARP3000
 amiga
>Description:
GCC 4.5.3 on m68k is generating undefined references to __fixxfsi for any code 
that converts long doubles to int (or short or char) when the "-m68040" flag is 
set (but not -m68060). This is a soft-float function that isn't defined in 
libgcc.a.

What's happening is that gcc/config/m68k/m68k.md generates different code for 
truncating floats to ints when TUNE_68040 is set because the M68040 must trap 
to the kernel to emulate the fintrz instruction that would otherwise be 
generated. This works for doubles, but not for long double types, and for some 
reason GCC is emitting code to call a soft-float routine that isn't included in 
libgcc for those cases.

I've attached a patch that fixes the problem by generalizing the 
fix_truncdfsi2, fix_truncdfhi2, and fix_truncdfqi2 instructions for 
"TARGET_68881 && TUNE_68040" to work for any of the floating point types. I 
haven't tested the code thoroughly yet, so I'll add to the PR if I discover any 
problems with the patch. It's a fairly straightforward change to use the same 
template that other platforms, e.g. i386, use for the same instruction patterns.

It's necessary to rebuild libgcc.a and libgcc_s.so.1 if they were compiled with 
"-m68040" so that its math routines don't include references to the undefined 
__fixxfsi function.
>How-To-Repeat:
This test program will fail to link with an "undefined reference to 
`__fixxfsi'" error when compiled with GCC 4.5.3 and "-m68040". It links and 
runs successfully when GCC and libgcc are recompiled with the attached patch.

#include <stdio.h>

long double gettestvalue() {
        int i;
        long double test = 1.0, test2 = 1.0;
        for (i = 0; i < 10; i++) {
                test2 /= 2;
                test = test + test2;
        }
        return test;
}

int main() {
        long double testval = gettestvalue();
        printf("testval is %Lg\n", testval);
        printf("testval as char is %d\n", (char) testval);
        printf("testval as short is %d\n", (short) testval);
        printf("testval as int is %d\n", (int) testval);
        printf("testval as long long is %lld\n", (long long) testval);
        return 0;
}

>Fix:
Index: external/gpl3/gcc/dist/gcc/config/m68k/m68k.md
===================================================================
RCS file: /cvsroot/src/external/gpl3/gcc/dist/gcc/config/m68k/m68k.md,v
retrieving revision 1.2
diff -u -r1.2 m68k.md
--- external/gpl3/gcc/dist/gcc/config/m68k/m68k.md      21 Jun 2011 02:41:37 
-0000      1.2
+++ external/gpl3/gcc/dist/gcc/config/m68k/m68k.md      19 Jan 2012 04:24:17 
-0000
@@ -2115,9 +2115,9 @@
 ;; into the kernel to emulate fintrz.  They should also be faster
 ;; than calling the subroutines fixsfsi or fixdfsi.
 
-(define_insn "fix_truncdfsi2"
+(define_insn "fix_trunc<mode>si2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
-       (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
+       (fix:SI (match_operand:FP 1 "register_operand" "f")))
    (clobber (match_scratch:SI 2 "=d"))
    (clobber (match_scratch:SI 3 "=d"))]
   "TARGET_68881 && TUNE_68040"
@@ -2126,9 +2126,9 @@
   return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w 
#-33,%3\;fmovem%.l %3,%!\;fmove%.l %1,%0\;fmovem%.l %2,%!";
 })
 
-(define_insn "fix_truncdfhi2"
+(define_insn "fix_trunc<mode>hi2"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
-       (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
+       (fix:HI (match_operand:FP 1 "register_operand" "f")))
    (clobber (match_scratch:SI 2 "=d"))
    (clobber (match_scratch:SI 3 "=d"))]
   "TARGET_68881 && TUNE_68040"
@@ -2137,9 +2137,9 @@
   return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w 
#-33,%3\;fmovem%.l %3,%!\;fmove%.w %1,%0\;fmovem%.l %2,%!";
 })
 
-(define_insn "fix_truncdfqi2"
+(define_insn "fix_trunc<mode>qi2"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
-       (fix:QI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
+       (fix:QI (match_operand:FP 1 "register_operand" "f")))
    (clobber (match_scratch:SI 2 "=d"))
    (clobber (match_scratch:SI 3 "=d"))]
   "TARGET_68881 && TUNE_68040"



Home | Main Index | Thread Index | Old Index