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