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

📄 bindec.s

📁 VXWORKS源代码
💻 S
📖 第 1 页 / 共 2 页
字号:
/* bindec.s - Motorola 68040 FP binary/decimal conversion routines (EXC) *//* Copyright 1991-1993 Wind River Systems, Inc. */	.data	.globl	_copyright_wind_river	.long	_copyright_wind_river/*modification history--------------------01e,21jul93,kdl  added .text (SPR #2372).01d,23aug92,jcf  changed bxxx to jxx.01c,26may92,rrr  the tree shuffle01b,10jan92,kdl  general cleanup.01b,01jan92,jcf	 reversed order of cmp <reg>,<reg>01a,12aug91,kdl	 changed routine names which begin "Ax_" to aboid		 confusion when converting to lower case reg names.*//*DESCRIPTION	__x_bindecsa 3.4 1/3/91	__x_bindec	Description:		Converts an input in extended precision format		to bcd format.	Input:		a0 points to the input extended precision value		value in memory|  d0 contains the k-factor sign-extended		to 32-bits.  The input may be either normalized,		unnormalized, or denormalized.	Output:	result in the FP_SCR1 space on the stack.	Saves and Modifies: D2-D7,A2,FP2	Algorithm:	A1.	Set RM and size ext|   Set SIGMA = sign of input.		The k-factor is saved for use in d7. Clear the		BINDEC_FLG for separating normalized/denormalized		input.  If input is unnormalized or denormalized,		normalize it.	A2.	Set X = abs(input).	A3.	Compute ILOG.		ILOG is the log base 10 of the input value.  It is		approximated by adding e + 0.f when the original		value is viewed as 2^^e * 1.f in extended precision.		This value is stored in d6.	A4.	Clr INEX bit.		The operation in A3 above may have set INEX2.	A5.	Set ICTR = 0|		ICTR is a flag used in A13.  It must be set before the		loop entry A6.	A6.	Calculate LEN.		LEN is the number of digits to be displayed.  The		k-factor can dictate either the total number of digits,		if it is a positive number, or the number of digits		after the decimal point which are to be included as		significant.  See the 68882 manual for examples.		If LEN is computed to be greater than 17, set OPERR in		USER_FPSR.  LEN is stored in d4.	A7.	Calculate SCALE.		SCALE is equal to 10^ISCALE, where ISCALE is the number		of decimal places needed to insure LEN integer digits		in the output before conversion to bcd. LAMBDA is the		sign of ISCALE, used in A9. Fp1 contains		10^^(abs(ISCALE)) using a rounding mode which is a		function of the original rounding mode and the signs		of ISCALE and X.  A table is given in the code.	A8.	Clr INEX|  Force RZ.		The operation in A3 above may have set INEX2.		RZ mode is forced for the scaling operation to insure		only one rounding error.  The grs bits are collected in		the INEX flag for use in A10.	A9.	Scale X -> Y.		The mantissa is scaled to the desired number of		significant digits.  The excess digits are collected		in INEX2.	A10.	Or in INEX.		If INEX is set, round error occured.  This is		compensated for by 'or-ing' in the INEX2 flag to		the lsb of Y.	A11.	Restore original fpcr|  set size ext.		Perform FINT operation in the user's rounding mode.		Keep the size to extended.	A12.	Calculate YINT = FINT(Y) according to user's rounding		mode.  The FPSP routine __x_sintd0 is used.  The output		is in fp0.	A13.	Check for LEN digits.		If the int operation results in more than LEN digits,		or less than LEN -1 digits, adjust ILOG and repeat from		A6.  This test occurs only on the first pass.  If the		result is exactly 10^LEN, decrement ILOG and divide		the mantissa by 10.	A14.	Convert the mantissa to bcd.		The __x_binstr routine is used to convert the LEN digit		mantissa to bcd in memory.  The input to __x_binstr is		to be a fraction|  i.e. (mantissa)/10^LEN and adjusted		such that the decimal point is to the left of bit 63.		The bcd digits are stored in the correct position in		the final string area in memory.	A15.	Convert the exponent to bcd.		As in A14 above, the exp is converted to bcd and the		digits are stored in the final string.		Test the length of the final exponent string.  If the		length is 4, set operr.	A16.	Write sign bits to final string.	Implementation Notes:	The registers are used as follows:		d0: scratch|  LEN input to __x_binstr		d1: scratch		d2: upper 32-bits of mantissa for __x_binstr		d3: scratch| lower 32-bits of mantissa for __x_binstr		d4: LEN      		d5: LAMBDA/ICTR		d6: ILOG		d7: k-factor		a0: ptr for original operand/final result		a1: scratch pointer		a2: pointer to FP_X|  abs(original value) in ext		fp0: scratch		fp1: scratch		fp2: scratch		F_SCR1:		F_SCR2:		L_SCR1:		L_SCR2:		Copyright (C) Motorola, Inc. 1990			All Rights Reserved	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA	The copyright notice above does not evidence any	actual or intended publication of such source code.BINDEC    idnt    2,1 Motorola 040 Floating Point Software PackageNOMANUAL*/#include "fpsp040E.h"|	section	8| Constants in extended precisionLOG2: 	.long	0x3FFD0000,0x9A209A84,0xFBCFF798,0x00000000LOG2UP1:	.long	0x3FFD0000,0x9A209A84,0xFBCFF799,0x00000000| Constants in single precisionFONE: 	.long	0x3F800000,0x00000000,0x00000000,0x00000000FTWO:	.long	0x40000000,0x00000000,0x00000000,0x00000000FTEN: 	.long	0x41200000,0x00000000,0x00000000,0x00000000F4933:	.long	0x459A2800,0x00000000,0x00000000,0x00000000RBDTBL: 	.byte	0,0,0,0	.byte	3,3,2,2	.byte	3,2,2,3	.byte	2,3,3,2|	xref	__x_binstr|	xref	__x_sintdo|	xref	ptenrn,ptenrm,ptenrp	.globl	__x_bindec	.globl	__x_sc_mul	.text__x_bindec:	moveml	d2-d7/a2,a7@-	fmovemx fp0-fp2,a7@-| A1. Set RM and size ext. Set SIGMA = sign input||     The k-factor is saved for use in d7.  Clear BINDEC_FLG for|     separating  normalized/denormalized input.  If the input|     is a denormalized number, set the BINDEC_FLG memory word|     to signal denorm.  If the input is unnormalized, normalize|     the input and test for denormalized result.|	fmovel	#rm_mode,fpcr	| set RM and ext	movel	a0@,a6@(L_SCR2)	| save exponent for sign check	movel	d0,d7		| move k-factor to d7	clrb	a6@(BINDEC_FLG)	| clr norm/denorm flag	movew	a6@(STAG),d0	| get stag	andiw	#0xe000,d0	| isolate stag bits	jeq 	__A2_str	| if zero, input is norm|| Normalize the denorm|un_de_norm:	movew	a0@,d0	andiw	#0x7fff,d0	| strip sign of normalized exp	movel	a0@(4),d1	movel	a0@(8),d2__x_norm_loop:	subw	#1,d0	lsll	#1,d2	roxll	#1,d1	tstl	d1	jge 	__x_norm_loop|| Test if the normalized input is denormalized|	tstw	d0	jgt 	pos_exp		| if greater than zero, it is a norm	st	a6@(BINDEC_FLG)	| set flag for denormpos_exp:	andiw	#0x7fff,d0	| strip sign of normalized exp	movew	d0,a0@	movel	d1,a0@(4)	movel	d2,a0@(8)| A2. Set X = abs(input).|__A2_str:	movel	a0@,a6@(FP_SCR2) |  move input to work space	movel	a0@(4),a6@(FP_SCR2+4) |  move input to work space	movel	a0@(8),a6@(FP_SCR2+8) |  move input to work space	andil	#0x7fffffff,a6@(FP_SCR2) | create abs(X)| A3. Compute ILOG.|     ILOG is the log base 10 of the input value.  It is approx-|     imated by adding e + 0.f when the original value is viewed|     as 2^^e * 1.f in extended precision.  This value is stored|     in d6.|| Register usage:|	Input/Output|	d0: k-factor/exponent|	d2: x/x|	d3: x/x|	d4: x/x|	d5: x/x|	d6: x/ILOG|	d7: k-factor/Unchanged|	a0: ptr for original operand/final result|	a1: x/x|	a2: x/x|	fp0: x/float(ILOG)|	fp1: x/x|	fp2: x/x|	F_SCR1:x/x|	F_SCR2:Abs(X)/Abs(X) with 0x3fff exponent|	L_SCR1:x/x|	L_SCR2:first word of X packed/Unchanged	tstb	a6@(BINDEC_FLG)	| check for denorm	jeq 	__A3_cont		| if clr, continue with norm	movel	#-4933,d6	| force ILOG = -4933	jra 	__A4_str__A3_cont:	movew	a6@(FP_SCR2),d0	| move exp to d0	movew	#0x3fff,a6@(FP_SCR2) | replace exponent with 0x3fff	fmovex	a6@(FP_SCR2),fp0	| now fp0 has 1.f	subw	#0x3fff,d0	| strip off bias	faddw	d0,fp0		| add in exp	fsubs	FONE,fp0	| subtract off 1.0	fbge	pos_res		| if pos, branch	fmulx	LOG2UP1,fp0	| if neg, mul by LOG2UP1	fmovel	fp0,d6		| put ILOG in d6 as a lword	jra 	__A4_str	| go move out ILOGpos_res:	fmulx	LOG2,fp0	| if pos, mul by LOG2	fmovel	fp0,d6		| put ILOG in d6 as a lword| A4. Clr INEX bit.|     The operation in A3 above may have set INEX2.__A4_str:	fmovel	#0,FPSR		| zero all of fpsr - nothing needed| A5. Set ICTR = 0||     ICTR is a flag used in A13.  It must be set before the|     loop entry A6. The lower word of d5 is used for ICTR.	clrw	d5		| clear ICTR| A6. Calculate LEN.|     LEN is the number of digits to be displayed.  The k-factor|     can dictate either the total number of digits, if it is|     a positive number, or the number of digits after the|     original decimal point which are to be included as|     significant.  See the 68882 manual for examples.|     If LEN is computed to be greater than 17, set OPERR in|     USER_FPSR.  LEN is stored in d4.|| Register usage:|	Input/Output|	d0: exponent/Unchanged|	d2: x/x/scratch|	d3: x/x|	d4: exc picture/LEN|	d5: ICTR/Unchanged|	d6: ILOG/Unchanged|	d7: k-factor/Unchanged|	a0: ptr for original operand/final result|	a1: x/x|	a2: x/x|	fp0: float(ILOG)/Unchanged|	fp1: x/x|	fp2: x/x|	F_SCR1:x/x|	F_SCR2:Abs(X) with 0x3fff exponent/Unchanged|	L_SCR1:x/x|	L_SCR2:first word of X packed/Unchanged__A6_str:	tstl	d7		| branch on sign of k	jle 	k_neg		| if k <= 0, LEN = ILOG + 1 - k	movel	d7,d4		| if k > 0, LEN = k	jra 	len_ck		| skip to LEN checkk_neg:	movel	d6,d4		| first load ILOG to d4	subl	d7,d4		| subtract off k	addql	#1,d4		| add in the 1len_ck:	tstl	d4		| LEN check: branch on sign of LEN	jle 	LEN_ng		| if neg, set LEN = 1	cmpl	#17,d4		| test if LEN > 17	jle 	__A7_str		| if not, forget it	movel	#17,d4		| set max LEN = 17	tstl	d7		| if negative, never set OPERR	jle 	__A7_str	| if positive, continue	orl	#opaop_mask,a6@(USER_FPSR) | set OPERR # AIOP in USER_FPSR	jra 	__A7_str	| finished hereLEN_ng:	moveql	#1,d4		| min LEN is 1| A7. Calculate SCALE.|     SCALE is equal to 10^ISCALE, where ISCALE is the number|     of decimal places needed to insure LEN integer digits|     in the output before conversion to bcd. LAMBDA is the sign|     of ISCALE, used in A9.  Fp1 contains 10^^(abs(ISCALE)) using|     the rounding mode as given in the following table (see|     Coonen, p. 7.23 as ref.|  however, the SCALE variable is|     of opposite sign in __x_bindecsa from Coonen).||	Initial					USE|	fpcr[6:5]	LAMBDA	SIGN(X)		fpcr[6:5]|	----------------------------------------------|	 RN	00	   0	   0		00/0	RN|	 RN	00	   0	   1		00/0	RN|	 RN	00	   1	   0		00/0	RN|	 RN	00	   1	   1		00/0	RN|	 RZ	01	   0	   0		11/3	RP|	 RZ	01	   0	   1		11/3	RP|	 RZ	01	   1	   0		10/2	RM|	 RZ	01	   1	   1		10/2	RM|	 RM	10	   0	   0		11/3	RP|	 RM	10	   0	   1		10/2	RM|	 RM	10	   1	   0		10/2	RM|	 RM	10	   1	   1		11/3	RP|	 RP	11	   0	   0		10/2	RM|	 RP	11	   0	   1		11/3	RP|	 RP	11	   1	   0		11/3	RP|	 RP	11	   1	   1		10/2	RM|| Register usage:|	Input/Output|	d0: exponent/scratch - final is 0|	d2: x/0 or 24 for A9|	d3: x/scratch - offset ptr into __x_PTENRM array|	d4: LEN/Unchanged|	d5: 0/ICTR:LAMBDA|	d6: ILOG/ILOG or k if ((k<=0)#(ILOG<k))|	d7: k-factor/Unchanged|	a0: ptr for original operand/final result|	a1: x/ptr to __x_PTENRM array|	a2: x/x|	fp0: float(ILOG)/Unchanged|	fp1: x/10^ISCALE|	fp2: x/x|	F_SCR1:x/x|	F_SCR2:Abs(X) with 0x3fff exponent/Unchanged|	L_SCR1:x/x|	L_SCR2:first word of X packed/Unchanged__A7_str:	tstl	d7		| test sign of k	jgt 	k_pos		| if pos and > 0, skip this	cmpl	d6,d7		| test ILOG - k	jlt 	k_pos		| if ILOG >= k, skip this	movel	d7,d6		| if ((k<0) # (ILOG < k)) ILOG = kk_pos:	movel	d6,d0		| calc ILOG + 1 - LEN in d0	addql	#1,d0		| add the 1	subl	d4,d0		| sub off LEN	swap	d5		| use upper word of d5 for LAMBDA	clrw	d5		| set it zero initially	clrw	d2		| set up d2 for very small case	tstl	d0		| test sign of ISCALE	jge 	iscale		| if pos, skip next inst	addqw	#1,d5		| if neg, set LAMBDA true	cmpl	#0xffffecd4,d0	| test iscale <= -4908	jgt 	no_inf		| if false, skip rest	addil	#24,d0		| add in 24 to iscale	movel	#24,d2		| put 24 in d2 for A9no_inf:	negl	d0		| and take abs of ISCALEiscale:	fmoves	FONE,fp1	| init fp1 to 1	bfextu	a6@(USER_FPCR){#26:#2},d1 | get initial rmode bits	lslw	#1,d1		| put them in bits 2:1	addw	d5,d1		| add in LAMBDA	lslw	#1,d1		| put them in bits 3:1	tstl	a6@(L_SCR2)	| test sign of original x	jge 	x_pos		/* | if pos, don't set bit 0 */	addql	#1,d1		| if neg, set bit 0x_pos:	lea	RBDTBL,a2	| load rbdtbl base	moveb	a2@(d1),d3	| load d3 with new rmode	lsll	#4,d3		| put bits in proper position	fmovel	d3,fpcr		| load bits into fpu	lsrl	#4,d3		| put bits in proper position	tstb	d3		| decode new rmode for pten table	jne 	not_rn		| if zero, it is RN	lea	__x_PTENRN,a1	| load a1 with RN table base	jra 	rmode		| exit decodenot_rn:	lsrb	#1,d3		| get lsb in carry	jcc 	not_rp		| if carry clear, it is RM	lea	__x_PTENRP,a1	| load a1 with RP table base	jra 	rmode		| exit decodenot_rp:	lea	__x_PTENRM,a1	| load a1 with RM table basermode:	clrl	d3		| clr table indexe_loop:	lsrl	#1,d0		| shift next bit into carry	jcc 	e_next		| if zero, skip the mul	fmulx	a1@(d3),fp1	| mul by 10**(d3_bit_no)e_next:	addl	#12,d3		| inc d3 to next __x_pwrten table entry	tstl	d0		| test if ISCALE is zero	jne 	e_loop		| if not, loop| A8. Clr INEX|  Force RZ.|     The operation in A3 above may have set INEX2.|     RZ mode is forced for the scaling operation to insure|     only one rounding error.  The grs bits are collected in|     the INEX flag for use in A10.|| Register usage:|	Input/Output	fmovel	#0,FPSR		| clr INEX

⌨️ 快捷键说明

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