1 /* libgcc routines for M68HC11 & M68HC12.
2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
4 This file is part of GNU CC.
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
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.)
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.
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. */
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. */
43 .type NAME,@object ; \
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. */
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. */
122 .globl _.d9,_.d10,_.d11,_.d12,_.d13,_.d14
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. */
144 .globl _.d17,_.d18,_.d19,_.d20,_.d21,_.d22
145 .globl _.d23,_.d24,_.d25,_.d26,_.d27,_.d28
146 .globl _.d29,_.d30,_.d31,_.d32
167 ;; Specific initialization for 68hc11 before the main.
168 ;; Nothing special for a generic routine; Just enable interrupts.
174 tap ; Clear both I and X.
180 ;; Exit operation. Just loop forever and wait for interrupts.
181 ;; (no other place to go)
197 ;; Abort operation. This is defined for the GCC testsuite.
206 .byte 0xCD ; Generate an illegal instruction trap
207 .byte 0x03 ; The simulator catches this and stops.
214 ;; Cleanup operation used by exit().
222 ;-----------------------------------------
223 ; required gcclib code
224 ;-----------------------------------------
231 ;;; void* memcpy(void*, const void*, size_t)
235 ;;; 4,sp = size HImode (size_t)
259 ldx 2,x ; SRC = X, DST = Y
263 inca ; Correction for the deca below
265 psha ; Save high-counter part
267 ldaa 0,x ; Copy up to 256 bytes
276 puly ; Restore Y to return the DST
288 ;;; void* memset(void*, int value, size_t)
290 #ifndef __HAVE_SHORT_INT__
292 ;;; 2,sp = src SImode
293 ;;; 6,sp = size HImode (size_t)
298 ;;; 2,sp = src SImode
299 ;;; 6,sp = size HImode (size_t)
321 ldy size,y ; DST = X, CNT = Y
325 stab 0,x ; Fill up to 256 bytes
329 pulx ; Restore X to return the DST
469 .globl ___one_cmplsi2
596 bge Return_minus_1_or_zero
606 Return_minus_1_or_zero:
622 bge Return_minus_1_or_zero
631 Return_minus_1_or_zero:
663 /* 68HC12 signed divisions are generated inline (idivs). */
678 comb ; D = -D <=> D = (~D) + 1
683 bpl Numerator_neg_denominator_pos
684 Numerator_neg_denominator_neg:
692 xgdx ; Remainder <= 0 and result >= 0
696 Numerator_pos_denominator_pos:
699 xgdx ; Both values are >= 0
705 bpl Numerator_pos_denominator_pos
706 Numerator_pos_denominator_neg:
712 xgdx ; Remainder >= 0 but result <= 0
718 Numerator_neg_denominator_pos:
721 coma ; One value is > 0 and the other < 0
722 comb ; Change the sign of result and remainder
729 #endif /* !mc68hc12 */
737 ; short __mulqi3(signed char a, signed char b);
739 ; signed char a -> register A
740 ; signed char b -> register B
742 ; returns the signed result of A * B in register D.
776 ; unsigned short ___mulhi3(unsigned short a, unsigned short b)
814 ; unsigned long __mulhi32(unsigned short a, unsigned short b)
831 ; +---------------+ <- 0,x
851 xgdy ; A.high * B.high
898 ; (((A.low * B.high) + (A.high * B.low)) << 16) + (A.low * B.low)
907 emul ; A.low * B.high
910 emul ; A.high * B.low
929 ; If B.low is 0, optimize into: (A.low * B.high) << 16
934 ; If A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
938 bsr ___mulhi3 ; A.high * B.low
940 ; If A.low is 0, optimize into: (A.high * B.low) << 16
943 beq A_low_zero ; X = 0, D = A.high * B.low
946 ; If B.high is 0, we can avoid the (A.low * B.high) << 16 term.
950 bsr ___mulhi3 ; A.low * B.high
954 ; Here, we know that A.low and B.low are not 0.
957 ldd B_low,y ; A.low is on the stack
958 bsr __mulhi32 ; A.low * B.low
960 tsy ; Y was clobbered, get it back
962 A_low_zero: ; See A_low_zero_non_optimized below
972 ; A_low_zero_non_optimized:
974 ; At this step, X = 0 and D = (A.high * B.low)
975 ; Optimize into: (A.high * B.low) << 16
978 ; clra ; Since X was 0, clearing D is superfuous.
982 ; B.low == 0, the result is: (A.low * B.high) << 16
987 ; A.low is at A_low,y ?
988 ; B.low is at B_low,y ?
1003 ; A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
1008 ; A.low is at A_low,y ?
1009 ; B.low is at B_low,y ?
1014 ldx B_high,y ; B.high
1018 bra B_high_zero ; Do the (A.low * B.low) and the add.
1021 ; A.high and B.high are 0 optimize into: (A.low * B.low)
1026 ; A.low is at A_low,y != 0
1027 ; B.high is at B_high,y = 0
1030 ldd B_low,y ; A.low is on the stack
1038 .sect .install3,"ax",@progbits
1039 .globl __map_data_section
1042 ldd #__data_section_size
1045 ldy #__data_section_start
1066 .sect .install3,"ax",@progbits
1067 .globl __init_bss_section
1087 ;-----------------------------------------
1088 ; end required gcclib code
1089 ;-----------------------------------------