diff --git a/rangetest.c b/rangetest.c index 0ffde97..99deb5e 100644 --- a/rangetest.c +++ b/rangetest.c @@ -293,6 +293,15 @@ int main(int argc, char** argv) testf(occam_LONGADD(2147483647,2147483647,0,"")); testf(occam_LONGADD(2147483647,2147483647,1,"")); //TODO LONGSUB + + testf(occam_ASHIFTLEFT(1,33,"")); + testf(occam_ASHIFTLEFT(1,32,"")); + testf(occam_ASHIFTLEFT(1,31,"")); + testp(0,occam_ASHIFTLEFT(0,32,"")); + testf(occam_ASHIFTLEFT(2,31,"")); + testf(occam_ASHIFTLEFT(INT_MIN,1,"")); + testp(INT_MIN,occam_ASHIFTLEFT(INT_MIN,0,"")); + testp(-4,occam_ASHIFTLEFT(-1,2,"")); //Floating point: testf(occam_ABS(NAN,"")); diff --git a/support/tock_intrinsics_arith.h b/support/tock_intrinsics_arith.h index ba402b5..1ead140 100644 --- a/support/tock_intrinsics_arith.h +++ b/support/tock_intrinsics_arith.h @@ -200,11 +200,6 @@ static inline INT occam_LONGDIV (INT dividend_hi, INT dividend_lo, INT divisor, } } - -//////////////////// -//TODO implement, and move into the correct order above: -/////////////////// - static inline INT occam_SHIFTLEFT (INT, INT, INT, INT*, const char *) occam_unused; static inline INT occam_SHIFTLEFT (INT hi_in, INT lo_in, INT places, INT* result1, const char *pos) { if (places >= CHAR_BIT*sizeof(INT)) { @@ -233,12 +228,25 @@ static inline INT occam_SHIFTRIGHT (INT hi_in, INT lo_in, INT places, INT* resul static inline INT occam_ASHIFTRIGHT (INT, INT, const char *) occam_unused; static inline INT occam_ASHIFTRIGHT (INT x, INT places, const char *pos) { - return 0; + return x >> places; } static inline INT occam_ASHIFTLEFT (INT, INT, const char *) occam_unused; static inline INT occam_ASHIFTLEFT (INT x, INT places, const char *pos) { - return 0; + //Overflows if positive and 1 bits are shifted out or highest bit ends as 1, + //or negative and 0 bits are shifted out or highest bit ends as 0 + if (places > CHAR_BIT*sizeof(INT) + || places < 0 + || (places == CHAR_BIT*sizeof(INT) && x != 0)) { + occam_stop(pos,3,"Overflow in ASHIFTLEFT(%d,%d)",x,places); + } + else if (places != CHAR_BIT*sizeof(INT) && places != 0 && + (occam_unsign(x) >> (CHAR_BIT*sizeof(INT)-places-1) != + occam_unsign(x < 0 ? (INT)-1 : (INT)0) >> (CHAR_BIT*sizeof(INT)-places-1))) { + occam_stop(pos,3,"Overflow in ASHIFTLEFT(%d,%d)",x,places); + } else { + return (x << places); + } } static inline INT occam_ROTATERIGHT (INT, INT, const char *) occam_unused;