GCC with Cortex-M4 hard float link error "X uses VFP register arguments, Y does not"

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

GCC with Cortex-M4 hard float link error "X uses VFP register arguments, Y does not"

Johannes Bauer-2
Hi list,

I have a problem with gcc-4.7.1 (and g++) for ARM, specifically the
Cortex M4 (Thumb2 variant). I've compiled it with newlib and multilib
support and am now trying to get hard float running, with no success so
far. Showing that multilib is enabled:

$ arm-none-eabi-g++ -print-multi-lib
.;
thumb;@mthumb
fpu;@mfloat-abi=hard

I compile with

arm-none-eabi-gcc -Wall -O2 -g -mcpu=cortex-m4 -mfloat-abi=hard -mthumb
-std=c99 -c -o foo.o foo.c

Compiling the modules works fine and hard float instructions are generated:

0000013c <floattest(float)>:
 13c:   ed9f 7b08       vldr    d7, [pc, #32]   ; 160
<floattest(float)+0x24>
 140:   eeb7 0ac0       vcvt.f64.f32    d0, s0
 144:   ee20 0b07       vmul.f64        d0, d0, d7
 148:   ed9f 7b07       vldr    d7, [pc, #28]   ; 168
<floattest(float)+0x2c>
 14c:   eeb7 0bc0       vcvt.f32.f64    s0, d0
 150:   eeb7 0ac0       vcvt.f64.f32    d0, s0
 154:   ee30 0b07       vadd.f64        d0, d0, d7
 158:   eeb7 0bc0       vcvt.f32.f64    s0, d0
 15c:   4770            bx      lr
 15e:   bf00            nop
 160:   e631f8a1        .word   0xe631f8a1
 164:   40c81cd6        .word   0x40c81cd6
 168:   692b3cc5        .word   0x692b3cc5
 16c:   3f5437c5        .word   0x3f5437c5

When it comes to linking, however, this is a different story. For each
module "m" and the final ELF target "t" I get a message:

[...]/bin/arm/lib/gcc/arm-none-eabi/4.7.1/../../../../arm-none-eabi/bin/ld:
error: m.o uses VFP register arguments, t does not
[...]/bin/arm/lib/gcc/arm-none-eabi/4.7.1/../../../../arm-none-eabi/bin/ld:
failed to merge target specific data of file m.o

I'm guessing it's trying to link newlib stuff in from the libcrt* which
might not be compiled with hard float, can that be correct? Then why
would gcc's multilib show the correct strings? Could somebody please
explain to me what I'm doing wrong?

Thank you very much,
Joe
Reply | Threaded
Open this post in threaded view
|

Re: GCC with Cortex-M4 hard float link error "X uses VFP register arguments, Y does not"

Matthew Gretton-Dann
On 22 August 2012 16:20, Johannes Bauer <[hidden email]> wrote:

> Hi list,
>
> I have a problem with gcc-4.7.1 (and g++) for ARM, specifically the
> Cortex M4 (Thumb2 variant). I've compiled it with newlib and multilib
> support and am now trying to get hard float running, with no success so
> far. Showing that multilib is enabled:
>
> $ arm-none-eabi-g++ -print-multi-lib
> .;
> thumb;@mthumb
> fpu;@mfloat-abi=hard
>
> I compile with
>
> arm-none-eabi-gcc -Wall -O2 -g -mcpu=cortex-m4 -mfloat-abi=hard -mthumb
> -std=c99 -c -o foo.o foo.c
>
> Compiling the modules works fine and hard float instructions are generated:
>
> 0000013c <floattest(float)>:
>  13c:   ed9f 7b08       vldr    d7, [pc, #32]   ; 160
> <floattest(float)+0x24>
>  140:   eeb7 0ac0       vcvt.f64.f32    d0, s0
>  144:   ee20 0b07       vmul.f64        d0, d0, d7
>  148:   ed9f 7b07       vldr    d7, [pc, #28]   ; 168
> <floattest(float)+0x2c>
>  14c:   eeb7 0bc0       vcvt.f32.f64    s0, d0
>  150:   eeb7 0ac0       vcvt.f64.f32    d0, s0
>  154:   ee30 0b07       vadd.f64        d0, d0, d7
>  158:   eeb7 0bc0       vcvt.f32.f64    s0, d0
>  15c:   4770            bx      lr
>  15e:   bf00            nop
>  160:   e631f8a1        .word   0xe631f8a1
>  164:   40c81cd6        .word   0x40c81cd6
>  168:   692b3cc5        .word   0x692b3cc5
>  16c:   3f5437c5        .word   0x3f5437c5
>
> When it comes to linking, however, this is a different story. For each
> module "m" and the final ELF target "t" I get a message:
>
> [...]/bin/arm/lib/gcc/arm-none-eabi/4.7.1/../../../../arm-none-eabi/bin/ld:
> error: m.o uses VFP register arguments, t does not
> [...]/bin/arm/lib/gcc/arm-none-eabi/4.7.1/../../../../arm-none-eabi/bin/ld:
> failed to merge target specific data of file m.o
>
> I'm guessing it's trying to link newlib stuff in from the libcrt* which
> might not be compiled with hard float, can that be correct? Then why
> would gcc's multilib show the correct strings? Could somebody please
> explain to me what I'm doing wrong?

A couple of questions which may help diagnose the issue:

1) How have you configured GCC? (What does gcc -v show?)

2) What does the following command say is the directory in use?

  arm-none-eabi-gcc -Wall -O2 -g -mcpu=cortex-m4 -mfloat-abi=hard -mthumb \
      -std=c99 -c -o foo.o foo.c -print-multi-directory

Thanks,

Matt

--
Matthew Gretton-Dann
Linaro Toolchain Working Group
[hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: GCC with Cortex-M4 hard float link error "X uses VFP register arguments, Y does not"

Johannes Bauer-2
Hi Matt,

On 22.08.2012 17:37, Matthew Gretton-Dann wrote:

>> I'm guessing it's trying to link newlib stuff in from the libcrt* which
>> might not be compiled with hard float, can that be correct? Then why
>> would gcc's multilib show the correct strings? Could somebody please
>> explain to me what I'm doing wrong?
>
> A couple of questions which may help diagnose the issue:
>
> 1) How have you configured GCC? (What does gcc -v show?)

Using built-in specs.
COLLECT_GCC=arm-none-eabi-gcc
COLLECT_LTO_WRAPPER=/home/joe/bin/arm/libexec/gcc/arm-none-eabi/4.7.1/lto-wrapper
Target: arm-none-eabi
Configured with: ../configure --prefix=/home/joe/bin/arm/
--enable-interwork --enable-multilib --with-newlib
--with-headers=/tmp/newlib-1.19.0/newlib/libc/include
--target=arm-none-eabi --disable-nls --disable-shared --disable-threads
--with-gnu-ld --with-gnu-as --disable-libssp --disable-libmudflap
--disable-libgomp --with-dwarf2 -v --disable-werror --with-cpu=cortex-m3
--with-cpu=cortex-m4 --with-tune=cortex-m3 --with-tune=cortex-m4
--with-mode=thumb --enable-target-optspace --with-float=hard
--with-float=soft --enable-languages=c,c++
Thread model: single
gcc version 4.7.1 (GCC)


> 2) What does the following command say is the directory in use?
>
>   arm-none-eabi-gcc -Wall -O2 -g -mcpu=cortex-m4 -mfloat-abi=hard -mthumb \
>       -std=c99 -c -o foo.o foo.c -print-multi-directory

This shows surprisingly little (only the CWD):
.

Also, if it is helpful, I've configured newlib like this:

./configure --target=arm-none-eabi --prefix='/home/joe/bin/arm/'
--disable-interwork --enable-thumb --enable-multilib --disable-libssp
--disable-nls --disable-newlib-supplied-syscalls

Best regards,
Joe


Reply | Threaded
Open this post in threaded view
|

Re: GCC with Cortex-M4 hard float link error "X uses VFP register arguments, Y does not"

Matthew Gretton-Dann
On 22 August 2012 17:38, Johannes Bauer <[hidden email]> wrote:

> Hi Matt,
>
> On 22.08.2012 17:37, Matthew Gretton-Dann wrote:
>
>>> I'm guessing it's trying to link newlib stuff in from the libcrt* which
>>> might not be compiled with hard float, can that be correct? Then why
>>> would gcc's multilib show the correct strings? Could somebody please
>>> explain to me what I'm doing wrong?
>>
>> A couple of questions which may help diagnose the issue:
>>
>> 1) How have you configured GCC? (What does gcc -v show?)
>
> Using built-in specs.
> COLLECT_GCC=arm-none-eabi-gcc
> COLLECT_LTO_WRAPPER=/home/joe/bin/arm/libexec/gcc/arm-none-eabi/4.7.1/lto-wrapper
> Target: arm-none-eabi
> Configured with: ../configure --prefix=/home/joe/bin/arm/
> --enable-interwork --enable-multilib --with-newlib
> --with-headers=/tmp/newlib-1.19.0/newlib/libc/include
> --target=arm-none-eabi --disable-nls --disable-shared --disable-threads
> --with-gnu-ld --with-gnu-as --disable-libssp --disable-libmudflap
> --disable-libgomp --with-dwarf2 -v --disable-werror --with-cpu=cortex-m3
> --with-cpu=cortex-m4 --with-tune=cortex-m3 --with-tune=cortex-m4
> --with-mode=thumb --enable-target-optspace --with-float=hard
> --with-float=soft --enable-languages=c,c++
> Thread model: single
> gcc version 4.7.1 (GCC)

