File:  [MW Coherent from dump] / coherent / b / lib / libc / crt / i8086 / dxdiv.s
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:35 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

////////
/
/ Intel 8086 floating point.
/ Double divide.
/ SMALL model.
/
////////

	.globl	drdiv
	.globl	dldiv
	.globl	_fpac_
	.globl	dzero

oerror_:	ret

////////
/
/ drdiv - double divide (rvalue)
/ dldiv - double divide (lvalue)
/
/ compiler calling sequences:
/	push	<right double argument>
/	push	<left  double argument>
/	call	drdiv
/	add	sp,16
/
/	mov	ax,offset <right double argument>
/	push	ax
/	push	<left  double argument>
/	call	dldiv
/	add	sp,10
/
/ outputs:
/	_fpac_ = result.
/
/ see Knuth "Art of Computer Programming" vol 2  for explanation of
/ multiprecision divide.
/
////////

l	=	8	/ left argument
r	=	16	/ right argument (rvalue)
rp	=	16	/ right argument (lvalue)

sign	=	-2
exp	=	-4
q0	=	-6
q1	=	-8
q2	=	-10
q3	=	-12

claim	=	-q3	/ stack claim size

drdiv:
	push	si
	push	di
	push	bp
	mov	bp, sp

	lea	si, r(bp)	/ si = pointer to right op.
	jmp	0f

dldiv:
	push	si
	push	di
	push	bp
	mov	bp, sp

	mov	si, rp(bp)	/ si = pointer to right op.
0:
	sub	sp, $claim

	mov	ax, l+6(bp)
	shl	ax, $1		/ l exp in ah
	jne	0f
retz:
	call	dzero
	jmp	done
0:
	rclb	dl, $1		/ form sign
	mov	bx, 6(si)
	shl	bx, $1		/ r exp in bh
	adcb	dl, $0
	movb	sign(bp), dl
	orb	bh, bh
	je	retinf

	movb	al, ah
	movb	bl, bh
	subb	ah, ah
	movb	bh, ah
	sub	ax, bx
	add	ax, $129
	js	retz		/ exp will only get smaller

	cmp	ax, $257	/ by at most 2
	ja	retinf

	mov	exp(bp), ax
	mov	bx, l+5(bp)	/ set up l fraction (u) for divide loop
	orb	bh, $128	/ implicit bit of hi order word
	mov	cx, l+3(bp)
	mov	di, l+1(bp)
	movb	ah, l(bp)
	subb	al, al
	shr	bx, $1		/ shift r to guarantee valid divide
	rcr	cx, $1
	rcr	di, $1
	rcr	ax, $1
	add	bp, $q0 + 2	/ quotient pushed from here to top
	jmp	0f
overf:
	mov	(bp), $-1	/ q^ = word size - 1
	sub	dx, cx		/ do multiply and subtract using adds
	mov	bx, ax		/ u1
	sub	ax, ax
	add	bx, cx
	adcb	dl, al		/ must keep track of u0 for a while

	sub	bx, 3(si)	/ u1 u2 -= q^ * v2
	sbbb	dl, al
	add	di, 3(si)
	adc	bx, ax
	adcb	dl, al
	js	2f		/ adjust q^ and fall in

	mov	cx, di		/ u2
	mov	di, 1(si)	/ v3
	sub	cx, di		/ u2 u3 -= q^ * v3
	sbb	bx, ax
	sbbb	dl, al
	add	di, _fpac_	/ pick up u3
	adc	cx, ax
	adc	bx, ax
	adcb	dl, al

	movb	ah, (si)	/ u3 u4 -= q^ * v4
	sub	di, ax
	jmp	3f		/ fall in

0:
	sub	bp, $2
	mov	_fpac_, ax	/ u3

	mov	dx, bx		/ u0
	mov	ax, cx		/ u1
	mov	cx, 5(si)
	orb	ch, $128	/ v1
	cmp	dx, cx
	je	overf
	jb	9f
	call	oerror_
9:

	div	cx
	mov	(bp), ax	/ q+2 >= a = q^ >= q
	mov	bx, dx		/ bx = dx = remainder = new u1 <= v1

	mul	3(si)		/ dx ax  =  q^ * v2
	sub	di, ax		/ subtract from  new u1 new u2
	sbb	bx, dx		/          =     new u1 old u3
	jnc	1f		/ ok - no prelim q^ adjust
2:
	dec	(bp)		/ q^ too big
	add	di, 3(si)	/ adjust u1 u2
	adc	bx, cx
	jnc	2b		/ until positive ( at most twice)
1:				/ now q+1 >= q^ >= q
	mov	cx, di		/ shift new u2 = old u3
	mov	di, _fpac_	/ shift new u3 = old u4
				/ (     new u4 = 0)
	mov	ax, 1(si)
	mul	(bp)		/ dx ax = v3 * q^
	sub	di, ax		/ subtract from u2 u3
	sbb	cx, dx
	mov	ax, $0
	sbb	bx, ax
	sbbb	ah, ah
	movb	_fpac_+2, ah	/ save carry into u0

	movb	ah, (si)	/ last word is short 8 bits
	mul	(bp)		/ dx ax = v4 * q^
	neg	ax		/ ax := u4 - ax = 0 - ax
	sbb	di, dx
	movb	dl, _fpac_+2
3:
	sbb	cx, $0
	sbb	bx, $0
	sbbb	dl, $0
	je	1f		/ q = q^ ok ( this is usually the case)

	dec	(bp)		/ else q = q^ - 1
	addb	ah, (si)	/ add v1 v2 v3 v4  to  u1 u2 u3 u4
	adc	di, 1(si)
	adc	cx, 3(si)
	adc	bx, $0
	mov	dx, 5(si)
	orb	dh, $128
	add	bx, dx
1:
	cmp	bp, sp
	jne	0b

	add	bp, $claim
	mov	ax, exp(bp)
	mov	dx, q3(bp)
	mov	di, q2(bp)
	mov	cx, q1(bp)
	mov	bx, q0(bp)
	orb	bh, bh
	js	0f		/ normalized

	dec	ax		/ only need to shift once
	shl	dx, $1
	rcl	di, $1
	rcl	cx, $1
	rcl	bx, $1
0:
	shlb	dl, $1		/ round
	adcb	dh, $0
	adc	di, $0
	adc	cx, $0
	adc	bx, $0
	jnc	0f

	rcr	bx, $1		/ exactly 1/2
	dec	ax
0:
	orb	ah, ah		/ check exp
	js	retz		/ too small
	jne	retinf		/ too big

	movb	_fpac_, dh	/ ok store it
	mov	_fpac_+1, di
	mov	_fpac_+3, cx
	shlb	bh, $1
	movb	ah, sign(bp)
	shr	ax, $1
	rcrb	bh, $1
	mov	_fpac_+5, bx
	movb	_fpac_+7, al
done:
	mov	sp, bp
	pop	bp
	pop	di
	pop	si
	ret
retinf:
	mov	ax, $-1
	mov	_fpac_, ax
	mov	_fpac_+2, ax
	mov	_fpac_+4, ax
	movb	dl, sign(bp)
	shrb	dl, $1
	rcrb	ah, $1
	mov	_fpac_+6, ax
	jmp	done

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.