diff mbox series

[avr,committed] LibF7: Implement a function that was missing for devices without MUL.

Message ID 4c64ce1d-790e-6c66-9824-5b31b9a4b662@gjlay.de
State New
Headers show
Series [avr,committed] LibF7: Implement a function that was missing for devices without MUL. | expand

Commit Message

Georg-Johann Lay Oct. 18, 2023, 5:03 p.m. UTC
This implements the worker function for double multiplication
for devices without MUL instruction.

Johann

--

LibF7: Implement mul_mant for devices without MUL instruction.

libgcc/config/avr/libf7/
	* libf7-asm.sx (mul_mant): Implement for devices without MUL.
	* asm-defs.h (wmov) [!HAVE_MUL]: Fix regno computation.
	* t-libf7 (F7_ASM_FLAGS): Add -g0.
diff mbox series

Patch

diff --git a/libgcc/config/avr/libf7/asm-defs.h 
b/libgcc/config/avr/libf7/asm-defs.h
index 4cfd3e61cbb..a50260a162f 100644
--- a/libgcc/config/avr/libf7/asm-defs.h
+++ b/libgcc/config/avr/libf7/asm-defs.h
@@ -134,14 +134,14 @@ 
      ..regno = 0

      .irp    reg,                        \
-            X, x, XL, xl, Xl, xL, x, x  \
+            X, x, XL, xl, Xl, xL, x, x, \
              Y, y, YL, yl, Yl, yL, y, y, \
              Z, z, ZL, zl, Zl, zL, z, z
          .ifc  \reg,\dst
-            ..dst = (..regno / 8) + 26
+            ..dst = 2 * (..regno / 8) + 26
          .endif
          .ifc  \reg,\src
-            ..src = (..regno / 8) + 26
+            ..src = 2 * (..regno / 8) + 26
          .endif
          ..regno = ..regno + 1
      .endr
diff --git a/libgcc/config/avr/libf7/libf7-asm.sx 
b/libgcc/config/avr/libf7/libf7-asm.sx
index 5df167fe73c..4505764c126 100644
--- a/libgcc/config/avr/libf7/libf7-asm.sx
+++ b/libgcc/config/avr/libf7/libf7-asm.sx
@@ -1067,6 +1067,100 @@  DEFUN mul_mant
  ENDF mul_mant
  #endif /* F7MOD_mul_mant_ && MUL */

+#if defined F7MOD_mul_mant_ && ! defined (__AVR_HAVE_MUL__)
+    #define     AA      TMP
+    #define     A0      13
+    #define     A1      A0+1
+    #define     A2      A0+2
+    #define     A3      A0+3
+    #define     A4      A0+4
+    #define     A5      r26
+    #define     A6      r27
+    #define     BB      ZERO
+    #define     Bits    r29
+    #define     Bytes   r28
+
+DEFUN mul_mant
+    do_prologue_saves 7
+    bst     r18,    0           ; T = 1: Don't round.
+    ;; Save result address for later.
+    push    r25
+    push    r24
+    ;; Load 1st operand mantissa.
+    wmov    r30,    r22
+    clr     AA
+    LDD     A0,     Z+0+Off
+    LDD     A1,     Z+1+Off
+    LDD     A2,     Z+2+Off
+    LDD     A3,     Z+3+Off
+    LDD     A4,     Z+4+Off
+    LDD     A5,     Z+5+Off
+    LDD     A6,     Z+6+Off
+    ;; Let Z point one past .mant of the 2nd input operand.
+    wmov    r30,    r20
+    adiw    r30,    Expo
+
+    ;; Clear the result mantissa.
+    .global __clr_8
+    XCALL   __clr_8
+
+    ;; Loop over the bytes of B's mantissa from highest to lowest.
+    ;; "+1" because we jump into the loop.
+    ldi     Bytes,  1 + F7_MANT_BYTES
+
+    ;; Divide one operand by 2 so that the result mantissa won't overflow.
+    ;; This is accounted for by "Carry = 1" below.
+    ldi     Bits,   1
+    rjmp    .Loop_entry
+
+.Loop_bytes:
+    ld      BB,     -Z
+    ;;  Loop over the bits of B's mantissa from highest to lowest.
+    ldi     Bits,   8
+.Loop_bits:
+    lsl     BB
+    brcc    .Lnext_bit
+
+    ADD     CA,     AA
+    adc     C0,     A0
+    adc     C1,     A1
+    adc     C2,     A2
+    adc     C3,     A3
+    adc     C4,     A4
+    adc     C5,     A5
+    adc     C6,     A6
+
+.Lnext_bit:
+.Loop_entry:
+    LSR     A6
+    ror     A5
+    ror     A4
+    ror     A3
+    ror     A2
+    ror     A1
+    ror     A0
+    ror     AA
+
+    dec     Bits
+    brne    .Loop_bits
+
+    dec     Bytes
+    brne    .Loop_bytes
+
+    ;; Finally...
+
+    pop     ZL
+    pop     ZH
+
+    ;; The result has to be left-shifted by one (multiplied by 2) in order
+    ;; to undo the division by 2 of the 1st operand.
+    ldi     Carry,  1
+    F7call  normalize.maybe_round.store_with_flags
+
+    do_epilogue_restores 7
+ENDF mul_mant
+#endif /* F7MOD_mul_mant_ && ! MUL */
+

  #if defined (F7MOD_div_)

diff --git a/libgcc/config/avr/libf7/t-libf7 
b/libgcc/config/avr/libf7/t-libf7
index 30aa280d11e..f17e67e8523 100644
--- a/libgcc/config/avr/libf7/t-libf7
+++ b/libgcc/config/avr/libf7/t-libf7
@@ -86,7 +86,7 @@  F7_C_FLAGS +=   $(F7_FLAGS) \
  		-fno-tree-loop-optimize \
  		-fno-tree-loop-im -fno-move-loop-invariants

-F7_ASM_FLAGS +=	$(F7_FLAGS)
+F7_ASM_FLAGS +=	$(F7_FLAGS) -g0

  $(patsubst %, f7_c_%.o, $(CALL_PROLOGUES)) \
  	: F7_C_FLAGS += -mcall-prologues