Using Sourcery G++ Lite for ARM EABI

ARMv7M Interrupt handlers

Because of a discrepancy between the ARMv7M Architecture and the ARM EABI, it is not safe to use normal C functions directly as interrupt handlers. The EABI requires the stack be 8-byte aligned, whereas ARMv7M only guarantees 4-byte alignment when calling an interrupt vector. This can cause subtle runtime failures, usually when 8-byte types are used.

Functions that are used directly as interrupt handlers should be annotated with __attribute__((__interrupt__)). This tells the compiler to add special stack alignment code to the function prologue.

ARM Interrupt Vectors

The ARM CS3 implementation treats all systems as address vector processors. On traditional ARM systems (everything except M profile devices) an exception causes the processor to jump to a fixed address. However the arrangement of these addresses is such that the CS3 code vector model is not feasible.

The default CS3 vector table emulates an address vector system by placing an indirect branch at the real exception vector. If you override the entire vector table (rather than individual vectors) the indirect stubs are not included, and your replacement table is placed at address zero.

NEON SIMD Code

Sourcery G++ includes support for automatic generation of NEON SIMD vector code. Autovectorization is a compiler optimization in which loops involving normal integer or floating-point code are transformed to use NEON SIMD instructions to process several data elements at once.

To enable generation of NEON vector code, use the command-line options -ftree-vectorize -mfpu=neon -mfloat-abi=softfp. The -mfpu=neon option also enables generation of VFPv3 scalar floating-point code.

Sourcery G++ also includes support for manual generation of NEON SIMD code using C intrinsic functions. These intrinsics, the same as those supported by the ARM RealView® compiler, are defined in the arm_neon.h header and are documented in the 'ARM NEON Intrinsics' section of the GCC manual. The command-line options -mfpu=neon -mfloat-abi=softfp must be specified to use these intrinsics; -ftree-vectorize is not required.

Half-Precision Floating Point

Sourcery G++ for ARM EABI includes support for half-precision (16-bit) floating point, including the new __fp16 data type in C and C++, support for generating conversion instructions when compiling for processors that support them, and library functions for use in other cases.

Representations

ARM supports two incompatible representations for half-precision floating-point values. You must choose one of the representations and use it consistently in your program. The linker gives an error if objects compiled or assembled with different half-precision float attributes are combined in the same executable.

Compiling or assembling with -mfp16-format=ieee selects the representation defined in the IEEE 754-2008 standard, with 1 sign bit, 5 exponent bits, and 10 significand bits (11 bits of significand precision, approximately 3 decimal digits). This format is capable of representing normalized values in the range of 2-14 to 65504. It includes support for infinities and NaNs, following the usual IEEE 754 rules.

ARM also supports an alternative half-precision representation, which you can select with -mfp16-format=alternative. This format does not include support for infinities and NaNs. Instead, the range of exponent values is extended, so that this format can represent normalized values in the range of 2-14 to 131008.

The default for this option is -mfp16-format=none, which disables support for half-precision floats.

C and C++ Usage

When you compile with -mfp16-format=ieee or -mfp16-format=alternative, GCC defines the __fp16 data type to represent half-precision float values. Objects of this type have a size of 2 bytes and a natural alignment of 2 bytes.

The __fp16 type is a storage format only. For purposes of arithmetic and other operations, __fp16 values are automatically promoted to float. In addition, you cannot declare a function with a return value or parameters of type __fp16.

Note that conversions from double to __fp16 involve an intermediate conversion to float. Because of rounding, this can sometimes produce a different result than a direct conversion.

Hardware and Library Support

ARM provides hardware support for conversions between __fp16 and float values as an extension to VFP and NEON (Advanced SIMD). GCC generates code using the instructions provided by this extension if you compile with the options -mfpu=neon-fp16 -mfloat-abi=softfp, in addition to the -mfp16-format option to select a half-precision format.

In other cases, conversions between __fp16 and float values are implemented as library calls.

ABI Compatibility

The Application Binary Interface (ABI) for the ARM Architecture is a collection of standards, published by ARM Ltd. and other organizations. The ABI makes it possible to combine tools from different vendors, including Sourcery G++ and ARM RealView®.

Sourcery G++ implements the ABI as described in these documents, which are available from the ARM Information Center:

  • BSABI - ARM IHI 0036A (25 October 2007)
  • BPABI - ARM IHI 0037A (25 October 2007)
  • EHABI - ARM IHI 0038A (25 October 2007)
  • CLIBABI - ARM IHI 0039A (25 October 2007)
  • AADWARF - ARM IHI 0040A (25 October 2007)
  • CPPABI - ARM IHI 0041A (25 October 2007)
  • AAPCS - ARM IHI 0042B (2 April 2008)
  • RTABI - ARM IHI 0043A (25 October 2007)
  • AAELF - ARM IHI 0044B (2 April 2008)
  • ABI Addenda - ARM IHI 0045A (13 November 2007)

Sourcery G++ currently produces DWARF version 2, rather than DWARF version 3 as specified in AADWARF.

Object File Portability

It is possible to create object files using Sourcery G++ for ARM EABI that are link-compatible with the GNU C library provided with Sourcery G++ for ARM GNU/Linux as well as with the Newlib C library provided with the ARM EABI toolchain. These object files are additionally link-compatible with other ARM C Library ABI-compliant static linking environments and toolchains.

To use this feature, when compiling your files with the bare-metal ARM EABI toolchain define the preprocessor constant _AEABI_PORTABILITY_LEVEL to 1 before including any system header files. For example, pass the option -D_AEABI_PORTABILITY_LEVEL=1 on your compilation command line. No special options are required when linking the resulting object files. When building applications for ARM EABI, files compiled with this definition may be linked freely with those compiled without it.

Files compiled in this manner may not use the functions fgetpos or fsetpos, or reference the type fpos_t. This is because Newlib assumes a representation for fpos_t that is not AEABI-compliant.

Note that object files are only portable from EABI to GNU/Linux, and not vice versa; object files compiled for ARM GNU/Linux targets cannot be linked into ARM EABI executables.

ARM Profiling Implementation

Profiling is enabled by means of the -pg compiler option. In this mode, the compiler inserts a call to __gnu_mcount_nc into every function prologue. However, no implementation of __gnu_mcount_nc is provided (to do so would be impossible without knowledge of the execution environment).

You must provide your own implementation of __gnu_mcount_nc . Here are the requirements:

  • On exit, pop the top value from the stack, and place it in the lr register. The sp register should be adjusted accordingly. For example, this is how to write it as a stub function:
            .globl __gnu_mcount_nc
            .type __gnu_mcount_nc, %function
    __gnu_mcount_nc:
            mov    ip, lr
            pop    { lr }
            bx     ip
  • Preserve all other register state except for r12 and the CPSR condition code bits. In particular all coprocessor state and registers r0-r3 must be preserved.
  • Record and count all occurrences of the function calls in the program. The caller can be determined from the lr value stored on the top of the stack (on entry to __gnu_mcount_nc), and the callee can be determined from the current value of the lr register (i.e. the caller of this function).
  • Arrange for the data to be saved to a file named gmon.out when the program exits (via atexit). Refer to the gprof profiler manual for more information.