Add login.
[glibc/history.git] / sysdeps / sparc / rem.S
blobd50f1af630230bb2f17a48583a4d58b479cf3516
1    /* This file is generated from divrem.m4; DO NOT EDIT! */
2 /*
3  * Division and remainder, from Appendix E of the Sparc Version 8
4  * Architecture Manual, with fixes from Gordon Irlam.
5  */
7 /*
8  * Input: dividend and divisor in %o0 and %o1 respectively.
9  *
10  * m4 parameters:
11  *  .rem        name of function to generate
12  *  rem         rem=div => %o0 / %o1; rem=rem => %o0 % %o1
13  *  true                true=true => signed; true=false => unsigned
14  *
15  * Algorithm parameters:
16  *  N           how many bits per iteration we try to get (4)
17  *  WORDSIZE    total number of bits (32)
18  *
19  * Derived constants:
20  *  TOPBITS     number of bits in the top decade of a number
21  *
22  * Important variables:
23  *  Q           the partial quotient under development (initially 0)
24  *  R           the remainder so far, initially the dividend
25  *  ITER        number of main division loop iterations required;
26  *              equal to ceil(log2(quotient) / N).  Note that this
27  *              is the log base (2^N) of the quotient.
28  *  V           the current comparand, initially divisor*2^(ITER*N-1)
29  *
30  * Cost:
31  *  Current estimate for non-large dividend is
32  *      ceil(log2(quotient) / N) * (10 + 7N/2) + C
33  *  A large dividend is one greater than 2^(31-TOPBITS) and takes a
34  *  different path, as the upper bits of the quotient must be developed
35  *  one bit at a time.
36  */
40 #include "sysdep.h"
41 #ifdef __linux__
42 #include <asm/traps.h>
43 #else
44 #ifdef __svr4__
45 #include <sys/trap.h>
46 #else
47 #include <machine/trap.h>
48 #endif
49 #endif
51 ENTRY(.rem)
52         ! compute sign of result; if neither is negative, no problem
53         orcc    %o1, %o0, %g0   ! either negative?
54         bge     2f                      ! no, go do the divide
55         mov     %o0, %g6                ! sign of remainder matches %o0
56         tst     %o1
57         bge     1f
58         tst     %o0
59         ! %o1 is definitely negative; %o0 might also be negative
60         bge     2f                      ! if %o0 not negative...
61         sub     %g0, %o1, %o1   ! in any case, make %o1 nonneg
62 1:      ! %o0 is negative, %o1 is nonnegative
63         sub     %g0, %o0, %o0   ! make %o0 nonnegative
66         ! Ready to divide.  Compute size of quotient; scale comparand.
67         orcc    %o1, %g0, %o5
68         bne     1f
69         mov     %o0, %o3
71                 ! Divide by zero trap.  If it returns, return 0 (about as
72                 ! wrong as possible, but that is what SunOS does...).
73                 ta      ST_DIV0
74                 retl
75                 clr     %o0
78         cmp     %o3, %o5                        ! if %o1 exceeds %o0, done
79         blu     Lgot_result             ! (and algorithm fails otherwise)
80         clr     %o2
81         sethi   %hi(1 << (32 - 4 - 1)), %g1
82         cmp     %o3, %g1
83         blu     Lnot_really_big
84         clr     %o4
86         ! Here the dividend is >= 2**(31-N) or so.  We must be careful here,
87         ! as our usual N-at-a-shot divide step will cause overflow and havoc.
88         ! The number of bits in the result here is N*ITER+SC, where SC <= N.
89         ! Compute ITER in an unorthodox manner: know we need to shift V into
90         ! the top decade: so do not even bother to compare to R.
91         1:
92                 cmp     %o5, %g1
93                 bgeu    3f
94                 mov     1, %g7
95                 sll     %o5, 4, %o5
96                 b       1b
97                 add     %o4, 1, %o4
99         ! Now compute %g7.
100         2:      addcc   %o5, %o5, %o5
101                 bcc     Lnot_too_big
102                 add     %g7, 1, %g7
104                 ! We get here if the %o1 overflowed while shifting.
105                 ! This means that %o3 has the high-order bit set.
106                 ! Restore %o5 and subtract from %o3.
107                 sll     %g1, 4, %g1     ! high order bit
108                 srl     %o5, 1, %o5             ! rest of %o5
109                 add     %o5, %g1, %o5
110                 b       Ldo_single_div
111                 sub     %g7, 1, %g7
113         Lnot_too_big:
114         3:      cmp     %o5, %o3
115                 blu     2b
116                 nop
117                 be      Ldo_single_div
118                 nop
119         /* NB: these are commented out in the V8-Sparc manual as well */
120         /* (I do not understand this) */
121         ! %o5 > %o3: went too far: back up 1 step
122         !       srl     %o5, 1, %o5
123         !       dec     %g7
124         ! do single-bit divide steps
125         !
126         ! We have to be careful here.  We know that %o3 >= %o5, so we can do the
127         ! first divide step without thinking.  BUT, the others are conditional,
128         ! and are only done if %o3 >= 0.  Because both %o3 and %o5 may have the high-
129         ! order bit set in the first step, just falling into the regular
130         ! division loop will mess up the first time around.
131         ! So we unroll slightly...
132         Ldo_single_div:
133                 subcc   %g7, 1, %g7
134                 bl      Lend_regular_divide
135                 nop
136                 sub     %o3, %o5, %o3
137                 mov     1, %o2
138                 b       Lend_single_divloop
139                 nop
140         Lsingle_divloop:
141                 sll     %o2, 1, %o2
142                 bl      1f
143                 srl     %o5, 1, %o5
144                 ! %o3 >= 0
145                 sub     %o3, %o5, %o3
146                 b       2f
147                 add     %o2, 1, %o2
148         1:      ! %o3 < 0
149                 add     %o3, %o5, %o3
150                 sub     %o2, 1, %o2
151         2:
152         Lend_single_divloop:
153                 subcc   %g7, 1, %g7
154                 bge     Lsingle_divloop
155                 tst     %o3
156                 b,a     Lend_regular_divide
158 Lnot_really_big:
160         sll     %o5, 4, %o5
161         cmp     %o5, %o3
162         bleu    1b
163         addcc   %o4, 1, %o4
164         be      Lgot_result
165         sub     %o4, 1, %o4
167         tst     %o3     ! set up for initial iteration
168 Ldivloop:
169         sll     %o2, 4, %o2
170                 ! depth 1, accumulated bits 0
171         bl      L.1.16
172         srl     %o5,1,%o5
173         ! remainder is positive
174         subcc   %o3,%o5,%o3
175                         ! depth 2, accumulated bits 1
176         bl      L.2.17
177         srl     %o5,1,%o5
178         ! remainder is positive
179         subcc   %o3,%o5,%o3
180                         ! depth 3, accumulated bits 3
181         bl      L.3.19
182         srl     %o5,1,%o5
183         ! remainder is positive
184         subcc   %o3,%o5,%o3
185                         ! depth 4, accumulated bits 7
186         bl      L.4.23
187         srl     %o5,1,%o5
188         ! remainder is positive
189         subcc   %o3,%o5,%o3
190                 b       9f
191                 add     %o2, (7*2+1), %o2
193 L.4.23:
194         ! remainder is negative
195         addcc   %o3,%o5,%o3
196                 b       9f
197                 add     %o2, (7*2-1), %o2
200 L.3.19:
201         ! remainder is negative
202         addcc   %o3,%o5,%o3
203                         ! depth 4, accumulated bits 5
204         bl      L.4.21
205         srl     %o5,1,%o5
206         ! remainder is positive
207         subcc   %o3,%o5,%o3
208                 b       9f
209                 add     %o2, (5*2+1), %o2
211 L.4.21:
212         ! remainder is negative
213         addcc   %o3,%o5,%o3
214                 b       9f
215                 add     %o2, (5*2-1), %o2
219 L.2.17:
220         ! remainder is negative
221         addcc   %o3,%o5,%o3
222                         ! depth 3, accumulated bits 1
223         bl      L.3.17
224         srl     %o5,1,%o5
225         ! remainder is positive
226         subcc   %o3,%o5,%o3
227                         ! depth 4, accumulated bits 3
228         bl      L.4.19
229         srl     %o5,1,%o5
230         ! remainder is positive
231         subcc   %o3,%o5,%o3
232                 b       9f
233                 add     %o2, (3*2+1), %o2
235 L.4.19:
236         ! remainder is negative
237         addcc   %o3,%o5,%o3
238                 b       9f
239                 add     %o2, (3*2-1), %o2
242 L.3.17:
243         ! remainder is negative
244         addcc   %o3,%o5,%o3
245                         ! depth 4, accumulated bits 1
246         bl      L.4.17
247         srl     %o5,1,%o5
248         ! remainder is positive
249         subcc   %o3,%o5,%o3
250                 b       9f
251                 add     %o2, (1*2+1), %o2
253 L.4.17:
254         ! remainder is negative
255         addcc   %o3,%o5,%o3
256                 b       9f
257                 add     %o2, (1*2-1), %o2
262 L.1.16:
263         ! remainder is negative
264         addcc   %o3,%o5,%o3
265                         ! depth 2, accumulated bits -1
266         bl      L.2.15
267         srl     %o5,1,%o5
268         ! remainder is positive
269         subcc   %o3,%o5,%o3
270                         ! depth 3, accumulated bits -1
271         bl      L.3.15
272         srl     %o5,1,%o5
273         ! remainder is positive
274         subcc   %o3,%o5,%o3
275                         ! depth 4, accumulated bits -1
276         bl      L.4.15
277         srl     %o5,1,%o5
278         ! remainder is positive
279         subcc   %o3,%o5,%o3
280                 b       9f
281                 add     %o2, (-1*2+1), %o2
283 L.4.15:
284         ! remainder is negative
285         addcc   %o3,%o5,%o3
286                 b       9f
287                 add     %o2, (-1*2-1), %o2
290 L.3.15:
291         ! remainder is negative
292         addcc   %o3,%o5,%o3
293                         ! depth 4, accumulated bits -3
294         bl      L.4.13
295         srl     %o5,1,%o5
296         ! remainder is positive
297         subcc   %o3,%o5,%o3
298                 b       9f
299                 add     %o2, (-3*2+1), %o2
301 L.4.13:
302         ! remainder is negative
303         addcc   %o3,%o5,%o3
304                 b       9f
305                 add     %o2, (-3*2-1), %o2
309 L.2.15:
310         ! remainder is negative
311         addcc   %o3,%o5,%o3
312                         ! depth 3, accumulated bits -3
313         bl      L.3.13
314         srl     %o5,1,%o5
315         ! remainder is positive
316         subcc   %o3,%o5,%o3
317                         ! depth 4, accumulated bits -5
318         bl      L.4.11
319         srl     %o5,1,%o5
320         ! remainder is positive
321         subcc   %o3,%o5,%o3
322                 b       9f
323                 add     %o2, (-5*2+1), %o2
325 L.4.11:
326         ! remainder is negative
327         addcc   %o3,%o5,%o3
328                 b       9f
329                 add     %o2, (-5*2-1), %o2
332 L.3.13:
333         ! remainder is negative
334         addcc   %o3,%o5,%o3
335                         ! depth 4, accumulated bits -7
336         bl      L.4.9
337         srl     %o5,1,%o5
338         ! remainder is positive
339         subcc   %o3,%o5,%o3
340                 b       9f
341                 add     %o2, (-7*2+1), %o2
343 L.4.9:
344         ! remainder is negative
345         addcc   %o3,%o5,%o3
346                 b       9f
347                 add     %o2, (-7*2-1), %o2
352         9:
353 Lend_regular_divide:
354         subcc   %o4, 1, %o4
355         bge     Ldivloop
356         tst     %o3
357         bl,a    Lgot_result
358         ! non-restoring fixup here (one instruction only!)
359         add     %o3, %o1, %o3
362 Lgot_result:
363         ! check to see if answer should be < 0
364         tst     %g6
365         bl,a    1f
366         sub %g0, %o3, %o3
368         retl
369         mov %o3, %o0