Selecting appropriate ARM -mfpu option in gcc based on CPU features - c

My CPU has following CPU features
cat /proc/cpuinfo
Processor : ARMv7 Processor rev 4 (v7l)
processor : 0
BogoMIPS : 1192.96
processor : 1
BogoMIPS : 1197.05
Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc07
CPU revision : 4
Hardware : sun7i
Revision : 0000
And gcc sets
-march=armv7ve -mfloat-abi=hard -mfpu=vfpv3-d16 -meabi=5
options for
cat main.c
#include <stdio.h>
void main()
{
printf("Hello World!\n");
}
compiled with
gcc -march=native -mtune=native -Q -v main.c
Isn't neon-vfpv4, which seems to be supported by CPU features, is superior to vfpv3-d16, which gcc sets?
I got only vague explanation of what vfpv3-d16 is from ARM's documentation and nothing on neon-vfpv4.
I'm using gcc 4.9.1

-march and -mtune (or -mcpu as a shorthand for both) only control the CPU options for instruction selection and scheduling. As an example, with a GCC 4.8-based cross-toolchain, when I do this:
arm-linux-gnueabihf-gcc -mcpu=arm250 -v -c test.c
I get this:
...
COLLECT_GCC_OPTIONS='-mcpu=arm250' '-v' '-c' '-mfloat-abi=hard'
'-mfpu=vfpv3-d16' '-mthumb' '-mtls-dialect=gnu'
...
which is clearly nonsense - the ARM250 predates VFP (and even Thumb) by a long way - because for any unspecified options it's just passing through whatever was configured as the default:
...
Configured with:
... --with-arch=armv7-a --with-tune=cortex-a9 --with-fpu=vfpv3-d16 ...
... --with-mode=thumb --with-float=hard
Your Cortex-A7 indeed supports full VFPv4 and NEON, so passing -mfpu=neon-vfpv4 to override the default would be the right thing to do. Unfortunately there doesn't seem to be an equivalent -mfpu=native option (at least documented - I don't have a native toolchain handy to check).

Related

How can i emulate an x86 32 bits program on an ARM host?

I am running a Kali Linux distribution on an arm cpu (aarch64).
I have successfully install x86_64-linux-gnux32-gcc and x86_64-linux-gnu-gcc.
I have wrote a basic c program:
#include <stdio.h>
void main()
{
printf("Hello world\n");
}
I have compiled 2 versions:
x86_64-linux-gnu-gcc test1.c -o test1_64
x86_64-linux-gnux32-gcc test1.c -o test1_32
The first binary (64 bits) works fine when i run it with this command:
qemu-x86_64-static ./test1_64
But i have an error with the second binary (32 bits):
qemu-x86_64-static ./test1_32
qemu-x86_64-static: ./test1_32: Invalid ELF image for this architecture
I have tried to force a 32 bits cpu with this command:
qemu-x86_64-static -cpu qemu32 ./test1_32
I have also tried to compile the binary with -static option. I got the same result.
How can i run my 32 bits executable ?
Thanks a lot
x86_64-linux-gnux32-gcc is not what you want for building 32-bit programs. This is actually a 64-bit compiler that targets the x32 ABI, a scheme to have 64-bit code that needs only 32 bits for pointers. It never really caught on and is fairly obscure these days, so I'm not surprised that qemu wouldn't support it.
The x86_64 target of gcc supports building 32-bit programs as well, using the -m32 option. So you ought to be able to build your 32-bit Hello World with
x86_64-linux-gnu-gcc test1.c -o test1_32 -m32
(You might have to separately install 32-bit x86 libraries to successfully cross compile.)
Then to run it, use qemu-i386 instead of qemu-x86_64.
file ./test1_32 should show you that you've still made an x86-64 executable, not i386, with a compiler for the x32 ABI as Nate noticed.
Unfortunately the file output says "ELF 32-bit LSB executable, x86-64, version 1 (SYSV), ..." so the 32-bit part could be misleading.
An actual 32-bit build has "ELF 32-bit LSB executable, Intel 80386,".
A single install of GCC/GAS can build for 32 or 64-bit x86, unlike for ARM32 vs. AArch64 where you need different builds of GCC, so I expect that was part of the confusion. GCC treats i386 and x86-64 as flavours of the same architecture, while AArch64 is treated as a totally separate architecture from ARM. (IDK if GCC did that because x86-64 machine code is similar to 32-bit, so the same assembler can pretty easily handle both. But AArch64 uses a totally different machine code format from ARM32, no point in trying to share code in the assembler between the two architectures.)
So you were probably expecting to need a GCC with 32 in its name to make 32-bit x86 executables. That is not the case.

