8

I'm trying to cross-compile a file to flash into the Beaglebone Black. All works fine, but if I try to enable the FPU with

#define set_en_bit_in_fpexc() do { \
    int dummy; \
    __asm__ __volatile__ ("fmrx %0,fpexc\n\t" \
                         "orr  %0,%0,#0x40000000\n\t" \
                         "fmxr fpexc,%0" : "=r" (dummy) : :); \
} while (0)

I get the following error

Error: selected processor does not support `fmrx r3,fpexc' in ARM mode
Error: selected processor does not support `fmxr fpexc,r3' in ARM mode

I also tried with thumb mode, but I get the same errors. Of course if I remove the part of the code that initialize the FPU it works fine.

Why I get those errors?

Makefile

[...]
CROSSPATH?=/usr/bin
CROSSPFX=$(CROSSPATH)/arm-none-eabi-
CC=$(CROSSPFX)gcc
AS=$(CROSSPFX)as
LD=$(CROSSPFX)ld
NM=$(CROSSPFX)nm
OBJCOPY=$(CROSSPFX)objcopy
OBJDUMP=$(CROSSPFX)objdump
CFLAGS=-Wall -Wextra -O2 -ffreestanding
ARCHFLAGS=-mcpu=cortex-a8 -march=armv7-a -mfpu=neon
CCARCHFLAGS=$(ARCHFLAGS) -marm
[...]

I'm on Arch, kernel 4.8.1

P.S. My professor uses the linaro cross-compiler and it works just fine

artless noise
  • 21,212
  • 6
  • 68
  • 105
igng
  • 372
  • 1
  • 6
  • 17

2 Answers2

4

Most of the Linaro toolchains are configured for ARMv7 hard-float by default (certainly the Linux ones, I'm less sure about the bare-metal ones). Looking at the configuration of the arm-none-eabi toolchain as packaged by Arch, I surmise it's just using the GCC defaults for things like that, which implies something like ARMv4t, and crucially, soft-float ABI.

Whilst the -mfpu option controls code generation in terms of which floating-point instructions may be used, apparently it's the float ABI which controls whether it'll let you do things which really only make sense on a hardware FPU, rather than under floating-point emulation.

When it's not configured by default, you need to explicitly select a floating-point ABI implying an actual hardware FPU, i.e. -mfloat-abi=hard (or -mfloat-abi=softfp, but there's really no reason to use that unless you need to link against other soft-float code).

Notlikethat
  • 20,095
  • 3
  • 40
  • 77
1

-mfpu=vfpv3-d16 -mfloat-abi=hard

Just to give a more direct solution, I had to add -mfpu=vfpv3-d16.

Test code a.S:

fmrx r2, fpscr

Working command:

sudo apt-get install binutils-arm-linux-gnueabihf
arm-linux-gnueabihf-as -mfpu=vfpv3-d16 -mfloat-abi=hard a.S

Note that -mfloat-abi=hard is enabled by default on this particular build of arm-linux-gnueabihf-as, and could be omitted.

The default value of float-abi likely depends on -msoft-float vs -mhard-float controlled at GCC build time with:

./configure --with-float=soft

as documented at: https://gcc.gnu.org/install/configure.html You can get the flags used for your toolchain build with gcc -v as mentioned at: What configure options were used when building gcc / libstdc++? I could not however easily determine its default value if not given.

You may also be interested in -mfloat-abi=softfp which can produce hard floats for the executable, but generate soft function calls: ARM compilation error, VFP registered used by executable, not object file

The possible values of -mfpu= can be found at: https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/ARM-Options.html#ARM-Options

Also note that FMRX is the pre-UAL syntax for VMRS which the newer recommended syntax, see also: Are ARM instructuons SWI and SVC exactly same thing?

Tested on Ubuntu 16.04, arm-linux-gnueabihf-as 2.26.1.

Ciro Santilli
  • 3,693
  • 1
  • 18
  • 44