blob: b40c0e632ef17238caf3fd0a977cc06b7353a9db [file] [log] [blame]
%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
movs${suff} VREG_ADDRESS(%rax), %xmm0
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
movsd %xmm0, VREG_ADDRESS(%rcx)
CLEAR_WIDE_REF %rcx
.else
movss %xmm0, VREG_ADDRESS(%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
movs${suff} VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
${instr}${suff} VREG_ADDRESS(%rax), %xmm0
movs${suff} %xmm0, VREG_ADDRESS(rINSTq) # vAA <- %xmm0
pxor %xmm0, %xmm0
movs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
%def sseBinop2Addr(instr="", suff=""):
movl rINST, %ecx # ecx <- A+
andl $$0xf, %ecx # ecx <- A
movs${suff} VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
sarl $$4, rINST # rINST<- B
${instr}${suff} VREG_ADDRESS(rINSTq), %xmm0
movs${suff} %xmm0, VREG_ADDRESS(%rcx) # vAA<- %xmm0
pxor %xmm0, %xmm0
movs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
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")