diff --git a/rangetest.c b/rangetest.c index 8c4c1dc..0ffde97 100644 --- a/rangetest.c +++ b/rangetest.c @@ -284,6 +284,16 @@ int main(int argc, char** argv) //TODO add tests for the index-checking functions too + //Arithmetic: + testp(-2,occam_LONGADD(-1,-1,0,"")); + testp(-1,occam_LONGADD(-1,0,0,"")); + testp(2147483647,occam_LONGADD(2147483647,0,0,"")); + testf(occam_LONGADD(2147483647,0,1,"")); + testp(2,occam_LONGADD(-1,3,0,"")); + testf(occam_LONGADD(2147483647,2147483647,0,"")); + testf(occam_LONGADD(2147483647,2147483647,1,"")); + //TODO LONGSUB + //Floating point: testf(occam_ABS(NAN,"")); testf(occam_DABS(NAN,"")); diff --git a/support/tock_intrinsics_arith.h b/support/tock_intrinsics_arith.h index 5d9e319..04dc7a7 100644 --- a/support/tock_intrinsics_arith.h +++ b/support/tock_intrinsics_arith.h @@ -22,13 +22,50 @@ static inline INT occam_LONGADD (INT left, INT right, INT carry_in, const char * } } +static inline INT occam_LONGDIFF (INT, INT, INT, INT*, const char *) occam_unused; +static inline INT occam_LONGDIFF (INT left, INT right, INT borrow_in, INT* result1, const char *pos) { + UINT leftu = occam_unsign(left); + UINT rightu = occam_unsign(right); + if (leftu == 0) { + if (rightu == __MAX(UINT)) { + *result1 = 1 - (borrow_in & 1); + return 1; + } else rightu += borrow_in & 1; + } else leftu -= borrow_in & 1; + + if (rightu > leftu) { + //This will overflow -- could be a problem on odd C implementations + *result1 = occam_sign(leftu - rightu); + return 1; + } else { + *result1 = occam_sign(leftu - rightu); + return 0; + } +} + + +static inline INT occam_LONGSUB (INT, INT, INT, const char *) occam_unused; +static inline INT occam_LONGSUB (INT left, INT right, INT borrow_in, const char *pos) { + if (left == __MIN(INT)) { + if (right == __MIN(INT)) { + occam_stop(pos, 3, "Overflow in LONGSUB: %d - %d", left, right); + } else right -= borrow_in & 1; + } else left -= borrow_in & 1; + + if (((right<1)&&(__MAX(INT)+right>=left)) || ((right>=1)&&(__MIN(INT)+right<=left))) { + return left - right; + } else { + occam_stop(pos, 3, "Overflow in LONGSUB: %d - %d", left, right); + } +} + static inline INT occam_LONGSUM (INT, INT, INT, INT*, const char *) occam_unused; static inline INT occam_LONGSUM (INT left, INT right, INT carry_in, INT* result1, const char *pos) { UINT leftu = occam_unsign(left); UINT rightu = occam_unsign(right); if (leftu == __MAX(UINT)) { if (rightu == __MAX(UINT)) { - *result1 = -2; + *result1 = -2 + (carry_in & 1); return 1; } else rightu += carry_in & 1; } else leftu += carry_in & 1; @@ -37,6 +74,7 @@ static inline INT occam_LONGSUM (INT left, INT right, INT carry_in, INT* result1 *result1 = occam_sign(leftu + rightu); return 0; } else { + //This will overflow -- could be a problem on odd C implementations *result1 = occam_sign(leftu + rightu); return 1; } @@ -68,16 +106,6 @@ static inline INT occam_NORMALISE (INT hi_in, INT lo_in, INT* result1, INT* resu //TODO implement, and move into the correct order above: /////////////////// -static inline INT occam_LONGSUB (INT, INT, INT, const char *) occam_unused; -static inline INT occam_LONGSUB (INT left, INT right, INT borrow_in, const char *pos) { - return 0; -} - -static inline INT occam_LONGDIFF (INT, INT, INT, INT*, const char *) occam_unused; -static inline INT occam_LONGDIFF (INT left, INT right, INT borrow_in, INT* result1, const char *pos) { - return 0; -} - static inline INT occam_LONGPROD (INT, INT, INT, INT*, const char *) occam_unused; static inline INT occam_LONGPROD (INT left, INT right, INT carry_in, INT* result1, const char *pos) { return 0;