OSDN Git Service

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