| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- /*
- * Copyright (C) 2019 Intel Corporation. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
- #include "jit_emit_compare.h"
- #include "jit_emit_function.h"
- #include "../jit_frontend.h"
- #include "../jit_codegen.h"
- static bool
- jit_compile_op_compare_integer(JitCompContext *cc, IntCond cond, bool is64Bit)
- {
- JitReg lhs, rhs, res, const_zero, const_one;
- if (cond < INT_EQZ || cond > INT_GE_U) {
- jit_set_last_error(cc, "unsupported comparation operation");
- goto fail;
- }
- res = jit_cc_new_reg_I32(cc);
- const_zero = NEW_CONST(I32, 0);
- const_one = NEW_CONST(I32, 1);
- if (is64Bit) {
- if (INT_EQZ == cond) {
- rhs = NEW_CONST(I64, 0);
- }
- else {
- POP_I64(rhs);
- }
- POP_I64(lhs);
- }
- else {
- if (INT_EQZ == cond) {
- rhs = NEW_CONST(I32, 0);
- }
- else {
- POP_I32(rhs);
- }
- POP_I32(lhs);
- }
- GEN_INSN(CMP, cc->cmp_reg, lhs, rhs);
- switch (cond) {
- case INT_EQ:
- case INT_EQZ:
- {
- GEN_INSN(SELECTEQ, res, cc->cmp_reg, const_one, const_zero);
- break;
- }
- case INT_NE:
- {
- GEN_INSN(SELECTNE, res, cc->cmp_reg, const_one, const_zero);
- break;
- }
- case INT_LT_S:
- {
- GEN_INSN(SELECTLTS, res, cc->cmp_reg, const_one, const_zero);
- break;
- }
- case INT_LT_U:
- {
- GEN_INSN(SELECTLTU, res, cc->cmp_reg, const_one, const_zero);
- break;
- }
- case INT_GT_S:
- {
- GEN_INSN(SELECTGTS, res, cc->cmp_reg, const_one, const_zero);
- break;
- }
- case INT_GT_U:
- {
- GEN_INSN(SELECTGTU, res, cc->cmp_reg, const_one, const_zero);
- break;
- }
- case INT_LE_S:
- {
- GEN_INSN(SELECTLES, res, cc->cmp_reg, const_one, const_zero);
- break;
- }
- case INT_LE_U:
- {
- GEN_INSN(SELECTLEU, res, cc->cmp_reg, const_one, const_zero);
- break;
- }
- case INT_GE_S:
- {
- GEN_INSN(SELECTGES, res, cc->cmp_reg, const_one, const_zero);
- break;
- }
- default: /* INT_GE_U */
- {
- GEN_INSN(SELECTGEU, res, cc->cmp_reg, const_one, const_zero);
- break;
- }
- }
- PUSH_I32(res);
- return true;
- fail:
- return false;
- }
- bool
- jit_compile_op_i32_compare(JitCompContext *cc, IntCond cond)
- {
- return jit_compile_op_compare_integer(cc, cond, false);
- }
- bool
- 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, args[2], const_zero, const_one;
- JitRegKind kind;
- void *func;
- if (cond == FLOAT_EQ || cond == FLOAT_NE) {
- kind = jit_reg_kind(lhs);
- if (cond == FLOAT_EQ)
- func = (kind == JIT_REG_KIND_F32) ? (void *)float_cmp_eq
- : (void *)double_cmp_eq;
- else
- func = (kind == JIT_REG_KIND_F32) ? (void *)float_cmp_ne
- : (void *)double_cmp_ne;
- res = jit_cc_new_reg_I32(cc);
- args[0] = lhs;
- args[1] = rhs;
- if (!jit_emit_callnative(cc, func, res, args, 2)) {
- goto fail;
- }
- }
- else {
- res = jit_cc_new_reg_I32(cc);
- const_zero = NEW_CONST(I32, 0);
- const_one = NEW_CONST(I32, 1);
- switch (cond) {
- case FLOAT_LT:
- {
- GEN_INSN(CMP, cc->cmp_reg, rhs, lhs);
- GEN_INSN(SELECTGTS, 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(SELECTGES, 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;
- }
- default:
- {
- bh_assert(!"unknown FloatCond");
- goto fail;
- }
- }
- }
- PUSH_I32(res);
- return true;
- fail:
- return false;
- }
- bool
- jit_compile_op_f32_compare(JitCompContext *cc, FloatCond cond)
- {
- JitReg res, const_zero, const_one;
- JitReg lhs, rhs;
- POP_F32(rhs);
- POP_F32(lhs);
- if (jit_reg_is_const(lhs) && jit_reg_is_const(rhs)) {
- float32 lvalue = jit_cc_get_const_F32(cc, lhs);
- float32 rvalue = jit_cc_get_const_F32(cc, rhs);
- const_zero = NEW_CONST(I32, 0);
- const_one = NEW_CONST(I32, 1);
- switch (cond) {
- case FLOAT_EQ:
- {
- res = (lvalue == rvalue) ? const_one : const_zero;
- break;
- }
- case FLOAT_NE:
- {
- res = (lvalue != rvalue) ? const_one : const_zero;
- break;
- }
- case FLOAT_LT:
- {
- res = (lvalue < rvalue) ? const_one : const_zero;
- break;
- }
- case FLOAT_GT:
- {
- res = (lvalue > rvalue) ? const_one : const_zero;
- break;
- }
- case FLOAT_LE:
- {
- res = (lvalue <= rvalue) ? const_one : const_zero;
- break;
- }
- case FLOAT_GE:
- {
- res = (lvalue >= rvalue) ? const_one : const_zero;
- break;
- }
- default:
- {
- bh_assert(!"unknown FloatCond");
- goto fail;
- }
- }
- PUSH_I32(res);
- return true;
- }
- return jit_compile_op_compare_float_point(cc, cond, lhs, rhs);
- fail:
- return false;
- }
- bool
- jit_compile_op_f64_compare(JitCompContext *cc, FloatCond cond)
- {
- JitReg res, const_zero, const_one;
- JitReg lhs, rhs;
- POP_F64(rhs);
- POP_F64(lhs);
- if (jit_reg_is_const(lhs) && jit_reg_is_const(rhs)) {
- float64 lvalue = jit_cc_get_const_F64(cc, lhs);
- float64 rvalue = jit_cc_get_const_F64(cc, rhs);
- const_zero = NEW_CONST(I32, 0);
- const_one = NEW_CONST(I32, 1);
- switch (cond) {
- case FLOAT_EQ:
- {
- res = (lvalue == rvalue) ? const_one : const_zero;
- break;
- }
- case FLOAT_NE:
- {
- res = (lvalue != rvalue) ? const_one : const_zero;
- break;
- }
- case FLOAT_LT:
- {
- res = (lvalue < rvalue) ? const_one : const_zero;
- break;
- }
- case FLOAT_GT:
- {
- res = (lvalue > rvalue) ? const_one : const_zero;
- break;
- }
- case FLOAT_LE:
- {
- res = (lvalue <= rvalue) ? const_one : const_zero;
- break;
- }
- case FLOAT_GE:
- {
- res = (lvalue >= rvalue) ? const_one : const_zero;
- break;
- }
- default:
- {
- bh_assert(!"unknown FloatCond");
- goto fail;
- }
- }
- PUSH_I32(res);
- return true;
- }
- return jit_compile_op_compare_float_point(cc, cond, lhs, rhs);
- fail:
- return false;
- }
|