Fix mdoc(7)/man(7) mix up.
[netbsd-mini2440.git] / lib / libc / arch / alpha / gen / divrem.m4
blob810fde247eb3746492e74357871541ce1dcd2860
1 /* $NetBSD: divrem.m4,v 1.8 2000/06/14 06:49:01 cgd Exp $ */
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@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  */
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  */
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  */
47 define(A, `t10')
48 define(B, `t11')
49 define(RESULT, `t12')
51 define(BIT, `t0')
52 define(I, `t1')
53 define(CC, `t2')
54 define(T_0, `t3')
55 ifelse(S, `true', `define(NEG, `t4')')
57 #include <machine/asm.h>
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     NEG, 32(sp)')
67         stq     A, 40(sp)
68         stq     B, 48(sp)
69         mov     zero, RESULT                    /* Initialize result to zero */
71 ifelse(S, `true',
73         /* Compute sign of result.  If either is negative, this is easy.  */
74         or      A, B, NEG                       /* not the sign, but... */
75         srl     NEG, WORDSIZE - 1, NEG          /* rather, or of high bits */
76         blbc    NEG, Ldoit                      /* neither negative? do it! */
78 ifelse(OP, `div',
79 `       xor     A, B, NEG                       /* THIS is the sign! */
80 ', `    mov     A, NEG                          /* sign follows A. */
82         srl     NEG, WORDSIZE - 1, NEG          /* make negation the low bit. */
84         srl     A, WORDSIZE - 1, I              /* is A negative? */
85         blbc    I, LnegB                        /* no. */
86         /* A is negative; flip it. */
87 ifelse(WORDSIZE, `32', `
88         /* top 32 bits may be random junk */
89         zap     A, 0xf0, A
91         subq    zero, A, A
92         srl     B, WORDSIZE - 1, I              /* is B negative? */
93         blbc    I, Ldoit                        /* no. */
94 LnegB:
95         /* B is definitely negative, no matter how we got here. */
96 ifelse(WORDSIZE, `32', `
97         /* top 32 bits may be random junk */
98         zap     B, 0xf0, B
100         subq    zero, B, B
101 Ldoit:
103 ifelse(WORDSIZE, `32', `
104         /*
105          * Clear the top 32 bits of each operand, as they may
106          * sign extension (if negated above), or random junk.
107          */
108         zap     A, 0xf0, A
109         zap     B, 0xf0, B
112         /* kill the special cases. */
113         beq     B, Ldotrap                      /* division by zero! */
115         cmpult  A, B, CC                        /* A < B? */
116         /* RESULT is already zero, from above.  A is untouched. */
117         bne     CC, Lret_result
119         cmpeq   A, B, CC                        /* A == B? */
120         cmovne  CC, 1, RESULT
121         cmovne  CC, zero, A
122         bne     CC, Lret_result
124         /*
125          * Find out how many bits of zeros are at the beginning of the divisor.
126          */
127 LBbits:
128         ldiq    T_0, 1                          /* I = 0; BIT = 1<<WORDSIZE-1 */
129         mov     zero, I
130         sll     T_0, WORDSIZE-1, BIT
131 LBloop:
132         and     B, BIT, CC                      /* if bit in B is set, done. */
133         bne     CC, LAbits
134         addq    I, 1, I                         /* increment I, shift bit */
135         srl     BIT, 1, BIT
136         cmplt   I, WORDSIZE-1, CC               /* if I leaves one bit, done. */
137         bne     CC, LBloop
139 LAbits:
140         beq     I, Ldodiv                       /* If I = 0, divide now.  */
141         ldiq    T_0, 1                          /* BIT = 1<<WORDSIZE-1 */
142         sll     T_0, WORDSIZE-1, BIT
144 LAloop:
145         and     A, BIT, CC                      /* if bit in A is set, done. */
146         bne     CC, Ldodiv
147         subq    I, 1, I                         /* decrement I, shift bit */
148         srl     BIT, 1, BIT 
149         bne     I, LAloop                       /* If I != 0, loop again */
151 Ldodiv:
152         sll     B, I, B                         /* B <<= i */
153         ldiq    T_0, 1
154         sll     T_0, I, BIT
156 Ldivloop:
157         cmpult  A, B, CC
158         or      RESULT, BIT, T_0
159         cmoveq  CC, T_0, RESULT
160         subq    A, B, T_0
161         cmoveq  CC, T_0, A
162         srl     BIT, 1, BIT     
163         srl     B, 1, B
164         beq     A, Lret_result
165         bne     BIT, Ldivloop
167 Lret_result:
168 ifelse(OP, `div',
169 `', `   mov     A, RESULT
171 ifelse(S, `true',
173         /* Check to see if we should negate it. */
174         subq    zero, RESULT, T_0
175         cmovlbs NEG, T_0, RESULT
178         ldq     BIT, 0(sp)
179         ldq     I, 8(sp)
180         ldq     CC, 16(sp)
181         ldq     T_0, 24(sp)
182 ifelse(S, `true',
183 `       ldq     NEG, 32(sp)')
184         ldq     A, 40(sp)
185         ldq     B, 48(sp)
186         lda     sp, 64(sp)
187         ret     zero, (t9), 1
189 Ldotrap:
190         ldiq    a0, -2                  /* This is the signal to SIGFPE! */
191         call_pal PAL_gentrap
192 ifelse(OP, `div',
193 `', `   mov     zero, A                 /* so that zero will be returned */
195         br      zero, Lret_result
197 END(NAME)