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