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