Home | History | Annotate | Download | only in mips
      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 
     13 d2i_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