;; 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__
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.
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)
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 */
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 */
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__
#undef GUARD
+#endif /* ! AVR_TINY */
+
/***********************************************************
Fixed unsigned saturated Multiplication 8.8 x 8.8
***********************************************************/
;; 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 */
Fixed unsigned saturated Multiplication 16.16 x 16.16
***********************************************************/
+#ifndef __AVR_TINY__
+
#define C0 18
#define C1 C0+1
#define C2 C0+2
#undef C7
#undef SS
+#endif /* ! AVR_TINY */
+
/*******************************************************
Fractional Division 8 / 8
*******************************************************/
#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
*******************************************************/
#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
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
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
#undef r_divHH
#undef r_cnt
+#endif /* ! AVR_TINY */
+
\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Saturation, 1 Byte
DEFUN __ssneg_2
NEG2 A0
brvc 0f
- sbiw A0, 1
+ wsubi A0, 1
0: ret
ENDF __ssneg_2
#endif /* L_ssneg_2 */
;; Saturation, 4 Bytes
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#ifndef __AVR_TINY__
+
;; First Argument and Return Register
#define A0 22
#define A1 A0+1
#undef B6
#undef B7
+#endif /* ! AVR_TINY */
+
\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Rounding Helpers
;; Rounding, 4 Bytes
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#ifndef __AVR_TINY__
+
#define A0 18
#define A1 A0 + 1
#define A2 A0 + 2
#undef RP
#undef FBITm1
+#endif /* ! AVR_TINY */
;; Supply implementations / symbols for the bit-banging functions
;; __builtin_avr_bitsfx and __builtin_avr_fxbits
ret
ENDF __ret
#endif /* L_ret */
-
-#endif /* if not __AVR_TINY__ */
#if defined (L_umulhisi3)
DEFUN __umulhisi3
+#ifndef __AVR_TINY__
wmov B0, 24
;; Zero-extend B
clr B2
;; 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
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.
sbc CC3, B1
XJMP __mulsi3_helper
#endif /* __AVR_ERRATA_SKIP_JMP_CALL__ */
+#endif /* AVR_TINY? */
ENDF __mulhisi3
#endif /* L_mulhisi3 */
_mulhi3 \
_mulqihi3 _umulqihi3 \
_mulpsi3 \
+ _mulhisi3 _umulhisi3 \
_mulsi3 \
_udivmodqi4 \
_divmodqi4 \
_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
FUNCS_notiny = \
_mulsqipsi3 \
- _mulhisi3 \
- _umulhisi3 \
_usmulhisi3 \
_muluhisi3 \
_mulshisi3 \
_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 \