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.
Johann
diff --git a/libgcc/config/avr/asm-defs.h b/libgcc/config/avr/asm-defs.h
index 62879464f9d..cf943f046e9 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 4b77ee2dd56..0414b3a2eed 100644
--- a/libgcc/config/avr/lib1funcs-fixed.S
+++ b/libgcc/config/avr/lib1funcs-fixed.S
@@ -1118,10 +1118,7 @@ DEFUN __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 6af40122f02..f307ea6a064 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -1509,37 +1509,16 @@ DEFUN __divmodsi4
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
+ .call_if_neg r_arg2HH, __negsi2_r18 ; divisor negative: negate
XCALL __udivmodsi4 ; do the unsigned div/mod
- sbrc __tmp_reg__, 7 ; correct quotient sign
- rcall __divmodsi4_neg2
+ .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 @@ DEFUN __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 9b05c8575b6..2f9a2efc3cf 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 \