lib1funcs-Os-4-200.S revision 1.1.1.11 1 1.1.1.11 mrg /* Copyright (C) 2006-2024 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 #ifdef L_udivsi3_i4i
29 1.1 mrg
30 1.1 mrg /* 88 bytes; sh4-200 cycle counts:
31 1.1 mrg divisor >= 2G: 11 cycles
32 1.1 mrg dividend < 2G: 48 cycles
33 1.1 mrg dividend >= 2G: divisor != 1: 54 cycles
34 1.1 mrg dividend >= 2G, divisor == 1: 22 cycles */
35 1.1 mrg #if defined (__SH_FPU_DOUBLE__) || defined (__SH4_SINGLE_ONLY__)
36 1.1 mrg !! args in r4 and r5, result in r0, clobber r1
37 1.1 mrg
38 1.1 mrg .global GLOBAL(udivsi3_i4i)
39 1.1 mrg FUNC(GLOBAL(udivsi3_i4i))
40 1.1 mrg GLOBAL(udivsi3_i4i):
41 1.1 mrg mova L1,r0
42 1.1 mrg cmp/pz r5
43 1.1 mrg sts fpscr,r1
44 1.1 mrg lds.l @r0+,fpscr
45 1.1 mrg sts.l fpul,@-r15
46 1.1 mrg bf LOCAL(huge_divisor)
47 1.1 mrg mov.l r1,@-r15
48 1.1 mrg lds r4,fpul
49 1.1 mrg cmp/pz r4
50 1.1 mrg #ifdef FMOVD_WORKS
51 1.1 mrg fmov.d dr0,@-r15
52 1.1 mrg float fpul,dr0
53 1.1 mrg fmov.d dr2,@-r15
54 1.1 mrg bt LOCAL(dividend_adjusted)
55 1.1 mrg mov #1,r1
56 1.1 mrg fmov.d @r0,dr2
57 1.1 mrg cmp/eq r1,r5
58 1.1 mrg bt LOCAL(div_by_1)
59 1.1 mrg fadd dr2,dr0
60 1.1 mrg LOCAL(dividend_adjusted):
61 1.1 mrg lds r5,fpul
62 1.1 mrg float fpul,dr2
63 1.1 mrg fdiv dr2,dr0
64 1.1 mrg LOCAL(div_by_1):
65 1.1 mrg fmov.d @r15+,dr2
66 1.1 mrg ftrc dr0,fpul
67 1.1 mrg fmov.d @r15+,dr0
68 1.1 mrg #else /* !FMOVD_WORKS */
69 1.1 mrg fmov.s DR01,@-r15
70 1.1 mrg mov #1,r1
71 1.1 mrg fmov.s DR00,@-r15
72 1.1 mrg float fpul,dr0
73 1.1 mrg fmov.s DR21,@-r15
74 1.1 mrg bt/s LOCAL(dividend_adjusted)
75 1.1 mrg fmov.s DR20,@-r15
76 1.1 mrg cmp/eq r1,r5
77 1.1 mrg bt LOCAL(div_by_1)
78 1.1 mrg fmov.s @r0+,DR20
79 1.1 mrg fmov.s @r0,DR21
80 1.1 mrg fadd dr2,dr0
81 1.1 mrg LOCAL(dividend_adjusted):
82 1.1 mrg lds r5,fpul
83 1.1 mrg float fpul,dr2
84 1.1 mrg fdiv dr2,dr0
85 1.1 mrg LOCAL(div_by_1):
86 1.1 mrg fmov.s @r15+,DR20
87 1.1 mrg fmov.s @r15+,DR21
88 1.1 mrg ftrc dr0,fpul
89 1.1 mrg fmov.s @r15+,DR00
90 1.1 mrg fmov.s @r15+,DR01
91 1.1 mrg #endif /* !FMOVD_WORKS */
92 1.1 mrg lds.l @r15+,fpscr
93 1.1 mrg sts fpul,r0
94 1.1 mrg rts
95 1.1 mrg lds.l @r15+,fpul
96 1.1 mrg
97 1.1 mrg #ifdef FMOVD_WORKS
98 1.1 mrg .p2align 3 ! make double below 8 byte aligned.
99 1.1 mrg #endif
100 1.1 mrg LOCAL(huge_divisor):
101 1.1 mrg lds r1,fpscr
102 1.1 mrg add #4,r15
103 1.1 mrg cmp/hs r5,r4
104 1.1 mrg rts
105 1.1 mrg movt r0
106 1.1 mrg
107 1.1 mrg .p2align 2
108 1.1 mrg L1:
109 1.1 mrg #ifndef FMOVD_WORKS
110 1.1 mrg .long 0x80000
111 1.1 mrg #else
112 1.1 mrg .long 0x180000
113 1.1 mrg #endif
114 1.1 mrg .double 4294967296
115 1.1 mrg
116 1.1 mrg ENDFUNC(GLOBAL(udivsi3_i4i))
117 1.1 mrg #elif !defined (__sh1__) /* !__SH_FPU_DOUBLE__ */
118 1.1 mrg
119 1.1 mrg #if 0
120 1.1 mrg /* With 36 bytes, the following would probably be the most compact
121 1.1 mrg implementation, but with 139 cycles on an sh4-200, it is extremely slow. */
122 1.1 mrg GLOBAL(udivsi3_i4i):
123 1.1 mrg mov.l r2,@-r15
124 1.1 mrg mov #0,r1
125 1.1 mrg div0u
126 1.1 mrg mov r1,r2
127 1.1 mrg mov.l r3,@-r15
128 1.1 mrg mov r1,r3
129 1.1 mrg sett
130 1.1 mrg mov r4,r0
131 1.1 mrg LOCAL(loop):
132 1.1 mrg rotcr r2
133 1.1 mrg ;
134 1.1 mrg bt/s LOCAL(end)
135 1.1 mrg cmp/gt r2,r3
136 1.1 mrg rotcl r0
137 1.1 mrg bra LOCAL(loop)
138 1.1 mrg div1 r5,r1
139 1.1 mrg LOCAL(end):
140 1.1 mrg rotcl r0
141 1.1 mrg mov.l @r15+,r3
142 1.1 mrg rts
143 1.1 mrg mov.l @r15+,r2
144 1.1 mrg #endif /* 0 */
145 1.1 mrg
146 1.1 mrg /* Size: 186 bytes jointly for udivsi3_i4i and sdivsi3_i4i
147 1.1 mrg sh4-200 run times:
148 1.1 mrg udiv small divisor: 55 cycles
149 1.1 mrg udiv large divisor: 52 cycles
150 1.1 mrg sdiv small divisor, positive result: 59 cycles
151 1.1 mrg sdiv large divisor, positive result: 56 cycles
152 1.1 mrg sdiv small divisor, negative result: 65 cycles (*)
153 1.1 mrg sdiv large divisor, negative result: 62 cycles (*)
154 1.1 mrg (*): r2 is restored in the rts delay slot and has a lingering latency
155 1.1 mrg of two more cycles. */
156 1.1 mrg .balign 4
157 1.1 mrg .global GLOBAL(udivsi3_i4i)
158 1.1 mrg FUNC(GLOBAL(udivsi3_i4i))
159 1.1 mrg FUNC(GLOBAL(sdivsi3_i4i))
160 1.1 mrg GLOBAL(udivsi3_i4i):
161 1.1 mrg sts pr,r1
162 1.1 mrg mov.l r4,@-r15
163 1.1 mrg extu.w r5,r0
164 1.1 mrg cmp/eq r5,r0
165 1.1 mrg swap.w r4,r0
166 1.1 mrg shlr16 r4
167 1.1 mrg bf/s LOCAL(large_divisor)
168 1.1 mrg div0u
169 1.1 mrg mov.l r5,@-r15
170 1.1 mrg shll16 r5
171 1.1 mrg LOCAL(sdiv_small_divisor):
172 1.1 mrg div1 r5,r4
173 1.1 mrg bsr LOCAL(div6)
174 1.1 mrg div1 r5,r4
175 1.1 mrg div1 r5,r4
176 1.1 mrg bsr LOCAL(div6)
177 1.1 mrg div1 r5,r4
178 1.1 mrg xtrct r4,r0
179 1.1 mrg xtrct r0,r4
180 1.1 mrg bsr LOCAL(div7)
181 1.1 mrg swap.w r4,r4
182 1.1 mrg div1 r5,r4
183 1.1 mrg bsr LOCAL(div7)
184 1.1 mrg div1 r5,r4
185 1.1 mrg xtrct r4,r0
186 1.1 mrg mov.l @r15+,r5
187 1.1 mrg swap.w r0,r0
188 1.1 mrg mov.l @r15+,r4
189 1.1 mrg jmp @r1
190 1.1 mrg rotcl r0
191 1.1 mrg LOCAL(div7):
192 1.1 mrg div1 r5,r4
193 1.1 mrg LOCAL(div6):
194 1.1 mrg div1 r5,r4; div1 r5,r4; div1 r5,r4
195 1.1 mrg div1 r5,r4; div1 r5,r4; rts; div1 r5,r4
196 1.1 mrg
197 1.1 mrg LOCAL(divx3):
198 1.1 mrg rotcl r0
199 1.1 mrg div1 r5,r4
200 1.1 mrg rotcl r0
201 1.1 mrg div1 r5,r4
202 1.1 mrg rotcl r0
203 1.1 mrg rts
204 1.1 mrg div1 r5,r4
205 1.1 mrg
206 1.1 mrg LOCAL(large_divisor):
207 1.1 mrg mov.l r5,@-r15
208 1.1 mrg LOCAL(sdiv_large_divisor):
209 1.1 mrg xor r4,r0
210 1.1 mrg .rept 4
211 1.1 mrg rotcl r0
212 1.1 mrg bsr LOCAL(divx3)
213 1.1 mrg div1 r5,r4
214 1.1 mrg .endr
215 1.1 mrg mov.l @r15+,r5
216 1.1 mrg mov.l @r15+,r4
217 1.1 mrg jmp @r1
218 1.1 mrg rotcl r0
219 1.1 mrg ENDFUNC(GLOBAL(udivsi3_i4i))
220 1.1 mrg
221 1.1 mrg .global GLOBAL(sdivsi3_i4i)
222 1.1 mrg GLOBAL(sdivsi3_i4i):
223 1.1 mrg mov.l r4,@-r15
224 1.1 mrg cmp/pz r5
225 1.1 mrg mov.l r5,@-r15
226 1.1 mrg bt/s LOCAL(pos_divisor)
227 1.1 mrg cmp/pz r4
228 1.1 mrg neg r5,r5
229 1.1 mrg extu.w r5,r0
230 1.1 mrg bt/s LOCAL(neg_result)
231 1.1 mrg cmp/eq r5,r0
232 1.1 mrg neg r4,r4
233 1.1 mrg LOCAL(pos_result):
234 1.1 mrg swap.w r4,r0
235 1.1 mrg bra LOCAL(sdiv_check_divisor)
236 1.1 mrg sts pr,r1
237 1.1 mrg LOCAL(pos_divisor):
238 1.1 mrg extu.w r5,r0
239 1.1 mrg bt/s LOCAL(pos_result)
240 1.1 mrg cmp/eq r5,r0
241 1.1 mrg neg r4,r4
242 1.1 mrg LOCAL(neg_result):
243 1.1 mrg mova LOCAL(negate_result),r0
244 1.1 mrg ;
245 1.1 mrg mov r0,r1
246 1.1 mrg swap.w r4,r0
247 1.1 mrg lds r2,macl
248 1.1 mrg sts pr,r2
249 1.1 mrg LOCAL(sdiv_check_divisor):
250 1.1 mrg shlr16 r4
251 1.1 mrg bf/s LOCAL(sdiv_large_divisor)
252 1.1 mrg div0u
253 1.1 mrg bra LOCAL(sdiv_small_divisor)
254 1.1 mrg shll16 r5
255 1.1 mrg .balign 4
256 1.1 mrg LOCAL(negate_result):
257 1.1 mrg neg r0,r0
258 1.1 mrg jmp @r2
259 1.1 mrg sts macl,r2
260 1.1 mrg ENDFUNC(GLOBAL(sdivsi3_i4i))
261 1.1 mrg #endif /* !__SH_FPU_DOUBLE__ */
262 1.1 mrg #endif /* L_udivsi3_i4i */
263 1.1 mrg
264 1.1 mrg #ifdef L_sdivsi3_i4i
265 1.1 mrg #if defined (__SH_FPU_DOUBLE__) || defined (__SH4_SINGLE_ONLY__)
266 1.1 mrg /* 48 bytes, 45 cycles on sh4-200 */
267 1.1 mrg !! args in r4 and r5, result in r0, clobber r1
268 1.1 mrg
269 1.1 mrg .global GLOBAL(sdivsi3_i4i)
270 1.1 mrg FUNC(GLOBAL(sdivsi3_i4i))
271 1.1 mrg GLOBAL(sdivsi3_i4i):
272 1.1 mrg sts.l fpscr,@-r15
273 1.1 mrg sts fpul,r1
274 1.1 mrg mova L1,r0
275 1.1 mrg lds.l @r0+,fpscr
276 1.1 mrg lds r4,fpul
277 1.1 mrg #ifdef FMOVD_WORKS
278 1.1 mrg fmov.d dr0,@-r15
279 1.1 mrg float fpul,dr0
280 1.1 mrg lds r5,fpul
281 1.1 mrg fmov.d dr2,@-r15
282 1.1 mrg #else
283 1.1 mrg fmov.s DR01,@-r15
284 1.1 mrg fmov.s DR00,@-r15
285 1.1 mrg float fpul,dr0
286 1.1 mrg lds r5,fpul
287 1.1 mrg fmov.s DR21,@-r15
288 1.1 mrg fmov.s DR20,@-r15
289 1.1 mrg #endif
290 1.1 mrg float fpul,dr2
291 1.1 mrg fdiv dr2,dr0
292 1.1 mrg #ifdef FMOVD_WORKS
293 1.1 mrg fmov.d @r15+,dr2
294 1.1 mrg #else
295 1.1 mrg fmov.s @r15+,DR20
296 1.1 mrg fmov.s @r15+,DR21
297 1.1 mrg #endif
298 1.1 mrg ftrc dr0,fpul
299 1.1 mrg #ifdef FMOVD_WORKS
300 1.1 mrg fmov.d @r15+,dr0
301 1.1 mrg #else
302 1.1 mrg fmov.s @r15+,DR00
303 1.1 mrg fmov.s @r15+,DR01
304 1.1 mrg #endif
305 1.1 mrg lds.l @r15+,fpscr
306 1.1 mrg sts fpul,r0
307 1.1 mrg rts
308 1.1 mrg lds r1,fpul
309 1.1 mrg
310 1.1 mrg .p2align 2
311 1.1 mrg L1:
312 1.1 mrg #ifndef FMOVD_WORKS
313 1.1 mrg .long 0x80000
314 1.1 mrg #else
315 1.1 mrg .long 0x180000
316 1.1 mrg #endif
317 1.1 mrg
318 1.1 mrg ENDFUNC(GLOBAL(sdivsi3_i4i))
319 1.1 mrg #endif /* __SH_FPU_DOUBLE__ */
320 1.1 mrg #endif /* L_sdivsi3_i4i */
321