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