ARM9 cross build fail: Error: selected processor does not support 'umaal r1,r5,r3,r0'

I’m trying to build mbed TLS 2.16.2 for an ARM926EJ-S Linux target
(Atmel AT91SAM9G20). The build fails because the bignum code tries to
use the ‘umaal’ instruction:

$ /home/nextgen/toolchain/bin/arm-linux-gcc --version

arm-linux-gcc (crosstool-NG 1.16.0) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ make clean

$ make CC=/home/nextgen/toolchain/bin/arm-linux-gcc
  CC    aes.c
  CC    aesni.c
  CC    arc4.c
  CC    aria.c
  CC    asn1parse.c
  CC    asn1write.c
  CC    base64.c
  CC    bignum.c
/tmp/ccbTqlwk.s: Assembler messages:
/tmp/ccbTqlwk.s:111: Error: selected processor does not support 'umaal r1,r5,r3,r0'
/tmp/ccbTqlwk.s:115: Error: selected processor does not support 'umaal r1,r5,r3,r0'
/tmp/ccbTqlwk.s:119: Error: selected processor does not support 'umaal r1,r5,r3,r0'
[... 20 more ...]
/tmp/ccbTqlwk.s:209: Error: selected processor does not support 'umaal r1,r5,r3,r0'
/tmp/ccbTqlwk.s:213: Error: selected processor does not support 'umaal r1,r5,r3,r0'
/tmp/ccbTqlwk.s:226: Error: selected processor does not support 'umaal r1,r5,r3,r0'
make[1]: *** [Makefile:196: bignum.o] Error 1
make: *** [Makefile:18: lib] Error 2

The code in question from bn_mul.h appears to be enabled by the
__ARM_FEATURES_DSP macro:

#elif defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)

#define MULADDC_INIT                            \
    asm(

#define MULADDC_CORE                            \
            "ldr    r0, [%0], #4        \n\t"   \
            "ldr    r1, [%1]            \n\t"   \
            "umaal  r1, %2, %3, r0      \n\t"   \
            "str    r1, [%1], #4        \n\t"

#define MULADDC_STOP                            \
         : "=r" (s),  "=r" (d), "=r" (c)        \
         : "r" (b), "0" (s), "1" (d), "2" (c)   \
         : "r0", "r1", "memory"                 \
         );

#else

That macro is defined by my toolchain:

$ /home/nextgen/toolchain/bin/arm-linux-gcc -dM -E - </dev/null | grep ARM
#define __ARMEL__ 1
#define __ARM_ARCH_5TE__ 1
#define __ARM_PCS 1
#define __ARM_EABI__ 1
#define __ARM_FEATURE_DSP 1

I’ve reviewed the ARM9E-S Core Technical Reference Manual, and though
it lists several multiply/accumulate instructions (UMLAL, SMLALx,
SMLAL) there is indeed no UMAAL.

Is this a bug in bn_mult.h?

Shold the code also be checking for !defined(ARM_ARCH_5TE) or
something?

The UMAAL instruction is only supported on ARMv6T2 and later. Simply checking for __ARM_FEATURE_DSP isn’t valid.

Hi @GrantEdwards
Thank you for your report.
We believe that this issue has been fixed and merged in this PR. Could you please confirm?
If so, this should be available on the mbedtls-2.16 branch, and on next release.

Regards,
Mbed TLS Support
Ron

roneld01 wrote:

We believe that this issue has been fixed and merged in this PR. Could you please confirm?

Yes, that appears to work with recent versions of gcc, but it doesn’t work correctly with older versions (e.g. 4.6.3). With older versions of gcc the head of the 2.16 branch does ‘make lib’ cleanly for both ARMv5te and ARMv6t2. but on the v6t2 architecture it isn’t using the umaal instruction as intended. The reason is that the code is checking for the preprocessor symbol __ARM_ARCH:

#elif (__ARM_ARCH >= 6) && \
    defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)
...
#else

That symbol isn’t provided by older versions of GCC:

$ arm-linux-gcc -dM -E - < /dev/null | grep -i arm
#define __ARMEL__ 1
#define __ARM_ARCH_5TE__ 1
#define __ARM_PCS 1
#define __arm__ 1
#define __ARM_EABI__ 1
#define __ARM_FEATURE_DSP 1

I don’t know at what point the __ARM_ARCH symbol was introduced. It would be understandable to abandon support for older versions of GCC, but it might be nice to put in a warning like this:

#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7)

#if !defined(__ARM_ARCH)
#warning "__ARM_ARCH not defined, DSP features won't be used"
#endif

#if defined(__thumb__) && !defined(__thumb2__)
...

In case anybody else runs into this, a simple work-around is to just undefine __ARM_FEATURE_DSP when building for v5 architectures:

make CC="arm-linux-gcc -U__ARM_FEATURE_DSP" lib