1 /* -*- Mode: Asm -*- */
2 /* Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009
3 Free Software Foundation, Inc.
4 Contributed by Denis Chertykov <chertykov@gmail.com>
6 This file is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
11 This file is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
25 #define __zero_reg__ r1
26 #define __tmp_reg__ r0
30 #define __RAMPZ__ 0x3B
33 /* Most of the functions here are called directly from avr.md
34 patterns, instead of using the standard libcall mechanisms.
35 This can make better code because GCC knows exactly which
36 of the call-used registers (not all of them) are clobbered. */
38 /* FIXME: At present, there is no SORT directive in the linker
39 script so that we must not assume that different modules
40 in the same input section like .libgcc.text.mul will be
41 located close together. Therefore, we cannot use
42 RCALL/RJMP to call a function like __udivmodhi4 from
43 __divmodhi4 and have to use lengthy XCALL/XJMP even
44 though they are in the same input section and all same
45 input sections together are small enough to reach every
46 location with a RCALL/RJMP instruction. */
48 .macro mov_l r_dest, r_src
49 #if defined (__AVR_HAVE_MOVW__)
56 .macro mov_h r_dest, r_src
57 #if defined (__AVR_HAVE_MOVW__)
64 .macro wmov r_dest, r_src
65 #if defined (__AVR_HAVE_MOVW__)
69 mov \r_dest+1, \r_src+1
73 #if defined (__AVR_HAVE_JMP_CALL__)
93 .section .text.libgcc.mul, "ax", @progbits
95 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
96 /* Note: mulqi3, mulhi3 are open-coded on the enhanced core. */
97 #if !defined (__AVR_HAVE_MUL__)
98 /*******************************************************
99 Multiplication 8 x 8 without MUL
100 *******************************************************/
101 #if defined (L_mulqi3)
103 #define r_arg2 r22 /* multiplicand */
104 #define r_arg1 r24 /* multiplier */
105 #define r_res __tmp_reg__ /* result */
108 clr r_res ; clear result
112 add r_arg2,r_arg2 ; shift multiplicand
113 breq __mulqi3_exit ; while multiplicand != 0
115 brne __mulqi3_loop ; exit if multiplier = 0
117 mov r_arg1,r_res ; result to return register
125 #endif /* defined (L_mulqi3) */
127 #if defined (L_mulqihi3)
137 #endif /* defined (L_mulqihi3) */
139 #if defined (L_umulqihi3)
145 #endif /* defined (L_umulqihi3) */
147 /*******************************************************
148 Multiplication 16 x 16 without MUL
149 *******************************************************/
150 #if defined (L_mulhi3)
151 #define r_arg1L r24 /* multiplier Low */
152 #define r_arg1H r25 /* multiplier High */
153 #define r_arg2L r22 /* multiplicand Low */
154 #define r_arg2H r23 /* multiplicand High */
155 #define r_resL __tmp_reg__ /* result Low */
156 #define r_resH r21 /* result High */
159 clr r_resH ; clear result
160 clr r_resL ; clear result
164 add r_resL,r_arg2L ; result + multiplicand
167 add r_arg2L,r_arg2L ; shift multiplicand
170 cp r_arg2L,__zero_reg__
171 cpc r_arg2H,__zero_reg__
172 breq __mulhi3_exit ; while multiplicand != 0
174 lsr r_arg1H ; gets LSB of multiplier
177 brne __mulhi3_loop ; exit if multiplier = 0
179 mov r_arg1H,r_resH ; result to return register
191 #endif /* defined (L_mulhi3) */
193 /*******************************************************
194 Widening Multiplication 32 = 16 x 16 without MUL
195 *******************************************************/
197 #if defined (L_mulhisi3)
199 ;;; FIXME: This is dead code (noone calls it)
212 #endif /* defined (L_mulhisi3) */
214 #if defined (L_umulhisi3)
216 ;;; FIXME: This is dead code (noone calls it)
225 #endif /* defined (L_umulhisi3) */
227 #if defined (L_mulsi3)
228 /*******************************************************
229 Multiplication 32 x 32 without MUL
230 *******************************************************/
231 #define r_arg1L r22 /* multiplier Low */
234 #define r_arg1HH r25 /* multiplier High */
236 #define r_arg2L r18 /* multiplicand Low */
239 #define r_arg2HH r21 /* multiplicand High */
241 #define r_resL r26 /* result Low */
244 #define r_resHH r31 /* result High */
247 clr r_resHH ; clear result
248 clr r_resHL ; clear result
249 clr r_resH ; clear result
250 clr r_resL ; clear result
254 add r_resL,r_arg2L ; result + multiplicand
259 add r_arg2L,r_arg2L ; shift multiplicand
261 adc r_arg2HL,r_arg2HL
262 adc r_arg2HH,r_arg2HH
264 lsr r_arg1HH ; gets LSB of multiplier
271 brne __mulsi3_loop ; exit if multiplier = 0
273 mov_h r_arg1HH,r_resHH ; result to return register
274 mov_l r_arg1HL,r_resHL
295 #endif /* defined (L_mulsi3) */
297 #endif /* !defined (__AVR_HAVE_MUL__) */
298 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
300 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
301 #if defined (__AVR_HAVE_MUL__)
316 /*******************************************************
317 Widening Multiplication 32 = 16 x 16
318 *******************************************************/
320 #if defined (L_mulhisi3)
321 ;;; R25:R22 = (signed long) R27:R26 * (signed long) R19:R18
322 ;;; C3:C0 = (signed long) A1:A0 * (signed long) B1:B0
323 ;;; Clobbers: __tmp_reg__
332 XJMP __usmulhisi3_tail
334 #endif /* L_mulhisi3 */
336 #if defined (L_usmulhisi3)
337 ;;; R25:R22 = (signed long) R27:R26 * (unsigned long) R19:R18
338 ;;; C3:C0 = (signed long) A1:A0 * (unsigned long) B1:B0
339 ;;; Clobbers: __tmp_reg__
345 DEFUN __usmulhisi3_tail
352 ENDF __usmulhisi3_tail
353 #endif /* L_usmulhisi3 */
355 #if defined (L_umulhisi3)
356 ;;; R25:R22 = (unsigned long) R27:R26 * (unsigned long) R19:R18
357 ;;; C3:C0 = (unsigned long) A1:A0 * (unsigned long) B1:B0
358 ;;; Clobbers: __tmp_reg__
373 #endif /* L_umulhisi3 */
375 /*******************************************************
376 Widening Multiplication 32 = 16 x 32
377 *******************************************************/
379 #if defined (L_mulshisi3)
380 ;;; R25:R22 = (signed long) R27:R26 * R21:R18
381 ;;; (C3:C0) = (signed long) A1:A0 * B3:B0
382 ;;; Clobbers: __tmp_reg__
384 #ifdef __AVR_ERRATA_SKIP_JMP_CALL__
385 ;; Some cores have problem skipping 2-word instruction
390 #endif /* __AVR_HAVE_JMP_CALL__ */
395 ;;; R25:R22 = (one-extended long) R27:R26 * R21:R18
396 ;;; (C3:C0) = (one-extended long) A1:A0 * B3:B0
397 ;;; Clobbers: __tmp_reg__
400 ;; One-extend R27:R26 (A1:A0)
405 #endif /* L_mulshisi3 */
407 #if defined (L_muluhisi3)
408 ;;; R25:R22 = (unsigned long) R27:R26 * R21:R18
409 ;;; (C3:C0) = (unsigned long) A1:A0 * B3:B0
410 ;;; Clobbers: __tmp_reg__
423 #endif /* L_muluhisi3 */
425 /*******************************************************
426 Multiplication 32 x 32
427 *******************************************************/
429 #if defined (L_mulsi3)
430 ;;; R25:R22 = R25:R22 * R21:R18
431 ;;; (C3:C0) = C3:C0 * B3:B0
432 ;;; Clobbers: R26, R27, __tmp_reg__
440 ;; A1:A0 now contains the high word of A
451 #endif /* L_mulsi3 */
466 #endif /* __AVR_HAVE_MUL__ */
468 /*******************************************************
469 Multiplication 24 x 24
470 *******************************************************/
472 #if defined (L_mulpsi3)
474 ;; A[0..2]: In: Multiplicand; Out: Product
479 ;; B[0..2]: In: Multiplier
484 #if defined (__AVR_HAVE_MUL__)
486 ;; C[0..2]: Expand Result
491 ;; R24:R22 *= R20:R18
492 ;; Clobbers: r21, r25, r26, r27, __tmp_reg__
501 mul AA2, B0 $ add C2, r0
502 mul AA0, B2 $ add C2, r0
514 #else /* !HAVE_MUL */
516 ;; C[0..2]: Expand Result
521 ;; R24:R22 *= R20:R18
522 ;; Clobbers: __tmp_reg__, R18, R19, R20, R21
530 0: ;; Shift N-th Bit of B[] into Carry. N = 24 - Loop
531 LSR B2 $ ror B1 $ ror B0
533 ;; If the N-th Bit of B[] was set...
536 ;; ...then add A[] * 2^N to the Result C[]
537 ADD C0,A0 $ adc C1,A1 $ adc C2,A2
539 1: ;; Multiply A[] by 2
540 LSL A0 $ rol A1 $ rol A2
542 ;; Loop until B[] is 0
543 subi B0,0 $ sbci B1,0 $ sbci B2,0
546 ;; Copy C[] to the return Register A[]
558 #endif /* HAVE_MUL */
568 #endif /* L_mulpsi3 */
570 #if defined (L_mulsqipsi3) && defined (__AVR_HAVE_MUL__)
572 ;; A[0..2]: In: Multiplicand
577 ;; BB: In: Multiplier
585 ;; C[] = A[] * sign_extend (BB)
613 #endif /* L_mulsqipsi3 && HAVE_MUL */
615 /*******************************************************
616 Multiplication 64 x 64
617 *******************************************************/
619 #if defined (L_muldi3)
623 ;; A[0..7]: In: Multiplicand
634 ;; B[0..7]: In: Multiplier
644 #if defined (__AVR_HAVE_MUL__)
646 ;; Define C[] for convenience
647 ;; Notice that parts of C[] overlap A[] respective B[]
658 ;; R25:R18 *= R17:R10
659 ;; Ordinary ABI-Function
667 ;; Counting in Words, we have to perform a 4 * 4 Multiplication
670 mul A7,B0 $ $ mov C7,r0
671 mul A0,B7 $ $ add C7,r0
672 mul A6,B1 $ $ add C7,r0
673 mul A6,B0 $ mov C6,r0 $ add C7,r1
674 mul B6,A1 $ $ add C7,r0
675 mul B6,A0 $ add C6,r0 $ adc C7,r1
678 mul A2,B4 $ add C6,r0 $ adc C7,r1
679 mul A3,B4 $ $ add C7,r0
680 mul A2,B5 $ $ add C7,r0
697 XCALL __umulhisi3 $ wmov C4,22 $ add C6,24 $ adc C7,25
707 XCALL __umulhisi3 $ add C4,22 $ adc C5,23 $ adc C6,24 $ adc C7,25
717 XCALL __umulhisi3 $ add C4,22 $ adc C5,23 $ adc C6,24 $ adc C7,25
721 XCALL __umulhisi3 $ $ $ add C6,22 $ adc C7,23
756 #else /* !HAVE_MUL */
770 ;; R25:R18 *= R17:R10
771 ;; Ordinary ABI-Function
787 0: ;; Rotate B[] right by 1 and set Carry to the N-th Bit of B[]
788 ;; where N = 64 - Loop.
789 ;; Notice that B[] = B[] >>> 64 so after this Routine has finished,
790 ;; B[] will have its initial Value again.
791 LSR B7 $ ror B6 $ ror B5 $ ror B4
792 ror B3 $ ror B2 $ ror B1 $ ror B0
794 ;; If the N-th Bit of B[] was set then...
796 ;; ...finish Rotation...
799 ;; ...and add A[] * 2^N to the Result C[]
800 ADD C0,A0 $ adc C1,A1 $ adc C2,A2 $ adc C3,A3
801 adc C4,A4 $ adc C5,A5 $ adc C6,A6 $ adc C7,A7
803 1: ;; Multiply A[] by 2
804 LSL A0 $ rol A1 $ rol A2 $ rol A3
805 rol A4 $ rol A5 $ rol A6 $ rol A7
810 ;; We expanded the Result in C[]
811 ;; Copy Result to the Return Register A[]
835 #endif /* HAVE_MUL */
855 #endif /* L_muldi3 */
857 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
860 .section .text.libgcc.div, "ax", @progbits
862 /*******************************************************
863 Division 8 / 8 => (result + remainder)
864 *******************************************************/
865 #define r_rem r25 /* remainder */
866 #define r_arg1 r24 /* dividend, quotient */
867 #define r_arg2 r22 /* divisor */
868 #define r_cnt r23 /* loop count */
870 #if defined (L_udivmodqi4)
872 sub r_rem,r_rem ; clear remainder and carry
873 ldi r_cnt,9 ; init loop counter
874 rjmp __udivmodqi4_ep ; jump to entry point
876 rol r_rem ; shift dividend into remainder
877 cp r_rem,r_arg2 ; compare remainder & divisor
878 brcs __udivmodqi4_ep ; remainder <= divisor
879 sub r_rem,r_arg2 ; restore remainder
881 rol r_arg1 ; shift dividend (with CARRY)
882 dec r_cnt ; decrement loop counter
883 brne __udivmodqi4_loop
884 com r_arg1 ; complement result
885 ; because C flag was complemented in loop
888 #endif /* defined (L_udivmodqi4) */
890 #if defined (L_divmodqi4)
892 bst r_arg1,7 ; store sign of dividend
893 mov __tmp_reg__,r_arg1
894 eor __tmp_reg__,r_arg2; r0.7 is sign of result
896 neg r_arg1 ; dividend negative : negate
898 neg r_arg2 ; divisor negative : negate
899 XCALL __udivmodqi4 ; do the unsigned div/mod
901 neg r_rem ; correct remainder sign
904 neg r_arg1 ; correct result sign
908 #endif /* defined (L_divmodqi4) */
916 /*******************************************************
917 Division 16 / 16 => (result + remainder)
918 *******************************************************/
919 #define r_remL r26 /* remainder Low */
920 #define r_remH r27 /* remainder High */
922 /* return: remainder */
923 #define r_arg1L r24 /* dividend Low */
924 #define r_arg1H r25 /* dividend High */
926 /* return: quotient */
927 #define r_arg2L r22 /* divisor Low */
928 #define r_arg2H r23 /* divisor High */
930 #define r_cnt r21 /* loop count */
932 #if defined (L_udivmodhi4)
935 sub r_remH,r_remH ; clear remainder and carry
936 ldi r_cnt,17 ; init loop counter
937 rjmp __udivmodhi4_ep ; jump to entry point
939 rol r_remL ; shift dividend into remainder
941 cp r_remL,r_arg2L ; compare remainder & divisor
943 brcs __udivmodhi4_ep ; remainder < divisor
944 sub r_remL,r_arg2L ; restore remainder
947 rol r_arg1L ; shift dividend (with CARRY)
949 dec r_cnt ; decrement loop counter
950 brne __udivmodhi4_loop
953 ; div/mod results to return registers, as for the div() function
954 mov_l r_arg2L, r_arg1L ; quotient
955 mov_h r_arg2H, r_arg1H
956 mov_l r_arg1L, r_remL ; remainder
957 mov_h r_arg1H, r_remH
960 #endif /* defined (L_udivmodhi4) */
962 #if defined (L_divmodhi4)
966 bst r_arg1H,7 ; store sign of dividend
967 mov __tmp_reg__,r_arg2H
969 com __tmp_reg__ ; r0.7 is sign of result
970 rcall __divmodhi4_neg1 ; dividend negative: negate
973 rcall __divmodhi4_neg2 ; divisor negative: negate
974 XCALL __udivmodhi4 ; do the unsigned div/mod
976 rcall __divmodhi4_neg2 ; correct remainder sign
977 brtc __divmodhi4_exit
979 ;; correct dividend/remainder sign
985 ;; correct divisor/result sign
992 #endif /* defined (L_divmodhi4) */
1005 /*******************************************************
1006 Division 24 / 24 => (result + remainder)
1007 *******************************************************/
1009 ;; A[0..2]: In: Dividend; Out: Quotient
1014 ;; B[0..2]: In: Divisor; Out: Remainder
1019 ;; C[0..2]: Expand remainder
1020 #define C0 __zero_reg__
1027 #if defined (L_udivmodpsi4)
1028 ;; R24:R22 = R24:R22 udiv R20:R18
1029 ;; R20:R18 = R24:R22 umod R20:R18
1030 ;; Clobbers: R21, R25, R26
1035 ; Clear remainder and carry. C0 is already 0
1038 ; jump to entry point
1039 rjmp __udivmodpsi4_start
1041 ; shift dividend into remainder
1045 ; compare remainder & divisor
1049 brcs __udivmodpsi4_start ; remainder <= divisor
1050 sub C0, B0 ; restore remainder
1053 __udivmodpsi4_start:
1054 ; shift dividend (with CARRY)
1058 ; decrement loop counter
1060 brne __udivmodpsi4_loop
1064 ; div/mod results to return registers
1069 clr __zero_reg__ ; C0
1072 #endif /* defined (L_udivmodpsi4) */
1074 #if defined (L_divmodpsi4)
1075 ;; R24:R22 = R24:R22 div R20:R18
1076 ;; R20:R18 = R24:R22 mod R20:R18
1077 ;; Clobbers: T, __tmp_reg__, R21, R25, R26
1080 ; R0.7 will contain the sign of the result:
1081 ; R0.7 = A.sign ^ B.sign
1083 ; T-flag = sign of dividend
1087 ; Adjust dividend's sign
1088 rcall __divmodpsi4_negA
1090 ; Adjust divisor's sign
1092 rcall __divmodpsi4_negB
1094 ; Do the unsigned div/mod
1097 ; Adjust quotient's sign
1099 rcall __divmodpsi4_negA
1101 ; Adjust remainder's sign
1102 brtc __divmodpsi4_end
1105 ; Correct divisor/remainder sign
1113 ; Correct dividend/quotient sign
1124 #endif /* defined (L_divmodpsi4) */
1140 /*******************************************************
1141 Division 32 / 32 => (result + remainder)
1142 *******************************************************/
1143 #define r_remHH r31 /* remainder High */
1146 #define r_remL r26 /* remainder Low */
1148 /* return: remainder */
1149 #define r_arg1HH r25 /* dividend High */
1150 #define r_arg1HL r24
1152 #define r_arg1L r22 /* dividend Low */
1154 /* return: quotient */
1155 #define r_arg2HH r21 /* divisor High */
1156 #define r_arg2HL r20
1158 #define r_arg2L r18 /* divisor Low */
1160 #define r_cnt __zero_reg__ /* loop count (0 after the loop!) */
1162 #if defined (L_udivmodsi4)
1164 ldi r_remL, 33 ; init loop counter
1167 sub r_remH,r_remH ; clear remainder and carry
1168 mov_l r_remHL, r_remL
1169 mov_h r_remHH, r_remH
1170 rjmp __udivmodsi4_ep ; jump to entry point
1172 rol r_remL ; shift dividend into remainder
1176 cp r_remL,r_arg2L ; compare remainder & divisor
1178 cpc r_remHL,r_arg2HL
1179 cpc r_remHH,r_arg2HH
1180 brcs __udivmodsi4_ep ; remainder <= divisor
1181 sub r_remL,r_arg2L ; restore remainder
1183 sbc r_remHL,r_arg2HL
1184 sbc r_remHH,r_arg2HH
1186 rol r_arg1L ; shift dividend (with CARRY)
1190 dec r_cnt ; decrement loop counter
1191 brne __udivmodsi4_loop
1192 ; __zero_reg__ now restored (r_cnt == 0)
1197 ; div/mod results to return registers, as for the ldiv() function
1198 mov_l r_arg2L, r_arg1L ; quotient
1199 mov_h r_arg2H, r_arg1H
1200 mov_l r_arg2HL, r_arg1HL
1201 mov_h r_arg2HH, r_arg1HH
1202 mov_l r_arg1L, r_remL ; remainder
1203 mov_h r_arg1H, r_remH
1204 mov_l r_arg1HL, r_remHL
1205 mov_h r_arg1HH, r_remHH
1208 #endif /* defined (L_udivmodsi4) */
1210 #if defined (L_divmodsi4)
1212 mov __tmp_reg__,r_arg2HH
1213 bst r_arg1HH,7 ; store sign of dividend
1215 com __tmp_reg__ ; r0.7 is sign of result
1216 rcall __divmodsi4_neg1 ; dividend negative: negate
1219 rcall __divmodsi4_neg2 ; divisor negative: negate
1220 XCALL __udivmodsi4 ; do the unsigned div/mod
1221 sbrc __tmp_reg__, 7 ; correct quotient sign
1222 rcall __divmodsi4_neg2
1223 brtc __divmodsi4_exit ; correct remainder sign
1225 ;; correct dividend/remainder sign
1235 ;; correct divisor/quotient sign
1246 #endif /* defined (L_divmodsi4) */
1249 /*******************************************************
1252 *******************************************************/
1254 ;; Use Speed-optimized Version on "big" Devices, i.e. Devices with
1255 ;; at least 16k of Program Memory. For smaller Devices, depend
1256 ;; on MOVW and SP Size. There is a Connexion between SP Size and
1257 ;; Flash Size so that SP Size can be used to test for Flash Size.
1259 #if defined (__AVR_HAVE_JMP_CALL__)
1260 # define SPEED_DIV 8
1261 #elif defined (__AVR_HAVE_MOVW__) && !defined (__AVR_HAVE_8BIT_SP__)
1262 # define SPEED_DIV 16
1264 # define SPEED_DIV 0
1267 ;; A[0..7]: In: Dividend;
1268 ;; Out: Quotient (T = 0)
1269 ;; Out: Remainder (T = 1)
1279 ;; B[0..7]: In: Divisor; Out: Clobber
1289 ;; C[0..7]: Expand remainder; Out: Remainder (unused)
1299 ;; Holds Signs during Division Routine
1300 #define SS __tmp_reg__
1302 ;; Bit-Counter in Division Routine
1303 #define R_cnt __zero_reg__
1305 ;; Scratch Register for Negation
1308 #if defined (L_udivdi3)
1310 ;; R25:R18 = R24:R18 umod R17:R10
1311 ;; Ordinary ABI-Function
1315 rjmp __udivdi3_umoddi3
1318 ;; R25:R18 = R24:R18 udiv R17:R10
1319 ;; Ordinary ABI-Function
1325 DEFUN __udivdi3_umoddi3
1336 ENDF __udivdi3_umoddi3
1337 #endif /* L_udivdi3 */
1339 #if defined (L_udivmod64)
1341 ;; Worker Routine for 64-Bit unsigned Quotient and Remainder Computation
1342 ;; No Registers saved/restored; the Callers will take Care.
1343 ;; Preserves B[] and T-flag
1344 ;; T = 0: Compute Quotient in A[]
1345 ;; T = 1: Compute Remainder in A[] and shift SS one Bit left
1349 ;; Clear Remainder (C6, C7 will follow)
1356 #if SPEED_DIV == 0 || SPEED_DIV == 16
1357 ;; Initialize Loop-Counter
1360 #endif /* SPEED_DIV */
1367 1: ;; Compare shifted Devidend against Divisor
1368 ;; If -- even after Shifting -- it is smaller...
1369 CP A7,B0 $ cpc C0,B1 $ cpc C1,B2 $ cpc C2,B3
1370 cpc C3,B4 $ cpc C4,B5 $ cpc C5,B6 $ cpc C6,B7
1373 ;; ...then we can subtract it. Thus, it is legal to shift left
1374 $ mov C6,C5 $ mov C5,C4 $ mov C4,C3
1375 mov C3,C2 $ mov C2,C1 $ mov C1,C0 $ mov C0,A7
1376 mov A7,A6 $ mov A6,A5 $ mov A5,A4 $ mov A4,A3
1377 mov A3,A2 $ mov A2,A1 $ mov A1,A0 $ clr A0
1383 ;; Shifted 64 Bits: A7 has traveled to C7
1385 ;; Divisor is greater than Dividend. We have:
1388 ;; Thus, we can return immediately
1391 2: ;; Initialze Bit-Counter with Number of Bits still to be performed
1394 ;; Push of A7 is not needed because C7 is still 0
1398 #elif SPEED_DIV == 16
1400 ;; Compare shifted Dividend against Divisor
1408 ;; Divisor is greater than shifted Dividen: We can shift the Dividend
1409 ;; and it is still smaller than the Divisor --> Shift one 32-Bit Chunk
1410 wmov C2,A6 $ wmov C0,A4
1411 wmov A6,A2 $ wmov A4,A0
1412 wmov A2,C6 $ wmov A0,C4
1414 ;; Set Bit Counter to 32
1418 #error SPEED_DIV = ?
1419 #endif /* SPEED_DIV */
1421 ;; The very Division + Remainder Routine
1423 3: ;; Left-shift Dividend...
1424 lsl A0 $ rol A1 $ rol A2 $ rol A3
1425 rol A4 $ rol A5 $ rol A6 $ rol A7
1427 ;; ...into Remainder
1428 rol C0 $ rol C1 $ rol C2 $ rol C3
1429 rol C4 $ rol C5 $ rol C6 $ rol C7
1431 ;; Compare Remainder and Divisor
1432 CP C0,B0 $ cpc C1,B1 $ cpc C2,B2 $ cpc C3,B3
1433 cpc C4,B4 $ cpc C5,B5 $ cpc C6,B6 $ cpc C7,B7
1437 ;; Divisor fits into Remainder: Subtract it from Remainder...
1438 SUB C0,B0 $ sbc C1,B1 $ sbc C2,B2 $ sbc C3,B3
1439 sbc C4,B4 $ sbc C5,B5 $ sbc C6,B6 $ sbc C7,B7
1441 ;; ...and set according Bit in the upcoming Quotient
1442 ;; The Bit will travel to its final Position
1445 4: ;; This Bit is done
1448 ;; __zero_reg__ is 0 again
1450 ;; T = 0: We are fine with the Quotient in A[]
1451 ;; T = 1: Copy Remainder to A[]
1457 ;; Move the Sign of the Result to SS.7
1463 #endif /* L_udivmod64 */
1466 #if defined (L_divdi3)
1468 ;; R25:R18 = R24:R18 mod R17:R10
1469 ;; Ordinary ABI-Function
1473 rjmp __divdi3_moddi3
1476 ;; R25:R18 = R24:R18 div R17:R10
1477 ;; Ordinary ABI-Function
1483 DEFUN __divdi3_moddi3
1488 ;; Both Signs are 0: the following Complexitiy is not needed
1489 XJMP __udivdi3_umoddi3
1490 #endif /* SPEED_DIV */
1493 ;; Save 12 Registers: Y, 17...8
1494 ;; No Frame needed (X = 0)
1497 ldi r30, lo8(gs(1f))
1498 ldi r31, hi8(gs(1f))
1499 XJMP __prologue_saves__ + ((18 - 12) * 2)
1501 1: ;; SS.7 will contain the Sign of the Quotient (A.sign * B.sign)
1502 ;; SS.6 will contain the Sign of the Remainder (A.sign)
1505 ;; Adjust Dividend's Sign as needed
1507 ;; Compiling for Speed we know that at least one Sign must be < 0
1508 ;; Thus, if A[] >= 0 then we know B[] < 0
1512 #endif /* SPEED_DIV */
1516 ;; Adjust Divisor's Sign and SS.7 as needed
1523 com B4 $ com B5 $ com B6 $ com B7
1524 $ com B1 $ com B2 $ com B3
1526 $ sbc B1,NN $ sbc B2,NN $ sbc B3,NN
1527 sbc B4,NN $ sbc B5,NN $ sbc B6,NN $ sbc B7,NN
1529 3: ;; Do the unsigned 64-Bit Division/Modulo (depending on T-flag)
1532 ;; Adjust Result's Sign
1533 #ifdef __AVR_ERRATA_SKIP_JMP_CALL__
1538 #endif /* __AVR_HAVE_JMP_CALL__ */
1541 4: ;; Epilogue: Restore the Z = 12 Registers and return
1543 #if defined (__AVR_HAVE_8BIT_SP__)
1547 #endif /* #SP = 8/16 */
1549 XJMP __epilogue_restores__ + ((18 - 12) * 2)
1551 ENDF __divdi3_moddi3
1557 #endif /* L_divdi3 */
1559 .section .text.libgcc, "ax", @progbits
1561 #define TT __tmp_reg__
1563 #if defined (L_adddi3)
1565 ;; (plus:DI (reg:DI 18)
1568 ADD A0,B0 $ adc A1,B1 $ adc A2,B2 $ adc A3,B3
1569 adc A4,B4 $ adc A5,B5 $ adc A6,B6 $ adc A7,B7
1572 #endif /* L_adddi3 */
1574 #if defined (L_adddi3_s8)
1576 ;; (plus:DI (reg:DI 18)
1577 ;; (sign_extend:SI (reg:QI 26))))
1582 ADD A0,r26 $ adc A1,TT $ adc A2,TT $ adc A3,TT
1583 adc A4,TT $ adc A5,TT $ adc A6,TT $ adc A7,TT
1586 #endif /* L_adddi3_s8 */
1588 #if defined (L_subdi3)
1590 ;; (minus:DI (reg:DI 18)
1593 SUB A0,B0 $ sbc A1,B1 $ sbc A2,B2 $ sbc A3,B3
1594 sbc A4,B4 $ sbc A5,B5 $ sbc A6,B6 $ sbc A7,B7
1597 #endif /* L_subdi3 */
1599 #if defined (L_cmpdi2)
1601 ;; (compare (reg:DI 18)
1604 CP A0,B0 $ cpc A1,B1 $ cpc A2,B2 $ cpc A3,B3
1605 cpc A4,B4 $ cpc A5,B5 $ cpc A6,B6 $ cpc A7,B7
1608 #endif /* L_cmpdi2 */
1610 #if defined (L_cmpdi2_s8)
1612 ;; (compare (reg:DI 18)
1613 ;; (sign_extend:SI (reg:QI 26))))
1618 CP A0,r26 $ cpc A1,TT $ cpc A2,TT $ cpc A3,TT
1619 cpc A4,TT $ cpc A5,TT $ cpc A6,TT $ cpc A7,TT
1622 #endif /* L_cmpdi2_s8 */
1624 #if defined (L_negdi2)
1627 com A4 $ com A5 $ com A6 $ com A7
1628 $ com A1 $ com A2 $ com A3
1630 $ sbci A1,-1 $ sbci A2,-1 $ sbci A3,-1
1631 sbci A4,-1 $ sbci A5,-1 $ sbci A6,-1 $ sbci A7,-1
1635 #endif /* L_negdi2 */
1667 .section .text.libgcc.prologue, "ax", @progbits
1669 /**********************************
1670 * This is a prologue subroutine
1671 **********************************/
1672 #if defined (L_prologue)
1674 ;; This function does not clobber T-flag; 64-bit division relies on it
1675 DEFUN __prologue_saves__
1694 #if defined (__AVR_HAVE_8BIT_SP__)
1699 #elif defined (__AVR_XMEGA__)
1711 in __tmp_reg__,__SREG__
1714 out __SREG__,__tmp_reg__
1716 #endif /* #SP = 8/16 */
1718 #if defined (__AVR_HAVE_EIJMP_EICALL__)
1724 ENDF __prologue_saves__
1725 #endif /* defined (L_prologue) */
1728 * This is an epilogue subroutine
1730 #if defined (L_epilogue)
1732 DEFUN __epilogue_restores__
1750 #if defined (__AVR_HAVE_8BIT_SP__)
1755 #elif defined (__AVR_XMEGA__)
1758 adc r29,__zero_reg__
1765 adc r29,__zero_reg__
1766 in __tmp_reg__,__SREG__
1769 out __SREG__,__tmp_reg__
1773 #endif /* #SP = 8/16 */
1775 ENDF __epilogue_restores__
1776 #endif /* defined (L_epilogue) */
1779 .section .fini9,"ax",@progbits
1785 /* Code from .fini8 ... .fini1 sections inserted by ld script. */
1787 .section .fini0,"ax",@progbits
1791 #endif /* defined (L_exit) */
1799 #endif /* defined (L_cleanup) */
1802 .section .text.libgcc, "ax", @progbits
1805 DEFUN __tablejump2__
1812 #if defined (__AVR_HAVE_LPMX__)
1815 mov r30, __tmp_reg__
1816 #if defined (__AVR_HAVE_EIJMP_EICALL__)
1822 #else /* !HAVE_LPMX */
1828 #if defined (__AVR_HAVE_EIJMP_EICALL__)
1829 in __tmp_reg__, __EIND__
1833 #endif /* !HAVE_LPMX */
1835 #endif /* defined (L_tablejump) */
1838 .section .init4,"ax",@progbits
1839 DEFUN __do_copy_data
1840 #if defined(__AVR_HAVE_ELPMX__)
1841 ldi r17, hi8(__data_end)
1842 ldi r26, lo8(__data_start)
1843 ldi r27, hi8(__data_start)
1844 ldi r30, lo8(__data_load_start)
1845 ldi r31, hi8(__data_load_start)
1846 ldi r16, hh8(__data_load_start)
1848 rjmp .L__do_copy_data_start
1849 .L__do_copy_data_loop:
1852 .L__do_copy_data_start:
1853 cpi r26, lo8(__data_end)
1855 brne .L__do_copy_data_loop
1856 #elif !defined(__AVR_HAVE_ELPMX__) && defined(__AVR_HAVE_ELPM__)
1857 ldi r17, hi8(__data_end)
1858 ldi r26, lo8(__data_start)
1859 ldi r27, hi8(__data_start)
1860 ldi r30, lo8(__data_load_start)
1861 ldi r31, hi8(__data_load_start)
1862 ldi r16, hh8(__data_load_start - 0x10000)
1863 .L__do_copy_data_carry:
1866 rjmp .L__do_copy_data_start
1867 .L__do_copy_data_loop:
1871 brcs .L__do_copy_data_carry
1872 .L__do_copy_data_start:
1873 cpi r26, lo8(__data_end)
1875 brne .L__do_copy_data_loop
1876 #elif !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__)
1877 ldi r17, hi8(__data_end)
1878 ldi r26, lo8(__data_start)
1879 ldi r27, hi8(__data_start)
1880 ldi r30, lo8(__data_load_start)
1881 ldi r31, hi8(__data_load_start)
1882 rjmp .L__do_copy_data_start
1883 .L__do_copy_data_loop:
1884 #if defined (__AVR_HAVE_LPMX__)
1891 .L__do_copy_data_start:
1892 cpi r26, lo8(__data_end)
1894 brne .L__do_copy_data_loop
1895 #endif /* !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__) */
1896 #if defined (__AVR_HAVE_ELPM__) && defined (__AVR_HAVE_RAMPD__)
1897 ;; Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM
1898 out __RAMPZ__, __zero_reg__
1899 #endif /* ELPM && RAMPD */
1901 #endif /* L_copy_data */
1903 /* __do_clear_bss is only necessary if there is anything in .bss section. */
1906 .section .init4,"ax",@progbits
1907 DEFUN __do_clear_bss
1908 ldi r17, hi8(__bss_end)
1909 ldi r26, lo8(__bss_start)
1910 ldi r27, hi8(__bss_start)
1911 rjmp .do_clear_bss_start
1914 .do_clear_bss_start:
1915 cpi r26, lo8(__bss_end)
1917 brne .do_clear_bss_loop
1919 #endif /* L_clear_bss */
1921 /* __do_global_ctors and __do_global_dtors are only necessary
1922 if there are any constructors/destructors. */
1925 .section .init6,"ax",@progbits
1926 DEFUN __do_global_ctors
1927 #if defined(__AVR_HAVE_ELPM__)
1928 ldi r17, hi8(__ctors_start)
1929 ldi r28, lo8(__ctors_end)
1930 ldi r29, hi8(__ctors_end)
1931 ldi r16, hh8(__ctors_end)
1932 rjmp .L__do_global_ctors_start
1933 .L__do_global_ctors_loop:
1935 sbc r16, __zero_reg__
1939 XCALL __tablejump_elpm__
1940 .L__do_global_ctors_start:
1941 cpi r28, lo8(__ctors_start)
1943 ldi r24, hh8(__ctors_start)
1945 brne .L__do_global_ctors_loop
1947 ldi r17, hi8(__ctors_start)
1948 ldi r28, lo8(__ctors_end)
1949 ldi r29, hi8(__ctors_end)
1950 rjmp .L__do_global_ctors_start
1951 .L__do_global_ctors_loop:
1956 .L__do_global_ctors_start:
1957 cpi r28, lo8(__ctors_start)
1959 brne .L__do_global_ctors_loop
1960 #endif /* defined(__AVR_HAVE_ELPM__) */
1961 ENDF __do_global_ctors
1962 #endif /* L_ctors */
1965 .section .fini6,"ax",@progbits
1966 DEFUN __do_global_dtors
1967 #if defined(__AVR_HAVE_ELPM__)
1968 ldi r17, hi8(__dtors_end)
1969 ldi r28, lo8(__dtors_start)
1970 ldi r29, hi8(__dtors_start)
1971 ldi r16, hh8(__dtors_start)
1972 rjmp .L__do_global_dtors_start
1973 .L__do_global_dtors_loop:
1975 sbc r16, __zero_reg__
1979 XCALL __tablejump_elpm__
1980 .L__do_global_dtors_start:
1981 cpi r28, lo8(__dtors_end)
1983 ldi r24, hh8(__dtors_end)
1985 brne .L__do_global_dtors_loop
1987 ldi r17, hi8(__dtors_end)
1988 ldi r28, lo8(__dtors_start)
1989 ldi r29, hi8(__dtors_start)
1990 rjmp .L__do_global_dtors_start
1991 .L__do_global_dtors_loop:
1996 .L__do_global_dtors_start:
1997 cpi r28, lo8(__dtors_end)
1999 brne .L__do_global_dtors_loop
2000 #endif /* defined(__AVR_HAVE_ELPM__) */
2001 ENDF __do_global_dtors
2002 #endif /* L_dtors */
2004 .section .text.libgcc, "ax", @progbits
2006 #ifdef L_tablejump_elpm
2007 DEFUN __tablejump_elpm__
2008 #if defined (__AVR_HAVE_ELPMX__)
2009 elpm __tmp_reg__, Z+
2011 mov r30, __tmp_reg__
2012 #if defined (__AVR_HAVE_RAMPD__)
2013 ;; Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM
2014 out __RAMPZ__, __zero_reg__
2016 #if defined (__AVR_HAVE_EIJMP_EICALL__)
2022 #elif defined (__AVR_HAVE_ELPM__)
2028 #if defined (__AVR_HAVE_EIJMP_EICALL__)
2029 in __tmp_reg__, __EIND__
2034 ENDF __tablejump_elpm__
2035 #endif /* defined (L_tablejump_elpm) */
2037 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2038 ;; Loading n bytes from Flash; n = 3,4
2039 ;; R22... = Flash[Z]
2040 ;; Clobbers: __tmp_reg__
2042 #if (defined (L_load_3) \
2043 || defined (L_load_4)) \
2044 && !defined (__AVR_HAVE_LPMX__)
2052 .macro .load dest, n
2055 .if \dest != D0+\n-1
2062 #if defined (L_load_3)
2069 #endif /* L_load_3 */
2071 #if defined (L_load_4)
2079 #endif /* L_load_4 */
2081 #endif /* L_load_3 || L_load_3 */
2083 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2084 ;; Loading n bytes from Flash or RAM; n = 1,2,3,4
2085 ;; R22... = Flash[R21:Z] or RAM[Z] depending on R21.7
2086 ;; Clobbers: __tmp_reg__, R21, R30, R31
2088 #if (defined (L_xload_1) \
2089 || defined (L_xload_2) \
2090 || defined (L_xload_3) \
2091 || defined (L_xload_4))
2099 ;; Register containing bits 16+ of the address
2103 .macro .xload dest, n
2104 #if defined (__AVR_HAVE_ELPMX__)
2106 #elif defined (__AVR_HAVE_ELPM__)
2109 .if \dest != D0+\n-1
2111 adc HHI8, __zero_reg__
2114 #elif defined (__AVR_HAVE_LPMX__)
2119 .if \dest != D0+\n-1
2123 #if defined (__AVR_HAVE_ELPM__) && defined (__AVR_HAVE_RAMPD__)
2124 .if \dest == D0+\n-1
2125 ;; Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM
2126 out __RAMPZ__, __zero_reg__
2131 #if defined (L_xload_1)
2133 #if defined (__AVR_HAVE_LPMX__) && !defined (__AVR_HAVE_ELPM__)
2142 #if defined (__AVR_HAVE_ELPM__)
2144 #endif /* __AVR_HAVE_ELPM__ */
2149 #endif /* LPMx && ! ELPM */
2151 #endif /* L_xload_1 */
2153 #if defined (L_xload_2)
2157 #if defined (__AVR_HAVE_ELPM__)
2159 #endif /* __AVR_HAVE_ELPM__ */
2167 #endif /* L_xload_2 */
2169 #if defined (L_xload_3)
2173 #if defined (__AVR_HAVE_ELPM__)
2175 #endif /* __AVR_HAVE_ELPM__ */
2185 #endif /* L_xload_3 */
2187 #if defined (L_xload_4)
2191 #if defined (__AVR_HAVE_ELPM__)
2193 #endif /* __AVR_HAVE_ELPM__ */
2205 #endif /* L_xload_4 */
2207 #endif /* L_xload_{1|2|3|4} */
2209 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2210 ;; memcopy from Address Space __pgmx to RAM
2211 ;; R23:Z = Source Address
2212 ;; X = Destination Address
2213 ;; Clobbers: __tmp_reg__, R23, R24, R25, X, Z
2215 #if defined (L_movmemx)
2221 ;; #Bytes to copy fity in 8 Bits (1..255)
2222 ;; Zero-extend Loop Counter
2235 #if defined (__AVR_HAVE_ELPM__)
2239 0: ;; Load 1 Byte from Flash...
2241 #if defined (__AVR_HAVE_ELPMX__)
2243 #elif defined (__AVR_HAVE_ELPM__)
2246 adc HHI8, __zero_reg__
2248 #elif defined (__AVR_HAVE_LPMX__)
2255 ;; ...and store that Byte to RAM Destination
2259 #if defined (__AVR_HAVE_ELPM__) && defined (__AVR_HAVE_RAMPD__)
2260 ;; Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM
2261 out __RAMPZ__, __zero_reg__
2262 #endif /* ELPM && RAMPD */
2267 1: ;; Read 1 Byte from RAM...
2269 ;; and store that Byte to RAM Destination
2279 #endif /* L_movmemx */
2282 .section .text.libgcc.builtins, "ax", @progbits
2284 /**********************************
2285 * Find first set Bit (ffs)
2286 **********************************/
2288 #if defined (L_ffssi2)
2289 ;; find first set bit
2290 ;; r25:r24 = ffs32 (r25:r22)
2291 ;; clobbers: r22, r26
2309 #endif /* defined (L_ffssi2) */
2311 #if defined (L_ffshi2)
2312 ;; find first set bit
2313 ;; r25:r24 = ffs16 (r25:r24)
2317 #ifdef __AVR_ERRATA_SKIP_JMP_CALL__
2318 ;; Some cores have problem skipping 2-word instruction
2322 cpse r24, __zero_reg__
2323 #endif /* __AVR_HAVE_JMP_CALL__ */
2324 1: XJMP __loop_ffsqi2
2330 #endif /* defined (L_ffshi2) */
2332 #if defined (L_loop_ffsqi2)
2333 ;; Helper for ffshi2, ffssi2
2334 ;; r25:r24 = r26 + zero_extend16 (ffs8(r24))
2345 #endif /* defined (L_loop_ffsqi2) */
2348 /**********************************
2349 * Count trailing Zeros (ctz)
2350 **********************************/
2352 #if defined (L_ctzsi2)
2353 ;; count trailing zeros
2354 ;; r25:r24 = ctz32 (r25:r22)
2355 ;; clobbers: r26, r22
2357 ;; Note that ctz(0) in undefined for GCC
2363 #endif /* defined (L_ctzsi2) */
2365 #if defined (L_ctzhi2)
2366 ;; count trailing zeros
2367 ;; r25:r24 = ctz16 (r25:r24)
2370 ;; Note that ctz(0) in undefined for GCC
2376 #endif /* defined (L_ctzhi2) */
2379 /**********************************
2380 * Count leading Zeros (clz)
2381 **********************************/
2383 #if defined (L_clzdi2)
2384 ;; count leading zeros
2385 ;; r25:r24 = clz64 (r25:r18)
2386 ;; clobbers: r22, r23, r26
2399 #endif /* defined (L_clzdi2) */
2401 #if defined (L_clzsi2)
2402 ;; count leading zeros
2403 ;; r25:r24 = clz32 (r25:r22)
2415 #endif /* defined (L_clzsi2) */
2417 #if defined (L_clzhi2)
2418 ;; count leading zeros
2419 ;; r25:r24 = clz16 (r25:r24)
2441 #endif /* defined (L_clzhi2) */
2444 /**********************************
2446 **********************************/
2448 #if defined (L_paritydi2)
2449 ;; r25:r24 = parity64 (r25:r18)
2450 ;; clobbers: __tmp_reg__
2458 #endif /* defined (L_paritydi2) */
2460 #if defined (L_paritysi2)
2461 ;; r25:r24 = parity32 (r25:r22)
2462 ;; clobbers: __tmp_reg__
2468 #endif /* defined (L_paritysi2) */
2470 #if defined (L_parityhi2)
2471 ;; r25:r24 = parity16 (r25:r24)
2472 ;; clobbers: __tmp_reg__
2478 ;; r25:r24 = parity8 (r24)
2479 ;; clobbers: __tmp_reg__
2481 ;; parity is in r24[0..7]
2482 mov __tmp_reg__, r24
2484 eor r24, __tmp_reg__
2485 ;; parity is in r24[0..3]
2489 ;; parity is in r24[0,3]
2492 ;; parity is in r24[0]
2497 #endif /* defined (L_parityhi2) */
2500 /**********************************
2502 **********************************/
2504 #if defined (L_popcounthi2)
2506 ;; r25:r24 = popcount16 (r25:r24)
2507 ;; clobbers: __tmp_reg__
2517 DEFUN __popcounthi2_tail
2519 add r24, __tmp_reg__
2521 ENDF __popcounthi2_tail
2522 #endif /* defined (L_popcounthi2) */
2524 #if defined (L_popcountsi2)
2526 ;; r25:r24 = popcount32 (r25:r22)
2527 ;; clobbers: __tmp_reg__
2534 XJMP __popcounthi2_tail
2536 #endif /* defined (L_popcountsi2) */
2538 #if defined (L_popcountdi2)
2540 ;; r25:r24 = popcount64 (r25:r18)
2541 ;; clobbers: r22, r23, __tmp_reg__
2550 XJMP __popcounthi2_tail
2552 #endif /* defined (L_popcountdi2) */
2554 #if defined (L_popcountqi2)
2556 ;; r24 = popcount8 (r24)
2557 ;; clobbers: __tmp_reg__
2559 mov __tmp_reg__, r24
2563 adc r24, __zero_reg__
2565 adc r24, __zero_reg__
2567 adc r24, __zero_reg__
2569 adc r24, __zero_reg__
2571 adc r24, __zero_reg__
2573 adc r24, __tmp_reg__
2576 #endif /* defined (L_popcountqi2) */
2579 /**********************************
2581 **********************************/
2583 ;; swap two registers with different register number
2590 #if defined (L_bswapsi2)
2592 ;; r25:r22 = bswap32 (r25:r22)
2598 #endif /* defined (L_bswapsi2) */
2600 #if defined (L_bswapdi2)
2602 ;; r25:r18 = bswap64 (r25:r18)
2610 #endif /* defined (L_bswapdi2) */
2613 /**********************************
2615 **********************************/
2617 #if defined (L_ashrdi3)
2618 ;; Arithmetic shift right
2619 ;; r25:r18 = ashr64 (r25:r18, r17:r16)
2637 #endif /* defined (L_ashrdi3) */
2639 #if defined (L_lshrdi3)
2640 ;; Logic shift right
2641 ;; r25:r18 = lshr64 (r25:r18, r17:r16)
2659 #endif /* defined (L_lshrdi3) */
2661 #if defined (L_ashldi3)
2663 ;; r25:r18 = ashl64 (r25:r18, r17:r16)
2681 #endif /* defined (L_ashldi3) */
2683 #if defined (L_rotldi3)
2685 ;; r25:r18 = rotl64 (r25:r18, r17:r16)
2698 adc r18, __zero_reg__
2704 #endif /* defined (L_rotldi3) */
2707 .section .text.libgcc.fmul, "ax", @progbits
2709 /***********************************************************/
2710 ;;; Softmul versions of FMUL, FMULS and FMULSU to implement
2711 ;;; __builtin_avr_fmul* if !AVR_HAVE_MUL
2712 /***********************************************************/
2718 #define A0 __tmp_reg__
2721 ;;; r23:r22 = fmuls (r24, r25) like in FMULS instruction
2722 ;;; Clobbers: r24, r25, __tmp_reg__
2724 ;; A0.7 = negate result?
2732 #endif /* L_fmuls */
2735 ;;; r23:r22 = fmulsu (r24, r25) like in FMULSU instruction
2736 ;;; Clobbers: r24, r25, __tmp_reg__
2738 ;; A0.7 = negate result?
2743 ;; Helper for __fmuls and __fmulsu
2748 #ifdef __AVR_ERRATA_SKIP_JMP_CALL__
2749 ;; Some cores have problem skipping 2-word instruction
2754 #endif /* __AVR_HAVE_JMP_CALL__ */
2757 ;; C = -C iff A0.7 = 1
2763 #endif /* L_fmulsu */
2767 ;;; r22:r23 = fmul (r24, r25) like in FMUL instruction
2768 ;;; Clobbers: r24, r25, __tmp_reg__
2775 ;; 1.0 = 0x80, so test for bit 7 of B to see if A must to be added to C.