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