clang links wrong ARM builtins in thumb mode

I am trying to build Cortex-M0 (ARMv6, thumb) firmware with clang 13.0. Everything seems fine except for builtin functions like __udivsi3, __udivmoddi4 that are in ARM mode. Of course the CPU only supports thumb and delivers a fault when trying to execute them. I know that these functions are wrong because the CPU faults, the debugger displays them as ARM mode and their addresses in the .elf have Lsb cleared. I am linking to newlib provided by gcc (v6 flavor of libc_nano.a) and the libc functions are correct (ie. thumb mode). Functions from my .c files are also correctly built in thumb mode and the firmware runs just fine until it encounters integer division.
My compile options:
clang -o some_file.o -c -MD --target=armv6m-none-eabi -nostdlib
--sysroot="/path/to/newlib/arm-none-eabi" -fshort-enums -mcpu=cortex-m0
-mthumb -mfloat-abi=soft -g3 -I ../some/includes -Oz -std=gnu11
-Wall -pipe -ffunction-sections -fdata-sections some_file.c
My linking options:
clang -o my_project.elf --target=armv6m-none-eabi -nostdlib
-L"/path/to/newlib/arm-none-eabi/lib/." "/path/to/newlib/lib/gcc/arm-none-eabi/9.2.1/libgcc.a"
"/path/to/newlib/arm-none-eabi/lib/thumb/v6-m/nofp/libc_nano.a"
-mcpu=cortex-m0 -mthumb -mfloat-abi=soft -g3 -Wl,--gc-sections
-T my_linker_script.ld object_file1.o object_file2.o object_file3.o -lm
The same happens when I try --target=arm-none-eabi or -mtune=cortex-m0. I am using clang 13.0.0 (official binaries from github). I tried building on both Windows and Linux machines. Clang lists cortex-m0 as available for target arm-none-eabi. llc lists thumb in the list of targets (and all my own functions are correctly built in thumb mode).
What am I doing wrong?
Thanks for help
I traced it down to the wrong libgcc.a being linked. I did not provide the correct architecture/thumb flags when executing arm-none-eabi-gcc -print-libgcc-file-name and it supplied the default version of that library build in ARM mode.

Floating point options difference in gcc for C C++ over AIX (gcc 4.2.0) and Linux (gcc 4.8.5)

