You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
6.9 KiB
251 lines
6.9 KiB
%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 */
|
|
movzbl 3(rPC), %ecx # ecx<- CC
|
|
movzbl 2(rPC), %eax # eax<- BB
|
|
GET_VREG_XMM${suff} %xmm0, %eax
|
|
xor %eax, %eax
|
|
ucomis${suff} VREG_ADDRESS(%ecx), %xmm0
|
|
jp .L${opcode}_nan_is_${nanval}
|
|
je .L${opcode}_finish
|
|
jb .L${opcode}_less
|
|
.L${opcode}_nan_is_pos:
|
|
incl %eax
|
|
jmp .L${opcode}_finish
|
|
.L${opcode}_nan_is_neg:
|
|
.L${opcode}_less:
|
|
decl %eax
|
|
.L${opcode}_finish:
|
|
SET_VREG %eax, rINST
|
|
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
|
|
|
|
%def fpcvt(instr="", load="", store="", wide="0"):
|
|
/*
|
|
* Generic 32-bit FP conversion operation.
|
|
*/
|
|
/* unop vA, vB */
|
|
movzbl rINSTbl, %ecx # ecx <- A+
|
|
sarl $$4, rINST # rINST <- B
|
|
$load VREG_ADDRESS(rINST) # %st0 <- vB
|
|
andb $$0xf, %cl # ecx <- A
|
|
$instr
|
|
$store VREG_ADDRESS(%ecx) # vA <- %st0
|
|
.if $wide
|
|
CLEAR_WIDE_REF %ecx
|
|
.else
|
|
CLEAR_REF %ecx
|
|
.endif
|
|
ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
|
|
|
|
%def sseBinop(instr="", suff=""):
|
|
movzbl 2(rPC), %ecx # ecx <- BB
|
|
movzbl 3(rPC), %eax # eax <- CC
|
|
GET_VREG_XMM${suff} %xmm0, %ecx # %xmm0 <- 1st src
|
|
#ifdef MTERP_USE_AVX
|
|
v${instr}${suff} VREG_ADDRESS(%eax), %xmm0, %xmm0
|
|
SET_VREG_XMM${suff} %xmm0, rINST # vAA <- %xmm0
|
|
vpxor %xmm0, %xmm0, %xmm0
|
|
vmovs${suff} %xmm0, VREG_REF_ADDRESS(rINST) # clear ref
|
|
#else
|
|
${instr}${suff} VREG_ADDRESS(%eax), %xmm0
|
|
SET_VREG_XMM${suff} %xmm0, rINST # vAA <- %xmm0
|
|
pxor %xmm0, %xmm0
|
|
movs${suff} %xmm0, VREG_REF_ADDRESS(rINST) # clear ref
|
|
#endif
|
|
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
|
|
|
|
%def sseBinop2Addr(instr="", suff=""):
|
|
movzx rINSTbl, %ecx # ecx <- A+
|
|
andl $$0xf, %ecx # ecx <- A
|
|
GET_VREG_XMM${suff} %xmm0, %ecx # %xmm0 <- 1st src
|
|
sarl $$4, rINST # rINST<- B
|
|
#ifdef MTERP_USE_AVX
|
|
v${instr}${suff} VREG_ADDRESS(rINST), %xmm0, %xmm0
|
|
SET_VREG_XMM${suff} %xmm0, %ecx # vAA<- %xmm0
|
|
vpxor %xmm0, %xmm0, %xmm0
|
|
vmovs${suff} %xmm0, VREG_REF_ADDRESS(rINST) # clear ref
|
|
#else
|
|
${instr}${suff} VREG_ADDRESS(rINST), %xmm0
|
|
SET_VREG_XMM${suff} %xmm0, %ecx # vAA<- %xmm0
|
|
pxor %xmm0, %xmm0
|
|
movs${suff} %xmm0, VREG_REF_ADDRESS(rINST) # 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(load="fldl", store="fstps")
|
|
|
|
%def op_double_to_int():
|
|
% cvtfp_int(srcdouble="1", tgtlong="0")
|
|
|
|
%def op_double_to_long():
|
|
% cvtfp_int(srcdouble="1", tgtlong="1")
|
|
|
|
%def op_float_to_double():
|
|
% fpcvt(load="flds", store="fstpl", wide="1")
|
|
|
|
%def op_float_to_int():
|
|
% cvtfp_int(srcdouble="0", tgtlong="0")
|
|
|
|
%def op_float_to_long():
|
|
% cvtfp_int(srcdouble="0", tgtlong="1")
|
|
|
|
%def op_int_to_double():
|
|
% fpcvt(load="fildl", store="fstpl", wide="1")
|
|
|
|
%def op_int_to_float():
|
|
% fpcvt(load="fildl", store="fstps")
|
|
|
|
%def op_long_to_double():
|
|
% fpcvt(load="fildll", store="fstpl", wide="1")
|
|
|
|
%def op_long_to_float():
|
|
% fpcvt(load="fildll", store="fstps")
|
|
|
|
%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():
|
|
% fpcvt(instr="fchs", load="fldl", store="fstpl", wide="1")
|
|
|
|
%def op_neg_float():
|
|
% fpcvt(instr="fchs", load="flds", store="fstps")
|
|
|
|
%def op_rem_double():
|
|
/* rem_double vAA, vBB, vCC */
|
|
movzbl 3(rPC), %ecx # ecx <- BB
|
|
movzbl 2(rPC), %eax # eax <- CC
|
|
fldl VREG_ADDRESS(%ecx) # %st1 <- fp[vBB]
|
|
fldl VREG_ADDRESS(%eax) # %st0 <- fp[vCC]
|
|
1:
|
|
fprem
|
|
fstsw %ax
|
|
sahf
|
|
jp 1b
|
|
fstp %st(1)
|
|
fstpl VREG_ADDRESS(rINST) # fp[vAA] <- %st
|
|
CLEAR_WIDE_REF rINST
|
|
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
|
|
|
|
%def op_rem_double_2addr():
|
|
/* rem_double/2addr vA, vB */
|
|
movzx rINSTbl, %ecx # ecx <- A+
|
|
sarl $$4, rINST # rINST <- B
|
|
fldl VREG_ADDRESS(rINST) # vB to fp stack
|
|
andb $$0xf, %cl # ecx <- A
|
|
fldl VREG_ADDRESS(%ecx) # vA to fp stack
|
|
1:
|
|
fprem
|
|
fstsw %ax
|
|
sahf
|
|
jp 1b
|
|
fstp %st(1)
|
|
fstpl VREG_ADDRESS(%ecx) # %st to vA
|
|
CLEAR_WIDE_REF %ecx
|
|
ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
|
|
|
|
%def op_rem_float():
|
|
/* rem_float vAA, vBB, vCC */
|
|
movzbl 3(rPC), %ecx # ecx <- BB
|
|
movzbl 2(rPC), %eax # eax <- CC
|
|
flds VREG_ADDRESS(%ecx) # vBB to fp stack
|
|
flds VREG_ADDRESS(%eax) # vCC to fp stack
|
|
1:
|
|
fprem
|
|
fstsw %ax
|
|
sahf
|
|
jp 1b
|
|
fstp %st(1)
|
|
fstps VREG_ADDRESS(rINST) # %st to vAA
|
|
CLEAR_REF rINST
|
|
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
|
|
|
|
%def op_rem_float_2addr():
|
|
/* rem_float/2addr vA, vB */
|
|
movzx rINSTbl, %ecx # ecx <- A+
|
|
sarl $$4, rINST # rINST <- B
|
|
flds VREG_ADDRESS(rINST) # vB to fp stack
|
|
andb $$0xf, %cl # ecx <- A
|
|
flds VREG_ADDRESS(%ecx) # vA to fp stack
|
|
1:
|
|
fprem
|
|
fstsw %ax
|
|
sahf
|
|
jp 1b
|
|
fstp %st(1)
|
|
fstps VREG_ADDRESS(%ecx) # %st to vA
|
|
CLEAR_REF %ecx
|
|
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")
|