1 /* libgcc routines for M68HC11 & M68HC12.
2 Copyright (C) 1999, 2000, 2001, 2002, 2003 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. */
38 #ifdef __HAVE_SHORT_INT__
44 #if defined(__USE_RTC__) && defined(mc68hc12)
54 .size \name,.Lend-\name
76 .size \name,.Lend-\name
87 .type NAME,@object ; \
91 /* Pseudo hard registers used by gcc.
92 They should be located in page0. */
138 /* Pseudo hard registers used by gcc.
139 They should be located in page0. */
141 .globl _.d9,_.d10,_.d11,_.d12,_.d13,_.d14
155 /* Pseudo hard registers used by gcc.
156 They should be located in page0. */
158 .globl _.d17,_.d18,_.d19,_.d20,_.d21,_.d22
159 .globl _.d23,_.d24,_.d25,_.d26,_.d27,_.d28
160 .globl _.d29,_.d30,_.d31,_.d32
181 ;; Specific initialization for 68hc11 before the main.
182 ;; Nothing special for a generic routine; Just enable interrupts.
186 tap ; Clear both I and X.
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
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. */
206 .sect .fini0,"ax",@progbits
215 .sect .fini4,"ax",@progbits
224 ;; Abort operation. This is defined for the GCC testsuite.
232 .byte 0xCD ; Generate an illegal instruction trap
233 .byte 0x03 ; The simulator catches this and stops.
240 ;; Cleanup operation used by exit().
247 ;-----------------------------------------
248 ; required gcclib code
249 ;-----------------------------------------
256 ;;; void* memcpy(void*, const void*, size_t)
260 ;;; 4,sp = size HImode (size_t)
282 ldx 2,x ; SRC = X, DST = Y
286 inca ; Correction for the deca below
288 psha ; Save high-counter part
290 ldaa 0,x ; Copy up to 256 bytes
299 puly ; Restore Y to return the DST
310 ;;; void* memset(void*, int value, size_t)
312 #ifndef __HAVE_SHORT_INT__
314 ;;; 2,sp = src SImode
315 ;;; 6,sp = size HImode (size_t)
320 ;;; 2,sp = src SImode
321 ;;; 6,sp = size HImode (size_t)
341 ldy size,y ; DST = X, CNT = Y
345 stab 0,x ; Fill up to 256 bytes
349 pulx ; Restore X to return the DST
361 ldd ARG(8),x ; Add LSB
363 std ARG(6),y ; Save (carry preserved)
376 adcb ARG(11),x ; Add MSB
389 ldd ARG(8),x ; Subtract LSB
391 std ARG(6),y ; Save, borrow preserved
403 ldd ARG(2),x ; Subtract MSB
460 .globl ___one_cmplsi2
628 bge Return_minus_1_or_zero
638 Return_minus_1_or_zero:
654 bge Return_minus_1_or_zero
663 Return_minus_1_or_zero:
695 /* 68HC12 signed divisions are generated inline (idivs). */
710 comb ; D = -D <=> D = (~D) + 1
715 bpl Numerator_neg_denominator_pos
716 Numerator_neg_denominator_neg:
724 xgdx ; Remainder <= 0 and result >= 0
728 Numerator_pos_denominator_pos:
731 xgdx ; Both values are >= 0
737 bpl Numerator_pos_denominator_pos
738 Numerator_pos_denominator_neg:
744 xgdx ; Remainder >= 0 but result <= 0
750 Numerator_neg_denominator_pos:
753 coma ; One value is > 0 and the other < 0
754 comb ; Change the sign of result and remainder
761 #endif /* !mc68hc12 */
769 ; short __mulqi3(signed char a, signed char b);
771 ; signed char a -> register A
772 ; signed char b -> register B
774 ; returns the signed result of A * B in register D.
808 ; unsigned short ___mulhi3(unsigned short a, unsigned short b)
824 ; 16 bit multiplication without temp memory location.
825 ; (smaller but slower)
834 mul ; (10) B.high * A.low
836 mul ; (10) B.low * A.high
840 mul ; (10) B.low * A.low
852 mul ; (10) B.high * A.low
856 mul ; (10) B.low * A.high
859 mul ; (10) B.low * A.low
862 rts ; (5) 20/26 bytes
870 mul ; (10) A.high * B.low
875 mul ; (10) A.low * B.high
880 mul ; (10) A.low * B.low
882 rts ; (5) 24/32 bytes
893 ; unsigned long __mulhi32(unsigned short a, unsigned short b)
914 ; +---------------+ <- 0,x
931 pshx ; Room for temp value
937 xgdy ; A.high * B.high
958 pulx ; Drop temp location
959 pshy ; Put high part in X
982 ; (((A.low * B.high) + (A.high * B.low)) << 16) + (A.low * B.low)
992 emul ; A.low * B.high
995 emul ; A.high * B.low
1014 ; If B.low is 0, optimize into: (A.low * B.high) << 16
1019 ; If A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
1023 bsr ___mulhi3 ; A.high * B.low
1025 ; If A.low is 0, optimize into: (A.high * B.low) << 16
1028 beq A_low_zero ; X = 0, D = A.high * B.low
1031 ; If B.high is 0, we can avoid the (A.low * B.high) << 16 term.
1035 bsr ___mulhi3 ; A.low * B.high
1039 ; Here, we know that A.low and B.low are not 0.
1042 ldd B_low,y ; A.low is on the stack
1043 bsr __mulhi32 ; A.low * B.low
1045 tsy ; Y was clobbered, get it back
1047 A_low_zero: ; See A_low_zero_non_optimized below
1057 ; A_low_zero_non_optimized:
1059 ; At this step, X = 0 and D = (A.high * B.low)
1060 ; Optimize into: (A.high * B.low) << 16
1063 ; clra ; Since X was 0, clearing D is superfuous.
1067 ; B.low == 0, the result is: (A.low * B.high) << 16
1072 ; A.low is at A_low,y ?
1073 ; B.low is at B_low,y ?
1088 ; A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
1093 ; A.low is at A_low,y ?
1094 ; B.low is at B_low,y ?
1099 ldx B_high,y ; B.high
1103 bra B_high_zero ; Do the (A.low * B.low) and the add.
1106 ; A.high and B.high are 0 optimize into: (A.low * B.low)
1111 ; A.low is at A_low,y != 0
1112 ; B.high is at B_high,y = 0
1115 ldd B_low,y ; A.low is on the stack
1123 .sect .install2,"ax",@progbits
1124 .globl __map_data_section
1127 .globl __data_section_size
1132 ldy #__data_section_start
1133 ldd #__data_section_size
1140 ldy #__data_section_start
1148 cpx #__data_image_end
1157 .sect .install2,"ax",@progbits
1158 .globl __init_bss_section
1180 ; End of constructor table
1181 .sect .install3,"ax",@progbits
1182 .globl __do_global_ctors
1185 ; Start from the end - sizeof(void*)
1203 .sect .fini3,"ax",@progbits
1204 .globl __do_global_dtors
1207 ;; This piece of code is inserted in the _exit() code by the linker.
1210 pshb ; Save exit code
1224 pula ; Restore exit code
1232 .globl __far_trampoline
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:
1240 ;; call __far_trampoline,page(foo)
1242 ;; The linker transforms:
1249 ;; The linker generated trampoline and _far_trampoline must be in
1250 ;; non-banked memory.
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).
1262 ;-----------------------------------------
1263 ; end required gcclib code
1264 ;-----------------------------------------