Substitute functions for the gcc support library. More...
Substitute functions for the gcc support library.
To do basic activities that are not available on the processor as hardware instructions, such as division or 64-bit multiplication, gcc uses a library of standard operational primitives. The library is called libgcc.a. This support library that comes with gcc contains handcrafted assembly routines for 32-bit operations and float-point arithmetics. However, 64-bit integer operations such as division, multiplication (in THUMB mode) and shifts are generated from general purpose (architecture agnostic) C source. That results in the 64-bit int support to be somewhat lacking in performance.
This library contains substitute functions for the gcc library ones for long long (i.e. 64-bit integer) operations. If you link this library after all your objects and other libraries but before the gcc support library, then these functions will replace the ones in the gcc support library. It also replaces the 32-bit and 64-bit division routines with faster ones. The replacement process is completely transparent to you. There will be no multiply-defined symbol errors during linking either.
These routines are functionally equivalent to the ones in gcc's own library, but they are faster and smaller. Unless there is some special reason for you to use the gcc supplied functions, it is generally a good idea to use these instead, especially if you compile for THUMB.
Note that if you use the div(), udiv(), lldiv() or ulldiv() functions from the C library, then you must link against this library as well, because the C library functions call the actual division core routines in this library.
There are no user callable functions in this library. All calls to these functions are created by gcc's code generator, therefore there is no documentation for this library other than what you are reading now.
The division by 0 handling in this library is equivalent to that of the one in the gcc support library. If you define a function called __div0(), which takes no arguments and returns void, then in case of a division by 0 that function is called. It is up to you what sort of error signalling or trapping you implement in that function. When that function returns, the division will also return. If you did not define __div0(), then the division routine simply returns if it detects a division by 0 condition. Regardless of whether you defined __div0() or not, if you divide by zero, then the returned quotient and/or remainder are unspecified, that is, you get whatever rubbish is left in the registers after the detection and error handling finished.
To help you to find the reason for the division by 0, we slightly modified the semantics of the __div0() function. If you define it as a function returning void but taking a void pointer argument, then that argument will be the address from where the division routine was called. You can still define it taking no argument, of course, to be completely compatible with the gcc semantics. Note, however, that if you use the argument taking form and you do not link this library, then gcc's own library will call your function but the argument that you receive is unpredictable (and most definitely not the address of the erroneous call).
When you compile for the ARM, only the division routines are used from this library, the 64-bit shift and multiplication is inlined by gcc. The division routines are 1 to 3 times faster than gcc's own (depending on how much work is actually needed) and in THUMB mode the 64-bit shifts are about twice as fast as gcc's own and the 64-bit multiply is about 8 times as fast. For each routine the code in this library is smaller than the same function in libgcc.a.
To give you some concrete data, on an LPC23xx processor running at 60MHz from its internal FLASH, the 64-bit division is about 12us worst case, the 32-bit division is about 3us worst case. The 64-bit multiply and shifts are all sub-microsecond, around the 300ns mark.
1.6.3