The multiple --with-cpu/--with-tune/--with-float options are
confusing, although probably OK as 'rightmost' should win.

You only need one of each of --with-cpu, --with-tune, and
--with-float.  [As an aside --with-cpu implies --with-tune for the
same CPU].

What I think you are missing is a default FPU though.  Add
--with-fpu=fpv4-sp-d16 to the configure line, and that should help.

In summary I think you want the following --with-* options on your command line:

   --with-cpu=cortex-m4 --with-fpu=fpv4-sp-d16 --with-mode=thumb
--with-float=soft

>> 2) What does the following command say is the directory in use?
>>
>>   arm-none-eabi-gcc -Wall -O2 -g -mcpu=cortex-m4 -mfloat-abi=hard -mthumb \
>>       -std=c99 -c -o foo.o foo.c -print-multi-directory
>
> This shows surprisingly little (only the CWD):
> .

This means that GCC has selected the default library to use, which
isn't what you want.  If the compiler has been configured correctly
then I would expect the output to be 'fpu'.

Once you've rebuilt GCC you will also need to build newlib again.
Your configuration options for that should be fine - as it will pick
the multilibs up from GCC.

I hope this helps.

Matt

--
Matthew Gretton-Dann
Linaro Toolchain Working Group
[hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: GCC with Cortex-M4 hard float link error "X uses VFP register arguments, Y does not"

Johannes Bauer-2
On 22.08.2012 22:24, Matthew Gretton-Dann wrote:

>>> 1) How have you configured GCC? (What does gcc -v show?)
>>
>> Using built-in specs.
>> COLLECT_GCC=arm-none-eabi-gcc
>> COLLECT_LTO_WRAPPER=/home/joe/bin/arm/libexec/gcc/arm-none-eabi/4.7.1/lto-wrapper
>> Target: arm-none-eabi
>> Configured with: ../configure --prefix=/home/joe/bin/arm/
>> --enable-interwork --enable-multilib --with-newlib
>> --with-headers=/tmp/newlib-1.19.0/newlib/libc/include
>> --target=arm-none-eabi --disable-nls --disable-shared --disable-threads
>> --with-gnu-ld --with-gnu-as --disable-libssp --disable-libmudflap
>> --disable-libgomp --with-dwarf2 -v --disable-werror --with-cpu=cortex-m3
>> --with-cpu=cortex-m4 --with-tune=cortex-m3 --with-tune=cortex-m4
>> --with-mode=thumb --enable-target-optspace --with-float=hard
>> --with-float=soft --enable-languages=c,c++
>> Thread model: single
>> gcc version 4.7.1 (GCC)
>
> The multiple --with-cpu/--with-tune/--with-float options are
> confusing, although probably OK as 'rightmost' should win.

