PR target/16201
[official-gcc.git] / gcc / config / mcore / lib1.asm
blob3eca5abbd97aed8e280e78568b88530f923e969a
1 /* libgcc routines for the MCore.
2 Copyright (C) 1993, 1999, 2000 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC 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.
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 into combinations with other programs,
14 and to distribute those combinations without any restriction coming
15 from the use of this file. (The General Public License restrictions
16 do apply in other respects; for example, they cover modification of
17 the file, and distribution when not linked into a combine
18 executable.)
20 This file is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; see the file COPYING. If not, write to
27 the Free Software Foundation, 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA. */
30 #define CONCAT1(a, b) CONCAT2(a, b)
31 #define CONCAT2(a, b) a ## b
33 /* Use the right prefix for global labels. */
35 #define SYM(x) CONCAT1 (__, x)
37 #ifdef __ELF__
38 #define TYPE(x) .type SYM (x),@function
39 #define SIZE(x) .size SYM (x), . - SYM (x)
40 #else
41 #define TYPE(x)
42 #define SIZE(x)
43 #endif
45 .macro FUNC_START name
46 .text
47 .globl SYM (\name)
48 TYPE (\name)
49 SYM (\name):
50 .endm
52 .macro FUNC_END name
53 SIZE (\name)
54 .endm
56 #ifdef L_udivsi3
57 FUNC_START udiv32
58 FUNC_START udivsi32
60 movi r1,0 // r1-r2 form 64 bit dividend
61 movi r4,1 // r4 is quotient (1 for a sentinel)
63 cmpnei r3,0 // look for 0 divisor
64 bt 9f
65 trap 3 // divide by 0
67 // control iterations; skip across high order 0 bits in dividend
68 mov r7,r2
69 cmpnei r7,0
70 bt 8f
71 movi r2,0 // 0 dividend
72 jmp r15 // quick return
74 ff1 r7 // figure distance to skip
75 lsl r4,r7 // move the sentinel along (with 0's behind)
76 lsl r2,r7 // and the low 32 bits of numerator
78 // appears to be wrong...
79 // tested out incorrectly in our OS work...
80 // mov r7,r3 // looking at divisor
81 // ff1 r7 // I can move 32-r7 more bits to left.
82 // addi r7,1 // ok, one short of that...
83 // mov r1,r2
84 // lsr r1,r7 // bits that came from low order...
85 // rsubi r7,31 // r7 == "32-n" == LEFT distance
86 // addi r7,1 // this is (32-n)
87 // lsl r4,r7 // fixes the high 32 (quotient)
88 // lsl r2,r7
89 // cmpnei r4,0
90 // bf 4f // the sentinel went away...
92 // run the remaining bits
94 1: lslc r2,1 // 1 bit left shift of r1-r2
95 addc r1,r1
96 cmphs r1,r3 // upper 32 of dividend >= divisor?
97 bf 2f
98 sub r1,r3 // if yes, subtract divisor
99 2: addc r4,r4 // shift by 1 and count subtracts
100 bf 1b // if sentinel falls out of quotient, stop
102 4: mov r2,r4 // return quotient
103 mov r3,r1 // and piggyback the remainder
104 jmp r15
105 FUNC_END udiv32
106 FUNC_END udivsi32
107 #endif
109 #ifdef L_umodsi3
110 FUNC_START urem32
111 FUNC_START umodsi3
112 movi r1,0 // r1-r2 form 64 bit dividend
113 movi r4,1 // r4 is quotient (1 for a sentinel)
114 cmpnei r3,0 // look for 0 divisor
115 bt 9f
116 trap 3 // divide by 0
118 // control iterations; skip across high order 0 bits in dividend
119 mov r7,r2
120 cmpnei r7,0
121 bt 8f
122 movi r2,0 // 0 dividend
123 jmp r15 // quick return
125 ff1 r7 // figure distance to skip
126 lsl r4,r7 // move the sentinel along (with 0's behind)
127 lsl r2,r7 // and the low 32 bits of numerator
129 1: lslc r2,1 // 1 bit left shift of r1-r2
130 addc r1,r1
131 cmphs r1,r3 // upper 32 of dividend >= divisor?
132 bf 2f
133 sub r1,r3 // if yes, subtract divisor
134 2: addc r4,r4 // shift by 1 and count subtracts
135 bf 1b // if sentinel falls out of quotient, stop
136 mov r2,r1 // return remainder
137 jmp r15
138 FUNC_END urem32
139 FUNC_END umodsi3
140 #endif
142 #ifdef L_divsi3
143 FUNC_START div32
144 FUNC_START divsi3
145 mov r5,r2 // calc sign of quotient
146 xor r5,r3
147 abs r2 // do unsigned divide
148 abs r3
149 movi r1,0 // r1-r2 form 64 bit dividend
150 movi r4,1 // r4 is quotient (1 for a sentinel)
151 cmpnei r3,0 // look for 0 divisor
152 bt 9f
153 trap 3 // divide by 0
155 // control iterations; skip across high order 0 bits in dividend
156 mov r7,r2
157 cmpnei r7,0
158 bt 8f
159 movi r2,0 // 0 dividend
160 jmp r15 // quick return
162 ff1 r7 // figure distance to skip
163 lsl r4,r7 // move the sentinel along (with 0's behind)
164 lsl r2,r7 // and the low 32 bits of numerator
166 // tested out incorrectly in our OS work...
167 // mov r7,r3 // looking at divisor
168 // ff1 r7 // I can move 32-r7 more bits to left.
169 // addi r7,1 // ok, one short of that...
170 // mov r1,r2
171 // lsr r1,r7 // bits that came from low order...
172 // rsubi r7,31 // r7 == "32-n" == LEFT distance
173 // addi r7,1 // this is (32-n)
174 // lsl r4,r7 // fixes the high 32 (quotient)
175 // lsl r2,r7
176 // cmpnei r4,0
177 // bf 4f // the sentinel went away...
179 // run the remaining bits
180 1: lslc r2,1 // 1 bit left shift of r1-r2
181 addc r1,r1
182 cmphs r1,r3 // upper 32 of dividend >= divisor?
183 bf 2f
184 sub r1,r3 // if yes, subtract divisor
185 2: addc r4,r4 // shift by 1 and count subtracts
186 bf 1b // if sentinel falls out of quotient, stop
188 4: mov r2,r4 // return quotient
189 mov r3,r1 // piggyback the remainder
190 btsti r5,31 // after adjusting for sign
191 bf 3f
192 rsubi r2,0
193 rsubi r3,0
194 3: jmp r15
195 FUNC_END div32
196 FUNC_END divsi3
197 #endif
199 #ifdef L_modsi3
200 FUNC_START rem32
201 FUNC_START modsi3
202 mov r5,r2 // calc sign of remainder
203 abs r2 // do unsigned divide
204 abs r3
205 movi r1,0 // r1-r2 form 64 bit dividend
206 movi r4,1 // r4 is quotient (1 for a sentinel)
207 cmpnei r3,0 // look for 0 divisor
208 bt 9f
209 trap 3 // divide by 0
211 // control iterations; skip across high order 0 bits in dividend
212 mov r7,r2
213 cmpnei r7,0
214 bt 8f
215 movi r2,0 // 0 dividend
216 jmp r15 // quick return
218 ff1 r7 // figure distance to skip
219 lsl r4,r7 // move the sentinel along (with 0's behind)
220 lsl r2,r7 // and the low 32 bits of numerator
222 1: lslc r2,1 // 1 bit left shift of r1-r2
223 addc r1,r1
224 cmphs r1,r3 // upper 32 of dividend >= divisor?
225 bf 2f
226 sub r1,r3 // if yes, subtract divisor
227 2: addc r4,r4 // shift by 1 and count subtracts
228 bf 1b // if sentinel falls out of quotient, stop
229 mov r2,r1 // return remainder
230 btsti r5,31 // after adjusting for sign
231 bf 3f
232 rsubi r2,0
233 3: jmp r15
234 FUNC_END rem32
235 FUNC_END modsi3
236 #endif
239 /* GCC expects that {__eq,__ne,__gt,__ge,__le,__lt}{df2,sf2}
240 will behave as __cmpdf2. So, we stub the implementations to
241 jump on to __cmpdf2 and __cmpsf2.
243 All of these shortcircuit the return path so that __cmp{sd}f2
244 will go directly back to the caller. */
246 .macro COMPARE_DF_JUMP name
247 .import SYM (cmpdf2)
248 FUNC_START \name
249 jmpi SYM (cmpdf2)
250 FUNC_END \name
251 .endm
253 #ifdef L_eqdf2
254 COMPARE_DF_JUMP eqdf2
255 #endif /* L_eqdf2 */
257 #ifdef L_nedf2
258 COMPARE_DF_JUMP nedf2
259 #endif /* L_nedf2 */
261 #ifdef L_gtdf2
262 COMPARE_DF_JUMP gtdf2
263 #endif /* L_gtdf2 */
265 #ifdef L_gedf2
266 COMPARE_DF_JUMP gedf2
267 #endif /* L_gedf2 */
269 #ifdef L_ltdf2
270 COMPARE_DF_JUMP ltdf2
271 #endif /* L_ltdf2 */
273 #ifdef L_ledf2
274 COMPARE_DF_JUMP ledf2
275 #endif /* L_ledf2 */
277 /* SINGLE PRECISION FLOATING POINT STUBS */
279 .macro COMPARE_SF_JUMP name
280 .import SYM (cmpsf2)
281 FUNC_START \name
282 jmpi SYM (cmpsf2)
283 FUNC_END \name
284 .endm
286 #ifdef L_eqsf2
287 COMPARE_SF_JUMP eqsf2
288 #endif /* L_eqsf2 */
290 #ifdef L_nesf2
291 COMPARE_SF_JUMP nesf2
292 #endif /* L_nesf2 */
294 #ifdef L_gtsf2
295 COMPARE_SF_JUMP gtsf2
296 #endif /* L_gtsf2 */
298 #ifdef L_gesf2
299 COMPARE_SF_JUMP __gesf2
300 #endif /* L_gesf2 */
302 #ifdef L_ltsf2
303 COMPARE_SF_JUMP __ltsf2
304 #endif /* L_ltsf2 */
306 #ifdef L_lesf2
307 COMPARE_SF_JUMP lesf2
308 #endif /* L_lesf2 */