C99 low level support functions
The C99 low level support library (C99Low) provides a number of low level functions required by the C99 compiler and usable by other clients. The library has no data requirements. The library has a SharedCLibrary library chunk ID of 4.
'long long' support
A 'long long' is a 64bit value which can be signed or unsigned. It is represented by two 32bit littleendian words, with the low word stored first. When passed to functions, a 'long long' can be effectively represented as a structure thus :
typedef __value_in_regs struct longlong_s {long lo;
unsigned long hi;
} longlong_t;
In this form, values are passed to functions as if there were two registers containing the lo and hi values.
Many of the functions are suffixed with characters indicating the argument types :
l  indicates a 64bit argument
s  indicates a 32bit signed argument
u  indicates a 32bit unsigned argument
Many of the 64bit operations are never referenced by the compiler. These operations can be placed inline and thus are never referenced.
Functions
All functions within the library use APCSR or APCS32 (dependent on linkage) calling conventions.
Runtime allocation
Entry number 0 : void *__rt_allocauto(int size);
Allocates a block of memory of the size specified for a Variable Length Array. The current implementation will not be automatically freed on return from the calling function. Clients using longjmp should take care to retain their own lists of allocated storage as it is not guaranteed to be tracked by the implementation. Returns a pointer to the allocated space.
Entry number 1: __rt_freeauto
Frees a block of memory allocated by the __rt_allocauto function. This call will be automatically added by the compiler as automatically allocated storage goes out of scope.
Long long conversion operations
Entry number 2 : long long _ll_from_u(unsigned long x);
Entry number 3 : long long _ll_from_l(long x);
Converts from 32bit values to 64bit values.
Entry number 4: long _ll_to_l(long long x);
Converts from a 64bit value to a 32bit value.
Arithmetic operations
Entry number 5: long long _ll_add(long long x, long long y);
Entry number 6: long long _ll_addlu(long long x, unsigned long y);
Entry number 7: long long _ll_addls(long long x, signed long y);
Entry number 8: long long _ll_adduu(unsigned long x, unsigned long y);
Entry number 9: long long _ll_addss(signed long x, signed long y);
Adds the two arguments together and returns the result as a 64bit value.
Entry number 10: long long _ll_sub(long long x, long long y);
Entry number 11: long long _ll_sublu(long long x, unsigned long y);
Entry number 12: long long _ll_subls(long long x, signed long y);
Entry number 13: long long _ll_subuu(unsigned long x, unsigned long y);
Entry number 14: long long _ll_subss(signed long x, signed long y);
Subtracts the second argument from the first and returns the result as a 64bit value.
Entry number 15: long long _ll_rsb(long long x, long long y);
Entry number 16: long long _ll_rsblu(long long x, unsigned long y);
Entry number 17: long long _ll_rsbls(long long x, signed long y);
Entry number 18: long long _ll_rsbuu(unsigned long x, unsigned long y);
Entry number 19: long long _ll_rsbss(signed long x, signed long y);
Subtracts the first argument from the second and returns the result as a 64bit value.
Entry number 20: long long _ll_mul(long long x, long long y);
Entry number 21: long long _ll_mullu(long long x, unsigned long y);
Entry number 22: long long _ll_mulls(long long x, signed long y);
Entry number 23: long long _ll_muluu(unsigned long x, unsigned long y);
Entry number 24: long long _ll_mulss(signed long x, signed long y);
Multiplies the arguments and returns the result as a 64bit value.
Entry number 25: __value_in_regs ulldiv_t _ll_udiv(unsigned long long x, unsigned long long y);
Entry number 26: __value_in_regs ulldiv_t _ll_urdv(unsigned long long x, unsigned long long y);
Divides a unsigned 64bit value by another unsigned 64bit value and returns the result as an unsigned 64bit value. The result is returned in R0R3.
{quotient , remainder} = _ll_udiv(x,y) = x/y
{quotient , remainder} = _ll_urdv(x,y) = y/x
typedef struct slldiv_t {long long quot;
long long rem;
} slldiv_t;
Entry number 27: unsigned long long _ll_udiv10(unsigned long long x);
Divides an unsigned 64bit value by 10 and returns the result as a 64bit value.
Entry number 28: __value_in_regs slldiv_t _ll_sdiv(signed long long x, signed long long y);
Entry number 29: __value_in_regs slldiv_t _ll_srdv(signed long long x, signed long long y);
Divides a signed 64bit value by another signed 64bit value and returns the result as a signed 64bit value. The result is returned in r0r3.
{quotient , remainder} = _ll_sdiv(x,y) = x/y {quotient , remainder} = _ll_srdv(x,y) = y/x
typedef struct slldiv_t {long long quot;
long long rem;
} slldiv_t;
Entry number 30: signed long long _ll_sdiv10(signed long long x);
Divides a signed 64bit value by 10 and returns the result as signed a 64bit value.
Divides a signed 64bit value by another signed 64bit value and returns the result as a signed 64bit value. The result is returned in r0r3.
{quotient , remainder} = _ll_sdiv(x,y) = x/y
{quotient , remainder} = _ll_srdv(x,y) = y/x
typedef struct lldiv_t {long long quot;
long long rem;
} lldiv_t;
Simple arithmetic operations
Entry number 31: long long _ll_not(long long x);
Returns the binary inverse of the argument.
Entry number 32: long long _ll_neg(long long x);
Returns 0x.
Entry number 33: long long _ll_and(long long x, long long y);
Returns the binary AND of the two arguments.
Entry number 34: long long _ll_or(long long x, long long y);
Returns the binary OR of the two arguments.
Entry number 35: long long _ll_eor(long long x, long long y);
Returns the binary EOR of the two arguments.
Entry number 36: long long _ll_shift_l(long long x, int n);
Returns a 64bit value shifted left by n bits. Negative values are not supported.
Entry number 37: long long _ll_ushift_r(long long x, int n);
Returns a 64bit value shifted right by n bits. Negative values are not supported.
Entry number 38: long long _ll_sshift_r(long long x, int n);
Returns a 64bit value arithmetically shifted right by n bits. Negative values are not supported.
Comparisons
Entry number 39: _ll_cmpu
Compares two 64bit values in r0,r1 and r2,r3. The comparison sets the processor flags in the same manner as 'CMP'.
Note: Does not follow APCS conventions.
Entry number 40: _ll_cmpge
Compares two 64bit values in r0,r1 and r2,r3. The result is the same as 'SUBS first, first, second'. r0,r1 are corrupted by the subtraction.
Note: Does not follow APCS conventions.
Entry number 41: long long _ll_cmple
Compares two 64bit values in r0,r1 and r2,r3. The result is the same as 'RSBS first, first, second'. r0,r1 are corrupted by the subtraction.
Note: Does not follow APCS conventions.
Floating point conversions
Entry number 42: double _ll_uto_d(unsigned long long x);
Entry number 44: float _ll_uto_f(unsigned long long x);
Converts unsigned 64bit values to double values.
Entry number 43: double _ll_sto_d(signed long long x);
Entry number 45: float _ll_sto_f(signed long long x);
Converts signed 64bit values to float values.
Entry number 46: unsigned long long _ll_ufrom_d(double x);
Entry number 47: signed long long _ll_sfrom_d(double x);
Converts from a double to an unsigned 64bit value.
Entry number 48: unsigned long long _ll_ufrom_f(float x);
Entry number 49: signed long long _ll_sfrom_f(float x);
Converts from a double to a signed 64bit value.
