Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/avr/libgcc.S @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 /* -*- Mode: Asm -*- */ | |
2 /* Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009 | |
3 Free Software Foundation, Inc. | |
4 Contributed by Denis Chertykov <denisc@overta.ru> | |
5 | |
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 | |
9 later version. | |
10 | |
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. | |
15 | |
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. | |
19 | |
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/>. */ | |
24 | |
25 #define __zero_reg__ r1 | |
26 #define __tmp_reg__ r0 | |
27 #define __SREG__ 0x3f | |
28 #define __SP_H__ 0x3e | |
29 #define __SP_L__ 0x3d | |
30 #define __RAMPZ__ 0x3B | |
31 | |
32 /* Most of the functions here are called directly from avr.md | |
33 patterns, instead of using the standard libcall mechanisms. | |
34 This can make better code because GCC knows exactly which | |
35 of the call-used registers (not all of them) are clobbered. */ | |
36 | |
37 .section .text.libgcc, "ax", @progbits | |
38 | |
39 .macro mov_l r_dest, r_src | |
40 #if defined (__AVR_HAVE_MOVW__) | |
41 movw \r_dest, \r_src | |
42 #else | |
43 mov \r_dest, \r_src | |
44 #endif | |
45 .endm | |
46 | |
47 .macro mov_h r_dest, r_src | |
48 #if defined (__AVR_HAVE_MOVW__) | |
49 ; empty | |
50 #else | |
51 mov \r_dest, \r_src | |
52 #endif | |
53 .endm | |
54 | |
55 /* Note: mulqi3, mulhi3 are open-coded on the enhanced core. */ | |
56 #if !defined (__AVR_HAVE_MUL__) | |
57 /******************************************************* | |
58 Multiplication 8 x 8 | |
59 *******************************************************/ | |
60 #if defined (L_mulqi3) | |
61 | |
62 #define r_arg2 r22 /* multiplicand */ | |
63 #define r_arg1 r24 /* multiplier */ | |
64 #define r_res __tmp_reg__ /* result */ | |
65 | |
66 .global __mulqi3 | |
67 .func __mulqi3 | |
68 __mulqi3: | |
69 clr r_res ; clear result | |
70 __mulqi3_loop: | |
71 sbrc r_arg1,0 | |
72 add r_res,r_arg2 | |
73 add r_arg2,r_arg2 ; shift multiplicand | |
74 breq __mulqi3_exit ; while multiplicand != 0 | |
75 lsr r_arg1 ; | |
76 brne __mulqi3_loop ; exit if multiplier = 0 | |
77 __mulqi3_exit: | |
78 mov r_arg1,r_res ; result to return register | |
79 ret | |
80 | |
81 #undef r_arg2 | |
82 #undef r_arg1 | |
83 #undef r_res | |
84 | |
85 .endfunc | |
86 #endif /* defined (L_mulqi3) */ | |
87 | |
88 #if defined (L_mulqihi3) | |
89 .global __mulqihi3 | |
90 .func __mulqihi3 | |
91 __mulqihi3: | |
92 clr r25 | |
93 sbrc r24, 7 | |
94 dec r25 | |
95 clr r23 | |
96 sbrc r22, 7 | |
97 dec r22 | |
98 rjmp __mulhi3 | |
99 .endfunc | |
100 #endif /* defined (L_mulqihi3) */ | |
101 | |
102 #if defined (L_umulqihi3) | |
103 .global __umulqihi3 | |
104 .func __umulqihi3 | |
105 __umulqihi3: | |
106 clr r25 | |
107 clr r23 | |
108 rjmp __mulhi3 | |
109 .endfunc | |
110 #endif /* defined (L_umulqihi3) */ | |
111 | |
112 /******************************************************* | |
113 Multiplication 16 x 16 | |
114 *******************************************************/ | |
115 #if defined (L_mulhi3) | |
116 #define r_arg1L r24 /* multiplier Low */ | |
117 #define r_arg1H r25 /* multiplier High */ | |
118 #define r_arg2L r22 /* multiplicand Low */ | |
119 #define r_arg2H r23 /* multiplicand High */ | |
120 #define r_resL __tmp_reg__ /* result Low */ | |
121 #define r_resH r21 /* result High */ | |
122 | |
123 .global __mulhi3 | |
124 .func __mulhi3 | |
125 __mulhi3: | |
126 clr r_resH ; clear result | |
127 clr r_resL ; clear result | |
128 __mulhi3_loop: | |
129 sbrs r_arg1L,0 | |
130 rjmp __mulhi3_skip1 | |
131 add r_resL,r_arg2L ; result + multiplicand | |
132 adc r_resH,r_arg2H | |
133 __mulhi3_skip1: | |
134 add r_arg2L,r_arg2L ; shift multiplicand | |
135 adc r_arg2H,r_arg2H | |
136 | |
137 cp r_arg2L,__zero_reg__ | |
138 cpc r_arg2H,__zero_reg__ | |
139 breq __mulhi3_exit ; while multiplicand != 0 | |
140 | |
141 lsr r_arg1H ; gets LSB of multiplier | |
142 ror r_arg1L | |
143 sbiw r_arg1L,0 | |
144 brne __mulhi3_loop ; exit if multiplier = 0 | |
145 __mulhi3_exit: | |
146 mov r_arg1H,r_resH ; result to return register | |
147 mov r_arg1L,r_resL | |
148 ret | |
149 | |
150 #undef r_arg1L | |
151 #undef r_arg1H | |
152 #undef r_arg2L | |
153 #undef r_arg2H | |
154 #undef r_resL | |
155 #undef r_resH | |
156 | |
157 .endfunc | |
158 #endif /* defined (L_mulhi3) */ | |
159 #endif /* !defined (__AVR_HAVE_MUL__) */ | |
160 | |
161 #if defined (L_mulhisi3) | |
162 .global __mulhisi3 | |
163 .func __mulhisi3 | |
164 __mulhisi3: | |
165 mov_l r18, r24 | |
166 mov_h r19, r25 | |
167 clr r24 | |
168 sbrc r23, 7 | |
169 dec r24 | |
170 mov r25, r24 | |
171 clr r20 | |
172 sbrc r19, 7 | |
173 dec r20 | |
174 mov r21, r20 | |
175 rjmp __mulsi3 | |
176 .endfunc | |
177 #endif /* defined (L_mulhisi3) */ | |
178 | |
179 #if defined (L_umulhisi3) | |
180 .global __umulhisi3 | |
181 .func __umulhisi3 | |
182 __umulhisi3: | |
183 mov_l r18, r24 | |
184 mov_h r19, r25 | |
185 clr r24 | |
186 clr r25 | |
187 clr r20 | |
188 clr r21 | |
189 rjmp __mulsi3 | |
190 .endfunc | |
191 #endif /* defined (L_umulhisi3) */ | |
192 | |
193 #if defined (L_mulsi3) | |
194 /******************************************************* | |
195 Multiplication 32 x 32 | |
196 *******************************************************/ | |
197 #define r_arg1L r22 /* multiplier Low */ | |
198 #define r_arg1H r23 | |
199 #define r_arg1HL r24 | |
200 #define r_arg1HH r25 /* multiplier High */ | |
201 | |
202 | |
203 #define r_arg2L r18 /* multiplicand Low */ | |
204 #define r_arg2H r19 | |
205 #define r_arg2HL r20 | |
206 #define r_arg2HH r21 /* multiplicand High */ | |
207 | |
208 #define r_resL r26 /* result Low */ | |
209 #define r_resH r27 | |
210 #define r_resHL r30 | |
211 #define r_resHH r31 /* result High */ | |
212 | |
213 | |
214 .global __mulsi3 | |
215 .func __mulsi3 | |
216 __mulsi3: | |
217 #if defined (__AVR_HAVE_MUL__) | |
218 mul r_arg1L, r_arg2L | |
219 movw r_resL, r0 | |
220 mul r_arg1H, r_arg2H | |
221 movw r_resHL, r0 | |
222 mul r_arg1HL, r_arg2L | |
223 add r_resHL, r0 | |
224 adc r_resHH, r1 | |
225 mul r_arg1L, r_arg2HL | |
226 add r_resHL, r0 | |
227 adc r_resHH, r1 | |
228 mul r_arg1HH, r_arg2L | |
229 add r_resHH, r0 | |
230 mul r_arg1HL, r_arg2H | |
231 add r_resHH, r0 | |
232 mul r_arg1H, r_arg2HL | |
233 add r_resHH, r0 | |
234 mul r_arg1L, r_arg2HH | |
235 add r_resHH, r0 | |
236 clr r_arg1HH ; use instead of __zero_reg__ to add carry | |
237 mul r_arg1H, r_arg2L | |
238 add r_resH, r0 | |
239 adc r_resHL, r1 | |
240 adc r_resHH, r_arg1HH ; add carry | |
241 mul r_arg1L, r_arg2H | |
242 add r_resH, r0 | |
243 adc r_resHL, r1 | |
244 adc r_resHH, r_arg1HH ; add carry | |
245 movw r_arg1L, r_resL | |
246 movw r_arg1HL, r_resHL | |
247 clr r1 ; __zero_reg__ clobbered by "mul" | |
248 ret | |
249 #else | |
250 clr r_resHH ; clear result | |
251 clr r_resHL ; clear result | |
252 clr r_resH ; clear result | |
253 clr r_resL ; clear result | |
254 __mulsi3_loop: | |
255 sbrs r_arg1L,0 | |
256 rjmp __mulsi3_skip1 | |
257 add r_resL,r_arg2L ; result + multiplicand | |
258 adc r_resH,r_arg2H | |
259 adc r_resHL,r_arg2HL | |
260 adc r_resHH,r_arg2HH | |
261 __mulsi3_skip1: | |
262 add r_arg2L,r_arg2L ; shift multiplicand | |
263 adc r_arg2H,r_arg2H | |
264 adc r_arg2HL,r_arg2HL | |
265 adc r_arg2HH,r_arg2HH | |
266 | |
267 lsr r_arg1HH ; gets LSB of multiplier | |
268 ror r_arg1HL | |
269 ror r_arg1H | |
270 ror r_arg1L | |
271 brne __mulsi3_loop | |
272 sbiw r_arg1HL,0 | |
273 cpc r_arg1H,r_arg1L | |
274 brne __mulsi3_loop ; exit if multiplier = 0 | |
275 __mulsi3_exit: | |
276 mov_h r_arg1HH,r_resHH ; result to return register | |
277 mov_l r_arg1HL,r_resHL | |
278 mov_h r_arg1H,r_resH | |
279 mov_l r_arg1L,r_resL | |
280 ret | |
281 #endif /* defined (__AVR_HAVE_MUL__) */ | |
282 #undef r_arg1L | |
283 #undef r_arg1H | |
284 #undef r_arg1HL | |
285 #undef r_arg1HH | |
286 | |
287 | |
288 #undef r_arg2L | |
289 #undef r_arg2H | |
290 #undef r_arg2HL | |
291 #undef r_arg2HH | |
292 | |
293 #undef r_resL | |
294 #undef r_resH | |
295 #undef r_resHL | |
296 #undef r_resHH | |
297 | |
298 .endfunc | |
299 #endif /* defined (L_mulsi3) */ | |
300 | |
301 /******************************************************* | |
302 Division 8 / 8 => (result + remainder) | |
303 *******************************************************/ | |
304 #define r_rem r25 /* remainder */ | |
305 #define r_arg1 r24 /* dividend, quotient */ | |
306 #define r_arg2 r22 /* divisor */ | |
307 #define r_cnt r23 /* loop count */ | |
308 | |
309 #if defined (L_udivmodqi4) | |
310 .global __udivmodqi4 | |
311 .func __udivmodqi4 | |
312 __udivmodqi4: | |
313 sub r_rem,r_rem ; clear remainder and carry | |
314 ldi r_cnt,9 ; init loop counter | |
315 rjmp __udivmodqi4_ep ; jump to entry point | |
316 __udivmodqi4_loop: | |
317 rol r_rem ; shift dividend into remainder | |
318 cp r_rem,r_arg2 ; compare remainder & divisor | |
319 brcs __udivmodqi4_ep ; remainder <= divisor | |
320 sub r_rem,r_arg2 ; restore remainder | |
321 __udivmodqi4_ep: | |
322 rol r_arg1 ; shift dividend (with CARRY) | |
323 dec r_cnt ; decrement loop counter | |
324 brne __udivmodqi4_loop | |
325 com r_arg1 ; complement result | |
326 ; because C flag was complemented in loop | |
327 ret | |
328 .endfunc | |
329 #endif /* defined (L_udivmodqi4) */ | |
330 | |
331 #if defined (L_divmodqi4) | |
332 .global __divmodqi4 | |
333 .func __divmodqi4 | |
334 __divmodqi4: | |
335 bst r_arg1,7 ; store sign of dividend | |
336 mov __tmp_reg__,r_arg1 | |
337 eor __tmp_reg__,r_arg2; r0.7 is sign of result | |
338 sbrc r_arg1,7 | |
339 neg r_arg1 ; dividend negative : negate | |
340 sbrc r_arg2,7 | |
341 neg r_arg2 ; divisor negative : negate | |
342 rcall __udivmodqi4 ; do the unsigned div/mod | |
343 brtc __divmodqi4_1 | |
344 neg r_rem ; correct remainder sign | |
345 __divmodqi4_1: | |
346 sbrc __tmp_reg__,7 | |
347 neg r_arg1 ; correct result sign | |
348 __divmodqi4_exit: | |
349 ret | |
350 .endfunc | |
351 #endif /* defined (L_divmodqi4) */ | |
352 | |
353 #undef r_rem | |
354 #undef r_arg1 | |
355 #undef r_arg2 | |
356 #undef r_cnt | |
357 | |
358 | |
359 /******************************************************* | |
360 Division 16 / 16 => (result + remainder) | |
361 *******************************************************/ | |
362 #define r_remL r26 /* remainder Low */ | |
363 #define r_remH r27 /* remainder High */ | |
364 | |
365 /* return: remainder */ | |
366 #define r_arg1L r24 /* dividend Low */ | |
367 #define r_arg1H r25 /* dividend High */ | |
368 | |
369 /* return: quotient */ | |
370 #define r_arg2L r22 /* divisor Low */ | |
371 #define r_arg2H r23 /* divisor High */ | |
372 | |
373 #define r_cnt r21 /* loop count */ | |
374 | |
375 #if defined (L_udivmodhi4) | |
376 .global __udivmodhi4 | |
377 .func __udivmodhi4 | |
378 __udivmodhi4: | |
379 sub r_remL,r_remL | |
380 sub r_remH,r_remH ; clear remainder and carry | |
381 ldi r_cnt,17 ; init loop counter | |
382 rjmp __udivmodhi4_ep ; jump to entry point | |
383 __udivmodhi4_loop: | |
384 rol r_remL ; shift dividend into remainder | |
385 rol r_remH | |
386 cp r_remL,r_arg2L ; compare remainder & divisor | |
387 cpc r_remH,r_arg2H | |
388 brcs __udivmodhi4_ep ; remainder < divisor | |
389 sub r_remL,r_arg2L ; restore remainder | |
390 sbc r_remH,r_arg2H | |
391 __udivmodhi4_ep: | |
392 rol r_arg1L ; shift dividend (with CARRY) | |
393 rol r_arg1H | |
394 dec r_cnt ; decrement loop counter | |
395 brne __udivmodhi4_loop | |
396 com r_arg1L | |
397 com r_arg1H | |
398 ; div/mod results to return registers, as for the div() function | |
399 mov_l r_arg2L, r_arg1L ; quotient | |
400 mov_h r_arg2H, r_arg1H | |
401 mov_l r_arg1L, r_remL ; remainder | |
402 mov_h r_arg1H, r_remH | |
403 ret | |
404 .endfunc | |
405 #endif /* defined (L_udivmodhi4) */ | |
406 | |
407 #if defined (L_divmodhi4) | |
408 .global __divmodhi4 | |
409 .func __divmodhi4 | |
410 __divmodhi4: | |
411 .global _div | |
412 _div: | |
413 bst r_arg1H,7 ; store sign of dividend | |
414 mov __tmp_reg__,r_arg1H | |
415 eor __tmp_reg__,r_arg2H ; r0.7 is sign of result | |
416 rcall __divmodhi4_neg1 ; dividend negative : negate | |
417 sbrc r_arg2H,7 | |
418 rcall __divmodhi4_neg2 ; divisor negative : negate | |
419 rcall __udivmodhi4 ; do the unsigned div/mod | |
420 rcall __divmodhi4_neg1 ; correct remainder sign | |
421 tst __tmp_reg__ | |
422 brpl __divmodhi4_exit | |
423 __divmodhi4_neg2: | |
424 com r_arg2H | |
425 neg r_arg2L ; correct divisor/result sign | |
426 sbci r_arg2H,0xff | |
427 __divmodhi4_exit: | |
428 ret | |
429 __divmodhi4_neg1: | |
430 brtc __divmodhi4_exit | |
431 com r_arg1H | |
432 neg r_arg1L ; correct dividend/remainder sign | |
433 sbci r_arg1H,0xff | |
434 ret | |
435 .endfunc | |
436 #endif /* defined (L_divmodhi4) */ | |
437 | |
438 #undef r_remH | |
439 #undef r_remL | |
440 | |
441 #undef r_arg1H | |
442 #undef r_arg1L | |
443 | |
444 #undef r_arg2H | |
445 #undef r_arg2L | |
446 | |
447 #undef r_cnt | |
448 | |
449 /******************************************************* | |
450 Division 32 / 32 => (result + remainder) | |
451 *******************************************************/ | |
452 #define r_remHH r31 /* remainder High */ | |
453 #define r_remHL r30 | |
454 #define r_remH r27 | |
455 #define r_remL r26 /* remainder Low */ | |
456 | |
457 /* return: remainder */ | |
458 #define r_arg1HH r25 /* dividend High */ | |
459 #define r_arg1HL r24 | |
460 #define r_arg1H r23 | |
461 #define r_arg1L r22 /* dividend Low */ | |
462 | |
463 /* return: quotient */ | |
464 #define r_arg2HH r21 /* divisor High */ | |
465 #define r_arg2HL r20 | |
466 #define r_arg2H r19 | |
467 #define r_arg2L r18 /* divisor Low */ | |
468 | |
469 #define r_cnt __zero_reg__ /* loop count (0 after the loop!) */ | |
470 | |
471 #if defined (L_udivmodsi4) | |
472 .global __udivmodsi4 | |
473 .func __udivmodsi4 | |
474 __udivmodsi4: | |
475 ldi r_remL, 33 ; init loop counter | |
476 mov r_cnt, r_remL | |
477 sub r_remL,r_remL | |
478 sub r_remH,r_remH ; clear remainder and carry | |
479 mov_l r_remHL, r_remL | |
480 mov_h r_remHH, r_remH | |
481 rjmp __udivmodsi4_ep ; jump to entry point | |
482 __udivmodsi4_loop: | |
483 rol r_remL ; shift dividend into remainder | |
484 rol r_remH | |
485 rol r_remHL | |
486 rol r_remHH | |
487 cp r_remL,r_arg2L ; compare remainder & divisor | |
488 cpc r_remH,r_arg2H | |
489 cpc r_remHL,r_arg2HL | |
490 cpc r_remHH,r_arg2HH | |
491 brcs __udivmodsi4_ep ; remainder <= divisor | |
492 sub r_remL,r_arg2L ; restore remainder | |
493 sbc r_remH,r_arg2H | |
494 sbc r_remHL,r_arg2HL | |
495 sbc r_remHH,r_arg2HH | |
496 __udivmodsi4_ep: | |
497 rol r_arg1L ; shift dividend (with CARRY) | |
498 rol r_arg1H | |
499 rol r_arg1HL | |
500 rol r_arg1HH | |
501 dec r_cnt ; decrement loop counter | |
502 brne __udivmodsi4_loop | |
503 ; __zero_reg__ now restored (r_cnt == 0) | |
504 com r_arg1L | |
505 com r_arg1H | |
506 com r_arg1HL | |
507 com r_arg1HH | |
508 ; div/mod results to return registers, as for the ldiv() function | |
509 mov_l r_arg2L, r_arg1L ; quotient | |
510 mov_h r_arg2H, r_arg1H | |
511 mov_l r_arg2HL, r_arg1HL | |
512 mov_h r_arg2HH, r_arg1HH | |
513 mov_l r_arg1L, r_remL ; remainder | |
514 mov_h r_arg1H, r_remH | |
515 mov_l r_arg1HL, r_remHL | |
516 mov_h r_arg1HH, r_remHH | |
517 ret | |
518 .endfunc | |
519 #endif /* defined (L_udivmodsi4) */ | |
520 | |
521 #if defined (L_divmodsi4) | |
522 .global __divmodsi4 | |
523 .func __divmodsi4 | |
524 __divmodsi4: | |
525 bst r_arg1HH,7 ; store sign of dividend | |
526 mov __tmp_reg__,r_arg1HH | |
527 eor __tmp_reg__,r_arg2HH ; r0.7 is sign of result | |
528 rcall __divmodsi4_neg1 ; dividend negative : negate | |
529 sbrc r_arg2HH,7 | |
530 rcall __divmodsi4_neg2 ; divisor negative : negate | |
531 rcall __udivmodsi4 ; do the unsigned div/mod | |
532 rcall __divmodsi4_neg1 ; correct remainder sign | |
533 rol __tmp_reg__ | |
534 brcc __divmodsi4_exit | |
535 __divmodsi4_neg2: | |
536 com r_arg2HH | |
537 com r_arg2HL | |
538 com r_arg2H | |
539 neg r_arg2L ; correct divisor/quotient sign | |
540 sbci r_arg2H,0xff | |
541 sbci r_arg2HL,0xff | |
542 sbci r_arg2HH,0xff | |
543 __divmodsi4_exit: | |
544 ret | |
545 __divmodsi4_neg1: | |
546 brtc __divmodsi4_exit | |
547 com r_arg1HH | |
548 com r_arg1HL | |
549 com r_arg1H | |
550 neg r_arg1L ; correct dividend/remainder sign | |
551 sbci r_arg1H, 0xff | |
552 sbci r_arg1HL,0xff | |
553 sbci r_arg1HH,0xff | |
554 ret | |
555 .endfunc | |
556 #endif /* defined (L_divmodsi4) */ | |
557 | |
558 /********************************** | |
559 * This is a prologue subroutine | |
560 **********************************/ | |
561 #if defined (L_prologue) | |
562 | |
563 .global __prologue_saves__ | |
564 .func __prologue_saves__ | |
565 __prologue_saves__: | |
566 push r2 | |
567 push r3 | |
568 push r4 | |
569 push r5 | |
570 push r6 | |
571 push r7 | |
572 push r8 | |
573 push r9 | |
574 push r10 | |
575 push r11 | |
576 push r12 | |
577 push r13 | |
578 push r14 | |
579 push r15 | |
580 push r16 | |
581 push r17 | |
582 push r28 | |
583 push r29 | |
584 in r28,__SP_L__ | |
585 in r29,__SP_H__ | |
586 sub r28,r26 | |
587 sbc r29,r27 | |
588 in __tmp_reg__,__SREG__ | |
589 cli | |
590 out __SP_H__,r29 | |
591 out __SREG__,__tmp_reg__ | |
592 out __SP_L__,r28 | |
593 #if defined (__AVR_HAVE_EIJMP_EICALL__) | |
594 eijmp | |
595 #else | |
596 ijmp | |
597 #endif | |
598 | |
599 .endfunc | |
600 #endif /* defined (L_prologue) */ | |
601 | |
602 /* | |
603 * This is an epilogue subroutine | |
604 */ | |
605 #if defined (L_epilogue) | |
606 | |
607 .global __epilogue_restores__ | |
608 .func __epilogue_restores__ | |
609 __epilogue_restores__: | |
610 ldd r2,Y+18 | |
611 ldd r3,Y+17 | |
612 ldd r4,Y+16 | |
613 ldd r5,Y+15 | |
614 ldd r6,Y+14 | |
615 ldd r7,Y+13 | |
616 ldd r8,Y+12 | |
617 ldd r9,Y+11 | |
618 ldd r10,Y+10 | |
619 ldd r11,Y+9 | |
620 ldd r12,Y+8 | |
621 ldd r13,Y+7 | |
622 ldd r14,Y+6 | |
623 ldd r15,Y+5 | |
624 ldd r16,Y+4 | |
625 ldd r17,Y+3 | |
626 ldd r26,Y+2 | |
627 ldd r27,Y+1 | |
628 add r28,r30 | |
629 adc r29,__zero_reg__ | |
630 in __tmp_reg__,__SREG__ | |
631 cli | |
632 out __SP_H__,r29 | |
633 out __SREG__,__tmp_reg__ | |
634 out __SP_L__,r28 | |
635 mov_l r28, r26 | |
636 mov_h r29, r27 | |
637 ret | |
638 .endfunc | |
639 #endif /* defined (L_epilogue) */ | |
640 | |
641 #ifdef L_exit | |
642 .section .fini9,"ax",@progbits | |
643 .global _exit | |
644 .func _exit | |
645 _exit: | |
646 .weak exit | |
647 exit: | |
648 | |
649 /* Code from .fini8 ... .fini1 sections inserted by ld script. */ | |
650 | |
651 .section .fini0,"ax",@progbits | |
652 cli | |
653 __stop_program: | |
654 rjmp __stop_program | |
655 .endfunc | |
656 #endif /* defined (L_exit) */ | |
657 | |
658 #ifdef L_cleanup | |
659 .weak _cleanup | |
660 .func _cleanup | |
661 _cleanup: | |
662 ret | |
663 .endfunc | |
664 #endif /* defined (L_cleanup) */ | |
665 | |
666 #ifdef L_tablejump | |
667 .global __tablejump2__ | |
668 .func __tablejump2__ | |
669 __tablejump2__: | |
670 lsl r30 | |
671 rol r31 | |
672 .global __tablejump__ | |
673 __tablejump__: | |
674 #if defined (__AVR_HAVE_LPMX__) | |
675 lpm __tmp_reg__, Z+ | |
676 lpm r31, Z | |
677 mov r30, __tmp_reg__ | |
678 | |
679 #if defined (__AVR_HAVE_EIJMP_EICALL__) | |
680 eijmp | |
681 #else | |
682 ijmp | |
683 #endif | |
684 | |
685 #else | |
686 lpm | |
687 adiw r30, 1 | |
688 push r0 | |
689 lpm | |
690 push r0 | |
691 #if defined (__AVR_HAVE_EIJMP_EICALL__) | |
692 push __zero_reg__ | |
693 #endif | |
694 ret | |
695 #endif | |
696 .endfunc | |
697 #endif /* defined (L_tablejump) */ | |
698 | |
699 #ifdef L_copy_data | |
700 .section .init4,"ax",@progbits | |
701 .global __do_copy_data | |
702 __do_copy_data: | |
703 #if defined(__AVR_HAVE_ELPMX__) | |
704 ldi r17, hi8(__data_end) | |
705 ldi r26, lo8(__data_start) | |
706 ldi r27, hi8(__data_start) | |
707 ldi r30, lo8(__data_load_start) | |
708 ldi r31, hi8(__data_load_start) | |
709 ldi r16, hh8(__data_load_start) | |
710 out __RAMPZ__, r16 | |
711 rjmp .L__do_copy_data_start | |
712 .L__do_copy_data_loop: | |
713 elpm r0, Z+ | |
714 st X+, r0 | |
715 .L__do_copy_data_start: | |
716 cpi r26, lo8(__data_end) | |
717 cpc r27, r17 | |
718 brne .L__do_copy_data_loop | |
719 #elif !defined(__AVR_HAVE_ELPMX__) && defined(__AVR_HAVE_ELPM__) | |
720 ldi r17, hi8(__data_end) | |
721 ldi r26, lo8(__data_start) | |
722 ldi r27, hi8(__data_start) | |
723 ldi r30, lo8(__data_load_start) | |
724 ldi r31, hi8(__data_load_start) | |
725 ldi r16, hh8(__data_load_start - 0x10000) | |
726 .L__do_copy_data_carry: | |
727 inc r16 | |
728 out __RAMPZ__, r16 | |
729 rjmp .L__do_copy_data_start | |
730 .L__do_copy_data_loop: | |
731 elpm | |
732 st X+, r0 | |
733 adiw r30, 1 | |
734 brcs .L__do_copy_data_carry | |
735 .L__do_copy_data_start: | |
736 cpi r26, lo8(__data_end) | |
737 cpc r27, r17 | |
738 brne .L__do_copy_data_loop | |
739 #elif !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__) | |
740 ldi r17, hi8(__data_end) | |
741 ldi r26, lo8(__data_start) | |
742 ldi r27, hi8(__data_start) | |
743 ldi r30, lo8(__data_load_start) | |
744 ldi r31, hi8(__data_load_start) | |
745 rjmp .L__do_copy_data_start | |
746 .L__do_copy_data_loop: | |
747 #if defined (__AVR_HAVE_LPMX__) | |
748 lpm r0, Z+ | |
749 #else | |
750 lpm | |
751 adiw r30, 1 | |
752 #endif | |
753 st X+, r0 | |
754 .L__do_copy_data_start: | |
755 cpi r26, lo8(__data_end) | |
756 cpc r27, r17 | |
757 brne .L__do_copy_data_loop | |
758 #endif /* !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__) */ | |
759 #endif /* L_copy_data */ | |
760 | |
761 /* __do_clear_bss is only necessary if there is anything in .bss section. */ | |
762 | |
763 #ifdef L_clear_bss | |
764 .section .init4,"ax",@progbits | |
765 .global __do_clear_bss | |
766 __do_clear_bss: | |
767 ldi r17, hi8(__bss_end) | |
768 ldi r26, lo8(__bss_start) | |
769 ldi r27, hi8(__bss_start) | |
770 rjmp .do_clear_bss_start | |
771 .do_clear_bss_loop: | |
772 st X+, __zero_reg__ | |
773 .do_clear_bss_start: | |
774 cpi r26, lo8(__bss_end) | |
775 cpc r27, r17 | |
776 brne .do_clear_bss_loop | |
777 #endif /* L_clear_bss */ | |
778 | |
779 /* __do_global_ctors and __do_global_dtors are only necessary | |
780 if there are any constructors/destructors. */ | |
781 | |
782 #if defined (__AVR_HAVE_JMP_CALL__) | |
783 #define XCALL call | |
784 #else | |
785 #define XCALL rcall | |
786 #endif | |
787 | |
788 #ifdef L_ctors | |
789 .section .init6,"ax",@progbits | |
790 .global __do_global_ctors | |
791 #if defined(__AVR_HAVE_RAMPZ__) | |
792 __do_global_ctors: | |
793 ldi r17, hi8(__ctors_start) | |
794 ldi r16, hh8(__ctors_start) | |
795 ldi r28, lo8(__ctors_end) | |
796 ldi r29, hi8(__ctors_end) | |
797 ldi r20, hh8(__ctors_end) | |
798 rjmp .L__do_global_ctors_start | |
799 .L__do_global_ctors_loop: | |
800 sbiw r28, 2 | |
801 sbc r20, __zero_reg__ | |
802 mov_h r31, r29 | |
803 mov_l r30, r28 | |
804 out __RAMPZ__, r20 | |
805 XCALL __tablejump_elpm__ | |
806 .L__do_global_ctors_start: | |
807 cpi r28, lo8(__ctors_start) | |
808 cpc r29, r17 | |
809 cpc r20, r16 | |
810 brne .L__do_global_ctors_loop | |
811 #else | |
812 __do_global_ctors: | |
813 ldi r17, hi8(__ctors_start) | |
814 ldi r28, lo8(__ctors_end) | |
815 ldi r29, hi8(__ctors_end) | |
816 rjmp .L__do_global_ctors_start | |
817 .L__do_global_ctors_loop: | |
818 sbiw r28, 2 | |
819 mov_h r31, r29 | |
820 mov_l r30, r28 | |
821 XCALL __tablejump__ | |
822 .L__do_global_ctors_start: | |
823 cpi r28, lo8(__ctors_start) | |
824 cpc r29, r17 | |
825 brne .L__do_global_ctors_loop | |
826 #endif /* defined(__AVR_HAVE_RAMPZ__) */ | |
827 #endif /* L_ctors */ | |
828 | |
829 #ifdef L_dtors | |
830 .section .fini6,"ax",@progbits | |
831 .global __do_global_dtors | |
832 #if defined(__AVR_HAVE_RAMPZ__) | |
833 __do_global_dtors: | |
834 ldi r17, hi8(__dtors_end) | |
835 ldi r16, hh8(__dtors_end) | |
836 ldi r28, lo8(__dtors_start) | |
837 ldi r29, hi8(__dtors_start) | |
838 ldi r20, hh8(__dtors_start) | |
839 rjmp .L__do_global_dtors_start | |
840 .L__do_global_dtors_loop: | |
841 sbiw r28, 2 | |
842 sbc r20, __zero_reg__ | |
843 mov_h r31, r29 | |
844 mov_l r30, r28 | |
845 out __RAMPZ__, r20 | |
846 XCALL __tablejump_elpm__ | |
847 .L__do_global_dtors_start: | |
848 cpi r28, lo8(__dtors_end) | |
849 cpc r29, r17 | |
850 cpc r20, r16 | |
851 brne .L__do_global_dtors_loop | |
852 #else | |
853 __do_global_dtors: | |
854 ldi r17, hi8(__dtors_end) | |
855 ldi r28, lo8(__dtors_start) | |
856 ldi r29, hi8(__dtors_start) | |
857 rjmp .L__do_global_dtors_start | |
858 .L__do_global_dtors_loop: | |
859 mov_h r31, r29 | |
860 mov_l r30, r28 | |
861 XCALL __tablejump__ | |
862 adiw r28, 2 | |
863 .L__do_global_dtors_start: | |
864 cpi r28, lo8(__dtors_end) | |
865 cpc r29, r17 | |
866 brne .L__do_global_dtors_loop | |
867 #endif /* defined(__AVR_HAVE_RAMPZ__) */ | |
868 #endif /* L_dtors */ | |
869 | |
870 #ifdef L_tablejump_elpm | |
871 .global __tablejump_elpm__ | |
872 .func __tablejump_elpm__ | |
873 __tablejump_elpm__: | |
874 #if defined (__AVR_HAVE_ELPM__) | |
875 #if defined (__AVR_HAVE_LPMX__) | |
876 elpm __tmp_reg__, Z+ | |
877 elpm r31, Z | |
878 mov r30, __tmp_reg__ | |
879 #if defined (__AVR_HAVE_EIJMP_EICALL__) | |
880 eijmp | |
881 #else | |
882 ijmp | |
883 #endif | |
884 | |
885 #else | |
886 elpm | |
887 adiw r30, 1 | |
888 push r0 | |
889 elpm | |
890 push r0 | |
891 #if defined (__AVR_HAVE_EIJMP_EICALL__) | |
892 push __zero_reg__ | |
893 #endif | |
894 ret | |
895 #endif | |
896 #endif /* defined (__AVR_HAVE_ELPM__) */ | |
897 .endfunc | |
898 #endif /* defined (L_tablejump_elpm) */ | |
899 |