ARM Technical Support Knowledge Articles

Some examples to compare Microlib vs. Stdlib

Applies to: DS-5, RealView Development Suite (RVDS)

Answer

This FAQ presents some simple examples to demonstrate some differences between the micro-library (Microlib) and the standard library (Stdlib). You might also find it useful to read the FAQ “How do I port project to Microlib? ” before reading this FAQ.

There are four build configurations:

  • Stdlib-ARM7TDMI: Build with standard library on ARM7TDMI
  • Stdlib-CM3: Build with standard library on Cortex-M3
  • Microlib-ARM7TDMI: Build with micro-library on ARM7TDMI
  • Microlib-CM3: Build with micro-library on Cortex-M3

The example was built in the Eclipse IDE. In addition, four batch files containing the above build configurations are provided for those who prefer to use the command line build environment.

The examples are contained in one C file (main.c) and a header file (stack.h). 

main.c contains macro definitions and conditional compilation switches to control which example to build:

#define MEMCPY   1 
#define INT_DIV  2
#define FP_EXP   3

#define CHOICE   INT_DIV   //set choice for build

stack.h defines the stack and heap values to be used by the main.c

The features demonstrated by the examples are:

1) memcpy() library function

Microlib provides two versions of memcpy() - one optimized for size, the other for speed. By default, armlink will use the faster word-by-word copy version using LDR/STR instructions. This is to ensure that reasonable performance is maintained. If code size is the main concern, the smaller byte-by-byte copy version using LDRB/STRB instructions can be selected instead by defining USE_SMALLER_MEMCPY in main.c (or in the build script), to import the __use_smaller_memcpy symbol. This will have a benefit of smaller code size but at a performance penalty cost.

This feature only applies to the Microlib-ARM7TDMI and Microlib-CM3 build configurations, because the symbol __use_smaller_memcpy is specific to the Microlib.  Use the following macro definition to select this feature:

#define CHOICE   MEMCPY   //set choice for build

The code simply does a call to memcpy() function to copy a 64-byte character array. You can then compare the code size information outputted by the linker switch --info totals. In addition, you may want to examine the disassembly output to check the memcpy library function, or benchmark the memcpy function using the RVISS (for ARM7TDMI) or ISSM (for Cortex-M3) simulators. You should see that the default memcpy() Microlib function is faster.

2) floating point exception

Floating point support in Microlib is not IEEE 754 compliant to minimize the code size. Microlib does not raise IEEE exceptions but returns an unpredictable result instead.

For comparison, start with building the Stdlib-ARM7TDMI build. In order to trap IEEE exceptions, you need to use the --fpmode=ieee_full compiler switch.

Use the following macro definition to allow relevant code to be built:-

#define CHOICE   FP_EXP   //set choice for build

The code will set the IEEE status by calling:

__ieee_status(FE_IEEE_MASK_ALL_EXCEPT, FE_IEEE_MASK_DIVBYZERO);

... to trap the invalid operation exception and untrap all other exceptions. The code will then perform a divide-one-by-zero operation, which will cause an exception to be trapped. The library exception handler will print out the error message “Divide by zero” then call the semihosted sys_exit() function to terminate the execution. Therefore you will not get the output message displaying the division result.

You will find similar behaviour when running the Stdlib-CM3 build.

Now build for Microlib-ARM7TDMI. The --fpmode=ieee_full has no effect because Microlib only supports --fpmode=std and --fpmode=fast. You will find that no arithmetic exception will be generated by the same divide-by-zero operation. The operation simply returns zero. The program prints the result a/b=0.000000 and exits normally.

You will find similar behaviour when running the Microlib-CM3 build.

3) integer division

Stage 2 above showed the different way of handling floating point divide-by-zero operation between Microlib and the standard library. Let’s now examine the difference when performing integer division by zero.

Use the following macro definition to allow relevant code to be built:-

#define CHOICE   INT_DIV   //set choice for build

Start with the Stdlib-ARM7TDMI and Stdlib-CM3 builds. You will find that zero is returned from the integer division-by-zero operation. (Since RVCT 3.0, the divide-by-zero library function does not call signal handling code by default. This behaviour is documented in the Libraries and Floating Point Support Guide in RVCT 3.1 and later documentation.)

Now try the Microlib-ARM7TDMI and Microlib-CM3 builds. You will find that for the Microlib-ARM7TDMI build the division result is -1; and for the Microlib-CM3 build the division result is zero. These are expected behaviours; the reason being that the Microlib division routine does not contain any code to test for division by zero (in order to minimize the library’s code size). For the Microlib-CM3 build, the division operation is compiled into one hardware division instruction, taking advantage of the Cortex-M3’s division hardware.

Zip file icon Download example project source

Attachments: microlib_example.zip

Article last edited on: 2012-03-20 16:38:31

Rate this article

[Bad]
|
|
[Good]
Disagree? Move your mouse over the bar and click

Did you find this article helpful? Yes No

How can we improve this article?

Link to this article
Copyright © 2011 ARM Limited. All rights reserved. External (Open), Non-Confidential