/* $OpenBSD: divu.S,v 1.6 2002/01/04 08:50:30 miod Exp $ */ /* * Copyright 1996 1995 by Open Software Foundation, Inc. * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appears in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ /* * pmk1.1 */ /* * (c) Copyright 1986 HEWLETT-PACKARD COMPANY * * To anyone who acknowledges that this file is provided "AS IS" * without any express or implied warranty: * permission to use, copy, modify, and distribute this file * for any purpose is hereby granted without fee, provided that * the above copyright notice and this notice appears in all * copies, and that the name of Hewlett-Packard Company not be * used in advertising or publicity pertaining to distribution * of the software without specific, written prior permission. * Hewlett-Packard Company makes no representations about the * suitability of this software for any purpose. */ #include /************************************************************************** * Implement an integer divide routine for 32-bit operands and 32-bit quotient * and remainder with operand values of zero (divisor only) treated specially. * ***************************************************************************/ /* * General registers */ gr0 .reg %r0 /* General register zero */ rem .reg %r3 /* remainder and upper part of dividend */ quo .reg %r4 /* quotient and lower part of dividend */ dvr .reg %r5 /* divisor */ tp .reg %r6 /* temp. reg. */ .text /*****************************************************************************/ LEAF_ENTRY(divu) stws,ma rem,4(sp) ; save registers on stack stws,ma quo,4(sp) ; save registers on stack stws,ma dvr,4(sp) ; save registers on stack stws,ma tp,4(sp) ; save registers on stack addi 0,arg2,dvr ; get divisor addi 0,arg1,quo ; get lower dividend addi 0,arg0,rem ; get upper dividend comib,>,n 0,dvr,hibit ; check for dvr >= 2**31 addi -1,gr0,tp ; set V-bit to 1 ds 0,tp,0 add quo,quo,quo ; shift msb bit into carry ds rem,dvr,rem ; 1st divide step, if carry ; out, msb of quotient = 0 addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 2nd divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 3rd divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 4th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 5th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 6th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 7th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 8th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 9th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 10th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 11th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 12th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 13th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 14th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 15th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 16th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 17th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 18th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 19th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 20th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 21st divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 22nd divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 23rd divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 24th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 25th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 26th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 27th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 28th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 29th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 30th divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 31st divide step addc quo,quo,quo ; shift quo with/into carry ds rem,dvr,rem ; 32nd divide step, addc quo,quo,quo ; shift last quo bit into quo addb,>=,n rem,0,finish ; branch if pos. rem add,< dvr,0,0 ; if dvr > 0, add dvr add,tr rem,dvr,rem ; for correcting rem. sub rem,dvr,rem ; else subtract dvr ; ; end of divide routine ; finish stws rem,0(arg3) ; save remainder in high part ; of result stws quo,4(arg3) ; save quotient in low part ; of result ldws,mb -4(sp),tp ; restore registers ldws,mb -4(sp),dvr ; restore registers ldws,mb -4(sp),quo ; restore registers bv 0(rp) ; return ldws,mb -4(sp),rem ; restore registers ; hibit ldo 32(0),tp ; initialize loop counter add quo,quo,quo ; shift high bit into carry loop addc rem,rem,rem ; shift in high bit of dvdl addc,<> 0,0,0 ; if bit shifted out of dvdu, ; want to do subtract comb,<<,n rem,dvr,nosub ; if upper dividend > dvr, sub rem,dvr,rem ; subtract and add,tr dvr,dvr,0 ; set carry nosub addi 0,0,0 ; otherwise clear carry addib,> -1,tp,loop ; inc. counter; finished? addc quo,quo,quo ; shift bit of result into dvdl b finish+4 ; finish up stws rem,0(arg3) ; save remainder in high part ; of result EXIT(divu) .end