PR target/16201
[official-gcc.git] / gcc / config / m68hc11 / larith.asm
blob6c26268b8c34a9b67a8bc879391248c288b0c896
1 /* libgcc routines for M68HC11 & M68HC12.
2 Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC 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 2, or (at your option) any
9 later version.
11 In addition to the permissions in the GNU General Public License, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of this file with other programs, and to distribute
14 those programs without any restriction coming from the use of this
15 file. (The General Public License restrictions do apply in other
16 respects; for example, they cover modification of the file, and
17 distribution when not linked into another program.)
19 This file is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA. */
29 /* As a special exception, if you link this library with other files,
30 some of which are compiled with GCC, to produce an executable,
31 this library does not by itself cause the resulting executable
32 to be covered by the GNU General Public License.
33 This exception does not however invalidate any other reasons why
34 the executable file might be covered by the GNU General Public License. */
36 .file "larith.asm"
38 #ifdef __HAVE_SHORT_INT__
39 .mode mshort
40 #else
41 .mode mlong
42 #endif
44 .macro declare_near name
45 .globl \name
46 .type \name,@function
47 .size \name,.Lend-\name
48 \name:
49 .endm
51 #if defined(__USE_RTC__)
52 # define ARG(N) N+1
54 .macro ret
55 #if defined(mc68hc12)
56 rtc
57 #else
58 jmp __return_32
59 #endif
60 .endm
62 .macro declare name
63 .globl \name
64 .type \name,@function
65 .size \name,.Lend-\name
66 .far \name
67 \name:
68 .endm
70 .macro farsym name
71 .far NAME
72 .endm
74 #else
75 # define ARG(N) N
77 .macro ret
78 rts
79 .endm
81 .macro farsym name
82 .endm
84 .macro declare name
85 .globl \name
86 .type \name,@function
87 .size \name,.Lend-\name
88 \name:
89 .endm
91 #endif
93 .sect .text
96 #define REG(NAME) \
97 NAME: .dc.w 1; \
98 .type NAME,@object ; \
99 .size NAME,2
101 #ifdef L_regs_min
102 /* Pseudo hard registers used by gcc.
103 They should be located in page0. */
105 .sect .softregs
106 .globl _.tmp
107 .globl _.z,_.xy
108 REG(_.tmp)
109 REG(_.z)
110 REG(_.xy)
112 #endif
114 #ifdef L_regs_frame
115 .sect .softregs
116 .globl _.frame
117 REG(_.frame)
118 #endif
120 #ifdef L_regs_d1_2
121 .sect .softregs
122 .globl _.d1,_.d2
123 REG(_.d1)
124 REG(_.d2)
125 #endif
127 #ifdef L_regs_d3_4
128 .sect .softregs
129 .globl _.d3,_.d4
130 REG(_.d3)
131 REG(_.d4)
132 #endif
134 #ifdef L_regs_d5_6
135 .sect .softregs
136 .globl _.d5,_.d6
137 REG(_.d5)
138 REG(_.d6)
139 #endif
141 #ifdef L_regs_d7_8
142 .sect .softregs
143 .globl _.d7,_.d8
144 REG(_.d7)
145 REG(_.d8)
146 #endif
148 #ifdef L_regs_d9_16
149 /* Pseudo hard registers used by gcc.
150 They should be located in page0. */
151 .sect .softregs
152 .globl _.d9,_.d10,_.d11,_.d12,_.d13,_.d14
153 .globl _.d15,_.d16
154 REG(_.d9)
155 REG(_.d10)
156 REG(_.d11)
157 REG(_.d12)
158 REG(_.d13)
159 REG(_.d14)
160 REG(_.d15)
161 REG(_.d16)
163 #endif
165 #ifdef L_regs_d17_32
166 /* Pseudo hard registers used by gcc.
167 They should be located in page0. */
168 .sect .softregs
169 .globl _.d17,_.d18,_.d19,_.d20,_.d21,_.d22
170 .globl _.d23,_.d24,_.d25,_.d26,_.d27,_.d28
171 .globl _.d29,_.d30,_.d31,_.d32
172 REG(_.d17)
173 REG(_.d18)
174 REG(_.d19)
175 REG(_.d20)
176 REG(_.d21)
177 REG(_.d22)
178 REG(_.d23)
179 REG(_.d24)
180 REG(_.d25)
181 REG(_.d26)
182 REG(_.d27)
183 REG(_.d28)
184 REG(_.d29)
185 REG(_.d30)
186 REG(_.d31)
187 REG(_.d32)
188 #endif
190 #ifdef L_premain
192 ;; Specific initialization for 68hc11 before the main.
193 ;; Nothing special for a generic routine; Just enable interrupts.
195 declare_near __premain
196 clra
197 tap ; Clear both I and X.
199 #endif
201 #ifdef L__exit
203 ;; Exit operation. Just loop forever and wait for interrupts.
204 ;; (no other place to go)
205 ;; This operation is split in several pieces collected together by
206 ;; the linker script. This allows to support destructors at the
207 ;; exit stage while not impacting program sizes when there is no
208 ;; destructors.
210 ;; _exit:
211 ;; *(.fini0) /* Beginning of finish code (_exit symbol). */
212 ;; *(.fini1) /* Place holder for applications. */
213 ;; *(.fini2) /* C++ destructors. */
214 ;; *(.fini3) /* Place holder for applications. */
215 ;; *(.fini4) /* Runtime exit. */
217 .sect .fini0,"ax",@progbits
218 .globl _exit
219 .globl exit
220 .weak exit
221 farsym exit
222 farsym _exit
223 exit:
224 _exit:
226 .sect .fini4,"ax",@progbits
227 fatal:
230 bra fatal
231 #endif
233 #ifdef L_abort
235 ;; Abort operation. This is defined for the GCC testsuite.
237 declare abort
239 ldd #255 ;
240 #ifdef mc68hc12
241 trap #0x30
242 #else
243 .byte 0xCD ; Generate an illegal instruction trap
244 .byte 0x03 ; The simulator catches this and stops.
245 #endif
246 jmp _exit
247 #endif
249 #ifdef L_cleanup
251 ;; Cleanup operation used by exit().
253 declare _cleanup
256 #endif
258 ;-----------------------------------------
259 ; required gcclib code
260 ;-----------------------------------------
261 #ifdef L_memcpy
262 declare memcpy
263 declare __memcpy
265 .weak memcpy
267 ;;; void* memcpy(void*, const void*, size_t)
268 ;;;
269 ;;; D = dst Pmode
270 ;;; 2,sp = src Pmode
271 ;;; 4,sp = size HImode (size_t)
272 ;;;
273 #ifdef mc68hc12
274 ldx ARG(2),sp
275 ldy ARG(4),sp
276 pshd
277 xgdy
278 lsrd
279 bcc Start
280 movb 1,x+,1,y+
281 Start:
282 beq Done
283 Loop:
284 movw 2,x+,2,y+
285 dbne d,Loop
286 Done:
287 puld
289 #else
290 xgdy
292 ldd ARG(4),x
293 ldx ARG(2),x ; SRC = X, DST = Y
294 cpd #0
295 beq End
296 pshy
297 inca ; Correction for the deca below
299 psha ; Save high-counter part
301 ldaa 0,x ; Copy up to 256 bytes
302 staa 0,y
305 decb
306 bne L1
307 pula
308 deca
309 bne L0
310 puly ; Restore Y to return the DST
311 End:
312 xgdy
314 #endif
315 #endif
317 #ifdef L_memset
318 declare memset
319 declare __memset
321 ;;; void* memset(void*, int value, size_t)
322 ;;;
323 #ifndef __HAVE_SHORT_INT__
324 ;;; D = dst Pmode
325 ;;; 2,sp = src SImode
326 ;;; 6,sp = size HImode (size_t)
327 val = ARG(5)
328 size = ARG(6)
329 #else
330 ;;; D = dst Pmode
331 ;;; 2,sp = src SImode
332 ;;; 6,sp = size HImode (size_t)
333 val = ARG(3)
334 size = ARG(4)
335 #endif
336 #ifdef mc68hc12
337 xgdx
338 ldab val,sp
339 ldy size,sp
340 pshx
341 beq End
342 Loop:
343 stab 1,x+
344 dbne y,Loop
345 End:
346 puld
348 #else
349 xgdx
351 ldab val,y
352 ldy size,y ; DST = X, CNT = Y
353 beq End
354 pshx
356 stab 0,x ; Fill up to 256 bytes
359 bne L0
360 pulx ; Restore X to return the DST
361 End:
362 xgdx
364 #endif
365 #endif
367 #ifdef L_adddi3
368 declare ___adddi3
371 xgdy
372 ldd ARG(8),x ; Add LSB
373 addd ARG(16),x
374 std 6,y ; Save (carry preserved)
376 ldd ARG(6),x
377 adcb ARG(15),x
378 adca ARG(14),x
379 std 4,y
381 ldd ARG(4),x
382 adcb ARG(13),x
383 adca ARG(12),x
384 std 2,y
386 ldd ARG(2),x
387 adcb ARG(11),x ; Add MSB
388 adca ARG(10),x
389 std 0,y
391 xgdy
393 #endif
395 #ifdef L_subdi3
396 declare ___subdi3
399 xgdy
400 ldd ARG(8),x ; Subtract LSB
401 subd ARG(16),x
402 std 6,y ; Save, borrow preserved
404 ldd ARG(6),x
405 sbcb ARG(15),x
406 sbca ARG(14),x
407 std 4,y
409 ldd ARG(4),x
410 sbcb ARG(13),x
411 sbca ARG(12),x
412 std 2,y
414 ldd ARG(2),x ; Subtract MSB
415 sbcb ARG(11),x
416 sbca ARG(10),x
417 std 0,y
419 xgdy ;
421 #endif
423 #ifdef L_notdi2
424 declare ___notdi2
427 xgdx
428 ldd ARG(8),y
429 coma
430 comb
431 std 6,x
433 ldd ARG(6),y
434 coma
435 comb
436 std 4,x
438 ldd ARG(4),y
439 coma
440 comb
441 std 2,x
443 ldd ARG(2),y
444 coma
445 comb
446 std 0,x
447 xgdx
449 #endif
451 #ifdef L_negsi2
452 declare_near ___negsi2
454 comb
455 coma
456 xgdx
457 comb
458 coma
460 xgdx
461 bne done
463 done:
465 #endif
467 #ifdef L_one_cmplsi2
468 declare_near ___one_cmplsi2
470 comb
471 coma
472 xgdx
473 comb
474 coma
475 xgdx
477 #endif
479 #ifdef L_ashlsi3
480 declare_near ___ashlsi3
482 xgdy
483 clra
484 andb #0x1f
485 xgdy
486 beq Return
487 Loop:
488 lsld
489 xgdx
490 rolb
491 rola
492 xgdx
494 bne Loop
495 Return:
497 #endif
499 #ifdef L_ashrsi3
500 declare_near ___ashrsi3
502 xgdy
503 clra
504 andb #0x1f
505 xgdy
506 beq Return
507 Loop:
508 xgdx
509 asra
510 rorb
511 xgdx
512 rora
513 rorb
515 bne Loop
516 Return:
518 #endif
520 #ifdef L_lshrsi3
521 declare_near ___lshrsi3
523 xgdy
524 clra
525 andb #0x1f
526 xgdy
527 beq Return
528 Loop:
529 xgdx
530 lsrd
531 xgdx
532 rora
533 rorb
535 bne Loop
536 Return:
538 #endif
540 #ifdef L_lshrhi3
541 declare_near ___lshrhi3
543 cpx #16
544 bge Return_zero
545 cpx #0
546 beq Return
547 Loop:
548 lsrd
550 bne Loop
551 Return:
553 Return_zero:
554 clra
555 clrb
557 #endif
559 #ifdef L_lshlhi3
560 declare_near ___lshlhi3
562 cpx #16
563 bge Return_zero
564 cpx #0
565 beq Return
566 Loop:
567 lsld
569 bne Loop
570 Return:
572 Return_zero:
573 clra
574 clrb
576 #endif
578 #ifdef L_rotrhi3
579 declare_near ___rotrhi3
581 ___rotrhi3:
582 xgdx
583 clra
584 andb #0x0f
585 xgdx
586 beq Return
587 Loop:
589 rorb
590 rora
592 bne Loop
593 Return:
595 #endif
597 #ifdef L_rotlhi3
598 declare_near ___rotlhi3
600 ___rotlhi3:
601 xgdx
602 clra
603 andb #0x0f
604 xgdx
605 beq Return
606 Loop:
607 asrb
608 rolb
609 rola
610 rolb
612 bne Loop
613 Return:
615 #endif
617 #ifdef L_ashrhi3
618 declare_near ___ashrhi3
620 cpx #16
621 bge Return_minus_1_or_zero
622 cpx #0
623 beq Return
624 Loop:
625 asra
626 rorb
628 bne Loop
629 Return:
631 Return_minus_1_or_zero:
632 clrb
633 tsta
634 bpl Return_zero
635 comb
636 Return_zero:
639 #endif
641 #ifdef L_ashrqi3
642 declare_near ___ashrqi3
644 cmpa #8
645 bge Return_minus_1_or_zero
646 tsta
647 beq Return
648 Loop:
649 asrb
650 deca
651 bne Loop
652 Return:
654 Return_minus_1_or_zero:
655 clrb
656 tstb
657 bpl Return_zero
658 coma
659 Return_zero:
662 #endif
664 #ifdef L_lshlqi3
665 declare_near ___lshlqi3
667 cmpa #8
668 bge Return_zero
669 tsta
670 beq Return
671 Loop:
672 lslb
673 deca
674 bne Loop
675 Return:
677 Return_zero:
678 clrb
680 #endif
682 #ifdef L_divmodhi4
683 #ifndef mc68hc12
684 /* 68HC12 signed divisions are generated inline (idivs). */
686 declare_near __divmodhi4
689 ;; D = numerator
690 ;; X = denominator
692 ;; Result: D = D / X
693 ;; X = D % X
695 tsta
696 bpl Numerator_pos
697 comb ; D = -D <=> D = (~D) + 1
698 coma
699 xgdx
701 tsta
702 bpl Numerator_neg_denominator_pos
703 Numerator_neg_denominator_neg:
704 comb ; X = -X
705 coma
706 addd #1
707 xgdx
708 idiv
709 coma
710 comb
711 xgdx ; Remainder <= 0 and result >= 0
715 Numerator_pos_denominator_pos:
716 xgdx
717 idiv
718 xgdx ; Both values are >= 0
721 Numerator_pos:
722 xgdx
723 tsta
724 bpl Numerator_pos_denominator_pos
725 Numerator_pos_denominator_neg:
726 coma ; X = -X
727 comb
728 xgdx
730 idiv
731 xgdx ; Remainder >= 0 but result <= 0
732 coma
733 comb
734 addd #1
737 Numerator_neg_denominator_pos:
738 xgdx
739 idiv
740 coma ; One value is > 0 and the other < 0
741 comb ; Change the sign of result and remainder
742 xgdx
744 coma
745 comb
746 addd #1
748 #endif /* !mc68hc12 */
749 #endif
751 #ifdef L_mulqi3
752 declare_near ___mulqi3
755 ; short __mulqi3(signed char a, signed char b);
757 ; signed char a -> register A
758 ; signed char b -> register B
760 ; returns the signed result of A * B in register D.
762 tsta
763 bmi A_neg
764 tstb
765 bmi B_neg
768 B_neg:
769 negb
770 bra A_or_B_neg
771 A_neg:
772 nega
773 tstb
774 bmi AB_neg
775 A_or_B_neg:
777 coma
778 comb
779 addd #1
781 AB_neg:
782 negb
785 #endif
787 #ifdef L_mulhi3
788 declare_near ___mulhi3
792 ; unsigned short ___mulhi3(unsigned short a, unsigned short b)
794 ; a = register D
795 ; b = register X
797 #ifdef mc68hc12
798 pshx ; Preserve X
799 exg x,y
800 emul
801 exg x,y
802 pulx
804 #else
805 #ifdef NO_TMP
807 ; 16 bit multiplication without temp memory location.
808 ; (smaller but slower)
810 pshx ; (4)
811 ins ; (3)
812 pshb ; (3)
813 psha ; (3)
814 pshx ; (4)
815 pula ; (4)
816 pulx ; (5)
817 mul ; (10) B.high * A.low
818 xgdx ; (3)
819 mul ; (10) B.low * A.high
820 abx ; (3)
821 pula ; (4)
822 pulb ; (4)
823 mul ; (10) B.low * A.low
824 pshx ; (4)
825 tsx ; (3)
826 adda 1,x ; (4)
827 pulx ; (5)
828 rts ; (5) 20 bytes
829 ; ---
830 ; 91 cycles
831 #else
832 stx *_.tmp ; (4)
833 pshb ; (3)
834 ldab *_.tmp+1 ; (3)
835 mul ; (10) A.high * B.low
836 ldaa *_.tmp ; (3)
837 stab *_.tmp ; (3)
838 pulb ; (4)
839 pshb ; (4)
840 mul ; (10) A.low * B.high
841 addb *_.tmp ; (4)
842 stab *_.tmp ; (3)
843 ldaa *_.tmp+1 ; (3)
844 pulb ; (4)
845 mul ; (10) A.low * B.low
846 adda *_.tmp ; (4)
847 rts ; (5) 24/32 bytes
848 ; 77/85 cycles
849 #endif
850 #endif
851 #endif
853 #ifdef L_mulhi32
857 ; unsigned long __mulhi32(unsigned short a, unsigned short b)
859 ; a = register D
860 ; b = value on stack
862 ; +---------------+
863 ; | B low | <- 7,x
864 ; +---------------+
865 ; | B high | <- 6,x
866 ; +---------------+
867 ; | PC low |
868 ; +---------------+
869 ; | PC high |
870 ; +---------------+
871 ; | Tmp low |
872 ; +---------------+
873 ; | Tmp high |
874 ; +---------------+
875 ; | A low |
876 ; +---------------+
877 ; | A high |
878 ; +---------------+ <- 0,x
881 ; <B-low> 5,x
882 ; <B-high> 4,x
883 ; <ret> 2,x
884 ; <A-low> 1,x
885 ; <A-high> 0,x
887 declare_near __mulhi32
889 #ifdef mc68hc12
890 ldy 2,sp
891 emul
892 exg x,y
894 #else
895 pshx ; Room for temp value
896 pshb
897 psha
899 ldab 6,x
901 xgdy ; A.high * B.high
902 ldab 7,x
903 pula
904 mul ; A.high * B.low
905 std 2,x
906 ldaa 1,x
907 ldab 6,x
908 mul ; A.low * B.high
909 addd 2,x
910 stab 2,x
913 bcc N
914 ldab #0xff
918 ldab 7,x
919 pula
920 mul ; A.low * B.low
921 adda 2,x
922 pulx ; Drop temp location
923 pshy ; Put high part in X
924 pulx
925 bcc Ret
927 Ret:
929 #endif
930 #endif
932 #ifdef L_mulsi3
935 ; <B-low> 8,y
936 ; <B-high> 6,y
937 ; <ret> 4,y
938 ; <tmp> 2,y
939 ; <A-low> 0,y
941 ; D,X -> A
942 ; Stack -> B
944 ; The result is:
946 ; (((A.low * B.high) + (A.high * B.low)) << 16) + (A.low * B.low)
951 declare __mulsi3
953 #ifdef mc68hc12
954 pshd ; Save A.low
955 ldy ARG(4),sp
956 emul ; A.low * B.high
957 ldy ARG(6),sp
958 exg x,d
959 emul ; A.high * B.low
960 leax d,x
961 ldy ARG(6),sp
962 puld
963 emul ; A.low * B.low
964 exg d,y
965 leax d,x
966 exg d,y
968 #else
969 B_low = ARG(8)
970 B_high = ARG(6)
971 A_low = 0
972 A_high = 2
973 pshx
974 pshb
975 psha
978 ; If B.low is 0, optimize into: (A.low * B.high) << 16
980 ldd B_low,y
981 beq B_low_zero
983 ; If A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
985 cpx #0
986 beq A_high_zero
987 bsr ___mulhi3 ; A.high * B.low
989 ; If A.low is 0, optimize into: (A.high * B.low) << 16
991 ldx A_low,y
992 beq A_low_zero ; X = 0, D = A.high * B.low
993 std 2,y
995 ; If B.high is 0, we can avoid the (A.low * B.high) << 16 term.
997 ldd B_high,y
998 beq B_high_zero
999 bsr ___mulhi3 ; A.low * B.high
1000 addd 2,y
1001 std 2,y
1003 ; Here, we know that A.low and B.low are not 0.
1005 B_high_zero:
1006 ldd B_low,y ; A.low is on the stack
1007 bsr __mulhi32 ; A.low * B.low
1008 xgdx
1009 tsy ; Y was clobbered, get it back
1010 addd 2,y
1011 A_low_zero: ; See A_low_zero_non_optimized below
1012 xgdx
1013 Return:
1021 ; A_low_zero_non_optimized:
1023 ; At this step, X = 0 and D = (A.high * B.low)
1024 ; Optimize into: (A.high * B.low) << 16
1026 ; xgdx
1027 ; clra ; Since X was 0, clearing D is superfuous.
1028 ; clrb
1029 ; bra Return
1030 ; ----------------
1031 ; B.low == 0, the result is: (A.low * B.high) << 16
1033 ; At this step:
1034 ; D = B.low = 0
1035 ; X = A.high ?
1036 ; A.low is at A_low,y ?
1037 ; B.low is at B_low,y ?
1039 B_low_zero:
1040 ldd A_low,y
1041 beq Zero1
1042 ldx B_high,y
1043 beq Zero2
1044 bsr ___mulhi3
1045 Zero1:
1046 xgdx
1047 Zero2:
1048 clra
1049 clrb
1050 bra Return
1051 ; ----------------
1052 ; A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
1054 ; At this step:
1055 ; D = B.low != 0
1056 ; X = A.high = 0
1057 ; A.low is at A_low,y ?
1058 ; B.low is at B_low,y ?
1060 A_high_zero:
1061 ldd A_low,y ; A.low
1062 beq Zero1
1063 ldx B_high,y ; B.high
1064 beq A_low_B_low
1065 bsr ___mulhi3
1066 std 2,y
1067 bra B_high_zero ; Do the (A.low * B.low) and the add.
1069 ; ----------------
1070 ; A.high and B.high are 0 optimize into: (A.low * B.low)
1072 ; At this step:
1073 ; D = B.high = 0
1074 ; X = A.low != 0
1075 ; A.low is at A_low,y != 0
1076 ; B.high is at B_high,y = 0
1078 A_low_B_low:
1079 ldd B_low,y ; A.low is on the stack
1080 bsr __mulhi32
1081 bra Return
1082 #endif
1083 #endif
1085 #ifdef L_map_data
1087 .sect .install2,"ax",@progbits
1088 .globl __map_data_section
1089 .globl __data_image
1090 #ifdef mc68hc12
1091 .globl __data_section_size
1092 #endif
1093 __map_data_section:
1094 #ifdef mc68hc12
1095 ldx #__data_image
1096 ldy #__data_section_start
1097 ldd #__data_section_size
1098 beq Done
1099 Loop:
1100 movb 1,x+,1,y+
1101 dbne d,Loop
1102 #else
1103 ldx #__data_image
1104 ldy #__data_section_start
1105 bra Start_map
1106 Loop:
1107 ldaa 0,x
1108 staa 0,y
1111 Start_map:
1112 cpx #__data_image_end
1113 blo Loop
1114 #endif
1115 Done:
1117 #endif
1119 #ifdef L_init_bss
1121 .sect .install2,"ax",@progbits
1122 .globl __init_bss_section
1124 __init_bss_section:
1125 ldd #__bss_size
1126 beq Done
1127 ldx #__bss_start
1128 Loop:
1129 #ifdef mc68hc12
1130 clr 1,x+
1131 dbne d,Loop
1132 #else
1133 clr 0,x
1135 subd #1
1136 bne Loop
1137 #endif
1138 Done:
1140 #endif
1142 #ifdef L_ctor
1144 ; End of constructor table
1145 .sect .install3,"ax",@progbits
1146 .globl __do_global_ctors
1148 __do_global_ctors:
1149 ; Start from the end - sizeof(void*)
1150 ldx #__CTOR_END__-2
1151 ctors_loop:
1152 cpx #__CTOR_LIST__
1153 blo ctors_done
1154 pshx
1155 ldx 0,x
1156 jsr 0,x
1157 pulx
1160 bra ctors_loop
1161 ctors_done:
1163 #endif
1165 #ifdef L_dtor
1167 .sect .fini3,"ax",@progbits
1168 .globl __do_global_dtors
1171 ;; This piece of code is inserted in the _exit() code by the linker.
1173 __do_global_dtors:
1174 pshb ; Save exit code
1175 psha
1176 ldx #__DTOR_LIST__
1177 dtors_loop:
1178 cpx #__DTOR_END__
1179 bhs dtors_done
1180 pshx
1181 ldx 0,x
1182 jsr 0,x
1183 pulx
1186 bra dtors_loop
1187 dtors_done:
1188 pula ; Restore exit code
1189 pulb
1191 #endif
1193 #ifdef L_far_tramp
1194 #ifdef mc68hc12
1195 .sect .tramp,"ax",@progbits
1196 .globl __far_trampoline
1198 ;; This is a trampoline used by the linker to invoke a function
1199 ;; using rtc to return and being called with jsr/bsr.
1200 ;; The trampoline generated is:
1202 ;; foo_tramp:
1203 ;; ldy #foo
1204 ;; call __far_trampoline,page(foo)
1206 ;; The linker transforms:
1208 ;; jsr foo
1210 ;; into
1211 ;; jsr foo_tramp
1213 ;; The linker generated trampoline and _far_trampoline must be in
1214 ;; non-banked memory.
1216 __far_trampoline:
1217 movb 0,sp, 2,sp ; Copy page register below the caller's return
1218 leas 2,sp ; address.
1219 jmp 0,y ; We have a 'call/rtc' stack layout now
1220 ; and can jump to the far handler
1221 ; (whose memory bank is mapped due to the
1222 ; call to the trampoline).
1223 #endif
1225 #ifdef mc68hc11
1226 .sect .tramp,"ax",@progbits
1227 .globl __far_trampoline
1229 ;; Trampoline generated by gcc for 68HC11:
1231 ;; pshb
1232 ;; ldab #%page(func)
1233 ;; ldy #%addr(func)
1234 ;; jmp __far_trampoline
1236 __far_trampoline:
1237 psha ; (2) Save function parameter (high)
1238 ;; <Read current page in A>
1239 psha ; (2)
1240 ;; <Set currenge page from B>
1241 pshx ; (4)
1242 tsx ; (3)
1243 ldab 4,x ; (4) Restore function parameter (low)
1244 ldaa 2,x ; (4) Get saved page number
1245 staa 4,x ; (4) Save it below return PC
1246 pulx ; (5)
1247 pula ; (3)
1248 pula ; (3) Restore function parameter (high)
1249 jmp 0,y ; (4)
1250 #endif
1251 #endif
1253 #ifdef L_call_far
1254 #ifdef mc68hc11
1255 .sect .tramp,"ax",@progbits
1256 .globl __call_a16
1257 .globl __call_a32
1259 ;; The call methods are used for 68HC11 to support memory bank switching.
1260 ;; Every far call is redirected to these call methods. Its purpose is to:
1262 ;; 1/ Save the current page on the stack (1 byte to follow 68HC12 call frame)
1263 ;; 2/ Install the new page
1264 ;; 3/ Jump to the real function
1266 ;; The page switching (get/save) is board dependent. The default provided
1267 ;; here does nothing (just create the appropriate call frame).
1269 ;; Call sequence (10 bytes, 13 cycles):
1271 ;; ldx #page ; (3)
1272 ;; ldy #func ; (4)
1273 ;; jsr __call_a16 ; (6)
1275 ;; Call trampoline (11 bytes, 19 cycles):
1277 __call_a16:
1278 ;; xgdx ; (3)
1279 ;; <Read current page in A> ; (3) ldaa _current_page
1280 psha ; (2)
1281 ;; <Set current page from B> ; (4) staa _current_page
1282 ;; xgdx ; (3)
1283 jmp 0,y ; (4)
1286 ;; Call sequence (10 bytes, 14 cycles):
1288 ;; pshb ; (2)
1289 ;; ldab #page ; (2)
1290 ;; ldy #func ; (4)
1291 ;; jsr __call_a32 ; (6)
1293 ;; Call trampoline (87 bytes, 57 cycles):
1295 __call_a32:
1296 pshx ; (4)
1297 psha ; (2)
1298 ;; <Read current page in A> ; (3) ldaa _current_page
1299 psha ; (2)
1300 ;; <Set current page from B> ; (4) staa _current_page
1301 tsx ; (3)
1302 ldab 6,x ; (4) Restore function parameter
1303 ldaa 5,x ; (4) Move PC return at good place
1304 staa 6,x ; (4)
1305 ldaa 4,x ; (4)
1306 staa 5,x ; (4)
1307 pula ; (3)
1308 staa 4,x ; (4)
1309 pula ; (3)
1310 pulx ; (5)
1311 jmp 0,y ; (4)
1312 #endif
1313 #endif
1315 #ifdef L_return_far
1316 #ifdef mc68hc11
1317 .sect .tramp,"ax",@progbits
1318 .globl __return_void
1319 .globl __return_16
1320 .globl __return_32
1322 __return_void:
1323 ;; pulb
1324 ;; <Set current page from B> (Board specific)
1325 ;; rts
1326 __return_16:
1327 ;; xgdx
1328 ;; pulb
1329 ;; <Set current page from B> (Board specific)
1330 ;; xgdx
1331 ;; rts
1332 __return_32:
1333 ;; xgdy
1334 ;; pulb
1335 ;; <Set current page from B> (Board specific)
1336 ;; xgdy
1337 ;; rts
1340 #endif
1341 #endif
1342 .Lend:
1343 ;-----------------------------------------
1344 ; end required gcclib code
1345 ;-----------------------------------------