%def fpcmp(suff="d", nanval="pos"): /* * Compare two floating-point values. Puts 0, 1, or -1 into the * destination register based on the results of the comparison. * * int compare(x, y) { * if (x == y) { * return 0; * } else if (x < y) { * return -1; * } else if (x > y) { * return 1; * } else { * return nanval ? 1 : -1; * } * } */ /* op vAA, vBB, vCC */ movzbq 3(rPC), %rcx # ecx<- CC movzbq 2(rPC), %rax # eax<- BB GET_VREG_XMM${suff} %xmm0, %rax xor %eax, %eax ucomis${suff} VREG_ADDRESS(%rcx), %xmm0 jp .L${opcode}_nan_is_${nanval} je .L${opcode}_finish jb .L${opcode}_less .L${opcode}_nan_is_pos: addb $$1, %al jmp .L${opcode}_finish .L${opcode}_nan_is_neg: .L${opcode}_less: movl $$-1, %eax .L${opcode}_finish: SET_VREG %eax, rINSTq ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 %def fpcvt(source_suffix="", dest_suffix="", wide=""): /* * Generic 32-bit FP conversion operation. */ /* unop vA, vB */ movl rINST, %ecx # rcx <- A+ sarl $$4, rINST # rINST <- B andb $$0xf, %cl # ecx <- A cvts${source_suffix}2s${dest_suffix} VREG_ADDRESS(rINSTq), %xmm0 .if $wide SET_VREG_XMMd %xmm0, %rcx CLEAR_WIDE_REF %rcx .else SET_VREG_XMMs %xmm0, %rcx CLEAR_REF %rcx .endif ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 %def sseBinop(instr="", suff=""): movzbq 2(rPC), %rcx # ecx <- BB movzbq 3(rPC), %rax # eax <- CC GET_VREG_XMM${suff} %xmm0, %rcx # %xmm0 <- 1st src #ifdef MTERP_USE_AVX v${instr}${suff} VREG_ADDRESS(%rax), %xmm0, %xmm0 SET_VREG_XMM${suff} %xmm0, rINSTq # vAA <- %xmm0 vpxor %xmm0, %xmm0, %xmm0 vmovs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref #else ${instr}${suff} VREG_ADDRESS(%rax), %xmm0 SET_VREG_XMM${suff} %xmm0, rINSTq # vAA <- %xmm0 pxor %xmm0, %xmm0 movs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref #endif ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 %def sseBinop2Addr(instr="", suff=""): movl rINST, %ecx # ecx <- A+ andl $$0xf, %ecx # ecx <- A GET_VREG_XMM${suff} %xmm0, %rcx # %xmm0 <- 1st src sarl $$4, rINST # rINST<- B #ifdef MTERP_USE_AVX v${instr}${suff} VREG_ADDRESS(rINSTq), %xmm0, %xmm0 SET_VREG_XMM${suff} %xmm0, %rcx # vAA <- %xmm0 vpxor %xmm0, %xmm0, %xmm0 vmovs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref #else ${instr}${suff} VREG_ADDRESS(rINSTq), %xmm0 SET_VREG_XMM${suff} %xmm0, %rcx # vAA <- %xmm0 pxor %xmm0, %xmm0 movs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref #endif ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 %def op_add_double(): % sseBinop(instr="adds", suff="d") %def op_add_double_2addr(): % sseBinop2Addr(instr="adds", suff="d") %def op_add_float(): % sseBinop(instr="adds", suff="s") %def op_add_float_2addr(): % sseBinop2Addr(instr="adds", suff="s") %def op_cmpg_double(): % fpcmp(suff="d", nanval="pos") %def op_cmpg_float(): % fpcmp(suff="s", nanval="pos") %def op_cmpl_double(): % fpcmp(suff="d", nanval="neg") %def op_cmpl_float(): % fpcmp(suff="s", nanval="neg") %def op_div_double(): % sseBinop(instr="divs", suff="d") %def op_div_double_2addr(): % sseBinop2Addr(instr="divs", suff="d") %def op_div_float(): % sseBinop(instr="divs", suff="s") %def op_div_float_2addr(): % sseBinop2Addr(instr="divs", suff="s") %def op_double_to_float(): % fpcvt(source_suffix="d", dest_suffix="s", wide="0") %def op_double_to_int(): % cvtfp_int(fp_suffix="d", i_suffix="l", max_const="$0x7fffffff", result_reg="%eax", wide="0") %def op_double_to_long(): % cvtfp_int(fp_suffix="d", i_suffix="q", max_const="$0x7fffffffffffffff", result_reg="%rax", wide="1") %def op_float_to_double(): % fpcvt(source_suffix="s", dest_suffix="d", wide="1") %def op_float_to_int(): % cvtfp_int(fp_suffix="s", i_suffix="l", max_const="$0x7fffffff", result_reg="%eax", wide="0") %def op_float_to_long(): % cvtfp_int(fp_suffix="s", i_suffix="q", max_const="$0x7fffffffffffffff", result_reg="%rax", wide="1") %def op_int_to_double(): % fpcvt(source_suffix="i", dest_suffix="dl", wide="1") %def op_int_to_float(): % fpcvt(source_suffix="i", dest_suffix="sl", wide="0") %def op_long_to_double(): % fpcvt(source_suffix="i", dest_suffix="dq", wide="1") %def op_long_to_float(): % fpcvt(source_suffix="i", dest_suffix="sq", wide="0") %def op_mul_double(): % sseBinop(instr="muls", suff="d") %def op_mul_double_2addr(): % sseBinop2Addr(instr="muls", suff="d") %def op_mul_float(): % sseBinop(instr="muls", suff="s") %def op_mul_float_2addr(): % sseBinop2Addr(instr="muls", suff="s") %def op_neg_double(): % unop(preinstr=" movq $0x8000000000000000, %rsi", instr=" xorq %rsi, %rax", wide="1") %def op_neg_float(): % unop(instr=" xorl $0x80000000, %eax") %def op_rem_double(): /* rem_double vAA, vBB, vCC */ movzbq 3(rPC), %rcx # ecx <- BB movzbq 2(rPC), %rax # eax <- CC fldl VREG_ADDRESS(%rcx) # %st1 <- fp[vBB] fldl VREG_ADDRESS(%rax) # %st0 <- fp[vCC] 1: fprem fstsw %ax sahf jp 1b fstp %st(1) fstpl VREG_ADDRESS(rINSTq) # fp[vAA] <- %st CLEAR_WIDE_REF rINSTq ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 %def op_rem_double_2addr(): /* rem_double/2addr vA, vB */ movzbq rINSTbl, %rcx # ecx <- A+ sarl $$4, rINST # rINST <- B fldl VREG_ADDRESS(rINSTq) # vB to fp stack andb $$0xf, %cl # ecx <- A fldl VREG_ADDRESS(%rcx) # vA to fp stack 1: fprem fstsw %ax sahf jp 1b fstp %st(1) fstpl VREG_ADDRESS(%rcx) # %st to vA CLEAR_WIDE_REF %rcx ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 %def op_rem_float(): /* rem_float vAA, vBB, vCC */ movzbq 3(rPC), %rcx # ecx <- BB movzbq 2(rPC), %rax # eax <- CC flds VREG_ADDRESS(%rcx) # vBB to fp stack flds VREG_ADDRESS(%rax) # vCC to fp stack 1: fprem fstsw %ax sahf jp 1b fstp %st(1) fstps VREG_ADDRESS(rINSTq) # %st to vAA CLEAR_REF rINSTq ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 %def op_rem_float_2addr(): /* rem_float/2addr vA, vB */ movzbq rINSTbl, %rcx # ecx <- A+ sarl $$4, rINST # rINST <- B flds VREG_ADDRESS(rINSTq) # vB to fp stack andb $$0xf, %cl # ecx <- A flds VREG_ADDRESS(%rcx) # vA to fp stack 1: fprem fstsw %ax sahf jp 1b fstp %st(1) fstps VREG_ADDRESS(%rcx) # %st to vA CLEAR_REF %rcx ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 %def op_sub_double(): % sseBinop(instr="subs", suff="d") %def op_sub_double_2addr(): % sseBinop2Addr(instr="subs", suff="d") %def op_sub_float(): % sseBinop(instr="subs", suff="s") %def op_sub_float_2addr(): % sseBinop2Addr(instr="subs", suff="s")