File:  [MW Coherent from dump] / coherent / b / lib / libc / gen / i8086 / modf.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 C runtime.
/ Split a double into the fraction and whole integer parts.
/ SMALL model.
/
////////

	.globl	modf_
	.globl	_fpac_
	.globl	dpush
	.globl	dladd
	.globl	dlsub
	.globl	dzero

////////
/
/ double
/ modf(d, *ip);
/ double d;
/ double *ip;
/ The "integer part" of the double "d" is stored
/ indirectly through "ip". The remaining fractional part
/ is returned. The return value is always positive.
/
////////

d	=	8			/ Double argument
ip	=	16			/ Whole part pointer.

EXP	=	-2			/ Exponant.
SIGN	=	-4			/ Sign flag.
CLAIM	=	4			/ # of bytes of autos.

modf_:	push	si			/ Standard
	push	di			/ C
	push	bp			/ calling
	mov	bp,sp			/ sequence.

	sub	sp,$CLAIM		/ Claim auto space
	cld				/ Incrementing.

	lea	si,d(bp)		/ Copy the "d" argument
	mov	di,ip(bp)		/ into the
	movsw				/ integer return
	movsw				/ value
	movsw				/ output
	movsw				/ area

	mov	ax,d+6(bp)		/ Get the first word.
	shl	ax,$1			/ Slide off the sign and
	rclb	SIGN(bp),$1		/ save it.
	movb	al,ah			/ Save the exponant
	subb	ah,ah			/ in the ax,
	sub	ax,$0x80		/ unbias it, and
	mov	EXP(bp),ax		/ save it away.

/ If the exponant is <= 0, then there is no
/ integer part. Set the integer part to 0.0, and get set
/ to return the argument as the fractional part.

	jg	0f			/ Jump if exponant > 0

	sub	ax,ax			/ Set 
	mov	di,ip(bp)		/ the
	stosw				/ integer
	stosw				/ part
	stosw				/ to
	stosw				/ zero.

	lea	si,d(bp)		/ Copy
	mov	di,$_fpac_		/ the
	movsw				/ argument
	movsw				/ to
	movsw				/ the
	movsw				/ return area.
	jmp	1f			/ Done.

/ If the exponant is > 56 then there are no fractional bits
/ at all. The integer part is correct. Zero out the floating point
/ return value.

0:	cmp	ax,$56			/ Any fractional bits ?
	jl	0f			/ Yes.

	call	dzero			/ Zero the _fpac_.
	jmp	1f			/ Done.

/ Clear 56-exp bits, starting at the right hand end of the
/ integer value. Clear as many full bytes as you can, then build a
/ mask and get the rest.

0:	neg	ax			/ Figure out
	add	ax,$56			/ 56-exp.
	mov	di,ip(bp)		/ Point di at low end.

0:	sub	ax,$8			/ Is there a full byte ?
	jl	0f			/ Nope.
	movb	(di),$0			/ Clear 8 bits.
	inc	di			/ Move to next byte and
	jmp	0b			/ try again.

0:	add	ax,$8			/ Figure out
	movb	cl,al			/ the
	movb	al,$0xFF		/ correct mask to
	shlb	al,cl			/ clear the rest, and
	andb	(di),al			/ do it.

/ Scoop up the number. Shift the binary point to just above
/ the hidden bit location, then shift it additional times to get
/ it normalized.

	mov	cx,EXP(bp)		/ Get exponant.

	movb	dl,d+6(bp)		/ Scoop
	mov	ax,d+4(bp)		/ up
	mov	si,d+2(bp)		/ the
	mov	di,d+0(bp)		/ number.

0:	shl	di,$1			/ Slide
	rcl	si,$1			/ up
	rcl	ax,$1			/ one
	rclb	dl,$1			/ bit, and
	loop	0b			/ loop until done.

	mov	cx,di			/ Check
	or	cx,si			/ if
	or	cx,ax			/ we
	orb	cl,dl			/ have a zero.
	jnz	0f			/ Nope.
	subb	dh,dh			/ Make all zeros and
	jmp	2f			/ return.

0:	mov	cx,$0x8000		/ ch=exp, cl=0

0:	orb	dl,dl			/ Normalized ?
	js	0f			/ Yes.
	shl	di,$1			/ Shift
	rcl	si,$1			/ up
	rcl	ax,$1			/ one
	rclb	dl,$1			/ place.
	decb	ch			/ Adjust exponant and
	jmp	0b			/ loop.

0:	and	dx,$0x7F		/ dh=0, dl=no hidden bit
	shrb	SIGN(bp),$1		/ carry=sign
	rcr	cx,$1			/ Pull into correct place and
	or	dx,cx			/ pack up double.

2:	mov	_fpac_+6,dx		/ Save
	mov	_fpac_+4,ax		/ into the
	mov	_fpac_+2,si		/ return
	mov	_fpac_+0,di		/ location.

1:	mov	sp,bp			/ Standard
	pop	bp			/ C
	pop	di			/ function
	pop	si			/ return
	ret				/ code.

	.shrd
one:	.byte	0x00, 0x00, 0x00, 0x00
	.byte	0x00, 0x00, 0x80, 0x40

unix.superglobalmegacorp.com

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