From 06c89b7963c5255dc82999f1eb1f5e18e220b3b6 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Mon, 5 Nov 2012 12:25:19 +0000 Subject: [PATCH] Finish cond_value with AND and INT_OP. --- API_CHANGES | 4 ++ sljit_src/sljitLir.c | 10 +-- sljit_src/sljitLir.h | 10 ++- sljit_src/sljitNativeARM_Thumb2.c | 37 ++++++----- sljit_src/sljitNativeARM_v5.c | 38 +++++------ sljit_src/sljitNativeMIPS_common.c | 8 ++- sljit_src/sljitNativePPC_common.c | 26 ++++++-- sljit_src/sljitNativeSPARC_common.c | 9 +-- sljit_src/sljitNativeX86_common.c | 128 +++++++++++++++++++----------------- test_src/sljitTest.c | 96 ++++++++++++++++++++++++++- 10 files changed, 247 insertions(+), 119 deletions(-) diff --git a/API_CHANGES b/API_CHANGES index 7885fd0..1a11719 100644 --- a/API_CHANGES +++ b/API_CHANGES @@ -1,5 +1,9 @@ This file is the short summary of the API changes: +05.10.2012 - Backward compatible + sljit_emit_cond_value now supports SLJIT_AND and SLJIT_INT_OP + flags, which makes this function complete. + 01.10.2012 - Non-backward compatible SLJIT_F* opcodes are renamed to SLJIT_*D to show that they are double precision operators. Furthermore diff --git a/sljit_src/sljitLir.c b/sljit_src/sljitLir.c index e71e49f..0ead335 100644 --- a/sljit_src/sljitLir.c +++ b/sljit_src/sljitLir.c @@ -1200,15 +1200,17 @@ static SLJIT_INLINE void check_sljit_emit_cond_value(struct sljit_compiler *comp SLJIT_UNUSED_ARG(type); SLJIT_ASSERT(type >= SLJIT_C_EQUAL && type < SLJIT_JUMP); - SLJIT_ASSERT(op == SLJIT_MOV || GET_OPCODE(op) == SLJIT_OR); - SLJIT_ASSERT(GET_ALL_FLAGS(op) == 0 || GET_ALL_FLAGS(op) == SLJIT_SET_E || GET_ALL_FLAGS(op) == SLJIT_KEEP_FLAGS); + SLJIT_ASSERT(op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI + || GET_OPCODE(op) == SLJIT_OR || GET_OPCODE(op) == SLJIT_AND); + SLJIT_ASSERT((op & (SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C)) == 0); + SLJIT_ASSERT((op & (SLJIT_SET_E | SLJIT_KEEP_FLAGS)) != (SLJIT_SET_E | SLJIT_KEEP_FLAGS)); #if (defined SLJIT_DEBUG && SLJIT_DEBUG) FUNCTION_CHECK_DST(dst, dstw); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " cond_set%s%s <%s> ", !(op & SLJIT_SET_E) ? "" : "E", - !(op & SLJIT_KEEP_FLAGS) ? "" : "K", op_names[GET_OPCODE(op)]); + fprintf(compiler->verbose, " %scond_value%s%s <%s> ", !(op & SLJIT_INT_OP) ? "" : "i", + !(op & SLJIT_SET_E) ? "" : "E", !(op & SLJIT_KEEP_FLAGS) ? "" : "K", op_names[GET_OPCODE(op)]); sljit_verbose_param(dst, dstw); fprintf(compiler->verbose, ", <%s>\n", jump_names[type]); } diff --git a/sljit_src/sljitLir.h b/sljit_src/sljitLir.h index e7ae930..1cc6d99 100644 --- a/sljit_src/sljitLir.h +++ b/sljit_src/sljitLir.h @@ -834,14 +834,18 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw Flags: destroy all flags for calls. */ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw); -/* If op == SLJIT_MOV: +/* If op == SLJIT_MOV, SLJIT_MOV_SI, SLJIT_MOV_UI: Set dst to 1 if condition is fulfilled, 0 otherwise type must be between SLJIT_C_EQUAL and SLJIT_C_FLOAT_ORDERED Flags: - (never set any flags) If op == SLJIT_OR Dst is used as src as well, and set its lowest bit to 1 if - the condition is fulfilled. Otherwise it does nothing. - Flags: E | K + the condition is fulfilled. Other bits are unaffected + Flags: I | E | K + If op == SLJIT_AND + Dst is used as src as well, and set its lowest bit to 0 if + the condition is not fulfilled. Resets all other bits. + Flags: I | E | K Note: sljit_emit_cond_value does nothing, if dst is SLJIT_UNUSED (regardless of op). */ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si type); diff --git a/sljit_src/sljitNativeARM_Thumb2.c b/sljit_src/sljitNativeARM_Thumb2.c index 435ad54..1c9e979 100644 --- a/sljit_src/sljitNativeARM_Thumb2.c +++ b/sljit_src/sljitNativeARM_Thumb2.c @@ -1892,7 +1892,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si type) { - sljit_si dst_r; + sljit_si dst_r, flags = GET_ALL_FLAGS(op); sljit_uw cc; CHECK_ERROR(); @@ -1902,37 +1902,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *c if (dst == SLJIT_UNUSED) return SLJIT_SUCCESS; + op = GET_OPCODE(op); cc = get_cc(type); - if (GET_OPCODE(op) == SLJIT_OR && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + if ((op == SLJIT_AND || op == SLJIT_OR) && dst <= SLJIT_NO_REGISTERS) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); - FAIL_IF(push_inst32(compiler, ORRI | RN4(dst) | RD4(dst) | 0x1)); - if (op & SLJIT_SET_E) { + FAIL_IF(push_inst32(compiler, ((op == SLJIT_AND) ? ANDI : ORRI) | RN4(dst) | RD4(dst) | 0x1)); + if (flags & SLJIT_SET_E) { + /* The condition must always be set, even if the AND/ORR is not executed above. */ if (reg_map[dst] <= 7) - return push_inst16(compiler, ORRS | RD3(dst) | RN3(dst)); - return push_inst32(compiler, ORR_W | SET_FLAGS | RD4(TMP_REG1) | RN4(dst) | RM4(dst)); + return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst)); + return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst)); } return SLJIT_SUCCESS; } + FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4)); dst_r = TMP_REG2; - if (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS && reg_map[dst] <= 7) + if (op < SLJIT_ADD && dst <= SLJIT_NO_REGISTERS) { + if (reg_map[dst] > 7) { + FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst) | 1)); + return push_inst32(compiler, MOV_WI | RD4(dst) | 0); + } dst_r = dst; + } - FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4)); - FAIL_IF(push_inst16(compiler, MOVSI | 0x1 | RDN3(dst_r))); - FAIL_IF(push_inst16(compiler, MOVSI | 0x0 | RDN3(dst_r))); + FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0x1)); + FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0x0)); if (dst_r == TMP_REG2) { - if (GET_OPCODE(op) == SLJIT_OR) { + if (op == SLJIT_AND || op == SLJIT_OR) { #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) compiler->skip_checks = 1; #endif - return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REG2, 0); + return sljit_emit_op2(compiler, op | flags, dst, dstw, dst, dstw, TMP_REG2, 0); } - if (dst & SLJIT_MEM) - return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw); - else - return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2)); + SLJIT_ASSERT(dst & SLJIT_MEM); + return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw); } return SLJIT_SUCCESS; diff --git a/sljit_src/sljitNativeARM_v5.c b/sljit_src/sljitNativeARM_v5.c index da06efb..054022e 100644 --- a/sljit_src/sljitNativeARM_v5.c +++ b/sljit_src/sljitNativeARM_v5.c @@ -2418,30 +2418,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *c return SLJIT_SUCCESS; cc = get_cc(type); - if (GET_OPCODE(op) == SLJIT_OR) { - if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { - EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ORR_DP, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc); - if (op & SLJIT_SET_E) - return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst))); - return SLJIT_SUCCESS; - } + if (GET_OPCODE(op) < SLJIT_ADD) { + reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; - EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 0)); - EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) - compiler->skip_checks = 1; -#endif - return emit_op(compiler, op, ALLOW_IMM, dst, dstw, TMP_REG1, 0, dst, dstw); - } + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 0)); + EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc); - reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; + return (reg == TMP_REG2) ? emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, TMP_REG2, 0) : SLJIT_SUCCESS; + } - EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 0)); - EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc); + if (dst <= SLJIT_NO_REGISTERS) { + EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(GET_OPCODE(op) == SLJIT_AND ? AND_DP : ORR_DP, + 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc); + /* The condition must always be set, even if the AND/ORR is not executed above. */ + return (op & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst))) : SLJIT_SUCCESS; + } - if (reg == TMP_REG2) - return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); - return SLJIT_SUCCESS; + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 0)); + EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc); +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + return emit_op(compiler, op, ALLOW_IMM, dst, dstw, TMP_REG1, 0, dst, dstw); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value) diff --git a/sljit_src/sljitNativeMIPS_common.c b/sljit_src/sljitNativeMIPS_common.c index 92b25a3..dd7606c 100644 --- a/sljit_src/sljitNativeMIPS_common.c +++ b/sljit_src/sljitNativeMIPS_common.c @@ -1748,6 +1748,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si type) { sljit_si sugg_dst_ar, dst_ar; + sljit_si flags = GET_ALL_FLAGS(op); CHECK_ERROR(); check_sljit_emit_cond_value(compiler, op, dst, dstw, type); @@ -1756,7 +1757,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *c if (dst == SLJIT_UNUSED) return SLJIT_SUCCESS; - sugg_dst_ar = DR((op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2); + op = GET_OPCODE(op); + sugg_dst_ar = DR((op < SLJIT_ADD && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2); switch (type) { case SLJIT_C_EQUAL: @@ -1818,10 +1820,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *c dst_ar = sugg_dst_ar; } - if (GET_OPCODE(op) == SLJIT_OR) { + if (op == SLJIT_AND || op == SLJIT_OR) { if (DR(TMP_REG2) != dst_ar) FAIL_IF(push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); - return emit_op(compiler, op, CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, dst, dstw, TMP_REG2, 0); + return emit_op(compiler, op | flags, CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, dst, dstw, TMP_REG2, 0); } if (dst & SLJIT_MEM) diff --git a/sljit_src/sljitNativePPC_common.c b/sljit_src/sljitNativePPC_common.c index d96c5f0..64a5907 100644 --- a/sljit_src/sljitNativePPC_common.c +++ b/sljit_src/sljitNativePPC_common.c @@ -1850,7 +1850,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si type) { - sljit_si reg; + sljit_si reg, flags = GET_ALL_FLAGS(op); CHECK_ERROR(); check_sljit_emit_cond_value(compiler, op, dst, dstw, type); @@ -1859,7 +1859,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *c if (dst == SLJIT_UNUSED) return SLJIT_SUCCESS; - reg = (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; + op = GET_OPCODE(op); + reg = (op < SLJIT_ADD && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; switch (type) { case SLJIT_C_EQUAL: @@ -1945,10 +1946,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *c break; } - if (GET_OPCODE(op) == SLJIT_OR) - return emit_op(compiler, SLJIT_OR, GET_FLAGS(op) ? ALT_SET_FLAGS : 0, dst, dstw, dst, dstw, TMP_REG2, 0); + if (op < SLJIT_ADD) { +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (op == SLJIT_MOV) + flags = WORD_DATA; + else { + op = SLJIT_MOV_UI; + flags = INT_DATA; + } +#else + op = SLJIT_MOV; + flags = WORD_DATA; +#endif + return (reg == TMP_REG2) ? emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0) : SLJIT_SUCCESS; + } - return (reg == TMP_REG2) ? emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0) : SLJIT_SUCCESS; +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + return sljit_emit_op2(compiler, op | flags, dst, dstw, dst, dstw, TMP_REG2, 0); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value) diff --git a/sljit_src/sljitNativeSPARC_common.c b/sljit_src/sljitNativeSPARC_common.c index 212d1ec..5fd8013 100644 --- a/sljit_src/sljitNativeSPARC_common.c +++ b/sljit_src/sljitNativeSPARC_common.c @@ -1272,7 +1272,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si type) { - sljit_si reg; + sljit_si reg, flags = (GET_FLAGS(op) ? SET_FLAGS : 0); CHECK_ERROR(); check_sljit_emit_cond_value(compiler, op, dst, dstw, type); @@ -1282,7 +1282,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *c return SLJIT_SUCCESS; #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) - reg = (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; + op = GET_OPCODE(op); + reg = (op < SLJIT_ADD && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; if (type < SLJIT_C_FLOAT_EQUAL) FAIL_IF(push_inst(compiler, BICC | get_cc(type) | 3, UNMOVABLE_INS)); @@ -1292,8 +1293,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *c FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(1), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(0), UNMOVABLE_INS)); - if (GET_OPCODE(op) == SLJIT_OR) - return emit_op(compiler, SLJIT_OR, (GET_FLAGS(op) ? SET_FLAGS : 0) | CUMULATIVE_OP | IMM_OP, dst, dstw, dst, dstw, TMP_REG2, 0); + if (op == SLJIT_AND || op == SLJIT_OR) + return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, dst, dstw, TMP_REG2, 0); return (reg == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS; #else diff --git a/sljit_src/sljitNativeX86_common.c b/sljit_src/sljitNativeX86_common.c index 6cade37..161fab3 100644 --- a/sljit_src/sljitNativeX86_common.c +++ b/sljit_src/sljitNativeX86_common.c @@ -263,9 +263,9 @@ static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = { built-in CPU features. Therefore they can be overwritten by different threads if they detect the CPU features in the same time. */ #if (defined SLJIT_SSE2 && SLJIT_SSE2) && (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) -static sljit_ui cpu_has_sse2 = -1; +static sljit_si cpu_has_sse2 = -1; #endif -static sljit_ui cpu_has_cmov = -1; +static sljit_si cpu_has_cmov = -1; #if defined(_MSC_VER) && (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) #include @@ -2604,10 +2604,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *c { sljit_ub *inst; sljit_ub cond_set = 0; - sljit_si dst_save = dst; - sljit_sw dstw_save = dstw; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) sljit_si reg; +#else + /* CHECK_EXTRA_REGS migh overwrite these values. */ + sljit_si dst_save = dst; + sljit_sw dstw_save = dstw; #endif CHECK_ERROR(); @@ -2703,21 +2705,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *c *inst++ = MOVZX_r_rm8; *inst = MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg]; - if (reg == TMP_REGISTER) { - if (op == SLJIT_MOV) { - compiler->mode32 = 0; - EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0); - } - else { + if (reg != TMP_REGISTER) + return SLJIT_SUCCESS; + + if (GET_OPCODE(op) < SLJIT_ADD) { + compiler->mode32 = GET_OPCODE(op) != SLJIT_MOV; + return emit_mov(compiler, dst, dstw, TMP_REGISTER, 0); + } #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) - compiler->skip_checks = 1; + compiler->skip_checks = 1; #endif - return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REGISTER, 0); - } - } -#else - if (op == SLJIT_MOV) { - if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_TEMPORARY_REG3) { + return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REGISTER, 0); +#else /* SLJIT_CONFIG_X86_64 */ + if (GET_OPCODE(op) < SLJIT_ADD && dst <= SLJIT_NO_REGISTERS) { + if (reg_map[dst] <= 4) { + /* Low byte is accessible. */ inst = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3); FAIL_IF(!inst); INC_SIZE(3 + 3); @@ -2729,66 +2731,68 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_cond_value(struct sljit_compiler *c *inst++ = GROUP_0F; *inst++ = MOVZX_r_rm8; *inst = MOD_REG | (reg_map[dst] << 3) | reg_map[dst]; + return SLJIT_SUCCESS; } - else { - EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0); - inst = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3); - FAIL_IF(!inst); - INC_SIZE(3 + 3); - /* Set al to conditional flag. */ - *inst++ = GROUP_0F; - *inst++ = cond_set; - *inst++ = MOD_REG; + /* Low byte is not accessible. */ + if (cpu_has_cmov == -1) + get_cpu_features(); - *inst++ = GROUP_0F; - *inst++ = MOVZX_r_rm8; - if (dst >= SLJIT_SAVED_REG1 && dst <= SLJIT_NO_REGISTERS) - *inst = MOD_REG | (reg_map[dst] << 3); - else { - *inst = MOD_REG; - EMIT_MOV(compiler, dst, dstw, SLJIT_TEMPORARY_REG1, 0); - } + if (cpu_has_cmov) { + EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_IMM, 1); + /* a xor reg, reg operation would overwrite the flags. */ + EMIT_MOV(compiler, dst, 0, SLJIT_IMM, 0); - EMIT_MOV(compiler, SLJIT_TEMPORARY_REG1, 0, TMP_REGISTER, 0); - } - } - else { - if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_TEMPORARY_REG3) { - EMIT_MOV(compiler, TMP_REGISTER, 0, dst, 0); inst = (sljit_ub*)ensure_buf(compiler, 1 + 3); FAIL_IF(!inst); INC_SIZE(3); *inst++ = GROUP_0F; - *inst++ = cond_set; - *inst++ = MOD_REG | reg_map[dst]; + *inst++ = cond_set - 0x50; + *inst++ = MOD_REG | (reg_map[dst] << 3) | reg_map[TMP_REGISTER]; + return SLJIT_SUCCESS; } - else { - EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0); - inst = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3 + 1); - FAIL_IF(!inst); - INC_SIZE(3 + 3 + 1); - /* Set al to conditional flag. */ - *inst++ = GROUP_0F; - *inst++ = cond_set; - *inst++ = MOD_REG; + inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1); + FAIL_IF(!inst); + INC_SIZE(1 + 3 + 3 + 1); + *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER]; + /* Set al to conditional flag. */ + *inst++ = GROUP_0F; + *inst++ = cond_set; + *inst++ = MOD_REG | 0 /* eax */; - *inst++ = GROUP_0F; - *inst++ = MOVZX_r_rm8; - *inst++ = MOD_REG; + *inst++ = GROUP_0F; + *inst++ = MOVZX_r_rm8; + *inst++ = MOD_REG | (reg_map[dst] << 3) | 0 /* eax */; + *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER]; + return SLJIT_SUCCESS; + } + + /* Set TMP_REGISTER to the bit. */ + inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1); + FAIL_IF(!inst); + INC_SIZE(1 + 3 + 3 + 1); + *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER]; + /* Set al to conditional flag. */ + *inst++ = GROUP_0F; + *inst++ = cond_set; + *inst++ = MOD_REG | 0 /* eax */; + + *inst++ = GROUP_0F; + *inst++ = MOVZX_r_rm8; + *inst++ = MOD_REG | (0 << 3) /* eax */ | 0 /* eax */; + + *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER]; + + if (GET_OPCODE(op) < SLJIT_ADD) + return emit_mov(compiler, dst, dstw, TMP_REGISTER, 0); - *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER]; - } #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) - compiler->skip_checks = 1; -#endif - return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REGISTER, 0); - } + compiler->skip_checks = 1; #endif - - return SLJIT_SUCCESS; + return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REGISTER, 0); +#endif /* SLJIT_CONFIG_X86_64 */ } SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset) diff --git a/test_src/sljitTest.c b/test_src/sljitTest.c index 062097e..6663432 100644 --- a/test_src/sljitTest.c +++ b/test_src/sljitTest.c @@ -3902,6 +3902,97 @@ static void test45(void) successful_tests++; } +static void test46(void) +{ + /* Test sljit_emit_cond_value with SLJIT_AND and SLJIT_INT_OP. */ + + executable_code code; + struct sljit_compiler* compiler = sljit_create_compiler(); + sljit_si buf[20]; + sljit_sw buf2[5]; + int i; + + for (i = 0; i < 20; ++i) + buf[i] = -17; + buf[16] = 0; + for (i = 0; i < 5; ++i) + buf2[i] = -13; + buf2[4] = -124; + + sljit_emit_enter(compiler, 2, 3, 3, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, -7); + sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_E | SLJIT_SET_U, SLJIT_UNUSED, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 13); + sljit_emit_cond_value(compiler, SLJIT_MOV_SI, SLJIT_MEM0(), (sljit_sw)&buf, SLJIT_C_LESS); + sljit_emit_cond_value(compiler, SLJIT_IAND, SLJIT_MEM1(SLJIT_SAVED_REG1), 2 * sizeof(sljit_si), SLJIT_C_GREATER); + + sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_E | SLJIT_SET_U, SLJIT_UNUSED, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, -7); + sljit_emit_cond_value(compiler, SLJIT_IAND | SLJIT_KEEP_FLAGS, SLJIT_MEM1(SLJIT_SAVED_REG1), 4 * sizeof(sljit_si), SLJIT_C_EQUAL); + sljit_emit_cond_value(compiler, SLJIT_IAND | SLJIT_KEEP_FLAGS, SLJIT_MEM1(SLJIT_SAVED_REG1), 6 * sizeof(sljit_si), SLJIT_C_EQUAL); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0x1235); + sljit_emit_cond_value(compiler, SLJIT_IAND | SLJIT_SET_E, SLJIT_TEMPORARY_REG1, 0, SLJIT_C_EQUAL); + sljit_emit_cond_value(compiler, SLJIT_IAND, SLJIT_MEM1(SLJIT_SAVED_REG1), 8 * sizeof(sljit_si), SLJIT_C_EQUAL); + sljit_emit_op1(compiler, SLJIT_MOV_UI, SLJIT_MEM1(SLJIT_SAVED_REG1), 10 * sizeof(sljit_si), SLJIT_TEMPORARY_REG1, 0); + + sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, -7); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 12); + sljit_emit_cond_value(compiler, SLJIT_MOV_UI, SLJIT_MEM2(SLJIT_SAVED_REG1, SLJIT_TEMPORARY_REG1), 2, SLJIT_C_EQUAL); + sljit_emit_cond_value(compiler, SLJIT_MOV_UI, SLJIT_TEMPORARY_REG1, 0, SLJIT_C_EQUAL); + sljit_emit_op1(compiler, SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SAVED_REG1), 14 * sizeof(sljit_si), SLJIT_TEMPORARY_REG1, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 16); + sljit_emit_cond_value(compiler, SLJIT_IAND | SLJIT_SET_E, SLJIT_MEM2(SLJIT_SAVED_REG1, SLJIT_TEMPORARY_REG1), 2, SLJIT_C_EQUAL); + sljit_emit_cond_value(compiler, SLJIT_MOV_UI, SLJIT_MEM1(SLJIT_SAVED_REG1), 18 * sizeof(sljit_si), SLJIT_C_NOT_EQUAL); + + sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_E | SLJIT_SET_U, SLJIT_UNUSED, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, -7); + sljit_emit_cond_value(compiler, SLJIT_AND, SLJIT_MEM0(), (sljit_sw)&buf2, SLJIT_C_GREATER); + sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U, SLJIT_UNUSED, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 5); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 1); + sljit_emit_cond_value(compiler, SLJIT_AND | SLJIT_KEEP_FLAGS, SLJIT_MEM2(SLJIT_SAVED_REG2, SLJIT_TEMPORARY_REG1), SLJIT_WORD_SHIFT, SLJIT_C_SIG_LESS); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 2); + sljit_emit_cond_value(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_SAVED_REG2, SLJIT_TEMPORARY_REG1), SLJIT_WORD_SHIFT, SLJIT_C_LESS); + sljit_emit_cond_value(compiler, SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_C_NOT_EQUAL); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SAVED_REG2), 3 * sizeof(sljit_sw), SLJIT_SAVED_REG3, 0); + sljit_emit_cond_value(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_SAVED_REG2), 4 * sizeof(sljit_sw), SLJIT_C_GREATER); + + sljit_emit_return(compiler, SLJIT_UNUSED, 0, 0); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + code.func2((sljit_sw)&buf, (sljit_sw)&buf2); + FAILED(buf[0] != 0, "test46 case 1 failed\n"); + FAILED(buf[1] != -17, "test46 case 2 failed\n"); + FAILED(buf[2] != 1, "test46 case 3 failed\n"); + FAILED(buf[3] != -17, "test46 case 4 failed\n"); + FAILED(buf[4] != 1, "test46 case 5 failed\n"); + FAILED(buf[5] != -17, "test46 case 6 failed\n"); + FAILED(buf[6] != 1, "test46 case 7 failed\n"); + FAILED(buf[7] != -17, "test46 case 8 failed\n"); + FAILED(buf[8] != 0, "test46 case 9 failed\n"); + FAILED(buf[9] != -17, "test46 case 10 failed\n"); + FAILED(buf[10] != 1, "test46 case 11 failed\n"); + FAILED(buf[11] != -17, "test46 case 12 failed\n"); + FAILED(buf[12] != 1, "test46 case 13 failed\n"); + FAILED(buf[13] != -17, "test46 case 14 failed\n"); + FAILED(buf[14] != 1, "test46 case 15 failed\n"); + FAILED(buf[15] != -17, "test46 case 16 failed\n"); + FAILED(buf[16] != 0, "test46 case 17 failed\n"); + FAILED(buf[17] != -17, "test46 case 18 failed\n"); + FAILED(buf[18] != 0, "test46 case 19 failed\n"); + FAILED(buf[19] != -17, "test46 case 20 failed\n"); + + FAILED(buf2[0] != 0, "test46 case 21 failed\n"); + FAILED(buf2[1] != 1, "test46 case 22 failed\n"); + FAILED(buf2[2] != 0, "test46 case 23 failed\n"); + FAILED(buf2[3] != 1, "test46 case 24 failed\n"); + FAILED(buf2[4] != -123, "test46 case 25 failed\n"); + + sljit_free_code(code.code); + printf("test46 ok\n"); + successful_tests++; +} + void sljit_test(void) { #if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) @@ -3952,9 +4043,10 @@ void sljit_test(void) test43(); test44(); test45(); + test46(); printf("On %s%s: ", sljit_get_platform_name(), sljit_is_fpu_available() ? " (+fpu)" : ""); - if (successful_tests == 45) + if (successful_tests == 46) printf("All tests are passed!\n"); else - printf("Successful test ratio: %d%%.\n", successful_tests * 100 / 45); + printf("Successful test ratio: %d%%.\n", successful_tests * 100 / 46); } -- 2.11.4.GIT