summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15>2012-01-13 13:34:07 +0000
committerzherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15>2012-01-13 13:34:07 +0000
commit873f3e06c2aff02a618a67ecb4167bbec0bcfd58 (patch)
treecfca991bef7deb0053db95ee10f3fc55f4d18d39
parent7e3f2077c984db31b5d303b88baeab6eadcb08f1 (diff)
downloadpcre-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.c77
-rw-r--r--sljit/sljitLir.h28
-rw-r--r--sljit/sljitNativeARM_Thumb2.c2
-rw-r--r--sljit/sljitNativeMIPS_common.c76
-rw-r--r--sljit/sljitNativeX86_64.c27
-rw-r--r--sljit/sljitNativeX86_common.c28
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
}