summaryrefslogtreecommitdiff
path: root/digital/avr
diff options
context:
space:
mode:
Diffstat (limited to 'digital/avr')
-rw-r--r--digital/avr/modules/math/fixed/fixed.h20
-rw-r--r--digital/avr/modules/math/fixed/fixed_div_f824.avr.S19
-rw-r--r--digital/avr/modules/math/fixed/test/Makefile3
-rw-r--r--digital/avr/modules/math/fixed/test/test_fixed.c2
4 files changed, 35 insertions, 9 deletions
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);
}