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