ARM: gmp has no support for thumb interworking

Richard Earnshaw Richard.Earnshaw at buzzard.freeserve.co.uk
Sat Nov 18 00:47:37 CET 2006


On 17 Nov 2006 20:16:25 +0100, Torbjorn Granlund wrote:
> Richard Earnshaw <Richard.Earnshaw at buzzard.freeserve.co.uk> writes:
> 
>   The hand-coded assembler functions in GMP have no support for being built 
>   with interworking as required by the ARM EABI.  This makes it impossible 
>   to link libgmp with any code compiled in Thumb state, and thus now 
>   prevents me from testing GCC development builds by bootstrapping in Thumb 
>   code.
>   
> I suppose "interworking" is something that works poorly in GMP, both
> with ARM and with other architectures.  Whatever it is.
> 

Sorry, I forget that not everybody who's seen some ARM assembler is going 
to be intimate with all the details.

ARM since architecture 4T has had two instruction sets: ARM and Thumb.  
The Thumb instructions are a 'compressed' 16-bit encoding of the most 
common ARM instructions and can be used to improve code density (typically 
by about 30%).  Interworking is when you write your code so that it can 
call (and be called from) the other instruction set from that in which it 
is written.

In architecture 4T there is just one instruction that can switch 
instruction sets: BX <reg>; this instruction needs to be used wherever mov 
pc, <reg> was previously used and must also not load values directly into 
the PC from memory (this latter restriction is lifted in architecture 5 
and above).  It's the linker's job to fix up direct call instructions (BL 
foo), but indirect call and return sequences need to be adjusted.

The problem is made more tricky by the fact that BX was a new instruction 
in architecture 4T, so there is no code sequence that is *both* 
interworking safe and backwards compatible with older architectures.  The 
best way around this in assembly routines is by using macros (the 
assembler routines that form libgcc.a have most if not all of the macros 
that you might need -- see gcc/config/arm/lib1funcs.asm in the gcc 
sources).

In summary,
        old code                             interworking code 
	mov	pc, lr			     bx lr

	ldr	pc, [address]                ldr <scratch>, [address]
                                             bx <scratch>

	ldmia   sp, {reg-list, pc}           ldmia sp, {reg-list, lr} (assuming 
lr is free)
                                             bx lr



>   The functions also unconditionally assume the presence of ARM architecture 
>   4.  Again this means that it is no longer possible to build a native 
>   version of GCC that will run on architecture 3 or earlier parts.
>   
> Oh man, this sounds serious.
> 
> If you worry about these shortcomings, and want them fixed, you need
> to be provide more detail.  I don't care about ARM, and I don't intend
> to spend my leisure time on trying to figure out what you're talking
> about.
> 
> But I'll try and fix the problems if you make it easy for me.

I'll help as much as I can, but I can't provide patches at this time.

> 
>   Also note that it is not possible to force use of the generic routines, 
>   because the longlong.h header assumes that the assembly functions exist 
>   and can be called.
> 
> Sure possible.  First step is to check the manual's chapter on how to
> install gmp.
> 

Now you've lost me.  Do you mean setting MPN_PATH=generic during 
configure?  if so, I've already tried it and it doesn't work.  I get link 
errors because udiv_qrnnd is #defined in longlong.h as a call to 
udiv_qrnnd_preinv, which is one of the assembler routines in the ARM 
directory.  building with -DLONGLONG_STANDALONE doesn't help either, 
because __gmpn_add_nc isn't defined anywhere.

Note: 

export MPN_PATH=generic; configure; make; make check 

fails even on i386 with

(cd .libs && rm -f libtests.la && ln -s ../libtests.la libtests.la)
gcc -DHAVE_CONFIG_H -I. -I/home/rearnsha/gnusrc/gmp-4.2.1/tests -I.. 
-I/home/rearnsha/gnusrc/gmp-4.2.1    -m32 -O2 -fomit-frame-pointer 
-mcpu=pentium4 -march=pentium4 -c /home/rearnsha/gnusrc/gmp-4.2.1/tests/t-b
swap.c
/usr/pkg/bin/bash ../libtool --mode=link gcc  -m32 -O2 
-fomit-frame-pointer -mcpu=pentium4 -march=pentium4   -o t-bswap  
t-bswap.o libtests.la ../libgmp.la
gcc -m32 -O2 -fomit-frame-pointer -mcpu=pentium4 -march=pentium4 -o 
.libs/t-bswap t-bswap.o  ./.libs/libtests.a /work/rearnsha/gnu/gmp/.libs/li
bgmp.so ../.libs/libgmp.so -Wl,--rpath -Wl,/usr/local/lib
/work/rearnsha/gnu/gmp/.libs/libgmp.so: undefined reference to 
`__gmpn_add_nc'
/work/rearnsha/gnu/gmp/.libs/libgmp.so: undefined reference to 
`__gmpn_sub_nc'
gnumake[4]: *** [t-bswap] Error 1












More information about the gmp-bugs mailing list