📄 fpsoft.s
字号:
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 RTs 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 RTs 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 RTs 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) */ srlv t8,t8,v0 /* shift the sticky register */ sllv t9,t2,v1 or t8,t9 srlv t2,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) */ srlv t8,t8,v0 /* shift the sticky register */ sllv t9,t6,v1 or t8,t9 srlv t6,t6,v0 /* shift the fraction */4: /* * 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 results 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 of */1: /* * RT is smaller so subtract RT from RS and use RSs 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 RTs sign as the sign * of the result. */ move t0,t4 /* use RTs 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_d -** Add (and subtract) double RD = RS + RT (or RD = RS - RT). Again the FUNC* field (t8) is zero for adds.*/ .globl GTEXT(add_d)FUNC_LABEL(add_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)&0xffff 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 C1_SR * (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, IV_FPA_INV_VEC jal post_signal li v0,1 b store_C1_SR /* * 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,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,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,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 C1_SR) 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 operands signs */1: 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 operands signs */ /* RS is a zero and RT is non-zero so the result is RT */2: move t2,t4 sll t5,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,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 denorms 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 bit */2: bne t5,zero,3f /* check for RT being denormalized */ li t5,-DEXP_BIAS+1 /* set denorms 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 bit */4: /* * 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 signs are the same continue */ bne t1,t5,2f /* - if the exps are not the same continue */ bne t2,t6,2f /* - if the fractions 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 operands 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 operands 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 RTs 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 RTs exponent * need to be moved into (t1). */ beq v0,zero,9f /* - if the exp diff is zero then no shift */ bgt v1,zero,6f /* if the exp diff > 0 shift RT */ move t1,t5 /* result exponent will be RTs exponent */ /* Shift the fraction of the RS value */ blt v0,32,5f /* check for shifts >= 32 */ move t8,t3 /* shift the fraction over 32 bits by */ move t3,t2 /* moving the words to the right and */ move t2,zero /* fill the highest word with a zero */ beq t8,zero,4f /* - if any 1s get into the sticky reg */ or t8,STKBIT /* make sure the sticky bit stays set */4: subu v0,32 /* the right shift amount (v0) */ negu v1,v0 /* the left shift amount which is 32 */ addu v1,32 /* minus right shift amount (v1) */ /* Now shift the fraction (only the low two words in this case) */ srlv t8,t8,v0 /* shift the sticky register */ sllv t9,t3,v1 or t8,t9 srlv t3,t3,v0 /* shift the low word of the fraction */ b 9f5: /* 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) */ srlv t8,t8,v0 /* shift the sticky register */ sllv t9,t3,v1 or t8,t9 srlv t3,t3,v0 /* shift the low word of the fraction */ sllv t9,t2,v1 or t3,t9 srlv t2,t2,v0 /* shift the high word of the fraction */ b 9f6: /* Shift the fraction of the RT value */ blt v0,32,8f /* check for shifts >= 32 */ move t8,t7 /* shift the fraction over 32 bits by */ move t7,t6 /* moving the words to the right and */ move t6,zero /* fill the highest word with a zero */ beq t8,zero,7f /* - if any 1s get into the sticky reg */ or t8,STKBIT /* make sure the sticky bit stays set */7: subu v0,32 /* the right shift amount (v0) */ negu v1,v0 /* the left shift amount which is 32 */ addu v1,32 /* minus right shift amount (v1) */ /* Now shift the fraction (only the low two words in this case) */ srlv t8,t8,v0 /* shift the sticky register */ sllv t9,t7,v1 or t8,t9 srlv t7,t7,v0 /* shift the low word of the fraction */ b 9f8: /* 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) */ srlv t8,t8,v0 /* shift the sticky register */ sllv t9,t7,v1 or t8,t9 srlv t7,t7,v0 /* shift the low word of the fraction */ sllv t9,t6,v1 or t7,t9 srlv t6,t6,v0 /* shift the high word of the fraction */9: /* * 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 results sign will be the sign of the * larger fraction. */ bne t0,t4,2f /* - if the signs not the same subtract */ /* Add the fractions */ not v0,t3 /* set carry out (t9) for the addition */ sltu t9,v0,t7 /* of the least fraction words */ addu t3,t7 /* add the least fraction words */ /* add the less fraction fraction words with the carry in */ bne t9,zero,1f /* see if there is a carry in */ /* no carry in to be added in (carry out is not possible or needed) */ addu t2,t6 /* add the less fraction words */ b norm_d /* a carry in is to be added in (carry out is not possible or needed) */1: addu t2,t6 /* add the less fraction words */ addu t2,1 /* add in the carry in */ b norm_d2: /* * 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,5f /* determine the smaller fraction */ bgt t2,t6,1f /* Note the case where they were equal */ bltu t3,t7,5f /* has already been taken care of */1: /* * RT is smaller so subtract RT from RS and use RSs 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 */ sltu t9,t3,t7 /* set barrow out for least fraction */ subu t3,t3,t7 /* subtract least fractions */ b 3f2: /* barrow in to be subtracted out */ sltu t9,t3,t7 /* set barrow out for least fraction */ subu t3,t3,t7 /* subtract least fractions */ seq v0,t3,zero /* set barrow out for barrow in */ or t9,v0 /* final barrow out */ subu t3,1 /* subtract barrow in */3: /* subtract less signifiant fraction words */ bne t9,zero,4f /* see if there is a barrow in */ /* no barrow in to be subtracted out (barrow out not possible or needed) */ subu t2,t2,t6 /* subtract less fractions */ b norm_d4: /* barrow in to be subtracted out (barrow out not possible or needed) */ subu t2,t2,t6 /* subtract less fractions */ subu t2,1 /* subtract barrow in */ b norm_d5: /* * RS is smaller so subtract RS from RT and use RTs sign as the sign * of the result. */ move t0,t4 /* use RTs 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 */ sltu t9,t7,t3 /* set barrow out for least fraction */ subu t3,t7,t3 /* subtract least fractions */ b 2f1: /* barrow in to be subtracted out */ sltu t9,t7,t3 /* set barrow out for least fraction */ subu t3,t7,t3 /* subtract least fractions */ seq v0,t3,zero /* set barrow out for barrow in */ or t9,v0 /* final barrow out */ subu t3,1 /* subtract barrow in */2: /* subtract less signifiant fraction words */ bne t9,zero,3f /* see if there is a barrow in */ /* no barrow in to be subtracted out (barrow out not possible or needed) */ subu t2,t6,t2 /* subtract less fractions */ b norm_d3: /* barrow in to be subtracted out (barrow out not possible or needed) */ subu t2,t6,t2 /* subtract least fractions */ subu t2,1 /* subtract barrow in */ b norm_dadd_e:add_q: b illfpinstfunc_mul: la v1,mul_fmt_tab addu v1, v0, v1 j v1 .set noreordermul_fmt_tab: b mul_s; nop b mul_d; nop b mul_e; nop b mul_q; nop b illfpinst; nop b illfpinst; nop .set reorder/********************************************************************************* mul_s - Multiplication single RD = RS * RT**/ .globl GTEXT(mul_s)FUNC_LABEL(mul_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 /* * With the Na
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -