The arithmetic functions provided by weAutSys fill the gaps of the 8 bit, CISC little endian architecture. Some have no direct substitute.
Those, replacing a C construct or library function are substantially faster. Those modulo, divide and multiply functions are unsigned — even without u in the names &mdash except stated otherwise.
Additionally some constants (values) and logical utilities are provided.
Defines | |
#define | clearBitMask(bitNum) |
Get the 8 bit "Clear bit mask" for the given bit. | |
#define | setBitMask(bitNum) |
Get the 8 bit "Set bit mask" for the given bit. | |
Optimised Divide functions | |
u8div_t | divByVal10 (uint8_t div) __attribute__((pure)) |
Divide an unsigned byte by the constant 10. | |
u8div_t | divWByVal10toByte (uint16_t div) __attribute__((pure)) |
Divide an unsigned word by by the constant 10 for a byte quotient. | |
u16div_t | divWByVal1000 (uint16_t div) __attribute__((pure)) |
Divide an unsigned word by by the constant 1000. | |
uint8_t | mod16byVal7 (uint16_t val) __attribute__((pure)) |
Modulo 7 of an unsigned 16 bit value. | |
uint8_t | mod8byVal7 (uint8_t val) __attribute__((pure)) |
Modulo 7 of an unsigned 8 bit value. | |
uint32_t | div32byVal512 (const uint32_t div) __attribute__((pure)) |
Divide unsigned 32 bit by the constant 512. | |
uint16_t | div16byVal512 (const uint16_t div) __attribute__((pure)) |
Divide unsigned 16 bit by the constant 512. | |
uint32_t | div32byVal1024 (const uint32_t div) __attribute__((pure)) |
Divide unsigned 32 bit by the constant 1024. | |
uint32_t | div32byVal2048 (const uint32_t div) __attribute__((pure)) |
Divide unsigned 32 bit by the constant 2048. | |
uint32_t | div32byVal256 (const uint32_t div) __attribute__((pure)) |
Divide unsigned 32 bit by 256. | |
uint32_t | div32byVal128 (const uint32_t div) __attribute__((pure)) |
Divide unsigned 32 bit by the constant 128. | |
#define | mod2pow(div, po2) |
Modulo by power of 2. | |
Optimised Multiplication functions | |
uint32_t | mul16with8 (const uint16_t f16, const uint8_t f8) __attribute__((pure)) |
Multiply unsigned 16 bit with 8 bit. | |
uint32_t | mul16 (const uint16_t ab, const uint16_t cd) __attribute__((pure)) |
Multiply unsigned 16 bit with 16 bit. | |
uint32_t | mul16with17 (const uint16_t ab, const uint16_t cd) __attribute__((pure)) |
Multiply unsigned 16 bit with 17 bit. | |
uint32_t | mul32withVal512 (const uint32_t fac) __attribute__((pure)) |
Multiply unsigned 32 bit with the constant 512. | |
uint16_t | mul16withVal512 (const uint16_t fac) __attribute__((pure)) |
Optimised Compare functions | |
uint8_t | geU32ModAr (uint32_t a, uint32_t b) __attribute__((always_inline)) |
A 32 bit unsigned greater equal (ge) comparison for modulo arithmetic. | |
uint8_t | leU32ModAr (uint32_t a, uint32_t b) __attribute__((always_inline)) |
A 32 bit unsigned less or equal (le) comparison for modulo arithmetic. | |
Endianess Handling functions | |
void | toggle32endian (ucnt32_t *value) |
Toggle the endianess of a 32 bit value. | |
void | toggle16endian (ucnt16_t *value) |
Toggle the endianess of a 16 bit value. | |
uint16_t | convert16endian (uint16_t value) |
Convert the endianess of a 16 bit value. | |
uint32_t | convert32endian (uint32_t value) |
Convert the endianess of a 32 bit value. | |
void | add16littleTo32bigEndian (ucnt32_t *opRes, uint16_t op2) |
Add a normal (little endian) 16 bit value to 32 bit big endian. | |
Optimised Divide functions (optionally in bootloader) | |
uint16_t | div16 (uint16_t *rem, uint16_t dividend, uint16_t divisor) |
Unsigned 16 bit divide. | |
uint32_t | div24 (uint32_t *rem, uint32_t dividend, uint32_t divisor) |
Unsigned 24 bit divide. | |
uint32_t | div32 (uint32_t *rem, uint32_t dividend, uint32_t divisor) |
Unsigned 32 bit divide. | |
uint32_t | div32by24 (uint32_t *rem, uint32_t dividend, uint32_t divisor) |
Unsigned 32 bit divide by 24 bit. | |
uint32_t | div32by16 (uint16_t *rem, uint32_t dividend, uint16_t divisor) |
Unsigned 32 bit divide by 16 bit. | |
Variables | |
uint8_t const | clearBitMasks [8] |
Clear bit masks (table in flash memory) | |
uint8_t const | setBitMasks [8] |
Set bit masks (table in flash memory) |
#define mod2pow | ( | div, | |
po2 | |||
) |
Modulo by power of 2.
This is a fast modulo implementation for an architecture without a divide instruction. As long as the (AVR-GC) C-compiler does not optimise power of 2 modulo this gives a quite significant performance improvement.
Warning: If po2
is not an unsigned power of 2 (i.e. just one bit set) this will not give the correct arithmetic result.
div | the (unsigned) dividend |
po2 | the (unsigned) quotient (must be a power of 2 and >= 2) |
#define setBitMask | ( | bitNum | ) |
Get the 8 bit "Set bit mask" for the given bit.
bitNum | the bit number; the value will be taken modulo 8, i.e. 0..7 |
#define clearBitMask | ( | bitNum | ) |
Get the 8 bit "Clear bit mask" for the given bit.
bitNum | the bit number; the value will be taken modulo 8, i.e. 0..7 |
This array of length 8 in flash memory contains the masks to set bits 0 .. 7 by ORing. Hence the values are 1, 2, 4 .... 128 (0x80).
u8div_t divByVal10 | ( | uint8_t | div | ) |
Divide an unsigned byte by the constant 10.
ATmega µ-controllers don't have any divide in their (RISC) instruction set. Nevertheless getting quotient and remainder by 10 in 8 bit unsigned arithmetic is needed quite often (even in loops).
Hence no effort was spared to make this a good implementation for uint8_t
dividends. This function is faster than direct usage of avr-gcc C compiler's / and % operators and also faster than using stdlib.h's div(...,10). The same is true for all the other divide functions coming with weAutSys and its serial bootloader.
div | the dividend (byte, unsigned, 0..255) |
u8div_t divWByVal10toByte | ( | uint16_t | div | ) |
Divide an unsigned word by by the constant 10 for a byte quotient.
ATmega µ-controllers don't have any divide in their (RISC) instruction set. Getting quotient and remainder by 10 is, nevertheless, needed quite often — especially for decimal formatting.
In that use case the dividends (div
) are often in the range 0..999. That may be achieved for larger numbers by divWByVal1000. Hence this is a highly optimised implementation for those small 16 bit dividends (0..999). It will fail without warning if the div
is 1286 or above!
It's the user's responsibility not to use this function outside its operation range. On the other hand the implementation is much faster than all equivalents expressed with avr-gcc or libc functions.
div | the dividend (16 Bit, unsigned, 0..1286) |
u16div_t divWByVal1000 | ( | uint16_t | div | ) |
Divide an unsigned word by by the constant 1000.
ATmega µ-controllers don't have any divide in their (RISC) instruction set. Getting quotient and remainder by 1000 is sometimes needed — for example as divide and conquer for subsequent divide by 10 on decimal formatting.
This implementation returns quotient and the remainder as 16 bit values (in an u16div_t), even if 8 bit would suffice for the quotient.
div | the dividend (16 Bit, unsigned, 0..65535) |
uint8_t mod16byVal7 | ( | uint16_t | val | ) |
Modulo 7 of an unsigned 16 bit value.
This is an efficient result = val % 7 without using any divide functions.
val | the unsigned number |
uint8_t mod8byVal7 | ( | uint8_t | val | ) |
Modulo 7 of an unsigned 8 bit value.
This is an efficient result = val % 7 without using any divide functions.
val | the unsigned number |
uint32_t mul16with8 | ( | const uint16_t | f16, |
const uint8_t | f8 | ||
) |
Multiply unsigned 16 bit with 8 bit.
This function calculates the the product of an 8 and a 16 bit number and returns the (24 bit) result as 32 bit.
The (ASM) implementation is far more efficient and the usage is less error prone as what could be expressed in C and then made by (AVR-) GCC.
f16 | the 16 bit (unsigned) factor |
f8 | the 8 bit (unsigned) factor |
uint32_t mul16 | ( | const uint16_t | ab, |
const uint16_t | cd | ||
) |
Multiply unsigned 16 bit with 16 bit.
This function calculates the the product of two 16 bit numbers and returns the 32 bit result.
The (ASM) implementation is far more efficient and the usage is less error prone as what could be expressed in C and then made by (AVR-) GCC.
ab | the first 16 bit (unsigned) factor |
cd | the second 16 bit (unsigned) factor |
uint32_t mul16with17 | ( | const uint16_t | ab, |
const uint16_t | cd | ||
) |
Multiply unsigned 16 bit with 17 bit.
This function calculates the the product of a 16 bit number with a 17 bit number and returns the 32 bit result. The second factor cd
is supplied as 16 bit unsigned number with bit 16 implied as 1. Hence the second factor is in the range 65536 .. 131071, as is e.g SECONDS_IN_DAY.
This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.
ab | the first 16 bit (unsigned) factor |
cd | the second 17 bit (unsigned) factor |
uint32_t mul32withVal512 | ( | const uint32_t | fac | ) |
Multiply unsigned 32 bit with the constant 512.
This function calculates the the product of a 32 bit number with the constant 512 and returns the 32 bit result. This multiplication is needed for certain memory card operations (sector number to byte address e.g.).
This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.
fac | the 32 bit (unsigned) factor fac's upper 9 bits are ignored and should be 0 to get a arithmetically correct result |
uint32_t div32byVal512 | ( | const uint32_t | div | ) |
Divide unsigned 32 bit by the constant 512.
This function calculates the the quotient of a 32 bit number resulting from division by 512 and returns the 32 bit result. This division is needed for certain memory card operations (with 512 byte sectors e.g.).
This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.
div | the 32 bit (unsigned) dividend |
uint16_t div16byVal512 | ( | const uint16_t | div | ) |
Divide unsigned 16 bit by the constant 512.
This function calculates the the quotient of a 16 bit number resulting from division by 512 and returns the 16 bit result. This division is needed for certain memory card operations (with 512 byte sectors e.g.).
This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.
div | the 16 bit (unsigned) dividend |
uint32_t div32byVal1024 | ( | const uint32_t | div | ) |
Divide unsigned 32 bit by the constant 1024.
This function calculates the the quotient of a 32 bit number resulting from division by 1024 and returns the 32 bit result. This division is needed for certain memory card operations.
This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.
div | the 32 bit (unsigned) dividend |
uint32_t div32byVal2048 | ( | const uint32_t | div | ) |
Divide unsigned 32 bit by the constant 2048.
This function calculates the the quotient of a 32 bit number resulting from division by 2048 and returns the 32 bit result. This division is needed for certain memory card operations.
This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.
div | the 32 bit (unsigned) dividend |
uint32_t div32byVal256 | ( | const uint32_t | div | ) |
Divide unsigned 32 bit by 256.
This function calculates the the quotient of a 32 bit number resulting from division by 2048 and returns the 32 bit result. This division is needed for certain memory card operations.
This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.
div | the 32 bit (unsigned) dividend |
uint32_t div32byVal128 | ( | const uint32_t | div | ) |
Divide unsigned 32 bit by the constant 128.
This function calculates the the quotient of a 32 bit number resulting from division by 2048 and returns the 32 bit result. This division is needed for certain memory card operations.
This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.
div | the 32 bit (unsigned) dividend |
uint8_t geU32ModAr | ( | uint32_t | a, |
uint32_t | b | ||
) |
A 32 bit unsigned greater equal (ge) comparison for modulo arithmetic.
This function will return true if a >= b, whereby a and b are considered as (counter) values in modulo 2**32 arithmetic. In that sense geU32ModAr(0x0001, 0xFFFE) will return true as 0x0001 is (as counter / modulo value) by 2 higher than 0xFFFE.
That will work correctly for differences less than 2**31 and, as said, very well over the "wrapping border".
a | will be compared to |
b | by a >= b in modulo arithmetic sense |
uint8_t leU32ModAr | ( | uint32_t | a, |
uint32_t | b | ||
) |
A 32 bit unsigned less or equal (le) comparison for modulo arithmetic.
This function will return true if a <= b, whereby a and b a considered as (counter) values in modulo 2**32 arithmetic. It is the counterpart to geU32ModAr() (but, n.b., not the inverse).
a | will be compared to |
b | by a <= b in modulo arithmetic sense |
void toggle32endian | ( | ucnt32_t * | value | ) |
Toggle the endianess of a 32 bit value.
value | the value to convert |
void toggle16endian | ( | ucnt16_t * | value | ) |
Toggle the endianess of a 16 bit value.
value | the value to convert |
uint16_t convert16endian | ( | uint16_t | value | ) |
Convert the endianess of a 16 bit value.
value | the value to convert |
uint32_t convert32endian | ( | uint32_t | value | ) |
Convert the endianess of a 32 bit value.
value | the value to convert |
void add16littleTo32bigEndian | ( | ucnt32_t * | opRes, |
uint16_t | op2 | ||
) |
Add a normal (little endian) 16 bit value to 32 bit big endian.
This type of addition is needed by uIP and this is the "good" architecture specific implementation.
opRes | the 32 bit big endian (network order) sum and summand |
op2 | the 16 bit little endian summand |
uint16_t div16 | ( | uint16_t * | rem, |
uint16_t | dividend, | ||
uint16_t | divisor | ||
) |
Unsigned 16 bit divide.
This functions's effect is
result (return) = dividend / divisor;
*rem = dividend % divisor;
As of June 13 this function is more than twice as fast — and shorter — as the code generated by the AVR-GCC C compiler.
Anyway divide is a quite expensive operation for an 8 bit RISC machine without a divide instruction. Hence the using divide operators (and their direct replacements e.g. by this function, even though optimised as said) is discouraged. For special cases use the faster implementations like divWByVal1000() — or, at least, use the function with the smallest possible operand and result types.
rem | pointer to remainder; if null the remainder is lost |
dividend | the number to be divided |
divisor | the divisor |
divisor
/ dividend
uint32_t div24 | ( | uint32_t * | rem, |
uint32_t | dividend, | ||
uint32_t | divisor | ||
) |
Unsigned 24 bit divide.
This functions's effect is
result (return) = dividend / divisor;
*rem = dividend % divisor;
This function is quite similar to div32. It also shares the 32 bit parameter and return types (as avr-gcc C has no 24 bit type). Nevertheless it just operates on and returns 24 bit unsigned numbers — just ignoring respectively setting 0 the upper byte.
So it is about twice as fast as the optimised div32.
rem | pointer to the 32 bit variable for the 24 bit remainder; if null the remainder is lost; upper byte will be 0. |
dividend | the 24 bit number to be divided (upper byte ignored) |
divisor | the 24 bit divisor (upper byte ignored) |
divisor
/ dividend
(upper byte 0) uint32_t div32 | ( | uint32_t * | rem, |
uint32_t | dividend, | ||
uint32_t | divisor | ||
) |
Unsigned 32 bit divide.
This functions's effect is
result (return) = dividend / divisor;
*rem = dividend % divisor;
As of June 13 this function is more than twice as fast — and shorter — as the code generated by the AVR-GCC C compiler.
32 Bit divide is a very expensive operation for an 8 bit RISC machine without a divide instruction and only single bit shifts for one byte.
Hence the using it this division by C operators and % or even this optimimised replacement function is discouraged. For special cases use the faster implementations like divWByVal1000() — or, at least, use the function with the smallest possible operand and result types. div16 e.g. will be four times faster.
rem | pointer to remainder; if null the remainder is lost |
dividend | the number to be divided |
divisor | the divisor |
divisor
/ dividend
uint32_t div32by24 | ( | uint32_t * | rem, |
uint32_t | dividend, | ||
uint32_t | divisor | ||
) |
Unsigned 32 bit divide by 24 bit.
This functions's effect is
result (return) = dividend / divisor;
*rem = dividend % divisor;
This function is quite similar to div32 respectively div24 or a mix of both. It shares the 32 bit parameter and return types (as avr-gcc C has no 24 bit type).
The divisor and remainder are 24 bit numbers (upper 32 bit byte ignored or set 0). The dividend and the quotient are 32 bit.
It is about 20% faster than div32 (which is quite a lot on a RICS without division).
rem | pointer to the 32 bit variable for the 24 bit remainder; if null the remainder is lost; upper byte will be 0. |
dividend | the 32 bit number to be divided |
divisor | the 24 bit divisor (upper 32 bit byte ignored) |
divisor
/ dividend
(upper byte 0) uint32_t div32by16 | ( | uint16_t * | rem, |
uint32_t | dividend, | ||
uint16_t | divisor | ||
) |
Unsigned 32 bit divide by 16 bit.
This functions's effect is
result (return) = dividend / divisor;
*rem = dividend % divisor;
This function is quite similar to div32 respectively div16 or a mix of both.
The divisor and remainder are 16 bit numbers. The dividend and the quotient are 32 bit.
It is about 35% faster than div32 (which is quite a lot on a RICS without division).
rem | pointer to the 16 bit remainder; if null the remainder is lost |
dividend | the 32 bit number to be divided |
divisor | the 16 bit divisor |
divisor
/ dividend
uint8_t const setBitMasks[8] |
Set bit masks (table in flash memory)
This array of length 8 in flash memory contains the masks to set bits 0 .. 7 by ORing. Hence the values are 1, 2, 4 .... 128 (0x80).
uint8_t const clearBitMasks[8] |
Clear bit masks (table in flash memory)
This array of length 8 in flash memory contains the masks to clear bits 0 .. 7 by ANDing. Hence the values are ~1, ~2, ~4 .... ~128 (0x7F).