.define .dvi2
.sect .text
.sect .rom
.sect .data
.sect .bss
.sect .text


! 16 bits signed and unsigned integer divide and remainder routine
! Bit 0 of a-reg is set iff quotient has to be delivered
! Bit 7 of a-reg is set iff the operands are signed, so:
! Expects in a-reg:	0 if called by rmu 2
!			1 if called by dvu 2
!			128 if called by rmi 2
!			129 if called by dvi 2
! Expects on stack:	divisor
!			dividend
! Yields in de-reg:	quotient or remainder

.dvi2:	pop h
	shld .retadr
	mov h,b
	mov l,c
	shld .bcreg

	sta .areg
	pop b		! bc = divisor
	mov a,b		! trap if divisor = 0
	ora c
	cz eidivz
	pop d		! de = dividend

	mvi h,0
	lda .areg
	ral
	jnc 0f		! jump if unsigned

	mov a,d
	ral
	jnc 1f		! jump if dividend >= 0
	mvi h,129	! indicate dividend is negative
	xra a		! negate dividend
	sub e
	mov e,a
	mvi a,0
	sbb d
	mov d,a
			! de is positive now

1:	mov a,b
	ral
	jc 2f		! jump if divisor < 0
0:	inr h		! indicate negation
	xra a		! negate divisor
	sub c
	mov c,a
	mvi a,0
	sbb b
	mov b,a
			! bc is negative now 

2:	push h		! save h-reg
	lxi h,0		! initial value of remainder
	mvi a,16	! initialize loop counter

3:	push psw	! save loop counter
	dad h		! shift left: hl <- de <- 0
	xchg
	dad h
	xchg
	jnc 4f
	inx h

4:	push h		! save remainder
	dad b		! subtract divisor (add negative)
	jnc 5f
	xthl
	inx d

5:	pop h
	pop psw		! restore loop counter
	dcr a
	jnz 3b

	pop b		! b-reg becomes what once was h-reg
	lda .areg
	rar		! what has to be delivered: quotient or remainder?
	jnc 6f

! for dvi 2 and dvu 2 only:
	mov a,b
	rar
	jc 8f		! jump if divisor and dividend had same sign
	xra a		! negate quotient
	sub e
	mov e,a
	mvi a,0
	sbb d
	mov d,a
	jmp 8f

! for rmi 2 and rmu 2 only:
6:	mov a,b
	ral
	jnc 7f		! negate remainder if dividend was negative
	xra a
	sub l
	mov l,a
	mvi a,0
	sbb h
	mov h,a
7:	mov d,h		! return remainder
	mov e,l

8:	lhld .bcreg
	mov b,h
	mov c,l
	lhld .retadr
	pchl
