| %default { "naninst":"li rTEMP, -1" } |
| %verify "executed" |
| %verify "basic lt, gt, eq */ |
| %verify "left arg NaN" |
| %verify "right arg NaN" |
| /* |
| * Compare two double precision floating-point values. Puts 0, 1, or -1 into the |
| * destination register based on the results of the comparison. |
| * |
| * Provide a "naninst" instruction that puts 1 or -1 into a1 depending |
| * on what value we'd like to return when one of the operands is NaN. |
| * |
| * The operation we're implementing is: |
| * if (x == y) |
| * return 0; |
| * else if (x < y) |
| * return -1; |
| * else if (x > y) |
| * return 1; |
| * else |
| * return {-1,1}; // one or both operands was NaN |
| * |
| * On entry: |
| * a0 = &op1 [vBB] |
| * a1 = &op2 [vCC] |
| * |
| * for: cmpl-double, cmpg-double |
| */ |
| /* op vAA, vBB, vCC */ |
| |
| /* "clasic" form */ |
| #ifdef SOFT_FLOAT |
| move rOBJ, a0 # save a0 |
| move rBIX, a1 # save a1 |
| LOAD64(rARG0, rARG1, rOBJ) # a0/a1<- vBB/vBB+1 |
| LOAD64(rARG2, rARG3, rBIX) # a2/a3<- vCC/vCC+1 |
| JAL(__eqdf2) # v0<- (vBB == vCC) |
| li rTEMP, 0 # vAA<- 0 |
| beqz v0, ${opcode}_finish |
| LOAD64(rARG0, rARG1, rOBJ) # a0/a1<- vBB/vBB+1 |
| LOAD64(rARG2, rARG3, rBIX) # a2/a3<- vCC/vCC+1 |
| JAL(__ltdf2) # a0<- (vBB < vCC) |
| li rTEMP, -1 # vAA<- -1 |
| bltz v0, ${opcode}_finish |
| LOAD64(rARG0, rARG1, rOBJ) # a0/a1<- vBB/vBB+1 |
| LOAD64(rARG2, rARG3, rBIX) # a2/a3<- vCC/vCC+1 |
| JAL(__gtdf2) # v0<- (vBB > vCC) |
| li rTEMP, 1 # vAA<- 1 |
| bgtz v0, ${opcode}_finish |
| #else |
| LOAD64_F(fs0, fs0f, a0) # fs0<- vBB |
| LOAD64_F(fs1, fs1f, a1) # fs1<- vCC |
| c.olt.d fcc0, fs0, fs1 # Is fs0 < fs1 |
| li rTEMP, -1 |
| bc1t fcc0, ${opcode}_finish |
| c.olt.d fcc0, fs1, fs0 |
| li rTEMP, 1 |
| bc1t fcc0, ${opcode}_finish |
| c.eq.d fcc0, fs0, fs1 |
| li rTEMP, 0 |
| bc1t fcc0, ${opcode}_finish |
| #endif |
| |
| $naninst |
| |
| ${opcode}_finish: |
| move v0, rTEMP # v0<- vAA |
| RETURN |