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