1%include "mips/unopNarrower.S" {"instr":"b d2i_doconv"}
2/*
3 * Convert the double in a0/a1 to an int in a0.
4 *
5 * We have to clip values to int min/max per the specification.  The
6 * expected common case is a "reasonable" value that converts directly
7 * to modest integer.  The EABI convert function isn't doing this for us.
8 */
9%break
10
11d2i_doconv:
12#ifdef MIPS32REVGE6
13    la        t0, .LDOUBLE_TO_INT_max
14    LOAD64_F(fa1, fa1f, t0)
15    cmp.ule.d ft2, fa1, fa0
16    l.s       fv0, .LDOUBLE_TO_INT_maxret
17    bc1nez    ft2, .L${opcode}_set_vreg_f
18
19    la        t0, .LDOUBLE_TO_INT_min
20    LOAD64_F(fa1, fa1f, t0)
21    cmp.ule.d ft2, fa0, fa1
22    l.s       fv0, .LDOUBLE_TO_INT_minret
23    bc1nez    ft2, .L${opcode}_set_vreg_f
24
25    mov.d     fa1, fa0
26    cmp.un.d  ft2, fa0, fa1
27    li.s      fv0, 0
28    bc1nez    ft2, .L${opcode}_set_vreg_f
29#else
30    la        t0, .LDOUBLE_TO_INT_max
31    LOAD64_F(fa1, fa1f, t0)
32    c.ole.d   fcc0, fa1, fa0
33    l.s       fv0, .LDOUBLE_TO_INT_maxret
34    bc1t      .L${opcode}_set_vreg_f
35
36    la        t0, .LDOUBLE_TO_INT_min
37    LOAD64_F(fa1, fa1f, t0)
38    c.ole.d   fcc0, fa0, fa1
39    l.s       fv0, .LDOUBLE_TO_INT_minret
40    bc1t      .L${opcode}_set_vreg_f
41
42    mov.d     fa1, fa0
43    c.un.d    fcc0, fa0, fa1
44    li.s      fv0, 0
45    bc1t      .L${opcode}_set_vreg_f
46#endif
47
48    trunc.w.d  fv0, fa0
49    b         .L${opcode}_set_vreg_f
50
51.LDOUBLE_TO_INT_max:
52    .dword 0x41dfffffffc00000
53.LDOUBLE_TO_INT_min:
54    .dword 0xc1e0000000000000              #  minint, as a double (high word)
55.LDOUBLE_TO_INT_maxret:
56    .word 0x7fffffff
57.LDOUBLE_TO_INT_minret:
58    .word 0x80000000
59