xref: /openbsd/sys/lib/libkern/arch/alpha/__divlu.S (revision 73471bf0)
1
2
3/*	$OpenBSD: __divlu.S,v 1.1 2007/11/25 18:25:34 deraadt Exp $	*/
4/*	$NetBSD: divrem.m4,v 1.5 1996/10/17 04:26:25 cgd Exp $	*/
5
6/*
7 * Copyright (c) 1994, 1995 Carnegie-Mellon University.
8 * All rights reserved.
9 *
10 * Author: Chris G. Demetriou
11 *
12 * Permission to use, copy, modify and distribute this software and
13 * its documentation is hereby granted, provided that both the copyright
14 * notice and this permission notice appear in all copies of the
15 * software, derivative works or modified versions, and any portions
16 * thereof, and that both notices appear in supporting documentation.
17 *
18 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
19 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
20 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
21 *
22 * Carnegie Mellon requests users of this software to return to
23 *
24 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
25 *  School of Computer Science
26 *  Carnegie Mellon University
27 *  Pittsburgh PA 15213-3890
28 *
29 * any improvements or extensions that they make and grant Carnegie the
30 * rights to redistribute these changes.
31 */
32
33/*
34 * Division and remainder.
35 *
36 * The use of m4 is modeled after the sparc code, but the algorithm is
37 * simple binary long division.
38 *
39 * Note that the loops could probably benefit from unrolling.
40 */
41
42/*
43 * M4 Parameters
44 * __divlu		name of function to generate
45 * div		div=div: t10 / t11 -> t12; div=rem: t10 % t11 -> t12
46 * false		false=true: signed; false=false: unsigned
47 * 32	total number of bits
48 */
49
50
51
52
53
54
55
56
57
58
59
60#include <machine/asm.h>
61
62LEAF(__divlu, 0)					/* XXX */
63	lda	sp, -64(sp)
64	stq	t0, 0(sp)
65	stq	t1, 8(sp)
66	stq	t2, 16(sp)
67	stq	t3, 24(sp)
68
69	stq	t10, 40(sp)
70	stq	t11, 48(sp)
71	mov	zero, t12			/* Initialize result to zero */
72
73
74
75	/*
76	 * Clear the top 32 bits of each operand, as they may
77	 * sign extension (if negated above), or random junk.
78	 */
79	zap	t10, 0xf0, t10
80	zap	t11, 0xf0, t11
81
82
83	/* kill the special cases. */
84	beq	t11, Ldotrap			/* division by zero! */
85
86	cmpult	t10, t11, t2			/* t10 < t11? */
87	/* t12 is already zero, from above.  t10 is untouched. */
88	bne	t2, Lret_result
89
90	cmpeq	t10, t11, t2			/* t10 == t11? */
91	cmovne	t2, 1, t12
92	cmovne	t2, zero, t10
93	bne	t2, Lret_result
94
95	/*
96	 * Find out how many bits of zeros are at the beginning of the divisor.
97	 */
98LBbits:
99	ldiq	t3, 1				/* t1 = 0; t0 = 1<<32-1 */
100	mov	zero, t1
101	sll	t3, 32-1, t0
102LBloop:
103	and	t11, t0, t2			/* if bit in t11 is set, done. */
104	bne	t2, LAbits
105	addq	t1, 1, t1				/* increment t1,  bit */
106	srl	t0, 1, t0
107	cmplt	t1, 32-1, t2		/* if t1 leaves one bit, done. */
108	bne	t2, LBloop
109
110LAbits:
111	beq	t1, Ldodiv			/* If t1 = 0, divide now.  */
112	ldiq	t3, 1				/* t0 = 1<<32-1 */
113	sll	t3, 32-1, t0
114
115LAloop:
116	and	t10, t0, t2			/* if bit in t10 is set, done. */
117	bne	t2, Ldodiv
118	subq	t1, 1, t1				/* decrement t1,  bit */
119	srl     t0, 1, t0
120	bne	t1, LAloop			/* If t1 != 0, loop again */
121
122Ldodiv:
123	sll	t11, t1, t11				/* t11 <<= i */
124	ldiq	t3, 1
125	sll	t3, t1, t0
126
127Ldivloop:
128	cmpult	t10, t11, t2
129	or	t12, t0, t3
130	cmoveq	t2, t3, t12
131	subq	t10, t11, t3
132	cmoveq	t2, t3, t10
133	srl	t0, 1, t0
134	srl	t11, 1, t11
135	beq	t10, Lret_result
136	bne	t0, Ldivloop
137
138Lret_result:
139
140
141
142	ldq	t0, 0(sp)
143	ldq	t1, 8(sp)
144	ldq	t2, 16(sp)
145	ldq	t3, 24(sp)
146
147	ldq	t10, 40(sp)
148	ldq	t11, 48(sp)
149	lda	sp, 64(sp)
150	ret	zero, (t9), 1
151
152Ldotrap:
153	ldiq	a0, -2			/* This is the signal to SIGFPE! */
154	call_pal PAL_gentrap
155
156	br	zero, Lret_result
157
158END(__divlu)
159