1%default { "naninst":"li rTEMP, -1" }
2    /*
3     * Compare two floating-point values.  Puts 0, 1, or -1 into the
4     * destination register rTEMP based on the results of the comparison.
5     *
6     * Provide a "naninst" instruction that puts 1 or -1 into rTEMP depending
7     * on what value we'd like to return when one of the operands is NaN.
8     *
9     * The operation we're implementing is:
10     *   if (x == y)
11     *     return 0;
12     *   else if (x < y)
13     *     return -1;
14     *   else if (x > y)
15     *     return 1;
16     *   else
17     *     return {-1 or 1};  // one or both operands was NaN
18     *
19     * for: cmpl-float, cmpg-float
20     */
21    /* op vAA, vBB, vCC */
22
23    /* "clasic" form */
24    FETCH(a0, 1)                           #  a0 <- CCBB
25    and       a2, a0, 255                  #  a2 <- BB
26    srl       a3, a0, 8
27    GET_VREG_F(ft0, a2)
28    GET_VREG_F(ft1, a3)
29#ifdef MIPS32REVGE6
30    cmp.ult.s ft2, ft0, ft1               # Is ft0 < ft1
31    li        rTEMP, -1
32    bc1nez    ft2, .L${opcode}_finish
33    cmp.ult.s ft2, ft1, ft0
34    li        rTEMP, 1
35    bc1nez    ft2, .L${opcode}_finish
36    cmp.eq.s  ft2, ft0, ft1
37    li        rTEMP, 0
38    bc1nez    ft2, .L${opcode}_finish
39    b         .L${opcode}_nan
40#else
41    c.olt.s   fcc0, ft0, ft1               # Is ft0 < ft1
42    li        rTEMP, -1
43    bc1t      fcc0, .L${opcode}_finish
44    c.olt.s   fcc0, ft1, ft0
45    li        rTEMP, 1
46    bc1t      fcc0, .L${opcode}_finish
47    c.eq.s    fcc0, ft0, ft1
48    li        rTEMP, 0
49    bc1t      fcc0, .L${opcode}_finish
50    b         .L${opcode}_nan
51#endif
52%break
53
54.L${opcode}_nan:
55    $naninst
56
57.L${opcode}_finish:
58    GET_OPA(rOBJ)
59    FETCH_ADVANCE_INST(2)                  #  advance rPC, load rINST
60    GET_INST_OPCODE(t0)                    #  extract opcode from rINST
61    SET_VREG_GOTO(rTEMP, rOBJ, t0)         #  vAA <- rTEMP
62