Ah okay, interesting. I was deliberately adding both because I work with
both the Cortex-M3 and Cortex-M4 and wanted to build one GCC that works
for both. Is this not possible? It wouldn't be a problem to build
different gccs (only inconvenient), but that would be very good to know
(if it's at all possible).

> You only need one of each of --with-cpu, --with-tune, and
> --with-float.  [As an aside --with-cpu implies --with-tune for the
> same CPU].
>
> What I think you are missing is a default FPU though.  Add
> --with-fpu=fpv4-sp-d16 to the configure line, and that should help.
>
> In summary I think you want the following --with-* options on your command line:
>
>    --with-cpu=cortex-m4 --with-fpu=fpv4-sp-d16 --with-mode=thumb
> --with-float=soft

Okay, I'm rebuilding right now. Curious though, since you specified
"--with-float=soft" -- at the moment, softfloat is working (actually
it's the only thing working), so what exactly does "with-float=soft" do
in conjunction with a default FPU specification? I find the options kind
of confusing to be honest and don't really know what they do exactly.

>>>   arm-none-eabi-gcc -Wall -O2 -g -mcpu=cortex-m4 -mfloat-abi=hard -mthumb \
>>>       -std=c99 -c -o foo.o foo.c -print-multi-directory
>>
>> This shows surprisingly little (only the CWD):
>> .
>
> This means that GCC has selected the default library to use, which
> isn't what you want.  If the compiler has been configured correctly
> then I would expect the output to be 'fpu'.

Okay, I'll check that.

> Once you've rebuilt GCC you will also need to build newlib again.
> Your configuration options for that should be fine - as it will pick
> the multilibs up from GCC.
>
> I hope this helps.

It does greatly. I'm compiling both gcc and newlib right now again and
will report what the results are. Thank you very much for your support.

Best regards,
Joe
Reply | Threaded
Open this post in threaded view
|

Re: GCC with Cortex-M4 hard float link error "X uses VFP register arguments, Y does not"

Matthew Gretton-Dann
On 22 August 2012 22:07, Johannes Bauer <[hidden email]> wrote:

> On 22.08.2012 22:24, Matthew Gretton-Dann wrote:
>
>>>> 1) How have you configured GCC? (What does gcc -v show?)
>>>
>>> Using built-in specs.
>>> COLLECT_GCC=arm-none-eabi-gcc
>>> COLLECT_LTO_WRAPPER=/home/joe/bin/arm/libexec/gcc/arm-none-eabi/4.7.1/lto-wrapper
>>> Target: arm-none-eabi
>>> Configured with: ../configure --prefix=/home/joe/bin/arm/
>>> --enable-interwork --enable-multilib --with-newlib
>>> --with-headers=/tmp/newlib-1.19.0/newlib/libc/include
>>> --target=arm-none-eabi --disable-nls --disable-shared --disable-threads
>>> --with-gnu-ld --with-gnu-as --disable-libssp --disable-libmudflap
>>> --disable-libgomp --with-dwarf2 -v --disable-werror --with-cpu=cortex-m3
>>> --with-cpu=cortex-m4 --with-tune=cortex-m3 --with-tune=cortex-m4
>>> --with-mode=thumb --enable-target-optspace --with-float=hard
>>> --with-float=soft --enable-languages=c,c++
>>> Thread model: single
>>> gcc version 4.7.1 (GCC)
>>
>> The multiple --with-cpu/--with-tune/--with-float options are
>> confusing, although probably OK as 'rightmost' should win.
>
> Ah okay, interesting. I was deliberately adding both because I work with
> both the Cortex-M3 and Cortex-M4 and wanted to build one GCC that works
> for both. Is this not possible? It wouldn't be a problem to build
> different gccs (only inconvenient), but that would be very good to know
> (if it's at all possible).

The configure option --with-cpu=, --with-fpu=, &c specify the defaults
GCC should use if no options are specified on the command line (-mcpu,
-mfpu, &c).  So you can specify different cores when building.

The issue comes with building different multilibs for the different
cores.  This is possible, but difficult to explain, and can involve
changing bits of the GCC source.  So, I will point you in the
direction of the ARM Embedded release of GCC:
https://launchpad.net/gcc-arm-embedded.  This is targetted at
M-profile cores, and provides appropriate multi-libs.  If its
appropriate you can use what they provide - there are binaries and
instructions on how to build from source available.

>> You only need one of each of --with-cpu, --with-tune, and
>> --with-float.  [As an aside --with-cpu implies --with-tune for the
>> same CPU].
>>
>> What I think you are missing is a default FPU though.  Add
>> --with-fpu=fpv4-sp-d16 to the configure line, and that should help.
>>
>> In summary I think you want the following --with-* options on your command line:
>>
>>    --with-cpu=cortex-m4 --with-fpu=fpv4-sp-d16 --with-mode=thumb
>> --with-float=soft
>
> Okay, I'm rebuilding right now. Curious though, since you specified
> "--with-float=soft" -- at the moment, softfloat is working (actually
> it's the only thing working), so what exactly does "with-float=soft" do
> in conjunction with a default FPU specification? I find the options kind
> of confusing to be honest and don't really know what they do exactly.

-mcpu/--with-cpu, -mfpu/--with-fpu, -mfloat-abi/--with-float are,
generally, orthogonal options:

 -mcpu/--with-cpu selects the integer side instruction set available.
 -mfpu/--with-fpu selects the FP/Advanced SIMD/WMMX instruction set available.
 -mfloat-abi/--with-float selects how floating-point instructions may be used.

The manual gives full details, but in summary:

 * -mfloat-abi=soft means don't use any Floating-Point instructions
anywhere, simulate them with integer side instructions.
 * -mfloat-abi=softfp means you can use FP instructions, but still use
the standard calling convention which passes float/double arguments in
integer registers.
 * -mfloat-abi=hard means you can use FP instructions, and the calling
convention changes to pass float/double arguments in S/D registers.

Thanks,

Matt

--
Matthew Gretton-Dann
Linaro Toolchain Working Group
[hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: GCC with Cortex-M4 hard float link error "X uses VFP register arguments, Y does not"

Johannes Bauer-2
On 23.08.2012 09:53, Matthew Gretton-Dann wrote:

> The issue comes with building different multilibs for the different
> cores.  This is possible, but difficult to explain, and can involve
> changing bits of the GCC source.  So, I will point you in the
> direction of the ARM Embedded release of GCC:
> https://launchpad.net/gcc-arm-embedded.  This is targetted at
> M-profile cores, and provides appropriate multi-libs.  If its
> appropriate you can use what they provide - there are binaries and
> instructions on how to build from source available.

Ah, interesting. I didn't know this was so complicated. Looked at their
build instructions PDF and it appears that they provided modified
sourcecode which already handles the magic. Probably the source code
changed that you spoke of are already patched in there, I'm assuming.

It's not a big deal to compile multiple gcc variants for me for
different compiler, just something to be aware of.

>>> You only need one of each of --with-cpu, --with-tune, and
>>> --with-float.  [As an aside --with-cpu implies --with-tune for the
>>> same CPU].
>>>
>>> What I think you are missing is a default FPU though.  Add
>>> --with-fpu=fpv4-sp-d16 to the configure line, and that should help.
>>>
>>> In summary I think you want the following --with-* options on your command line:
>>>
>>>    --with-cpu=cortex-m4 --with-fpu=fpv4-sp-d16 --with-mode=thumb
>>> --with-float=soft

The only change I did was "--"with-float=hard" instead of "soft", then
it worked perfectly (the --with-fpu switch was apparently missing).
Thank you very much!

> -mcpu/--with-cpu, -mfpu/--with-fpu, -mfloat-abi/--with-float are,
> generally, orthogonal options:
>
>  -mcpu/--with-cpu selects the integer side instruction set available.
>  -mfpu/--with-fpu selects the FP/Advanced SIMD/WMMX instruction set available.
>  -mfloat-abi/--with-float selects how floating-point instructions may be used.
>
> The manual gives full details, but in summary:
>
>  * -mfloat-abi=soft means don't use any Floating-Point instructions
> anywhere, simulate them with integer side instructions.
>  * -mfloat-abi=softfp means you can use FP instructions, but still use
> the standard calling convention which passes float/double arguments in
> integer registers.
>  * -mfloat-abi=hard means you can use FP instructions, and the calling
> convention changes to pass float/double arguments in S/D registers.

Thank you for that explanation as well, it makes things much clearer.

Have a nice day,
Best regards,
Johannes