summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15>2013-01-01 21:41:23 +0000
committerzherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15>2013-01-01 21:41:23 +0000
commitdff3c63ddf5f19647a0115d05ee708d382be184d (patch)
tree54faccd2d9eda40578d1500ac2495d81a29ff58b
parentc34d7c547e81cb171e90ecbf171865d2bceac9be (diff)
downloadpcre-dff3c63ddf5f19647a0115d05ee708d382be184d.tar.gz
JIT compiler update.
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1237 2f5784b3-3f2a-0410-8824-cb99058d5e15
-rw-r--r--sljit/sljitLir.c44
-rw-r--r--sljit/sljitNativeX86_common.c81
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);
}