From e3a05e050226aaaa4e2a2e7aee1e5651212a68f6 Mon Sep 17 00:00:00 2001 From: Georg-Johann Lay Date: Mon, 6 Oct 2025 21:31:46 +0200 Subject: [PATCH] AVR/LibF7: Implement sincos. libgcc/config/avr/libf7/ * libf7-common.mk (F7_ASM_PARTS): Add D_sincos. * libf7-asm.sx: (D_sincos): New module implements sincos / sincosl. gcc/testsuite/ * gcc.target/avr/sincos-1.c: New test. --- gcc/testsuite/gcc.target/avr/sincos-1.c | 35 ++++++++++++++++ libgcc/config/avr/libf7/libf7-asm.sx | 53 +++++++++++++++++++++++++ libgcc/config/avr/libf7/libf7-common.mk | 2 +- 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/avr/sincos-1.c diff --git a/gcc/testsuite/gcc.target/avr/sincos-1.c b/gcc/testsuite/gcc.target/avr/sincos-1.c new file mode 100644 index 000000000000..3cf543cee2e6 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/sincos-1.c @@ -0,0 +1,35 @@ +/* { dg-do run { target { ! avr_tiny } } } */ +/* { dg-additional-options { -std=gnu99 -Os -mcall-prologues } } */ + +#if __SIZEOF_LONG_DOUBLE__ == 8 +typedef long double D; + +extern void sincosl (D, D*, D*); +extern D sinl (D); +extern D cosl (D); + +D s1, c1; + +int main (void) +{ + for (D x = -20; x < 20; x += 1.1) + { + sincosl (x, &s1, &c1); + + __asm ("" : "+r" (x) :: "memory"); + + if (s1 != sinl (x)) + __builtin_exit (1); + + if (c1 != cosl (x)) + __builtin_exit (2); + } + + 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 33e8f78006cf..bafb490c5c7e 100644 --- a/libgcc/config/avr/libf7/libf7-asm.sx +++ b/libgcc/config/avr/libf7/libf7-asm.sx @@ -1989,6 +1989,59 @@ LALIAS fmaxl _ENDF __fmax #endif /* F7MOD_D_fminfmax_ */ + +#ifdef F7MOD_D_sincos_ +;;; void sincos (double R18, double *R16, double *R14); +_DEFUN __sincos +DALIAS sincos +LALIAS sincosl + +#define n_pushed 4 +#define n_frame (2 * F7_SIZEOF) + do_prologue_saves n_pushed, n_frame + ;; Y = FramePointer + 1 + adiw Y, 1 + ;; R16 = frame-arg 1 + wmov r16, Y + ;; The double argument is in R18[]. + XCALL F7_NAME (set_double_impl) + ;; void f7_sincos (f7_t *ss, f7_t *cc, const f7_t *aa) + ;; Note that aa may equal ss or cc. + wmov r20, r16 ; aa + wmov r24, r16 ; ss = FP + 1 + subi r16, lo8(-F7_SIZEOF) + sbci r17, hi8(-F7_SIZEOF) + wmov r22, r16 ; cc = FP + 1 + F7_SIZEOF + XCALL F7_NAME (sincos) + + ;; double R18 = get_double (cc) + wmov r24, r16 + XCALL F7_NAME (get_double) + wmov XL, r14 ; double *pcos + rcall store.r18.X ; *pcos = R18 + + ;; double R18 = get_double (ss) + wmov r24, Y + XCALL F7_NAME (get_double) + ldd XL, Y + n_frame + 3 ; Saved R16 + ldd XH, Y + n_frame + 2 ; Saved R17 + rcall store.r18.X ; *psin = R18 + + do_epilogue_restores n_pushed, n_frame + +store.r18.X: + st X+, r18 + st X+, r19 + st X+, r20 + st X+, r21 + st X+, r22 + st X+, r23 + st X+, r24 + st X+, r25 + ret +_ENDF __sincos +#endif /* F7MOD_D_sincos_ */ + #ifdef F7MOD_call_dd_ ;; Provide double wrappers for functions that operate on f7_t and get f7_t*. diff --git a/libgcc/config/avr/libf7/libf7-common.mk b/libgcc/config/avr/libf7/libf7-common.mk index 2d3adaf45697..153266ba141e 100644 --- a/libgcc/config/avr/libf7/libf7-common.mk +++ b/libgcc/config/avr/libf7/libf7-common.mk @@ -22,7 +22,7 @@ F7_ASM_PARTS += addsub_mant_scaled store load F7_ASM_PARTS += to_integer to_unsigned clz normalize_with_carry normalize F7_ASM_PARTS += store_expo sqrt16 sqrt_approx div -F7_ASM_PARTS += D_class D_fma D_powi +F7_ASM_PARTS += D_class D_fma D_powi D_sincos F7_ASM_PARTS += D_isnan D_isinf D_isfinite D_signbit D_copysign D_neg D_fabs F7_ASM_PARTS += D_cmp D_eq D_ne D_ge D_gt D_le D_lt D_unord D_fminfmax