📄 ieee754-sf.s
字号:
mvn r1, r2, asr #22 subs r1, r1, #7 bgt LSYM(Lml_ur) @ Shift value left, round, etc. add r1, r1, #32 orrs r0, r0, r3, lsr r1 rsb r1, r1, #32 adc r0, r0, ip, lsl r1 mov ip, r3, lsl r1 teq ip, #0x80000000 biceq r0, r0, #1 RET @ Shift value right, round, etc. @ Note: r1 must not be 0 otherwise carry does not get set.LSYM(Lml_ur): orrs r0, r0, ip, lsr r1 adc r0, r0, #0 rsb r1, r1, #32 mov ip, ip, lsl r1 teq r3, #0 teqeq ip, #0x80000000 biceq r0, r0, #1 RET @ One or both arguments are denormalized. @ Scale them leftwards and preserve sign bit.LSYM(Lml_d): teq r2, #0 and ip, r0, #0x800000001: moveq r0, r0, lsl #1 tsteq r0, #0x00800000 subeq r2, r2, #(1 << 22) beq 1b orr r0, r0, ip teq r3, #0 and ip, r1, #0x800000002: moveq r1, r1, lsl #1 tsteq r1, #0x00800000 subeq r3, r3, #(1 << 23) beq 2b orr r1, r1, ip b LSYM(Lml_x) @ One or both args are INF or NAN.LSYM(Lml_s): teq r0, #0x0 teqne r1, #0x0 teqne r0, #0x80000000 teqne r1, #0x80000000 beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN teq r2, ip, lsr #1 bne 1f movs r2, r0, lsl #9 bne LSYM(Lml_n) @ NAN * <anything> -> NAN1: teq r3, ip, lsr #1 bne LSYM(Lml_i) movs r3, r1, lsl #9 bne LSYM(Lml_n) @ <anything> * NAN -> NAN @ Result is INF, but we need to determine its sign.LSYM(Lml_i): eor r0, r0, r1 @ Overflow: return INF (sign already in r0).LSYM(Lml_o): and r0, r0, #0x80000000 orr r0, r0, #0x7f000000 orr r0, r0, #0x00800000 RET @ Return NAN.LSYM(Lml_n): mov r0, #0x7f000000 orr r0, r0, #0x00c00000 RET FUNC_END mulsf3ARM_FUNC_START divsf3 @ Mask out exponents. mov ip, #0xff000000 and r2, r0, ip, lsr #1 and r3, r1, ip, lsr #1 @ Trap any INF/NAN or zeroes. teq r2, ip, lsr #1 teqne r3, ip, lsr #1 bicnes ip, r0, #0x80000000 bicnes ip, r1, #0x80000000 beq LSYM(Ldv_s) @ Shift exponents right one bit to make room for overflow bit. @ If either of them is 0, scale denormalized arguments off line. @ Then substract divisor exponent from dividend''s. movs r2, r2, lsr #1 teqne r3, #0 beq LSYM(Ldv_d)LSYM(Ldv_x): sub r2, r2, r3, asr #1 @ Preserve final sign into ip. eor ip, r0, r1 @ Convert mantissa to unsigned integer. @ Dividend -> r3, divisor -> r1. mov r3, #0x10000000 movs r1, r1, lsl #9 mov r0, r0, lsl #9 beq LSYM(Ldv_1) orr r1, r3, r1, lsr #4 orr r3, r3, r0, lsr #4 @ Initialize r0 (result) with final sign bit. and r0, ip, #0x80000000 @ Ensure result will land to known bit position. cmp r3, r1 subcc r2, r2, #(1 << 22) movcc r3, r3, lsl #1 @ Apply exponent bias, check range for over/underflow. add r2, r2, #(127 << 22) cmn r2, #(24 << 22) RETc(le) cmp r2, #(255 << 22) bge LSYM(Lml_o) @ The actual division loop. mov ip, #0x008000001: cmp r3, r1 subcs r3, r3, r1 orrcs r0, r0, ip cmp r3, r1, lsr #1 subcs r3, r3, r1, lsr #1 orrcs r0, r0, ip, lsr #1 cmp r3, r1, lsr #2 subcs r3, r3, r1, lsr #2 orrcs r0, r0, ip, lsr #2 cmp r3, r1, lsr #3 subcs r3, r3, r1, lsr #3 orrcs r0, r0, ip, lsr #3 movs r3, r3, lsl #4 movnes ip, ip, lsr #4 bne 1b @ Check if denormalized result is needed. cmp r2, #0 ble LSYM(Ldv_u) @ Apply proper rounding. cmp r3, r1 addcs r0, r0, #1 biceq r0, r0, #1 @ Add exponent to result. bic r0, r0, #0x00800000 orr r0, r0, r2, lsl #1 RET @ Division by 0x1p*: let''s shortcut a lot of code.LSYM(Ldv_1): and ip, ip, #0x80000000 orr r0, ip, r0, lsr #9 add r2, r2, #(127 << 22) cmp r2, #(255 << 22) bge LSYM(Lml_o) cmp r2, #0 orrgt r0, r0, r2, lsl #1 RETc(gt) cmn r2, #(24 << 22) movle r0, ip RETc(le) orr r0, r0, #0x00800000 mov r3, #0 @ Result must be denormalized: prepare parameters to use code above. @ r3 already contains remainder for rounding considerations.LSYM(Ldv_u): bic ip, r0, #0x80000000 and r0, r0, #0x80000000 mvn r1, r2, asr #22 add r1, r1, #2 b LSYM(Lml_ur) @ One or both arguments are denormalized. @ Scale them leftwards and preserve sign bit.LSYM(Ldv_d): teq r2, #0 and ip, r0, #0x800000001: moveq r0, r0, lsl #1 tsteq r0, #0x00800000 subeq r2, r2, #(1 << 22) beq 1b orr r0, r0, ip teq r3, #0 and ip, r1, #0x800000002: moveq r1, r1, lsl #1 tsteq r1, #0x00800000 subeq r3, r3, #(1 << 23) beq 2b orr r1, r1, ip b LSYM(Ldv_x) @ One or both arguments is either INF, NAN or zero.LSYM(Ldv_s): mov ip, #0xff000000 teq r2, ip, lsr #1 teqeq r3, ip, lsr #1 beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN teq r2, ip, lsr #1 bne 1f movs r2, r0, lsl #9 bne LSYM(Lml_n) @ NAN / <anything> -> NAN b LSYM(Lml_i) @ INF / <anything> -> INF1: teq r3, ip, lsr #1 bne 2f movs r3, r1, lsl #9 bne LSYM(Lml_n) @ <anything> / NAN -> NAN b LSYM(Lml_z) @ <anything> / INF -> 02: @ One or both arguments are 0. bics r2, r0, #0x80000000 bne LSYM(Lml_i) @ <non_zero> / 0 -> INF bics r3, r1, #0x80000000 bne LSYM(Lml_z) @ 0 / <non_zero> -> 0 b LSYM(Lml_n) @ 0 / 0 -> NAN FUNC_END divsf3#endif /* L_muldivsf3 */#ifdef L_cmpsf2ARM_FUNC_START gtsf2ARM_FUNC_ALIAS gesf2 gtsf2 mov r3, #-1 b 1fARM_FUNC_START ltsf2ARM_FUNC_ALIAS lesf2 ltsf2 mov r3, #1 b 1fARM_FUNC_START cmpsf2ARM_FUNC_ALIAS nesf2 cmpsf2ARM_FUNC_ALIAS eqsf2 cmpsf2 mov r3, #1 @ how should we specify unordered here?1: @ Trap any INF/NAN first. mov ip, #0xff000000 and r2, r1, ip, lsr #1 teq r2, ip, lsr #1 and r2, r0, ip, lsr #1 teqne r2, ip, lsr #1 beq 3f @ Test for equality. @ Note that 0.0 is equal to -0.0.2: orr r3, r0, r1 bics r3, r3, #0x80000000 @ either 0.0 or -0.0 teqne r0, r1 @ or both the same moveq r0, #0 RETc(eq) @ Check for sign difference. The N flag is set if it is the case. @ If so, return sign of r0. movmi r0, r0, asr #31 orrmi r0, r0, #1 RETc(mi) @ Compare exponents. and r3, r1, ip, lsr #1 cmp r2, r3 @ Compare mantissa if exponents are equal moveq r0, r0, lsl #9 cmpeq r0, r1, lsl #9 movcs r0, r1, asr #31 mvncc r0, r1, asr #31 orr r0, r0, #1 RET @ Look for a NAN. 3: and r2, r1, ip, lsr #1 teq r2, ip, lsr #1 bne 4f movs r2, r1, lsl #9 bne 5f @ r1 is NAN4: and r2, r0, ip, lsr #1 teq r2, ip, lsr #1 bne 2b movs ip, r0, lsl #9 beq 2b @ r0 is not NAN5: mov r0, r3 @ return unordered code from r3. RET FUNC_END gesf2 FUNC_END gtsf2 FUNC_END lesf2 FUNC_END ltsf2 FUNC_END nesf2 FUNC_END eqsf2 FUNC_END cmpsf2#endif /* L_cmpsf2 */#ifdef L_unordsf2ARM_FUNC_START unordsf2 mov ip, #0xff000000 and r2, r1, ip, lsr #1 teq r2, ip, lsr #1 bne 1f movs r2, r1, lsl #9 bne 3f @ r1 is NAN1: and r2, r0, ip, lsr #1 teq r2, ip, lsr #1 bne 2f movs r2, r0, lsl #9 bne 3f @ r0 is NAN2: mov r0, #0 @ arguments are ordered. RET3: mov r0, #1 @ arguments are unordered. RET FUNC_END unordsf2#endif /* L_unordsf2 */#ifdef L_fixsfsiARM_FUNC_START fixsfsi movs r0, r0, lsl #1 RETc(eq) @ value is 0. mov r1, r1, rrx @ preserve C flag (the actual sign) @ check exponent range. and r2, r0, #0xff000000 cmp r2, #(127 << 24) movcc r0, #0 @ value is too small RETc(cc) cmp r2, #((127 + 31) << 24) bcs 1f @ value is too large mov r0, r0, lsl #7 orr r0, r0, #0x80000000 mov r2, r2, lsr #24 rsb r2, r2, #(127 + 31) tst r1, #0x80000000 @ the sign bit mov r0, r0, lsr r2 rsbne r0, r0, #0 RET1: teq r2, #0xff000000 bne 2f movs r0, r0, lsl #8 bne 3f @ r0 is NAN.2: ands r0, r1, #0x80000000 @ the sign bit moveq r0, #0x7fffffff @ the maximum signed positive si RET3: mov r0, #0 @ What should we convert NAN to? RET FUNC_END fixsfsi#endif /* L_fixsfsi */#ifdef L_fixunssfsiARM_FUNC_START fixunssfsi movs r0, r0, lsl #1 movcss r0, #0 @ value is negative... RETc(eq) @ ... or 0. @ check exponent range. and r2, r0, #0xff000000 cmp r2, #(127 << 24) movcc r0, #0 @ value is too small RETc(cc) cmp r2, #((127 + 32) << 24) bcs 1f @ value is too large mov r0, r0, lsl #7 orr r0, r0, #0x80000000 mov r2, r2, lsr #24 rsb r2, r2, #(127 + 31) mov r0, r0, lsr r2 RET1: teq r2, #0xff000000 bne 2f movs r0, r0, lsl #8 bne 3f @ r0 is NAN.2: mov r0, #0xffffffff @ maximum unsigned si RET3: mov r0, #0 @ What should we convert NAN to? RET FUNC_END fixunssfsi#endif /* L_fixunssfsi */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -