1@include "arm/unopWide.S" {"instr":"bl __aeabi_d2lz"} 2%include "arm/unopWide.S" {"instr":"bl d2l_doconv"} 3 4%break 5/* 6 * Convert the double in r0/r1 to a long in r0/r1. 7 * 8 * We have to clip values to long min/max per the specification. The 9 * expected common case is a "reasonable" value that converts directly 10 * to modest integer. The EABI convert function isn't doing this for us. 11 */ 12d2l_doconv: 13 stmfd sp!, {r4, r5, lr} @ save regs 14 mov r3, #0x43000000 @ maxlong, as a double (high word) 15 add r3, #0x00e00000 @ 0x43e00000 16 mov r2, #0 @ maxlong, as a double (low word) 17 sub sp, sp, #4 @ align for EABI 18 mov r4, r0 @ save a copy of r0 19 mov r5, r1 @ and r1 20 bl __aeabi_dcmpge @ is arg >= maxlong? 21 cmp r0, #0 @ nonzero == yes 22 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 23 mvnne r1, #0x80000000 24 bne 1f 25 26 mov r0, r4 @ recover arg 27 mov r1, r5 28 mov r3, #0xc3000000 @ minlong, as a double (high word) 29 add r3, #0x00e00000 @ 0xc3e00000 30 mov r2, #0 @ minlong, as a double (low word) 31 bl __aeabi_dcmple @ is arg <= minlong? 32 cmp r0, #0 @ nonzero == yes 33 movne r0, #0 @ return minlong (8000000000000000) 34 movne r1, #0x80000000 35 bne 1f 36 37 mov r0, r4 @ recover arg 38 mov r1, r5 39 mov r2, r4 @ compare against self 40 mov r3, r5 41 bl __aeabi_dcmpeq @ is arg == self? 42 cmp r0, #0 @ zero == no 43 moveq r1, #0 @ return zero for NaN 44 beq 1f 45 46 mov r0, r4 @ recover arg 47 mov r1, r5 48 bl __aeabi_d2lz @ convert double to long 49 501: 51 add sp, sp, #4 52 ldmfd sp!, {r4, r5, pc} 53