--- /dev/null
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options { -std=gnu99 -Os -mcall-prologues } } */
+
+#if __SIZEOF_LONG_DOUBLE__ == 8
+
+typedef long double D;
+typedef __INT32_TYPE__ int32_t;
+typedef __UINT32_TYPE__ uint32_t;
+typedef __UINT8_TYPE__ uint8_t;
+
+#define ARRAY_SIZE(X) (sizeof(X) / sizeof(*X))
+
+void testu (void)
+{
+ static const volatile __flash uint32_t vals[] =
+ {
+ 0, 1ul, -1ul, (-1ul) << 1,
+ 1ul << 31, 1ul << 30, 1ul << 29, 1ul << 28, 1ul << 27, 1ul << 26,
+ 1ul << 25, 1ul << 24, 0xff, 123456789
+ };
+
+ for (uint8_t i = 0; i < ARRAY_SIZE (vals); ++i)
+ {
+ D x = (D) vals[i];
+ __asm ("" : "+r" (x));
+ if ((uint32_t) x != vals[i])
+ __builtin_exit (__LINE__);
+ }
+}
+
+void tests (void)
+{
+ static const volatile __flash int32_t vals[] =
+ {
+ 0, 1L, -1L, 0x7fffffff, -0x7fffffff, -0x7fffffff - 1,
+ -123456789
+ };
+
+ for (uint8_t i = 0; i < ARRAY_SIZE (vals); ++i)
+ {
+ D x = (D) vals[i];
+ __asm ("" : "+r" (x));
+ if ((int32_t) x != vals[i])
+ __builtin_exit (__LINE__);
+ }
+}
+
+int main (void)
+{
+ testu ();
+ tests ();
+
+ return 0;
+}
+#else
+int main (void)
+{
+ return 0;
+}
+#endif
#define f7_min __f7_min
#define f7_max __f7_max
#define f7_exp10 __f7_exp10
-#define f7_floatunsidf __f7_floatunsidf
-#define f7_floatsidf __f7_floatsidf
#define f7_extendsfdf2 __f7_extendsfdf2
#define f7_fixdfsi __f7_fixdfsi
#define f7_fixdfdi __f7_fixdfdi
#endif /* F7MOD_D_truncdfsf2_ */
;; Functions that usually live in libgcc: __<name> for <name> in:
-;; floatunsidf floatsidf extendsfdf2
-
-;; double __floatunsidf (type_t) ; floatunsidf
-#ifdef F7MOD_D_floatunsidf_
-_DEFUN __floatunsidf
- .global F7_NAME(floatunsidf)
- ldi ZH, hi8(gs(F7_NAME(floatunsidf)))
- ldi ZL, lo8(gs(F7_NAME(floatunsidf)))
- F7jmp call_dx
-_ENDF __floatunsidf
-#endif /* F7MOD_D_floatunsidf_ */
-
-;; double __floatsidf (type_t) ; floatsidf
-#ifdef F7MOD_D_floatsidf_
-_DEFUN __floatsidf
- .global F7_NAME(floatsidf)
- ldi ZH, hi8(gs(F7_NAME(floatsidf)))
- ldi ZL, lo8(gs(F7_NAME(floatsidf)))
- F7jmp call_dx
-_ENDF __floatsidf
-#endif /* F7MOD_D_floatsidf_ */
+;; extendsfdf2
;; double __extendsfdf2 (type_t) ; extendsfdf2
#ifdef F7MOD_D_extendsfdf2_
;;; 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))
+#define DEX16(x) (x) << (52 - 48)
+#define dex_lo(x) lo8 (DEX16 (x))
+#define dex_hi(x) hi8 (DEX16 (x))
#ifdef F7MOD_usa2D_
_DEFUN __fractusadf
#endif /* F7MOD_D2usa_ */
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; [u]int32_t -> double conversions.
+
+;; double __floatsidf (int32_t);
+#ifdef F7MOD_D_floatsidf_
+_DEFUN __floatsidf
+ bst r25, 7
+ brtc 0f
+ XCALL __negsi2
+0: XJMP __floatunsidf.ge0
+_ENDF __floatsidf
+#endif /* F7MOD_D_floatsidf_ */
+
+;; double __floatunsidf (uint32_t);
+#ifdef F7MOD_D_floatunsidf_
+_DEFUN __floatunsidf
+ clt
+_LABEL __floatunsidf.ge0
+ ;; Zero-extend SI at the low end.
+ clr r18
+ clr r19
+ wmov r20, r18
+ ;; Input is zero?
+ sbiw r24, 0
+ sbci r23, 0
+ sbci r22, 0
+ breq 9f
+ ;; No: The double exponent of 0x80000000 is 31 plus a bias of 1023.
+ ;; Align the SI value such that the MSBit is as R25.4.
+ ;; For each << we have to subtract 1 from the exponent, and for
+ ;; each >> we have to add 1. Since we want the MSB in R25.4 and
+ ;; not in R25.7, the initial exponent must be reduced by 3.
+ ldi Xl, dex_lo (31 + 1023 - 3)
+ ldi Xh, dex_hi (31 + 1023 - 3)
+ ;; Move the MSByte to R25.
+1: tst r25
+ brne 2f
+ subi Xl, dex_lo (8)
+ sbci Xh, dex_hi (8)
+ mov r25, r24
+ mov r24, r23
+ mov r23, r22
+ clr r22
+ rjmp 1b
+2: ;; Now we have R25 != 0.
+ cpi r25, 0x20
+ brlo 3f
+ adiw Xl, DEX16 (1)
+ lsr r25
+ ror r24
+ ror r23
+ ror r22
+ ror r21
+ rjmp 2b
+3: cpi r25, 0x10
+ brsh 4f
+ sbiw Xl, DEX16 (1)
+ lsl r22
+ rol r23
+ rol r24
+ rol r25
+ rjmp 3b
+4: ;; Move the mantissa into place and clear the redundant leading 1.
+ cbr r25, 0x10
+ mov r20, r21
+ mov r21, r22
+ mov r22, r23
+ mov r23, r24
+ mov r24, r25
+ ;; Insert the biased exponent.
+ or r24, Xl
+ mov r25, Xh
+ ;; Insert the sign.
+ bld r25, 7
+9: ret
+_ENDF __floatunsidf
+#endif /* F7MOD_D_floatunsidf_ */
+
+
#endif /* !AVR_TINY */
F7_ASM_PARTS += D2qq D2uqq D2hq D2uhq
F7_ASM_PARTS += D2ha D2uha D2sa D2usa
+# Integer -> double conversions
+F7_ASM_PARTS += D_floatsidf D_floatunsidf
+
# 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
g_xdd_cmp +=
-g_dx += floatunsidf floatsidf extendsfdf2
+g_dx += extendsfdf2
g_xd += fixdfsi fixdfdi fixunsdfdi fixunsdfsi truncdfsf2
m_ddd += pow fmod hypot atan2 fdim
# Renames for ALIASes without own module.
F7F += min max exp10
-F7F += floatunsidf floatsidf extendsfdf2
+F7F += extendsfdf2
F7F += fixdfsi fixdfdi fixunsdfdi fixunsdfsi truncdfsf2
# Renames for f7-const.def.
cc->flags = flags;
return cc;
}
-ALIAS (f7_set_s32, f7_floatsidf)
#endif // F7MOD_set_s32_
cc->expo = 31;
return f7_normalize_asm (cc);
}
-ALIAS (f7_set_u32, f7_floatunsidf)
#endif // F7MOD_set_u32_