2 * Copyright 2004-2009 Analog Devices Inc.
4 * Licensed under the ADI BSD license or the GPL-2 (or later)
6 * 16 / 32 bit signed division.
8 * 1) If(numerator == 0)
10 * 2) If(denominator ==0)
11 * return positive max = 0x7fffffff
12 * 3) If(numerator == denominator)
14 * 4) If(denominator ==1)
16 * 5) If(denominator == -1)
19 * Operand : R0 - Numerator (i)
20 * R1 - Denominator (i)
22 * Registers Used : R2-R7,P0-P2
27 .type ___divsi3, STT_FUNC;
29 #ifdef CONFIG_ARITHMETIC_OPS_L1
45 r1 = abs r1; /* now both positive, r3.30 means "negate result",
46 ** r3.31 means overflow, add one to result
49 if cc jump .Lret_zero;
76 r1 = r3 >> 31; /* add overflow issue back in */
83 /* Can't use the primitives. Test common identities.
84 ** If the identity is true, return the value in R2.
88 CC = R1 == 0; /* check for divide by zero */
89 IF CC JUMP .Lident_return;
91 CC = R0 == 0; /* check for division of zero */
92 IF CC JUMP .Lzero_return;
94 CC = R0 == R1; /* check for identical operands */
95 IF CC JUMP .Lident_return;
97 CC = R1 == 1; /* check for divide by 1 */
98 IF CC JUMP .Lident_return;
103 IF CC JUMP .Lpower_of_two;
105 /* Identities haven't helped either.
106 ** Perform the full division process.
109 P1 = 31; /* Set loop counter */
111 [--SP] = (R7:5); /* Push registers R5-R7 */
114 R2 = R0 << 1; /* R2 lsw of dividend */
115 R6 = R0 ^ R1; /* Get sign */
116 R5 = R6 >> 31; /* Shift sign to LSB */
118 R0 = 0 ; /* Clear msw partial remainder */
119 R2 = R2 | R5; /* Shift quotient bit */
120 R6 = R0 ^ R1; /* Get new quotient bit */
122 LSETUP(.Llst,.Llend) LC0 = P1; /* Setup loop */
123 .Llst: R7 = R2 >> 31; /* record copy of carry from R2 */
124 R2 = R2 << 1; /* Shift 64 bit dividend up by 1 bit */
125 R0 = R0 << 1 || R5 = [SP];
126 R0 = R0 | R7; /* and add carry */
127 CC = R6 < 0; /* Check quotient(AQ) */
128 /* we might be subtracting divisor (AQ==0) */
129 IF CC R5 = R1; /* or we might be adding divisor (AQ==1)*/
130 R0 = R0 + R5; /* do add or subtract, as indicated by AQ */
131 R6 = R0 ^ R1; /* Generate next quotient bit */
133 /* Assume AQ==1, shift in zero */
134 BITTGL(R5,0); /* tweak AQ to be what we want to shift in */
135 .Llend: R2 = R2 + R5; /* and then set shifted-in value to
144 (R7:5)= [SP++]; /* Pop registers R6-R7 */
148 CC = R1 == 0; /* check for divide by zero => 0x7fffffff */
151 IF CC JUMP .Ltrue_ident_return;
153 CC = R0 == R1; /* check for identical operands => 1 */
155 IF CC JUMP .Ltrue_ident_return;
157 R2 = R0; /* assume divide by 1 => numerator */
161 R0 = R2; /* Return an identity value */
166 RTS; /* ...including zero */
169 /* Y has a single bit set, which means it's a power of two.
170 ** That means we can perform the division just by shifting
171 ** X to the right the appropriate number of bits
174 /* signbits returns the number of sign bits, minus one.
175 ** 1=>30, 2=>29, ..., 0x40000000=>0. Which means we need
176 ** to shift right n-signbits spaces. It also means 0x80000000
177 ** is a special case, because that *also* gives a signbits of 0
182 IF CC JUMP .Ltrue_ident_return;
187 R0 = LSHIFT R0 by R1.L;
190 R2 = -R0; // negate result if necessary
199 .size ___divsi3, .-___divsi3