• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1%verify "executed"
2%include "mips/funopNarrower.S" {"instr":"b    d2i_doconv","instr_f":"b    d2i_doconv"}
3
4/*
5 * Convert the double in a0/a1 to an int in a0.
6 *
7 * We have to clip values to int 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 * Use rBIX / rOBJ as global to hold arguments (they are not bound to a global var)
11 */
12
13d2i_doconv:
14#ifdef SOFT_FLOAT
15    la          t0, .LDOUBLE_TO_INT_max
16    LOAD64(rARG2, rARG3, t0)
17    move        rBIX, rARG0                       # save a0
18    move        rOBJ, rARG1                       #  and a1
19    JAL(__gedf2)                               # is arg >= maxint?
20
21    move        t0, v0
22    li          v0, ~0x80000000                # return maxint (7fffffff)
23    bgez        t0, .L${opcode}_set_vreg       # nonzero == yes
24
25    move        rARG0, rBIX                       # recover arg
26    move        rARG1, rOBJ
27    la          t0, .LDOUBLE_TO_INT_min
28    LOAD64(rARG2, rARG3, t0)
29    JAL(__ledf2)                               # is arg <= minint?
30
31    move        t0, v0
32    li          v0, 0x80000000                 # return minint (80000000)
33    blez        t0, .L${opcode}_set_vreg       # nonzero == yes
34
35    move        rARG0, rBIX                  # recover arg
36    move        rARG1, rOBJ
37    move        rARG2, rBIX                  # compare against self
38    move        rARG3, rOBJ
39    JAL(__nedf2)                        # is arg == self?
40
41    move        t0, v0                  # zero == no
42    li          v0, 0
43    bnez        t0, .L${opcode}_set_vreg        # return zero for NaN
44
45    move        rARG0, rBIX                  # recover arg
46    move        rARG1, rOBJ
47    JAL(__fixdfsi)                      # convert double to int
48    b           .L${opcode}_set_vreg
49#else
50    la          t0, .LDOUBLE_TO_INT_max
51    LOAD64_F(fa1, fa1f, t0)
52    c.ole.d     fcc0, fa1, fa0
53    l.s         fv0, .LDOUBLE_TO_INT_maxret
54    bc1t        .L${opcode}_set_vreg_f
55
56    la          t0, .LDOUBLE_TO_INT_min
57    LOAD64_F(fa1, fa1f, t0)
58    c.ole.d     fcc0, fa0, fa1
59    l.s         fv0, .LDOUBLE_TO_INT_minret
60    bc1t        .L${opcode}_set_vreg_f
61
62    mov.d       fa1, fa0
63    c.un.d      fcc0, fa0, fa1
64    li.s        fv0, 0
65    bc1t        .L${opcode}_set_vreg_f
66
67    trunc.w.d   fv0, fa0
68    b           .L${opcode}_set_vreg_f
69#endif
70
71
72.LDOUBLE_TO_INT_max:
73    .dword   0x41dfffffffc00000
74.LDOUBLE_TO_INT_min:
75    .dword   0xc1e0000000000000                  # minint, as a double (high word)
76.LDOUBLE_TO_INT_maxret:
77    .word   0x7fffffff
78.LDOUBLE_TO_INT_minret:
79    .word   0x80000000
80