xref: /plan9/sys/src/ape/lib/ap/sparc/muldiv.s (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier/*
2*219b2ee8SDavid du Colombier *	ulong
3*219b2ee8SDavid du Colombier *	_udiv(ulong num, ulong den)
4*219b2ee8SDavid du Colombier *	{
5*219b2ee8SDavid du Colombier *		int i;
6*219b2ee8SDavid du Colombier *		ulong quo;
7*219b2ee8SDavid du Colombier *
8*219b2ee8SDavid du Colombier *		if(den == 0)
9*219b2ee8SDavid du Colombier *			*(ulong*)-1 = 0;
10*219b2ee8SDavid du Colombier *		quo = num;
11*219b2ee8SDavid du Colombier *		if(quo > 1<<(32-1))
12*219b2ee8SDavid du Colombier *			quo = 1<<(32-1);
13*219b2ee8SDavid du Colombier *		for(i=0; den<quo; i++)
14*219b2ee8SDavid du Colombier *			den <<= 1;
15*219b2ee8SDavid du Colombier *		quo = 0;
16*219b2ee8SDavid du Colombier *		for(; i>=0; i--) {
17*219b2ee8SDavid du Colombier *			quo <<= 1;
18*219b2ee8SDavid du Colombier *			if(num >= den) {
19*219b2ee8SDavid du Colombier *				num -= den;
20*219b2ee8SDavid du Colombier *				quo |= 1;
21*219b2ee8SDavid du Colombier *			}
22*219b2ee8SDavid du Colombier *			den >>= 1;
23*219b2ee8SDavid du Colombier *		}
24*219b2ee8SDavid du Colombier *		return quo::num;
25*219b2ee8SDavid du Colombier *	}
26*219b2ee8SDavid du Colombier */
27*219b2ee8SDavid du Colombier
28*219b2ee8SDavid du Colombier#define	NOPROF	1
29*219b2ee8SDavid du Colombier
30*219b2ee8SDavid du Colombier/*
31*219b2ee8SDavid du Colombier * calling sequence:
32*219b2ee8SDavid du Colombier *	num: 4(R1)
33*219b2ee8SDavid du Colombier *	den: 8(R1)
34*219b2ee8SDavid du Colombier * returns
35*219b2ee8SDavid du Colombier *	quo: 4(R1)
36*219b2ee8SDavid du Colombier *	rem: 8(R1)
37*219b2ee8SDavid du Colombier */
38*219b2ee8SDavid du ColombierTEXT	_udivmod(SB), NOPROF, $-4
39*219b2ee8SDavid du Colombier
40*219b2ee8SDavid du Colombier	MOVW	$(1<<31), R11
41*219b2ee8SDavid du Colombier	MOVW	4(R1), R13	/* numerator */
42*219b2ee8SDavid du Colombier	MOVW	8(R1), R10	/* denominator */
43*219b2ee8SDavid du Colombier	CMP	R10, R0
44*219b2ee8SDavid du Colombier	BNE	udm20
45*219b2ee8SDavid du Colombier	MOVW	R0, -1(R0)	/* fault -- divide by zero */
46*219b2ee8SDavid du Colombierudm20:
47*219b2ee8SDavid du Colombier	MOVW	R13, R12
48*219b2ee8SDavid du Colombier	CMP	R13, R11
49*219b2ee8SDavid du Colombier	BLEU	udm34
50*219b2ee8SDavid du Colombier	MOVW	R11, R12
51*219b2ee8SDavid du Colombierudm34:
52*219b2ee8SDavid du Colombier	MOVW	R0, R11
53*219b2ee8SDavid du Colombierudm38:
54*219b2ee8SDavid du Colombier	CMP	R10, R12
55*219b2ee8SDavid du Colombier	BCC	udm54
56*219b2ee8SDavid du Colombier	SLL	$1, R10
57*219b2ee8SDavid du Colombier	ADD	$1, R11
58*219b2ee8SDavid du Colombier	BA	udm38
59*219b2ee8SDavid du Colombierudm54:
60*219b2ee8SDavid du Colombier	MOVW	R0, R12
61*219b2ee8SDavid du Colombierudm58:
62*219b2ee8SDavid du Colombier	CMP	R11, R0
63*219b2ee8SDavid du Colombier	BL	udm8c
64*219b2ee8SDavid du Colombier	SLL	$1, R12
65*219b2ee8SDavid du Colombier	CMP	R13, R10
66*219b2ee8SDavid du Colombier	BCS	udm7c
67*219b2ee8SDavid du Colombier	SUB	R10, R13
68*219b2ee8SDavid du Colombier	OR	$1, R12
69*219b2ee8SDavid du Colombierudm7c:
70*219b2ee8SDavid du Colombier	SRL	$1, R10
71*219b2ee8SDavid du Colombier	SUB	$1, R11
72*219b2ee8SDavid du Colombier	BA	udm58
73*219b2ee8SDavid du Colombierudm8c:
74*219b2ee8SDavid du Colombier	MOVW	R12, 4(R1)	/* quotent */
75*219b2ee8SDavid du Colombier	MOVW	R13, 8(R1)	/* remainder */
76*219b2ee8SDavid du Colombier	JMPL	8(R15)
77*219b2ee8SDavid du Colombier
78*219b2ee8SDavid du Colombier/*
79*219b2ee8SDavid du Colombier * save working registers
80*219b2ee8SDavid du Colombier * and bring in num/den parameters
81*219b2ee8SDavid du Colombier */
82*219b2ee8SDavid du ColombierTEXT	_unsarg(SB), NOPROF, $-4
83*219b2ee8SDavid du Colombier	MOVW	R10, 12(R1)
84*219b2ee8SDavid du Colombier	MOVW	R11, 16(R1)
85*219b2ee8SDavid du Colombier	MOVW	R12, 20(R1)
86*219b2ee8SDavid du Colombier	MOVW	R13, 24(R1)
87*219b2ee8SDavid du Colombier
88*219b2ee8SDavid du Colombier	MOVW	R14, 4(R1)
89*219b2ee8SDavid du Colombier	MOVW	32(R1), R14
90*219b2ee8SDavid du Colombier	MOVW	R14, 8(R1)
91*219b2ee8SDavid du Colombier
92*219b2ee8SDavid du Colombier	JMPL	8(R15)
93*219b2ee8SDavid du Colombier
94*219b2ee8SDavid du Colombier/*
95*219b2ee8SDavid du Colombier * save working registers
96*219b2ee8SDavid du Colombier * and bring in absolute value
97*219b2ee8SDavid du Colombier * of num/den parameters
98*219b2ee8SDavid du Colombier */
99*219b2ee8SDavid du ColombierTEXT	_absarg(SB), NOPROF, $-4
100*219b2ee8SDavid du Colombier	MOVW	R10, 12(R1)
101*219b2ee8SDavid du Colombier	MOVW	R11, 16(R1)
102*219b2ee8SDavid du Colombier	MOVW	R12, 20(R1)
103*219b2ee8SDavid du Colombier	MOVW	R13, 24(R1)
104*219b2ee8SDavid du Colombier
105*219b2ee8SDavid du Colombier	MOVW	R14, 28(R1)
106*219b2ee8SDavid du Colombier	CMP	R14, R0
107*219b2ee8SDavid du Colombier	BGE	ab1
108*219b2ee8SDavid du Colombier	SUB	R14, R0, R14
109*219b2ee8SDavid du Colombierab1:
110*219b2ee8SDavid du Colombier	MOVW	R14, 4(R1)	/* numerator */
111*219b2ee8SDavid du Colombier
112*219b2ee8SDavid du Colombier	MOVW	32(R1), R14
113*219b2ee8SDavid du Colombier	CMP	R14, R0
114*219b2ee8SDavid du Colombier	BGE	ab2
115*219b2ee8SDavid du Colombier	SUB	R14, R0, R14
116*219b2ee8SDavid du Colombierab2:
117*219b2ee8SDavid du Colombier	MOVW	R14, 8(R1)	/* denominator */
118*219b2ee8SDavid du Colombier	JMPL	8(R15)
119*219b2ee8SDavid du Colombier
120*219b2ee8SDavid du Colombier/*
121*219b2ee8SDavid du Colombier * restore registers and
122*219b2ee8SDavid du Colombier * return to original caller
123*219b2ee8SDavid du Colombier * answer is in R14
124*219b2ee8SDavid du Colombier */
125*219b2ee8SDavid du ColombierTEXT	_retarg(SB), NOPROF, $-4
126*219b2ee8SDavid du Colombier	MOVW	12(R1), R10
127*219b2ee8SDavid du Colombier	MOVW	16(R1), R11
128*219b2ee8SDavid du Colombier	MOVW	20(R1), R12
129*219b2ee8SDavid du Colombier	MOVW	24(R1), R13
130*219b2ee8SDavid du Colombier	MOVW	0(R1), R15
131*219b2ee8SDavid du Colombier
132*219b2ee8SDavid du Colombier	ADD	$28, R1
133*219b2ee8SDavid du Colombier	JMP	8(R15)		/* back to main sequence */
134*219b2ee8SDavid du Colombier
135*219b2ee8SDavid du Colombier/*
136*219b2ee8SDavid du Colombier * calling sequence
137*219b2ee8SDavid du Colombier *	num: R14
138*219b2ee8SDavid du Colombier *	den: 8(R1)
139*219b2ee8SDavid du Colombier * returns
140*219b2ee8SDavid du Colombier *	quo: R14
141*219b2ee8SDavid du Colombier */
142*219b2ee8SDavid du ColombierTEXT	_div(SB), NOPROF, $-4
143*219b2ee8SDavid du Colombier	SUB	$28, R1		/* 4 reg save, 2 parameters, link */
144*219b2ee8SDavid du Colombier	MOVW	R15, 0(R1)
145*219b2ee8SDavid du Colombier
146*219b2ee8SDavid du Colombier	JMPL	_absarg(SB)
147*219b2ee8SDavid du Colombier	JMPL	_udivmod(SB)
148*219b2ee8SDavid du Colombier	MOVW	4(R1), R14
149*219b2ee8SDavid du Colombier
150*219b2ee8SDavid du Colombier	MOVW	28(R1), R10	/* clean up the sign */
151*219b2ee8SDavid du Colombier	MOVW	32(R1), R11
152*219b2ee8SDavid du Colombier	XORCC	R11, R10, R0
153*219b2ee8SDavid du Colombier	BGE	div1
154*219b2ee8SDavid du Colombier	SUB	R14, R0, R14
155*219b2ee8SDavid du Colombierdiv1:
156*219b2ee8SDavid du Colombier
157*219b2ee8SDavid du Colombier	JMPL	_retarg(SB)
158*219b2ee8SDavid du Colombier	JMP	8(R15)		/* not executed */
159*219b2ee8SDavid du Colombier
160*219b2ee8SDavid du Colombier/*
161*219b2ee8SDavid du Colombier * calling sequence
162*219b2ee8SDavid du Colombier *	num: R14
163*219b2ee8SDavid du Colombier *	den: 8(R1)
164*219b2ee8SDavid du Colombier * returns
165*219b2ee8SDavid du Colombier *	quo: R14
166*219b2ee8SDavid du Colombier */
167*219b2ee8SDavid du ColombierTEXT	_divl(SB), NOPROF, $-4
168*219b2ee8SDavid du Colombier	SUB	$((4+2+1)*4), R1	/* 4 reg save, 2 parameters, link */
169*219b2ee8SDavid du Colombier	MOVW	R15, 0(R1)
170*219b2ee8SDavid du Colombier
171*219b2ee8SDavid du Colombier	JMPL	_unsarg(SB)
172*219b2ee8SDavid du Colombier	JMPL	_udivmod(SB)
173*219b2ee8SDavid du Colombier	MOVW	4(R1), R14
174*219b2ee8SDavid du Colombier
175*219b2ee8SDavid du Colombier	JMPL	_retarg(SB)
176*219b2ee8SDavid du Colombier	JMP	8(R15)		/* not executed */
177*219b2ee8SDavid du Colombier
178*219b2ee8SDavid du Colombier/*
179*219b2ee8SDavid du Colombier * calling sequence
180*219b2ee8SDavid du Colombier *	num: R14
181*219b2ee8SDavid du Colombier *	den: 8(R1)
182*219b2ee8SDavid du Colombier * returns
183*219b2ee8SDavid du Colombier *	rem: R14
184*219b2ee8SDavid du Colombier */
185*219b2ee8SDavid du ColombierTEXT	_mod(SB), NOPROF, $-4
186*219b2ee8SDavid du Colombier	SUB	$28, R1		/* 4 reg save, 2 parameters, link */
187*219b2ee8SDavid du Colombier
188*219b2ee8SDavid du Colombier	MOVW	R15, 0(R1)
189*219b2ee8SDavid du Colombier	JMPL	_absarg(SB)
190*219b2ee8SDavid du Colombier	JMPL	_udivmod(SB)
191*219b2ee8SDavid du Colombier	MOVW	8(R1), R14
192*219b2ee8SDavid du Colombier
193*219b2ee8SDavid du Colombier	MOVW	28(R1), R10	/* clean up the sign */
194*219b2ee8SDavid du Colombier	CMP	R10, R0
195*219b2ee8SDavid du Colombier	BGE	mod1
196*219b2ee8SDavid du Colombier	SUB	R14, R0, R14
197*219b2ee8SDavid du Colombiermod1:
198*219b2ee8SDavid du Colombier
199*219b2ee8SDavid du Colombier	JMPL	_retarg(SB)
200*219b2ee8SDavid du Colombier	JMP	8(R15)		/* not executed */
201*219b2ee8SDavid du Colombier
202*219b2ee8SDavid du Colombier/*
203*219b2ee8SDavid du Colombier * calling sequence
204*219b2ee8SDavid du Colombier *	num: R14
205*219b2ee8SDavid du Colombier *	den: 8(R1)
206*219b2ee8SDavid du Colombier * returns
207*219b2ee8SDavid du Colombier *	rem: R14
208*219b2ee8SDavid du Colombier */
209*219b2ee8SDavid du ColombierTEXT	_modl(SB), NOPROF, $-4
210*219b2ee8SDavid du Colombier	SUB	$28, R1		/* 4 reg save, 2 parameters, link */
211*219b2ee8SDavid du Colombier
212*219b2ee8SDavid du Colombier
213*219b2ee8SDavid du Colombier	MOVW	R15, 0(R1)
214*219b2ee8SDavid du Colombier	JMPL	_unsarg(SB)
215*219b2ee8SDavid du Colombier	JMPL	_udivmod(SB)
216*219b2ee8SDavid du Colombier	MOVW	8(R1), R14
217*219b2ee8SDavid du Colombier
218*219b2ee8SDavid du Colombier	JMPL	_retarg(SB)
219*219b2ee8SDavid du Colombier	JMP	8(R15)		/* not executed */
220*219b2ee8SDavid du Colombier
221*219b2ee8SDavid du Colombier/*
222*219b2ee8SDavid du Colombier * special calling sequence:
223*219b2ee8SDavid du Colombier *	arg1 in R14
224*219b2ee8SDavid du Colombier *	arg2 in 4(R1),    will save R9
225*219b2ee8SDavid du Colombier *	nothing in 0(R1), will save R8
226*219b2ee8SDavid du Colombier * 	result in R14
227*219b2ee8SDavid du Colombier */
228*219b2ee8SDavid du ColombierTEXT	_mul+0(SB), NOPROF, $-4
229*219b2ee8SDavid du Colombier
230*219b2ee8SDavid du Colombier	/*
231*219b2ee8SDavid du Colombier	 * exchange stack and registers
232*219b2ee8SDavid du Colombier	 */
233*219b2ee8SDavid du Colombier	MOVW	R8, 0(R1)
234*219b2ee8SDavid du Colombier	MOVW	4(R1), R8
235*219b2ee8SDavid du Colombier	MOVW	R9, 4(R1)
236*219b2ee8SDavid du Colombier
237*219b2ee8SDavid du Colombier	CMP	R14, R8
238*219b2ee8SDavid du Colombier	BLE	mul1
239*219b2ee8SDavid du Colombier	MOVW	R14, R9
240*219b2ee8SDavid du Colombier	MOVW	R8, R14
241*219b2ee8SDavid du Colombier	MOVW	R9, R8
242*219b2ee8SDavid du Colombiermul1:
243*219b2ee8SDavid du Colombier	MOVW	R14, Y
244*219b2ee8SDavid du Colombier	ANDNCC	$0xFFF, R14, R0
245*219b2ee8SDavid du Colombier	BE	mul_shortway
246*219b2ee8SDavid du Colombier	ANDCC	R0, R0, R9	/* zero partial product and clear N and V cond's */
247*219b2ee8SDavid du Colombier
248*219b2ee8SDavid du Colombier	/* long multiply */
249*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 0 */
250*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 1 */
251*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 2 */
252*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 3 */
253*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 4 */
254*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 5 */
255*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 6 */
256*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 7 */
257*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 8 */
258*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 9 */
259*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 10 */
260*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 11 */
261*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 12 */
262*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 13 */
263*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 14 */
264*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 15 */
265*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 16 */
266*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 17 */
267*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 18 */
268*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 19 */
269*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 20 */
270*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 21 */
271*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 22 */
272*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 23 */
273*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 24 */
274*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 25 */
275*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 26 */
276*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 27 */
277*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 28 */
278*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 29 */
279*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 30 */
280*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 31 */
281*219b2ee8SDavid du Colombier	MULSCC	R0, R9, R9		/* 32; shift only */
282*219b2ee8SDavid du Colombier
283*219b2ee8SDavid du Colombier	MOVW	Y, R14			/* get low part */
284*219b2ee8SDavid du Colombier	BA	mul_return
285*219b2ee8SDavid du Colombier
286*219b2ee8SDavid du Colombiermul_shortway:
287*219b2ee8SDavid du Colombier	ANDCC	R0, R0, R9	/* zero partial product and clear N and V cond's */
288*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/*  0 */
289*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/*  1 */
290*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/*  2 */
291*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/*  3 */
292*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/*  4 */
293*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/*  5 */
294*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/*  6 */
295*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/*  7 */
296*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/*  8 */
297*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/*  9 */
298*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 10 */
299*219b2ee8SDavid du Colombier	MULSCC	R8, R9, R9		/* 11 */
300*219b2ee8SDavid du Colombier	MULSCC	R0, R9, R9		/* 12; shift only */
301*219b2ee8SDavid du Colombier
302*219b2ee8SDavid du Colombier	MOVW	Y, R8
303*219b2ee8SDavid du Colombier	SLL	$12, R9
304*219b2ee8SDavid du Colombier	SRL	$20, R8
305*219b2ee8SDavid du Colombier	OR	R8, R9, R14
306*219b2ee8SDavid du Colombier
307*219b2ee8SDavid du Colombiermul_return:
308*219b2ee8SDavid du Colombier	MOVW	0(R1), R8
309*219b2ee8SDavid du Colombier	MOVW	4(R1), R9
310*219b2ee8SDavid du Colombier	JMP	8(R15)
311