My question is: is there an option on gcc Linux that behaves like fast-math on gcc AIX (in this particular case)?
I had to migrate from AIX to Linux, a couple of hundred C and C++ programs. On AIX we used xlc to compile. On Linux we will use gcc.
In some programs, we have floating point operations, I know that floating point could give different results on different platforms, but I'm curious about a situation where gcc gives me a different result than xlc (which is normal), when I add --ffast-math option it gives me the result that I want, but on Linux, the same option doesn't have any impact on the result.
Here's the code and what I've done:
#include <stdio.h>
int main () {
double importe, franja, base, porcentaje, irpf;
printf("/*-----------------*/\n");
importe = 10562.5;
franja = 3.0;
base = 2226.0;
porcentaje = 10.0;
irpf = franja * base * ( porcentaje/ 100 );
printf("Redondeo1 [%.16f]\n", irpf );
importe -= franja * base;
franja = 5;
porcentaje = 15.0;
irpf += importe * ( porcentaje / 100 );
printf("Redondeo2 [%.16f]\n", irpf );
return 0;
}
Compiled with
AIX> /usr/vac/bin/xlc -o redondo.xlc redondo.c
and executed
AIX> redondo.xlc
/*-----------------*/
Redondeo1 [667.8000000000000682]
Redondeo2 [1250.4750000000001364]
Then I tried a first step, compiling with gcc on AIX
AIX> gcc -o redondo.gcc redondo.c
executing it, gives a difference on the second result
AIX> redondo.gcc
/*-----------------*/
Redondeo1 [667.8000000000000682]
Redondeo2 [1250.4749999999999091]
so I tried -ffast-math
AIX> gcc -ffast-math -o redondo.gcc-ffast-math redondo.c
and executed
AIX> redondo.gcc-ffast-math
/*-----------------*/
Redondeo1 [667.8000000000000682]
Redondeo2 [1250.4750000000001364]
solves the situation ....on AIX. When I tried to replicate the solution on Linux, it always gives the same result:
Linux> gcc -o redondo.gcc redondo.c
Linux> redondo.gcc
/*-----------------*/
Redondeo1 [667.8000000000000682]
Redondeo2 [1250.4749999999999091]
Linux> gcc -ffast-math -o redondo.gcc-ffast-math redondo.c
Linux> redondo.gcc-ffast-math
/*-----------------*/
Redondeo1 [667.8000000000000682]
Redondeo2 [1250.4749999999999091]
I know that floating point is non deterministic, not every number is representable, the results depends on the system architecture and the compiler and libraries, etc. etc. .... but perhaps, there's and option on gcc Linux that behaves like fast-math on gcc AIX. I tried a lot of gcc options (frounding-math, mfpmath, contract, store, excess, m387, unsafe, reciprocal, finite, ffast-math) and even reordering the operations, with no success.
AIX info:
AIX> oslevel -s
7100-04-05-1720
AIX> prtconf
System Model: IBM,9009-42A
Processor Type: PowerPC_POWER9
Processor Implementation Mode: POWER 8
Processor Version: PV_8_Compat
Number Of Processors: 2
Processor Clock Speed: 2750 MHz
CPU Type: 64-bit
Kernel Type: 64-bit
LPAR Info: 24 dc4_bpdesa6
Memory Size: 8192 MB
Good Memory Size: 8192 MB
Platform Firmware level: VL910_135
Firmware Version: IBM,VL910_135
Console Login: enable
Auto Restart: true
Full Core: false
AIX> gcc --version
gcc (GCC) 4.2.0
Copyright (C) 2007 Free Software Foundation, Inc.
Linux info:
Linux> cat /etc/os-release
NAME="Red Hat Enterprise Linux Server"
VERSION="7.5 (Maipo)"
ID="rhel"
ID_LIKE="fedora"
VARIANT="Server"
VARIANT_ID="server"
VERSION_ID="7.5"
PRETTY_NAME="Red Hat Enterprise Linux"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:redhat:enterprise_linux:7.5:GA:server"
HOME_URL="https://www.redhat.com/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 7"
REDHAT_BUGZILLA_PRODUCT_VERSION=7.5
REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="7.5"
Linux> gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36)
Copyright (C) 2015 Free Software Foundation, Inc.

clang ARM neon support

I just cross-compiled the clang compiler for ARM on my x86 machine with instructions from here. I am trying to compile a c code containing NEON intrinsics with clang compiler. It is giving error, (which i do not encounter with arm-linux-gnueabi-gcc)
$ clang -march=armv7-a -mfpu=neon -mfloat-abi=soft -integrated-as test.c -o test
In file included from test.c:2:
/home/junaid/llvm/build/Release+Asserts/bin/../lib/clang/3.2/include/arm_neon.h:28:2: error:
"NEON support not enabled"
The line test.c:2 is #include arm_neon.h
It will be the -mfloat-abi=soft. I'm surprised that works for you with an arm-none-linux-gnueabi toolchain.
For Neon support you will want to be targetting either the softfp, or hard float ABI, with either -mfloat-abi=softfp or -mfloat-abi=hard

