When converting a fixed-point value to double, there is no need to
use ldexp to adjust for FBIT of the result. Instead, FBIT can be
added to the double exponent without any further ado. When the
input is +/-0.0 then the outcome of adding FBIT to the exponent
is a small number that __fix[uns]dfdi converts to 0.
Johann
--
AVR: ad target/125752 - Simplify double -> 64-bit fixed conversions.
When converting a fixed-point value to double, there is no need to
use ldexp to adjust for FBIT of the result. Instead, FBIT can be
added to the double exponent without any further ado. When the
input is +/-0.0 then the outcome of adding FBIT to the exponent
is a small number that __fix[uns]dfdi converts to 0.
PR target/125752
libgcc/config/avr/libf7/
* libf7.c (d_to_ufx, d_to_sfx): Remove prototypes.
(__fractdfda, __fractdfuda, __fractdfta, __fractdfuta)
(__fractdfdq, __fractdfudq): Move implementation to...
* libf7-asm.sx: ...here.
(d_to_fx64): Remove.
* libf7-common.mk (F7_ASM_PARTS): Add D2dq, D2udq, D2da,
D2uda, D2ta, D2uta.
(F7F_asm): Remove d_to_fx64.
* t-libf7 (LIBF7_DF_CONV): Remove fractdfda, fractdfta,
fractdfdq, fractdfuda, fractdfuta, fractdfudq.
* f7-renames.h: Rebuild.
diff --git a/libgcc/config/avr/libf7/f7-renames.h b/libgcc/config/avr/libf7/f7-renames.h
index c9f654a032c..55299df9e4a 100644
--- a/libgcc/config/avr/libf7/f7-renames.h
+++ b/libgcc/config/avr/libf7/f7-renames.h
@@ -222,7 +222,6 @@
#define f7_sqrt16_floor_asm __f7_sqrt16_floor_asm
#define f7_lshrdi3_asm __f7_lshrdi3_asm
#define f7_ashldi3_asm __f7_ashldi3_asm
-#define f7_d_to_fx64_asm __f7_d_to_fx64_asm
#define f7_ufx64_to_d_asm __f7_ufx64_to_d_asm
#define f7_sfx64_to_d_asm __f7_sfx64_to_d_asm
#define f7_class_D_asm __f7_class_D_asm
diff --git a/libgcc/config/avr/libf7/libf7-asm.sx b/libgcc/config/avr/libf7/libf7-asm.sx
index 2644845d528..c5040fd14cf 100644
--- a/libgcc/config/avr/libf7/libf7-asm.sx
+++ b/libgcc/config/avr/libf7/libf7-asm.sx
@@ -2465,48 +2465,56 @@ _DEFUN __fractdfusa
_ENDF __fractdfusa
#endif /* F7MOD_D2usa_ */
-
-#ifdef F7MOD_D2fx_
-;;; Convert double R18 to a 64-bit fixed point value.
-;;; R18 d_to_fx64 (double R18, int8_t fbit R16);
-;;; |FBIT| accounts for the extra fbits compared to [u]int64_t.
-;;; FBIT < 0 indicates a signed conversion.
-;;; FBIT > 0 indicates an unsigned conversion.
-DEFUN d_to_fx64
- do_prologue_saves 4, F7_SIZEOF
-
- ;; Y = FramePointer + 1
- adiw Y, 1
-
- ;; FP + 1 = (f7_t) arg
- wmov r16, Y
-
- ;; Convert double R18 to f7_t *R16.
- XCALL F7_NAME (set_double_impl)
-
- ;; Prepare for *R24 = ldexp (*R24, R22). ldexp() accounts for the
- ;; fractional bits of the fixed point value, i.e. we have to <<= FBIT.
- wmov r24, r16
- ;; Zero-extend FBIT.
- clr r23
- ;; R16 has been clobbered. Fetch it from where prologue_saves put it.
- ldd r22, Y + F7_SIZEOF + 3 ; Saved R16
- tst r22
- brmi 1f
-
- ;; Positive FBIT indicates an unsigned conversion.
- XCALL F7_NAME (Ildexp)
- XCALL F7_NAME (get_u64)
- rjmp 9f
-
-1: ;; Negative FBIT indicates a signed conversion.
- neg r22 ; FBIT := |FBIT|
- XCALL F7_NAME (Ildexp)
- XCALL F7_NAME (get_s64)
-
-9: do_epilogue_restores 4, F7_SIZEOF
-ENDF d_to_fx64
-#endif /* F7MOD_D2fx_ */
+#ifdef F7MOD_D2da_
+_DEFUN __fractdfda
+ ;; Multiply with 2^FBIT to get a DA result in r25:r18.
+ subi r24, dex_lo (-__DA_FBIT__)
+ sbci r25, dex_hi (-__DA_FBIT__)
+ XJMP __fixdfdi
+_ENDF __fractdfda
+#endif /* F7MOD_D2da_ */
+
+#ifdef F7MOD_D2uda_
+_DEFUN __fractdfuda
+ ;; Multiply with 2^FBIT to get an UDA result in r25:r18.
+ subi r25, dex_hi (-__UDA_FBIT__)
+ XJMP __fixunsdfdi
+_ENDF __fractdfuda
+#endif /* F7MOD_D2uda_ */
+
+#ifdef F7MOD_D2ta_
+_DEFUN __fractdfta
+ ;; Multiply with 2^FBIT to get a TA result in r25:r18.
+ subi r24, dex_lo (-__TA_FBIT__)
+ sbci r25, dex_hi (-__TA_FBIT__)
+ XJMP __fixdfdi
+_ENDF __fractdfta
+#endif /* F7MOD_D2ta_ */
+
+#ifdef F7MOD_D2uta_
+_DEFUN __fractdfuta
+ ;; Multiply with 2^FBIT to get an UTA result in r25:r18.
+ subi r25, dex_hi (-__UTA_FBIT__)
+ XJMP __fixunsdfdi
+_ENDF __fractdfuta
+#endif /* F7MOD_D2uta_ */
+
+#ifdef F7MOD_D2dq_
+_DEFUN __fractdfdq
+ ;; Multiply with 2^FBIT to get a DQ result in r25:r18.
+ subi r24, dex_lo (-__DQ_FBIT__)
+ sbci r25, dex_hi (-__DQ_FBIT__)
+ XJMP __fixdfdi
+_ENDF __fractdfdq
+#endif /* F7MOD_D2dq_ */
+
+#ifdef F7MOD_D2udq_
+_DEFUN __fractdfudq
+ ;; Multiply with 2^FBIT to get an UDQ result in r25:r18.
+ subi r25, dex_hi (-__UDQ_FBIT__)
+ XJMP __fixunsdfdi
+_ENDF __fractdfudq
+#endif /* F7MOD_D2udq_ */
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/libgcc/config/avr/libf7/libf7-common.mk b/libgcc/config/avr/libf7/libf7-common.mk
index 4c3091f4f43..3ebe101c9c1 100644
--- a/libgcc/config/avr/libf7/libf7-common.mk
+++ b/libgcc/config/avr/libf7/libf7-common.mk
@@ -34,9 +34,8 @@ F7_ASM_PARTS += ha2D uha2D sa2D usa2D da2D uda2D ta2D uta2D
F7_ASM_PARTS += fx2D
# Double -> fixed-point conversions
-F7_ASM_PARTS += D2qq D2uqq D2hq D2uhq
-F7_ASM_PARTS += D2ha D2uha D2sa D2usa
-F7_ASM_PARTS += D2fx
+F7_ASM_PARTS += D2qq D2uqq D2hq D2uhq D2dq D2udq
+F7_ASM_PARTS += D2ha D2uha D2sa D2usa D2da D2uda D2ta D2uta
# Integer -> double conversions
F7_ASM_PARTS += D_floatsidf D_floatunsidf
@@ -109,7 +108,7 @@ F7F_asm += set_u64 set_s64 addsub_mant_scaled mul_mant
F7F_asm += to_integer to_unsigned clr_mant_lsbs
F7F_asm += div sqrt_approx sqrt16_round sqrt16_floor
F7F_asm += lshrdi3 ashldi3
-F7F_asm += d_to_fx64 ufx64_to_d sfx64_to_d
+F7F_asm += ufx64_to_d sfx64_to_d
F7F_asm += class_D
F7F_asm += call_ddd call_xdd call_ddx
diff --git a/libgcc/config/avr/libf7/libf7.c b/libgcc/config/avr/libf7/libf7.c
index b4ce1348d67..5c2c9e9cc50 100644
--- a/libgcc/config/avr/libf7/libf7.c
+++ b/libgcc/config/avr/libf7/libf7.c
@@ -140,58 +140,6 @@ f7_double_t __floatdidf (int64_t x)
#endif // F7MOD_floatdidf_
-extern uint64_t d_to_ufx (f7_double_t, int8_t) F7ASM(f7_d_to_fx64_asm);
-extern int64_t d_to_sfx (f7_double_t, int8_t) F7ASM(f7_d_to_fx64_asm);
-
-#ifdef F7MOD_fractdfda_
-F7_WEAK
-int64_t __fractdfda (f7_double_t d)
-{
- return d_to_sfx (d, -__DA_FBIT__);
-}
-#endif // F7MOD_fractdfda_
-
-#ifdef F7MOD_fractdfuda_
-F7_WEAK
-uint64_t __fractdfuda (f7_double_t d)
-{
- return d_to_ufx (d, __UDA_FBIT__);
-}
-#endif // F7MOD_fractdfuda_
-
-#ifdef F7MOD_fractdfta_
-F7_WEAK
-int64_t __fractdfta (f7_double_t d)
-{
- return d_to_sfx (d, -__TA_FBIT__);
-}
-#endif // F7MOD_fractdfta_
-
-#ifdef F7MOD_fractdfuta_
-F7_WEAK
-uint64_t __fractdfuta (f7_double_t d)
-{
- return d_to_ufx (d, __UTA_FBIT__);
-}
-#endif // F7MOD_fractdfuta_
-
-#ifdef F7MOD_fractdfdq_
-F7_WEAK
-int64_t __fractdfdq (f7_double_t d)
-{
- return d_to_sfx (d, -__DQ_FBIT__);
-}
-#endif // F7MOD_fractdfdq_
-
-#ifdef F7MOD_fractdfudq_
-F7_WEAK
-uint64_t __fractdfudq (f7_double_t d)
-{
- return d_to_ufx (d, __UDQ_FBIT__);
-}
-#endif // F7MOD_fractdfudq_
-
-
#ifdef F7MOD_init_
f7_t* f7_init_impl (uint64_t mant, uint8_t flags, f7_t *cc, int16_t expo)
{
diff --git a/libgcc/config/avr/libf7/t-libf7 b/libgcc/config/avr/libf7/t-libf7
index d087053526e..9ec70d84ae8 100644
--- a/libgcc/config/avr/libf7/t-libf7
+++ b/libgcc/config/avr/libf7/t-libf7
@@ -9,8 +9,6 @@ F7_PREFIX = __f7_
include $(libf7)/libf7-common.mk
LIBF7_DF_CONV += floatundidf floatdidf # floatunsidf floatsidf
-LIBF7_DF_CONV += fractdfda fractdfta fractdfdq
-LIBF7_DF_CONV += fractdfuda fractdfuta fractdfudq
# Wrappers like f7_lt_impl for f7_lt etc. because the latter is inline.
LIBF7_DF_CMP += lt le gt ge ne eq unord