]>
Commit | Line | Data |
---|---|---|
7857f134 | 1 | /* libgcc routines for the MCore. |
748086b7 | 2 | Copyright (C) 1993, 1999, 2000, 2009 Free Software Foundation, Inc. |
8f90be4c | 3 | |
7ec022b2 | 4 | This file is part of GCC. |
8f90be4c | 5 | |
7ec022b2 | 6 | GCC is free software; you can redistribute it and/or modify it |
8f90be4c | 7 | under the terms of the GNU General Public License as published by the |
748086b7 | 8 | Free Software Foundation; either version 3, or (at your option) any |
8f90be4c NC |
9 | later version. |
10 | ||
8f90be4c NC |
11 | This file is distributed in the hope that it will be useful, but |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | General Public License for more details. | |
15 | ||
748086b7 JJ |
16 | Under Section 7 of GPL version 3, you are granted additional |
17 | permissions described in the GCC Runtime Library Exception, version | |
18 | 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | You should have received a copy of the GNU General Public License and | |
21 | a copy of the GCC Runtime Library Exception along with this program; | |
22 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | <http://www.gnu.org/licenses/>. */ | |
8f90be4c | 24 | |
8f90be4c NC |
25 | #define CONCAT1(a, b) CONCAT2(a, b) |
26 | #define CONCAT2(a, b) a ## b | |
27 | ||
28 | /* Use the right prefix for global labels. */ | |
29 | ||
30 | #define SYM(x) CONCAT1 (__, x) | |
31 | ||
32 | #ifdef __ELF__ | |
33 | #define TYPE(x) .type SYM (x),@function | |
34 | #define SIZE(x) .size SYM (x), . - SYM (x) | |
35 | #else | |
36 | #define TYPE(x) | |
37 | #define SIZE(x) | |
38 | #endif | |
39 | ||
40 | .macro FUNC_START name | |
41 | .text | |
42 | .globl SYM (\name) | |
43 | TYPE (\name) | |
44 | SYM (\name): | |
45 | .endm | |
46 | ||
47 | .macro FUNC_END name | |
48 | SIZE (\name) | |
49 | .endm | |
50 | ||
51 | #ifdef L_udivsi3 | |
52 | FUNC_START udiv32 | |
53 | FUNC_START udivsi32 | |
54 | ||
55 | movi r1,0 // r1-r2 form 64 bit dividend | |
56 | movi r4,1 // r4 is quotient (1 for a sentinel) | |
57 | ||
58 | cmpnei r3,0 // look for 0 divisor | |
59 | bt 9f | |
60 | trap 3 // divide by 0 | |
61 | 9: | |
62 | // control iterations; skip across high order 0 bits in dividend | |
63 | mov r7,r2 | |
64 | cmpnei r7,0 | |
65 | bt 8f | |
66 | movi r2,0 // 0 dividend | |
67 | jmp r15 // quick return | |
68 | 8: | |
69 | ff1 r7 // figure distance to skip | |
70 | lsl r4,r7 // move the sentinel along (with 0's behind) | |
71 | lsl r2,r7 // and the low 32 bits of numerator | |
72 | ||
73 | // appears to be wrong... | |
74 | // tested out incorrectly in our OS work... | |
75 | // mov r7,r3 // looking at divisor | |
76 | // ff1 r7 // I can move 32-r7 more bits to left. | |
77 | // addi r7,1 // ok, one short of that... | |
78 | // mov r1,r2 | |
79 | // lsr r1,r7 // bits that came from low order... | |
80 | // rsubi r7,31 // r7 == "32-n" == LEFT distance | |
81 | // addi r7,1 // this is (32-n) | |
82 | // lsl r4,r7 // fixes the high 32 (quotient) | |
83 | // lsl r2,r7 | |
84 | // cmpnei r4,0 | |
85 | // bf 4f // the sentinel went away... | |
86 | ||
87 | // run the remaining bits | |
88 | ||
89 | 1: lslc r2,1 // 1 bit left shift of r1-r2 | |
90 | addc r1,r1 | |
91 | cmphs r1,r3 // upper 32 of dividend >= divisor? | |
92 | bf 2f | |
93 | sub r1,r3 // if yes, subtract divisor | |
94 | 2: addc r4,r4 // shift by 1 and count subtracts | |
95 | bf 1b // if sentinel falls out of quotient, stop | |
96 | ||
97 | 4: mov r2,r4 // return quotient | |
98 | mov r3,r1 // and piggyback the remainder | |
99 | jmp r15 | |
100 | FUNC_END udiv32 | |
101 | FUNC_END udivsi32 | |
102 | #endif | |
103 | ||
104 | #ifdef L_umodsi3 | |
105 | FUNC_START urem32 | |
106 | FUNC_START umodsi3 | |
107 | movi r1,0 // r1-r2 form 64 bit dividend | |
108 | movi r4,1 // r4 is quotient (1 for a sentinel) | |
109 | cmpnei r3,0 // look for 0 divisor | |
110 | bt 9f | |
111 | trap 3 // divide by 0 | |
112 | 9: | |
113 | // control iterations; skip across high order 0 bits in dividend | |
114 | mov r7,r2 | |
115 | cmpnei r7,0 | |
116 | bt 8f | |
117 | movi r2,0 // 0 dividend | |
118 | jmp r15 // quick return | |
119 | 8: | |
120 | ff1 r7 // figure distance to skip | |
121 | lsl r4,r7 // move the sentinel along (with 0's behind) | |
122 | lsl r2,r7 // and the low 32 bits of numerator | |
123 | ||
124 | 1: lslc r2,1 // 1 bit left shift of r1-r2 | |
125 | addc r1,r1 | |
126 | cmphs r1,r3 // upper 32 of dividend >= divisor? | |
127 | bf 2f | |
128 | sub r1,r3 // if yes, subtract divisor | |
129 | 2: addc r4,r4 // shift by 1 and count subtracts | |
130 | bf 1b // if sentinel falls out of quotient, stop | |
131 | mov r2,r1 // return remainder | |
132 | jmp r15 | |
133 | FUNC_END urem32 | |
134 | FUNC_END umodsi3 | |
135 | #endif | |
136 | ||
137 | #ifdef L_divsi3 | |
138 | FUNC_START div32 | |
139 | FUNC_START divsi3 | |
140 | mov r5,r2 // calc sign of quotient | |
141 | xor r5,r3 | |
142 | abs r2 // do unsigned divide | |
143 | abs r3 | |
144 | movi r1,0 // r1-r2 form 64 bit dividend | |
145 | movi r4,1 // r4 is quotient (1 for a sentinel) | |
146 | cmpnei r3,0 // look for 0 divisor | |
147 | bt 9f | |
148 | trap 3 // divide by 0 | |
149 | 9: | |
150 | // control iterations; skip across high order 0 bits in dividend | |
151 | mov r7,r2 | |
152 | cmpnei r7,0 | |
153 | bt 8f | |
154 | movi r2,0 // 0 dividend | |
155 | jmp r15 // quick return | |
156 | 8: | |
157 | ff1 r7 // figure distance to skip | |
158 | lsl r4,r7 // move the sentinel along (with 0's behind) | |
159 | lsl r2,r7 // and the low 32 bits of numerator | |
160 | ||
161 | // tested out incorrectly in our OS work... | |
162 | // mov r7,r3 // looking at divisor | |
163 | // ff1 r7 // I can move 32-r7 more bits to left. | |
164 | // addi r7,1 // ok, one short of that... | |
165 | // mov r1,r2 | |
166 | // lsr r1,r7 // bits that came from low order... | |
167 | // rsubi r7,31 // r7 == "32-n" == LEFT distance | |
168 | // addi r7,1 // this is (32-n) | |
169 | // lsl r4,r7 // fixes the high 32 (quotient) | |
170 | // lsl r2,r7 | |
171 | // cmpnei r4,0 | |
172 | // bf 4f // the sentinel went away... | |
173 | ||
174 | // run the remaining bits | |
175 | 1: lslc r2,1 // 1 bit left shift of r1-r2 | |
176 | addc r1,r1 | |
177 | cmphs r1,r3 // upper 32 of dividend >= divisor? | |
178 | bf 2f | |
179 | sub r1,r3 // if yes, subtract divisor | |
180 | 2: addc r4,r4 // shift by 1 and count subtracts | |
181 | bf 1b // if sentinel falls out of quotient, stop | |
182 | ||
183 | 4: mov r2,r4 // return quotient | |
184 | mov r3,r1 // piggyback the remainder | |
185 | btsti r5,31 // after adjusting for sign | |
186 | bf 3f | |
187 | rsubi r2,0 | |
188 | rsubi r3,0 | |
189 | 3: jmp r15 | |
190 | FUNC_END div32 | |
191 | FUNC_END divsi3 | |
192 | #endif | |
193 | ||
194 | #ifdef L_modsi3 | |
195 | FUNC_START rem32 | |
196 | FUNC_START modsi3 | |
197 | mov r5,r2 // calc sign of remainder | |
198 | abs r2 // do unsigned divide | |
199 | abs r3 | |
200 | movi r1,0 // r1-r2 form 64 bit dividend | |
201 | movi r4,1 // r4 is quotient (1 for a sentinel) | |
202 | cmpnei r3,0 // look for 0 divisor | |
203 | bt 9f | |
204 | trap 3 // divide by 0 | |
205 | 9: | |
206 | // control iterations; skip across high order 0 bits in dividend | |
207 | mov r7,r2 | |
208 | cmpnei r7,0 | |
209 | bt 8f | |
210 | movi r2,0 // 0 dividend | |
211 | jmp r15 // quick return | |
212 | 8: | |
213 | ff1 r7 // figure distance to skip | |
214 | lsl r4,r7 // move the sentinel along (with 0's behind) | |
215 | lsl r2,r7 // and the low 32 bits of numerator | |
216 | ||
217 | 1: lslc r2,1 // 1 bit left shift of r1-r2 | |
218 | addc r1,r1 | |
219 | cmphs r1,r3 // upper 32 of dividend >= divisor? | |
220 | bf 2f | |
221 | sub r1,r3 // if yes, subtract divisor | |
222 | 2: addc r4,r4 // shift by 1 and count subtracts | |
223 | bf 1b // if sentinel falls out of quotient, stop | |
224 | mov r2,r1 // return remainder | |
225 | btsti r5,31 // after adjusting for sign | |
226 | bf 3f | |
227 | rsubi r2,0 | |
228 | 3: jmp r15 | |
229 | FUNC_END rem32 | |
230 | FUNC_END modsi3 | |
231 | #endif | |
232 | ||
233 | ||
234 | /* GCC expects that {__eq,__ne,__gt,__ge,__le,__lt}{df2,sf2} | |
235 | will behave as __cmpdf2. So, we stub the implementations to | |
236 | jump on to __cmpdf2 and __cmpsf2. | |
237 | ||
238 | All of these shortcircuit the return path so that __cmp{sd}f2 | |
14bc6742 | 239 | will go directly back to the caller. */ |
8f90be4c NC |
240 | |
241 | .macro COMPARE_DF_JUMP name | |
242 | .import SYM (cmpdf2) | |
243 | FUNC_START \name | |
244 | jmpi SYM (cmpdf2) | |
245 | FUNC_END \name | |
246 | .endm | |
247 | ||
248 | #ifdef L_eqdf2 | |
249 | COMPARE_DF_JUMP eqdf2 | |
250 | #endif /* L_eqdf2 */ | |
251 | ||
252 | #ifdef L_nedf2 | |
253 | COMPARE_DF_JUMP nedf2 | |
254 | #endif /* L_nedf2 */ | |
255 | ||
256 | #ifdef L_gtdf2 | |
257 | COMPARE_DF_JUMP gtdf2 | |
258 | #endif /* L_gtdf2 */ | |
259 | ||
260 | #ifdef L_gedf2 | |
261 | COMPARE_DF_JUMP gedf2 | |
262 | #endif /* L_gedf2 */ | |
263 | ||
264 | #ifdef L_ltdf2 | |
265 | COMPARE_DF_JUMP ltdf2 | |
266 | #endif /* L_ltdf2 */ | |
267 | ||
268 | #ifdef L_ledf2 | |
269 | COMPARE_DF_JUMP ledf2 | |
270 | #endif /* L_ledf2 */ | |
271 | ||
272 | /* SINGLE PRECISION FLOATING POINT STUBS */ | |
273 | ||
274 | .macro COMPARE_SF_JUMP name | |
275 | .import SYM (cmpsf2) | |
276 | FUNC_START \name | |
277 | jmpi SYM (cmpsf2) | |
278 | FUNC_END \name | |
279 | .endm | |
280 | ||
281 | #ifdef L_eqsf2 | |
282 | COMPARE_SF_JUMP eqsf2 | |
283 | #endif /* L_eqsf2 */ | |
284 | ||
285 | #ifdef L_nesf2 | |
286 | COMPARE_SF_JUMP nesf2 | |
287 | #endif /* L_nesf2 */ | |
288 | ||
289 | #ifdef L_gtsf2 | |
290 | COMPARE_SF_JUMP gtsf2 | |
291 | #endif /* L_gtsf2 */ | |
292 | ||
293 | #ifdef L_gesf2 | |
294 | COMPARE_SF_JUMP __gesf2 | |
295 | #endif /* L_gesf2 */ | |
296 | ||
297 | #ifdef L_ltsf2 | |
298 | COMPARE_SF_JUMP __ltsf2 | |
299 | #endif /* L_ltsf2 */ | |
300 | ||
301 | #ifdef L_lesf2 | |
302 | COMPARE_SF_JUMP lesf2 | |
303 | #endif /* L_lesf2 */ |