This commit implements fma and fmal which were missing from LibF7.

Johann

--

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.


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 @@ DEFUN 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 @@ DEFUN call_dd   ; WHAT = R13 = 3
     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 @@ DEFUN call_ddd
     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 @@ DEFUN call_ddd
     ;; 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 b50e6e218ba..2b6beac0df8 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)

Reply via email to