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

📄 softfp.s

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 S
📖 第 1 页 / 共 5 页
字号:
/* * Both add and subtract functions come here.  The difference is that * the FUNC field (t8) is zero for adds. */func_add:	lw	v1,add_fmt_tab(v0)	j	v1	.rdataadd_fmt_tab:	.word	add_s:1, add_d:1, add_e:1, add_q:1, illfpinst:1	.text/* * Add (and subtract) single RD = RS + RT (or RD = RS - RT).  Again the FUNC * field (t8) is zero for adds. */.globl	add_sadd_s:	/*	 * Break out the operands into their fields (sign,exp,fraction) and	 * handle NaN operands by calling {rs,rt}breakout_s() .	 */	li	t9,C1_FMT_SINGLE*4	li	v1,1	jal	rs_breakout_s	jal	rt_breakout_s		beq	t8,zero,1f	# if doing a subtract then negate RT	lui	v0,SIGNBIT>>16	xor	t4,v01:	# Check for addition of infinities, and produce the correct action if so	bne	t1,SEXP_INF,5f	# is RS an infinity?				# RS is an infinity	bne	t5,SEXP_INF,4f	# is RT also an infinity?				# RT is an infinity	beq	t0,t4,3f	# do the infinities have the same sign?	/*	 * The infinities do NOT have the same sign thus this is an invalid	 * operation for addition so set the invalid exception in the fpc_csr	 * (a3) and setup the result depending if the enable for the invalid	 * exception is set.	 */	or	a3,INVALID_EXC	and	v0,a3,INVALID_ENABLE	beq	v0,zero,2f	/*	 * The invalid trap was enabled so signal a SIGFPE and leave the	 * result register unmodified.	 */	li	v0,SIGFPE	jal	post_signal	li	v0,1	b	store_fpc_csr	/*	 * The invalid trap was NOT enabled so the result is a quiet NaN.	 * So use the default quiet NaN and exit softfp().	 */2:	li	t2,SQUIETNAN_LEAST	move	v0,zero	b	rd_1w	/*	 * This is just a normal infinity + infinity so the result is just	 * an infinity with the sign of the operands.	 */3:	move	t2,t0	sll	t1,SEXP_SHIFT	or	t2,t1	move	v0,zero	b	rd_1w	/*	 * This is infinity + x , where RS is the infinity so the result is	 * just RS (the infinity).	 */4:	move	t2,t0	sll	t1,SEXP_SHIFT	or	t2,t1	move	v0,zero	b	rd_1w	/*	 * Check RT for an infinity value.  At this point it is know that RS	 * is not an infinity.  If RT is an infinity it will be the result.	 */5:	bne	t5,SEXP_INF,6f	move	t2,t4	sll	t5,SEXP_SHIFT	or	t2,t5	move	v0,zero	b	rd_1w6:	# Check for the addition of zeros and produce the correct action if so	bne	t1,zero,3f	# check RS for a zero value (first the exp)	bne	t2,zero,3f	# then the fraction				# Now RS is known to be zero	bne	t5,zero,2f	# check RT for a zero value (first the exp)	bne	t6,zero,2f	# then the fraction	/*	 * Now RS and RT are known to be zeroes so set the correct result	 * according to the rounding mode (in the fpc_csr) and exit.	 */	and	v0,a3,CSR_RM_MASK	# get the rounding mode	bne	v0,CSR_RM_RMI,1f	# check for round to - infinity	or	t2,t0,t4		# set the result and exit, for round to	move	v0,zero			#  - infinity the zero result is the	b	rd_1w			#  and of the operand's signs1:	and	t2,t0,t4		# set the result and exit, for other	move	v0,zero			#  rounding modes the zero result is the	b	rd_1w			#  or of the operand's signs	# RS is a zero and RT is non-zero so the result is RT2:	move	t2,t4	sll	t5,SEXP_SHIFT	or	t2,t5	or	t2,t6	move	v0,zero	b	rd_1w	# RS is now known not to be zero so check RT for a zero value.3:	bne	t5,zero,4f	# check RT for a zero value (first the exp)	bne	t6,zero,4f	# then the fraction	or	t2,t0		# RT is a zero so the result is RS	sll	t1,SEXP_SHIFT	or	t2,t1	move	v0,zero	b	rd_1w4:	/*	 * Now that all the NaN, infinity and zero cases have been taken care	 * of what is left are values that can be added.  So get all values	 * into a format that can be added.  For normalized numbers set the	 * implied one and remove the exponent bias.  For denormalized numbers	 * convert to normalized numbers with the correct exponent.	 */	bne	t1,zero,1f	# check for RS being denormalized	li	t1,-SEXP_BIAS+1	# set denorm's exponent	jal	rs_renorm_s	# normalize it	b	2f1:	subu	t1,SEXP_BIAS	# if RS is not denormalized then remove the	or	t2,SIMP_1BIT	#  exponent bias, and set the implied 1 bit2:	bne	t5,zero,3f	# check for RT being denormalized	li	t5,-SEXP_BIAS+1	# set denorm's exponent	jal	rt_renorm_s	# normalize it	b	4f3:	subu	t5,SEXP_BIAS	# if RT is not denormalized then remove the	or	t6,SIMP_1BIT	#  exponent bias, and set the implied 1 bit4:	/*	 * If the two values are the same except the sign return the correct	 * zero according to the rounding mode.	 */	beq	t0,t4,2f		# if the sign's are the same continue	bne	t1,t5,2f		# if the exp's are not the same continue	bne	t2,t6,2f		# if the fraction's are not the					#  same continue	and	v0,a3,CSR_RM_MASK	# get the rounding mode	bne	v0,CSR_RM_RMI,1f	# check for round to - infinity	or	t2,t0,t4		# set the result and exit, for round to					#  - infinity the zero result is the	move	v0,zero			#  and of the operand's signs	b	rd_1w1:	and	t2,t0,t4		# set the result and exit, for other					#  rounding modes the zero result is the	move	v0,zero			#  or of the operand's signs	b	rd_1w2:	subu	v1,t1,t5		# find the difference of the exponents	move	v0,v1			#  in (v1) and the absolute value of	bge	v1,zero,1f		#  the difference in (v0)	negu	v01:	ble	v0,SFRAC_BITS+2,2f	# is the difference is greater than the					#  number of bits of precision?	li	t8,STKBIT		# set the sticky register	bge	v1,zero,1f	# result is RT added with a sticky bit (for RS)	move	t1,t5			# result exponent will be RT's exponent	move	t2,zero	b	4f1:	# the result is RS added with a sticky bit (for RT)	move	t6,zero	b	4f2:	move	t8,zero			# clear the sticky register	/*	 * If the exponent difference is greater than zero shift the smaller	 * value right by the exponent difference to align the binary point	 * before the addition.  Also select the exponent of the result to	 * be the largest exponent of the two values.  The result exponent is	 * left in (t1) so only if RS is to be shifted does RT's exponent	 * need to be moved into (t1).	 */	beq	v0,zero,4f		# if the exp diff is zero then no shift	bgt	v1,zero,3f		# if the exp diff > 0 shift RT	move	t1,t5			# result exponent will be RT's exponent	# Shift the fraction value of RS by < 32 (the right shift amount (v0))	negu	v1,v0			# the left shift amount which is 32	addu	v1,32			#  minus right shift amount (v1)	srl	t8,v0			# shift the sticky register	sll	t9,t2,v1	or	t8,t9	srl	t2,v0			# shift the fraction	b	4f3:	# Shift the fraction value of RT by < 32 (the right shift amount (v0))	negu	v1,v0			# the left shift amount which is 32	addu	v1,32			#  minus right shift amount (v1)	srl	t8,v0			# shift the sticky register	sll	t9,t6,v1	or	t8,t9	srl	t6,v0			# shift the fraction4:	/*	 * Now if the signs are the same add the two fractions, else if the	 * signs are different then subtract the smaller fraction from the	 * larger fraction and the result's sign will be the sign of the	 * larger fraction.	 */	bne	t0,t4,1f		# if the signs not the same subtract	# Add the fractions	addu	t2,t6			# add fraction words	b	norm_s1:	/*	 * Subtract the smaller fraction from the larger fraction and set the	 * sign of the result to the sign of the larger fraction.	 */	blt	t2,t6,3f		# determine the smaller fraction					#  Note the case where they were equal					#  has already been taken care of1:	/*	 * RT is smaller so subtract RT from RS and use RS's sign as the sign	 * of the result (the sign is already in the correct place (t0)).	 */	sltu	t9,zero,t8		# set barrow out for sticky register	subu	t8,zero,t8	# subtract least signifiant fraction words	bne	t9,zero,2f		# see if there is a barrow in	# no barrow in to be subtracted out	subu	t2,t2,t6		# subtract fractions	b	norm_s2:	# barrow in to be subtracted out	subu	t2,t2,t6		# subtract least fractions	subu	t2,1			# subtract barrow in	b	norm_s3:	/*	 * RS is smaller so subtract RS from RT and use RT's sign as the sign	 * of the result.	 */	move	t0,t4			# use RT's sign as the sign of result	sltu	t9,zero,t8		# set barrow out for sticky register	subu	t8,zero,t8	# subtract least signifiant fraction words	bne	t9,zero,1f		# see if there is a barrow in	# no barrow in to be subtracted out	subu	t2,t6,t2		# subtract least fractions	b	norm_s1:	# barrow in to be subtracted out	subu	t2,t6,t2		# subtract least fractions	subu	t2,1			# subtract barrow in	b	norm_s/* * Add (and subtract) double RD = RS + RT (or RD = RS - RT).  Again the FUNC * field (t8) is zero for adds. */.globl	add_dadd_d:	/*	 * Break out the operands into their fields (sign,exp,fraction) and	 * handle NaN operands by calling {rs,rt}breakout_d() .	 */	li	t9,C1_FMT_DOUBLE*4	li	v1,1	jal	rs_breakout_d	jal	rt_breakout_d		beq	t8,zero,1f	# if doing a subtract then negate RT	lui	v0,SIGNBIT>>16	xor	t4,v01:	# Check for addition of infinities, and produce the correct action if so	bne	t1,DEXP_INF,5f	# is RS an infinity?				# RS is an infinity	bne	t5,DEXP_INF,4f	# is RT also an infinity?				# RT is an infinity	beq	t0,t4,3f	# do the infinities have the same sign?	/*	 * The infinities do NOT have the same sign thus this is an invalid	 * operation for addition so set the invalid exception in the fpc_csr	 * (a3) and setup the result depending if the enable for the invalid	 * exception is set.	 */	or	a3,INVALID_EXC	and	v0,a3,INVALID_ENABLE	beq	v0,zero,2f	/*	 * The invalid trap was enabled so signal a SIGFPE and leave the	 * result register unmodified.	 */	li	v0,SIGFPE	jal	post_signal	li	v0,1	b	store_fpc_csr	/*	 * The invalid trap was NOT enabled so the result is a quiet NaN.	 * So use the default quiet NaN and exit softfp().	 */2:	li	t2,DQUIETNAN_LESS	li	t3,DQUIETNAN_LEAST	move	v0,zero	b	rd_2w	/*	 * This is just a normal infinity + infinity so the result is just	 * an infinity with the sign of the operands.	 */3:	move	t2,t0	sll	t1,DEXP_SHIFT	or	t2,t1	move	v0,zero	b	rd_2w	/*	 * This is infinity + x , where RS is the infinity so the result is	 * just RS (the infinity).	 */4:	move	t2,t0	sll	t1,DEXP_SHIFT	or	t2,t1	move	v0,zero	b	rd_2w	/*	 * Check RT for an infinity value.  At this point it is know that RS	 * is not an infinity.  If RT is an infinity it will be the result.	 */5:	bne	t5,DEXP_INF,6f	move	t2,t4	sll	t5,DEXP_SHIFT	or	t2,t5	move	t3,t7	move	v0,zero	b	rd_2w6:	# Check for the addition of zeros and produce the correct action if so	bne	t1,zero,3f	# check RS for a zero value (first the exp)	bne	t2,zero,3f	# then the high part of the fraction	bne	t3,zero,3f	# then the low part of the fraction				# Now RS is known to be zero	bne	t5,zero,2f	# check RT for a zero value (first the exp)	bne	t6,zero,2f	# then the high part of the fraction	bne	t7,zero,2f	# then the low part of the fraction	/*	 * Now RS and RT are known to be zeroes so set the correct result	 * according to the rounding mode (in the fpc_csr) and exit.	 */	and	v0,a3,CSR_RM_MASK	# get the rounding mode	bne	v0,CSR_RM_RMI,1f	# check for round to - infinity	or	t2,t0,t4		# set the result and exit, for round to	move	v0,zero			#  - infinity the zero result is the	b	rd_2w			#  and of the operand's signs1:	and	t2,t0,t4		# set the result and exit, for other	move	v0,zero			#  rounding modes the zero result is the	b	rd_2w			#  or of the operand's signs	# RS is a zero and RT is non-zero so the result is RT2:	move	t2,t4	sll	t5,DEXP_SHIFT	or	t2,t5	or	t2,t6	move	t3,t7	move	v0,zero	b	rd_2w	# RS is now known not to be zero so check RT for a zero value.3:	bne	t5,zero,4f	# check RT for a zero value (first the exp)	bne	t6,zero,4f	# then the high part of the fraction	bne	t7,zero,4f	# then the low part of the fraction	or	t2,t0		# RT is a zero so the result is RS	sll	t1,DEXP_SHIFT	or	t2,t1	move	v0,zero	b	rd_2w4:	/*	 * Now that all the NaN, infinity and zero cases have been taken care	 * of what is left are values that can be added.  So get all values	 * into a format that can be added.  For normalized numbers set the	 * implied one and remove the exponent bias.  For denormalized numbers	 * convert to normalized numbers with the correct exponent.	 */	bne	t1,zero,1f	# check for RS being denormalized	li	t1,-DEXP_BIAS+1	# set denorm's exponent	jal	rs_renorm_d	# normalize it	b	2f1:	subu	t1,DEXP_BIAS	# if RS is not denormalized then remove the	or	t2,DIMP_1BIT	#  exponent bias, and set the implied 1 bit2:	bne	t5,zero,3f	# check for RT being denormalized	li	t5,-DEXP_BIAS+1	# set denorm's exponent	jal	rt_renorm_d	# normalize it	b	4f3:	subu	t5,DEXP_BIAS	# if RT is not denormalized then remove the	or	t6,DIMP_1BIT	#  exponent bias, and set the implied 1 bit4:	/*	 * If the two values are the same except the sign return the correct	 * zero according to the rounding mode.	 */	beq	t0,t4,2f		# if the sign's are the same continue	bne	t1,t5,2f		# if the exp's are not the same continue	bne	t2,t6,2f		# if the fraction's are not the	bne	t3,t7,2f		#  same continue	and	v0,a3,CSR_RM_MASK	# get the rounding mode	bne	v0,CSR_RM_RMI,1f	# check for round to - infinity	or	t2,t0,t4		# set the result and exit, for round to	move	t3,zero			#  - infinity the zero result is the	move	v0,zero			#  and of the operand's signs	b	rd_2w1:	and	t2,t0,t4		# set the result and exit, for other	move	t3,zero			#  rounding modes the zero result is the	move	v0,zero			#  or of the operand's signs	b	rd_2w2:	subu	v1,t1,t5		# find the difference of the exponents	move	v0,v1			#  in (v1) and the absolute value of	bge	v1,zero,1f		#  the difference in (v0)	negu	v01:	ble	v0,DFRAC_BITS+2,3f	# is the difference is greater than the					#  number of bits of precision	li	t8,STKBIT		# set the sticky register	bge	v1,zero,2f	# result is RT with a STKBIT added (for RS)	move	t1,t5			# result exponent will be RT's exponent	move	t2,zero	move	t3,zero	b	9f2:	# the result is RS with a STKBIT added (for RT)	move	t6,zero	move	t7,zero	b	9f3:	move	t8,zero			# clear the sticky register	/*	 * If the exponent difference is greater than zero shift the smaller	 * value right by the exponent difference to align the binary point	 * before the addition.  Also select the exponent of the result to	 * be the largest exponent of the two values.  The result exponent is	 * left in (t1) so only if RS is to be shifted does RT's exponent	 * need to be moved into (t1).

⌨️ 快捷键说明

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