Introduction and Overview
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.
Technical Details
'long long' support
A 'long long' is a 64bit value which can be signed or unsigned. It is represented by two 32bit little-endian 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:
| Suffix | Argument type |
|---|---|
| l | A 64bit argument |
| s | A 32bit signed argument |
| u | 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.
Calling conventions
All functions within the library use APCS-R or APCS-32 (dependent on linkage) calling conventions, except where stated.
Functions
The entry numbers are those of the entries within the C99Low library chunk.
Runtime allocation
| Entry | Function | Description |
|---|---|---|
| 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. |
| 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 | Function | Description |
|---|---|---|
| 2 | long long _ll_from_u(unsigned long x); | Converts from a 32bit unsigned value to a 64bit value. |
| 3 | long long _ll_from_l(long x); | Converts from a 32bit signed value to a 64bit value. |
| 4 | long _ll_to_l(long long x); | Converts from a 64bit value to a 32bit value. |
Arithmetic operations
Addition
| Entry | Function | Description |
|---|---|---|
| 5 | long long _ll_add(long long x, long long y); | 64bit + 64bit |
| 6 | long long _ll_addlu(long long x, unsigned long y); | 64bit + unsigned 32bit |
| 7 | long long _ll_addls(long long x, signed long y); | 64bit + signed 32bit |
| 8 | long long _ll_adduu(unsigned long x, unsigned long y); | unsigned 32bit + unsigned 32bit |
| 9 | long long _ll_addss(signed long x, signed long y); | signed 32bit + signed 32bit |
Adds the two arguments together and returns the result as a 64bit value.
Subtraction
| Entry | Function | Description |
|---|---|---|
| 10 | long long _ll_sub(long long x, long long y); | 64bit - 64bit |
| 11 | long long _ll_sublu(long long x, unsigned long y); | 64bit - unsigned 32bit |
| 12 | long long _ll_subls(long long x, signed long y); | 64bit - signed 32bit |
| 13 | long long _ll_subuu(unsigned long x, unsigned long y); | unsigned 32bit - unsigned 32bit |
| 14 | long long _ll_subss(signed long x, signed long y); | signed 32bit - signed 32bit |
Subtracts the second argument from the first and returns the result as a 64bit value.
Reverse subtraction
| Entry | Function | Description |
|---|---|---|
| 15 | long long _ll_rsb(long long x, long long y); | 64bit, 64bit |
| 16 | long long _ll_rsblu(long long x, unsigned long y); | 64bit, unsigned 32bit |
| 17 | long long _ll_rsbls(long long x, signed long y); | 64bit, signed 32bit |
| 18 | long long _ll_rsbuu(unsigned long x, unsigned long y); | unsigned 32bit, unsigned 32bit |
| 19 | long long _ll_rsbss(signed long x, signed long y); | signed 32bit, signed 32bit |
Subtracts the first argument from the second and returns the result as a 64bit value.
Multiplication
| Entry | Function | Description |
|---|---|---|
| 20 | long long _ll_mul(long long x, long long y); | 64bit × 64bit |
| 21 | long long _ll_mullu(long long x, unsigned long y); | 64bit × unsigned 32bit |
| 22 | long long _ll_mulls(long long x, signed long y); | 64bit × signed 32bit |
| 23 | long long _ll_muluu(unsigned long x, unsigned long y); | unsigned 32bit × unsigned 32bit |
| 24 | long long _ll_mulss(signed long x, signed long y); | signed 32bit × signed 32bit |
Multiplies the arguments and returns the result as a 64bit value.
Unsigned division
| Entry | Function | Description |
|---|---|---|
| 25 | __value_in_regs ulldiv_t _ll_udiv(unsigned long long x, unsigned long long y); | Divides x by y |
| 26 | __value_in_regs ulldiv_t _ll_urdv(unsigned long long x, unsigned long long y); | Divides y by x (reverse divide) |
| 27 | unsigned long long _ll_udiv10(unsigned long long x); | Divides x by 10 |
_ll_udiv and _ll_urdv divide an unsigned
64bit value by another unsigned 64bit value and return the quotient and
remainder as unsigned 64bit values. The result is returned in R0-R3.
{quotient , remainder} = _ll_udiv(x,y) = x/y
{quotient , remainder} = _ll_urdv(x,y) = y/x
typedef struct ulldiv_t { unsigned long long quot;
unsigned long long rem;
} ulldiv_t;
_ll_udiv10 divides an unsigned 64bit value by 10 and returns the
result as a 64bit value.
Signed division
| Entry | Function | Description |
|---|---|---|
| 28 | __value_in_regs slldiv_t _ll_sdiv(signed long long x, signed long long y); | Divides x by y |
| 29 | __value_in_regs slldiv_t _ll_srdv(signed long long x, signed long long y); | Divides y by x (reverse divide) |
| 30 | signed long long _ll_sdiv10(signed long long x); | Divides x by 10 |
_ll_sdiv and _ll_srdv divide a signed
64bit value by another signed 64bit value and return the quotient and
remainder as signed 64bit values. The result is returned in R0-R3.
{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;
_ll_sdiv10 divides a signed 64bit value by 10 and returns the
result as a signed 64bit value.
Simple arithmetic operations
| Entry | Function | Description |
|---|---|---|
| 31 | long long _ll_not(long long x); | Returns the binary inverse of the argument. |
| 32 | long long _ll_neg(long long x); | Returns 0-x. |
| 33 | long long _ll_and(long long x, long long y); | Returns the binary AND of the two arguments. |
| 34 | long long _ll_or(long long x, long long y); | Returns the binary OR of the two arguments. |
| 35 | long long _ll_eor(long long x, long long y); | Returns the binary EOR of the two arguments. |
| 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. |
| 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. |
| 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
These functions do not follow the APCS conventions. The values to be compared are passed in registers.
| Entry | Function | Description |
|---|---|---|
| 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'. Does not follow APCS conventions. |
| 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. Does not follow APCS conventions. |
| 41 | _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. Does not follow APCS conventions. |
Floating point conversions
| Entry | Function | Description |
|---|---|---|
| 42 | double _ll_uto_d(unsigned long long x); | Converts an unsigned 64bit value to a double value. |
| 43 | double _ll_sto_d(signed long long x); | Converts a signed 64bit value to a double value. |
| 44 | float _ll_uto_f(unsigned long long x); | Converts an unsigned 64bit value to a float value. |
| 45 | float _ll_sto_f(signed long long x); | Converts a signed 64bit value to a float value. |
| 46 | unsigned long long _ll_ufrom_d(double x); | Converts from a double to an unsigned 64bit value. |
| 47 | signed long long _ll_sfrom_d(double x); | Converts from a double to a signed 64bit value. |
| 48 | unsigned long long _ll_ufrom_f(float x); | Converts from a float to an unsigned 64bit value. |
| 49 | signed long long _ll_sfrom_f(float x); | Converts from a float to a signed 64bit value. |