https://gcc.gnu.org/g:939fa28d265d4707ad717fcff0c46329b6dc39c2
commit r15-9235-g939fa28d265d4707ad717fcff0c46329b6dc39c2 Author: Georg-Johann Lay <a...@gjlay.de> Date: Sun Apr 6 16:44:21 2025 +0200 AVRrc: Support 8-bit and 16-bit fixed-point arith in libgcc. With some minor changes, 8-bit and 16-bit fixed-point operations can be supported on the reduced core. libgcc/ * config/avr/t-avr (LIB1ASMFUNCS): Add (and remove from FUNCS_notiny): _mulhisi3, _umulhisi3, _mulqq3, _mulhq3, _muluhq3, _mulha3, _muluha3 _muluha3_round, _usmuluha3, _ssmulha3, _divqq3, _udivuqq3, _divqq_helper, _divhq3, _udivuhq3. _divha3 _udivuha3, _ssneg_2, _ssabs_1, _ssabs_2, _mask1, _ret, _roundqq3 _rounduqq3, _round_s2, _round_u2, _round_2_const, _addmask_2. * config/avr/lib1funcs.S (__umulhisi3, __mulhisi3): Make work on AVRrc. * config/avr/lib1funcs-fixed.S: Build 8-bit and 16-bit functions on AVRrc, too. Diff: --- libgcc/config/avr/lib1funcs-fixed.S | 66 ++++++++++++++++++++++++++++--------- libgcc/config/avr/lib1funcs.S | 41 ++++++++++++++++++++++- libgcc/config/avr/t-avr | 32 +++++++++--------- 3 files changed, 106 insertions(+), 33 deletions(-) diff --git a/libgcc/config/avr/lib1funcs-fixed.S b/libgcc/config/avr/lib1funcs-fixed.S index 278ee1b4a5dd..4115589b5707 100644 --- a/libgcc/config/avr/lib1funcs-fixed.S +++ b/libgcc/config/avr/lib1funcs-fixed.S @@ -31,14 +31,6 @@ ;; Fixed point library routines for AVR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -#if defined __AVR_TINY__ -#define __zero_reg__ r17 -#define __tmp_reg__ r16 -#else -#define __zero_reg__ r1 -#define __tmp_reg__ r0 -#endif - .section .text.libgcc.fixed, "ax", @progbits #ifndef __AVR_TINY__ @@ -251,6 +243,7 @@ DEFUN __fractsfusa ENDF __fractsfusa #endif /* L_fractsfusa */ +#endif /* ! AVR_TINY */ ;; For multiplication the functions here are called directly from ;; avr-fixed.md instead of using the standard libcall mechanisms. @@ -295,8 +288,14 @@ DEFUN __mulhq3 rol r25 brvs 1f ;; Round +#ifndef __AVR_TINY__ sbrc r23, 7 adiw r24, 1 +#else + lsl r23 + adc r24, __zero_reg__ + adc r25, __zero_reg__ +#endif /* AVR_TINY? */ ret 1: ;; Overflow. TR 18037 requires (-1)^2 not to overflow ldi r24, lo8 (0x7fff) @@ -315,8 +314,14 @@ ENDF __mulhq3 DEFUN __muluhq3 XCALL __umulhisi3 ;; Round +#ifndef __AVR_TINY__ sbrc r23, 7 adiw r24, 1 +#else + lsl r23 + adc r24, __zero_reg__ + adc r25, __zero_reg__ +#endif /* AVR_TINY? */ ret ENDF __muluhq3 #endif /* L_muluhq3 */ @@ -361,8 +366,14 @@ DEFUN __muluha3_round mov r25, r24 mov r24, r23 ;; Round +#ifndef __AVR_TINY__ sbrc r22, 7 adiw r24, 1 +#else + lsl r22 + adc r24, __zero_reg__ + adc r25, __zero_reg__ +#endif /* AVR_TINY? */ ret ENDF __muluha3_round #endif /* L_muluha3_round */ @@ -372,6 +383,8 @@ ENDF __muluha3_round Fixed Multiplication 16.16 x 16.16 *******************************************************/ +#ifndef __AVR_TINY__ + ;; Bits outside the result (below LSB), used in the signed version #define GUARD __tmp_reg__ @@ -679,6 +692,8 @@ ENDF __mulusa3_round #undef GUARD +#endif /* ! AVR_TINY */ + /*********************************************************** Fixed unsigned saturated Multiplication 8.8 x 8.8 ***********************************************************/ @@ -762,8 +777,14 @@ DEFUN __ssmulha3 ;; SS = 0 --> 0x7fff ldi C3, 0x7f ldi C2, 0xff +#ifndef __AVR_TINY__ sbrc SS, 7 adiw C2, 1 +#else + lsl SS + adc C2, __zero_reg__ + adc C3, __zero_reg__ +#endif /* AVR_TINY? */ ret ENDF __ssmulha3 #endif /* L_ssmulha3 */ @@ -778,6 +799,8 @@ ENDF __ssmulha3 Fixed unsigned saturated Multiplication 16.16 x 16.16 ***********************************************************/ +#ifndef __AVR_TINY__ + #define C0 18 #define C1 C0+1 #define C2 C0+2 @@ -883,6 +906,8 @@ ENDF __ssmulsa3 #undef C7 #undef SS +#endif /* ! AVR_TINY */ + /******************************************************* Fractional Division 8 / 8 *******************************************************/ @@ -962,8 +987,8 @@ ENDF __divqq_helper #if defined (L_divhq3) DEFUN __divhq3 - mov r0, r_divdH - eor r0, r_divH + mov __tmp_reg__, r_divdH + eor __tmp_reg__, r_divH sbrs r_divH, 7 rjmp 1f NEG2 r_divL @@ -1027,8 +1052,8 @@ ENDF __udivuha3_common *******************************************************/ #if defined (L_divha3) DEFUN __divha3 - mov r0, r_divdH - eor r0, r_divH + mov __tmp_reg__, r_divdH + eor __tmp_reg__, r_divH sbrs r_divH, 7 rjmp 1f NEG2 r_divL @@ -1040,7 +1065,7 @@ DEFUN __divha3 XCALL __udivuha3 lsr r_quoH ; adjust to 7 fractional bits ror r_quoL - sbrs r0, 7 ; negate result if needed + sbrs __tmp_reg__, 7 ; negate result if needed ret NEG2 r_quoL ret @@ -1069,6 +1094,8 @@ ENDF __udivuha3 Fixed Division 16.16 / 16.16 *******************************************************/ +#ifndef __AVR_TINY__ + #define r_arg1L 24 /* arg1 gets passed already in place */ #define r_arg1H 25 #define r_arg1HL 26 @@ -1171,6 +1198,8 @@ ENDF __udivusa3 #undef r_divHH #undef r_cnt +#endif /* ! AVR_TINY */ + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Saturation, 1 Byte @@ -1206,7 +1235,7 @@ ENDF __ssabs_1 DEFUN __ssneg_2 NEG2 A0 brvc 0f - sbiw A0, 1 + wsubi A0, 1 0: ret ENDF __ssneg_2 #endif /* L_ssneg_2 */ @@ -1228,6 +1257,8 @@ ENDF __ssabs_2 ;; Saturation, 4 Bytes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +#ifndef __AVR_TINY__ + ;; First Argument and Return Register #define A0 22 #define A1 A0+1 @@ -1413,6 +1444,8 @@ ENDF __sssub_8 #undef B6 #undef B7 +#endif /* ! AVR_TINY */ + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Rounding Helpers @@ -1613,6 +1646,8 @@ ENDF __round_u2_const ;; Rounding, 4 Bytes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +#ifndef __AVR_TINY__ + #define A0 18 #define A1 A0 + 1 #define A2 A0 + 2 @@ -1915,6 +1950,7 @@ ENDF __round_x8 #undef RP #undef FBITm1 +#endif /* ! AVR_TINY */ ;; Supply implementations / symbols for the bit-banging functions ;; __builtin_avr_bitsfx and __builtin_avr_fxbits @@ -1923,5 +1959,3 @@ DEFUN __ret ret ENDF __ret #endif /* L_ret */ - -#endif /* if not __AVR_TINY__ */ diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S index 01208927c6b0..52ce051e00fe 100644 --- a/libgcc/config/avr/lib1funcs.S +++ b/libgcc/config/avr/lib1funcs.S @@ -395,6 +395,7 @@ ENDF __mulhi3 #if defined (L_umulhisi3) DEFUN __umulhisi3 +#ifndef __AVR_TINY__ wmov B0, 24 ;; Zero-extend B clr B2 @@ -402,11 +403,48 @@ DEFUN __umulhisi3 ;; Zero-extend A wmov A2, B2 XJMP __mulsi3 +#else + ;; Push zero-extended R24 + push __zero_reg__ + push __zero_reg__ + push r25 + push r24 + ;; Zero-extend R22 + clr R24 + clr R25 + XCALL __mulsi3 + pop __tmp_reg__ + pop __tmp_reg__ + pop __tmp_reg__ + pop __tmp_reg__ + ret +#endif /* AVR_TINY? */ ENDF __umulhisi3 #endif /* L_umulhisi3 */ #if defined (L_mulhisi3) DEFUN __mulhisi3 +#ifdef __AVR_TINY__ + ;; Push sign-extended R24 + mov __tmp_reg__, r25 + lsl __tmp_reg__ + sbc __tmp_reg__, __tmp_reg__ + push __tmp_reg__ + push __tmp_reg__ + push r25 + push r24 + ;; Sign-extend R22 + mov r24, r23 + lsl r24 + sbc r24, r24 + sbc r25, r25 + XCALL __mulsi3 + pop __tmp_reg__ + pop __tmp_reg__ + pop __tmp_reg__ + pop __tmp_reg__ + ret +#else wmov B0, 24 ;; Sign-extend B lsl r25 @@ -418,7 +456,7 @@ DEFUN __mulhisi3 sbrc A1, 7 com A2 mov A3, A2 - XJMP __mulsi3 + XJMP __mulsi3 #else /* no __AVR_ERRATA_SKIP_JMP_CALL__ */ ;; Zero-extend A and __mulsi3 will run at least twice as fast ;; compared to a sign-extended A. @@ -434,6 +472,7 @@ DEFUN __mulhisi3 sbc CC3, B1 XJMP __mulsi3_helper #endif /* __AVR_ERRATA_SKIP_JMP_CALL__ */ +#endif /* AVR_TINY? */ ENDF __mulhisi3 #endif /* L_mulhisi3 */ diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr index b10542c8945e..d181784e0e72 100644 --- a/libgcc/config/avr/t-avr +++ b/libgcc/config/avr/t-avr @@ -4,6 +4,7 @@ LIB1ASMFUNCS = \ _mulhi3 \ _mulqihi3 _umulqihi3 \ _mulpsi3 \ + _mulhisi3 _umulhisi3 \ _mulsi3 \ _udivmodqi4 \ _divmodqi4 \ @@ -33,12 +34,23 @@ LIB1ASMFUNCS = \ _popcountsi2 \ _popcountqi2 \ _bswapsi2 \ - _fmul _fmuls _fmulsu + _fmul _fmuls _fmulsu \ + _mulqq3 \ + _mulhq3 _muluhq3 \ + _mulha3 _muluha3 _muluha3_round \ + _usmuluha3 _ssmulha3 \ + _divqq3 _udivuqq3 _divqq_helper \ + _divhq3 _udivuhq3 \ + _divha3 _udivuha3 \ + _ssneg_2 \ + _ssabs_1 _ssabs_2 \ + _mask1 _ret \ + _roundqq3 _rounduqq3 \ + _round_s2 _round_u2 _round_2_const _addmask_2 \ # The below functions either use registers that are not present # in tiny core, or use a different register convention (don't save # callee saved regs, for example) -# _mulhisi3 and variations - clobber R18, R19 # All *di funcs - use regs < R16 or expect args in regs < R20 # _prologue and _epilogue save registers < R16 # _load, __fload and _xload variations - expect lpm and elpm support @@ -46,8 +58,6 @@ LIB1ASMFUNCS = \ FUNCS_notiny = \ _mulsqipsi3 \ - _mulhisi3 \ - _umulhisi3 \ _usmulhisi3 \ _muluhisi3 \ _mulshisi3 \ @@ -81,24 +91,14 @@ FUNCS_notiny += \ _fractsfqq _fractsfuqq \ _fractsfhq _fractsfuhq _fractsfha _fractsfuha \ _fractsfsq _fractsfusq _fractsfsa _fractsfusa \ - _mulqq3 \ - _mulhq3 _muluhq3 \ - _mulha3 _muluha3 _muluha3_round \ _mulsa3 _mulusa3 \ - _usmuluha3 _ssmulha3 \ _usmulusa3 _ssmulsa3 \ - _divqq3 _udivuqq3 _divqq_helper \ - _divhq3 _udivuhq3 \ - _divha3 _udivuha3 \ _divsa3 _udivusa3 \ _clr_8 \ - _ssneg_2 _ssneg_4 _ssneg_8 \ - _ssabs_1 _ssabs_2 _ssabs_4 _ssabs_8 \ + _ssneg_4 _ssneg_8 \ + _ssabs_4 _ssabs_8 \ _ssadd_8 _sssub_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 \