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