Upgrade the bundled PCRE to 8.32
Changelog: http://pcre.org/changelog.txt Amongst other things, the Unicode tables were upgraded to 6.2.0 and case folding support was added, which also fixes a QString autotest (marked as XFAIL). Qt still requires 8.30, not 8.32. Change-Id: I4056c1dc1d949d33443bb8ca280de4c8c363ac74 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Lars Knoll <lars.knoll@digia.com>bb10
parent
3499940289
commit
bb5552a229
|
|
@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
/* The current PCRE version information. */
|
||||
|
||||
#define PCRE_MAJOR 8
|
||||
#define PCRE_MINOR 30
|
||||
#define PCRE_MINOR 32
|
||||
#define PCRE_PRERELEASE
|
||||
#define PCRE_DATE 2012-02-04
|
||||
#define PCRE_DATE 2012-11-30
|
||||
|
||||
/* When an application links to a PCRE DLL in Windows, the symbols that are
|
||||
imported have to be identified as such. When building PCRE, the appropriate
|
||||
|
|
@ -95,54 +95,70 @@ it is needed here for malloc. */
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Options. Some are compile-time only, some are run-time only, and some are
|
||||
both, so we keep them all distinct. However, almost all the bits in the options
|
||||
word are now used. In the long run, we may have to re-use some of the
|
||||
compile-time only bits for runtime options, or vice versa. In the comments
|
||||
below, "compile", "exec", and "DFA exec" mean that the option is permitted to
|
||||
be set for those functions; "used in" means that an option may be set only for
|
||||
compile, but is subsequently referenced in exec and/or DFA exec. Any of the
|
||||
/* Public options. Some are compile-time only, some are run-time only, and some
|
||||
are both, so we keep them all distinct. However, almost all the bits in the
|
||||
options word are now used. In the long run, we may have to re-use some of the
|
||||
compile-time only bits for runtime options, or vice versa. Any of the
|
||||
compile-time options may be inspected during studying (and therefore JIT
|
||||
compiling). */
|
||||
compiling).
|
||||
|
||||
#define PCRE_CASELESS 0x00000001 /* Compile */
|
||||
#define PCRE_MULTILINE 0x00000002 /* Compile */
|
||||
#define PCRE_DOTALL 0x00000004 /* Compile */
|
||||
#define PCRE_EXTENDED 0x00000008 /* Compile */
|
||||
#define PCRE_ANCHORED 0x00000010 /* Compile, exec, DFA exec */
|
||||
#define PCRE_DOLLAR_ENDONLY 0x00000020 /* Compile, used in exec, DFA exec */
|
||||
#define PCRE_EXTRA 0x00000040 /* Compile */
|
||||
#define PCRE_NOTBOL 0x00000080 /* Exec, DFA exec */
|
||||
#define PCRE_NOTEOL 0x00000100 /* Exec, DFA exec */
|
||||
#define PCRE_UNGREEDY 0x00000200 /* Compile */
|
||||
#define PCRE_NOTEMPTY 0x00000400 /* Exec, DFA exec */
|
||||
/* The next two are also used in exec and DFA exec */
|
||||
#define PCRE_UTF8 0x00000800 /* Compile (same as PCRE_UTF16) */
|
||||
#define PCRE_UTF16 0x00000800 /* Compile (same as PCRE_UTF8) */
|
||||
#define PCRE_NO_AUTO_CAPTURE 0x00001000 /* Compile */
|
||||
/* The next two are also used in exec and DFA exec */
|
||||
#define PCRE_NO_UTF8_CHECK 0x00002000 /* Compile (same as PCRE_NO_UTF16_CHECK) */
|
||||
#define PCRE_NO_UTF16_CHECK 0x00002000 /* Compile (same as PCRE_NO_UTF8_CHECK) */
|
||||
#define PCRE_AUTO_CALLOUT 0x00004000 /* Compile */
|
||||
#define PCRE_PARTIAL_SOFT 0x00008000 /* Exec, DFA exec */
|
||||
#define PCRE_PARTIAL 0x00008000 /* Backwards compatible synonym */
|
||||
#define PCRE_DFA_SHORTEST 0x00010000 /* DFA exec */
|
||||
#define PCRE_DFA_RESTART 0x00020000 /* DFA exec */
|
||||
#define PCRE_FIRSTLINE 0x00040000 /* Compile, used in exec, DFA exec */
|
||||
#define PCRE_DUPNAMES 0x00080000 /* Compile */
|
||||
#define PCRE_NEWLINE_CR 0x00100000 /* Compile, exec, DFA exec */
|
||||
#define PCRE_NEWLINE_LF 0x00200000 /* Compile, exec, DFA exec */
|
||||
#define PCRE_NEWLINE_CRLF 0x00300000 /* Compile, exec, DFA exec */
|
||||
#define PCRE_NEWLINE_ANY 0x00400000 /* Compile, exec, DFA exec */
|
||||
#define PCRE_NEWLINE_ANYCRLF 0x00500000 /* Compile, exec, DFA exec */
|
||||
#define PCRE_BSR_ANYCRLF 0x00800000 /* Compile, exec, DFA exec */
|
||||
#define PCRE_BSR_UNICODE 0x01000000 /* Compile, exec, DFA exec */
|
||||
#define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* Compile, used in exec */
|
||||
#define PCRE_NO_START_OPTIMIZE 0x04000000 /* Compile, exec, DFA exec */
|
||||
#define PCRE_NO_START_OPTIMISE 0x04000000 /* Synonym */
|
||||
#define PCRE_PARTIAL_HARD 0x08000000 /* Exec, DFA exec */
|
||||
#define PCRE_NOTEMPTY_ATSTART 0x10000000 /* Exec, DFA exec */
|
||||
#define PCRE_UCP 0x20000000 /* Compile, used in exec, DFA exec */
|
||||
Some options for pcre_compile() change its behaviour but do not affect the
|
||||
behaviour of the execution functions. Other options are passed through to the
|
||||
execution functions and affect their behaviour, with or without affecting the
|
||||
behaviour of pcre_compile().
|
||||
|
||||
Options that can be passed to pcre_compile() are tagged Cx below, with these
|
||||
variants:
|
||||
|
||||
C1 Affects compile only
|
||||
C2 Does not affect compile; affects exec, dfa_exec
|
||||
C3 Affects compile, exec, dfa_exec
|
||||
C4 Affects compile, exec, dfa_exec, study
|
||||
C5 Affects compile, exec, study
|
||||
|
||||
Options that can be set for pcre_exec() and/or pcre_dfa_exec() are flagged with
|
||||
E and D, respectively. They take precedence over C3, C4, and C5 settings passed
|
||||
from pcre_compile(). Those that are compatible with JIT execution are flagged
|
||||
with J. */
|
||||
|
||||
#define PCRE_CASELESS 0x00000001 /* C1 */
|
||||
#define PCRE_MULTILINE 0x00000002 /* C1 */
|
||||
#define PCRE_DOTALL 0x00000004 /* C1 */
|
||||
#define PCRE_EXTENDED 0x00000008 /* C1 */
|
||||
#define PCRE_ANCHORED 0x00000010 /* C4 E D */
|
||||
#define PCRE_DOLLAR_ENDONLY 0x00000020 /* C2 */
|
||||
#define PCRE_EXTRA 0x00000040 /* C1 */
|
||||
#define PCRE_NOTBOL 0x00000080 /* E D J */
|
||||
#define PCRE_NOTEOL 0x00000100 /* E D J */
|
||||
#define PCRE_UNGREEDY 0x00000200 /* C1 */
|
||||
#define PCRE_NOTEMPTY 0x00000400 /* E D J */
|
||||
#define PCRE_UTF8 0x00000800 /* C4 ) */
|
||||
#define PCRE_UTF16 0x00000800 /* C4 ) Synonyms */
|
||||
#define PCRE_UTF32 0x00000800 /* C4 ) */
|
||||
#define PCRE_NO_AUTO_CAPTURE 0x00001000 /* C1 */
|
||||
#define PCRE_NO_UTF8_CHECK 0x00002000 /* C1 E D J ) */
|
||||
#define PCRE_NO_UTF16_CHECK 0x00002000 /* C1 E D J ) Synonyms */
|
||||
#define PCRE_NO_UTF32_CHECK 0x00002000 /* C1 E D J ) */
|
||||
#define PCRE_AUTO_CALLOUT 0x00004000 /* C1 */
|
||||
#define PCRE_PARTIAL_SOFT 0x00008000 /* E D J ) Synonyms */
|
||||
#define PCRE_PARTIAL 0x00008000 /* E D J ) */
|
||||
#define PCRE_DFA_SHORTEST 0x00010000 /* D */
|
||||
#define PCRE_DFA_RESTART 0x00020000 /* D */
|
||||
#define PCRE_FIRSTLINE 0x00040000 /* C3 */
|
||||
#define PCRE_DUPNAMES 0x00080000 /* C1 */
|
||||
#define PCRE_NEWLINE_CR 0x00100000 /* C3 E D */
|
||||
#define PCRE_NEWLINE_LF 0x00200000 /* C3 E D */
|
||||
#define PCRE_NEWLINE_CRLF 0x00300000 /* C3 E D */
|
||||
#define PCRE_NEWLINE_ANY 0x00400000 /* C3 E D */
|
||||
#define PCRE_NEWLINE_ANYCRLF 0x00500000 /* C3 E D */
|
||||
#define PCRE_BSR_ANYCRLF 0x00800000 /* C3 E D */
|
||||
#define PCRE_BSR_UNICODE 0x01000000 /* C3 E D */
|
||||
#define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* C5 */
|
||||
#define PCRE_NO_START_OPTIMIZE 0x04000000 /* C2 E D ) Synonyms */
|
||||
#define PCRE_NO_START_OPTIMISE 0x04000000 /* C2 E D ) */
|
||||
#define PCRE_PARTIAL_HARD 0x08000000 /* E D J */
|
||||
#define PCRE_NOTEMPTY_ATSTART 0x10000000 /* E D J */
|
||||
#define PCRE_UCP 0x20000000 /* C3 */
|
||||
|
||||
/* Exec-time and get/set-time error codes */
|
||||
|
||||
|
|
@ -156,8 +172,9 @@ compiling). */
|
|||
#define PCRE_ERROR_NOSUBSTRING (-7)
|
||||
#define PCRE_ERROR_MATCHLIMIT (-8)
|
||||
#define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */
|
||||
#define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16 */
|
||||
#define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16 */
|
||||
#define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16/32 */
|
||||
#define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16/32 */
|
||||
#define PCRE_ERROR_BADUTF32 (-10) /* Same for 8/16/32 */
|
||||
#define PCRE_ERROR_BADUTF8_OFFSET (-11) /* Same for 8/16 */
|
||||
#define PCRE_ERROR_BADUTF16_OFFSET (-11) /* Same for 8/16 */
|
||||
#define PCRE_ERROR_PARTIAL (-12)
|
||||
|
|
@ -179,6 +196,9 @@ compiling). */
|
|||
#define PCRE_ERROR_JIT_STACKLIMIT (-27)
|
||||
#define PCRE_ERROR_BADMODE (-28)
|
||||
#define PCRE_ERROR_BADENDIANNESS (-29)
|
||||
#define PCRE_ERROR_DFA_BADRESTART (-30)
|
||||
#define PCRE_ERROR_JIT_BADOPTION (-31)
|
||||
#define PCRE_ERROR_BADLENGTH (-32)
|
||||
|
||||
/* Specific error codes for UTF-8 validity checks */
|
||||
|
||||
|
|
@ -204,6 +224,7 @@ compiling). */
|
|||
#define PCRE_UTF8_ERR19 19
|
||||
#define PCRE_UTF8_ERR20 20
|
||||
#define PCRE_UTF8_ERR21 21
|
||||
#define PCRE_UTF8_ERR22 22
|
||||
|
||||
/* Specific error codes for UTF-16 validity checks */
|
||||
|
||||
|
|
@ -213,6 +234,13 @@ compiling). */
|
|||
#define PCRE_UTF16_ERR3 3
|
||||
#define PCRE_UTF16_ERR4 4
|
||||
|
||||
/* Specific error codes for UTF-32 validity checks */
|
||||
|
||||
#define PCRE_UTF32_ERR0 0
|
||||
#define PCRE_UTF32_ERR1 1
|
||||
#define PCRE_UTF32_ERR2 2
|
||||
#define PCRE_UTF32_ERR3 3
|
||||
|
||||
/* Request types for pcre_fullinfo() */
|
||||
|
||||
#define PCRE_INFO_OPTIONS 0
|
||||
|
|
@ -234,6 +262,11 @@ compiling). */
|
|||
#define PCRE_INFO_MINLENGTH 15
|
||||
#define PCRE_INFO_JIT 16
|
||||
#define PCRE_INFO_JITSIZE 17
|
||||
#define PCRE_INFO_MAXLOOKBEHIND 18
|
||||
#define PCRE_INFO_FIRSTCHARACTER 19
|
||||
#define PCRE_INFO_FIRSTCHARACTERFLAGS 20
|
||||
#define PCRE_INFO_REQUIREDCHAR 21
|
||||
#define PCRE_INFO_REQUIREDCHARFLAGS 22
|
||||
|
||||
/* Request types for pcre_config(). Do not re-arrange, in order to remain
|
||||
compatible. */
|
||||
|
|
@ -250,13 +283,17 @@ compatible. */
|
|||
#define PCRE_CONFIG_JIT 9
|
||||
#define PCRE_CONFIG_UTF16 10
|
||||
#define PCRE_CONFIG_JITTARGET 11
|
||||
#define PCRE_CONFIG_UTF32 12
|
||||
|
||||
/* Request types for pcre_study(). Do not re-arrange, in order to remain
|
||||
compatible. */
|
||||
|
||||
#define PCRE_STUDY_JIT_COMPILE 0x0001
|
||||
#define PCRE_STUDY_JIT_COMPILE 0x0001
|
||||
#define PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE 0x0002
|
||||
#define PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE 0x0004
|
||||
#define PCRE_STUDY_EXTRA_NEEDED 0x0008
|
||||
|
||||
/* Bit flags for the pcre[16]_extra structure. Do not re-arrange or redefine
|
||||
/* Bit flags for the pcre[16|32]_extra structure. Do not re-arrange or redefine
|
||||
these bits, just add new ones on the end, in order to remain compatible. */
|
||||
|
||||
#define PCRE_EXTRA_STUDY_DATA 0x0001
|
||||
|
|
@ -275,12 +312,18 @@ typedef struct real_pcre pcre;
|
|||
struct real_pcre16; /* declaration; the definition is private */
|
||||
typedef struct real_pcre16 pcre16;
|
||||
|
||||
struct real_pcre32; /* declaration; the definition is private */
|
||||
typedef struct real_pcre32 pcre32;
|
||||
|
||||
struct real_pcre_jit_stack; /* declaration; the definition is private */
|
||||
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;
|
||||
|
||||
struct real_pcre32_jit_stack; /* declaration; the definition is private */
|
||||
typedef struct real_pcre32_jit_stack pcre32_jit_stack;
|
||||
|
||||
/* 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. */
|
||||
|
|
@ -292,6 +335,17 @@ pcre16 functions are not implemented. There is a check for this in pcre_internal
|
|||
#define PCRE_SPTR16 const PCRE_UCHAR16 *
|
||||
#endif
|
||||
|
||||
/* If PCRE is compiled with 32 bit character support, PCRE_UCHAR32 must contain
|
||||
a 32 bit wide signed data type. Otherwise it can be a dummy data type since
|
||||
pcre32 functions are not implemented. There is a check for this in pcre_internal.h. */
|
||||
#ifndef PCRE_UCHAR32
|
||||
#define PCRE_UCHAR32 unsigned int
|
||||
#endif
|
||||
|
||||
#ifndef PCRE_SPTR32
|
||||
#define PCRE_SPTR32 const PCRE_UCHAR32 *
|
||||
#endif
|
||||
|
||||
/* When PCRE is compiled as a C++ library, the subject pointer type can be
|
||||
replaced with a custom type. For conventional use, the public interface is a
|
||||
const char *. */
|
||||
|
|
@ -328,6 +382,19 @@ typedef struct pcre16_extra {
|
|||
void *executable_jit; /* Contains a pointer to a compiled jit code */
|
||||
} pcre16_extra;
|
||||
|
||||
/* Same structure as above, but with 32 bit char pointers. */
|
||||
|
||||
typedef struct pcre32_extra {
|
||||
unsigned long int flags; /* Bits for which fields are set */
|
||||
void *study_data; /* Opaque data from pcre_study() */
|
||||
unsigned long int match_limit; /* Maximum number of calls to match() */
|
||||
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_UCHAR32 **mark; /* For passing back a mark pointer */
|
||||
void *executable_jit; /* Contains a pointer to a compiled jit code */
|
||||
} pcre32_extra;
|
||||
|
||||
/* The structure for passing out data via the pcre_callout_function. We use a
|
||||
structure so that new fields can be added on the end in future versions,
|
||||
without changing the API of the function, thereby allowing old clients to work
|
||||
|
|
@ -375,6 +442,28 @@ typedef struct pcre16_callout_block {
|
|||
/* ------------------------------------------------------------------ */
|
||||
} pcre16_callout_block;
|
||||
|
||||
/* Same structure as above, but with 32 bit char pointers. */
|
||||
|
||||
typedef struct pcre32_callout_block {
|
||||
int version; /* Identifies version of block */
|
||||
/* ------------------------ Version 0 ------------------------------- */
|
||||
int callout_number; /* Number compiled into pattern */
|
||||
int *offset_vector; /* The offset vector */
|
||||
PCRE_SPTR32 subject; /* The subject being matched */
|
||||
int subject_length; /* The length of the subject */
|
||||
int start_match; /* Offset to start of this match attempt */
|
||||
int current_position; /* Where we currently are in the subject */
|
||||
int capture_top; /* Max current capture */
|
||||
int capture_last; /* Most recently closed capture */
|
||||
void *callout_data; /* Data passed in with the call */
|
||||
/* ------------------- Added for Version 1 -------------------------- */
|
||||
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_UCHAR32 *mark; /* Pointer to current mark or NULL */
|
||||
/* ------------------------------------------------------------------ */
|
||||
} pcre32_callout_block;
|
||||
|
||||
/* Indirection for store get and free functions. These can be set to
|
||||
alternative malloc/free functions if required. Special ones are used in the
|
||||
non-recursive case for "frames". There is also an optional callout function
|
||||
|
|
@ -393,6 +482,12 @@ PCRE_EXP_DECL void (*pcre16_free)(void *);
|
|||
PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t);
|
||||
PCRE_EXP_DECL void (*pcre16_stack_free)(void *);
|
||||
PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *);
|
||||
|
||||
PCRE_EXP_DECL void *(*pcre32_malloc)(size_t);
|
||||
PCRE_EXP_DECL void (*pcre32_free)(void *);
|
||||
PCRE_EXP_DECL void *(*pcre32_stack_malloc)(size_t);
|
||||
PCRE_EXP_DECL void (*pcre32_stack_free)(void *);
|
||||
PCRE_EXP_DECL int (*pcre32_callout)(pcre32_callout_block *);
|
||||
#else /* VPCOMPAT */
|
||||
PCRE_EXP_DECL void *pcre_malloc(size_t);
|
||||
PCRE_EXP_DECL void pcre_free(void *);
|
||||
|
|
@ -405,12 +500,19 @@ PCRE_EXP_DECL void pcre16_free(void *);
|
|||
PCRE_EXP_DECL void *pcre16_stack_malloc(size_t);
|
||||
PCRE_EXP_DECL void pcre16_stack_free(void *);
|
||||
PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *);
|
||||
|
||||
PCRE_EXP_DECL void *pcre32_malloc(size_t);
|
||||
PCRE_EXP_DECL void pcre32_free(void *);
|
||||
PCRE_EXP_DECL void *pcre32_stack_malloc(size_t);
|
||||
PCRE_EXP_DECL void pcre32_stack_free(void *);
|
||||
PCRE_EXP_DECL int pcre32_callout(pcre32_callout_block *);
|
||||
#endif /* VPCOMPAT */
|
||||
|
||||
/* User defined callback which provides a stack just before the match starts. */
|
||||
|
||||
typedef pcre_jit_stack *(*pcre_jit_callback)(void *);
|
||||
typedef pcre16_jit_stack *(*pcre16_jit_callback)(void *);
|
||||
typedef pcre32_jit_stack *(*pcre32_jit_callback)(void *);
|
||||
|
||||
/* Exported PCRE functions */
|
||||
|
||||
|
|
@ -418,83 +520,131 @@ PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *,
|
|||
const unsigned char *);
|
||||
PCRE_EXP_DECL pcre16 *pcre16_compile(PCRE_SPTR16, int, const char **, int *,
|
||||
const unsigned char *);
|
||||
PCRE_EXP_DECL pcre32 *pcre32_compile(PCRE_SPTR32, int, const char **, int *,
|
||||
const unsigned char *);
|
||||
PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **,
|
||||
int *, const unsigned char *);
|
||||
PCRE_EXP_DECL pcre16 *pcre16_compile2(PCRE_SPTR16, int, int *, const char **,
|
||||
int *, const unsigned char *);
|
||||
PCRE_EXP_DECL pcre32 *pcre32_compile2(PCRE_SPTR32, int, int *, const char **,
|
||||
int *, const unsigned char *);
|
||||
PCRE_EXP_DECL int pcre_config(int, void *);
|
||||
PCRE_EXP_DECL int pcre16_config(int, void *);
|
||||
PCRE_EXP_DECL int pcre32_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_UCHAR16 *, int);
|
||||
PCRE_EXP_DECL int pcre32_copy_named_substring(const pcre32 *, PCRE_SPTR32,
|
||||
int *, int, PCRE_SPTR32, PCRE_UCHAR32 *, 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_UCHAR16 *, int);
|
||||
PCRE_EXP_DECL int pcre32_copy_substring(PCRE_SPTR32, int *, int, int,
|
||||
PCRE_UCHAR32 *, 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 *,
|
||||
PCRE_SPTR16, int, int, int, int *, int , int *, int);
|
||||
PCRE_EXP_DECL int pcre32_dfa_exec(const pcre32 *, const pcre32_extra *,
|
||||
PCRE_SPTR32, int, int, int, int *, int , int *, int);
|
||||
PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR,
|
||||
int, int, int, int *, int);
|
||||
PCRE_EXP_DECL int pcre16_exec(const pcre16 *, const pcre16_extra *,
|
||||
PCRE_SPTR16, int, int, int, int *, int);
|
||||
PCRE_EXP_DECL int pcre32_exec(const pcre32 *, const pcre32_extra *,
|
||||
PCRE_SPTR32, int, int, int, int *, int);
|
||||
PCRE_EXP_DECL int pcre_jit_exec(const pcre *, const pcre_extra *,
|
||||
PCRE_SPTR, int, int, int, int *, int,
|
||||
pcre_jit_stack *);
|
||||
PCRE_EXP_DECL int pcre16_jit_exec(const pcre16 *, const pcre16_extra *,
|
||||
PCRE_SPTR16, int, int, int, int *, int,
|
||||
pcre16_jit_stack *);
|
||||
PCRE_EXP_DECL int pcre32_jit_exec(const pcre32 *, const pcre32_extra *,
|
||||
PCRE_SPTR32, int, int, int, int *, int,
|
||||
pcre32_jit_stack *);
|
||||
PCRE_EXP_DECL void pcre_free_substring(const char *);
|
||||
PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16);
|
||||
PCRE_EXP_DECL void pcre32_free_substring(PCRE_SPTR32);
|
||||
PCRE_EXP_DECL void pcre_free_substring_list(const char **);
|
||||
PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *);
|
||||
PCRE_EXP_DECL void pcre32_free_substring_list(PCRE_SPTR32 *);
|
||||
PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int,
|
||||
void *);
|
||||
PCRE_EXP_DECL int pcre16_fullinfo(const pcre16 *, const pcre16_extra *, int,
|
||||
void *);
|
||||
PCRE_EXP_DECL int pcre32_fullinfo(const pcre32 *, const pcre32_extra *, int,
|
||||
void *);
|
||||
PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *,
|
||||
int *, int, const char *, const char **);
|
||||
PCRE_EXP_DECL int pcre16_get_named_substring(const pcre16 *, PCRE_SPTR16,
|
||||
int *, int, PCRE_SPTR16, PCRE_SPTR16 *);
|
||||
PCRE_EXP_DECL int pcre32_get_named_substring(const pcre32 *, PCRE_SPTR32,
|
||||
int *, int, PCRE_SPTR32, PCRE_SPTR32 *);
|
||||
PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *);
|
||||
PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16);
|
||||
PCRE_EXP_DECL int pcre32_get_stringnumber(const pcre32 *, PCRE_SPTR32);
|
||||
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_UCHAR16 **, PCRE_UCHAR16 **);
|
||||
PCRE_EXP_DECL int pcre32_get_stringtable_entries(const pcre32 *, PCRE_SPTR32,
|
||||
PCRE_UCHAR32 **, PCRE_UCHAR32 **);
|
||||
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,
|
||||
PCRE_SPTR16 *);
|
||||
PCRE_EXP_DECL int pcre32_get_substring(PCRE_SPTR32, int *, int, int,
|
||||
PCRE_SPTR32 *);
|
||||
PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int,
|
||||
const char ***);
|
||||
PCRE_EXP_DECL int pcre16_get_substring_list(PCRE_SPTR16, int *, int,
|
||||
PCRE_SPTR16 **);
|
||||
PCRE_EXP_DECL int pcre32_get_substring_list(PCRE_SPTR32, int *, int,
|
||||
PCRE_SPTR32 **);
|
||||
PCRE_EXP_DECL const unsigned char *pcre_maketables(void);
|
||||
PCRE_EXP_DECL const unsigned char *pcre16_maketables(void);
|
||||
PCRE_EXP_DECL const unsigned char *pcre32_maketables(void);
|
||||
PCRE_EXP_DECL int pcre_refcount(pcre *, int);
|
||||
PCRE_EXP_DECL int pcre16_refcount(pcre16 *, int);
|
||||
PCRE_EXP_DECL int pcre32_refcount(pcre32 *, int);
|
||||
PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **);
|
||||
PCRE_EXP_DECL pcre16_extra *pcre16_study(const pcre16 *, int, const char **);
|
||||
PCRE_EXP_DECL pcre32_extra *pcre32_study(const pcre32 *, int, const char **);
|
||||
PCRE_EXP_DECL void pcre_free_study(pcre_extra *);
|
||||
PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *);
|
||||
PCRE_EXP_DECL void pcre32_free_study(pcre32_extra *);
|
||||
PCRE_EXP_DECL const char *pcre_version(void);
|
||||
PCRE_EXP_DECL const char *pcre16_version(void);
|
||||
PCRE_EXP_DECL const char *pcre32_version(void);
|
||||
|
||||
/* Utility functions for byte order swaps. */
|
||||
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 pcre32_pattern_to_host_byte_order(pcre32 *, pcre32_extra *,
|
||||
const unsigned char *);
|
||||
PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *,
|
||||
PCRE_SPTR16, int, int *, int);
|
||||
PCRE_EXP_DECL int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *,
|
||||
PCRE_SPTR32, int, int *, int);
|
||||
|
||||
/* JIT compiler related functions. */
|
||||
|
||||
PCRE_EXP_DECL pcre_jit_stack *pcre_jit_stack_alloc(int, int);
|
||||
PCRE_EXP_DECL pcre16_jit_stack *pcre16_jit_stack_alloc(int, int);
|
||||
PCRE_EXP_DECL pcre32_jit_stack *pcre32_jit_stack_alloc(int, int);
|
||||
PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *);
|
||||
PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *);
|
||||
PCRE_EXP_DECL void pcre32_jit_stack_free(pcre32_jit_stack *);
|
||||
PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *,
|
||||
pcre_jit_callback, void *);
|
||||
PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *,
|
||||
pcre16_jit_callback, void *);
|
||||
PCRE_EXP_DECL void pcre32_assign_jit_stack(pcre32_extra *,
|
||||
pcre32_jit_callback, void *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
|||
|
|
@ -64,16 +64,11 @@ Arguments:
|
|||
Returns: number of characters placed in the buffer
|
||||
*/
|
||||
|
||||
int
|
||||
unsigned int
|
||||
PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer)
|
||||
{
|
||||
#ifdef SUPPORT_UTF
|
||||
|
||||
/* Checking invalid cvalue character, encoded as invalid UTF-16 character.
|
||||
Should never happen in practice. */
|
||||
if ((cvalue & 0xf800) == 0xd800 || cvalue >= 0x110000)
|
||||
cvalue = 0xfffe;
|
||||
|
||||
if (cvalue <= 0xffff)
|
||||
{
|
||||
*buffer = (pcre_uchar)cvalue;
|
||||
|
|
|
|||
|
|
@ -118,10 +118,11 @@ while (iptr < end)
|
|||
if (host_byte_order != NULL)
|
||||
*host_byte_order = host_bo;
|
||||
|
||||
#else /* SUPPORT_UTF */
|
||||
#else /* Not SUPPORT_UTF */
|
||||
(void)(output); /* Keep picky compilers happy */
|
||||
(void)(input);
|
||||
(void)(keep_boms);
|
||||
(void)(host_byte_order);
|
||||
#endif /* SUPPORT_UTF */
|
||||
return length;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ PCRE_UTF16_ERR0 No error
|
|||
PCRE_UTF16_ERR1 Missing low surrogate at the end of the string
|
||||
PCRE_UTF16_ERR2 Invalid low surrogate
|
||||
PCRE_UTF16_ERR3 Isolated low surrogate
|
||||
PCRE_UTF16_ERR4 Not allowed character
|
||||
PCRE_UTF16_ERR4 Non-character
|
||||
|
||||
Arguments:
|
||||
string points to the string
|
||||
|
|
@ -85,7 +85,7 @@ PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset)
|
|||
{
|
||||
#ifdef SUPPORT_UTF
|
||||
register PCRE_PUCHAR p;
|
||||
register pcre_uchar c;
|
||||
register pcre_uint32 c;
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
|
|
@ -101,9 +101,8 @@ for (p = string; length-- > 0; p++)
|
|||
{
|
||||
/* Normal UTF-16 code point. Neither high nor low surrogate. */
|
||||
|
||||
/* This is probably a BOM from a different byte-order.
|
||||
Regardless, the string is rejected. */
|
||||
if (c == 0xfffe)
|
||||
/* Check for non-characters */
|
||||
if ((c & 0xfffeu) == 0xfffeu || (c >= 0xfdd0u && c <= 0xfdefu))
|
||||
{
|
||||
*erroroffset = p - string;
|
||||
return PCRE_UTF16_ERR4;
|
||||
|
|
@ -126,6 +125,16 @@ for (p = string; length-- > 0; p++)
|
|||
*erroroffset = p - string;
|
||||
return PCRE_UTF16_ERR2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Valid surrogate, but check for non-characters */
|
||||
c = (((c & 0x3ffu) << 10) | (*p & 0x3ffu)) + 0x10000u;
|
||||
if ((c & 0xfffeu) == 0xfffeu)
|
||||
{
|
||||
*erroroffset = p - string;
|
||||
return PCRE_UTF16_ERR4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -138,6 +147,7 @@ for (p = string; length-- > 0; p++)
|
|||
#else /* SUPPORT_UTF */
|
||||
(void)(string); /* Keep picky compilers happy */
|
||||
(void)(length);
|
||||
(void)(erroroffset);
|
||||
#endif /* SUPPORT_UTF */
|
||||
|
||||
return PCRE_UTF16_ERR0; /* This indicates success */
|
||||
|
|
|
|||
|
|
@ -95,12 +95,15 @@ Arguments:
|
|||
Returns: 0 if the swap is successful, negative on error
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *argument_re,
|
||||
pcre_extra *extra_data, const unsigned char *tables)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *argument_re,
|
||||
pcre16_extra *extra_data, const unsigned char *tables)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *argument_re,
|
||||
pcre32_extra *extra_data, const unsigned char *tables)
|
||||
#endif
|
||||
{
|
||||
REAL_PCRE *re = (REAL_PCRE *)argument_re;
|
||||
|
|
@ -108,10 +111,10 @@ pcre_study_data *study;
|
|||
#ifndef COMPILE_PCRE8
|
||||
pcre_uchar *ptr;
|
||||
int length;
|
||||
#ifdef SUPPORT_UTF
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE16
|
||||
BOOL utf;
|
||||
BOOL utf16_char;
|
||||
#endif /* SUPPORT_UTF */
|
||||
#endif /* SUPPORT_UTF && COMPILE_PCRE16 */
|
||||
#endif /* !COMPILE_PCRE8 */
|
||||
|
||||
if (re == NULL) return PCRE_ERROR_NULL;
|
||||
|
|
@ -131,13 +134,22 @@ re->options = swap_uint32(re->options);
|
|||
re->flags = swap_uint16(re->flags);
|
||||
re->top_bracket = swap_uint16(re->top_bracket);
|
||||
re->top_backref = swap_uint16(re->top_backref);
|
||||
#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
|
||||
re->first_char = swap_uint16(re->first_char);
|
||||
re->req_char = swap_uint16(re->req_char);
|
||||
#elif defined COMPILE_PCRE32
|
||||
re->first_char = swap_uint32(re->first_char);
|
||||
re->req_char = swap_uint32(re->req_char);
|
||||
#endif
|
||||
re->name_table_offset = swap_uint16(re->name_table_offset);
|
||||
re->name_entry_size = swap_uint16(re->name_entry_size);
|
||||
re->name_count = swap_uint16(re->name_count);
|
||||
re->ref_count = swap_uint16(re->ref_count);
|
||||
re->tables = tables;
|
||||
#ifdef COMPILE_PCRE32
|
||||
re->dummy1 = swap_uint16(re->dummy1);
|
||||
re->dummy2 = swap_uint16(re->dummy2);
|
||||
#endif
|
||||
|
||||
if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0)
|
||||
{
|
||||
|
|
@ -150,20 +162,24 @@ if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0)
|
|||
#ifndef COMPILE_PCRE8
|
||||
ptr = (pcre_uchar *)re + re->name_table_offset;
|
||||
length = re->name_count * re->name_entry_size;
|
||||
#ifdef SUPPORT_UTF
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE16
|
||||
utf = (re->options & PCRE_UTF16) != 0;
|
||||
utf16_char = FALSE;
|
||||
#endif
|
||||
#endif /* SUPPORT_UTF && COMPILE_PCRE16 */
|
||||
|
||||
while(TRUE)
|
||||
{
|
||||
/* Swap previous characters. */
|
||||
while (length-- > 0)
|
||||
{
|
||||
#if defined COMPILE_PCRE16
|
||||
*ptr = swap_uint16(*ptr);
|
||||
#elif defined COMPILE_PCRE32
|
||||
*ptr = swap_uint32(*ptr);
|
||||
#endif
|
||||
ptr++;
|
||||
}
|
||||
#ifdef SUPPORT_UTF
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE16
|
||||
if (utf16_char)
|
||||
{
|
||||
if (HAS_EXTRALEN(ptr[-1]))
|
||||
|
|
@ -178,13 +194,17 @@ while(TRUE)
|
|||
|
||||
/* Get next opcode. */
|
||||
length = 0;
|
||||
#if defined COMPILE_PCRE16
|
||||
*ptr = swap_uint16(*ptr);
|
||||
#elif defined COMPILE_PCRE32
|
||||
*ptr = swap_uint32(*ptr);
|
||||
#endif
|
||||
switch (*ptr)
|
||||
{
|
||||
case OP_END:
|
||||
return 0;
|
||||
|
||||
#ifdef SUPPORT_UTF
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE16
|
||||
case OP_CHAR:
|
||||
case OP_CHARI:
|
||||
case OP_NOT:
|
||||
|
|
@ -259,16 +279,26 @@ while(TRUE)
|
|||
case OP_XCLASS:
|
||||
/* Reverse the size of the XCLASS instance. */
|
||||
ptr++;
|
||||
#if defined COMPILE_PCRE16
|
||||
*ptr = swap_uint16(*ptr);
|
||||
#elif defined COMPILE_PCRE32
|
||||
*ptr = swap_uint32(*ptr);
|
||||
#endif
|
||||
#ifndef COMPILE_PCRE32
|
||||
if (LINK_SIZE > 1)
|
||||
{
|
||||
/* LINK_SIZE can be 1 or 2 in 16 bit mode. */
|
||||
ptr++;
|
||||
*ptr = swap_uint16(*ptr);
|
||||
}
|
||||
#endif
|
||||
ptr++;
|
||||
length = (GET(ptr, -LINK_SIZE)) - (1 + LINK_SIZE + 1);
|
||||
#if defined COMPILE_PCRE16
|
||||
*ptr = swap_uint16(*ptr);
|
||||
#elif defined COMPILE_PCRE32
|
||||
*ptr = swap_uint32(*ptr);
|
||||
#endif
|
||||
if ((*ptr & XCL_MAP) != 0)
|
||||
{
|
||||
/* Skip the character bit map. */
|
||||
|
|
@ -279,7 +309,7 @@ while(TRUE)
|
|||
}
|
||||
ptr++;
|
||||
}
|
||||
/* Control should never reach here in 16 bit mode. */
|
||||
/* Control should never reach here in 16/32 bit mode. */
|
||||
#endif /* !COMPILE_PCRE8 */
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -65,18 +65,21 @@ Arguments:
|
|||
Returns: 0 if data returned, negative on error
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_config(int what, void *where)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_config(int what, void *where)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre32_config(int what, void *where)
|
||||
#endif
|
||||
{
|
||||
switch (what)
|
||||
{
|
||||
case PCRE_CONFIG_UTF8:
|
||||
#if defined COMPILE_PCRE16
|
||||
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
|
||||
*((int *)where) = 0;
|
||||
return PCRE_ERROR_BADOPTION;
|
||||
#else
|
||||
|
|
@ -89,7 +92,20 @@ switch (what)
|
|||
#endif
|
||||
|
||||
case PCRE_CONFIG_UTF16:
|
||||
#if defined COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8 || defined COMPILE_PCRE32
|
||||
*((int *)where) = 0;
|
||||
return PCRE_ERROR_BADOPTION;
|
||||
#else
|
||||
#if defined SUPPORT_UTF
|
||||
*((int *)where) = 1;
|
||||
#else
|
||||
*((int *)where) = 0;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
case PCRE_CONFIG_UTF32:
|
||||
#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
|
||||
*((int *)where) = 0;
|
||||
return PCRE_ERROR_BADOPTION;
|
||||
#else
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -65,14 +65,18 @@ Arguments:
|
|||
Returns: 0 if data returned, negative on error
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data,
|
||||
int what, void *where)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_fullinfo(const pcre16 *argument_re, const pcre16_extra *extra_data,
|
||||
int what, void *where)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre32_fullinfo(const pcre32 *argument_re, const pcre32_extra *extra_data,
|
||||
int what, void *where)
|
||||
#endif
|
||||
{
|
||||
const REAL_PCRE *re = (const REAL_PCRE *)argument_re;
|
||||
|
|
@ -132,10 +136,21 @@ switch (what)
|
|||
|
||||
case PCRE_INFO_FIRSTBYTE:
|
||||
*((int *)where) =
|
||||
((re->flags & PCRE_FIRSTSET) != 0)? re->first_char :
|
||||
((re->flags & PCRE_FIRSTSET) != 0)? (int)re->first_char :
|
||||
((re->flags & PCRE_STARTLINE) != 0)? -1 : -2;
|
||||
break;
|
||||
|
||||
case PCRE_INFO_FIRSTCHARACTER:
|
||||
*((pcre_uint32 *)where) =
|
||||
(re->flags & PCRE_FIRSTSET) != 0 ? re->first_char : 0;
|
||||
break;
|
||||
|
||||
case PCRE_INFO_FIRSTCHARACTERFLAGS:
|
||||
*((int *)where) =
|
||||
((re->flags & PCRE_FIRSTSET) != 0) ? 1 :
|
||||
((re->flags & PCRE_STARTLINE) != 0) ? 2 : 0;
|
||||
break;
|
||||
|
||||
/* Make sure we pass back the pointer to the bit vector in the external
|
||||
block, not the internal copy (with flipped integer fields). */
|
||||
|
||||
|
|
@ -159,9 +174,19 @@ switch (what)
|
|||
|
||||
case PCRE_INFO_LASTLITERAL:
|
||||
*((int *)where) =
|
||||
((re->flags & PCRE_REQCHSET) != 0)? re->req_char : -1;
|
||||
((re->flags & PCRE_REQCHSET) != 0)? (int)re->req_char : -1;
|
||||
break;
|
||||
|
||||
case PCRE_INFO_REQUIREDCHAR:
|
||||
*((pcre_uint32 *)where) =
|
||||
((re->flags & PCRE_REQCHSET) != 0) ? re->req_char : 0;
|
||||
break;
|
||||
|
||||
case PCRE_INFO_REQUIREDCHARFLAGS:
|
||||
*((int *)where) =
|
||||
((re->flags & PCRE_REQCHSET) != 0);
|
||||
break;
|
||||
|
||||
case PCRE_INFO_NAMEENTRYSIZE:
|
||||
*((int *)where) = re->name_entry_size;
|
||||
break;
|
||||
|
|
@ -193,6 +218,10 @@ switch (what)
|
|||
*((int *)where) = (re->flags & PCRE_HASCRORLF) != 0;
|
||||
break;
|
||||
|
||||
case PCRE_INFO_MAXLOOKBEHIND:
|
||||
*((int *)where) = re->max_lookbehind;
|
||||
break;
|
||||
|
||||
default: return PCRE_ERROR_BADOPTION;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,12 +65,15 @@ Returns: the number of the named parentheses, or a negative number
|
|||
(PCRE_ERROR_NOSUBSTRING) if not found
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_get_stringnumber(const pcre *code, const char *stringname)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_get_stringnumber(const pcre16 *code, PCRE_SPTR16 stringname)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre32_get_stringnumber(const pcre32 *code, PCRE_SPTR32 stringname)
|
||||
#endif
|
||||
{
|
||||
int rc;
|
||||
|
|
@ -98,6 +101,16 @@ if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0
|
|||
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
|
||||
return rc;
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE32
|
||||
if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
|
||||
return rc;
|
||||
if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
|
||||
|
||||
if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
|
||||
return rc;
|
||||
if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
bot = 0;
|
||||
while (top > bot)
|
||||
|
|
@ -132,14 +145,18 @@ Returns: the length of each entry, or a negative number
|
|||
(PCRE_ERROR_NOSUBSTRING) if not found
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_get_stringtable_entries(const pcre *code, const char *stringname,
|
||||
char **firstptr, char **lastptr)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 stringname,
|
||||
PCRE_UCHAR16 **firstptr, PCRE_UCHAR16 **lastptr)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre32_get_stringtable_entries(const pcre32 *code, PCRE_SPTR32 stringname,
|
||||
PCRE_UCHAR32 **firstptr, PCRE_UCHAR32 **lastptr)
|
||||
#endif
|
||||
{
|
||||
int rc;
|
||||
|
|
@ -167,6 +184,16 @@ if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0
|
|||
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
|
||||
return rc;
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE32
|
||||
if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
|
||||
return rc;
|
||||
if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
|
||||
|
||||
if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
|
||||
return rc;
|
||||
if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
lastentry = nametable + entrysize * (top - 1);
|
||||
bot = 0;
|
||||
|
|
@ -192,12 +219,15 @@ while (top > bot)
|
|||
(pcre_uchar *)(last + entrysize + IMM2_SIZE)) != 0) break;
|
||||
last += entrysize;
|
||||
}
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
*firstptr = (char *)first;
|
||||
*lastptr = (char *)last;
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
*firstptr = (PCRE_UCHAR16 *)first;
|
||||
*lastptr = (PCRE_UCHAR16 *)last;
|
||||
#elif defined COMPILE_PCRE32
|
||||
*firstptr = (PCRE_UCHAR32 *)first;
|
||||
*lastptr = (PCRE_UCHAR32 *)last;
|
||||
#endif
|
||||
return entrysize;
|
||||
}
|
||||
|
|
@ -226,31 +256,40 @@ Returns: the number of the first that is set,
|
|||
or a negative number on error
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
static int
|
||||
get_first_set(const pcre *code, const char *stringname, int *ovector)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
static int
|
||||
get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector)
|
||||
#elif defined COMPILE_PCRE32
|
||||
static int
|
||||
get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector)
|
||||
#endif
|
||||
{
|
||||
const REAL_PCRE *re = (const REAL_PCRE *)code;
|
||||
int entrysize;
|
||||
pcre_uchar *entry;
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
char *first, *last;
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_UCHAR16 *first, *last;
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_UCHAR32 *first, *last;
|
||||
#endif
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
|
||||
return pcre_get_stringnumber(code, stringname);
|
||||
entrysize = pcre_get_stringtable_entries(code, stringname, &first, &last);
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
|
||||
return pcre16_get_stringnumber(code, stringname);
|
||||
entrysize = pcre16_get_stringtable_entries(code, stringname, &first, &last);
|
||||
#elif defined COMPILE_PCRE32
|
||||
if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
|
||||
return pcre32_get_stringnumber(code, stringname);
|
||||
entrysize = pcre32_get_stringtable_entries(code, stringname, &first, &last);
|
||||
#endif
|
||||
if (entrysize <= 0) return entrysize;
|
||||
for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize)
|
||||
|
|
@ -291,14 +330,18 @@ Returns: if successful:
|
|||
PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_copy_substring(const char *subject, int *ovector, int stringcount,
|
||||
int stringnumber, char *buffer, int size)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
|
||||
int stringnumber, PCRE_UCHAR16 *buffer, int size)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre32_copy_substring(PCRE_SPTR32 subject, int *ovector, int stringcount,
|
||||
int stringnumber, PCRE_UCHAR32 *buffer, int size)
|
||||
#endif
|
||||
{
|
||||
int yield;
|
||||
|
|
@ -342,24 +385,31 @@ Returns: if successful:
|
|||
PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_copy_named_substring(const pcre *code, const char *subject,
|
||||
int *ovector, int stringcount, const char *stringname,
|
||||
char *buffer, int size)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
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_UCHAR16 *buffer, int size)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
|
||||
int *ovector, int stringcount, PCRE_SPTR32 stringname,
|
||||
PCRE_UCHAR32 *buffer, int size)
|
||||
#endif
|
||||
{
|
||||
int n = get_first_set(code, stringname, ovector);
|
||||
if (n <= 0) return n;
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
return pcre16_copy_substring(subject, ovector, stringcount, n, buffer, size);
|
||||
#elif defined COMPILE_PCRE32
|
||||
return pcre32_copy_substring(subject, ovector, stringcount, n, buffer, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -386,14 +436,18 @@ Returns: if successful: 0
|
|||
PCRE_ERROR_NOMEMORY (-6) failed to get store
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_get_substring_list(const char *subject, int *ovector, int stringcount,
|
||||
const char ***listptr)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount,
|
||||
PCRE_SPTR16 **listptr)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre32_get_substring_list(PCRE_SPTR32 subject, int *ovector, int stringcount,
|
||||
PCRE_SPTR32 **listptr)
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
|
|
@ -408,10 +462,12 @@ for (i = 0; i < double_count; i += 2)
|
|||
stringlist = (pcre_uchar **)(PUBL(malloc))(size);
|
||||
if (stringlist == NULL) return PCRE_ERROR_NOMEMORY;
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
*listptr = (const char **)stringlist;
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
*listptr = (PCRE_SPTR16 *)stringlist;
|
||||
#elif defined COMPILE_PCRE32
|
||||
*listptr = (PCRE_SPTR32 *)stringlist;
|
||||
#endif
|
||||
p = (pcre_uchar *)(stringlist + stringcount + 1);
|
||||
|
||||
|
|
@ -442,12 +498,15 @@ Argument: the result of a previous pcre_get_substring_list()
|
|||
Returns: nothing
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
|
||||
pcre_free_substring_list(const char **pointer)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
|
||||
pcre16_free_substring_list(PCRE_SPTR16 *pointer)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
|
||||
pcre32_free_substring_list(PCRE_SPTR32 *pointer)
|
||||
#endif
|
||||
{
|
||||
(PUBL(free))((void *)pointer);
|
||||
|
|
@ -480,14 +539,18 @@ Returns: if successful:
|
|||
PCRE_ERROR_NOSUBSTRING (-7) substring not present
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_get_substring(const char *subject, int *ovector, int stringcount,
|
||||
int stringnumber, const char **stringptr)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
|
||||
int stringnumber, PCRE_SPTR16 *stringptr)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre32_get_substring(PCRE_SPTR32 subject, int *ovector, int stringcount,
|
||||
int stringnumber, PCRE_SPTR32 *stringptr)
|
||||
#endif
|
||||
{
|
||||
int yield;
|
||||
|
|
@ -500,10 +563,12 @@ substring = (pcre_uchar *)(PUBL(malloc))(IN_UCHARS(yield + 1));
|
|||
if (substring == NULL) return PCRE_ERROR_NOMEMORY;
|
||||
memcpy(substring, subject + ovector[stringnumber], IN_UCHARS(yield));
|
||||
substring[yield] = 0;
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
*stringptr = (const char *)substring;
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
*stringptr = (PCRE_SPTR16)substring;
|
||||
#elif defined COMPILE_PCRE32
|
||||
*stringptr = (PCRE_SPTR32)substring;
|
||||
#endif
|
||||
return yield;
|
||||
}
|
||||
|
|
@ -537,24 +602,31 @@ Returns: if successful:
|
|||
PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_get_named_substring(const pcre *code, const char *subject,
|
||||
int *ovector, int stringcount, const char *stringname,
|
||||
const char **stringptr)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_get_named_substring(const pcre16 *code, PCRE_SPTR16 subject,
|
||||
int *ovector, int stringcount, PCRE_SPTR16 stringname,
|
||||
PCRE_SPTR16 *stringptr)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
|
||||
int *ovector, int stringcount, PCRE_SPTR32 stringname,
|
||||
PCRE_SPTR32 *stringptr)
|
||||
#endif
|
||||
{
|
||||
int n = get_first_set(code, stringname, ovector);
|
||||
if (n <= 0) return n;
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
return pcre_get_substring(subject, ovector, stringcount, n, stringptr);
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
return pcre16_get_substring(subject, ovector, stringcount, n, stringptr);
|
||||
#elif defined COMPILE_PCRE32
|
||||
return pcre32_get_substring(subject, ovector, stringcount, n, stringptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -573,12 +645,15 @@ Argument: the result of a previous pcre_get_substring()
|
|||
Returns: nothing
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
|
||||
pcre_free_substring(const char *pointer)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
|
||||
pcre16_free_substring(PCRE_SPTR16 pointer)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
|
||||
pcre32_free_substring(PCRE_SPTR32 pointer)
|
||||
#endif
|
||||
{
|
||||
(PUBL(free))((void *)pointer);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -66,12 +66,15 @@ Arguments: none
|
|||
Returns: pointer to the contiguous block of data
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
const unsigned char *
|
||||
pcre_maketables(void)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
const unsigned char *
|
||||
pcre16_maketables(void)
|
||||
#elif defined COMPILE_PCRE32
|
||||
const unsigned char *
|
||||
pcre32_maketables(void)
|
||||
#endif
|
||||
{
|
||||
unsigned char *yield, *p;
|
||||
|
|
@ -127,7 +130,7 @@ within regexes. */
|
|||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
int x = 0;
|
||||
if (i != 0x0b && isspace(i)) x += ctype_space;
|
||||
if (i != CHAR_VT && isspace(i)) x += ctype_space;
|
||||
if (isalpha(i)) x += ctype_letter;
|
||||
if (isdigit(i)) x += ctype_digit;
|
||||
if (isxdigit(i)) x += ctype_xdigit;
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ BOOL
|
|||
PRIV(is_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR endptr, int *lenptr,
|
||||
BOOL utf)
|
||||
{
|
||||
int c;
|
||||
pcre_uint32 c;
|
||||
(void)utf;
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf)
|
||||
|
|
@ -87,11 +87,13 @@ else
|
|||
#endif /* SUPPORT_UTF */
|
||||
c = *ptr;
|
||||
|
||||
/* Note that this function is called only for ANY or ANYCRLF. */
|
||||
|
||||
if (type == NLTYPE_ANYCRLF) switch(c)
|
||||
{
|
||||
case 0x000a: *lenptr = 1; return TRUE; /* LF */
|
||||
case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1;
|
||||
return TRUE; /* CR */
|
||||
case CHAR_LF: *lenptr = 1; return TRUE;
|
||||
case CHAR_CR: *lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1;
|
||||
return TRUE;
|
||||
default: return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -99,20 +101,29 @@ if (type == NLTYPE_ANYCRLF) switch(c)
|
|||
|
||||
else switch(c)
|
||||
{
|
||||
case 0x000a: /* LF */
|
||||
case 0x000b: /* VT */
|
||||
case 0x000c: *lenptr = 1; return TRUE; /* FF */
|
||||
case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1;
|
||||
return TRUE; /* CR */
|
||||
#ifdef EBCDIC
|
||||
case CHAR_NEL:
|
||||
#endif
|
||||
case CHAR_LF:
|
||||
case CHAR_VT:
|
||||
case CHAR_FF: *lenptr = 1; return TRUE;
|
||||
|
||||
case CHAR_CR:
|
||||
*lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1;
|
||||
return TRUE;
|
||||
|
||||
#ifndef EBCDIC
|
||||
#ifdef COMPILE_PCRE8
|
||||
case 0x0085: *lenptr = utf? 2 : 1; return TRUE; /* NEL */
|
||||
case CHAR_NEL: *lenptr = utf? 2 : 1; return TRUE;
|
||||
case 0x2028: /* LS */
|
||||
case 0x2029: *lenptr = 3; return TRUE; /* PS */
|
||||
#else
|
||||
case 0x0085: /* NEL */
|
||||
#else /* COMPILE_PCRE16 || COMPILE_PCRE32 */
|
||||
case CHAR_NEL:
|
||||
case 0x2028: /* LS */
|
||||
case 0x2029: *lenptr = 1; return TRUE; /* PS */
|
||||
#endif /* COMPILE_PCRE8 */
|
||||
#endif /* COMPILE_PCRE8 */
|
||||
#endif /* Not EBCDIC */
|
||||
|
||||
default: return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -140,7 +151,7 @@ BOOL
|
|||
PRIV(was_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR startptr, int *lenptr,
|
||||
BOOL utf)
|
||||
{
|
||||
int c;
|
||||
pcre_uint32 c;
|
||||
(void)utf;
|
||||
ptr--;
|
||||
#ifdef SUPPORT_UTF
|
||||
|
|
@ -153,30 +164,45 @@ else
|
|||
#endif /* SUPPORT_UTF */
|
||||
c = *ptr;
|
||||
|
||||
/* Note that this function is called only for ANY or ANYCRLF. */
|
||||
|
||||
if (type == NLTYPE_ANYCRLF) switch(c)
|
||||
{
|
||||
case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1;
|
||||
return TRUE; /* LF */
|
||||
case 0x000d: *lenptr = 1; return TRUE; /* CR */
|
||||
case CHAR_LF:
|
||||
*lenptr = (ptr > startptr && ptr[-1] == CHAR_CR)? 2 : 1;
|
||||
return TRUE;
|
||||
|
||||
case CHAR_CR: *lenptr = 1; return TRUE;
|
||||
default: return FALSE;
|
||||
}
|
||||
|
||||
/* NLTYPE_ANY */
|
||||
|
||||
else switch(c)
|
||||
{
|
||||
case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1;
|
||||
return TRUE; /* LF */
|
||||
case 0x000b: /* VT */
|
||||
case 0x000c: /* FF */
|
||||
case 0x000d: *lenptr = 1; return TRUE; /* CR */
|
||||
case CHAR_LF:
|
||||
*lenptr = (ptr > startptr && ptr[-1] == CHAR_CR)? 2 : 1;
|
||||
return TRUE;
|
||||
|
||||
#ifdef EBCDIC
|
||||
case CHAR_NEL:
|
||||
#endif
|
||||
case CHAR_VT:
|
||||
case CHAR_FF:
|
||||
case CHAR_CR: *lenptr = 1; return TRUE;
|
||||
|
||||
#ifndef EBCDIC
|
||||
#ifdef COMPILE_PCRE8
|
||||
case 0x0085: *lenptr = utf? 2 : 1; return TRUE; /* NEL */
|
||||
case 0x2028: /* LS */
|
||||
case 0x2029: *lenptr = 3; return TRUE; /* PS */
|
||||
#else
|
||||
case 0x0085: /* NEL */
|
||||
case CHAR_NEL: *lenptr = utf? 2 : 1; return TRUE;
|
||||
case 0x2028: /* LS */
|
||||
case 0x2029: *lenptr = 3; return TRUE; /* PS */
|
||||
#else /* COMPILE_PCRE16 || COMPILE_PCRE32 */
|
||||
case CHAR_NEL:
|
||||
case 0x2028: /* LS */
|
||||
case 0x2029: *lenptr = 1; return TRUE; /* PS */
|
||||
#endif /* COMPILE_PCRE8 */
|
||||
#endif /* COMPILE_PCRE8 */
|
||||
#endif /* NotEBCDIC */
|
||||
|
||||
default: return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,15 +45,16 @@ character value into a UTF8 string. */
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcre_internal.h"
|
||||
#define COMPILE_PCRE8
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
/*************************************************
|
||||
* Convert character value to UTF-8 *
|
||||
*************************************************/
|
||||
|
||||
/* This function takes an integer value in the range 0 - 0x10ffff
|
||||
and encodes it as a UTF-8 character in 1 to 6 pcre_uchars.
|
||||
and encodes it as a UTF-8 character in 1 to 4 pcre_uchars.
|
||||
|
||||
Arguments:
|
||||
cvalue the character value
|
||||
|
|
@ -62,6 +63,7 @@ Arguments:
|
|||
Returns: number of characters placed in the buffer
|
||||
*/
|
||||
|
||||
unsigned
|
||||
int
|
||||
PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer)
|
||||
{
|
||||
|
|
@ -69,11 +71,6 @@ PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer)
|
|||
|
||||
register int i, j;
|
||||
|
||||
/* Checking invalid cvalue character, encoded as invalid UTF-16 character.
|
||||
Should never happen in practice. */
|
||||
if ((cvalue & 0xf800) == 0xd800 || cvalue >= 0x110000)
|
||||
cvalue = 0xfffe;
|
||||
|
||||
for (i = 0; i < PRIV(utf8_table1_size); i++)
|
||||
if ((int)cvalue <= PRIV(utf8_table1)[i]) break;
|
||||
buffer += i;
|
||||
|
|
|
|||
|
|
@ -68,12 +68,15 @@ Returns: the (possibly updated) count value (a non-negative number), or
|
|||
a negative error number
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_refcount(pcre *argument_re, int adjust)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_refcount(pcre16 *argument_re, int adjust)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre32_refcount(pcre32 *argument_re, int adjust)
|
||||
#endif
|
||||
{
|
||||
REAL_PCRE *re = (REAL_PCRE *)argument_re;
|
||||
|
|
|
|||
|
|
@ -81,6 +81,27 @@ while (*str1 != '\0' || *str2 != '\0')
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef COMPILE_PCRE32
|
||||
|
||||
int
|
||||
PRIV(strcmp_uc_uc_utf)(const pcre_uchar *str1, const pcre_uchar *str2)
|
||||
{
|
||||
pcre_uchar c1;
|
||||
pcre_uchar c2;
|
||||
|
||||
while (*str1 != '\0' || *str2 != '\0')
|
||||
{
|
||||
c1 = RAWUCHARINC(str1);
|
||||
c2 = RAWUCHARINC(str2);
|
||||
if (c1 != c2)
|
||||
return ((c1 > c2) << 1) - 1;
|
||||
}
|
||||
/* Both length and characters must be equal. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* COMPILE_PCRE32 */
|
||||
|
||||
int
|
||||
PRIV(strcmp_uc_c8)(const pcre_uchar *str1, const char *str2)
|
||||
{
|
||||
|
|
@ -99,6 +120,28 @@ while (*str1 != '\0' || *ustr2 != '\0')
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef COMPILE_PCRE32
|
||||
|
||||
int
|
||||
PRIV(strcmp_uc_c8_utf)(const pcre_uchar *str1, const char *str2)
|
||||
{
|
||||
const pcre_uint8 *ustr2 = (pcre_uint8 *)str2;
|
||||
pcre_uchar c1;
|
||||
pcre_uchar c2;
|
||||
|
||||
while (*str1 != '\0' || *ustr2 != '\0')
|
||||
{
|
||||
c1 = RAWUCHARINC(str1);
|
||||
c2 = (pcre_uchar)*ustr2++;
|
||||
if (c1 != c2)
|
||||
return ((c1 > c2) << 1) - 1;
|
||||
}
|
||||
/* Both length and characters must be equal. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* COMPILE_PCRE32 */
|
||||
|
||||
/* The following two functions compares two, fixed length
|
||||
strings. Basically an strncmp for non 8 bit characters.
|
||||
|
||||
|
|
@ -163,6 +206,6 @@ while (*str++ != 0)
|
|||
return len;
|
||||
}
|
||||
|
||||
#endif /* COMPILE_PCRE8 */
|
||||
#endif /* !COMPILE_PCRE8 */
|
||||
|
||||
/* End of pcre_string_utils.c */
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ for (;;)
|
|||
{
|
||||
int d, min;
|
||||
pcre_uchar *cs, *ce;
|
||||
register int op = *cc;
|
||||
register pcre_uchar op = *cc;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
|
|
@ -323,15 +323,19 @@ for (;;)
|
|||
|
||||
/* Check a class for variable quantification */
|
||||
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
case OP_XCLASS:
|
||||
cc += GET(cc, 1) - PRIV(OP_lengths)[OP_CLASS];
|
||||
/* Fall through */
|
||||
#endif
|
||||
|
||||
case OP_CLASS:
|
||||
case OP_NCLASS:
|
||||
#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
|
||||
case OP_XCLASS:
|
||||
/* The original code caused an unsigned overflow in 64 bit systems,
|
||||
so now we use a conditional statement. */
|
||||
if (op == OP_XCLASS)
|
||||
cc += GET(cc, 1);
|
||||
else
|
||||
cc += PRIV(OP_lengths)[OP_CLASS];
|
||||
#else
|
||||
cc += PRIV(OP_lengths)[OP_CLASS];
|
||||
#endif
|
||||
|
||||
switch (*cc)
|
||||
{
|
||||
|
|
@ -538,7 +542,7 @@ Arguments:
|
|||
p points to the character
|
||||
caseless the caseless flag
|
||||
cd the block with char table pointers
|
||||
utf TRUE for UTF-8 / UTF-16 mode
|
||||
utf TRUE for UTF-8 / UTF-16 / UTF-32 mode
|
||||
|
||||
Returns: pointer after the character
|
||||
*/
|
||||
|
|
@ -547,7 +551,7 @@ static const pcre_uchar *
|
|||
set_table_bit(pcre_uint8 *start_bits, const pcre_uchar *p, BOOL caseless,
|
||||
compile_data *cd, BOOL utf)
|
||||
{
|
||||
unsigned int c = *p;
|
||||
pcre_uint32 c = *p;
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
SET_BIT(c);
|
||||
|
|
@ -564,18 +568,20 @@ if (utf && c > 127)
|
|||
(void)PRIV(ord2utf)(c, buff);
|
||||
SET_BIT(buff[0]);
|
||||
}
|
||||
#endif
|
||||
#endif /* Not SUPPORT_UCP */
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
#else /* Not SUPPORT_UTF */
|
||||
(void)(utf); /* Stops warning for unused parameter */
|
||||
#endif /* SUPPORT_UTF */
|
||||
|
||||
/* Not UTF-8 mode, or character is less than 127. */
|
||||
|
||||
if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
|
||||
return p + 1;
|
||||
#endif
|
||||
#endif /* COMPILE_PCRE8 */
|
||||
|
||||
#ifdef COMPILE_PCRE16
|
||||
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
|
||||
if (c > 0xff)
|
||||
{
|
||||
c = 0xff;
|
||||
|
|
@ -595,10 +601,12 @@ if (utf && c > 127)
|
|||
c = 0xff;
|
||||
SET_BIT(c);
|
||||
}
|
||||
#endif
|
||||
#endif /* SUPPORT_UCP */
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
#else /* Not SUPPORT_UTF */
|
||||
(void)(utf); /* Stops warning for unused parameter */
|
||||
#endif /* SUPPORT_UTF */
|
||||
|
||||
if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
|
||||
return p + 1;
|
||||
|
|
@ -628,10 +636,10 @@ Returns: nothing
|
|||
*/
|
||||
|
||||
static void
|
||||
set_type_bits(pcre_uint8 *start_bits, int cbit_type, int table_limit,
|
||||
set_type_bits(pcre_uint8 *start_bits, int cbit_type, unsigned int table_limit,
|
||||
compile_data *cd)
|
||||
{
|
||||
register int c;
|
||||
register pcre_uint32 c;
|
||||
for (c = 0; c < table_limit; c++) start_bits[c] |= cd->cbits[c+cbit_type];
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
|
||||
if (table_limit == 32) return;
|
||||
|
|
@ -670,10 +678,10 @@ Returns: nothing
|
|||
*/
|
||||
|
||||
static void
|
||||
set_nottype_bits(pcre_uint8 *start_bits, int cbit_type, int table_limit,
|
||||
set_nottype_bits(pcre_uint8 *start_bits, int cbit_type, unsigned int table_limit,
|
||||
compile_data *cd)
|
||||
{
|
||||
register int c;
|
||||
register pcre_uint32 c;
|
||||
for (c = 0; c < table_limit; c++) start_bits[c] |= ~cd->cbits[c+cbit_type];
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
|
||||
if (table_limit != 32) for (c = 24; c < 32; c++) start_bits[c] = 0xff;
|
||||
|
|
@ -697,7 +705,7 @@ function fails unless the result is SSB_DONE.
|
|||
Arguments:
|
||||
code points to an expression
|
||||
start_bits points to a 32-byte table, initialized to 0
|
||||
utf TRUE if in UTF-8 / UTF-16 mode
|
||||
utf TRUE if in UTF-8 / UTF-16 / UTF-32 mode
|
||||
cd the block with char table pointers
|
||||
|
||||
Returns: SSB_FAIL => Failed to find any starting bytes
|
||||
|
|
@ -710,7 +718,7 @@ static int
|
|||
set_start_bits(const pcre_uchar *code, pcre_uint8 *start_bits, BOOL utf,
|
||||
compile_data *cd)
|
||||
{
|
||||
register int c;
|
||||
register pcre_uint32 c;
|
||||
int yield = SSB_DONE;
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
|
||||
int table_limit = utf? 16:32;
|
||||
|
|
@ -986,8 +994,8 @@ do
|
|||
identical. */
|
||||
|
||||
case OP_HSPACE:
|
||||
SET_BIT(0x09);
|
||||
SET_BIT(0x20);
|
||||
SET_BIT(CHAR_HT);
|
||||
SET_BIT(CHAR_SPACE);
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf)
|
||||
{
|
||||
|
|
@ -996,46 +1004,46 @@ do
|
|||
SET_BIT(0xE1); /* For U+1680, U+180E */
|
||||
SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */
|
||||
SET_BIT(0xE3); /* For U+3000 */
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE16
|
||||
#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
|
||||
SET_BIT(0xA0);
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
#endif /* COMPILE_PCRE[8|16|32] */
|
||||
}
|
||||
else
|
||||
#endif /* SUPPORT_UTF */
|
||||
{
|
||||
#ifndef EBCDIC
|
||||
SET_BIT(0xA0);
|
||||
#ifdef COMPILE_PCRE16
|
||||
#endif /* Not EBCDIC */
|
||||
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
#endif /* COMPILE_PCRE[16|32] */
|
||||
}
|
||||
try_next = FALSE;
|
||||
break;
|
||||
|
||||
case OP_ANYNL:
|
||||
case OP_VSPACE:
|
||||
SET_BIT(0x0A);
|
||||
SET_BIT(0x0B);
|
||||
SET_BIT(0x0C);
|
||||
SET_BIT(0x0D);
|
||||
SET_BIT(CHAR_LF);
|
||||
SET_BIT(CHAR_VT);
|
||||
SET_BIT(CHAR_FF);
|
||||
SET_BIT(CHAR_CR);
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf)
|
||||
{
|
||||
#ifdef COMPILE_PCRE8
|
||||
SET_BIT(0xC2); /* For U+0085 */
|
||||
SET_BIT(0xE2); /* For U+2028, U+2029 */
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE16
|
||||
SET_BIT(0x85);
|
||||
#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
|
||||
SET_BIT(CHAR_NEL);
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
#endif /* COMPILE_PCRE[8|16|32] */
|
||||
}
|
||||
else
|
||||
#endif /* SUPPORT_UTF */
|
||||
{
|
||||
SET_BIT(0x85);
|
||||
#ifdef COMPILE_PCRE16
|
||||
SET_BIT(CHAR_NEL);
|
||||
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1058,7 +1066,8 @@ do
|
|||
break;
|
||||
|
||||
/* The cbit_space table has vertical tab as whitespace; we have to
|
||||
ensure it is set as not whitespace. */
|
||||
ensure it is set as not whitespace. Luckily, the code value is the same
|
||||
(0x0b) in ASCII and EBCDIC, so we can just adjust the appropriate bit. */
|
||||
|
||||
case OP_NOT_WHITESPACE:
|
||||
set_nottype_bits(start_bits, cbit_space, table_limit, cd);
|
||||
|
|
@ -1066,8 +1075,9 @@ do
|
|||
try_next = FALSE;
|
||||
break;
|
||||
|
||||
/* The cbit_space table has vertical tab as whitespace; we have to
|
||||
not set it from the table. */
|
||||
/* The cbit_space table has vertical tab as whitespace; we have to not
|
||||
set it from the table. Luckily, the code value is the same (0x0b) in
|
||||
ASCII and EBCDIC, so we can just adjust the appropriate bit. */
|
||||
|
||||
case OP_WHITESPACE:
|
||||
c = start_bits[1]; /* Save in case it was already set */
|
||||
|
|
@ -1121,9 +1131,9 @@ do
|
|||
return SSB_FAIL;
|
||||
|
||||
case OP_HSPACE:
|
||||
SET_BIT(0x09);
|
||||
SET_BIT(0x20);
|
||||
#ifdef COMPILE_PCRE8
|
||||
SET_BIT(CHAR_HT);
|
||||
SET_BIT(CHAR_SPACE);
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf)
|
||||
{
|
||||
#ifdef COMPILE_PCRE8
|
||||
|
|
@ -1131,38 +1141,38 @@ do
|
|||
SET_BIT(0xE1); /* For U+1680, U+180E */
|
||||
SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */
|
||||
SET_BIT(0xE3); /* For U+3000 */
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE16
|
||||
#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
|
||||
SET_BIT(0xA0);
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
#endif /* COMPILE_PCRE[8|16|32] */
|
||||
}
|
||||
else
|
||||
#endif /* SUPPORT_UTF */
|
||||
#ifndef EBCDIC
|
||||
SET_BIT(0xA0);
|
||||
#endif /* Not EBCDIC */
|
||||
break;
|
||||
|
||||
case OP_ANYNL:
|
||||
case OP_VSPACE:
|
||||
SET_BIT(0x0A);
|
||||
SET_BIT(0x0B);
|
||||
SET_BIT(0x0C);
|
||||
SET_BIT(0x0D);
|
||||
#ifdef COMPILE_PCRE8
|
||||
SET_BIT(CHAR_LF);
|
||||
SET_BIT(CHAR_VT);
|
||||
SET_BIT(CHAR_FF);
|
||||
SET_BIT(CHAR_CR);
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf)
|
||||
{
|
||||
#ifdef COMPILE_PCRE8
|
||||
SET_BIT(0xC2); /* For U+0085 */
|
||||
SET_BIT(0xE2); /* For U+2028, U+2029 */
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE16
|
||||
SET_BIT(0x85);
|
||||
#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
|
||||
SET_BIT(CHAR_NEL);
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
#endif /* COMPILE_PCRE16 */
|
||||
}
|
||||
else
|
||||
#endif /* SUPPORT_UTF */
|
||||
SET_BIT(0x85);
|
||||
SET_BIT(CHAR_NEL);
|
||||
break;
|
||||
|
||||
case OP_NOT_DIGIT:
|
||||
|
|
@ -1174,7 +1184,9 @@ do
|
|||
break;
|
||||
|
||||
/* The cbit_space table has vertical tab as whitespace; we have to
|
||||
ensure it gets set as not whitespace. */
|
||||
ensure it gets set as not whitespace. Luckily, the code value is the
|
||||
same (0x0b) in ASCII and EBCDIC, so we can just adjust the appropriate
|
||||
bit. */
|
||||
|
||||
case OP_NOT_WHITESPACE:
|
||||
set_nottype_bits(start_bits, cbit_space, table_limit, cd);
|
||||
|
|
@ -1182,7 +1194,8 @@ do
|
|||
break;
|
||||
|
||||
/* The cbit_space table has vertical tab as whitespace; we have to
|
||||
avoid setting it. */
|
||||
avoid setting it. Luckily, the code value is the same (0x0b) in ASCII
|
||||
and EBCDIC, so we can just adjust the appropriate bit. */
|
||||
|
||||
case OP_WHITESPACE:
|
||||
c = start_bits[1]; /* Save in case it was already set */
|
||||
|
|
@ -1216,7 +1229,7 @@ do
|
|||
memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */
|
||||
}
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE16
|
||||
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
/* Fall through */
|
||||
|
|
@ -1312,12 +1325,15 @@ Returns: pointer to a pcre[16]_extra block, with study_data filled in and
|
|||
NULL on error or if no optimization possible
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN pcre_extra * PCRE_CALL_CONVENTION
|
||||
pcre_study(const pcre *external_re, int options, const char **errorptr)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN pcre16_extra * PCRE_CALL_CONVENTION
|
||||
pcre16_study(const pcre16 *external_re, int options, const char **errorptr)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN pcre32_extra * PCRE_CALL_CONVENTION
|
||||
pcre32_study(const pcre32 *external_re, int options, const char **errorptr)
|
||||
#endif
|
||||
{
|
||||
int min;
|
||||
|
|
@ -1340,10 +1356,12 @@ if (re == NULL || re->magic_number != MAGIC_NUMBER)
|
|||
|
||||
if ((re->flags & PCRE_MODE) == 0)
|
||||
{
|
||||
#ifdef COMPILE_PCRE8
|
||||
*errorptr = "argument is compiled in 16 bit mode";
|
||||
#else
|
||||
*errorptr = "argument is compiled in 8 bit mode";
|
||||
#if defined COMPILE_PCRE8
|
||||
*errorptr = "argument not compiled in 8 bit mode";
|
||||
#elif defined COMPILE_PCRE16
|
||||
*errorptr = "argument not compiled in 16 bit mode";
|
||||
#elif defined COMPILE_PCRE32
|
||||
*errorptr = "argument not compiled in 32 bit mode";
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1370,14 +1388,18 @@ if ((re->options & PCRE_ANCHORED) == 0 &&
|
|||
|
||||
tables = re->tables;
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
if (tables == NULL)
|
||||
(void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
|
||||
(void *)(&tables));
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
if (tables == NULL)
|
||||
(void)pcre16_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
|
||||
(void *)(&tables));
|
||||
#elif defined COMPILE_PCRE32
|
||||
if (tables == NULL)
|
||||
(void)pcre32_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
|
||||
(void *)(&tables));
|
||||
#endif
|
||||
|
||||
compile_block.lcc = tables + lcc_offset;
|
||||
|
|
@ -1408,19 +1430,20 @@ switch(min = find_minlength(code, code, re->options, 0))
|
|||
}
|
||||
|
||||
/* If a set of starting bytes has been identified, or if the minimum length is
|
||||
greater than zero, or if JIT optimization has been requested, get a
|
||||
pcre[16]_extra block and a pcre_study_data block. The study data is put in the
|
||||
latter, which is pointed to by the former, which may also get additional data
|
||||
set later by the calling program. At the moment, the size of pcre_study_data
|
||||
is fixed. We nevertheless save it in a field for returning via the
|
||||
pcre_fullinfo() function so that if it becomes variable in the future,
|
||||
we don't have to change that code. */
|
||||
greater than zero, or if JIT optimization has been requested, or if
|
||||
PCRE_STUDY_EXTRA_NEEDED is set, get a pcre[16]_extra block and a
|
||||
pcre_study_data block. The study data is put in the latter, which is pointed to
|
||||
by the former, which may also get additional data set later by the calling
|
||||
program. At the moment, the size of pcre_study_data is fixed. We nevertheless
|
||||
save it in a field for returning via the pcre_fullinfo() function so that if it
|
||||
becomes variable in the future, we don't have to change that code. */
|
||||
|
||||
if (bits_set || min > 0
|
||||
if (bits_set || min > 0 || (options & (
|
||||
#ifdef SUPPORT_JIT
|
||||
|| (options & PCRE_STUDY_JIT_COMPILE) != 0
|
||||
PCRE_STUDY_JIT_COMPILE | PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE |
|
||||
PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE |
|
||||
#endif
|
||||
)
|
||||
PCRE_STUDY_EXTRA_NEEDED)) != 0)
|
||||
{
|
||||
extra = (PUBL(extra) *)(PUBL(malloc))
|
||||
(sizeof(PUBL(extra)) + sizeof(pcre_study_data));
|
||||
|
|
@ -1474,18 +1497,27 @@ if (bits_set || min > 0
|
|||
|
||||
/* If JIT support was compiled and requested, attempt the JIT compilation.
|
||||
If no starting bytes were found, and the minimum length is zero, and JIT
|
||||
compilation fails, abandon the extra block and return NULL. */
|
||||
compilation fails, abandon the extra block and return NULL, unless
|
||||
PCRE_STUDY_EXTRA_NEEDED is set. */
|
||||
|
||||
#ifdef SUPPORT_JIT
|
||||
extra->executable_jit = NULL;
|
||||
if ((options & PCRE_STUDY_JIT_COMPILE) != 0) PRIV(jit_compile)(re, extra);
|
||||
if (study->flags == 0 && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) == 0)
|
||||
if ((options & PCRE_STUDY_JIT_COMPILE) != 0)
|
||||
PRIV(jit_compile)(re, extra, JIT_COMPILE);
|
||||
if ((options & PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE) != 0)
|
||||
PRIV(jit_compile)(re, extra, JIT_PARTIAL_SOFT_COMPILE);
|
||||
if ((options & PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE) != 0)
|
||||
PRIV(jit_compile)(re, extra, JIT_PARTIAL_HARD_COMPILE);
|
||||
|
||||
if (study->flags == 0 && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) == 0 &&
|
||||
(options & PCRE_STUDY_EXTRA_NEEDED) == 0)
|
||||
{
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
pcre_free_study(extra);
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE16
|
||||
#elif defined COMPILE_PCRE16
|
||||
pcre16_free_study(extra);
|
||||
#elif defined COMPILE_PCRE32
|
||||
pcre32_free_study(extra);
|
||||
#endif
|
||||
extra = NULL;
|
||||
}
|
||||
|
|
@ -1506,12 +1538,15 @@ Argument: a pointer to the pcre[16]_extra block
|
|||
Returns: nothing
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN void
|
||||
pcre_free_study(pcre_extra *extra)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN void
|
||||
pcre16_free_study(pcre16_extra *extra)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN void
|
||||
pcre32_free_study(pcre32_extra *extra)
|
||||
#endif
|
||||
{
|
||||
if (extra == NULL)
|
||||
|
|
|
|||
|
|
@ -58,6 +58,12 @@ the definition is next to the definition of the opcodes in pcre_internal.h. */
|
|||
|
||||
const pcre_uint8 PRIV(OP_lengths)[] = { OP_LENGTHS };
|
||||
|
||||
/* Tables of horizontal and vertical whitespace characters, suitable for
|
||||
adding to classes. */
|
||||
|
||||
const pcre_uint32 PRIV(hspace_list)[] = { HSPACE_LIST };
|
||||
const pcre_uint32 PRIV(vspace_list)[] = { VSPACE_LIST };
|
||||
|
||||
|
||||
|
||||
/*************************************************
|
||||
|
|
@ -68,9 +74,9 @@ const pcre_uint8 PRIV(OP_lengths)[] = { OP_LENGTHS };
|
|||
character. */
|
||||
|
||||
#if (defined SUPPORT_UTF && defined COMPILE_PCRE8) \
|
||||
|| (defined PCRE_INCLUDED && defined SUPPORT_PCRE16)
|
||||
|| (defined PCRE_INCLUDED && (defined SUPPORT_PCRE16 || defined SUPPORT_PCRE32))
|
||||
|
||||
/* These tables are also required by pcretest in 16 bit mode. */
|
||||
/* These tables are also required by pcretest in 16- or 32-bit mode. */
|
||||
|
||||
const int PRIV(utf8_table1)[] =
|
||||
{ 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
|
||||
|
|
@ -92,13 +98,13 @@ const pcre_uint8 PRIV(utf8_table4)[] = {
|
|||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
|
||||
|
||||
#endif /* (SUPPORT_UTF && COMPILE_PCRE8) || (PCRE_INCLUDED && SUPPORT_PCRE16)*/
|
||||
#endif /* (SUPPORT_UTF && COMPILE_PCRE8) || (PCRE_INCLUDED && SUPPORT_PCRE[16|32])*/
|
||||
|
||||
#ifdef SUPPORT_UTF
|
||||
|
||||
/* Table to translate from particular type value to the general value. */
|
||||
|
||||
const int PRIV(ucp_gentype)[] = {
|
||||
const pcre_uint32 PRIV(ucp_gentype)[] = {
|
||||
ucp_C, ucp_C, ucp_C, ucp_C, ucp_C, /* Cc, Cf, Cn, Co, Cs */
|
||||
ucp_L, ucp_L, ucp_L, ucp_L, ucp_L, /* Ll, Lu, Lm, Lo, Lt */
|
||||
ucp_M, ucp_M, ucp_M, /* Mc, Me, Mn */
|
||||
|
|
@ -109,6 +115,66 @@ const int PRIV(ucp_gentype)[] = {
|
|||
ucp_Z, ucp_Z, ucp_Z /* Zl, Zp, Zs */
|
||||
};
|
||||
|
||||
/* This table encodes the rules for finding the end of an extended grapheme
|
||||
cluster. Every code point has a grapheme break property which is one of the
|
||||
ucp_gbXX values defined in ucp.h. The 2-dimensional table is indexed by the
|
||||
properties of two adjacent code points. The left property selects a word from
|
||||
the table, and the right property selects a bit from that word like this:
|
||||
|
||||
ucp_gbtable[left-property] & (1 << right-property)
|
||||
|
||||
The value is non-zero if a grapheme break is NOT permitted between the relevant
|
||||
two code points. The breaking rules are as follows:
|
||||
|
||||
1. Break at the start and end of text (pretty obviously).
|
||||
|
||||
2. Do not break between a CR and LF; otherwise, break before and after
|
||||
controls.
|
||||
|
||||
3. Do not break Hangul syllable sequences, the rules for which are:
|
||||
|
||||
L may be followed by L, V, LV or LVT
|
||||
LV or V may be followed by V or T
|
||||
LVT or T may be followed by T
|
||||
|
||||
4. Do not break before extending characters.
|
||||
|
||||
The next two rules are only for extended grapheme clusters (but that's what we
|
||||
are implementing).
|
||||
|
||||
5. Do not break before SpacingMarks.
|
||||
|
||||
6. Do not break after Prepend characters.
|
||||
|
||||
7. Otherwise, break everywhere.
|
||||
*/
|
||||
|
||||
const pcre_uint32 PRIV(ucp_gbtable[]) = {
|
||||
(1<<ucp_gbLF), /* 0 CR */
|
||||
0, /* 1 LF */
|
||||
0, /* 2 Control */
|
||||
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark), /* 3 Extend */
|
||||
(1<<ucp_gbExtend)|(1<<ucp_gbPrepend)| /* 4 Prepend */
|
||||
(1<<ucp_gbSpacingMark)|(1<<ucp_gbL)|
|
||||
(1<<ucp_gbV)|(1<<ucp_gbT)|(1<<ucp_gbLV)|
|
||||
(1<<ucp_gbLVT)|(1<<ucp_gbOther),
|
||||
|
||||
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark), /* 5 SpacingMark */
|
||||
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbL)| /* 6 L */
|
||||
(1<<ucp_gbL)|(1<<ucp_gbV)|(1<<ucp_gbLV)|(1<<ucp_gbLVT),
|
||||
|
||||
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbV)| /* 7 V */
|
||||
(1<<ucp_gbT),
|
||||
|
||||
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbT), /* 8 T */
|
||||
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbV)| /* 9 LV */
|
||||
(1<<ucp_gbT),
|
||||
|
||||
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbT), /* 10 LVT */
|
||||
(1<<ucp_gbRegionalIndicator), /* 11 RegionalIndicator */
|
||||
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark) /* 12 Other */
|
||||
};
|
||||
|
||||
#ifdef SUPPORT_JIT
|
||||
/* This table reverses PRIV(ucp_gentype). We can save the cost
|
||||
of a memory load. */
|
||||
|
|
@ -159,6 +225,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
|||
#define STRING_Carian0 STR_C STR_a STR_r STR_i STR_a STR_n "\0"
|
||||
#define STRING_Cc0 STR_C STR_c "\0"
|
||||
#define STRING_Cf0 STR_C STR_f "\0"
|
||||
#define STRING_Chakma0 STR_C STR_h STR_a STR_k STR_m STR_a "\0"
|
||||
#define STRING_Cham0 STR_C STR_h STR_a STR_m "\0"
|
||||
#define STRING_Cherokee0 STR_C STR_h STR_e STR_r STR_o STR_k STR_e STR_e "\0"
|
||||
#define STRING_Cn0 STR_C STR_n "\0"
|
||||
|
|
@ -216,6 +283,9 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
|||
#define STRING_Mc0 STR_M STR_c "\0"
|
||||
#define STRING_Me0 STR_M STR_e "\0"
|
||||
#define STRING_Meetei_Mayek0 STR_M STR_e STR_e STR_t STR_e STR_i STR_UNDERSCORE STR_M STR_a STR_y STR_e STR_k "\0"
|
||||
#define STRING_Meroitic_Cursive0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_C STR_u STR_r STR_s STR_i STR_v STR_e "\0"
|
||||
#define STRING_Meroitic_Hieroglyphs0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
|
||||
#define STRING_Miao0 STR_M STR_i STR_a STR_o "\0"
|
||||
#define STRING_Mn0 STR_M STR_n "\0"
|
||||
#define STRING_Mongolian0 STR_M STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0"
|
||||
#define STRING_Myanmar0 STR_M STR_y STR_a STR_n STR_m STR_a STR_r "\0"
|
||||
|
|
@ -249,11 +319,13 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
|||
#define STRING_Samaritan0 STR_S STR_a STR_m STR_a STR_r STR_i STR_t STR_a STR_n "\0"
|
||||
#define STRING_Saurashtra0 STR_S STR_a STR_u STR_r STR_a STR_s STR_h STR_t STR_r STR_a "\0"
|
||||
#define STRING_Sc0 STR_S STR_c "\0"
|
||||
#define STRING_Sharada0 STR_S STR_h STR_a STR_r STR_a STR_d STR_a "\0"
|
||||
#define STRING_Shavian0 STR_S STR_h STR_a STR_v STR_i STR_a STR_n "\0"
|
||||
#define STRING_Sinhala0 STR_S STR_i STR_n STR_h STR_a STR_l STR_a "\0"
|
||||
#define STRING_Sk0 STR_S STR_k "\0"
|
||||
#define STRING_Sm0 STR_S STR_m "\0"
|
||||
#define STRING_So0 STR_S STR_o "\0"
|
||||
#define STRING_Sora_Sompeng0 STR_S STR_o STR_r STR_a STR_UNDERSCORE STR_S STR_o STR_m STR_p STR_e STR_n STR_g "\0"
|
||||
#define STRING_Sundanese0 STR_S STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0"
|
||||
#define STRING_Syloti_Nagri0 STR_S STR_y STR_l STR_o STR_t STR_i STR_UNDERSCORE STR_N STR_a STR_g STR_r STR_i "\0"
|
||||
#define STRING_Syriac0 STR_S STR_y STR_r STR_i STR_a STR_c "\0"
|
||||
|
|
@ -262,6 +334,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
|||
#define STRING_Tai_Le0 STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_e "\0"
|
||||
#define STRING_Tai_Tham0 STR_T STR_a STR_i STR_UNDERSCORE STR_T STR_h STR_a STR_m "\0"
|
||||
#define STRING_Tai_Viet0 STR_T STR_a STR_i STR_UNDERSCORE STR_V STR_i STR_e STR_t "\0"
|
||||
#define STRING_Takri0 STR_T STR_a STR_k STR_r STR_i "\0"
|
||||
#define STRING_Tamil0 STR_T STR_a STR_m STR_i STR_l "\0"
|
||||
#define STRING_Telugu0 STR_T STR_e STR_l STR_u STR_g STR_u "\0"
|
||||
#define STRING_Thaana0 STR_T STR_h STR_a STR_a STR_n STR_a "\0"
|
||||
|
|
@ -299,6 +372,7 @@ const char PRIV(utt_names)[] =
|
|||
STRING_Carian0
|
||||
STRING_Cc0
|
||||
STRING_Cf0
|
||||
STRING_Chakma0
|
||||
STRING_Cham0
|
||||
STRING_Cherokee0
|
||||
STRING_Cn0
|
||||
|
|
@ -356,6 +430,9 @@ const char PRIV(utt_names)[] =
|
|||
STRING_Mc0
|
||||
STRING_Me0
|
||||
STRING_Meetei_Mayek0
|
||||
STRING_Meroitic_Cursive0
|
||||
STRING_Meroitic_Hieroglyphs0
|
||||
STRING_Miao0
|
||||
STRING_Mn0
|
||||
STRING_Mongolian0
|
||||
STRING_Myanmar0
|
||||
|
|
@ -389,11 +466,13 @@ const char PRIV(utt_names)[] =
|
|||
STRING_Samaritan0
|
||||
STRING_Saurashtra0
|
||||
STRING_Sc0
|
||||
STRING_Sharada0
|
||||
STRING_Shavian0
|
||||
STRING_Sinhala0
|
||||
STRING_Sk0
|
||||
STRING_Sm0
|
||||
STRING_So0
|
||||
STRING_Sora_Sompeng0
|
||||
STRING_Sundanese0
|
||||
STRING_Syloti_Nagri0
|
||||
STRING_Syriac0
|
||||
|
|
@ -402,6 +481,7 @@ const char PRIV(utt_names)[] =
|
|||
STRING_Tai_Le0
|
||||
STRING_Tai_Tham0
|
||||
STRING_Tai_Viet0
|
||||
STRING_Takri0
|
||||
STRING_Tamil0
|
||||
STRING_Telugu0
|
||||
STRING_Thaana0
|
||||
|
|
@ -439,126 +519,133 @@ const ucp_type_table PRIV(utt)[] = {
|
|||
{ 118, PT_SC, ucp_Carian },
|
||||
{ 125, PT_PC, ucp_Cc },
|
||||
{ 128, PT_PC, ucp_Cf },
|
||||
{ 131, PT_SC, ucp_Cham },
|
||||
{ 136, PT_SC, ucp_Cherokee },
|
||||
{ 145, PT_PC, ucp_Cn },
|
||||
{ 148, PT_PC, ucp_Co },
|
||||
{ 151, PT_SC, ucp_Common },
|
||||
{ 158, PT_SC, ucp_Coptic },
|
||||
{ 165, PT_PC, ucp_Cs },
|
||||
{ 168, PT_SC, ucp_Cuneiform },
|
||||
{ 178, PT_SC, ucp_Cypriot },
|
||||
{ 186, PT_SC, ucp_Cyrillic },
|
||||
{ 195, PT_SC, ucp_Deseret },
|
||||
{ 203, PT_SC, ucp_Devanagari },
|
||||
{ 214, PT_SC, ucp_Egyptian_Hieroglyphs },
|
||||
{ 235, PT_SC, ucp_Ethiopic },
|
||||
{ 244, PT_SC, ucp_Georgian },
|
||||
{ 253, PT_SC, ucp_Glagolitic },
|
||||
{ 264, PT_SC, ucp_Gothic },
|
||||
{ 271, PT_SC, ucp_Greek },
|
||||
{ 277, PT_SC, ucp_Gujarati },
|
||||
{ 286, PT_SC, ucp_Gurmukhi },
|
||||
{ 295, PT_SC, ucp_Han },
|
||||
{ 299, PT_SC, ucp_Hangul },
|
||||
{ 306, PT_SC, ucp_Hanunoo },
|
||||
{ 314, PT_SC, ucp_Hebrew },
|
||||
{ 321, PT_SC, ucp_Hiragana },
|
||||
{ 330, PT_SC, ucp_Imperial_Aramaic },
|
||||
{ 347, PT_SC, ucp_Inherited },
|
||||
{ 357, PT_SC, ucp_Inscriptional_Pahlavi },
|
||||
{ 379, PT_SC, ucp_Inscriptional_Parthian },
|
||||
{ 402, PT_SC, ucp_Javanese },
|
||||
{ 411, PT_SC, ucp_Kaithi },
|
||||
{ 418, PT_SC, ucp_Kannada },
|
||||
{ 426, PT_SC, ucp_Katakana },
|
||||
{ 435, PT_SC, ucp_Kayah_Li },
|
||||
{ 444, PT_SC, ucp_Kharoshthi },
|
||||
{ 455, PT_SC, ucp_Khmer },
|
||||
{ 461, PT_GC, ucp_L },
|
||||
{ 463, PT_LAMP, 0 },
|
||||
{ 466, PT_SC, ucp_Lao },
|
||||
{ 470, PT_SC, ucp_Latin },
|
||||
{ 476, PT_SC, ucp_Lepcha },
|
||||
{ 483, PT_SC, ucp_Limbu },
|
||||
{ 489, PT_SC, ucp_Linear_B },
|
||||
{ 498, PT_SC, ucp_Lisu },
|
||||
{ 503, PT_PC, ucp_Ll },
|
||||
{ 506, PT_PC, ucp_Lm },
|
||||
{ 509, PT_PC, ucp_Lo },
|
||||
{ 512, PT_PC, ucp_Lt },
|
||||
{ 515, PT_PC, ucp_Lu },
|
||||
{ 518, PT_SC, ucp_Lycian },
|
||||
{ 525, PT_SC, ucp_Lydian },
|
||||
{ 532, PT_GC, ucp_M },
|
||||
{ 534, PT_SC, ucp_Malayalam },
|
||||
{ 544, PT_SC, ucp_Mandaic },
|
||||
{ 552, PT_PC, ucp_Mc },
|
||||
{ 555, PT_PC, ucp_Me },
|
||||
{ 558, PT_SC, ucp_Meetei_Mayek },
|
||||
{ 571, PT_PC, ucp_Mn },
|
||||
{ 574, PT_SC, ucp_Mongolian },
|
||||
{ 584, PT_SC, ucp_Myanmar },
|
||||
{ 592, PT_GC, ucp_N },
|
||||
{ 594, PT_PC, ucp_Nd },
|
||||
{ 597, PT_SC, ucp_New_Tai_Lue },
|
||||
{ 609, PT_SC, ucp_Nko },
|
||||
{ 613, PT_PC, ucp_Nl },
|
||||
{ 616, PT_PC, ucp_No },
|
||||
{ 619, PT_SC, ucp_Ogham },
|
||||
{ 625, PT_SC, ucp_Ol_Chiki },
|
||||
{ 634, PT_SC, ucp_Old_Italic },
|
||||
{ 645, PT_SC, ucp_Old_Persian },
|
||||
{ 657, PT_SC, ucp_Old_South_Arabian },
|
||||
{ 675, PT_SC, ucp_Old_Turkic },
|
||||
{ 686, PT_SC, ucp_Oriya },
|
||||
{ 692, PT_SC, ucp_Osmanya },
|
||||
{ 700, PT_GC, ucp_P },
|
||||
{ 702, PT_PC, ucp_Pc },
|
||||
{ 705, PT_PC, ucp_Pd },
|
||||
{ 708, PT_PC, ucp_Pe },
|
||||
{ 711, PT_PC, ucp_Pf },
|
||||
{ 714, PT_SC, ucp_Phags_Pa },
|
||||
{ 723, PT_SC, ucp_Phoenician },
|
||||
{ 734, PT_PC, ucp_Pi },
|
||||
{ 737, PT_PC, ucp_Po },
|
||||
{ 740, PT_PC, ucp_Ps },
|
||||
{ 743, PT_SC, ucp_Rejang },
|
||||
{ 750, PT_SC, ucp_Runic },
|
||||
{ 756, PT_GC, ucp_S },
|
||||
{ 758, PT_SC, ucp_Samaritan },
|
||||
{ 768, PT_SC, ucp_Saurashtra },
|
||||
{ 779, PT_PC, ucp_Sc },
|
||||
{ 782, PT_SC, ucp_Shavian },
|
||||
{ 790, PT_SC, ucp_Sinhala },
|
||||
{ 798, PT_PC, ucp_Sk },
|
||||
{ 801, PT_PC, ucp_Sm },
|
||||
{ 804, PT_PC, ucp_So },
|
||||
{ 807, PT_SC, ucp_Sundanese },
|
||||
{ 817, PT_SC, ucp_Syloti_Nagri },
|
||||
{ 830, PT_SC, ucp_Syriac },
|
||||
{ 837, PT_SC, ucp_Tagalog },
|
||||
{ 845, PT_SC, ucp_Tagbanwa },
|
||||
{ 854, PT_SC, ucp_Tai_Le },
|
||||
{ 861, PT_SC, ucp_Tai_Tham },
|
||||
{ 870, PT_SC, ucp_Tai_Viet },
|
||||
{ 879, PT_SC, ucp_Tamil },
|
||||
{ 885, PT_SC, ucp_Telugu },
|
||||
{ 892, PT_SC, ucp_Thaana },
|
||||
{ 899, PT_SC, ucp_Thai },
|
||||
{ 904, PT_SC, ucp_Tibetan },
|
||||
{ 912, PT_SC, ucp_Tifinagh },
|
||||
{ 921, PT_SC, ucp_Ugaritic },
|
||||
{ 930, PT_SC, ucp_Vai },
|
||||
{ 934, PT_ALNUM, 0 },
|
||||
{ 938, PT_PXSPACE, 0 },
|
||||
{ 942, PT_SPACE, 0 },
|
||||
{ 946, PT_WORD, 0 },
|
||||
{ 950, PT_SC, ucp_Yi },
|
||||
{ 953, PT_GC, ucp_Z },
|
||||
{ 955, PT_PC, ucp_Zl },
|
||||
{ 958, PT_PC, ucp_Zp },
|
||||
{ 961, PT_PC, ucp_Zs }
|
||||
{ 131, PT_SC, ucp_Chakma },
|
||||
{ 138, PT_SC, ucp_Cham },
|
||||
{ 143, PT_SC, ucp_Cherokee },
|
||||
{ 152, PT_PC, ucp_Cn },
|
||||
{ 155, PT_PC, ucp_Co },
|
||||
{ 158, PT_SC, ucp_Common },
|
||||
{ 165, PT_SC, ucp_Coptic },
|
||||
{ 172, PT_PC, ucp_Cs },
|
||||
{ 175, PT_SC, ucp_Cuneiform },
|
||||
{ 185, PT_SC, ucp_Cypriot },
|
||||
{ 193, PT_SC, ucp_Cyrillic },
|
||||
{ 202, PT_SC, ucp_Deseret },
|
||||
{ 210, PT_SC, ucp_Devanagari },
|
||||
{ 221, PT_SC, ucp_Egyptian_Hieroglyphs },
|
||||
{ 242, PT_SC, ucp_Ethiopic },
|
||||
{ 251, PT_SC, ucp_Georgian },
|
||||
{ 260, PT_SC, ucp_Glagolitic },
|
||||
{ 271, PT_SC, ucp_Gothic },
|
||||
{ 278, PT_SC, ucp_Greek },
|
||||
{ 284, PT_SC, ucp_Gujarati },
|
||||
{ 293, PT_SC, ucp_Gurmukhi },
|
||||
{ 302, PT_SC, ucp_Han },
|
||||
{ 306, PT_SC, ucp_Hangul },
|
||||
{ 313, PT_SC, ucp_Hanunoo },
|
||||
{ 321, PT_SC, ucp_Hebrew },
|
||||
{ 328, PT_SC, ucp_Hiragana },
|
||||
{ 337, PT_SC, ucp_Imperial_Aramaic },
|
||||
{ 354, PT_SC, ucp_Inherited },
|
||||
{ 364, PT_SC, ucp_Inscriptional_Pahlavi },
|
||||
{ 386, PT_SC, ucp_Inscriptional_Parthian },
|
||||
{ 409, PT_SC, ucp_Javanese },
|
||||
{ 418, PT_SC, ucp_Kaithi },
|
||||
{ 425, PT_SC, ucp_Kannada },
|
||||
{ 433, PT_SC, ucp_Katakana },
|
||||
{ 442, PT_SC, ucp_Kayah_Li },
|
||||
{ 451, PT_SC, ucp_Kharoshthi },
|
||||
{ 462, PT_SC, ucp_Khmer },
|
||||
{ 468, PT_GC, ucp_L },
|
||||
{ 470, PT_LAMP, 0 },
|
||||
{ 473, PT_SC, ucp_Lao },
|
||||
{ 477, PT_SC, ucp_Latin },
|
||||
{ 483, PT_SC, ucp_Lepcha },
|
||||
{ 490, PT_SC, ucp_Limbu },
|
||||
{ 496, PT_SC, ucp_Linear_B },
|
||||
{ 505, PT_SC, ucp_Lisu },
|
||||
{ 510, PT_PC, ucp_Ll },
|
||||
{ 513, PT_PC, ucp_Lm },
|
||||
{ 516, PT_PC, ucp_Lo },
|
||||
{ 519, PT_PC, ucp_Lt },
|
||||
{ 522, PT_PC, ucp_Lu },
|
||||
{ 525, PT_SC, ucp_Lycian },
|
||||
{ 532, PT_SC, ucp_Lydian },
|
||||
{ 539, PT_GC, ucp_M },
|
||||
{ 541, PT_SC, ucp_Malayalam },
|
||||
{ 551, PT_SC, ucp_Mandaic },
|
||||
{ 559, PT_PC, ucp_Mc },
|
||||
{ 562, PT_PC, ucp_Me },
|
||||
{ 565, PT_SC, ucp_Meetei_Mayek },
|
||||
{ 578, PT_SC, ucp_Meroitic_Cursive },
|
||||
{ 595, PT_SC, ucp_Meroitic_Hieroglyphs },
|
||||
{ 616, PT_SC, ucp_Miao },
|
||||
{ 621, PT_PC, ucp_Mn },
|
||||
{ 624, PT_SC, ucp_Mongolian },
|
||||
{ 634, PT_SC, ucp_Myanmar },
|
||||
{ 642, PT_GC, ucp_N },
|
||||
{ 644, PT_PC, ucp_Nd },
|
||||
{ 647, PT_SC, ucp_New_Tai_Lue },
|
||||
{ 659, PT_SC, ucp_Nko },
|
||||
{ 663, PT_PC, ucp_Nl },
|
||||
{ 666, PT_PC, ucp_No },
|
||||
{ 669, PT_SC, ucp_Ogham },
|
||||
{ 675, PT_SC, ucp_Ol_Chiki },
|
||||
{ 684, PT_SC, ucp_Old_Italic },
|
||||
{ 695, PT_SC, ucp_Old_Persian },
|
||||
{ 707, PT_SC, ucp_Old_South_Arabian },
|
||||
{ 725, PT_SC, ucp_Old_Turkic },
|
||||
{ 736, PT_SC, ucp_Oriya },
|
||||
{ 742, PT_SC, ucp_Osmanya },
|
||||
{ 750, PT_GC, ucp_P },
|
||||
{ 752, PT_PC, ucp_Pc },
|
||||
{ 755, PT_PC, ucp_Pd },
|
||||
{ 758, PT_PC, ucp_Pe },
|
||||
{ 761, PT_PC, ucp_Pf },
|
||||
{ 764, PT_SC, ucp_Phags_Pa },
|
||||
{ 773, PT_SC, ucp_Phoenician },
|
||||
{ 784, PT_PC, ucp_Pi },
|
||||
{ 787, PT_PC, ucp_Po },
|
||||
{ 790, PT_PC, ucp_Ps },
|
||||
{ 793, PT_SC, ucp_Rejang },
|
||||
{ 800, PT_SC, ucp_Runic },
|
||||
{ 806, PT_GC, ucp_S },
|
||||
{ 808, PT_SC, ucp_Samaritan },
|
||||
{ 818, PT_SC, ucp_Saurashtra },
|
||||
{ 829, PT_PC, ucp_Sc },
|
||||
{ 832, PT_SC, ucp_Sharada },
|
||||
{ 840, PT_SC, ucp_Shavian },
|
||||
{ 848, PT_SC, ucp_Sinhala },
|
||||
{ 856, PT_PC, ucp_Sk },
|
||||
{ 859, PT_PC, ucp_Sm },
|
||||
{ 862, PT_PC, ucp_So },
|
||||
{ 865, PT_SC, ucp_Sora_Sompeng },
|
||||
{ 878, PT_SC, ucp_Sundanese },
|
||||
{ 888, PT_SC, ucp_Syloti_Nagri },
|
||||
{ 901, PT_SC, ucp_Syriac },
|
||||
{ 908, PT_SC, ucp_Tagalog },
|
||||
{ 916, PT_SC, ucp_Tagbanwa },
|
||||
{ 925, PT_SC, ucp_Tai_Le },
|
||||
{ 932, PT_SC, ucp_Tai_Tham },
|
||||
{ 941, PT_SC, ucp_Tai_Viet },
|
||||
{ 950, PT_SC, ucp_Takri },
|
||||
{ 956, PT_SC, ucp_Tamil },
|
||||
{ 962, PT_SC, ucp_Telugu },
|
||||
{ 969, PT_SC, ucp_Thaana },
|
||||
{ 976, PT_SC, ucp_Thai },
|
||||
{ 981, PT_SC, ucp_Tibetan },
|
||||
{ 989, PT_SC, ucp_Tifinagh },
|
||||
{ 998, PT_SC, ucp_Ugaritic },
|
||||
{ 1007, PT_SC, ucp_Vai },
|
||||
{ 1011, PT_ALNUM, 0 },
|
||||
{ 1015, PT_PXSPACE, 0 },
|
||||
{ 1019, PT_SPACE, 0 },
|
||||
{ 1023, PT_WORD, 0 },
|
||||
{ 1027, PT_SC, ucp_Yi },
|
||||
{ 1030, PT_GC, ucp_Z },
|
||||
{ 1032, PT_PC, ucp_Zl },
|
||||
{ 1035, PT_PC, ucp_Zp },
|
||||
{ 1038, PT_PC, ucp_Zs }
|
||||
};
|
||||
|
||||
const int PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -92,6 +92,7 @@ PCRE_UTF8_ERR18 Overlong 5-byte sequence (won't ever occur)
|
|||
PCRE_UTF8_ERR19 Overlong 6-byte sequence (won't ever occur)
|
||||
PCRE_UTF8_ERR20 Isolated 0x80 byte (not within UTF-8 character)
|
||||
PCRE_UTF8_ERR21 Byte with the illegal value 0xfe or 0xff
|
||||
PCRE_UTF8_ERR22 Non-character
|
||||
|
||||
Arguments:
|
||||
string points to the string
|
||||
|
|
@ -116,7 +117,8 @@ if (length < 0)
|
|||
|
||||
for (p = string; length-- > 0; p++)
|
||||
{
|
||||
register int ab, c, d;
|
||||
register pcre_uchar ab, c, d;
|
||||
pcre_uint32 v = 0;
|
||||
|
||||
c = *p;
|
||||
if (c < 128) continue; /* ASCII character */
|
||||
|
|
@ -185,6 +187,7 @@ for (p = string; length-- > 0; p++)
|
|||
*erroroffset = (int)(p - string) - 2;
|
||||
return PCRE_UTF8_ERR14;
|
||||
}
|
||||
v = ((c & 0x0f) << 12) | ((d & 0x3f) << 6) | (*p & 0x3f);
|
||||
break;
|
||||
|
||||
/* 4-byte character. Check 3rd and 4th bytes for 0x80. Then check first 2
|
||||
|
|
@ -212,6 +215,7 @@ for (p = string; length-- > 0; p++)
|
|||
*erroroffset = (int)(p - string) - 3;
|
||||
return PCRE_UTF8_ERR13;
|
||||
}
|
||||
v = ((c & 0x07) << 18) | ((d & 0x3f) << 12) | ((p[-1] & 0x3f) << 6) | (*p & 0x3f);
|
||||
break;
|
||||
|
||||
/* 5-byte and 6-byte characters are not allowed by RFC 3629, and will be
|
||||
|
|
@ -286,11 +290,20 @@ for (p = string; length-- > 0; p++)
|
|||
*erroroffset = (int)(p - string) - ab;
|
||||
return (ab == 4)? PCRE_UTF8_ERR11 : PCRE_UTF8_ERR12;
|
||||
}
|
||||
|
||||
/* Reject non-characters. The pointer p is currently at the last byte of the
|
||||
character. */
|
||||
if ((v & 0xfffeu) == 0xfffeu || (v >= 0xfdd0 && v <= 0xfdef))
|
||||
{
|
||||
*erroroffset = (int)(p - string) - ab;
|
||||
return PCRE_UTF8_ERR22;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* SUPPORT_UTF */
|
||||
#else /* Not SUPPORT_UTF */
|
||||
(void)(string); /* Keep picky compilers happy */
|
||||
(void)(length);
|
||||
(void)(erroroffset);
|
||||
#endif
|
||||
|
||||
return PCRE_UTF8_ERR0; /* This indicates success */
|
||||
|
|
|
|||
|
|
@ -79,12 +79,15 @@ I could find no way of detecting that a macro is defined as an empty string at
|
|||
pre-processor time. This hack uses a standard trick for avoiding calling
|
||||
the STRING macro with an empty argument when doing the test. */
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
#if defined COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
|
||||
pcre_version(void)
|
||||
#else
|
||||
#elif defined COMPILE_PCRE16
|
||||
PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
|
||||
pcre16_version(void)
|
||||
#elif defined COMPILE_PCRE32
|
||||
PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
|
||||
pcre32_version(void)
|
||||
#endif
|
||||
{
|
||||
return (XSTRING(Z PCRE_PRERELEASE)[1] == 0)?
|
||||
|
|
|
|||
|
|
@ -64,9 +64,9 @@ Returns: TRUE if character matches, else FALSE
|
|||
*/
|
||||
|
||||
BOOL
|
||||
PRIV(xclass)(int c, const pcre_uchar *data, BOOL utf)
|
||||
PRIV(xclass)(pcre_uint32 c, const pcre_uchar *data, BOOL utf)
|
||||
{
|
||||
int t;
|
||||
pcre_uchar t;
|
||||
BOOL negated = (*data & XCL_NOT) != 0;
|
||||
|
||||
(void)utf;
|
||||
|
|
@ -94,7 +94,7 @@ if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(pcre_uchar);
|
|||
|
||||
while ((t = *data++) != XCL_END)
|
||||
{
|
||||
int x, y;
|
||||
pcre_uint32 x, y;
|
||||
if (t == XCL_SINGLE)
|
||||
{
|
||||
#ifdef SUPPORT_UTF
|
||||
|
|
|
|||
|
|
@ -27,11 +27,18 @@
|
|||
#ifndef _SLJIT_CONFIG_H_
|
||||
#define _SLJIT_CONFIG_H_
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Custom defines */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Put your custom defines here. This empty section will never change
|
||||
which helps maintaining patches (with diff / patch utilities). */
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Architecture */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Architecture selection */
|
||||
/* Architecture selection. */
|
||||
/* #define SLJIT_CONFIG_X86_32 1 */
|
||||
/* #define SLJIT_CONFIG_X86_64 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_V5 1 */
|
||||
|
|
@ -40,6 +47,7 @@
|
|||
/* #define SLJIT_CONFIG_PPC_32 1 */
|
||||
/* #define SLJIT_CONFIG_PPC_64 1 */
|
||||
/* #define SLJIT_CONFIG_MIPS_32 1 */
|
||||
/* #define SLJIT_CONFIG_SPARC_32 1 */
|
||||
|
||||
/* #define SLJIT_CONFIG_AUTO 1 */
|
||||
/* #define SLJIT_CONFIG_UNSUPPORTED 1 */
|
||||
|
|
@ -60,6 +68,12 @@
|
|||
#define SLJIT_UTIL_STACK 1
|
||||
#endif
|
||||
|
||||
/* Single threaded application. Does not require any locks. */
|
||||
#ifndef SLJIT_SINGLE_THREADED
|
||||
/* Disabled by default. */
|
||||
#define SLJIT_SINGLE_THREADED 0
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Configuration */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
|
|
|||
|
|
@ -33,18 +33,23 @@
|
|||
Feature detection (boolean) macros:
|
||||
SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
|
||||
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
|
||||
SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_w/sljit_uw array by index
|
||||
SLJIT_FLOAT_SHIFT : the shift required to apply when accessing a double array by index
|
||||
SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index
|
||||
SLJIT_DOUBLE_SHIFT : the shift required to apply when accessing a double array by index
|
||||
SLJIT_LITTLE_ENDIAN : little endian architecture
|
||||
SLJIT_BIG_ENDIAN : big endian architecture
|
||||
SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!)
|
||||
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET() for more information
|
||||
SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
|
||||
|
||||
Types and useful macros:
|
||||
sljit_b, sljit_ub : signed and unsigned 8 bit byte
|
||||
sljit_h, sljit_uh : signed and unsigned 16 bit half-word (short) type
|
||||
sljit_i, sljit_ui : signed and unsigned 32 bit integer type
|
||||
sljit_w, sljit_uw : signed and unsigned machine word, enough to store a pointer (same as intptr_t)
|
||||
sljit_sb, sljit_ub : signed and unsigned 8 bit byte
|
||||
sljit_sh, sljit_uh : signed and unsigned 16 bit half-word (short) type
|
||||
sljit_si, sljit_ui : signed and unsigned 32 bit integer type
|
||||
sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer
|
||||
sljit_p : unsgined pointer value (usually the same as sljit_uw, but
|
||||
some 64 bit ABIs may use 32 bit pointers)
|
||||
sljit_s : single precision floating point value
|
||||
sljit_d : double precision floating point value
|
||||
SLJIT_CALL : C calling convention define for both calling JIT form C and C callbacks for JIT
|
||||
SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (compiler independent helper)
|
||||
*/
|
||||
|
|
@ -57,6 +62,7 @@
|
|||
|| (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|
||||
|| (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|
||||
|| (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|
||||
|| (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED))
|
||||
#error "An architecture must be selected"
|
||||
|
|
@ -71,6 +77,7 @@
|
|||
+ (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
+ (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
+ (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|
||||
+ (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|
||||
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|
||||
+ (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
|
||||
#error "Multiple architectures are selected"
|
||||
|
|
@ -93,12 +100,14 @@
|
|||
#else
|
||||
#define SLJIT_CONFIG_ARM_V5 1
|
||||
#endif
|
||||
#elif defined(__ppc64__) || defined(__powerpc64__)
|
||||
#elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_PPC64) || (defined(_POWER) && defined(__64BIT__))
|
||||
#define SLJIT_CONFIG_PPC_64 1
|
||||
#elif defined(__ppc__) || defined(__powerpc__)
|
||||
#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER)
|
||||
#define SLJIT_CONFIG_PPC_32 1
|
||||
#elif defined(__mips__)
|
||||
#define SLJIT_CONFIG_MIPS_32 1
|
||||
#elif defined(__sparc__) || defined(__sparc)
|
||||
#define SLJIT_CONFIG_SPARC_32 1
|
||||
#else
|
||||
/* Unsupported architecture */
|
||||
#define SLJIT_CONFIG_UNSUPPORTED 1
|
||||
|
|
@ -194,16 +203,31 @@
|
|||
|
||||
#ifndef SLJIT_CACHE_FLUSH
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
|
||||
/* Not required to implement on archs with unified caches. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to)
|
||||
|
||||
#elif defined __APPLE__
|
||||
|
||||
/* Supported by all macs since Mac OS 10.5.
|
||||
However, it does not work on non-jailbroken iOS devices,
|
||||
although the compilation is successful. */
|
||||
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
sys_icache_invalidate((char*)(from), (char*)(to) - (char*)(from))
|
||||
|
||||
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
|
||||
/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
ppc_cache_flush((from), (to))
|
||||
|
||||
#elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
|
||||
/* Not required to implement on archs with unified caches. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to)
|
||||
/* The __clear_cache() implementation of GCC is a dummy function on Sparc. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
sparc_cache_flush((from), (to))
|
||||
|
||||
#else
|
||||
|
||||
|
|
@ -217,15 +241,15 @@
|
|||
|
||||
/* 8 bit byte type. */
|
||||
typedef unsigned char sljit_ub;
|
||||
typedef signed char sljit_b;
|
||||
typedef signed char sljit_sb;
|
||||
|
||||
/* 16 bit half-word type. */
|
||||
typedef unsigned short int sljit_uh;
|
||||
typedef signed short int sljit_h;
|
||||
typedef signed short int sljit_sh;
|
||||
|
||||
/* 32 bit integer type. */
|
||||
typedef unsigned int sljit_ui;
|
||||
typedef signed int sljit_i;
|
||||
typedef signed int sljit_si;
|
||||
|
||||
/* Machine word type. Can encapsulate a pointer.
|
||||
32 bit for 32 bit machines.
|
||||
|
|
@ -234,26 +258,35 @@ typedef signed int sljit_i;
|
|||
/* Just to have something. */
|
||||
#define SLJIT_WORD_SHIFT 0
|
||||
typedef unsigned long int sljit_uw;
|
||||
typedef long int sljit_w;
|
||||
typedef long int sljit_sw;
|
||||
#elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define SLJIT_32BIT_ARCHITECTURE 1
|
||||
#define SLJIT_WORD_SHIFT 2
|
||||
typedef unsigned int sljit_uw;
|
||||
typedef int sljit_w;
|
||||
typedef int sljit_sw;
|
||||
#else
|
||||
#define SLJIT_64BIT_ARCHITECTURE 1
|
||||
#define SLJIT_WORD_SHIFT 3
|
||||
#ifdef _WIN32
|
||||
typedef unsigned __int64 sljit_uw;
|
||||
typedef __int64 sljit_w;
|
||||
typedef __int64 sljit_sw;
|
||||
#else
|
||||
typedef unsigned long int sljit_uw;
|
||||
typedef long int sljit_w;
|
||||
typedef long int sljit_sw;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Double precision. */
|
||||
#define SLJIT_FLOAT_SHIFT 3
|
||||
typedef sljit_uw sljit_p;
|
||||
|
||||
/* Floating point types. */
|
||||
typedef float sljit_s;
|
||||
typedef double sljit_d;
|
||||
|
||||
/* Shift for pointer sized data. */
|
||||
#define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT
|
||||
|
||||
/* Shift for double precision sized data. */
|
||||
#define SLJIT_DOUBLE_SHIFT 3
|
||||
|
||||
#ifndef SLJIT_W
|
||||
|
||||
|
|
@ -276,20 +309,24 @@ typedef long int sljit_w;
|
|||
#define SLJIT_CALL __attribute__ ((fastcall))
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#elif defined(_WIN32)
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#define SLJIT_CALL __msfastcall
|
||||
#else /* __BORLANDC__ */
|
||||
#define SLJIT_CALL __fastcall
|
||||
#endif /* __BORLANDC__ */
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#else /* defined(_WIN32) */
|
||||
#define SLJIT_CALL __stdcall
|
||||
#elif defined(__BORLANDC__)
|
||||
|
||||
#define SLJIT_CALL __msfastcall
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#else /* Unknown compiler. */
|
||||
|
||||
/* The cdecl attribute is the default. */
|
||||
#define SLJIT_CALL
|
||||
|
||||
#endif
|
||||
|
||||
#else /* Other architectures. */
|
||||
#else /* Non x86-32 architectures. */
|
||||
|
||||
#define SLJIT_CALL
|
||||
|
||||
|
|
@ -300,7 +337,9 @@ typedef long int sljit_w;
|
|||
#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
|
||||
|
||||
/* These macros are useful for the application. */
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
|| (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
|
||||
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
|
|
@ -326,23 +365,32 @@ typedef long int sljit_w;
|
|||
#error "Exactly one endianness must be selected"
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
/* It seems ppc64 compilers use an indirect addressing for functions.
|
||||
It makes things really complicated. */
|
||||
#ifndef SLJIT_INDIRECT_CALL
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32 && defined _AIX)
|
||||
/* It seems certain ppc compilers use an indirect addressing for functions
|
||||
which makes things complicated. */
|
||||
#define SLJIT_INDIRECT_CALL 1
|
||||
#endif
|
||||
#endif /* SLJIT_INDIRECT_CALL */
|
||||
|
||||
#ifndef SLJIT_RETURN_ADDRESS_OFFSET
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
#define SLJIT_RETURN_ADDRESS_OFFSET 8
|
||||
#else
|
||||
#define SLJIT_RETURN_ADDRESS_OFFSET 0
|
||||
#endif
|
||||
#endif /* SLJIT_RETURN_ADDRESS_OFFSET */
|
||||
|
||||
#ifndef SLJIT_SSE2
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
/* Turn on SSE2 support on x86 (operating on doubles).
|
||||
(Better performance than legacy fpu instructions). */
|
||||
/* Turn on SSE2 support on x86. */
|
||||
#define SLJIT_SSE2 1
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
/* Auto detect SSE2 support using CPUID.
|
||||
On 64 bit x86 cpus, sse2 must be present. */
|
||||
#define SLJIT_SSE2_AUTO 1
|
||||
#define SLJIT_DETECT_SSE2 1
|
||||
#endif
|
||||
|
||||
#endif /* (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) */
|
||||
|
|
@ -369,17 +417,28 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
|
|||
#define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr)
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG) || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
|
||||
/* Feel free to redefine these two macros. */
|
||||
#ifndef SLJIT_ASSERT
|
||||
#if !defined(SLJIT_ASSERT) || !defined(SLJIT_ASSERT_STOP)
|
||||
|
||||
/* SLJIT_HALT_PROCESS must halt the process. */
|
||||
#ifndef SLJIT_HALT_PROCESS
|
||||
#include <stdlib.h>
|
||||
|
||||
#define SLJIT_HALT_PROCESS() \
|
||||
*((int*)0) = 0
|
||||
abort();
|
||||
#endif /* !SLJIT_HALT_PROCESS */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#endif /* !SLJIT_ASSERT || !SLJIT_ASSERT_STOP */
|
||||
|
||||
/* Feel free to redefine these two macros. */
|
||||
#ifndef SLJIT_ASSERT
|
||||
|
||||
#define SLJIT_ASSERT(x) \
|
||||
do { \
|
||||
|
|
@ -403,6 +462,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
|
|||
|
||||
#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
|
||||
|
||||
/* Forcing empty, but valid statements. */
|
||||
#undef SLJIT_ASSERT
|
||||
#undef SLJIT_ASSERT_STOP
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
The unused blocks are stored in a chain list pointed by free_blocks. This
|
||||
list is useful if we need to find a suitable memory area when the allocator
|
||||
is called.
|
||||
|
||||
|
||||
When a block is freed, the new free block is connected to its adjacent free
|
||||
blocks if possible.
|
||||
|
||||
|
|
@ -83,7 +83,7 @@
|
|||
|
||||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
|
||||
|
|
@ -94,11 +94,20 @@ static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
|
|||
|
||||
#else
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
void* retval = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
void* retval;
|
||||
|
||||
#ifdef MAP_ANON
|
||||
retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
#else
|
||||
if (dev_zero < 0) {
|
||||
if (open_dev_zero())
|
||||
return NULL;
|
||||
}
|
||||
retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, dev_zero, 0);
|
||||
#endif
|
||||
|
||||
return (retval != MAP_FAILED) ? retval : NULL;
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +211,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
|
|||
|
||||
chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK;
|
||||
header = (struct block_header*)alloc_chunk(chunk_size);
|
||||
PTR_FAIL_IF(!header);
|
||||
if (!header) {
|
||||
allocator_release_lock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chunk_size -= sizeof(struct block_header);
|
||||
total_size += chunk_size;
|
||||
|
|
@ -237,14 +249,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
|
|||
struct free_block* free_block;
|
||||
|
||||
allocator_grab_lock();
|
||||
header = AS_BLOCK_HEADER(ptr, -(sljit_w)sizeof(struct block_header));
|
||||
header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));
|
||||
allocated_size -= header->size;
|
||||
|
||||
/* Connecting free blocks together if possible. */
|
||||
|
||||
/* If header->prev_size == 0, free_block will equal to header.
|
||||
In this case, free_block->header.size will be > 0. */
|
||||
free_block = AS_FREE_BLOCK(header, -(sljit_w)header->prev_size);
|
||||
free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);
|
||||
if (SLJIT_UNLIKELY(!free_block->header.size)) {
|
||||
free_block->size += header->size;
|
||||
header = AS_BLOCK_HEADER(free_block, free_block->size);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -34,28 +34,39 @@
|
|||
|
||||
Short description
|
||||
Advantages:
|
||||
- The execution can be continued from any LIR instruction
|
||||
In other words, jump into and out of the code is safe
|
||||
- Both target of (conditional) jump and call instructions
|
||||
and constants can be dynamically modified during runtime
|
||||
- The execution can be continued from any LIR instruction. In other
|
||||
words, it is possible to jump to any label from anywhere, even from
|
||||
a code fragment, which is compiled later, if both compiled code
|
||||
shares the same context. See sljit_emit_enter for more details
|
||||
- Supports self modifying code: target of (conditional) jump and call
|
||||
instructions and some constant values can be dynamically modified
|
||||
during runtime
|
||||
- although it is not suggested to do it frequently
|
||||
- very effective to cache an important value once
|
||||
- can be used for inline caching: save an important value once
|
||||
in the instruction stream
|
||||
- since this feature limits the optimization possibilities, a
|
||||
special flag must be passed at compile time when these
|
||||
instructions are emitted
|
||||
- A fixed stack space can be allocated for local variables
|
||||
- The compiler is thread-safe
|
||||
- The compiler is highly configurable through preprocessor macros.
|
||||
You can disable unneeded features (multithreading in single
|
||||
threaded applications), and you can use your own system functions
|
||||
(including memory allocators). See sljitConfig.h
|
||||
Disadvantages:
|
||||
- No automatic register allocation, and temporary results are
|
||||
not stored on the stack. (hence the name comes)
|
||||
- Limited number of registers (only 6+4 integer registers, max 3+2
|
||||
temporary, max 3+2 saved and 4 floating point registers)
|
||||
scratch, max 3+2 saved and 6 floating point registers)
|
||||
In practice:
|
||||
- This approach is very effective for interpreters
|
||||
- One of the saved registers typically points to a stack interface
|
||||
- It can jump to any exception handler anytime (even for another
|
||||
function. It is safe for SLJIT.)
|
||||
- Fast paths can be modified during runtime reflecting the changes
|
||||
- It can jump to any exception handler anytime (even if it belongs
|
||||
to another function)
|
||||
- Hot paths can be modified during runtime reflecting the changes
|
||||
of the fastest execution path of the dynamic language
|
||||
- SLJIT supports complex memory addressing modes
|
||||
- mainly position independent code
|
||||
- Optimizations (perhaps later)
|
||||
- Only for basic blocks (when no labels inserted between LIR instructions)
|
||||
- mainly position and context independent code (except some cases)
|
||||
|
||||
For valgrind users:
|
||||
- pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code"
|
||||
|
|
@ -95,12 +106,14 @@ of sljitConfigInternal.h */
|
|||
|
||||
#define SLJIT_UNUSED 0
|
||||
|
||||
/* Temporary (scratch) registers may not preserve their values across function calls. */
|
||||
#define SLJIT_TEMPORARY_REG1 1
|
||||
#define SLJIT_TEMPORARY_REG2 2
|
||||
#define SLJIT_TEMPORARY_REG3 3
|
||||
/* Note: Extra Registers cannot be used for memory addressing. */
|
||||
/* Note: on x86-32, these registers are emulated (using stack loads & stores). */
|
||||
/* Scratch (temporary) registers whose may not preserve their values
|
||||
across function calls. */
|
||||
#define SLJIT_SCRATCH_REG1 1
|
||||
#define SLJIT_SCRATCH_REG2 2
|
||||
#define SLJIT_SCRATCH_REG3 3
|
||||
/* Note: extra registers cannot be used for memory addressing. */
|
||||
/* Note: on x86-32, these registers are emulated (using stack
|
||||
loads & stores). */
|
||||
#define SLJIT_TEMPORARY_EREG1 4
|
||||
#define SLJIT_TEMPORARY_EREG2 5
|
||||
|
||||
|
|
@ -108,14 +121,17 @@ of sljitConfigInternal.h */
|
|||
#define SLJIT_SAVED_REG1 6
|
||||
#define SLJIT_SAVED_REG2 7
|
||||
#define SLJIT_SAVED_REG3 8
|
||||
/* Note: Extra Registers cannot be used for memory addressing. */
|
||||
/* Note: on x86-32, these registers are emulated (using stack loads & stores). */
|
||||
/* Note: extra registers cannot be used for memory addressing. */
|
||||
/* Note: on x86-32, these registers are emulated (using stack
|
||||
loads & stores). */
|
||||
#define SLJIT_SAVED_EREG1 9
|
||||
#define SLJIT_SAVED_EREG2 10
|
||||
|
||||
/* Read-only register (cannot be the destination of an operation). */
|
||||
/* Note: SLJIT_MEM2( ... , SLJIT_LOCALS_REG) is not supported (x86 limitation). */
|
||||
/* Note: SLJIT_LOCALS_REG is not necessary the real stack pointer. See sljit_emit_enter. */
|
||||
/* Read-only register (cannot be the destination of an operation).
|
||||
Only SLJIT_MEM1(SLJIT_LOCALS_REG) addressing mode is allowed since
|
||||
several ABIs has certain limitations about the stack layout. However
|
||||
sljit_get_local_base() can be used to obtain the offset of a value
|
||||
on the stack. */
|
||||
#define SLJIT_LOCALS_REG 11
|
||||
|
||||
/* Number of registers. */
|
||||
|
|
@ -125,15 +141,15 @@ of sljitConfigInternal.h */
|
|||
|
||||
/* Return with machine word. */
|
||||
|
||||
#define SLJIT_RETURN_REG SLJIT_TEMPORARY_REG1
|
||||
#define SLJIT_RETURN_REG SLJIT_SCRATCH_REG1
|
||||
|
||||
/* x86 prefers specific registers for special purposes. In case of shift
|
||||
by register it supports only SLJIT_TEMPORARY_REG3 for shift argument
|
||||
by register it supports only SLJIT_SCRATCH_REG3 for shift argument
|
||||
(which is the src2 argument of sljit_emit_op2). If another register is
|
||||
used, sljit must exchange data between registers which cause a minor
|
||||
slowdown. Other architectures has no such limitation. */
|
||||
|
||||
#define SLJIT_PREF_SHIFT_REG SLJIT_TEMPORARY_REG3
|
||||
#define SLJIT_PREF_SHIFT_REG SLJIT_SCRATCH_REG3
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Floating point registers */
|
||||
|
|
@ -142,12 +158,15 @@ of sljitConfigInternal.h */
|
|||
/* Note: SLJIT_UNUSED as destination is not valid for floating point
|
||||
operations, since they cannot be used for setting flags. */
|
||||
|
||||
/* Floating point operations are performed on double precision values. */
|
||||
/* Floating point operations are performed on double or
|
||||
single precision values. */
|
||||
|
||||
#define SLJIT_FLOAT_REG1 1
|
||||
#define SLJIT_FLOAT_REG2 2
|
||||
#define SLJIT_FLOAT_REG3 3
|
||||
#define SLJIT_FLOAT_REG4 4
|
||||
#define SLJIT_FLOAT_REG5 5
|
||||
#define SLJIT_FLOAT_REG6 6
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Main structures and functions */
|
||||
|
|
@ -156,6 +175,7 @@ of sljitConfigInternal.h */
|
|||
struct sljit_memory_fragment {
|
||||
struct sljit_memory_fragment *next;
|
||||
sljit_uw used_size;
|
||||
/* Must be aligned to sljit_sw. */
|
||||
sljit_ub memory[1];
|
||||
};
|
||||
|
||||
|
|
@ -169,7 +189,7 @@ struct sljit_label {
|
|||
struct sljit_jump {
|
||||
struct sljit_jump *next;
|
||||
sljit_uw addr;
|
||||
sljit_w flags;
|
||||
sljit_sw flags;
|
||||
union {
|
||||
sljit_uw target;
|
||||
struct sljit_label* label;
|
||||
|
|
@ -182,7 +202,7 @@ struct sljit_const {
|
|||
};
|
||||
|
||||
struct sljit_compiler {
|
||||
int error;
|
||||
sljit_si error;
|
||||
|
||||
struct sljit_label *labels;
|
||||
struct sljit_jump *jumps;
|
||||
|
|
@ -195,31 +215,29 @@ struct sljit_compiler {
|
|||
struct sljit_memory_fragment *abuf;
|
||||
|
||||
/* Used local registers. */
|
||||
int temporaries;
|
||||
sljit_si scratches;
|
||||
/* Used saved registers. */
|
||||
int saveds;
|
||||
sljit_si saveds;
|
||||
/* Local stack size. */
|
||||
int local_size;
|
||||
sljit_si local_size;
|
||||
/* Code size. */
|
||||
sljit_uw size;
|
||||
/* For statistical purposes. */
|
||||
sljit_uw executable_size;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
int args;
|
||||
int temporaries_start;
|
||||
int saveds_start;
|
||||
sljit_si args;
|
||||
sljit_si locals_offset;
|
||||
sljit_si scratches_start;
|
||||
sljit_si saveds_start;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
int mode32;
|
||||
#ifdef _WIN64
|
||||
int has_locals;
|
||||
#endif
|
||||
sljit_si mode32;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
int flags_saved;
|
||||
sljit_si flags_saved;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
|
|
@ -236,35 +254,44 @@ struct sljit_compiler {
|
|||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||
/* Temporary fields. */
|
||||
sljit_uw shift_imm;
|
||||
int cache_arg;
|
||||
sljit_w cache_argw;
|
||||
sljit_si cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
||||
int cache_arg;
|
||||
sljit_w cache_argw;
|
||||
sljit_si cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
int has_locals;
|
||||
sljit_w imm;
|
||||
int cache_arg;
|
||||
sljit_w cache_argw;
|
||||
sljit_sw imm;
|
||||
sljit_si cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
int has_locals;
|
||||
int delay_slot;
|
||||
int cache_arg;
|
||||
sljit_w cache_argw;
|
||||
sljit_si delay_slot;
|
||||
sljit_si cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
sljit_si delay_slot;
|
||||
sljit_si cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
FILE* verbose;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
/* Local size passed to the functions. */
|
||||
sljit_si logical_local_size;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
int skip_checks;
|
||||
sljit_si skip_checks;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -275,22 +302,29 @@ struct sljit_compiler {
|
|||
/* Creates an sljit compiler.
|
||||
Returns NULL if failed. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void);
|
||||
/* Free everything except the codes. */
|
||||
|
||||
/* Free everything except the compiled machine code. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler);
|
||||
|
||||
static SLJIT_INLINE int sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; }
|
||||
/* Returns the current error code. If an error is occured, future sljit
|
||||
calls which uses the same compiler argument returns early with the same
|
||||
error code. Thus there is no need for checking the error after every
|
||||
call, it is enough to do it before the code is compiled. Removing
|
||||
these checks increases the performance of the compiling process. */
|
||||
static SLJIT_INLINE sljit_si sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; }
|
||||
|
||||
/*
|
||||
Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit,
|
||||
and <= 128 bytes on 64 bit architectures. The memory area is owned by the compiler,
|
||||
and freed by sljit_free_compiler. The returned pointer is sizeof(sljit_w) aligned.
|
||||
Excellent for allocating small blocks during the compiling, and no need to worry
|
||||
about freeing them. The size is enough to contain at most 16 pointers.
|
||||
If the size is outside of the range, the function will return with NULL,
|
||||
but this return value does not indicate that there is no more memory (does
|
||||
not set the compiler to out-of-memory status).
|
||||
and <= 128 bytes on 64 bit architectures. The memory area is owned by the
|
||||
compiler, and freed by sljit_free_compiler. The returned pointer is
|
||||
sizeof(sljit_sw) aligned. Excellent for allocating small blocks during
|
||||
the compiling, and no need to worry about freeing them. The size is
|
||||
enough to contain at most 16 pointers. If the size is outside of the range,
|
||||
the function will return with NULL. However, this return value does not
|
||||
indicate that there is no more memory (does not set the current error code
|
||||
of the compiler to out-of-memory status).
|
||||
*/
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_si size);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
/* Passing NULL disables verbose. */
|
||||
|
|
@ -301,15 +335,17 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code);
|
||||
|
||||
/*
|
||||
After the code generation we can retrieve the allocated executable memory size,
|
||||
although this area may not be fully filled with instructions depending on some
|
||||
optimizations. This function is useful only for statistical purposes.
|
||||
After the machine code generation is finished we can retrieve the allocated
|
||||
executable memory size, although this area may not be fully filled with
|
||||
instructions depending on some optimizations. This function is useful only
|
||||
for statistical purposes.
|
||||
|
||||
Before a successful code generation, this function returns with 0.
|
||||
*/
|
||||
static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; }
|
||||
|
||||
/* Instruction generation. Returns with error code. */
|
||||
/* Instruction generation. Returns with any error code. If there is no
|
||||
error, they return with SLJIT_SUCCESS. */
|
||||
|
||||
/*
|
||||
The executable code is basically a function call from the viewpoint of
|
||||
|
|
@ -320,8 +356,8 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
|
|||
for the executable code and moves function arguments to the saved
|
||||
registers. The number of arguments are specified in the "args"
|
||||
parameter and the first argument goes to SLJIT_SAVED_REG1, the second
|
||||
goes to SLJIT_SAVED_REG2 and so on. The number of temporary and
|
||||
saved registers are passed in "temporaries" and "saveds" arguments
|
||||
goes to SLJIT_SAVED_REG2 and so on. The number of scratch and
|
||||
saved registers are passed in "scratches" and "saveds" arguments
|
||||
respectively. Since the saved registers contains the arguments,
|
||||
"args" must be less or equal than "saveds". The sljit_emit_enter
|
||||
is also capable of allocating a stack space for local variables. The
|
||||
|
|
@ -332,54 +368,53 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
|
|||
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. */
|
||||
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 saveds, int local_size);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size);
|
||||
|
||||
/* 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.
|
||||
function below we can specify their 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_set_context(struct sljit_compiler *compiler,
|
||||
int args, int temporaries, int saveds, int local_size);
|
||||
sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size);
|
||||
|
||||
/* Return from machine code. The op argument can be SLJIT_UNUSED which means the
|
||||
function does not return with anything or any opcode between SLJIT_MOV and
|
||||
SLJIT_MOV_SI (see sljit_emit_op1). As for src and srcw they must be 0 if op
|
||||
SLJIT_MOV_P (see sljit_emit_op1). As for src and srcw they must be 0 if op
|
||||
is SLJIT_UNUSED, otherwise see below the description about source and
|
||||
destination arguments. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op,
|
||||
int src, sljit_w srcw);
|
||||
|
||||
/* Really fast calling method for utility functions inside sljit (see SLJIT_FAST_CALL).
|
||||
All registers and even the stack frame is passed to the callee. The return address is
|
||||
preserved in dst/dstw by sljit_emit_fast_enter, and sljit_emit_fast_return can
|
||||
use this as a return value later. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si src, sljit_sw srcw);
|
||||
|
||||
/* Note: only for sljit specific, non ABI compilant calls. Fast, since only a few machine instructions
|
||||
are needed. Excellent for small uility functions, where saving registers and setting up
|
||||
a new stack frame would cost too much performance. However, it is still possible to return
|
||||
to the address of the caller (or anywhere else). */
|
||||
/* Fast calling mechanism for utility functions (see SLJIT_FAST_CALL). All registers and
|
||||
even the stack frame is passed to the callee. The return address is preserved in
|
||||
dst/dstw by sljit_emit_fast_enter (the type of the value stored by this function
|
||||
is sljit_p), and sljit_emit_fast_return can use this as a return value later. */
|
||||
|
||||
/* Note: only for sljit specific, non ABI compilant calls. Fast, since only a few machine
|
||||
instructions are needed. Excellent for small uility functions, where saving registers
|
||||
and setting up a new stack frame would cost too much performance. However, it is still
|
||||
possible to return to the address of the caller (or anywhere else). */
|
||||
|
||||
/* Note: flags are not changed (unlike sljit_emit_enter / sljit_emit_return). */
|
||||
|
||||
/* Note: although sljit_emit_fast_return could be replaced by an ijump, it is not suggested,
|
||||
since many architectures do clever branch prediction on call / return instruction pairs. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size);
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw);
|
||||
|
||||
/*
|
||||
Source and destination values for arithmetical instructions
|
||||
|
|
@ -388,7 +423,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
|
|||
[imm] - absolute immediate memory address
|
||||
[reg+imm] - indirect memory address
|
||||
[reg+(reg<<imm)] - indirect indexed memory address (shift must be between 0 and 3)
|
||||
useful for (byte, half, int, sljit_w) array access
|
||||
useful for (byte, half, int, sljit_sw) array access
|
||||
(fully supported by both x86 and ARM architectures, and cheap operation on others)
|
||||
*/
|
||||
|
||||
|
|
@ -398,24 +433,40 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
|
|||
|
||||
length | alignment
|
||||
---------+-----------
|
||||
byte | 1 byte (not aligned)
|
||||
half | 2 byte (real_address & 0x1 == 0)
|
||||
int | 4 byte (real_address & 0x3 == 0)
|
||||
sljit_w | 4 byte if SLJIT_32BIT_ARCHITECTURE is defined and its value is 1
|
||||
byte | 1 byte (any physical_address is accepted)
|
||||
half | 2 byte (physical_address & 0x1 == 0)
|
||||
int | 4 byte (physical_address & 0x3 == 0)
|
||||
word | 4 byte if SLJIT_32BIT_ARCHITECTURE is defined and its value is 1
|
||||
| 8 byte if SLJIT_64BIT_ARCHITECTURE is defined and its value is 1
|
||||
pointer | size of sljit_p type (4 byte on 32 bit machines, 4 or 8 byte
|
||||
| on 64 bit machines)
|
||||
|
||||
Note: different architectures have different addressing limitations
|
||||
Thus sljit may generate several instructions for other addressing modes
|
||||
x86: all addressing modes supported, but write-back is not supported
|
||||
(requires an extra instruction). On x86-64 only 32 bit signed
|
||||
integers are supported by the architecture.
|
||||
arm: [reg+imm] supported for small immediates (-4095 <= imm <= 4095
|
||||
or -255 <= imm <= 255 for loading signed bytes, any halfs or doubles)
|
||||
[reg+(reg<<imm)] are supported or requires only two instructions
|
||||
Write back is limited to small immediates on thumb2
|
||||
ppc: [reg+imm], -65535 <= imm <= 65535. 64 bit moves requires immediates
|
||||
divisible by 4. [reg+reg] supported, write-back supported
|
||||
[reg+(reg<<imm)] (imm != 0) is cheap (requires two instructions)
|
||||
Note: Different architectures have different addressing limitations.
|
||||
A single instruction is enough for the following addressing
|
||||
modes. Other adrressing modes are emulated by instruction
|
||||
sequences. This information could help to improve those code
|
||||
generators which focuses only a few architectures.
|
||||
|
||||
x86: [reg+imm], -2^32+1 <= imm <= 2^32-1 (full adress space on x86-32)
|
||||
[reg+(reg<<imm)] is supported
|
||||
[imm], -2^32+1 <= imm <= 2^32-1 is supported
|
||||
Write-back is not supported
|
||||
arm: [reg+imm], -4095 <= imm <= 4095 or -255 <= imm <= 255 for signed
|
||||
bytes, any halfs or floating point values)
|
||||
[reg+(reg<<imm)] is supported
|
||||
Write-back is supported
|
||||
arm-t2: [reg+imm], -255 <= imm <= 4095
|
||||
[reg+(reg<<imm)] is supported
|
||||
Write back is supported only for [reg+imm], where -255 <= imm <= 255
|
||||
ppc: [reg+imm], -65536 <= imm <= 65535. 64 bit loads/stores and 32 bit
|
||||
signed load on 64 bit requires immediates divisible by 4.
|
||||
[reg+imm] is not supported for signed 8 bit values.
|
||||
[reg+reg] is supported
|
||||
Write-back is supported except for one instruction: 32 bit signed
|
||||
load with [reg+imm] addressing mode on 64 bit.
|
||||
mips: [reg+imm], -65536 <= imm <= 65535
|
||||
sparc: [reg+imm], -4096 <= imm <= 4095
|
||||
[reg+reg] is supported
|
||||
*/
|
||||
|
||||
/* Register output: simply the name of the register.
|
||||
|
|
@ -427,12 +478,31 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
|
|||
#define SLJIT_IMM 0x200
|
||||
|
||||
/* Set 32 bit operation mode (I) on 64 bit CPUs. The flag is totally ignored on
|
||||
32 bit CPUs. The arithmetic instruction uses only the lower 32 bit of the
|
||||
input register(s), and set the flags according to the 32 bit result. If the
|
||||
destination is a register, the higher 32 bit of the result is undefined.
|
||||
The addressing modes (SLJIT_MEM1/SLJIT_MEM2 macros) are unaffected by this flag. */
|
||||
32 bit CPUs. If this flag is set for an arithmetic operation, it uses only the
|
||||
lower 32 bit of the input register(s), and set the CPU status flags according
|
||||
to the 32 bit result. The higher 32 bits are undefined for both the input and
|
||||
output. However, the CPU might not ignore those higher 32 bits, like MIPS, which
|
||||
expects it to be the sign extension of the lower 32 bit. All 32 bit operations
|
||||
are undefined, if this condition is not fulfilled. Therefore, when SLJIT_INT_OP
|
||||
is specified, all register arguments must be the result of other operations with
|
||||
the same SLJIT_INT_OP flag. In other words, although a register can hold either
|
||||
a 64 or 32 bit value, these values cannot be mixed. The only exceptions are
|
||||
SLJIT_IMOV and SLJIT_IMOVU (SLJIT_MOV_SI/SLJIT_MOV_UI/SLJIT_MOVU_SI/SLJIT_MOV_UI
|
||||
with SLJIT_INT_OP flag) which can convert any source argument to SLJIT_INT_OP
|
||||
compatible result. This conversion might be unnecessary on some CPUs like x86-64,
|
||||
since the upper 32 bit is always ignored. In this case SLJIT is clever enough
|
||||
to not generate any instructions if the source and destination operands are the
|
||||
same registers. Affects sljit_emit_op0, sljit_emit_op1 and sljit_emit_op2. */
|
||||
#define SLJIT_INT_OP 0x100
|
||||
|
||||
/* Single precision mode (SP). This flag is similar to SLJIT_INT_OP, just
|
||||
it applies to floating point registers (it is even the same bit). When
|
||||
this flag is passed, the CPU performs single precision floating point
|
||||
operations. Similar to SLJIT_INT_OP, all register arguments must be the
|
||||
result of other floating point operations with this flag. Affects
|
||||
sljit_emit_fop1, sljit_emit_fop2 and sljit_emit_fcmp. */
|
||||
#define SLJIT_SINGLE_OP 0x100
|
||||
|
||||
/* Common CPU status flags for all architectures (x86, ARM, PPC)
|
||||
- carry flag
|
||||
- overflow flag
|
||||
|
|
@ -474,124 +544,165 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
|
|||
Note: may or may not cause an extra cycle wait
|
||||
it can even decrease the runtime in a few cases. */
|
||||
#define SLJIT_NOP 1
|
||||
/* Flags: may destroy flags
|
||||
Unsigned multiplication of SLJIT_TEMPORARY_REG1 and SLJIT_TEMPORARY_REG2.
|
||||
Result goes to SLJIT_TEMPORARY_REG2:SLJIT_TEMPORARY_REG1 (high:low) word */
|
||||
/* Flags: - (may destroy flags)
|
||||
Unsigned multiplication of SLJIT_SCRATCH_REG1 and SLJIT_SCRATCH_REG2.
|
||||
Result goes to SLJIT_SCRATCH_REG2:SLJIT_SCRATCH_REG1 (high:low) word */
|
||||
#define SLJIT_UMUL 2
|
||||
/* Flags: may destroy flags
|
||||
Signed multiplication of SLJIT_TEMPORARY_REG1 and SLJIT_TEMPORARY_REG2.
|
||||
Result goes to SLJIT_TEMPORARY_REG2:SLJIT_TEMPORARY_REG1 (high:low) word */
|
||||
/* Flags: - (may destroy flags)
|
||||
Signed multiplication of SLJIT_SCRATCH_REG1 and SLJIT_SCRATCH_REG2.
|
||||
Result goes to SLJIT_SCRATCH_REG2:SLJIT_SCRATCH_REG1 (high:low) word */
|
||||
#define SLJIT_SMUL 3
|
||||
/* Flags: I | may destroy flags
|
||||
Unsigned divide of the value in SLJIT_TEMPORARY_REG1 by the value in SLJIT_TEMPORARY_REG2.
|
||||
The result is placed in SLJIT_TEMPORARY_REG1 and the remainder goes to SLJIT_TEMPORARY_REG2.
|
||||
Note: if SLJIT_TEMPORARY_REG2 contains 0, the behaviour is undefined. */
|
||||
/* Flags: I - (may destroy flags)
|
||||
Unsigned divide of the value in SLJIT_SCRATCH_REG1 by the value in SLJIT_SCRATCH_REG2.
|
||||
The result is placed in SLJIT_SCRATCH_REG1 and the remainder goes to SLJIT_SCRATCH_REG2.
|
||||
Note: if SLJIT_SCRATCH_REG2 contains 0, the behaviour is undefined. */
|
||||
#define SLJIT_UDIV 4
|
||||
/* Flags: I | may destroy flags
|
||||
Signed divide of the value in SLJIT_TEMPORARY_REG1 by the value in SLJIT_TEMPORARY_REG2.
|
||||
The result is placed in SLJIT_TEMPORARY_REG1 and the remainder goes to SLJIT_TEMPORARY_REG2.
|
||||
Note: if SLJIT_TEMPORARY_REG2 contains 0, the behaviour is undefined. */
|
||||
#define SLJIT_IUDIV (SLJIT_UDIV | SLJIT_INT_OP)
|
||||
/* Flags: I - (may destroy flags)
|
||||
Signed divide of the value in SLJIT_SCRATCH_REG1 by the value in SLJIT_SCRATCH_REG2.
|
||||
The result is placed in SLJIT_SCRATCH_REG1 and the remainder goes to SLJIT_SCRATCH_REG2.
|
||||
Note: if SLJIT_SCRATCH_REG2 contains 0, the behaviour is undefined. */
|
||||
#define SLJIT_SDIV 5
|
||||
#define SLJIT_ISDIV (SLJIT_SDIV | SLJIT_INT_OP)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op);
|
||||
|
||||
/* Notes for MOV instructions:
|
||||
U = Mov with update (post form). If source or destination defined as SLJIT_MEM1(r1)
|
||||
or SLJIT_MEM2(r1, r2), r1 is increased by the sum of r2 and the constant argument
|
||||
UB = unsigned byte (8 bit)
|
||||
SB = signed byte (8 bit)
|
||||
UH = unsgined half (16 bit)
|
||||
SH = unsgined half (16 bit) */
|
||||
UH = unsigned half (16 bit)
|
||||
SH = signed half (16 bit)
|
||||
UI = unsigned int (32 bit)
|
||||
SI = signed int (32 bit)
|
||||
P = pointer (sljit_p) size */
|
||||
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV 6
|
||||
/* Flags: - (never set any flags) */
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOV_UB 7
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_IMOV_UB (SLJIT_MOV_UB | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOV_SB 8
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_IMOV_SB (SLJIT_MOV_SB | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOV_UH 9
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_IMOV_UH (SLJIT_MOV_UH | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOV_SH 10
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_IMOV_SH (SLJIT_MOV_SH | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags)
|
||||
Note: see SLJIT_INT_OP for further details. */
|
||||
#define SLJIT_MOV_UI 11
|
||||
/* Flags: - (never set any flags) */
|
||||
/* No SLJIT_INT_OP form, since it the same as SLJIT_IMOVU. */
|
||||
/* Flags: I - (never set any flags)
|
||||
Note: see SLJIT_INT_OP for further details. */
|
||||
#define SLJIT_MOV_SI 12
|
||||
#define SLJIT_IMOV (SLJIT_MOV_SI | SLJIT_INT_OP)
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU 13
|
||||
#define SLJIT_MOV_P 13
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_UB 14
|
||||
#define SLJIT_MOVU 14
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOVU_UB 15
|
||||
#define SLJIT_IMOVU_UB (SLJIT_MOVU_UB | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOVU_SB 16
|
||||
#define SLJIT_IMOVU_SB (SLJIT_MOVU_SB | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOVU_UH 17
|
||||
#define SLJIT_IMOVU_UH (SLJIT_MOVU_UH | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOVU_SH 18
|
||||
#define SLJIT_IMOVU_SH (SLJIT_MOVU_SH | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags)
|
||||
Note: see SLJIT_INT_OP for further details. */
|
||||
#define SLJIT_MOVU_UI 19
|
||||
/* No SLJIT_INT_OP form, since it the same as SLJIT_IMOVU. */
|
||||
/* Flags: I - (never set any flags)
|
||||
Note: see SLJIT_INT_OP for further details. */
|
||||
#define SLJIT_MOVU_SI 20
|
||||
#define SLJIT_IMOVU (SLJIT_MOVU_SI | SLJIT_INT_OP)
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_SB 15
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_UH 16
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_SH 17
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_UI 18
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_SI 19
|
||||
#define SLJIT_MOVU_P 21
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_NOT 20
|
||||
#define SLJIT_NOT 22
|
||||
#define SLJIT_INOT (SLJIT_NOT | SLJIT_INT_OP)
|
||||
/* Flags: I | E | O | K */
|
||||
#define SLJIT_NEG 21
|
||||
#define SLJIT_NEG 23
|
||||
#define SLJIT_INEG (SLJIT_NEG | SLJIT_INT_OP)
|
||||
/* Count leading zeroes
|
||||
Flags: I | E | K */
|
||||
#define SLJIT_CLZ 22
|
||||
Flags: I | E | K
|
||||
Important note! Sparc 32 does not support K flag, since
|
||||
the required popc instruction is introduced only in sparc 64. */
|
||||
#define SLJIT_CLZ 24
|
||||
#define SLJIT_ICLZ (SLJIT_CLZ | SLJIT_INT_OP)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src, sljit_w srcw);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw);
|
||||
|
||||
/* Flags: I | E | O | C | K */
|
||||
#define SLJIT_ADD 23
|
||||
#define SLJIT_ADD 25
|
||||
#define SLJIT_IADD (SLJIT_ADD | SLJIT_INT_OP)
|
||||
/* Flags: I | C | K */
|
||||
#define SLJIT_ADDC 24
|
||||
#define SLJIT_ADDC 26
|
||||
#define SLJIT_IADDC (SLJIT_ADDC | SLJIT_INT_OP)
|
||||
/* Flags: I | E | S | U | O | C | K */
|
||||
#define SLJIT_SUB 25
|
||||
#define SLJIT_SUB 27
|
||||
#define SLJIT_ISUB (SLJIT_SUB | SLJIT_INT_OP)
|
||||
/* Flags: I | C | K */
|
||||
#define SLJIT_SUBC 26
|
||||
#define SLJIT_SUBC 28
|
||||
#define SLJIT_ISUBC (SLJIT_SUBC | SLJIT_INT_OP)
|
||||
/* Note: integer mul
|
||||
Flags: I | O (see SLJIT_C_MUL_*) | K */
|
||||
#define SLJIT_MUL 27
|
||||
#define SLJIT_MUL 29
|
||||
#define SLJIT_IMUL (SLJIT_MUL | SLJIT_INT_OP)
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_AND 28
|
||||
#define SLJIT_AND 30
|
||||
#define SLJIT_IAND (SLJIT_AND | SLJIT_INT_OP)
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_OR 29
|
||||
#define SLJIT_OR 31
|
||||
#define SLJIT_IOR (SLJIT_OR | SLJIT_INT_OP)
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_XOR 30
|
||||
#define SLJIT_XOR 32
|
||||
#define SLJIT_IXOR (SLJIT_XOR | SLJIT_INT_OP)
|
||||
/* 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
|
||||
#define SLJIT_SHL 33
|
||||
#define SLJIT_ISHL (SLJIT_SHL | SLJIT_INT_OP)
|
||||
/* 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
|
||||
#define SLJIT_LSHR 34
|
||||
#define SLJIT_ILSHR (SLJIT_LSHR | SLJIT_INT_OP)
|
||||
/* 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
|
||||
#define SLJIT_ASHR 35
|
||||
#define SLJIT_IASHR (SLJIT_ASHR | SLJIT_INT_OP)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w);
|
||||
|
||||
/* The following function is a helper function for sljit_emit_op_custom.
|
||||
It returns with the real machine register index of any SLJIT_TEMPORARY
|
||||
It returns with the real machine register index of any SLJIT_SCRATCH
|
||||
SLJIT_SAVED or SLJIT_LOCALS register.
|
||||
Note: it returns with -1 for virtual registers (all EREGs on x86-32).
|
||||
Note: register returned by SLJIT_LOCALS_REG is not necessary the real
|
||||
stack pointer register of the target architecture. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg);
|
||||
|
||||
/* Any instruction can be inserted into the instruction stream by
|
||||
sljit_emit_op_custom. It has a similar purpose as inline assembly.
|
||||
|
|
@ -603,42 +714,50 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg);
|
|||
if size == 4, the instruction argument must be 4 byte aligned.
|
||||
Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, int size);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, sljit_si size);
|
||||
|
||||
/* Returns with non-zero if fpu is available. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void);
|
||||
|
||||
/* Note: dst is the left and src is the right operand for SLJIT_FCMP.
|
||||
Note: NaN check is always performed. If SLJIT_C_FLOAT_NAN is set,
|
||||
Note: NaN check is always performed. If SLJIT_C_FLOAT_UNORDERED is set,
|
||||
the comparison result is unpredictable.
|
||||
Flags: E | S (see SLJIT_C_FLOAT_*) */
|
||||
#define SLJIT_FCMP 34
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FMOV 35
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FNEG 36
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FABS 37
|
||||
Flags: SP | E | S (see SLJIT_C_FLOAT_*) */
|
||||
#define SLJIT_CMPD 36
|
||||
#define SLJIT_CMPS (SLJIT_CMPD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_MOVD 37
|
||||
#define SLJIT_MOVS (SLJIT_MOVD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_NEGD 38
|
||||
#define SLJIT_NEGS (SLJIT_NEGD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_ABSD 39
|
||||
#define SLJIT_ABSS (SLJIT_ABSD | SLJIT_SINGLE_OP)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src, sljit_w srcw);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw);
|
||||
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FADD 38
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FSUB 39
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FMUL 40
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FDIV 41
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_ADDD 40
|
||||
#define SLJIT_ADDS (SLJIT_ADDD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_SUBD 41
|
||||
#define SLJIT_SUBS (SLJIT_SUBD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_MULD 42
|
||||
#define SLJIT_MULS (SLJIT_MULD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_DIVD 43
|
||||
#define SLJIT_DIVS (SLJIT_DIVD | SLJIT_SINGLE_OP)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w);
|
||||
|
||||
/* Label and jump instructions. */
|
||||
|
||||
|
|
@ -671,8 +790,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
|
|||
#define SLJIT_C_FLOAT_GREATER_EQUAL 17
|
||||
#define SLJIT_C_FLOAT_GREATER 18
|
||||
#define SLJIT_C_FLOAT_LESS_EQUAL 19
|
||||
#define SLJIT_C_FLOAT_NAN 20
|
||||
#define SLJIT_C_FLOAT_NOT_NAN 21
|
||||
#define SLJIT_C_FLOAT_UNORDERED 20
|
||||
#define SLJIT_C_FLOAT_ORDERED 21
|
||||
|
||||
#define SLJIT_JUMP 22
|
||||
#define SLJIT_FAST_CALL 23
|
||||
|
|
@ -691,7 +810,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
|
|||
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
|
||||
Flags: - (never set any flags) for both conditional and unconditional jumps.
|
||||
Flags: destroy all flags for calls. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type);
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type);
|
||||
|
||||
/* Basic arithmetic comparison. In most architectures it is implemented as
|
||||
an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting
|
||||
|
|
@ -701,23 +820,23 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
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. */
|
||||
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);
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw 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
|
||||
type must be between SLJIT_C_FLOAT_EQUAL and SLJIT_C_FLOAT_ORDERED
|
||||
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and SLJIT_SINGLE_OP
|
||||
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);
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw 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);
|
||||
|
|
@ -731,25 +850,38 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
|
|||
Indirect form: any other valid addressing mode
|
||||
Flags: - (never set any flags) for unconditional jumps.
|
||||
Flags: destroy all flags for calls. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw);
|
||||
|
||||
/* If op == SLJIT_MOV:
|
||||
Set dst to 1 if condition is fulfilled, 0 otherwise
|
||||
type must be between SLJIT_C_EQUAL and SLJIT_C_FLOAT_NOT_NAN
|
||||
/* Perform the operation using the conditional flags as the second argument.
|
||||
Type must always be between SLJIT_C_EQUAL and SLJIT_C_FLOAT_ORDERED. The
|
||||
value represented by the type is 1, if the condition represented by the type
|
||||
is fulfilled, and 0 otherwise.
|
||||
|
||||
If op == SLJIT_MOV, SLJIT_MOV_SI, SLJIT_MOV_UI:
|
||||
Set dst to the value represented by the type (0 or 1).
|
||||
Src must be SLJIT_UNUSED, and srcw must be 0
|
||||
Flags: - (never set any flags)
|
||||
If op == SLJIT_OR
|
||||
Dst is used as src as well, and set its lowest bit to 1 if
|
||||
the condition is fulfilled. Otherwise it does nothing.
|
||||
Flags: E | K
|
||||
Note: sljit_emit_cond_value does nothing, if dst is SLJIT_UNUSED (regardless of op). */
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type);
|
||||
If op == SLJIT_OR, op == SLJIT_AND, op == SLJIT_XOR
|
||||
Performs the binary operation using src as the first, and the value
|
||||
represented by type as the second argument.
|
||||
Important note: only dst=src and dstw=srcw is supported at the moment!
|
||||
Flags: I | E | K
|
||||
Note: sljit_emit_op_flags does nothing, if dst is SLJIT_UNUSED (regardless of op). */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw,
|
||||
sljit_si type);
|
||||
|
||||
/* Copies the base address of SLJIT_LOCALS_REG+offset to dst.
|
||||
Flags: - (never set any flags) */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset);
|
||||
|
||||
/* The constant can be changed runtime (see: sljit_set_const)
|
||||
Flags: - (never set any flags) */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value);
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value);
|
||||
|
||||
/* After the code generation the address for label, jump and const instructions
|
||||
are computed. Since these structures are freed sljit_free_compiler, the
|
||||
are computed. Since these structures are freed by sljit_free_compiler, the
|
||||
addresses must be preserved by the user program elsewere. */
|
||||
static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->addr; }
|
||||
static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; }
|
||||
|
|
@ -757,22 +889,22 @@ static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) {
|
|||
|
||||
/* Only the address is required to rewrite the code. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant);
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Miscellaneous utility functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#define SLJIT_MAJOR_VERSION 0
|
||||
#define SLJIT_MINOR_VERSION 87
|
||||
#define SLJIT_MINOR_VERSION 90
|
||||
|
||||
/* Get the human readable name of the platfrom.
|
||||
Can be useful for debugging on platforms like ARM, where ARM and
|
||||
Thumb2 functions can be mixed. */
|
||||
/* Get the human readable name of the platform. Can be useful on platforms
|
||||
like ARM, where ARM and Thumb2 functions can be mixed, and
|
||||
it is useful to know the type of the code generator. */
|
||||
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)
|
||||
/* Portable helper function to get an offset of a member. */
|
||||
#define SLJIT_OFFSETOF(base, member) ((sljit_sw)(&((base*)0x10)->member) - 0x10)
|
||||
|
||||
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
/* This global lock is useful to compile common functions. */
|
||||
|
|
@ -821,32 +953,32 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* st
|
|||
since the growth ratio can be added to the current limit, and sljit_stack_resize
|
||||
will do all the necessary checks. The fields of the stack are not changed if
|
||||
sljit_stack_resize fails. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit);
|
||||
|
||||
#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */
|
||||
|
||||
#if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
|
||||
|
||||
/* Get the entry address of a given function. */
|
||||
#define SLJIT_FUNC_OFFSET(func_name) ((sljit_w)func_name)
|
||||
#define SLJIT_FUNC_OFFSET(func_name) ((sljit_sw)func_name)
|
||||
|
||||
#else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
|
||||
|
||||
/* All JIT related code should be placed in the same context (library, binary, etc.). */
|
||||
|
||||
#define SLJIT_FUNC_OFFSET(func_name) ((sljit_w)*(void**)func_name)
|
||||
#define SLJIT_FUNC_OFFSET(func_name) (*(sljit_sw*)(void*)func_name)
|
||||
|
||||
/* For powerpc64, the function pointers point to a context descriptor. */
|
||||
struct sljit_function_context {
|
||||
sljit_w addr;
|
||||
sljit_w r2;
|
||||
sljit_w r11;
|
||||
sljit_sw addr;
|
||||
sljit_sw r2;
|
||||
sljit_sw r11;
|
||||
};
|
||||
|
||||
/* Fill the context arguments using the addr and the function.
|
||||
If func_ptr is NULL, it will not be set to the address of context
|
||||
If addr is NULL, the function address also comes from the func pointer. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_w addr, void* func);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func);
|
||||
|
||||
#endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
/* mips 32-bit arch dependent functions. */
|
||||
|
||||
static int load_immediate(struct sljit_compiler *compiler, int dst_ar, sljit_w imm)
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
|
||||
{
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
|
@ -66,12 +66,92 @@ static int load_immediate(struct sljit_compiler *compiler, int dst_ar, sljit_w i
|
|||
FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
|
||||
int dst, int src1, sljit_w src2)
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_sw src2)
|
||||
{
|
||||
int overflow_ra = 0;
|
||||
sljit_si overflow_ra = 0;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB) {
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
|
||||
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
|
||||
#endif
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH) {
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
|
||||
#endif
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
|
||||
#else
|
||||
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
|
||||
FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
|
||||
return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
|
||||
}
|
||||
/* Nearly all instructions are unmovable in the following sequence. */
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
/* Check zero. */
|
||||
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | SA(0) | T(dst) | IMM(-1), DR(dst)));
|
||||
/* Loop for searching the highest bit. */
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(dst) | T(dst) | IMM(1), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
|
||||
if (op & SLJIT_SET_E)
|
||||
return push_inst(compiler, ADDU_W | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
|
|
@ -293,97 +373,16 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
|||
case SLJIT_ASHR:
|
||||
EMIT_SHIFT(SRA, SRAV);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB) {
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
|
||||
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
|
||||
#endif
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH) {
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
|
||||
#endif
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
|
||||
#else
|
||||
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
|
||||
FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
|
||||
return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
|
||||
}
|
||||
/* Nearly all instructions are unmovable in the following sequence. */
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
/* Check zero. */
|
||||
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(6), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
|
||||
/* Check sign bit. */
|
||||
FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG1) | IMM(4), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(0), UNMOVABLE_INS));
|
||||
/* Loop for searching the highest bit. */
|
||||
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(dst) | T(dst) | IMM(1), UNMOVABLE_INS));
|
||||
if (op & SLJIT_SET_E)
|
||||
return push_inst(compiler, ADDU_W | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, LUI | T(reg) | IMM(init_value >> 16), DR(reg)));
|
||||
return push_inst(compiler, ORI | S(reg) | T(reg) | IMM(init_value), DR(reg));
|
||||
FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));
|
||||
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
|
|
@ -395,7 +394,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ad
|
|||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
/* ppc 32-bit arch dependent functions. */
|
||||
|
||||
static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
|
||||
{
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
|
||||
|
|
@ -41,10 +41,59 @@ static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
|
|||
#define INS_CLEAR_LEFT(dst, src, from) \
|
||||
(RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1))
|
||||
|
||||
static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
|
||||
int dst, int src1, int src2)
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_si src2)
|
||||
{
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
|
||||
}
|
||||
else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH)
|
||||
return push_inst(compiler, EXTSH | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_NEG:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
|
|
@ -71,7 +120,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
|||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | S(0)));
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, MTXER | S(0));
|
||||
}
|
||||
|
|
@ -106,7 +155,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
|||
|
||||
case SLJIT_SUBC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | S(0)));
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
|
||||
return push_inst(compiler, MTXER | S(0));
|
||||
}
|
||||
|
|
@ -179,65 +228,23 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
|||
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_ASHR:
|
||||
if (flags & ALT_FORM3)
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
compiler->imm &= 0x1f;
|
||||
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
|
||||
FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
|
||||
}
|
||||
return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
|
||||
}
|
||||
else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH)
|
||||
return push_inst(compiler, EXTSH | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_NEG:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)));
|
||||
return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
|
||||
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
|
||||
|
|
@ -252,7 +259,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ad
|
|||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,9 +26,11 @@
|
|||
|
||||
/* ppc 64-bit arch dependent functions. */
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
|
||||
#define ASM_SLJIT_CLZ(src, dst) \
|
||||
asm volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
|
||||
__asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
|
||||
#elif defined(__xlc__)
|
||||
#error "Please enable GCC syntax for inline assembly statements"
|
||||
#else
|
||||
#error "Must implement count leading zeroes"
|
||||
#endif
|
||||
|
|
@ -39,7 +41,7 @@
|
|||
#define PUSH_RLDICR(reg, shift) \
|
||||
push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))
|
||||
|
||||
static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
|
||||
{
|
||||
sljit_uw tmp;
|
||||
sljit_uw shift;
|
||||
|
|
@ -143,10 +145,74 @@ static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
|
|||
src1 = TMP_REG1; \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
|
||||
int dst, int src1, int src2)
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_si src2)
|
||||
{
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SI)
|
||||
return push_inst(compiler, EXTSW | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0));
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
|
||||
}
|
||||
else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH)
|
||||
return push_inst(compiler, EXTSH | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
UN_EXTS();
|
||||
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_NEG:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
UN_EXTS();
|
||||
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (flags & ALT_FORM1)
|
||||
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
|
||||
return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst));
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
|
|
@ -175,7 +241,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
|||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | S(0)));
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, MTXER | S(0));
|
||||
}
|
||||
|
|
@ -212,7 +278,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
|||
|
||||
case SLJIT_SUBC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | S(0)));
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
|
||||
return push_inst(compiler, MTXER | S(0));
|
||||
}
|
||||
|
|
@ -284,9 +350,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
|||
return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags));
|
||||
}
|
||||
}
|
||||
if (flags & ALT_FORM2)
|
||||
return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
return push_inst(compiler, SLD | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_LSHR:
|
||||
if (flags & ALT_FORM1) {
|
||||
|
|
@ -300,92 +364,32 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
|||
return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags));
|
||||
}
|
||||
}
|
||||
if (flags & ALT_FORM2)
|
||||
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
return push_inst(compiler, SRD | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_ASHR:
|
||||
if (flags & ALT_FORM3)
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
if (flags & ALT_FORM2) {
|
||||
compiler->imm &= 0x1f;
|
||||
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
|
||||
FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
|
||||
}
|
||||
else {
|
||||
compiler->imm &= 0x3f;
|
||||
return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4));
|
||||
FAIL_IF(push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4)));
|
||||
}
|
||||
}
|
||||
if (flags & ALT_FORM2)
|
||||
return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
return push_inst(compiler, SRAD | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_MOV:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SI)
|
||||
return push_inst(compiler, EXTSW | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
|
||||
}
|
||||
else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH)
|
||||
return push_inst(compiler, EXTSH | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
UN_EXTS();
|
||||
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_NEG:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
UN_EXTS();
|
||||
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (flags & ALT_FORM1)
|
||||
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
|
||||
return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2)));
|
||||
return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));
|
||||
|
|
@ -405,7 +409,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ad
|
|||
SLJIT_CACHE_FLUSH(inst, inst + 5);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
|
|
@ -415,14 +419,3 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constan
|
|||
inst[4] = (inst[4] & 0xffff0000) | (new_constant & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 5);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_w addr, void* func)
|
||||
{
|
||||
sljit_w* ptrs;
|
||||
if (func_ptr)
|
||||
*func_ptr = (void*)context;
|
||||
ptrs = (sljit_w*)func;
|
||||
context->addr = addr ? addr : ptrs[0];
|
||||
context->r2 = ptrs[1];
|
||||
context->r11 = ptrs[2];
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sljit_sw imm)
|
||||
{
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, OR | D(dst) | S1(0) | IMM(imm), DR(dst));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((imm >> 10) & 0x3fffff), DR(dst)));
|
||||
return (imm & 0x3ff) ? push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (imm & 0x3ff), DR(dst)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#define ARG2(flags, src2) ((flags & SRC2_IMM) ? IMM(src2) : S2(src2))
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_sw src2)
|
||||
{
|
||||
SLJIT_COMPILE_ASSERT(ICC_IS_SET == SET_FLAGS, icc_is_set_and_set_flags_must_be_the_same);
|
||||
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, OR | D(dst) | S1(0) | S2(src2), DR(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_UB)
|
||||
return push_inst(compiler, AND | D(dst) | S1(src2) | IMM(0xff), DR(dst));
|
||||
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(24), DR(dst)));
|
||||
return push_inst(compiler, SRA | D(dst) | S1(dst) | IMM(24), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(16), DR(dst)));
|
||||
return push_inst(compiler, (op == SLJIT_MOV_SH ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
return push_inst(compiler, XNOR | (flags & SET_FLAGS) | D(dst) | S1(0) | S2(src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
/* sparc 32 does not support SLJIT_KEEP_FLAGS. Not sure I can fix this. */
|
||||
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS));
|
||||
FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS | (flags & SET_FLAGS)));
|
||||
FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst)));
|
||||
|
||||
/* Loop. */
|
||||
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS));
|
||||
FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS));
|
||||
return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_ADD:
|
||||
return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_ADDC:
|
||||
return push_inst(compiler, ADDC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_SUB:
|
||||
return push_inst(compiler, SUB | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_SUBC:
|
||||
return push_inst(compiler, SUBC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_MUL:
|
||||
FAIL_IF(push_inst(compiler, SMUL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
if (!(flags & SET_FLAGS))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(dst) | IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, RDY | D(TMP_REG4), DR(TMP_REG4)));
|
||||
return push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(TMP_REG4), MOVABLE_INS | SET_FLAGS);
|
||||
|
||||
case SLJIT_AND:
|
||||
return push_inst(compiler, AND | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_OR:
|
||||
return push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_XOR:
|
||||
return push_inst(compiler, XOR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_SHL:
|
||||
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
|
||||
|
||||
case SLJIT_LSHR:
|
||||
FAIL_IF(push_inst(compiler, SRL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
|
||||
|
||||
case SLJIT_ASHR:
|
||||
FAIL_IF(push_inst(compiler, SRA | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((init_value >> 10) & 0x3fffff), DR(dst)));
|
||||
return push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (init_value & 0x3ff), DR(dst));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffc00000) | ((new_addr >> 10) & 0x3fffff);
|
||||
inst[1] = (inst[1] & 0xfffffc00) | (new_addr & 0x3ff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffc00000) | ((new_constant >> 10) & 0x3fffff);
|
||||
inst[1] = (inst[1] & 0xfffffc00) | (new_constant & 0x3ff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -26,30 +26,30 @@
|
|||
|
||||
/* x86 32-bit arch dependent functions. */
|
||||
|
||||
static int emit_do_imm(struct sljit_compiler *compiler, sljit_ub opcode, sljit_w imm)
|
||||
static sljit_si emit_do_imm(struct sljit_compiler *compiler, sljit_ub opcode, sljit_sw imm)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *inst;
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_w));
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(1 + sizeof(sljit_w));
|
||||
*buf++ = opcode;
|
||||
*(sljit_w*)buf = imm;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1 + sizeof(sljit_sw));
|
||||
*inst++ = opcode;
|
||||
*(sljit_sw*)inst = imm;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type)
|
||||
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type)
|
||||
{
|
||||
if (type == SLJIT_JUMP) {
|
||||
*code_ptr++ = 0xe9;
|
||||
*code_ptr++ = JMP_i32;
|
||||
jump->addr++;
|
||||
}
|
||||
else if (type >= SLJIT_FAST_CALL) {
|
||||
*code_ptr++ = 0xe8;
|
||||
*code_ptr++ = CALL_i32;
|
||||
jump->addr++;
|
||||
}
|
||||
else {
|
||||
*code_ptr++ = 0x0f;
|
||||
*code_ptr++ = GROUP_0F;
|
||||
*code_ptr++ = get_jump_code(type);
|
||||
jump->addr += 2;
|
||||
}
|
||||
|
|
@ -57,39 +57,43 @@ static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_
|
|||
if (jump->flags & JUMP_LABEL)
|
||||
jump->flags |= PATCH_MW;
|
||||
else
|
||||
*(sljit_w*)code_ptr = jump->u.target - (jump->addr + 4);
|
||||
*(sljit_sw*)code_ptr = jump->u.target - (jump->addr + 4);
|
||||
code_ptr += 4;
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
{
|
||||
int size;
|
||||
sljit_ub *buf;
|
||||
sljit_si size;
|
||||
sljit_si locals_offset;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
|
||||
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->args = args;
|
||||
compiler->flags_saved = 0;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
|
||||
#else
|
||||
size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (2 + args * 3) : 0);
|
||||
#endif
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
PUSH_REG(reg_map[TMP_REGISTER]);
|
||||
#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (args > 0) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc4 | (reg_map[TMP_REGISTER] << 3);
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[TMP_REGISTER] << 3) | 0x4 /* esp */;
|
||||
}
|
||||
#endif
|
||||
if (saveds > 2)
|
||||
|
|
@ -101,81 +105,105 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
|||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (args > 0) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[SLJIT_TEMPORARY_REG3];
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[SLJIT_SCRATCH_REG3];
|
||||
}
|
||||
if (args > 1) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[SLJIT_TEMPORARY_REG2];
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[SLJIT_SCRATCH_REG2];
|
||||
}
|
||||
if (args > 2) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0x44 | (reg_map[SLJIT_SAVED_REG3] << 3);
|
||||
*buf++ = 0x24;
|
||||
*buf++ = sizeof(sljit_w) * (3 + 2); /* saveds >= 3 as well. */
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x4 /* esp */;
|
||||
*inst++ = 0x24;
|
||||
*inst++ = sizeof(sljit_sw) * (3 + 2); /* saveds >= 3 as well. */
|
||||
}
|
||||
#else
|
||||
if (args > 0) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REGISTER];
|
||||
*buf++ = sizeof(sljit_w) * 2;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REGISTER];
|
||||
*inst++ = sizeof(sljit_sw) * 2;
|
||||
}
|
||||
if (args > 1) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REGISTER];
|
||||
*buf++ = sizeof(sljit_w) * 3;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REGISTER];
|
||||
*inst++ = sizeof(sljit_sw) * 3;
|
||||
}
|
||||
if (args > 2) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REGISTER];
|
||||
*buf++ = sizeof(sljit_w) * 4;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REGISTER];
|
||||
*inst++ = sizeof(sljit_sw) * 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
|
||||
compiler->temporaries_start = local_size;
|
||||
if (temporaries > 3)
|
||||
local_size += (temporaries - 3) * sizeof(sljit_uw);
|
||||
compiler->saveds_start = local_size;
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
locals_offset = 2 * sizeof(sljit_uw);
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(FIXED_LOCALS_OFFSET >= 2 * sizeof(sljit_uw), require_at_least_two_words);
|
||||
locals_offset = FIXED_LOCALS_OFFSET;
|
||||
#endif
|
||||
compiler->scratches_start = locals_offset;
|
||||
if (scratches > 3)
|
||||
locals_offset += (scratches - 3) * sizeof(sljit_uw);
|
||||
compiler->saveds_start = locals_offset;
|
||||
if (saveds > 3)
|
||||
local_size += (saveds - 3) * sizeof(sljit_uw);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (local_size > 1024) {
|
||||
FAIL_IF(emit_do_imm(compiler, 0xb8 + reg_map[SLJIT_TEMPORARY_REG1], local_size));
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_touch_stack)));
|
||||
}
|
||||
#endif
|
||||
locals_offset += (saveds - 3) * sizeof(sljit_uw);
|
||||
compiler->locals_offset = locals_offset;
|
||||
local_size = locals_offset + ((local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1));
|
||||
|
||||
compiler->local_size = local_size;
|
||||
if (local_size > 0)
|
||||
return emit_non_cum_binary(compiler, 0x2b, 0x29, 0x5 << 3, 0x2d,
|
||||
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size);
|
||||
#ifdef _WIN32
|
||||
if (local_size > 1024) {
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_SCRATCH_REG1], local_size));
|
||||
#else
|
||||
local_size -= FIXED_LOCALS_OFFSET;
|
||||
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_SCRATCH_REG1], local_size));
|
||||
FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
|
||||
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, FIXED_LOCALS_OFFSET));
|
||||
#endif
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
|
||||
}
|
||||
#endif
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
SLJIT_ASSERT(local_size > 0);
|
||||
return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
|
||||
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
{
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
|
||||
sljit_si locals_offset;
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
|
||||
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->args = args;
|
||||
compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
|
||||
compiler->temporaries_start = compiler->local_size;
|
||||
if (temporaries > 3)
|
||||
compiler->local_size += (temporaries - 3) * sizeof(sljit_uw);
|
||||
compiler->saveds_start = compiler->local_size;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
locals_offset = 2 * sizeof(sljit_uw);
|
||||
#else
|
||||
locals_offset = FIXED_LOCALS_OFFSET;
|
||||
#endif
|
||||
compiler->scratches_start = locals_offset;
|
||||
if (scratches > 3)
|
||||
locals_offset += (scratches - 3) * sizeof(sljit_uw);
|
||||
compiler->saveds_start = locals_offset;
|
||||
if (saveds > 3)
|
||||
compiler->local_size += (saveds - 3) * sizeof(sljit_uw);
|
||||
locals_offset += (saveds - 3) * sizeof(sljit_uw);
|
||||
compiler->locals_offset = locals_offset;
|
||||
compiler->local_size = locals_offset + ((local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
int size;
|
||||
sljit_ub *buf;
|
||||
sljit_si size;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, op, src, srcw);
|
||||
|
|
@ -184,9 +212,9 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
|||
compiler->flags_saved = 0;
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
if (compiler->local_size > 0)
|
||||
FAIL_IF(emit_cum_binary(compiler, 0x03, 0x01, 0x0 << 3, 0x05,
|
||||
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size));
|
||||
SLJIT_ASSERT(compiler->local_size > 0);
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size));
|
||||
|
||||
size = 2 + (compiler->saveds <= 3 ? compiler->saveds : 3);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
|
|
@ -196,8 +224,8 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
|||
if (compiler->args > 0)
|
||||
size += 2;
|
||||
#endif
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
|
||||
|
|
@ -210,14 +238,11 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
|||
POP_REG(reg_map[TMP_REGISTER]);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (compiler->args > 2)
|
||||
RETN(sizeof(sljit_w));
|
||||
RET_I16(sizeof(sljit_sw));
|
||||
else
|
||||
RET();
|
||||
#else
|
||||
if (compiler->args > 0)
|
||||
RETN(compiler->args * sizeof(sljit_w));
|
||||
else
|
||||
RET();
|
||||
RET();
|
||||
#endif
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
|
|
@ -228,16 +253,16 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
|||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Size contains the flags as well. */
|
||||
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
||||
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size,
|
||||
/* The register or immediate operand. */
|
||||
int a, sljit_w imma,
|
||||
sljit_si a, sljit_sw imma,
|
||||
/* The general operand (not immediate). */
|
||||
int b, sljit_w immb)
|
||||
sljit_si b, sljit_sw immb)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *inst;
|
||||
sljit_ub *buf_ptr;
|
||||
int flags = size & ~0xf;
|
||||
int inst_size;
|
||||
sljit_si flags = size & ~0xf;
|
||||
sljit_si inst_size;
|
||||
|
||||
/* Both cannot be switched on. */
|
||||
SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
|
||||
|
|
@ -248,13 +273,16 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
/* SSE2 and immediate is not possible. */
|
||||
SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
|
||||
SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
|
||||
&& (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
|
||||
&& (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
|
||||
#endif
|
||||
|
||||
size &= 0xf;
|
||||
inst_size = size;
|
||||
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (flags & EX86_PREF_F2)
|
||||
if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
|
||||
inst_size++;
|
||||
#endif
|
||||
if (flags & EX86_PREF_66)
|
||||
|
|
@ -264,13 +292,13 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
inst_size += 1; /* mod r/m byte. */
|
||||
if (b & SLJIT_MEM) {
|
||||
if ((b & 0x0f) == SLJIT_UNUSED)
|
||||
inst_size += sizeof(sljit_w);
|
||||
inst_size += sizeof(sljit_sw);
|
||||
else if (immb != 0 && !(b & 0xf0)) {
|
||||
/* Immediate operand. */
|
||||
if (immb <= 127 && immb >= -128)
|
||||
inst_size += sizeof(sljit_b);
|
||||
inst_size += sizeof(sljit_sb);
|
||||
else
|
||||
inst_size += sizeof(sljit_w);
|
||||
inst_size += sizeof(sljit_sw);
|
||||
}
|
||||
|
||||
if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
|
||||
|
|
@ -300,29 +328,31 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
else if (flags & EX86_HALF_ARG)
|
||||
inst_size += sizeof(short);
|
||||
else
|
||||
inst_size += sizeof(sljit_w);
|
||||
inst_size += sizeof(sljit_sw);
|
||||
}
|
||||
else
|
||||
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
|
||||
PTR_FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
|
||||
PTR_FAIL_IF(!inst);
|
||||
|
||||
/* Encoding the byte. */
|
||||
INC_SIZE(inst_size);
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (flags & EX86_PREF_F2)
|
||||
*buf++ = 0xf2;
|
||||
*inst++ = 0xf2;
|
||||
if (flags & EX86_PREF_F3)
|
||||
*inst++ = 0xf3;
|
||||
#endif
|
||||
if (flags & EX86_PREF_66)
|
||||
*buf++ = 0x66;
|
||||
*inst++ = 0x66;
|
||||
|
||||
buf_ptr = buf + size;
|
||||
buf_ptr = inst + size;
|
||||
|
||||
/* Encode mod/rm byte. */
|
||||
if (!(flags & EX86_SHIFT_INS)) {
|
||||
if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
|
||||
*buf = (flags & EX86_BYTE_ARG) ? 0x83 : 0x81;
|
||||
*inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
|
||||
|
||||
if ((a & SLJIT_IMM) || (a == 0))
|
||||
*buf_ptr = 0;
|
||||
|
|
@ -339,19 +369,19 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
else {
|
||||
if (a & SLJIT_IMM) {
|
||||
if (imma == 1)
|
||||
*buf = 0xd1;
|
||||
*inst = GROUP_SHIFT_1;
|
||||
else
|
||||
*buf = 0xc1;
|
||||
*inst = GROUP_SHIFT_N;
|
||||
} else
|
||||
*buf = 0xd3;
|
||||
*inst = GROUP_SHIFT_CL;
|
||||
*buf_ptr = 0;
|
||||
}
|
||||
|
||||
if (!(b & SLJIT_MEM))
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
*buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_map[b] : b);
|
||||
*buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2)) ? reg_map[b] : b);
|
||||
#else
|
||||
*buf_ptr++ |= 0xc0 + reg_map[b];
|
||||
*buf_ptr++ |= MOD_REG + reg_map[b];
|
||||
#endif
|
||||
else if ((b & 0x0f) != SLJIT_UNUSED) {
|
||||
if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
|
||||
|
|
@ -373,8 +403,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr++ = immb; /* 8 bit displacement. */
|
||||
else {
|
||||
*(sljit_w*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_w);
|
||||
*(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_sw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -385,8 +415,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
}
|
||||
else {
|
||||
*buf_ptr++ |= 0x05;
|
||||
*(sljit_w*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_w);
|
||||
*(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_sw);
|
||||
}
|
||||
|
||||
if (a & SLJIT_IMM) {
|
||||
|
|
@ -395,121 +425,121 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
else if (flags & EX86_HALF_ARG)
|
||||
*(short*)buf_ptr = imma;
|
||||
else if (!(flags & EX86_SHIFT_INS))
|
||||
*(sljit_w*)buf_ptr = imma;
|
||||
*(sljit_sw*)buf_ptr = imma;
|
||||
}
|
||||
|
||||
return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1);
|
||||
return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Call / return instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type)
|
||||
static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *inst;
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
buf = (sljit_ub*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(type >= SLJIT_CALL3 ? 2 + 1 : 2);
|
||||
|
||||
if (type >= SLJIT_CALL3)
|
||||
PUSH_REG(reg_map[SLJIT_TEMPORARY_REG3]);
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_TEMPORARY_REG3] << 3) | reg_map[SLJIT_TEMPORARY_REG1];
|
||||
PUSH_REG(reg_map[SLJIT_SCRATCH_REG3]);
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SCRATCH_REG3] << 3) | reg_map[SLJIT_SCRATCH_REG1];
|
||||
#else
|
||||
buf = (sljit_ub*)ensure_buf(compiler, type - SLJIT_CALL0 + 1);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(type - SLJIT_CALL0);
|
||||
if (type >= SLJIT_CALL3)
|
||||
PUSH_REG(reg_map[SLJIT_TEMPORARY_REG3]);
|
||||
if (type >= SLJIT_CALL2)
|
||||
PUSH_REG(reg_map[SLJIT_TEMPORARY_REG2]);
|
||||
PUSH_REG(reg_map[SLJIT_TEMPORARY_REG1]);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 * (type - SLJIT_CALL0));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4 * (type - SLJIT_CALL0));
|
||||
|
||||
*inst++ = MOV_rm_r;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SCRATCH_REG1] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_LOCALS_REG];
|
||||
*inst++ = 0;
|
||||
if (type >= SLJIT_CALL2) {
|
||||
*inst++ = MOV_rm_r;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SCRATCH_REG2] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_LOCALS_REG];
|
||||
*inst++ = sizeof(sljit_sw);
|
||||
}
|
||||
if (type >= SLJIT_CALL3) {
|
||||
*inst++ = MOV_rm_r;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SCRATCH_REG3] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_LOCALS_REG];
|
||||
*inst++ = 2 * sizeof(sljit_sw);
|
||||
}
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->saveds = saveds;
|
||||
compiler->args = args;
|
||||
compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
|
||||
compiler->temporaries_start = compiler->local_size;
|
||||
if (temporaries > 3)
|
||||
compiler->local_size += (temporaries - 3) * sizeof(sljit_uw);
|
||||
compiler->saveds_start = compiler->local_size;
|
||||
if (saveds > 3)
|
||||
compiler->local_size += (saveds - 3) * sizeof(sljit_uw);
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw);
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
CHECK_EXTRA_REGS(dst, dstw, (void)0);
|
||||
|
||||
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
/* For UNUSED dst. Uncommon, but possible. */
|
||||
if (dst == SLJIT_UNUSED)
|
||||
dst = TMP_REGISTER;
|
||||
|
||||
if (dst <= TMP_REGISTER) {
|
||||
/* Unused dest is possible here. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(1);
|
||||
POP_REG(reg_map[dst]);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
else if (dst & SLJIT_MEM) {
|
||||
buf = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
|
||||
FAIL_IF(!buf);
|
||||
*buf++ = 0x8f;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* For UNUSED dst. Uncommon, but possible. */
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(1);
|
||||
POP_REG(reg_map[TMP_REGISTER]);
|
||||
/* Memory. */
|
||||
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = POP_rm;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_return(compiler, src, srcw);
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||
|
||||
if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
if (src <= TMP_REGISTER) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(1 + 1);
|
||||
PUSH_REG(reg_map[src]);
|
||||
}
|
||||
else if (src & SLJIT_MEM) {
|
||||
buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
|
||||
FAIL_IF(!buf);
|
||||
*buf++ = 0xff;
|
||||
*buf |= 6 << 3;
|
||||
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = GROUP_FF;
|
||||
*inst |= PUSH_rm;
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
}
|
||||
else {
|
||||
/* SLJIT_IMM. */
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(5 + 1);
|
||||
*buf++ = 0x68;
|
||||
*(sljit_w*)buf = srcw;
|
||||
buf += sizeof(sljit_w);
|
||||
*inst++ = PUSH_i32;
|
||||
*(sljit_sw*)inst = srcw;
|
||||
inst += sizeof(sljit_sw);
|
||||
}
|
||||
|
||||
RET();
|
||||
|
|
|
|||
|
|
@ -26,118 +26,116 @@
|
|||
|
||||
/* x86 64-bit arch dependent functions. */
|
||||
|
||||
static int emit_load_imm64(struct sljit_compiler *compiler, int reg, sljit_w imm)
|
||||
static sljit_si emit_load_imm64(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *inst;
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_w));
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(2 + sizeof(sljit_w));
|
||||
*buf++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
|
||||
*buf++ = 0xb8 + (reg_map[reg] & 0x7);
|
||||
*(sljit_w*)buf = imm;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(2 + sizeof(sljit_sw));
|
||||
*inst++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
|
||||
*inst++ = MOV_r_i32 + (reg_map[reg] & 0x7);
|
||||
*(sljit_sw*)inst = imm;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type)
|
||||
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type)
|
||||
{
|
||||
if (type < SLJIT_JUMP) {
|
||||
/* Invert type. */
|
||||
*code_ptr++ = get_jump_code(type ^ 0x1) - 0x10;
|
||||
*code_ptr++ = 10 + 3;
|
||||
}
|
||||
|
||||
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first);
|
||||
*code_ptr++ = REX_W | REX_B;
|
||||
*code_ptr++ = 0xb8 + 1;
|
||||
*code_ptr++ = MOV_r_i32 + 1;
|
||||
jump->addr = (sljit_uw)code_ptr;
|
||||
|
||||
if (jump->flags & JUMP_LABEL)
|
||||
jump->flags |= PATCH_MD;
|
||||
else
|
||||
*(sljit_w*)code_ptr = jump->u.target;
|
||||
*(sljit_sw*)code_ptr = jump->u.target;
|
||||
|
||||
code_ptr += sizeof(sljit_w);
|
||||
code_ptr += sizeof(sljit_sw);
|
||||
*code_ptr++ = REX_B;
|
||||
*code_ptr++ = 0xff;
|
||||
*code_ptr++ = (type >= SLJIT_FAST_CALL) ? 0xd1 /* call */ : 0xe1 /* jmp */;
|
||||
*code_ptr++ = GROUP_FF;
|
||||
*code_ptr++ = (type >= SLJIT_FAST_CALL) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_w addr, int type)
|
||||
static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si type)
|
||||
{
|
||||
sljit_w delta = addr - ((sljit_w)code_ptr + 1 + sizeof(sljit_hw));
|
||||
sljit_sw delta = addr - ((sljit_sw)code_ptr + 1 + sizeof(sljit_si));
|
||||
|
||||
if (delta <= SLJIT_W(0x7fffffff) && delta >= SLJIT_W(-0x80000000)) {
|
||||
*code_ptr++ = (type == 2) ? 0xe8 /* call */ : 0xe9 /* jmp */;
|
||||
*(sljit_w*)code_ptr = delta;
|
||||
*code_ptr++ = (type == 2) ? CALL_i32 : JMP_i32;
|
||||
*(sljit_sw*)code_ptr = delta;
|
||||
}
|
||||
else {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second);
|
||||
*code_ptr++ = REX_W | REX_B;
|
||||
*code_ptr++ = 0xb8 + 1;
|
||||
*(sljit_w*)code_ptr = addr;
|
||||
code_ptr += sizeof(sljit_w);
|
||||
*code_ptr++ = MOV_r_i32 + 1;
|
||||
*(sljit_sw*)code_ptr = addr;
|
||||
code_ptr += sizeof(sljit_sw);
|
||||
*code_ptr++ = REX_B;
|
||||
*code_ptr++ = 0xff;
|
||||
*code_ptr++ = (type == 2) ? 0xd1 /* call */ : 0xe1 /* jmp */;
|
||||
*code_ptr++ = GROUP_FF;
|
||||
*code_ptr++ = (type == 2) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
|
||||
}
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
{
|
||||
int size, pushed_size;
|
||||
sljit_ub *buf;
|
||||
sljit_si size, pushed_size;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
|
||||
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->flags_saved = 0;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
size = saveds;
|
||||
/* Including the return address saved by the call instruction. */
|
||||
pushed_size = (saveds + 1) * sizeof(sljit_w);
|
||||
pushed_size = (saveds + 1) * sizeof(sljit_sw);
|
||||
#ifndef _WIN64
|
||||
if (saveds >= 2)
|
||||
size += saveds - 1;
|
||||
#else
|
||||
/* Saving the virtual stack pointer. */
|
||||
compiler->has_locals = local_size > 0;
|
||||
if (local_size > 0) {
|
||||
size += 2;
|
||||
pushed_size += sizeof(sljit_w);
|
||||
}
|
||||
if (saveds >= 4)
|
||||
size += saveds - 3;
|
||||
if (temporaries >= 5) {
|
||||
if (scratches >= 5) {
|
||||
size += (5 - 4) * 2;
|
||||
pushed_size += sizeof(sljit_w);
|
||||
pushed_size += sizeof(sljit_sw);
|
||||
}
|
||||
#endif
|
||||
size += args * 3;
|
||||
if (size > 0) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
if (saveds >= 5) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG2] >= 8, saved_ereg2_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
*inst++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_SAVED_EREG2]);
|
||||
}
|
||||
if (saveds >= 4) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG1] >= 8, saved_ereg1_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
*inst++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_SAVED_EREG1]);
|
||||
}
|
||||
if (saveds >= 3) {
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] >= 8, saved_reg3_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
*inst++ = REX_B;
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] < 8, saved_reg3_is_loreg);
|
||||
#endif
|
||||
|
|
@ -146,7 +144,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
|||
if (saveds >= 2) {
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] >= 8, saved_reg2_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
*inst++ = REX_B;
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] < 8, saved_reg2_is_loreg);
|
||||
#endif
|
||||
|
|
@ -157,149 +155,138 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
|||
PUSH_REG(reg_lmap[SLJIT_SAVED_REG1]);
|
||||
}
|
||||
#ifdef _WIN64
|
||||
if (temporaries >= 5) {
|
||||
if (scratches >= 5) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_EREG2] >= 8, temporary_ereg2_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
*inst++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
|
||||
}
|
||||
if (local_size > 0) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_LOCALS_REG] >= 8, locals_reg_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_LOCALS_REG]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN64
|
||||
if (args > 0) {
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x7;
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x7 /* rdi */;
|
||||
}
|
||||
if (args > 1) {
|
||||
*buf++ = REX_W | REX_R;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG2] << 3) | 0x6;
|
||||
*inst++ = REX_W | REX_R;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_lmap[SLJIT_SAVED_REG2] << 3) | 0x6 /* rsi */;
|
||||
}
|
||||
if (args > 2) {
|
||||
*buf++ = REX_W | REX_R;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG3] << 3) | 0x2;
|
||||
*inst++ = REX_W | REX_R;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_lmap[SLJIT_SAVED_REG3] << 3) | 0x2 /* rdx */;
|
||||
}
|
||||
#else
|
||||
if (args > 0) {
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x1;
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x1 /* rcx */;
|
||||
}
|
||||
if (args > 1) {
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | 0x2;
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG2] << 3) | 0x2 /* rdx */;
|
||||
}
|
||||
if (args > 2) {
|
||||
*buf++ = REX_W | REX_B;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x0;
|
||||
*inst++ = REX_W | REX_B;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x0 /* r8 */;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
|
||||
#ifdef _WIN64
|
||||
local_size += 4 * sizeof(sljit_w);
|
||||
local_size = ((local_size + FIXED_LOCALS_OFFSET + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
|
||||
compiler->local_size = local_size;
|
||||
#ifdef _WIN64
|
||||
if (local_size > 1024) {
|
||||
/* Allocate the stack for the function itself. */
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(4);
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x83;
|
||||
*buf++ = 0xc0 | (5 << 3) | 4;
|
||||
/* Allocate stack for the callback, which grows the stack. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + (3 + sizeof(sljit_si)));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4 + (3 + sizeof(sljit_si)));
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_83;
|
||||
*inst++ = MOD_REG | SUB | 4;
|
||||
/* Pushed size must be divisible by 8. */
|
||||
SLJIT_ASSERT(!(pushed_size & 0x7));
|
||||
if (pushed_size & 0x8) {
|
||||
*buf++ = 5 * sizeof(sljit_w);
|
||||
local_size -= 5 * sizeof(sljit_w);
|
||||
*inst++ = 5 * sizeof(sljit_sw);
|
||||
local_size -= 5 * sizeof(sljit_sw);
|
||||
} else {
|
||||
*buf++ = 4 * sizeof(sljit_w);
|
||||
local_size -= 4 * sizeof(sljit_w);
|
||||
*inst++ = 4 * sizeof(sljit_sw);
|
||||
local_size -= 4 * sizeof(sljit_sw);
|
||||
}
|
||||
FAIL_IF(emit_load_imm64(compiler, SLJIT_TEMPORARY_REG1, local_size));
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_touch_stack)));
|
||||
}
|
||||
#else
|
||||
compiler->local_size = local_size;
|
||||
if (local_size > 0) {
|
||||
/* Second instruction */
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG1] < 8, temporary_reg1_is_loreg);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_rm_i32;
|
||||
*inst++ = MOD_REG | reg_lmap[SLJIT_SCRATCH_REG1];
|
||||
*(sljit_si*)inst = local_size;
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
/* In case of Win64, local_size is always > 4 * sizeof(sljit_w) */
|
||||
if (local_size <= 127) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(4);
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x83;
|
||||
*buf++ = 0xc0 | (5 << 3) | 4;
|
||||
*buf++ = local_size;
|
||||
}
|
||||
else {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(7);
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x81;
|
||||
*buf++ = 0xc0 | (5 << 3) | 4;
|
||||
*(sljit_hw*)buf = local_size;
|
||||
buf += sizeof(sljit_hw);
|
||||
}
|
||||
#ifndef _WIN64
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(local_size > 0);
|
||||
if (local_size <= 127) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_83;
|
||||
*inst++ = MOD_REG | SUB | 4;
|
||||
*inst++ = local_size;
|
||||
}
|
||||
else {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 7);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(7);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_81;
|
||||
*inst++ = MOD_REG | SUB | 4;
|
||||
*(sljit_si*)inst = local_size;
|
||||
inst += sizeof(sljit_si);
|
||||
}
|
||||
#ifdef _WIN64
|
||||
if (compiler->has_locals) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(5);
|
||||
*buf++ = REX_W | REX_R;
|
||||
*buf++ = 0x8d;
|
||||
*buf++ = 0x40 | (reg_lmap[SLJIT_LOCALS_REG] << 3) | 0x4;
|
||||
*buf++ = 0x24;
|
||||
*buf = 4 * sizeof(sljit_w);
|
||||
}
|
||||
/* Save xmm6 with MOVAPS instruction. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(5);
|
||||
*inst++ = GROUP_0F;
|
||||
*(sljit_si*)inst = 0x20247429;
|
||||
#endif
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
{
|
||||
int pushed_size;
|
||||
sljit_si pushed_size;
|
||||
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
|
||||
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
/* Including the return address saved by the call instruction. */
|
||||
pushed_size = (saveds + 1) * sizeof(sljit_w);
|
||||
pushed_size = (saveds + 1) * sizeof(sljit_sw);
|
||||
#ifdef _WIN64
|
||||
compiler->has_locals = local_size > 0;
|
||||
if (local_size > 0)
|
||||
pushed_size += sizeof(sljit_w);
|
||||
if (temporaries >= 5)
|
||||
pushed_size += sizeof(sljit_w);
|
||||
#endif
|
||||
compiler->local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
|
||||
#ifdef _WIN64
|
||||
compiler->local_size += 4 * sizeof(sljit_w);
|
||||
if (scratches >= 5)
|
||||
pushed_size += sizeof(sljit_sw);
|
||||
#endif
|
||||
compiler->local_size = ((local_size + FIXED_LOCALS_OFFSET + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
int size;
|
||||
sljit_ub *buf;
|
||||
sljit_si size;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, op, src, srcw);
|
||||
|
|
@ -307,25 +294,32 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
|||
compiler->flags_saved = 0;
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
if (compiler->local_size > 0) {
|
||||
if (compiler->local_size <= 127) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(4);
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x83;
|
||||
*buf++ = 0xc0 | (0 << 3) | 4;
|
||||
*buf = compiler->local_size;
|
||||
}
|
||||
else {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(7);
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x81;
|
||||
*buf++ = 0xc0 | (0 << 3) | 4;
|
||||
*(sljit_hw*)buf = compiler->local_size;
|
||||
}
|
||||
#ifdef _WIN64
|
||||
/* Restore xmm6 with MOVAPS instruction. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(5);
|
||||
*inst++ = GROUP_0F;
|
||||
*(sljit_si*)inst = 0x20247428;
|
||||
#endif
|
||||
SLJIT_ASSERT(compiler->local_size > 0);
|
||||
if (compiler->local_size <= 127) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_83;
|
||||
*inst++ = MOD_REG | ADD | 4;
|
||||
*inst = compiler->local_size;
|
||||
}
|
||||
else {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 7);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(7);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_81;
|
||||
*inst++ = MOD_REG | ADD | 4;
|
||||
*(sljit_si*)inst = compiler->local_size;
|
||||
}
|
||||
|
||||
size = 1 + compiler->saveds;
|
||||
|
|
@ -333,25 +327,19 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
|||
if (compiler->saveds >= 2)
|
||||
size += compiler->saveds - 1;
|
||||
#else
|
||||
if (compiler->has_locals)
|
||||
size += 2;
|
||||
if (compiler->saveds >= 4)
|
||||
size += compiler->saveds - 3;
|
||||
if (compiler->temporaries >= 5)
|
||||
if (compiler->scratches >= 5)
|
||||
size += (5 - 4) * 2;
|
||||
#endif
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
|
||||
#ifdef _WIN64
|
||||
if (compiler->has_locals) {
|
||||
*buf++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_LOCALS_REG]);
|
||||
}
|
||||
if (compiler->temporaries >= 5) {
|
||||
*buf++ = REX_B;
|
||||
if (compiler->scratches >= 5) {
|
||||
*inst++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -359,22 +347,22 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
|||
POP_REG(reg_map[SLJIT_SAVED_REG1]);
|
||||
if (compiler->saveds >= 2) {
|
||||
#ifndef _WIN64
|
||||
*buf++ = REX_B;
|
||||
*inst++ = REX_B;
|
||||
#endif
|
||||
POP_REG(reg_lmap[SLJIT_SAVED_REG2]);
|
||||
}
|
||||
if (compiler->saveds >= 3) {
|
||||
#ifndef _WIN64
|
||||
*buf++ = REX_B;
|
||||
*inst++ = REX_B;
|
||||
#endif
|
||||
POP_REG(reg_lmap[SLJIT_SAVED_REG3]);
|
||||
}
|
||||
if (compiler->saveds >= 4) {
|
||||
*buf++ = REX_B;
|
||||
*inst++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_SAVED_EREG1]);
|
||||
}
|
||||
if (compiler->saveds >= 5) {
|
||||
*buf++ = REX_B;
|
||||
*inst++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_SAVED_EREG2]);
|
||||
}
|
||||
|
||||
|
|
@ -386,39 +374,32 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
|||
/* Operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static int emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_w imm)
|
||||
static sljit_si emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_sw imm)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *inst;
|
||||
sljit_si length = 1 + (rex ? 1 : 0) + sizeof(sljit_si);
|
||||
|
||||
if (rex != 0) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_hw));
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(2 + sizeof(sljit_hw));
|
||||
*buf++ = rex;
|
||||
*buf++ = opcode;
|
||||
*(sljit_hw*)buf = imm;
|
||||
}
|
||||
else {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_hw));
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(1 + sizeof(sljit_hw));
|
||||
*buf++ = opcode;
|
||||
*(sljit_hw*)buf = imm;
|
||||
}
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + length);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(length);
|
||||
if (rex)
|
||||
*inst++ = rex;
|
||||
*inst++ = opcode;
|
||||
*(sljit_si*)inst = imm;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
||||
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size,
|
||||
/* The register or immediate operand. */
|
||||
int a, sljit_w imma,
|
||||
sljit_si a, sljit_sw imma,
|
||||
/* The general operand (not immediate). */
|
||||
int b, sljit_w immb)
|
||||
sljit_si b, sljit_sw immb)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *inst;
|
||||
sljit_ub *buf_ptr;
|
||||
sljit_ub rex = 0;
|
||||
int flags = size & ~0xf;
|
||||
int inst_size;
|
||||
sljit_si flags = size & ~0xf;
|
||||
sljit_si inst_size;
|
||||
|
||||
/* The immediate operand must be 32 bit. */
|
||||
SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
|
||||
|
|
@ -431,6 +412,9 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
/* SSE2 and immediate is not possible. */
|
||||
SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
|
||||
SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
|
||||
&& (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
|
||||
&& (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
|
||||
#endif
|
||||
|
||||
size &= 0xf;
|
||||
|
|
@ -452,7 +436,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
rex |= REX;
|
||||
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (flags & EX86_PREF_F2)
|
||||
if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
|
||||
inst_size++;
|
||||
#endif
|
||||
if (flags & EX86_PREF_66)
|
||||
|
|
@ -462,23 +446,21 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
inst_size += 1; /* mod r/m byte. */
|
||||
if (b & SLJIT_MEM) {
|
||||
if ((b & 0x0f) == SLJIT_UNUSED)
|
||||
inst_size += 1 + sizeof(sljit_hw); /* SIB byte required to avoid RIP based addressing. */
|
||||
inst_size += 1 + sizeof(sljit_si); /* SIB byte required to avoid RIP based addressing. */
|
||||
else {
|
||||
if (reg_map[b & 0x0f] >= 8)
|
||||
rex |= REX_B;
|
||||
if (immb != 0 && !(b & 0xf0)) {
|
||||
/* Immediate operand. */
|
||||
if (immb <= 127 && immb >= -128)
|
||||
inst_size += sizeof(sljit_b);
|
||||
inst_size += sizeof(sljit_sb);
|
||||
else
|
||||
inst_size += sizeof(sljit_hw);
|
||||
inst_size += sizeof(sljit_si);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _WIN64
|
||||
if ((b & 0xf) == SLJIT_LOCALS_REG && (b & 0xf0) == 0)
|
||||
if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
|
||||
b |= SLJIT_LOCALS_REG << 4;
|
||||
#endif
|
||||
|
||||
if ((b & 0xf0) != SLJIT_UNUSED) {
|
||||
inst_size += 1; /* SIB byte. */
|
||||
|
|
@ -513,7 +495,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
else if (flags & EX86_HALF_ARG)
|
||||
inst_size += sizeof(short);
|
||||
else
|
||||
inst_size += sizeof(sljit_hw);
|
||||
inst_size += sizeof(sljit_si);
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
|
||||
|
|
@ -530,25 +512,27 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
if (rex)
|
||||
inst_size++;
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
|
||||
PTR_FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
|
||||
PTR_FAIL_IF(!inst);
|
||||
|
||||
/* Encoding the byte. */
|
||||
INC_SIZE(inst_size);
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (flags & EX86_PREF_F2)
|
||||
*buf++ = 0xf2;
|
||||
*inst++ = 0xf2;
|
||||
if (flags & EX86_PREF_F3)
|
||||
*inst++ = 0xf3;
|
||||
#endif
|
||||
if (flags & EX86_PREF_66)
|
||||
*buf++ = 0x66;
|
||||
*inst++ = 0x66;
|
||||
if (rex)
|
||||
*buf++ = rex;
|
||||
buf_ptr = buf + size;
|
||||
*inst++ = rex;
|
||||
buf_ptr = inst + size;
|
||||
|
||||
/* Encode mod/rm byte. */
|
||||
if (!(flags & EX86_SHIFT_INS)) {
|
||||
if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
|
||||
*buf = (flags & EX86_BYTE_ARG) ? 0x83 : 0x81;
|
||||
*inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
|
||||
|
||||
if ((a & SLJIT_IMM) || (a == 0))
|
||||
*buf_ptr = 0;
|
||||
|
|
@ -565,24 +549,21 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
else {
|
||||
if (a & SLJIT_IMM) {
|
||||
if (imma == 1)
|
||||
*buf = 0xd1;
|
||||
*inst = GROUP_SHIFT_1;
|
||||
else
|
||||
*buf = 0xc1;
|
||||
*inst = GROUP_SHIFT_N;
|
||||
} else
|
||||
*buf = 0xd3;
|
||||
*inst = GROUP_SHIFT_CL;
|
||||
*buf_ptr = 0;
|
||||
}
|
||||
|
||||
if (!(b & SLJIT_MEM))
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
*buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_lmap[b] : b);
|
||||
*buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2)) ? reg_lmap[b] : b);
|
||||
#else
|
||||
*buf_ptr++ |= 0xc0 + reg_lmap[b];
|
||||
*buf_ptr++ |= MOD_REG + reg_lmap[b];
|
||||
#endif
|
||||
else if ((b & 0x0f) != SLJIT_UNUSED) {
|
||||
#ifdef _WIN64
|
||||
SLJIT_ASSERT((b & 0xf0) != (SLJIT_LOCALS_REG << 4));
|
||||
#endif
|
||||
if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
|
||||
if (immb != 0) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
|
|
@ -602,8 +583,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr++ = immb; /* 8 bit displacement. */
|
||||
else {
|
||||
*(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_hw);
|
||||
*(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_si);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -615,8 +596,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = 0x25;
|
||||
*(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_hw);
|
||||
*(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_si);
|
||||
}
|
||||
|
||||
if (a & SLJIT_IMM) {
|
||||
|
|
@ -625,154 +606,141 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
|||
else if (flags & EX86_HALF_ARG)
|
||||
*(short*)buf_ptr = imma;
|
||||
else if (!(flags & EX86_SHIFT_INS))
|
||||
*(sljit_hw*)buf_ptr = imma;
|
||||
*(sljit_si*)buf_ptr = imma;
|
||||
}
|
||||
|
||||
return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1);
|
||||
return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Call / return instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type)
|
||||
static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *inst;
|
||||
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 6 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers);
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG2] == 6 && reg_map[SLJIT_SCRATCH_REG1] < 8 && reg_map[SLJIT_SCRATCH_REG3] < 8, args_registers);
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
|
||||
if (type >= SLJIT_CALL3) {
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (0x2 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3];
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x2 /* rdx */ << 3) | reg_lmap[SLJIT_SCRATCH_REG3];
|
||||
}
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (0x7 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x7 /* rdi */ << 3) | reg_lmap[SLJIT_SCRATCH_REG1];
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 2 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers);
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG2] == 2 && reg_map[SLJIT_SCRATCH_REG1] < 8 && reg_map[SLJIT_SCRATCH_REG3] < 8, args_registers);
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
|
||||
if (type >= SLJIT_CALL3) {
|
||||
*buf++ = REX_W | REX_R;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (0x0 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3];
|
||||
*inst++ = REX_W | REX_R;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x0 /* r8 */ << 3) | reg_lmap[SLJIT_SCRATCH_REG3];
|
||||
}
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (0x1 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x1 /* rcx */ << 3) | reg_lmap[SLJIT_SCRATCH_REG1];
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->saveds = saveds;
|
||||
compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
|
||||
#ifdef _WIN64
|
||||
compiler->local_size += 4 * sizeof(sljit_w);
|
||||
#endif
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw);
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
/* For UNUSED dst. Uncommon, but possible. */
|
||||
if (dst == SLJIT_UNUSED)
|
||||
dst = TMP_REGISTER;
|
||||
|
||||
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
|
||||
if (dst <= TMP_REGISTER) {
|
||||
if (reg_map[dst] < 8) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
POP_REG(reg_lmap[dst]);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
else {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(2);
|
||||
*buf++ = REX_B;
|
||||
POP_REG(reg_lmap[dst]);
|
||||
}
|
||||
}
|
||||
else if (dst & SLJIT_MEM) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
/* REX_W is not necessary (src is not immediate). */
|
||||
compiler->mode32 = 1;
|
||||
#endif
|
||||
buf = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
|
||||
FAIL_IF(!buf);
|
||||
*buf++ = 0x8f;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 2);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(2);
|
||||
*inst++ = REX_B;
|
||||
POP_REG(reg_lmap[dst]);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* REX_W is not necessary (src is not immediate). */
|
||||
compiler->mode32 = 1;
|
||||
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = POP_rm;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_return(compiler, src, srcw);
|
||||
|
||||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) {
|
||||
FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, srcw));
|
||||
src = TMP_REGISTER;
|
||||
}
|
||||
|
||||
if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REGISTER) {
|
||||
if (src <= TMP_REGISTER) {
|
||||
if (reg_map[src] < 8) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(1 + 1);
|
||||
PUSH_REG(reg_lmap[src]);
|
||||
}
|
||||
else {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(2 + 1);
|
||||
*buf++ = REX_B;
|
||||
*inst++ = REX_B;
|
||||
PUSH_REG(reg_lmap[src]);
|
||||
}
|
||||
}
|
||||
else if (src & SLJIT_MEM) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
/* REX_W is not necessary (src is not immediate). */
|
||||
compiler->mode32 = 1;
|
||||
#endif
|
||||
buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
|
||||
FAIL_IF(!buf);
|
||||
*buf++ = 0xff;
|
||||
*buf |= 6 << 3;
|
||||
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = GROUP_FF;
|
||||
*inst |= PUSH_rm;
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(IS_HALFWORD(srcw));
|
||||
/* SLJIT_IMM. */
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!buf);
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(5 + 1);
|
||||
*buf++ = 0x68;
|
||||
*(sljit_hw*)buf = srcw;
|
||||
buf += sizeof(sljit_hw);
|
||||
*inst++ = PUSH_i32;
|
||||
*(sljit_si*)inst = srcw;
|
||||
inst += sizeof(sljit_si);
|
||||
}
|
||||
|
||||
RET();
|
||||
|
|
@ -784,12 +752,12 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
|
|||
/* Extend input */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static int emit_mov_int(struct sljit_compiler *compiler, int sign,
|
||||
int dst, sljit_w dstw,
|
||||
int src, sljit_w srcw)
|
||||
static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_ub* code;
|
||||
int dst_r;
|
||||
sljit_ub* inst;
|
||||
sljit_si dst_r;
|
||||
|
||||
compiler->mode32 = 0;
|
||||
|
||||
|
|
@ -797,32 +765,32 @@ 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 <= TMP_REGISTER) {
|
||||
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;
|
||||
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
*inst = MOV_rm_i32;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
return emit_load_imm64(compiler, dst, srcw);
|
||||
}
|
||||
compiler->mode32 = 1;
|
||||
code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
|
||||
FAIL_IF(!code);
|
||||
*code = 0xc7;
|
||||
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
*inst = MOV_rm_i32;
|
||||
compiler->mode32 = 0;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_SAVED_REG3) ? dst : TMP_REGISTER;
|
||||
dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
|
||||
|
||||
if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_SAVED_REG3))
|
||||
if ((dst & SLJIT_MEM) && (src <= TMP_REGISTER))
|
||||
dst_r = src;
|
||||
else {
|
||||
if (sign) {
|
||||
code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
|
||||
FAIL_IF(!code);
|
||||
*code++ = 0x63;
|
||||
inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = MOVSXD_r_rm;
|
||||
} else {
|
||||
compiler->mode32 = 1;
|
||||
FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw));
|
||||
|
|
@ -832,9 +800,9 @@ static int emit_mov_int(struct sljit_compiler *compiler, int sign,
|
|||
|
||||
if (dst & SLJIT_MEM) {
|
||||
compiler->mode32 = 1;
|
||||
code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
|
||||
FAIL_IF(!code);
|
||||
*code = 0x89;
|
||||
inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
*inst = MOV_rm_r;
|
||||
compiler->mode32 = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -30,7 +30,37 @@
|
|||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) || (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
|
||||
#ifdef _WIN32
|
||||
#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
|
||||
static SLJIT_INLINE void allocator_grab_lock(void)
|
||||
{
|
||||
/* Always successful. */
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void allocator_release_lock(void)
|
||||
{
|
||||
/* Always successful. */
|
||||
}
|
||||
|
||||
#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
|
||||
{
|
||||
/* Always successful. */
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
|
||||
{
|
||||
/* Always successful. */
|
||||
}
|
||||
|
||||
#endif /* SLJIT_UTIL_GLOBAL_LOCK */
|
||||
|
||||
#elif defined(_WIN32) /* SLJIT_SINGLE_THREADED */
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
|
|
@ -76,10 +106,10 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
|
|||
|
||||
#else /* _WIN32 */
|
||||
|
||||
#include "pthread.h"
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_mutex_t allocator_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static SLJIT_INLINE void allocator_grab_lock(void)
|
||||
|
|
@ -96,6 +126,8 @@ static SLJIT_INLINE void allocator_release_lock(void)
|
|||
|
||||
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
|
||||
|
|
@ -116,17 +148,57 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
|
|||
/* Stack */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
|
||||
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "windows.h"
|
||||
#else
|
||||
/* Provides mmap function. */
|
||||
#include <sys/mman.h>
|
||||
/* For detecting the page size. */
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef MAP_ANON
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
/* Some old systems does not have MAP_ANON. */
|
||||
static sljit_si dev_zero = -1;
|
||||
|
||||
#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
|
||||
|
||||
static SLJIT_INLINE sljit_si open_dev_zero(void)
|
||||
{
|
||||
dev_zero = open("/dev/zero", O_RDWR);
|
||||
return dev_zero < 0;
|
||||
}
|
||||
|
||||
#else /* SLJIT_SINGLE_THREADED */
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static SLJIT_INLINE sljit_si open_dev_zero(void)
|
||||
{
|
||||
pthread_mutex_lock(&dev_zero_mutex);
|
||||
dev_zero = open("/dev/zero", O_RDWR);
|
||||
pthread_mutex_unlock(&dev_zero_mutex);
|
||||
return dev_zero < 0;
|
||||
}
|
||||
|
||||
#endif /* SLJIT_SINGLE_THREADED */
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SLJIT_UTIL_STACK || SLJIT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
|
||||
|
||||
/* Planning to make it even more clever in the future. */
|
||||
static sljit_w sljit_page_align = 0;
|
||||
static sljit_sw sljit_page_align = 0;
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit)
|
||||
{
|
||||
|
|
@ -165,7 +237,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
|
|||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
base.ptr = VirtualAlloc(0, max_limit, MEM_RESERVE, PAGE_READWRITE);
|
||||
base.ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
|
||||
if (!base.ptr) {
|
||||
SLJIT_FREE(stack);
|
||||
return NULL;
|
||||
|
|
@ -178,7 +250,17 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
|
|||
return NULL;
|
||||
}
|
||||
#else
|
||||
base.ptr = mmap(0, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
#ifdef MAP_ANON
|
||||
base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
#else
|
||||
if (dev_zero < 0) {
|
||||
if (open_dev_zero()) {
|
||||
SLJIT_FREE(stack);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
|
||||
#endif
|
||||
if (base.ptr == MAP_FAILED) {
|
||||
SLJIT_FREE(stack);
|
||||
return NULL;
|
||||
|
|
@ -203,7 +285,7 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* st
|
|||
SLJIT_FREE(stack);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
|
||||
{
|
||||
sljit_uw aligned_old_limit;
|
||||
sljit_uw aligned_new_limit;
|
||||
|
|
@ -232,10 +314,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stac
|
|||
}
|
||||
aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
|
||||
aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
|
||||
/* If madvise is available, we release the unnecessary space. */
|
||||
#if defined(POSIX_MADV_DONTNEED)
|
||||
if (aligned_new_limit < aligned_old_limit)
|
||||
#if defined(__QNXNTO__) || defined(__LSB_VERSION__)
|
||||
posix_madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, POSIX_MADV_DONTNEED);
|
||||
#else
|
||||
#elif defined(MADV_DONTNEED)
|
||||
if (aligned_new_limit < aligned_old_limit)
|
||||
madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED);
|
||||
#endif
|
||||
stack->limit = new_limit;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@
|
|||
|
||||
/* This file contains definitions of the property values that are returned by
|
||||
the UCD access macros. New values that are added for new releases of Unicode
|
||||
should always be at the end of each enum, for backwards compatibility. */
|
||||
should always be at the end of each enum, for backwards compatibility.
|
||||
|
||||
IMPORTANT: Note also that the specific numeric values of the enums have to be
|
||||
the same as the values that are generated by the maint/MultiStage2.py script,
|
||||
where the equivalent property descriptive names are listed in vectors. */
|
||||
|
||||
/* These are the general character categories. */
|
||||
|
||||
|
|
@ -21,7 +25,7 @@ enum {
|
|||
ucp_Z /* Separator */
|
||||
};
|
||||
|
||||
/* These are the particular character types. */
|
||||
/* These are the particular character categories. */
|
||||
|
||||
enum {
|
||||
ucp_Cc, /* Control */
|
||||
|
|
@ -56,6 +60,26 @@ enum {
|
|||
ucp_Zs /* Space separator */
|
||||
};
|
||||
|
||||
/* These are grapheme break properties. Note that the code for processing them
|
||||
assumes that the values are less than 16. If more values are added that take
|
||||
the number to 16 or more, the code will have to be rewritten. */
|
||||
|
||||
enum {
|
||||
ucp_gbCR, /* 0 */
|
||||
ucp_gbLF, /* 1 */
|
||||
ucp_gbControl, /* 2 */
|
||||
ucp_gbExtend, /* 3 */
|
||||
ucp_gbPrepend, /* 4 */
|
||||
ucp_gbSpacingMark, /* 5 */
|
||||
ucp_gbL, /* 6 Hangul syllable type L */
|
||||
ucp_gbV, /* 7 Hangul syllable type V */
|
||||
ucp_gbT, /* 8 Hangul syllable type T */
|
||||
ucp_gbLV, /* 9 Hangul syllable type LV */
|
||||
ucp_gbLVT, /* 10 Hangul syllable type LVT */
|
||||
ucp_gbRegionalIndicator, /* 11 */
|
||||
ucp_gbOther /* 12 */
|
||||
};
|
||||
|
||||
/* These are the script identifications. */
|
||||
|
||||
enum {
|
||||
|
|
@ -157,7 +181,15 @@ enum {
|
|||
/* New for Unicode 6.0.0: */
|
||||
ucp_Batak,
|
||||
ucp_Brahmi,
|
||||
ucp_Mandaic
|
||||
ucp_Mandaic,
|
||||
/* New for Unicode 6.1.0: */
|
||||
ucp_Chakma,
|
||||
ucp_Meroitic_Cursive,
|
||||
ucp_Meroitic_Hieroglyphs,
|
||||
ucp_Miao,
|
||||
ucp_Sharada,
|
||||
ucp_Sora_Sompeng,
|
||||
ucp_Takri
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1164,8 +1164,6 @@ void tst_QString::indexOf()
|
|||
options |= QRegularExpression::CaseInsensitiveOption;
|
||||
|
||||
QRegularExpression re(QRegularExpression::escape(needle), options);
|
||||
QEXPECT_FAIL("data58", "QRegularExpression does not support case folding", Continue);
|
||||
QEXPECT_FAIL("data59", "QRegularExpression does not support case folding", Continue);
|
||||
QCOMPARE( haystack.indexOf(re, startpos), resultpos );
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue