summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--pcre.h.in20
-rw-r--r--pcre16_utf16_utils.c2
-rw-r--r--pcre_get.c12
-rw-r--r--pcre_internal.h4
-rw-r--r--pcre_jit_compile.c3
-rw-r--r--pcre_jit_test.c8
-rw-r--r--pcretest.c4
-rw-r--r--sljit/sljitLir.c6
-rw-r--r--sljit/sljitLir.h72
-rw-r--r--sljit/sljitNativeARM_Thumb2.c27
-rw-r--r--sljit/sljitNativeARM_v5.c8
-rw-r--r--sljit/sljitNativeMIPS_common.c4
-rw-r--r--sljit/sljitNativePPC_32.c29
-rw-r--r--sljit/sljitNativePPC_64.c32
-rw-r--r--sljit/sljitNativePPC_common.c124
-rw-r--r--sljit/sljitNativeX86_32.c4
-rw-r--r--sljit/sljitNativeX86_64.c6
-rw-r--r--sljit/sljitNativeX86_common.c49
19 files changed, 279 insertions, 138 deletions
diff --git a/ChangeLog b/ChangeLog
index 0701dcb..c58ab53 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
------------------------
diff --git a/pcre.h.in b/pcre.h.in
index a63092c..0a61c27 100644
--- a/pcre.h.in
+++ b/pcre.h.in
@@ -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
diff --git a/pcre_get.c b/pcre_get.c
index 6ea17b7..6c61b02 100644
--- a/pcre_get.c
+++ b/pcre_get.c
@@ -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 */
diff --git a/pcretest.c b/pcretest.c
index b62ecbb..133e833 100644
--- a/pcretest.c
+++ b/pcretest.c
@@ -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);
}