#include <machine/asm.h>
#include <machine/frame.h>
;************************************************************************
; Implement an integer divide routine for 32-bit operands and 32-bit quotient
; and remainder with operand values of zero (divisor only) treated specially.
;
;****************************************************************************
; Definitions
;****************************************************************************
;
; 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