⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atof.s

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 S
字号:
/*	@(#)atof.s	4.1	ULTRIX	7/3/90	*/#include "DEFS.h"/************************************************************************ *									* *			Copyright (c) 1984, 1988 by			* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//************************************************************************ * *		Modification History * * 	Andy Gadsby, 27-Nov-86 * INTL	Added code to allow change of radix character.  * *	Stephen Reilly, 14-May-84 * 003- Change the symbol MVAXI to GFLOAT to reflect the meaning of the *	code *	Stephen Reilly, 04-Apr-84 * 002- Change the symbol MicroVAX to MVAXI * *	Stephen Reilly, 04-Oct-83: * 001 - Added code to handle gfloat conversions for MicroVax * ************************************************************************//*	The range is a limit for the exponent of the converted number *	SLR001*/#ifdef GFLOAT# define range 400#else# define range 100#endif/* *	atof: convert ascii to floating * *	C usage: * *		double atof (s) *		char *s; * *	Register usage: * *		r0-1:	value being developed *		r2:	first section: pointer to the next character *			second section: binary exponent *		r3:	flags *		r4:	first section: the current character *			second section: scratch *		r5:	the decimal exponent *		r6-7:	scratch * *	Flag definitions */	.set	msign,0		# mantissa has negative sign	.set	esign,1		# exponent has negative sign	.set	decpt,2		# decimal point encountered	.align	2# ifdef GFLOATtwo31:	.word	0x4200		# slr001 2**31 in gfloat# elsetwo31:	.word	0x5000		# 2 ** 31 or double# endif	.word	0		# (=2147483648)	.word	0		# in floating-point	.word	0		# (so atof doesn't have to convert it)	.globl	__lc_radix	# INTL international radix character /* *	Entry point */ENTRY(atof)	pushl	r6	pushl	r7/* *	Initialization */	clrl	r3		# All flags start out false	movl	4(ap),r2	# Address the first character	clrl	r5		# Clear starting exponent/* *	Skip leading white space */sk0:	movzbl	(r2)+,r4	# Fetch the next (first) character	cmpb	$' ,r4		# Is it blank?	jeql	sk0		#   ...yes	cmpb	r4,$8		# 8 is lowest of white-space group	jlss	sk1		# Jump if char too low to be white space	cmpb	r4,$13		# 13 is highest of white-space group	jleq	sk0		# Jump if character is white spacesk1:/* *	Check for a sign */	cmpb	$'+,r4		# Positive sign?	jeql	cs1		#   ... yes	cmpb	$'-,r4		# Negative sign?	jneq	cs2		#   ... no	bisb2	$1<msign,r3	# Indicate a negative mantissacs1:	movzbl	(r2)+,r4	# Skip the charactercs2:/* *	Accumulate digits, keeping track of the exponent */	clrq	r0		# Clear the accumulatorad0:	cmpb	r4,$'0		# Do we have a digit?	jlss	ad4		#   ... no, too small	cmpb	r4,$'9	jgtr	ad4		#   ... no, too large/* *	We got a digit.  Accumulate it */	cmpl	r1,$214748364	# Would this digit cause overflow?	jgeq	ad1		#   ... yes/* *	Multiply (r0,r1) by 10.  This is done by developing *	(r0,r1)*2 in (r6,r7), shifting (r0,r1) left three bits, *	and adding the two quadwords. */	ashq	$1,r0,r6	# (r6,r7)=(r0,r1)*2	ashq	$3,r0,r0	# (r0,r1)=(r0,r1)*8	addl2	r6,r0		# Add low halves	adwc	r7,r1		# Add high halves/* *	Add in the digit */	subl2	$'0,r4		# Get the digit value	addl2	r4,r0		# Add it into the accumulator	adwc	$0,r1		# Possible carry into high half	jbr	ad2		# Join common code/* *	Here when the digit won't fit in the accumulator */ad1:	incl	r5		# Ignore the digit, bump exponent/* *	If we have seen a decimal point, decrease the exponent by 1 */ad2:	jbc	$decpt,r3,ad3	# Jump if decimal point not seen	decl	r5		# Decrease exponentad3:/* *	Fetch the next character, back for more */	movzbl	(r2)+,r4	# Fetch	jbr	ad0		# Try again/* *	Not a digit.  Could it be a decimal point? */ad4:	cmpb	r4, __lc_radix	# INTL If it's not a decimal point, either it's	jneq	ad5		#   the end of the number or the start of				#   the exponent.	jbcs	$decpt,r3,ad3	# If it IS a decimal point, we record that				#   we've seen one, and keep collecting				#   digits if it is the first one./* *	Check for an exponent */ad5:	clrl	r6		# Initialize the exponent accumulator	cmpb	r4,$'e		# We allow both lower case e	jeql	ex1		#   ... and ...	cmpb	r4,$'E		#   upper-case E	jneq	ex7/* *	Does the exponent have a sign? */ex1:	movzbl	(r2)+,r4	# Get next character	cmpb	r4,$'+		# Positive sign?	jeql	ex2		#   ... yes ...	cmpb	r4,$'-		# Negative sign?	jneq	ex3		#   ... no ...	bisb2	$1<esign,r3	# Indicate exponent is negativeex2:	movzbl	(r2)+,r4	# Grab the next character/* *	Accumulate exponent digits in r6 */ex3:	cmpb	r4,$'0		# A digit is within the range	jlss	ex4		# '0' through	cmpb	r4,$'9		# '9',	jgtr	ex4		# inclusive.	cmpl	r6,$214748364	# Exponent outrageously large already?	jgeq	ex2		#   ... yes	moval	(r6)[r6],r6	# r6 *= 5	movaw	-'0(r4)[r6],r6	# r6 = r6 * 2 + r4 - '0'	jbr	ex2		# Go 'round againex4:/* *	Now get the final exponent and force it within a reasonable *	range so our scaling loops don't take forever for values *	that will ultimately cause overflow or underflow anyway. *	A tight check on over/underflow will be done by ldexp. */	jbc	$esign,r3,ex5	# Jump if exponent not negative	mnegl	r6,r6		# If sign, negate exponentex5:	addl2	r6,r5		# Add given exponent to calculated exponent	cmpl	r5,$-range	# slr001 Absurdly small?	jgtr	ex6		#   ... no	movl	$-range,r5	# slr001  ... yes, force within limitex6:	cmpl	r5,$range	# slr001 Absurdly large?	jlss	ex7		#   ... no	movl	$range,r5	# slr001  ... yes, force within boundsex7:/* *	Our number has now been reduced to a mantissa and an exponent. *	The mantissa is a 63-bit positive binary integer in r0,r1, *	and the exponent is a signed power of 10 in r5.  The msign *	bit in r3 will be on if the mantissa should ultimately be *	considered negative. * *	We now have to convert it to a standard format floating point *	number.  This will be done by accumulating a binary exponent *	in r2, as we progressively get r5 closer to zero. * *	Don't bother scaling if the mantissa is zero */	movq	r0,r0		# Mantissa zero?	jeql	exit		#   ... yes	clrl	r2		# Initialize binary exponent	tstl	r5		# Which way to scale?	jleq	sd0		# Scale down if decimal exponent <= 0/* *	Scale up by "multiplying" r0,r1 by 10 as many times as necessary, *	as follows: * *	Step 1: Shift r0,r1 right as necessary to ensure that no *	overflow can occur when multiplying. */su0:	cmpl	r1,$429496729	# Compare high word to (2**31)/5	jlss	su1		# Jump out if guaranteed safe	ashq	$-1,r0,r0	# Else shift right one bit	incl	r2		#    bump exponent to compensate	jbr	su0		#    and go back to test again./* *	Step 2: Multiply r0,r1 by 5, by appropriate shifting and *	double-precision addition */su1:	ashq	$2,r0,r6	# (r6,r7) := (r0,r1) * 4	addl2	r6,r0		# Add low-order halves	adwc	r7,r1		#   and high-order halves/* *	Step 3: Increment the binary exponent to take care of the final *	factor of 2, and go back if we still need to scale more. */	incl	r2		# Increment the exponent	sobgtr	r5,su0		#    and back for more (maybe)	jbr	cm0		# Merge to build final value/* *	Scale down.  We must "divide" r0,r1 by 10 as many times *	as needed, as follows: * *	Step 0: Right now, the condition codes reflect the state *	of r5.  If it's zero, we are done. */sd0:	jeql	cm0		# If finished, build final number/* *	Step 1: Shift r0,r1 left until the high-order bit (not counting *	the sign bit) is nonzero, so that the division will preserve *	as much precision as possible. */	tstl	r1		# Is the entire high-order half zero?	jneq	sd2		#   ...no, go shift one bit at a time	ashq	$30,r0,r0	#   ...yes, shift left 30,	subl2	$30,r2		#   decrement the exponent to compensate,				#   and now it's known to be safe to shift				#   at least once more.sd1:	ashq	$1,r0,r0	# Shift (r0,r1) left one, and	decl	r2		#   decrement the exponent to compensatesd2:	jbc	$30,r1,sd1	# If the high-order bit is off, go shift/* *	Step 2: Divide the high-order part of (r0,r1) by 5, *	giving a quotient in r1 and a remainder in r7. */sd3:	movl	r1,r6		# Copy the high-order part	clrl	r7		# Zero-extend to 64 bits	ediv	$5,r6,r1,r7	# Divide (cannot overflow)/* *	Step 3: Divide the low-order part of (r0,r1) by 5, *	using the remainder from step 2 for rounding. *	Note that the result of this computation is unsigned, *	so we have to allow for the fact that an ordinary division *	by 5 could overflow.  We make allowance by dividing by 10, *	multiplying the quotient by 2, and using the remainder *	to adjust the modified quotient. */	addl3	$2,r0,r6	# Dividend is low part of (r0,r1) plus	adwc	$0,r7		#  2 for rounding plus				#  (2**32) * previous remainder	ediv	$10,r6,r0,r6	# r0 := quotient, r6 := remainder.	addl2	r0,r0		# Make r0 result of dividing by 5	cmpl	r6,$5		# If remainder is 5 or greater,	jlss	sd4		#   increment the adjustted quotient.	incl	r0/* *	Step 4: Increment the decimal exponent, decrement the binary *	exponent (to make the division by 5 into a division by 10), *	and back for another iteration. */sd4:	decl	r2		# Binary exponent	aoblss	$0,r5,sd2/* *	We now have the following: * *	r0:	low-order half of a 64-bit integer *	r1:	high-order half of the same 64-bit integer *	r2:	a binary exponent * *	Our final result is the integer represented by (r0,r1) *	multiplied by 2 to the power contained in r2. *	We will transform (r0,r1) into a floating-point value, *	set the sign appropriately, and let ldexp do the *	rest of the work. * *	Step 1: if the high-order bit (excluding the sign) of *	the high-order half (r1) is 1, then we have 63 bits of *	fraction, too many to convert easily.  However, we also *	know we won't need them all, so we will just throw the *	low-order bit away (and adjust the exponent appropriately). */cm0:	jbc	$30,r1,cm1	# jump if no adjustment needed	ashq	$-1,r0,r0	# lose the low-order bit	incl	r2		# increase the exponent to compensate/* *	Step 2: split the 62-bit number in (r0,r1) into two *	31-bit positive quantities */cm1:	ashq	$1,r0,r0	# put the high-order bits in r1				#   and a 0 in the bottom of r0	rotl	$-1,r0,r0	# right-justify the bits in r0				#   moving the 0 from the ashq				#   into the sign bit./* *	Step 3: convert both halves to floating point */#ifdef	GFLOAT	cvtlg	r0,r6		# slr001 low-order part in r6-r7	cvtlg	r1,r0		# slr001 high-order part in r0-r1#else	cvtld	r0,r6		# low-order part in r6-r7	cvtld	r1,r0		# high-order part in r0-r1#endif/* *	Step 4: multiply the high order part by 2**31 and combine them */#ifdef	GFLOAT	mulg2	two31,r0	# slr001 multiply	addg2	r6,r0		# slr001 combine#else	muld2	two31,r0	# multiply	addd2	r6,r0		# combine#endif/* *	Step 5: if appropriate, negate the floating value */	jbc	$msign,r3,cm2	# Jump if mantissa not signed#ifdef	GFLOAT	mnegg	r0,r0		# slr001 If negative, make it so#else	mnegd	r0,r0		# slr001 If negative, make it so#endif/* *	Step 6: call ldexp to complete the job */cm2:	pushl	r2		# Put exponent in parameter list#ifdef	GFLOAT	movg	r0,-(sp)	# slr001    and also mantissa#else	movd	r0,-(sp)	# slr001   and also mantissa#endif	calls	$3,_ldexp	# go combine themexit:	movl	(sp)+,r7	movl	(sp)+,r6	ret

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -