File:  [MW Coherent from dump] / coherent / b / lib / libc / crt / i8086 / dxadd.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 add and subtract.
/ SMALL model.
/
////////

	.globl	dradd
	.globl	dladd
	.globl	drsub
	.globl	dlsub
	.globl	_fpac_

////////
/
/ dradd - double add (rvalue)
/ dladd - double add (lvalue)
/ drsub - double subtract (rvalue)
/ dlsub - double subtract (lvalue)
/
/ compiler calling sequences:
/	push	<right double argument>
/	push	<left  double argument>
/	call	dradd/drsub
/	add	sp,16
/
/	mov	ax,offset <right double argument>
/	push	ax
/	push	<left  double argument>
/	call	dladd/dlsub
/	add	sp,10
/
/ outputs:
/	_fpac_=result.
/
/ uses:
/	ax, bx, cx, dx
/
////////

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

signs	=	-2			/ signs
ls	=	-2			/ left  sign (byte)
rs	=	-1			/ right sign (byte)
rexp	=	-4			/ right exponant
lexp	=	-6			/ left  exponant
rop	=	-14			/ right op
lop	=	-22			/ left  op
claim	=	22			/ stack claim size

dradd:	push	si			/ standard
	push	di			/ c
	push	bp			/ function
	mov	bp,sp			/ linkage

	lea	bx,r(bp)		/ bx=pointer to right op.
	jmp	L0			/ go to common code.

dladd:	push	si			/ standard
	push	di			/ c
	push	bp			/ function
	mov	bp,sp			/ linkage

	mov	bx,rp(bp)		/ bx=pointer to right op.

L0:	sub	ax,ax			/ ax=sign flip flag.
	jmp	L2			/ go to common code.

drsub:	push	si			/ standard
	push	di			/ c
	push	bp			/ function
	mov	bp,sp			/ linkage.

	lea	bx,r(bp)		/ bx=pointer to right op.
	jmp	L1			/ go to common code.

dlsub:	push	si			/ standard
	push	di			/ c
	push	bp			/ function
	mov	bp,sp			/ linkage.

	mov	bx,rp(bp)		/ bx=pointer to right op.

L1:	mov	ax,$0x8000		/ ax=sign flip flag.

L2:	sub	sp,$claim		/ get some autos.
	mov	signs(bp),$0		/ ls=rs=0
	cld				/ ascending direction.

	add	ax,6(bx)		/ get highest word.
	mov	dx,ax			/ save adjusted sign.
	shl	ax,$1			/ save
	rclb	rs(bp),$1		/ sign in rs.
	stc				/ insert the hidden bit
	rcrb	al,$1			/ into the number.
	movb	rop+6(bp),al		/ save hi byte.
	movb	rop+7(bp),$0		/ clear rest of word for add.
	movb	al,ah			/ al=exponant.
	and	ax,$0xFF		/ mask, test for zero.
	jnz	L3			/ jump if non zero.
	mov	dx,l+6(bp)		/ if right is zero,
	mov	si,l+4(bp)		/ just return
	mov	di,l+2(bp)		/ the left
	mov	ax,l+0(bp)		/ operand to
	jmp	L16			/ the caller.

L3:	mov	rexp(bp),ax		/ save right exponant.
	mov	si,bx			/ si=source.
	lea	di,rop(bp)		/ di=destination.
	movsw				/ copy 3 words from the argument
	movsw				/ list to the
	movsw				/ auto buffer.

	mov	ax,l+6(bp)		/ ax=hi word of left operand
	shl	ax,$1			/ slide
	rclb	ls(bp),$1		/ sign into ls.
	stc				/ insert
	rcrb	al,$1			/ hidden bit.
	movb	lop+6(bp),al		/ save top byte of left.
	movb	lop+7(bp),$0		/ clear rest of word for add.
	movb	al,ah			/ al=exponant.
	and	ax,$0xFF		/ mask, test for zero.
	jnz	L4			/ jump if not zero.
	mov	si,4(bx)		/ just send
	mov	di,2(bx)		/ the right operand
	mov	ax,0(bx)		/ back to
	jmp	L16			/ the caller.

