Subject: bug#12754: factor.c selects 64 bit code from longlong.h on 32-bit hppa systems

From: Pádraig Brady <[email-masked]>
Date: Tue, 30 Oct 2012 01:59:11 +0000

On 10/29/2012 01:27 PM, Torbjorn Granlund wrote:
> Pádraig Brady <[email-masked]> writes:
>
>    Sure, but from the message linked above it seems that
>    the size of uintmax_t is significant here rather than the "word" size.
>
>    Torbjorn should W_TYPE_SIZE match the "word" size or uintmax_t ?
>
> We're setting things up for arithmetic on uintmax_t (one or two of
> these).
>
> W_TYPE_SIZE is then used to ask longlong.h to define a couple of macros
> (documented in the beginning of that file) which provide arithmetic
> based on that size.  Then longlong.h will do it in assembly or in C.
>
> W_TYPE_SIZE must thus be the size of uintmax_t.
>
> The problems we've seen are related to this slightly backward use of
> longlong in factor.c.  In GMP (the main home of longlong.h) we figure
> out the real word size, and then define W_TYPE_SIZE to that.
>
> The trick around this is to find better API specific predefs to test in
> longlong.h, juist like Pádraig did for sparc.  If no such predefs exist,
> we can either set something up via configure to define some cpp symbol,
> or we need to disable the problematic assembly.  This will hurt
> performance, but will not affect program behaviour.

OK thanks for the info.
I tested with gcc-4.3.2 on 9000/785/J6000 and similarly
to the sparc case, the default compile failed because
gcc defaulted to a more compatible arch.

So using the same technique to get something for
the preprocessor to key on...

$ for cpu in 1.0 1.1 2.0; do
   echo "--------- $cpu --------"
   cpp -march=$cpu -dM /dev/null |
   grep -i pa_
done
--------- 1.0 --------
#define _PA_RISC1_0 1
#define __hppa__ 1
--------- 1.1 --------
#define _PA_RISC1_1 1
#define __hppa__ 1
--------- 2.0 --------
#define _PA_RISC2_0 1
#define __hppa__ 1

Since 2.0 is the only arch that supports the 64 bit hppa code in longlong.h,
the following enables the code to compile by default.

diff --git a/src/longlong.h b/src/longlong.h
index 8d71611..8b01696 100644
--- a/src/longlong.h
+++ b/src/longlong.h
@@ -679,7 +679,7 @@ extern UWtype __MPN(udiv_qrnnd) (UWtype *, UWtype, UWtype, UWtype);
  /* These macros are for ABI=2.0w.  In ABI=2.0n they can't be used, since GCC
     (3.2) puts longlong into two adjacent 32-bit registers.  Presumably this
     is just a case of no direct support for 2.0n but treating it like 1.0. */
-#if defined (__hppa) && W_TYPE_SIZE == 64 && ! defined (_LONG_LONG_LIMB)
+#if defined (__hppa) && defined (_PA_RISC2_0) && W_TYPE_SIZE == 64 && ! defined (_LONG_LONG_LIMB)
  #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
    __asm__ ("add%I5 %5,%r4,%1\n\tadd,dc %r2,%r3,%0"                     \
            : "=r" (sh), "=&r" (sl)                                      \

Note even though I've not encountered a system yet where uintmax_t != 64 bit,
I'll add the guards around "#define W_TYPE_SIZE", previously mentioned in
this thread, in a separate patch.

cheers,
Pádraig.