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 $ */
5 * Copyright (c) 1994, 1995 Carnegie-Mellon University.
8 * Author: Chris G. Demetriou
10 * Permission to use, copy, modify and distribute this software and
11 * its documentation is hereby granted, provided that both the copyright
12 * notice and this permission notice appear in all copies of the
13 * software, derivative works or modified versions, and any portions
14 * thereof, and that both notices appear in supporting documentation.
16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
18 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
20 * Carnegie Mellon requests users of this software to return to
22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23 * School of Computer Science
24 * Carnegie Mellon University
25 * Pittsburgh PA 15213-3890
27 * any improvements or extensions that they make and grant Carnegie the
28 * rights to redistribute these changes.
32 * Division and remainder.
34 * The use of m4 is modeled after the sparc code, but the algorithm is
35 * simple binary long division.
37 * Note that the loops could probably benefit from unrolling.
42 * NAME name of function to generate
43 * OP OP=div: t10 / t11 -> t12; OP=rem: t10 % t11 -> t12
44 * S S=true: signed; S=false: unsigned
45 * WORDSIZE total number of bits
56 ifelse(S, `true', `define(NEG, `t4')')
58 #include <machine/asm.h>
60 NESTED(NAME, 0, 0, t9, 0, 0) /* Get the right ra */
70 mov zero, RESULT /* Initialize result to zero */
74 /* Compute sign of result. If either is negative, this is easy. */
75 or A, B, NEG /* not the sign, but... */
76 srl NEG, WORDSIZE - 1, NEG /* rather, or of high bits */
77 blbc NEG, Ldoit /* neither negative? do it! */
80 ` xor A, B, NEG /* THIS is the sign! */
81 ', ` mov A, NEG /* sign follows A. */
83 srl NEG, WORDSIZE - 1, NEG /* make negation the low bit. */
85 srl A, WORDSIZE - 1, I /* is A negative? */
86 blbc I, LnegB /* no. */
87 /* A is negative; flip it. */
88 ifelse(WORDSIZE, `32', `
89 /* top 32 bits may be random junk */
93 srl B, WORDSIZE - 1, I /* is B negative? */
94 blbc I, Ldoit /* no. */
96 /* B is definitely negative, no matter how we got here. */
97 ifelse(WORDSIZE, `32', `
98 /* top 32 bits may be random junk */
104 ifelse(WORDSIZE, `32', `
106 * Clear the top 32 bits of each operand, as they may
107 * sign extension (if negated above), or random junk.
113 /* kill the special cases. */
114 beq B, Ldotrap /* division by zero! */
116 cmpult A, B, CC /* A < B? */
117 /* RESULT is already zero, from above. A is untouched. */
120 cmpeq A, B, CC /* A == B? */
126 * Find out how many bits of zeros are at the beginning of the divisor.
129 ldiq T_0, 1 /* I = 0; BIT = 1<<WORDSIZE-1 */
131 sll T_0, WORDSIZE-1, BIT
133 and B, BIT, CC /* if bit in B is set, done. */
135 addq I, 1, I /* increment I, shift bit */
137 cmplt I, WORDSIZE-1, CC /* if I leaves one bit, done. */
141 beq I, Ldodiv /* If I = 0, divide now. */
142 ldiq T_0, 1 /* BIT = 1<<WORDSIZE-1 */
143 sll T_0, WORDSIZE-1, BIT
146 and A, BIT, CC /* if bit in A is set, done. */
148 subq I, 1, I /* decrement I, shift bit */
150 bne I, LAloop /* If I != 0, loop again */
153 sll B, I, B /* B <<= i */
160 cmoveq CC, T_0, RESULT
174 /* Check to see if we should negate it. */
175 subqv zero, RESULT, T_0
176 cmovlbs NEG, T_0, RESULT
191 ldiq a0, -2 /* This is the signal to SIGFPE! */
194 `', ` mov zero, A /* so that zero will be returned */