L4:	mov	lexp(bp),ax		/ save left exponant.
	lea	si,l(bp)		/ si=source.
	lea	di,lop(bp)		/ di=destination.
	movsw				/ copy 3 words
	movsw				/ to the
	movsw				/ auto buffer.

	mov	dx,rop+6(bp)		/ assume
	mov	si,rop+4(bp)		/ rop
	mov	di,rop+2(bp)		/ is
	mov	ax,rop+0(bp)		/ smallest.

	mov	cx,lexp(bp)		/ compute the difference
	sub	cx,rexp(bp)		/ of the exponants.
	jge	L5			/ the rop was the smallest.

	mov	bx,rexp(bp)		/ reset
	mov	lexp(bp),bx		/ le.
	mov	bx,signs(bp)		/ swap
	xchgb	bh,bl			/ the
	mov	signs(bp),bx		/ signs.
	neg	cx			/ fix shift count.

	xchg	dx,lop+6(bp)		/ this sequence puts
	xchg	si,lop+4(bp)		/ rop in lop,
	xchg	di,lop+2(bp)		/ and loads the lop
	xchg	ax,lop+0(bp)		/ into the regs.

L5:	cmp	cx,$57			/ too many shifts ??
	jle	L6			/ nope.
	movb	dl,lop+6(bp)		/ load
	mov	si,lop+4(bp)		/ up
	mov	di,lop+2(bp)		/ the
	mov	ax,lop+0(bp)		/ result
	mov	cx,lexp(bp)		/ and its exponant
	movb	bl,ls(bp)		/ and its sign.
	shl	ax,$1			/ shift left one
	rcl	di,$1			/ to properly
	rcl	si,$1			/ position
	rclb	dl,$1			/ hidden bit,
	jmp	L15			/ and go pack up.

L6:	jcxz	L8			/ jump if aligned.

L7:	shr	dx,$1			/ do
	rcr	si,$1			/ the
	rcr	di,$1			/ big
	rcr	ax,$1			/ shift.
	loop	L7			/ do all of them.

L8:	mov	cx,lexp(bp)		/ cx=result exponant.
	mov	bx,signs(bp)		/ bx=signs.
	cmpb	bh,bl			/ are they the same ??
	je	L9			/ yes.
	call	negreg			/ nope, negate.

L9:	add	ax,lop+0(bp)		/ do
	adc	di,lop+2(bp)		/ the
	adc	si,lop+4(bp)		/ big
	adc	dx,lop+6(bp)		/ add
	cmpb	bh,bl			/ same signs.
	jne	L11			/ nope, check for zero.
	testb	dh,$0x01		/ hidden correct.
	jz	L13			/ no, one left will fix it.
	inc	cx			/ correct, fix exponant.
	jmp	L14			/ done.

L11:	or	dx,dx			/ zero ??
	jnz	L12			/ nope.
	or	si,si			/ zero ??
	jnz	L13			/ nope.
	or	di,di			/ zero ??
	jnz	L13			/ nope.
	or	ax,ax			/ zero ??
	jz	L16			/ yes, return 0.0
	jmp	L13			/ no

L12:	jns	L13			/ jump if > 0.0
	xchgb	bh,bl			/ swap signs.
	call	negreg			/ negate.

L13:	shl	ax,$1			/ shift
	rcl	di,$1			/ one
	rcl	si,$1			/ bit
	rclb	dl,$1			/ left
	jc	L14			/ jump if hidden shifted off.
	dec	cx			/ fix exponant
	jmp	L13			/ loop.

L14:	add	ax,$1			/ round
	adc	di,$0			/ up
	adc	si,$0			/ the
	adcb	dl,$0			/ number.
	jnc	L15			/ jump if hidden bit valid.
	shrb	dl,$1			/ the carry
	rcr	si,$1			/ must have
	rcr	di,$1			/ complemented the
	rcr	ax,$1			/ hidden bit.
	inc	cx			/ so shift and fix exp.

L15:	movb	dh,cl			/ put exponant in result.
	shrb	bl,$1			/ sign in carry.
	rcr	dx,$1			/ put
	rcr	si,$1			/ number
	rcr	di,$1			/ back
	rcr	ax,$1			/ together.

L16:	mov	_fpac_+6,dx		/ store
	mov	_fpac_+4,si		/ result
	mov	_fpac_+2,di		/ in
	mov	_fpac_+0,ax		/ _fpac_

L17:	mov	sp,bp			/ do the
	pop	bp			/ standard
	pop	di			/ c
	pop	si			/ function
	ret				/ return.

////////
/
/ negreg - negate the big register.
/
/ this local routine negates dx,si,di,ax
/
////////

negreg:	not	dx			/ complement
	not	si			/ all
	not	di			/ of the
	not	ax			/ bits.

	add	ax,$1			/ then
	adc	di,$0			/ increment
	adc	si,$0			/ the
	adc	dx,$0			/ result

	ret				/ done

unix.superglobalmegacorp.com

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