📄 fp.s
字号:
div_d: jal get_ft_fs_d xor t0, t0, t4 # compute sign of result move t4, t0 bne t1, DEXP_INF, 1f # is FS an infinity? bne t2, zero, result_fs_d # if FS is NAN, result is FS bne t3, zero, result_fs_d bne t5, DEXP_INF, result_fs_d # is FT an infinity? bne t6, zero, result_ft_d # if FT is NAN, result is FT bne t7, zero, result_ft_d b invalid_d # infinity/infinity is invalid1: bne t5, DEXP_INF, 1f # is FT an infinity? bne t6, zero, result_ft_d # if FT is NAN, result is FT bne t7, zero, result_ft_d move t1, zero # x / infinity is zero move t2, zero move t3, zero b result_fs_d1: bne t1, zero, 2f # is FS zero? bne t2, zero, 1f bne t3, zero, 1f bne t5, zero, result_fs_d # FS=zero, is FT zero? bne t6, zero, result_fs_d beq t7, zero, invalid_d # 0 / 0 b result_fs_d # result = zero1: jal renorm_fs_d b 3f2: subu t1, t1, DEXP_BIAS # unbias FS exponent or t2, t2, DIMPL_ONE # set implied one bit3: bne t5, zero, 2f # is FT zero? bne t6, zero, 1f bne t7, zero, 1f or a1, a1, MACH_FPC_EXCEPTION_DIV0 | MACH_FPC_STICKY_DIV0 and v0, a1, MACH_FPC_ENABLE_DIV0 # trap enabled? bne v0, zero, fpe_trap ctc1 a1, MACH_FPC_CSR # Save exceptions li t1, DEXP_INF # result is infinity move t2, zero move t3, zero b result_fs_d1: jal renorm_ft_d b 3f2: subu t5, t5, DEXP_BIAS # unbias FT exponent or t6, t6, DIMPL_ONE # set implied one bit3: subu t1, t1, t5 # compute exponent subu t1, t1, 3 # compensate for result position li v0, DFRAC_BITS+3 # number of bits to divide move t8, t2 # init dividend move t9, t3 move t2, zero # init result move t3, zero1: bltu t8, t6, 3f # is dividend >= divisor? bne t8, t6, 2f bltu t9, t7, 3f2: sltu v1, t9, t7 # subtract divisor from dividend subu t9, t9, t7 subu t8, t8, t6 subu t8, t8, v1 or t3, t3, 1 # remember that we did bne t8, zero, 3f # if not done, continue bne t9, zero, 3f li v1, 32 # shift result to final position blt v0, v1, 2f # shift < 32 bits? subu v0, v0, v1 # shift by > 32 bits sll t2, t3, v0 # shift upper part move t3, zero b norm_d2: subu v1, v1, v0 # shift by < 32 bits sll t2, t2, v0 # shift upper part srl t9, t3, v1 # save bits shifted out or t2, t2, t9 # and put into upper part sll t3, t3, v0 b norm_d3: sll t8, t8, 1 # shift dividend srl v1, t9, 31 # save bit shifted out or t8, t8, v1 # and put into upper part sll t9, t9, 1 sll t2, t2, 1 # shift result srl v1, t3, 31 # save bit shifted out or t2, t2, v1 # and put into upper part sll t3, t3, 1 subu v0, v0, 1 # are we done? bne v0, zero, 1b # no, continue sltu v0, zero, t9 # be sure to save any one bits or t8, t8, v0 # from the lower remainder b norm_d/* * Single precision absolute value. */abs_s: jal get_fs_s move t0, zero # set sign positive b result_fs_s/* * Double precision absolute value. */abs_d: jal get_fs_d move t0, zero # set sign positive b result_fs_d/* * Single precision move. */mov_s: jal get_fs_s b result_fs_s/* * Double precision move. */mov_d: jal get_fs_d b result_fs_d/* * Single precision negate. */neg_s: jal get_fs_s xor t0, t0, 1 # reverse sign b result_fs_s/* * Double precision negate. */neg_d: jal get_fs_d xor t0, t0, 1 # reverse sign b result_fs_d/* * Convert double to single. */cvt_s_d: jal get_fs_d bne t1, DEXP_INF, 1f # is FS an infinity? li t1, SEXP_INF # convert to single sll t2, t2, 3 # convert D fraction to S srl t8, t3, 32 - 3 or t2, t2, t8 b result_fs_s1: bne t1, zero, 2f # is FS zero? bne t2, zero, 1f beq t3, zero, result_fs_s # result=01: jal renorm_fs_d subu t1, t1, 3 # correct exp for shift below b 3f2: subu t1, t1, DEXP_BIAS # unbias exponent or t2, t2, DIMPL_ONE # add implied one bit3: sll t2, t2, 3 # convert D fraction to S srl t8, t3, 32 - 3 or t2, t2, t8 sll t8, t3, 3 b norm_noshift_s/* * Convert integer to single. */cvt_s_w: jal get_fs_int bne t2, zero, 1f # check for zero move t1, zero b result_fs_s/* * Find out how many leading zero bits are in t2 and put in t9. */1: move v0, t2 move t9, zero 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 the correct number of bits. */1: subu t9, t9, SLEAD_ZEROS # dont count leading zeros li t1, 23 # init exponent subu t1, t1, t9 # compute exponent beq t9, zero, 1f li v0, 32 blt t9, zero, 2f # if shift < 0, shift right subu v0, v0, t9 sll t2, t2, t9 # shift left1: add t1, t1, SEXP_BIAS # bias exponent and t2, t2, ~SIMPL_ONE # clear implied one bit b result_fs_s2: negu t9 # shift right by t9 subu v0, v0, t9 sll t8, t2, v0 # save bits shifted out srl t2, t2, t9 b norm_noshift_s/* * Convert single to double. */cvt_d_s: jal get_fs_s move t3, zero bne t1, SEXP_INF, 1f # is FS an infinity? li t1, DEXP_INF # convert to double b result_fs_d1: bne t1, zero, 2f # is FS denormalized or zero? beq t2, zero, result_fs_d # is FS zero? jal renorm_fs_s move t8, zero b norm_d2: addu t1, t1, DEXP_BIAS - SEXP_BIAS # bias exponent correctly sll t3, t2, 32 - 3 # convert S fraction to D srl t2, t2, 3 b result_fs_d/* * Convert integer to double. */cvt_d_w: jal get_fs_int bne t2, zero, 1f # check for zero move t1, zero # result=0 move t3, zero b result_fs_d/* * Find out how many leading zero bits are in t2 and put in t9. */1: move v0, t2 move t9, zero 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 the correct number of bits. */1: subu t9, t9, DLEAD_ZEROS # dont count leading zeros li t1, DEXP_BIAS + 20 # init exponent subu t1, t1, t9 # compute exponent beq t9, zero, 1f li v0, 32 blt t9, zero, 2f # if shift < 0, shift right subu v0, v0, t9 sll t2, t2, t9 # shift left1: and t2, t2, ~DIMPL_ONE # clear implied one bit move t3, zero b result_fs_d2: negu t9 # shift right by t9 subu v0, v0, t9 sll t3, t2, v0 srl t2, t2, t9 and t2, t2, ~DIMPL_ONE # clear implied one bit b result_fs_d/* * Convert single to integer. */cvt_w_s: jal get_fs_s bne t1, SEXP_INF, 1f # is FS an infinity? bne t2, zero, invalid_w # invalid conversion1: bne t1, zero, 1f # is FS zero? beq t2, zero, result_fs_w # result is zero move t2, zero # result is an inexact zero b inexact_w1: subu t1, t1, SEXP_BIAS # unbias exponent or t2, t2, SIMPL_ONE # add implied one bit sll t3, t2, 32 - 3 # convert S fraction to D srl t2, t2, 3 b cvt_w/* * Convert double to integer. */cvt_w_d: jal get_fs_d bne t1, DEXP_INF, 1f # is FS an infinity? bne t2, zero, invalid_w # invalid conversion bne t3, zero, invalid_w # invalid conversion1: bne t1, zero, 2f # is FS zero? bne t2, zero, 1f beq t3, zero, result_fs_w # result is zero1: move t2, zero # result is an inexact zero b inexact_w2: subu t1, t1, DEXP_BIAS # unbias exponent or t2, t2, DIMPL_ONE # add implied one bitcvt_w: blt t1, WEXP_MIN, underflow_w # is exponent too small? li v0, WEXP_MAX+1 bgt t1, v0, overflow_w # is exponent too large? bne t1, v0, 1f # special check for INT_MIN beq t0, zero, overflow_w # if positive, overflow bne t2, DIMPL_ONE, overflow_w bne t3, zero, overflow_w li t2, INT_MIN # result is INT_MIN b result_fs_w1: subu v0, t1, 20 # compute amount to shift beq v0, zero, 2f # is shift needed? li v1, 32 blt v0, zero, 1f # if shift < 0, shift right subu v1, v1, v0 # shift left sll t2, t2, v0 srl t9, t3, v1 # save bits shifted out of t3 or t2, t2, t9 # and put into t2 sll t3, t3, v0 # shift FSs fraction b 2f1: negu v0 # shift right by v0 subu v1, v1, v0 sll t8, t3, v1 # save bits shifted out sltu t8, zero, t8 # dont lose any ones srl t3, t3, v0 # shift FSs fraction or t3, t3, t8 sll t9, t2, v1 # save bits shifted out of t2 or t3, t3, t9 # and put into t3 srl t2, t2, v0/* * round result (t0 is sign, t2 is integer part, t3 is fractional part). */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 t3, zero, 5f # if no fraction bits, continue addu t2, t2, 1 # add rounding bit blt t2, zero, overflow_w # overflow? b 5f3: li v0, GUARDBIT # load guard bit for rounding addu v0, v0, t3 # add remainder sltu v1, v0, t3 # compute carry out beq v1, zero, 4f # if no carry, continue addu t2, t2, 1 # add carry to result blt t2, zero, overflow_w # overflow?4: bne v0, zero, 5f # if rounded remainder is zero and t2, t2, ~1 # clear LSB (round to nearest)5: beq t0, zero, 1f # result positive? negu t2 # convert to negative integer1: beq t3, zero, result_fs_w # is result exact?/* * Handle inexact exception. */inexact_w: 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 result_fs_w/* * Conversions to integer which overflow will trap (if enabled), * or generate an inexact trap (if enabled), * or generate an invalid exception. */overflow_w: or a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW and v0, a1, MACH_FPC_ENABLE_OVERFLOW bne v0, zero, fpe_trap and v0, a1, MACH_FPC_ENABLE_INEXACT bne v0, zero, inexact_w # inexact traps enabled? b invalid_w/* * Conversions to integer which underflow will trap (if enabled), * or generate an inexact trap (if enabled), * or generate an invalid exception. */underflow_w: or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW and v0, a1, MACH_FPC_ENABLE_UNDERFLOW bne v0, zero, fpe_trap and v0, a1, MACH_FPC_ENABLE_INEXACT bne v0, zero, inexact_w # inexact traps enabled? b invalid_w/* * Compare single. */cmp_s: jal get_cmp_s bne t1, SEXP_INF, 1f # is FS an infinity? bne t2, zero, unordered # FS is a NAN1: bne t5, SEXP_INF, 2f # is FT an infinity? bne t6, zero, unordered # FT is a NAN2: sll t1, t1, 23 # reassemble exp & frac or t1, t1, t2 sll t5, t5, 23 # reassemble exp & frac or t5, t5, t6 beq t0, zero, 1f # is FS positive? negu t11: beq t4, zero, 1f # is FT positive? negu t51: li v0, COND_LESS blt t1, t5, test_cond # is FS < FT? li v0, COND_EQUAL beq t1, t5, test_cond # is FS == FT? move v0, zero # FS > FT b test_cond/* * Compare double. */cmp_d: jal get_cmp_d bne t1, DEXP_INF, 1f # is FS an infinity? bne t2, zero, unordered bne t3, zero, unordered # FS is a NAN1: bne t5, DEXP_INF, 2f # is FT an infinity? bne t6, zero, unordered bne t7, zero, unordered # FT is a NAN2: sll t1, t1, 20 # reassemble exp & frac or t1, t1, t2 sll t5, t5, 20 # reassemble exp & frac or t5, t5, t6 beq t0, zero, 1f # is FS positive? not t3 # negate t1,t3 not t1 addu t3, t3, 1 seq v0, t3, zero # compute carry addu t1, t1, v01: beq t4, zero, 1f # is FT positive? not t7 # negate t5,t7 not t5 addu t7, t7, 1 seq v0, t7, zero # compute carry addu t5, t5, v01: li v0, COND_LESS blt t1, t5, test_cond # is FS(MSW) < FT(MSW)? move v0, zero bne t1, t5, test_cond # is FS(MSW) > FT(MSW)? li v0, COND_LESS bltu t3, t7, test_cond # is FS(LSW) < FT(LSW)? li v0, COND_EQUAL beq t3, t7, test_cond # is FS(LSW) == FT(LSW)? move v0, zero # FS > FTtest_cond: and v0, v0, a0 # condition match instruction?set_cond: bne v0, zero, 1f and a1, a1, ~MACH_FPC_COND_BIT # clear condition bit b 2f1: or a1, a1, MACH_FPC_COND_BIT # set condition bit2: ctc1 a1, MACH_FPC_CSR # save condition bit b doneunordered: and v0, a0, COND_UNORDERED # this cmp match unordered? bne v0, zero, 1f and a1, a1, ~MACH_FPC_COND_BIT # clear condition bit b 2f1: or a1, a1, MACH_FPC_COND_BIT # set condition bit2: and v0, a0, COND_SIGNAL beq v0, zero, 1f # is this a signaling cmp? or a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID and v0, a1, MACH_FPC_ENABLE_INVALID bne v0, zero, fpe_trap1: ctc1 a1, MACH_FPC_CSR # save condition bit b done/* * Determine the amount to shift the fraction in order to restore the * normalized position. After that, round and handle exceptions. */norm_s: move v0, t2 move t9, zero # t9 = num of leading zeros bne t2, zero, 1f move v0, t8
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -