xref: /minix3/lib/libc/arch/alpha/gen/divrem.m4 (revision 2fe8fb192fe7e8720e3e7a77f928da545e872a6a)
1*2fe8fb19SBen Gras/* $NetBSD: divrem.m4,v 1.9 2002/01/21 23:40:41 ross Exp $ */
2*2fe8fb19SBen Gras
3*2fe8fb19SBen Gras/*
4*2fe8fb19SBen Gras * Copyright (c) 1994, 1995 Carnegie-Mellon University.
5*2fe8fb19SBen Gras * All rights reserved.
6*2fe8fb19SBen Gras *
7*2fe8fb19SBen Gras * Author: Chris G. Demetriou
8*2fe8fb19SBen Gras *
9*2fe8fb19SBen Gras * Permission to use, copy, modify and distribute this software and
10*2fe8fb19SBen Gras * its documentation is hereby granted, provided that both the copyright
11*2fe8fb19SBen Gras * notice and this permission notice appear in all copies of the
12*2fe8fb19SBen Gras * software, derivative works or modified versions, and any portions
13*2fe8fb19SBen Gras * thereof, and that both notices appear in supporting documentation.
14*2fe8fb19SBen Gras *
15*2fe8fb19SBen Gras * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16*2fe8fb19SBen Gras * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17*2fe8fb19SBen Gras * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18*2fe8fb19SBen Gras *
19*2fe8fb19SBen Gras * Carnegie Mellon requests users of this software to return to
20*2fe8fb19SBen Gras *
21*2fe8fb19SBen Gras *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22*2fe8fb19SBen Gras *  School of Computer Science
23*2fe8fb19SBen Gras *  Carnegie Mellon University
24*2fe8fb19SBen Gras *  Pittsburgh PA 15213-3890
25*2fe8fb19SBen Gras *
26*2fe8fb19SBen Gras * any improvements or extensions that they make and grant Carnegie the
27*2fe8fb19SBen Gras * rights to redistribute these changes.
28*2fe8fb19SBen Gras */
29*2fe8fb19SBen Gras
30*2fe8fb19SBen Gras/*
31*2fe8fb19SBen Gras * Division and remainder.
32*2fe8fb19SBen Gras *
33*2fe8fb19SBen Gras * The use of m4 is modeled after the sparc code, but the algorithm is
34*2fe8fb19SBen Gras * simple binary long division.
35*2fe8fb19SBen Gras *
36*2fe8fb19SBen Gras * Note that the loops could probably benefit from unrolling.
37*2fe8fb19SBen Gras */
38*2fe8fb19SBen Gras
39*2fe8fb19SBen Gras/*
40*2fe8fb19SBen Gras * M4 Parameters
41*2fe8fb19SBen Gras * NAME		name of function to generate
42*2fe8fb19SBen Gras * OP		OP=div: t10 / t11 -> t12; OP=rem: t10 % t11 -> t12
43*2fe8fb19SBen Gras * S		S=true: signed; S=false: unsigned
44*2fe8fb19SBen Gras * WORDSIZE	total number of bits
45*2fe8fb19SBen Gras */
46*2fe8fb19SBen Gras
47*2fe8fb19SBen Grasdefine(A, `t10')
48*2fe8fb19SBen Grasdefine(B, `t11')
49*2fe8fb19SBen Grasdefine(RESULT, `t12')
50*2fe8fb19SBen Gras
51*2fe8fb19SBen Grasdefine(BIT, `t0')
52*2fe8fb19SBen Grasdefine(I, `t1')
53*2fe8fb19SBen Grasdefine(CC, `t2')
54*2fe8fb19SBen Grasdefine(T_0, `t3')
55*2fe8fb19SBen Grasifelse(S, `true', `define(NEG, `t4')')
56*2fe8fb19SBen Gras
57*2fe8fb19SBen Gras#include <machine/asm.h>
58*2fe8fb19SBen Gras
59*2fe8fb19SBen GrasLEAF(NAME, 0)					/* XXX */
60*2fe8fb19SBen Gras	lda	sp, -64(sp)
61*2fe8fb19SBen Gras	stq	BIT, 0(sp)
62*2fe8fb19SBen Gras	stq	I, 8(sp)
63*2fe8fb19SBen Gras	stq	CC, 16(sp)
64*2fe8fb19SBen Gras	stq	T_0, 24(sp)
65*2fe8fb19SBen Grasifelse(S, `true',
66*2fe8fb19SBen Gras`	stq	NEG, 32(sp)')
67*2fe8fb19SBen Gras	stq	A, 40(sp)
68*2fe8fb19SBen Gras	stq	B, 48(sp)
69*2fe8fb19SBen Gras	mov	zero, RESULT			/* Initialize result to zero */
70*2fe8fb19SBen Gras
71*2fe8fb19SBen Grasifelse(S, `true',
72*2fe8fb19SBen Gras`
73*2fe8fb19SBen Gras	/* Compute sign of result.  If either is negative, this is easy.  */
74*2fe8fb19SBen Gras	or	A, B, NEG			/* not the sign, but... */
75*2fe8fb19SBen Gras	srl	NEG, WORDSIZE - 1, NEG		/* rather, or of high bits */
76*2fe8fb19SBen Gras	blbc	NEG, Ldoit			/* neither negative? do it! */
77*2fe8fb19SBen Gras
78*2fe8fb19SBen Grasifelse(OP, `div',
79*2fe8fb19SBen Gras`	xor	A, B, NEG			/* THIS is the sign! */
80*2fe8fb19SBen Gras', `	mov	A, NEG				/* sign follows A. */
81*2fe8fb19SBen Gras')
82*2fe8fb19SBen Gras	srl	NEG, WORDSIZE - 1, NEG		/* make negation the low bit. */
83*2fe8fb19SBen Gras
84*2fe8fb19SBen Gras	srl	A, WORDSIZE - 1, I		/* is A negative? */
85*2fe8fb19SBen Gras	blbc	I, LnegB			/* no. */
86*2fe8fb19SBen Gras	/* A is negative; flip it. */
87*2fe8fb19SBen Grasifelse(WORDSIZE, `32', `
88*2fe8fb19SBen Gras	/* top 32 bits may be random junk */
89*2fe8fb19SBen Gras	zap	A, 0xf0, A
90*2fe8fb19SBen Gras')
91*2fe8fb19SBen Gras	subq	zero, A, A
92*2fe8fb19SBen Gras	srl	B, WORDSIZE - 1, I		/* is B negative? */
93*2fe8fb19SBen Gras	blbc	I, Ldoit			/* no. */
94*2fe8fb19SBen GrasLnegB:
95*2fe8fb19SBen Gras	/* B is definitely negative, no matter how we got here. */
96*2fe8fb19SBen Grasifelse(WORDSIZE, `32', `
97*2fe8fb19SBen Gras	/* top 32 bits may be random junk */
98*2fe8fb19SBen Gras	zap	B, 0xf0, B
99*2fe8fb19SBen Gras')
100*2fe8fb19SBen Gras	subq	zero, B, B
101*2fe8fb19SBen GrasLdoit:
102*2fe8fb19SBen Gras')
103*2fe8fb19SBen Grasifelse(WORDSIZE, `32', `
104*2fe8fb19SBen Gras	/*
105*2fe8fb19SBen Gras	 * Clear the top 32 bits of each operand, as they may
106*2fe8fb19SBen Gras	 * sign extension (if negated above), or random junk.
107*2fe8fb19SBen Gras	 */
108*2fe8fb19SBen Gras	zap	A, 0xf0, A
109*2fe8fb19SBen Gras	zap	B, 0xf0, B
110*2fe8fb19SBen Gras')
111*2fe8fb19SBen Gras
112*2fe8fb19SBen Gras	/* kill the special cases. */
113*2fe8fb19SBen Gras	beq	B, Ldotrap			/* division by zero! */
114*2fe8fb19SBen Gras
115*2fe8fb19SBen Gras	cmpult	A, B, CC			/* A < B? */
116*2fe8fb19SBen Gras	/* RESULT is already zero, from above.  A is untouched. */
117*2fe8fb19SBen Gras	bne	CC, Lret_result
118*2fe8fb19SBen Gras
119*2fe8fb19SBen Gras	cmpeq	A, B, CC			/* A == B? */
120*2fe8fb19SBen Gras	cmovne	CC, 1, RESULT
121*2fe8fb19SBen Gras	cmovne	CC, zero, A
122*2fe8fb19SBen Gras	bne	CC, Lret_result
123*2fe8fb19SBen Gras
124*2fe8fb19SBen Gras	/*
125*2fe8fb19SBen Gras	 * Find out how many bits of zeros are at the beginning of the divisor.
126*2fe8fb19SBen Gras	 */
127*2fe8fb19SBen GrasLBbits:
128*2fe8fb19SBen Gras	ldiq	T_0, 1				/* I = 0; BIT = 1<<WORDSIZE-1 */
129*2fe8fb19SBen Gras	mov	zero, I
130*2fe8fb19SBen Gras	sll	T_0, WORDSIZE-1, BIT
131*2fe8fb19SBen GrasLBloop:
132*2fe8fb19SBen Gras	and	B, BIT, CC			/* if bit in B is set, done. */
133*2fe8fb19SBen Gras	bne	CC, LAbits
134*2fe8fb19SBen Gras	addq	I, 1, I				/* increment I, shift bit */
135*2fe8fb19SBen Gras	srl	BIT, 1, BIT
136*2fe8fb19SBen Gras	cmplt	I, WORDSIZE-1, CC		/* if I leaves one bit, done. */
137*2fe8fb19SBen Gras	bne	CC, LBloop
138*2fe8fb19SBen Gras
139*2fe8fb19SBen GrasLAbits:
140*2fe8fb19SBen Gras	beq	I, Ldodiv			/* If I = 0, divide now.  */
141*2fe8fb19SBen Gras	ldiq	T_0, 1				/* BIT = 1<<WORDSIZE-1 */
142*2fe8fb19SBen Gras	sll	T_0, WORDSIZE-1, BIT
143*2fe8fb19SBen Gras
144*2fe8fb19SBen GrasLAloop:
145*2fe8fb19SBen Gras	and	A, BIT, CC			/* if bit in A is set, done. */
146*2fe8fb19SBen Gras	bne	CC, Ldodiv
147*2fe8fb19SBen Gras	subq	I, 1, I				/* decrement I, shift bit */
148*2fe8fb19SBen Gras	srl     BIT, 1, BIT
149*2fe8fb19SBen Gras	bne	I, LAloop			/* If I != 0, loop again */
150*2fe8fb19SBen Gras
151*2fe8fb19SBen GrasLdodiv:
152*2fe8fb19SBen Gras	sll	B, I, B				/* B <<= i */
153*2fe8fb19SBen Gras	ldiq	T_0, 1
154*2fe8fb19SBen Gras	sll	T_0, I, BIT
155*2fe8fb19SBen Gras
156*2fe8fb19SBen GrasLdivloop:
157*2fe8fb19SBen Gras	cmpult	A, B, CC
158*2fe8fb19SBen Gras	or	RESULT, BIT, T_0
159*2fe8fb19SBen Gras	cmoveq	CC, T_0, RESULT
160*2fe8fb19SBen Gras	subq	A, B, T_0
161*2fe8fb19SBen Gras	cmoveq	CC, T_0, A
162*2fe8fb19SBen Gras	srl	BIT, 1, BIT
163*2fe8fb19SBen Gras	srl	B, 1, B
164*2fe8fb19SBen Gras	beq	A, Lret_result
165*2fe8fb19SBen Gras	bne	BIT, Ldivloop
166*2fe8fb19SBen Gras
167*2fe8fb19SBen GrasLret_result:
168*2fe8fb19SBen Grasifelse(OP, `div',
169*2fe8fb19SBen Gras`', `	mov	A, RESULT
170*2fe8fb19SBen Gras')
171*2fe8fb19SBen Grasifelse(S, `true',
172*2fe8fb19SBen Gras`
173*2fe8fb19SBen Gras	/* Check to see if we should negate it. */
174*2fe8fb19SBen Gras	subq	zero, RESULT, T_0
175*2fe8fb19SBen Gras	cmovlbs	NEG, T_0, RESULT
176*2fe8fb19SBen Gras')
177*2fe8fb19SBen Gras
178*2fe8fb19SBen Gras	ldq	BIT, 0(sp)
179*2fe8fb19SBen Gras	ldq	I, 8(sp)
180*2fe8fb19SBen Gras	ldq	CC, 16(sp)
181*2fe8fb19SBen Gras	ldq	T_0, 24(sp)
182*2fe8fb19SBen Grasifelse(S, `true',
183*2fe8fb19SBen Gras`	ldq	NEG, 32(sp)')
184*2fe8fb19SBen Gras	ldq	A, 40(sp)
185*2fe8fb19SBen Gras	ldq	B, 48(sp)
186*2fe8fb19SBen Gras	lda	sp, 64(sp)
187*2fe8fb19SBen Gras	ret	zero, (t9), 1
188*2fe8fb19SBen Gras
189*2fe8fb19SBen GrasLdotrap:
190*2fe8fb19SBen Gras	ldiq	a0, -2			/* This is the signal to SIGFPE! */
191*2fe8fb19SBen Gras	call_pal PAL_gentrap
192*2fe8fb19SBen Grasifelse(OP, `div',
193*2fe8fb19SBen Gras`', `	mov	zero, A			/* so that zero will be returned */
194*2fe8fb19SBen Gras')
195*2fe8fb19SBen Gras	br	zero, Lret_result
196*2fe8fb19SBen Gras
197*2fe8fb19SBen GrasEND(NAME)
198