OSDN Git Service

GNU CC -> GCC
[pf3gnuchains/gcc-fork.git] / gcc / config / m68hc11 / larith.asm
1 /* libgcc routines for M68HC11 & M68HC12.
2    Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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.
10
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.)
18
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.
23
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.  */
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)                       \
97 NAME:   .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
108 REG(_.tmp)
109 REG(_.z)
110 REG(_.xy)
111
112 #endif
113
114 #ifdef L_regs_frame
115         .sect .softregs
116         .globl _.frame
117 REG(_.frame)
118 #endif
119
120 #ifdef L_regs_d1_2
121         .sect .softregs
122         .globl _.d1,_.d2
123 REG(_.d1)
124 REG(_.d2)
125 #endif
126
127 #ifdef L_regs_d3_4
128         .sect .softregs
129         .globl _.d3,_.d4
130 REG(_.d3)
131 REG(_.d4)
132 #endif
133
134 #ifdef L_regs_d5_6
135         .sect .softregs
136         .globl _.d5,_.d6
137 REG(_.d5)
138 REG(_.d6)
139 #endif
140
141 #ifdef L_regs_d7_8
142         .sect .softregs
143         .globl _.d7,_.d8
144 REG(_.d7)
145 REG(_.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
154 REG(_.d9)
155 REG(_.d10)
156 REG(_.d11)
157 REG(_.d12)
158 REG(_.d13)
159 REG(_.d14)
160 REG(_.d15)
161 REG(_.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
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
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
223 exit:
224 _exit:
225
226         .sect .fini4,"ax",@progbits
227 fatal:
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+
281 Start:
282         beq     Done
283 Loop:
284         movw    2,x+,2,y+
285         dbne    d,Loop
286 Done:
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
298 L0:
299         psha                    ; Save high-counter part
300 L1:
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
311 End:
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
342 Loop:
343         stab    1,x+
344         dbne    y,Loop
345 End:
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
355 L0:
356         stab    0,x             ; Fill up to 256 bytes
357         inx
358         dey
359         bne     L0
360         pulx                    ; Restore X to return the DST
361 End:
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
463 done:
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
487 Loop:
488         lsld
489         xgdx
490         rolb
491         rola
492         xgdx
493         dey
494         bne     Loop
495 Return:
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
507 Loop:
508         xgdx
509         asra
510         rorb
511         xgdx
512         rora
513         rorb
514         dey
515         bne     Loop
516 Return:
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
528 Loop:
529         xgdx
530         lsrd
531         xgdx
532         rora
533         rorb
534         dey
535         bne     Loop
536 Return:
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
547 Loop:
548         lsrd
549         dex
550         bne     Loop
551 Return:
552         rts
553 Return_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
566 Loop:
567         lsld
568         dex
569         bne     Loop
570 Return:
571         rts
572 Return_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
587 Loop:
588         tap
589         rorb
590         rora
591         dex
592         bne     Loop
593 Return:
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
606 Loop:
607         asrb
608         rolb
609         rola
610         rolb
611         dex
612         bne     Loop
613 Return:
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
624 Loop:
625         asra
626         rorb
627         dex
628         bne     Loop
629 Return:
630         rts
631 Return_minus_1_or_zero:
632         clrb
633         tsta
634         bpl     Return_zero
635         comb
636 Return_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
648 Loop:
649         asrb
650         deca
651         bne     Loop
652 Return:
653         rts
654 Return_minus_1_or_zero:
655         clrb
656         tstb
657         bpl     Return_zero
658         coma
659 Return_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
671 Loop:
672         lslb
673         deca
674         bne     Loop
675 Return:
676         rts
677 Return_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
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
712         inx
713         rts
714
715 Numerator_pos_denominator_pos:
716         xgdx
717         idiv
718         xgdx                    ; Both values are >= 0
719         rts
720         
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
729         inx
730         idiv
731         xgdx                    ; Remainder >= 0 but result <= 0
732         coma
733         comb
734         addd    #1
735         rts
736         
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
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
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:
776         mul
777         coma
778         comb
779         addd    #1
780         rts
781 AB_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
917 N:
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
927 Ret:
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
969 B_low   =       ARG(8)
970 B_high  =       ARG(6)
971 A_low   =       0
972 A_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 ;
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:
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 ;
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)
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 ;
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.
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 ;
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
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
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
1109         inx
1110         iny
1111 Start_map:
1112         cpx     #__data_image_end
1113         blo     Loop
1114 #endif
1115 Done:
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
1128 Loop:
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
1138 Done:
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
1151 ctors_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
1161 ctors_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__
1177 dtors_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
1187 dtors_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 ;-----------------------------------------