1 /* $NetBSD: divrem.m4,v 1.7 1996/10/17 03:08:04 cgd Exp $ */
2 /* $FreeBSD: src/lib/libc/alpha/gen/divrem.m4,v 1.2.2.1 2000/08/21 21:09:28 jhb Exp $ */
3 /* $DragonFly: src/lib/libc/alpha/gen/Attic/divrem.m4,v 1.2 2003/06/17 04:26:41 dillon Exp $ */
6 * Copyright (c) 1994, 1995 Carnegie-Mellon University.
9 * Author: Chris G. Demetriou
11 * Permission to use, copy, modify and distribute this software and
12 * its documentation is hereby granted, provided that both the copyright
13 * notice and this permission notice appear in all copies of the
14 * software, derivative works or modified versions, and any portions
15 * thereof, and that both notices appear in supporting documentation.
17 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
18 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
19 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
21 * Carnegie Mellon requests users of this software to return to
23 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
24 * School of Computer Science
25 * Carnegie Mellon University
26 * Pittsburgh PA 15213-3890
28 * any improvements or extensions that they make and grant Carnegie the
29 * rights to redistribute these changes.
33 * Division and remainder.
35 * The use of m4 is modeled after the sparc code, but the algorithm is
36 * simple binary long division.
38 * Note that the loops could probably benefit from unrolling.
43 * NAME name of function to generate
44 * OP OP=div: t10 / t11 -> t12; OP=rem: t10 % t11 -> t12
45 * S S=true: signed; S=false: unsigned
46 * WORDSIZE total number of bits
57 ifelse(S, `true', `define(NEG, `t4')')
59 #include <machine/asm.h>
61 NESTED(NAME, 0, 0, t9, 0, 0) /* Get the right ra */
71 mov zero, RESULT /* Initialize result to zero */
75 /* Compute sign of result. If either is negative, this is easy. */
76 or A, B, NEG /* not the sign, but... */
77 srl NEG, WORDSIZE - 1, NEG /* rather, or of high bits */
78 blbc NEG, Ldoit /* neither negative? do it! */
81 ` xor A, B, NEG /* THIS is the sign! */
82 ', ` mov A, NEG /* sign follows A. */
84 srl NEG, WORDSIZE - 1, NEG /* make negation the low bit. */
86 srl A, WORDSIZE - 1, I /* is A negative? */
87 blbc I, LnegB /* no. */
88 /* A is negative; flip it. */
89 ifelse(WORDSIZE, `32', `
90 /* top 32 bits may be random junk */
94 srl B, WORDSIZE - 1, I /* is B negative? */
95 blbc I, Ldoit /* no. */
97 /* B is definitely negative, no matter how we got here. */
98 ifelse(WORDSIZE, `32', `
99 /* top 32 bits may be random junk */
105 ifelse(WORDSIZE, `32', `
107 * Clear the top 32 bits of each operand, as they may
108 * sign extension (if negated above), or random junk.
114 /* kill the special cases. */
115 beq B, Ldotrap /* division by zero! */
117 cmpult A, B, CC /* A < B? */
118 /* RESULT is already zero, from above. A is untouched. */
121 cmpeq A, B, CC /* A == B? */
127 * Find out how many bits of zeros are at the beginning of the divisor.
130 ldiq T_0, 1 /* I = 0; BIT = 1<<WORDSIZE-1 */
132 sll T_0, WORDSIZE-1, BIT
134 and B, BIT, CC /* if bit in B is set, done. */
136 addq I, 1, I /* increment I, shift bit */
138 cmplt I, WORDSIZE-1, CC /* if I leaves one bit, done. */
142 beq I, Ldodiv /* If I = 0, divide now. */
143 ldiq T_0, 1 /* BIT = 1<<WORDSIZE-1 */
144 sll T_0, WORDSIZE-1, BIT
147 and A, BIT, CC /* if bit in A is set, done. */
149 subq I, 1, I /* decrement I, shift bit */
151 bne I, LAloop /* If I != 0, loop again */
154 sll B, I, B /* B <<= i */
161 cmoveq CC, T_0, RESULT
175 /* Check to see if we should negate it. */
176 subqv zero, RESULT, T_0
177 cmovlbs NEG, T_0, RESULT
192 ldiq a0, -2 /* This is the signal to SIGFPE! */
195 `', ` mov zero, A /* so that zero will be returned */