xref: /openbsd/sys/lib/libkern/arch/alpha/__remqu.S (revision 09467b48)
1
2
3/*	$OpenBSD: __remqu.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 * __remqu		name of function to generate
45 * rem		rem=div: t10 / t11 -> t12; rem=rem: t10 % t11 -> t12
46 * false		false=true: signed; false=false: unsigned
47 * 64	total number of bits
48 */
49
50
51
52
53
54
55
56
57
58
59
60#include <machine/asm.h>
61
62LEAF(__remqu, 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	/* kill the special cases. */
77	beq	t11, Ldotrap			/* division by zero! */
78
79	cmpult	t10, t11, t2			/* t10 < t11? */
80	/* t12 is already zero, from above.  t10 is untouched. */
81	bne	t2, Lret_result
82
83	cmpeq	t10, t11, t2			/* t10 == t11? */
84	cmovne	t2, 1, t12
85	cmovne	t2, zero, t10
86	bne	t2, Lret_result
87
88	/*
89	 * Find out how many bits of zeros are at the beginning of the divisor.
90	 */
91LBbits:
92	ldiq	t3, 1				/* t1 = 0; t0 = 1<<64-1 */
93	mov	zero, t1
94	sll	t3, 64-1, t0
95LBloop:
96	and	t11, t0, t2			/* if bit in t11 is set, done. */
97	bne	t2, LAbits
98	addq	t1, 1, t1				/* increment t1,  bit */
99	srl	t0, 1, t0
100	cmplt	t1, 64-1, t2		/* if t1 leaves one bit, done. */
101	bne	t2, LBloop
102
103LAbits:
104	beq	t1, Ldodiv			/* If t1 = 0, divide now.  */
105	ldiq	t3, 1				/* t0 = 1<<64-1 */
106	sll	t3, 64-1, t0
107
108LAloop:
109	and	t10, t0, t2			/* if bit in t10 is set, done. */
110	bne	t2, Ldodiv
111	subq	t1, 1, t1				/* decrement t1,  bit */
112	srl     t0, 1, t0
113	bne	t1, LAloop			/* If t1 != 0, loop again */
114
115Ldodiv:
116	sll	t11, t1, t11				/* t11 <<= i */
117	ldiq	t3, 1
118	sll	t3, t1, t0
119
120Ldivloop:
121	cmpult	t10, t11, t2
122	or	t12, t0, t3
123	cmoveq	t2, t3, t12
124	subq	t10, t11, t3
125	cmoveq	t2, t3, t10
126	srl	t0, 1, t0
127	srl	t11, 1, t11
128	beq	t10, Lret_result
129	bne	t0, Ldivloop
130
131Lret_result:
132	mov	t10, t12
133
134
135
136	ldq	t0, 0(sp)
137	ldq	t1, 8(sp)
138	ldq	t2, 16(sp)
139	ldq	t3, 24(sp)
140
141	ldq	t10, 40(sp)
142	ldq	t11, 48(sp)
143	lda	sp, 64(sp)
144	ret	zero, (t9), 1
145
146Ldotrap:
147	ldiq	a0, -2			/* This is the signal to SIGFPE! */
148	call_pal PAL_gentrap
149	mov	zero, t10			/* so that zero will be returned */
150
151	br	zero, Lret_result
152
153END(__remqu)
154