From: Georg-Johann Lay Date: Thu, 9 Oct 2025 16:35:34 +0000 (+0200) Subject: AVR: target/122222 - Add modules for __floatsidf, __floatunsidf. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fcae8c376adb63b40915624c97c00f717344cb98;p=thirdparty%2Fgcc.git AVR: target/122222 - Add modules for __floatsidf, __floatunsidf. PR target/122222 libgcc/config/avr/libf7/ * libf7-asm.sx (D_floatsidf, D_floatunsidf): New modules. * libf7-common.mk (F7_ASM_PARTS): Add D_floatsidf, D_floatunsidf. (F7F, g_dx): Remove floatunsidf, floatsidf. * libf7.c (f7_set_s32): Don't alias to f7_floatsidf. (f7_set_u32): Don't alias to f7_floatunsidf. * f7-renames.h: Rebuild * f7-wraps.h: Rebuild. gcc/testsuite/ * gcc.target/avr/pr122222-sitod.c: New test. (cherry picked from commit 078208cf15bb373dc7931d6b373689cdff70cdc5) --- diff --git a/gcc/testsuite/gcc.target/avr/pr122222-sitod.c b/gcc/testsuite/gcc.target/avr/pr122222-sitod.c new file mode 100644 index 00000000000..d8f172005e3 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/pr122222-sitod.c @@ -0,0 +1,60 @@ +/* { 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 diff --git a/libgcc/config/avr/libf7/f7-renames.h b/libgcc/config/avr/libf7/f7-renames.h index e8f181f30f3..a3898d2aecb 100644 --- a/libgcc/config/avr/libf7/f7-renames.h +++ b/libgcc/config/avr/libf7/f7-renames.h @@ -159,8 +159,6 @@ #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 diff --git a/libgcc/config/avr/libf7/f7-wraps.h b/libgcc/config/avr/libf7/f7-wraps.h index 167ffc0b06b..3f91415a936 100644 --- a/libgcc/config/avr/libf7/f7-wraps.h +++ b/libgcc/config/avr/libf7/f7-wraps.h @@ -135,27 +135,7 @@ _ENDF __truncdfsf2 #endif /* F7MOD_D_truncdfsf2_ */ ;; Functions that usually live in libgcc: __ for 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_ diff --git a/libgcc/config/avr/libf7/libf7-asm.sx b/libgcc/config/avr/libf7/libf7-asm.sx index 21a2affd798..16395b37879 100644 --- a/libgcc/config/avr/libf7/libf7-asm.sx +++ b/libgcc/config/avr/libf7/libf7-asm.sx @@ -2201,8 +2201,9 @@ _ENDF __powidf2 ;;; 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 @@ -2388,4 +2389,83 @@ _ENDF __fractdfusa #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 */ diff --git a/libgcc/config/avr/libf7/libf7-common.mk b/libgcc/config/avr/libf7/libf7-common.mk index 6d35454ee04..e2b47409ba8 100644 --- a/libgcc/config/avr/libf7/libf7-common.mk +++ b/libgcc/config/avr/libf7/libf7-common.mk @@ -36,11 +36,14 @@ F7_ASM_PARTS += ha2D uha2D sa2D usa2D 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 @@ -91,7 +94,7 @@ F7F += set_eps set_1pow2 # 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. diff --git a/libgcc/config/avr/libf7/libf7.c b/libgcc/config/avr/libf7/libf7.c index 482dbd23cdb..4e3cc9fc634 100644 --- a/libgcc/config/avr/libf7/libf7.c +++ b/libgcc/config/avr/libf7/libf7.c @@ -207,7 +207,6 @@ f7_t* f7_set_s32 (f7_t *cc, int32_t i32) cc->flags = flags; return cc; } -ALIAS (f7_set_s32, f7_floatsidf) #endif // F7MOD_set_s32_ @@ -219,7 +218,6 @@ f7_t* f7_set_u32 (f7_t *cc, uint32_t u32) cc->expo = 31; return f7_normalize_asm (cc); } -ALIAS (f7_set_u32, f7_floatunsidf) #endif // F7MOD_set_u32_