diff options
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/avr/avr.md | 270 | ||||
-rw-r--r-- | gcc/config/avr/libgcc.S | 47 |
2 files changed, 298 insertions, 19 deletions
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 250133e..66c3db2 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -55,6 +55,7 @@ UNSPEC_FMUL UNSPEC_FMULS UNSPEC_FMULSU + UNSPEC_COPYSIGN ]) (define_c_enum "unspecv" @@ -3680,6 +3681,275 @@ [(set_attr "length" "9") (set_attr "cc" "clobber")]) + +;; Parity + +(define_expand "parityhi2" + [(set (reg:HI 24) + (match_operand:HI 1 "register_operand" "")) + (set (reg:HI 24) + (parity:HI (reg:HI 24))) + (set (match_operand:HI 0 "register_operand" "") + (reg:HI 24))] + "" + "") + +(define_expand "paritysi2" + [(set (reg:SI 22) + (match_operand:SI 1 "register_operand" "")) + (set (reg:HI 24) + (parity:HI (reg:SI 22))) + (set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (reg:HI 24)))] + "" + "") + +(define_insn "*parityhi2.libgcc" + [(set (reg:HI 24) + (parity:HI (reg:HI 24)))] + "" + "%~call __parityhi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +(define_insn "*parityqihi2.libgcc" + [(set (reg:HI 24) + (parity:HI (reg:QI 24)))] + "" + "%~call __parityqi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +(define_insn "*paritysihi2.libgcc" + [(set (reg:HI 24) + (parity:HI (reg:SI 22)))] + "" + "%~call __paritysi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + + +;; Popcount + +(define_expand "popcounthi2" + [(set (reg:HI 24) + (match_operand:HI 1 "register_operand" "")) + (set (reg:HI 24) + (popcount:HI (reg:HI 24))) + (set (match_operand:HI 0 "register_operand" "") + (reg:HI 24))] + "" + "") + +(define_expand "popcountsi2" + [(set (reg:SI 22) + (match_operand:SI 1 "register_operand" "")) + (set (reg:HI 24) + (popcount:HI (reg:SI 22))) + (set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (reg:HI 24)))] + "" + "") + +(define_insn "*popcounthi2.libgcc" + [(set (reg:HI 24) + (popcount:HI (reg:HI 24)))] + "" + "%~call __popcounthi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +(define_insn "*popcountsi2.libgcc" + [(set (reg:HI 24) + (popcount:HI (reg:SI 22)))] + "" + "%~call __popcountsi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +(define_insn "*popcountqi2.libgcc" + [(set (reg:QI 24) + (popcount:QI (reg:QI 24)))] + "" + "%~call __popcountqi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +(define_insn_and_split "*popcountqihi2.libgcc" + [(set (reg:HI 24) + (popcount:HI (reg:QI 24)))] + "" + "#" + "" + [(set (reg:QI 24) + (popcount:QI (reg:QI 24))) + (set (reg:QI 25) + (const_int 0))] + "") + +;; Count Leading Zeros + +(define_expand "clzhi2" + [(set (reg:HI 24) + (match_operand:HI 1 "register_operand" "")) + (parallel [(set (reg:HI 24) + (clz:HI (reg:HI 24))) + (clobber (reg:QI 26))]) + (set (match_operand:HI 0 "register_operand" "") + (reg:HI 24))] + "" + "") + +(define_expand "clzsi2" + [(set (reg:SI 22) + (match_operand:SI 1 "register_operand" "")) + (parallel [(set (reg:HI 24) + (clz:HI (reg:SI 22))) + (clobber (reg:QI 26))]) + (set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (reg:HI 24)))] + "" + "") + +(define_insn "*clzhi2.libgcc" + [(parallel [(set (reg:HI 24) + (clz:HI (reg:HI 24))) + (clobber (reg:QI 26))])] + "" + "%~call __clzhi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +(define_insn "*clzsihi2.libgcc" + [(parallel [(set (reg:HI 24) + (clz:HI (reg:SI 22))) + (clobber (reg:QI 26))])] + "" + "%~call __clzsi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +;; Count Trailing Zeros + +(define_expand "ctzhi2" + [(set (reg:HI 24) + (match_operand:HI 1 "register_operand" "")) + (parallel [(set (reg:HI 24) + (ctz:HI (reg:HI 24))) + (clobber (reg:QI 26))]) + (set (match_operand:HI 0 "register_operand" "") + (reg:HI 24))] + "" + "") + +(define_expand "ctzsi2" + [(set (reg:SI 22) + (match_operand:SI 1 "register_operand" "")) + (parallel [(set (reg:HI 24) + (ctz:HI (reg:SI 22))) + (clobber (reg:QI 22)) + (clobber (reg:QI 26))]) + (set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (reg:HI 24)))] + "" + "") + +(define_insn "*ctzhi2.libgcc" + [(set (reg:HI 24) + (ctz:HI (reg:HI 24))) + (clobber (reg:QI 26))] + "" + "%~call __ctzhi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +(define_insn "*ctzsihi2.libgcc" + [(set (reg:HI 24) + (ctz:HI (reg:SI 22))) + (clobber (reg:QI 22)) + (clobber (reg:QI 26))] + "" + "%~call __ctzsi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +;; Find First Set + +(define_expand "ffshi2" + [(set (reg:HI 24) + (match_operand:HI 1 "register_operand" "")) + (parallel [(set (reg:HI 24) + (ffs:HI (reg:HI 24))) + (clobber (reg:QI 26))]) + (set (match_operand:HI 0 "register_operand" "") + (reg:HI 24))] + "" + "") + +(define_expand "ffssi2" + [(set (reg:SI 22) + (match_operand:SI 1 "register_operand" "")) + (parallel [(set (reg:HI 24) + (ffs:HI (reg:SI 22))) + (clobber (reg:QI 22)) + (clobber (reg:QI 26))]) + (set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (reg:HI 24)))] + "" + "") + +(define_insn "*ffshi2.libgcc" + [(parallel [(set (reg:HI 24) + (ffs:HI (reg:HI 24))) + (clobber (reg:QI 26))])] + "" + "%~call __ffshi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +(define_insn "*ffssihi2.libgcc" + [(parallel [(set (reg:HI 24) + (ffs:HI (reg:SI 22))) + (clobber (reg:QI 22)) + (clobber (reg:QI 26))])] + "" + "%~call __ffssi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +;; Copysign + +(define_insn "copysignsf3" + [(set (match_operand:SF 0 "register_operand" "=r") + (unspec:SF [(match_operand:SF 1 "register_operand" "0") + (match_operand:SF 2 "register_operand" "r")] + UNSPEC_COPYSIGN))] + "" + "bst %D2,7\;bld %D0,7" + [(set_attr "length" "2") + (set_attr "cc" "none")]) + +;; Swap Bytes (change byte-endianess) + +(define_expand "bswapsi2" + [(set (reg:SI 22) + (match_operand:SI 1 "register_operand" "")) + (set (reg:SI 22) + (bswap:SI (reg:SI 22))) + (set (match_operand:SI 0 "register_operand" "") + (reg:SI 22))] + "" + "") + +(define_insn "*bswapsi2.libgcc" + [(set (reg:SI 22) + (bswap:SI (reg:SI 22)))] + "" + "%~call __bswapsi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + + ;; CPU instructions ;; NOP taking 1 or 2 Ticks diff --git a/gcc/config/avr/libgcc.S b/gcc/config/avr/libgcc.S index c2459d0..7f3feeb 100644 --- a/gcc/config/avr/libgcc.S +++ b/gcc/config/avr/libgcc.S @@ -1061,9 +1061,15 @@ ENDF __ffssi2 ;; clobbers: r26 DEFUN __ffshi2 clr r26 +#ifdef __AVR_HAVE_JMP_CALL__ + ;; Some cores have problem skipping 2-word instruction + tst r24 + breq 2f +#else cpse r24, __zero_reg__ +#endif /* __AVR_HAVE_JMP_CALL__ */ 1: XJMP __loop_ffsqi2 - ldi r26, 8 +2: ldi r26, 8 or r24, r25 brne 1b ret @@ -1093,12 +1099,12 @@ ENDF __loop_ffsqi2 #if defined (L_ctzsi2) ;; count trailing zeros ;; r25:r24 = ctz32 (r25:r22) -;; ctz(0) = 32 +;; clobbers: r26, r22 +;; ctz(0) = 255 +;; Note that ctz(0) in undefined for GCC DEFUN __ctzsi2 XCALL __ffssi2 dec r24 - sbrc r24, 7 - ldi r24, 32 ret ENDF __ctzsi2 #endif /* defined (L_ctzsi2) */ @@ -1106,12 +1112,12 @@ ENDF __ctzsi2 #if defined (L_ctzhi2) ;; count trailing zeros ;; r25:r24 = ctz16 (r25:r24) -;; ctz(0) = 16 +;; clobbers: r26 +;; ctz(0) = 255 +;; Note that ctz(0) in undefined for GCC DEFUN __ctzhi2 XCALL __ffshi2 dec r24 - sbrc r24, 7 - ldi r24, 16 ret ENDF __ctzhi2 #endif /* defined (L_ctzhi2) */ @@ -1245,47 +1251,50 @@ ENDF __parityqi2 #if defined (L_popcounthi2) ;; population count ;; r25:r24 = popcount16 (r25:r24) -;; clobbers: r30, __tmp_reg__ +;; clobbers: __tmp_reg__ DEFUN __popcounthi2 XCALL __popcountqi2 - mov r30, r24 + push r24 mov r24, r25 XCALL __popcountqi2 - add r24, r30 clr r25 - ret + ;; FALLTHRU ENDF __popcounthi2 + +DEFUN __popcounthi2_tail + pop __tmp_reg__ + add r24, __tmp_reg__ + ret +ENDF __popcounthi2_tail #endif /* defined (L_popcounthi2) */ #if defined (L_popcountsi2) ;; population count ;; r25:r24 = popcount32 (r25:r22) -;; clobbers: r26, r30, __tmp_reg__ +;; clobbers: __tmp_reg__ DEFUN __popcountsi2 XCALL __popcounthi2 - mov r26, r24 + push r24 mov_l r24, r22 mov_h r25, r23 XCALL __popcounthi2 - add r24, r26 - ret + XJMP __popcounthi2_tail ENDF __popcountsi2 #endif /* defined (L_popcountsi2) */ #if defined (L_popcountdi2) ;; population count ;; r25:r24 = popcount64 (r25:r18) -;; clobbers: r22, r23, r26, r27, r30, __tmp_reg__ +;; clobbers: r22, r23, __tmp_reg__ DEFUN __popcountdi2 XCALL __popcountsi2 - mov r27, r24 + push r24 mov_l r22, r18 mov_h r23, r19 mov_l r24, r20 mov_h r25, r21 XCALL __popcountsi2 - add r24, r27 - ret + XJMP __popcounthi2_tail ENDF __popcountdi2 #endif /* defined (L_popcountdi2) */ |