summaryrefslogtreecommitdiff
path: root/gcc/config/avr/libgcc.S
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/avr/libgcc.S')
-rw-r--r--gcc/config/avr/libgcc.S1533
1 files changed, 0 insertions, 1533 deletions
diff --git a/gcc/config/avr/libgcc.S b/gcc/config/avr/libgcc.S
deleted file mode 100644
index 8c369c96a77..00000000000
--- a/gcc/config/avr/libgcc.S
+++ /dev/null
@@ -1,1533 +0,0 @@
-/* -*- Mode: Asm -*- */
-/* Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009
- Free Software Foundation, Inc.
- Contributed by Denis Chertykov <chertykov@gmail.com>
-
-This file 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.
-
-This file 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/>. */
-
-#define __zero_reg__ r1
-#define __tmp_reg__ r0
-#define __SREG__ 0x3f
-#define __SP_H__ 0x3e
-#define __SP_L__ 0x3d
-#define __RAMPZ__ 0x3B
-#define __EIND__ 0x3C
-
-/* Most of the functions here are called directly from avr.md
- patterns, instead of using the standard libcall mechanisms.
- This can make better code because GCC knows exactly which
- of the call-used registers (not all of them) are clobbered. */
-
-/* FIXME: At present, there is no SORT directive in the linker
- script so that we must not assume that different modules
- in the same input section like .libgcc.text.mul will be
- located close together. Therefore, we cannot use
- RCALL/RJMP to call a function like __udivmodhi4 from
- __divmodhi4 and have to use lengthy XCALL/XJMP even
- though they are in the same input section and all same
- input sections together are small enough to reach every
- location with a RCALL/RJMP instruction. */
-
- .macro mov_l r_dest, r_src
-#if defined (__AVR_HAVE_MOVW__)
- movw \r_dest, \r_src
-#else
- mov \r_dest, \r_src
-#endif
- .endm
-
- .macro mov_h r_dest, r_src
-#if defined (__AVR_HAVE_MOVW__)
- ; empty
-#else
- mov \r_dest, \r_src
-#endif
- .endm
-
-#if defined (__AVR_HAVE_JMP_CALL__)
-#define XCALL call
-#define XJMP jmp
-#else
-#define XCALL rcall
-#define XJMP rjmp
-#endif
-
-.macro DEFUN name
-.global \name
-.func \name
-\name:
-.endm
-
-.macro ENDF name
-.size \name, .-\name
-.endfunc
-.endm
-
-
-.section .text.libgcc.mul, "ax", @progbits
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-/* Note: mulqi3, mulhi3 are open-coded on the enhanced core. */
-#if !defined (__AVR_HAVE_MUL__)
-/*******************************************************
- Multiplication 8 x 8 without MUL
-*******************************************************/
-#if defined (L_mulqi3)
-
-#define r_arg2 r22 /* multiplicand */
-#define r_arg1 r24 /* multiplier */
-#define r_res __tmp_reg__ /* result */
-
-DEFUN __mulqi3
- clr r_res ; clear result
-__mulqi3_loop:
- sbrc r_arg1,0
- add r_res,r_arg2
- add r_arg2,r_arg2 ; shift multiplicand
- breq __mulqi3_exit ; while multiplicand != 0
- lsr r_arg1 ;
- brne __mulqi3_loop ; exit if multiplier = 0
-__mulqi3_exit:
- mov r_arg1,r_res ; result to return register
- ret
-ENDF __mulqi3
-
-#undef r_arg2
-#undef r_arg1
-#undef r_res
-
-#endif /* defined (L_mulqi3) */
-
-#if defined (L_mulqihi3)
-DEFUN __mulqihi3
- clr r25
- sbrc r24, 7
- dec r25
- clr r23
- sbrc r22, 7
- dec r22
- XJMP __mulhi3
-ENDF __mulqihi3:
-#endif /* defined (L_mulqihi3) */
-
-#if defined (L_umulqihi3)
-DEFUN __umulqihi3
- clr r25
- clr r23
- XJMP __mulhi3
-ENDF __umulqihi3
-#endif /* defined (L_umulqihi3) */
-
-/*******************************************************
- Multiplication 16 x 16 without MUL
-*******************************************************/
-#if defined (L_mulhi3)
-#define r_arg1L r24 /* multiplier Low */
-#define r_arg1H r25 /* multiplier High */
-#define r_arg2L r22 /* multiplicand Low */
-#define r_arg2H r23 /* multiplicand High */
-#define r_resL __tmp_reg__ /* result Low */
-#define r_resH r21 /* result High */
-
-DEFUN __mulhi3
- clr r_resH ; clear result
- clr r_resL ; clear result
-__mulhi3_loop:
- sbrs r_arg1L,0
- rjmp __mulhi3_skip1
- add r_resL,r_arg2L ; result + multiplicand
- adc r_resH,r_arg2H
-__mulhi3_skip1:
- add r_arg2L,r_arg2L ; shift multiplicand
- adc r_arg2H,r_arg2H
-
- cp r_arg2L,__zero_reg__
- cpc r_arg2H,__zero_reg__
- breq __mulhi3_exit ; while multiplicand != 0
-
- lsr r_arg1H ; gets LSB of multiplier
- ror r_arg1L
- sbiw r_arg1L,0
- brne __mulhi3_loop ; exit if multiplier = 0
-__mulhi3_exit:
- mov r_arg1H,r_resH ; result to return register
- mov r_arg1L,r_resL
- ret
-ENDF __mulhi3
-
-#undef r_arg1L
-#undef r_arg1H
-#undef r_arg2L
-#undef r_arg2H
-#undef r_resL
-#undef r_resH
-
-#endif /* defined (L_mulhi3) */
-
-/*******************************************************
- Widening Multiplication 32 = 16 x 16 without MUL
-*******************************************************/
-
-#if defined (L_mulhisi3)
-DEFUN __mulhisi3
-;;; FIXME: This is dead code (noone calls it)
- mov_l r18, r24
- mov_h r19, r25
- clr r24
- sbrc r23, 7
- dec r24
- mov r25, r24
- clr r20
- sbrc r19, 7
- dec r20
- mov r21, r20
- XJMP __mulsi3
-ENDF __mulhisi3
-#endif /* defined (L_mulhisi3) */
-
-#if defined (L_umulhisi3)
-DEFUN __umulhisi3
-;;; FIXME: This is dead code (noone calls it)
- mov_l r18, r24
- mov_h r19, r25
- clr r24
- clr r25
- mov_l r20, r24
- mov_h r21, r25
- XJMP __mulsi3
-ENDF __umulhisi3
-#endif /* defined (L_umulhisi3) */
-
-#if defined (L_mulsi3)
-/*******************************************************
- Multiplication 32 x 32 without MUL
-*******************************************************/
-#define r_arg1L r22 /* multiplier Low */
-#define r_arg1H r23
-#define r_arg1HL r24
-#define r_arg1HH r25 /* multiplier High */
-
-#define r_arg2L r18 /* multiplicand Low */
-#define r_arg2H r19
-#define r_arg2HL r20
-#define r_arg2HH r21 /* multiplicand High */
-
-#define r_resL r26 /* result Low */
-#define r_resH r27
-#define r_resHL r30
-#define r_resHH r31 /* result High */
-
-DEFUN __mulsi3
- clr r_resHH ; clear result
- clr r_resHL ; clear result
- clr r_resH ; clear result
- clr r_resL ; clear result
-__mulsi3_loop:
- sbrs r_arg1L,0
- rjmp __mulsi3_skip1
- add r_resL,r_arg2L ; result + multiplicand
- adc r_resH,r_arg2H
- adc r_resHL,r_arg2HL
- adc r_resHH,r_arg2HH
-__mulsi3_skip1:
- add r_arg2L,r_arg2L ; shift multiplicand
- adc r_arg2H,r_arg2H
- adc r_arg2HL,r_arg2HL
- adc r_arg2HH,r_arg2HH
-
- lsr r_arg1HH ; gets LSB of multiplier
- ror r_arg1HL
- ror r_arg1H
- ror r_arg1L
- brne __mulsi3_loop
- sbiw r_arg1HL,0
- cpc r_arg1H,r_arg1L
- brne __mulsi3_loop ; exit if multiplier = 0
-__mulsi3_exit:
- mov_h r_arg1HH,r_resHH ; result to return register
- mov_l r_arg1HL,r_resHL
- mov_h r_arg1H,r_resH
- mov_l r_arg1L,r_resL
- ret
-ENDF __mulsi3
-
-#undef r_arg1L
-#undef r_arg1H
-#undef r_arg1HL
-#undef r_arg1HH
-
-#undef r_arg2L
-#undef r_arg2H
-#undef r_arg2HL
-#undef r_arg2HH
-
-#undef r_resL
-#undef r_resH
-#undef r_resHL
-#undef r_resHH
-
-#endif /* defined (L_mulsi3) */
-
-#endif /* !defined (__AVR_HAVE_MUL__) */
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#if defined (__AVR_HAVE_MUL__)
-#define A0 26
-#define B0 18
-#define C0 22
-
-#define A1 A0+1
-
-#define B1 B0+1
-#define B2 B0+2
-#define B3 B0+3
-
-#define C1 C0+1
-#define C2 C0+2
-#define C3 C0+3
-
-/*******************************************************
- Widening Multiplication 32 = 16 x 16
-*******************************************************/
-
-#if defined (L_mulhisi3)
-;;; R25:R22 = (signed long) R27:R26 * (signed long) R19:R18
-;;; C3:C0 = (signed long) A1:A0 * (signed long) B1:B0
-;;; Clobbers: __tmp_reg__
-DEFUN __mulhisi3
- XCALL __umulhisi3
- ;; Sign-extend B
- tst B1
- brpl 1f
- sub C2, A0
- sbc C3, A1
-1: ;; Sign-extend A
- XJMP __usmulhisi3_tail
-ENDF __mulhisi3
-#endif /* L_mulhisi3 */
-
-#if defined (L_usmulhisi3)
-;;; R25:R22 = (signed long) R27:R26 * (unsigned long) R19:R18
-;;; C3:C0 = (signed long) A1:A0 * (unsigned long) B1:B0
-;;; Clobbers: __tmp_reg__
-DEFUN __usmulhisi3
- XCALL __umulhisi3
- ;; FALLTHRU
-ENDF __usmulhisi3
-
-DEFUN __usmulhisi3_tail
- ;; Sign-extend A
- sbrs A1, 7
- ret
- sub C2, B0
- sbc C3, B1
- ret
-ENDF __usmulhisi3_tail
-#endif /* L_usmulhisi3 */
-
-#if defined (L_umulhisi3)
-;;; R25:R22 = (unsigned long) R27:R26 * (unsigned long) R19:R18
-;;; C3:C0 = (unsigned long) A1:A0 * (unsigned long) B1:B0
-;;; Clobbers: __tmp_reg__
-DEFUN __umulhisi3
- mul A0, B0
- movw C0, r0
- mul A1, B1
- movw C2, r0
- mul A0, B1
- rcall 1f
- mul A1, B0
-1: add C1, r0
- adc C2, r1
- clr __zero_reg__
- adc C3, __zero_reg__
- ret
-ENDF __umulhisi3
-#endif /* L_umulhisi3 */
-
-/*******************************************************
- Widening Multiplication 32 = 16 x 32
-*******************************************************/
-
-#if defined (L_mulshisi3)
-;;; R25:R22 = (signed long) R27:R26 * R21:R18
-;;; (C3:C0) = (signed long) A1:A0 * B3:B0
-;;; Clobbers: __tmp_reg__
-DEFUN __mulshisi3
-#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
- ;; Some cores have problem skipping 2-word instruction
- tst A1
- brmi __mulohisi3
-#else
- sbrs A1, 7
-#endif /* __AVR_HAVE_JMP_CALL__ */
- XJMP __muluhisi3
- ;; FALLTHRU
-ENDF __mulshisi3
-
-;;; R25:R22 = (one-extended long) R27:R26 * R21:R18
-;;; (C3:C0) = (one-extended long) A1:A0 * B3:B0
-;;; Clobbers: __tmp_reg__
-DEFUN __mulohisi3
- XCALL __muluhisi3
- ;; One-extend R27:R26 (A1:A0)
- sub C2, B0
- sbc C3, B1
- ret
-ENDF __mulohisi3
-#endif /* L_mulshisi3 */
-
-#if defined (L_muluhisi3)
-;;; R25:R22 = (unsigned long) R27:R26 * R21:R18
-;;; (C3:C0) = (unsigned long) A1:A0 * B3:B0
-;;; Clobbers: __tmp_reg__
-DEFUN __muluhisi3
- XCALL __umulhisi3
- mul A0, B3
- add C3, r0
- mul A1, B2
- add C3, r0
- mul A0, B2
- add C2, r0
- adc C3, r1
- clr __zero_reg__
- ret
-ENDF __muluhisi3
-#endif /* L_muluhisi3 */
-
-/*******************************************************
- Multiplication 32 x 32
-*******************************************************/
-
-#if defined (L_mulsi3)
-;;; R25:R22 = R25:R22 * R21:R18
-;;; (C3:C0) = C3:C0 * B3:B0
-;;; Clobbers: R26, R27, __tmp_reg__
-DEFUN __mulsi3
- movw A0, C0
- push C2
- push C3
- XCALL __muluhisi3
- pop A1
- pop A0
- ;; A1:A0 now contains the high word of A
- mul A0, B0
- add C2, r0
- adc C3, r1
- mul A0, B1
- add C3, r0
- mul A1, B0
- add C3, r0
- clr __zero_reg__
- ret
-ENDF __mulsi3
-#endif /* L_mulsi3 */
-
-#undef A0
-#undef A1
-
-#undef B0
-#undef B1
-#undef B2
-#undef B3
-
-#undef C0
-#undef C1
-#undef C2
-#undef C3
-
-#endif /* __AVR_HAVE_MUL__ */
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-.section .text.libgcc.div, "ax", @progbits
-
-/*******************************************************
- Division 8 / 8 => (result + remainder)
-*******************************************************/
-#define r_rem r25 /* remainder */
-#define r_arg1 r24 /* dividend, quotient */
-#define r_arg2 r22 /* divisor */
-#define r_cnt r23 /* loop count */
-
-#if defined (L_udivmodqi4)
-DEFUN __udivmodqi4
- sub r_rem,r_rem ; clear remainder and carry
- ldi r_cnt,9 ; init loop counter
- rjmp __udivmodqi4_ep ; jump to entry point
-__udivmodqi4_loop:
- rol r_rem ; shift dividend into remainder
- cp r_rem,r_arg2 ; compare remainder & divisor
- brcs __udivmodqi4_ep ; remainder <= divisor
- sub r_rem,r_arg2 ; restore remainder
-__udivmodqi4_ep:
- rol r_arg1 ; shift dividend (with CARRY)
- dec r_cnt ; decrement loop counter
- brne __udivmodqi4_loop
- com r_arg1 ; complement result
- ; because C flag was complemented in loop
- ret
-ENDF __udivmodqi4
-#endif /* defined (L_udivmodqi4) */
-
-#if defined (L_divmodqi4)
-DEFUN __divmodqi4
- bst r_arg1,7 ; store sign of dividend
- mov __tmp_reg__,r_arg1
- eor __tmp_reg__,r_arg2; r0.7 is sign of result
- sbrc r_arg1,7
- neg r_arg1 ; dividend negative : negate
- sbrc r_arg2,7
- neg r_arg2 ; divisor negative : negate
- XCALL __udivmodqi4 ; do the unsigned div/mod
- brtc __divmodqi4_1
- neg r_rem ; correct remainder sign
-__divmodqi4_1:
- sbrc __tmp_reg__,7
- neg r_arg1 ; correct result sign
-__divmodqi4_exit:
- ret
-ENDF __divmodqi4
-#endif /* defined (L_divmodqi4) */
-
-#undef r_rem
-#undef r_arg1
-#undef r_arg2
-#undef r_cnt
-
-
-/*******************************************************
- Division 16 / 16 => (result + remainder)
-*******************************************************/
-#define r_remL r26 /* remainder Low */
-#define r_remH r27 /* remainder High */
-
-/* return: remainder */
-#define r_arg1L r24 /* dividend Low */
-#define r_arg1H r25 /* dividend High */
-
-/* return: quotient */
-#define r_arg2L r22 /* divisor Low */
-#define r_arg2H r23 /* divisor High */
-
-#define r_cnt r21 /* loop count */
-
-#if defined (L_udivmodhi4)
-DEFUN __udivmodhi4
- sub r_remL,r_remL
- sub r_remH,r_remH ; clear remainder and carry
- ldi r_cnt,17 ; init loop counter
- rjmp __udivmodhi4_ep ; jump to entry point
-__udivmodhi4_loop:
- rol r_remL ; shift dividend into remainder
- rol r_remH
- cp r_remL,r_arg2L ; compare remainder & divisor
- cpc r_remH,r_arg2H
- brcs __udivmodhi4_ep ; remainder < divisor
- sub r_remL,r_arg2L ; restore remainder
- sbc r_remH,r_arg2H
-__udivmodhi4_ep:
- rol r_arg1L ; shift dividend (with CARRY)
- rol r_arg1H
- dec r_cnt ; decrement loop counter
- brne __udivmodhi4_loop
- com r_arg1L
- com r_arg1H
-; div/mod results to return registers, as for the div() function
- mov_l r_arg2L, r_arg1L ; quotient
- mov_h r_arg2H, r_arg1H
- mov_l r_arg1L, r_remL ; remainder
- mov_h r_arg1H, r_remH
- ret
-ENDF __udivmodhi4
-#endif /* defined (L_udivmodhi4) */
-
-#if defined (L_divmodhi4)
-DEFUN __divmodhi4
- .global _div
-_div:
- bst r_arg1H,7 ; store sign of dividend
- mov __tmp_reg__,r_arg1H
- eor __tmp_reg__,r_arg2H ; r0.7 is sign of result
- rcall __divmodhi4_neg1 ; dividend negative : negate
- sbrc r_arg2H,7
- rcall __divmodhi4_neg2 ; divisor negative : negate
- XCALL __udivmodhi4 ; do the unsigned div/mod
- rcall __divmodhi4_neg1 ; correct remainder sign
- tst __tmp_reg__
- brpl __divmodhi4_exit
-__divmodhi4_neg2:
- com r_arg2H
- neg r_arg2L ; correct divisor/result sign
- sbci r_arg2H,0xff
-__divmodhi4_exit:
- ret
-__divmodhi4_neg1:
- brtc __divmodhi4_exit
- com r_arg1H
- neg r_arg1L ; correct dividend/remainder sign
- sbci r_arg1H,0xff
- ret
-ENDF __divmodhi4
-#endif /* defined (L_divmodhi4) */
-
-#undef r_remH
-#undef r_remL
-
-#undef r_arg1H
-#undef r_arg1L
-
-#undef r_arg2H
-#undef r_arg2L
-
-#undef r_cnt
-
-/*******************************************************
- Division 32 / 32 => (result + remainder)
-*******************************************************/
-#define r_remHH r31 /* remainder High */
-#define r_remHL r30
-#define r_remH r27
-#define r_remL r26 /* remainder Low */
-
-/* return: remainder */
-#define r_arg1HH r25 /* dividend High */
-#define r_arg1HL r24
-#define r_arg1H r23
-#define r_arg1L r22 /* dividend Low */
-
-/* return: quotient */
-#define r_arg2HH r21 /* divisor High */
-#define r_arg2HL r20
-#define r_arg2H r19
-#define r_arg2L r18 /* divisor Low */
-
-#define r_cnt __zero_reg__ /* loop count (0 after the loop!) */
-
-#if defined (L_udivmodsi4)
-DEFUN __udivmodsi4
- ldi r_remL, 33 ; init loop counter
- mov r_cnt, r_remL
- sub r_remL,r_remL
- sub r_remH,r_remH ; clear remainder and carry
- mov_l r_remHL, r_remL
- mov_h r_remHH, r_remH
- rjmp __udivmodsi4_ep ; jump to entry point
-__udivmodsi4_loop:
- rol r_remL ; shift dividend into remainder
- rol r_remH
- rol r_remHL
- rol r_remHH
- cp r_remL,r_arg2L ; compare remainder & divisor
- cpc r_remH,r_arg2H
- cpc r_remHL,r_arg2HL
- cpc r_remHH,r_arg2HH
- brcs __udivmodsi4_ep ; remainder <= divisor
- sub r_remL,r_arg2L ; restore remainder
- sbc r_remH,r_arg2H
- sbc r_remHL,r_arg2HL
- sbc r_remHH,r_arg2HH
-__udivmodsi4_ep:
- rol r_arg1L ; shift dividend (with CARRY)
- rol r_arg1H
- rol r_arg1HL
- rol r_arg1HH
- dec r_cnt ; decrement loop counter
- brne __udivmodsi4_loop
- ; __zero_reg__ now restored (r_cnt == 0)
- com r_arg1L
- com r_arg1H
- com r_arg1HL
- com r_arg1HH
-; div/mod results to return registers, as for the ldiv() function
- mov_l r_arg2L, r_arg1L ; quotient
- mov_h r_arg2H, r_arg1H
- mov_l r_arg2HL, r_arg1HL
- mov_h r_arg2HH, r_arg1HH
- mov_l r_arg1L, r_remL ; remainder
- mov_h r_arg1H, r_remH
- mov_l r_arg1HL, r_remHL
- mov_h r_arg1HH, r_remHH
- ret
-ENDF __udivmodsi4
-#endif /* defined (L_udivmodsi4) */
-
-#if defined (L_divmodsi4)
-DEFUN __divmodsi4
- bst r_arg1HH,7 ; store sign of dividend
- mov __tmp_reg__,r_arg1HH
- eor __tmp_reg__,r_arg2HH ; r0.7 is sign of result
- rcall __divmodsi4_neg1 ; dividend negative : negate
- sbrc r_arg2HH,7
- rcall __divmodsi4_neg2 ; divisor negative : negate
- XCALL __udivmodsi4 ; do the unsigned div/mod
- rcall __divmodsi4_neg1 ; correct remainder sign
- rol __tmp_reg__
- brcc __divmodsi4_exit
-__divmodsi4_neg2:
- com r_arg2HH
- com r_arg2HL
- com r_arg2H
- neg r_arg2L ; correct divisor/quotient sign
- sbci r_arg2H,0xff
- sbci r_arg2HL,0xff
- sbci r_arg2HH,0xff
-__divmodsi4_exit:
- ret
-__divmodsi4_neg1:
- brtc __divmodsi4_exit
- com r_arg1HH
- com r_arg1HL
- com r_arg1H
- neg r_arg1L ; correct dividend/remainder sign
- sbci r_arg1H, 0xff
- sbci r_arg1HL,0xff
- sbci r_arg1HH,0xff
- ret
-ENDF __divmodsi4
-#endif /* defined (L_divmodsi4) */
-
-
-.section .text.libgcc.prologue, "ax", @progbits
-
-/**********************************
- * This is a prologue subroutine
- **********************************/
-#if defined (L_prologue)
-
-DEFUN __prologue_saves__
- push r2
- push r3
- push r4
- push r5
- push r6
- push r7
- push r8
- push r9
- push r10
- push r11
- push r12
- push r13
- push r14
- push r15
- push r16
- push r17
- push r28
- push r29
- in r28,__SP_L__
- in r29,__SP_H__
- sub r28,r26
- sbc r29,r27
- in __tmp_reg__,__SREG__
- cli
- out __SP_H__,r29
- out __SREG__,__tmp_reg__
- out __SP_L__,r28
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
- eijmp
-#else
- ijmp
-#endif
-
-ENDF __prologue_saves__
-#endif /* defined (L_prologue) */
-
-/*
- * This is an epilogue subroutine
- */
-#if defined (L_epilogue)
-
-DEFUN __epilogue_restores__
- ldd r2,Y+18
- ldd r3,Y+17
- ldd r4,Y+16
- ldd r5,Y+15
- ldd r6,Y+14
- ldd r7,Y+13
- ldd r8,Y+12
- ldd r9,Y+11
- ldd r10,Y+10
- ldd r11,Y+9
- ldd r12,Y+8
- ldd r13,Y+7
- ldd r14,Y+6
- ldd r15,Y+5
- ldd r16,Y+4
- ldd r17,Y+3
- ldd r26,Y+2
- ldd r27,Y+1
- add r28,r30
- adc r29,__zero_reg__
- in __tmp_reg__,__SREG__
- cli
- out __SP_H__,r29
- out __SREG__,__tmp_reg__
- out __SP_L__,r28
- mov_l r28, r26
- mov_h r29, r27
- ret
-ENDF __epilogue_restores__
-#endif /* defined (L_epilogue) */
-
-#ifdef L_exit
- .section .fini9,"ax",@progbits
-DEFUN _exit
- .weak exit
-exit:
-ENDF _exit
-
- /* Code from .fini8 ... .fini1 sections inserted by ld script. */
-
- .section .fini0,"ax",@progbits
- cli
-__stop_program:
- rjmp __stop_program
-#endif /* defined (L_exit) */
-
-#ifdef L_cleanup
- .weak _cleanup
- .func _cleanup
-_cleanup:
- ret
-.endfunc
-#endif /* defined (L_cleanup) */
-
-
-.section .text.libgcc, "ax", @progbits
-
-#ifdef L_tablejump
-DEFUN __tablejump2__
- lsl r30
- rol r31
- ;; FALLTHRU
-ENDF __tablejump2__
-
-DEFUN __tablejump__
-#if defined (__AVR_HAVE_LPMX__)
- lpm __tmp_reg__, Z+
- lpm r31, Z
- mov r30, __tmp_reg__
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
- eijmp
-#else
- ijmp
-#endif
-
-#else /* !HAVE_LPMX */
- lpm
- adiw r30, 1
- push r0
- lpm
- push r0
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
- in __tmp_reg__, __EIND__
- push __tmp_reg__
-#endif
- ret
-#endif /* !HAVE_LPMX */
-ENDF __tablejump__
-#endif /* defined (L_tablejump) */
-
-#ifdef L_copy_data
- .section .init4,"ax",@progbits
-DEFUN __do_copy_data
-#if defined(__AVR_HAVE_ELPMX__)
- ldi r17, hi8(__data_end)
- ldi r26, lo8(__data_start)
- ldi r27, hi8(__data_start)
- ldi r30, lo8(__data_load_start)
- ldi r31, hi8(__data_load_start)
- ldi r16, hh8(__data_load_start)
- out __RAMPZ__, r16
- rjmp .L__do_copy_data_start
-.L__do_copy_data_loop:
- elpm r0, Z+
- st X+, r0
-.L__do_copy_data_start:
- cpi r26, lo8(__data_end)
- cpc r27, r17
- brne .L__do_copy_data_loop
-#elif !defined(__AVR_HAVE_ELPMX__) && defined(__AVR_HAVE_ELPM__)
- ldi r17, hi8(__data_end)
- ldi r26, lo8(__data_start)
- ldi r27, hi8(__data_start)
- ldi r30, lo8(__data_load_start)
- ldi r31, hi8(__data_load_start)
- ldi r16, hh8(__data_load_start - 0x10000)
-.L__do_copy_data_carry:
- inc r16
- out __RAMPZ__, r16
- rjmp .L__do_copy_data_start
-.L__do_copy_data_loop:
- elpm
- st X+, r0
- adiw r30, 1
- brcs .L__do_copy_data_carry
-.L__do_copy_data_start:
- cpi r26, lo8(__data_end)
- cpc r27, r17
- brne .L__do_copy_data_loop
-#elif !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__)
- ldi r17, hi8(__data_end)
- ldi r26, lo8(__data_start)
- ldi r27, hi8(__data_start)
- ldi r30, lo8(__data_load_start)
- ldi r31, hi8(__data_load_start)
- rjmp .L__do_copy_data_start
-.L__do_copy_data_loop:
-#if defined (__AVR_HAVE_LPMX__)
- lpm r0, Z+
-#else
- lpm
- adiw r30, 1
-#endif
- st X+, r0
-.L__do_copy_data_start:
- cpi r26, lo8(__data_end)
- cpc r27, r17
- brne .L__do_copy_data_loop
-#endif /* !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__) */
-ENDF __do_copy_data
-#endif /* L_copy_data */
-
-/* __do_clear_bss is only necessary if there is anything in .bss section. */
-
-#ifdef L_clear_bss
- .section .init4,"ax",@progbits
-DEFUN __do_clear_bss
- ldi r17, hi8(__bss_end)
- ldi r26, lo8(__bss_start)
- ldi r27, hi8(__bss_start)
- rjmp .do_clear_bss_start
-.do_clear_bss_loop:
- st X+, __zero_reg__
-.do_clear_bss_start:
- cpi r26, lo8(__bss_end)
- cpc r27, r17
- brne .do_clear_bss_loop
-ENDF __do_clear_bss
-#endif /* L_clear_bss */
-
-/* __do_global_ctors and __do_global_dtors are only necessary
- if there are any constructors/destructors. */
-
-#ifdef L_ctors
- .section .init6,"ax",@progbits
-DEFUN __do_global_ctors
-#if defined(__AVR_HAVE_RAMPZ__)
- ldi r17, hi8(__ctors_start)
- ldi r28, lo8(__ctors_end)
- ldi r29, hi8(__ctors_end)
- ldi r16, hh8(__ctors_end)
- rjmp .L__do_global_ctors_start
-.L__do_global_ctors_loop:
- sbiw r28, 2
- sbc r16, __zero_reg__
- mov_h r31, r29
- mov_l r30, r28
- out __RAMPZ__, r16
- XCALL __tablejump_elpm__
-.L__do_global_ctors_start:
- cpi r28, lo8(__ctors_start)
- cpc r29, r17
- ldi r24, hh8(__ctors_start)
- cpc r16, r24
- brne .L__do_global_ctors_loop
-#else
- ldi r17, hi8(__ctors_start)
- ldi r28, lo8(__ctors_end)
- ldi r29, hi8(__ctors_end)
- rjmp .L__do_global_ctors_start
-.L__do_global_ctors_loop:
- sbiw r28, 2
- mov_h r31, r29
- mov_l r30, r28
- XCALL __tablejump__
-.L__do_global_ctors_start:
- cpi r28, lo8(__ctors_start)
- cpc r29, r17
- brne .L__do_global_ctors_loop
-#endif /* defined(__AVR_HAVE_RAMPZ__) */
-ENDF __do_global_ctors
-#endif /* L_ctors */
-
-#ifdef L_dtors
- .section .fini6,"ax",@progbits
-DEFUN __do_global_dtors
-#if defined(__AVR_HAVE_RAMPZ__)
- ldi r17, hi8(__dtors_end)
- ldi r28, lo8(__dtors_start)
- ldi r29, hi8(__dtors_start)
- ldi r16, hh8(__dtors_start)
- rjmp .L__do_global_dtors_start
-.L__do_global_dtors_loop:
- sbiw r28, 2
- sbc r16, __zero_reg__
- mov_h r31, r29
- mov_l r30, r28
- out __RAMPZ__, r16
- XCALL __tablejump_elpm__
-.L__do_global_dtors_start:
- cpi r28, lo8(__dtors_end)
- cpc r29, r17
- ldi r24, hh8(__dtors_end)
- cpc r16, r24
- brne .L__do_global_dtors_loop
-#else
- ldi r17, hi8(__dtors_end)
- ldi r28, lo8(__dtors_start)
- ldi r29, hi8(__dtors_start)
- rjmp .L__do_global_dtors_start
-.L__do_global_dtors_loop:
- mov_h r31, r29
- mov_l r30, r28
- XCALL __tablejump__
- adiw r28, 2
-.L__do_global_dtors_start:
- cpi r28, lo8(__dtors_end)
- cpc r29, r17
- brne .L__do_global_dtors_loop
-#endif /* defined(__AVR_HAVE_RAMPZ__) */
-ENDF __do_global_dtors
-#endif /* L_dtors */
-
-.section .text.libgcc, "ax", @progbits
-
-#ifdef L_tablejump_elpm
-DEFUN __tablejump_elpm__
-#if defined (__AVR_HAVE_ELPM__)
-#if defined (__AVR_HAVE_LPMX__)
- elpm __tmp_reg__, Z+
- elpm r31, Z
- mov r30, __tmp_reg__
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
- eijmp
-#else
- ijmp
-#endif
-
-#else
- elpm
- adiw r30, 1
- push r0
- elpm
- push r0
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
- in __tmp_reg__, __EIND__
- push __tmp_reg__
-#endif
- ret
-#endif
-#endif /* defined (__AVR_HAVE_ELPM__) */
-ENDF __tablejump_elpm__
-#endif /* defined (L_tablejump_elpm) */
-
-
-.section .text.libgcc.builtins, "ax", @progbits
-
-/**********************************
- * Find first set Bit (ffs)
- **********************************/
-
-#if defined (L_ffssi2)
-;; find first set bit
-;; r25:r24 = ffs32 (r25:r22)
-;; clobbers: r22, r26
-DEFUN __ffssi2
- clr r26
- tst r22
- brne 1f
- subi r26, -8
- or r22, r23
- brne 1f
- subi r26, -8
- or r22, r24
- brne 1f
- subi r26, -8
- or r22, r25
- brne 1f
- ret
-1: mov r24, r22
- XJMP __loop_ffsqi2
-ENDF __ffssi2
-#endif /* defined (L_ffssi2) */
-
-#if defined (L_ffshi2)
-;; find first set bit
-;; r25:r24 = ffs16 (r25:r24)
-;; clobbers: r26
-DEFUN __ffshi2
- clr r26
-#ifdef __AVR_ERRATA_SKIP_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
-2: ldi r26, 8
- or r24, r25
- brne 1b
- ret
-ENDF __ffshi2
-#endif /* defined (L_ffshi2) */
-
-#if defined (L_loop_ffsqi2)
-;; Helper for ffshi2, ffssi2
-;; r25:r24 = r26 + zero_extend16 (ffs8(r24))
-;; r24 must be != 0
-;; clobbers: r26
-DEFUN __loop_ffsqi2
- inc r26
- lsr r24
- brcc __loop_ffsqi2
- mov r24, r26
- clr r25
- ret
-ENDF __loop_ffsqi2
-#endif /* defined (L_loop_ffsqi2) */
-
-
-/**********************************
- * Count trailing Zeros (ctz)
- **********************************/
-
-#if defined (L_ctzsi2)
-;; count trailing zeros
-;; r25:r24 = ctz32 (r25:r22)
-;; clobbers: r26, r22
-;; ctz(0) = 255
-;; Note that ctz(0) in undefined for GCC
-DEFUN __ctzsi2
- XCALL __ffssi2
- dec r24
- ret
-ENDF __ctzsi2
-#endif /* defined (L_ctzsi2) */
-
-#if defined (L_ctzhi2)
-;; count trailing zeros
-;; r25:r24 = ctz16 (r25:r24)
-;; clobbers: r26
-;; ctz(0) = 255
-;; Note that ctz(0) in undefined for GCC
-DEFUN __ctzhi2
- XCALL __ffshi2
- dec r24
- ret
-ENDF __ctzhi2
-#endif /* defined (L_ctzhi2) */
-
-
-/**********************************
- * Count leading Zeros (clz)
- **********************************/
-
-#if defined (L_clzdi2)
-;; count leading zeros
-;; r25:r24 = clz64 (r25:r18)
-;; clobbers: r22, r23, r26
-DEFUN __clzdi2
- XCALL __clzsi2
- sbrs r24, 5
- ret
- mov_l r22, r18
- mov_h r23, r19
- mov_l r24, r20
- mov_h r25, r21
- XCALL __clzsi2
- subi r24, -32
- ret
-ENDF __clzdi2
-#endif /* defined (L_clzdi2) */
-
-#if defined (L_clzsi2)
-;; count leading zeros
-;; r25:r24 = clz32 (r25:r22)
-;; clobbers: r26
-DEFUN __clzsi2
- XCALL __clzhi2
- sbrs r24, 4
- ret
- mov_l r24, r22
- mov_h r25, r23
- XCALL __clzhi2
- subi r24, -16
- ret
-ENDF __clzsi2
-#endif /* defined (L_clzsi2) */
-
-#if defined (L_clzhi2)
-;; count leading zeros
-;; r25:r24 = clz16 (r25:r24)
-;; clobbers: r26
-DEFUN __clzhi2
- clr r26
- tst r25
- brne 1f
- subi r26, -8
- or r25, r24
- brne 1f
- ldi r24, 16
- ret
-1: cpi r25, 16
- brsh 3f
- subi r26, -3
- swap r25
-2: inc r26
-3: lsl r25
- brcc 2b
- mov r24, r26
- clr r25
- ret
-ENDF __clzhi2
-#endif /* defined (L_clzhi2) */
-
-
-/**********************************
- * Parity
- **********************************/
-
-#if defined (L_paritydi2)
-;; r25:r24 = parity64 (r25:r18)
-;; clobbers: __tmp_reg__
-DEFUN __paritydi2
- eor r24, r18
- eor r24, r19
- eor r24, r20
- eor r24, r21
- XJMP __paritysi2
-ENDF __paritydi2
-#endif /* defined (L_paritydi2) */
-
-#if defined (L_paritysi2)
-;; r25:r24 = parity32 (r25:r22)
-;; clobbers: __tmp_reg__
-DEFUN __paritysi2
- eor r24, r22
- eor r24, r23
- XJMP __parityhi2
-ENDF __paritysi2
-#endif /* defined (L_paritysi2) */
-
-#if defined (L_parityhi2)
-;; r25:r24 = parity16 (r25:r24)
-;; clobbers: __tmp_reg__
-DEFUN __parityhi2
- eor r24, r25
-;; FALLTHRU
-ENDF __parityhi2
-
-;; r25:r24 = parity8 (r24)
-;; clobbers: __tmp_reg__
-DEFUN __parityqi2
- ;; parity is in r24[0..7]
- mov __tmp_reg__, r24
- swap __tmp_reg__
- eor r24, __tmp_reg__
- ;; parity is in r24[0..3]
- subi r24, -4
- andi r24, -5
- subi r24, -6
- ;; parity is in r24[0,3]
- sbrc r24, 3
- inc r24
- ;; parity is in r24[0]
- andi r24, 1
- clr r25
- ret
-ENDF __parityqi2
-#endif /* defined (L_parityhi2) */
-
-
-/**********************************
- * Population Count
- **********************************/
-
-#if defined (L_popcounthi2)
-;; population count
-;; r25:r24 = popcount16 (r25:r24)
-;; clobbers: __tmp_reg__
-DEFUN __popcounthi2
- XCALL __popcountqi2
- push r24
- mov r24, r25
- XCALL __popcountqi2
- clr r25
- ;; 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: __tmp_reg__
-DEFUN __popcountsi2
- XCALL __popcounthi2
- push r24
- mov_l r24, r22
- mov_h r25, r23
- XCALL __popcounthi2
- XJMP __popcounthi2_tail
-ENDF __popcountsi2
-#endif /* defined (L_popcountsi2) */
-
-#if defined (L_popcountdi2)
-;; population count
-;; r25:r24 = popcount64 (r25:r18)
-;; clobbers: r22, r23, __tmp_reg__
-DEFUN __popcountdi2
- XCALL __popcountsi2
- push r24
- mov_l r22, r18
- mov_h r23, r19
- mov_l r24, r20
- mov_h r25, r21
- XCALL __popcountsi2
- XJMP __popcounthi2_tail
-ENDF __popcountdi2
-#endif /* defined (L_popcountdi2) */
-
-#if defined (L_popcountqi2)
-;; population count
-;; r24 = popcount8 (r24)
-;; clobbers: __tmp_reg__
-DEFUN __popcountqi2
- mov __tmp_reg__, r24
- andi r24, 1
- lsr __tmp_reg__
- lsr __tmp_reg__
- adc r24, __zero_reg__
- lsr __tmp_reg__
- adc r24, __zero_reg__
- lsr __tmp_reg__
- adc r24, __zero_reg__
- lsr __tmp_reg__
- adc r24, __zero_reg__
- lsr __tmp_reg__
- adc r24, __zero_reg__
- lsr __tmp_reg__
- adc r24, __tmp_reg__
- ret
-ENDF __popcountqi2
-#endif /* defined (L_popcountqi2) */
-
-
-/**********************************
- * Swap bytes
- **********************************/
-
-;; swap two registers with different register number
-.macro bswap a, b
- eor \a, \b
- eor \b, \a
- eor \a, \b
-.endm
-
-#if defined (L_bswapsi2)
-;; swap bytes
-;; r25:r22 = bswap32 (r25:r22)
-DEFUN __bswapsi2
- bswap r22, r25
- bswap r23, r24
- ret
-ENDF __bswapsi2
-#endif /* defined (L_bswapsi2) */
-
-#if defined (L_bswapdi2)
-;; swap bytes
-;; r25:r18 = bswap64 (r25:r18)
-DEFUN __bswapdi2
- bswap r18, r25
- bswap r19, r24
- bswap r20, r23
- bswap r21, r22
- ret
-ENDF __bswapdi2
-#endif /* defined (L_bswapdi2) */
-
-
-/**********************************
- * 64-bit shifts
- **********************************/
-
-#if defined (L_ashrdi3)
-;; Arithmetic shift right
-;; r25:r18 = ashr64 (r25:r18, r17:r16)
-DEFUN __ashrdi3
- push r16
- andi r16, 63
- breq 2f
-1: asr r25
- ror r24
- ror r23
- ror r22
- ror r21
- ror r20
- ror r19
- ror r18
- dec r16
- brne 1b
-2: pop r16
- ret
-ENDF __ashrdi3
-#endif /* defined (L_ashrdi3) */
-
-#if defined (L_lshrdi3)
-;; Logic shift right
-;; r25:r18 = lshr64 (r25:r18, r17:r16)
-DEFUN __lshrdi3
- push r16
- andi r16, 63
- breq 2f
-1: lsr r25
- ror r24
- ror r23
- ror r22
- ror r21
- ror r20
- ror r19
- ror r18
- dec r16
- brne 1b
-2: pop r16
- ret
-ENDF __lshrdi3
-#endif /* defined (L_lshrdi3) */
-
-#if defined (L_ashldi3)
-;; Shift left
-;; r25:r18 = ashl64 (r25:r18, r17:r16)
-DEFUN __ashldi3
- push r16
- andi r16, 63
- breq 2f
-1: lsl r18
- rol r19
- rol r20
- rol r21
- rol r22
- rol r23
- rol r24
- rol r25
- dec r16
- brne 1b
-2: pop r16
- ret
-ENDF __ashldi3
-#endif /* defined (L_ashldi3) */
-
-
-.section .text.libgcc.fmul, "ax", @progbits
-
-/***********************************************************/
-;;; Softmul versions of FMUL, FMULS and FMULSU to implement
-;;; __builtin_avr_fmul* if !AVR_HAVE_MUL
-/***********************************************************/
-
-#define A1 24
-#define B1 25
-#define C0 22
-#define C1 23
-#define A0 __tmp_reg__
-
-#ifdef L_fmuls
-;;; r23:r22 = fmuls (r24, r25) like in FMULS instruction
-;;; Clobbers: r24, r25, __tmp_reg__
-DEFUN __fmuls
- ;; A0.7 = negate result?
- mov A0, A1
- eor A0, B1
- ;; B1 = |B1|
- sbrc B1, 7
- neg B1
- XJMP __fmulsu_exit
-ENDF __fmuls
-#endif /* L_fmuls */
-
-#ifdef L_fmulsu
-;;; r23:r22 = fmulsu (r24, r25) like in FMULSU instruction
-;;; Clobbers: r24, r25, __tmp_reg__
-DEFUN __fmulsu
- ;; A0.7 = negate result?
- mov A0, A1
-;; FALLTHRU
-ENDF __fmulsu
-
-;; Helper for __fmuls and __fmulsu
-DEFUN __fmulsu_exit
- ;; A1 = |A1|
- sbrc A1, 7
- neg A1
-#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
- ;; Some cores have problem skipping 2-word instruction
- tst A0
- brmi 1f
-#else
- sbrs A0, 7
-#endif /* __AVR_HAVE_JMP_CALL__ */
- XJMP __fmul
-1: XCALL __fmul
- ;; C = -C iff A0.7 = 1
- com C1
- neg C0
- sbci C1, -1
- ret
-ENDF __fmulsu_exit
-#endif /* L_fmulsu */
-
-
-#ifdef L_fmul
-;;; r22:r23 = fmul (r24, r25) like in FMUL instruction
-;;; Clobbers: r24, r25, __tmp_reg__
-DEFUN __fmul
- ; clear result
- clr C0
- clr C1
- clr A0
-1: tst B1
- ;; 1.0 = 0x80, so test for bit 7 of B to see if A must to be added to C.
-2: brpl 3f
- ;; C += A
- add C0, A0
- adc C1, A1
-3: ;; A >>= 1
- lsr A1
- ror A0
- ;; B <<= 1
- lsl B1
- brne 2b
- ret
-ENDF __fmul
-#endif /* L_fmul */
-
-#undef A0
-#undef A1
-#undef B1
-#undef C0
-#undef C1