https://gcc.gnu.org/g:7b350a051058e95bb2640469bd040daab671f26c

commit r17-2262-g7b350a051058e95bb2640469bd040daab671f26c
Author: Georg-Johann Lay <[email protected]>
Date:   Wed Jul 8 19:40:26 2026 +0200

    AVR: Add R18:SI = neg R18:SI to libgcc.
    
    This patch factors out negating R18:SI which is used in several
    places.  It also adds
    
       .macro  .call_if_neg  reg, labl
    
    for convenience.  It calls <labl> iff <reg> < 0.
    
    libgcc/
            * config/avr/t-avr (LIB1ASMFUNCS): Add _negsi2_r18.
            * config/avr/asm-defs.h (.call_if_neg): New .macro.
            * config/avr/lib1funcs.S (__divmodsi4): Use .call_if_neg.
            (__negsi2_r18): New function.
            * config/avr/lib1funcs-fixed.S (__divsa3): Use .call_if_neg.

Diff:
---
 libgcc/config/avr/asm-defs.h        | 15 ++++++++++
 libgcc/config/avr/lib1funcs-fixed.S |  5 +---
 libgcc/config/avr/lib1funcs.S       | 55 ++++++++++++++++++-------------------
 libgcc/config/avr/t-avr             |  1 +
 4 files changed, 44 insertions(+), 32 deletions(-)

diff --git a/libgcc/config/avr/asm-defs.h b/libgcc/config/avr/asm-defs.h
index 62879464f9d3..cf943f046e9a 100644
--- a/libgcc/config/avr/asm-defs.h
+++ b/libgcc/config/avr/asm-defs.h
@@ -159,6 +159,21 @@
 .endm ; .branch_plus
 
 
+;;; [R]CALL label LABL when REG is negative (REG.7 = 1).
+;;; Otherwise, fallthrough.
+.macro  .call_if_neg  reg, labl
+#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
+    ;; Some cores have a problem skipping 2-word instructions.
+    tst     \reg
+    brpl    .L.call_if_neg.\@
+#else
+    sbrc    \reg, 7
+#endif /* skip erratum */
+    XCALL   \labl
+.L.call_if_neg.\@:
+.endm ; .call_if_neg
+
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Macros for convenience.
 
diff --git a/libgcc/config/avr/lib1funcs-fixed.S 
b/libgcc/config/avr/lib1funcs-fixed.S
index 4b77ee2dd56d..0414b3a2eed9 100644
--- a/libgcc/config/avr/lib1funcs-fixed.S
+++ b/libgcc/config/avr/lib1funcs-fixed.S
@@ -1118,10 +1118,7 @@ ENDF __udivuha3
 DEFUN   __divsa3
     mov     r0, r_arg1HH
     eor     r0, r_divHH
-    sbrs    r_divHH, 7
-    rjmp    1f
-    NEG4    r_divL
-1:
+    .call_if_neg r_divHH, __negsi2_r18
     sbrs    r_arg1HH, 7
     rjmp    2f
     NEG4    r_arg1L
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index 6af40122f022..2e30c796ef94 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -1504,42 +1504,21 @@ ENDF __udivmodsi4
 #if defined (L_divmodsi4)
 DEFUN __divmodsi4
     mov     __tmp_reg__,r_arg2HH
-    bst     r_arg1HH,7          ; store sign of dividend
+    bst     r_arg1HH,7                  ; store sign of dividend
     brtc    0f
-    com     __tmp_reg__         ; r0.7 is sign of result
-    XCALL   __negsi2            ; dividend negative: negate
+    com     __tmp_reg__                 ; r0.7 is sign of result
+    XCALL   __negsi2                    ; dividend negative: negate
 0:
-    sbrc    r_arg2HH,7
-    rcall   __divmodsi4_neg2    ; divisor negative: negate
-    XCALL   __udivmodsi4        ; do the unsigned div/mod
-    sbrc    __tmp_reg__, 7      ; correct quotient sign
-    rcall   __divmodsi4_neg2
-    brtc    __divmodsi4_exit    ; correct remainder sign
+    .call_if_neg r_arg2HH, __negsi2_r18 ; divisor negative: negate
+    XCALL   __udivmodsi4                ; do the unsigned div/mod
+    .call_if_neg __tmp_reg__, __negsi2_r18 ; correct quotient sign
+    brtc    __divmodsi4_exit            ; correct remainder sign
     XJMP    __negsi2
-__divmodsi4_neg2:
-    ;; correct divisor/quotient sign
-    com     r_arg2HH
-    com     r_arg2HL
-    com     r_arg2H
-    neg     r_arg2L
-    sbci    r_arg2H,0xff
-    sbci    r_arg2HL,0xff
-    sbci    r_arg2HH,0xff
 __divmodsi4_exit:
     ret
 ENDF __divmodsi4
 #endif /* defined (L_divmodsi4) */
 
-#if defined (L_negsi2)
-;; (set (reg:SI 22)
-;;      (neg:SI (reg:SI 22)))
-;; Sets the V flag for signed overflow tests
-DEFUN __negsi2
-    NEG4    22
-    ret
-ENDF __negsi2
-#endif /* L_negsi2 */
-
 #undef r_remHH
 #undef r_remHL
 #undef r_remH
@@ -1554,6 +1533,26 @@ ENDF __negsi2
 #undef r_arg2L
 #undef r_cnt
 
+#if defined (L_negsi2)
+;; (set (reg:SI 22)
+;;      (neg:SI (reg:SI 22)))
+;; Sets the V flag for signed overflow tests
+DEFUN __negsi2
+    NEG4    22
+    ret
+ENDF __negsi2
+#endif /* L_negsi2 */
+
+#if defined (L_negsi2_r18)
+;; (set (reg:SI 18)
+;;      (neg:SI (reg:SI 18)))
+;; Sets the V flag for signed overflow tests
+DEFUN __negsi2_r18
+    NEG4    18
+    ret
+ENDF __negsi2_r18
+#endif /* L_negsi2_r18 */
+
 /* *di routines use registers below R19 and won't work with tiny arch
    right now. */
 
diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr
index 9b05c8575b6a..2f9a2efc3cf4 100644
--- a/libgcc/config/avr/t-avr
+++ b/libgcc/config/avr/t-avr
@@ -14,6 +14,7 @@ LIB1ASMFUNCS = \
        _udivmodsi4 \
        _divmodsi4 \
        _negsi2 \
+       _negsi2_r18 \
        _exit \
        _cleanup \
        _tablejump2 \

Reply via email to