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)
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
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. */
194 .sect .fini0
,"ax",@progbits
201 .sect .fini4
,"ax",@progbits
210 ;; Abort operation. This is defined for the GCC testsuite.
219 .
byte 0xCD ; Generate an illegal instruction trap
220 .
byte 0x03 ; The simulator catches this and stops.
227 ;; Cleanup operation used by exit().
235 ;-----------------------------------------
236 ; required gcclib code
237 ;-----------------------------------------
244 ;;; void* memcpy(void*, const void*, size_t)
248 ;;; 4,sp = size HImode (size_t)
272 ldx
2,x
; SRC = X, DST = Y
276 inca
; Correction for the deca below
278 psha
; Save high-counter part
280 ldaa
0,x
; Copy up to 256 bytes
289 puly
; Restore Y to return the DST
301 ;;; void* memset(void*, int value, size_t)
303 #ifndef __HAVE_SHORT_INT__
305 ;;; 2,sp = src SImode
306 ;;; 6,sp = size HImode (size_t)
311 ;;; 2,sp = src SImode
312 ;;; 6,sp = size HImode (size_t)
334 ldy
size,y
; DST = X, CNT = Y
338 stab
0,x
; Fill up to 256 bytes
342 pulx
; Restore X to return the DST
482 .globl ___one_cmplsi2
609 bge Return_minus_1_or_zero
619 Return_minus_1_or_zero:
635 bge Return_minus_1_or_zero
644 Return_minus_1_or_zero:
676 /* 68HC
12 signed divisions are generated inline
(idivs
).
*/
691 comb
; D = -D <=> D = (~D) + 1
696 bpl Numerator_neg_denominator_pos
697 Numerator_neg_denominator_neg:
705 xgdx
; Remainder <= 0 and result >= 0
709 Numerator_pos_denominator_pos:
712 xgdx
; Both values are >= 0
718 bpl Numerator_pos_denominator_pos
719 Numerator_pos_denominator_neg:
725 xgdx
; Remainder >= 0 but result <= 0
731 Numerator_neg_denominator_pos:
734 coma
; One value is > 0 and the other < 0
735 comb
; Change the sign of result and remainder
742 #endif
/* !mc68hc12
*/
750 ; short __mulqi3(signed char a, signed char b);
752 ; signed char a -> register A
753 ; signed char b -> register B
755 ; returns the signed result of A * B in register D.
789 ; unsigned short ___mulhi3(unsigned short a, unsigned short b)
827 ; unsigned long __mulhi32(unsigned short a, unsigned short b)
844 ; +---------------+ <- 0,x
864 xgdy
; A.high * B.high
911 ; (((A.low * B.high) + (A.high * B.low)) << 16) + (A.low * B.low)
920 emul
; A.low * B.high
923 emul
; A.high * B.low
942 ; If B.low is 0, optimize into: (A.low * B.high) << 16
947 ; If A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
951 bsr ___mulhi3
; A.high * B.low
953 ; If A.low is 0, optimize into: (A.high * B.low) << 16
956 beq A_low_zero
; X = 0, D = A.high * B.low
959 ; If B.high is 0, we can avoid the (A.low * B.high) << 16 term.
963 bsr ___mulhi3
; A.low * B.high
967 ; Here, we know that A.low and B.low are not 0.
970 ldd B_low
,y
; A.low is on the stack
971 bsr __mulhi32
; A.low * B.low
973 tsy
; Y was clobbered, get it back
975 A_low_zero: ; See A_low_zero_non_optimized below
985 ; A_low_zero_non_optimized:
987 ; At this step, X = 0 and D = (A.high * B.low)
988 ; Optimize into: (A.high * B.low) << 16
991 ; clra ; Since X was 0, clearing D is superfuous.
995 ; B.low == 0, the result is: (A.low * B.high) << 16
1000 ; A.low is at A_low,y ?
1001 ; B.low is at B_low,y ?
1016 ; A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
1021 ; A.low is at A_low,y ?
1022 ; B.low is at B_low,y ?
1027 ldx B_high
,y
; B.high
1031 bra B_high_zero
; Do the (A.low * B.low) and the add.
1034 ; A.high and B.high are 0 optimize into: (A.low * B.low)
1039 ; A.low is at A_low,y != 0
1040 ; B.high is at B_high,y = 0
1043 ldd B_low
,y
; A.low is on the stack
1051 .sect .install2
,"ax",@progbits
1052 .globl __map_data_section
1055 ldd #__data_section_size
1058 ldy #__data_section_start
1079 .sect .install2
,"ax",@progbits
1080 .globl __init_bss_section
1102 ; End of constructor table
1103 .sect .install3
,"ax",@progbits
1104 .globl __do_global_ctors
1107 ; Start from the end - sizeof(void*)
1125 .sect .fini3
,"ax",@progbits
1126 .globl __do_global_dtors
1129 ;; This piece of code is inserted in the _exit() code by the linker.
1132 pshb
; Save exit code
1146 pula
; Restore exit code
1151 ;-----------------------------------------
1152 ; end required gcclib code
1153 ;-----------------------------------------