📄 fp.s
字号:
addu t9, 321: srl v1, v0, 16 bne v1, zero, 1f addu t9, 16 sll v0, 161: srl v1, v0, 24 bne v1, zero, 1f addu t9, 8 sll v0, 81: srl v1, v0, 28 bne v1, zero, 1f addu t9, 4 sll v0, 41: srl v1, v0, 30 bne v1, zero, 1f addu t9, 2 sll v0, 21: srl v1, v0, 31 bne v1, zero, 1f addu t9, 1/* * Now shift t2,t8 the correct number of bits. */1: subu t9, t9, SLEAD_ZEROS # dont count leading zeros subu t1, t1, t9 # adjust the exponent beq t9, zero, norm_noshift_s li v1, 32 blt t9, zero, 1f # if shift < 0, shift right subu v1, v1, t9 sll t2, t2, t9 # shift t2,t8 left srl v0, t8, v1 # save bits shifted out or t2, t2, v0 sll t8, t8, t9 b norm_noshift_s1: negu t9 # shift t2,t8 right by t9 subu v1, v1, t9 sll v0, t8, v1 # save bits shifted out sltu v0, zero, v0 # be sure to save any one bits srl t8, t8, t9 or t8, t8, v0 sll v0, t2, v1 # save bits shifted out or t8, t8, v0 srl t2, t2, t9norm_noshift_s: move t5, t1 # save unrounded exponent move t6, t2 # save unrounded fraction and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode beq v0, MACH_FPC_ROUND_RN, 3f # round to nearest beq v0, MACH_FPC_ROUND_RZ, 5f # round to zero (truncate) beq v0, MACH_FPC_ROUND_RP, 1f # round to +infinity beq t0, zero, 5f # if sign is positive, truncate b 2f1: bne t0, zero, 5f # if sign is negative, truncate2: beq t8, zero, 5f # if exact, continue addu t2, t2, 1 # add rounding bit bne t2, SIMPL_ONE<<1, 5f # need to adjust exponent? addu t1, t1, 1 # adjust exponent srl t2, t2, 1 # renormalize fraction b 5f3: li v0, GUARDBIT # load guard bit for rounding addu v0, v0, t8 # add remainder sltu v1, v0, t8 # compute carry out beq v1, zero, 4f # if no carry, continue addu t2, t2, 1 # add carry to result bne t2, SIMPL_ONE<<1, 4f # need to adjust exponent? addu t1, t1, 1 # adjust exponent srl t2, t2, 1 # renormalize fraction4: bne v0, zero, 5f # if rounded remainder is zero and t2, t2, ~1 # clear LSB (round to nearest)5: bgt t1, SEXP_MAX, overflow_s # overflow? blt t1, SEXP_MIN, underflow_s # underflow? bne t8, zero, inexact_s # is result inexact? addu t1, t1, SEXP_BIAS # bias exponent and t2, t2, ~SIMPL_ONE # clear implied one bit b result_fs_s/* * Handle inexact exception. */inexact_s: addu t1, t1, SEXP_BIAS # bias exponent and t2, t2, ~SIMPL_ONE # clear implied one bitinexact_nobias_s: jal set_fd_s # save result or a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT and v0, a1, MACH_FPC_ENABLE_INEXACT bne v0, zero, fpe_trap ctc1 a1, MACH_FPC_CSR # save exceptions b done/* * Overflow will trap (if enabled), * or generate an inexact trap (if enabled), * or generate an infinity. */overflow_s: or a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW and v0, a1, MACH_FPC_ENABLE_OVERFLOW beq v0, zero, 1f subu t1, t1, 192 # bias exponent and t2, t2, ~SIMPL_ONE # clear implied one bit jal set_fd_s # save result b fpe_trap1: and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode beq v0, MACH_FPC_ROUND_RN, 3f # round to nearest beq v0, MACH_FPC_ROUND_RZ, 1f # round to zero (truncate) beq v0, MACH_FPC_ROUND_RP, 2f # round to +infinity bne t0, zero, 3f1: li t1, SEXP_MAX # result is max finite li t2, 0x007fffff b inexact_s2: bne t0, zero, 1b3: li t1, SEXP_MAX + 1 # result is infinity move t2, zero b inexact_s/* * In this implementation, "tininess" is detected "after rounding" and * "loss of accuracy" is detected as "an inexact result". */underflow_s: and v0, a1, MACH_FPC_ENABLE_UNDERFLOW beq v0, zero, 1f/* * Underflow is enabled so compute the result and trap. */ addu t1, t1, 192 # bias exponent and t2, t2, ~SIMPL_ONE # clear implied one bit jal set_fd_s # save result or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW b fpe_trap/* * Underflow is not enabled so compute the result, * signal inexact result (if it is) and trap (if enabled). */1: move t1, t5 # get unrounded exponent move t2, t6 # get unrounded fraction li t9, SEXP_MIN # compute shift amount subu t9, t9, t1 # shift t2,t8 right by t9 blt t9, SFRAC_BITS+2, 3f # shift all the bits out? move t1, zero # result is inexact zero move t2, zero or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW/* * Now round the zero result. * Only need to worry about rounding to +- infinity when the sign matches. */ and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode beq v0, MACH_FPC_ROUND_RN, inexact_nobias_s # round to nearest beq v0, MACH_FPC_ROUND_RZ, inexact_nobias_s # round to zero beq v0, MACH_FPC_ROUND_RP, 1f # round to +infinity beq t0, zero, inexact_nobias_s # if sign is positive, truncate b 2f1: bne t0, zero, inexact_nobias_s # if sign is negative, truncate2: addu t2, t2, 1 # add rounding bit b inexact_nobias_s3: li v1, 32 subu v1, v1, t9 sltu v0, zero, t8 # be sure to save any one bits sll t8, t2, v1 # save bits shifted out or t8, t8, v0 # include sticky bits srl t2, t2, t9/* * Now round the denormalized result. */ and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode beq v0, MACH_FPC_ROUND_RN, 3f # round to nearest beq v0, MACH_FPC_ROUND_RZ, 5f # round to zero (truncate) beq v0, MACH_FPC_ROUND_RP, 1f # round to +infinity beq t0, zero, 5f # if sign is positive, truncate b 2f1: bne t0, zero, 5f # if sign is negative, truncate2: beq t8, zero, 5f # if exact, continue addu t2, t2, 1 # add rounding bit b 5f3: li v0, GUARDBIT # load guard bit for rounding addu v0, v0, t8 # add remainder sltu v1, v0, t8 # compute carry out beq v1, zero, 4f # if no carry, continue addu t2, t2, 1 # add carry to result4: bne v0, zero, 5f # if rounded remainder is zero and t2, t2, ~1 # clear LSB (round to nearest)5: move t1, zero # denorm or zero exponent jal set_fd_s # save result beq t8, zero, done # check for exact result or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW or a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT and v0, a1, MACH_FPC_ENABLE_INEXACT bne v0, zero, fpe_trap ctc1 a1, MACH_FPC_CSR # save exceptions b done/* * Determine the amount to shift the fraction in order to restore the * normalized position. After that, round and handle exceptions. */norm_d: move v0, t2 move t9, zero # t9 = num of leading zeros bne t2, zero, 1f move v0, t3 addu t9, 32 bne t3, zero, 1f move v0, t8 addu t9, 321: srl v1, v0, 16 bne v1, zero, 1f addu t9, 16 sll v0, 161: srl v1, v0, 24 bne v1, zero, 1f addu t9, 8 sll v0, 81: srl v1, v0, 28 bne v1, zero, 1f addu t9, 4 sll v0, 41: srl v1, v0, 30 bne v1, zero, 1f addu t9, 2 sll v0, 21: srl v1, v0, 31 bne v1, zero, 1f addu t9, 1/* * Now shift t2,t3,t8 the correct number of bits. */1: subu t9, t9, DLEAD_ZEROS # dont count leading zeros subu t1, t1, t9 # adjust the exponent beq t9, zero, norm_noshift_d li v1, 32 blt t9, zero, 2f # if shift < 0, shift right blt t9, v1, 1f # shift by < 32? subu t9, t9, v1 # shift by >= 32 subu v1, v1, t9 sll t2, t3, t9 # shift left by t9 srl v0, t8, v1 # save bits shifted out or t2, t2, v0 sll t3, t8, t9 move t8, zero b norm_noshift_d1: subu v1, v1, t9 sll t2, t2, t9 # shift left by t9 srl v0, t3, v1 # save bits shifted out or t2, t2, v0 sll t3, t3, t9 srl v0, t8, v1 # save bits shifted out or t3, t3, v0 sll t8, t8, t9 b norm_noshift_d2: negu t9 # shift right by t9 subu v1, v1, t9 # (known to be < 32 bits) sll v0, t8, v1 # save bits shifted out sltu v0, zero, v0 # be sure to save any one bits srl t8, t8, t9 or t8, t8, v0 sll v0, t3, v1 # save bits shifted out or t8, t8, v0 srl t3, t3, t9 sll v0, t2, v1 # save bits shifted out or t3, t3, v0 srl t2, t2, t9norm_noshift_d: move t5, t1 # save unrounded exponent move t6, t2 # save unrounded fraction (MS) move t7, t3 # save unrounded fraction (LS) and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode beq v0, MACH_FPC_ROUND_RN, 3f # round to nearest beq v0, MACH_FPC_ROUND_RZ, 5f # round to zero (truncate) beq v0, MACH_FPC_ROUND_RP, 1f # round to +infinity beq t0, zero, 5f # if sign is positive, truncate b 2f1: bne t0, zero, 5f # if sign is negative, truncate2: beq t8, zero, 5f # if exact, continue addu t3, t3, 1 # add rounding bit bne t3, zero, 5f # branch if no carry addu t2, t2, 1 # add carry bne t2, DIMPL_ONE<<1, 5f # need to adjust exponent? addu t1, t1, 1 # adjust exponent srl t2, t2, 1 # renormalize fraction b 5f3: li v0, GUARDBIT # load guard bit for rounding addu v0, v0, t8 # add remainder sltu v1, v0, t8 # compute carry out beq v1, zero, 4f # branch if no carry addu t3, t3, 1 # add carry bne t3, zero, 4f # branch if no carry addu t2, t2, 1 # add carry to result bne t2, DIMPL_ONE<<1, 4f # need to adjust exponent? addu t1, t1, 1 # adjust exponent srl t2, t2, 1 # renormalize fraction4: bne v0, zero, 5f # if rounded remainder is zero and t3, t3, ~1 # clear LSB (round to nearest)5: bgt t1, DEXP_MAX, overflow_d # overflow? blt t1, DEXP_MIN, underflow_d # underflow? bne t8, zero, inexact_d # is result inexact? addu t1, t1, DEXP_BIAS # bias exponent and t2, t2, ~DIMPL_ONE # clear implied one bit b result_fs_d/* * Handle inexact exception. */inexact_d: addu t1, t1, DEXP_BIAS # bias exponent and t2, t2, ~DIMPL_ONE # clear implied one bitinexact_nobias_d: jal set_fd_d # save result or a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT and v0, a1, MACH_FPC_ENABLE_INEXACT bne v0, zero, fpe_trap ctc1 a1, MACH_FPC_CSR # save exceptions b done/* * Overflow will trap (if enabled), * or generate an inexact trap (if enabled), * or generate an infinity. */overflow_d: or a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW and v0, a1, MACH_FPC_ENABLE_OVERFLOW beq v0, zero, 1f subu t1, t1, 1536 # bias exponent and t2, t2, ~DIMPL_ONE # clear implied one bit jal set_fd_d # save result b fpe_trap1: and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode beq v0, MACH_FPC_ROUND_RN, 3f # round to nearest beq v0, MACH_FPC_ROUND_RZ, 1f # round to zero (truncate) beq v0, MACH_FPC_ROUND_RP, 2f # round to +infinity bne t0, zero, 3f1: li t1, DEXP_MAX # result is max finite li t2, 0x000fffff li t3, 0xffffffff b inexact_d2: bne t0, zero, 1b3: li t1, DEXP_MAX + 1 # result is infinity move t2, zero move t3, zero b inexact_d/* * In this implementation, "tininess" is detected "after rounding" and * "loss of accuracy" is detected as "an inexact result". */underflow_d: and v0, a1, MACH_FPC_ENABLE_UNDERFLOW beq v0, zero, 1f/* * Underflow is enabled so compute the result and trap. */ addu t1, t1, 1536 # bias exponent and t2, t2, ~DIMPL_ONE # clear implied one bit jal set_fd_d # save result or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW b fpe_trap/* * Underflow is not enabled so compute the result, * signal inexact result (if it is) and trap (if enabled). */1: move t1, t5 # get unrounded exponent move t2, t6 # get unrounded fraction (MS) move t3, t7 # get unrounded fraction (LS) li t9, DEXP_MIN # compute shift amount subu t9, t9, t1 # shift t2,t8 right by t9 blt t9, DFRAC_BITS+2, 3f # shift all the bits out? move t1, zero # result is inexact zero move t2, zero move t3, zero or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW/* * Now round the zero result. * Only need to worry about rounding to +- infinity when the sign matches. */ and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode beq v0, MACH_FPC_ROUND_RN, inexact_nobias_d # round to nearest beq v0, MACH_FPC_ROUND_RZ, inexact_nobias_d # round to zero beq v0, MACH_FPC_ROUND_RP, 1f # round to +infinity beq t0, zero, inexact_nobias_d # if sign is positive, truncate b 2f1: bne t0, zero, inexact_nobias_d # if sign is negative, truncate2: addu t3, t3, 1 # add rounding bit b inexact_nobias_d3: li v1, 32 blt t9, v1, 1f # shift by < 32? subu t9, t9, v1 # shift right by >= 32 subu v1, v1, t9 sltu v0, zero, t8 # be sure to save any one bits sll t8, t2, v1 # save bits shifted out or t8, t8, v0 # include sticky bits srl t3, t2, t9 move t2, zero b 2f1: subu v1, v1, t9 # shift right by t9 sltu v0, zero, t8 # be sure to save any one bits sll t8, t3, v1 # save bits shifted out or t8, t8, v0 # include sticky bits srl t3, t3, t9 sll v0, t2, v1 # save bits shifted out or t3, t3, v0 srl t2, t2, t9/* * Now round the denormalized result. */2: and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode beq v0, MACH_FPC_ROUND_RN, 3f # round to nearest beq v0, MACH_FPC_ROUND_RZ, 5f # round to zero (truncate) beq v0, MACH_FPC_ROUND_RP, 1f # round to +infinity beq t0, zero, 5f # if sign is positive, truncate b 2f1: bne t0, zero, 5f # if sign is negative, truncate2: beq t8, zero, 5f # if exact, continue addu t3, t3, 1 # add rounding bit bne t3, zero, 5f # if no carry, continue addu t2, t2, 1 # add carry b 5f3: li v0, GUARDBIT # load guard bit for rounding addu v0, v0, t8 # add remainder sltu v1, v0, t8 # compute carry out beq v1, zero, 4f # if no carry, continue addu t3, t3, 1 # add rounding bit bne t3, zero, 4f # if no carry, continue addu t2, t2, 1 # add carry4: bne v0, zero, 5f # if rounded remainder is zero and t3, t3, ~1 # clear LSB (round to nearest)5: move t1, zero # denorm or zero exponent jal set_fd_d # save result beq t8, zero, done # check for exact result or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW or a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT and v0, a1, MACH_FPC_ENABLE_INEXACT bne v0, zero, fpe_trap ctc1 a1, MACH_FPC_CSR # save exceptions b done/* * Signal an invalid operation if the trap is enabled; otherwise, * the result is a quiet NAN. */invalid_s: # trap invalid operation or a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID and v0, a1, MACH_FPC_ENABLE_INVALID bne v0, zero, fpe_trap ctc1 a1, MACH_FPC_CSR # save exceptions move t0, zero # result is a quiet NAN li t1, SEXP_INF li t2, SQUIET_NAN jal set_fd_s # save result (in t0,t1,t2) b done/* * Signal an invalid operation if the trap is enabled; otherwise, * the result is a quiet NAN. */invalid_d: # trap invalid operation or a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID and v0, a1, MACH_FPC_ENABLE_INVALID bne v0, zero, fpe_trap ctc1 a1, MACH_FPC_CSR # save exceptions move t0, zero # result is a quiet NAN li t1, DEXP_INF li t2, DQUIET_NAN0 li t3, DQUIET_NAN1 jal set_fd_d # save result (in t0,t1,t2,t3) b done/* * Signal an invalid operation if the trap is enabled; otherwise, * the result is INT_MAX or INT_MIN. */invalid_w: # trap invalid operation or a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID and v0, a1, MACH_FPC_ENABLE_INVALID bne v0, zero, fpe_trap ctc1 a1, MACH_FPC_CSR # save exceptions bne t0, zero, 1f li t2, INT_MAX # result is INT_MAX b result_fs_w1: li t2, INT_MIN # result is INT_MIN b result_fs_w/* * Trap if the hardware should have handled this case. */fpe_trap: move a2, a1 # code = FP CSR ctc1 a1, MACH_FPC_CSR # save exceptions break 0/* * Send an illegal instruction signal to the current process. */ill: ctc1 a1, MACH_FPC_CSR # save exceptions move a2, a0 # code = FP instruction break 0result_ft_s: move t0, t4 # result is FT move t1, t5 move t2, t6result_fs_s: # result is FS jal set_fd_s # save result (in t0,t1,t2) b done
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -