Home | History | Annotate | Download | only in armv5te
      1 %default { "naninst":"mvn     r1, #0" }
      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 r1 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      * The straightforward implementation requires 3 calls to functions
     24      * that return a result in r0.  We can do it with two calls if our
     25      * EABI library supports __aeabi_cfcmple (only one if we want to check
     26      * for NaN directly):
     27      *   check x <= y
     28      *     if <, return -1
     29      *     if ==, return 0
     30      *   check y <= x
     31      *     if <, return 1
     32      *   return {-1,1}
     33      *
     34      * for: cmpl-float, cmpg-float
     35      */
     36     /* op vAA, vBB, vCC */
     37     FETCH(r0, 1)                        @ r0<- CCBB
     38     and     r2, r0, #255                @ r2<- BB
     39     mov     r3, r0, lsr #8              @ r3<- CC
     40     GET_VREG(r9, r2)                    @ r9<- vBB
     41     GET_VREG(r10, r3)                   @ r10<- vCC
     42     mov     r0, r9                      @ copy to arg registers
     43     mov     r1, r10
     44     bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
     45     bhi     .L${opcode}_gt_or_nan       @ C set and Z clear, disambiguate
     46     mvncc   r1, #0                      @ (less than) r1<- -1
     47     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
     48 .L${opcode}_finish:
     49     mov     r3, rINST, lsr #8           @ r3<- AA
     50     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     51     SET_VREG(r1, r3)                    @ vAA<- r1
     52     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     53     GOTO_OPCODE(ip)                     @ jump to next instruction
     54 %break
     55 
     56     @ Test for NaN with a second comparison.  EABI forbids testing bit
     57     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
     58     @ make the library call.
     59 .L${opcode}_gt_or_nan:
     60     mov     r1, r9                      @ reverse order
     61     mov     r0, r10
     62     bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
     63     @bleq    common_abort
     64     movcc   r1, #1                      @ (greater than) r1<- 1
     65     bcc     .L${opcode}_finish
     66     $naninst                            @ r1<- 1 or -1 for NaN
     67     b       .L${opcode}_finish
     68 
     69 
     70 #if 0       /* "clasic" form */
     71     FETCH(r0, 1)                        @ r0<- CCBB
     72     and     r2, r0, #255                @ r2<- BB
     73     mov     r3, r0, lsr #8              @ r3<- CC
     74     GET_VREG(r9, r2)                    @ r9<- vBB
     75     GET_VREG(r10, r3)                   @ r10<- vCC
     76     mov     r0, r9                      @ r0<- vBB
     77     mov     r1, r10                     @ r1<- vCC
     78     bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
     79     cmp     r0, #0                      @ equal?
     80     movne   r1, #0                      @ yes, result is 0
     81     bne     ${opcode}_finish
     82     mov     r0, r9                      @ r0<- vBB
     83     mov     r1, r10                     @ r1<- vCC
     84     bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
     85     cmp     r0, #0                      @ less than?
     86     b       ${opcode}_continue
     87 @%break
     88 
     89 ${opcode}_continue:
     90     mvnne   r1, #0                      @ yes, result is -1
     91     bne     ${opcode}_finish
     92     mov     r0, r9                      @ r0<- vBB
     93     mov     r1, r10                     @ r1<- vCC
     94     bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
     95     cmp     r0, #0                      @ greater than?
     96     beq     ${opcode}_nan               @ no, must be NaN
     97     mov     r1, #1                      @ yes, result is 1
     98     @ fall through to _finish
     99 
    100 ${opcode}_finish:
    101     mov     r3, rINST, lsr #8           @ r3<- AA
    102     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    103     SET_VREG(r1, r3)                    @ vAA<- r1
    104     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    105     GOTO_OPCODE(ip)                     @ jump to next instruction
    106 
    107     /*
    108      * This is expected to be uncommon, so we double-branch (once to here,
    109      * again back to _finish).
    110      */
    111 ${opcode}_nan:
    112     $naninst                            @ r1<- 1 or -1 for NaN
    113     b       ${opcode}_finish
    114 
    115 #endif
    116