OSDN Git Service

Add NIOS2 support. Code from SourceyG++.
[pf3gnuchains/gcc-fork.git] / gcc / config / m68hc11 / larith.asm
1 /* libgcc routines for M68HC11 & M68HC12.
2    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2008, 2009
3    Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3, or (at your option) any
10 later version.
11
12 This file is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
20
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see 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)                       \
85 NAME:   .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
96 REG(_.tmp)
97 REG(_.z)
98 REG(_.xy)
99
100 #endif
101
102 #ifdef L_regs_frame
103         .sect .softregs
104         .globl _.frame
105 REG(_.frame)
106 #endif
107
108 #ifdef L_regs_d1_2
109         .sect .softregs
110         .globl _.d1,_.d2
111 REG(_.d1)
112 REG(_.d2)
113 #endif
114
115 #ifdef L_regs_d3_4
116         .sect .softregs
117         .globl _.d3,_.d4
118 REG(_.d3)
119 REG(_.d4)
120 #endif
121
122 #ifdef L_regs_d5_6
123         .sect .softregs
124         .globl _.d5,_.d6
125 REG(_.d5)
126 REG(_.d6)
127 #endif
128
129 #ifdef L_regs_d7_8
130         .sect .softregs
131         .globl _.d7,_.d8
132 REG(_.d7)
133 REG(_.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
142 REG(_.d9)
143 REG(_.d10)
144 REG(_.d11)
145 REG(_.d12)
146 REG(_.d13)
147 REG(_.d14)
148 REG(_.d15)
149 REG(_.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
160 REG(_.d17)
161 REG(_.d18)
162 REG(_.d19)
163 REG(_.d20)
164 REG(_.d21)
165 REG(_.d22)
166 REG(_.d23)
167 REG(_.d24)
168 REG(_.d25)
169 REG(_.d26)
170 REG(_.d27)
171 REG(_.d28)
172 REG(_.d29)
173 REG(_.d30)
174 REG(_.d31)
175 REG(_.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
211 exit:
212 _exit:
213
214         .sect .fini4,"ax",@progbits
215 fatal:
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+
269 Start:
270         beq     Done
271 Loop:
272         movw    2,x+,2,y+
273         dbne    d,Loop
274 Done:
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
286 L0:
287         psha                    ; Save high-counter part
288 L1:
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
299 End:
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
330 Loop:
331         stab    1,x+
332         dbne    y,Loop
333 End:
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
343 L0:
344         stab    0,x             ; Fill up to 256 bytes
345         inx
346         dey
347         bne     L0
348         pulx                    ; Restore X to return the DST
349 End:
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
451 done:
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
475 Loop:
476         lsld
477         xgdx
478         rolb
479         rola
480         xgdx
481         dey
482         bne     Loop
483 Return:
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
495 Loop:
496         xgdx
497         asra
498         rorb
499         xgdx
500         rora
501         rorb
502         dey
503         bne     Loop
504 Return:
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
516 Loop:
517         xgdx
518         lsrd
519         xgdx
520         rora
521         rorb
522         dey
523         bne     Loop
524 Return:
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
535 Loop:
536         lsrd
537         dex
538         bne     Loop
539 Return:
540         rts
541 Return_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
554 Loop:
555         lsld
556         dex
557         bne     Loop
558 Return:
559         rts
560 Return_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
575 Loop:
576         tap
577         rorb
578         rora
579         dex
580         bne     Loop
581 Return:
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
594 Loop:
595         asrb
596         rolb
597         rola
598         rolb
599         dex
600         bne     Loop
601 Return:
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
612 Loop:
613         asra
614         rorb
615         dex
616         bne     Loop
617 Return:
618         rts
619 Return_minus_1_or_zero:
620         clrb
621         tsta
622         bpl     Return_zero
623         comb
624 Return_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
636 Loop:
637         asrb
638         deca
639         bne     Loop
640 Return:
641         rts
642 Return_minus_1_or_zero:
643         clrb
644         tstb
645         bpl     Return_zero
646         coma
647 Return_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
659 Loop:
660         lslb
661         deca
662         bne     Loop
663 Return:
664         rts
665 Return_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
691 Numerator_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
703 Numerator_pos_denominator_pos:
704         xgdx
705         idiv
706         xgdx                    ; Both values are >= 0
707         rts
708         
709 Numerator_pos:
710         xgdx
711         tsta
712         bpl     Numerator_pos_denominator_pos
713 Numerator_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         
725 Numerator_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
756 B_neg:
757         negb
758         bra     A_or_B_neg
759 A_neg:
760         nega
761         tstb
762         bmi     AB_neg
763 A_or_B_neg:
764         mul
765         coma
766         comb
767         addd    #1
768         rts
769 AB_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
905 N:
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
915 Ret:
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
957 B_low   =       ARG(8)
958 B_high  =       ARG(6)
959 A_low   =       0
960 A_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 ;
993 B_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
999 A_low_zero:                             ; See A_low_zero_non_optimized below
1000         xgdx
1001 Return:
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 ;
1027 B_low_zero:
1028         ldd     A_low,y
1029         beq     Zero1
1030         ldx     B_high,y
1031         beq     Zero2
1032         bsr     ___mulhi3
1033 Zero1:
1034         xgdx
1035 Zero2:
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 ;
1048 A_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 ;
1066 A_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
1087 Loop:
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
1094 Loop:
1095         ldaa    0,x
1096         staa    0,y
1097         inx
1098         iny
1099 Start_map:
1100         cpx     #__data_image_end
1101         blo     Loop
1102 #endif
1103 Done:
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
1116 Loop:
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
1126 Done:
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
1139 ctors_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
1149 ctors_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__
1165 dtors_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
1175 dtors_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 ;-----------------------------------------