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

📄 doprnt.s

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 S
📖 第 1 页 / 共 4 页
字号:
# define local_frame cry+16					# size of data area to allocate on stack# define t_bexp 16					# the binary exponent is bytes 16-17 of each table entry# define t_dexp 18					# the decimal exponent is bytes 18-19/**	This is a jacket routine that is needed to interface*	doprnt with the gfloat conversion routine*/g_text:		movab	4(sp),r5		# r5 -> addr to receive number		movl	sp,r1			# r1 -> start of common_frame		movad	(ap)+,r0		# r0 -> addr of number to convert		movab	common_frame(sp),sp	# subract common_frame from stack		movl	r5,string_addr(r1)	# store addr to common_frame		movl	$17,sig_digits(r1)	# cheat and say that we need 17		pushr	$1<8			# save reg 8		jsb	ots$$cvt_g_t_r8		# call the convertion routine		popr	$1<8			# restore reg 8		movl	dec_exp(r1),exp		# get computed exponent		movb	sig(r1),sign		# get computed sign		movl	r1,sp			# restore stack		rsb				# return#/** functional description:**	this routine converts a g or h floating point value to a string*	of ascii digits.  it is intended to form the base of a*	language's floating point output conversion routine.*** calling sequence:**	movab	common_frame, r1	; see common_frame definition above*	movl	string_address, string_addr(r1)*	movl	sig_digits, sig_digits(r1)*	movl	user_flags, gflags(r1)*	movl	rt_round, rt_rnd(r1)	;  optional*	movab	value, r0*	jsb	ots$$cvt_x_t_r8		; x is the datatype, g or h*	; outputs are:*	;	offset(r1) - offset*	;	dec_exp(r1) - decimal exponent*	;	sig(r1) - sign** input parameters:**	value				; floating value to be converted*	sig_digits(r1)			; number of significant digits to*					; generate.  if neither v_truncate*					; or v_round_right is set, the*					; value will be rounded to this*					; many digits.*	gflags(r1)			; caller supplied flags:*	    v_truncate = 24		; truncate, don't round.*	    v_round_right = 25		; round "rt_round" digits to*					; right of decimal point.*	rt_rnd(r1)			; number of places to the right*					; of the decimal point to round*					; after.  ignored if v_round_right*					; is clear.** implicit inputs:**	none** output parameters:**	out_string			; string with result.  it will*					; not have valid digits after the*					; requested number of significant*					; digits.*					; the length must be at least:*					; (9*int((sig_digits+8)/9))+2*	offset				; the offset into out_string at*					; which the first significant digit*					; may be found.  it is guaranteed*					; to be either 0 or 1.*	exponent			; the signed decimal exponent of*					; the value, assuming a radix point*					; immediately to the left of the*					; most significant digit.*	sign				; -1 if the value is negative*					; 0 if the value is zero*					; 1 if the value is positive** implicit outputs:**	none** side effects:**	alters registers r0 through r8.**			  this routine does not check the length, it*			  is up to the caller to insure the correct*			  length is present.**//**	.sbttl	ots$$cvt_g_t_r8*//** jsb entry point*/	.globl	ots$$cvt_g_t_r8ots$$cvt_g_t_r8:	movl	r1, r7			# use r7 as base	clrl	dec_exp(r7)		# init decimal exponenttstval_g:	extv	$4, $12, (r0), r1	# test for zero and negative	jneq	1f			# not zero	jbr	zero			# is zero1:	jlss	neg_val_g		# negative? #	movl	$1, sig(r7)		# no, set sign	clrl	sig(r7)	jbr	notres_g		# continueneg_val_g:	extzv	$0, $11, r1, r1		# reserved operand?	jneq	1f			# no #	calls	$0,5f 			# reserved operand	cmpzv	$4, $12, (r0), $0x800	# still reserved?	jneq	tstval_g		# no, try again	jbr	zero			# still reserved, call it zero #5:	.word	^m<> #	movab	w'cvt_handler, (fp)	# enable condition handler #	tstg	(r0)			# force reserved operand fault #	ret				# continue1: #	mnegl	$1, sig(r7)		# set negative sign        	movl	$1, sig(r7)notres_g:	subl2	$local_frame, sp	# allocate local data on stack	movl	sp, r8			# setup pointer to local data area	subl3	$0x400, r1, binexp(r8)	# remove excess from exponent		/* pick up g-floating fraction and store as a left		* normalized unsigned 4-longword integer with the binary		* point between bits 32 & 31 of "binnum+12"		*/	rotl	$16, (r0), r4		# get high fraction	rotl	$16, 4(r0), r3		# get low fraction		/* denormalize by 1 bit to insert		* the hidden bit. 		*/	clrq	binnum+0(r8)		# clear low order bits	clrl	r2	extv	$21, $32, r2, binnum+8(r8)	extzv	$21, $31, r3, r4	bisl3	$0x80000000, r4, binnum+12(r8)	# and set hidden bit	jbr	begsrc		# now convert the value		/* now search the power-of-ten table to find		* an entry close to the value stored		* in binexp & binnum. then divide (or rather		* multiply by the reciprocal) binexp & binnum		* by that table entry to get the resultant		* fraction into the range:		*	 1.0 .gt. (fraction * 2** exponent) .ge. 0.1		* the table search is broken into three pieces: the		* big number exponential search (starting at bigexp), 		* the small number exponential search (starting at		* smlexp), and the middle number search of the linear		* portion of the table (starting at srclin).		*/begsrc:	movaw	tm16, r2		# get 1st adr of linear table	cmpw	t_bexp(r2), binexp(r8)	# compare with entry's bin exp	jgtr	smlexp			# branch for small numbers #	cmpw	<t16-tm16>+t_bexp(r2), binexp(r8)		cmpw	0x290(r2),binexp(r8)					# compare with last linear entry	jgtr	srclin			# branch for linear search		/* the two searches which follow (bigexp & smlexp) find		* the table entry closest to the number stored in		* binexp(r8). this table entry is used to divide (or		* multiply by the reciprocal) binexp & binnum.		*/bigexp:	movaw	t16, r2			# exponential search for big numbers	jbr	bigex1smlexp:	movaw	tsmall, r2		# exponential search for small numbersbigex1:	cvtwl	t_bexp(r2), r0		# get power-of-2 from table	ashl	$-1, r0, r1		# for large, calc: 1.5*entry	jgeq	bigex2			# xfer for big nums (positive exponent)	ashl	$-1, r1, r1		# for small, calc: .75*entry	mnegl	r1, r1bigex2:	addl2	r1, r0			# form .75*entry or 1.5*entry					# r0 now contains value half way					# between this and next entry.	cmpw	r0, binexp(r8)		# is this closest table entry?	jgeq	bigex3			# if yes, xfer #	addl2	$<t1-t0>, r2		# no, go look at next entry		addl2	$0x14,r2	jbr	bigex1bigex3:	bsbw	rmul			# yes, go mul by reciprocal	jbr	begsrc			#   and go try againsrclin:		/* the conversion will take place from the linear (in		* powers of ten) part of the table.		* the decimal_exponent = 1 + log10(2) * (bin_exp - 1). use this		* approximation to get the 1st probe into the table.		* this approx may be 1 small, but no more than that.		* the approx has been tested exhaustively over the		* range -106 .le. bin_exp .le. +108 and always works		* except for bin_exp=1 which has a special code hack.		*/	subl3	$1, binexp(r8), r1	# get (binexp - 1)	jeql	srcl1			# if binexp=+1, return 0 (hack)	mull2	$1233, r1		# 1233 = 4096 * log10(2)	ashl	$-12, r1, r1		# remove the 4096 factor	incl	r1			# final +1srcl1:	 #	mull2	$<t1-t0>, r1		# mul by size of table entry		mull2	$0x14,r1	addl2	r1, r2			# get index*size+tm16 #	addl2	$<t0-tm16>, r2		# get index*size+t0		addl2	$0x140,r2	cmpw	t_bexp(r2), binexp(r8)	# compare exponents	jgtr	found			# xfer if entry .gt. binnum		# the next instruction is commented out. it can not xfer./*	jlss	small			; xfer if entry too small */	cmpl	12(r2), binnum+12(r8)	# compare high-order fraction	jgtru	found	jlssu	small	cmpl	8(r2), binnum+8(r8)	jgtru	found	jlssu	small	cmpl	4(r2), binnum+4(r8)	jgtru	found	jlssu	small	cmpl	0(r2), binnum+0(r8)	# compare low-order fraction	jgtru	foundsmall:	 #	addl2	$<t1-t0>, r2		# advance to next table item		addl2	$0x14,r2		/* final check for debugging. remove these next three		* instructions after all the testing is done. (or		* leave them in-- they don't really hurt.)		*//*	cmpw	t_bexp(r2), binexp(r8)	; final size check*	jgtr	found*	halt				; bad index formula*/found:	movaw	t0, r0			# get table base adr	cmpl	r2, r0	jeql	muldun			# if 0, don't mul by 1.0	bsbw	rmul			# and multiply by reciprocalmuldun:		/* binexp should now contain 0, -1, -2, or -3.		* shift binnum right by that number of places		* in order to reduce binexp to zero, thus		* finally finishing with the binary exponent		* round using the bits shifted off to the right		*/	mnegl	binexp(r8), r0			# find bit $ from binexp	jeql	getdig				# if 0, skip right shift	subl3	$1, r0, r1			# get pos of 1st discarded bit	extzv	r1, $1, binnum+0(r8), r1	# get 1st discarde bit	extv	r0, $32, binnum+0(r8), binnum+0(r8)	extv	r0, $32, binnum+4(r8), binnum+4(r8)	extv	r0, $32, binnum+8(r8), binnum+8(r8)	clrl	binnum+16(r8)			# next extv will get 0's here	extv	r0, $32, binnum+12(r8), binnum+12(r8)/*	clrl	binexp(r8)			; binexp now reduced to zero */	addl2	r1, binnum+0(r8)		# round with 1st discarded bit	adwc	$0, binnum+4(r8)	adwc	$0, binnum+8(r8)	adwc	$0, binnum+12(r8)getdig:	movl	string_addr(r7), r5		# get adr for digit string	addl3	$1, sig_digits(r7), r6		# number of digits wanted	movl	$1, offset(r7)			# initial offset #	movb	$^a/0/, (r5)+			# start out with a zero #		movb	$0x30,(r5)+		/* now mul the binnum fraction by 10**9 in order to		* force 9 digits to the left of the decimal point.		* then convert that 9 digit binary integer to a		* string for output in the final answer. repeat		* the process until enough digits are output.		*//* .macro imul2 i, r, ?l*	emul	i, r, $0, r0*	tstl	r*	jgeq	l*	addl2	i, r1*l:	movl	r0, r*	addl2	r1, 4+r*.endm imul2*/diglup:	clrl	int(r8)			# clear for digits left of bin point		/* multiply 4-long-words by 10**9, propogating carries		* across the long-word boundaries.		*/	movl	$1000000000, r2			# setup 10**9/*	imul2	r2, binnum+12(r8)	*/		emul	r2, binnum+12(r8), $0, r0		tstl	binnum+12(r8)		jgeq	1f		addl2	r2, r11:		movl	r0, binnum+12(r8)		addl2	r1, 4+binnum+12(r8)/*	imul2	r2, binnum+8(r8)		*/		emul	r2, binnum+8(r8), $0, r0		tstl	binnum+8(r8)		jgeq	2f		addl2	r2, r12:		movl	r0, binnum+8(r8)		addl2	r1, 4+binnum+8(r8)	adwc	$0, int(r8)/*	imul2	r2, binnum+4(r8)		*/		emul	r2, binnum+4(r8), $0, r0		tstl	binnum+4(r8)		jgeq	3f		addl2	r2, r13:		movl	r0, binnum+4(r8)		addl2	r1, 4+binnum+4(r8)	adwc	$0, binnum+12(r8)	adwc	$0, int(r8) #	imul2	r2, binnum+0(r8)		emul	r2, binnum+0(r8), $0, r0		tstl	binnum+0(r8)		jgeq	4f		addl2	r2, r14:		movl	r0, binnum+0(r8)		addl2	r1, 4+binnum+0(r8)	adwc	$0, binnum+8(r8)	adwc	$0, binnum+12(r8)	adwc	$0, int(r8)		# convert binary num now left of decimal point into		# 9 packed digits. #	cvtlp	int(r8),$9,packed(r7)	# store 9 packed digits #	movb	-(r5), r4			# save byte #	cvtps	$9,packed(r7),$9,(r5)	# convert to separate #	movb	r4, (r5)+			# restore byte # 	addl2	$9, r5				# advance output string adr 	subl2	$9, r6				# 9 more digits #	jleq	round				# loop for more?		jleq	finis1		cvtlp	int(r8),$9,packed(r7)	# Get the first nine digits		ashp	$9,$9,packed(r7),$0,$19,(r5)						# At the end we will have 18						# digits but we need space for 19 #	movb	-(r5), r4			# save byte	jbr	diglup				# yes/** this routine rounds the value to the given number of significant* digits, unless flag v_truncate is on.  if so, the value is truncated* at the next digit.round:	decl	r6	addl2	r6, r5			# find least significant + 1	jbs	$v_truncate, gflags(r7), finis	# truncate if desired	jbc	$v_round_right, gflags(r7), 5f	# round to right of dec pt?	addl3	dec_exp(r7), rt_rnd(r7), r1	# yes, find it	jlss	finis			# exit if round to zero	cmpl	r1, sig_digits(r7)	# round to right of $ sig digits?	jgeq	5f			# yes, use number of significant					# digits instead.	incl	r1			# finish calculation	addl3	r1, string_addr(r7), r5	# get rounding character address5: #	cmpb	(r5), $^a/5/		# round?		cmpb	(r5), $0x35	jlss	finis			# no, just finish	movl	r5, r0			# save position1: #	cmpb	-(r0), $^a/9/		# if this is a 9...		cmpb	-(r0),$0x39	jlss	2f #	movb	$^a/0/, (r0)		# then it becomes a zero		movb	$30,(r0)	jbr	1b			# and we continue2:	incb	(r0)			# else this is last carry	subl2	string_addr(r7), r0	# do we need to change offset	jgtr	finis			# no	clrl	offset(r7)		# yes, set new offset	incl	dec_exp(r7)		# set new exponent*//*	* all done.*/finis1:	cvtlp	int(r8),$9,packed(r7)	# Get the trailing nine digits	addp4	$9,packed(r7),$19,(r5)	# Add the front nine with the back nine	ashp	$-1,$fltprec+3,(r5),$0,$fltprec+2,12(r5)	# Get the 17 significant digits

⌨️ 快捷键说明

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