/* -*- Mode: Asm -*- */
|
/* -*- Mode: Asm -*- */
|
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
Contributed by Denis Chertykov
|
Contributed by Denis Chertykov
|
|
|
This file is free software; you can redistribute it and/or modify it
|
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
|
under the terms of the GNU General Public License as published by the
|
Free Software Foundation; either version 2, or (at your option) any
|
Free Software Foundation; either version 2, or (at your option) any
|
later version.
|
later version.
|
|
|
In addition to the permissions in the GNU General Public License, the
|
In addition to the permissions in the GNU General Public License, the
|
Free Software Foundation gives you unlimited permission to link the
|
Free Software Foundation gives you unlimited permission to link the
|
compiled version of this file into combinations with other programs,
|
compiled version of this file into combinations with other programs,
|
and to distribute those combinations without any restriction coming
|
and to distribute those combinations without any restriction coming
|
from the use of this file. (The General Public License restrictions
|
from the use of this file. (The General Public License restrictions
|
do apply in other respects; for example, they cover modification of
|
do apply in other respects; for example, they cover modification of
|
the file, and distribution when not linked into a combine
|
the file, and distribution when not linked into a combine
|
executable.)
|
executable.)
|
|
|
This file is distributed in the hope that it will be useful, but
|
This file is distributed in the hope that it will be useful, but
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
General Public License for more details.
|
General Public License for more details.
|
|
|
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
along with this program; see the file COPYING. If not, write to
|
along with this program; see the file COPYING. If not, write to
|
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
Boston, MA 02110-1301, USA. */
|
Boston, MA 02110-1301, USA. */
|
|
|
#define __zero_reg__ r1
|
#define __zero_reg__ r1
|
#define __tmp_reg__ r0
|
#define __tmp_reg__ r0
|
#define __SREG__ 0x3f
|
#define __SREG__ 0x3f
|
#define __SP_H__ 0x3e
|
#define __SP_H__ 0x3e
|
#define __SP_L__ 0x3d
|
#define __SP_L__ 0x3d
|
|
|
/* Most of the functions here are called directly from avr.md
|
/* Most of the functions here are called directly from avr.md
|
patterns, instead of using the standard libcall mechanisms.
|
patterns, instead of using the standard libcall mechanisms.
|
This can make better code because GCC knows exactly which
|
This can make better code because GCC knows exactly which
|
of the call-used registers (not all of them) are clobbered. */
|
of the call-used registers (not all of them) are clobbered. */
|
|
|
.section .text.libgcc, "ax", @progbits
|
.section .text.libgcc, "ax", @progbits
|
|
|
.macro mov_l r_dest, r_src
|
.macro mov_l r_dest, r_src
|
#if defined (__AVR_HAVE_MOVW__)
|
#if defined (__AVR_HAVE_MOVW__)
|
movw \r_dest, \r_src
|
movw \r_dest, \r_src
|
#else
|
#else
|
mov \r_dest, \r_src
|
mov \r_dest, \r_src
|
#endif
|
#endif
|
.endm
|
.endm
|
|
|
.macro mov_h r_dest, r_src
|
.macro mov_h r_dest, r_src
|
#if defined (__AVR_HAVE_MOVW__)
|
#if defined (__AVR_HAVE_MOVW__)
|
; empty
|
; empty
|
#else
|
#else
|
mov \r_dest, \r_src
|
mov \r_dest, \r_src
|
#endif
|
#endif
|
.endm
|
.endm
|
|
|
/* Note: mulqi3, mulhi3 are open-coded on the enhanced core. */
|
/* Note: mulqi3, mulhi3 are open-coded on the enhanced core. */
|
#if !defined (__AVR_ENHANCED__)
|
#if !defined (__AVR_ENHANCED__)
|
/*******************************************************
|
/*******************************************************
|
Multiplication 8 x 8
|
Multiplication 8 x 8
|
*******************************************************/
|
*******************************************************/
|
#if defined (L_mulqi3)
|
#if defined (L_mulqi3)
|
|
|
#define r_arg2 r22 /* multiplicand */
|
#define r_arg2 r22 /* multiplicand */
|
#define r_arg1 r24 /* multiplier */
|
#define r_arg1 r24 /* multiplier */
|
#define r_res __tmp_reg__ /* result */
|
#define r_res __tmp_reg__ /* result */
|
|
|
.global __mulqi3
|
.global __mulqi3
|
.func __mulqi3
|
.func __mulqi3
|
__mulqi3:
|
__mulqi3:
|
clr r_res ; clear result
|
clr r_res ; clear result
|
__mulqi3_loop:
|
__mulqi3_loop:
|
sbrc r_arg1,0
|
sbrc r_arg1,0
|
add r_res,r_arg2
|
add r_res,r_arg2
|
add r_arg2,r_arg2 ; shift multiplicand
|
add r_arg2,r_arg2 ; shift multiplicand
|
breq __mulqi3_exit ; while multiplicand != 0
|
breq __mulqi3_exit ; while multiplicand != 0
|
lsr r_arg1 ;
|
lsr r_arg1 ;
|
brne __mulqi3_loop ; exit if multiplier = 0
|
brne __mulqi3_loop ; exit if multiplier = 0
|
__mulqi3_exit:
|
__mulqi3_exit:
|
mov r_arg1,r_res ; result to return register
|
mov r_arg1,r_res ; result to return register
|
ret
|
ret
|
|
|
#undef r_arg2
|
#undef r_arg2
|
#undef r_arg1
|
#undef r_arg1
|
#undef r_res
|
#undef r_res
|
|
|
.endfunc
|
.endfunc
|
#endif /* defined (L_mulqi3) */
|
#endif /* defined (L_mulqi3) */
|
|
|
#if defined (L_mulqihi3)
|
#if defined (L_mulqihi3)
|
.global __mulqihi3
|
.global __mulqihi3
|
.func __mulqihi3
|
.func __mulqihi3
|
__mulqihi3:
|
__mulqihi3:
|
clr r25
|
clr r25
|
sbrc r24, 7
|
sbrc r24, 7
|
dec r25
|
dec r25
|
clr r23
|
clr r23
|
sbrc r22, 7
|
sbrc r22, 7
|
dec r22
|
dec r22
|
rjmp __mulhi3
|
rjmp __mulhi3
|
.endfunc
|
.endfunc
|
#endif /* defined (L_mulqihi3) */
|
#endif /* defined (L_mulqihi3) */
|
|
|
#if defined (L_umulqihi3)
|
#if defined (L_umulqihi3)
|
.global __umulqihi3
|
.global __umulqihi3
|
.func __umulqihi3
|
.func __umulqihi3
|
__umulqihi3:
|
__umulqihi3:
|
clr r25
|
clr r25
|
clr r23
|
clr r23
|
rjmp __mulhi3
|
rjmp __mulhi3
|
.endfunc
|
.endfunc
|
#endif /* defined (L_umulqihi3) */
|
#endif /* defined (L_umulqihi3) */
|
|
|
/*******************************************************
|
/*******************************************************
|
Multiplication 16 x 16
|
Multiplication 16 x 16
|
*******************************************************/
|
*******************************************************/
|
#if defined (L_mulhi3)
|
#if defined (L_mulhi3)
|
#define r_arg1L r24 /* multiplier Low */
|
#define r_arg1L r24 /* multiplier Low */
|
#define r_arg1H r25 /* multiplier High */
|
#define r_arg1H r25 /* multiplier High */
|
#define r_arg2L r22 /* multiplicand Low */
|
#define r_arg2L r22 /* multiplicand Low */
|
#define r_arg2H r23 /* multiplicand High */
|
#define r_arg2H r23 /* multiplicand High */
|
#define r_resL __tmp_reg__ /* result Low */
|
#define r_resL __tmp_reg__ /* result Low */
|
#define r_resH r21 /* result High */
|
#define r_resH r21 /* result High */
|
|
|
.global __mulhi3
|
.global __mulhi3
|
.func __mulhi3
|
.func __mulhi3
|
__mulhi3:
|
__mulhi3:
|
clr r_resH ; clear result
|
clr r_resH ; clear result
|
clr r_resL ; clear result
|
clr r_resL ; clear result
|
__mulhi3_loop:
|
__mulhi3_loop:
|
sbrs r_arg1L,0
|
sbrs r_arg1L,0
|
rjmp __mulhi3_skip1
|
rjmp __mulhi3_skip1
|
add r_resL,r_arg2L ; result + multiplicand
|
add r_resL,r_arg2L ; result + multiplicand
|
adc r_resH,r_arg2H
|
adc r_resH,r_arg2H
|
__mulhi3_skip1:
|
__mulhi3_skip1:
|
add r_arg2L,r_arg2L ; shift multiplicand
|
add r_arg2L,r_arg2L ; shift multiplicand
|
adc r_arg2H,r_arg2H
|
adc r_arg2H,r_arg2H
|
|
|
cp r_arg2L,__zero_reg__
|
cp r_arg2L,__zero_reg__
|
cpc r_arg2H,__zero_reg__
|
cpc r_arg2H,__zero_reg__
|
breq __mulhi3_exit ; while multiplicand != 0
|
breq __mulhi3_exit ; while multiplicand != 0
|
|
|
lsr r_arg1H ; gets LSB of multiplier
|
lsr r_arg1H ; gets LSB of multiplier
|
ror r_arg1L
|
ror r_arg1L
|
sbiw r_arg1L,0
|
sbiw r_arg1L,0
|
brne __mulhi3_loop ; exit if multiplier = 0
|
brne __mulhi3_loop ; exit if multiplier = 0
|
__mulhi3_exit:
|
__mulhi3_exit:
|
mov r_arg1H,r_resH ; result to return register
|
mov r_arg1H,r_resH ; result to return register
|
mov r_arg1L,r_resL
|
mov r_arg1L,r_resL
|
ret
|
ret
|
|
|
#undef r_arg1L
|
#undef r_arg1L
|
#undef r_arg1H
|
#undef r_arg1H
|
#undef r_arg2L
|
#undef r_arg2L
|
#undef r_arg2H
|
#undef r_arg2H
|
#undef r_resL
|
#undef r_resL
|
#undef r_resH
|
#undef r_resH
|
|
|
.endfunc
|
.endfunc
|
#endif /* defined (L_mulhi3) */
|
#endif /* defined (L_mulhi3) */
|
#endif /* !defined (__AVR_ENHANCED__) */
|
#endif /* !defined (__AVR_ENHANCED__) */
|
|
|
#if defined (L_mulhisi3)
|
#if defined (L_mulhisi3)
|
.global __mulhisi3
|
.global __mulhisi3
|
.func __mulhisi3
|
.func __mulhisi3
|
__mulhisi3:
|
__mulhisi3:
|
mov_l r18, r24
|
mov_l r18, r24
|
mov_h r19, r25
|
mov_h r19, r25
|
clr r24
|
clr r24
|
sbrc r23, 7
|
sbrc r23, 7
|
dec r24
|
dec r24
|
mov r25, r24
|
mov r25, r24
|
clr r20
|
clr r20
|
sbrc r19, 7
|
sbrc r19, 7
|
dec r20
|
dec r20
|
mov r21, r20
|
mov r21, r20
|
rjmp __mulsi3
|
rjmp __mulsi3
|
.endfunc
|
.endfunc
|
#endif /* defined (L_mulhisi3) */
|
#endif /* defined (L_mulhisi3) */
|
|
|
#if defined (L_umulhisi3)
|
#if defined (L_umulhisi3)
|
.global __umulhisi3
|
.global __umulhisi3
|
.func __umulhisi3
|
.func __umulhisi3
|
__umulhisi3:
|
__umulhisi3:
|
mov_l r18, r24
|
mov_l r18, r24
|
mov_h r19, r25
|
mov_h r19, r25
|
clr r24
|
clr r24
|
clr r25
|
clr r25
|
clr r20
|
clr r20
|
clr r21
|
clr r21
|
rjmp __mulsi3
|
rjmp __mulsi3
|
.endfunc
|
.endfunc
|
#endif /* defined (L_umulhisi3) */
|
#endif /* defined (L_umulhisi3) */
|
|
|
#if defined (L_mulsi3)
|
#if defined (L_mulsi3)
|
/*******************************************************
|
/*******************************************************
|
Multiplication 32 x 32
|
Multiplication 32 x 32
|
*******************************************************/
|
*******************************************************/
|
#define r_arg1L r22 /* multiplier Low */
|
#define r_arg1L r22 /* multiplier Low */
|
#define r_arg1H r23
|
#define r_arg1H r23
|
#define r_arg1HL r24
|
#define r_arg1HL r24
|
#define r_arg1HH r25 /* multiplier High */
|
#define r_arg1HH r25 /* multiplier High */
|
|
|
|
|
#define r_arg2L r18 /* multiplicand Low */
|
#define r_arg2L r18 /* multiplicand Low */
|
#define r_arg2H r19
|
#define r_arg2H r19
|
#define r_arg2HL r20
|
#define r_arg2HL r20
|
#define r_arg2HH r21 /* multiplicand High */
|
#define r_arg2HH r21 /* multiplicand High */
|
|
|
#define r_resL r26 /* result Low */
|
#define r_resL r26 /* result Low */
|
#define r_resH r27
|
#define r_resH r27
|
#define r_resHL r30
|
#define r_resHL r30
|
#define r_resHH r31 /* result High */
|
#define r_resHH r31 /* result High */
|
|
|
|
|
.global __mulsi3
|
.global __mulsi3
|
.func __mulsi3
|
.func __mulsi3
|
__mulsi3:
|
__mulsi3:
|
#if defined (__AVR_ENHANCED__)
|
#if defined (__AVR_ENHANCED__)
|
mul r_arg1L, r_arg2L
|
mul r_arg1L, r_arg2L
|
movw r_resL, r0
|
movw r_resL, r0
|
mul r_arg1H, r_arg2H
|
mul r_arg1H, r_arg2H
|
movw r_resHL, r0
|
movw r_resHL, r0
|
mul r_arg1HL, r_arg2L
|
mul r_arg1HL, r_arg2L
|
add r_resHL, r0
|
add r_resHL, r0
|
adc r_resHH, r1
|
adc r_resHH, r1
|
mul r_arg1L, r_arg2HL
|
mul r_arg1L, r_arg2HL
|
add r_resHL, r0
|
add r_resHL, r0
|
adc r_resHH, r1
|
adc r_resHH, r1
|
mul r_arg1HH, r_arg2L
|
mul r_arg1HH, r_arg2L
|
add r_resHH, r0
|
add r_resHH, r0
|
mul r_arg1HL, r_arg2H
|
mul r_arg1HL, r_arg2H
|
add r_resHH, r0
|
add r_resHH, r0
|
mul r_arg1H, r_arg2HL
|
mul r_arg1H, r_arg2HL
|
add r_resHH, r0
|
add r_resHH, r0
|
mul r_arg1L, r_arg2HH
|
mul r_arg1L, r_arg2HH
|
add r_resHH, r0
|
add r_resHH, r0
|
clr r_arg1HH ; use instead of __zero_reg__ to add carry
|
clr r_arg1HH ; use instead of __zero_reg__ to add carry
|
mul r_arg1H, r_arg2L
|
mul r_arg1H, r_arg2L
|
add r_resH, r0
|
add r_resH, r0
|
adc r_resHL, r1
|
adc r_resHL, r1
|
adc r_resHH, r_arg1HH ; add carry
|
adc r_resHH, r_arg1HH ; add carry
|
mul r_arg1L, r_arg2H
|
mul r_arg1L, r_arg2H
|
add r_resH, r0
|
add r_resH, r0
|
adc r_resHL, r1
|
adc r_resHL, r1
|
adc r_resHH, r_arg1HH ; add carry
|
adc r_resHH, r_arg1HH ; add carry
|
movw r_arg1L, r_resL
|
movw r_arg1L, r_resL
|
movw r_arg1HL, r_resHL
|
movw r_arg1HL, r_resHL
|
clr r1 ; __zero_reg__ clobbered by "mul"
|
clr r1 ; __zero_reg__ clobbered by "mul"
|
ret
|
ret
|
#else
|
#else
|
clr r_resHH ; clear result
|
clr r_resHH ; clear result
|
clr r_resHL ; clear result
|
clr r_resHL ; clear result
|
clr r_resH ; clear result
|
clr r_resH ; clear result
|
clr r_resL ; clear result
|
clr r_resL ; clear result
|
__mulsi3_loop:
|
__mulsi3_loop:
|
sbrs r_arg1L,0
|
sbrs r_arg1L,0
|
rjmp __mulsi3_skip1
|
rjmp __mulsi3_skip1
|
add r_resL,r_arg2L ; result + multiplicand
|
add r_resL,r_arg2L ; result + multiplicand
|
adc r_resH,r_arg2H
|
adc r_resH,r_arg2H
|
adc r_resHL,r_arg2HL
|
adc r_resHL,r_arg2HL
|
adc r_resHH,r_arg2HH
|
adc r_resHH,r_arg2HH
|
__mulsi3_skip1:
|
__mulsi3_skip1:
|
add r_arg2L,r_arg2L ; shift multiplicand
|
add r_arg2L,r_arg2L ; shift multiplicand
|
adc r_arg2H,r_arg2H
|
adc r_arg2H,r_arg2H
|
adc r_arg2HL,r_arg2HL
|
adc r_arg2HL,r_arg2HL
|
adc r_arg2HH,r_arg2HH
|
adc r_arg2HH,r_arg2HH
|
|
|
lsr r_arg1HH ; gets LSB of multiplier
|
lsr r_arg1HH ; gets LSB of multiplier
|
ror r_arg1HL
|
ror r_arg1HL
|
ror r_arg1H
|
ror r_arg1H
|
ror r_arg1L
|
ror r_arg1L
|
brne __mulsi3_loop
|
brne __mulsi3_loop
|
sbiw r_arg1HL,0
|
sbiw r_arg1HL,0
|
cpc r_arg1H,r_arg1L
|
cpc r_arg1H,r_arg1L
|
brne __mulsi3_loop ; exit if multiplier = 0
|
brne __mulsi3_loop ; exit if multiplier = 0
|
__mulsi3_exit:
|
__mulsi3_exit:
|
mov_h r_arg1HH,r_resHH ; result to return register
|
mov_h r_arg1HH,r_resHH ; result to return register
|
mov_l r_arg1HL,r_resHL
|
mov_l r_arg1HL,r_resHL
|
mov_h r_arg1H,r_resH
|
mov_h r_arg1H,r_resH
|
mov_l r_arg1L,r_resL
|
mov_l r_arg1L,r_resL
|
ret
|
ret
|
#endif /* !defined (__AVR_ENHANCED__) */
|
#endif /* !defined (__AVR_ENHANCED__) */
|
#undef r_arg1L
|
#undef r_arg1L
|
#undef r_arg1H
|
#undef r_arg1H
|
#undef r_arg1HL
|
#undef r_arg1HL
|
#undef r_arg1HH
|
#undef r_arg1HH
|
|
|
|
|
#undef r_arg2L
|
#undef r_arg2L
|
#undef r_arg2H
|
#undef r_arg2H
|
#undef r_arg2HL
|
#undef r_arg2HL
|
#undef r_arg2HH
|
#undef r_arg2HH
|
|
|
#undef r_resL
|
#undef r_resL
|
#undef r_resH
|
#undef r_resH
|
#undef r_resHL
|
#undef r_resHL
|
#undef r_resHH
|
#undef r_resHH
|
|
|
.endfunc
|
.endfunc
|
#endif /* defined (L_mulsi3) */
|
#endif /* defined (L_mulsi3) */
|
|
|
/*******************************************************
|
/*******************************************************
|
Division 8 / 8 => (result + remainder)
|
Division 8 / 8 => (result + remainder)
|
*******************************************************/
|
*******************************************************/
|
#define r_rem r25 /* remainder */
|
#define r_rem r25 /* remainder */
|
#define r_arg1 r24 /* dividend, quotient */
|
#define r_arg1 r24 /* dividend, quotient */
|
#define r_arg2 r22 /* divisor */
|
#define r_arg2 r22 /* divisor */
|
#define r_cnt r23 /* loop count */
|
#define r_cnt r23 /* loop count */
|
|
|
#if defined (L_udivmodqi4)
|
#if defined (L_udivmodqi4)
|
.global __udivmodqi4
|
.global __udivmodqi4
|
.func __udivmodqi4
|
.func __udivmodqi4
|
__udivmodqi4:
|
__udivmodqi4:
|
sub r_rem,r_rem ; clear remainder and carry
|
sub r_rem,r_rem ; clear remainder and carry
|
ldi r_cnt,9 ; init loop counter
|
ldi r_cnt,9 ; init loop counter
|
rjmp __udivmodqi4_ep ; jump to entry point
|
rjmp __udivmodqi4_ep ; jump to entry point
|
__udivmodqi4_loop:
|
__udivmodqi4_loop:
|
rol r_rem ; shift dividend into remainder
|
rol r_rem ; shift dividend into remainder
|
cp r_rem,r_arg2 ; compare remainder & divisor
|
cp r_rem,r_arg2 ; compare remainder & divisor
|
brcs __udivmodqi4_ep ; remainder <= divisor
|
brcs __udivmodqi4_ep ; remainder <= divisor
|
sub r_rem,r_arg2 ; restore remainder
|
sub r_rem,r_arg2 ; restore remainder
|
__udivmodqi4_ep:
|
__udivmodqi4_ep:
|
rol r_arg1 ; shift dividend (with CARRY)
|
rol r_arg1 ; shift dividend (with CARRY)
|
dec r_cnt ; decrement loop counter
|
dec r_cnt ; decrement loop counter
|
brne __udivmodqi4_loop
|
brne __udivmodqi4_loop
|
com r_arg1 ; complement result
|
com r_arg1 ; complement result
|
; because C flag was complemented in loop
|
; because C flag was complemented in loop
|
ret
|
ret
|
.endfunc
|
.endfunc
|
#endif /* defined (L_udivmodqi4) */
|
#endif /* defined (L_udivmodqi4) */
|
|
|
#if defined (L_divmodqi4)
|
#if defined (L_divmodqi4)
|
.global __divmodqi4
|
.global __divmodqi4
|
.func __divmodqi4
|
.func __divmodqi4
|
__divmodqi4:
|
__divmodqi4:
|
bst r_arg1,7 ; store sign of dividend
|
bst r_arg1,7 ; store sign of dividend
|
mov __tmp_reg__,r_arg1
|
mov __tmp_reg__,r_arg1
|
eor __tmp_reg__,r_arg2; r0.7 is sign of result
|
eor __tmp_reg__,r_arg2; r0.7 is sign of result
|
sbrc r_arg1,7
|
sbrc r_arg1,7
|
neg r_arg1 ; dividend negative : negate
|
neg r_arg1 ; dividend negative : negate
|
sbrc r_arg2,7
|
sbrc r_arg2,7
|
neg r_arg2 ; divisor negative : negate
|
neg r_arg2 ; divisor negative : negate
|
rcall __udivmodqi4 ; do the unsigned div/mod
|
rcall __udivmodqi4 ; do the unsigned div/mod
|
brtc __divmodqi4_1
|
brtc __divmodqi4_1
|
neg r_rem ; correct remainder sign
|
neg r_rem ; correct remainder sign
|
__divmodqi4_1:
|
__divmodqi4_1:
|
sbrc __tmp_reg__,7
|
sbrc __tmp_reg__,7
|
neg r_arg1 ; correct result sign
|
neg r_arg1 ; correct result sign
|
__divmodqi4_exit:
|
__divmodqi4_exit:
|
ret
|
ret
|
.endfunc
|
.endfunc
|
#endif /* defined (L_divmodqi4) */
|
#endif /* defined (L_divmodqi4) */
|
|
|
#undef r_rem
|
#undef r_rem
|
#undef r_arg1
|
#undef r_arg1
|
#undef r_arg2
|
#undef r_arg2
|
#undef r_cnt
|
#undef r_cnt
|
|
|
|
|
/*******************************************************
|
/*******************************************************
|
Division 16 / 16 => (result + remainder)
|
Division 16 / 16 => (result + remainder)
|
*******************************************************/
|
*******************************************************/
|
#define r_remL r26 /* remainder Low */
|
#define r_remL r26 /* remainder Low */
|
#define r_remH r27 /* remainder High */
|
#define r_remH r27 /* remainder High */
|
|
|
/* return: remainder */
|
/* return: remainder */
|
#define r_arg1L r24 /* dividend Low */
|
#define r_arg1L r24 /* dividend Low */
|
#define r_arg1H r25 /* dividend High */
|
#define r_arg1H r25 /* dividend High */
|
|
|
/* return: quotient */
|
/* return: quotient */
|
#define r_arg2L r22 /* divisor Low */
|
#define r_arg2L r22 /* divisor Low */
|
#define r_arg2H r23 /* divisor High */
|
#define r_arg2H r23 /* divisor High */
|
|
|
#define r_cnt r21 /* loop count */
|
#define r_cnt r21 /* loop count */
|
|
|
#if defined (L_udivmodhi4)
|
#if defined (L_udivmodhi4)
|
.global __udivmodhi4
|
.global __udivmodhi4
|
.func __udivmodhi4
|
.func __udivmodhi4
|
__udivmodhi4:
|
__udivmodhi4:
|
sub r_remL,r_remL
|
sub r_remL,r_remL
|
sub r_remH,r_remH ; clear remainder and carry
|
sub r_remH,r_remH ; clear remainder and carry
|
ldi r_cnt,17 ; init loop counter
|
ldi r_cnt,17 ; init loop counter
|
rjmp __udivmodhi4_ep ; jump to entry point
|
rjmp __udivmodhi4_ep ; jump to entry point
|
__udivmodhi4_loop:
|
__udivmodhi4_loop:
|
rol r_remL ; shift dividend into remainder
|
rol r_remL ; shift dividend into remainder
|
rol r_remH
|
rol r_remH
|
cp r_remL,r_arg2L ; compare remainder & divisor
|
cp r_remL,r_arg2L ; compare remainder & divisor
|
cpc r_remH,r_arg2H
|
cpc r_remH,r_arg2H
|
brcs __udivmodhi4_ep ; remainder < divisor
|
brcs __udivmodhi4_ep ; remainder < divisor
|
sub r_remL,r_arg2L ; restore remainder
|
sub r_remL,r_arg2L ; restore remainder
|
sbc r_remH,r_arg2H
|
sbc r_remH,r_arg2H
|
__udivmodhi4_ep:
|
__udivmodhi4_ep:
|
rol r_arg1L ; shift dividend (with CARRY)
|
rol r_arg1L ; shift dividend (with CARRY)
|
rol r_arg1H
|
rol r_arg1H
|
dec r_cnt ; decrement loop counter
|
dec r_cnt ; decrement loop counter
|
brne __udivmodhi4_loop
|
brne __udivmodhi4_loop
|
com r_arg1L
|
com r_arg1L
|
com r_arg1H
|
com r_arg1H
|
; div/mod results to return registers, as for the div() function
|
; div/mod results to return registers, as for the div() function
|
mov_l r_arg2L, r_arg1L ; quotient
|
mov_l r_arg2L, r_arg1L ; quotient
|
mov_h r_arg2H, r_arg1H
|
mov_h r_arg2H, r_arg1H
|
mov_l r_arg1L, r_remL ; remainder
|
mov_l r_arg1L, r_remL ; remainder
|
mov_h r_arg1H, r_remH
|
mov_h r_arg1H, r_remH
|
ret
|
ret
|
.endfunc
|
.endfunc
|
#endif /* defined (L_udivmodhi4) */
|
#endif /* defined (L_udivmodhi4) */
|
|
|
#if defined (L_divmodhi4)
|
#if defined (L_divmodhi4)
|
.global __divmodhi4
|
.global __divmodhi4
|
.func __divmodhi4
|
.func __divmodhi4
|
__divmodhi4:
|
__divmodhi4:
|
.global _div
|
.global _div
|
_div:
|
_div:
|
bst r_arg1H,7 ; store sign of dividend
|
bst r_arg1H,7 ; store sign of dividend
|
mov __tmp_reg__,r_arg1H
|
mov __tmp_reg__,r_arg1H
|
eor __tmp_reg__,r_arg2H ; r0.7 is sign of result
|
eor __tmp_reg__,r_arg2H ; r0.7 is sign of result
|
rcall __divmodhi4_neg1 ; dividend negative : negate
|
rcall __divmodhi4_neg1 ; dividend negative : negate
|
sbrc r_arg2H,7
|
sbrc r_arg2H,7
|
rcall __divmodhi4_neg2 ; divisor negative : negate
|
rcall __divmodhi4_neg2 ; divisor negative : negate
|
rcall __udivmodhi4 ; do the unsigned div/mod
|
rcall __udivmodhi4 ; do the unsigned div/mod
|
rcall __divmodhi4_neg1 ; correct remainder sign
|
rcall __divmodhi4_neg1 ; correct remainder sign
|
tst __tmp_reg__
|
tst __tmp_reg__
|
brpl __divmodhi4_exit
|
brpl __divmodhi4_exit
|
__divmodhi4_neg2:
|
__divmodhi4_neg2:
|
com r_arg2H
|
com r_arg2H
|
neg r_arg2L ; correct divisor/result sign
|
neg r_arg2L ; correct divisor/result sign
|
sbci r_arg2H,0xff
|
sbci r_arg2H,0xff
|
__divmodhi4_exit:
|
__divmodhi4_exit:
|
ret
|
ret
|
__divmodhi4_neg1:
|
__divmodhi4_neg1:
|
brtc __divmodhi4_exit
|
brtc __divmodhi4_exit
|
com r_arg1H
|
com r_arg1H
|
neg r_arg1L ; correct dividend/remainder sign
|
neg r_arg1L ; correct dividend/remainder sign
|
sbci r_arg1H,0xff
|
sbci r_arg1H,0xff
|
ret
|
ret
|
.endfunc
|
.endfunc
|
#endif /* defined (L_divmodhi4) */
|
#endif /* defined (L_divmodhi4) */
|
|
|
#undef r_remH
|
#undef r_remH
|
#undef r_remL
|
#undef r_remL
|
|
|
#undef r_arg1H
|
#undef r_arg1H
|
#undef r_arg1L
|
#undef r_arg1L
|
|
|
#undef r_arg2H
|
#undef r_arg2H
|
#undef r_arg2L
|
#undef r_arg2L
|
|
|
#undef r_cnt
|
#undef r_cnt
|
|
|
/*******************************************************
|
/*******************************************************
|
Division 32 / 32 => (result + remainder)
|
Division 32 / 32 => (result + remainder)
|
*******************************************************/
|
*******************************************************/
|
#define r_remHH r31 /* remainder High */
|
#define r_remHH r31 /* remainder High */
|
#define r_remHL r30
|
#define r_remHL r30
|
#define r_remH r27
|
#define r_remH r27
|
#define r_remL r26 /* remainder Low */
|
#define r_remL r26 /* remainder Low */
|
|
|
/* return: remainder */
|
/* return: remainder */
|
#define r_arg1HH r25 /* dividend High */
|
#define r_arg1HH r25 /* dividend High */
|
#define r_arg1HL r24
|
#define r_arg1HL r24
|
#define r_arg1H r23
|
#define r_arg1H r23
|
#define r_arg1L r22 /* dividend Low */
|
#define r_arg1L r22 /* dividend Low */
|
|
|
/* return: quotient */
|
/* return: quotient */
|
#define r_arg2HH r21 /* divisor High */
|
#define r_arg2HH r21 /* divisor High */
|
#define r_arg2HL r20
|
#define r_arg2HL r20
|
#define r_arg2H r19
|
#define r_arg2H r19
|
#define r_arg2L r18 /* divisor Low */
|
#define r_arg2L r18 /* divisor Low */
|
|
|
#define r_cnt __zero_reg__ /* loop count (0 after the loop!) */
|
#define r_cnt __zero_reg__ /* loop count (0 after the loop!) */
|
|
|
#if defined (L_udivmodsi4)
|
#if defined (L_udivmodsi4)
|
.global __udivmodsi4
|
.global __udivmodsi4
|
.func __udivmodsi4
|
.func __udivmodsi4
|
__udivmodsi4:
|
__udivmodsi4:
|
ldi r_remL, 33 ; init loop counter
|
ldi r_remL, 33 ; init loop counter
|
mov r_cnt, r_remL
|
mov r_cnt, r_remL
|
sub r_remL,r_remL
|
sub r_remL,r_remL
|
sub r_remH,r_remH ; clear remainder and carry
|
sub r_remH,r_remH ; clear remainder and carry
|
mov_l r_remHL, r_remL
|
mov_l r_remHL, r_remL
|
mov_h r_remHH, r_remH
|
mov_h r_remHH, r_remH
|
rjmp __udivmodsi4_ep ; jump to entry point
|
rjmp __udivmodsi4_ep ; jump to entry point
|
__udivmodsi4_loop:
|
__udivmodsi4_loop:
|
rol r_remL ; shift dividend into remainder
|
rol r_remL ; shift dividend into remainder
|
rol r_remH
|
rol r_remH
|
rol r_remHL
|
rol r_remHL
|
rol r_remHH
|
rol r_remHH
|
cp r_remL,r_arg2L ; compare remainder & divisor
|
cp r_remL,r_arg2L ; compare remainder & divisor
|
cpc r_remH,r_arg2H
|
cpc r_remH,r_arg2H
|
cpc r_remHL,r_arg2HL
|
cpc r_remHL,r_arg2HL
|
cpc r_remHH,r_arg2HH
|
cpc r_remHH,r_arg2HH
|
brcs __udivmodsi4_ep ; remainder <= divisor
|
brcs __udivmodsi4_ep ; remainder <= divisor
|
sub r_remL,r_arg2L ; restore remainder
|
sub r_remL,r_arg2L ; restore remainder
|
sbc r_remH,r_arg2H
|
sbc r_remH,r_arg2H
|
sbc r_remHL,r_arg2HL
|
sbc r_remHL,r_arg2HL
|
sbc r_remHH,r_arg2HH
|
sbc r_remHH,r_arg2HH
|
__udivmodsi4_ep:
|
__udivmodsi4_ep:
|
rol r_arg1L ; shift dividend (with CARRY)
|
rol r_arg1L ; shift dividend (with CARRY)
|
rol r_arg1H
|
rol r_arg1H
|
rol r_arg1HL
|
rol r_arg1HL
|
rol r_arg1HH
|
rol r_arg1HH
|
dec r_cnt ; decrement loop counter
|
dec r_cnt ; decrement loop counter
|
brne __udivmodsi4_loop
|
brne __udivmodsi4_loop
|
; __zero_reg__ now restored (r_cnt == 0)
|
; __zero_reg__ now restored (r_cnt == 0)
|
com r_arg1L
|
com r_arg1L
|
com r_arg1H
|
com r_arg1H
|
com r_arg1HL
|
com r_arg1HL
|
com r_arg1HH
|
com r_arg1HH
|
; div/mod results to return registers, as for the ldiv() function
|
; div/mod results to return registers, as for the ldiv() function
|
mov_l r_arg2L, r_arg1L ; quotient
|
mov_l r_arg2L, r_arg1L ; quotient
|
mov_h r_arg2H, r_arg1H
|
mov_h r_arg2H, r_arg1H
|
mov_l r_arg2HL, r_arg1HL
|
mov_l r_arg2HL, r_arg1HL
|
mov_h r_arg2HH, r_arg1HH
|
mov_h r_arg2HH, r_arg1HH
|
mov_l r_arg1L, r_remL ; remainder
|
mov_l r_arg1L, r_remL ; remainder
|
mov_h r_arg1H, r_remH
|
mov_h r_arg1H, r_remH
|
mov_l r_arg1HL, r_remHL
|
mov_l r_arg1HL, r_remHL
|
mov_h r_arg1HH, r_remHH
|
mov_h r_arg1HH, r_remHH
|
ret
|
ret
|
.endfunc
|
.endfunc
|
#endif /* defined (L_udivmodsi4) */
|
#endif /* defined (L_udivmodsi4) */
|
|
|
#if defined (L_divmodsi4)
|
#if defined (L_divmodsi4)
|
.global __divmodsi4
|
.global __divmodsi4
|
.func __divmodsi4
|
.func __divmodsi4
|
__divmodsi4:
|
__divmodsi4:
|
bst r_arg1HH,7 ; store sign of dividend
|
bst r_arg1HH,7 ; store sign of dividend
|
mov __tmp_reg__,r_arg1HH
|
mov __tmp_reg__,r_arg1HH
|
eor __tmp_reg__,r_arg2HH ; r0.7 is sign of result
|
eor __tmp_reg__,r_arg2HH ; r0.7 is sign of result
|
rcall __divmodsi4_neg1 ; dividend negative : negate
|
rcall __divmodsi4_neg1 ; dividend negative : negate
|
sbrc r_arg2HH,7
|
sbrc r_arg2HH,7
|
rcall __divmodsi4_neg2 ; divisor negative : negate
|
rcall __divmodsi4_neg2 ; divisor negative : negate
|
rcall __udivmodsi4 ; do the unsigned div/mod
|
rcall __udivmodsi4 ; do the unsigned div/mod
|
rcall __divmodsi4_neg1 ; correct remainder sign
|
rcall __divmodsi4_neg1 ; correct remainder sign
|
rol __tmp_reg__
|
rol __tmp_reg__
|
brcc __divmodsi4_exit
|
brcc __divmodsi4_exit
|
__divmodsi4_neg2:
|
__divmodsi4_neg2:
|
com r_arg2HH
|
com r_arg2HH
|
com r_arg2HL
|
com r_arg2HL
|
com r_arg2H
|
com r_arg2H
|
neg r_arg2L ; correct divisor/quotient sign
|
neg r_arg2L ; correct divisor/quotient sign
|
sbci r_arg2H,0xff
|
sbci r_arg2H,0xff
|
sbci r_arg2HL,0xff
|
sbci r_arg2HL,0xff
|
sbci r_arg2HH,0xff
|
sbci r_arg2HH,0xff
|
__divmodsi4_exit:
|
__divmodsi4_exit:
|
ret
|
ret
|
__divmodsi4_neg1:
|
__divmodsi4_neg1:
|
brtc __divmodsi4_exit
|
brtc __divmodsi4_exit
|
com r_arg1HH
|
com r_arg1HH
|
com r_arg1HL
|
com r_arg1HL
|
com r_arg1H
|
com r_arg1H
|
neg r_arg1L ; correct dividend/remainder sign
|
neg r_arg1L ; correct dividend/remainder sign
|
sbci r_arg1H, 0xff
|
sbci r_arg1H, 0xff
|
sbci r_arg1HL,0xff
|
sbci r_arg1HL,0xff
|
sbci r_arg1HH,0xff
|
sbci r_arg1HH,0xff
|
ret
|
ret
|
.endfunc
|
.endfunc
|
#endif /* defined (L_divmodsi4) */
|
#endif /* defined (L_divmodsi4) */
|
|
|
/**********************************
|
/**********************************
|
* This is a prologue subroutine
|
* This is a prologue subroutine
|
**********************************/
|
**********************************/
|
#if defined (L_prologue)
|
#if defined (L_prologue)
|
|
|
.global __prologue_saves__
|
.global __prologue_saves__
|
.func __prologue_saves__
|
.func __prologue_saves__
|
__prologue_saves__:
|
__prologue_saves__:
|
push r2
|
push r2
|
push r3
|
push r3
|
push r4
|
push r4
|
push r5
|
push r5
|
push r6
|
push r6
|
push r7
|
push r7
|
push r8
|
push r8
|
push r9
|
push r9
|
push r10
|
push r10
|
push r11
|
push r11
|
push r12
|
push r12
|
push r13
|
push r13
|
push r14
|
push r14
|
push r15
|
push r15
|
push r16
|
push r16
|
push r17
|
push r17
|
push r28
|
push r28
|
push r29
|
push r29
|
in r28,__SP_L__
|
in r28,__SP_L__
|
in r29,__SP_H__
|
in r29,__SP_H__
|
sub r28,r26
|
sub r28,r26
|
sbc r29,r27
|
sbc r29,r27
|
in __tmp_reg__,__SREG__
|
in __tmp_reg__,__SREG__
|
cli
|
cli
|
out __SP_H__,r29
|
out __SP_H__,r29
|
out __SREG__,__tmp_reg__
|
out __SREG__,__tmp_reg__
|
out __SP_L__,r28
|
out __SP_L__,r28
|
ijmp
|
ijmp
|
.endfunc
|
.endfunc
|
#endif /* defined (L_prologue) */
|
#endif /* defined (L_prologue) */
|
|
|
/*
|
/*
|
* This is an epilogue subroutine
|
* This is an epilogue subroutine
|
*/
|
*/
|
#if defined (L_epilogue)
|
#if defined (L_epilogue)
|
|
|
.global __epilogue_restores__
|
.global __epilogue_restores__
|
.func __epilogue_restores__
|
.func __epilogue_restores__
|
__epilogue_restores__:
|
__epilogue_restores__:
|
ldd r2,Y+18
|
ldd r2,Y+18
|
ldd r3,Y+17
|
ldd r3,Y+17
|
ldd r4,Y+16
|
ldd r4,Y+16
|
ldd r5,Y+15
|
ldd r5,Y+15
|
ldd r6,Y+14
|
ldd r6,Y+14
|
ldd r7,Y+13
|
ldd r7,Y+13
|
ldd r8,Y+12
|
ldd r8,Y+12
|
ldd r9,Y+11
|
ldd r9,Y+11
|
ldd r10,Y+10
|
ldd r10,Y+10
|
ldd r11,Y+9
|
ldd r11,Y+9
|
ldd r12,Y+8
|
ldd r12,Y+8
|
ldd r13,Y+7
|
ldd r13,Y+7
|
ldd r14,Y+6
|
ldd r14,Y+6
|
ldd r15,Y+5
|
ldd r15,Y+5
|
ldd r16,Y+4
|
ldd r16,Y+4
|
ldd r17,Y+3
|
ldd r17,Y+3
|
ldd r26,Y+2
|
ldd r26,Y+2
|
ldd r27,Y+1
|
ldd r27,Y+1
|
add r28,r30
|
add r28,r30
|
adc r29,__zero_reg__
|
adc r29,__zero_reg__
|
in __tmp_reg__,__SREG__
|
in __tmp_reg__,__SREG__
|
cli
|
cli
|
out __SP_H__,r29
|
out __SP_H__,r29
|
out __SREG__,__tmp_reg__
|
out __SREG__,__tmp_reg__
|
out __SP_L__,r28
|
out __SP_L__,r28
|
mov_l r28, r26
|
mov_l r28, r26
|
mov_h r29, r27
|
mov_h r29, r27
|
ret
|
ret
|
.endfunc
|
.endfunc
|
#endif /* defined (L_epilogue) */
|
#endif /* defined (L_epilogue) */
|
|
|
#ifdef L_exit
|
#ifdef L_exit
|
.section .fini9,"ax",@progbits
|
.section .fini9,"ax",@progbits
|
.global _exit
|
.global _exit
|
.func _exit
|
.func _exit
|
_exit:
|
_exit:
|
.weak exit
|
.weak exit
|
exit:
|
exit:
|
|
|
/* Code from .fini8 ... .fini1 sections inserted by ld script. */
|
/* Code from .fini8 ... .fini1 sections inserted by ld script. */
|
|
|
.section .fini0,"ax",@progbits
|
.section .fini0,"ax",@progbits
|
__stop_program:
|
__stop_program:
|
rjmp __stop_program
|
rjmp __stop_program
|
.endfunc
|
.endfunc
|
#endif /* defined (L_exit) */
|
#endif /* defined (L_exit) */
|
|
|
#ifdef L_cleanup
|
#ifdef L_cleanup
|
.weak _cleanup
|
.weak _cleanup
|
.func _cleanup
|
.func _cleanup
|
_cleanup:
|
_cleanup:
|
ret
|
ret
|
.endfunc
|
.endfunc
|
#endif /* defined (L_cleanup) */
|
#endif /* defined (L_cleanup) */
|
|
|
#ifdef L_tablejump
|
#ifdef L_tablejump
|
.global __tablejump2__
|
.global __tablejump2__
|
.func __tablejump2__
|
.func __tablejump2__
|
__tablejump2__:
|
__tablejump2__:
|
lsl r30
|
lsl r30
|
rol r31
|
rol r31
|
.global __tablejump__
|
.global __tablejump__
|
__tablejump__:
|
__tablejump__:
|
#if defined (__AVR_ENHANCED__)
|
#if defined (__AVR_ENHANCED__)
|
lpm __tmp_reg__, Z+
|
lpm __tmp_reg__, Z+
|
lpm r31, Z
|
lpm r31, Z
|
mov r30, __tmp_reg__
|
mov r30, __tmp_reg__
|
ijmp
|
ijmp
|
#else
|
#else
|
lpm
|
lpm
|
adiw r30, 1
|
adiw r30, 1
|
push r0
|
push r0
|
lpm
|
lpm
|
push r0
|
push r0
|
ret
|
ret
|
#endif
|
#endif
|
.endfunc
|
.endfunc
|
#endif /* defined (L_tablejump) */
|
#endif /* defined (L_tablejump) */
|
|
|
/* __do_copy_data is only necessary if there is anything in .data section.
|
/* __do_copy_data is only necessary if there is anything in .data section.
|
Does not use RAMPZ - crt*.o provides a replacement for >64K devices. */
|
Does not use RAMPZ - crt*.o provides a replacement for >64K devices. */
|
|
|
#ifdef L_copy_data
|
#ifdef L_copy_data
|
.section .init4,"ax",@progbits
|
.section .init4,"ax",@progbits
|
.global __do_copy_data
|
.global __do_copy_data
|
__do_copy_data:
|
__do_copy_data:
|
ldi r17, hi8(__data_end)
|
ldi r17, hi8(__data_end)
|
ldi r26, lo8(__data_start)
|
ldi r26, lo8(__data_start)
|
ldi r27, hi8(__data_start)
|
ldi r27, hi8(__data_start)
|
ldi r30, lo8(__data_load_start)
|
ldi r30, lo8(__data_load_start)
|
ldi r31, hi8(__data_load_start)
|
ldi r31, hi8(__data_load_start)
|
rjmp .do_copy_data_start
|
rjmp .do_copy_data_start
|
.do_copy_data_loop:
|
.do_copy_data_loop:
|
#if defined (__AVR_HAVE_LPMX__)
|
#if defined (__AVR_HAVE_LPMX__)
|
lpm r0, Z+
|
lpm r0, Z+
|
#else
|
#else
|
lpm
|
lpm
|
adiw r30, 1
|
adiw r30, 1
|
#endif
|
#endif
|
st X+, r0
|
st X+, r0
|
.do_copy_data_start:
|
.do_copy_data_start:
|
cpi r26, lo8(__data_end)
|
cpi r26, lo8(__data_end)
|
cpc r27, r17
|
cpc r27, r17
|
brne .do_copy_data_loop
|
brne .do_copy_data_loop
|
#endif /* L_copy_data */
|
#endif /* L_copy_data */
|
|
|
/* __do_clear_bss is only necessary if there is anything in .bss section. */
|
/* __do_clear_bss is only necessary if there is anything in .bss section. */
|
|
|
#ifdef L_clear_bss
|
#ifdef L_clear_bss
|
.section .init4,"ax",@progbits
|
.section .init4,"ax",@progbits
|
.global __do_clear_bss
|
.global __do_clear_bss
|
__do_clear_bss:
|
__do_clear_bss:
|
ldi r17, hi8(__bss_end)
|
ldi r17, hi8(__bss_end)
|
ldi r26, lo8(__bss_start)
|
ldi r26, lo8(__bss_start)
|
ldi r27, hi8(__bss_start)
|
ldi r27, hi8(__bss_start)
|
rjmp .do_clear_bss_start
|
rjmp .do_clear_bss_start
|
.do_clear_bss_loop:
|
.do_clear_bss_loop:
|
st X+, __zero_reg__
|
st X+, __zero_reg__
|
.do_clear_bss_start:
|
.do_clear_bss_start:
|
cpi r26, lo8(__bss_end)
|
cpi r26, lo8(__bss_end)
|
cpc r27, r17
|
cpc r27, r17
|
brne .do_clear_bss_loop
|
brne .do_clear_bss_loop
|
#endif /* L_clear_bss */
|
#endif /* L_clear_bss */
|
|
|
/* __do_global_ctors and __do_global_dtors are only necessary
|
/* __do_global_ctors and __do_global_dtors are only necessary
|
if there are any constructors/destructors. */
|
if there are any constructors/destructors. */
|
|
|
#if defined (__AVR_MEGA__)
|
#if defined (__AVR_MEGA__)
|
#define XCALL call
|
#define XCALL call
|
#else
|
#else
|
#define XCALL rcall
|
#define XCALL rcall
|
#endif
|
#endif
|
|
|
#ifdef L_ctors
|
#ifdef L_ctors
|
.section .init6,"ax",@progbits
|
.section .init6,"ax",@progbits
|
.global __do_global_ctors
|
.global __do_global_ctors
|
__do_global_ctors:
|
__do_global_ctors:
|
ldi r17, hi8(__ctors_start)
|
ldi r17, hi8(__ctors_start)
|
ldi r28, lo8(__ctors_end)
|
ldi r28, lo8(__ctors_end)
|
ldi r29, hi8(__ctors_end)
|
ldi r29, hi8(__ctors_end)
|
rjmp .do_global_ctors_start
|
rjmp .do_global_ctors_start
|
.do_global_ctors_loop:
|
.do_global_ctors_loop:
|
sbiw r28, 2
|
sbiw r28, 2
|
mov_h r31, r29
|
mov_h r31, r29
|
mov_l r30, r28
|
mov_l r30, r28
|
XCALL __tablejump__
|
XCALL __tablejump__
|
.do_global_ctors_start:
|
.do_global_ctors_start:
|
cpi r28, lo8(__ctors_start)
|
cpi r28, lo8(__ctors_start)
|
cpc r29, r17
|
cpc r29, r17
|
brne .do_global_ctors_loop
|
brne .do_global_ctors_loop
|
#endif /* L_ctors */
|
#endif /* L_ctors */
|
|
|
#ifdef L_dtors
|
#ifdef L_dtors
|
.section .fini6,"ax",@progbits
|
.section .fini6,"ax",@progbits
|
.global __do_global_dtors
|
.global __do_global_dtors
|
__do_global_dtors:
|
__do_global_dtors:
|
ldi r17, hi8(__dtors_end)
|
ldi r17, hi8(__dtors_end)
|
ldi r28, lo8(__dtors_start)
|
ldi r28, lo8(__dtors_start)
|
ldi r29, hi8(__dtors_start)
|
ldi r29, hi8(__dtors_start)
|
rjmp .do_global_dtors_start
|
rjmp .do_global_dtors_start
|
.do_global_dtors_loop:
|
.do_global_dtors_loop:
|
mov_h r31, r29
|
mov_h r31, r29
|
mov_l r30, r28
|
mov_l r30, r28
|
XCALL __tablejump__
|
XCALL __tablejump__
|
adiw r28, 2
|
adiw r28, 2
|
.do_global_dtors_start:
|
.do_global_dtors_start:
|
cpi r28, lo8(__dtors_end)
|
cpi r28, lo8(__dtors_end)
|
cpc r29, r17
|
cpc r29, r17
|
brne .do_global_dtors_loop
|
brne .do_global_dtors_loop
|
#endif /* L_dtors */
|
#endif /* L_dtors */
|
|
|
|
|