diff options
author | Georg-Johann Lay <avr@gjlay.de> | 2013-02-08 10:13:37 +0000 |
---|---|---|
committer | Georg-Johann Lay <gjl@gcc.gnu.org> | 2013-02-08 10:13:37 +0000 |
commit | 85d768f349087f3766ff84054ec7b3403c52ac7a (patch) | |
tree | c41ab849c5ffa4c56a753d5d4502a23fdc14617d /libgcc/config/avr | |
parent | 661bc682bcb87f5faa709f9bcd1679874f6652f6 (diff) | |
download | gcc-85d768f349087f3766ff84054ec7b3403c52ac7a.zip gcc-85d768f349087f3766ff84054ec7b3403c52ac7a.tar.gz gcc-85d768f349087f3766ff84054ec7b3403c52ac7a.tar.bz2 |
re PR target/54222 ([avr] Implement fixed-point support)
gcc/
PR target/54222
* config/avr/avr.md (unspec) <UNSPEC_ROUND>: Add.
* config/avr/avr-fixed.md (ALL4QA, ALL124QA): New mode iterators.
(round<mode>3, round<mode>3_const): New expanders for fixed-mode.
(*round<mode>3.libgcc): New insns for fixed-modes.
* config/avr/builtins.def (ABSxx): Use a non-NULL LIBNAME.
(ROUNDxx, COUNTLSxx, BITSxx, xxBITS): New DEF_BUILTINs.
(ROUNDFX, COUNTLSFX, ABSFX): New DEF_BUILTINs.
* config/avr/stdfix.h (absFX, bitsFX, FXbits): Remove inline
implementations. Define to __builtin_avr_absFX,
__builtin_avr_bitsFX, __builtin_avr_FXbits, respectively.
(roundFX, countlsFX): Define to __builtin_avr_roundFX,
__builtin_avr_countlsFX, respectively.
* config/avr/avr-c.c (target.h): Include it.
(enum avr_builtin_id): New enum.
(avr_resolve_overloaded_builtin): New static function.
(avr_register_target_pragmas): Use it to set
targetm.resolve_overloaded_builtin.
* config/avr/avr.c (avr_init_builtins): Supply myriads of local
tree nodes used by DEF_BUILTIN.
(avr_expand_builtin) <AVR_BUILTIN_ROUNDxx>: Sanity-check them.
(avr_fold_builtin) <AVR_BUILTIN_BITSxx>: Fold to VIEW_COVERT_EXPR.
<AVR_BUILTIN_xxBITS>: Same.
libgcc/
PR target/54222
* config/avr/lib2funcs.c: New C sources for modules for libgcc.a.
* config/avr/lib2-object.mk: New iterator to build objects from it.
* config/avr/t-avr: Iterate lib2-object.mk to build objects from
lib2funcs.c.
(LIB2FUNCS_EXCLUDE): Add _clrsbdi2.
(LIB1ASMFUNCS): Add: _ssabs_1, _mask1, _ret, _roundqq3, _rounduqq3,
_round_s2, _round_u2, _round_2_const, _addmask_2, _round_s4,
_round_u4, _round_4_const, _addmask_4, _round_x8, _rounddq3
_roundudq3, _roundda3 _rounduda3, _roundta3 _rounduta3.
* config/avr/lib1funcs-fixed.S: Implement them.
gcc/testsuite/
PR target/54222
* gcc.target/avr/torture/builtins-4-roundfx.c: New test.
* gcc.target/avr/torture/builtins-5-countlsfx.c: New test.
From-SVN: r195878
Diffstat (limited to 'libgcc/config/avr')
-rw-r--r-- | libgcc/config/avr/lib1funcs-fixed.S | 528 | ||||
-rw-r--r-- | libgcc/config/avr/lib1funcs.S | 4 | ||||
-rw-r--r-- | libgcc/config/avr/lib2-object.mk | 23 | ||||
-rw-r--r-- | libgcc/config/avr/lib2funcs.c | 226 | ||||
-rw-r--r-- | libgcc/config/avr/t-avr | 94 |
5 files changed, 867 insertions, 8 deletions
diff --git a/libgcc/config/avr/lib1funcs-fixed.S b/libgcc/config/avr/lib1funcs-fixed.S index 731da44..92d8eaf 100644 --- a/libgcc/config/avr/lib1funcs-fixed.S +++ b/libgcc/config/avr/lib1funcs-fixed.S @@ -959,6 +959,28 @@ ENDF __udivusa3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Saturation, 1 Byte +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; First Argument and Return Register +#define A0 24 + +#if defined (L_ssabs_1) +DEFUN __ssabs_1 + sbrs A0, 7 + ret + neg A0 + sbrc A0,7 + dec A0 + ret +ENDF __ssabs_1 +#endif /* L_ssabs_1 */ + +#undef A0 + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Saturation, 2 Bytes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1176,3 +1198,509 @@ ENDF __sssub_8 #undef B5 #undef B6 #undef B7 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Rounding Helpers +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +#ifdef L_mask1 + +#define AA 24 +#define CC 25 + +;; R25 = 1 << (R24 & 7) +;; CC = 1 << (AA & 7) +;; Clobbers: None +DEFUN __mask1 + ;; CC = 2 ^ AA.1 + ldi CC, 1 << 2 + sbrs AA, 1 + ldi CC, 1 << 0 + ;; CC *= 2 ^ AA.0 + sbrc AA, 0 + lsl CC + ;; CC *= 2 ^ AA.2 + sbrc AA, 2 + swap CC + ret +ENDF __mask1 + +#undef AA +#undef CC +#endif /* L_mask1 */ + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; The rounding point. Any bits smaller than +;; 2^{-RP} will be cleared. +#define RP R24 + +#define A0 22 +#define A1 A0 + 1 + +#define C0 24 +#define C1 C0 + 1 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Rounding, 1 Byte +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +#ifdef L_roundqq3 + +;; R24 = round (R22, R24) +;; Clobbers: R22, __tmp_reg__ +DEFUN __roundqq3 + mov __tmp_reg__, C1 + subi RP, __QQ_FBIT__ - 1 + neg RP + ;; R25 = 1 << RP (Total offset is FBIT-1 - RP) + XCALL __mask1 + mov C0, C1 + ;; Add-Saturate 2^{-RP-1} + add A0, C0 + brvc 0f + ldi A0, 0x7f +0: ;; Mask out bits beyond RP + lsl C0 + neg C0 + and C0, A0 + mov C1, __tmp_reg__ + ret +ENDF __roundqq3 +#endif /* L_roundqq3 */ + +#ifdef L_rounduqq3 + +;; R24 = round (R22, R24) +;; Clobbers: R22, __tmp_reg__ +DEFUN __rounduqq3 + mov __tmp_reg__, C1 + subi RP, __UQQ_FBIT__ - 1 + neg RP + ;; R25 = 1 << RP (Total offset is FBIT-1 - RP) + XCALL __mask1 + mov C0, C1 + ;; Add-Saturate 2^{-RP-1} + add A0, C0 + brcc 0f + ldi A0, 0xff +0: ;; Mask out bits beyond RP + lsl C0 + neg C0 + and C0, A0 + mov C1, __tmp_reg__ + ret +ENDF __rounduqq3 +#endif /* L_rounduqq3 */ + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Rounding, 2 Bytes +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +#ifdef L_addmask_2 + +;; [ R25:R24 = 1 << (R24 & 15) +;; R23:R22 += 1 << (R24 & 15) ] +;; SREG is set according to the addition +DEFUN __addmask_2 + ;; R25 = 1 << (R24 & 7) + XCALL __mask1 + cpi RP, 1 << 3 + sbc C0, C0 + ;; Swap C0 and C1 if RP.3 was set + and C0, C1 + eor C1, C0 + ;; Finally, add the power-of-two: A[] += C[] + add A0, C0 + adc A1, C1 + ret +ENDF __addmask_2 +#endif /* L_addmask_2 */ + +#ifdef L_round_s2 + +;; R25:R24 = round (R23:R22, R24) +;; Clobbers: R23, R22 +DEFUN __roundhq3 + subi RP, __HQ_FBIT__ - __HA_FBIT__ +ENDF __roundhq3 +DEFUN __roundha3 + subi RP, __HA_FBIT__ - 1 + neg RP + ;; [ R25:R24 = 1 << (FBIT-1 - RP) + ;; R23:R22 += 1 << (FBIT-1 - RP) ] + XCALL __addmask_2 + XJMP __round_s2_const +ENDF __roundha3 + +#endif /* L_round_s2 */ + +#ifdef L_round_u2 + +;; R25:R24 = round (R23:R22, R24) +;; Clobbers: R23, R22 +DEFUN __rounduhq3 + subi RP, __UHQ_FBIT__ - __UHA_FBIT__ +ENDF __rounduhq3 +DEFUN __rounduha3 + subi RP, __UHA_FBIT__ - 1 + neg RP + ;; [ R25:R24 = 1 << (FBIT-1 - RP) + ;; R23:R22 += 1 << (FBIT-1 - RP) ] + XCALL __addmask_2 + XJMP __round_u2_const +ENDF __rounduha3 + +#endif /* L_round_u2 */ + + +#ifdef L_round_2_const + +;; Helpers for 2 byte wide rounding + +DEFUN __round_s2_const + brvc 2f + ldi A1, 0x7f + rjmp 1f + ;; FALLTHRU (Barrier) +ENDF __round_s2_const + +DEFUN __round_u2_const + brcc 2f + ldi A1, 0xff +1: + ldi A0, 0xff +2: + ;; Saturation is performed now. + ;; Currently, we have C[] = 2^{-RP-1} + ;; C[] = 2^{-RP} + lsl C0 + rol C1 + ;; + NEG2 C0 + ;; Clear the bits beyond the rounding point. + and C0, A0 + and C1, A1 + ret +ENDF __round_u2_const + +#endif /* L_round_2_const */ + +#undef A0 +#undef A1 +#undef C0 +#undef C1 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Rounding, 4 Bytes +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +#define A0 18 +#define A1 A0 + 1 +#define A2 A0 + 2 +#define A3 A0 + 3 + +#define C0 22 +#define C1 C0 + 1 +#define C2 C0 + 2 +#define C3 C0 + 3 + +#ifdef L_addmask_4 + +;; [ R25:R22 = 1 << (R24 & 31) +;; R21:R18 += 1 << (R24 & 31) ] +;; SREG is set according to the addition +DEFUN __addmask_4 + ;; R25 = 1 << (R24 & 7) + XCALL __mask1 + cpi RP, 1 << 4 + sbc C0, C0 + sbc C1, C1 + ;; Swap C2 with C3 if RP.3 is not set + cpi RP, 1 << 3 + sbc C2, C2 + and C2, C3 + eor C3, C2 + ;; Swap C3:C2 with C1:C0 if RP.4 is not set + and C0, C2 $ eor C2, C0 + and C1, C3 $ eor C3, C1 + ;; Finally, add the power-of-two: A[] += C[] + add A0, C0 + adc A1, C1 + adc A2, C2 + adc A3, C3 + ret +ENDF __addmask_4 +#endif /* L_addmask_4 */ + +#ifdef L_round_s4 + +;; R25:R22 = round (R21:R18, R24) +;; Clobbers: R18...R21 +DEFUN __roundsq3 + subi RP, __SQ_FBIT__ - __SA_FBIT__ +ENDF __roundsq3 +DEFUN __roundsa3 + subi RP, __SA_FBIT__ - 1 + neg RP + ;; [ R25:R22 = 1 << (FBIT-1 - RP) + ;; R21:R18 += 1 << (FBIT-1 - RP) ] + XCALL __addmask_4 + XJMP __round_s4_const +ENDF __roundsa3 + +#endif /* L_round_s4 */ + +#ifdef L_round_u4 + +;; R25:R22 = round (R21:R18, R24) +;; Clobbers: R18...R21 +DEFUN __roundusq3 + subi RP, __USQ_FBIT__ - __USA_FBIT__ +ENDF __roundusq3 +DEFUN __roundusa3 + subi RP, __USA_FBIT__ - 1 + neg RP + ;; [ R25:R22 = 1 << (FBIT-1 - RP) + ;; R21:R18 += 1 << (FBIT-1 - RP) ] + XCALL __addmask_4 + XJMP __round_u4_const +ENDF __roundusa3 + +#endif /* L_round_u4 */ + + +#ifdef L_round_4_const + +;; Helpers for 4 byte wide rounding + +DEFUN __round_s4_const + brvc 2f + ldi A3, 0x7f + rjmp 1f + ;; FALLTHRU (Barrier) +ENDF __round_s4_const + +DEFUN __round_u4_const + brcc 2f + ldi A3, 0xff +1: + ldi A2, 0xff + ldi A1, 0xff + ldi A0, 0xff +2: + ;; Saturation is performed now. + ;; Currently, we have C[] = 2^{-RP-1} + ;; C[] = 2^{-RP} + lsl C0 + rol C1 + rol C2 + rol C3 + XCALL __negsi2 + ;; Clear the bits beyond the rounding point. + and C0, A0 + and C1, A1 + and C2, A2 + and C3, A3 + ret +ENDF __round_u4_const + +#endif /* L_round_4_const */ + +#undef A0 +#undef A1 +#undef A2 +#undef A3 +#undef C0 +#undef C1 +#undef C2 +#undef C3 + +#undef RP + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Rounding, 8 Bytes +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +#define RP 16 +#define FBITm1 31 + +#define C0 18 +#define C1 C0 + 1 +#define C2 C0 + 2 +#define C3 C0 + 3 +#define C4 C0 + 4 +#define C5 C0 + 5 +#define C6 C0 + 6 +#define C7 C0 + 7 + +#define A0 16 +#define A1 17 +#define A2 26 +#define A3 27 +#define A4 28 +#define A5 29 +#define A6 30 +#define A7 31 + + +#ifdef L_rounddq3 +;; R25:R18 = round (R25:R18, R16) +;; Clobbers: ABI +DEFUN __rounddq3 + ldi FBITm1, __DQ_FBIT__ - 1 + clt + XJMP __round_x8 +ENDF __rounddq3 +#endif /* L_rounddq3 */ + +#ifdef L_roundudq3 +;; R25:R18 = round (R25:R18, R16) +;; Clobbers: ABI +DEFUN __roundudq3 + ldi FBITm1, __UDQ_FBIT__ - 1 + set + XJMP __round_x8 +ENDF __roundudq3 +#endif /* L_roundudq3 */ + +#ifdef L_roundda3 +;; R25:R18 = round (R25:R18, R16) +;; Clobbers: ABI +DEFUN __roundda3 + ldi FBITm1, __DA_FBIT__ - 1 + clt + XJMP __round_x8 +ENDF __roundda3 +#endif /* L_roundda3 */ + +#ifdef L_rounduda3 +;; R25:R18 = round (R25:R18, R16) +;; Clobbers: ABI +DEFUN __rounduda3 + ldi FBITm1, __UDA_FBIT__ - 1 + set + XJMP __round_x8 +ENDF __rounduda3 +#endif /* L_rounduda3 */ + +#ifdef L_roundta3 +;; R25:R18 = round (R25:R18, R16) +;; Clobbers: ABI +DEFUN __roundta3 + ldi FBITm1, __TA_FBIT__ - 1 + clt + XJMP __round_x8 +ENDF __roundta3 +#endif /* L_roundta3 */ + +#ifdef L_rounduta3 +;; R25:R18 = round (R25:R18, R16) +;; Clobbers: ABI +DEFUN __rounduta3 + ldi FBITm1, __UTA_FBIT__ - 1 + set + XJMP __round_x8 +ENDF __rounduta3 +#endif /* L_rounduta3 */ + + +#ifdef L_round_x8 +DEFUN __round_x8 + push r16 + push r17 + push r28 + push r29 + ;; Compute log2 of addend from rounding point + sub RP, FBITm1 + neg RP + ;; Move input to work register A[] + push C0 + mov A1, C1 + wmov A2, C2 + wmov A4, C4 + wmov A6, C6 + ;; C[] = 1 << (FBIT-1 - RP) + XCALL __clr_8 + inc C0 + XCALL __ashldi3 + pop A0 + ;; A[] += C[] + add A0, C0 + adc A1, C1 + adc A2, C2 + adc A3, C3 + adc A4, C4 + adc A5, C5 + adc A6, C6 + adc A7, C7 + brts 1f + ;; Signed + brvc 3f + ;; Signed overflow: A[] = 0x7f... + brvs 2f +1: ;; Unsigned + brcc 3f + ;; Unsigned overflow: A[] = 0xff... +2: ldi A7, 0xff + ldi A6, 0xff + wmov A0, A6 + wmov A2, A6 + wmov A4, A6 + bld A7, 7 +3: + ;; C[] = -C[] - C[] + push A0 + ldi r16, 1 + XCALL __ashldi3 + pop A0 + XCALL __negdi2 + ;; Clear the bits beyond the rounding point. + and C0, A0 + and C1, A1 + and C2, A2 + and C3, A3 + and C4, A4 + and C5, A5 + and C6, A6 + and C7, A7 + ;; Epilogue + pop r29 + pop r28 + pop r17 + pop r16 + ret +ENDF __round_x8 + +#endif /* L_round_x8 */ + +#undef A0 +#undef A1 +#undef A2 +#undef A3 +#undef A4 +#undef A5 +#undef A6 +#undef A7 + +#undef C0 +#undef C1 +#undef C2 +#undef C3 +#undef C4 +#undef C5 +#undef C6 +#undef C7 + +#undef RP +#undef FBITm1 + + +;; Supply implementations / symbols for the bit-banging functions +;; __builtin_avr_bitsfx and __builtin_avr_fxbits +#ifdef L_ret +DEFUN __ret + ret +ENDF __ret +#endif /* L_ret */ diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S index 9ca83a8..0a406d5 100644 --- a/libgcc/config/avr/lib1funcs.S +++ b/libgcc/config/avr/lib1funcs.S @@ -1684,12 +1684,12 @@ DEFUN __divdi3_moddi3 ENDF __divdi3_moddi3 +#endif /* L_divdi3 */ + #undef R_cnt #undef SS #undef NN -#endif /* L_divdi3 */ - .section .text.libgcc, "ax", @progbits #define TT __tmp_reg__ diff --git a/libgcc/config/avr/lib2-object.mk b/libgcc/config/avr/lib2-object.mk new file mode 100644 index 0000000..6a9e04d --- /dev/null +++ b/libgcc/config/avr/lib2-object.mk @@ -0,0 +1,23 @@ +# This file is included several times in a row, once for each element of +# $(iter-items). On each inclusion, we advance $o to the next element. +# $(iter-labels) and $(iter-flags) are also advanced. +# This works similar to $(srcdir)/siditi-object.mk. + +o := $(firstword $(iter-items)) +iter-items := $(filter-out $o,$(iter-items)) + +$o-label := $(firstword $(iter-labels)) +iter-labels := $(wordlist 2,$(words $(iter-labels)),$(iter-labels)) + +$o-flag := $(firstword $(iter-flags)) +iter-flags := $(wordlist 2,$(words $(iter-flags)),$(iter-flags)) + +$o$(objext): %$(objext): $(srcdir)/config/avr/lib2funcs.c + $(gcc_compile) -DL_$($*-label) -DL_LABEL=$($*-label) $($*-flag) \ + -c $< $(vis_hide) + +ifeq ($(enable_shared),yes) +$(o)_s$(objext): %_s$(objext): $(srcdir)/config/avr/lib2funcs.c + $(gcc_s_compile) -DL_$($*-label) -DL_LABEL=$($*-label) $($*-flag) \ + -c $< +endif diff --git a/libgcc/config/avr/lib2funcs.c b/libgcc/config/avr/lib2funcs.c new file mode 100644 index 0000000..83f2e23 --- /dev/null +++ b/libgcc/config/avr/lib2funcs.c @@ -0,0 +1,226 @@ +/* Copyright (C) 2013 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3, or (at your option) any later + version. + + GCC is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + + +/* This file supplies implementations for some AVR-specific builtin + functions so that code like the following works as expected: + + int (*f (void))(_Fract) + { + return __builtin_avr_countlsr; + } + + In this specific case, the generated code is: + + f: + ldi r24,lo8(gs(__countlsHI)) + ldi r25,hi8(gs(__countlsHI)) + ret +*/ + +/* Map fixed-point suffix to the corresponding fixed-point type. */ + +typedef short _Fract fx_hr_t; +typedef _Fract fx_r_t; +typedef long _Fract fx_lr_t; +typedef long long _Fract fx_llr_t; + +typedef unsigned short _Fract fx_uhr_t; +typedef unsigned _Fract fx_ur_t; +typedef unsigned long _Fract fx_ulr_t; +typedef unsigned long long _Fract fx_ullr_t; + +typedef short _Accum fx_hk_t; +typedef _Accum fx_k_t; +typedef long _Accum fx_lk_t; +typedef long long _Accum fx_llk_t; + +typedef unsigned short _Accum fx_uhk_t; +typedef unsigned _Accum fx_uk_t; +typedef unsigned long _Accum fx_ulk_t; +typedef unsigned long long _Accum fx_ullk_t; + +/* Map fixed-point suffix to the corresponding natural integer type. */ + +typedef char int_hr_t; +typedef int int_r_t; +typedef long int_lr_t; +typedef long long int_llr_t; + +typedef unsigned char int_uhr_t; +typedef unsigned int int_ur_t; +typedef unsigned long int_ulr_t; +typedef unsigned long long int_ullr_t; + +typedef int int_hk_t; +typedef long int_k_t; +typedef long long int_lk_t; +typedef long long int_llk_t; + +typedef unsigned int int_uhk_t; +typedef unsigned long int_uk_t; +typedef unsigned long long int_ulk_t; +typedef unsigned long long int_ullk_t; + +/* Map mode to the corresponding integer type. */ + +typedef char int_qi_t; +typedef int int_hi_t; +typedef long int_si_t; +typedef long long int_di_t; + +typedef unsigned char uint_qi_t; +typedef unsigned int uint_hi_t; +typedef unsigned long uint_si_t; +typedef unsigned long long uint_di_t; + + + +/************************************************************************/ + +/* Supply implementations / symbols for __builtin_roundFX ASM_NAME. */ + +#ifdef L_round + +#define ROUND1(FX) \ + ROUND2 (FX) + +#define ROUND2(FX) \ + extern fx_## FX ##_t __round## FX (fx_## FX ##_t x, int rpoint); \ + \ + fx_## FX ##_t \ + __round## FX (fx_## FX ##_t x, int rpoint) \ + { \ + return __builtin_avr_round ##FX (x, rpoint); \ + } + +ROUND1(L_LABEL) + +#endif /* L_round */ + + + +/*********************************************************************/ + +/* Implement some count-leading-redundant-sign-bits to be used with + coundlsFX implementation. */ + +#ifdef L__clrsbqi +extern int __clrsbqi2 (char x); + +int +__clrsbqi2 (char x) +{ + int ret; + + if (x < 0) + x = ~x; + + if (x == 0) + return 8 * sizeof (x) -1; + + ret = __builtin_clz (x << 8); + return ret - 1; +} +#endif /* L__clrsbqi */ + + +#ifdef L__clrsbdi +extern int __clrsbdi2 (long long x); + +int +__clrsbdi2 (long long x) +{ + int ret; + + if (x < 0LL) + x = ~x; + + if (x == 0LL) + return 8 * sizeof (x) -1; + + ret = __builtin_clzll ((unsigned long long) x); + return ret - 1; +} +#endif /* L__clrsbdi */ + + + +/*********************************************************************/ + +/* Supply implementations / symbols for __builtin_avr_countlsFX. */ + +/* Signed */ + +#ifdef L_countls + +#define COUNTLS1(MM) \ + COUNTLS2 (MM) + +#define COUNTLS2(MM) \ + extern int __countls## MM ##2 (int_## MM ##_t); \ + extern int __clrsb## MM ##2 (int_## MM ##_t); \ + \ + int \ + __countls## MM ##2 (int_## MM ##_t x) \ + { \ + if (x == 0) \ + return __INT8_MAX__; \ + \ + return __clrsb## MM ##2 (x); \ + } + +COUNTLS1(L_LABEL) + +#endif /* L_countls */ + +/* Unsigned */ + +#ifdef L_countlsu + +#define clz_qi2 __builtin_clz /* unused, avoid warning */ +#define clz_hi2 __builtin_clz +#define clz_si2 __builtin_clzl +#define clz_di2 __builtin_clzll + +#define COUNTLS1(MM) \ + COUNTLS2 (MM) + +#define COUNTLS2(MM) \ + extern int __countlsu## MM ##2 (uint_## MM ##_t); \ + \ + int \ + __countlsu## MM ##2 (uint_## MM ##_t x) \ + { \ + if (x == 0) \ + return __INT8_MAX__; \ + \ + if (sizeof (x) == 1) \ + return clz_hi2 (x << 8); \ + else \ + return clz_## MM ##2 (x); \ + } + +COUNTLS1(L_LABEL) + +#endif /* L_countlsu */ diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr index 3bc0718..a4b8113e 100644 --- a/libgcc/config/avr/t-avr +++ b/libgcc/config/avr/t-avr @@ -75,13 +75,24 @@ LIB1ASMFUNCS += \ _divsa3 _udivusa3 \ _clr_8 \ _ssneg_2 _ssneg_4 _ssneg_8 \ - _ssabs_2 _ssabs_4 _ssabs_8 \ + _ssabs_1 _ssabs_2 _ssabs_4 _ssabs_8 \ _ssadd_8 _sssub_8 \ - _usadd_8 _ussub_8 + _usadd_8 _ussub_8 \ + _mask1 _ret \ + _roundqq3 _rounduqq3 \ + _round_s2 _round_u2 _round_2_const _addmask_2 \ + _round_s4 _round_u4 _round_4_const _addmask_4 \ + _round_x8 \ + _rounddq3 _roundudq3 \ + _roundda3 _rounduda3 \ + _roundta3 _rounduta3 \ + LIB2FUNCS_EXCLUDE = \ _moddi3 _umoddi3 \ - _clz + _clz \ + _clrsbdi2 \ + # We do not have the DF type. # Most of the C functions in libgcc2 use almost all registers, @@ -106,13 +117,84 @@ ifeq ($(enable_shared),yes) libgcc-s-objects += $(patsubst %,%_s$(objext),$(hiintfuncs16)) endif - -# Filter out supported conversions from fixed-bit.c -# Also filter out TQ and UTQ. +### conv_XY=$(conv)$(mode1)$(mode2) func_X=$(func)$(mode) +# Compile C functions from lib2funcs.c and add them to libgcc.a. +# +# Some functions which are not performance.critical are more convenient +# to implement in C than in assembler. Most of them serve as implementation +# for AVR-specific builtins in the case where the address of a builtin +# function is taken or if there is no insn that implements the builtin. +# +# We don't use LIB2ADD because we want to iterate over the source for +# different modes, fixed-point suffixes, etc. See iter-labels and L_LABEL. +# iter-label will get one more underscore in order to avoid too short +# labels like -DLk and we use -DL_k instead. + +# Build roundFX functions from lib2funcs.c + +round_suffix := hr r lr uhr ur ulr \ + hk k uhk uk +round_funcs := $(foreach func,_round,\ + $(foreach mode,$(round_suffix),$(func_X))) + +iter-items := $(round_funcs) +iter-labels := $(round_suffix) +iter-flags := $(patsubst %,-DL_round,$(iter-items)) + +include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items)) + +libgcc-objects += $(patsubst %,%$(objext),$(round_funcs)) + +# Build clrsbXX functions from lib2funcs.c + +clrsb_modes := qi di +clrsb_funcs := $(foreach func,_clrsb,\ + $(foreach mode,$(clrsb_modes),$(func_X))) + +iter-items := $(clrsb_funcs) +iter-labels := $(clrsb_funcs) +iter-flags := $(patsubst %,-DL_clrsb,$(iter-items)) + +include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items)) + +libgcc-objects += $(patsubst %,%$(objext),$(clrsb_funcs)) + +# Build signed countlsFX functions from lib2funcs.c + +countls_modes := qi hi si di +countls_funcs := $(foreach func,_countls,\ + $(foreach mode,$(countls_modes),$(func_X))) + +iter-items := $(countls_funcs) +iter-labels := $(countls_modes) +iter-flags := $(patsubst %,-DL_countls,$(iter-items)) + +include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items)) + +libgcc-objects += $(patsubst %,%$(objext),$(countls_funcs)) + +# Build unsigned countlsFX functions from lib2funcs.c + +countlsu_modes := qi hi si di +countlsu_funcs := $(foreach func,_countlsu,\ + $(foreach mode,$(countlsu_modes),$(func_X))) + +iter-items := $(countlsu_funcs) +iter-labels := $(countlsu_modes) +iter-flags := $(patsubst %,-DL_countlsu,$(iter-items)) + +include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items)) + +libgcc-objects += $(patsubst %,%$(objext),$(countlsu_funcs)) + + +# Filter out supported conversions from fixed-bit.c +# Also filter out TQ and UTQ. + # Conversions supported by the compiler convf_modes = QI UQI QQ UQQ \ |