--- /dev/null
+/* { 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
_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 */
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