C99 low level support functions

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:

SuffixArgument type
lA 64bit argument
sA 32bit signed argument
uA 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

EntryFunctionDescription
0void *__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_freeautoFrees 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

EntryFunctionDescription
2long long _ll_from_u(unsigned long x);Converts from a 32bit unsigned value to a 64bit value.
3long long _ll_from_l(long x);Converts from a 32bit signed value to a 64bit value.
4long _ll_to_l(long long x);Converts from a 64bit value to a 32bit value.

Arithmetic operations

Addition

EntryFunctionDescription
5long long _ll_add(long long x, long long y);64bit + 64bit
6long long _ll_addlu(long long x, unsigned long y);64bit + unsigned 32bit
7long long _ll_addls(long long x, signed long y);64bit + signed 32bit
8long long _ll_adduu(unsigned long x, unsigned long y);unsigned 32bit + unsigned 32bit
9long 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

EntryFunctionDescription
10long long _ll_sub(long long x, long long y);64bit - 64bit
11long long _ll_sublu(long long x, unsigned long y);64bit - unsigned 32bit
12long long _ll_subls(long long x, signed long y);64bit - signed 32bit
13long long _ll_subuu(unsigned long x, unsigned long y);unsigned 32bit - unsigned 32bit
14long 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

EntryFunctionDescription
15long long _ll_rsb(long long x, long long y);64bit, 64bit
16long long _ll_rsblu(long long x, unsigned long y);64bit, unsigned 32bit
17long long _ll_rsbls(long long x, signed long y);64bit, signed 32bit
18long long _ll_rsbuu(unsigned long x, unsigned long y);unsigned 32bit, unsigned 32bit
19long 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

EntryFunctionDescription
20long long _ll_mul(long long x, long long y);64bit × 64bit
21long long _ll_mullu(long long x, unsigned long y);64bit × unsigned 32bit
22long long _ll_mulls(long long x, signed long y);64bit × signed 32bit
23long long _ll_muluu(unsigned long x, unsigned long y);unsigned 32bit × unsigned 32bit
24long 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

EntryFunctionDescription
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)
27unsigned 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

EntryFunctionDescription
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)
30signed 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

EntryFunctionDescription
31long long _ll_not(long long x);Returns the binary inverse of the argument.
32long long _ll_neg(long long x);Returns 0-x.
33long long _ll_and(long long x, long long y);Returns the binary AND of the two arguments.
34long long _ll_or(long long x, long long y);Returns the binary OR of the two arguments.
35long long _ll_eor(long long x, long long y);Returns the binary EOR of the two arguments.
36long long _ll_shift_l(long long x, int n);Returns a 64bit value shifted left by n bits. Negative values are not supported.
37long long _ll_ushift_r(long long x, int n);Returns a 64bit value shifted right by n bits. Negative values are not supported.
38long 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.

EntryFunctionDescription
39_ll_cmpuCompares 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_cmpgeCompares 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_cmpleCompares 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

EntryFunctionDescription
42double _ll_uto_d(unsigned long long x);Converts an unsigned 64bit value to a double value.
43double _ll_sto_d(signed long long x);Converts a signed 64bit value to a double value.
44float _ll_uto_f(unsigned long long x);Converts an unsigned 64bit value to a float value.
45float _ll_sto_f(signed long long x);Converts a signed 64bit value to a float value.
46unsigned long long _ll_ufrom_d(double x);Converts from a double to an unsigned 64bit value.
47signed long long _ll_sfrom_d(double x);Converts from a double to a signed 64bit value.
48unsigned long long _ll_ufrom_f(float x);Converts from a float to an unsigned 64bit value.
49signed long long _ll_sfrom_f(float x);Converts from a float to a signed 64bit value.