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 movzbq 3(rPC), %rcx # ecx<- CC 20 movzbq 2(rPC), %rax # eax<- BB 21 GET_VREG_XMM${suff} %xmm0, %rax 22 xor %eax, %eax 23 ucomis${suff} VREG_ADDRESS(%rcx), %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 addb $$1, %al 29 jmp .L${opcode}_finish 30.L${opcode}_nan_is_neg: 31.L${opcode}_less: 32 movl $$-1, %eax 33.L${opcode}_finish: 34 SET_VREG %eax, rINSTq 35 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 36 37%def fpcvt(source_suffix="", dest_suffix="", wide=""): 38/* 39 * Generic 32-bit FP conversion operation. 40 */ 41 /* unop vA, vB */ 42 movl rINST, %ecx # rcx <- A+ 43 sarl $$4, rINST # rINST <- B 44 andb $$0xf, %cl # ecx <- A 45 cvts${source_suffix}2s${dest_suffix} VREG_ADDRESS(rINSTq), %xmm0 46 .if $wide 47 SET_VREG_XMMd %xmm0, %rcx 48 CLEAR_WIDE_REF %rcx 49 .else 50 SET_VREG_XMMs %xmm0, %rcx 51 CLEAR_REF %rcx 52 .endif 53 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 54 55%def sseBinop(instr="", suff=""): 56 movzbq 2(rPC), %rcx # ecx <- BB 57 movzbq 3(rPC), %rax # eax <- CC 58 GET_VREG_XMM${suff} %xmm0, %rcx # %xmm0 <- 1st src 59 ${instr}${suff} VREG_ADDRESS(%rax), %xmm0 60 SET_VREG_XMM${suff} %xmm0, rINSTq # vAA <- %xmm0 61 pxor %xmm0, %xmm0 62 movs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref 63 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 64 65%def sseBinop2Addr(instr="", suff=""): 66 movl rINST, %ecx # ecx <- A+ 67 andl $$0xf, %ecx # ecx <- A 68 GET_VREG_XMM${suff} %xmm0, %rcx # %xmm0 <- 1st src 69 sarl $$4, rINST # rINST<- B 70 ${instr}${suff} VREG_ADDRESS(rINSTq), %xmm0 71 SET_VREG_XMM${suff} %xmm0, %rcx # vAA <- %xmm0 72 pxor %xmm0, %xmm0 73 movs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # 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(source_suffix="d", dest_suffix="s", wide="0") 114 115%def op_double_to_int(): 116% cvtfp_int(fp_suffix="d", i_suffix="l", max_const="$0x7fffffff", result_reg="%eax", wide="0") 117 118%def op_double_to_long(): 119% cvtfp_int(fp_suffix="d", i_suffix="q", max_const="$0x7fffffffffffffff", result_reg="%rax", wide="1") 120 121%def op_float_to_double(): 122% fpcvt(source_suffix="s", dest_suffix="d", wide="1") 123 124%def op_float_to_int(): 125% cvtfp_int(fp_suffix="s", i_suffix="l", max_const="$0x7fffffff", result_reg="%eax", wide="0") 126 127%def op_float_to_long(): 128% cvtfp_int(fp_suffix="s", i_suffix="q", max_const="$0x7fffffffffffffff", result_reg="%rax", wide="1") 129 130%def op_int_to_double(): 131% fpcvt(source_suffix="i", dest_suffix="dl", wide="1") 132 133%def op_int_to_float(): 134% fpcvt(source_suffix="i", dest_suffix="sl", wide="0") 135 136%def op_long_to_double(): 137% fpcvt(source_suffix="i", dest_suffix="dq", wide="1") 138 139%def op_long_to_float(): 140% fpcvt(source_suffix="i", dest_suffix="sq", wide="0") 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% unop(preinstr=" movq $0x8000000000000000, %rsi", instr=" xorq %rsi, %rax", wide="1") 156 157%def op_neg_float(): 158% unop(instr=" xorl $0x80000000, %eax") 159 160%def op_rem_double(): 161 /* rem_double vAA, vBB, vCC */ 162 movzbq 3(rPC), %rcx # ecx <- BB 163 movzbq 2(rPC), %rax # eax <- CC 164 fldl VREG_ADDRESS(%rcx) # %st1 <- fp[vBB] 165 fldl VREG_ADDRESS(%rax) # %st0 <- fp[vCC] 1661: 167 fprem 168 fstsw %ax 169 sahf 170 jp 1b 171 fstp %st(1) 172 fstpl VREG_ADDRESS(rINSTq) # fp[vAA] <- %st 173 CLEAR_WIDE_REF rINSTq 174 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 175 176%def op_rem_double_2addr(): 177 /* rem_double/2addr vA, vB */ 178 movzbq rINSTbl, %rcx # ecx <- A+ 179 sarl $$4, rINST # rINST <- B 180 fldl VREG_ADDRESS(rINSTq) # vB to fp stack 181 andb $$0xf, %cl # ecx <- A 182 fldl VREG_ADDRESS(%rcx) # vA to fp stack 1831: 184 fprem 185 fstsw %ax 186 sahf 187 jp 1b 188 fstp %st(1) 189 fstpl VREG_ADDRESS(%rcx) # %st to vA 190 CLEAR_WIDE_REF %rcx 191 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 192 193%def op_rem_float(): 194 /* rem_float vAA, vBB, vCC */ 195 movzbq 3(rPC), %rcx # ecx <- BB 196 movzbq 2(rPC), %rax # eax <- CC 197 flds VREG_ADDRESS(%rcx) # vBB to fp stack 198 flds VREG_ADDRESS(%rax) # vCC to fp stack 1991: 200 fprem 201 fstsw %ax 202 sahf 203 jp 1b 204 fstp %st(1) 205 fstps VREG_ADDRESS(rINSTq) # %st to vAA 206 CLEAR_REF rINSTq 207 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 208 209%def op_rem_float_2addr(): 210 /* rem_float/2addr vA, vB */ 211 movzbq rINSTbl, %rcx # ecx <- A+ 212 sarl $$4, rINST # rINST <- B 213 flds VREG_ADDRESS(rINSTq) # vB to fp stack 214 andb $$0xf, %cl # ecx <- A 215 flds VREG_ADDRESS(%rcx) # vA to fp stack 2161: 217 fprem 218 fstsw %ax 219 sahf 220 jp 1b 221 fstp %st(1) 222 fstps VREG_ADDRESS(%rcx) # %st to vA 223 CLEAR_REF %rcx 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