OSDN Git Service

Update FSF address.
[pf3gnuchains/gcc-fork.git] / gcc / config / mcore / lib1.asm
1 /* libgcc routines for the MCore.
2    Copyright (C) 1993, 1999, 2000 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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.
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 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.)
19
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.
24
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, 51 Franklin Street, Fifth Floor,
28 Boston, MA 02110-1301, USA.  */
29
30 #define CONCAT1(a, b) CONCAT2(a, b)
31 #define CONCAT2(a, b) a ## b
32
33 /* Use the right prefix for global labels.  */
34
35 #define SYM(x) CONCAT1 (__, x)
36
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
44
45 .macro FUNC_START name
46         .text
47         .globl SYM (\name)
48         TYPE (\name)
49 SYM (\name):
50 .endm
51
52 .macro FUNC_END name
53         SIZE (\name)
54 .endm
55
56 #ifdef  L_udivsi3
57 FUNC_START udiv32
58 FUNC_START udivsi32
59
60         movi    r1,0            // r1-r2 form 64 bit dividend
61         movi    r4,1            // r4 is quotient (1 for a sentinel)
62
63         cmpnei  r3,0            // look for 0 divisor
64         bt      9f
65         trap    3               // divide by 0
66 9:
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
73 8:
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
77
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...
91
92         // run the remaining bits
93
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
101
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
108
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
117 9:
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
124 8:
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
128
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
141
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
154 9:
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
161 8:
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
165
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...
178
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
187
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
198
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
210 9: 
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
217 8:
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
221
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
237
238
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.
242  
243    All of these shortcircuit the return path so that __cmp{sd}f2
244    will go directly back to the caller.  */
245
246 .macro  COMPARE_DF_JUMP name
247         .import SYM (cmpdf2)
248 FUNC_START \name
249         jmpi SYM (cmpdf2)
250 FUNC_END \name
251 .endm
252                 
253 #ifdef  L_eqdf2
254 COMPARE_DF_JUMP eqdf2
255 #endif /* L_eqdf2 */
256
257 #ifdef  L_nedf2
258 COMPARE_DF_JUMP nedf2
259 #endif /* L_nedf2 */
260
261 #ifdef  L_gtdf2
262 COMPARE_DF_JUMP gtdf2
263 #endif /* L_gtdf2 */
264
265 #ifdef  L_gedf2
266 COMPARE_DF_JUMP gedf2
267 #endif /* L_gedf2 */
268
269 #ifdef  L_ltdf2
270 COMPARE_DF_JUMP ltdf2
271 #endif /* L_ltdf2 */
272         
273 #ifdef  L_ledf2
274 COMPARE_DF_JUMP ledf2
275 #endif /* L_ledf2 */
276
277 /* SINGLE PRECISION FLOATING POINT STUBS */
278
279 .macro  COMPARE_SF_JUMP name
280         .import SYM (cmpsf2)
281 FUNC_START \name
282         jmpi SYM (cmpsf2)
283 FUNC_END \name
284 .endm
285                 
286 #ifdef  L_eqsf2
287 COMPARE_SF_JUMP eqsf2
288 #endif /* L_eqsf2 */
289         
290 #ifdef  L_nesf2
291 COMPARE_SF_JUMP nesf2
292 #endif /* L_nesf2 */
293         
294 #ifdef  L_gtsf2
295 COMPARE_SF_JUMP gtsf2
296 #endif /* L_gtsf2 */
297         
298 #ifdef  L_gesf2
299 COMPARE_SF_JUMP __gesf2
300 #endif /* L_gesf2 */
301         
302 #ifdef  L_ltsf2
303 COMPARE_SF_JUMP __ltsf2
304 #endif /* L_ltsf2 */
305         
306 #ifdef  L_lesf2
307 COMPARE_SF_JUMP lesf2
308 #endif /* L_lesf2 */