Merged with mainline at revision 128810.
[official-gcc.git] / gcc / config / score / mul-div.S
blob4853a0ae13248cd30c26467fb2baa0c3a9bea4f1
1 /* Copyright (C) 2005, 2007 Free Software Foundation, Inc.
2    Contributed by Sunnorth
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
8    by the Free Software Foundation; either version 3, or (at your
9    option) any later version.
11    GCC is distributed in the hope that it will be useful, but WITHOUT
12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14    License for more details.
16    You should have received a copy of the GNU General Public License
17         along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
20 #define ra r3
21 #define a0 r4
22 #define a1 r5
23 #define a2 r6
24 #define a3 r7
25 #define v0 r23
27 #define t0 r8
28 #define t1 r9
29 #define t2 r10
30 #define t3 r11
31 #define t4 r22
33 #ifndef __pic__
34 #if !defined(L_mulsi3) && !defined(L_divsi3)
35        .text
36        .global _flush_cache
37 _flush_cache:
38         srli    r9, r5, 4
39         mv      r8, r4
40         mtsr    r9, sr0
42         cache   0xe, [r8, 0]            # write back invalid dcache
43         addi    r8, 16
44         bcnz    1b
45         mfcr    r8, cr4
46         bittst! r8, 0x3                 # if LDM is enable, write back LDM
47         beq!    6f
48         ldi     r10, 0
49         cache   0xc, [r10, 0]
51         bittst! r8, 0x2                 # if LIM is enable, refill it
52         beq!    7f
53         cache   0x4, [r10, 0]
55         #nop!
56         #nop!
57         #nop!
58         #nop!
59         #nop!
60         mv      r8, r4
61         mtsr    r9, sr0
63         cache   0x2, [r8, 0]            # invalid unlock icache
64         #nop!
65         #nop!
66         #nop!
67         #nop!
68         #nop!
69         addi    r8, 16
70         bcnz    2b
71         br      r3
72 #endif
74 /* FUNCTION
75    (U) INT32 v0 = __mulsi3 ((U) INT32 a0, (U) INT32 a1);
76    REGISTERS:
77         use     t0
78         modify  a0
79         a1      -> become 0
80    NOTE:
81    this seems to give better performance to just rotate and add.  */
83 #ifdef L_mulsi3
84         .text
85         .global __umulsi3
86         .global __mulsi3
87         /* signed multiplication (32x32)  */
88         .ent    __mulsi3
89 __umulsi3:
90 __mulsi3:
91         li      t1, 0
92 __mulsi3_loop:
93         andri.c t0, a1, 1               # t0 = multiplier[0]
94         srli    a1, a1, 1               # a1 /= 2
95         beq     __mulsi3_loop2          # skip if (t0 == 0)
96         add     t1, t1, a0              # add multiplicand
97 __mulsi3_loop2:
98         slli    a0, a0, 1               # multiplicand mul 2
99         cmpi.c  a1, 0
100         bne     __mulsi3_loop
101         mv      r4, t1
102         br      ra
103         .end    __mulsi3
104 #endif /* L_mulsi3 */
106 /* FUNCTION
107    UINT32 (v0) = __udivsi3 (UINT32 (a0), UINT32 (a1));
108    INT32 (v0) = __divsi3 (INT32 (a0),  INT32 (a1));
109    UINT32 (v0) = __umodsi3 (UINT32 (a0), UINT32 (a1));
110    INT32 (v0) = __modsi3 (INT32 (a0),  INT32 (a1));
111    DESCRIPTION
112    performs 32-bit division/modulo.
113    REGISTERS
114    used t0      bit-index
115         t1
116    modify a0    becomes remainer  */
117 #ifdef L_divsi3
118         .text
119         .global __udivsi3
120         .global __umodsi3
121         .global __divsi3
122         .global __modsi3
124         /* unsigned division  */
125         .ent    __udivsi3
126 __udivsi3:
127         li      t4, 0
128         cmpi.c  a1, 0
129         beq     __uds_exit
130         li      t0, 1
131         blt     __uds_ok
132 __uds_normalize:
133         cmp.c   a0, a1
134         bcc     __uds_ok
135         slli    a1, a1, 1
136         slli    t0, t0, 1
137         cmpi.c  a1, 0
138         bge     __uds_normalize
139 __uds_ok:
140 __uds_loop2:
141         cmp.c   a0, a1
142         bcc     __uds_loop3
143         sub     a0, a0, a1
144         or      t4, t4, t0
145 __uds_loop3:
146         srli    t0, t0, 1
147         srli    a1, a1, 1
148         cmpi.c  t0, 0
149         bne     __uds_loop2
150 __uds_exit:
151         mv      a1, a0
152         mv      r4, t4
153         br      ra
154         .end    __udivsi3
156         /* unsigned modulus  */
157         .ent    __umodsi3
158 __umodsi3:
159         mv      t3, ra
160         jl      __udivsi3
161         mv      r4, a1
162         br      t3
163         .end    __umodsi3
165         /* abs and div  */
166         .ent    __orgsi3
167 __orgsi3:
168         cmpi.c  a0, 0
169         bge     __orgsi3_a0p
170         neg     a0, a0
171 __orgsi3_a0p:
172         cmpi.c  a1, 0
173         bge     __udivsi3
174         neg     a1, a1
175         b       __udivsi3               # goto udivsi3
176         .end    __orgsi3
178         /* signed division  */
179         .ent    __divsi3
180 __divsi3:
181         mv      t3, ra
182         xor     t2, a0, a1
183         jl      __orgsi3
184 __divsi3_adjust:
185         cmpi.c  t2, 0
186         bge     __divsi3_exit
187         neg     r4, r4
188 __divsi3_exit:
189         br      t3
190         .end    __divsi3
192         /* signed modulus  */
193         .ent    __modsi3
194 __modsi3:
195         mv      t3, ra
196         mv      t2, a0
197         jl      __orgsi3
198         mv      r4, a1
199         b       __divsi3_adjust
200         .end    __modsi3
202 #endif /* L_divsi3 */
203 #else /* -fPIC */
204 #if !defined(L_mulsi3) && !defined(L_divsi3)
205         .set pic
206         .text
207         .global _flush_cache
208 _flush_cache:
209         addi    r0, -8                  # pic used
210         .cpload r29                     # pic used
211         srli    r9, r5, 4
212         mv      r8, r4
213         mtsr    r9, sr0
215         cache   0xe, [r8, 0]            # write back invalid dcache
216         addi    r8, 16
217         bcnz    1b
218         mfcr    r8, cr4
219         bittst! r8, 0x3                 # if LDM is enable, write back LDM
220         beq!    6f
221         ldi     r10, 0
222         cache   0xc, [r10, 0]
224         bittst! r8, 0x2                 # if LIM is enable, refill it
225         beq!    7f
226         cache   0x4, [r10, 0]
228         #nop!
229         #nop!
230         #nop!
231         #nop!
232         #nop!
233         mv      r8, r4
234         mtsr    r9, sr0
236         cache   0x2, [r8, 0]            # invalid unlock icache
237         #nop!
238         #nop!
239         #nop!
240         #nop!
241         #nop!
242         addi    r8, 16
243         bcnz    2b
244         .cprestore r0, 12               # pic used
245         addi    r0, 8                   # pic used
246         br      r3
247 #endif
249 /* FUNCTION
250    (U) INT32 v0 = __mulsi3 ((U) INT32 a0, (U) INT32 a1);
251    REGISTERS:
252         use     t0
253         modify  a0
254         a1      -> become 0
255    NOTE:
256    this seems to give better performance to just rotate and add.  */
258 #ifdef L_mulsi3
259         .set pic
260         .text
261         .global __umulsi3
262         .global __mulsi3
263         /* signed multiplication (32x32)  */
264         .ent    __mulsi3
265 __umulsi3:
266 __mulsi3:
267         addi    r0, -8                  # pic used
268         .cpload r29                     # pic used
269         li      t1, 0
270 __mulsi3_loop:
271         andri.c t0, a1, 1               # t0 = multiplier[0]
272         srli    a1, a1, 1               # a1 /= 2
273         beq     __mulsi3_loop2          # skip if (t0 == 0)
274         add     t1, t1, a0              # add multiplicand
275 __mulsi3_loop2:
276         slli    a0, a0, 1               # multiplicand mul 2
277         cmpi.c  a1, 0
278         bne     __mulsi3_loop
279         mv      r4, t1
280         .cprestore r0, 12               # pic used
281         addi    r0, 8                   # pic used
282         br      ra
283         .end    __mulsi3
284 #endif /* L_mulsi3 */
286 /* FUNCTION
287    UINT32 (v0) = __udivsi3 (UINT32 (a0), UINT32 (a1));
288    INT32 (v0) = __divsi3 (INT32 (a0),  INT32 (a1));
289    UINT32 (v0) = __umodsi3 (UINT32 (a0), UINT32 (a1));
290    INT32 (v0) = __modsi3 (INT32 (a0),  INT32 (a1));
291    DESCRIPTION
292    performs 32-bit division/modulo.
293    REGISTERS
294    used t0      bit-index
295         t1
296    modify a0    becomes remainer  */
297 #ifdef L_divsi3
298         .set pic
299         .text
300         .global __udivsi3
301         .global __umodsi3
302         .global __divsi3
303         .global __modsi3
305         /* unsigned division  */
306         .ent    __udivsi3
307 __udivsi3:
308         addi    r0, -8                  # pic used
309         .cpload r29                     # pic used
310         li      t4, 0
311         cmpi.c  a1, 0
312         beq     __uds_exit
313         li      t0, 1
314         blt     __uds_ok
315 __uds_normalize:
316         cmp.c   a0, a1
317         bcc     __uds_ok
318         slli    a1, a1, 1
319         slli    t0, t0, 1
320         cmpi.c  a1, 0
321         bge     __uds_normalize
322 __uds_ok:
323 __uds_loop2:
324         cmp.c   a0, a1
325         bcc     __uds_loop3
326         sub     a0, a0, a1
327         or      t4, t4, t0
328 __uds_loop3:
329         srli    t0, t0, 1
330         srli    a1, a1, 1
331         cmpi.c  t0, 0
332         bne     __uds_loop2
333 __uds_exit:
334         mv      a1, a0
335         mv      r4, t4
336         .cprestore r0, 12               # pic used
337         addi    r0, 8                   # pic used
338         br      ra
339         .end    __udivsi3
341         /* unsigned modulus  */
342         .ent    __umodsi3
343 __umodsi3:
344         addi    r0, -8                  # pic used
345         .cpload r29                     # pic used
346         li      t1, 0
347         mv      t3, ra
348 #       jl      __udivsi3
349         la      r29, __udivsi3
350         brl     r29
351         mv      r4, a1
352         .cprestore r0, 12               # pic used
353         addi    r0, 8                   # pic used
354         br      t3
355         .end    __umodsi3
357         /* abs and div  */
358         .ent    __orgsi3
359 __orgsi3:
360         cmpi.c  a0, 0
361         bge     __orgsi3_a0p
362         neg     a0, a0
363 __orgsi3_a0p:
364         cmpi.c  a1, 0
365         bge     __udivsi3
366         neg     a1, a1
367         b       __udivsi3               # goto udivsi3
368         .end    __orgsi3
370         /* signed division  */
371         .ent    __divsi3
372 __divsi3:
373         addi    r0, -8                  # pic used
374         .cpload r29                     # pic used
375         mv      t3, ra
376         xor     t2, a0, a1
377 #       jl      __orgsi3
378         la      r29, __orgsi3
379         brl     r29
380 __divsi3_adjust:
381         cmpi.c  t2, 0
382         bge     __divsi3_exit
383         neg     r4, r4
384 __divsi3_exit:
385         .cprestore r0, 12               # pic used
386         addi    r0, 8                   # pic used
387         br      t3
388         .end    __divsi3
390         /* signed modulus  */
391         .ent    __modsi3
392 __modsi3:
393         addi    r0, -8                  # pic used
394         .cpload r29                     # pic used
395         mv      t3, ra
396         mv      t2, a0
397 #       jl      __orgsi3
398         la      r29, __orgsi3
399         brl     r29
400         mv      r4, a1
401         b       __divsi3_adjust
402         .end    __modsi3
404 #endif /*L_divsi3 */
405 #endif