Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/blackfin/lib/divsi3.S
10817 views
1
/*
2
* Copyright 2004-2009 Analog Devices Inc.
3
*
4
* Licensed under the ADI BSD license or the GPL-2 (or later)
5
*
6
* 16 / 32 bit signed division.
7
* Special cases :
8
* 1) If(numerator == 0)
9
* return 0
10
* 2) If(denominator ==0)
11
* return positive max = 0x7fffffff
12
* 3) If(numerator == denominator)
13
* return 1
14
* 4) If(denominator ==1)
15
* return numerator
16
* 5) If(denominator == -1)
17
* return -numerator
18
*
19
* Operand : R0 - Numerator (i)
20
* R1 - Denominator (i)
21
* R0 - Quotient (o)
22
* Registers Used : R2-R7,P0-P2
23
*
24
*/
25
26
.global ___divsi3;
27
.type ___divsi3, STT_FUNC;
28
29
#ifdef CONFIG_ARITHMETIC_OPS_L1
30
.section .l1.text
31
#else
32
.text
33
#endif
34
35
.align 2;
36
___divsi3 :
37
38
39
R3 = R0 ^ R1;
40
R0 = ABS R0;
41
42
CC = V;
43
44
r3 = rot r3 by -1;
45
r1 = abs r1; /* now both positive, r3.30 means "negate result",
46
** r3.31 means overflow, add one to result
47
*/
48
cc = r0 < r1;
49
if cc jump .Lret_zero;
50
r2 = r1 >> 15;
51
cc = r2;
52
if cc jump .Lidents;
53
r2 = r1 << 16;
54
cc = r2 <= r0;
55
if cc jump .Lidents;
56
57
DIVS(R0, R1);
58
DIVQ(R0, R1);
59
DIVQ(R0, R1);
60
DIVQ(R0, R1);
61
DIVQ(R0, R1);
62
DIVQ(R0, R1);
63
DIVQ(R0, R1);
64
DIVQ(R0, R1);
65
DIVQ(R0, R1);
66
DIVQ(R0, R1);
67
DIVQ(R0, R1);
68
DIVQ(R0, R1);
69
DIVQ(R0, R1);
70
DIVQ(R0, R1);
71
DIVQ(R0, R1);
72
DIVQ(R0, R1);
73
DIVQ(R0, R1);
74
75
R0 = R0.L (Z);
76
r1 = r3 >> 31; /* add overflow issue back in */
77
r0 = r0 + r1;
78
r1 = -r0;
79
cc = bittst(r3, 30);
80
if cc r0 = r1;
81
RTS;
82
83
/* Can't use the primitives. Test common identities.
84
** If the identity is true, return the value in R2.
85
*/
86
87
.Lidents:
88
CC = R1 == 0; /* check for divide by zero */
89
IF CC JUMP .Lident_return;
90
91
CC = R0 == 0; /* check for division of zero */
92
IF CC JUMP .Lzero_return;
93
94
CC = R0 == R1; /* check for identical operands */
95
IF CC JUMP .Lident_return;
96
97
CC = R1 == 1; /* check for divide by 1 */
98
IF CC JUMP .Lident_return;
99
100
R2.L = ONES R1;
101
R2 = R2.L (Z);
102
CC = R2 == 1;
103
IF CC JUMP .Lpower_of_two;
104
105
/* Identities haven't helped either.
106
** Perform the full division process.
107
*/
108
109
P1 = 31; /* Set loop counter */
110
111
[--SP] = (R7:5); /* Push registers R5-R7 */
112
R2 = -R1;
113
[--SP] = R2;
114
R2 = R0 << 1; /* R2 lsw of dividend */
115
R6 = R0 ^ R1; /* Get sign */
116
R5 = R6 >> 31; /* Shift sign to LSB */
117
118
R0 = 0 ; /* Clear msw partial remainder */
119
R2 = R2 | R5; /* Shift quotient bit */
120
R6 = R0 ^ R1; /* Get new quotient bit */
121
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 */
132
R5 = R6 >> 31;
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
136
** tweaked AQ.
137
*/
138
r1 = r3 >> 31;
139
r2 = r2 + r1;
140
cc = bittst(r3,30);
141
r0 = -r2;
142
if !cc r0 = r2;
143
SP += 4;
144
(R7:5)= [SP++]; /* Pop registers R6-R7 */
145
RTS;
146
147
.Lident_return:
148
CC = R1 == 0; /* check for divide by zero => 0x7fffffff */
149
R2 = -1 (X);
150
R2 >>= 1;
151
IF CC JUMP .Ltrue_ident_return;
152
153
CC = R0 == R1; /* check for identical operands => 1 */
154
R2 = 1 (Z);
155
IF CC JUMP .Ltrue_ident_return;
156
157
R2 = R0; /* assume divide by 1 => numerator */
158
/*FALLTHRU*/
159
160
.Ltrue_ident_return:
161
R0 = R2; /* Return an identity value */
162
R2 = -R2;
163
CC = bittst(R3,30);
164
IF CC R0 = R2;
165
.Lzero_return:
166
RTS; /* ...including zero */
167
168
.Lpower_of_two:
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
172
*/
173
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
178
*/
179
180
R2 = R0 >> 31;
181
CC = R1 < 0;
182
IF CC JUMP .Ltrue_ident_return;
183
184
R1.l = SIGNBITS R1;
185
R1 = R1.L (Z);
186
R1 += -30;
187
R0 = LSHIFT R0 by R1.L;
188
r1 = r3 >> 31;
189
r0 = r0 + r1;
190
R2 = -R0; // negate result if necessary
191
CC = bittst(R3,30);
192
IF CC R0 = R2;
193
RTS;
194
195
.Lret_zero:
196
R0 = 0;
197
RTS;
198
199
.size ___divsi3, .-___divsi3
200
201