summaryrefslogtreecommitdiff
path: root/libgcc/config
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc/config')
-rw-r--r--libgcc/config/avr/lib1funcs-fixed.S224
-rw-r--r--libgcc/config/avr/lib1funcs.S41
-rw-r--r--libgcc/config/avr/t-avr24
3 files changed, 273 insertions, 16 deletions
diff --git a/libgcc/config/avr/lib1funcs-fixed.S b/libgcc/config/avr/lib1funcs-fixed.S
index c1aff53d5fd..ddcd02e197c 100644
--- a/libgcc/config/avr/lib1funcs-fixed.S
+++ b/libgcc/config/avr/lib1funcs-fixed.S
@@ -808,8 +808,8 @@ DEFUN __divsa3
XCALL __udivusa3
sbrs r0, 7 ; negate result if needed
ret
- NEG4 r_quoL
- ret
+ ;; negate r_quoL
+ XJMP __negsi2
ENDF __divsa3
#endif /* defined (L_divsa3) */
@@ -872,3 +872,223 @@ ENDF __udivusa3
#undef r_divHL
#undef r_divHH
#undef r_cnt
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Saturation, 2 Bytes
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; First Argument and Return Register
+#define A0 24
+#define A1 A0+1
+
+#if defined (L_ssneg_2)
+DEFUN __ssneg_2
+ NEG2 A0
+ brvc 0f
+ sbiw A0, 1
+0: ret
+ENDF __ssneg_2
+#endif /* L_ssneg_2 */
+
+#if defined (L_ssabs_2)
+DEFUN __ssabs_2
+ sbrs A1, 7
+ ret
+ XJMP __ssneg_2
+ENDF __ssabs_2
+#endif /* L_ssabs_2 */
+
+#undef A0
+#undef A1
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Saturation, 4 Bytes
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; First Argument and Return Register
+#define A0 22
+#define A1 A0+1
+#define A2 A0+2
+#define A3 A0+3
+
+#if defined (L_ssneg_4)
+DEFUN __ssneg_4
+ XCALL __negsi2
+ brvc 0f
+ ldi A3, 0x7f
+ ldi A2, 0xff
+ ldi A1, 0xff
+ ldi A0, 0xff
+0: ret
+ENDF __ssneg_4
+#endif /* L_ssneg_4 */
+
+#if defined (L_ssabs_4)
+DEFUN __ssabs_4
+ sbrs A3, 7
+ ret
+ XJMP __ssneg_4
+ENDF __ssabs_4
+#endif /* L_ssabs_4 */
+
+#undef A0
+#undef A1
+#undef A2
+#undef A3
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Saturation, 8 Bytes
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; First Argument and Return Register
+#define A0 18
+#define A1 A0+1
+#define A2 A0+2
+#define A3 A0+3
+#define A4 A0+4
+#define A5 A0+5
+#define A6 A0+6
+#define A7 A0+7
+
+#if defined (L_clr_8)
+FALIAS __usneguta2
+FALIAS __usneguda2
+FALIAS __usnegudq2
+
+;; Clear Carry and all Bytes
+DEFUN __clr_8
+ ;; Clear Carry and set Z
+ sub A7, A7
+ ;; FALLTHRU
+ENDF __clr_8
+;; Propagate Carry to all Bytes, Carry unaltered
+DEFUN __sbc_8
+ sbc A7, A7
+ sbc A6, A6
+ wmov A4, A6
+ wmov A2, A6
+ wmov A0, A6
+ ret
+ENDF __sbc_8
+#endif /* L_clr_8 */
+
+#if defined (L_ssneg_8)
+FALIAS __ssnegta2
+FALIAS __ssnegda2
+FALIAS __ssnegdq2
+
+DEFUN __ssneg_8
+ XCALL __negdi2
+ brvc 0f
+ ;; A[] = 0x7fffffff
+ sec
+ XCALL __sbc_8
+ ldi A7, 0x7f
+0: ret
+ENDF __ssneg_8
+#endif /* L_ssneg_8 */
+
+#if defined (L_ssabs_8)
+FALIAS __ssabsta2
+FALIAS __ssabsda2
+FALIAS __ssabsdq2
+
+DEFUN __ssabs_8
+ sbrs A7, 7
+ ret
+ XJMP __ssneg_8
+ENDF __ssabs_8
+#endif /* L_ssabs_8 */
+
+;; Second Argument
+#define B0 10
+#define B1 B0+1
+#define B2 B0+2
+#define B3 B0+3
+#define B4 B0+4
+#define B5 B0+5
+#define B6 B0+6
+#define B7 B0+7
+
+#if defined (L_usadd_8)
+FALIAS __usadduta3
+FALIAS __usadduda3
+FALIAS __usaddudq3
+
+DEFUN __usadd_8
+ XCALL __adddi3
+ brcs 0f
+ ret
+ ;; A[] = 0xffffffff
+0: XJMP __sbc_8
+ENDF __usadd_8
+#endif /* L_usadd_8 */
+
+#if defined (L_ussub_8)
+FALIAS __ussubuta3
+FALIAS __ussubuda3
+FALIAS __ussubudq3
+
+DEFUN __ussub_8
+ XCALL __subdi3
+ brcs 0f
+ ret
+ ;; A[] = 0
+0: XJMP __clr_8
+ENDF __ussub_8
+#endif /* L_ussub_8 */
+
+#if defined (L_ssadd_8)
+FALIAS __ssaddta3
+FALIAS __ssaddda3
+FALIAS __ssadddq3
+
+DEFUN __ssadd_8
+ ;; A = (B >= 0) ? INT64_MAX : INT64_MIN
+ XCALL __adddi3
+ brvc 0f
+ cpi B7, 0x80
+ XCALL __sbc_8
+ subi A7, 0x80
+0: ret
+ENDF __ssadd_8
+#endif /* L_ssadd_8 */
+
+#if defined (L_sssub_8)
+FALIAS __sssubta3
+FALIAS __sssubda3
+FALIAS __sssubdq3
+
+DEFUN __sssub_8
+ XCALL __subdi3
+ brvc 0f
+ ;; A = (B < 0) ? INT64_MAX : INT64_MIN
+ ldi A7, 0x7f
+ cp A7, B7
+ XCALL __sbc_8
+ subi A7, 0x80
+0: ret
+ENDF __sssub_8
+#endif /* L_sssub_8 */
+
+#undef A0
+#undef A1
+#undef A2
+#undef A3
+#undef A4
+#undef A5
+#undef A6
+#undef A7
+#undef B0
+#undef B1
+#undef B2
+#undef B3
+#undef B4
+#undef B5
+#undef B6
+#undef B7
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index 6b9879ee7d7..ad979189306 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -91,6 +91,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
.endfunc
.endm
+.macro FALIAS name
+.global \name
+.func \name
+\name:
+.size \name, .-\name
+.endfunc
+.endm
+
;; Negate a 2-byte value held in consecutive registers
.macro NEG2 reg
com \reg+1
@@ -99,6 +107,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
.endm
;; Negate a 4-byte value held in consecutive registers
+;; Sets the V flag for signed overflow tests if REG >= 16
.macro NEG4 reg
com \reg+3
com \reg+2
@@ -1325,7 +1334,7 @@ DEFUN __divmodsi4
bst r_arg1HH,7 ; store sign of dividend
brtc 0f
com __tmp_reg__ ; r0.7 is sign of result
- rcall __divmodsi4_neg1 ; dividend negative: negate
+ XCALL __negsi2 ; dividend negative: negate
0:
sbrc r_arg2HH,7
rcall __divmodsi4_neg2 ; divisor negative: negate
@@ -1333,16 +1342,7 @@ DEFUN __divmodsi4
sbrc __tmp_reg__, 7 ; correct quotient sign
rcall __divmodsi4_neg2
brtc __divmodsi4_exit ; correct remainder sign
-__divmodsi4_neg1:
- ;; correct dividend/remainder sign
- com r_arg1HH
- com r_arg1HL
- com r_arg1H
- neg r_arg1L
- sbci r_arg1H, 0xff
- sbci r_arg1HL,0xff
- sbci r_arg1HH,0xff
- ret
+ XJMP __negsi2
__divmodsi4_neg2:
;; correct divisor/quotient sign
com r_arg2HH
@@ -1357,6 +1357,16 @@ __divmodsi4_exit:
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
@@ -1689,6 +1699,8 @@ ENDF __divdi3_moddi3
;; (set (reg:DI 18)
;; (plus:DI (reg:DI 18)
;; (reg:DI 10)))
+;; Sets the V flag for signed overflow tests
+;; Sets the C flag for unsigned overflow tests
DEFUN __adddi3
ADD A0,B0 $ adc A1,B1 $ adc A2,B2 $ adc A3,B3
adc A4,B4 $ adc A5,B5 $ adc A6,B6 $ adc A7,B7
@@ -1700,6 +1712,8 @@ ENDF __adddi3
;; (set (reg:DI 18)
;; (plus:DI (reg:DI 18)
;; (sign_extend:SI (reg:QI 26))))
+;; Sets the V flag for signed overflow tests
+;; Sets the C flag for unsigned overflow tests provided 0 <= R26 < 128
DEFUN __adddi3_s8
clr TT
sbrc r26, 7
@@ -1714,6 +1728,8 @@ ENDF __adddi3_s8
;; (set (reg:DI 18)
;; (minus:DI (reg:DI 18)
;; (reg:DI 10)))
+;; Sets the V flag for signed overflow tests
+;; Sets the C flag for unsigned overflow tests
DEFUN __subdi3
SUB A0,B0 $ sbc A1,B1 $ sbc A2,B2 $ sbc A3,B3
sbc A4,B4 $ sbc A5,B5 $ sbc A6,B6 $ sbc A7,B7
@@ -1747,6 +1763,9 @@ ENDF __cmpdi2_s8
#endif /* L_cmpdi2_s8 */
#if defined (L_negdi2)
+;; (set (reg:DI 18)
+;; (neg:DI (reg:DI 18)))
+;; Sets the V flag for signed overflow tests
DEFUN __negdi2
com A4 $ com A5 $ com A6 $ com A7
diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr
index 749613376b3..d1f55e408d3 100644
--- a/libgcc/config/avr/t-avr
+++ b/libgcc/config/avr/t-avr
@@ -20,7 +20,7 @@ LIB1ASMFUNCS = \
_divdi3 _udivdi3 \
_muldi3 \
_udivmod64 \
- _negdi2 \
+ _negsi2 _negdi2 \
_prologue \
_epilogue \
_exit \
@@ -72,7 +72,12 @@ LIB1ASMFUNCS += \
_divqq3 _udivuqq3 \
_divhq3 _udivuhq3 \
_divha3 _udivuha3 \
- _divsa3 _udivusa3
+ _divsa3 _udivusa3 \
+ _clr_8 \
+ _ssneg_2 _ssneg_4 _ssneg_8 \
+ _ssabs_2 _ssabs_4 _ssabs_8 \
+ _ssadd_8 _sssub_8 \
+ _usadd_8 _ussub_8
LIB2FUNCS_EXCLUDE = \
_moddi3 _umoddi3 \
@@ -103,6 +108,7 @@ endif
# Filter out supported conversions from fixed-bit.c
+# Also filter out TQ and UTQ.
conv_XY=$(conv)$(mode1)$(mode2)
func_X=$(func)$(mode)
@@ -141,8 +147,20 @@ allfix_modes = QQ UQQ HQ UHQ HA UHA SQ USQ SA USA DA UDA DQ UDQ TQ UTQ TA UTA
LIB2FUNCS_EXCLUDE += \
$(foreach func,_add _sub,\
- $(foreach mode,$(allfix_modes),$(func_X)3))
+ $(foreach mode,$(allfix_modes),$(func_X)))
LIB2FUNCS_EXCLUDE += \
$(foreach func,_lshr _ashl _ashr _cmp,\
$(foreach mode,$(allfix_modes),$(func_X)))
+
+
+usat_modes = UQQ UHQ UHA USQ USA UDQ UDA UTQ UTA
+ssat_modes = QQ HQ HA SQ SA DQ DA TQ TA
+
+LIB2FUNCS_EXCLUDE += \
+ $(foreach func,_ssadd _sssub _ssneg _ssabs,\
+ $(foreach mode,$(ssat_modes),$(func_X)))
+
+LIB2FUNCS_EXCLUDE += \
+ $(foreach func,_usadd _ussub _usneg,\
+ $(foreach mode,$(usat_modes),$(func_X)))