Building Cross-Compiler: Intel Xeon E5649 >>> ARMv7 with libcURL

i don't exactly understand the manual/help from libcURL. I'm trying to build a Cross-Compiler including the libcURL library. I installed a Cross-Compiler on my Server with the help of this video and can start it with arm-linux-gnueabihf-gcc hello_simple.c. I could compile simple c-code like printf ("Hello World"); After that i tried to install libcURL and read that I need to compile the lib and use the configure file to set the build and host. I used different configuration like: sudo ./configure --build=i586-pc-linux-gnu --host=arm-linux --target=arm-linux --prefix=/home/nevadmin/dev/gcc but neither did one worked. I think I'm making somewhere mistakes. This is the output after configuration is made:
curl version: 7.46.0
Host setup: arm-unknown-linux-gnu
Install prefix: /home/nevadmin/dev/gcc
Compiler: gcc
SSL support: no (--with-{ssl,gnutls,nss,polarssl,mbedtls,cyassl,axtls,winssl,darwinssl} )
SSH support: no (--with-libssh2)
zlib support: no (--with-zlib)
GSS-API support: no (--with-gssapi)
TLS-SRP support: no (--enable-tls-srp)
resolver: default (--enable-ares / --enable-threaded-resolver)
IPv6 support: no (--enable-ipv6)
Unix sockets support: enabled
IDN support: no (--with-{libidn,winidn})
Build libcurl: Shared=yes, Static=yes
Built-in manual: enabled
--libcurl option: enabled (--disable-libcurl-option)
Verbose errors: enabled (--disable-verbose)
SSPI support: no (--enable-sspi)
ca cert bundle: no
ca cert path: no
LDAP support: no (--enable-ldap / --with-ldap-lib / --with-lber-lib)
LDAPS support: no (--enable-ldaps)
RTSP support: enabled
RTMP support: no (--with-librtmp)
metalink support: no (--with-libmetalink)
PSL support: no (libpsl not found)
HTTP2 support: disabled (--with-nghttp2)
Protocols: DICT FILE FTP GOPHER HTTP IMAP POP3 RTSP SMTP TELNET TFTP
My Server cpuinfo:
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 44
model name : Intel(R) Xeon(R) CPU E5649 # 2.53GHz
stepping : 2
microcode : 0x15
cpu MHz : 2533.423
cache size : 12288 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts nopl xtopology tsc_reliable nonstop_tsc aperfmperf pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes hypervisor lahf_lm ida arat dtherm
bogomips : 5066.84
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management:
And my controller:
Processor : ARMv7 Processor rev 2 (v7l)
BogoMIPS : 298.80
Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x3
CPU part : 0xc08
CPU revision : 2
Using for example gcc hello_world.c -o hello_world it compile it for the amd processor architecture and not arm. It seems I'm missing the linking to the library for libcURL? I appreciate every help. And sorry my english, it's not my native language.
Linking with L/home/nevadmin/dev/gcc -lcurl is working an I can compile a c-code with libcURL but it still compiling it for amd64 and not arm. :/
You need to set the proper compiler to use when you configure curl. If you look at curl's configure output from
./configure --help
You'll see this at the end:
...
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir>
LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
CPP C preprocessor
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
You can set these variables with a command line like:
CC=arm-linux-gnueabihf-gcc ./configure --build=i586-pc-linux-gnu --host=arm-linux --target=arm-linux --prefix=/home/nevadmin/dev/gcc
(You don't need the "sudo" to configure.)
gcc by itself will give you an AMD executable. You need to use arm-linux-gnueabihf-gcc to get an ARM executable.
Notice that in your curl configuration output it says
Compiler: gcc
That's why your getting a curl library built for your AMD. Bibliothek is called "library" in English. ;-)
If you continue to have problems cross compiling for ARM you could take a look at the binary releases of the cross compilation tool chain ELLCC. As of version 0.1.21 it comes with several pre-compiled libraries, including curl. Here's the ChangeLog.

Resources