| %include "mips/unopNarrower.S" {"instr":"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. |
| */ |
| %break |
| |
| d2i_doconv: |
| #ifdef MIPS32REVGE6 |
| la t0, .LDOUBLE_TO_INT_max |
| LOAD64_F(fa1, fa1f, t0) |
| cmp.le.d ft2, fa1, fa0 |
| l.s fv0, .LDOUBLE_TO_INT_maxret |
| bc1nez ft2, .L${opcode}_set_vreg_f |
| |
| la t0, .LDOUBLE_TO_INT_min |
| LOAD64_F(fa1, fa1f, t0) |
| cmp.le.d ft2, fa0, fa1 |
| l.s fv0, .LDOUBLE_TO_INT_minret |
| bc1nez ft2, .L${opcode}_set_vreg_f |
| |
| mov.d fa1, fa0 |
| cmp.un.d ft2, fa0, fa1 |
| li.s fv0, 0 |
| bc1nez ft2, .L${opcode}_set_vreg_f |
| #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 |
| #endif |
| |
| trunc.w.d fv0, fa0 |
| b .L${opcode}_set_vreg_f |
| |
| .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 |