📄 ieee754-df.s
字号:
cmphi ip, #0x700 bhi LSYM(Lml_u) @ Round the result, merge final exponent. cmp lr, #0x80000000 moveqs lr, xl, lsr #1 adcs xl, xl, #0 adc xh, xh, r4, lsl #20 RETLDM "r4, r5, r6" @ Multiplication by 0x1p*: let''s shortcut a lot of code.LSYM(Lml_1): and r6, r6, #0x80000000 orr xh, r6, xh orr xl, xl, yl eor xh, xh, yh subs r4, r4, ip, lsr #1 rsbgts r5, r4, ip orrgt xh, xh, r4, lsl #20 RETLDM "r4, r5, r6" gt @ Under/overflow: fix things up for the code below. orr xh, xh, #0x00100000 mov lr, #0 subs r4, r4, #1LSYM(Lml_u): @ Overflow? bgt LSYM(Lml_o) @ Check if denormalized result is possible, otherwise return signed 0. cmn r4, #(53 + 1) movle xl, #0 bicle xh, xh, #0x7fffffff RETLDM "r4, r5, r6" le @ Find out proper shift value. rsb r4, r4, #0 subs r4, r4, #32 bge 2f adds r4, r4, #12 bgt 1f @ shift result right of 1 to 20 bits, preserve sign bit, round, etc. add r4, r4, #20 rsb r5, r4, #32 mov r3, xl, lsl r5 mov xl, xl, lsr r4 orr xl, xl, xh, lsl r5 and r2, xh, #0x80000000 bic xh, xh, #0x80000000 adds xl, xl, r3, lsr #31 adc xh, r2, xh, lsr r4 orrs lr, lr, r3, lsl #1 biceq xl, xl, r3, lsr #31 RETLDM "r4, r5, r6" @ shift result right of 21 to 31 bits, or left 11 to 1 bits after @ a register switch from xh to xl. Then round.1: rsb r4, r4, #12 rsb r5, r4, #32 mov r3, xl, lsl r4 mov xl, xl, lsr r5 orr xl, xl, xh, lsl r4 bic xh, xh, #0x7fffffff adds xl, xl, r3, lsr #31 adc xh, xh, #0 orrs lr, lr, r3, lsl #1 biceq xl, xl, r3, lsr #31 RETLDM "r4, r5, r6" @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch @ from xh to xl. Leftover bits are in r3-r6-lr for rounding.2: rsb r5, r4, #32 orr lr, lr, xl, lsl r5 mov r3, xl, lsr r4 orr r3, r3, xh, lsl r5 mov xl, xh, lsr r4 bic xh, xh, #0x7fffffff bic xl, xl, xh, lsr r4 add xl, xl, r3, lsr #31 orrs lr, lr, r3, lsl #1 biceq xl, xl, r3, lsr #31 RETLDM "r4, r5, r6" @ One or both arguments are denormalized. @ Scale them leftwards and preserve sign bit.LSYM(Lml_d): teq r4, #0 bne 2f and r6, xh, #0x800000001: movs xl, xl, lsl #1 adc xh, xh, xh tst xh, #0x00100000 subeq r4, r4, #1 beq 1b orr xh, xh, r6 teq r5, #0 movne pc, lr2: and r6, yh, #0x800000003: movs yl, yl, lsl #1 adc yh, yh, yh tst yh, #0x00100000 subeq r5, r5, #1 beq 3b orr yh, yh, r6 mov pc, lrLSYM(Lml_s): @ Isolate the INF and NAN cases away teq r4, ip and r5, ip, yh, lsr #20 teqne r5, ip beq 1f @ Here, one or more arguments are either denormalized or zero. orrs r6, xl, xh, lsl #1 orrnes r6, yl, yh, lsl #1 bne LSYM(Lml_d) @ Result is 0, but determine sign anyway.LSYM(Lml_z): eor xh, xh, yh bic xh, xh, #0x7fffffff mov xl, #0 RETLDM "r4, r5, r6"1: @ One or both args are INF or NAN. orrs r6, xl, xh, lsl #1 moveq xl, yl moveq xh, yh orrnes r6, yl, yh, lsl #1 beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN teq r4, ip bne 1f orrs r6, xl, xh, lsl #12 bne LSYM(Lml_n) @ NAN * <anything> -> NAN1: teq r5, ip bne LSYM(Lml_i) orrs r6, yl, yh, lsl #12 movne xl, yl movne xh, yh bne LSYM(Lml_n) @ <anything> * NAN -> NAN @ Result is INF, but we need to determine its sign.LSYM(Lml_i): eor xh, xh, yh @ Overflow: return INF (sign already in xh).LSYM(Lml_o): and xh, xh, #0x80000000 orr xh, xh, #0x7f000000 orr xh, xh, #0x00f00000 mov xl, #0 RETLDM "r4, r5, r6" @ Return a quiet NAN.LSYM(Lml_n): orr xh, xh, #0x7f000000 orr xh, xh, #0x00f80000 RETLDM "r4, r5, r6" FUNC_END aeabi_dmul FUNC_END muldf3ARM_FUNC_START divdf3ARM_FUNC_ALIAS aeabi_ddiv divdf3 stmfd sp!, {r4, r5, r6, lr} @ Mask out exponents, trap any zero/denormal/INF/NAN. mov ip, #0xff orr ip, ip, #0x700 ands r4, ip, xh, lsr #20 andnes r5, ip, yh, lsr #20 teqne r4, ip teqne r5, ip bleq LSYM(Ldv_s) @ Substract divisor exponent from dividend''s. sub r4, r4, r5 @ Preserve final sign into lr. eor lr, xh, yh @ Convert mantissa to unsigned integer. @ Dividend -> r5-r6, divisor -> yh-yl. orrs r5, yl, yh, lsl #12 mov xh, xh, lsl #12 beq LSYM(Ldv_1) mov yh, yh, lsl #12 mov r5, #0x10000000 orr yh, r5, yh, lsr #4 orr yh, yh, yl, lsr #24 mov yl, yl, lsl #8 orr r5, r5, xh, lsr #4 orr r5, r5, xl, lsr #24 mov r6, xl, lsl #8 @ Initialize xh with final sign bit. and xh, lr, #0x80000000 @ Ensure result will land to known bit position. @ Apply exponent bias accordingly. cmp r5, yh cmpeq r6, yl adc r4, r4, #(255 - 2) add r4, r4, #0x300 bcs 1f movs yh, yh, lsr #1 mov yl, yl, rrx1: @ Perform first substraction to align result to a nibble. subs r6, r6, yl sbc r5, r5, yh movs yh, yh, lsr #1 mov yl, yl, rrx mov xl, #0x00100000 mov ip, #0x00080000 @ The actual division loop.1: subs lr, r6, yl sbcs lr, r5, yh subcs r6, r6, yl movcs r5, lr orrcs xl, xl, ip movs yh, yh, lsr #1 mov yl, yl, rrx subs lr, r6, yl sbcs lr, r5, yh subcs r6, r6, yl movcs r5, lr orrcs xl, xl, ip, lsr #1 movs yh, yh, lsr #1 mov yl, yl, rrx subs lr, r6, yl sbcs lr, r5, yh subcs r6, r6, yl movcs r5, lr orrcs xl, xl, ip, lsr #2 movs yh, yh, lsr #1 mov yl, yl, rrx subs lr, r6, yl sbcs lr, r5, yh subcs r6, r6, yl movcs r5, lr orrcs xl, xl, ip, lsr #3 orrs lr, r5, r6 beq 2f mov r5, r5, lsl #4 orr r5, r5, r6, lsr #28 mov r6, r6, lsl #4 mov yh, yh, lsl #3 orr yh, yh, yl, lsr #29 mov yl, yl, lsl #3 movs ip, ip, lsr #4 bne 1b @ We are done with a word of the result. @ Loop again for the low word if this pass was for the high word. tst xh, #0x00100000 bne 3f orr xh, xh, xl mov xl, #0 mov ip, #0x80000000 b 1b2: @ Be sure result starts in the high word. tst xh, #0x00100000 orreq xh, xh, xl moveq xl, #03: @ Check exponent range for under/overflow. subs ip, r4, #(254 - 1) cmphi ip, #0x700 bhi LSYM(Lml_u) @ Round the result, merge final exponent. subs ip, r5, yh subeqs ip, r6, yl moveqs ip, xl, lsr #1 adcs xl, xl, #0 adc xh, xh, r4, lsl #20 RETLDM "r4, r5, r6" @ Division by 0x1p*: shortcut a lot of code.LSYM(Ldv_1): and lr, lr, #0x80000000 orr xh, lr, xh, lsr #12 adds r4, r4, ip, lsr #1 rsbgts r5, r4, ip orrgt xh, xh, r4, lsl #20 RETLDM "r4, r5, r6" gt orr xh, xh, #0x00100000 mov lr, #0 subs r4, r4, #1 b LSYM(Lml_u) @ Result mightt need to be denormalized: put remainder bits @ in lr for rounding considerations.LSYM(Ldv_u): orr lr, r5, r6 b LSYM(Lml_u) @ One or both arguments is either INF, NAN or zero.LSYM(Ldv_s): and r5, ip, yh, lsr #20 teq r4, ip teqeq r5, ip beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN teq r4, ip bne 1f orrs r4, xl, xh, lsl #12 bne LSYM(Lml_n) @ NAN / <anything> -> NAN teq r5, ip bne LSYM(Lml_i) @ INF / <anything> -> INF mov xl, yl mov xh, yh b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN1: teq r5, ip bne 2f orrs r5, yl, yh, lsl #12 beq LSYM(Lml_z) @ <anything> / INF -> 0 mov xl, yl mov xh, yh b LSYM(Lml_n) @ <anything> / NAN -> NAN2: @ If both are non-zero, we need to normalize and resume above. orrs r6, xl, xh, lsl #1 orrnes r6, yl, yh, lsl #1 bne LSYM(Lml_d) @ One or both arguments are 0. orrs r4, xl, xh, lsl #1 bne LSYM(Lml_i) @ <non_zero> / 0 -> INF orrs r5, yl, yh, lsl #1 bne LSYM(Lml_z) @ 0 / <non_zero> -> 0 b LSYM(Lml_n) @ 0 / 0 -> NAN FUNC_END aeabi_ddiv FUNC_END divdf3#endif /* L_muldivdf3 */#ifdef L_cmpdf2@ Note: only r0 (return value) and ip are clobbered here.ARM_FUNC_START gtdf2ARM_FUNC_ALIAS gedf2 gtdf2 mov ip, #-1 b 1fARM_FUNC_START ltdf2ARM_FUNC_ALIAS ledf2 ltdf2 mov ip, #1 b 1fARM_FUNC_START cmpdf2ARM_FUNC_ALIAS nedf2 cmpdf2ARM_FUNC_ALIAS eqdf2 cmpdf2 mov ip, #1 @ how should we specify unordered here?1: str ip, [sp, #-4] @ Trap any INF/NAN first. mov ip, xh, lsl #1 mvns ip, ip, asr #21 mov ip, yh, lsl #1 mvnnes ip, ip, asr #21 beq 3f @ Test for equality. @ Note that 0.0 is equal to -0.0.2: orrs ip, xl, xh, lsl #1 @ if x == 0.0 or -0.0 orreqs ip, yl, yh, lsl #1 @ and y == 0.0 or -0.0 teqne xh, yh @ or xh == yh teqeq xl, yl @ and xl == yl moveq r0, #0 @ then equal. RETc(eq) @ Clear C flag cmn r0, #0 @ Compare sign, teq xh, yh @ Compare values if same sign cmppl xh, yh cmpeq xl, yl @ Result: movcs r0, yh, asr #31 mvncc r0, yh, asr #31 orr r0, r0, #1 RET @ Look for a NAN.3: mov ip, xh, lsl #1 mvns ip, ip, asr #21 bne 4f orrs ip, xl, xh, lsl #12 bne 5f @ x is NAN4: mov ip, yh, lsl #1 mvns ip, ip, asr #21 bne 2b orrs ip, yl, yh, lsl #12 beq 2b @ y is not NAN5: ldr r0, [sp, #-4] @ unordered return code RET FUNC_END gedf2 FUNC_END gtdf2 FUNC_END ledf2 FUNC_END ltdf2 FUNC_END nedf2 FUNC_END eqdf2 FUNC_END cmpdf2ARM_FUNC_START aeabi_cdrcmple mov ip, r0 mov r0, r2 mov r2, ip mov ip, r1 mov r1, r3 mov r3, ip b 6f ARM_FUNC_START aeabi_cdcmpeqARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq @ The status-returning routines are required to preserve all @ registers except ip, lr, and cpsr.6: stmfd sp!, {r0, lr} ARM_CALL cmpdf2 @ Set the Z flag correctly, and the C flag unconditionally. cmp r0, #0 @ Clear the C flag if the return value was -1, indicating @ that the first operand was smaller than the second. cmnmi r0, #0 RETLDM "r0" FUNC_END aeabi_cdcmple FUNC_END aeabi_cdcmpeq FUNC_END aeabi_cdrcmple ARM_FUNC_START aeabi_dcmpeq str lr, [sp, #-4]! ARM_CALL aeabi_cdcmple moveq r0, #1 @ Equal to. movne r0, #0 @ Less than, greater than, or unordered. RETLDM FUNC_END aeabi_dcmpeqARM_FUNC_START aeabi_dcmplt str lr, [sp, #-4]! ARM_CALL aeabi_cdcmple movcc r0, #1 @ Less than. movcs r0, #0 @ Equal to, greater than, or unordered. RETLDM FUNC_END aeabi_dcmpltARM_FUNC_START aeabi_dcmple str lr, [sp, #-4]! ARM_CALL aeabi_cdcmple movls r0, #1 @ Less than or equal to. movhi r0, #0 @ Greater than or unordered. RETLDM FUNC_END aeabi_dcmpleARM_FUNC_START aeabi_dcmpge str lr, [sp, #-4]! ARM_CALL aeabi_cdrcmple movls r0, #1 @ Operand 2 is less than or equal to operand 1. movhi r0, #0 @ Operand 2 greater than operand 1, or unordered. RETLDM FUNC_END aeabi_dcmpgeARM_FUNC_START aeabi_dcmpgt str lr, [sp, #-4]! ARM_CALL aeabi_cdrcmple movcc r0, #1 @ Operand 2 is less than operand 1. movcs r0, #0 @ Operand 2 is greater than or equal to operand 1, @ or they are unordered. RETLDM FUNC_END aeabi_dcmpgt#endif /* L_cmpdf2 */#ifdef L_unorddf2ARM_FUNC_START unorddf2ARM_FUNC_ALIAS aeabi_dcmpun unorddf2 mov ip, xh, lsl #1 mvns ip, ip, asr #21 bne 1f orrs ip, xl, xh, lsl #12 bne 3f @ x is NAN1: mov ip, yh, lsl #1 mvns ip, ip, asr #21 bne 2f orrs ip, yl, yh, lsl #12 bne 3f @ y is NAN2: mov r0, #0 @ arguments are ordered. RET3: mov r0, #1 @ arguments are unordered. RET FUNC_END aeabi_dcmpun FUNC_END unorddf2#endif /* L_unorddf2 */#ifdef L_fixdfsiARM_FUNC_START fixdfsiARM_FUNC_ALIAS aeabi_d2iz fixdfsi @ check exponent range. mov r2, xh, lsl #1 adds r2, r2, #(1 << 21) bcs 2f @ value is INF or NAN bpl 1f @ value is too small mov r3, #(0xfffffc00 + 31) subs r2, r3, r2, asr #21 bls 3f @ value is too large @ scale value mov r3, xh, lsl #11 orr r3, r3, #0x80000000 orr r3, r3, xl, lsr #21 tst xh, #0x80000000 @ the sign bit mov r0, r3, lsr r2 rsbne r0, r0, #0 RET1: mov r0, #0 RET2: orrs xl, xl, xh, lsl #12 bne 4f @ x is NAN.3: ands r0, xh, #0x80000000 @ the sign bit moveq r0, #0x7fffffff @ maximum signed positive si RET4: mov r0, #0 @ How should we convert NAN? RET FUNC_END aeabi_d2iz FUNC_END fixdfsi#endif /* L_fixdfsi */#ifdef L_fixunsdfsiARM_FUNC_START fixunsdfsiARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi @ check exponent range. movs r2, xh, lsl #1 bcs 1f @ value is negative adds r2, r2, #(1 << 21) bcs 2f @ value is INF or NAN bpl 1f @ value is too small mov r3, #(0xfffffc00 + 31) subs r2, r3, r2, asr #21 bmi 3f @ value is too large @ scale value mov r3, xh, lsl #11 orr r3, r3, #0x80000000 orr r3, r3, xl, lsr #21 mov r0, r3, lsr r2 RET1: mov r0, #0 RET2: orrs xl, xl, xh, lsl #12 bne 4f @ value is NAN.3: mov r0, #0xffffffff @ maximum unsigned si RET4: mov r0, #0 @ How should we convert NAN? RET FUNC_END aeabi_d2uiz FUNC_END fixunsdfsi#endif /* L_fixunsdfsi */#ifdef L_truncdfsf2ARM_FUNC_START truncdfsf2ARM_FUNC_ALIAS aeabi_d2f truncdfsf2 @ check exponent range. mov r2, xh, lsl #1 subs r3, r2, #((1023 - 127) << 21) subcss ip, r3, #(1 << 21) rsbcss ip, ip, #(254 << 21) bls 2f @ value is out of range1: @ shift and round mantissa and ip, xh, #0x80000000 mov r2, xl, lsl #3 orr xl, ip, xl, lsr #29 cmp r2, #0x80000000 adc r0, xl, r3, lsl #2 biceq r0, r0, #1 RET2: @ either overflow or underflow tst xh, #0x40000000 bne 3f @ overflow @ check if denormalized value is possible adds r2, r3, #(23 << 21) andlt r0, xh, #0x80000000 @ too small, return signed 0. RETc(lt) @ denormalize value so we can resume with the code above afterwards. orr xh, xh, #0x00100000 mov r2, r2, lsr #21 rsb r2, r2, #24 rsb ip, r2, #32 movs r3, xl, lsl ip mov xl, xl, lsr r2 orrne xl, xl, #1 @ fold r3 for rounding considerations. mov r3, xh, lsl #11 mov r3, r3, lsr #11 orr xl, xl, r3, lsl ip mov r3, r3, lsr r2 mov r3, r3, lsl #1 b 1b3: @ chech for NAN mvns r3, r2, asr #21 bne 5f @ simple overflow orrs r3, xl, xh, lsl #12 movne r0, #0x7f000000 orrne r0, r0, #0x00c00000 RETc(ne) @ return NAN5: @ return INF with sign and r0, xh, #0x80000000 orr r0, r0, #0x7f000000 orr r0, r0, #0x00800000 RET FUNC_END aeabi_d2f FUNC_END truncdfsf2#endif /* L_truncdfsf2 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -