Soft Float on x86_64

2019-04-19 13:05发布

问题:

I work on software for an embedded system which does not have an FPU. I would like to be able to build this software with a software floating point library on my desktop in order to get a more realistic view of performance. Does anyone have any ideas about how to achieve this?

Thus far I have not made much progress with using -msoft-float with gcc. I am currently looking at using clang. By using the flags -Xclang -msoft-float -Xclang -no-implicit-float and specifying a library which has implementations of soft-float routines, I am able to get my application to compile. When I try to run it, it always segfaults. As best I can tell, this is because the libraries on which this program depends were not compiled with soft-float. The app depends on gtk, sqlite, expat, gcrypt, a number of internal libraries, and libc.

I would like to try to figure out how to build a complete build environment with soft-float support. I tried uclibc's buildroot and setting CC and CXX to clang's binaries, but this did not work due to the requirements for compiling the gcc toolchain (things such as autotools complaining about the compiler version being incorrect). Since I would like to use clang as the compiler in the new buildroot (in order to have soft-float support), I don't see a pressing need to build gcc. Is it possible to do this without gcc?

回答1:

GCC can not do it out-of-box without some additional libraries. Basically, -msoft-float just generate calls for floating point libraries but the required libraries are not part of GCC.

To link the soft-fp libraries you can use the switch -lsoft-fp.

X86_64 architecture contains SSE extensions, so the compiler will try to generate SSE-code for basic operations like + - * /. We will use -mno-sse switch suppress this unauthorized behavior.

It may look as follows:

gcc -g -msoft-float -mno-sse -m64 -lsoft-fp

For the code:

int main()
{
    float a = 10;
    float b = 20;

    float c = a * b;

    return 0;
}

The resulting assembly will be:

    .file   "12.cpp"
    .def    __main; .scl    2;  .type   32; .endef
    .def    __mulsf3;   .scl    2;  .type   32; .endef
    .text
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    subq    $48, %rsp
    .seh_stackalloc 48
    .seh_setframe   %rbp, 48
    .seh_endprologue
    call    __main
    movl    .LC0(%rip), %eax
    movl    %eax, -4(%rbp)
    movl    .LC1(%rip), %eax
    movl    %eax, -8(%rbp)
    movl    -8(%rbp), %edx
    movl    -4(%rbp), %ecx
    call    __mulsf3
    movl    %eax, -12(%rbp)
    movl    $0, %eax
    addq    $48, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .section .rdata,"dr"
    .align 4
.LC0:
    .long   1092616192
    .align 4
.LC1:
    .long   1101004800
    .ident  "GCC: (GNU) 4.8.0 20120624 (experimental)"

No SSE instructions were generated. Note the call to __mulsf3.

Some interesting ideas can be found in this question: Using software floating point on x86 linux