diff options
author | zherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2012-01-13 13:34:07 +0000 |
---|---|---|
committer | zherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2012-01-13 13:34:07 +0000 |
commit | 873f3e06c2aff02a618a67ecb4167bbec0bcfd58 (patch) | |
tree | cfca991bef7deb0053db95ee10f3fc55f4d18d39 | |
parent | 7e3f2077c984db31b5d303b88baeab6eadcb08f1 (diff) | |
download | pcre-873f3e06c2aff02a618a67ecb4167bbec0bcfd58.tar.gz |
JIT compiler update
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@867 2f5784b3-3f2a-0410-8824-cb99058d5e15
-rw-r--r-- | sljit/sljitLir.c | 77 | ||||
-rw-r--r-- | sljit/sljitLir.h | 28 | ||||
-rw-r--r-- | sljit/sljitNativeARM_Thumb2.c | 2 | ||||
-rw-r--r-- | sljit/sljitNativeMIPS_common.c | 76 | ||||
-rw-r--r-- | sljit/sljitNativeX86_64.c | 27 | ||||
-rw-r--r-- | sljit/sljitNativeX86_common.c | 28 |
6 files changed, 196 insertions, 42 deletions
diff --git a/sljit/sljitLir.c b/sljit/sljitLir.c index 4a6928c..58c12bb 100644 --- a/sljit/sljitLir.c +++ b/sljit/sljitLir.c @@ -895,6 +895,13 @@ static SLJIT_INLINE void check_sljit_emit_fop1(struct sljit_compiler *compiler, int dst, sljit_w dstw, int src, sljit_w srcw) { +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + return; + } +#endif + /* If debug and verbose are disabled, all arguments are unused. */ SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(op); @@ -1018,6 +1025,35 @@ static SLJIT_INLINE void check_sljit_emit_cmp(struct sljit_compiler *compiler, i #endif } +static SLJIT_INLINE void check_sljit_emit_fcmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(src1); + SLJIT_UNUSED_ARG(src1w); + SLJIT_UNUSED_ARG(src2); + SLJIT_UNUSED_ARG(src2w); + + SLJIT_ASSERT(sljit_is_fpu_available()); + SLJIT_ASSERT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP))); + SLJIT_ASSERT((type & 0xff) >= SLJIT_C_FLOAT_EQUAL && (type & 0xff) <= SLJIT_C_FLOAT_NOT_NAN); +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + FUNCTION_FCHECK(src1, src1w); + FUNCTION_FCHECK(src2, src2w); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " fcmp%s <%s> ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : "R", jump_names[type & 0xff]); + sljit_verbose_fparam(src1, src1w); + fprintf(compiler->verbose, ", "); + sljit_verbose_fparam(src2, src2w); + fprintf(compiler->verbose, "\n"); + } +#endif +} + static SLJIT_INLINE void check_sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw) { /* If debug and verbose are disabled, all arguments are unused. */ @@ -1103,6 +1139,7 @@ static SLJIT_INLINE void check_sljit_emit_const(struct sljit_compiler *compiler, #endif #if !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type, int src1, sljit_w src1w, int src2, sljit_w src2w) @@ -1169,6 +1206,32 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler #endif return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP)); } + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + int flags, condition; + + check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w); + + condition = type & 0xff; + if (condition <= SLJIT_C_FLOAT_NOT_EQUAL) + flags = SLJIT_SET_E; + else + flags = SLJIT_SET_S; + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + sljit_emit_fop1(compiler, SLJIT_FCMP | flags, src1, src1w, src2, src2w); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP)); +} + #endif #else /* SLJIT_CONFIG_UNSUPPORTED */ @@ -1379,6 +1442,20 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler return NULL; } +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(src1); + SLJIT_UNUSED_ARG(src1w); + SLJIT_UNUSED_ARG(src2); + SLJIT_UNUSED_ARG(src2w); + SLJIT_ASSERT_STOP(); + return NULL; +} + SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label) { SLJIT_UNUSED_ARG(jump); diff --git a/sljit/sljitLir.h b/sljit/sljitLir.h index 995f70b..685ee80 100644 --- a/sljit/sljitLir.h +++ b/sljit/sljitLir.h @@ -686,11 +686,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi Flags: destroy all flags for calls. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type); -/* Basic arithmetic comparison. In most architectures it is equal to - an SLJIT_SUB operation (with SLJIT_UNUSED destination) followed by a - sljit_emit_jump. However some architectures (i.e: MIPS) may employ - special optimizations here. It is suggested to use this comparison - form when flags are unimportant. +/* Basic arithmetic comparison. In most architectures it is implemented as + an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting + appropriate flags) followed by a sljit_emit_jump. However some + architectures (i.e: MIPS) may employ special optimizations here. It is + suggested to use this comparison form when appropriate. type must be between SLJIT_C_EQUAL and SLJIT_C_SIG_LESS_EQUAL type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP or SLJIT_INT_OP Flags: destroy flags. */ @@ -698,6 +698,20 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler int src1, sljit_w src1w, int src2, sljit_w src2w); +/* Basic floating point comparison. In most architectures it is implemented as + an SLJIT_FCMP operation (setting appropriate flags) followed by a + sljit_emit_jump. However some architectures (i.e: MIPS) may employ + special optimizations here. It is suggested to use this comparison form + when appropriate. + type must be between SLJIT_C_FLOAT_EQUAL and SLJIT_C_FLOAT_NOT_NAN + type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP + Flags: destroy flags. + Note: if either operand is NaN, the behaviour is undefined for + type <= SLJIT_C_FLOAT_LESS_EQUAL. */ +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w); + /* Set the destination of the jump to this label. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label); /* Only for jumps defined with SLJIT_REWRITABLE_JUMP flag. @@ -743,7 +757,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constan /* --------------------------------------------------------------------- */ #define SLJIT_MAJOR_VERSION 0 -#define SLJIT_MINOR_VERSION 82 +#define SLJIT_MINOR_VERSION 87 /* Get the human readable name of the platfrom. Can be useful for debugging on platforms like ARM, where ARM and @@ -751,7 +765,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constan SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void); /* Portble helper function to get an offset of a member. */ -#define SLJIT_OFFSETOF(base, member) ((sljit_w)(&((base*)0x10)->member) - 0x10) +#define SLJIT_OFFSETOF(base, member) ((sljit_w)(&((base*)0x10)->member) - 0x10) #if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) /* This global lock is useful to compile common functions. */ diff --git a/sljit/sljitNativeARM_Thumb2.c b/sljit/sljitNativeARM_Thumb2.c index f5ae679..f69f91a 100644 --- a/sljit/sljitNativeARM_Thumb2.c +++ b/sljit/sljitNativeARM_Thumb2.c @@ -1179,6 +1179,8 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG) { if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REG3) FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_RETURN_REG, src))); + else if (src & SLJIT_IMM) + FAIL_IF(load_immediate(compiler, SLJIT_RETURN_REG, srcw)); else FAIL_IF(emit_op_mem(compiler, WORD_SIZE, SLJIT_RETURN_REG, src, srcw)); } diff --git a/sljit/sljitNativeMIPS_common.c b/sljit/sljitNativeMIPS_common.c index 0e9f209..a1026f9 100644 --- a/sljit/sljitNativeMIPS_common.c +++ b/sljit/sljitNativeMIPS_common.c @@ -109,6 +109,7 @@ typedef sljit_ui sljit_ins; #define BREAK (HI(0) | LO(13)) #define C_UN_D (HI(17) | FMT_D | LO(49)) #define C_UEQ_D (HI(17) | FMT_D | LO(51)) +#define C_ULE_D (HI(17) | FMT_D | LO(55)) #define C_ULT_D (HI(17) | FMT_D | LO(53)) #define DIV (HI(0) | LO(26)) #define DIVU (HI(0) | LO(27)) @@ -1588,6 +1589,81 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler #undef RESOLVE_IMM1 #undef RESOLVE_IMM2 +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + struct sljit_jump *jump; + sljit_ins inst; + int if_true; + + CHECK_ERROR_PTR(); + check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + if (src1 > SLJIT_FLOAT_REG4) { + PTR_FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w)); + src1 = TMP_FREG1; + } + if (src2 > SLJIT_FLOAT_REG4) { + PTR_FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w)); + src2 = TMP_FREG2; + } + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + jump->flags |= IS_BIT16_COND; + type &= 0xff; + + switch (type) { + case SLJIT_C_FLOAT_EQUAL: + inst = C_UEQ_D; + if_true = 1; + break; + case SLJIT_C_FLOAT_NOT_EQUAL: + inst = C_UEQ_D; + if_true = 0; + break; + case SLJIT_C_FLOAT_LESS: + inst = C_ULT_D; + if_true = 1; + break; + case SLJIT_C_FLOAT_GREATER_EQUAL: + inst = C_ULT_D; + if_true = 0; + break; + case SLJIT_C_FLOAT_GREATER: + inst = C_ULE_D; + if_true = 0; + break; + case SLJIT_C_FLOAT_LESS_EQUAL: + inst = C_ULE_D; + if_true = 1; + break; + case SLJIT_C_FLOAT_NAN: + inst = C_UN_D; + if_true = 1; + break; + case SLJIT_C_FLOAT_NOT_NAN: + default: /* Make compilers happy. */ + inst = C_UN_D; + if_true = 0; + break; + } + + PTR_FAIL_IF(push_inst(compiler, inst | FT(src2) | FS(src1), UNMOVABLE_INS)); + /* Intentionally the other opcode. */ + PTR_FAIL_IF(push_inst(compiler, (if_true ? BC1F : BC1T) | JUMP_LENGTH, UNMOVABLE_INS)); + PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0)); + PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS)); + jump->addr = compiler->size; + PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); + return jump; +} + #undef JUMP_LENGTH #undef BR_Z #undef BR_NZ diff --git a/sljit/sljitNativeX86_64.c b/sljit/sljitNativeX86_64.c index 05b3952..587c53a 100644 --- a/sljit/sljitNativeX86_64.c +++ b/sljit/sljitNativeX86_64.c @@ -802,10 +802,17 @@ static int emit_mov_int(struct sljit_compiler *compiler, int sign, return SLJIT_SUCCESS; /* Empty instruction. */ if (src & SLJIT_IMM) { - if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + if (sign || ((sljit_uw)srcw <= 0x7fffffff)) { + code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw); + FAIL_IF(!code); + *code = 0xc7; + return SLJIT_SUCCESS; + } return emit_load_imm64(compiler, dst, srcw); + } compiler->mode32 = 1; - code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(int)srcw, dst, dstw); + code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw); FAIL_IF(!code); *code = 0xc7; compiler->mode32 = 0; @@ -821,23 +828,9 @@ static int emit_mov_int(struct sljit_compiler *compiler, int sign, code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw); FAIL_IF(!code); *code++ = 0x63; - } else if (dst_r == src) { - compiler->mode32 = 0; - code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 32, dst, 0); - FAIL_IF(!code); - *code |= 0x4 << 3; - code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 32, dst, 0); - FAIL_IF(!code); - *code |= 0x7 << 3; } else { - /* xor reg, reg. */ - code = emit_x86_instruction(compiler, 1, dst_r, 0, dst_r, 0); - FAIL_IF(!code); - *code++ = 0x33; compiler->mode32 = 1; - code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw); - FAIL_IF(!code); - *code++ = 0x8b; + FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw)); compiler->mode32 = 0; } } diff --git a/sljit/sljitNativeX86_common.c b/sljit/sljitNativeX86_common.c index 66bf7c3..6bd734b 100644 --- a/sljit/sljitNativeX86_common.c +++ b/sljit/sljitNativeX86_common.c @@ -602,34 +602,26 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int if (op == SLJIT_SDIV) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG2, 0); - EMIT_MOV(compiler, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG1, 0); -#else - EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0); #endif + /* CDQ instruction */ #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - buf = (sljit_ub*)ensure_buf(compiler, 1 + 3); + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1); FAIL_IF(!buf); - INC_SIZE(3); - *buf++ = 0xc1; - *buf++ = 0xfa; - *buf = 0x1f; + INC_SIZE(1); + *buf = 0x99; #else if (compiler->mode32) { - buf = (sljit_ub*)ensure_buf(compiler, 1 + 3); + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1); FAIL_IF(!buf); - INC_SIZE(3); - *buf++ = 0xc1; - *buf++ = 0xfa; - *buf = 0x1f; + INC_SIZE(1); + *buf = 0x99; } else { - buf = (sljit_ub*)ensure_buf(compiler, 1 + 4); + buf = (sljit_ub*)ensure_buf(compiler, 1 + 2); FAIL_IF(!buf); - INC_SIZE(4); + INC_SIZE(2); *buf++ = REX_W; - *buf++ = 0xc1; - *buf++ = 0xfa; - *buf = 0x3f; + *buf = 0x99; } #endif } |