diff options
author | zherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2013-01-01 21:41:23 +0000 |
---|---|---|
committer | zherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2013-01-01 21:41:23 +0000 |
commit | dff3c63ddf5f19647a0115d05ee708d382be184d (patch) | |
tree | 54faccd2d9eda40578d1500ac2495d81a29ff58b /sljit | |
parent | c34d7c547e81cb171e90ecbf171865d2bceac9be (diff) | |
download | pcre-dff3c63ddf5f19647a0115d05ee708d382be184d.tar.gz |
JIT compiler update.
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1237 2f5784b3-3f2a-0410-8824-cb99058d5e15
Diffstat (limited to 'sljit')
-rw-r--r-- | sljit/sljitLir.c | 44 | ||||
-rw-r--r-- | sljit/sljitNativeX86_common.c | 81 |
2 files changed, 92 insertions, 33 deletions
diff --git a/sljit/sljitLir.c b/sljit/sljitLir.c index 6979841..20e1e61 100644 --- a/sljit/sljitLir.c +++ b/sljit/sljitLir.c @@ -652,14 +652,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp } static char* reg_names[] = { - (char*)"<noreg>", (char*)"t1", (char*)"t2", (char*)"t3", - (char*)"te1", (char*)"te2", (char*)"s1", (char*)"s2", - (char*)"s3", (char*)"se1", (char*)"se2", (char*)"lcr" + (char*)"unused", (char*)"s1", (char*)"s2", (char*)"s3", + (char*)"se1", (char*)"se2", (char*)"p1", (char*)"p2", + (char*)"p3", (char*)"pe1", (char*)"pe2", (char*)"lc" }; static char* freg_names[] = { - (char*)"<noreg>", (char*)"float_r1", (char*)"float_r2", (char*)"float_r3", - (char*)"float_r4", (char*)"float_r5", (char*)"float_r6" + (char*)"unused", (char*)"f1", (char*)"f2", (char*)"f3", + (char*)"f4", (char*)"f5", (char*)"f6" }; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) @@ -736,17 +736,17 @@ static SLJIT_CONST char* op_names[] = { }; static char* jump_names[] = { - (char*)"c_equal", (char*)"c_not_equal", - (char*)"c_less", (char*)"c_greater_equal", - (char*)"c_greater", (char*)"c_less_equal", - (char*)"c_sig_less", (char*)"c_sig_greater_equal", - (char*)"c_sig_greater", (char*)"c_sig_less_equal", - (char*)"c_overflow", (char*)"c_not_overflow", - (char*)"c_mul_overflow", (char*)"c_mul_not_overflow", - (char*)"c_float_equal", (char*)"c_float_not_equal", - (char*)"c_float_less", (char*)"c_float_greater_equal", - (char*)"c_float_greater", (char*)"c_float_less_equal", - (char*)"c_float_unordered", (char*)"c_float_ordered", + (char*)"equal", (char*)"not_equal", + (char*)"less", (char*)"greater_equal", + (char*)"greater", (char*)"less_equal", + (char*)"sig_less", (char*)"sig_greater_equal", + (char*)"sig_greater", (char*)"sig_less_equal", + (char*)"overflow", (char*)"not_overflow", + (char*)"mul_overflow", (char*)"mul_not_overflow", + (char*)"float_equal", (char*)"float_not_equal", + (char*)"float_less", (char*)"float_greater_equal", + (char*)"float_greater", (char*)"float_less_equal", + (char*)"float_unordered", (char*)"float_ordered", (char*)"jump", (char*)"fast_call", (char*)"call0", (char*)"call1", (char*)"call2", (char*)"call3" }; @@ -1104,7 +1104,7 @@ static SLJIT_INLINE void check_sljit_emit_jump(struct sljit_compiler *compiler, SLJIT_ASSERT((type & 0xff) >= SLJIT_C_EQUAL && (type & 0xff) <= SLJIT_CALL3); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) - fprintf(compiler->verbose, " jump%s<%s>\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]); + fprintf(compiler->verbose, " jump%s.%s\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]); #endif } @@ -1127,7 +1127,7 @@ static SLJIT_INLINE void check_sljit_emit_cmp(struct sljit_compiler *compiler, s #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " %scmp%s<%s> ", !(type & SLJIT_INT_OP) ? "" : "i", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]); + fprintf(compiler->verbose, " %scmp%s.%s ", !(type & SLJIT_INT_OP) ? "" : "i", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]); sljit_verbose_param(src1, src1w); fprintf(compiler->verbose, ", "); sljit_verbose_param(src2, src2w); @@ -1156,7 +1156,7 @@ static SLJIT_INLINE void check_sljit_emit_fcmp(struct sljit_compiler *compiler, #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " %scmp%s<%s> ", (type & SLJIT_SINGLE_OP) ? "s" : "d", + fprintf(compiler->verbose, " %scmp%s.%s ", (type & SLJIT_SINGLE_OP) ? "s" : "d", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]); sljit_verbose_fparam(src1, src1w); fprintf(compiler->verbose, ", "); @@ -1187,7 +1187,7 @@ static SLJIT_INLINE void check_sljit_emit_ijump(struct sljit_compiler *compiler, #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " ijump<%s> ", jump_names[type]); + fprintf(compiler->verbose, " ijump.%s ", jump_names[type]); sljit_verbose_param(src, srcw); fprintf(compiler->verbose, "\n"); } @@ -1223,14 +1223,14 @@ static SLJIT_INLINE void check_sljit_emit_op_flags(struct sljit_compiler *compil #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " op_flags<%s%s%s%s> ", !(op & SLJIT_INT_OP) ? "" : "i", + fprintf(compiler->verbose, " %sflags.%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)], !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k"); sljit_verbose_param(dst, dstw); if (src != SLJIT_UNUSED) { fprintf(compiler->verbose, ", "); sljit_verbose_param(src, srcw); } - fprintf(compiler->verbose, ", <%s>\n", jump_names[type]); + fprintf(compiler->verbose, ", %s\n", jump_names[type]); } #endif } diff --git a/sljit/sljitNativeX86_common.c b/sljit/sljitNativeX86_common.c index 8aca5b9..41ff874 100644 --- a/sljit/sljitNativeX86_common.c +++ b/sljit/sljitNativeX86_common.c @@ -206,6 +206,7 @@ static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = { #define OR_r_rm 0x0b #define OR_EAX_i32 0x0d #define OR_rm_r 0x09 +#define OR_rm8_r8 0x08 #define POP_r 0x58 #define POP_rm 0x8f #define POPF 0x9d @@ -286,12 +287,20 @@ static void get_cpu_features(void) /* AT&T syntax. */ __asm__ ( "movl $0x1, %%eax\n" +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + /* On x86-32, there is no red zone, so this + should work (no need for a local variable). */ + "push %%ebx\n" +#endif "cpuid\n" +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + "pop %%ebx\n" +#endif "movl %%edx, %0\n" : "=g" (features) : #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - : "%eax", "%ebx", "%ecx", "%edx" + : "%eax", "%ecx", "%edx" #else : "%rax", "%rbx", "%rcx", "%rdx" #endif @@ -1757,7 +1766,7 @@ static sljit_si emit_mul(struct sljit_compiler *compiler, return SLJIT_SUCCESS; } -static sljit_si emit_lea_binary(struct sljit_compiler *compiler, +static sljit_si emit_lea_binary(struct sljit_compiler *compiler, sljit_si keep_flags, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w) @@ -1766,10 +1775,12 @@ static sljit_si emit_lea_binary(struct sljit_compiler *compiler, sljit_si dst_r, done = 0; /* These cases better be left to handled by normal way. */ - if (dst == src1 && dstw == src1w) - return SLJIT_ERR_UNSUPPORTED; - if (dst == src2 && dstw == src2w) - return SLJIT_ERR_UNSUPPORTED; + if (!keep_flags) { + if (dst == src1 && dstw == src1w) + return SLJIT_ERR_UNSUPPORTED; + if (dst == src2 && dstw == src2w) + return SLJIT_ERR_UNSUPPORTED; + } dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER; @@ -2125,7 +2136,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler switch (GET_OPCODE(op)) { case SLJIT_ADD: if (!GET_FLAGS(op)) { - if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED) + if (emit_lea_binary(compiler, op & SLJIT_KEEP_FLAGS, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED) return compiler->error; } else @@ -2145,7 +2156,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUB: if (!GET_FLAGS(op)) { - if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED) + if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, op & SLJIT_KEEP_FLAGS, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED) return compiler->error; } else @@ -2609,6 +2620,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com cond_set = get_jump_code(type) + 0x10; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && dst <= TMP_REGISTER && dst == src) { + inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + 3); + FAIL_IF(!inst); + INC_SIZE(4 + 3); + /* Set low register to conditional flag. */ + *inst++ = (reg_map[TMP_REGISTER] <= 7) ? REX : REX_B; + *inst++ = GROUP_0F; + *inst++ = cond_set; + *inst++ = MOD_REG | reg_lmap[TMP_REGISTER]; + *inst++ = REX | (reg_map[TMP_REGISTER] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B); + *inst++ = OR_rm8_r8; + *inst++ = MOD_REG | (reg_lmap[TMP_REGISTER] << 3) | reg_lmap[dst]; + return SLJIT_SUCCESS; + } + reg = (op == SLJIT_MOV && dst <= TMP_REGISTER) ? dst : TMP_REGISTER; inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + 4); @@ -2689,6 +2715,39 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com return SLJIT_SUCCESS; } + if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && dst <= TMP_REGISTER && dst == src && reg_map[dst] <= 4) { + SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG1] == 0, scratch_reg1_must_be_eax); + if (dst != SLJIT_SCRATCH_REG1) { + inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 2 + 1); + FAIL_IF(!inst); + INC_SIZE(1 + 3 + 2 + 1); + /* Set low register to conditional flag. */ + *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER]; + *inst++ = GROUP_0F; + *inst++ = cond_set; + *inst++ = MOD_REG | 0 /* eax */; + *inst++ = OR_rm8_r8; + *inst++ = MOD_REG | (0 /* eax */ << 3) | reg_map[dst]; + *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER]; + } + else { + inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 3 + 2 + 2); + FAIL_IF(!inst); + INC_SIZE(2 + 3 + 2 + 2); + /* Set low register to conditional flag. */ + *inst++ = XCHG_r_rm; + *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REGISTER]; + *inst++ = GROUP_0F; + *inst++ = cond_set; + *inst++ = MOD_REG | 1 /* ecx */; + *inst++ = OR_rm8_r8; + *inst++ = MOD_REG | (1 /* ecx */ << 3) | 0 /* eax */; + *inst++ = XCHG_r_rm; + *inst++ = MOD_REG | (1 /* ecx */ << 3) | 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); @@ -2733,16 +2792,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *co if (NOT_HALFWORD(offset)) { FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, offset)); #if (defined SLJIT_DEBUG && SLJIT_DEBUG) - SLJIT_ASSERT(emit_lea_binary(compiler, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REGISTER, 0) != SLJIT_ERR_UNSUPPORTED); + SLJIT_ASSERT(emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REGISTER, 0) != SLJIT_ERR_UNSUPPORTED); return compiler->error; #else - return emit_lea_binary(compiler, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REGISTER, 0); + return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REGISTER, 0); #endif } #endif if (offset != 0) - return emit_lea_binary(compiler, dst, dstw, SLJIT_LOCALS_REG, 0, SLJIT_IMM, offset); + return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, SLJIT_IMM, offset); return emit_mov(compiler, dst, dstw, SLJIT_LOCALS_REG, 0); } |