Yes, the GNU Compiler Collection (GCC) does work on ARM processors. GCC is a widely used compiler system that supports multiple programming languages and targets various instruction set architectures, including ARM.
GCC can generate both 32-bit and 64-bit ARM machine code that is optimized for different ARM architectures. This allows developers to compile source code written in languages like C, C++, Objective-C, and Fortran for ARM devices.
Overview of GCC and ARM
GCC started out as the GNU C Compiler and was originally written by Richard Stallman in 1987 for the GNU operating system. Over time it evolved into a cross-platform compiler system that could target many CPU architectures beyond x86, including ARM.
ARM refers to the instruction set architecture designed by ARM Holdings for use in embedded systems and mobile devices. Unlike x86, ARM relies on reduced instruction set computing (RISC) which favors simpler instructions that can execute quickly. This makes ARM ideal for low-power devices.
GCC contains front ends for converting source code into compiler IR, optimizing passes to improve the IR, and back ends to convert IR into target machine code. The ARM backend supports generating code for the various ARM instruction sets like ARMv6, ARMv7-A, ARMv8-A etc.
Generating ARM Code with GCC
To generate ARM code with GCC, you need to specify one of the ARM target triples during compilation. Some examples:
- arm-none-eabi – for bare metal ARM
- arm-linux-gnueabihf – for ARM Linux in hard-float mode
- arm-linux-gnueabi – for ARM Linux in soft-float mode
- aarch64-linux-gnu – for 64-bit ARM Linux
For example: gcc -march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8 -c test.c -o test.o
This compiles test.c into test.o targeting ARMv7-A architecture, hard-float ABI, with NEON SIMD support, and optimized for Cortex-A8 CPU.
The ARM backends in GCC support -mcpu and -mtune flags to generate code optimized for specific ARM processors. There are also flags like -mthumb and -mfloat-abi to control the instruction set and floating point ABI used.
Supported Languages and Features
GCC supports compiling several programming languages for ARM:
- C – Full C89/C90, C99 and partial C11 support
- C++ – Full C++98/C++03 and partial C++11/C++14 support
- Objective-C/Objective-C++ – Objective-C variant used in Apple iOS development
- Fortran – Fortran 77 and partial Fortran 90/95 support
- Ada – Ada 95 and partial Ada 2005 support
- Go – Go language support
Beyond compiling to ARM assembly, GCC enables linking against pre-compiled libraries like libc, dynamic loading, stack protection, and other advanced features when targeting ARM Linux and bare metal environments.
GCC implements full support for ARM’s Thumb-2 instruction set which improves code density. The compiler can intermix 32-bit ARM and 16-bit Thumb instructions automatically via the -mthumb flag.
For math intensive code, the compiler can leverage NEON SIMD instructions when available by auto-vectorizing loops. This generates much faster code to process vector/matrix data.
Using GCC with Embedded ARM
GCC is commonly used in embedded projects based on ARM Cortex-M and Cortex-R processor cores. These microcontroller chips are designed to be low cost and low power for use in IoT devices.
For Cortex-M, the gcc-arm-embedded toolchain is often used. It pre-configures GCC with the right settings to target the Cortex-M architecture and includes newlib, a libc implementation for embedded systems.
With this toolchain, developers can compile C/C++ code for Cortex-M and generate optimized machine code. The newlib library provides lower level functions like printf() and malloc() catered for resource constrained devices.
For bare metal projects, GCC links directly against the startup code and vector table defined in the ARM chip. For RTOS based projects, GCC can link to the kernel port and generate thread-safe code.
Using GCC on ARM Linux
GCC is the default system compiler on Linux distros running on ARM like Raspbian and Ubuntu ARM. This allows developers to natively compile C/C++ applications on an ARM board itself.
The system GCC on ARM Linux targets the ARMv7-A or ARMv8-A instruction sets. It is pre-configured with the optimal settings for the SoC like tuning for Cortex-A72 or using neon for SIMD.
GCC links against glibc which has full POSIX support and a complete C standard library implementation. Shared libraries compiled on ARM Linux with GCC are compatible with dynamic linker and loader.
The ARMv8 architecture used in 64-bit ARM chips like the Cortex-A72 has advanced features like ARMv8 NEON SIMD and v8.1-M SVE vector extensions which GCC can utilize for performance.
Using GCC for Cross Compiling
GCC makes it easy to cross compile C/C++ code on a host Linux machine for targeting ARM devices. This approach allows compiling code much quicker compared to compiling natively on low-power ARM boards.
For cross compiling with GCC, you need to install a cross compiler toolchain on the host x86 Linux. Some examples are:
- GCC ARM Embedded toolchain for Cortex-M
- Linaro toolchain for ARMv7 and ARMv8
- CodeSourcery toolchain for ARM Linux
These toolchains contain a version of GCC and other tools like binutils targeted at ARM. They also include sysroot files needed during linking stage.
With the cross toolchain installed, developers can configure GCC to point to the ARM version of gcc/g++ compilers instead of the host compilers. This then generates code for targeting the ARM architecture instead of x86 architecture.
Performance of GCC on ARM
GCC is able to generate pretty efficient code for ARM just like any other architecture it supports. The compiler applies optimizations to reduce code size, improve speed, lower power usage and exploit SIMD capabilities.
However, GCC compiled code is not going to be as fast as code produced by commercial compilers like ARM Compiler, IAR or Keil toolchains that are designed specifically for optimizing across ARM cores.
For example, on Cortex-M4, ARM Compiler 6 can produce code that is ~15% faster on average than GCC 7 code. The core issue is GCC struggles to utilize some of the specialized DSP instructions on Cortex-M4 as well as the commercial compilers.
That said, GCC delivers good enough performance in most cases while being free to use. For non-performance critical applications, GCC is a great choice for compiling to ARM thanks to its maturity, stability and open source nature.
GCC also catches up and improves its optimizations for ARM cores over time. For example, GCC 9 significantly improved code generation for ARMv8-A compared to GCC 8.
In summary, GCC is a versatile compiler that supports multiple programming languages and enables compiling software for various ARM devices ranging from microcontrollers to Linux systems.
Developers can use GCC to build bare metal embedded applications with newlib, cross compile code on Linux hosts, and also natively compile applications on ARM Linux distributions.
While commercial compilers can produce faster code for ARM, GCC delivers sufficiently good performance for most use cases while being free and open source. Its support for ARMv6, ARMv7-A, ARMv7-M, ARMv7E-M, ARMv8-A and newer 64-bit v8-A instruction sets makes it a popular compiler option for ARM targets.