Fix issues of fnn.cmp (#1204)

- use native functions to do f.eq and f.ne
- only use ZF=0 and CF=0 to do f.lt and f.gt
- only use CF=0 to do f.le and f.ge

could use comiss and setCC to replace comiss and jmpCC

be able to pass f32_cmp and f64_cmp

```
cmp_eq:
  xor     eax, eax
  ucomisd xmm0, xmm1
  mov     edx, 0
  setnp   al
  cmovne  eax, edx
  ret

cmp_ne:
  xor     eax, eax
  ucomisd xmm0, xmm1
  mov edx, 1
  setp al
  cmovne eax, edx
  ret
```
This commit is contained in:
liang.he 2022-06-03 10:02:51 +08:00 committed by GitHub
parent 66cd90d847
commit b3a27e7257
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 119 additions and 43 deletions

View File

@ -363,7 +363,7 @@ cmp_r_and_jmp_label(JitCompContext *cc, x86::Assembler &a,
case GTS:
{
if (fp_cmp) {
a.jnbe(imm);
a.ja(imm);
}
else {
a.jg(imm);
@ -373,7 +373,7 @@ cmp_r_and_jmp_label(JitCompContext *cc, x86::Assembler &a,
case LES:
{
if (fp_cmp) {
a.jbe(imm);
a.jnb(imm);
}
else {
a.jng(imm);
@ -394,7 +394,7 @@ cmp_r_and_jmp_label(JitCompContext *cc, x86::Assembler &a,
case LTS:
{
if (fp_cmp) {
a.jb(imm);
a.ja(imm);
}
else {
a.jl(imm);
@ -5071,7 +5071,7 @@ cmp_r_and_jmp_relative(JitCompContext *cc, x86::Assembler &a, int32 reg_no,
case GTS:
{
if (fp_cmp) {
a.jnbe(target);
a.ja(target);
}
else {
a.jg(target);
@ -5081,7 +5081,7 @@ cmp_r_and_jmp_relative(JitCompContext *cc, x86::Assembler &a, int32 reg_no,
case LES:
{
if (fp_cmp) {
a.jbe(target);
a.jnb(target);
}
else {
a.jng(target);
@ -5094,7 +5094,6 @@ cmp_r_and_jmp_relative(JitCompContext *cc, x86::Assembler &a, int32 reg_no,
a.jnb(target);
}
else {
a.jnl(target);
}
break;
@ -5102,7 +5101,7 @@ cmp_r_and_jmp_relative(JitCompContext *cc, x86::Assembler &a, int32 reg_no,
case LTS:
{
if (fp_cmp) {
a.jb(target);
a.ja(target);
}
else {
a.jl(target);

View File

@ -5,6 +5,7 @@
#include "jit_emit_compare.h"
#include "../jit_frontend.h"
#include "../jit_codegen.h"
static bool
jit_compile_op_compare_integer(JitCompContext *cc, IntCond cond, bool is64Bit)
@ -116,45 +117,120 @@ jit_compile_op_i64_compare(JitCompContext *cc, IntCond cond)
return jit_compile_op_compare_integer(cc, cond, true);
}
static int32
float_cmp_eq(float f1, float f2)
{
if (isnan(f1) || isnan(f2))
return 0;
return f1 == f2;
}
static int32
float_cmp_ne(float f1, float f2)
{
if (isnan(f1) || isnan(f2))
return 1;
return f1 != f2;
}
static int32
double_cmp_eq(double d1, double d2)
{
if (isnan(d1) || isnan(d2))
return 0;
return d1 == d2;
}
static int32
double_cmp_ne(double d1, double d2)
{
if (isnan(d1) || isnan(d2))
return 1;
return d1 != d2;
}
static bool
jit_compile_op_compare_float_point(JitCompContext *cc, FloatCond cond,
JitReg lhs, JitReg rhs)
{
JitReg res, const_zero, const_one;
GEN_INSN(CMP, cc->cmp_reg, lhs, rhs);
if (cond == FLOAT_EQ) {
JitInsn *insn = NULL;
JitRegKind kind = jit_reg_kind(lhs);
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
res = jit_codegen_get_hreg_by_name("eax");
#else
res = jit_cc_new_reg_I32(cc);
#endif
if (kind == JIT_REG_KIND_F32) {
insn = GEN_INSN(CALLNATIVE, res,
NEW_CONST(PTR, (uintptr_t)float_cmp_eq), 2);
}
else {
insn = GEN_INSN(CALLNATIVE, res,
NEW_CONST(PTR, (uintptr_t)double_cmp_eq), 2);
}
if (!insn) {
goto fail;
}
*(jit_insn_opndv(insn, 2)) = lhs;
*(jit_insn_opndv(insn, 3)) = rhs;
}
else if (cond == FLOAT_NE) {
JitInsn *insn = NULL;
JitRegKind kind = jit_reg_kind(lhs);
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
res = jit_codegen_get_hreg_by_name("eax");
#else
res = jit_cc_new_reg_I32(cc);
#endif
if (kind == JIT_REG_KIND_F32) {
insn = GEN_INSN(CALLNATIVE, res,
NEW_CONST(PTR, (uintptr_t)float_cmp_ne), 2);
}
else {
insn = GEN_INSN(CALLNATIVE, res,
NEW_CONST(PTR, (uintptr_t)double_cmp_ne), 2);
}
if (!insn) {
goto fail;
}
*(jit_insn_opndv(insn, 2)) = lhs;
*(jit_insn_opndv(insn, 3)) = rhs;
}
else {
res = jit_cc_new_reg_I32(cc);
const_zero = NEW_CONST(I32, 0);
const_one = NEW_CONST(I32, 1);
switch (cond) {
case FLOAT_EQ:
{
GEN_INSN(SELECTEQ, res, cc->cmp_reg, const_one, const_zero);
break;
}
case FLOAT_NE:
{
GEN_INSN(SELECTNE, res, cc->cmp_reg, const_one, const_zero);
break;
}
case FLOAT_LT:
{
GEN_INSN(CMP, cc->cmp_reg, rhs, lhs);
GEN_INSN(SELECTLTS, res, cc->cmp_reg, const_one, const_zero);
break;
}
case FLOAT_GT:
{
GEN_INSN(CMP, cc->cmp_reg, lhs, rhs);
GEN_INSN(SELECTGTS, res, cc->cmp_reg, const_one, const_zero);
break;
}
case FLOAT_LE:
{
GEN_INSN(CMP, cc->cmp_reg, rhs, lhs);
GEN_INSN(SELECTLES, res, cc->cmp_reg, const_one, const_zero);
break;
}
case FLOAT_GE:
{
GEN_INSN(CMP, cc->cmp_reg, lhs, rhs);
GEN_INSN(SELECTGES, res, cc->cmp_reg, const_one, const_zero);
break;
}
@ -164,6 +240,7 @@ jit_compile_op_compare_float_point(JitCompContext *cc, FloatCond cond,
goto fail;
}
}
}
PUSH_I32(res);
return true;