Home | History | Annotate | Download | only in x86
      1 %def fpcmp(suff="d", nanval="pos"):
      2 /*
      3  * Compare two floating-point values.  Puts 0, 1, or -1 into the
      4  * destination register based on the results of the comparison.
      5  *
      6  * int compare(x, y) {
      7  *     if (x == y) {
      8  *         return 0;
      9  *     } else if (x < y) {
     10  *         return -1;
     11  *     } else if (x > y) {
     12  *         return 1;
     13  *     } else {
     14  *         return nanval ? 1 : -1;
     15  *     }
     16  * }
     17  */
     18     /* op vAA, vBB, vCC */
     19     movzbl  3(rPC), %ecx                    # ecx<- CC
     20     movzbl  2(rPC), %eax                    # eax<- BB
     21     GET_VREG_XMM${suff} %xmm0, %eax
     22     xor     %eax, %eax
     23     ucomis${suff} VREG_ADDRESS(%ecx), %xmm0
     24     jp      .L${opcode}_nan_is_${nanval}
     25     je      .L${opcode}_finish
     26     jb      .L${opcode}_less
     27 .L${opcode}_nan_is_pos:
     28     incl    %eax
     29     jmp     .L${opcode}_finish
     30 .L${opcode}_nan_is_neg:
     31 .L${opcode}_less:
     32     decl    %eax
     33 .L${opcode}_finish:
     34     SET_VREG %eax, rINST
     35     ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
     36 
     37 %def fpcvt(instr="", load="", store="", wide="0"):
     38 /*
     39  * Generic 32-bit FP conversion operation.
     40  */
     41     /* unop vA, vB */
     42     movzbl  rINSTbl, %ecx                   # ecx <- A+
     43     sarl    $$4, rINST                      # rINST <- B
     44     $load   VREG_ADDRESS(rINST)             # %st0 <- vB
     45     andb    $$0xf, %cl                      # ecx <- A
     46     $instr
     47     $store  VREG_ADDRESS(%ecx)              # vA <- %st0
     48     .if $wide
     49     CLEAR_WIDE_REF %ecx
     50     .else
     51     CLEAR_REF %ecx
     52     .endif
     53     ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
     54 
     55 %def sseBinop(instr="", suff=""):
     56     movzbl  2(rPC), %ecx                    # ecx <- BB
     57     movzbl  3(rPC), %eax                    # eax <- CC
     58     GET_VREG_XMM${suff} %xmm0, %ecx         # %xmm0 <- 1st src
     59     ${instr}${suff} VREG_ADDRESS(%eax), %xmm0
     60     SET_VREG_XMM${suff} %xmm0, rINST        # vAA <- %xmm0
     61     pxor    %xmm0, %xmm0
     62     movs${suff}   %xmm0, VREG_REF_ADDRESS(rINST) # clear ref
     63     ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
     64 
     65 %def sseBinop2Addr(instr="", suff=""):
     66     movzx   rINSTbl, %ecx                   # ecx <- A+
     67     andl    $$0xf, %ecx                     # ecx <- A
     68     GET_VREG_XMM${suff} %xmm0, %ecx         # %xmm0 <- 1st src
     69     sarl    $$4, rINST                      # rINST<- B
     70     ${instr}${suff} VREG_ADDRESS(rINST), %xmm0
     71     SET_VREG_XMM${suff} %xmm0, %ecx         # vAA<- %xmm0
     72     pxor    %xmm0, %xmm0
     73     movs${suff} %xmm0, VREG_REF_ADDRESS(rINST)  # clear ref
     74     ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
     75 
     76 %def op_add_double():
     77 %  sseBinop(instr="adds", suff="d")
     78 
     79 %def op_add_double_2addr():
     80 %  sseBinop2Addr(instr="adds", suff="d")
     81 
     82 %def op_add_float():
     83 %  sseBinop(instr="adds", suff="s")
     84 
     85 %def op_add_float_2addr():
     86 %  sseBinop2Addr(instr="adds", suff="s")
     87 
     88 %def op_cmpg_double():
     89 %  fpcmp(suff="d", nanval="pos")
     90 
     91 %def op_cmpg_float():
     92 %  fpcmp(suff="s", nanval="pos")
     93 
     94 %def op_cmpl_double():
     95 %  fpcmp(suff="d", nanval="neg")
     96 
     97 %def op_cmpl_float():
     98 %  fpcmp(suff="s", nanval="neg")
     99 
    100 %def op_div_double():
    101 %  sseBinop(instr="divs", suff="d")
    102 
    103 %def op_div_double_2addr():
    104 %  sseBinop2Addr(instr="divs", suff="d")
    105 
    106 %def op_div_float():
    107 %  sseBinop(instr="divs", suff="s")
    108 
    109 %def op_div_float_2addr():
    110 %  sseBinop2Addr(instr="divs", suff="s")
    111 
    112 %def op_double_to_float():
    113 %  fpcvt(load="fldl", store="fstps")
    114 
    115 %def op_double_to_int():
    116 %  cvtfp_int(srcdouble="1", tgtlong="0")
    117 
    118 %def op_double_to_long():
    119 %  cvtfp_int(srcdouble="1", tgtlong="1")
    120 
    121 %def op_float_to_double():
    122 %  fpcvt(load="flds", store="fstpl", wide="1")
    123 
    124 %def op_float_to_int():
    125 %  cvtfp_int(srcdouble="0", tgtlong="0")
    126 
    127 %def op_float_to_long():
    128 %  cvtfp_int(srcdouble="0", tgtlong="1")
    129 
    130 %def op_int_to_double():
    131 %  fpcvt(load="fildl", store="fstpl", wide="1")
    132 
    133 %def op_int_to_float():
    134 %  fpcvt(load="fildl", store="fstps")
    135 
    136 %def op_long_to_double():
    137 %  fpcvt(load="fildll", store="fstpl", wide="1")
    138 
    139 %def op_long_to_float():
    140 %  fpcvt(load="fildll", store="fstps")
    141 
    142 %def op_mul_double():
    143 %  sseBinop(instr="muls", suff="d")
    144 
    145 %def op_mul_double_2addr():
    146 %  sseBinop2Addr(instr="muls", suff="d")
    147 
    148 %def op_mul_float():
    149 %  sseBinop(instr="muls", suff="s")
    150 
    151 %def op_mul_float_2addr():
    152 %  sseBinop2Addr(instr="muls", suff="s")
    153 
    154 %def op_neg_double():
    155 %  fpcvt(instr="fchs", load="fldl", store="fstpl", wide="1")
    156 
    157 %def op_neg_float():
    158 %  fpcvt(instr="fchs", load="flds", store="fstps")
    159 
    160 %def op_rem_double():
    161     /* rem_double vAA, vBB, vCC */
    162     movzbl  3(rPC), %ecx                    # ecx <- BB
    163     movzbl  2(rPC), %eax                    # eax <- CC
    164     fldl    VREG_ADDRESS(%ecx)              # %st1 <- fp[vBB]
    165     fldl    VREG_ADDRESS(%eax)              # %st0 <- fp[vCC]
    166 1:
    167     fprem
    168     fstsw   %ax
    169     sahf
    170     jp      1b
    171     fstp    %st(1)
    172     fstpl   VREG_ADDRESS(rINST)             # fp[vAA] <- %st
    173     CLEAR_WIDE_REF rINST
    174     ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
    175 
    176 %def op_rem_double_2addr():
    177     /* rem_double/2addr vA, vB */
    178     movzx   rINSTbl, %ecx                   # ecx <- A+
    179     sarl    $$4, rINST                      # rINST <- B
    180     fldl    VREG_ADDRESS(rINST)             # vB to fp stack
    181     andb    $$0xf, %cl                      # ecx <- A
    182     fldl    VREG_ADDRESS(%ecx)              # vA to fp stack
    183 1:
    184     fprem
    185     fstsw   %ax
    186     sahf
    187     jp      1b
    188     fstp    %st(1)
    189     fstpl   VREG_ADDRESS(%ecx)              # %st to vA
    190     CLEAR_WIDE_REF %ecx
    191     ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
    192 
    193 %def op_rem_float():
    194     /* rem_float vAA, vBB, vCC */
    195     movzbl  3(rPC), %ecx                    # ecx <- BB
    196     movzbl  2(rPC), %eax                    # eax <- CC
    197     flds    VREG_ADDRESS(%ecx)              # vBB to fp stack
    198     flds    VREG_ADDRESS(%eax)              # vCC to fp stack
    199 1:
    200     fprem
    201     fstsw   %ax
    202     sahf
    203     jp      1b
    204     fstp    %st(1)
    205     fstps   VREG_ADDRESS(rINST)             # %st to vAA
    206     CLEAR_REF rINST
    207     ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
    208 
    209 %def op_rem_float_2addr():
    210     /* rem_float/2addr vA, vB */
    211     movzx   rINSTbl, %ecx                   # ecx <- A+
    212     sarl    $$4, rINST                      # rINST <- B
    213     flds    VREG_ADDRESS(rINST)             # vB to fp stack
    214     andb    $$0xf, %cl                      # ecx <- A
    215     flds    VREG_ADDRESS(%ecx)              # vA to fp stack
    216 1:
    217     fprem
    218     fstsw   %ax
    219     sahf
    220     jp      1b
    221     fstp    %st(1)
    222     fstps   VREG_ADDRESS(%ecx)              # %st to vA
    223     CLEAR_REF %ecx
    224     ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
    225 
    226 %def op_sub_double():
    227 %  sseBinop(instr="subs", suff="d")
    228 
    229 %def op_sub_double_2addr():
    230 %  sseBinop2Addr(instr="subs", suff="d")
    231 
    232 %def op_sub_float():
    233 %  sseBinop(instr="subs", suff="s")
    234 
    235 %def op_sub_float_2addr():
    236 %  sseBinop2Addr(instr="subs", suff="s")
    237