aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2023-10-17 11:36:52 +0200
committerGeorg-Johann Lay <avr@gjlay.de>2023-10-17 11:54:31 +0200
commite889ba1c5edba0fdff2ab9ad9176485ca1ff0bc1 (patch)
tree61d49cccd5db4a8d3d481c373a820cb48ec151a3
parent27165633859bdf92589428213edfeccdb49b7d83 (diff)
LibF7: Implement fma / fmal.
libgcc/config/avr/libf7/ * libf7.h (F7_SIZEOF): New macro. * libf7-asm.sx: Use F7_SIZEOF instead of magic number "10". (F7MOD_D_fma_, __fma): New module and function. (fma) [-mdouble=64]: Define as alias for __fma. (fmal) [-mlong-double=64]: Define as alias for __fma. * libf7-common.mk (F7_ASM_PARTS): Add D_fma.
-rw-r--r--libgcc/config/avr/libf7/libf7-asm.sx69
-rw-r--r--libgcc/config/avr/libf7/libf7-common.mk2
-rw-r--r--libgcc/config/avr/libf7/libf7.h1
3 files changed, 62 insertions, 10 deletions
diff --git a/libgcc/config/avr/libf7/libf7-asm.sx b/libgcc/config/avr/libf7/libf7-asm.sx
index 8fbd66bd290..5df167fe73c 100644
--- a/libgcc/config/avr/libf7/libf7-asm.sx
+++ b/libgcc/config/avr/libf7/libf7-asm.sx
@@ -283,8 +283,8 @@ DEFUN copy
cp XL, ZL
cpc XH, ZH
breq 9f
- adiw XL, 10
- adiw ZL, 10
+ adiw XL, F7_SIZEOF
+ adiw ZL, F7_SIZEOF
set
bld ZERO, 1
bld ZERO, 3 ; ZERO = 0b1010 = 10.
@@ -312,8 +312,8 @@ DEFUN copy_P
st X+, TMP
dec ZERO
brne .Loop
- sbiw X, 10
- sbiw Z, 10
+ sbiw X, F7_SIZEOF
+ sbiw Z, F7_SIZEOF
ret
ENDF copy_P
#endif /* F7MOD_copy_P_ */
@@ -1328,6 +1328,58 @@ ENDF sqrt_approx
#undef Carry
+#ifdef F7MOD_D_fma_
+_DEFUN __fma
+ DALIAS fma
+ LALIAS fmal
+
+#define n_pushed 4
+#define n_frame (2 * F7_SIZEOF)
+
+ do_prologue_saves n_pushed, n_frame
+ ;; Y = FramePointer + 1
+ adiw Y, 1
+
+ ;; FP + 1 = (f7_t) arg1
+ wmov r16, Y
+ ;; The double argument arg1 is already in R18[].
+ XCALL F7_NAME (set_double_impl)
+
+ ;; The double argument arg2 is in R10[]. Move it to R18[].
+ wmov r18, r10
+ wmov r20, r12
+ wmov r22, r14
+ ;; R16, R17 are clobbered. Fetch them from where prologue_saves put them.
+ ldd r24, Y + n_frame + 3 ; Saved R16
+ ldd r25, Y + n_frame + 2 ; Saved R17
+ ;; FP + 1 + 10 = (f7_t) arg2
+ subi r16, lo8 (-F7_SIZEOF)
+ sbci r17, hi8 (-F7_SIZEOF)
+ XCALL F7_NAME (set_double_impl)
+
+ wmov r24, Y ; &arg1
+ wmov r22, r16 ; &arg2
+ XCALL F7_NAME (Imul) ; arg1 *= arg2
+
+ ;; The 3rd double argument arg3 was passed on the stack. Move it to R18[],
+ ;; Don't use f7_set_pdouble() because that function is unused (for now).
+ .irp n, 0, 1, 2, 3, 4, 5, 6, 7
+ ldd 18+\n, Y + n_frame + n_pushed + PC_SIZE + \n
+ .endr
+ XCALL F7_NAME (set_double_impl)
+
+ wmov r24, Y ; &arg1
+ wmov r22, r16 ; &arg2
+ XCALL F7_NAME (Iadd) ; arg1 += arg2
+
+ wmov r24, Y ; &arg1
+ XCALL F7_NAME (get_double)
+
+ do_epilogue_restores n_pushed, n_frame
+_ENDF __fma
+#endif /* F7MOD_D_fma_ */
+
+
#ifdef F7MOD_D_fabs_
_DEFUN __fabs
DALIAS fabs
@@ -1493,7 +1545,7 @@ LABEL call_dx ; WHAT = R13 = 0
wmov r14, Z
#define n_pushed 4
-#define n_frame 10
+#define n_frame F7_SIZEOF
do_prologue_saves n_pushed, n_frame
;; Y = FramePointer + 1
@@ -1565,7 +1617,7 @@ LABEL call_xdd
ret
#define n_pushed 4
-#define n_frame 20
+#define n_frame (2 * F7_SIZEOF)
call.2:
do_prologue_saves n_pushed, n_frame
@@ -1576,9 +1628,8 @@ call.2:
;; First double argument is already in R18[].
XCALL F7_NAME (set_double_impl)
;; FP + 11 = (f7_t) arg2
- wmov r16, Y
- subi r16, lo8 (-10)
- sbci r17, hi8 (-10)
+ subi r16, lo8 (-F7_SIZEOF)
+ sbci r17, hi8 (-F7_SIZEOF)
;; Move second double argument to R18[].
wmov r18, r10
wmov r20, r12
diff --git a/libgcc/config/avr/libf7/libf7-common.mk b/libgcc/config/avr/libf7/libf7-common.mk
index e417715a7e5..d541b48ff3c 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
+F7_ASM_PARTS += D_class D_fma
F7_ASM_PARTS += D_isnan D_isinf D_isfinite D_signbit D_copysign D_neg D_fabs
F7_ASM_PARTS += call_dd call_ddd
diff --git a/libgcc/config/avr/libf7/libf7.h b/libgcc/config/avr/libf7/libf7.h
index 7236e611341..d1169b18c99 100644
--- a/libgcc/config/avr/libf7/libf7.h
+++ b/libgcc/config/avr/libf7/libf7.h
@@ -29,6 +29,7 @@
#define F7_MANT_BYTES 7
#define F7_MANT_BITS (8 * F7_MANT_BYTES)
+#define F7_SIZEOF (1 + F7_MANT_BYTES + 2)
/* Using the following GCC features:
-- Unnamed structs / unions (GNU-C)