diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | pcre.h.in | 20 | ||||
-rw-r--r-- | pcre16_utf16_utils.c | 2 | ||||
-rw-r--r-- | pcre_get.c | 12 | ||||
-rw-r--r-- | pcre_internal.h | 4 | ||||
-rw-r--r-- | pcre_jit_compile.c | 3 | ||||
-rw-r--r-- | pcre_jit_test.c | 8 | ||||
-rw-r--r-- | pcretest.c | 4 | ||||
-rw-r--r-- | sljit/sljitLir.c | 6 | ||||
-rw-r--r-- | sljit/sljitLir.h | 72 | ||||
-rw-r--r-- | sljit/sljitNativeARM_Thumb2.c | 27 | ||||
-rw-r--r-- | sljit/sljitNativeARM_v5.c | 8 | ||||
-rw-r--r-- | sljit/sljitNativeMIPS_common.c | 4 | ||||
-rw-r--r-- | sljit/sljitNativePPC_32.c | 29 | ||||
-rw-r--r-- | sljit/sljitNativePPC_64.c | 32 | ||||
-rw-r--r-- | sljit/sljitNativePPC_common.c | 124 | ||||
-rw-r--r-- | sljit/sljitNativeX86_32.c | 4 | ||||
-rw-r--r-- | sljit/sljitNativeX86_64.c | 6 | ||||
-rw-r--r-- | sljit/sljitNativeX86_common.c | 49 |
19 files changed, 279 insertions, 138 deletions
@@ -30,6 +30,9 @@ Version 8.30 command "pattern=`printf 'xxx\r\njkl'`" was run. The pattern is now taken from a file. +8. Ovector size of 2 is also supported by JIT based pcre_exec (the ovector size + rounding is not applied in this particular case). + Version 8.21 12-Dec-2011 ------------------------ @@ -280,15 +280,15 @@ typedef struct real_pcre_jit_stack pcre_jit_stack; struct real_pcre16_jit_stack; /* declaration; the definition is private */ typedef struct real_pcre16_jit_stack pcre16_jit_stack; -/* If PCRE is compiled with 16 bit character support, PCRE_SCHAR16 must contain +/* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must contain a 16 bit wide signed data type. Otherwise it can be a dummy data type since pcre16 functions are not implemented. There is a check for this in pcre_internal.h. */ -#ifndef PCRE_SCHAR16 -#define PCRE_SCHAR16 unsigned short +#ifndef PCRE_UCHAR16 +#define PCRE_UCHAR16 unsigned short #endif #ifndef PCRE_SPTR16 -#define PCRE_SPTR16 const PCRE_SCHAR16 * +#define PCRE_SPTR16 const PCRE_UCHAR16 * #endif /* When PCRE is compiled as a C++ library, the subject pointer type can be @@ -323,7 +323,7 @@ typedef struct pcre16_extra { void *callout_data; /* Data passed back in callouts */ const unsigned char *tables; /* Pointer to character tables */ unsigned long int match_limit_recursion; /* Max recursive calls to match() */ - PCRE_SCHAR16 **mark; /* For passing back a mark pointer */ + PCRE_UCHAR16 **mark; /* For passing back a mark pointer */ void *executable_jit; /* Contains a pointer to a compiled jit code */ } pcre16_extra; @@ -370,7 +370,7 @@ typedef struct pcre16_callout_block { int pattern_position; /* Offset to next item in the pattern */ int next_item_length; /* Length of next item in the pattern */ /* ------------------- Added for Version 2 -------------------------- */ - const PCRE_SCHAR16 *mark; /* Pointer to current mark or NULL */ + const PCRE_UCHAR16 *mark; /* Pointer to current mark or NULL */ /* ------------------------------------------------------------------ */ } pcre16_callout_block; @@ -426,11 +426,11 @@ PCRE_EXP_DECL int pcre16_config(int, void *); PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *, int *, int, const char *, char *, int); PCRE_EXP_DECL int pcre16_copy_named_substring(const pcre16 *, PCRE_SPTR16, - int *, int, PCRE_SPTR16, PCRE_SCHAR16 *, int); + int *, int, PCRE_SPTR16, PCRE_UCHAR16 *, int); PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int, char *, int); PCRE_EXP_DECL int pcre16_copy_substring(PCRE_SPTR16, int *, int, int, - PCRE_SCHAR16 *, int); + PCRE_UCHAR16 *, int); PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *, const char *, int, int, int, int *, int , int *, int); PCRE_EXP_DECL int pcre16_dfa_exec(const pcre16 *, const pcre16_extra *, @@ -456,7 +456,7 @@ PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16); PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *, char **, char **); PCRE_EXP_DECL int pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR16, - PCRE_SCHAR16 **, PCRE_SCHAR16 **); + PCRE_UCHAR16 **, PCRE_UCHAR16 **); PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int, const char **); PCRE_EXP_DECL int pcre16_get_substring(PCRE_SPTR16, int *, int, int, @@ -481,7 +481,7 @@ PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *, pcre_extra *, const unsigned char *); PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *, pcre16_extra *, const unsigned char *); -PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_SCHAR16 *, +PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *, PCRE_SPTR16, int, int *, int); /* JIT compiler related functions. */ diff --git a/pcre16_utf16_utils.c b/pcre16_utf16_utils.c index 5baefcb..1f97293 100644 --- a/pcre16_utf16_utils.c +++ b/pcre16_utf16_utils.c @@ -82,7 +82,7 @@ Returns: the number of 16-bit units placed into the output buffer, */ int -pcre16_utf16_to_host_byte_order(PCRE_SCHAR16 *output, PCRE_SPTR16 input, +pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *output, PCRE_SPTR16 input, int length, int *host_byte_order, int keep_boms) { #ifdef SUPPORT_UTF @@ -139,7 +139,7 @@ pcre_get_stringtable_entries(const pcre *code, const char *stringname, #else PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 stringname, - PCRE_SCHAR16 **firstptr, PCRE_SCHAR16 **lastptr) + PCRE_UCHAR16 **firstptr, PCRE_UCHAR16 **lastptr) #endif { int rc; @@ -196,8 +196,8 @@ while (top > bot) *firstptr = (char *)first; *lastptr = (char *)last; #else - *firstptr = (PCRE_SCHAR16 *)first; - *lastptr = (PCRE_SCHAR16 *)last; + *firstptr = (PCRE_UCHAR16 *)first; + *lastptr = (PCRE_UCHAR16 *)last; #endif return entrysize; } @@ -247,7 +247,7 @@ entrysize = pcre_get_stringtable_entries(code, stringname, if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0) return pcre16_get_stringnumber(code, stringname); entrysize = pcre16_get_stringtable_entries(code, stringname, - (PCRE_SCHAR16 **)&first, (PCRE_SCHAR16 **)&last); + (PCRE_UCHAR16 **)&first, (PCRE_UCHAR16 **)&last); #endif if (entrysize <= 0) return entrysize; for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize) @@ -295,7 +295,7 @@ pcre_copy_substring(const char *subject, int *ovector, int stringcount, #else PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, - int stringnumber, PCRE_SCHAR16 *buffer, int size) + int stringnumber, PCRE_UCHAR16 *buffer, int size) #endif { int yield; @@ -348,7 +348,7 @@ pcre_copy_named_substring(const pcre *code, const char *subject, PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_copy_named_substring(const pcre16 *code, PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 stringname, - PCRE_SCHAR16 *buffer, int size) + PCRE_UCHAR16 *buffer, int size) #endif { int n = get_first_set(code, stringname, ovector); diff --git a/pcre_internal.h b/pcre_internal.h index e5d42bd..49558e1 100644 --- a/pcre_internal.h +++ b/pcre_internal.h @@ -254,9 +254,9 @@ typedef unsigned char pcre_uchar; #ifdef COMPILE_PCRE16 #if USHRT_MAX != 65535 -/* This is a warning message. Change PCRE_SCHAR16 to a 16 bit data type in +/* This is a warning message. Change PCRE_UCHAR16 to a 16 bit data type in pcre.h(.in) and disable (comment out) this message. */ -#error Warning: PCRE_SCHAR16 is not a 16 bit data type. +#error Warning: PCRE_UCHAR16 is not a 16 bit data type. #endif typedef pcre_uint16 pcre_uchar; diff --git a/pcre_jit_compile.c b/pcre_jit_compile.c index ec7dece..599619a 100644 --- a/pcre_jit_compile.c +++ b/pcre_jit_compile.c @@ -6772,7 +6772,8 @@ workspace. We don't need the workspace here. For compatibility, we limit the number of captured strings in the same way as pcre_exec(), so that the user gets the same result with and without JIT. */ -offsetcount = ((offsetcount - (offsetcount % 3)) * 2)/3; +if (offsetcount != 2) + offsetcount = ((offsetcount - (offsetcount % 3)) * 2) / 3; maxoffsetcount = (re->top_bracket + 1) * 2; if (offsetcount > maxoffsetcount) offsetcount = maxoffsetcount; diff --git a/pcre_jit_test.c b/pcre_jit_test.c index f9e9991..0f394f7 100644 --- a/pcre_jit_test.c +++ b/pcre_jit_test.c @@ -680,7 +680,7 @@ static const unsigned char *tables(int mode) char null_str[1] = { 0 }; #else pcre16 *regex; - PCRE_SCHAR16 null_str[1] = { 0 }; + PCRE_UCHAR16 null_str[1] = { 0 }; #endif if (mode) { @@ -771,7 +771,7 @@ static void setstack16(pcre16_extra *extra) #ifdef SUPPORT_PCRE16 -static int convert_utf8_to_utf16(const char *input, PCRE_SCHAR16 *output, int *offsetmap, int max_length) +static int convert_utf8_to_utf16(const char *input, PCRE_UCHAR16 *output, int *offsetmap, int max_length) { unsigned char *iptr = (unsigned char*)input; unsigned short *optr = (unsigned short *)output; @@ -819,7 +819,7 @@ static int convert_utf8_to_utf16(const char *input, PCRE_SCHAR16 *output, int *o return (int)(optr - (unsigned short *)output); } -static int copy_char8_to_char16(const char *input, PCRE_SCHAR16 *output, int max_length) +static int copy_char8_to_char16(const char *input, PCRE_UCHAR16 *output, int max_length) { unsigned char *iptr = (unsigned char*)input; unsigned short *optr = (unsigned short *)output; @@ -836,7 +836,7 @@ static int copy_char8_to_char16(const char *input, PCRE_SCHAR16 *output, int max } #define REGTEST_MAX_LENGTH 4096 -static PCRE_SCHAR16 regtest_buf[REGTEST_MAX_LENGTH]; +static PCRE_UCHAR16 regtest_buf[REGTEST_MAX_LENGTH]; static int regtest_offsetmap[REGTEST_MAX_LENGTH]; #endif /* SUPPORT_PCRE16 */ @@ -307,11 +307,11 @@ argument, the casting might be incorrectly applied. */ #define PCRE_COPY_NAMED_SUBSTRING16(rc, re, bptr, offsets, count, \ namesptr, cbuffer, size) \ rc = pcre16_copy_named_substring((pcre16 *)re, (PCRE_SPTR16)bptr, offsets, \ - count, (PCRE_SPTR16)namesptr, (PCRE_SCHAR16 *)cbuffer, size/2) + count, (PCRE_SPTR16)namesptr, (PCRE_UCHAR16 *)cbuffer, size/2) #define PCRE_COPY_SUBSTRING16(rc, bptr, offsets, count, i, cbuffer, size) \ rc = pcre16_copy_substring((PCRE_SPTR16)bptr, offsets, count, i, \ - (PCRE_SCHAR16 *)cbuffer, size/2) + (PCRE_UCHAR16 *)cbuffer, size/2) #define PCRE_DFA_EXEC16(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets, workspace, size_workspace) \ diff --git a/sljit/sljitLir.c b/sljit/sljitLir.c index 1c44f3b..4a6928c 100644 --- a/sljit/sljitLir.c +++ b/sljit/sljitLir.c @@ -694,7 +694,7 @@ static SLJIT_INLINE void check_sljit_emit_enter(struct sljit_compiler *compiler, #endif } -static SLJIT_INLINE void check_sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) +static SLJIT_INLINE void check_sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) { /* If debug and verbose are disabled, all arguments are unused. */ SLJIT_UNUSED_ARG(compiler); @@ -798,7 +798,7 @@ static SLJIT_INLINE void check_sljit_emit_op0(struct sljit_compiler *compiler, i || ((op & ~SLJIT_INT_OP) >= SLJIT_UDIV && (op & ~SLJIT_INT_OP) <= SLJIT_SDIV)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) - fprintf(compiler->verbose, " %s%s\n", op_names[GET_OPCODE(op)], !(op & SLJIT_INT_OP) ? "" : "i"); + fprintf(compiler->verbose, " %s%s\n", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)]); #endif } @@ -1233,7 +1233,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i return SLJIT_ERR_UNSUPPORTED; } -SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(args); diff --git a/sljit/sljitLir.h b/sljit/sljitLir.h index 4db6e93..995f70b 100644 --- a/sljit/sljitLir.h +++ b/sljit/sljitLir.h @@ -312,32 +312,46 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler /* Instruction generation. Returns with error code. */ /* - Entry instruction. The instruction has "args" number of arguments - and will use the first "general" number of general registers. - The arguments are passed into the general registers (arg1 to general_reg1, and so on). - Thus, "args" must be less or equal than "general". A local_size extra - stack space is allocated for the jit code (must be less or equal than - SLJIT_MAX_LOCAL_SIZE), which can accessed through SLJIT_LOCALS_REG (see - the notes there). SLJIT_LOCALS_REG is not necessary the real stack pointer! - It just points somewhere in the stack if local_size > 0 (!). Thus, the only - thing which is known that the memory area between SLJIT_LOCALS_REG and - SLJIT_LOCALS_REG + local_size is a valid stack area if local_size > 0 -*/ - -/* Note: multiple calls of this function overwrites the previous call. */ + The executable code is basically a function call from the viewpoint of + the C language. The function calls must obey to the ABI (Application + Binary Interface) of the platform, which specify the purpose of machine + registers and stack handling among other things. The sljit_emit_enter + function emits the necessary instructions for setting up a new context + for the executable code and moves function arguments to the general + registers. The number of arguments are specified in the "args" + parameter and the first argument goes to SLJIT_GENERAL_REG1, the second + goes to SLJIT_GENERAL_REG2 and so on. The number of temporary and + general registers are passed in "temporaries" and "generals" arguments + respectively. Since the general registers contains the arguments, + "args" must be less or equal than "generals". The sljit_emit_enter + is also capable of allocating a stack space for local variables. The + "local_size" argument contains the size in bytes of this local area + and its staring address is stored in SLJIT_LOCALS_REG. However + the SLJIT_LOCALS_REG is not necessary the machine stack pointer. + The memory bytes between SLJIT_LOCALS_REG (inclusive) and + SLJIT_LOCALS_REG + local_size (exclusive) can be modified freely + until the function returns. The stack space is uninitialized. + + Note: every call of sljit_emit_enter and sljit_set_context overwrites + the previous context. */ #define SLJIT_MAX_LOCAL_SIZE 65536 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size); -/* Since sljit_emit_return (and many asserts) uses variables which are initialized - by sljit_emit_enter, a simple return is not possible if these variables are not - initialized. sljit_fake_enter does not emit any instruction, just initialize - those variables. */ +/* The machine code has a context (which contains the local stack space size, + number of used registers, etc.) which initialized by sljit_emit_enter. Several + functions (like sljit_emit_return) requres this context to be able to generate + the appropriate code. However, some code fragments (like inline cache) may have + no normal entry point so their context is unknown for the compiler. Using the + function below we can specify thir context. + + Note: every call of sljit_emit_enter and sljit_set_context overwrites + the previous context. */ /* Note: multiple calls of this function overwrites the previous call. */ -SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size); +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size); /* Return from jit. See below the possible values for src and srcw. */ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw); @@ -530,8 +544,8 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int #define SLJIT_SUB 25 /* Flags: I | C | K */ #define SLJIT_SUBC 26 -/* Note: integer mul */ -/* Flags: I | O (see SLJIT_C_MUL_*) | K */ +/* Note: integer mul + Flags: I | O (see SLJIT_C_MUL_*) | K */ #define SLJIT_MUL 27 /* Flags: I | E | K */ #define SLJIT_AND 28 @@ -539,11 +553,23 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int #define SLJIT_OR 29 /* Flags: I | E | K */ #define SLJIT_XOR 30 -/* Flags: I | E | K */ +/* Flags: I | E | K + Let bit_length be the length of the shift operation: 32 or 64. + If src2 is immediate, src2w is masked by (bit_length - 1). + Otherwise, if the content of src2 is outside the range from 0 + to bit_length - 1, the operation is undefined. */ #define SLJIT_SHL 31 -/* Flags: I | E | K */ +/* Flags: I | E | K + Let bit_length be the length of the shift operation: 32 or 64. + If src2 is immediate, src2w is masked by (bit_length - 1). + Otherwise, if the content of src2 is outside the range from 0 + to bit_length - 1, the operation is undefined. */ #define SLJIT_LSHR 32 -/* Flags: I | E | K */ +/* Flags: I | E | K + Let bit_length be the length of the shift operation: 32 or 64. + If src2 is immediate, src2w is masked by (bit_length - 1). + Otherwise, if the content of src2 is outside the range from 0 + to bit_length - 1, the operation is undefined. */ #define SLJIT_ASHR 33 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op, diff --git a/sljit/sljitNativeARM_Thumb2.c b/sljit/sljitNativeARM_Thumb2.c index 6f27060..f5ae679 100644 --- a/sljit/sljitNativeARM_Thumb2.c +++ b/sljit/sljitNativeARM_Thumb2.c @@ -122,9 +122,11 @@ typedef sljit_ui sljit_ins; #define LSR_W 0xfa20f000 #define LSR_WI 0xea4f0010 #define MOV 0x4600 +#define MOVS 0x0000 #define MOVSI 0x2000 #define MOVT 0xf2c00000 #define MOVW 0xf2400000 +#define MOV_W 0xea4f0000 #define MOV_WI 0xf04f0000 #define MUL 0xfb00f000 #define MVNS 0x43c0 @@ -617,6 +619,13 @@ static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, slji case SLJIT_SHL: if (flags & ARG2_IMM) { imm &= 0x1f; + if (imm == 0) { + if (!(flags & SET_FLAGS)) + return push_inst16(compiler, MOV | SET_REGS44(dst, reg)); + if (IS_2_LO_REGS(dst, reg)) + return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg)); + return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg)); + } if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); @@ -625,6 +634,13 @@ static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, slji case SLJIT_LSHR: if (flags & ARG2_IMM) { imm &= 0x1f; + if (imm == 0) { + if (!(flags & SET_FLAGS)) + return push_inst16(compiler, MOV | SET_REGS44(dst, reg)); + if (IS_2_LO_REGS(dst, reg)) + return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg)); + return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg)); + } if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); @@ -633,6 +649,13 @@ static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, slji case SLJIT_ASHR: if (flags & ARG2_IMM) { imm &= 0x1f; + if (imm == 0) { + if (!(flags & SET_FLAGS)) + return push_inst16(compiler, MOV | SET_REGS44(dst, reg)); + if (IS_2_LO_REGS(dst, reg)) + return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg)); + return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg)); + } if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); @@ -1129,12 +1152,12 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) { int size; CHECK_ERROR_VOID(); - check_sljit_fake_enter(compiler, args, temporaries, generals, local_size); + check_sljit_set_context(compiler, args, temporaries, generals, local_size); compiler->temporaries = temporaries; compiler->generals = generals; diff --git a/sljit/sljitNativeARM_v5.c b/sljit/sljitNativeARM_v5.c index e9b2228..c83b3c3 100644 --- a/sljit/sljitNativeARM_v5.c +++ b/sljit/sljitNativeARM_v5.c @@ -871,12 +871,12 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) { int size; CHECK_ERROR_VOID(); - check_sljit_fake_enter(compiler, args, temporaries, generals, local_size); + check_sljit_set_context(compiler, args, temporaries, generals, local_size); compiler->temporaries = temporaries; compiler->generals = generals; @@ -993,7 +993,9 @@ static sljit_w data_transfer_insts[16] = { if (compiler->shift_imm != 0x20) { \ SLJIT_ASSERT(src1 == TMP_REG1); \ SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \ - return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (compiler->shift_imm << 7) | (opcode << 5) | reg_map[src2])); \ + if (compiler->shift_imm != 0) \ + return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (compiler->shift_imm << 7) | (opcode << 5) | reg_map[src2])); \ + return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, reg_map[src2])); \ } \ return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | ((flags & ARGS_SWAPPED) ? reg_map[src2] : reg_map[src1]))); diff --git a/sljit/sljitNativeMIPS_common.c b/sljit/sljitNativeMIPS_common.c index 8b5bc1b..0e9f209 100644 --- a/sljit/sljitNativeMIPS_common.c +++ b/sljit/sljitNativeMIPS_common.c @@ -513,10 +513,10 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) { CHECK_ERROR_VOID(); - check_sljit_fake_enter(compiler, args, temporaries, generals, local_size); + check_sljit_set_context(compiler, args, temporaries, generals, local_size); compiler->temporaries = temporaries; compiler->generals = generals; diff --git a/sljit/sljitNativePPC_32.c b/sljit/sljitNativePPC_32.c index 82be28c..82d0508 100644 --- a/sljit/sljitNativePPC_32.c +++ b/sljit/sljitNativePPC_32.c @@ -47,10 +47,12 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, switch (op) { case SLJIT_ADD: if (flags & ALT_FORM1) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm); } if (flags & ALT_FORM2) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); } @@ -58,6 +60,11 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm); } + if (flags & ALT_FORM4) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ + FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff))); + return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))); + } if (!(flags & ALT_SET_FLAGS)) return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)); return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); @@ -72,22 +79,28 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, case SLJIT_SUB: if (flags & ALT_FORM1) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm); } - if (flags & ALT_FORM2) { + if (flags & (ALT_FORM2 | ALT_FORM3)) { SLJIT_ASSERT(src2 == TMP_REG2); - return push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm); + if (flags & ALT_FORM2) + FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm)); + if (flags & ALT_FORM3) + return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm); + return SLJIT_SUCCESS; } - if (flags & ALT_FORM3) { - SLJIT_ASSERT(src2 == TMP_REG2); - return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm); + if (flags & (ALT_FORM4 | ALT_FORM5)) { + if (flags & ALT_FORM4) + FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2))); + if (flags & ALT_FORM5) + FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2))); + return SLJIT_SUCCESS; } - if (flags & ALT_FORM4) - return push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)); if (!(flags & ALT_SET_FLAGS)) return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); - if (flags & ALT_FORM5) + if (flags & ALT_FORM6) FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2))); return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); diff --git a/sljit/sljitNativePPC_64.c b/sljit/sljitNativePPC_64.c index e35e862..cc2ae37 100644 --- a/sljit/sljitNativePPC_64.c +++ b/sljit/sljitNativePPC_64.c @@ -149,12 +149,12 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, switch (op) { case SLJIT_ADD: if (flags & ALT_FORM1) { - /* Flags not set: BIN_IMM_EXTS unnecessary. */ + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm); } if (flags & ALT_FORM2) { - /* Flags not set: BIN_IMM_EXTS unnecessary. */ + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); } @@ -163,6 +163,11 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, BIN_IMM_EXTS(); return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm); } + if (flags & ALT_FORM4) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ + FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff))); + return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))); + } if (!(flags & ALT_SET_FLAGS)) return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)); BIN_EXTS(); @@ -179,24 +184,29 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, case SLJIT_SUB: if (flags & ALT_FORM1) { - /* Flags not set: BIN_IMM_EXTS unnecessary. */ + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm); } - if (flags & ALT_FORM2) { + if (flags & (ALT_FORM2 | ALT_FORM3)) { SLJIT_ASSERT(src2 == TMP_REG2); - return push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm); + if (flags & ALT_FORM2) + FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm)); + if (flags & ALT_FORM3) + return push_inst(compiler, CMPLI | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm); + return SLJIT_SUCCESS; } - if (flags & ALT_FORM3) { - SLJIT_ASSERT(src2 == TMP_REG2); - return push_inst(compiler, CMPLI | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm); + if (flags & (ALT_FORM4 | ALT_FORM5)) { + if (flags & ALT_FORM4) + FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2))); + if (flags & ALT_FORM5) + return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)); + return SLJIT_SUCCESS; } - if (flags & ALT_FORM4) - return push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)); if (!(flags & ALT_SET_FLAGS)) return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); BIN_EXTS(); - if (flags & ALT_FORM5) + if (flags & ALT_FORM6) FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2))); return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); diff --git a/sljit/sljitNativePPC_common.c b/sljit/sljitNativePPC_common.c index ee8e173..462ccc3 100644 --- a/sljit/sljitNativePPC_common.c +++ b/sljit/sljitNativePPC_common.c @@ -75,9 +75,9 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to) /* Instruction bit sections. OE and Rc flag (see ALT_SET_FLAGS). */ -#define OERC(flags) (((flags & ALT_SET_FLAGS) >> 15) | ((flags & ALT_SET_FLAGS) >> 5)) +#define OERC(flags) (((flags & ALT_SET_FLAGS) >> 10) | (flags & ALT_SET_FLAGS)) /* Rc flag (see ALT_SET_FLAGS). */ -#define RC(flags) ((flags & ALT_SET_FLAGS) >> 15) +#define RC(flags) ((flags & ALT_SET_FLAGS) >> 10) #define HI(opcode) ((opcode) << 26) #define LO(opcode) ((opcode) << 1) @@ -97,6 +97,7 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to) #define BLR (HI(19) | LO(16) | (0x14 << 21)) #define CNTLZD (HI(31) | LO(58)) #define CNTLZW (HI(31) | LO(26)) +#define CMP (HI(31) | LO(0)) #define CMPI (HI(11)) #define CMPL (HI(31) | LO(32)) #define CMPLI (HI(10)) @@ -390,32 +391,32 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil /* Other inp_flags. */ -#define ARG_TEST 0x0100 -#define ALT_FORM1 0x0200 -#define ALT_FORM2 0x0400 -#define ALT_FORM3 0x0800 -#define ALT_FORM4 0x1000 -#define ALT_FORM5 0x2000 +#define ARG_TEST 0x000100 /* Integer opertion and set flags -> requires exts on 64 bit systems. */ -#define ALT_SIGN_EXT 0x4000 +#define ALT_SIGN_EXT 0x000200 /* This flag affects the RC() and OERC() macros. */ -#define ALT_SET_FLAGS 0x8000 - - /* Source and destination is register. */ -#define REG_DEST 0x0001 -#define REG1_SOURCE 0x0002 -#define REG2_SOURCE 0x0004 - /* getput_arg_fast returned true. */ -#define FAST_DEST 0x0008 - /* Multiple instructions are required. */ -#define SLOW_DEST 0x0010 -/* ALT_FORM1 0x0200 - ALT_FORM2 0x0400 - ALT_FORM3 0x0800 - ALT_FORM4 0x1000 - ALT_FORM5 0x2000 - ALT_SIGN_EXT 0x4000 - ALT_SET_FLAGS 0x8000 */ +#define ALT_SET_FLAGS 0x000400 +#define ALT_FORM1 0x010000 +#define ALT_FORM2 0x020000 +#define ALT_FORM3 0x040000 +#define ALT_FORM4 0x080000 +#define ALT_FORM5 0x100000 +#define ALT_FORM6 0x200000 + +/* Source and destination is register. */ +#define REG_DEST 0x000001 +#define REG1_SOURCE 0x000002 +#define REG2_SOURCE 0x000004 +/* getput_arg_fast returned true. */ +#define FAST_DEST 0x000008 +/* Multiple instructions are required. */ +#define SLOW_DEST 0x000010 +/* +ALT_SIGN_EXT 0x000200 +ALT_SET_FLAGS 0x000400 +ALT_FORM1 0x010000 +... +ALT_FORM6 0x200000 */ #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) #include "sljitNativePPC_32.c" @@ -499,10 +500,10 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) { CHECK_ERROR_VOID(); - check_sljit_fake_enter(compiler, args, temporaries, generals, local_size); + check_sljit_set_context(compiler, args, temporaries, generals, local_size); compiler->temporaries = temporaries; compiler->generals = generals; @@ -901,7 +902,7 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags, int src1_r; int src2_r; int sugg_src2_r = TMP_REG2; - int flags = inp_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS); + int flags = inp_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_FORM6 | ALT_SIGN_EXT | ALT_SET_FLAGS); compiler->cache_arg = 0; compiler->cache_argw = 0; @@ -1173,6 +1174,14 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int (((src) & SLJIT_IMM) && !((srcw) & ~0xffff0000)) #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +#define TEST_ADD_IMM(src, srcw) \ + (((src) & SLJIT_IMM) && (srcw) <= SLJIT_W(0x7fff7fff) && (srcw) >= SLJIT_W(-0x80000000)) +#else +#define TEST_ADD_IMM(src, srcw) \ + ((src) & SLJIT_IMM) +#endif + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #define TEST_UI_IMM(src, srcw) \ (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff)) #else @@ -1211,7 +1220,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int switch (GET_OPCODE(op)) { case SLJIT_ADD: - if (!GET_FLAGS(op)) { + if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) { if (TEST_SL_IMM(src2, src2w)) { compiler->imm = src2w & 0xffff; return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); @@ -1228,6 +1237,15 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int compiler->imm = (src1w >> 16) & 0xffff; return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); } + /* Range between -1 and -32768 is covered above. */ + if (TEST_ADD_IMM(src2, src2w)) { + compiler->imm = src2w & 0xffffffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0); + } + if (TEST_ADD_IMM(src1, src1w)) { + compiler->imm = src1w & 0xffffffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0); + } } if (!(GET_FLAGS(op) & (SLJIT_SET_E | SLJIT_SET_O))) { if (TEST_SL_IMM(src2, src2w)) { @@ -1245,7 +1263,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int return emit_op(compiler, SLJIT_ADDC, inp_flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUB: - if (!GET_FLAGS(op)) { + if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) { if (TEST_SL_IMM(src2, -src2w)) { compiler->imm = (-src2w) & 0xffff; return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); @@ -1258,25 +1276,37 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int compiler->imm = ((-src2w) >> 16) & 0xffff; return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); } + /* Range between -1 and -32768 is covered above. */ + if (TEST_ADD_IMM(src2, -src2w)) { + compiler->imm = -src2w & 0xffffffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0); + } } - if (dst == SLJIT_UNUSED && !(GET_FLAGS(op) & ~(SLJIT_SET_E | SLJIT_SET_S))) { - /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */ - if (TEST_SL_IMM(src2, src2w)) { - compiler->imm = src2w & 0xffff; - return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); + if (dst == SLJIT_UNUSED && (op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U)) && !(op & (SLJIT_SET_O | SLJIT_SET_C))) { + if (!(op & SLJIT_SET_U)) { + /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */ + if (TEST_SL_IMM(src2, src2w)) { + compiler->imm = src2w & 0xffff; + return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); + } + if (GET_FLAGS(op) == SLJIT_SET_E && TEST_SL_IMM(src1, src1w)) { + compiler->imm = src1w & 0xffff; + return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); + } } - if (GET_FLAGS(op) == SLJIT_SET_E && TEST_SL_IMM(src1, src1w)) { - compiler->imm = src1w & 0xffff; - return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); + if (!(op & (SLJIT_SET_E | SLJIT_SET_S))) { + /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */ + if (TEST_UL_IMM(src2, src2w)) { + compiler->imm = src2w & 0xffff; + return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); + } + return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w); } - } - if (dst == SLJIT_UNUSED && GET_FLAGS(op) == SLJIT_SET_U) { - /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */ - if (TEST_UL_IMM(src2, src2w)) { - compiler->imm = src2w & 0xffff; - return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); + if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= 0x7fff) { + compiler->imm = src2w; + return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); } - return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w); + return emit_op(compiler, SLJIT_SUB, inp_flags | ((op & SLJIT_SET_U) ? ALT_FORM4 : 0) | ((op & (SLJIT_SET_E | SLJIT_SET_S)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w); } if (!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O))) { if (TEST_SL_IMM(src2, -src2w)) { @@ -1285,7 +1315,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int } } /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */ - return emit_op(compiler, SLJIT_SUB, inp_flags | (!(op & SLJIT_SET_U) ? 0 : ALT_FORM5), dst, dstw, src1, src1w, src2, src2w); + return emit_op(compiler, SLJIT_SUB, inp_flags | (!(op & SLJIT_SET_U) ? 0 : ALT_FORM6), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUBC: return emit_op(compiler, SLJIT_SUBC, inp_flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w); diff --git a/sljit/sljitNativeX86_32.c b/sljit/sljitNativeX86_32.c index 53d3cd5..1470c5f 100644 --- a/sljit/sljitNativeX86_32.c +++ b/sljit/sljitNativeX86_32.c @@ -156,10 +156,10 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) { CHECK_ERROR_VOID(); - check_sljit_fake_enter(compiler, args, temporaries, generals, local_size); + check_sljit_set_context(compiler, args, temporaries, generals, local_size); compiler->temporaries = temporaries; compiler->generals = generals; diff --git a/sljit/sljitNativeX86_64.c b/sljit/sljitNativeX86_64.c index 7a1e28e..05b3952 100644 --- a/sljit/sljitNativeX86_64.c +++ b/sljit/sljitNativeX86_64.c @@ -273,12 +273,12 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) { int pushed_size; CHECK_ERROR_VOID(); - check_sljit_fake_enter(compiler, args, temporaries, generals, local_size); + check_sljit_set_context(compiler, args, temporaries, generals, local_size); compiler->temporaries = temporaries; compiler->generals = generals; @@ -508,7 +508,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size, inst_size += 4; } else if (flags & EX86_SHIFT_INS) { - imma &= 0x3f; + imma &= compiler->mode32 ? 0x1f : 0x3f; if (imma != 1) { inst_size ++; flags |= EX86_BYTE_ARG; diff --git a/sljit/sljitNativeX86_common.c b/sljit/sljitNativeX86_common.c index 7b1efe0..66bf7c3 100644 --- a/sljit/sljitNativeX86_common.c +++ b/sljit/sljitNativeX86_common.c @@ -1836,21 +1836,19 @@ static int emit_shift(struct sljit_compiler *compiler, EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0); } else { - /* This case is really difficult, since ecx can be used for - addressing as well, and we must ensure to work even in that case. */ + /* This case is really difficult, since ecx itself may used for + addressing, and we must ensure to work even in that case. */ + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0); #else /* [esp - 4] is reserved for eflags. */ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), -(int)(2 * sizeof(sljit_w)), SLJIT_PREF_SHIFT_REG, 0); #endif - - EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0); FAIL_IF(!code); *code |= mode; - #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0); #else @@ -1863,6 +1861,41 @@ static int emit_shift(struct sljit_compiler *compiler, return SLJIT_SUCCESS; } +static int emit_shift_with_flags(struct sljit_compiler *compiler, + sljit_ub mode, int set_flags, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + /* The CPU does not set flags if the shift count is 0. */ + if (src2 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if ((src2w & 0x3f) != 0 || (compiler->mode32 && (src2w & 0x1f) != 0)) + return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); +#else + if ((src2w & 0x1f) != 0) + return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); +#endif + if (!set_flags) + return emit_mov(compiler, dst, dstw, src1, src1w); + /* OR dst, src, 0 */ + return emit_cum_binary(compiler, 0x0b, 0x09, 0x1 << 3, 0x0d, + dst, dstw, src1, src1w, SLJIT_IMM, 0); + } + + if (!set_flags) + return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); + + if (!(dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)) + FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0)); + + FAIL_IF(emit_shift(compiler,mode, dst, dstw, src1, src1w, src2, src2w)); + + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) + return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0); + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int src1, sljit_w src1w, @@ -1942,13 +1975,13 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int return emit_cum_binary(compiler, 0x33, 0x31, 0x6 << 3, 0x35, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: - return emit_shift(compiler, 0x4 << 3, + return emit_shift_with_flags(compiler, 0x4 << 3, GET_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); case SLJIT_LSHR: - return emit_shift(compiler, 0x5 << 3, + return emit_shift_with_flags(compiler, 0x5 << 3, GET_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); case SLJIT_ASHR: - return emit_shift(compiler, 0x7 << 3, + return emit_shift_with_flags(compiler, 0x7 << 3, GET_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); } |