2 * File: arch/blackfin/lib/udivsi3.S
10 * Copyright 2004-2006 Analog Devices Inc.
12 * Bugs: Enter bugs at http://blackfin.uclinux.org/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see the file COPYING, or write
26 * to the Free Software Foundation, Inc.,
27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 #include <linux/linkage.h>
34 #ifdef CONFIG_ARITHMETIC_OPS_L1
43 CC = R0 < R1 (IU); /* If X < Y, always return 0 */
44 IF CC JUMP .Lreturn_ident;
50 R2 = R0 >> 31; /* if X is a 31-bit number */
51 R3 = R1 >> 15; /* and Y is a 15-bit number */
52 R2 = R2 | R3; /* then it's okay to use the DIVQ builtins (fallthrough to fast)*/
56 /* METHOD 1: FAST DIVQ
57 We know we have a 31-bit dividend, and 15-bit divisor so we can use the
58 simple divq approach (first setting AQ to 0 - implying unsigned division,
62 AQ = CC; /* Clear AQ (CC==0) */
64 /* ISR States: When dividing two integers (32.0/16.0) using divide primitives,
65 we need to shift the dividend one bit to the left.
66 We have already checked that we have a 31-bit number so we are safe to do
90 /* We know that the upper 17 bits of Y might have bits set,
91 ** or that the sign bit of X might have a bit. If Y is a
92 ** 16-bit number, but not bigger, then we can use the builtins
93 ** with a post-divide correction.
94 ** R3 currently holds Y>>15, which means R3's LSB is the
95 ** bit we're interested in.
98 /* According to the ISR, to use the Divide primitives for
99 ** unsigned integer divide, the useable range is 31 bits
101 CC = ! BITTST(R0, 31);
103 /* IF condition is true we can scale our inputs and use the divide primitives,
104 ** with some post-adjustment
106 R3 += -1; /* if so, Y is 0x00008nnn */
109 /* If condition is true we can scale our inputs and use the divide primitives,
110 ** with some post-adjustment
112 R3 = R1 >> 1; /* Pre-scaled divisor for primitive case */
115 R2 = R3 - R2; /* shifted divisor < upper 16 bits of dividend */
117 IF CC JUMP .Lshift_and_correct;
119 /* Fall through to the identities */
121 /* METHOD 2: identities and manual calculation
122 We are not able to use the divide primites, but may still catch some special
126 /* Test for common identities. Value to be returned is placed in R2. */
127 CC = R0 == 0; /* 0/Y => 0 */
128 IF CC JUMP .Lreturn_r0;
129 CC = R0 == R1; /* X==Y => 1 */
130 IF CC JUMP .Lreturn_ident;
131 CC = R1 == 1; /* X/1 => X */
132 IF CC JUMP .Lreturn_ident;
137 IF CC JUMP .Lpower_of_two;
139 [--SP] = (R7:5); /* Push registers R5-R7 */
141 /* Idents don't match. Go for the full operation. */
144 R6 = 2; /* assume we'll shift two */
148 /* If either R0 or R1 have sign set, */
149 /* divide them by two, and note it's */
153 IF CC R1 = R2; /* Possibly-shifted R1 */
154 IF !CC R6 = R3; /* R1 doesn't, so at most 1 shifted */
162 IF CC P0 = R6; /* Number of values divided */
163 IF !CC R2 = R0; /* Shifted R0 */
165 /* P0 is 0, 1 (NR/=2) or 2 (NR/=2, DR/=2) */
167 /* r2 holds Copy dividend */
168 R3 = 0; /* Clear partial remainder */
169 R7 = 0; /* Initialise quotient bit */
171 P1 = 32; /* Set loop counter */
172 LSETUP(.Lulst, .Lulend) LC0 = P1; /* Set loop counter */
173 .Lulst: R6 = R2 >> 31; /* R6 = sign bit of R2, for carry */
174 R2 = R2 << 1; /* Shift 64 bit dividend up by 1 bit */
175 R3 = R3 << 1 || R5 = [SP];
176 R3 = R3 | R6; /* Include any carry */
177 CC = R7 < 0; /* Check quotient(AQ) */
178 /* If AQ==0, we'll sub divisor */
179 IF CC R5 = R1; /* and if AQ==1, we'll add it. */
180 R3 = R3 + R5; /* Add/sub divsor to partial remainder */
181 R7 = R3 ^ R1; /* Generate next quotient bit */
183 R5 = R7 >> 31; /* Get AQ */
184 BITTGL(R5, 0); /* Invert it, to get what we'll shift */
185 .Lulend: R2 = R2 + R5; /* and "shift" it in. */
187 CC = P0 == 0; /* Check how many inputs we shifted */
188 IF CC JUMP .Lno_mult; /* if none... */
191 IF CC R2 = R6; /* if 1, Q = Q*2 */
192 IF !CC R1 = P2; /* if 2, restore stored divisor */
194 R3 = R2; /* Copy of R2 */
195 R3 *= R1; /* Q * divisor */
196 R5 = R0 - R3; /* Z = (dividend - Q * divisor) */
197 CC = R1 <= R5 (IU); /* Check if divisor <= Z? */
198 R6 = CC; /* if yes, R6 = 1 */
199 R2 = R2 + R6; /* if yes, add one to quotient(Q) */
202 (R7:5) = [SP++]; /* Pop registers R5-R7 */
203 R0 = R2; /* Store quotient */
207 CC = R0 < R1 (IU); /* If X < Y, always return 0 */
209 IF CC JUMP .Ltrue_return_ident;
210 R2 = -1 (X); /* X/0 => 0xFFFFFFFF */
212 IF CC JUMP .Ltrue_return_ident;
213 R2 = -R2; /* R2 now 1 */
214 CC = R0 == R1; /* X==Y => 1 */
215 IF CC JUMP .Ltrue_return_ident;
216 R2 = R0; /* X/1 => X */
225 /* Y has a single bit set, which means it's a power of two.
226 ** That means we can perform the division just by shifting
227 ** X to the right the appropriate number of bits
230 /* signbits returns the number of sign bits, minus one.
231 ** 1=>30, 2=>29, ..., 0x40000000=>0. Which means we need
232 ** to shift right n-signbits spaces. It also means 0x80000000
233 ** is a special case, because that *also* gives a signbits of 0
238 IF CC JUMP .Ltrue_return_ident;
243 R0 = LSHIFT R0 by R1.L;
246 /* METHOD 3: PRESCALE AND USE THE DIVIDE PRIMITIVES WITH SOME POST-CORRECTION
247 Two scaling operations are required to use the divide primitives with a
249 Firstly (as in method 1) we need to shift the dividend 1 to the left for
251 Secondly we need to shift both the divisor and dividend 1 to the right so
252 both are in range for the primitives.
253 The left/right shift of the dividend does nothing so we can skip it.
257 // R3 is already R1 >> 1
259 AQ = CC; /* Clear AQ, got here with CC = 0 */
277 /* According to the Instruction Set Reference:
278 To divide by a divisor > 0x7FFF,
279 1. prescale and perform divide to obtain quotient (Q) (done above),
280 2. multiply quotient by unscaled divisor (result M)
281 3. subtract the product from the divident to get an error (E = X - M)
282 4. if E < divisor (Y) subtract 1, if E > divisor (Y) add 1, else return quotient (Q)
284 R3 = R2.L (Z); /* Q = X' / Y' */
285 R2 = R3; /* Preserve Q */
286 R2 *= R1; /* M = Q * Y */
287 R2 = R0 - R2; /* E = X - M */
288 R0 = R3; /* Copy Q into result reg */
290 /* Correction: If result of the multiply is negative, we overflowed
291 and need to correct the result by subtracting 1 from the result.*/
293 R2 = R2 >> 16; /* E >> 16 */