From 7bf92a1ee80c988f736d4f3f1a5a8edbca74456e Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Mon, 24 Aug 2009 21:27:30 +0200 Subject: * digital/avr/modules/math/fixed: - round division result (closes #96). - changed macros to inlined. --- digital/avr/modules/math/fixed/fixed.h | 20 +++++++++++++++----- digital/avr/modules/math/fixed/fixed_div_f824.avr.S | 19 +++++++++++++++++-- digital/avr/modules/math/fixed/test/Makefile | 3 ++- digital/avr/modules/math/fixed/test/test_fixed.c | 2 +- 4 files changed, 35 insertions(+), 9 deletions(-) (limited to 'digital/avr/modules/math/fixed') diff --git a/digital/avr/modules/math/fixed/fixed.h b/digital/avr/modules/math/fixed/fixed.h index 7bc45d6a..89aa5ba4 100644 --- a/digital/avr/modules/math/fixed/fixed.h +++ b/digital/avr/modules/math/fixed/fixed.h @@ -54,13 +54,23 @@ fixed_div_f824 (int32_t a, int32_t b); #else /* HOST */ /** Multiply f8.24 by f8.24, return f8.24. */ -#define fixed_mul_f824(a, b) \ - (((int64_t) (int32_t) (a) * (int64_t) (int32_t) (b) \ - + 0x800000LL) >> 24) +extern inline +int32_t +fixed_mul_f824 (int32_t a, int32_t b) +{ + return ((int64_t) a * b + 0x800000) >> 24; +} /** Divide f8.24 by f8.24, return f8.24. */ -#define fixed_div_f824(a, b) \ - (((int64_t) (int32_t) (a) << 24) / (int64_t) (int32_t) (b)) +extern inline +int32_t +fixed_div_f824 (int32_t a, int32_t b) +{ + if ((a ^ b) >= 0) + return (((int64_t) a << 24) + b / 2) / b; + else + return (((int64_t) a << 24) - b / 2) / b; +} #endif diff --git a/digital/avr/modules/math/fixed/fixed_div_f824.avr.S b/digital/avr/modules/math/fixed/fixed_div_f824.avr.S index 43f4e0c3..b231ac23 100644 --- a/digital/avr/modules/math/fixed/fixed_div_f824.avr.S +++ b/digital/avr/modules/math/fixed/fixed_div_f824.avr.S @@ -24,8 +24,8 @@ ; }}} ; Perfs: -; 1186 cycles in worse case -; 843 per second, per MHz +; 1199 cycles in worse case +; 834 per second, per MHz #define dd3 r25 #define dd2 r24 @@ -150,6 +150,21 @@ fixed_div_f824: rol dd1 rol dd2 rol dd3 +; Rounding. + lsl rem0 ; shift rem + rol rem1 + rol rem2 + rol rem3 + cp rem0, dv0 ; rem -= dv + cpc rem1, dv1 + cpc rem2, dv2 + cpc rem3, dv3 + brcs 2f ; if positive or equal, round up + subi dd0, 0xff + sbci dd1, 0xff + sbci dd2, 0xff + sbci dd3, 0xff +2: ; else, nothing, round down ; Restore sign. sbrs __tmp_reg__, 7 rjmp 1f diff --git a/digital/avr/modules/math/fixed/test/Makefile b/digital/avr/modules/math/fixed/test/Makefile index 04aa4cff..17412941 100644 --- a/digital/avr/modules/math/fixed/test/Makefile +++ b/digital/avr/modules/math/fixed/test/Makefile @@ -28,6 +28,7 @@ clean.test: rm -f $(TEST_FILES) SIMULAVR = simulavr -d $(AVR_MCU) -W 0x22,- -R 0x20,- -T uart0_exit +CR2NL = tr '\r' '\n' .PRECIOUS: $(TEST_FILES) @@ -35,4 +36,4 @@ test.%.host: test_fixed.host echo '!$(call code,$@,host)' | ./$< > $@ test.%.simu: test_fixed.avr.simu.elf - echo '!$(call code,$@,simu)\r' | $(SIMULAVR) -f $< > $@ + echo -e '!$(call code,$@,simu)\r' | $(SIMULAVR) -f $< | $(CR2NL) > $@ diff --git a/digital/avr/modules/math/fixed/test/test_fixed.c b/digital/avr/modules/math/fixed/test/test_fixed.c index 875aad4f..cc9a6045 100644 --- a/digital/avr/modules/math/fixed/test/test_fixed.c +++ b/digital/avr/modules/math/fixed/test/test_fixed.c @@ -53,7 +53,7 @@ check_div (int32_t a, int32_t b, int32_t r) feclearexcept (FE_ALL_EXCEPT); double af = (double) a / (1 << 24); double bf = (double) b / (1 << 24); - int32_t ri = af / bf * (1 << 24); + int32_t ri = rint (af / bf * (1 << 24)); if (r != ri && !fetestexcept (FE_INVALID)) printf ("error: %08x / %08x != %08x (%08x)\n", a, b, r, ri); } -- cgit v1.2.3