2018-03-23 Eric Botcazou <ebotcazou@adacore.com>
[official-gcc.git] / libgcc / config / sh / lib1funcs-Os-4-200.S
blob63083ab1134f2f83a1d0710891496b5b0f5c5df6
1 /* Copyright (C) 2006-2018 Free Software Foundation, Inc.
3 This file is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 3, or (at your option) any
6 later version.
8 This file is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 General Public License for more details.
13 Under Section 7 of GPL version 3, you are granted additional
14 permissions described in the GCC Runtime Library Exception, version
15 3.1, as published by the Free Software Foundation.
17 You should have received a copy of the GNU General Public License and
18 a copy of the GCC Runtime Library Exception along with this program;
19 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
20 <http://www.gnu.org/licenses/>.  */
22 /* Moderately Space-optimized libgcc routines for the Renesas SH /
23    STMicroelectronics ST40 CPUs.
24    Contributed by J"orn Rennecke joern.rennecke@st.com.  */
26 #include "lib1funcs.h"
28 #ifdef L_udivsi3_i4i
30 /* 88 bytes; sh4-200 cycle counts:
31    divisor  >= 2G: 11 cycles
32    dividend <  2G: 48 cycles
33    dividend >= 2G: divisor != 1: 54 cycles
34    dividend >= 2G, divisor == 1: 22 cycles */
35 #if defined (__SH_FPU_DOUBLE__) || defined (__SH4_SINGLE_ONLY__)
36 !! args in r4 and r5, result in r0, clobber r1
38         .global GLOBAL(udivsi3_i4i)
39         FUNC(GLOBAL(udivsi3_i4i))
40 GLOBAL(udivsi3_i4i):
41         mova L1,r0
42         cmp/pz r5
43         sts fpscr,r1
44         lds.l @r0+,fpscr
45         sts.l fpul,@-r15
46         bf LOCAL(huge_divisor)
47         mov.l r1,@-r15
48         lds r4,fpul
49         cmp/pz r4
50 #ifdef FMOVD_WORKS
51         fmov.d dr0,@-r15
52         float fpul,dr0
53         fmov.d dr2,@-r15
54         bt LOCAL(dividend_adjusted)
55         mov #1,r1
56         fmov.d @r0,dr2
57         cmp/eq r1,r5
58         bt LOCAL(div_by_1)
59         fadd dr2,dr0
60 LOCAL(dividend_adjusted):
61         lds r5,fpul
62         float fpul,dr2
63         fdiv dr2,dr0
64 LOCAL(div_by_1):
65         fmov.d @r15+,dr2
66         ftrc dr0,fpul
67         fmov.d @r15+,dr0
68 #else /* !FMOVD_WORKS */
69         fmov.s DR01,@-r15
70         mov #1,r1
71         fmov.s DR00,@-r15
72         float fpul,dr0
73         fmov.s DR21,@-r15
74         bt/s LOCAL(dividend_adjusted)
75         fmov.s DR20,@-r15
76         cmp/eq r1,r5
77         bt LOCAL(div_by_1)
78         fmov.s @r0+,DR20
79         fmov.s @r0,DR21
80         fadd dr2,dr0
81 LOCAL(dividend_adjusted):
82         lds r5,fpul
83         float fpul,dr2
84         fdiv dr2,dr0
85 LOCAL(div_by_1):
86         fmov.s @r15+,DR20
87         fmov.s @r15+,DR21
88         ftrc dr0,fpul
89         fmov.s @r15+,DR00
90         fmov.s @r15+,DR01
91 #endif /* !FMOVD_WORKS */
92         lds.l @r15+,fpscr
93         sts fpul,r0
94         rts
95         lds.l @r15+,fpul
97 #ifdef FMOVD_WORKS
98         .p2align 3        ! make double below 8 byte aligned.
99 #endif
100 LOCAL(huge_divisor):
101         lds r1,fpscr
102         add #4,r15
103         cmp/hs r5,r4
104         rts
105         movt r0
107         .p2align 2
109 #ifndef FMOVD_WORKS
110         .long 0x80000
111 #else
112         .long 0x180000
113 #endif
114         .double 4294967296
116         ENDFUNC(GLOBAL(udivsi3_i4i))
117 #elif !defined (__sh1__)  /* !__SH_FPU_DOUBLE__ */
119 #if 0
120 /* With 36 bytes, the following would probably be the most compact
121    implementation, but with 139 cycles on an sh4-200, it is extremely slow.  */
122 GLOBAL(udivsi3_i4i):
123         mov.l r2,@-r15
124         mov #0,r1
125         div0u
126         mov r1,r2
127         mov.l r3,@-r15
128         mov r1,r3
129         sett
130         mov r4,r0
131 LOCAL(loop):
132         rotcr r2
133         ;
134         bt/s LOCAL(end)
135         cmp/gt r2,r3
136         rotcl r0
137         bra LOCAL(loop)
138         div1 r5,r1
139 LOCAL(end):
140         rotcl r0
141         mov.l @r15+,r3
142         rts
143         mov.l @r15+,r2
144 #endif /* 0 */
146 /* Size: 186 bytes jointly for udivsi3_i4i and sdivsi3_i4i
147    sh4-200 run times:
148    udiv small divisor: 55 cycles
149    udiv large divisor: 52 cycles
150    sdiv small divisor, positive result: 59 cycles
151    sdiv large divisor, positive result: 56 cycles
152    sdiv small divisor, negative result: 65 cycles (*)
153    sdiv large divisor, negative result: 62 cycles (*)
154    (*): r2 is restored in the rts delay slot and has a lingering latency
155         of two more cycles.  */
156         .balign 4
157         .global GLOBAL(udivsi3_i4i)
158         FUNC(GLOBAL(udivsi3_i4i))
159         FUNC(GLOBAL(sdivsi3_i4i))
160 GLOBAL(udivsi3_i4i):
161         sts pr,r1
162         mov.l r4,@-r15
163         extu.w r5,r0
164         cmp/eq r5,r0
165         swap.w r4,r0
166         shlr16 r4
167         bf/s LOCAL(large_divisor)
168         div0u
169         mov.l r5,@-r15
170         shll16 r5
171 LOCAL(sdiv_small_divisor):
172         div1 r5,r4
173         bsr LOCAL(div6)
174         div1 r5,r4
175         div1 r5,r4
176         bsr LOCAL(div6)
177         div1 r5,r4
178         xtrct r4,r0
179         xtrct r0,r4
180         bsr LOCAL(div7)
181         swap.w r4,r4
182         div1 r5,r4
183         bsr LOCAL(div7)
184         div1 r5,r4
185         xtrct r4,r0
186         mov.l @r15+,r5
187         swap.w r0,r0
188         mov.l @r15+,r4
189         jmp @r1
190         rotcl r0
191 LOCAL(div7):
192         div1 r5,r4
193 LOCAL(div6):
194                     div1 r5,r4; div1 r5,r4; div1 r5,r4
195         div1 r5,r4; div1 r5,r4; rts;        div1 r5,r4
197 LOCAL(divx3):
198         rotcl r0
199         div1 r5,r4
200         rotcl r0
201         div1 r5,r4
202         rotcl r0
203         rts
204         div1 r5,r4
206 LOCAL(large_divisor):
207         mov.l r5,@-r15
208 LOCAL(sdiv_large_divisor):
209         xor r4,r0
210         .rept 4
211         rotcl r0
212         bsr LOCAL(divx3)
213         div1 r5,r4
214         .endr
215         mov.l @r15+,r5
216         mov.l @r15+,r4
217         jmp @r1
218         rotcl r0
219         ENDFUNC(GLOBAL(udivsi3_i4i))
221         .global GLOBAL(sdivsi3_i4i)
222 GLOBAL(sdivsi3_i4i):
223         mov.l r4,@-r15
224         cmp/pz r5
225         mov.l r5,@-r15
226         bt/s LOCAL(pos_divisor)
227         cmp/pz r4
228         neg r5,r5
229         extu.w r5,r0
230         bt/s LOCAL(neg_result)
231         cmp/eq r5,r0
232         neg r4,r4
233 LOCAL(pos_result):
234         swap.w r4,r0
235         bra LOCAL(sdiv_check_divisor)
236         sts pr,r1
237 LOCAL(pos_divisor):
238         extu.w r5,r0
239         bt/s LOCAL(pos_result)
240         cmp/eq r5,r0
241         neg r4,r4
242 LOCAL(neg_result):
243         mova LOCAL(negate_result),r0
244         ;
245         mov r0,r1
246         swap.w r4,r0
247         lds r2,macl
248         sts pr,r2
249 LOCAL(sdiv_check_divisor):
250         shlr16 r4
251         bf/s LOCAL(sdiv_large_divisor)
252         div0u
253         bra LOCAL(sdiv_small_divisor)
254         shll16 r5
255         .balign 4
256 LOCAL(negate_result):
257         neg r0,r0
258         jmp @r2
259         sts macl,r2
260         ENDFUNC(GLOBAL(sdivsi3_i4i))
261 #endif /* !__SH_FPU_DOUBLE__ */
262 #endif /* L_udivsi3_i4i */
264 #ifdef L_sdivsi3_i4i
265 #if defined (__SH_FPU_DOUBLE__) || defined (__SH4_SINGLE_ONLY__)
266 /* 48 bytes, 45 cycles on sh4-200  */
267 !! args in r4 and r5, result in r0, clobber r1
269         .global GLOBAL(sdivsi3_i4i)
270         FUNC(GLOBAL(sdivsi3_i4i))
271 GLOBAL(sdivsi3_i4i):
272         sts.l fpscr,@-r15
273         sts fpul,r1
274         mova L1,r0
275         lds.l @r0+,fpscr
276         lds r4,fpul
277 #ifdef FMOVD_WORKS
278         fmov.d dr0,@-r15
279         float fpul,dr0
280         lds r5,fpul
281         fmov.d dr2,@-r15
282 #else
283         fmov.s DR01,@-r15
284         fmov.s DR00,@-r15
285         float fpul,dr0
286         lds r5,fpul
287         fmov.s DR21,@-r15
288         fmov.s DR20,@-r15
289 #endif
290         float fpul,dr2
291         fdiv dr2,dr0
292 #ifdef FMOVD_WORKS
293         fmov.d @r15+,dr2
294 #else
295         fmov.s @r15+,DR20
296         fmov.s @r15+,DR21
297 #endif
298         ftrc dr0,fpul
299 #ifdef FMOVD_WORKS
300         fmov.d @r15+,dr0
301 #else
302         fmov.s @r15+,DR00
303         fmov.s @r15+,DR01
304 #endif
305         lds.l @r15+,fpscr
306         sts fpul,r0
307         rts
308         lds r1,fpul
310         .p2align 2
312 #ifndef FMOVD_WORKS
313         .long 0x80000
314 #else
315         .long 0x180000
316 #endif
318         ENDFUNC(GLOBAL(sdivsi3_i4i))
319 #endif /* __SH_FPU_DOUBLE__ */
320 #endif /* L_sdivsi3_i4i */