OSDN Git Service

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