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#ifdef MTERP_USE_AVX 60 v${instr}${suff} VREG_ADDRESS(%rax), %xmm0, %xmm0 61 SET_VREG_XMM${suff} %xmm0, rINSTq # vAA <- %xmm0 62 vpxor %xmm0, %xmm0, %xmm0 63 vmovs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref 64#else 65 ${instr}${suff} VREG_ADDRESS(%rax), %xmm0 66 SET_VREG_XMM${suff} %xmm0, rINSTq # vAA <- %xmm0 67 pxor %xmm0, %xmm0 68 movs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref 69#endif 70 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 71 72%def sseBinop2Addr(instr="", suff=""): 73 movl rINST, %ecx # ecx <- A+ 74 andl $$0xf, %ecx # ecx <- A 75 GET_VREG_XMM${suff} %xmm0, %rcx # %xmm0 <- 1st src 76 sarl $$4, rINST # rINST<- B 77#ifdef MTERP_USE_AVX 78 v${instr}${suff} VREG_ADDRESS(rINSTq), %xmm0, %xmm0 79 SET_VREG_XMM${suff} %xmm0, %rcx # vAA <- %xmm0 80 vpxor %xmm0, %xmm0, %xmm0 81 vmovs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref 82#else 83 ${instr}${suff} VREG_ADDRESS(rINSTq), %xmm0 84 SET_VREG_XMM${suff} %xmm0, %rcx # vAA <- %xmm0 85 pxor %xmm0, %xmm0 86 movs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref 87#endif 88 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 89 90%def op_add_double(): 91% sseBinop(instr="adds", suff="d") 92 93%def op_add_double_2addr(): 94% sseBinop2Addr(instr="adds", suff="d") 95 96%def op_add_float(): 97% sseBinop(instr="adds", suff="s") 98 99%def op_add_float_2addr(): 100% sseBinop2Addr(instr="adds", suff="s") 101 102%def op_cmpg_double(): 103% fpcmp(suff="d", nanval="pos") 104 105%def op_cmpg_float(): 106% fpcmp(suff="s", nanval="pos") 107 108%def op_cmpl_double(): 109% fpcmp(suff="d", nanval="neg") 110 111%def op_cmpl_float(): 112% fpcmp(suff="s", nanval="neg") 113 114%def op_div_double(): 115% sseBinop(instr="divs", suff="d") 116 117%def op_div_double_2addr(): 118% sseBinop2Addr(instr="divs", suff="d") 119 120%def op_div_float(): 121% sseBinop(instr="divs", suff="s") 122 123%def op_div_float_2addr(): 124% sseBinop2Addr(instr="divs", suff="s") 125 126%def op_double_to_float(): 127% fpcvt(source_suffix="d", dest_suffix="s", wide="0") 128 129%def op_double_to_int(): 130% cvtfp_int(fp_suffix="d", i_suffix="l", max_const="$0x7fffffff", result_reg="%eax", wide="0") 131 132%def op_double_to_long(): 133% cvtfp_int(fp_suffix="d", i_suffix="q", max_const="$0x7fffffffffffffff", result_reg="%rax", wide="1") 134 135%def op_float_to_double(): 136% fpcvt(source_suffix="s", dest_suffix="d", wide="1") 137 138%def op_float_to_int(): 139% cvtfp_int(fp_suffix="s", i_suffix="l", max_const="$0x7fffffff", result_reg="%eax", wide="0") 140 141%def op_float_to_long(): 142% cvtfp_int(fp_suffix="s", i_suffix="q", max_const="$0x7fffffffffffffff", result_reg="%rax", wide="1") 143 144%def op_int_to_double(): 145% fpcvt(source_suffix="i", dest_suffix="dl", wide="1") 146 147%def op_int_to_float(): 148% fpcvt(source_suffix="i", dest_suffix="sl", wide="0") 149 150%def op_long_to_double(): 151% fpcvt(source_suffix="i", dest_suffix="dq", wide="1") 152 153%def op_long_to_float(): 154% fpcvt(source_suffix="i", dest_suffix="sq", wide="0") 155 156%def op_mul_double(): 157% sseBinop(instr="muls", suff="d") 158 159%def op_mul_double_2addr(): 160% sseBinop2Addr(instr="muls", suff="d") 161 162%def op_mul_float(): 163% sseBinop(instr="muls", suff="s") 164 165%def op_mul_float_2addr(): 166% sseBinop2Addr(instr="muls", suff="s") 167 168%def op_neg_double(): 169% unop(preinstr=" movq $0x8000000000000000, %rsi", instr=" xorq %rsi, %rax", wide="1") 170 171%def op_neg_float(): 172% unop(instr=" xorl $0x80000000, %eax") 173 174%def op_rem_double(): 175 /* rem_double vAA, vBB, vCC */ 176 movzbq 3(rPC), %rcx # ecx <- BB 177 movzbq 2(rPC), %rax # eax <- CC 178 fldl VREG_ADDRESS(%rcx) # %st1 <- fp[vBB] 179 fldl VREG_ADDRESS(%rax) # %st0 <- fp[vCC] 1801: 181 fprem 182 fstsw %ax 183 sahf 184 jp 1b 185 fstp %st(1) 186 fstpl VREG_ADDRESS(rINSTq) # fp[vAA] <- %st 187 CLEAR_WIDE_REF rINSTq 188 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 189 190%def op_rem_double_2addr(): 191 /* rem_double/2addr vA, vB */ 192 movzbq rINSTbl, %rcx # ecx <- A+ 193 sarl $$4, rINST # rINST <- B 194 fldl VREG_ADDRESS(rINSTq) # vB to fp stack 195 andb $$0xf, %cl # ecx <- A 196 fldl VREG_ADDRESS(%rcx) # vA to fp stack 1971: 198 fprem 199 fstsw %ax 200 sahf 201 jp 1b 202 fstp %st(1) 203 fstpl VREG_ADDRESS(%rcx) # %st to vA 204 CLEAR_WIDE_REF %rcx 205 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 206 207%def op_rem_float(): 208 /* rem_float vAA, vBB, vCC */ 209 movzbq 3(rPC), %rcx # ecx <- BB 210 movzbq 2(rPC), %rax # eax <- CC 211 flds VREG_ADDRESS(%rcx) # vBB to fp stack 212 flds VREG_ADDRESS(%rax) # vCC to fp stack 2131: 214 fprem 215 fstsw %ax 216 sahf 217 jp 1b 218 fstp %st(1) 219 fstps VREG_ADDRESS(rINSTq) # %st to vAA 220 CLEAR_REF rINSTq 221 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 222 223%def op_rem_float_2addr(): 224 /* rem_float/2addr vA, vB */ 225 movzbq rINSTbl, %rcx # ecx <- A+ 226 sarl $$4, rINST # rINST <- B 227 flds VREG_ADDRESS(rINSTq) # vB to fp stack 228 andb $$0xf, %cl # ecx <- A 229 flds VREG_ADDRESS(%rcx) # vA to fp stack 2301: 231 fprem 232 fstsw %ax 233 sahf 234 jp 1b 235 fstp %st(1) 236 fstps VREG_ADDRESS(%rcx) # %st to vA 237 CLEAR_REF %rcx 238 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 239 240%def op_sub_double(): 241% sseBinop(instr="subs", suff="d") 242 243%def op_sub_double_2addr(): 244% sseBinop2Addr(instr="subs", suff="d") 245 246%def op_sub_float(): 247% sseBinop(instr="subs", suff="s") 248 249%def op_sub_float_2addr(): 250% sseBinop2Addr(instr="subs", suff="s") 251