blob: b10081052e57bcf6c618e10e01b273508d4e4076 [file] [log] [blame]
buzbee1452bee2015-03-06 14:43:04 -08001@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}