1 /* $NetBSD: divu.S,v 1.1.10.3 2004/09/21 13:16:34 skrll Exp $ */
3 /* $OpenBSD: divu.S,v 1.5 2001/03/29 03:58:18 mickey Exp $ */
6 * Copyright 1996 1995 by Open Software Foundation, Inc.
9 * Permission to use, copy, modify, and distribute this software and
10 * its documentation for any purpose and without fee is hereby granted,
11 * provided that the above copyright notice appears in all copies and
12 * that both the copyright notice and this permission notice appear in
13 * supporting documentation.
15 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
17 * FOR A PARTICULAR PURPOSE.
19 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
22 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
23 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30 * (c) Copyright 1986 HEWLETT-PACKARD COMPANY
32 * To anyone who acknowledges that this file is provided "AS IS"
33 * without any express or implied warranty:
34 * permission to use, copy, modify, and distribute this file
35 * for any purpose is hereby granted without fee, provided that
36 * the above copyright notice and this notice appears in all
37 * copies, and that the name of Hewlett-Packard Company not be
38 * used in advertising or publicity pertaining to distribution
39 * of the software without specific, written prior permission.
40 * Hewlett-Packard Company makes no representations about the
41 * suitability of this software for any purpose.
44 #include <machine/asm.h>
46 /**************************************************************************
47 * Implement an integer divide routine for 32-bit operands and 32-bit quotient
48 * and remainder with operand values of zero (divisor only) treated specially.
50 ***************************************************************************/
54 gr0: .reg %r0 /* General register zero */
55 rem: .reg %r3 /* remainder and upper part of dividend */
56 quo: .reg %r4 /* quotient and lower part of dividend */
57 dvr: .reg %r5 /* divisor */
58 tp: .reg %r6 /* temp. reg. */
62 /*****************************************************************************/
64 stws,ma rem,4(%sp) ; save registers on stack
65 stws,ma quo,4(%sp) ; save registers on stack
66 stws,ma dvr,4(%sp) ; save registers on stack
67 stws,ma tp,4(%sp) ; save registers on stack
69 addi 0,%arg2,dvr ; get divisor
70 addi 0,%arg1,quo ; get lower dividend
71 addi 0,%arg0,rem ; get upper dividend
73 comib,>,n 0,dvr,hibit ; check for dvr >= 2**31
74 addi -1,gr0,tp ; set V-bit to 1
76 add quo,quo,quo ; shift msb bit into carry
77 ds rem,dvr,rem ; 1st divide step, if carry
78 ; out, msb of quotient = 0
79 addc quo,quo,quo ; shift quo with/into carry
80 ds rem,dvr,rem ; 2nd divide step
81 addc quo,quo,quo ; shift quo with/into carry
82 ds rem,dvr,rem ; 3rd divide step
83 addc quo,quo,quo ; shift quo with/into carry
84 ds rem,dvr,rem ; 4th divide step
85 addc quo,quo,quo ; shift quo with/into carry
86 ds rem,dvr,rem ; 5th divide step
87 addc quo,quo,quo ; shift quo with/into carry
88 ds rem,dvr,rem ; 6th divide step
89 addc quo,quo,quo ; shift quo with/into carry
90 ds rem,dvr,rem ; 7th divide step
91 addc quo,quo,quo ; shift quo with/into carry
92 ds rem,dvr,rem ; 8th divide step
93 addc quo,quo,quo ; shift quo with/into carry
94 ds rem,dvr,rem ; 9th divide step
95 addc quo,quo,quo ; shift quo with/into carry
96 ds rem,dvr,rem ; 10th divide step
97 addc quo,quo,quo ; shift quo with/into carry
98 ds rem,dvr,rem ; 11th divide step
99 addc quo,quo,quo ; shift quo with/into carry
100 ds rem,dvr,rem ; 12th divide step
101 addc quo,quo,quo ; shift quo with/into carry
102 ds rem,dvr,rem ; 13th divide step
103 addc quo,quo,quo ; shift quo with/into carry
104 ds rem,dvr,rem ; 14th divide step
105 addc quo,quo,quo ; shift quo with/into carry
106 ds rem,dvr,rem ; 15th divide step
107 addc quo,quo,quo ; shift quo with/into carry
108 ds rem,dvr,rem ; 16th divide step
109 addc quo,quo,quo ; shift quo with/into carry
110 ds rem,dvr,rem ; 17th divide step
111 addc quo,quo,quo ; shift quo with/into carry
112 ds rem,dvr,rem ; 18th divide step
113 addc quo,quo,quo ; shift quo with/into carry
114 ds rem,dvr,rem ; 19th divide step
115 addc quo,quo,quo ; shift quo with/into carry
116 ds rem,dvr,rem ; 20th divide step
117 addc quo,quo,quo ; shift quo with/into carry
118 ds rem,dvr,rem ; 21st divide step
119 addc quo,quo,quo ; shift quo with/into carry
120 ds rem,dvr,rem ; 22nd divide step
121 addc quo,quo,quo ; shift quo with/into carry
122 ds rem,dvr,rem ; 23rd divide step
123 addc quo,quo,quo ; shift quo with/into carry
124 ds rem,dvr,rem ; 24th divide step
125 addc quo,quo,quo ; shift quo with/into carry
126 ds rem,dvr,rem ; 25th divide step
127 addc quo,quo,quo ; shift quo with/into carry
128 ds rem,dvr,rem ; 26th divide step
129 addc quo,quo,quo ; shift quo with/into carry
130 ds rem,dvr,rem ; 27th divide step
131 addc quo,quo,quo ; shift quo with/into carry
132 ds rem,dvr,rem ; 28th divide step
133 addc quo,quo,quo ; shift quo with/into carry
134 ds rem,dvr,rem ; 29th divide step
135 addc quo,quo,quo ; shift quo with/into carry
136 ds rem,dvr,rem ; 30th divide step
137 addc quo,quo,quo ; shift quo with/into carry
138 ds rem,dvr,rem ; 31st divide step
139 addc quo,quo,quo ; shift quo with/into carry
140 ds rem,dvr,rem ; 32nd divide step,
141 addc quo,quo,quo ; shift last quo bit into quo
142 addb,>=,n rem,0,finish ; branch if pos. rem
143 add,< dvr,0,0 ; if dvr > 0, add dvr
144 add,tr rem,dvr,rem ; for correcting rem.
145 sub rem,dvr,rem ; else subtract dvr
147 ; end of divide routine
149 finish: stws rem,0(%arg3) ; save remainder in high part
151 stws quo,4(%arg3) ; save quotient in low part
153 ldws,mb -4(%sp),tp ; restore registers
154 ldws,mb -4(%sp),dvr ; restore registers
155 ldws,mb -4(%sp),quo ; restore registers
157 ldws,mb -4(%sp),rem ; restore registers
159 hibit: ldo 32(0),tp ; initialize loop counter
160 add quo,quo,quo ; shift high bit into carry
161 loop: addc rem,rem,rem ; shift in high bit of dvdl
162 addc,<> 0,0,0 ; if bit shifted out of dvdu,
163 ; want to do subtract
164 comb,<<,n rem,dvr,nosub ; if upper dividend > dvr,
165 sub rem,dvr,rem ; subtract and
166 add,tr dvr,dvr,0 ; set carry
167 nosub: addi 0,0,0 ; otherwise clear carry
168 addib,> -1,tp,loop ; inc. counter; finished?
169 addc quo,quo,quo ; shift bit of result into dvdl
170 b finish+4 ; finish up
171 stws rem,0(%arg3) ; save remainder in high part