[gcc r17-3805] AVR: Fix 64-bit signed fixed-point multiply
Georg-Johann Lay
gjl@gcc.gnu.org
Tue Sep 1 08:21:11 GMT 2026
https://gcc.gnu.org/g:b65eb20e8fff1bc572a49fae254055ccfc7799aa
commit r17-3805-gb65eb20e8fff1bc572a49fae254055ccfc7799aa
Author: Georg-Johann Lay <avr@gjlay.de>
Date: Tue Sep 1 09:47:46 2026 +0200
AVR: Fix 64-bit signed fixed-point multiply
The recently added 64-bit signed fixed-point multiply
calculated |B| but didn't restore it, which is wrong
code when the caller reuses B after the multiplication
in the assumption that the respective callee-saved regs
are unaltered.
This patch stores the sign of B and unclobbers B by
negating it twice when it is negative, instead of only once.
libgcc/
* config/avr/lib1funcs-fixed.S (__mulQ64_work):
Restore B = R10..R17 to its orignal value.
Diff:
---
libgcc/config/avr/lib1funcs-fixed.S | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/libgcc/config/avr/lib1funcs-fixed.S b/libgcc/config/avr/lib1funcs-fixed.S
index 142b832c2a18..1ac7b5cf9862 100644
--- a/libgcc/config/avr/lib1funcs-fixed.S
+++ b/libgcc/config/avr/lib1funcs-fixed.S
@@ -1152,6 +1152,8 @@ ENDF __multa3
DEFUN __mulQ64_work
mov __tmp_reg__, A7
eor __tmp_reg__, B7
+ bst B7, 7
+ bld __tmp_reg__, 0
push __tmp_reg__
.call_if_neg A7, __negdi2 ; A = |A|
@@ -1160,6 +1162,20 @@ DEFUN __mulQ64_work
set ; for signed
XICALL ; __muluxx3.2
+ ;; r30.7 = sign result
+ ;; r30.0 = sign B
+ pop r30
+
+ ;; If we clobbered B, unclobber it now.
+#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
+ asr r30
+ brcc 0f
+#else
+ sbrc r30, 0
+#endif
+ XCALL __negdi2_r10
+0:
+
;; Adjust for signed Q formats that have one FBIT less.
lsl A0
;; Insert LSB from the unsigned mult.
@@ -1172,9 +1188,6 @@ DEFUN __mulQ64_work
rol A6
rol A7
- ;; r30.7 = result sign
- pop r30
-
;; Handle overflow.
brcs .Lsaturate
;; In the negative result case, A = 0x80.. is no overflow,
More information about the Gcc-cvs
mailing list