1 %default { "naninst":"li rTEMP, -1" } 2 %verify "executed" 3 %verify "basic lt, gt, eq */ 4 %verify "left arg NaN" 5 %verify "right arg NaN" 6 /* 7 * Compare two floating-point values. Puts 0, 1, or -1 into the 8 * destination register based on the results of the comparison. 9 * 10 * Provide a "naninst" instruction that puts 1 or -1 into a1 depending 11 * on what value we'd like to return when one of the operands is NaN. 12 * 13 * The operation we're implementing is: 14 * if (x == y) 15 * return 0; 16 * else if (x < y) 17 * return -1; 18 * else if (x > y) 19 * return 1; 20 * else 21 * return {-1,1}; // one or both operands was NaN 22 * 23 * for: cmpl-float, cmpg-float 24 */ 25 /* op vAA, vBB, vCC */ 26 27 /* "clasic" form */ 28 FETCH(a0, 1) # a0 <- CCBB 29 and a2, a0, 255 # a2 <- BB 30 srl a3, a0, 8 31 #ifdef SOFT_FLOAT 32 GET_VREG(rOBJ, a2) # rOBJ <- vBB 33 GET_VREG(rBIX, a3) # rBIX <- vCC 34 move a0, rOBJ # a0 <- vBB 35 move a1, rBIX # a1 <- vCC 36 JAL(__eqsf2) # a0 <- (vBB == vCC) 37 li rTEMP, 0 # set rTEMP to 0 38 beqz v0, ${opcode}_finish 39 move a0, rOBJ # a0 <- vBB 40 move a1, rBIX # a1 <- vCC 41 JAL(__ltsf2) # a0 <- (vBB < vCC) 42 li rTEMP, -1 43 bltz v0, ${opcode}_finish 44 move a0, rOBJ # a0 <- vBB 45 move a1, rBIX # a1 <- vCC 46 b ${opcode}_continue 47 #else 48 GET_VREG_F(ft0, a2) 49 GET_VREG_F(ft1, a3) 50 c.olt.s fcc0, ft0, ft1 # Is ft0 < ft1 51 li rTEMP, -1 52 bc1t fcc0, ${opcode}_finish 53 c.olt.s fcc0, ft1, ft0 54 li rTEMP, 1 55 bc1t fcc0, ${opcode}_finish 56 c.eq.s fcc0, ft0, ft1 57 li rTEMP, 0 58 bc1t fcc0, ${opcode}_finish 59 b ${opcode}_nan 60 61 #endif 62 63 %break 64 65 ${opcode}_nan: 66 $naninst 67 b ${opcode}_finish 68 69 #ifdef SOFT_FLOAT 70 ${opcode}_continue: 71 JAL(__gtsf2) # v0 <- (vBB > vCC) 72 li rTEMP, 1 # rTEMP = 1 if v0 != 0 73 bgtz v0, ${opcode}_finish 74 b ${opcode}_nan 75 #endif 76 77 ${opcode}_finish: 78 GET_OPA(t0) 79 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 80 SET_VREG(rTEMP, t0) # vAA <- rTEMP 81 GET_INST_OPCODE(t0) # extract opcode from rINST 82 GOTO_OPCODE(t0) 83