Fixed-point <-> double conversions were missing.
This patch adds the conversions for the fixed-point
types ≤ 32 bits as obvious.

Johann

--
    AVR: target/122210 - Add fixed-point -> double conversions.

            PR target/122210
    libgcc/config/avr/libf7/
            * libf7-common.mk (F7_ASM_PARTS): Add <fx>2D modules.
            * libf7-asm.sx: Implement the <fx>2D modules.

    gcc/testsuite/
            * gcc.target/avr/fxtod.c: New test.

--
    AVR: target/122210 - Add double -> fixed-point conversions.

            PR target/122210
    libgcc/config/avr/libf7/
            * libf7-common.mk (F7_ASM_PARTS): Add D2<fx> modules.
            * libf7-asm.sx: Implement the D2<fx> modules.

    gcc/testsuite/
            * gcc.target/avr/dtofx.c: New test.
    AVR: target/122210 - Add fixed-point -> double conversions.
    
            PR target/122210
    libgcc/config/avr/libf7/
            * libf7-common.mk (F7_ASM_PARTS): Add <fx>2D modules.
            * libf7-asm.sx: Implement the <fx>2D modules.
    
    gcc/testsuite/
            * gcc.target/avr/fxtod.c: New test.

diff --git a/gcc/testsuite/gcc.target/avr/fxtod.c b/gcc/testsuite/gcc.target/avr/fxtod.c
new file mode 100644
index 00000000000..e069a312290
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/fxtod.c
@@ -0,0 +1,115 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options { -std=gnu99 -Os -mcall-prologues -fwrapv -Wno-overflow } } */
+
+#include <stdfix.h>
+
+#if __SIZEOF_LONG_DOUBLE__ == 8
+
+#define NI __attribute__((noipa))
+
+typedef long double D;
+
+extern D ldexpl (D, int);
+
+typedef short fract hr_t;
+typedef unsigned short fract uhr_t;
+typedef fract r_t;
+typedef unsigned fract ur_t;
+
+typedef short accum hk_t;
+typedef unsigned short accum uhk_t;
+typedef accum k_t;
+typedef unsigned accum uk_t;
+
+#define FBITuhr 8
+#define FBIThr  7
+#define FBITur  16
+#define FBITr   15
+
+#define FBITuhk 8
+#define FBIThk  7
+#define FBITuk  16
+#define FBITk   15
+
+#define VALff(S) ((2ul << (8 * sizeof (S##bits(0)) - 1)) - 1)
+#define VAL80(S) (1ul << (8 * sizeof (S##bits(0)) - 1))
+#define VAL00(S) 0
+#define VAL01(S) 1
+
+
+#define TEST_U(S, V)				\
+  NI void test_##S##_##V (void)			\
+  {						\
+    S##_t x = S##bits (VAL##V (S));		\
+    __asm ("" : "+r" (x));			\
+    D d = (D) x;				\
+    D z = ldexpl (VAL##V (S), - FBIT##S);	\
+    if (d != z)					\
+      __builtin_exit (1);			\
+  }
+
+#define TEST_S(S, V)				\
+  NI void test_##S##_##V (void)			\
+  {						\
+    uint32_t u32 = (VAL##V (S) & VAL80 (S))	\
+      ? 1u + (VAL##V (S) ^ VALff (S))		\
+      : VAL##V (S);				\
+    S##_t x = S##bits (VAL##V (S));		\
+    __asm ("" : "+r" (x));			\
+    D d = (D) x;				\
+    D z = ldexpl (u32, - FBIT##S);		\
+    int s = (VAL##V (S) & VAL80 (S)) != 0;	\
+    if (s == 0 && d != z)			\
+      __builtin_exit (2);			\
+    if (s == 1 && d != -z)			\
+      __builtin_exit (3);			\
+  }
+
+#define TESTS_U(S)				\
+  TEST_U (S, 00)				\
+  TEST_U (S, 01)				\
+  TEST_U (S, ff)				\
+  TEST_U (S, 80)
+
+#define TESTS_S(S)				\
+  TEST_S (S, 00)				\
+  TEST_S (S, 01)				\
+  TEST_S (S, ff)				\
+  TEST_S (S, 80)
+
+TESTS_U (uhr)
+TESTS_U (ur)
+TESTS_U (uhk)
+TESTS_U (uk)
+
+TESTS_S (hr)
+TESTS_S (r)
+TESTS_S (hk)
+TESTS_S (k)
+
+#define RUN(S)		\
+  test_##S##_00 ();	\
+  test_##S##_01 ();	\
+  test_##S##_ff ();	\
+  test_##S##_80 ()
+  
+int main (void)
+{
+  RUN (uhr);
+  RUN (ur);
+  RUN (uhk);
+  RUN (uk);
+
+  RUN (hr);
+  RUN (r);
+  RUN (hk);
+  RUN (k);
+
+  return 0;
+}
+#else
+int main (void)
+{
+  return 0;
+}
+#endif
diff --git a/libgcc/config/avr/libf7/libf7-asm.sx b/libgcc/config/avr/libf7/libf7-asm.sx
index bafb490c5c7..18e676ace0f 100644
--- a/libgcc/config/avr/libf7/libf7-asm.sx
+++ b/libgcc/config/avr/libf7/libf7-asm.sx
@@ -2209,4 +2209,116 @@ _DEFUN __powidf2
 _ENDF __powidf2
 #endif /* F7MOD_D_powi_ */
 
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Fixed-point -> double conversions.
+
+;;; The double exponent starts at bit 52 since the encoded mantissa has 52 bits.
+;;; Note that when X is a multiple of 16, then dex_lo(x) evaluates to 0.
+#define dex_lo(x) hlo8((x) << (52 - 32))
+#define dex_hi(x) hhi8((x) << (52 - 32))
+
+#ifdef F7MOD_usa2D_
+_DEFUN __fractusadf
+    ;; Convert USI to DF.
+    XCALL   __floatunsidf
+    ;; The MSB indicates a value of 0.
+    cpse    r25, __zero_reg__
+    ;; Divide non-zero values by 2^16 in order to adjust for FBIT = 16.
+    subi    r25, dex_hi (16)
+    ret
+_ENDF __fractusadf
+#endif /* F7MOD_usa2D_ */
+
+#ifdef F7MOD_sa2D_
+_DEFUN __fractsadf
+    ;; Convert SI to DF.
+    XCALL   __floatsidf
+    ;; The MSB indicates a value of 0.
+    tst     r25
+    breq 0f
+    ;; Divide non-zero values by 2^15 in order to adjust for FBIT = 15.
+    subi    r24, dex_lo (15)
+    sbci    r25, dex_hi (15)
+0:  ret
+_ENDF __fractsadf
+#endif /* F7MOD_sa2D_ */
+
+#ifdef F7MOD_uha2D_
+_DEFUN __fractuhadf
+    ;; Extend UHA to USA.
+    clr     r22
+    mov     r23, r24
+    mov     r24, r25
+    clr     r25
+    XJMP    __fractusadf
+_ENDF __fractuhadf
+#endif /* F7MOD_uha2D_ */
+
+#ifdef F7MOD_ha2D_
+_DEFUN __fracthadf
+    ;; Extend HA to SA.
+    clr     r22
+    mov     r23, r24
+    mov     r24, r25
+    lsl     r25
+    sbc     r25, r25
+    XJMP    __fractsadf
+_ENDF __fracthadf
+#endif /* F7MOD_ha2D_ */
+
+
+#ifdef F7MOD_usq2D_
+_DEFUN __fractusqdf
+    ;; Convert USI to DF.
+    XCALL   __floatunsidf
+    ;; The MSB indicates a value of 0.
+    cpse    r25, __zero_reg__
+    ;; Divide non-zero values by 2^32 in order to adjust for FBIT = 32.
+    subi    r25, dex_hi (32)
+    ret
+_ENDF __fractusqdf
+#endif /* F7MOD_usq2D_ */
+
+#ifdef F7MOD_sq2D_
+_DEFUN __fractsqdf
+    ;; Convert SI to DF.
+    XCALL   __floatsidf
+    ;; The MSB indicates a value of 0.
+    tst     r25
+    breq 0f
+    ;; Divide non-zero values by 2^31 in order to adjust for FBIT = 31.
+    subi    r24, dex_lo (31)
+    sbci    r25, dex_hi (31)
+0:  ret
+_ENDF __fractsqdf
+#endif /* F7MOD_sq2D_ */
+
+#ifdef F7MOD_uqq2D_
+_DEFUN __fractuqqdf
+    ;; Extend UQQ to UHQ.
+    mov     r25, r24
+    clr     r24
+_LABEL __fractuhqdf
+    ;; Extend UHQ to USQ.
+    clr     r23
+    clr     r22
+    XJMP    __fractusqdf
+_ENDF __fractuqqdf
+#endif /* F7MOD_uqq2D_ */
+
+#ifdef F7MOD_qq2D_
+_DEFUN __fractqqdf
+    ;; Extend QQ to HQ.
+    mov     r25, r24
+    clr     r24
+_LABEL __fracthqdf
+    ;; Extend HQ to SQ.
+    clr     r23
+    clr     r22
+    XJMP    __fractsqdf
+_ENDF __fractqqdf
+#endif /* F7MOD_qq2D_ */
+
+
 #endif /* !AVR_TINY */
diff --git a/libgcc/config/avr/libf7/libf7-common.mk b/libgcc/config/avr/libf7/libf7-common.mk
index 153266ba141..85f83504969 100644
--- a/libgcc/config/avr/libf7/libf7-common.mk
+++ b/libgcc/config/avr/libf7/libf7-common.mk
@@ -28,6 +28,10 @@ F7_ASM_PARTS += D_cmp D_eq D_ne D_ge D_gt D_le D_lt D_unord D_fminfmax
 
 F7_ASM_PARTS += call_dd call_ddd
 
+# Fixed-point -> double conversions
+F7_ASM_PARTS += qq2D uqq2D            sq2D usq2D
+F7_ASM_PARTS +=            ha2D uha2D sa2D usa2D
+
 # Stuff that will be wrapped in f7-wraps.h (included by libf7-asm.sx)
 # and give f7_asm_D_*.o modules.
 g_ddd += add sub mul div
    AVR: target/122210 - Add double -> fixed-point conversions.
    
            PR target/122210
    libgcc/config/avr/libf7/
            * libf7-common.mk (F7_ASM_PARTS): Add D2<fx> modules.
            * libf7-asm.sx: Implement the D2<fx> modules.
    
    gcc/testsuite/
            * gcc.target/avr/dtofx.c: New test.

diff --git a/gcc/testsuite/gcc.target/avr/dtofx.c b/gcc/testsuite/gcc.target/avr/dtofx.c
new file mode 100644
index 00000000000..f7e28159f92
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/dtofx.c
@@ -0,0 +1,98 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options { -std=gnu99 -Os -mcall-prologues -Wno-pedantic } } */
+
+#include <stdfix.h>
+
+#if __SIZEOF_LONG_DOUBLE__ == 8
+
+typedef long double D;
+
+volatile D d0 = 0;
+volatile D dm15 = -1.5;
+volatile D dp15 = +1.5;
+volatile D dm05 = -0.5;
+volatile D dp05 = +0.5;
+
+void test0 (void)
+{
+  if (0hk != (short accum) d0)
+    __builtin_exit (__LINE__);
+
+  if (0uhk != (unsigned short accum) d0)
+    __builtin_exit (__LINE__);
+
+  if (0hr != (short fract) d0)
+    __builtin_exit (__LINE__);
+
+  if (0uhr != (unsigned short fract) d0)
+    __builtin_exit (__LINE__);
+
+  if (0k != (accum) d0)
+    __builtin_exit (__LINE__);
+
+  if (0uk != (unsigned accum) d0)
+    __builtin_exit (__LINE__);
+
+  if (0r != (fract) d0)
+    __builtin_exit (__LINE__);
+
+  if (0ur != (unsigned fract) d0)
+    __builtin_exit (__LINE__);
+}
+
+void testp (void)
+{
+  if (0.5hr != (short fract) dp05)
+    __builtin_exit (__LINE__);
+
+  if (0.5uhr != (unsigned short fract) dp05)
+    __builtin_exit (__LINE__);
+
+  if (0.5r != (fract) dp05)
+    __builtin_exit (__LINE__);
+
+  if (0.5ur != (unsigned fract) dp05)
+    __builtin_exit (__LINE__);
+
+  if (1.5hk != (short accum) dp15)
+    __builtin_exit (__LINE__);
+
+  if (1.5uhk != (unsigned short accum) dp15)
+    __builtin_exit (__LINE__);
+
+  if (1.5k != (accum) dp15)
+    __builtin_exit (__LINE__);
+
+  if (1.5uk != (unsigned accum) dp15)
+    __builtin_exit (__LINE__);
+}
+
+void testm (void)
+{
+  if (-0.5hr != (short fract) dm05)
+    __builtin_exit (__LINE__);
+
+  if (-0.5r != (fract) dm05)
+    __builtin_exit (__LINE__);
+
+  if (-1.5hk != (short accum) dm15)
+    __builtin_exit (__LINE__);
+
+  if (-1.5k != (accum) dm15)
+    __builtin_exit (__LINE__);
+}
+
+int main (void)
+{
+  test0 ();
+  testp ();
+  testm ();
+
+  return 0;
+}
+#else
+int main (void)
+{
+  return 0;
+}
+#endif
diff --git a/libgcc/config/avr/libf7/libf7-asm.sx b/libgcc/config/avr/libf7/libf7-asm.sx
index 18e676ace0f..4b42947e2ed 100644
--- a/libgcc/config/avr/libf7/libf7-asm.sx
+++ b/libgcc/config/avr/libf7/libf7-asm.sx
@@ -2321,4 +2321,85 @@ _DEFUN __fractqqdf
 #endif /* F7MOD_qq2D_ */
 
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Fixed-point -> double conversions.
+
+#ifdef F7MOD_D2qq_
+_DEFUN __fractdfqq
+    ;; Multiply with 2^{24+7} to get a QQ result in r25.
+    subi    r24, dex_lo (-31)
+    sbci    r25, dex_hi (-31)
+    XCALL   __fixdfsi
+    mov     r24, r25
+    ret
+_ENDF __fractdfqq
+#endif /* F7MOD_D2qq_ */
+
+#ifdef F7MOD_D2uqq_
+_DEFUN __fractdfuqq
+    ;; Multiply with 2^{24+8} to get a UQQ result in r25.
+    subi    r25, dex_hi (-32)
+    XCALL   __fixunsdfsi
+    mov     r24, r25
+    ret
+_ENDF __fractdfuqq
+#endif /* F7MOD_D2uqq_ */
+
+#ifdef F7MOD_D2ha_
+_DEFUN __fractdfha
+    ;; Multiply with 2^{16+7} to get a HA result in r25:r24
+    subi    r24, dex_lo (-23)
+    sbci    r25, dex_hi (-23)
+    XJMP    __fixdfsi
+_ENDF __fractdfha
+#endif /* F7MOD_D2ha_ */
+
+#ifdef F7MOD_D2uha_
+_DEFUN __fractdfuha
+    ;; Multiply with 2^24 to get a UHA result in r25:r24.
+    subi    r24, dex_lo (-24)
+    sbci    r25, dex_hi (-24)
+    XJMP    __fixunsdfsi
+_ENDF __fractdfuha
+#endif /* F7MOD_D2uha_ */
+
+#ifdef F7MOD_D2hq_
+_DEFUN __fractdfhq
+    ;; Multiply with 2^{16+15} to get a HQ result in r25:r24
+    ;; resp. with 2^31 to get a SQ result in r25:r22.
+_LABEL __fractdfsq
+    subi    r24, dex_lo (-31)
+    sbci    r25, dex_hi (-31)
+    XJMP    __fixdfsi
+_ENDF __fractdfhq
+#endif /* F7MOD_D2hq_ */
+
+#ifdef F7MOD_D2uhq_
+_DEFUN __fractdfuhq
+    ;; Multiply with 2^{16+16} to get a UHQ result in r25:r24
+    ;; resp. with 2^32 to get a USQ result in r25:r22.
+_LABEL  __fractdfusq
+    subi    r25, dex_hi (-32)
+    XJMP    __fixunsdfsi
+_ENDF __fractdfuhq
+#endif /* F7MOD_D2uhq_ */
+
+#ifdef F7MOD_D2sa_
+_DEFUN __fractdfsa
+    ;; Multiply with 2^15 to get a SA result in r25:r22.
+    subi    r24, dex_lo (-15)
+    sbci    r25, dex_hi (-15)
+    XJMP    __fixdfsi
+_ENDF __fractdfsa
+#endif /* F7MOD_D2sa_ */
+
+#ifdef F7MOD_D2usa_
+_DEFUN __fractdfusa
+    ;; Multiply with 2^16 to get a USA result in r25:r22.
+    subi    r25, dex_hi (-16)
+    XJMP    __fixunsdfsi
+_ENDF __fractdfusa
+#endif /* F7MOD_D2usa_ */
+
+
 #endif /* !AVR_TINY */
diff --git a/libgcc/config/avr/libf7/libf7-common.mk b/libgcc/config/avr/libf7/libf7-common.mk
index 85f83504969..6d35454ee04 100644
--- a/libgcc/config/avr/libf7/libf7-common.mk
+++ b/libgcc/config/avr/libf7/libf7-common.mk
@@ -32,6 +32,10 @@ F7_ASM_PARTS += call_dd call_ddd
 F7_ASM_PARTS += qq2D uqq2D            sq2D usq2D
 F7_ASM_PARTS +=            ha2D uha2D sa2D usa2D
 
+# Double -> fixed-point conversions
+F7_ASM_PARTS += D2qq D2uqq D2hq D2uhq
+F7_ASM_PARTS +=            D2ha D2uha D2sa D2usa
+
 # Stuff that will be wrapped in f7-wraps.h (included by libf7-asm.sx)
 # and give f7_asm_D_*.o modules.
 g_ddd += add sub mul div

Reply via email to