Annotation of sys/lib/libkern/arch/alpha/divrem.m4, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: divrem.m4,v 1.3 1996/10/31 00:43:17 niklas Exp $ */
2: /* $NetBSD: divrem.m4,v 1.5 1996/10/17 04:26:25 cgd Exp $ */
3:
4: /*
5: * Copyright (c) 1994, 1995 Carnegie-Mellon University.
6: * All rights reserved.
7: *
8: * Author: Chris G. Demetriou
9: *
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.
15: *
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.
19: *
20: * Carnegie Mellon requests users of this software to return to
21: *
22: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23: * School of Computer Science
24: * Carnegie Mellon University
25: * Pittsburgh PA 15213-3890
26: *
27: * any improvements or extensions that they make and grant Carnegie the
28: * rights to redistribute these changes.
29: */
30:
31: /*
32: * Division and remainder.
33: *
34: * The use of m4 is modeled after the sparc code, but the algorithm is
35: * simple binary long division.
36: *
37: * Note that the loops could probably benefit from unrolling.
38: */
39:
40: /*
41: * M4 Parameters
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
46: */
47:
48: define(A, `t10')
49: define(B, `t11')
50: define(RESULT, `t12')
51:
52: define(BIT, `t0')
53: define(I, `t1')
54: define(CC, `t2')
55: define(T_0, `t3')
56: ifelse(S, `true', `define(NEG, `t4')')
57:
58: #include <machine/asm.h>
59:
60: LEAF(NAME, 0) /* XXX */
61: lda sp, -64(sp)
62: stq BIT, 0(sp)
63: stq I, 8(sp)
64: stq CC, 16(sp)
65: stq T_0, 24(sp)
66: ifelse(S, `true',
67: ` stq NEG, 32(sp)')
68: stq A, 40(sp)
69: stq B, 48(sp)
70: mov zero, RESULT /* Initialize result to zero */
71:
72: ifelse(S, `true',
73: `
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! */
78:
79: ifelse(OP, `div',
80: ` xor A, B, NEG /* THIS is the sign! */
81: ', ` mov A, NEG /* sign follows A. */
82: ')
83: srl NEG, WORDSIZE - 1, NEG /* make negation the low bit. */
84:
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 */
90: zap A, 0xf0, A
91: ')
92: subq zero, A, A
93: srl B, WORDSIZE - 1, I /* is B negative? */
94: blbc I, Ldoit /* no. */
95: LnegB:
96: /* B is definitely negative, no matter how we got here. */
97: ifelse(WORDSIZE, `32', `
98: /* top 32 bits may be random junk */
99: zap B, 0xf0, B
100: ')
101: subq zero, B, B
102: Ldoit:
103: ')
104: ifelse(WORDSIZE, `32', `
105: /*
106: * Clear the top 32 bits of each operand, as they may
107: * sign extension (if negated above), or random junk.
108: */
109: zap A, 0xf0, A
110: zap B, 0xf0, B
111: ')
112:
113: /* kill the special cases. */
114: beq B, Ldotrap /* division by zero! */
115:
116: cmpult A, B, CC /* A < B? */
117: /* RESULT is already zero, from above. A is untouched. */
118: bne CC, Lret_result
119:
120: cmpeq A, B, CC /* A == B? */
121: cmovne CC, 1, RESULT
122: cmovne CC, zero, A
123: bne CC, Lret_result
124:
125: /*
126: * Find out how many bits of zeros are at the beginning of the divisor.
127: */
128: LBbits:
129: ldiq T_0, 1 /* I = 0; BIT = 1<<WORDSIZE-1 */
130: mov zero, I
131: sll T_0, WORDSIZE-1, BIT
132: LBloop:
133: and B, BIT, CC /* if bit in B is set, done. */
134: bne CC, LAbits
135: addq I, 1, I /* increment I, shift bit */
136: srl BIT, 1, BIT
137: cmplt I, WORDSIZE-1, CC /* if I leaves one bit, done. */
138: bne CC, LBloop
139:
140: LAbits:
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
144:
145: LAloop:
146: and A, BIT, CC /* if bit in A is set, done. */
147: bne CC, Ldodiv
148: subq I, 1, I /* decrement I, shift bit */
149: srl BIT, 1, BIT
150: bne I, LAloop /* If I != 0, loop again */
151:
152: Ldodiv:
153: sll B, I, B /* B <<= i */
154: ldiq T_0, 1
155: sll T_0, I, BIT
156:
157: Ldivloop:
158: cmpult A, B, CC
159: or RESULT, BIT, T_0
160: cmoveq CC, T_0, RESULT
161: subq A, B, T_0
162: cmoveq CC, T_0, A
163: srl BIT, 1, BIT
164: srl B, 1, B
165: beq A, Lret_result
166: bne BIT, Ldivloop
167:
168: Lret_result:
169: ifelse(OP, `div',
170: `', ` mov A, RESULT
171: ')
172: ifelse(S, `true',
173: `
174: /* Check to see if we should negate it. */
175: subqv zero, RESULT, T_0
176: cmovlbs NEG, T_0, RESULT
177: ')
178:
179: ldq BIT, 0(sp)
180: ldq I, 8(sp)
181: ldq CC, 16(sp)
182: ldq T_0, 24(sp)
183: ifelse(S, `true',
184: ` ldq NEG, 32(sp)')
185: ldq A, 40(sp)
186: ldq B, 48(sp)
187: lda sp, 64(sp)
188: ret zero, (t9), 1
189:
190: Ldotrap:
191: ldiq a0, -2 /* This is the signal to SIGFPE! */
192: call_pal PAL_gentrap
193: ifelse(OP, `div',
194: `', ` mov zero, A /* so that zero will be returned */
195: ')
196: br zero, Lret_result
197:
198: END(NAME)
CVSweb