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 \
