1/* libgcc routines for M68HC11 & M68HC12.
2   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11In addition to the permissions in the GNU General Public License, the
12Free Software Foundation gives you unlimited permission to link the
13compiled version of this file with other programs, and to distribute
14those programs without any restriction coming from the use of this
15file.  (The General Public License restrictions do apply in other
16respects; for example, they cover modification of the file, and
17distribution when not linked into another program.)
18
19This file is distributed in the hope that it will be useful, but
20WITHOUT ANY WARRANTY; without even the implied warranty of
21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22General Public License for more details.
23
24You should have received a copy of the GNU General Public License
25along with this program; see the file COPYING.  If not, write to
26the Free Software Foundation, 59 Temple Place - Suite 330,
27Boston, MA 02111-1307, USA.  */
28
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.  */
35
36	.file "larith.asm"
37
38#ifdef __HAVE_SHORT_INT__
39	.mode mshort
40#else
41	.mode mlong
42#endif
43
44	.macro declare_near name
45	.globl \name
46	.type  \name,@function
47	.size  \name,.Lend-\name
48\name:
49	.endm
50
51#if defined(__USE_RTC__)
52# define ARG(N) N+1
53
54	.macro ret
55#if defined(mc68hc12)
56	rtc
57#else
58	jmp __return_32
59#endif
60	.endm
61
62	.macro declare name
63	.globl \name
64	.type  \name,@function
65	.size  \name,.Lend-\name
66	.far   \name
67\name:
68	.endm
69
70	.macro farsym name
71	.far NAME
72	.endm
73
74#else
75# define ARG(N) N
76
77	.macro ret
78	rts
79	.endm
80
81	.macro farsym name
82	.endm
83
84	.macro declare name
85	.globl \name
86	.type  \name,@function
87	.size  \name,.Lend-\name
88\name:
89	.endm
90
91#endif
92
93	.sect .text
94
95
96#define REG(NAME)			\
97NAME:	.dc.w	1;			\
98	.type NAME,@object ;		\
99	.size NAME,2
100
101#ifdef L_regs_min
102/* Pseudo hard registers used by gcc.
103   They should be located in page0.  */
104
105	.sect .softregs
106	.globl _.tmp
107	.globl _.z,_.xy
108REG(_.tmp)
109REG(_.z)
110REG(_.xy)
111
112#endif
113
114#ifdef L_regs_frame
115	.sect .softregs
116	.globl _.frame
117REG(_.frame)
118#endif
119
120#ifdef L_regs_d1_2
121	.sect .softregs
122	.globl _.d1,_.d2
123REG(_.d1)
124REG(_.d2)
125#endif
126
127#ifdef L_regs_d3_4
128	.sect .softregs
129	.globl _.d3,_.d4
130REG(_.d3)
131REG(_.d4)
132#endif
133
134#ifdef L_regs_d5_6
135	.sect .softregs
136	.globl _.d5,_.d6
137REG(_.d5)
138REG(_.d6)
139#endif
140
141#ifdef L_regs_d7_8
142	.sect .softregs
143	.globl _.d7,_.d8
144REG(_.d7)
145REG(_.d8)
146#endif
147
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
154REG(_.d9)
155REG(_.d10)
156REG(_.d11)
157REG(_.d12)
158REG(_.d13)
159REG(_.d14)
160REG(_.d15)
161REG(_.d16)
162
163#endif
164
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
172REG(_.d17)
173REG(_.d18)
174REG(_.d19)
175REG(_.d20)
176REG(_.d21)
177REG(_.d22)
178REG(_.d23)
179REG(_.d24)
180REG(_.d25)
181REG(_.d26)
182REG(_.d27)
183REG(_.d28)
184REG(_.d29)
185REG(_.d30)
186REG(_.d31)
187REG(_.d32)
188#endif
189
190#ifdef L_premain
191;;
192;; Specific initialization for 68hc11 before the main.
193;; Nothing special for a generic routine; Just enable interrupts.
194;;
195	declare_near	__premain
196	clra
197	tap	; Clear both I and X.
198	rts
199#endif
200
201#ifdef L__exit
202;;
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.
209;;
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.  */
216;;
217	.sect .fini0,"ax",@progbits
218	.globl _exit
219	.globl exit
220	.weak  exit
221	farsym  exit
222	farsym  _exit
223exit:
224_exit:
225
226	.sect .fini4,"ax",@progbits
227fatal:
228	cli
229	wai
230	bra fatal
231#endif
232
233#ifdef L_abort
234;;
235;; Abort operation.  This is defined for the GCC testsuite.
236;;
237	declare	abort
238
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
248
249#ifdef L_cleanup
250;;
251;; Cleanup operation used by exit().
252;;
253	declare	_cleanup
254
255	ret
256#endif
257
258;-----------------------------------------
259; required gcclib code
260;-----------------------------------------
261#ifdef L_memcpy
262       declare	memcpy
263       declare	__memcpy
264
265	.weak memcpy
266;;;
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+
281Start:
282	beq	Done
283Loop:
284	movw	2,x+,2,y+
285	dbne	d,Loop
286Done:
287	puld
288	ret
289#else
290	xgdy
291	tsx
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
298L0:
299	psha			; Save high-counter part
300L1:
301	ldaa	0,x		; Copy up to 256 bytes
302	staa	0,y
303	inx
304	iny
305	decb
306	bne	L1
307	pula
308	deca
309	bne	L0
310	puly			; Restore Y to return the DST
311End:
312	xgdy
313	ret
314#endif
315#endif
316
317#ifdef L_memset
318       declare	memset
319       declare	__memset
320;;;
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
342Loop:
343	stab	1,x+
344	dbne	y,Loop
345End:
346	puld
347	ret
348#else
349	xgdx
350	tsy
351	ldab	val,y
352	ldy	size,y		; DST = X, CNT = Y
353	beq	End
354	pshx
355L0:
356	stab	0,x		; Fill up to 256 bytes
357	inx
358	dey
359	bne	L0
360	pulx			; Restore X to return the DST
361End:
362	xgdx
363	ret
364#endif
365#endif
366
367#ifdef L_adddi3
368	declare	___adddi3
369
370	tsx
371	xgdy
372	ldd	ARG(8),x		; Add LSB
373	addd	ARG(16),x
374	std	6,y		; Save (carry preserved)
375
376	ldd	ARG(6),x
377	adcb	ARG(15),x
378	adca	ARG(14),x
379	std	4,y
380
381	ldd	ARG(4),x
382	adcb	ARG(13),x
383	adca	ARG(12),x
384	std	2,y
385
386	ldd	ARG(2),x
387	adcb	ARG(11),x		; Add MSB
388	adca	ARG(10),x
389	std	0,y
390
391	xgdy
392	ret
393#endif
394
395#ifdef L_subdi3
396	declare	___subdi3
397
398	tsx
399	xgdy
400	ldd	ARG(8),x		; Subtract LSB
401	subd	ARG(16),x
402	std	6,y			; Save, borrow preserved
403
404	ldd	ARG(6),x
405	sbcb	ARG(15),x
406	sbca	ARG(14),x
407	std	4,y
408
409	ldd	ARG(4),x
410	sbcb	ARG(13),x
411	sbca	ARG(12),x
412	std	2,y
413
414	ldd	ARG(2),x		; Subtract MSB
415	sbcb	ARG(11),x
416	sbca	ARG(10),x
417	std	0,y
418
419	xgdy			;
420	ret
421#endif
422
423#ifdef L_notdi2
424	declare	___notdi2
425
426	tsy
427	xgdx
428	ldd	ARG(8),y
429	coma
430	comb
431	std	6,x
432
433	ldd	ARG(6),y
434	coma
435	comb
436	std	4,x
437
438	ldd	ARG(4),y
439	coma
440	comb
441	std	2,x
442
443	ldd	ARG(2),y
444	coma
445	comb
446	std	0,x
447	xgdx
448	ret
449#endif
450
451#ifdef L_negsi2
452	declare_near ___negsi2
453
454	comb
455	coma
456	xgdx
457	comb
458	coma
459	inx
460	xgdx
461	bne	done
462	inx
463done:
464	rts
465#endif
466
467#ifdef L_one_cmplsi2
468	declare_near ___one_cmplsi2
469
470	comb
471	coma
472	xgdx
473	comb
474	coma
475	xgdx
476	rts
477#endif
478
479#ifdef L_ashlsi3
480	declare_near ___ashlsi3
481
482	xgdy
483	clra
484	andb	#0x1f
485	xgdy
486	beq	Return
487Loop:
488	lsld
489	xgdx
490	rolb
491	rola
492	xgdx
493	dey
494	bne	Loop
495Return:
496	rts
497#endif
498
499#ifdef L_ashrsi3
500	declare_near ___ashrsi3
501
502	xgdy
503	clra
504	andb	#0x1f
505	xgdy
506	beq	Return
507Loop:
508	xgdx
509	asra
510	rorb
511	xgdx
512	rora
513	rorb
514	dey
515	bne	Loop
516Return:
517	rts
518#endif
519
520#ifdef L_lshrsi3
521	declare_near ___lshrsi3
522
523	xgdy
524	clra
525	andb	#0x1f
526	xgdy
527	beq	Return
528Loop:
529	xgdx
530	lsrd
531	xgdx
532	rora
533	rorb
534	dey
535	bne	Loop
536Return:
537	rts
538#endif
539
540#ifdef L_lshrhi3
541	declare_near ___lshrhi3
542
543	cpx	#16
544	bge	Return_zero
545	cpx	#0
546	beq	Return
547Loop:
548	lsrd
549	dex
550	bne	Loop
551Return:
552	rts
553Return_zero:
554	clra
555	clrb
556	rts
557#endif
558
559#ifdef L_lshlhi3
560	declare_near ___lshlhi3
561
562	cpx	#16
563	bge	Return_zero
564	cpx	#0
565	beq	Return
566Loop:
567	lsld
568	dex
569	bne	Loop
570Return:
571	rts
572Return_zero:
573	clra
574	clrb
575	rts
576#endif
577
578#ifdef L_rotrhi3
579	declare_near ___rotrhi3
580
581___rotrhi3:
582	xgdx
583	clra
584	andb	#0x0f
585	xgdx
586	beq	Return
587Loop:
588	tap
589	rorb
590	rora
591	dex
592	bne	Loop
593Return:
594	rts
595#endif
596
597#ifdef L_rotlhi3
598	declare_near ___rotlhi3
599
600___rotlhi3:
601	xgdx
602	clra
603	andb	#0x0f
604	xgdx
605	beq	Return
606Loop:
607	asrb
608	rolb
609	rola
610	rolb
611	dex
612	bne	Loop
613Return:
614	rts
615#endif
616
617#ifdef L_ashrhi3
618	declare_near ___ashrhi3
619
620	cpx	#16
621	bge	Return_minus_1_or_zero
622	cpx	#0
623	beq	Return
624Loop:
625	asra
626	rorb
627	dex
628	bne	Loop
629Return:
630	rts
631Return_minus_1_or_zero:
632	clrb
633	tsta
634	bpl	Return_zero
635	comb
636Return_zero:
637	tba
638	rts
639#endif
640
641#ifdef L_ashrqi3
642	declare_near ___ashrqi3
643
644	cmpa	#8
645	bge	Return_minus_1_or_zero
646	tsta
647	beq	Return
648Loop:
649	asrb
650	deca
651	bne	Loop
652Return:
653	rts
654Return_minus_1_or_zero:
655	clrb
656	tstb
657	bpl	Return_zero
658	coma
659Return_zero:
660	tab
661	rts
662#endif
663
664#ifdef L_lshlqi3
665	declare_near ___lshlqi3
666
667	cmpa	#8
668	bge	Return_zero
669	tsta
670	beq	Return
671Loop:
672	lslb
673	deca
674	bne	Loop
675Return:
676	rts
677Return_zero:
678	clrb
679	rts
680#endif
681
682#ifdef L_divmodhi4
683#ifndef mc68hc12
684/* 68HC12 signed divisions are generated inline (idivs).  */
685
686	declare_near __divmodhi4
687
688;
689;; D = numerator
690;; X = denominator
691;;
692;; Result:	D = D / X
693;;		X = D % X
694;;
695	tsta
696	bpl	Numerator_pos
697	comb			; D = -D <=> D = (~D) + 1
698	coma
699	xgdx
700	inx
701	tsta
702	bpl	Numerator_neg_denominator_pos
703Numerator_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
712	inx
713	rts
714
715Numerator_pos_denominator_pos:
716	xgdx
717	idiv
718	xgdx			; Both values are >= 0
719	rts
720
721Numerator_pos:
722	xgdx
723	tsta
724	bpl	Numerator_pos_denominator_pos
725Numerator_pos_denominator_neg:
726	coma			; X = -X
727	comb
728	xgdx
729	inx
730	idiv
731	xgdx			; Remainder >= 0 but result <= 0
732	coma
733	comb
734	addd	#1
735	rts
736
737Numerator_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
743	inx
744	coma
745	comb
746	addd	#1
747	rts
748#endif /* !mc68hc12 */
749#endif
750
751#ifdef L_mulqi3
752	declare_near ___mulqi3
753
754;
755; short __mulqi3(signed char a, signed char b);
756;
757;	signed char a	-> register A
758;	signed char b	-> register B
759;
760; returns the signed result of A * B in register D.
761;
762	tsta
763	bmi	A_neg
764	tstb
765	bmi	B_neg
766	mul
767	rts
768B_neg:
769	negb
770	bra	A_or_B_neg
771A_neg:
772	nega
773	tstb
774	bmi	AB_neg
775A_or_B_neg:
776	mul
777	coma
778	comb
779	addd	#1
780	rts
781AB_neg:
782	negb
783	mul
784	rts
785#endif
786
787#ifdef L_mulhi3
788	declare_near ___mulhi3
789
790;
791;
792;  unsigned short ___mulhi3(unsigned short a, unsigned short b)
793;
794;	a = register D
795;	b = register X
796;
797#ifdef mc68hc12
798	pshx			; Preserve X
799	exg	x,y
800	emul
801	exg	x,y
802	pulx
803	rts
804#else
805#ifdef NO_TMP
806	;
807	; 16 bit multiplication without temp memory location.
808	; (smaller but slower)
809	;
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
852
853#ifdef L_mulhi32
854
855;
856;
857;  unsigned long __mulhi32(unsigned short a, unsigned short b)
858;
859;	a = register D
860;	b = value on stack
861;
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
879;
880;
881;      <B-low>    5,x
882;      <B-high>   4,x
883;      <ret>      2,x
884;      <A-low>    1,x
885;      <A-high>   0,x
886;
887	declare_near	__mulhi32
888
889#ifdef mc68hc12
890	ldy	2,sp
891	emul
892	exg	x,y
893	rts
894#else
895	pshx			; Room for temp value
896	pshb
897	psha
898	tsx
899	ldab	6,x
900	mul
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
911	tab
912	aby
913	bcc	N
914	ldab	#0xff
915	aby
916	iny
917N:
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
926	inx
927Ret:
928	rts
929#endif
930#endif
931
932#ifdef L_mulsi3
933
934;
935;      <B-low>    8,y
936;      <B-high>   6,y
937;      <ret>      4,y
938;	<tmp>	  2,y
939;      <A-low>    0,y
940;
941; D,X   -> A
942; Stack -> B
943;
944; The result is:
945;
946;	(((A.low * B.high) + (A.high * B.low)) << 16) + (A.low * B.low)
947;
948;
949;
950
951	declare	__mulsi3
952
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
967	ret
968#else
969B_low	=	ARG(8)
970B_high	=	ARG(6)
971A_low	=	0
972A_high	=	2
973	pshx
974	pshb
975	psha
976	tsy
977;
978; If B.low is 0, optimize into: (A.low * B.high) << 16
979;
980	ldd	B_low,y
981	beq	B_low_zero
982;
983; If A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
984;
985	cpx	#0
986	beq	A_high_zero
987	bsr	___mulhi3		; A.high * B.low
988;
989; If A.low is 0, optimize into: (A.high * B.low) << 16
990;
991	ldx	A_low,y
992	beq	A_low_zero		; X = 0, D = A.high * B.low
993	std	2,y
994;
995; If B.high is 0, we can avoid the (A.low * B.high) << 16 term.
996;
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
1002;
1003; Here, we know that A.low and B.low are not 0.
1004;
1005B_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
1011A_low_zero:				; See A_low_zero_non_optimized below
1012	xgdx
1013Return:
1014	ins
1015	ins
1016	ins
1017	ins
1018	ret
1019;
1020;
1021; A_low_zero_non_optimized:
1022;
1023; At this step, X = 0 and D = (A.high * B.low)
1024; Optimize into: (A.high * B.low) << 16
1025;
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
1032;
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		?
1038;
1039B_low_zero:
1040	ldd	A_low,y
1041	beq	Zero1
1042	ldx	B_high,y
1043	beq	Zero2
1044	bsr	___mulhi3
1045Zero1:
1046	xgdx
1047Zero2:
1048	clra
1049	clrb
1050	bra	Return
1051; ----------------
1052; A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
1053;
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		?
1059;
1060A_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.
1068
1069; ----------------
1070; A.high and B.high are 0 optimize into: (A.low * B.low)
1071;
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
1077;
1078A_low_B_low:
1079	ldd	B_low,y			; A.low is on the stack
1080	bsr	__mulhi32
1081	bra	Return
1082#endif
1083#endif
1084
1085#ifdef L_map_data
1086
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
1099Loop:
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
1106Loop:
1107	ldaa	0,x
1108	staa	0,y
1109	inx
1110	iny
1111Start_map:
1112	cpx	#__data_image_end
1113	blo	Loop
1114#endif
1115Done:
1116
1117#endif
1118
1119#ifdef L_init_bss
1120
1121	.sect	.install2,"ax",@progbits
1122	.globl	__init_bss_section
1123
1124__init_bss_section:
1125	ldd	#__bss_size
1126	beq	Done
1127	ldx	#__bss_start
1128Loop:
1129#ifdef mc68hc12
1130	clr	1,x+
1131	dbne	d,Loop
1132#else
1133	clr	0,x
1134	inx
1135	subd	#1
1136	bne	Loop
1137#endif
1138Done:
1139
1140#endif
1141
1142#ifdef L_ctor
1143
1144; End of constructor table
1145	.sect	.install3,"ax",@progbits
1146	.globl	__do_global_ctors
1147
1148__do_global_ctors:
1149	; Start from the end - sizeof(void*)
1150	ldx	#__CTOR_END__-2
1151ctors_loop:
1152	cpx	#__CTOR_LIST__
1153	blo	ctors_done
1154	pshx
1155	ldx	0,x
1156	jsr	0,x
1157	pulx
1158	dex
1159	dex
1160	bra	ctors_loop
1161ctors_done:
1162
1163#endif
1164
1165#ifdef L_dtor
1166
1167	.sect	.fini3,"ax",@progbits
1168	.globl	__do_global_dtors
1169
1170;;
1171;; This piece of code is inserted in the _exit() code by the linker.
1172;;
1173__do_global_dtors:
1174	pshb	; Save exit code
1175	psha
1176	ldx	#__DTOR_LIST__
1177dtors_loop:
1178	cpx	#__DTOR_END__
1179	bhs	dtors_done
1180	pshx
1181	ldx	0,x
1182	jsr	0,x
1183	pulx
1184	inx
1185	inx
1186	bra	dtors_loop
1187dtors_done:
1188	pula	; Restore exit code
1189	pulb
1190
1191#endif
1192
1193#ifdef L_far_tramp
1194#ifdef mc68hc12
1195	.sect	.tramp,"ax",@progbits
1196	.globl	__far_trampoline
1197
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:
1201;;
1202;;	foo_tramp:
1203;;		ldy	#foo
1204;;		call	__far_trampoline,page(foo)
1205;;
1206;; The linker transforms:
1207;;
1208;;		jsr	foo
1209;;
1210;; into
1211;;		jsr	foo_tramp
1212;;
1213;; The linker generated trampoline and _far_trampoline must be in
1214;; non-banked memory.
1215;;
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
1224
1225#ifdef mc68hc11
1226	.sect	.tramp,"ax",@progbits
1227	.globl __far_trampoline
1228
1229;; Trampoline generated by gcc for 68HC11:
1230;;
1231;;	pshb
1232;;	ldab	#%page(func)
1233;;	ldy	#%addr(func)
1234;;	jmp	__far_trampoline
1235;;
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
1252
1253#ifdef L_call_far
1254#ifdef mc68hc11
1255	.sect	.tramp,"ax",@progbits
1256	.globl __call_a16
1257	.globl __call_a32
1258;;
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:
1261;;
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
1265;;
1266;; The page switching (get/save) is board dependent.  The default provided
1267;; here does nothing (just create the appropriate call frame).
1268;;
1269;; Call sequence (10 bytes, 13 cycles):
1270;;
1271;;	ldx #page			; (3)
1272;;	ldy #func			; (4)
1273;;	jsr __call_a16			; (6)
1274;;
1275;; Call trampoline (11 bytes, 19 cycles):
1276;;
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)
1284
1285;;
1286;; Call sequence (10 bytes, 14 cycles):
1287;;
1288;;	pshb				; (2)
1289;;	ldab #page			; (2)
1290;;	ldy  #func			; (4)
1291;;	jsr __call_a32			; (6)
1292;;
1293;; Call trampoline (87 bytes, 57 cycles):
1294;;
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
1314
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
1321
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
1338	ins
1339	rts
1340#endif
1341#endif
1342.Lend:
1343;-----------------------------------------
1344; end required gcclib code
1345;-----------------------------------------
1346