📄 softfp.s
字号:
*/sqrt_d: /* * Break out the operand into its fields (sign,exp,fraction) and * handle a NaN operand by calling rs_breakout_d() . */ li t9,C1_FMT_DOUBLE*4 move v1,zero jal rs_breakout_d # Check for sqrt of infinity, and produce the correct action if so bne t1,DEXP_INF,4f # is RS an infinity? # RS is an infinity beq t0,zero,3f # check for -infinity /* * This is -infinity so this is an invalid operation for sqrt so set * the invalid exception in the fpc_csr (a3) and setup the result * depending if the enable for the invalid exception is set. */1: 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 +infinity so the result is just +infinity. */3: sll t2,t1,DEXP_SHIFT move v0,zero b rd_2w4: # Check for the sqrt of zero and produce the correct action if so bne t1,zero,5f # check RS for a zero value (first the exp) bne t2,zero,5f # then the high part of the fraction bne t3,zero,5f # then the low part of the fraction # Now RS is known to be zero so just return it move t2,t0 # get the sign of the zero move v0,zero b rd_2w5: # Check for sqrt of a negitive number if so it is an invalid bne t0,zero,1b /* * Now that all the NaN, infinity and zero and negitive cases have * been taken care of what is left is a value that the sqrt can be * taken. So get the value into a format that can be used. 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: /* * Now take the sqrt of the value. Written by George Tayor. * t1 -- two's comp exponent * t2, t3 -- 53-bit fraction * t8, t9 -- temps * v0, v1 -- trial subtraction * t4, t5 -- remainder * t6, t7 -- 54-bit result * t8 -- sticky */ andi t9, t1, 1 /* last bit of unbiased exponent */ sra t1, 1 /* divide exponent by 2 */ addi t1, -1 /* subtract 1, deliver 54-bit result */ beq t9, zero, 1f sll t2, 1 /* shift operand left by 1 */ srl t9, t3, 31 /* if exponent was odd */ or t2, t9 sll t3, 11: move t6, zero /* initialize answer msw */ li t7, 1 /* initialize answer lsw */ move t4, zero /* initialize remainder msw */ move t5, zero /* initialize remainder lsw */ srl t5, t2, 20 /* shift operand left by 12 so that */ sll t2, 12 /* 2 bits go into remainder */ srl t9, t3, 20 or t2, t9 sll t3, 12 li t8, 54 /* set cycle counter */2: sltu t9, t5, t7 /* trial subtraction */ subu v1, t5, t7 subu v0, t4, t6 subu v0, t9 sll t6, 1 /* shift answer left by 1 */ srl t9, t7, 31 or t6, t9 sll t7, 1 li t9, -4 /* put 01 back in low order bits */ and t7, t9 /* using 0xfffffffc mask */ or t7, 1 bltz v0, 3f /* branch on sign of trial subtract */ ori t7, 4 /* set new bit of answer */ sll t4, v0, 2 /* shift trial result left by 2 */ srl t9, v1, 30 /* and put in remainder */ or t4, t9 sll t5, v1, 2 b 4f3: sll t4, 2 /* shift remainder left by 2 */ srl t9, t5, 30 or t4, t9 sll t5, 24: srl t9, t2, 30 /* shift operand left by 2 */ or t5, t9 sll t2, 2 srl t9, t3, 30 or t2, t9 sll t3, 2 addi t8, -1 bne t8, zero, 2b srl t7, 2 /* shift answer right by 2 */ sll t9, t6, 30 /* to eliminate extra bits */ or t7, t9 srl t6, 2 or t8, t4, t5 /* form sticky bit */ move t2, t6 move t3, t7 b norm_dsqrt_e:sqrt_q: b illfpinstfunc_abs: lw v1,abs_fmt_tab(v0) j v1 .rdataabs_fmt_tab: .word abs_s:1, abs_d:1, abs_e:1, abs_q:1, illfpinst:1 .text/* * Absolute value single */abs_s: move t6,t2 # save the unmodified word /* * Handle a NaN operand by calling rs_breakout_s(). * The broken out results are discarded. */ li t9,C1_FMT_SINGLE*4 jal rs_breakout_s /* * Now just clear the signbit after restoring the unmodified word. */ move t2,t6 and t2,~SIGNBIT move v0,zero b rd_1w/* * Absolute value double */abs_d: move t6,t2 # save the unmodified word /* * Handle a NaN operand by calling rs_breakout_d(). * The broken out results are discarded. */ li t9,C1_FMT_DOUBLE*4 jal rs_breakout_d /* * Now just clear the signbit after restoring the unmodified word. */ move t2,t6 and t2,~SIGNBIT move v0,zero b rd_2wabs_e:abs_q: b illfpinstfunc_mov: lw v1,mov_fmt_tab(v0) j v1 .rdatamov_fmt_tab: .word mov_s:1, mov_d:1, mov_e:1, mov_q:1, illfpinst:1 .text/* * Move single */mov_s: move v0,zero b rd_1w/* * Move double */mov_d: move v0,zero b rd_2wmov_e:mov_q: b illfpinstfunc_neg: lw v1,neg_fmt_tab(v0) j v1 .rdataneg_fmt_tab: .word neg_s:1, neg_d:1, neg_e:1, neg_q:1, illfpinst:1 .text/* * Negation single */neg_s: move t6,t2 # save the unmodified word /* * Handle a NaN operand by calling rs_breakout_s(). * The broken out results are discarded. */ li t9,C1_FMT_SINGLE*4 jal rs_breakout_s /* * Now just negate the operand after restoring the unmodified word. */ move t2,t6 xor t2,SIGNBIT move v0,zero b rd_1w/* * Negation double */neg_d: move t6,t2 # save the unmodified word /* * Handle a NaN operand by calling rs_breakout_d(). * The broken out results are discarded. */ li t9,C1_FMT_DOUBLE*4 jal rs_breakout_d /* * Now just negate the operand after restoring the unmodified word. */ move t2,t6 xor t2,SIGNBIT move v0,zero b rd_2wneg_e:neg_q: b illfpinst/* * Load the floating point value from the register specified by the * RT field into gp registers. The gp registers which are used for * the value specified by the RT feild is dependent on its format * as follows: * single t6 * double t6,t7 * extended t6,t7,s6,s7 (where t7 is really zero) * quad t6,t7,s6,s7 */load_rt: srl v1,a1,RT_SHIFT-2 # get the RT field times 4 right and v1,RT_FPRMASK<<2 # justified into v1 with the last bit # of the field cleared. /* * If fptype_word (a2) is non-zero then the floating-point values * are loaded from the coprocessor else they are loaded from the pcb. */ beq a2,zero,rt_pcb /* * At this point the floating-point value for the specified FPR register * in the RT field will loaded from the coprocessor registers for the * FMT specified (v0). */ # setup to branch to the code to load lw t9,cp_rt_fmt_tab(v0) # the right number of words from the j t9 # cp for the specified format. .rdatacp_rt_fmt_tab: .word rt_cp_1w:1, rt_cp_2w:1, illfpinst:1, illfpinst:1, rt_cp_1w:1 .text/* * Load the one word from the coprocessor for the FPR register specified by * the RT (v1) field into GPR register t6. */rt_cp_1w: srl v1,1 lw v1,rt_cp_1w_tab(v1) j v1 .rdatart_cp_1w_tab: .word rt_cp_1w_fpr0:1, rt_cp_1w_fpr2:1, rt_cp_1w_fpr4:1 .word rt_cp_1w_fpr6:1, rt_cp_1w_fpr8:1, rt_cp_1w_fpr10:1 .word rt_cp_1w_fpr12:1, rt_cp_1w_fpr14:1, rt_cp_1w_fpr16:1 .word rt_cp_1w_fpr18:1, rt_cp_1w_fpr20:1, rt_cp_1w_fpr22:1 .word rt_cp_1w_fpr24:1, rt_cp_1w_fpr26:1, rt_cp_1w_fpr28:1 .word rt_cp_1w_fpr30:1 .textrt_cp_1w_fpr0: mfc1 t6,$f0; b load_rt_donert_cp_1w_fpr2: mfc1 t6,$f2; b load_rt_donert_cp_1w_fpr4: mfc1 t6,$f4; b load_rt_donert_cp_1w_fpr6: mfc1 t6,$f6; b load_rt_donert_cp_1w_fpr8: mfc1 t6,$f8; b load_rt_donert_cp_1w_fpr10: mfc1 t6,$f10; b load_rt_donert_cp_1w_fpr12: mfc1 t6,$f12; b load_rt_donert_cp_1w_fpr14: mfc1 t6,$f14; b load_rt_donert_cp_1w_fpr16: mfc1 t6,$f16; b load_rt_donert_cp_1w_fpr18: mfc1 t6,$f18; b load_rt_donert_cp_1w_fpr20: mfc1 t6,$f20; b load_rt_donert_cp_1w_fpr22: mfc1 t6,$f22; b load_rt_donert_cp_1w_fpr24: mfc1 t6,$f24; b load_rt_donert_cp_1w_fpr26: mfc1 t6,$f26; b load_rt_donert_cp_1w_fpr28: mfc1 t6,$f28; b load_rt_donert_cp_1w_fpr30: mfc1 t6,$f30; b load_rt_done/* * Load the two words from the coprocessor for the FPR register specified by * the RT (v1) field into GPR registers t6,t7. */rt_cp_2w: srl v1,1 lw v1,rt_cp_2w_tab(v1) j v1 .rdatart_cp_2w_tab: .word rt_cp_2w_fpr0:1, rt_cp_2w_fpr2:1, rt_cp_2w_fpr4:1 .word rt_cp_2w_fpr6:1, rt_cp_2w_fpr8:1, rt_cp_2w_fpr10:1 .word rt_cp_2w_fpr12:1, rt_cp_2w_fpr14:1, rt_cp_2w_fpr16:1 .word rt_cp_2w_fpr18:1, rt_cp_2w_fpr20:1, rt_cp_2w_fpr22:1 .word rt_cp_2w_fpr24:1, rt_cp_2w_fpr26:1, rt_cp_2w_fpr28:1 .word rt_cp_2w_fpr30:1 .textrt_cp_2w_fpr0: mfc1 t7,$f0; mfc1 t6,$f1; b load_rt_donert_cp_2w_fpr2: mfc1 t7,$f2; mfc1 t6,$f3; b load_rt_donert_cp_2w_fpr4: mfc1 t7,$f4; mfc1 t6,$f5; b load_rt_donert_cp_2w_fpr6: mfc1 t7,$f6; mfc1 t6,$f7; b load_rt_donert_cp_2w_fpr8: mfc1 t7,$f8; mfc1 t6,$f9; b load_rt_donert_cp_2w_fpr10: mfc1 t7,$f10; mfc1 t6,$f11; b load_rt_donert_cp_2w_fpr12: mfc1 t7,$f12; mfc1 t6,$f13; b load_rt_donert_cp_2w_fpr14: mfc1 t7,$f14; mfc1 t6,$f15; b load_rt_donert_cp_2w_fpr16: mfc1 t7,$f16; mfc1 t6,$f17; b load_rt_donert_cp_2w_fpr18: mfc1 t7,$f18; mfc1 t6,$f19; b load_rt_donert_cp_2w_fpr20: mfc1 t7,$f20; mfc1 t6,$f21; b load_rt_donert_cp_2w_fpr22: mfc1 t7,$f22; mfc1 t6,$f23; b load_rt_donert_cp_2w_fpr24: mfc1 t7,$f24; mfc1 t6,$f25; b load_rt_donert_cp_2w_fpr26: mfc1 t7,$f26; mfc1 t6,$f27; b load_rt_donert_cp_2w_fpr28: mfc1 t7,$f28; mfc1 t6,$f29; b load_rt_donert_cp_2w_fpr30: mfc1 t7,$f30; mfc1 t6,$f31; b load_rt_done/* * At this point the floating-point value for the specified FPR register * in the RT field (v1) will loaded from the process control block (pcb) * of the current process for FMT specified (v0). */rt_pcb: lw t9,rt_pcb_fmt_tab(v0) j t9 .rdatart_pcb_fmt_tab: .word rt_pcb_s:1, rt_pcb_d:1, illfpinst:1, illfpinst:1, rt_pcb_w:1 .textrt_pcb_s:rt_pcb_w: lw t6,u+PCB_FPREGS(v1) b load_rt_donert_pcb_d: lw t7,u+PCB_FPREGS(v1) lw t6,u+PCB_FPREGS+4(v1)/* * At this point the both the floating-point value for the specified FPR * registers of the RS and RT fields have been loaded into GPR registers. * What is done next is to decode the FUNC field (t8) for the dyadic operations. */load_rt_done: bge t8,C1_FUNC_1stCMP,comp sll t8,2 lw t9,dy_func_tab(t8) j t9 .rdatady_func_tab: .word func_add:1, func_add:1, func_mul:1, func_div:1 .text
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -