1%include "arm/unopWide.S" {"instr":"bl      d2l_doconv"}
2
3%break
4/*
5 * Convert the double in r0/r1 to a long in r0/r1.
6 *
7 * We have to clip values to long min/max per the specification.  The
8 * expected common case is a "reasonable" value that converts directly
9 * to modest integer.  The EABI convert function isn't doing this for us.
10 */
11d2l_doconv:
12    ubfx    r2, r1, #20, #11            @ grab the exponent
13    movw    r3, #0x43e
14    cmp     r2, r3                      @ MINLONG < x > MAXLONG?
15    bhs     d2l_special_cases
16    b       __aeabi_d2lz                @ tail call to convert double to long
17d2l_special_cases:
18    movw    r3, #0x7ff
19    cmp     r2, r3
20    beq     d2l_maybeNaN                @ NaN?
21d2l_notNaN:
22    adds    r1, r1, r1                  @ sign bit to carry
23    mov     r0, #0xffffffff             @ assume maxlong for lsw
24    mov     r1, #0x7fffffff             @ assume maxlong for msw
25    adc     r0, r0, #0
26    adc     r1, r1, #0                  @ convert maxlong to minlong if exp negative
27    bx      lr                          @ return
28d2l_maybeNaN:
29    orrs    r3, r0, r1, lsl #12
30    beq     d2l_notNaN                  @ if fraction is non-zero, it's a NaN
31    mov     r0, #0
32    mov     r1, #0
33    bx      lr                          @ return 0 for NaN
34