]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/mcore/lib1.asm
Backend for Motorola's MCore processors.
[thirdparty/gcc.git] / gcc / config / mcore / lib1.asm
1 /* libgcc1 routines for the MCore.
2 Copyright (C) 1993, 1999, 2000 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 files
30 compiled with GCC to produce an executable, this does not cause
31 the resulting executable to be covered by the GNU General Public License.
32 This exception does not however invalidate any other reasons why
33 the executable file might be covered by the GNU General Public License. */
34
35 #define CONCAT1(a, b) CONCAT2(a, b)
36 #define CONCAT2(a, b) a ## b
37
38 /* Use the right prefix for global labels. */
39
40 #define SYM(x) CONCAT1 (__, x)
41
42 #ifdef __ELF__
43 #define TYPE(x) .type SYM (x),@function
44 #define SIZE(x) .size SYM (x), . - SYM (x)
45 #else
46 #define TYPE(x)
47 #define SIZE(x)
48 #endif
49
50 .macro FUNC_START name
51 .text
52 .globl SYM (\name)
53 TYPE (\name)
54 SYM (\name):
55 .endm
56
57 .macro FUNC_END name
58 SIZE (\name)
59 .endm
60
61 #ifdef L_udivsi3
62 FUNC_START udiv32
63 FUNC_START udivsi32
64
65 movi r1,0 // r1-r2 form 64 bit dividend
66 movi r4,1 // r4 is quotient (1 for a sentinel)
67
68 cmpnei r3,0 // look for 0 divisor
69 bt 9f
70 trap 3 // divide by 0
71 9:
72 // control iterations; skip across high order 0 bits in dividend
73 mov r7,r2
74 cmpnei r7,0
75 bt 8f
76 movi r2,0 // 0 dividend
77 jmp r15 // quick return
78 8:
79 ff1 r7 // figure distance to skip
80 lsl r4,r7 // move the sentinel along (with 0's behind)
81 lsl r2,r7 // and the low 32 bits of numerator
82
83 // appears to be wrong...
84 // tested out incorrectly in our OS work...
85 // mov r7,r3 // looking at divisor
86 // ff1 r7 // I can move 32-r7 more bits to left.
87 // addi r7,1 // ok, one short of that...
88 // mov r1,r2
89 // lsr r1,r7 // bits that came from low order...
90 // rsubi r7,31 // r7 == "32-n" == LEFT distance
91 // addi r7,1 // this is (32-n)
92 // lsl r4,r7 // fixes the high 32 (quotient)
93 // lsl r2,r7
94 // cmpnei r4,0
95 // bf 4f // the sentinel went away...
96
97 // run the remaining bits
98
99 1: lslc r2,1 // 1 bit left shift of r1-r2
100 addc r1,r1
101 cmphs r1,r3 // upper 32 of dividend >= divisor?
102 bf 2f
103 sub r1,r3 // if yes, subtract divisor
104 2: addc r4,r4 // shift by 1 and count subtracts
105 bf 1b // if sentinel falls out of quotient, stop
106
107 4: mov r2,r4 // return quotient
108 mov r3,r1 // and piggyback the remainder
109 jmp r15
110 FUNC_END udiv32
111 FUNC_END udivsi32
112 #endif
113
114 #ifdef L_umodsi3
115 FUNC_START urem32
116 FUNC_START umodsi3
117 movi r1,0 // r1-r2 form 64 bit dividend
118 movi r4,1 // r4 is quotient (1 for a sentinel)
119 cmpnei r3,0 // look for 0 divisor
120 bt 9f
121 trap 3 // divide by 0
122 9:
123 // control iterations; skip across high order 0 bits in dividend
124 mov r7,r2
125 cmpnei r7,0
126 bt 8f
127 movi r2,0 // 0 dividend
128 jmp r15 // quick return
129 8:
130 ff1 r7 // figure distance to skip
131 lsl r4,r7 // move the sentinel along (with 0's behind)
132 lsl r2,r7 // and the low 32 bits of numerator
133
134 1: lslc r2,1 // 1 bit left shift of r1-r2
135 addc r1,r1
136 cmphs r1,r3 // upper 32 of dividend >= divisor?
137 bf 2f
138 sub r1,r3 // if yes, subtract divisor
139 2: addc r4,r4 // shift by 1 and count subtracts
140 bf 1b // if sentinel falls out of quotient, stop
141 mov r2,r1 // return remainder
142 jmp r15
143 FUNC_END urem32
144 FUNC_END umodsi3
145 #endif
146
147 #ifdef L_divsi3
148 FUNC_START div32
149 FUNC_START divsi3
150 mov r5,r2 // calc sign of quotient
151 xor r5,r3
152 abs r2 // do unsigned divide
153 abs r3
154 movi r1,0 // r1-r2 form 64 bit dividend
155 movi r4,1 // r4 is quotient (1 for a sentinel)
156 cmpnei r3,0 // look for 0 divisor
157 bt 9f
158 trap 3 // divide by 0
159 9:
160 // control iterations; skip across high order 0 bits in dividend
161 mov r7,r2
162 cmpnei r7,0
163 bt 8f
164 movi r2,0 // 0 dividend
165 jmp r15 // quick return
166 8:
167 ff1 r7 // figure distance to skip
168 lsl r4,r7 // move the sentinel along (with 0's behind)
169 lsl r2,r7 // and the low 32 bits of numerator
170
171 // tested out incorrectly in our OS work...
172 // mov r7,r3 // looking at divisor
173 // ff1 r7 // I can move 32-r7 more bits to left.
174 // addi r7,1 // ok, one short of that...
175 // mov r1,r2
176 // lsr r1,r7 // bits that came from low order...
177 // rsubi r7,31 // r7 == "32-n" == LEFT distance
178 // addi r7,1 // this is (32-n)
179 // lsl r4,r7 // fixes the high 32 (quotient)
180 // lsl r2,r7
181 // cmpnei r4,0
182 // bf 4f // the sentinel went away...
183
184 // run the remaining bits
185 1: lslc r2,1 // 1 bit left shift of r1-r2
186 addc r1,r1
187 cmphs r1,r3 // upper 32 of dividend >= divisor?
188 bf 2f
189 sub r1,r3 // if yes, subtract divisor
190 2: addc r4,r4 // shift by 1 and count subtracts
191 bf 1b // if sentinel falls out of quotient, stop
192
193 4: mov r2,r4 // return quotient
194 mov r3,r1 // piggyback the remainder
195 btsti r5,31 // after adjusting for sign
196 bf 3f
197 rsubi r2,0
198 rsubi r3,0
199 3: jmp r15
200 FUNC_END div32
201 FUNC_END divsi3
202 #endif
203
204 #ifdef L_modsi3
205 FUNC_START rem32
206 FUNC_START modsi3
207 mov r5,r2 // calc sign of remainder
208 abs r2 // do unsigned divide
209 abs r3
210 movi r1,0 // r1-r2 form 64 bit dividend
211 movi r4,1 // r4 is quotient (1 for a sentinel)
212 cmpnei r3,0 // look for 0 divisor
213 bt 9f
214 trap 3 // divide by 0
215 9:
216 // control iterations; skip across high order 0 bits in dividend
217 mov r7,r2
218 cmpnei r7,0
219 bt 8f
220 movi r2,0 // 0 dividend
221 jmp r15 // quick return
222 8:
223 ff1 r7 // figure distance to skip
224 lsl r4,r7 // move the sentinel along (with 0's behind)
225 lsl r2,r7 // and the low 32 bits of numerator
226
227 1: lslc r2,1 // 1 bit left shift of r1-r2
228 addc r1,r1
229 cmphs r1,r3 // upper 32 of dividend >= divisor?
230 bf 2f
231 sub r1,r3 // if yes, subtract divisor
232 2: addc r4,r4 // shift by 1 and count subtracts
233 bf 1b // if sentinel falls out of quotient, stop
234 mov r2,r1 // return remainder
235 btsti r5,31 // after adjusting for sign
236 bf 3f
237 rsubi r2,0
238 3: jmp r15
239 FUNC_END rem32
240 FUNC_END modsi3
241 #endif
242
243
244 /* GCC expects that {__eq,__ne,__gt,__ge,__le,__lt}{df2,sf2}
245 will behave as __cmpdf2. So, we stub the implementations to
246 jump on to __cmpdf2 and __cmpsf2.
247
248 All of these shortcircuit the return path so that __cmp{sd}f2
249 will go directly back to the caller. */
250
251 .macro COMPARE_DF_JUMP name
252 .import SYM (cmpdf2)
253 FUNC_START \name
254 jmpi SYM (cmpdf2)
255 FUNC_END \name
256 .endm
257
258 #ifdef L_eqdf2
259 COMPARE_DF_JUMP eqdf2
260 #endif /* L_eqdf2 */
261
262 #ifdef L_nedf2
263 COMPARE_DF_JUMP nedf2
264 #endif /* L_nedf2 */
265
266 #ifdef L_gtdf2
267 COMPARE_DF_JUMP gtdf2
268 #endif /* L_gtdf2 */
269
270 #ifdef L_gedf2
271 COMPARE_DF_JUMP gedf2
272 #endif /* L_gedf2 */
273
274 #ifdef L_ltdf2
275 COMPARE_DF_JUMP ltdf2
276 #endif /* L_ltdf2 */
277
278 #ifdef L_ledf2
279 COMPARE_DF_JUMP ledf2
280 #endif /* L_ledf2 */
281
282 /* SINGLE PRECISION FLOATING POINT STUBS */
283
284 .macro COMPARE_SF_JUMP name
285 .import SYM (cmpsf2)
286 FUNC_START \name
287 jmpi SYM (cmpsf2)
288 FUNC_END \name
289 .endm
290
291 #ifdef L_eqsf2
292 COMPARE_SF_JUMP eqsf2
293 #endif /* L_eqsf2 */
294
295 #ifdef L_nesf2
296 COMPARE_SF_JUMP nesf2
297 #endif /* L_nesf2 */
298
299 #ifdef L_gtsf2
300 COMPARE_SF_JUMP gtsf2
301 #endif /* L_gtsf2 */
302
303 #ifdef L_gesf2
304 COMPARE_SF_JUMP __gesf2
305 #endif /* L_gesf2 */
306
307 #ifdef L_ltsf2
308 COMPARE_SF_JUMP __ltsf2
309 #endif /* L_ltsf2 */
310
311 #ifdef L_lesf2
312 COMPARE_SF_JUMP lesf2
313 #endif /* L_lesf2 */