| %verify "executed" |
| %include "mips/unopNarrower.S" {"instr":"b d2i_doconv", "instr_f":"b d2i_doconv"} |
| /* |
| * Convert the double in a0/a1 to an int in a0. |
| * |
| * We have to clip values to int min/max per the specification. The |
| * expected common case is a "reasonable" value that converts directly |
| * to modest integer. The EABI convert function isn't doing this for us. |
| * Use rBIX / rTEMP as global to hold arguments (they are not bound to a global var) |
| */ |
| %break |
| |
| |
| d2i_doconv: |
| #ifdef SOFT_FLOAT |
| la t0, .LDOUBLE_TO_INT_max |
| LOAD64(rARG2, rARG3, t0) |
| move rBIX, rARG0 # save a0 |
| move rTEMP, rARG1 # and a1 |
| JAL(__gedf2) # is arg >= maxint? |
| |
| move t0, v0 |
| li v0, ~0x80000000 # return maxint (7fffffff) |
| bgez t0, .L${opcode}_set_vreg # nonzero == yes |
| |
| move rARG0, rBIX # recover arg |
| move rARG1, rTEMP |
| la t0, .LDOUBLE_TO_INT_min |
| LOAD64(rARG2, rARG3, t0) |
| JAL(__ledf2) # is arg <= minint? |
| |
| move t0, v0 |
| li v0, 0x80000000 # return minint (80000000) |
| blez t0, .L${opcode}_set_vreg # nonzero == yes |
| |
| move rARG0, rBIX # recover arg |
| move rARG1, rTEMP |
| move rARG2, rBIX # compare against self |
| move rARG3, rTEMP |
| JAL(__nedf2) # is arg == self? |
| |
| move t0, v0 # zero == no |
| li v0, 0 |
| bnez t0, .L${opcode}_set_vreg # return zero for NaN |
| |
| move rARG0, rBIX # recover arg |
| move rARG1, rTEMP |
| JAL(__fixdfsi) # convert double to int |
| b .L${opcode}_set_vreg |
| #else |
| la t0, .LDOUBLE_TO_INT_max |
| LOAD64_F(fa1, fa1f, t0) |
| c.ole.d fcc0, fa1, fa0 |
| l.s fv0, .LDOUBLE_TO_INT_maxret |
| bc1t .L${opcode}_set_vreg_f |
| |
| la t0, .LDOUBLE_TO_INT_min |
| LOAD64_F(fa1, fa1f, t0) |
| c.ole.d fcc0, fa0, fa1 |
| l.s fv0, .LDOUBLE_TO_INT_minret |
| bc1t .L${opcode}_set_vreg_f |
| |
| mov.d fa1, fa0 |
| c.un.d fcc0, fa0, fa1 |
| li.s fv0, 0 |
| bc1t .L${opcode}_set_vreg_f |
| |
| trunc.w.d fv0, fa0 |
| b .L${opcode}_set_vreg_f |
| #endif |
| |
| |
| .LDOUBLE_TO_INT_max: |
| .dword 0x41dfffffffc00000 |
| .LDOUBLE_TO_INT_min: |
| .dword 0xc1e0000000000000 # minint, as a double (high word) |
| .LDOUBLE_TO_INT_maxret: |
| .word 0x7fffffff |
| .LDOUBLE_TO_INT_minret: |
| .word 0x80000000 |