2012-02-08 01:51 UTC+0100 Viktor Szakats (harbour syenar.net)
* src/3rd/pcre/pcre.dif
* deleted patch applied upstream
* src/3rd/pcre/Makefile
- src/3rd/pcre/pcreinfo.c
- src/3rd/pcre/pcretryf.c
- src/3rd/pcre/pcreprni.h
+ src/3rd/pcre/pcreprni.c
* src/3rd/pcre/*
* 8.21 -> 8.30 (using hb3rdpat)
; supports 16-bit char API flavour (pcre16_*()).
not enabled in Harbour ATM.
This commit is contained in:
@@ -16,6 +16,20 @@
|
||||
The license applies to all entries newer than 2009-04-28.
|
||||
*/
|
||||
|
||||
2012-02-08 01:51 UTC+0100 Viktor Szakats (harbour syenar.net)
|
||||
* src/3rd/pcre/pcre.dif
|
||||
* deleted patch applied upstream
|
||||
|
||||
* src/3rd/pcre/Makefile
|
||||
- src/3rd/pcre/pcreinfo.c
|
||||
- src/3rd/pcre/pcretryf.c
|
||||
- src/3rd/pcre/pcreprni.h
|
||||
+ src/3rd/pcre/pcreprni.c
|
||||
* src/3rd/pcre/*
|
||||
* 8.21 -> 8.30 (using hb3rdpat)
|
||||
; supports 16-bit char API flavour (pcre16_*()).
|
||||
not enabled in Harbour ATM.
|
||||
|
||||
2012-02-08 01:25 UTC+0100 Viktor Szakats (harbour syenar.net)
|
||||
* src/3rd/pcre/Makefile
|
||||
+ added translation for JIT files from PCRE package
|
||||
|
||||
@@ -24,7 +24,7 @@ Email domain: cam.ac.uk
|
||||
University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2011 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2010-2011 Zoltan Herczeg
|
||||
Copyright(c) 2010-2012 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2009-2011 Zoltan Herczeg
|
||||
Copyright(c) 2009-2012 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ THE C++ WRAPPER FUNCTIONS
|
||||
|
||||
Contributed by: Google Inc.
|
||||
|
||||
Copyright (c) 2007-2011, Google Inc.
|
||||
Copyright (c) 2007-2012, Google Inc.
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
||||
@@ -81,8 +81,8 @@ else
|
||||
endif
|
||||
|
||||
# ORIGIN http://www.pcre.org/
|
||||
# VER 8.21
|
||||
# URL ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.21.tar.gz
|
||||
# VER 8.30
|
||||
# URL ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.30.tar.gz
|
||||
# DIFF pcre.dif
|
||||
#
|
||||
# MAP LICENCE
|
||||
@@ -98,16 +98,14 @@ endif
|
||||
# MAP pcre_fullinfo.c pcrefinf.c
|
||||
# MAP pcre_get.c pcreget.c
|
||||
# MAP pcre_globals.c pcreglob.c
|
||||
# MAP pcre_info.c pcreinfo.c
|
||||
# MAP pcre_jit_compile.c pcrejitc.c
|
||||
# MAP pcre_maketables.c pcremktb.c
|
||||
# MAP pcre_newline.c pcrenewl.c
|
||||
# MAP pcre_ord2utf8.c pcreoutf.c
|
||||
# MAP pcre_printint.src pcreprni.h
|
||||
# MAP pcre_printint.c pcreprni.c
|
||||
# MAP pcre_refcount.c pcrerefc.c
|
||||
# MAP pcre_study.c pcrestud.c
|
||||
# MAP pcre_tables.c pcretabs.c
|
||||
# MAP pcre_try_flipped.c pcretryf.c
|
||||
# MAP pcre_ucd.c pcreucd.c
|
||||
# MAP pcre_valid_utf8.c pcrevutf.c
|
||||
# MAP pcre_version.c pcrever.c
|
||||
|
||||
@@ -26,7 +26,7 @@ unit might reference this" and so it will always be supplied to the linker. */
|
||||
|
||||
#include "pcreinal.h"
|
||||
|
||||
const unsigned char _pcre_default_tables[] = {
|
||||
const pcre_uint8 PRIV(default_tables)[] = {
|
||||
|
||||
/* This table is a lower casing table. */
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ them both to 0; an emulation function will be used. */
|
||||
character codes, define this macro as 1. On systems that can use
|
||||
"configure", this can be done via --enable-ebcdic. PCRE will then assume
|
||||
that all input strings are in EBCDIC. If you do not define this macro, PCRE
|
||||
will assume input strings are ASCII or UTF-8 Unicode. It is not possible to
|
||||
build a version of PCRE that supports both EBCDIC and UTF-8. */
|
||||
will assume input strings are ASCII or UTF-8/16 Unicode. It is not possible
|
||||
to build a version of PCRE that supports both EBCDIC and UTF-8/16. */
|
||||
/* #undef EBCDIC */
|
||||
|
||||
/* Define to 1 if you have the `bcopy' function. */
|
||||
@@ -250,7 +250,7 @@ them both to 0; an emulation function will be used. */
|
||||
#define PACKAGE_NAME "PCRE"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "PCRE 8.21"
|
||||
#define PACKAGE_STRING "PCRE 8.30"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "pcre"
|
||||
@@ -259,7 +259,7 @@ them both to 0; an emulation function will be used. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "8.21"
|
||||
#define PACKAGE_VERSION "8.30"
|
||||
|
||||
/* The value of PCREGREP_BUFSIZE determines the size of buffer used by
|
||||
pcregrep to hold parts of the file it is searching. On systems that support
|
||||
@@ -317,21 +317,29 @@ them both to 0; an emulation function will be used. */
|
||||
handle .gz files. */
|
||||
/* #undef SUPPORT_LIBZ */
|
||||
|
||||
/* Define to enable the 16 bit PCRE library. */
|
||||
/* #undef SUPPORT_PCRE16 */
|
||||
|
||||
/* Define to enable the 8 bit PCRE library. */
|
||||
#ifndef SUPPORT_PCRE8
|
||||
#define SUPPORT_PCRE8 /**/
|
||||
#endif
|
||||
|
||||
/* Define to enable JIT support in pcregrep. */
|
||||
/* #undef SUPPORT_PCREGREP_JIT */
|
||||
|
||||
/* Define to enable support for Unicode properties. */
|
||||
/* #undef SUPPORT_UCP */
|
||||
|
||||
/* Define to enable support for the UTF-8 Unicode encoding. This will work
|
||||
/* Define to enable support for the UTF-8/16 Unicode encoding. This will work
|
||||
even in an EBCDIC environment, but it is incompatible with the EBCDIC
|
||||
macro. That is, PCRE can support *either* EBCDIC code *or* ASCII/UTF-8, but
|
||||
not both at once. */
|
||||
/* #undef SUPPORT_UTF8 */
|
||||
macro. That is, PCRE can support *either* EBCDIC code *or* ASCII/UTF-8/16,
|
||||
but not both at once. */
|
||||
/* #undef SUPPORT_UTF */
|
||||
|
||||
/* Version number of package */
|
||||
#ifndef VERSION
|
||||
#define VERSION "8.21"
|
||||
#define VERSION "8.30"
|
||||
#endif
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
|
||||
@@ -1,39 +1,41 @@
|
||||
diff -urN pcre.orig\pcrefinf.c pcre\pcrefinf.c
|
||||
--- pcre.orig\pcrefinf.c Wed Feb 08 01:29:30 2012
|
||||
+++ pcre\pcrefinf.c Wed Feb 08 01:29:30 2012
|
||||
@@ -139,7 +139,7 @@
|
||||
case PCRE_INFO_MINLENGTH:
|
||||
*((int *)where) =
|
||||
(study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0)?
|
||||
- study->minlength : -1;
|
||||
+ (int)study->minlength : -1;
|
||||
break;
|
||||
|
||||
case PCRE_INFO_JIT:
|
||||
diff -urN pcre.orig\pcreglob.c pcre\pcreglob.c
|
||||
--- pcre.orig\pcreglob.c Wed Feb 08 01:29:30 2012
|
||||
+++ pcre\pcreglob.c Wed Feb 08 01:29:30 2012
|
||||
@@ -74,11 +74,17 @@
|
||||
PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL;
|
||||
|
||||
#elif !defined VPCOMPAT
|
||||
+#if defined( __cplusplus ) && !defined( __IBMCPP__ )
|
||||
+extern "C" {
|
||||
+#endif
|
||||
PCRE_EXP_DATA_DEFN void *(*pcre_malloc)(size_t) = malloc;
|
||||
PCRE_EXP_DATA_DEFN void (*pcre_free)(void *) = free;
|
||||
PCRE_EXP_DATA_DEFN void *(*pcre_stack_malloc)(size_t) = malloc;
|
||||
PCRE_EXP_DATA_DEFN void (*pcre_stack_free)(void *) = free;
|
||||
PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL;
|
||||
+#if defined( __cplusplus ) && !defined( __IBMCPP__ )
|
||||
+}
|
||||
+#endif
|
||||
#endif
|
||||
|
||||
/* End of pcre_globals.c */
|
||||
diff -urN pcre.orig\pcreglob.c.rej pcre\pcreglob.c.rej
|
||||
--- pcre.orig\pcreglob.c.rej Thu Jan 01 01:00:00 1970
|
||||
+++ pcre\pcreglob.c.rej Wed Feb 08 01:46:37 2012
|
||||
@@ -0,0 +1,31 @@
|
||||
+***************
|
||||
+*** 74,84 ****
|
||||
+ PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL;
|
||||
+
|
||||
+ #elif !defined VPCOMPAT
|
||||
+ PCRE_EXP_DATA_DEFN void *(*pcre_malloc)(size_t) = malloc;
|
||||
+ PCRE_EXP_DATA_DEFN void (*pcre_free)(void *) = free;
|
||||
+ PCRE_EXP_DATA_DEFN void *(*pcre_stack_malloc)(size_t) = malloc;
|
||||
+ PCRE_EXP_DATA_DEFN void (*pcre_stack_free)(void *) = free;
|
||||
+ PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL;
|
||||
+ #endif
|
||||
+
|
||||
+ /* End of pcre_globals.c */
|
||||
+--- 74,90 ----
|
||||
+ PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL;
|
||||
+
|
||||
+ #elif !defined VPCOMPAT
|
||||
++ #if defined( __cplusplus ) && !defined( __IBMCPP__ )
|
||||
++ extern "C" {
|
||||
++ #endif
|
||||
+ PCRE_EXP_DATA_DEFN void *(*pcre_malloc)(size_t) = malloc;
|
||||
+ PCRE_EXP_DATA_DEFN void (*pcre_free)(void *) = free;
|
||||
+ PCRE_EXP_DATA_DEFN void *(*pcre_stack_malloc)(size_t) = malloc;
|
||||
+ PCRE_EXP_DATA_DEFN void (*pcre_stack_free)(void *) = free;
|
||||
+ PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL;
|
||||
++ #if defined( __cplusplus ) && !defined( __IBMCPP__ )
|
||||
++ }
|
||||
++ #endif
|
||||
+ #endif
|
||||
+
|
||||
+ /* End of pcre_globals.c */
|
||||
diff -urN pcre.orig\pcrejitc.c pcre\pcrejitc.c
|
||||
--- pcre.orig\pcrejitc.c Wed Feb 08 01:29:30 2012
|
||||
+++ pcre\pcrejitc.c Wed Feb 08 01:29:30 2012
|
||||
--- pcre.orig\pcrejitc.c Wed Feb 08 01:46:37 2012
|
||||
+++ pcre\pcrejitc.c Wed Feb 08 01:46:37 2012
|
||||
@@ -59,7 +59,7 @@
|
||||
#define SLJIT_VERBOSE 0
|
||||
#define SLJIT_DEBUG 0
|
||||
@@ -42,4 +44,4 @@ diff -urN pcre.orig\pcrejitc.c pcre\pcrejitc.c
|
||||
+#include "sjlir.c"
|
||||
|
||||
#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
|
||||
#error "Unsupported architecture"
|
||||
#error Unsupported architecture
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* This is the public header file for the PCRE library, to be #included by
|
||||
applications that call the PCRE functions.
|
||||
|
||||
Copyright (c) 1997-2011 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
/* The current PCRE version information. */
|
||||
|
||||
#define PCRE_MAJOR 8
|
||||
#define PCRE_MINOR 21
|
||||
#define PCRE_MINOR 30
|
||||
#define PCRE_PRERELEASE
|
||||
#define PCRE_DATE 2011-12-12
|
||||
#define PCRE_DATE 2012-02-04
|
||||
|
||||
/* 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
|
||||
@@ -116,9 +116,13 @@ compiling). */
|
||||
#define PCRE_NOTEOL 0x00000100 /* Exec, DFA exec */
|
||||
#define PCRE_UNGREEDY 0x00000200 /* Compile */
|
||||
#define PCRE_NOTEMPTY 0x00000400 /* Exec, DFA exec */
|
||||
#define PCRE_UTF8 0x00000800 /* Compile, used in 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 */
|
||||
#define PCRE_NO_UTF8_CHECK 0x00002000 /* Compile, exec, DFA exec */
|
||||
/* 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 */
|
||||
@@ -142,34 +146,39 @@ compiling). */
|
||||
|
||||
/* Exec-time and get/set-time error codes */
|
||||
|
||||
#define PCRE_ERROR_NOMATCH (-1)
|
||||
#define PCRE_ERROR_NULL (-2)
|
||||
#define PCRE_ERROR_BADOPTION (-3)
|
||||
#define PCRE_ERROR_BADMAGIC (-4)
|
||||
#define PCRE_ERROR_UNKNOWN_OPCODE (-5)
|
||||
#define PCRE_ERROR_UNKNOWN_NODE (-5) /* For backward compatibility */
|
||||
#define PCRE_ERROR_NOMEMORY (-6)
|
||||
#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)
|
||||
#define PCRE_ERROR_BADUTF8_OFFSET (-11)
|
||||
#define PCRE_ERROR_PARTIAL (-12)
|
||||
#define PCRE_ERROR_BADPARTIAL (-13)
|
||||
#define PCRE_ERROR_INTERNAL (-14)
|
||||
#define PCRE_ERROR_BADCOUNT (-15)
|
||||
#define PCRE_ERROR_DFA_UITEM (-16)
|
||||
#define PCRE_ERROR_DFA_UCOND (-17)
|
||||
#define PCRE_ERROR_DFA_UMLIMIT (-18)
|
||||
#define PCRE_ERROR_DFA_WSSIZE (-19)
|
||||
#define PCRE_ERROR_DFA_RECURSE (-20)
|
||||
#define PCRE_ERROR_RECURSIONLIMIT (-21)
|
||||
#define PCRE_ERROR_NULLWSLIMIT (-22) /* No longer actually used */
|
||||
#define PCRE_ERROR_BADNEWLINE (-23)
|
||||
#define PCRE_ERROR_BADOFFSET (-24)
|
||||
#define PCRE_ERROR_SHORTUTF8 (-25)
|
||||
#define PCRE_ERROR_RECURSELOOP (-26)
|
||||
#define PCRE_ERROR_JIT_STACKLIMIT (-27)
|
||||
#define PCRE_ERROR_NOMATCH (-1)
|
||||
#define PCRE_ERROR_NULL (-2)
|
||||
#define PCRE_ERROR_BADOPTION (-3)
|
||||
#define PCRE_ERROR_BADMAGIC (-4)
|
||||
#define PCRE_ERROR_UNKNOWN_OPCODE (-5)
|
||||
#define PCRE_ERROR_UNKNOWN_NODE (-5) /* For backward compatibility */
|
||||
#define PCRE_ERROR_NOMEMORY (-6)
|
||||
#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_OFFSET (-11) /* Same for 8/16 */
|
||||
#define PCRE_ERROR_BADUTF16_OFFSET (-11) /* Same for 8/16 */
|
||||
#define PCRE_ERROR_PARTIAL (-12)
|
||||
#define PCRE_ERROR_BADPARTIAL (-13)
|
||||
#define PCRE_ERROR_INTERNAL (-14)
|
||||
#define PCRE_ERROR_BADCOUNT (-15)
|
||||
#define PCRE_ERROR_DFA_UITEM (-16)
|
||||
#define PCRE_ERROR_DFA_UCOND (-17)
|
||||
#define PCRE_ERROR_DFA_UMLIMIT (-18)
|
||||
#define PCRE_ERROR_DFA_WSSIZE (-19)
|
||||
#define PCRE_ERROR_DFA_RECURSE (-20)
|
||||
#define PCRE_ERROR_RECURSIONLIMIT (-21)
|
||||
#define PCRE_ERROR_NULLWSLIMIT (-22) /* No longer actually used */
|
||||
#define PCRE_ERROR_BADNEWLINE (-23)
|
||||
#define PCRE_ERROR_BADOFFSET (-24)
|
||||
#define PCRE_ERROR_SHORTUTF8 (-25)
|
||||
#define PCRE_ERROR_SHORTUTF16 (-25) /* Same for 8/16 */
|
||||
#define PCRE_ERROR_RECURSELOOP (-26)
|
||||
#define PCRE_ERROR_JIT_STACKLIMIT (-27)
|
||||
#define PCRE_ERROR_BADMODE (-28)
|
||||
#define PCRE_ERROR_BADENDIANNESS (-29)
|
||||
|
||||
/* Specific error codes for UTF-8 validity checks */
|
||||
|
||||
@@ -196,6 +205,14 @@ compiling). */
|
||||
#define PCRE_UTF8_ERR20 20
|
||||
#define PCRE_UTF8_ERR21 21
|
||||
|
||||
/* Specific error codes for UTF-16 validity checks */
|
||||
|
||||
#define PCRE_UTF16_ERR0 0
|
||||
#define PCRE_UTF16_ERR1 1
|
||||
#define PCRE_UTF16_ERR2 2
|
||||
#define PCRE_UTF16_ERR3 3
|
||||
#define PCRE_UTF16_ERR4 4
|
||||
|
||||
/* Request types for pcre_fullinfo() */
|
||||
|
||||
#define PCRE_INFO_OPTIONS 0
|
||||
@@ -231,13 +248,15 @@ compatible. */
|
||||
#define PCRE_CONFIG_MATCH_LIMIT_RECURSION 7
|
||||
#define PCRE_CONFIG_BSR 8
|
||||
#define PCRE_CONFIG_JIT 9
|
||||
#define PCRE_CONFIG_UTF16 10
|
||||
#define PCRE_CONFIG_JITTARGET 11
|
||||
|
||||
/* Request types for pcre_study(). Do not re-arrange, in order to remain
|
||||
compatible. */
|
||||
|
||||
#define PCRE_STUDY_JIT_COMPILE 0x0001
|
||||
|
||||
/* Bit flags for the pcre_extra structure. Do not re-arrange or redefine
|
||||
/* Bit flags for the pcre[16]_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
|
||||
@@ -253,9 +272,26 @@ these bits, just add new ones on the end, in order to remain compatible. */
|
||||
struct real_pcre; /* declaration; the definition is private */
|
||||
typedef struct real_pcre pcre;
|
||||
|
||||
struct real_pcre16; /* declaration; the definition is private */
|
||||
typedef struct real_pcre16 pcre16;
|
||||
|
||||
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;
|
||||
|
||||
/* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must contain
|
||||
a 16 bit wide signed data type. Otherwise it can be a dummy data type since
|
||||
pcre16 functions are not implemented. There is a check for this in pcre_internal.h. */
|
||||
#ifndef PCRE_UCHAR16
|
||||
#define PCRE_UCHAR16 unsigned short
|
||||
#endif
|
||||
|
||||
#ifndef PCRE_SPTR16
|
||||
#define PCRE_SPTR16 const PCRE_UCHAR16 *
|
||||
#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 *. */
|
||||
@@ -279,6 +315,19 @@ typedef struct pcre_extra {
|
||||
void *executable_jit; /* Contains a pointer to a compiled jit code */
|
||||
} pcre_extra;
|
||||
|
||||
/* Same structure as above, but with 16 bit char pointers. */
|
||||
|
||||
typedef struct pcre16_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_UCHAR16 **mark; /* For passing back a mark pointer */
|
||||
void *executable_jit; /* Contains a pointer to a compiled jit code */
|
||||
} pcre16_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
|
||||
@@ -304,6 +353,28 @@ typedef struct pcre_callout_block {
|
||||
/* ------------------------------------------------------------------ */
|
||||
} pcre_callout_block;
|
||||
|
||||
/* Same structure as above, but with 16 bit char pointers. */
|
||||
|
||||
typedef struct pcre16_callout_block {
|
||||
int version; /* Identifies version of block */
|
||||
/* ------------------------ Version 0 ------------------------------- */
|
||||
int callout_number; /* Number compiled into pattern */
|
||||
int *offset_vector; /* The offset vector */
|
||||
PCRE_SPTR16 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_UCHAR16 *mark; /* Pointer to current mark or NULL */
|
||||
/* ------------------------------------------------------------------ */
|
||||
} pcre16_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
|
||||
@@ -316,58 +387,114 @@ PCRE_EXP_DECL void (*pcre_free)(void *);
|
||||
PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t);
|
||||
PCRE_EXP_DECL void (*pcre_stack_free)(void *);
|
||||
PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *);
|
||||
|
||||
PCRE_EXP_DECL void *(*pcre16_malloc)(size_t);
|
||||
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 *);
|
||||
#else /* VPCOMPAT */
|
||||
PCRE_EXP_DECL void *pcre_malloc(size_t);
|
||||
PCRE_EXP_DECL void pcre_free(void *);
|
||||
PCRE_EXP_DECL void *pcre_stack_malloc(size_t);
|
||||
PCRE_EXP_DECL void pcre_stack_free(void *);
|
||||
PCRE_EXP_DECL int pcre_callout(pcre_callout_block *);
|
||||
|
||||
PCRE_EXP_DECL void *pcre16_malloc(size_t);
|
||||
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 *);
|
||||
#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 *);
|
||||
|
||||
/* Exported PCRE functions */
|
||||
|
||||
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 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 int pcre_config(int, void *);
|
||||
PCRE_EXP_DECL int pcre16_config(int, void *);
|
||||
PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *,
|
||||
int *, int, const char *, char *, int);
|
||||
PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int, 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 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 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 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 void pcre_free_substring(const char *);
|
||||
PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16);
|
||||
PCRE_EXP_DECL void pcre_free_substring_list(const char **);
|
||||
PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *);
|
||||
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 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 pcre_get_stringnumber(const pcre *, const char *);
|
||||
PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16);
|
||||
PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *,
|
||||
char **, char **);
|
||||
PCRE_EXP_DECL int pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR16,
|
||||
PCRE_UCHAR16 **, PCRE_UCHAR16 **);
|
||||
PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int,
|
||||
const char **);
|
||||
PCRE_EXP_DECL int pcre16_get_substring(PCRE_SPTR16, int *, int, int,
|
||||
PCRE_SPTR16 *);
|
||||
PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int,
|
||||
const char ***);
|
||||
PCRE_EXP_DECL int pcre_info(const pcre *, int *, int *);
|
||||
PCRE_EXP_DECL int pcre16_get_substring_list(PCRE_SPTR16, int *, int,
|
||||
PCRE_SPTR16 **);
|
||||
PCRE_EXP_DECL const unsigned char *pcre_maketables(void);
|
||||
PCRE_EXP_DECL const unsigned char *pcre16_maketables(void);
|
||||
PCRE_EXP_DECL int pcre_refcount(pcre *, int);
|
||||
PCRE_EXP_DECL int pcre16_refcount(pcre16 *, 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 void pcre_free_study(pcre_extra *);
|
||||
PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *);
|
||||
PCRE_EXP_DECL const char *pcre_version(void);
|
||||
PCRE_EXP_DECL const char *pcre16_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 pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *,
|
||||
PCRE_SPTR16, 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 void pcre_jit_stack_free(pcre_jit_stack *);
|
||||
PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *, pcre_jit_callback, void *);
|
||||
PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_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 *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2011 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -45,6 +45,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* Keep the original link size. */
|
||||
static int real_link_size = LINK_SIZE;
|
||||
|
||||
#include "pcreinal.h"
|
||||
|
||||
|
||||
@@ -62,18 +65,41 @@ Arguments:
|
||||
Returns: 0 if data returned, negative on error
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_config(int what, void *where)
|
||||
#else
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_config(int what, void *where)
|
||||
#endif
|
||||
{
|
||||
switch (what)
|
||||
{
|
||||
case PCRE_CONFIG_UTF8:
|
||||
#ifdef SUPPORT_UTF8
|
||||
#if defined COMPILE_PCRE16
|
||||
*((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_UTF16:
|
||||
#if defined COMPILE_PCRE8
|
||||
*((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_UNICODE_PROPERTIES:
|
||||
#ifdef SUPPORT_UCP
|
||||
@@ -91,6 +117,14 @@ switch (what)
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PCRE_CONFIG_JITTARGET:
|
||||
#ifdef SUPPORT_JIT
|
||||
*((const char **)where) = PRIV(jit_get_target)();
|
||||
#else
|
||||
*((const char **)where) = NULL;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PCRE_CONFIG_NEWLINE:
|
||||
*((int *)where) = NEWLINE;
|
||||
break;
|
||||
@@ -104,7 +138,7 @@ switch (what)
|
||||
break;
|
||||
|
||||
case PCRE_CONFIG_LINK_SIZE:
|
||||
*((int *)where) = LINK_SIZE;
|
||||
*((int *)where) = real_link_size;
|
||||
break;
|
||||
|
||||
case PCRE_CONFIG_POSIX_MALLOC_THRESHOLD:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2011 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -65,13 +65,17 @@ Arguments:
|
||||
Returns: 0 if data returned, negative on error
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data, int what,
|
||||
void *where)
|
||||
pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data,
|
||||
int what, void *where)
|
||||
#else
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_fullinfo(const pcre16 *argument_re, const pcre16_extra *extra_data,
|
||||
int what, void *where)
|
||||
#endif
|
||||
{
|
||||
real_pcre internal_re;
|
||||
pcre_study_data internal_study;
|
||||
const real_pcre *re = (const real_pcre *)argument_re;
|
||||
const REAL_PCRE *re = (const REAL_PCRE *)argument_re;
|
||||
const pcre_study_data *study = NULL;
|
||||
|
||||
if (re == NULL || where == NULL) return PCRE_ERROR_NULL;
|
||||
@@ -79,12 +83,18 @@ if (re == NULL || where == NULL) return PCRE_ERROR_NULL;
|
||||
if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0)
|
||||
study = (const pcre_study_data *)extra_data->study_data;
|
||||
|
||||
/* Check that the first field in the block is the magic number. If it is not,
|
||||
return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to
|
||||
REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which
|
||||
means that the pattern is likely compiled with different endianness. */
|
||||
|
||||
if (re->magic_number != MAGIC_NUMBER)
|
||||
{
|
||||
re = _pcre_try_flipped(re, &internal_re, study, &internal_study);
|
||||
if (re == NULL) return PCRE_ERROR_BADMAGIC;
|
||||
if (study != NULL) study = &internal_study;
|
||||
}
|
||||
return re->magic_number == REVERSED_MAGIC_NUMBER?
|
||||
PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC;
|
||||
|
||||
/* Check that this pattern was compiled in the correct bit mode */
|
||||
|
||||
if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
|
||||
|
||||
switch (what)
|
||||
{
|
||||
@@ -106,11 +116,10 @@ switch (what)
|
||||
(extra_data != NULL &&
|
||||
(extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
|
||||
extra_data->executable_jit != NULL)?
|
||||
_pcre_jit_get_size(extra_data->executable_jit) : 0;
|
||||
PRIV(jit_get_size)(extra_data->executable_jit) : 0;
|
||||
#else
|
||||
*((size_t *)where) = 0;
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case PCRE_INFO_CAPTURECOUNT:
|
||||
@@ -123,7 +132,7 @@ switch (what)
|
||||
|
||||
case PCRE_INFO_FIRSTBYTE:
|
||||
*((int *)where) =
|
||||
((re->flags & PCRE_FIRSTSET) != 0)? re->first_byte :
|
||||
((re->flags & PCRE_FIRSTSET) != 0)? re->first_char :
|
||||
((re->flags & PCRE_STARTLINE) != 0)? -1 : -2;
|
||||
break;
|
||||
|
||||
@@ -131,7 +140,7 @@ switch (what)
|
||||
block, not the internal copy (with flipped integer fields). */
|
||||
|
||||
case PCRE_INFO_FIRSTTABLE:
|
||||
*((const uschar **)where) =
|
||||
*((const pcre_uint8 **)where) =
|
||||
(study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)?
|
||||
((const pcre_study_data *)extra_data->study_data)->start_bits : NULL;
|
||||
break;
|
||||
@@ -139,7 +148,7 @@ switch (what)
|
||||
case PCRE_INFO_MINLENGTH:
|
||||
*((int *)where) =
|
||||
(study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0)?
|
||||
(int)study->minlength : -1;
|
||||
(int)(study->minlength) : -1;
|
||||
break;
|
||||
|
||||
case PCRE_INFO_JIT:
|
||||
@@ -150,7 +159,7 @@ switch (what)
|
||||
|
||||
case PCRE_INFO_LASTLITERAL:
|
||||
*((int *)where) =
|
||||
((re->flags & PCRE_REQCHSET) != 0)? re->req_byte : -1;
|
||||
((re->flags & PCRE_REQCHSET) != 0)? re->req_char : -1;
|
||||
break;
|
||||
|
||||
case PCRE_INFO_NAMEENTRYSIZE:
|
||||
@@ -162,11 +171,11 @@ switch (what)
|
||||
break;
|
||||
|
||||
case PCRE_INFO_NAMETABLE:
|
||||
*((const uschar **)where) = (const uschar *)re + re->name_table_offset;
|
||||
*((const pcre_uchar **)where) = (const pcre_uchar *)re + re->name_table_offset;
|
||||
break;
|
||||
|
||||
case PCRE_INFO_DEFAULT_TABLES:
|
||||
*((const uschar **)where) = (const uschar *)(_pcre_default_tables);
|
||||
*((const pcre_uint8 **)where) = (const pcre_uint8 *)(PRIV(default_tables));
|
||||
break;
|
||||
|
||||
/* From release 8.00 this will always return TRUE because NOPARTIAL is
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2008 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -65,14 +65,20 @@ Returns: the number of the named parentheses, or a negative number
|
||||
(PCRE_ERROR_NOSUBSTRING) if not found
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_get_stringnumber(const pcre *code, const char *stringname)
|
||||
#else
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_get_stringnumber(const pcre16 *code, PCRE_SPTR16 stringname)
|
||||
#endif
|
||||
{
|
||||
int rc;
|
||||
int entrysize;
|
||||
int top, bot;
|
||||
uschar *nametable;
|
||||
pcre_uchar *nametable;
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
|
||||
return rc;
|
||||
if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
|
||||
@@ -81,14 +87,26 @@ if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
|
||||
return rc;
|
||||
if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
|
||||
return rc;
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE16
|
||||
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
|
||||
return rc;
|
||||
if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
|
||||
|
||||
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
|
||||
return rc;
|
||||
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
bot = 0;
|
||||
while (top > bot)
|
||||
{
|
||||
int mid = (top + bot) / 2;
|
||||
uschar *entry = nametable + entrysize*mid;
|
||||
int c = strcmp(stringname, (char *)(entry + 2));
|
||||
if (c == 0) return (entry[0] << 8) + entry[1];
|
||||
pcre_uchar *entry = nametable + entrysize*mid;
|
||||
int c = STRCMP_UC_UC((pcre_uchar *)stringname,
|
||||
(pcre_uchar *)(entry + IMM2_SIZE));
|
||||
if (c == 0) return GET2(entry, 0);
|
||||
if (c > 0) bot = mid + 1; else top = mid;
|
||||
}
|
||||
|
||||
@@ -114,15 +132,22 @@ Returns: the length of each entry, or a negative number
|
||||
(PCRE_ERROR_NOSUBSTRING) if not found
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_get_stringtable_entries(const pcre *code, const char *stringname,
|
||||
char **firstptr, char **lastptr)
|
||||
#else
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 stringname,
|
||||
PCRE_UCHAR16 **firstptr, PCRE_UCHAR16 **lastptr)
|
||||
#endif
|
||||
{
|
||||
int rc;
|
||||
int entrysize;
|
||||
int top, bot;
|
||||
uschar *nametable, *lastentry;
|
||||
pcre_uchar *nametable, *lastentry;
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
|
||||
return rc;
|
||||
if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
|
||||
@@ -131,30 +156,49 @@ if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
|
||||
return rc;
|
||||
if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
|
||||
return rc;
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE16
|
||||
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
|
||||
return rc;
|
||||
if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
|
||||
|
||||
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
|
||||
return rc;
|
||||
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
lastentry = nametable + entrysize * (top - 1);
|
||||
bot = 0;
|
||||
while (top > bot)
|
||||
{
|
||||
int mid = (top + bot) / 2;
|
||||
uschar *entry = nametable + entrysize*mid;
|
||||
int c = strcmp(stringname, (char *)(entry + 2));
|
||||
pcre_uchar *entry = nametable + entrysize*mid;
|
||||
int c = STRCMP_UC_UC((pcre_uchar *)stringname,
|
||||
(pcre_uchar *)(entry + IMM2_SIZE));
|
||||
if (c == 0)
|
||||
{
|
||||
uschar *first = entry;
|
||||
uschar *last = entry;
|
||||
pcre_uchar *first = entry;
|
||||
pcre_uchar *last = entry;
|
||||
while (first > nametable)
|
||||
{
|
||||
if (strcmp(stringname, (char *)(first - entrysize + 2)) != 0) break;
|
||||
if (STRCMP_UC_UC((pcre_uchar *)stringname,
|
||||
(pcre_uchar *)(first - entrysize + IMM2_SIZE)) != 0) break;
|
||||
first -= entrysize;
|
||||
}
|
||||
while (last < lastentry)
|
||||
{
|
||||
if (strcmp(stringname, (char *)(last + entrysize + 2)) != 0) break;
|
||||
if (STRCMP_UC_UC((pcre_uchar *)stringname,
|
||||
(pcre_uchar *)(last + entrysize + IMM2_SIZE)) != 0) break;
|
||||
last += entrysize;
|
||||
}
|
||||
#ifdef COMPILE_PCRE8
|
||||
*firstptr = (char *)first;
|
||||
*lastptr = (char *)last;
|
||||
#else
|
||||
*firstptr = (PCRE_UCHAR16 *)first;
|
||||
*lastptr = (PCRE_UCHAR16 *)last;
|
||||
#endif
|
||||
return entrysize;
|
||||
}
|
||||
if (c > 0) bot = mid + 1; else top = mid;
|
||||
@@ -182,23 +226,39 @@ Returns: the number of the first that is set,
|
||||
or a negative number on error
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
static int
|
||||
get_first_set(const pcre *code, const char *stringname, int *ovector)
|
||||
#else
|
||||
static int
|
||||
get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector)
|
||||
#endif
|
||||
{
|
||||
const real_pcre *re = (const real_pcre *)code;
|
||||
const REAL_PCRE *re = (const REAL_PCRE *)code;
|
||||
int entrysize;
|
||||
pcre_uchar *entry;
|
||||
#ifdef COMPILE_PCRE8
|
||||
char *first, *last;
|
||||
uschar *entry;
|
||||
#else
|
||||
PCRE_UCHAR16 *first, *last;
|
||||
#endif
|
||||
|
||||
#ifdef 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
|
||||
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);
|
||||
#endif
|
||||
if (entrysize <= 0) return entrysize;
|
||||
for (entry = (uschar *)first; entry <= (uschar *)last; entry += entrysize)
|
||||
for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize)
|
||||
{
|
||||
int n = (entry[0] << 8) + entry[1];
|
||||
int n = GET2(entry, 0);
|
||||
if (ovector[n*2] >= 0) return n;
|
||||
}
|
||||
return (first[0] << 8) + first[1];
|
||||
return GET2(entry, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -231,9 +291,15 @@ Returns: if successful:
|
||||
PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
|
||||
*/
|
||||
|
||||
#ifdef 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
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
|
||||
int stringnumber, PCRE_UCHAR16 *buffer, int size)
|
||||
#endif
|
||||
{
|
||||
int yield;
|
||||
if (stringnumber < 0 || stringnumber >= stringcount)
|
||||
@@ -241,7 +307,7 @@ if (stringnumber < 0 || stringnumber >= stringcount)
|
||||
stringnumber *= 2;
|
||||
yield = ovector[stringnumber+1] - ovector[stringnumber];
|
||||
if (size < yield + 1) return PCRE_ERROR_NOMEMORY;
|
||||
memcpy(buffer, subject + ovector[stringnumber], yield);
|
||||
memcpy(buffer, subject + ovector[stringnumber], IN_UCHARS(yield));
|
||||
buffer[yield] = 0;
|
||||
return yield;
|
||||
}
|
||||
@@ -276,13 +342,25 @@ Returns: if successful:
|
||||
PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
|
||||
*/
|
||||
|
||||
#ifdef 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)
|
||||
pcre_copy_named_substring(const pcre *code, const char *subject,
|
||||
int *ovector, int stringcount, const char *stringname,
|
||||
char *buffer, int size)
|
||||
#else
|
||||
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)
|
||||
#endif
|
||||
{
|
||||
int n = get_first_set(code, stringname, ovector);
|
||||
if (n <= 0) return n;
|
||||
#ifdef COMPILE_PCRE8
|
||||
return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
|
||||
#else
|
||||
return pcre16_copy_substring(subject, ovector, stringcount, n, buffer, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -308,29 +386,39 @@ Returns: if successful: 0
|
||||
PCRE_ERROR_NOMEMORY (-6) failed to get store
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_get_substring_list(const char *subject, int *ovector, int stringcount,
|
||||
const char ***listptr)
|
||||
#else
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount,
|
||||
PCRE_SPTR16 **listptr)
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
int size = sizeof(char *);
|
||||
int size = sizeof(pcre_uchar *);
|
||||
int double_count = stringcount * 2;
|
||||
char **stringlist;
|
||||
char *p;
|
||||
pcre_uchar **stringlist;
|
||||
pcre_uchar *p;
|
||||
|
||||
for (i = 0; i < double_count; i += 2)
|
||||
size += sizeof(char *) + ovector[i+1] - ovector[i] + 1;
|
||||
size += sizeof(pcre_uchar *) + IN_UCHARS(ovector[i+1] - ovector[i] + 1);
|
||||
|
||||
stringlist = (char **)(pcre_malloc)(size);
|
||||
stringlist = (pcre_uchar **)(PUBL(malloc))(size);
|
||||
if (stringlist == NULL) return PCRE_ERROR_NOMEMORY;
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
*listptr = (const char **)stringlist;
|
||||
p = (char *)(stringlist + stringcount + 1);
|
||||
#else
|
||||
*listptr = (PCRE_SPTR16 *)stringlist;
|
||||
#endif
|
||||
p = (pcre_uchar *)(stringlist + stringcount + 1);
|
||||
|
||||
for (i = 0; i < double_count; i += 2)
|
||||
{
|
||||
int len = ovector[i+1] - ovector[i];
|
||||
memcpy(p, subject + ovector[i], len);
|
||||
memcpy(p, subject + ovector[i], IN_UCHARS(len));
|
||||
*stringlist++ = p;
|
||||
p += len;
|
||||
*p++ = 0;
|
||||
@@ -347,16 +435,22 @@ return 0;
|
||||
*************************************************/
|
||||
|
||||
/* This function exists for the benefit of people calling PCRE from non-C
|
||||
programs that can call its functions, but not free() or (pcre_free)() directly.
|
||||
programs that can call its functions, but not free() or (PUBL(free))()
|
||||
directly.
|
||||
|
||||
Argument: the result of a previous pcre_get_substring_list()
|
||||
Returns: nothing
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
|
||||
pcre_free_substring_list(const char **pointer)
|
||||
#else
|
||||
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
|
||||
pcre16_free_substring_list(PCRE_SPTR16 *pointer)
|
||||
#endif
|
||||
{
|
||||
(pcre_free)((void *)pointer);
|
||||
(PUBL(free))((void *)pointer);
|
||||
}
|
||||
|
||||
|
||||
@@ -386,21 +480,31 @@ Returns: if successful:
|
||||
PCRE_ERROR_NOSUBSTRING (-7) substring not present
|
||||
*/
|
||||
|
||||
#ifdef 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
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
|
||||
int stringnumber, PCRE_SPTR16 *stringptr)
|
||||
#endif
|
||||
{
|
||||
int yield;
|
||||
char *substring;
|
||||
pcre_uchar *substring;
|
||||
if (stringnumber < 0 || stringnumber >= stringcount)
|
||||
return PCRE_ERROR_NOSUBSTRING;
|
||||
stringnumber *= 2;
|
||||
yield = ovector[stringnumber+1] - ovector[stringnumber];
|
||||
substring = (char *)(pcre_malloc)(yield + 1);
|
||||
substring = (pcre_uchar *)(PUBL(malloc))(IN_UCHARS(yield + 1));
|
||||
if (substring == NULL) return PCRE_ERROR_NOMEMORY;
|
||||
memcpy(substring, subject + ovector[stringnumber], yield);
|
||||
memcpy(substring, subject + ovector[stringnumber], IN_UCHARS(yield));
|
||||
substring[yield] = 0;
|
||||
*stringptr = substring;
|
||||
#ifdef COMPILE_PCRE8
|
||||
*stringptr = (const char *)substring;
|
||||
#else
|
||||
*stringptr = (PCRE_SPTR16)substring;
|
||||
#endif
|
||||
return yield;
|
||||
}
|
||||
|
||||
@@ -433,13 +537,25 @@ Returns: if successful:
|
||||
PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
|
||||
*/
|
||||
|
||||
#ifdef 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)
|
||||
pcre_get_named_substring(const pcre *code, const char *subject,
|
||||
int *ovector, int stringcount, const char *stringname,
|
||||
const char **stringptr)
|
||||
#else
|
||||
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)
|
||||
#endif
|
||||
{
|
||||
int n = get_first_set(code, stringname, ovector);
|
||||
if (n <= 0) return n;
|
||||
#ifdef COMPILE_PCRE8
|
||||
return pcre_get_substring(subject, ovector, stringcount, n, stringptr);
|
||||
#else
|
||||
return pcre16_get_substring(subject, ovector, stringcount, n, stringptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -450,16 +566,22 @@ return pcre_get_substring(subject, ovector, stringcount, n, stringptr);
|
||||
*************************************************/
|
||||
|
||||
/* This function exists for the benefit of people calling PCRE from non-C
|
||||
programs that can call its functions, but not free() or (pcre_free)() directly.
|
||||
programs that can call its functions, but not free() or (PUBL(free))()
|
||||
directly.
|
||||
|
||||
Argument: the result of a previous pcre_get_substring()
|
||||
Returns: nothing
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
|
||||
pcre_free_substring(const char *pointer)
|
||||
#else
|
||||
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
|
||||
pcre16_free_substring(PCRE_SPTR16 pointer)
|
||||
#endif
|
||||
{
|
||||
(pcre_free)((void *)pointer);
|
||||
(PUBL(free))((void *)pointer);
|
||||
}
|
||||
|
||||
/* End of pcre_get.c */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2008 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -67,24 +67,18 @@ static void LocalPcreFree(void* aPtr)
|
||||
{
|
||||
free(aPtr);
|
||||
}
|
||||
PCRE_EXP_DATA_DEFN void *(*pcre_malloc)(size_t) = LocalPcreMalloc;
|
||||
PCRE_EXP_DATA_DEFN void (*pcre_free)(void *) = LocalPcreFree;
|
||||
PCRE_EXP_DATA_DEFN void *(*pcre_stack_malloc)(size_t) = LocalPcreMalloc;
|
||||
PCRE_EXP_DATA_DEFN void (*pcre_stack_free)(void *) = LocalPcreFree;
|
||||
PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL;
|
||||
PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = LocalPcreMalloc;
|
||||
PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = LocalPcreFree;
|
||||
PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = LocalPcreMalloc;
|
||||
PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = LocalPcreFree;
|
||||
PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL;
|
||||
|
||||
#elif !defined VPCOMPAT
|
||||
#if defined( __cplusplus ) && !defined( __IBMCPP__ )
|
||||
extern "C" {
|
||||
#endif
|
||||
PCRE_EXP_DATA_DEFN void *(*pcre_malloc)(size_t) = malloc;
|
||||
PCRE_EXP_DATA_DEFN void (*pcre_free)(void *) = free;
|
||||
PCRE_EXP_DATA_DEFN void *(*pcre_stack_malloc)(size_t) = malloc;
|
||||
PCRE_EXP_DATA_DEFN void (*pcre_stack_free)(void *) = free;
|
||||
PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL;
|
||||
#if defined( __cplusplus ) && !defined( __IBMCPP__ )
|
||||
}
|
||||
#endif
|
||||
PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = malloc;
|
||||
PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = free;
|
||||
PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = malloc;
|
||||
PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = free;
|
||||
PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL;
|
||||
#endif
|
||||
|
||||
/* End of pcre_globals.c */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,93 +0,0 @@
|
||||
/*************************************************
|
||||
* Perl-Compatible Regular Expressions *
|
||||
*************************************************/
|
||||
|
||||
/* PCRE is a library of functions to support regular expressions whose syntax
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2009 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* 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.
|
||||
|
||||
* Neither the name of the University of Cambridge nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 OWNER 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.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/* This module contains the external function pcre_info(), which gives some
|
||||
information about a compiled pattern. However, use of this function is now
|
||||
deprecated, as it has been superseded by pcre_fullinfo(). */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcreinal.h"
|
||||
|
||||
|
||||
/*************************************************
|
||||
* (Obsolete) Return info about compiled pattern *
|
||||
*************************************************/
|
||||
|
||||
/* This is the original "info" function. It picks potentially useful data out
|
||||
of the private structure, but its interface was too rigid. It remains for
|
||||
backwards compatibility. The public options are passed back in an int - though
|
||||
the re->options field has been expanded to a long int, all the public options
|
||||
at the low end of it, and so even on 16-bit systems this will still be OK.
|
||||
Therefore, I haven't changed the API for pcre_info().
|
||||
|
||||
Arguments:
|
||||
argument_re points to compiled code
|
||||
optptr where to pass back the options
|
||||
first_byte where to pass back the first character,
|
||||
or -1 if multiline and all branches start ^,
|
||||
or -2 otherwise
|
||||
|
||||
Returns: number of capturing subpatterns
|
||||
or negative values on error
|
||||
*/
|
||||
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_info(const pcre *argument_re, int *optptr, int *first_byte)
|
||||
{
|
||||
real_pcre internal_re;
|
||||
const real_pcre *re = (const real_pcre *)argument_re;
|
||||
if (re == NULL) return PCRE_ERROR_NULL;
|
||||
if (re->magic_number != MAGIC_NUMBER)
|
||||
{
|
||||
re = _pcre_try_flipped(re, &internal_re, NULL, NULL);
|
||||
if (re == NULL) return PCRE_ERROR_BADMAGIC;
|
||||
}
|
||||
if (optptr != NULL) *optptr = (int)(re->options & PUBLIC_COMPILE_OPTIONS);
|
||||
if (first_byte != NULL)
|
||||
*first_byte = ((re->flags & PCRE_FIRSTSET) != 0)? re->first_byte :
|
||||
((re->flags & PCRE_STARTLINE) != 0)? -1 : -2;
|
||||
return re->top_bracket;
|
||||
}
|
||||
|
||||
/* End of pcre_info.c */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2008 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -59,21 +59,26 @@ compilation of dftables.c, in which case the macro DFTABLES is defined. */
|
||||
/* This function builds a set of character tables for use by PCRE and returns
|
||||
a pointer to them. They are build using the ctype functions, and consequently
|
||||
their contents will depend upon the current locale setting. When compiled as
|
||||
part of the library, the store is obtained via pcre_malloc(), but when compiled
|
||||
inside dftables, use malloc().
|
||||
part of the library, the store is obtained via PUBL(malloc)(), but when
|
||||
compiled inside dftables, use malloc().
|
||||
|
||||
Arguments: none
|
||||
Returns: pointer to the contiguous block of data
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
const unsigned char *
|
||||
pcre_maketables(void)
|
||||
#else
|
||||
const unsigned char *
|
||||
pcre16_maketables(void)
|
||||
#endif
|
||||
{
|
||||
unsigned char *yield, *p;
|
||||
int i;
|
||||
|
||||
#ifndef DFTABLES
|
||||
yield = (unsigned char*)(pcre_malloc)(tables_length);
|
||||
yield = (unsigned char*)(PUBL(malloc))(tables_length);
|
||||
#else
|
||||
yield = (unsigned char*)malloc(tables_length);
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2009 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -67,16 +67,25 @@ Arguments:
|
||||
type the newline type
|
||||
endptr pointer to the end of the string
|
||||
lenptr where to return the length
|
||||
utf8 TRUE if in utf8 mode
|
||||
utf TRUE if in utf mode
|
||||
|
||||
Returns: TRUE or FALSE
|
||||
*/
|
||||
|
||||
BOOL
|
||||
_pcre_is_newline(USPTR ptr, int type, USPTR endptr, int *lenptr, BOOL utf8)
|
||||
PRIV(is_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR endptr, int *lenptr,
|
||||
BOOL utf)
|
||||
{
|
||||
int c;
|
||||
if (utf8) { GETCHAR(c, ptr); } else c = *ptr;
|
||||
(void)utf;
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf)
|
||||
{
|
||||
GETCHAR(c, ptr);
|
||||
}
|
||||
else
|
||||
#endif /* SUPPORT_UTF */
|
||||
c = *ptr;
|
||||
|
||||
if (type == NLTYPE_ANYCRLF) switch(c)
|
||||
{
|
||||
@@ -95,9 +104,15 @@ else switch(c)
|
||||
case 0x000c: *lenptr = 1; return TRUE; /* FF */
|
||||
case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1;
|
||||
return TRUE; /* CR */
|
||||
case 0x0085: *lenptr = utf8? 2 : 1; return TRUE; /* NEL */
|
||||
#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 0x2028: /* LS */
|
||||
case 0x2029: *lenptr = 1; return TRUE; /* PS */
|
||||
#endif /* COMPILE_PCRE8 */
|
||||
default: return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -116,26 +131,27 @@ Arguments:
|
||||
type the newline type
|
||||
startptr pointer to the start of the string
|
||||
lenptr where to return the length
|
||||
utf8 TRUE if in utf8 mode
|
||||
utf TRUE if in utf mode
|
||||
|
||||
Returns: TRUE or FALSE
|
||||
*/
|
||||
|
||||
BOOL
|
||||
_pcre_was_newline(USPTR ptr, int type, USPTR startptr, int *lenptr, BOOL utf8)
|
||||
PRIV(was_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR startptr, int *lenptr,
|
||||
BOOL utf)
|
||||
{
|
||||
int c;
|
||||
(void)utf;
|
||||
ptr--;
|
||||
#ifdef SUPPORT_UTF8
|
||||
if (utf8)
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf)
|
||||
{
|
||||
BACKCHAR(ptr);
|
||||
GETCHAR(c, ptr);
|
||||
}
|
||||
else c = *ptr;
|
||||
#else /* no UTF-8 support */
|
||||
c = *ptr;
|
||||
#endif /* SUPPORT_UTF8 */
|
||||
else
|
||||
#endif /* SUPPORT_UTF */
|
||||
c = *ptr;
|
||||
|
||||
if (type == NLTYPE_ANYCRLF) switch(c)
|
||||
{
|
||||
@@ -152,9 +168,15 @@ else switch(c)
|
||||
case 0x000b: /* VT */
|
||||
case 0x000c: /* FF */
|
||||
case 0x000d: *lenptr = 1; return TRUE; /* CR */
|
||||
case 0x0085: *lenptr = utf8? 2 : 1; return TRUE; /* NEL */
|
||||
#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 0x2028: /* LS */
|
||||
case 0x2029: *lenptr = 1; return TRUE; /* PS */
|
||||
#endif /* COMPILE_PCRE8 */
|
||||
default: return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2008 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -52,35 +52,45 @@ character value into a UTF8 string. */
|
||||
* Convert character value to UTF-8 *
|
||||
*************************************************/
|
||||
|
||||
/* This function takes an integer value in the range 0 - 0x7fffffff
|
||||
and encodes it as a UTF-8 character in 0 to 6 bytes.
|
||||
/* 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.
|
||||
|
||||
Arguments:
|
||||
cvalue the character value
|
||||
buffer pointer to buffer for result - at least 6 bytes long
|
||||
buffer pointer to buffer for result - at least 6 pcre_uchars long
|
||||
|
||||
Returns: number of characters placed in the buffer
|
||||
*/
|
||||
|
||||
int
|
||||
_pcre_ord2utf8(int cvalue, uschar *buffer)
|
||||
PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer)
|
||||
{
|
||||
#ifdef SUPPORT_UTF8
|
||||
#ifdef SUPPORT_UTF
|
||||
|
||||
register int i, j;
|
||||
for (i = 0; i < _pcre_utf8_table1_size; i++)
|
||||
if (cvalue <= _pcre_utf8_table1[i]) break;
|
||||
|
||||
/* 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;
|
||||
for (j = i; j > 0; j--)
|
||||
{
|
||||
*buffer-- = 0x80 | (cvalue & 0x3f);
|
||||
cvalue >>= 6;
|
||||
}
|
||||
*buffer = _pcre_utf8_table2[i] | cvalue;
|
||||
*buffer = PRIV(utf8_table2)[i] | cvalue;
|
||||
return i + 1;
|
||||
|
||||
#else
|
||||
|
||||
(void)(cvalue); /* Keep compiler happy; this function won't ever be */
|
||||
(void)(buffer); /* called when SUPPORT_UTF8 is not defined. */
|
||||
(void)(buffer); /* called when SUPPORT_UTF is not defined. */
|
||||
return 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2010 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -44,16 +44,50 @@ local functions. This source file is used in two places:
|
||||
|
||||
(1) It is #included by pcre_compile.c when it is compiled in debugging mode
|
||||
(PCRE_DEBUG defined in pcre_internal.h). It is not included in production
|
||||
compiles.
|
||||
compiles. In this case PCRE_INCLUDED is defined.
|
||||
|
||||
(2) It is always #included by pcretest.c, which can be asked to print out a
|
||||
compiled regex for debugging purposes. */
|
||||
(2) It is also compiled separately and linked with pcretest.c, which can be
|
||||
asked to print out a compiled regex for debugging purposes. */
|
||||
|
||||
#ifndef PCRE_INCLUDED
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* For pcretest program. */
|
||||
#define PRIV(name) name
|
||||
|
||||
/* We have to include pcre_internal.h because we need the internal info for
|
||||
displaying the results of pcre_study() and we also need to know about the
|
||||
internal macros, structures, and other internal data values; pcretest has
|
||||
"inside information" compared to a program that strictly follows the PCRE API.
|
||||
|
||||
Although pcre_internal.h does itself include pcre.h, we explicitly include it
|
||||
here before pcre_internal.h so that the PCRE_EXP_xxx macros get set
|
||||
appropriately for an application, not for building PCRE. */
|
||||
|
||||
#include "pcre.h"
|
||||
#include "pcreinal.h"
|
||||
|
||||
/* These are the funtions that are contained within. It doesn't seem worth
|
||||
having a separate .h file just for this. */
|
||||
|
||||
#endif /* PCRE_INCLUDED */
|
||||
|
||||
#ifdef PCRE_INCLUDED
|
||||
static /* Keep the following function as private. */
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE8
|
||||
void pcre_printint(pcre *external_re, FILE *f, BOOL print_lengths);
|
||||
#else
|
||||
void pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths);
|
||||
#endif
|
||||
|
||||
/* Macro that decides whether a character should be output as a literal or in
|
||||
hexadecimal. We don't use isprint() because that can vary from system to system
|
||||
(even without the use of locales) and we want the output always to be the same,
|
||||
for testing purposes. This macro is used in pcretest as well as in this file. */
|
||||
for testing purposes. */
|
||||
|
||||
#ifdef EBCDIC
|
||||
#define PRINTABLE(c) ((c) >= 64 && (c) < 255)
|
||||
@@ -63,7 +97,13 @@ for testing purposes. This macro is used in pcretest as well as in this file. */
|
||||
|
||||
/* The table of operator names. */
|
||||
|
||||
static const char *OP_names[] = { OP_NAME_LIST };
|
||||
static const char *priv_OP_names[] = { OP_NAME_LIST };
|
||||
|
||||
/* This table of operator lengths is not actually used by the working code,
|
||||
but its size is needed for a check that ensures it is the correct size for the
|
||||
number of opcodes (thus catching update omissions). */
|
||||
|
||||
static const pcre_uint8 priv_OP_lengths[] = { OP_LENGTHS };
|
||||
|
||||
|
||||
|
||||
@@ -72,17 +112,23 @@ static const char *OP_names[] = { OP_NAME_LIST };
|
||||
*************************************************/
|
||||
|
||||
static int
|
||||
print_char(FILE *f, uschar *ptr, BOOL utf8)
|
||||
print_char(FILE *f, pcre_uchar *ptr, BOOL utf)
|
||||
{
|
||||
int c = *ptr;
|
||||
|
||||
#ifndef SUPPORT_UTF8
|
||||
utf8 = utf8; /* Avoid compiler warning */
|
||||
if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02x", c);
|
||||
#ifndef SUPPORT_UTF
|
||||
|
||||
(void)utf; /* Avoid compiler warning */
|
||||
if (PRINTABLE(c)) fprintf(f, "%c", c);
|
||||
else if (c <= 0xff) fprintf(f, "\\x%02x", c);
|
||||
else fprintf(f, "\\x{%x}", c);
|
||||
return 0;
|
||||
|
||||
#else
|
||||
if (!utf8 || (c & 0xc0) != 0xc0)
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
|
||||
if (!utf || (c & 0xc0) != 0xc0)
|
||||
{
|
||||
if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02x", c);
|
||||
return 0;
|
||||
@@ -90,9 +136,9 @@ if (!utf8 || (c & 0xc0) != 0xc0)
|
||||
else
|
||||
{
|
||||
int i;
|
||||
int a = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */
|
||||
int a = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */
|
||||
int s = 6*a;
|
||||
c = (c & _pcre_utf8_table3[a]) << s;
|
||||
c = (c & PRIV(utf8_table3)[a]) << s;
|
||||
for (i = 1; i <= a; i++)
|
||||
{
|
||||
/* This is a check for malformed UTF-8; it should only occur if the sanity
|
||||
@@ -110,13 +156,58 @@ else
|
||||
s -= 6;
|
||||
c |= (ptr[i] & 0x3f) << s;
|
||||
}
|
||||
if (c < 128) fprintf(f, "\\x%02x", c); else fprintf(f, "\\x{%x}", c);
|
||||
fprintf(f, "\\x{%x}", c);
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifdef COMPILE_PCRE16
|
||||
|
||||
if (!utf || (c & 0xfc00) != 0xd800)
|
||||
{
|
||||
if (PRINTABLE(c)) fprintf(f, "%c", c);
|
||||
else if (c <= 0xff) fprintf(f, "\\x%02x", c);
|
||||
else fprintf(f, "\\x{%x}", c);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a check for malformed UTF-16; it should only occur if the sanity
|
||||
check has been turned off. Rather than swallow a low surrogate, just stop if
|
||||
we hit a bad one. Print it with \X instead of \x as an indication. */
|
||||
|
||||
if ((ptr[1] & 0xfc00) != 0xdc00)
|
||||
{
|
||||
fprintf(f, "\\X{%x}", c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = (((c & 0x3ff) << 10) | (ptr[1] & 0x3ff)) + 0x10000;
|
||||
fprintf(f, "\\x{%x}", c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* COMPILE_PCRE16 */
|
||||
|
||||
#endif /* COMPILE_PCRE8 */
|
||||
|
||||
#endif /* SUPPORT_UTF */
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* Print uchar string (regardless of utf) *
|
||||
*************************************************/
|
||||
|
||||
static void
|
||||
print_puchar(FILE *f, PCRE_PUCHAR ptr)
|
||||
{
|
||||
while (*ptr != '\0')
|
||||
{
|
||||
register int c = *ptr++;
|
||||
if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* Find Unicode property name *
|
||||
@@ -127,11 +218,11 @@ get_ucpname(int ptype, int pvalue)
|
||||
{
|
||||
#ifdef SUPPORT_UCP
|
||||
int i;
|
||||
for (i = _pcre_utt_size - 1; i >= 0; i--)
|
||||
for (i = PRIV(utt_size) - 1; i >= 0; i--)
|
||||
{
|
||||
if (ptype == _pcre_utt[i].type && pvalue == _pcre_utt[i].value) break;
|
||||
if (ptype == PRIV(utt)[i].type && pvalue == PRIV(utt)[i].value) break;
|
||||
}
|
||||
return (i >= 0)? _pcre_utt_names + _pcre_utt[i].name_offset : "??";
|
||||
return (i >= 0)? PRIV(utt_names) + PRIV(utt)[i].name_offset : "??";
|
||||
#else
|
||||
/* It gets harder and harder to shut off unwanted compiler warnings. */
|
||||
ptype = ptype * pvalue;
|
||||
@@ -151,12 +242,20 @@ print_lengths flag controls whether offsets and lengths of items are printed.
|
||||
They can be turned off from pcretest so that automatic tests on bytecode can be
|
||||
written that do not depend on the value of LINK_SIZE. */
|
||||
|
||||
static void
|
||||
#ifdef PCRE_INCLUDED
|
||||
static /* Keep the following function as private. */
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE8
|
||||
void
|
||||
pcre_printint(pcre *external_re, FILE *f, BOOL print_lengths)
|
||||
#else
|
||||
void
|
||||
pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths)
|
||||
#endif
|
||||
{
|
||||
real_pcre *re = (real_pcre *)external_re;
|
||||
uschar *codestart, *code;
|
||||
BOOL utf8;
|
||||
REAL_PCRE *re = (REAL_PCRE *)external_re;
|
||||
pcre_uchar *codestart, *code;
|
||||
BOOL utf;
|
||||
|
||||
unsigned int options = re->options;
|
||||
int offset = re->name_table_offset;
|
||||
@@ -174,12 +273,13 @@ if (re->magic_number != MAGIC_NUMBER)
|
||||
((options >> 24) & 0x000000ff);
|
||||
}
|
||||
|
||||
code = codestart = (uschar *)re + offset + count * size;
|
||||
utf8 = (options & PCRE_UTF8) != 0;
|
||||
code = codestart = (pcre_uchar *)re + offset + count * size;
|
||||
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
|
||||
utf = (options & PCRE_UTF8) != 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
uschar *ccode;
|
||||
pcre_uchar *ccode;
|
||||
const char *flag = " ";
|
||||
int c;
|
||||
int extra = 0;
|
||||
@@ -193,25 +293,20 @@ for(;;)
|
||||
{
|
||||
/* ========================================================================== */
|
||||
/* These cases are never obeyed. This is a fudge that causes a compile-
|
||||
time error if the vectors OP_names or _pcre_OP_lengths, which are indexed
|
||||
time error if the vectors OP_names or OP_lengths, which are indexed
|
||||
by opcode, are not the correct length. It seems to be the only way to do
|
||||
such a check at compile time, as the sizeof() operator does not work in
|
||||
the C preprocessor. We do this while compiling pcretest, because that
|
||||
#includes pcre_tables.c, which holds _pcre_OP_lengths. We can't do this
|
||||
when building pcre_compile.c with PCRE_DEBUG set, because it doesn't then
|
||||
know the size of _pcre_OP_lengths. */
|
||||
the C preprocessor. */
|
||||
|
||||
#ifdef COMPILING_PCRETEST
|
||||
case OP_TABLE_LENGTH:
|
||||
case OP_TABLE_LENGTH +
|
||||
((sizeof(OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) &&
|
||||
(sizeof(_pcre_OP_lengths) == OP_TABLE_LENGTH)):
|
||||
((sizeof(priv_OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) &&
|
||||
(sizeof(priv_OP_lengths) == OP_TABLE_LENGTH)):
|
||||
break;
|
||||
#endif
|
||||
/* ========================================================================== */
|
||||
|
||||
case OP_END:
|
||||
fprintf(f, " %s\n", OP_names[*code]);
|
||||
fprintf(f, " %s\n", priv_OP_names[*code]);
|
||||
fprintf(f, "------------------------------------------------------------------\n");
|
||||
return;
|
||||
|
||||
@@ -220,7 +315,7 @@ for(;;)
|
||||
do
|
||||
{
|
||||
code++;
|
||||
code += 1 + print_char(f, code, utf8);
|
||||
code += 1 + print_char(f, code, utf);
|
||||
}
|
||||
while (*code == OP_CHAR);
|
||||
fprintf(f, "\n");
|
||||
@@ -231,7 +326,7 @@ for(;;)
|
||||
do
|
||||
{
|
||||
code++;
|
||||
code += 1 + print_char(f, code, utf8);
|
||||
code += 1 + print_char(f, code, utf);
|
||||
}
|
||||
while (*code == OP_CHARI);
|
||||
fprintf(f, "\n");
|
||||
@@ -243,7 +338,7 @@ for(;;)
|
||||
case OP_SCBRAPOS:
|
||||
if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
|
||||
else fprintf(f, " ");
|
||||
fprintf(f, "%s %d", OP_names[*code], GET2(code, 1+LINK_SIZE));
|
||||
fprintf(f, "%s %d", priv_OP_names[*code], GET2(code, 1+LINK_SIZE));
|
||||
break;
|
||||
|
||||
case OP_BRA:
|
||||
@@ -266,16 +361,16 @@ for(;;)
|
||||
case OP_REVERSE:
|
||||
if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
|
||||
else fprintf(f, " ");
|
||||
fprintf(f, "%s", OP_names[*code]);
|
||||
fprintf(f, "%s", priv_OP_names[*code]);
|
||||
break;
|
||||
|
||||
case OP_CLOSE:
|
||||
fprintf(f, " %s %d", OP_names[*code], GET2(code, 1));
|
||||
fprintf(f, " %s %d", priv_OP_names[*code], GET2(code, 1));
|
||||
break;
|
||||
|
||||
case OP_CREF:
|
||||
case OP_NCREF:
|
||||
fprintf(f, "%3d %s", GET2(code,1), OP_names[*code]);
|
||||
fprintf(f, "%3d %s", GET2(code,1), priv_OP_names[*code]);
|
||||
break;
|
||||
|
||||
case OP_RREF:
|
||||
@@ -330,15 +425,15 @@ for(;;)
|
||||
fprintf(f, " %s ", flag);
|
||||
if (*code >= OP_TYPESTAR)
|
||||
{
|
||||
fprintf(f, "%s", OP_names[code[1]]);
|
||||
fprintf(f, "%s", priv_OP_names[code[1]]);
|
||||
if (code[1] == OP_PROP || code[1] == OP_NOTPROP)
|
||||
{
|
||||
fprintf(f, " %s ", get_ucpname(code[2], code[3]));
|
||||
extra = 2;
|
||||
}
|
||||
}
|
||||
else extra = print_char(f, code+1, utf8);
|
||||
fprintf(f, "%s", OP_names[*code]);
|
||||
else extra = print_char(f, code+1, utf);
|
||||
fprintf(f, "%s", priv_OP_names[*code]);
|
||||
break;
|
||||
|
||||
case OP_EXACTI:
|
||||
@@ -352,7 +447,7 @@ for(;;)
|
||||
case OP_MINUPTO:
|
||||
case OP_POSUPTO:
|
||||
fprintf(f, " %s ", flag);
|
||||
extra = print_char(f, code+3, utf8);
|
||||
extra = print_char(f, code + 1 + IMM2_SIZE, utf);
|
||||
fprintf(f, "{");
|
||||
if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,");
|
||||
fprintf(f, "%d}", GET2(code,1));
|
||||
@@ -364,10 +459,11 @@ for(;;)
|
||||
case OP_TYPEUPTO:
|
||||
case OP_TYPEMINUPTO:
|
||||
case OP_TYPEPOSUPTO:
|
||||
fprintf(f, " %s", OP_names[code[3]]);
|
||||
if (code[3] == OP_PROP || code[3] == OP_NOTPROP)
|
||||
fprintf(f, " %s", priv_OP_names[code[1 + IMM2_SIZE]]);
|
||||
if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
|
||||
{
|
||||
fprintf(f, " %s ", get_ucpname(code[4], code[5]));
|
||||
fprintf(f, " %s ", get_ucpname(code[1 + IMM2_SIZE + 1],
|
||||
code[1 + IMM2_SIZE + 2]));
|
||||
extra = 2;
|
||||
}
|
||||
fprintf(f, "{");
|
||||
@@ -383,7 +479,10 @@ for(;;)
|
||||
case OP_NOT:
|
||||
c = code[1];
|
||||
if (PRINTABLE(c)) fprintf(f, " %s [^%c]", flag, c);
|
||||
else fprintf(f, " %s [^\\x%02x]", flag, c);
|
||||
else if (utf || c > 0xff)
|
||||
fprintf(f, " %s [^\\x{%02x}]", flag, c);
|
||||
else
|
||||
fprintf(f, " %s [^\\x%02x]", flag, c);
|
||||
break;
|
||||
|
||||
case OP_NOTSTARI:
|
||||
@@ -410,7 +509,7 @@ for(;;)
|
||||
c = code[1];
|
||||
if (PRINTABLE(c)) fprintf(f, " %s [^%c]", flag, c);
|
||||
else fprintf(f, " %s [^\\x%02x]", flag, c);
|
||||
fprintf(f, "%s", OP_names[*code]);
|
||||
fprintf(f, "%s", priv_OP_names[*code]);
|
||||
break;
|
||||
|
||||
case OP_NOTEXACTI:
|
||||
@@ -424,7 +523,7 @@ for(;;)
|
||||
case OP_NOTUPTO:
|
||||
case OP_NOTMINUPTO:
|
||||
case OP_NOTPOSUPTO:
|
||||
c = code[3];
|
||||
c = code[1 + IMM2_SIZE];
|
||||
if (PRINTABLE(c)) fprintf(f, " %s [^%c]{", flag, c);
|
||||
else fprintf(f, " %s [^\\x%02x]{", flag, c);
|
||||
if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,");
|
||||
@@ -437,7 +536,7 @@ for(;;)
|
||||
case OP_RECURSE:
|
||||
if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
|
||||
else fprintf(f, " ");
|
||||
fprintf(f, "%s", OP_names[*code]);
|
||||
fprintf(f, "%s", priv_OP_names[*code]);
|
||||
break;
|
||||
|
||||
case OP_REFI:
|
||||
@@ -445,22 +544,22 @@ for(;;)
|
||||
/* Fall through */
|
||||
case OP_REF:
|
||||
fprintf(f, " %s \\%d", flag, GET2(code,1));
|
||||
ccode = code + _pcre_OP_lengths[*code];
|
||||
ccode = code + priv_OP_lengths[*code];
|
||||
goto CLASS_REF_REPEAT;
|
||||
|
||||
case OP_CALLOUT:
|
||||
fprintf(f, " %s %d %d %d", OP_names[*code], code[1], GET(code,2),
|
||||
fprintf(f, " %s %d %d %d", priv_OP_names[*code], code[1], GET(code,2),
|
||||
GET(code, 2 + LINK_SIZE));
|
||||
break;
|
||||
|
||||
case OP_PROP:
|
||||
case OP_NOTPROP:
|
||||
fprintf(f, " %s %s", OP_names[*code], get_ucpname(code[1], code[2]));
|
||||
fprintf(f, " %s %s", priv_OP_names[*code], get_ucpname(code[1], code[2]));
|
||||
break;
|
||||
|
||||
/* OP_XCLASS can only occur in UTF-8 mode. However, there's no harm in
|
||||
having this code always here, and it makes it less messy without all those
|
||||
#ifdefs. */
|
||||
/* OP_XCLASS can only occur in UTF or PCRE16 modes. However, there's no
|
||||
harm in having this code always here, and it makes it less messy without
|
||||
all those #ifdefs. */
|
||||
|
||||
case OP_CLASS:
|
||||
case OP_NCLASS:
|
||||
@@ -468,6 +567,7 @@ for(;;)
|
||||
{
|
||||
int i, min, max;
|
||||
BOOL printmap;
|
||||
pcre_uint8 *map;
|
||||
|
||||
fprintf(f, " [");
|
||||
|
||||
@@ -488,13 +588,14 @@ for(;;)
|
||||
|
||||
if (printmap)
|
||||
{
|
||||
map = (pcre_uint8 *)ccode;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
if ((ccode[i/8] & (1 << (i&7))) != 0)
|
||||
if ((map[i/8] & (1 << (i&7))) != 0)
|
||||
{
|
||||
int j;
|
||||
for (j = i+1; j < 256; j++)
|
||||
if ((ccode[j/8] & (1 << (j&7))) == 0) break;
|
||||
if ((map[j/8] & (1 << (j&7))) == 0) break;
|
||||
if (i == '-' || i == ']') fprintf(f, "\\");
|
||||
if (PRINTABLE(i)) fprintf(f, "%c", i);
|
||||
else fprintf(f, "\\x%02x", i);
|
||||
@@ -508,7 +609,7 @@ for(;;)
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
ccode += 32;
|
||||
ccode += 32 / sizeof(pcre_uchar);
|
||||
}
|
||||
|
||||
/* For an XCLASS there is always some additional data */
|
||||
@@ -532,17 +633,17 @@ for(;;)
|
||||
}
|
||||
else
|
||||
{
|
||||
ccode += 1 + print_char(f, ccode, TRUE);
|
||||
ccode += 1 + print_char(f, ccode, utf);
|
||||
if (ch == XCL_RANGE)
|
||||
{
|
||||
fprintf(f, "-");
|
||||
ccode += 1 + print_char(f, ccode, TRUE);
|
||||
ccode += 1 + print_char(f, ccode, utf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Indicate a non-UTF8 class which was created by negation */
|
||||
/* Indicate a non-UTF class which was created by negation */
|
||||
|
||||
fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : "");
|
||||
|
||||
@@ -557,18 +658,18 @@ for(;;)
|
||||
case OP_CRMINPLUS:
|
||||
case OP_CRQUERY:
|
||||
case OP_CRMINQUERY:
|
||||
fprintf(f, "%s", OP_names[*ccode]);
|
||||
extra += _pcre_OP_lengths[*ccode];
|
||||
fprintf(f, "%s", priv_OP_names[*ccode]);
|
||||
extra += priv_OP_lengths[*ccode];
|
||||
break;
|
||||
|
||||
case OP_CRRANGE:
|
||||
case OP_CRMINRANGE:
|
||||
min = GET2(ccode,1);
|
||||
max = GET2(ccode,3);
|
||||
max = GET2(ccode,1 + IMM2_SIZE);
|
||||
if (max == 0) fprintf(f, "{%d,}", min);
|
||||
else fprintf(f, "{%d,%d}", min, max);
|
||||
if (*ccode == OP_CRMINRANGE) fprintf(f, "?");
|
||||
extra += _pcre_OP_lengths[*ccode];
|
||||
extra += priv_OP_lengths[*ccode];
|
||||
break;
|
||||
|
||||
/* Do nothing if it's not a repeat; this code stops picky compilers
|
||||
@@ -583,17 +684,14 @@ for(;;)
|
||||
case OP_MARK:
|
||||
case OP_PRUNE_ARG:
|
||||
case OP_SKIP_ARG:
|
||||
fprintf(f, " %s %s", OP_names[*code], code + 2);
|
||||
case OP_THEN_ARG:
|
||||
fprintf(f, " %s ", priv_OP_names[*code]);
|
||||
print_puchar(f, code + 2);
|
||||
extra += code[1];
|
||||
break;
|
||||
|
||||
case OP_THEN:
|
||||
fprintf(f, " %s", OP_names[*code]);
|
||||
break;
|
||||
|
||||
case OP_THEN_ARG:
|
||||
fprintf(f, " %s %s", OP_names[*code], code + 2);
|
||||
extra += code[1];
|
||||
fprintf(f, " %s", priv_OP_names[*code]);
|
||||
break;
|
||||
|
||||
case OP_CIRCM:
|
||||
@@ -604,11 +702,11 @@ for(;;)
|
||||
/* Anything else is just an item with no data, but possibly a flag. */
|
||||
|
||||
default:
|
||||
fprintf(f, " %s %s", flag, OP_names[*code]);
|
||||
fprintf(f, " %s %s", flag, priv_OP_names[*code]);
|
||||
break;
|
||||
}
|
||||
|
||||
code += _pcre_OP_lengths[*code] + extra;
|
||||
code += priv_OP_lengths[*code] + extra;
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2008 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -68,11 +68,18 @@ Returns: the (possibly updated) count value (a non-negative number), or
|
||||
a negative error number
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre_refcount(pcre *argument_re, int adjust)
|
||||
#else
|
||||
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
|
||||
pcre16_refcount(pcre16 *argument_re, int adjust)
|
||||
#endif
|
||||
{
|
||||
real_pcre *re = (real_pcre *)argument_re;
|
||||
REAL_PCRE *re = (REAL_PCRE *)argument_re;
|
||||
if (re == NULL) return PCRE_ERROR_NULL;
|
||||
if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
|
||||
if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
|
||||
re->ref_count = (-adjust > re->ref_count)? 0 :
|
||||
(adjust + re->ref_count > 65535)? 65535 :
|
||||
re->ref_count + adjust;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2010 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -78,17 +78,18 @@ Returns: the minimum length
|
||||
*/
|
||||
|
||||
static int
|
||||
find_minlength(const uschar *code, const uschar *startcode, int options,
|
||||
find_minlength(const pcre_uchar *code, const pcre_uchar *startcode, int options,
|
||||
int recurse_depth)
|
||||
{
|
||||
int length = -1;
|
||||
BOOL utf8 = (options & PCRE_UTF8) != 0;
|
||||
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
|
||||
BOOL utf = (options & PCRE_UTF8) != 0;
|
||||
BOOL had_recurse = FALSE;
|
||||
register int branchlength = 0;
|
||||
register uschar *cc = (uschar *)code + 1 + LINK_SIZE;
|
||||
register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE;
|
||||
|
||||
if (*code == OP_CBRA || *code == OP_SCBRA ||
|
||||
*code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += 2;
|
||||
*code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE;
|
||||
|
||||
/* Scan along the opcodes for this branch. If we get to the end of the
|
||||
branch, check the length against that of the other branches. */
|
||||
@@ -96,7 +97,7 @@ branch, check the length against that of the other branches. */
|
||||
for (;;)
|
||||
{
|
||||
int d, min;
|
||||
uschar *cs, *ce;
|
||||
pcre_uchar *cs, *ce;
|
||||
register int op = *cc;
|
||||
|
||||
switch (op)
|
||||
@@ -189,7 +190,7 @@ for (;;)
|
||||
case OP_DOLLM:
|
||||
case OP_NOT_WORD_BOUNDARY:
|
||||
case OP_WORD_BOUNDARY:
|
||||
cc += _pcre_OP_lengths[*cc];
|
||||
cc += PRIV(OP_lengths)[*cc];
|
||||
break;
|
||||
|
||||
/* Skip over a subpattern that has a {0} or {0,x} quantifier */
|
||||
@@ -198,7 +199,7 @@ for (;;)
|
||||
case OP_BRAMINZERO:
|
||||
case OP_BRAPOSZERO:
|
||||
case OP_SKIPZERO:
|
||||
cc += _pcre_OP_lengths[*cc];
|
||||
cc += PRIV(OP_lengths)[*cc];
|
||||
do cc += GET(cc, 1); while (*cc == OP_ALT);
|
||||
cc += 1 + LINK_SIZE;
|
||||
break;
|
||||
@@ -223,8 +224,8 @@ for (;;)
|
||||
case OP_NOTPOSPLUSI:
|
||||
branchlength++;
|
||||
cc += 2;
|
||||
#ifdef SUPPORT_UTF8
|
||||
if (utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -243,15 +244,16 @@ for (;;)
|
||||
case OP_NOTEXACT:
|
||||
case OP_NOTEXACTI:
|
||||
branchlength += GET2(cc,1);
|
||||
cc += 4;
|
||||
#ifdef SUPPORT_UTF8
|
||||
if (utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
|
||||
cc += 2 + IMM2_SIZE;
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OP_TYPEEXACT:
|
||||
branchlength += GET2(cc,1);
|
||||
cc += (cc[3] == OP_PROP || cc[3] == OP_NOTPROP)? 6 : 4;
|
||||
cc += 2 + IMM2_SIZE + ((cc[1 + IMM2_SIZE] == OP_PROP
|
||||
|| cc[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0);
|
||||
break;
|
||||
|
||||
/* Handle single-char non-literal matchers */
|
||||
@@ -291,8 +293,8 @@ for (;;)
|
||||
appear, but leave the code, just in case.) */
|
||||
|
||||
case OP_ANYBYTE:
|
||||
#ifdef SUPPORT_UTF8
|
||||
if (utf8) return -1;
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf) return -1;
|
||||
#endif
|
||||
branchlength++;
|
||||
cc++;
|
||||
@@ -308,27 +310,28 @@ for (;;)
|
||||
case OP_TYPEPOSSTAR:
|
||||
case OP_TYPEPOSQUERY:
|
||||
if (cc[1] == OP_PROP || cc[1] == OP_NOTPROP) cc += 2;
|
||||
cc += _pcre_OP_lengths[op];
|
||||
cc += PRIV(OP_lengths)[op];
|
||||
break;
|
||||
|
||||
case OP_TYPEUPTO:
|
||||
case OP_TYPEMINUPTO:
|
||||
case OP_TYPEPOSUPTO:
|
||||
if (cc[3] == OP_PROP || cc[3] == OP_NOTPROP) cc += 2;
|
||||
cc += _pcre_OP_lengths[op];
|
||||
if (cc[1 + IMM2_SIZE] == OP_PROP
|
||||
|| cc[1 + IMM2_SIZE] == OP_NOTPROP) cc += 2;
|
||||
cc += PRIV(OP_lengths)[op];
|
||||
break;
|
||||
|
||||
/* Check a class for variable quantification */
|
||||
|
||||
#ifdef SUPPORT_UTF8
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
case OP_XCLASS:
|
||||
cc += GET(cc, 1) - 33;
|
||||
cc += GET(cc, 1) - PRIV(OP_lengths)[OP_CLASS];
|
||||
/* Fall through */
|
||||
#endif
|
||||
|
||||
case OP_CLASS:
|
||||
case OP_NCLASS:
|
||||
cc += 33;
|
||||
cc += PRIV(OP_lengths)[OP_CLASS];
|
||||
|
||||
switch (*cc)
|
||||
{
|
||||
@@ -347,7 +350,7 @@ for (;;)
|
||||
case OP_CRRANGE:
|
||||
case OP_CRMINRANGE:
|
||||
branchlength += GET2(cc,1);
|
||||
cc += 5;
|
||||
cc += 1 + 2 * IMM2_SIZE;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -372,7 +375,7 @@ for (;;)
|
||||
case OP_REFI:
|
||||
if ((options & PCRE_JAVASCRIPT_COMPAT) == 0)
|
||||
{
|
||||
ce = cs = (uschar *)_pcre_find_bracket(startcode, utf8, GET2(cc, 1));
|
||||
ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(cc, 1));
|
||||
if (cs == NULL) return -2;
|
||||
do ce += GET(ce, 1); while (*ce == OP_ALT);
|
||||
if (cc > cs && cc < ce)
|
||||
@@ -386,7 +389,7 @@ for (;;)
|
||||
}
|
||||
}
|
||||
else d = 0;
|
||||
cc += 3;
|
||||
cc += 1 + IMM2_SIZE;
|
||||
|
||||
/* Handle repeated back references */
|
||||
|
||||
@@ -409,7 +412,7 @@ for (;;)
|
||||
case OP_CRRANGE:
|
||||
case OP_CRMINRANGE:
|
||||
min = GET2(cc, 1);
|
||||
cc += 5;
|
||||
cc += 1 + 2 * IMM2_SIZE;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -424,7 +427,7 @@ for (;;)
|
||||
caught by a recursion depth count. */
|
||||
|
||||
case OP_RECURSE:
|
||||
cs = ce = (uschar *)startcode + GET(cc, 1);
|
||||
cs = ce = (pcre_uchar *)startcode + GET(cc, 1);
|
||||
do ce += GET(ce, 1); while (*ce == OP_ALT);
|
||||
if ((cc > cs && cc < ce) || recurse_depth > 10)
|
||||
had_recurse = TRUE;
|
||||
@@ -482,9 +485,9 @@ for (;;)
|
||||
case OP_NOTPOSQUERY:
|
||||
case OP_NOTPOSQUERYI:
|
||||
|
||||
cc += _pcre_OP_lengths[op];
|
||||
#ifdef SUPPORT_UTF8
|
||||
if (utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
|
||||
cc += PRIV(OP_lengths)[op];
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -494,7 +497,7 @@ for (;;)
|
||||
case OP_PRUNE_ARG:
|
||||
case OP_SKIP_ARG:
|
||||
case OP_THEN_ARG:
|
||||
cc += _pcre_OP_lengths[op] + cc[1];
|
||||
cc += PRIV(OP_lengths)[op] + cc[1];
|
||||
break;
|
||||
|
||||
/* The remaining opcodes are just skipped over. */
|
||||
@@ -506,7 +509,7 @@ for (;;)
|
||||
case OP_SET_SOM:
|
||||
case OP_SKIP:
|
||||
case OP_THEN:
|
||||
cc += _pcre_OP_lengths[op];
|
||||
cc += PRIV(OP_lengths)[op];
|
||||
break;
|
||||
|
||||
/* This should not occur: we list all opcodes explicitly so that when
|
||||
@@ -535,29 +538,30 @@ Arguments:
|
||||
p points to the character
|
||||
caseless the caseless flag
|
||||
cd the block with char table pointers
|
||||
utf8 TRUE for UTF-8 mode
|
||||
utf TRUE for UTF-8 / UTF-16 mode
|
||||
|
||||
Returns: pointer after the character
|
||||
*/
|
||||
|
||||
static const uschar *
|
||||
set_table_bit(uschar *start_bits, const uschar *p, BOOL caseless,
|
||||
compile_data *cd, BOOL utf8)
|
||||
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;
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
SET_BIT(c);
|
||||
|
||||
#ifdef SUPPORT_UTF8
|
||||
if (utf8 && c > 127)
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf && c > 127)
|
||||
{
|
||||
GETCHARINC(c, p);
|
||||
#ifdef SUPPORT_UCP
|
||||
if (caseless)
|
||||
{
|
||||
uschar buff[8];
|
||||
pcre_uchar buff[6];
|
||||
c = UCD_OTHERCASE(c);
|
||||
(void)_pcre_ord2utf8(c, buff);
|
||||
(void)PRIV(ord2utf)(c, buff);
|
||||
SET_BIT(buff[0]);
|
||||
}
|
||||
#endif
|
||||
@@ -569,6 +573,36 @@ if (utf8 && c > 127)
|
||||
|
||||
if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
|
||||
return p + 1;
|
||||
#endif
|
||||
|
||||
#ifdef COMPILE_PCRE16
|
||||
if (c > 0xff)
|
||||
{
|
||||
c = 0xff;
|
||||
caseless = FALSE;
|
||||
}
|
||||
SET_BIT(c);
|
||||
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf && c > 127)
|
||||
{
|
||||
GETCHARINC(c, p);
|
||||
#ifdef SUPPORT_UCP
|
||||
if (caseless)
|
||||
{
|
||||
c = UCD_OTHERCASE(c);
|
||||
if (c > 0xff)
|
||||
c = 0xff;
|
||||
SET_BIT(c);
|
||||
}
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
|
||||
return p + 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -594,21 +628,23 @@ Returns: nothing
|
||||
*/
|
||||
|
||||
static void
|
||||
set_type_bits(uschar *start_bits, int cbit_type, int table_limit,
|
||||
set_type_bits(pcre_uint8 *start_bits, int cbit_type, int table_limit,
|
||||
compile_data *cd)
|
||||
{
|
||||
register int 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;
|
||||
for (c = 128; c < 256; c++)
|
||||
{
|
||||
if ((cd->cbits[c/8] & (1 << (c&7))) != 0)
|
||||
{
|
||||
uschar buff[8];
|
||||
(void)_pcre_ord2utf8(c, buff);
|
||||
pcre_uchar buff[6];
|
||||
(void)PRIV(ord2utf)(c, buff);
|
||||
SET_BIT(buff[0]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -634,12 +670,14 @@ Returns: nothing
|
||||
*/
|
||||
|
||||
static void
|
||||
set_nottype_bits(uschar *start_bits, int cbit_type, int table_limit,
|
||||
set_nottype_bits(pcre_uint8 *start_bits, int cbit_type, int table_limit,
|
||||
compile_data *cd)
|
||||
{
|
||||
register int 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;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -659,7 +697,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
|
||||
utf8 TRUE if in UTF-8 mode
|
||||
utf TRUE if in UTF-8 / UTF-16 mode
|
||||
cd the block with char table pointers
|
||||
|
||||
Returns: SSB_FAIL => Failed to find any starting bytes
|
||||
@@ -669,12 +707,16 @@ Returns: SSB_FAIL => Failed to find any starting bytes
|
||||
*/
|
||||
|
||||
static int
|
||||
set_start_bits(const uschar *code, uschar *start_bits, BOOL utf8,
|
||||
set_start_bits(const pcre_uchar *code, pcre_uint8 *start_bits, BOOL utf,
|
||||
compile_data *cd)
|
||||
{
|
||||
register int c;
|
||||
int yield = SSB_DONE;
|
||||
int table_limit = utf8? 16:32;
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
|
||||
int table_limit = utf? 16:32;
|
||||
#else
|
||||
int table_limit = 32;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* ========================================================================= */
|
||||
@@ -696,10 +738,10 @@ volatile int dummy;
|
||||
do
|
||||
{
|
||||
BOOL try_next = TRUE;
|
||||
const uschar *tcode = code + 1 + LINK_SIZE;
|
||||
const pcre_uchar *tcode = code + 1 + LINK_SIZE;
|
||||
|
||||
if (*code == OP_CBRA || *code == OP_SCBRA ||
|
||||
*code == OP_CBRAPOS || *code == OP_SCBRAPOS) tcode += 2;
|
||||
*code == OP_CBRAPOS || *code == OP_SCBRAPOS) tcode += IMM2_SIZE;
|
||||
|
||||
while (try_next) /* Loop for items in this branch */
|
||||
{
|
||||
@@ -785,7 +827,9 @@ do
|
||||
case OP_SOM:
|
||||
case OP_THEN:
|
||||
case OP_THEN_ARG:
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
case OP_XCLASS:
|
||||
#endif
|
||||
return SSB_FAIL;
|
||||
|
||||
/* We can ignore word boundary tests. */
|
||||
@@ -811,7 +855,7 @@ do
|
||||
case OP_ONCE:
|
||||
case OP_ONCE_NC:
|
||||
case OP_ASSERT:
|
||||
rc = set_start_bits(tcode, start_bits, utf8, cd);
|
||||
rc = set_start_bits(tcode, start_bits, utf, cd);
|
||||
if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc;
|
||||
if (rc == SSB_DONE) try_next = FALSE; else
|
||||
{
|
||||
@@ -858,7 +902,7 @@ do
|
||||
case OP_BRAZERO:
|
||||
case OP_BRAMINZERO:
|
||||
case OP_BRAPOSZERO:
|
||||
rc = set_start_bits(++tcode, start_bits, utf8, cd);
|
||||
rc = set_start_bits(++tcode, start_bits, utf, cd);
|
||||
if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc;
|
||||
/* =========================================================================
|
||||
See the comment at the head of this function concerning the next line,
|
||||
@@ -885,7 +929,7 @@ do
|
||||
case OP_QUERY:
|
||||
case OP_MINQUERY:
|
||||
case OP_POSQUERY:
|
||||
tcode = set_table_bit(start_bits, tcode + 1, FALSE, cd, utf8);
|
||||
tcode = set_table_bit(start_bits, tcode + 1, FALSE, cd, utf);
|
||||
break;
|
||||
|
||||
case OP_STARI:
|
||||
@@ -894,7 +938,7 @@ do
|
||||
case OP_QUERYI:
|
||||
case OP_MINQUERYI:
|
||||
case OP_POSQUERYI:
|
||||
tcode = set_table_bit(start_bits, tcode + 1, TRUE, cd, utf8);
|
||||
tcode = set_table_bit(start_bits, tcode + 1, TRUE, cd, utf);
|
||||
break;
|
||||
|
||||
/* Single-char upto sets the bit and tries the next */
|
||||
@@ -902,36 +946,36 @@ do
|
||||
case OP_UPTO:
|
||||
case OP_MINUPTO:
|
||||
case OP_POSUPTO:
|
||||
tcode = set_table_bit(start_bits, tcode + 3, FALSE, cd, utf8);
|
||||
tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, FALSE, cd, utf);
|
||||
break;
|
||||
|
||||
case OP_UPTOI:
|
||||
case OP_MINUPTOI:
|
||||
case OP_POSUPTOI:
|
||||
tcode = set_table_bit(start_bits, tcode + 3, TRUE, cd, utf8);
|
||||
tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, TRUE, cd, utf);
|
||||
break;
|
||||
|
||||
/* At least one single char sets the bit and stops */
|
||||
|
||||
case OP_EXACT:
|
||||
tcode += 2;
|
||||
tcode += IMM2_SIZE;
|
||||
/* Fall through */
|
||||
case OP_CHAR:
|
||||
case OP_PLUS:
|
||||
case OP_MINPLUS:
|
||||
case OP_POSPLUS:
|
||||
(void)set_table_bit(start_bits, tcode + 1, FALSE, cd, utf8);
|
||||
(void)set_table_bit(start_bits, tcode + 1, FALSE, cd, utf);
|
||||
try_next = FALSE;
|
||||
break;
|
||||
|
||||
case OP_EXACTI:
|
||||
tcode += 2;
|
||||
tcode += IMM2_SIZE;
|
||||
/* Fall through */
|
||||
case OP_CHARI:
|
||||
case OP_PLUSI:
|
||||
case OP_MINPLUSI:
|
||||
case OP_POSPLUSI:
|
||||
(void)set_table_bit(start_bits, tcode + 1, TRUE, cd, utf8);
|
||||
(void)set_table_bit(start_bits, tcode + 1, TRUE, cd, utf);
|
||||
try_next = FALSE;
|
||||
break;
|
||||
|
||||
@@ -944,14 +988,28 @@ do
|
||||
case OP_HSPACE:
|
||||
SET_BIT(0x09);
|
||||
SET_BIT(0x20);
|
||||
if (utf8)
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf)
|
||||
{
|
||||
#ifdef COMPILE_PCRE8
|
||||
SET_BIT(0xC2); /* For U+00A0 */
|
||||
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
|
||||
SET_BIT(0xA0);
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif /* SUPPORT_UTF */
|
||||
{
|
||||
SET_BIT(0xA0);
|
||||
#ifdef COMPILE_PCRE16
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
}
|
||||
else SET_BIT(0xA0);
|
||||
try_next = FALSE;
|
||||
break;
|
||||
|
||||
@@ -961,12 +1019,26 @@ do
|
||||
SET_BIT(0x0B);
|
||||
SET_BIT(0x0C);
|
||||
SET_BIT(0x0D);
|
||||
if (utf8)
|
||||
#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);
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif /* SUPPORT_UTF */
|
||||
{
|
||||
SET_BIT(0x85);
|
||||
#ifdef COMPILE_PCRE16
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
}
|
||||
else SET_BIT(0x85);
|
||||
try_next = FALSE;
|
||||
break;
|
||||
|
||||
@@ -1024,7 +1096,7 @@ do
|
||||
break;
|
||||
|
||||
case OP_TYPEEXACT:
|
||||
tcode += 3;
|
||||
tcode += 1 + IMM2_SIZE;
|
||||
break;
|
||||
|
||||
/* Zero or more repeats of character types set the bits and then
|
||||
@@ -1033,7 +1105,7 @@ do
|
||||
case OP_TYPEUPTO:
|
||||
case OP_TYPEMINUPTO:
|
||||
case OP_TYPEPOSUPTO:
|
||||
tcode += 2; /* Fall through */
|
||||
tcode += IMM2_SIZE; /* Fall through */
|
||||
|
||||
case OP_TYPESTAR:
|
||||
case OP_TYPEMINSTAR:
|
||||
@@ -1051,14 +1123,23 @@ do
|
||||
case OP_HSPACE:
|
||||
SET_BIT(0x09);
|
||||
SET_BIT(0x20);
|
||||
if (utf8)
|
||||
#ifdef COMPILE_PCRE8
|
||||
if (utf)
|
||||
{
|
||||
#ifdef COMPILE_PCRE8
|
||||
SET_BIT(0xC2); /* For U+00A0 */
|
||||
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
|
||||
SET_BIT(0xA0);
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
}
|
||||
else SET_BIT(0xA0);
|
||||
else
|
||||
#endif /* SUPPORT_UTF */
|
||||
SET_BIT(0xA0);
|
||||
break;
|
||||
|
||||
case OP_ANYNL:
|
||||
@@ -1067,12 +1148,21 @@ do
|
||||
SET_BIT(0x0B);
|
||||
SET_BIT(0x0C);
|
||||
SET_BIT(0x0D);
|
||||
if (utf8)
|
||||
#ifdef COMPILE_PCRE8
|
||||
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);
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
}
|
||||
else SET_BIT(0x85);
|
||||
else
|
||||
#endif /* SUPPORT_UTF */
|
||||
SET_BIT(0x85);
|
||||
break;
|
||||
|
||||
case OP_NOT_DIGIT:
|
||||
@@ -1119,18 +1209,23 @@ do
|
||||
character with a value > 255. */
|
||||
|
||||
case OP_NCLASS:
|
||||
#ifdef SUPPORT_UTF8
|
||||
if (utf8)
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
|
||||
if (utf)
|
||||
{
|
||||
start_bits[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */
|
||||
memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */
|
||||
}
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE16
|
||||
SET_BIT(0xFF); /* For characters > 255 */
|
||||
#endif
|
||||
/* Fall through */
|
||||
|
||||
case OP_CLASS:
|
||||
{
|
||||
pcre_uint8 *map;
|
||||
tcode++;
|
||||
map = (pcre_uint8 *)tcode;
|
||||
|
||||
/* In UTF-8 mode, the bits in a bit map correspond to character
|
||||
values, not to byte values. However, the bit map we are constructing is
|
||||
@@ -1138,13 +1233,13 @@ do
|
||||
value is > 127. In fact, there are only two possible starting bytes for
|
||||
characters in the range 128 - 255. */
|
||||
|
||||
#ifdef SUPPORT_UTF8
|
||||
if (utf8)
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
|
||||
if (utf)
|
||||
{
|
||||
for (c = 0; c < 16; c++) start_bits[c] |= tcode[c];
|
||||
for (c = 0; c < 16; c++) start_bits[c] |= map[c];
|
||||
for (c = 128; c < 256; c++)
|
||||
{
|
||||
if ((tcode[c/8] && (1 << (c&7))) != 0)
|
||||
if ((map[c/8] && (1 << (c&7))) != 0)
|
||||
{
|
||||
int d = (c >> 6) | 0xc0; /* Set bit for this starter */
|
||||
start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */
|
||||
@@ -1152,19 +1247,17 @@ do
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* In non-UTF-8 mode, the two bit maps are completely compatible. */
|
||||
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for (c = 0; c < 32; c++) start_bits[c] |= tcode[c];
|
||||
/* In non-UTF-8 mode, the two bit maps are completely compatible. */
|
||||
for (c = 0; c < 32; c++) start_bits[c] |= map[c];
|
||||
}
|
||||
|
||||
/* Advance past the bit map, and act on what follows. For a zero
|
||||
minimum repeat, continue; otherwise stop processing. */
|
||||
|
||||
tcode += 32;
|
||||
tcode += 32 / sizeof(pcre_uchar);
|
||||
switch (*tcode)
|
||||
{
|
||||
case OP_CRSTAR:
|
||||
@@ -1176,7 +1269,7 @@ do
|
||||
|
||||
case OP_CRRANGE:
|
||||
case OP_CRMINRANGE:
|
||||
if (((tcode[1] << 8) + tcode[2]) == 0) tcode += 5;
|
||||
if (GET2(tcode, 1) == 0) tcode += 1 + 2 * IMM2_SIZE;
|
||||
else try_next = FALSE;
|
||||
break;
|
||||
|
||||
@@ -1205,7 +1298,7 @@ return yield;
|
||||
*************************************************/
|
||||
|
||||
/* This function is handed a compiled expression that it must study to produce
|
||||
information that will speed up the matching. It returns a pcre_extra block
|
||||
information that will speed up the matching. It returns a pcre[16]_extra block
|
||||
which then gets handed back to pcre_exec().
|
||||
|
||||
Arguments:
|
||||
@@ -1214,23 +1307,28 @@ Arguments:
|
||||
errorptr points to where to place error messages;
|
||||
set NULL unless error
|
||||
|
||||
Returns: pointer to a pcre_extra block, with study_data filled in and the
|
||||
appropriate flags set;
|
||||
Returns: pointer to a pcre[16]_extra block, with study_data filled in and
|
||||
the appropriate flags set;
|
||||
NULL on error or if no optimization possible
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN pcre_extra * PCRE_CALL_CONVENTION
|
||||
pcre_study(const pcre *external_re, int options, const char **errorptr)
|
||||
#else
|
||||
PCRE_EXP_DEFN pcre16_extra * PCRE_CALL_CONVENTION
|
||||
pcre16_study(const pcre16 *external_re, int options, const char **errorptr)
|
||||
#endif
|
||||
{
|
||||
int min;
|
||||
BOOL bits_set = FALSE;
|
||||
uschar start_bits[32];
|
||||
pcre_extra *extra = NULL;
|
||||
pcre_uint8 start_bits[32];
|
||||
PUBL(extra) *extra = NULL;
|
||||
pcre_study_data *study;
|
||||
const uschar *tables;
|
||||
uschar *code;
|
||||
const pcre_uint8 *tables;
|
||||
pcre_uchar *code;
|
||||
compile_data compile_block;
|
||||
const real_pcre *re = (const real_pcre *)external_re;
|
||||
const REAL_PCRE *re = (const REAL_PCRE *)external_re;
|
||||
|
||||
*errorptr = NULL;
|
||||
|
||||
@@ -1240,13 +1338,23 @@ if (re == NULL || re->magic_number != MAGIC_NUMBER)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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";
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((options & ~PUBLIC_STUDY_OPTIONS) != 0)
|
||||
{
|
||||
*errorptr = "unknown or incorrect option bit(s) set";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
code = (uschar *)re + re->name_table_offset +
|
||||
code = (pcre_uchar *)re + re->name_table_offset +
|
||||
(re->name_count * re->name_entry_size);
|
||||
|
||||
/* For an anchored pattern, or an unanchored pattern that has a first char, or
|
||||
@@ -1261,9 +1369,16 @@ if ((re->options & PCRE_ANCHORED) == 0 &&
|
||||
/* Set the character tables in the block that is passed around */
|
||||
|
||||
tables = re->tables;
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
if (tables == NULL)
|
||||
(void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
|
||||
(void *)(&tables));
|
||||
#else
|
||||
if (tables == NULL)
|
||||
(void)pcre16_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
|
||||
(void *)(&tables));
|
||||
#endif
|
||||
|
||||
compile_block.lcc = tables + lcc_offset;
|
||||
compile_block.fcc = tables + fcc_offset;
|
||||
@@ -1272,7 +1387,7 @@ if ((re->options & PCRE_ANCHORED) == 0 &&
|
||||
|
||||
/* See if we can find a fixed set of initial characters for the pattern. */
|
||||
|
||||
memset(start_bits, 0, 32 * sizeof(uschar));
|
||||
memset(start_bits, 0, 32 * sizeof(pcre_uint8));
|
||||
rc = set_start_bits(code, start_bits, (re->options & PCRE_UTF8) != 0,
|
||||
&compile_block);
|
||||
bits_set = rc == SSB_DONE;
|
||||
@@ -1293,13 +1408,13 @@ 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_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, 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
|
||||
#ifdef SUPPORT_JIT
|
||||
@@ -1307,15 +1422,15 @@ if (bits_set || min > 0
|
||||
#endif
|
||||
)
|
||||
{
|
||||
extra = (pcre_extra *)(pcre_malloc)
|
||||
(sizeof(pcre_extra) + sizeof(pcre_study_data));
|
||||
extra = (PUBL(extra) *)(PUBL(malloc))
|
||||
(sizeof(PUBL(extra)) + sizeof(pcre_study_data));
|
||||
if (extra == NULL)
|
||||
{
|
||||
*errorptr = "failed to get memory";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
study = (pcre_study_data *)((char *)extra + sizeof(pcre_extra));
|
||||
study = (pcre_study_data *)((char *)extra + sizeof(PUBL(extra)));
|
||||
extra->flags = PCRE_EXTRA_STUDY_DATA;
|
||||
extra->study_data = study;
|
||||
|
||||
@@ -1331,7 +1446,19 @@ if (bits_set || min > 0
|
||||
study->flags |= PCRE_STUDY_MAPPED;
|
||||
memcpy(study->start_bits, start_bits, sizeof(start_bits));
|
||||
}
|
||||
else memset(study->start_bits, 0, 32 * sizeof(uschar));
|
||||
else memset(study->start_bits, 0, 32 * sizeof(pcre_uint8));
|
||||
|
||||
#ifdef PCRE_DEBUG
|
||||
if (bits_set)
|
||||
{
|
||||
pcre_uint8 *ptr = start_bits;
|
||||
int i;
|
||||
|
||||
printf("Start bits:\n");
|
||||
for (i = 0; i < 32; i++)
|
||||
printf("%3d: %02x%s", i * 8, *ptr++, ((i + 1) & 0x7) != 0? " " : "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Always set the minlength value in the block, because the JIT compiler
|
||||
makes use of it. However, don't set the bit unless the length is greater than
|
||||
@@ -1351,10 +1478,15 @@ if (bits_set || min > 0
|
||||
|
||||
#ifdef SUPPORT_JIT
|
||||
extra->executable_jit = NULL;
|
||||
if ((options & PCRE_STUDY_JIT_COMPILE) != 0) _pcre_jit_compile(re, extra);
|
||||
if ((options & PCRE_STUDY_JIT_COMPILE) != 0) PRIV(jit_compile)(re, extra);
|
||||
if (study->flags == 0 && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) == 0)
|
||||
{
|
||||
#ifdef COMPILE_PCRE8
|
||||
pcre_free_study(extra);
|
||||
#endif
|
||||
#ifdef COMPILE_PCRE16
|
||||
pcre16_free_study(extra);
|
||||
#endif
|
||||
extra = NULL;
|
||||
}
|
||||
#endif
|
||||
@@ -1370,19 +1502,26 @@ return extra;
|
||||
|
||||
/* This function frees the memory that was obtained by pcre_study().
|
||||
|
||||
Argument: a pointer to the pcre_extra block
|
||||
Argument: a pointer to the pcre[16]_extra block
|
||||
Returns: nothing
|
||||
*/
|
||||
|
||||
#ifdef COMPILE_PCRE8
|
||||
PCRE_EXP_DEFN void
|
||||
pcre_free_study(pcre_extra *extra)
|
||||
#else
|
||||
PCRE_EXP_DEFN void
|
||||
pcre16_free_study(pcre16_extra *extra)
|
||||
#endif
|
||||
{
|
||||
if (extra == NULL)
|
||||
return;
|
||||
#ifdef SUPPORT_JIT
|
||||
if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
|
||||
extra->executable_jit != NULL)
|
||||
_pcre_jit_free(extra->executable_jit);
|
||||
PRIV(jit_free)(extra->executable_jit);
|
||||
#endif
|
||||
pcre_free(extra);
|
||||
PUBL(free)(extra);
|
||||
}
|
||||
|
||||
/* End of pcre_study.c */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2009 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef PCRE_INCLUDED
|
||||
|
||||
/* This module contains some fixed tables that are used by more than one of the
|
||||
PCRE code modules. The tables are also #included by the pcretest program, which
|
||||
@@ -50,11 +51,12 @@ clashes with the library. */
|
||||
|
||||
#include "pcreinal.h"
|
||||
|
||||
#endif /* PCRE_INCLUDED */
|
||||
|
||||
/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that
|
||||
the definition is next to the definition of the opcodes in pcre_internal.h. */
|
||||
|
||||
const uschar _pcre_OP_lengths[] = { OP_LENGTHS };
|
||||
const pcre_uint8 PRIV(OP_lengths)[] = { OP_LENGTHS };
|
||||
|
||||
|
||||
|
||||
@@ -65,44 +67,38 @@ const uschar _pcre_OP_lengths[] = { OP_LENGTHS };
|
||||
/* These are the breakpoints for different numbers of bytes in a UTF-8
|
||||
character. */
|
||||
|
||||
#ifdef SUPPORT_UTF8
|
||||
#if (defined SUPPORT_UTF && defined COMPILE_PCRE8) \
|
||||
|| (defined PCRE_INCLUDED && defined SUPPORT_PCRE16)
|
||||
|
||||
const int _pcre_utf8_table1[] =
|
||||
/* These tables are also required by pcretest in 16 bit mode. */
|
||||
|
||||
const int PRIV(utf8_table1)[] =
|
||||
{ 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
|
||||
|
||||
const int _pcre_utf8_table1_size = sizeof(_pcre_utf8_table1)/sizeof(int);
|
||||
const int PRIV(utf8_table1_size) = sizeof(PRIV(utf8_table1)) / sizeof(int);
|
||||
|
||||
/* These are the indicator bits and the mask for the data bits to set in the
|
||||
first byte of a character, indexed by the number of additional bytes. */
|
||||
|
||||
const int _pcre_utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
|
||||
const int _pcre_utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
|
||||
const int PRIV(utf8_table2)[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
|
||||
const int PRIV(utf8_table3)[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
|
||||
|
||||
/* Table of the number of extra bytes, indexed by the first byte masked with
|
||||
0x3f. The highest number for a valid UTF-8 first byte is in fact 0x3d. */
|
||||
|
||||
const uschar _pcre_utf8_table4[] = {
|
||||
const pcre_uint8 PRIV(utf8_table4)[] = {
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
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 };
|
||||
|
||||
#ifdef SUPPORT_JIT
|
||||
/* Full table of the number of extra bytes when the
|
||||
character code is greater or equal than 0xc0.
|
||||
See _pcre_utf8_table4 above. */
|
||||
#endif /* (SUPPORT_UTF && COMPILE_PCRE8) || (PCRE_INCLUDED && SUPPORT_PCRE16)*/
|
||||
|
||||
const uschar _pcre_utf8_char_sizes[] = {
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
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,4,4,4,4,
|
||||
};
|
||||
#endif
|
||||
#ifdef SUPPORT_UTF
|
||||
|
||||
/* Table to translate from particular type value to the general value. */
|
||||
|
||||
const int _pcre_ucp_gentype[] = {
|
||||
const int 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 */
|
||||
@@ -114,10 +110,10 @@ const int _pcre_ucp_gentype[] = {
|
||||
};
|
||||
|
||||
#ifdef SUPPORT_JIT
|
||||
/* This table reverses _pcre_ucp_gentype. We can save the cost
|
||||
/* This table reverses PRIV(ucp_gentype). We can save the cost
|
||||
of a memory load. */
|
||||
|
||||
const int _pcre_ucp_typerange[] = {
|
||||
const int PRIV(ucp_typerange)[] = {
|
||||
ucp_Cc, ucp_Cs,
|
||||
ucp_Ll, ucp_Lu,
|
||||
ucp_Mc, ucp_Mn,
|
||||
@@ -126,7 +122,7 @@ const int _pcre_ucp_typerange[] = {
|
||||
ucp_Sc, ucp_So,
|
||||
ucp_Zl, ucp_Zs,
|
||||
};
|
||||
#endif
|
||||
#endif /* SUPPORT_JIT */
|
||||
|
||||
/* The pcre_utt[] table below translates Unicode property names into type and
|
||||
code values. It is searched by binary chop, so must be in collating sequence of
|
||||
@@ -284,7 +280,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
||||
#define STRING_Zp0 STR_Z STR_p "\0"
|
||||
#define STRING_Zs0 STR_Z STR_s "\0"
|
||||
|
||||
const char _pcre_utt_names[] =
|
||||
const char PRIV(utt_names)[] =
|
||||
STRING_Any0
|
||||
STRING_Arabic0
|
||||
STRING_Armenian0
|
||||
@@ -424,7 +420,7 @@ const char _pcre_utt_names[] =
|
||||
STRING_Zp0
|
||||
STRING_Zs0;
|
||||
|
||||
const ucp_type_table _pcre_utt[] = {
|
||||
const ucp_type_table PRIV(utt)[] = {
|
||||
{ 0, PT_ANY, 0 },
|
||||
{ 4, PT_SC, ucp_Arabic },
|
||||
{ 11, PT_SC, ucp_Armenian },
|
||||
@@ -565,8 +561,8 @@ const ucp_type_table _pcre_utt[] = {
|
||||
{ 961, PT_PC, ucp_Zs }
|
||||
};
|
||||
|
||||
const int _pcre_utt_size = sizeof(_pcre_utt)/sizeof(ucp_type_table);
|
||||
const int PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
|
||||
|
||||
#endif /* SUPPORT_UTF8 */
|
||||
#endif /* SUPPORT_UTF */
|
||||
|
||||
/* End of pcre_tables.c */
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
/*************************************************
|
||||
* Perl-Compatible Regular Expressions *
|
||||
*************************************************/
|
||||
|
||||
/* PCRE is a library of functions to support regular expressions whose syntax
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2009 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* 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.
|
||||
|
||||
* Neither the name of the University of Cambridge nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 OWNER 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.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/* This module contains an internal function that tests a compiled pattern to
|
||||
see if it was compiled with the opposite endianness. If so, it uses an
|
||||
auxiliary local function to flip the appropriate bytes. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcreinal.h"
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Flip bytes in an integer *
|
||||
*************************************************/
|
||||
|
||||
/* This function is called when the magic number in a regex doesn't match, in
|
||||
order to flip its bytes to see if we are dealing with a pattern that was
|
||||
compiled on a host of different endianness. If so, this function is used to
|
||||
flip other byte values.
|
||||
|
||||
Arguments:
|
||||
value the number to flip
|
||||
n the number of bytes to flip (assumed to be 2 or 4)
|
||||
|
||||
Returns: the flipped value
|
||||
*/
|
||||
|
||||
static unsigned long int
|
||||
byteflip(unsigned long int value, int n)
|
||||
{
|
||||
if (n == 2) return ((value & 0x00ff) << 8) | ((value & 0xff00) >> 8);
|
||||
return ((value & 0x000000ff) << 24) |
|
||||
((value & 0x0000ff00) << 8) |
|
||||
((value & 0x00ff0000) >> 8) |
|
||||
((value & 0xff000000) >> 24);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Test for a byte-flipped compiled regex *
|
||||
*************************************************/
|
||||
|
||||
/* This function is called from pcre_exec(), pcre_dfa_exec(), and also from
|
||||
pcre_fullinfo(). Its job is to test whether the regex is byte-flipped - that
|
||||
is, it was compiled on a system of opposite endianness. The function is called
|
||||
only when the native MAGIC_NUMBER test fails. If the regex is indeed flipped,
|
||||
we flip all the relevant values into a different data block, and return it.
|
||||
|
||||
Arguments:
|
||||
re points to the regex
|
||||
study points to study data, or NULL
|
||||
internal_re points to a new regex block
|
||||
internal_study points to a new study block
|
||||
|
||||
Returns: the new block if is is indeed a byte-flipped regex
|
||||
NULL if it is not
|
||||
*/
|
||||
|
||||
real_pcre *
|
||||
_pcre_try_flipped(const real_pcre *re, real_pcre *internal_re,
|
||||
const pcre_study_data *study, pcre_study_data *internal_study)
|
||||
{
|
||||
if (byteflip(re->magic_number, sizeof(re->magic_number)) != MAGIC_NUMBER)
|
||||
return NULL;
|
||||
|
||||
*internal_re = *re; /* To copy other fields */
|
||||
internal_re->size = byteflip(re->size, sizeof(re->size));
|
||||
internal_re->options = byteflip(re->options, sizeof(re->options));
|
||||
internal_re->flags = (pcre_uint16)byteflip(re->flags, sizeof(re->flags));
|
||||
internal_re->top_bracket =
|
||||
(pcre_uint16)byteflip(re->top_bracket, sizeof(re->top_bracket));
|
||||
internal_re->top_backref =
|
||||
(pcre_uint16)byteflip(re->top_backref, sizeof(re->top_backref));
|
||||
internal_re->first_byte =
|
||||
(pcre_uint16)byteflip(re->first_byte, sizeof(re->first_byte));
|
||||
internal_re->req_byte =
|
||||
(pcre_uint16)byteflip(re->req_byte, sizeof(re->req_byte));
|
||||
internal_re->name_table_offset =
|
||||
(pcre_uint16)byteflip(re->name_table_offset, sizeof(re->name_table_offset));
|
||||
internal_re->name_entry_size =
|
||||
(pcre_uint16)byteflip(re->name_entry_size, sizeof(re->name_entry_size));
|
||||
internal_re->name_count =
|
||||
(pcre_uint16)byteflip(re->name_count, sizeof(re->name_count));
|
||||
|
||||
if (study != NULL)
|
||||
{
|
||||
*internal_study = *study; /* To copy other fields */
|
||||
internal_study->size = byteflip(study->size, sizeof(study->size));
|
||||
internal_study->flags = byteflip(study->flags, sizeof(study->flags));
|
||||
internal_study->minlength = byteflip(study->minlength,
|
||||
sizeof(study->minlength));
|
||||
}
|
||||
|
||||
return internal_re;
|
||||
}
|
||||
|
||||
/* End of pcre_tryflipped.c */
|
||||
@@ -18,21 +18,21 @@
|
||||
/* Instead, just supply small dummy tables. */
|
||||
|
||||
#ifndef SUPPORT_UCP
|
||||
const ucd_record _pcre_ucd_records[] = {{0,0,0 }};
|
||||
const uschar _pcre_ucd_stage1[] = {0};
|
||||
const pcre_uint16 _pcre_ucd_stage2[] = {0};
|
||||
const ucd_record PRIV(ucd_records)[] = {{0,0,0 }};
|
||||
const pcre_uint8 PRIV(ucd_stage1)[] = {0};
|
||||
const pcre_uint16 PRIV(ucd_stage2)[] = {0};
|
||||
#else
|
||||
|
||||
/* When recompiling tables with a new Unicode version,
|
||||
please check types in the structure definition from pcre_internal.h:
|
||||
typedef struct {
|
||||
uschar property_0;
|
||||
uschar property_1;
|
||||
pcre_uint8 property_0;
|
||||
pcre_uint8 property_1;
|
||||
pcre_int32 property_2;
|
||||
} ucd_record; */
|
||||
|
||||
|
||||
const ucd_record _pcre_ucd_records[] = { /* 4320 bytes, record size 8 */
|
||||
const ucd_record PRIV(ucd_records)[] = { /* 4320 bytes, record size 8 */
|
||||
{ 9, 0, 0, }, /* 0 */
|
||||
{ 9, 29, 0, }, /* 1 */
|
||||
{ 9, 21, 0, }, /* 2 */
|
||||
@@ -575,7 +575,7 @@ const ucd_record _pcre_ucd_records[] = { /* 4320 bytes, record size 8 */
|
||||
{ 26, 26, 0, }, /* 539 */
|
||||
};
|
||||
|
||||
const uschar _pcre_ucd_stage1[] = { /* 8704 bytes */
|
||||
const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* U+0000 */
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* U+0800 */
|
||||
32, 33, 34, 34, 35, 36, 37, 38, 39, 40, 40, 40, 41, 42, 43, 44, /* U+1000 */
|
||||
@@ -1122,7 +1122,7 @@ const uschar _pcre_ucd_stage1[] = { /* 8704 bytes */
|
||||
114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,184, /* U+10F800 */
|
||||
};
|
||||
|
||||
const pcre_uint16 _pcre_ucd_stage2[] = { /* 47360 bytes, block = 128 */
|
||||
const pcre_uint16 PRIV(ucd_stage2)[] = { /* 47360 bytes, block = 128 */
|
||||
/* block 0 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2008 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -79,8 +79,13 @@ 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
|
||||
PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
|
||||
pcre_version(void)
|
||||
#else
|
||||
PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
|
||||
pcre16_version(void)
|
||||
#endif
|
||||
{
|
||||
return (XSTRING(Z PCRE_PRERELEASE)[1] == 0)?
|
||||
XSTRING(PCRE_MAJOR.PCRE_MINOR PCRE_DATE) :
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2009 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -103,10 +103,10 @@ Returns: = 0 if the string is a valid UTF-8 string
|
||||
*/
|
||||
|
||||
int
|
||||
_pcre_valid_utf8(USPTR string, int length, int *erroroffset)
|
||||
PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset)
|
||||
{
|
||||
#ifdef SUPPORT_UTF8
|
||||
register USPTR p;
|
||||
#ifdef SUPPORT_UTF
|
||||
register PCRE_PUCHAR p;
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
@@ -133,7 +133,7 @@ for (p = string; length-- > 0; p++)
|
||||
return PCRE_UTF8_ERR21;
|
||||
}
|
||||
|
||||
ab = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */
|
||||
ab = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */
|
||||
if (length < ab)
|
||||
{
|
||||
*erroroffset = (int)(p - string); /* Missing bytes */
|
||||
@@ -288,7 +288,7 @@ for (p = string; length-- > 0; p++)
|
||||
}
|
||||
}
|
||||
|
||||
#else /* SUPPORT_UTF8 */
|
||||
#else /* SUPPORT_UTF */
|
||||
(void)(string); /* Keep picky compilers happy */
|
||||
(void)(length);
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2010 University of Cambridge
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -64,39 +64,63 @@ Returns: TRUE if character matches, else FALSE
|
||||
*/
|
||||
|
||||
BOOL
|
||||
_pcre_xclass(int c, const uschar *data)
|
||||
PRIV(xclass)(int c, const pcre_uchar *data, BOOL utf)
|
||||
{
|
||||
int t;
|
||||
BOOL negated = (*data & XCL_NOT) != 0;
|
||||
|
||||
(void)utf;
|
||||
#ifdef COMPILE_PCRE8
|
||||
/* In 8 bit mode, this must always be TRUE. Help the compiler to know that. */
|
||||
utf = TRUE;
|
||||
#endif
|
||||
|
||||
/* Character values < 256 are matched against a bitmap, if one is present. If
|
||||
not, we still carry on, because there may be ranges that start below 256 in the
|
||||
additional data. */
|
||||
|
||||
if (c < 256)
|
||||
{
|
||||
if ((*data & XCL_MAP) != 0 && (data[1 + c/8] & (1 << (c&7))) != 0)
|
||||
return !negated; /* char found */
|
||||
if ((*data & XCL_MAP) != 0 &&
|
||||
(((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0)
|
||||
return !negated; /* char found */
|
||||
}
|
||||
|
||||
/* First skip the bit map if present. Then match against the list of Unicode
|
||||
properties or large chars or ranges that end with a large char. We won't ever
|
||||
encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */
|
||||
|
||||
if ((*data++ & XCL_MAP) != 0) data += 32;
|
||||
if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(pcre_uchar);
|
||||
|
||||
while ((t = *data++) != XCL_END)
|
||||
{
|
||||
int x, y;
|
||||
if (t == XCL_SINGLE)
|
||||
{
|
||||
GETCHARINC(x, data);
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf)
|
||||
{
|
||||
GETCHARINC(x, data); /* macro generates multiple statements */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
x = *data++;
|
||||
if (c == x) return !negated;
|
||||
}
|
||||
else if (t == XCL_RANGE)
|
||||
{
|
||||
GETCHARINC(x, data);
|
||||
GETCHARINC(y, data);
|
||||
#ifdef SUPPORT_UTF
|
||||
if (utf)
|
||||
{
|
||||
GETCHARINC(x, data); /* macro generates multiple statements */
|
||||
GETCHARINC(y, data); /* macro generates multiple statements */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
x = *data++;
|
||||
y = *data++;
|
||||
}
|
||||
if (c >= x && c <= y) return !negated;
|
||||
}
|
||||
|
||||
@@ -117,7 +141,7 @@ while ((t = *data++) != XCL_END)
|
||||
break;
|
||||
|
||||
case PT_GC:
|
||||
if ((data[1] == _pcre_ucp_gentype[prop->chartype]) == (t == XCL_PROP))
|
||||
if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == (t == XCL_PROP))
|
||||
return !negated;
|
||||
break;
|
||||
|
||||
@@ -130,28 +154,28 @@ while ((t = *data++) != XCL_END)
|
||||
break;
|
||||
|
||||
case PT_ALNUM:
|
||||
if ((_pcre_ucp_gentype[prop->chartype] == ucp_L ||
|
||||
_pcre_ucp_gentype[prop->chartype] == ucp_N) == (t == XCL_PROP))
|
||||
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
|
||||
PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (t == XCL_PROP))
|
||||
return !negated;
|
||||
break;
|
||||
|
||||
case PT_SPACE: /* Perl space */
|
||||
if ((_pcre_ucp_gentype[prop->chartype] == ucp_Z ||
|
||||
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
|
||||
c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)
|
||||
== (t == XCL_PROP))
|
||||
return !negated;
|
||||
break;
|
||||
|
||||
case PT_PXSPACE: /* POSIX space */
|
||||
if ((_pcre_ucp_gentype[prop->chartype] == ucp_Z ||
|
||||
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
|
||||
c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
|
||||
c == CHAR_FF || c == CHAR_CR) == (t == XCL_PROP))
|
||||
return !negated;
|
||||
break;
|
||||
|
||||
case PT_WORD:
|
||||
if ((_pcre_ucp_gentype[prop->chartype] == ucp_L ||
|
||||
_pcre_ucp_gentype[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE)
|
||||
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
|
||||
PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE)
|
||||
== (t == XCL_PROP))
|
||||
return !negated;
|
||||
break;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
|
||||
{
|
||||
return "arm-thumb2";
|
||||
return "ARM-Thumb2" SLJIT_CPUINFO;
|
||||
}
|
||||
|
||||
/* Last register + 1. */
|
||||
@@ -38,7 +38,7 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
|
||||
#define TMP_FREG1 (SLJIT_FLOAT_REG4 + 1)
|
||||
#define TMP_FREG2 (SLJIT_FLOAT_REG4 + 2)
|
||||
|
||||
/* See sljit_emit_enter if you want to change them. */
|
||||
/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
|
||||
0, 0, 1, 2, 12, 5, 6, 7, 8, 10, 11, 13, 3, 4, 14, 15
|
||||
};
|
||||
@@ -122,9 +122,11 @@ typedef sljit_ui sljit_ins;
|
||||
#define LSR_W 0xfa20f000
|
||||
#define LSR_WI 0xea4f0010
|
||||
#define MOV 0x4600
|
||||
#define MOVS 0x0000
|
||||
#define MOVSI 0x2000
|
||||
#define MOVT 0xf2c00000
|
||||
#define MOVW 0xf2400000
|
||||
#define MOV_W 0xea4f0000
|
||||
#define MOV_WI 0xf04f0000
|
||||
#define MUL 0xfb00f000
|
||||
#define MVNS 0x43c0
|
||||
@@ -158,6 +160,7 @@ typedef sljit_ui sljit_ins;
|
||||
#define SXTH 0xb200
|
||||
#define SXTH_W 0xfa0ff080
|
||||
#define TST 0x4200
|
||||
#define UMULL 0xfba00000
|
||||
#define UXTB 0xb2c0
|
||||
#define UXTB_W 0xfa5ff080
|
||||
#define UXTH 0xb280
|
||||
@@ -616,6 +619,13 @@ static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, slji
|
||||
case SLJIT_SHL:
|
||||
if (flags & ARG2_IMM) {
|
||||
imm &= 0x1f;
|
||||
if (imm == 0) {
|
||||
if (!(flags & SET_FLAGS))
|
||||
return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
|
||||
if (IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
|
||||
return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
|
||||
}
|
||||
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6));
|
||||
return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
|
||||
@@ -624,6 +634,13 @@ static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, slji
|
||||
case SLJIT_LSHR:
|
||||
if (flags & ARG2_IMM) {
|
||||
imm &= 0x1f;
|
||||
if (imm == 0) {
|
||||
if (!(flags & SET_FLAGS))
|
||||
return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
|
||||
if (IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
|
||||
return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
|
||||
}
|
||||
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6));
|
||||
return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
|
||||
@@ -632,6 +649,13 @@ static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, slji
|
||||
case SLJIT_ASHR:
|
||||
if (flags & ARG2_IMM) {
|
||||
imm &= 0x1f;
|
||||
if (imm == 0) {
|
||||
if (!(flags & SET_FLAGS))
|
||||
return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
|
||||
if (IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
|
||||
return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
|
||||
}
|
||||
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6));
|
||||
return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
|
||||
@@ -1077,36 +1101,36 @@ static SLJIT_INLINE int emit_op_mem(struct sljit_compiler *compiler, int flags,
|
||||
return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
int size;
|
||||
sljit_ins push;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, temporaries, generals, local_size);
|
||||
check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
|
||||
push = (1 << 4);
|
||||
if (generals >= 5)
|
||||
if (saveds >= 5)
|
||||
push |= 1 << 11;
|
||||
if (generals >= 4)
|
||||
if (saveds >= 4)
|
||||
push |= 1 << 10;
|
||||
if (generals >= 3)
|
||||
if (saveds >= 3)
|
||||
push |= 1 << 8;
|
||||
if (generals >= 2)
|
||||
if (saveds >= 2)
|
||||
push |= 1 << 7;
|
||||
if (generals >= 1)
|
||||
if (saveds >= 1)
|
||||
push |= 1 << 6;
|
||||
if (temporaries >= 5)
|
||||
push |= 1 << 5;
|
||||
FAIL_IF(generals >= 3
|
||||
FAIL_IF(saveds >= 3
|
||||
? push_inst32(compiler, PUSH_W | (1 << 14) | push)
|
||||
: push_inst16(compiler, PUSH | push));
|
||||
|
||||
/* Stack must be aligned to 8 bytes: */
|
||||
size = (3 + generals) * sizeof(sljit_uw);
|
||||
size = (3 + saveds) * sizeof(sljit_uw);
|
||||
local_size += size;
|
||||
local_size = (local_size + 7) & ~7;
|
||||
local_size -= size;
|
||||
@@ -1119,45 +1143,40 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
||||
}
|
||||
|
||||
if (args >= 1)
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_GENERAL_REG1, SLJIT_TEMPORARY_REG1)));
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG1, SLJIT_TEMPORARY_REG1)));
|
||||
if (args >= 2)
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_GENERAL_REG2, SLJIT_TEMPORARY_REG2)));
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG2, SLJIT_TEMPORARY_REG2)));
|
||||
if (args >= 3)
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_GENERAL_REG3, SLJIT_TEMPORARY_REG3)));
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG3, SLJIT_TEMPORARY_REG3)));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
int size;
|
||||
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_fake_enter(compiler, args, temporaries, generals, local_size);
|
||||
check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
|
||||
size = (3 + generals) * sizeof(sljit_uw);
|
||||
size = (3 + saveds) * sizeof(sljit_uw);
|
||||
local_size += size;
|
||||
local_size = (local_size + 7) & ~7;
|
||||
local_size -= size;
|
||||
compiler->local_size = local_size;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
|
||||
{
|
||||
sljit_ins pop;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, src, srcw);
|
||||
check_sljit_emit_return(compiler, op, src, srcw);
|
||||
|
||||
if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG) {
|
||||
if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REG3)
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_RETURN_REG, src)));
|
||||
else
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, SLJIT_RETURN_REG, src, srcw));
|
||||
}
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
if (compiler->local_size > 0) {
|
||||
if (compiler->local_size <= (127 << 2))
|
||||
@@ -1167,19 +1186,19 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
||||
}
|
||||
|
||||
pop = (1 << 4);
|
||||
if (compiler->generals >= 5)
|
||||
if (compiler->saveds >= 5)
|
||||
pop |= 1 << 11;
|
||||
if (compiler->generals >= 4)
|
||||
if (compiler->saveds >= 4)
|
||||
pop |= 1 << 10;
|
||||
if (compiler->generals >= 3)
|
||||
if (compiler->saveds >= 3)
|
||||
pop |= 1 << 8;
|
||||
if (compiler->generals >= 2)
|
||||
if (compiler->saveds >= 2)
|
||||
pop |= 1 << 7;
|
||||
if (compiler->generals >= 1)
|
||||
if (compiler->saveds >= 1)
|
||||
pop |= 1 << 6;
|
||||
if (compiler->temporaries >= 5)
|
||||
pop |= 1 << 5;
|
||||
return compiler->generals >= 3
|
||||
return compiler->saveds >= 3
|
||||
? push_inst32(compiler, POP_W | (1 << 15) | pop)
|
||||
: push_inst16(compiler, POP | pop);
|
||||
}
|
||||
@@ -1188,6 +1207,21 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
||||
/* Operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator);
|
||||
extern unsigned int __aeabi_idivmod(unsigned numerator, unsigned denominator);
|
||||
#else
|
||||
#error "Software divmod functions are needed"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
@@ -1201,6 +1235,32 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
|
||||
case SLJIT_NOP:
|
||||
push_inst16(compiler, NOP);
|
||||
break;
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
return push_inst32(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
|
||||
| (reg_map[SLJIT_TEMPORARY_REG2] << 8)
|
||||
| (reg_map[SLJIT_TEMPORARY_REG1] << 12)
|
||||
| (reg_map[SLJIT_TEMPORARY_REG1] << 16)
|
||||
| reg_map[SLJIT_TEMPORARY_REG2]);
|
||||
case SLJIT_UDIV:
|
||||
case SLJIT_SDIV:
|
||||
if (compiler->temporaries >= 4) {
|
||||
FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */));
|
||||
FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */));
|
||||
} else if (compiler->temporaries >= 3)
|
||||
FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */));
|
||||
#if defined(__GNUC__)
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
|
||||
(op == SLJIT_UDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
|
||||
#else
|
||||
#error "Software divmod functions are needed"
|
||||
#endif
|
||||
if (compiler->temporaries >= 4) {
|
||||
FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */));
|
||||
return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */);
|
||||
} else if (compiler->temporaries >= 3)
|
||||
return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
@@ -1412,6 +1472,24 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
|
||||
{
|
||||
check_sljit_get_register_index(reg);
|
||||
return reg_map[reg];
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, int size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_op_custom(compiler, instruction, size);
|
||||
SLJIT_ASSERT(size == 2 || size == 4);
|
||||
|
||||
if (size == 2)
|
||||
return push_inst16(compiler, *(sljit_uh*)instruction);
|
||||
return push_inst32(compiler, *(sljit_ins*)instruction);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Floating point operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
@@ -1567,17 +1645,17 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, in
|
||||
/* Other instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int generals, int local_size)
|
||||
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)
|
||||
{
|
||||
int size;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size);
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
|
||||
size = (3 + generals) * sizeof(sljit_uw);
|
||||
size = (3 + saveds) * sizeof(sljit_uw);
|
||||
local_size += size;
|
||||
local_size = (local_size + 7) & ~7;
|
||||
local_size -= size;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -27,9 +27,9 @@
|
||||
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
|
||||
{
|
||||
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||
return "arm-v7";
|
||||
return "ARMv7" SLJIT_CPUINFO;
|
||||
#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
return "arm-v5";
|
||||
return "ARMv5" SLJIT_CPUINFO;
|
||||
#else
|
||||
#error "Internal error: Unknown ARM architecture"
|
||||
#endif
|
||||
@@ -54,7 +54,7 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
|
||||
#define MAX_DIFFERENCE(max_diff) \
|
||||
(((max_diff) / (int)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1))
|
||||
|
||||
/* See sljit_emit_enter if you want to change them. */
|
||||
/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
|
||||
0, 0, 1, 2, 10, 11, 4, 5, 6, 7, 8, 13, 3, 12, 14, 15
|
||||
};
|
||||
@@ -84,7 +84,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
|
||||
#define BX 0xe12fff10
|
||||
#define CLZ 0xe16f0f10
|
||||
#define CMP_DP 0xa
|
||||
#define DEBUGGER 0xe1200070
|
||||
#define BKPT 0xe1200070
|
||||
#define EOR_DP 0x1
|
||||
#define MOV_DP 0xd
|
||||
#define MUL 0xe0000090
|
||||
@@ -98,6 +98,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
|
||||
#define SBC_DP 0x6
|
||||
#define SMULL 0xe0c00090
|
||||
#define SUB_DP 0x2
|
||||
#define UMULL 0xe0800090
|
||||
#define VABS_F64 0xeeb00bc0
|
||||
#define VADD_F64 0xee300b00
|
||||
#define VCMP_F64 0xeeb40b40
|
||||
@@ -819,38 +820,38 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w);
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
int size;
|
||||
sljit_uw push;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, temporaries, generals, local_size);
|
||||
check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
|
||||
/* Push general registers, temporary registers
|
||||
/* Push saved registers, temporary registers
|
||||
stmdb sp!, {..., lr} */
|
||||
push = PUSH | (1 << 14);
|
||||
if (temporaries >= 5)
|
||||
push |= 1 << 11;
|
||||
if (temporaries >= 4)
|
||||
push |= 1 << 10;
|
||||
if (generals >= 5)
|
||||
if (saveds >= 5)
|
||||
push |= 1 << 8;
|
||||
if (generals >= 4)
|
||||
if (saveds >= 4)
|
||||
push |= 1 << 7;
|
||||
if (generals >= 3)
|
||||
if (saveds >= 3)
|
||||
push |= 1 << 6;
|
||||
if (generals >= 2)
|
||||
if (saveds >= 2)
|
||||
push |= 1 << 5;
|
||||
if (generals >= 1)
|
||||
if (saveds >= 1)
|
||||
push |= 1 << 4;
|
||||
EMIT_INSTRUCTION(push);
|
||||
|
||||
/* Stack must be aligned to 8 bytes: */
|
||||
size = (1 + generals) * sizeof(sljit_uw);
|
||||
size = (1 + saveds) * sizeof(sljit_uw);
|
||||
if (temporaries >= 4)
|
||||
size += (temporaries - 3) * sizeof(sljit_uw);
|
||||
local_size += size;
|
||||
@@ -861,26 +862,26 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
||||
FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size));
|
||||
|
||||
if (args >= 1)
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_GENERAL_REG1, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG1)));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG1, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG1)));
|
||||
if (args >= 2)
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_GENERAL_REG2, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG2)));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG2, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG2)));
|
||||
if (args >= 3)
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_GENERAL_REG3, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG3)));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG3, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG3)));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
int size;
|
||||
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_fake_enter(compiler, args, temporaries, generals, local_size);
|
||||
check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
|
||||
size = (1 + generals) * sizeof(sljit_uw);
|
||||
size = (1 + saveds) * sizeof(sljit_uw);
|
||||
if (temporaries >= 4)
|
||||
size += (temporaries - 3) * sizeof(sljit_uw);
|
||||
local_size += size;
|
||||
@@ -889,35 +890,34 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler,
|
||||
compiler->local_size = local_size;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
|
||||
{
|
||||
sljit_uw pop;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, src, srcw);
|
||||
check_sljit_emit_return(compiler, op, src, srcw);
|
||||
|
||||
if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG)
|
||||
FAIL_IF(emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, SLJIT_RETURN_REG, 0, TMP_REG1, 0, src, srcw));
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
if (compiler->local_size > 0)
|
||||
FAIL_IF(emit_op(compiler, SLJIT_ADD, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size));
|
||||
|
||||
pop = POP | (1 << 15);
|
||||
/* Push general registers, temporary registers
|
||||
/* Push saved registers, temporary registers
|
||||
ldmia sp!, {..., pc} */
|
||||
if (compiler->temporaries >= 5)
|
||||
pop |= 1 << 11;
|
||||
if (compiler->temporaries >= 4)
|
||||
pop |= 1 << 10;
|
||||
if (compiler->generals >= 5)
|
||||
if (compiler->saveds >= 5)
|
||||
pop |= 1 << 8;
|
||||
if (compiler->generals >= 4)
|
||||
if (compiler->saveds >= 4)
|
||||
pop |= 1 << 7;
|
||||
if (compiler->generals >= 3)
|
||||
if (compiler->saveds >= 3)
|
||||
pop |= 1 << 6;
|
||||
if (compiler->generals >= 2)
|
||||
if (compiler->saveds >= 2)
|
||||
pop |= 1 << 5;
|
||||
if (compiler->generals >= 1)
|
||||
if (compiler->saveds >= 1)
|
||||
pop |= 1 << 4;
|
||||
|
||||
return push_inst(compiler, pop);
|
||||
@@ -992,7 +992,9 @@ static sljit_w data_transfer_insts[16] = {
|
||||
if (compiler->shift_imm != 0x20) { \
|
||||
SLJIT_ASSERT(src1 == TMP_REG1); \
|
||||
SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \
|
||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (compiler->shift_imm << 7) | (opcode << 5) | reg_map[src2])); \
|
||||
if (compiler->shift_imm != 0) \
|
||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (compiler->shift_imm << 7) | (opcode << 5) | reg_map[src2])); \
|
||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, reg_map[src2])); \
|
||||
} \
|
||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | ((flags & ARGS_SWAPPED) ? reg_map[src2] : reg_map[src1])));
|
||||
|
||||
@@ -1755,6 +1757,21 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator);
|
||||
extern unsigned int __aeabi_idivmod(unsigned numerator, unsigned denominator);
|
||||
#else
|
||||
#error "Software divmod functions are needed"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
@@ -1763,11 +1780,40 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
|
||||
op = GET_OPCODE(op);
|
||||
switch (op) {
|
||||
case SLJIT_BREAKPOINT:
|
||||
EMIT_INSTRUCTION(DEBUGGER);
|
||||
EMIT_INSTRUCTION(BKPT);
|
||||
break;
|
||||
case SLJIT_NOP:
|
||||
EMIT_INSTRUCTION(NOP);
|
||||
break;
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||
return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
|
||||
| (reg_map[SLJIT_TEMPORARY_REG2] << 16)
|
||||
| (reg_map[SLJIT_TEMPORARY_REG1] << 12)
|
||||
| (reg_map[SLJIT_TEMPORARY_REG1] << 8)
|
||||
| reg_map[SLJIT_TEMPORARY_REG2]);
|
||||
#else
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG2)));
|
||||
return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
|
||||
| (reg_map[SLJIT_TEMPORARY_REG2] << 16)
|
||||
| (reg_map[SLJIT_TEMPORARY_REG1] << 12)
|
||||
| (reg_map[SLJIT_TEMPORARY_REG1] << 8)
|
||||
| reg_map[TMP_REG1]);
|
||||
#endif
|
||||
case SLJIT_UDIV:
|
||||
case SLJIT_SDIV:
|
||||
if (compiler->temporaries >= 3)
|
||||
EMIT_INSTRUCTION(0xe52d2008 /* str r2, [sp, #-8]! */);
|
||||
#if defined(__GNUC__)
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
|
||||
(op == SLJIT_UDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
|
||||
#else
|
||||
#error "Software divmod functions are needed"
|
||||
#endif
|
||||
if (compiler->temporaries >= 3)
|
||||
return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
@@ -1870,6 +1916,22 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
|
||||
{
|
||||
check_sljit_get_register_index(reg);
|
||||
return reg_map[reg];
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, int size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_op_custom(compiler, instruction, size);
|
||||
SLJIT_ASSERT(size == 4);
|
||||
|
||||
return push_inst(compiler, *(sljit_uw*)instruction);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Floating point operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
@@ -2079,17 +2141,17 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, in
|
||||
/* Other instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int generals, int local_size)
|
||||
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)
|
||||
{
|
||||
int size;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size);
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
|
||||
size = (1 + generals) * sizeof(sljit_uw);
|
||||
size = (1 + saveds) * sizeof(sljit_uw);
|
||||
if (temporaries >= 4)
|
||||
size += (temporaries - 3) * sizeof(sljit_uw);
|
||||
local_size += size;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -28,21 +28,25 @@
|
||||
#define _SLJIT_CONFIG_INTERNAL_H_
|
||||
|
||||
/*
|
||||
SLJIT defines the following variables itself depending on the configuration:
|
||||
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_CALL : C calling convention for both calling JIT and C callbacks from JIT
|
||||
SLJIT defines the following macros depending on the target architecture:
|
||||
|
||||
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_BIG_ENDIAN : big endian architecture
|
||||
SLJIT_LITTLE_ENDIAN : little endian architecture
|
||||
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET()
|
||||
SLJIT_W : for defining 64 bit constants on 64 bit architectures (compiler workaround)
|
||||
SLJIT_UNALIGNED : allows unaligned memory accesses for integer arithmetic (only!)
|
||||
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
|
||||
|
||||
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_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)
|
||||
*/
|
||||
|
||||
#if !((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
@@ -226,7 +230,12 @@ typedef signed int sljit_i;
|
||||
/* Machine word type. Can encapsulate a pointer.
|
||||
32 bit for 32 bit machines.
|
||||
64 bit for 64 bit machines. */
|
||||
#if !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
|
||||
/* Just to have something. */
|
||||
#define SLJIT_WORD_SHIFT 0
|
||||
typedef unsigned long int sljit_uw;
|
||||
typedef long int sljit_w;
|
||||
#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;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -263,8 +263,11 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
|
||||
header->prev_size = free_block->size;
|
||||
}
|
||||
|
||||
/* The whole chunk is free. */
|
||||
if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {
|
||||
/* If this block is freed, we still have (allocated_size / 2) free space. */
|
||||
if (total_size - free_block->size > (allocated_size * 3 / 2)) {
|
||||
total_size -= free_block->size;
|
||||
sljit_remove_free_block(free_block);
|
||||
free_chunk(free_block, free_block->size + sizeof(struct block_header));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -228,7 +228,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
|
||||
compiler->abuf->used_size = 0;
|
||||
|
||||
compiler->temporaries = -1;
|
||||
compiler->generals = -1;
|
||||
compiler->saveds = -1;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
compiler->args = -1;
|
||||
@@ -475,12 +475,12 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
||||
#define FUNCTION_CHECK_IS_REG(r) \
|
||||
((r) == SLJIT_UNUSED || (r) == SLJIT_LOCALS_REG || \
|
||||
((r) >= SLJIT_TEMPORARY_REG1 && (r) <= SLJIT_TEMPORARY_REG3 && (r) <= SLJIT_TEMPORARY_REG1 - 1 + compiler->temporaries) || \
|
||||
((r) >= SLJIT_GENERAL_REG1 && (r) <= SLJIT_GENERAL_REG3 && (r) <= SLJIT_GENERAL_REG1 - 1 + compiler->generals)) \
|
||||
((r) >= SLJIT_SAVED_REG1 && (r) <= SLJIT_SAVED_REG3 && (r) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds)) \
|
||||
|
||||
#define FUNCTION_CHECK_SRC(p, i) \
|
||||
SLJIT_ASSERT(compiler->temporaries != -1 && compiler->generals != -1); \
|
||||
SLJIT_ASSERT(compiler->temporaries != -1 && compiler->saveds != -1); \
|
||||
if (((p) >= SLJIT_TEMPORARY_REG1 && (p) <= SLJIT_TEMPORARY_REG1 - 1 + compiler->temporaries) || \
|
||||
((p) >= SLJIT_GENERAL_REG1 && (p) <= SLJIT_GENERAL_REG1 - 1 + compiler->generals) || \
|
||||
((p) >= SLJIT_SAVED_REG1 && (p) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds) || \
|
||||
(p) == SLJIT_LOCALS_REG) \
|
||||
SLJIT_ASSERT(i == 0); \
|
||||
else if ((p) == SLJIT_IMM) \
|
||||
@@ -498,9 +498,9 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
||||
SLJIT_ASSERT_STOP();
|
||||
|
||||
#define FUNCTION_CHECK_DST(p, i) \
|
||||
SLJIT_ASSERT(compiler->temporaries != -1 && compiler->generals != -1); \
|
||||
SLJIT_ASSERT(compiler->temporaries != -1 && compiler->saveds != -1); \
|
||||
if (((p) >= SLJIT_TEMPORARY_REG1 && (p) <= SLJIT_TEMPORARY_REG1 - 1 + compiler->temporaries) || \
|
||||
((p) >= SLJIT_GENERAL_REG1 && (p) <= SLJIT_GENERAL_REG1 - 1 + compiler->generals) || \
|
||||
((p) >= SLJIT_SAVED_REG1 && (p) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds) || \
|
||||
(p) == SLJIT_UNUSED) \
|
||||
SLJIT_ASSERT(i == 0); \
|
||||
else if ((p) & SLJIT_MEM) { \
|
||||
@@ -551,9 +551,9 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp
|
||||
}
|
||||
|
||||
static char* reg_names[] = {
|
||||
(char*)"<noreg>", (char*)"tmp_r1", (char*)"tmp_r2", (char*)"tmp_r3",
|
||||
(char*)"tmp_er1", (char*)"tmp_er2", (char*)"gen_r1", (char*)"gen_r2",
|
||||
(char*)"gen_r3", (char*)"gen_er1", (char*)"gen_er2", (char*)"stack_r"
|
||||
(char*)"<noreg>", (char*)"t1", (char*)"t2", (char*)"t3",
|
||||
(char*)"te1", (char*)"te2", (char*)"s1", (char*)"s2",
|
||||
(char*)"s3", (char*)"se1", (char*)"se2", (char*)"lcr"
|
||||
};
|
||||
|
||||
static char* freg_names[] = {
|
||||
@@ -616,6 +616,7 @@ static char* freg_names[] = {
|
||||
static SLJIT_CONST char* op_names[] = {
|
||||
/* op0 */
|
||||
(char*)"breakpoint", (char*)"nop",
|
||||
(char*)"umul", (char*)"smul", (char*)"udiv", (char*)"sdiv",
|
||||
/* op1 */
|
||||
(char*)"mov", (char*)"mov.ub", (char*)"mov.sb", (char*)"mov.uh",
|
||||
(char*)"mov.sh", (char*)"mov.ui", (char*)"mov.si", (char*)"movu",
|
||||
@@ -673,70 +674,76 @@ static SLJIT_INLINE void check_sljit_generate_code(struct sljit_compiler *compil
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
static SLJIT_INLINE void check_sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
/* If debug and verbose are disabled, all arguments are unused. */
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(args);
|
||||
SLJIT_UNUSED_ARG(temporaries);
|
||||
SLJIT_UNUSED_ARG(generals);
|
||||
SLJIT_UNUSED_ARG(saveds);
|
||||
SLJIT_UNUSED_ARG(local_size);
|
||||
|
||||
SLJIT_ASSERT(args >= 0 && args <= 3);
|
||||
SLJIT_ASSERT(temporaries >= 0 && temporaries <= SLJIT_NO_TMP_REGISTERS);
|
||||
SLJIT_ASSERT(generals >= 0 && generals <= SLJIT_NO_GEN_REGISTERS);
|
||||
SLJIT_ASSERT(args <= generals);
|
||||
SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS);
|
||||
SLJIT_ASSERT(args <= saveds);
|
||||
SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose))
|
||||
fprintf(compiler->verbose, " enter args=%d temporaries=%d generals=%d local_size=%d\n", args, temporaries, generals, local_size);
|
||||
fprintf(compiler->verbose, " enter args=%d temporaries=%d saveds=%d local_size=%d\n", args, temporaries, saveds, local_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
static SLJIT_INLINE void check_sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
/* If debug and verbose are disabled, all arguments are unused. */
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(args);
|
||||
SLJIT_UNUSED_ARG(temporaries);
|
||||
SLJIT_UNUSED_ARG(generals);
|
||||
SLJIT_UNUSED_ARG(saveds);
|
||||
SLJIT_UNUSED_ARG(local_size);
|
||||
|
||||
SLJIT_ASSERT(args >= 0 && args <= 3);
|
||||
SLJIT_ASSERT(temporaries >= 0 && temporaries <= SLJIT_NO_TMP_REGISTERS);
|
||||
SLJIT_ASSERT(generals >= 0 && generals <= SLJIT_NO_GEN_REGISTERS);
|
||||
SLJIT_ASSERT(args <= generals);
|
||||
SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS);
|
||||
SLJIT_ASSERT(args <= saveds);
|
||||
SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose))
|
||||
fprintf(compiler->verbose, " fake_enter args=%d temporaries=%d generals=%d local_size=%d\n", args, temporaries, generals, local_size);
|
||||
fprintf(compiler->verbose, " fake_enter args=%d temporaries=%d saveds=%d local_size=%d\n", args, temporaries, saveds, local_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
static SLJIT_INLINE void check_sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
|
||||
{
|
||||
/* If debug and verbose are disabled, all arguments are unused. */
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(op);
|
||||
SLJIT_UNUSED_ARG(src);
|
||||
SLJIT_UNUSED_ARG(srcw);
|
||||
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
if (src != SLJIT_UNUSED) {
|
||||
if (op != SLJIT_UNUSED) {
|
||||
SLJIT_ASSERT(op >= SLJIT_MOV && op <= SLJIT_MOV_SI);
|
||||
FUNCTION_CHECK_SRC(src, srcw);
|
||||
}
|
||||
else
|
||||
SLJIT_ASSERT(srcw == 0);
|
||||
SLJIT_ASSERT(src == 0 && srcw == 0);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " return ");
|
||||
sljit_verbose_param(src, srcw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
if (op == SLJIT_UNUSED)
|
||||
fprintf(compiler->verbose, " return\n");
|
||||
else {
|
||||
fprintf(compiler->verbose, " return %s ", op_names[op]);
|
||||
sljit_verbose_param(src, srcw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int generals, int local_size)
|
||||
static SLJIT_INLINE void check_sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
/* If debug and verbose are disabled, all arguments are unused. */
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
@@ -744,26 +751,26 @@ static SLJIT_INLINE void check_sljit_emit_fast_enter(struct sljit_compiler *comp
|
||||
SLJIT_UNUSED_ARG(dstw);
|
||||
SLJIT_UNUSED_ARG(args);
|
||||
SLJIT_UNUSED_ARG(temporaries);
|
||||
SLJIT_UNUSED_ARG(generals);
|
||||
SLJIT_UNUSED_ARG(saveds);
|
||||
SLJIT_UNUSED_ARG(local_size);
|
||||
|
||||
SLJIT_ASSERT(args >= 0 && args <= 3);
|
||||
SLJIT_ASSERT(temporaries >= 0 && temporaries <= SLJIT_NO_TMP_REGISTERS);
|
||||
SLJIT_ASSERT(generals >= 0 && generals <= SLJIT_NO_GEN_REGISTERS);
|
||||
SLJIT_ASSERT(args <= generals);
|
||||
SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS);
|
||||
SLJIT_ASSERT(args <= saveds);
|
||||
SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
FUNCTION_CHECK_DST(dst, dstw);
|
||||
compiler->temporaries = -1;
|
||||
compiler->generals = -1;
|
||||
compiler->saveds = -1;
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " fast_enter ");
|
||||
sljit_verbose_param(dst, dstw);
|
||||
fprintf(compiler->verbose, " args=%d temporaries=%d generals=%d local_size=%d\n", args, temporaries, generals, local_size);
|
||||
fprintf(compiler->verbose, " args=%d temporaries=%d saveds=%d local_size=%d\n", args, temporaries, saveds, local_size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -793,10 +800,11 @@ static SLJIT_INLINE void check_sljit_emit_op0(struct sljit_compiler *compiler, i
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(op);
|
||||
|
||||
SLJIT_ASSERT(op >= SLJIT_BREAKPOINT && op <= SLJIT_NOP);
|
||||
SLJIT_ASSERT((op >= SLJIT_BREAKPOINT && op <= SLJIT_SMUL)
|
||||
|| ((op & ~SLJIT_INT_OP) >= SLJIT_UDIV && (op & ~SLJIT_INT_OP) <= SLJIT_SDIV));
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose))
|
||||
fprintf(compiler->verbose, " %s\n", op_names[op]);
|
||||
fprintf(compiler->verbose, " %s%s\n", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)]);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -812,6 +820,13 @@ static SLJIT_INLINE void check_sljit_emit_op1(struct sljit_compiler *compiler, i
|
||||
SLJIT_UNUSED_ARG(src);
|
||||
SLJIT_UNUSED_ARG(srcw);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
|
||||
compiler->skip_checks = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_CLZ);
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
FUNCTION_CHECK_OP();
|
||||
@@ -874,6 +889,21 @@ static SLJIT_INLINE void check_sljit_emit_op2(struct sljit_compiler *compiler, i
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_get_register_index(int reg)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(reg);
|
||||
SLJIT_ASSERT(reg > 0 && reg <= SLJIT_NO_REGISTERS);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, int size)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(instruction);
|
||||
SLJIT_UNUSED_ARG(size);
|
||||
SLJIT_ASSERT(instruction);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_fop1(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src, sljit_w srcw)
|
||||
@@ -886,6 +916,13 @@ static SLJIT_INLINE void check_sljit_emit_fop1(struct sljit_compiler *compiler,
|
||||
SLJIT_UNUSED_ARG(src);
|
||||
SLJIT_UNUSED_ARG(srcw);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
|
||||
compiler->skip_checks = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(sljit_is_fpu_available());
|
||||
SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_FCMP && GET_OPCODE(op) <= SLJIT_FABS);
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
@@ -1001,6 +1038,35 @@ static SLJIT_INLINE void check_sljit_emit_cmp(struct sljit_compiler *compiler, i
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(src1);
|
||||
SLJIT_UNUSED_ARG(src1w);
|
||||
SLJIT_UNUSED_ARG(src2);
|
||||
SLJIT_UNUSED_ARG(src2w);
|
||||
|
||||
SLJIT_ASSERT(sljit_is_fpu_available());
|
||||
SLJIT_ASSERT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP)));
|
||||
SLJIT_ASSERT((type & 0xff) >= SLJIT_C_FLOAT_EQUAL && (type & 0xff) <= SLJIT_C_FLOAT_NOT_NAN);
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
FUNCTION_FCHECK(src1, src1w);
|
||||
FUNCTION_FCHECK(src2, src2w);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " fcmp%s <%s> ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : "R", jump_names[type & 0xff]);
|
||||
sljit_verbose_fparam(src1, src1w);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_fparam(src2, src2w);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
|
||||
{
|
||||
/* If debug and verbose are disabled, all arguments are unused. */
|
||||
@@ -1067,6 +1133,52 @@ static SLJIT_INLINE void check_sljit_emit_const(struct sljit_compiler *compiler,
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE int emit_mov_before_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
|
||||
{
|
||||
/* Return if don't need to do anything. */
|
||||
if (op == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
||||
if (src == SLJIT_RETURN_REG && op == SLJIT_MOV)
|
||||
return SLJIT_SUCCESS;
|
||||
#else
|
||||
if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI))
|
||||
return SLJIT_SUCCESS;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);
|
||||
}
|
||||
|
||||
/* CPU description section */
|
||||
|
||||
#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
|
||||
#define SLJIT_CPUINFO_PART1 " 32bit ("
|
||||
#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
||||
#define SLJIT_CPUINFO_PART1 " 64bit ("
|
||||
#else
|
||||
#error "Internal error: CPU type info missing"
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
|
||||
#define SLJIT_CPUINFO_PART2 "little endian + "
|
||||
#elif (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)
|
||||
#define SLJIT_CPUINFO_PART2 "big endian + "
|
||||
#else
|
||||
#error "Internal error: CPU type info missing"
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED)
|
||||
#define SLJIT_CPUINFO_PART3 "unaligned)"
|
||||
#else
|
||||
#define SLJIT_CPUINFO_PART3 "aligned)"
|
||||
#endif
|
||||
|
||||
#define SLJIT_CPUINFO SLJIT_CPUINFO_PART1 SLJIT_CPUINFO_PART2 SLJIT_CPUINFO_PART3
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
#include "sjx86c.c"
|
||||
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
@@ -1086,6 +1198,7 @@ static SLJIT_INLINE void check_sljit_emit_const(struct sljit_compiler *compiler,
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w)
|
||||
@@ -1152,6 +1265,32 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
|
||||
#endif
|
||||
return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w)
|
||||
{
|
||||
int flags, condition;
|
||||
|
||||
check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w);
|
||||
|
||||
condition = type & 0xff;
|
||||
if (condition <= SLJIT_C_FLOAT_NOT_EQUAL)
|
||||
flags = SLJIT_SET_E;
|
||||
else
|
||||
flags = SLJIT_SET_S;
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
sljit_emit_fop1(compiler, SLJIT_FCMP | flags, src1, src1w, src2, src2w);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#else /* SLJIT_CONFIG_UNSUPPORTED */
|
||||
@@ -1205,44 +1344,45 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
|
||||
SLJIT_ASSERT_STOP();
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(args);
|
||||
SLJIT_UNUSED_ARG(temporaries);
|
||||
SLJIT_UNUSED_ARG(generals);
|
||||
SLJIT_UNUSED_ARG(saveds);
|
||||
SLJIT_UNUSED_ARG(local_size);
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(args);
|
||||
SLJIT_UNUSED_ARG(temporaries);
|
||||
SLJIT_UNUSED_ARG(generals);
|
||||
SLJIT_UNUSED_ARG(saveds);
|
||||
SLJIT_UNUSED_ARG(local_size);
|
||||
SLJIT_ASSERT_STOP();
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(op);
|
||||
SLJIT_UNUSED_ARG(src);
|
||||
SLJIT_UNUSED_ARG(srcw);
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int generals, int local_size)
|
||||
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_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(dst);
|
||||
SLJIT_UNUSED_ARG(dstw);
|
||||
SLJIT_UNUSED_ARG(args);
|
||||
SLJIT_UNUSED_ARG(temporaries);
|
||||
SLJIT_UNUSED_ARG(generals);
|
||||
SLJIT_UNUSED_ARG(saveds);
|
||||
SLJIT_UNUSED_ARG(local_size);
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
@@ -1296,6 +1436,22 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
|
||||
{
|
||||
SLJIT_ASSERT_STOP();
|
||||
return reg;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, int size)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(instruction);
|
||||
SLJIT_UNUSED_ARG(size);
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
|
||||
{
|
||||
SLJIT_ASSERT_STOP();
|
||||
@@ -1362,6 +1518,20 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(src1);
|
||||
SLJIT_UNUSED_ARG(src1w);
|
||||
SLJIT_UNUSED_ARG(src2);
|
||||
SLJIT_UNUSED_ARG(src2w);
|
||||
SLJIT_ASSERT_STOP();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(jump);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -44,10 +44,10 @@
|
||||
- The compiler is thread-safe
|
||||
Disadvantages:
|
||||
- Limited number of registers (only 6+4 integer registers, max 3+2
|
||||
temporary and max 3+2 general, and 4 floating point registers)
|
||||
temporary, max 3+2 saved and 4 floating point registers)
|
||||
In practice:
|
||||
- This approach is very effective for interpreters
|
||||
- One of the general registers typically points to a stack interface
|
||||
- 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
|
||||
@@ -64,6 +64,11 @@
|
||||
#if !(defined SLJIT_NO_DEFAULT_CONFIG && SLJIT_NO_DEFAULT_CONFIG)
|
||||
#include "sjconf.h"
|
||||
#endif
|
||||
|
||||
/* The following header file defines useful macros for fine tuning
|
||||
sljit based code generators. They are listed in the begining
|
||||
of sljitConfigInternal.h */
|
||||
|
||||
#include "sjconfi.h"
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
@@ -99,14 +104,14 @@
|
||||
#define SLJIT_TEMPORARY_EREG1 4
|
||||
#define SLJIT_TEMPORARY_EREG2 5
|
||||
|
||||
/* General (saved) registers preserve their values across function calls. */
|
||||
#define SLJIT_GENERAL_REG1 6
|
||||
#define SLJIT_GENERAL_REG2 7
|
||||
#define SLJIT_GENERAL_REG3 8
|
||||
/* Saved registers whose preserve their values across function calls. */
|
||||
#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). */
|
||||
#define SLJIT_GENERAL_EREG1 9
|
||||
#define SLJIT_GENERAL_EREG2 10
|
||||
#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). */
|
||||
@@ -122,9 +127,11 @@
|
||||
|
||||
#define SLJIT_RETURN_REG SLJIT_TEMPORARY_REG1
|
||||
|
||||
/* x86 prefers temporary registers for special purposes. If other
|
||||
registers are used such purpose, it costs a little performance
|
||||
drawback. It doesn't matter for other archs. */
|
||||
/* x86 prefers specific registers for special purposes. In case of shift
|
||||
by register it supports only SLJIT_TEMPORARY_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
|
||||
|
||||
@@ -189,8 +196,8 @@ struct sljit_compiler {
|
||||
|
||||
/* Used local registers. */
|
||||
int temporaries;
|
||||
/* Used general registers. */
|
||||
int generals;
|
||||
/* Used saved registers. */
|
||||
int saveds;
|
||||
/* Local stack size. */
|
||||
int local_size;
|
||||
/* Code size. */
|
||||
@@ -201,7 +208,7 @@ struct sljit_compiler {
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
int args;
|
||||
int temporaries_start;
|
||||
int generals_start;
|
||||
int saveds_start;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
@@ -221,7 +228,7 @@ struct sljit_compiler {
|
||||
sljit_ub *cpool_unique;
|
||||
sljit_uw cpool_diff;
|
||||
sljit_uw cpool_fill;
|
||||
/* General fields. */
|
||||
/* Other members. */
|
||||
/* Contains pointer, "ldr pc, [...]" pairs. */
|
||||
sljit_uw patches;
|
||||
#endif
|
||||
@@ -305,35 +312,56 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
|
||||
/* Instruction generation. Returns with error code. */
|
||||
|
||||
/*
|
||||
Entry instruction. The instruction has "args" number of arguments
|
||||
and will use the first "general" number of general registers.
|
||||
The arguments are passed into the general registers (arg1 to general_reg1, and so on).
|
||||
Thus, "args" must be less or equal than "general". A local_size extra
|
||||
stack space is allocated for the jit code (must be less or equal than
|
||||
SLJIT_MAX_LOCAL_SIZE), which can accessed through SLJIT_LOCALS_REG (see
|
||||
the notes there). SLJIT_LOCALS_REG is not necessary the real stack pointer!
|
||||
It just points somewhere in the stack if local_size > 0 (!). Thus, the only
|
||||
thing which is known that the memory area between SLJIT_LOCALS_REG and
|
||||
SLJIT_LOCALS_REG + local_size is a valid stack area if local_size > 0
|
||||
*/
|
||||
The executable code is basically a function call from the viewpoint of
|
||||
the C language. The function calls must obey to the ABI (Application
|
||||
Binary Interface) of the platform, which specify the purpose of machine
|
||||
registers and stack handling among other things. The sljit_emit_enter
|
||||
function emits the necessary instructions for setting up a new context
|
||||
for the executable code and moves function arguments to the 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
|
||||
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
|
||||
"local_size" argument contains the size in bytes of this local area
|
||||
and its staring address is stored in SLJIT_LOCALS_REG. However
|
||||
the SLJIT_LOCALS_REG is not necessary the machine stack pointer.
|
||||
The memory bytes between SLJIT_LOCALS_REG (inclusive) and
|
||||
SLJIT_LOCALS_REG + local_size (exclusive) can be modified freely
|
||||
until the function returns. The stack space is uninitialized.
|
||||
|
||||
/* Note: multiple calls of this function overwrites the previous call. */
|
||||
Note: every call of sljit_emit_enter and sljit_set_context overwrites
|
||||
the previous context. */
|
||||
|
||||
#define SLJIT_MAX_LOCAL_SIZE 65536
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size);
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
int args, int temporaries, int saveds, int local_size);
|
||||
|
||||
/* Since sljit_emit_return (and many asserts) uses variables which are initialized
|
||||
by sljit_emit_enter, a simple return is not possible if these variables are not
|
||||
initialized. sljit_fake_enter does not emit any instruction, just initialize
|
||||
those variables. */
|
||||
/* The machine code has a context (which contains the local stack space size,
|
||||
number of used registers, etc.) which initialized by sljit_emit_enter. Several
|
||||
functions (like sljit_emit_return) requres this context to be able to generate
|
||||
the appropriate code. However, some code fragments (like inline cache) may have
|
||||
no normal entry point so their context is unknown for the compiler. Using the
|
||||
function below we can specify thir context.
|
||||
|
||||
Note: every call of sljit_emit_enter and sljit_set_context overwrites
|
||||
the previous context. */
|
||||
|
||||
/* Note: multiple calls of this function overwrites the previous call. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
int args, int temporaries, int saveds, int local_size);
|
||||
|
||||
/* Return from jit. See below the possible values for src and srcw. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw);
|
||||
/* 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
|
||||
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
|
||||
@@ -341,7 +369,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
||||
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 general registers and setting up
|
||||
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). */
|
||||
|
||||
@@ -350,7 +378,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
||||
/* 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 generals, int local_size);
|
||||
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);
|
||||
|
||||
/*
|
||||
@@ -365,15 +393,16 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
|
||||
*/
|
||||
|
||||
/*
|
||||
IMPORATNT NOTE: memory access MUST be naturally aligned.
|
||||
IMPORATNT NOTE: memory access MUST be naturally aligned except
|
||||
SLJIT_UNALIGNED macro is defined and its value is 1.
|
||||
|
||||
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 defined
|
||||
| 8 byte if SLJIT_64BIT_ARCHITECTURE defined
|
||||
(This is a strict requirement for embedded systems.)
|
||||
sljit_w | 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
|
||||
|
||||
Note: different architectures have different addressing limitations
|
||||
Thus sljit may generate several instructions for other addressing modes
|
||||
@@ -445,6 +474,24 @@ 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 */
|
||||
#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 */
|
||||
#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. */
|
||||
#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_SDIV 5
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op);
|
||||
|
||||
@@ -457,100 +504,136 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
|
||||
SH = unsgined half (16 bit) */
|
||||
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV 2
|
||||
#define SLJIT_MOV 6
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_UB 3
|
||||
#define SLJIT_MOV_UB 7
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_SB 4
|
||||
#define SLJIT_MOV_SB 8
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_UH 5
|
||||
#define SLJIT_MOV_UH 9
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_SH 6
|
||||
#define SLJIT_MOV_SH 10
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_UI 7
|
||||
#define SLJIT_MOV_UI 11
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_SI 8
|
||||
#define SLJIT_MOV_SI 12
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU 9
|
||||
#define SLJIT_MOVU 13
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_UB 10
|
||||
#define SLJIT_MOVU_UB 14
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_SB 11
|
||||
#define SLJIT_MOVU_SB 15
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_UH 12
|
||||
#define SLJIT_MOVU_UH 16
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_SH 13
|
||||
#define SLJIT_MOVU_SH 17
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_UI 14
|
||||
#define SLJIT_MOVU_UI 18
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_SI 15
|
||||
#define SLJIT_MOVU_SI 19
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_NOT 16
|
||||
#define SLJIT_NOT 20
|
||||
/* Flags: I | E | O | K */
|
||||
#define SLJIT_NEG 17
|
||||
#define SLJIT_NEG 21
|
||||
/* Count leading zeroes
|
||||
Flags: I | E | K */
|
||||
#define SLJIT_CLZ 18
|
||||
#define SLJIT_CLZ 22
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src, sljit_w srcw);
|
||||
|
||||
/* Flags: I | E | O | C | K */
|
||||
#define SLJIT_ADD 19
|
||||
#define SLJIT_ADD 23
|
||||
/* Flags: I | C | K */
|
||||
#define SLJIT_ADDC 20
|
||||
#define SLJIT_ADDC 24
|
||||
/* Flags: I | E | S | U | O | C | K */
|
||||
#define SLJIT_SUB 21
|
||||
#define SLJIT_SUB 25
|
||||
/* Flags: I | C | K */
|
||||
#define SLJIT_SUBC 22
|
||||
/* Note: integer mul */
|
||||
/* Flags: I | O (see SLJIT_C_MUL_*) | K */
|
||||
#define SLJIT_MUL 23
|
||||
#define SLJIT_SUBC 26
|
||||
/* Note: integer mul
|
||||
Flags: I | O (see SLJIT_C_MUL_*) | K */
|
||||
#define SLJIT_MUL 27
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_AND 24
|
||||
#define SLJIT_AND 28
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_OR 25
|
||||
#define SLJIT_OR 29
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_XOR 26
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_SHL 27
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_LSHR 28
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_ASHR 29
|
||||
#define SLJIT_XOR 30
|
||||
/* Flags: I | E | K
|
||||
Let bit_length be the length of the shift operation: 32 or 64.
|
||||
If src2 is immediate, src2w is masked by (bit_length - 1).
|
||||
Otherwise, if the content of src2 is outside the range from 0
|
||||
to bit_length - 1, the operation is undefined. */
|
||||
#define SLJIT_SHL 31
|
||||
/* Flags: I | E | K
|
||||
Let bit_length be the length of the shift operation: 32 or 64.
|
||||
If src2 is immediate, src2w is masked by (bit_length - 1).
|
||||
Otherwise, if the content of src2 is outside the range from 0
|
||||
to bit_length - 1, the operation is undefined. */
|
||||
#define SLJIT_LSHR 32
|
||||
/* Flags: I | E | K
|
||||
Let bit_length be the length of the shift operation: 32 or 64.
|
||||
If src2 is immediate, src2w is masked by (bit_length - 1).
|
||||
Otherwise, if the content of src2 is outside the range from 0
|
||||
to bit_length - 1, the operation is undefined. */
|
||||
#define SLJIT_ASHR 33
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w 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
|
||||
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);
|
||||
|
||||
/* Any instruction can be inserted into the instruction stream by
|
||||
sljit_emit_op_custom. It has a similar purpose as inline assembly.
|
||||
The size parameter must match to the instruction size of the target
|
||||
architecture:
|
||||
|
||||
x86: 0 < size <= 15. The instruction argument can be byte aligned.
|
||||
Thumb2: if size == 2, the instruction argument must be 2 byte aligned.
|
||||
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);
|
||||
|
||||
/* Returns with non-zero if fpu is available. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int 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,
|
||||
the comparison result is unpredictable.
|
||||
Flags: E | S (see SLJIT_C_FLOAT_*) */
|
||||
#define SLJIT_FCMP 30
|
||||
#define SLJIT_FCMP 34
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FMOV 31
|
||||
#define SLJIT_FMOV 35
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FNEG 32
|
||||
#define SLJIT_FNEG 36
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FABS 33
|
||||
#define SLJIT_FABS 37
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src, sljit_w srcw);
|
||||
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FADD 34
|
||||
#define SLJIT_FADD 38
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FSUB 35
|
||||
#define SLJIT_FSUB 39
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FMUL 36
|
||||
#define SLJIT_FMUL 40
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FDIV 37
|
||||
#define SLJIT_FDIV 41
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
@@ -610,11 +693,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
|
||||
Flags: destroy all flags for calls. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type);
|
||||
|
||||
/* Basic arithmetic comparison. In most architectures it is equal to
|
||||
an SLJIT_SUB operation (with SLJIT_UNUSED destination) followed by a
|
||||
sljit_emit_jump. However some architectures (i.e: MIPS) may employ
|
||||
special optimizations here. It is suggested to use this comparison
|
||||
form when flags are unimportant.
|
||||
/* Basic arithmetic comparison. In most architectures it is implemented as
|
||||
an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting
|
||||
appropriate flags) followed by a sljit_emit_jump. However some
|
||||
architectures (i.e: MIPS) may employ special optimizations here. It is
|
||||
suggested to use this comparison form when appropriate.
|
||||
type must be between SLJIT_C_EQUAL and SLJIT_C_SIG_LESS_EQUAL
|
||||
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP or SLJIT_INT_OP
|
||||
Flags: destroy flags. */
|
||||
@@ -622,6 +705,20 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w);
|
||||
|
||||
/* Basic floating point comparison. In most architectures it is implemented as
|
||||
an SLJIT_FCMP operation (setting appropriate flags) followed by a
|
||||
sljit_emit_jump. However some architectures (i.e: MIPS) may employ
|
||||
special optimizations here. It is suggested to use this comparison form
|
||||
when appropriate.
|
||||
type must be between SLJIT_C_FLOAT_EQUAL and SLJIT_C_FLOAT_NOT_NAN
|
||||
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
|
||||
Flags: destroy flags.
|
||||
Note: if either operand is NaN, the behaviour is undefined for
|
||||
type <= SLJIT_C_FLOAT_LESS_EQUAL. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w);
|
||||
|
||||
/* Set the destination of the jump to this label. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label);
|
||||
/* Only for jumps defined with SLJIT_REWRITABLE_JUMP flag.
|
||||
@@ -667,7 +764,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constan
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#define SLJIT_MAJOR_VERSION 0
|
||||
#define SLJIT_MINOR_VERSION 82
|
||||
#define SLJIT_MINOR_VERSION 87
|
||||
|
||||
/* Get the human readable name of the platfrom.
|
||||
Can be useful for debugging on platforms like ARM, where ARM and
|
||||
@@ -675,7 +772,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constan
|
||||
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void);
|
||||
|
||||
/* Portble helper function to get an offset of a member. */
|
||||
#define SLJIT_OFFSETOF(base, member) ((sljit_w)(&((base*)0x10)->member) - 0x10)
|
||||
#define SLJIT_OFFSETOF(base, member) ((sljit_w)(&((base*)0x10)->member) - 0x10)
|
||||
|
||||
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
/* This global lock is useful to compile common functions. */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -26,11 +26,7 @@
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
|
||||
{
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
return "mips-32";
|
||||
#else
|
||||
#error "mips-64 is not yet supported"
|
||||
#endif
|
||||
return "MIPS" SLJIT_CPUINFO;
|
||||
}
|
||||
|
||||
/* Latest MIPS architecture. */
|
||||
@@ -109,7 +105,10 @@ typedef sljit_ui sljit_ins;
|
||||
#define BREAK (HI(0) | LO(13))
|
||||
#define C_UN_D (HI(17) | FMT_D | LO(49))
|
||||
#define C_UEQ_D (HI(17) | FMT_D | LO(51))
|
||||
#define C_ULE_D (HI(17) | FMT_D | LO(55))
|
||||
#define C_ULT_D (HI(17) | FMT_D | LO(53))
|
||||
#define DIV (HI(0) | LO(26))
|
||||
#define DIVU (HI(0) | LO(27))
|
||||
#define DIV_D (HI(17) | FMT_D | LO(3))
|
||||
#define J (HI(2))
|
||||
#define JAL (HI(3))
|
||||
@@ -128,6 +127,7 @@ typedef sljit_ui sljit_ins;
|
||||
#define MOVZ (HI(0) | LO(10))
|
||||
#define MUL_D (HI(17) | FMT_D | LO(2))
|
||||
#define MULT (HI(0) | LO(24))
|
||||
#define MULTU (HI(0) | LO(25))
|
||||
#define NOP (HI(0) | LO(0))
|
||||
#define NOR (HI(0) | LO(39))
|
||||
#define OR (HI(0) | LO(37))
|
||||
@@ -455,18 +455,18 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w);
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
sljit_ins base;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, temporaries, generals, local_size);
|
||||
check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
|
||||
compiler->has_locals = local_size > 0;
|
||||
local_size += (generals + 2 + 4) * sizeof(sljit_w);
|
||||
local_size += (saveds + 2 + 4) * sizeof(sljit_w);
|
||||
local_size = (local_size + 15) & ~0xf;
|
||||
compiler->local_size = local_size;
|
||||
|
||||
@@ -486,56 +486,54 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(local_size - 1 * (int)sizeof(sljit_w)), MOVABLE_INS));
|
||||
if (compiler->has_locals)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_LOCALS_REG) | IMM(local_size - 2 * (int)sizeof(sljit_w)), MOVABLE_INS));
|
||||
if (generals >= 1)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_GENERAL_REG1) | IMM(local_size - 3 * (int)sizeof(sljit_w)), MOVABLE_INS));
|
||||
if (generals >= 2)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_GENERAL_REG2) | IMM(local_size - 4 * (int)sizeof(sljit_w)), MOVABLE_INS));
|
||||
if (generals >= 3)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_GENERAL_REG3) | IMM(local_size - 5 * (int)sizeof(sljit_w)), MOVABLE_INS));
|
||||
if (generals >= 4)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_GENERAL_EREG1) | IMM(local_size - 6 * (int)sizeof(sljit_w)), MOVABLE_INS));
|
||||
if (generals >= 5)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_GENERAL_EREG2) | IMM(local_size - 7 * (int)sizeof(sljit_w)), MOVABLE_INS));
|
||||
if (saveds >= 1)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG1) | IMM(local_size - 3 * (int)sizeof(sljit_w)), MOVABLE_INS));
|
||||
if (saveds >= 2)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG2) | IMM(local_size - 4 * (int)sizeof(sljit_w)), MOVABLE_INS));
|
||||
if (saveds >= 3)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG3) | IMM(local_size - 5 * (int)sizeof(sljit_w)), MOVABLE_INS));
|
||||
if (saveds >= 4)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_EREG1) | IMM(local_size - 6 * (int)sizeof(sljit_w)), MOVABLE_INS));
|
||||
if (saveds >= 5)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_EREG2) | IMM(local_size - 7 * (int)sizeof(sljit_w)), MOVABLE_INS));
|
||||
|
||||
if (compiler->has_locals)
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(REAL_STACK_PTR) | T(SLJIT_LOCALS_REG) | IMM(4 * sizeof(sljit_w)), DR(SLJIT_LOCALS_REG)));
|
||||
|
||||
if (args >= 1)
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(4) | TA(0) | D(SLJIT_GENERAL_REG1), DR(SLJIT_GENERAL_REG1)));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(4) | TA(0) | D(SLJIT_SAVED_REG1), DR(SLJIT_SAVED_REG1)));
|
||||
if (args >= 2)
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(5) | TA(0) | D(SLJIT_GENERAL_REG2), DR(SLJIT_GENERAL_REG2)));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(5) | TA(0) | D(SLJIT_SAVED_REG2), DR(SLJIT_SAVED_REG2)));
|
||||
if (args >= 3)
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(6) | TA(0) | D(SLJIT_GENERAL_REG3), DR(SLJIT_GENERAL_REG3)));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(6) | TA(0) | D(SLJIT_SAVED_REG3), DR(SLJIT_SAVED_REG3)));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_fake_enter(compiler, args, temporaries, generals, local_size);
|
||||
check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
|
||||
compiler->has_locals = local_size > 0;
|
||||
local_size += (generals + 2 + 4) * sizeof(sljit_w);
|
||||
local_size += (saveds + 2 + 4) * sizeof(sljit_w);
|
||||
compiler->local_size = (local_size + 15) & ~0xf;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
|
||||
{
|
||||
int local_size;
|
||||
sljit_ins base;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, src, srcw);
|
||||
check_sljit_emit_return(compiler, op, src, srcw);
|
||||
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
local_size = compiler->local_size;
|
||||
|
||||
if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG)
|
||||
FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, SLJIT_RETURN_REG, 0, TMP_REG1, 0, src, srcw));
|
||||
|
||||
if (local_size <= SIMM_MAX)
|
||||
base = S(REAL_STACK_PTR);
|
||||
else {
|
||||
@@ -546,16 +544,16 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - 1 * (int)sizeof(sljit_w)), RETURN_ADDR_REG));
|
||||
if (compiler->generals >= 5)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_GENERAL_EREG2) | IMM(local_size - 7 * (int)sizeof(sljit_w)), DR(SLJIT_GENERAL_EREG2)));
|
||||
if (compiler->generals >= 4)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_GENERAL_EREG1) | IMM(local_size - 6 * (int)sizeof(sljit_w)), DR(SLJIT_GENERAL_EREG1)));
|
||||
if (compiler->generals >= 3)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_GENERAL_REG3) | IMM(local_size - 5 * (int)sizeof(sljit_w)), DR(SLJIT_GENERAL_REG3)));
|
||||
if (compiler->generals >= 2)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_GENERAL_REG2) | IMM(local_size - 4 * (int)sizeof(sljit_w)), DR(SLJIT_GENERAL_REG2)));
|
||||
if (compiler->generals >= 1)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_GENERAL_REG1) | IMM(local_size - 3 * (int)sizeof(sljit_w)), DR(SLJIT_GENERAL_REG1)));
|
||||
if (compiler->saveds >= 5)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_EREG2) | IMM(local_size - 7 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_EREG2)));
|
||||
if (compiler->saveds >= 4)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_EREG1) | IMM(local_size - 6 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_EREG1)));
|
||||
if (compiler->saveds >= 3)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG3) | IMM(local_size - 5 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_REG3)));
|
||||
if (compiler->saveds >= 2)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG2) | IMM(local_size - 4 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_REG2)));
|
||||
if (compiler->saveds >= 1)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG1) | IMM(local_size - 3 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_REG1)));
|
||||
if (compiler->has_locals)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_LOCALS_REG) | IMM(local_size - 2 * (int)sizeof(sljit_w)), DR(SLJIT_LOCALS_REG)));
|
||||
|
||||
@@ -929,6 +927,20 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
|
||||
return push_inst(compiler, BREAK, UNMOVABLE_INS);
|
||||
case SLJIT_NOP:
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? MULTU : MULT) | S(SLJIT_TEMPORARY_REG1) | T(SLJIT_TEMPORARY_REG2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_TEMPORARY_REG1), DR(SLJIT_TEMPORARY_REG1)));
|
||||
return push_inst(compiler, MFHI | D(SLJIT_TEMPORARY_REG2), DR(SLJIT_TEMPORARY_REG2));
|
||||
case SLJIT_UDIV:
|
||||
case SLJIT_SDIV:
|
||||
#if !(defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_TEMPORARY_REG1) | T(SLJIT_TEMPORARY_REG2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_TEMPORARY_REG1), DR(SLJIT_TEMPORARY_REG1)));
|
||||
return push_inst(compiler, MFHI | D(SLJIT_TEMPORARY_REG2), DR(SLJIT_TEMPORARY_REG2));
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
@@ -1054,6 +1066,22 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
|
||||
#endif
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
|
||||
{
|
||||
check_sljit_get_register_index(reg);
|
||||
return reg_map[reg];
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, int size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_op_custom(compiler, instruction, size);
|
||||
SLJIT_ASSERT(size == 4);
|
||||
|
||||
return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Floating point operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
@@ -1232,16 +1260,16 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, in
|
||||
/* Other instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int generals, int local_size)
|
||||
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)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size);
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
|
||||
compiler->has_locals = local_size > 0;
|
||||
local_size += (generals + 2 + 4) * sizeof(sljit_w);
|
||||
local_size += (saveds + 2 + 4) * sizeof(sljit_w);
|
||||
compiler->local_size = (local_size + 15) & ~0xf;
|
||||
|
||||
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
|
||||
@@ -1555,6 +1583,81 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
|
||||
#undef RESOLVE_IMM1
|
||||
#undef RESOLVE_IMM2
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w)
|
||||
{
|
||||
struct sljit_jump *jump;
|
||||
sljit_ins inst;
|
||||
int if_true;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
if (src1 > SLJIT_FLOAT_REG4) {
|
||||
PTR_FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w));
|
||||
src1 = TMP_FREG1;
|
||||
}
|
||||
if (src2 > SLJIT_FLOAT_REG4) {
|
||||
PTR_FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w));
|
||||
src2 = TMP_FREG2;
|
||||
}
|
||||
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
PTR_FAIL_IF(!jump);
|
||||
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
||||
jump->flags |= IS_BIT16_COND;
|
||||
type &= 0xff;
|
||||
|
||||
switch (type) {
|
||||
case SLJIT_C_FLOAT_EQUAL:
|
||||
inst = C_UEQ_D;
|
||||
if_true = 1;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_NOT_EQUAL:
|
||||
inst = C_UEQ_D;
|
||||
if_true = 0;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_LESS:
|
||||
inst = C_ULT_D;
|
||||
if_true = 1;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_GREATER_EQUAL:
|
||||
inst = C_ULT_D;
|
||||
if_true = 0;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_GREATER:
|
||||
inst = C_ULE_D;
|
||||
if_true = 0;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_LESS_EQUAL:
|
||||
inst = C_ULE_D;
|
||||
if_true = 1;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_NAN:
|
||||
inst = C_UN_D;
|
||||
if_true = 1;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_NOT_NAN:
|
||||
default: /* Make compilers happy. */
|
||||
inst = C_UN_D;
|
||||
if_true = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
PTR_FAIL_IF(push_inst(compiler, inst | FT(src2) | FS(src1), UNMOVABLE_INS));
|
||||
/* Intentionally the other opcode. */
|
||||
PTR_FAIL_IF(push_inst(compiler, (if_true ? BC1F : BC1T) | JUMP_LENGTH, UNMOVABLE_INS));
|
||||
PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
|
||||
PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
|
||||
jump->addr = compiler->size;
|
||||
PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
return jump;
|
||||
}
|
||||
|
||||
#undef JUMP_LENGTH
|
||||
#undef BR_Z
|
||||
#undef BR_NZ
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -31,6 +31,9 @@ static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
|
||||
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | S(ZERO_REG) | A(reg) | IMM(imm));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
|
||||
}
|
||||
@@ -44,10 +47,12 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
||||
switch (op) {
|
||||
case SLJIT_ADD:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
@@ -55,6 +60,11 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM4) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
|
||||
}
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
||||
return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
@@ -69,22 +79,28 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
||||
|
||||
case SLJIT_SUB:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
if (flags & (ALT_FORM2 | ALT_FORM3)) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm);
|
||||
if (flags & ALT_FORM2)
|
||||
FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
|
||||
if (flags & ALT_FORM3)
|
||||
return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm);
|
||||
if (flags & (ALT_FORM4 | ALT_FORM5)) {
|
||||
if (flags & ALT_FORM4)
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
|
||||
if (flags & ALT_FORM5)
|
||||
FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
if (flags & ALT_FORM4)
|
||||
return push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2));
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
if (flags & ALT_FORM5)
|
||||
if (flags & ALT_FORM6)
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -49,6 +49,9 @@ static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
|
||||
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | S(ZERO_REG) | A(reg) | IMM(imm));
|
||||
|
||||
if (imm <= SLJIT_W(0x7fffffff) && imm >= SLJIT_W(-0x80000000)) {
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
|
||||
@@ -146,12 +149,12 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
||||
switch (op) {
|
||||
case SLJIT_ADD:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags not set: BIN_IMM_EXTS unnecessary. */
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
/* Flags not set: BIN_IMM_EXTS unnecessary. */
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
@@ -160,6 +163,11 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
||||
BIN_IMM_EXTS();
|
||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM4) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
|
||||
}
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
||||
BIN_EXTS();
|
||||
@@ -176,24 +184,29 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
|
||||
|
||||
case SLJIT_SUB:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags not set: BIN_IMM_EXTS unnecessary. */
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
if (flags & (ALT_FORM2 | ALT_FORM3)) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
|
||||
if (flags & ALT_FORM2)
|
||||
FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
|
||||
if (flags & ALT_FORM3)
|
||||
return push_inst(compiler, CMPLI | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, CMPLI | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
|
||||
if (flags & (ALT_FORM4 | ALT_FORM5)) {
|
||||
if (flags & ALT_FORM4)
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
|
||||
if (flags & ALT_FORM5)
|
||||
return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
if (flags & ALT_FORM4)
|
||||
return push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
BIN_EXTS();
|
||||
if (flags & ALT_FORM5)
|
||||
if (flags & ALT_FORM6)
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -26,11 +26,7 @@
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
|
||||
{
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
return "ppc-32";
|
||||
#else
|
||||
return "ppc-64";
|
||||
#endif
|
||||
return "PowerPC" SLJIT_CPUINFO;
|
||||
}
|
||||
|
||||
/* Length of an instruction word.
|
||||
@@ -75,9 +71,9 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
|
||||
|
||||
/* Instruction bit sections.
|
||||
OE and Rc flag (see ALT_SET_FLAGS). */
|
||||
#define OERC(flags) (((flags & ALT_SET_FLAGS) >> 15) | ((flags & ALT_SET_FLAGS) >> 5))
|
||||
#define OERC(flags) (((flags & ALT_SET_FLAGS) >> 10) | (flags & ALT_SET_FLAGS))
|
||||
/* Rc flag (see ALT_SET_FLAGS). */
|
||||
#define RC(flags) ((flags & ALT_SET_FLAGS) >> 15)
|
||||
#define RC(flags) ((flags & ALT_SET_FLAGS) >> 10)
|
||||
#define HI(opcode) ((opcode) << 26)
|
||||
#define LO(opcode) ((opcode) << 1)
|
||||
|
||||
@@ -97,10 +93,15 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
|
||||
#define BLR (HI(19) | LO(16) | (0x14 << 21))
|
||||
#define CNTLZD (HI(31) | LO(58))
|
||||
#define CNTLZW (HI(31) | LO(26))
|
||||
#define CMP (HI(31) | LO(0))
|
||||
#define CMPI (HI(11))
|
||||
#define CMPL (HI(31) | LO(32))
|
||||
#define CMPLI (HI(10))
|
||||
#define CROR (HI(19) | LO(449))
|
||||
#define DIVD (HI(31) | LO(489))
|
||||
#define DIVDU (HI(31) | LO(457))
|
||||
#define DIVW (HI(31) | LO(491))
|
||||
#define DIVWU (HI(31) | LO(459))
|
||||
#define EXTSB (HI(31) | LO(954))
|
||||
#define EXTSH (HI(31) | LO(922))
|
||||
#define EXTSW (HI(31) | LO(986))
|
||||
@@ -123,6 +124,10 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
|
||||
#define MTCTR (HI(31) | LO(467) | 0x90000)
|
||||
#define MTLR (HI(31) | LO(467) | 0x80000)
|
||||
#define MTXER (HI(31) | LO(467) | 0x10000)
|
||||
#define MULHD (HI(31) | LO(73))
|
||||
#define MULHDU (HI(31) | LO(9))
|
||||
#define MULHW (HI(31) | LO(75))
|
||||
#define MULHWU (HI(31) | LO(11))
|
||||
#define MULLD (HI(31) | LO(233))
|
||||
#define MULLI (HI(7))
|
||||
#define MULLW (HI(31) | LO(235))
|
||||
@@ -382,32 +387,32 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||
|
||||
/* Other inp_flags. */
|
||||
|
||||
#define ARG_TEST 0x0100
|
||||
#define ALT_FORM1 0x0200
|
||||
#define ALT_FORM2 0x0400
|
||||
#define ALT_FORM3 0x0800
|
||||
#define ALT_FORM4 0x1000
|
||||
#define ALT_FORM5 0x2000
|
||||
#define ARG_TEST 0x000100
|
||||
/* Integer opertion and set flags -> requires exts on 64 bit systems. */
|
||||
#define ALT_SIGN_EXT 0x4000
|
||||
#define ALT_SIGN_EXT 0x000200
|
||||
/* This flag affects the RC() and OERC() macros. */
|
||||
#define ALT_SET_FLAGS 0x8000
|
||||
#define ALT_SET_FLAGS 0x000400
|
||||
#define ALT_FORM1 0x010000
|
||||
#define ALT_FORM2 0x020000
|
||||
#define ALT_FORM3 0x040000
|
||||
#define ALT_FORM4 0x080000
|
||||
#define ALT_FORM5 0x100000
|
||||
#define ALT_FORM6 0x200000
|
||||
|
||||
/* Source and destination is register. */
|
||||
#define REG_DEST 0x0001
|
||||
#define REG1_SOURCE 0x0002
|
||||
#define REG2_SOURCE 0x0004
|
||||
/* getput_arg_fast returned true. */
|
||||
#define FAST_DEST 0x0008
|
||||
/* Multiple instructions are required. */
|
||||
#define SLOW_DEST 0x0010
|
||||
/* ALT_FORM1 0x0200
|
||||
ALT_FORM2 0x0400
|
||||
ALT_FORM3 0x0800
|
||||
ALT_FORM4 0x1000
|
||||
ALT_FORM5 0x2000
|
||||
ALT_SIGN_EXT 0x4000
|
||||
ALT_SET_FLAGS 0x8000 */
|
||||
/* Source and destination is register. */
|
||||
#define REG_DEST 0x000001
|
||||
#define REG1_SOURCE 0x000002
|
||||
#define REG2_SOURCE 0x000004
|
||||
/* getput_arg_fast returned true. */
|
||||
#define FAST_DEST 0x000008
|
||||
/* Multiple instructions are required. */
|
||||
#define SLOW_DEST 0x000010
|
||||
/*
|
||||
ALT_SIGN_EXT 0x000200
|
||||
ALT_SET_FLAGS 0x000400
|
||||
ALT_FORM1 0x010000
|
||||
...
|
||||
ALT_FORM6 0x200000 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
#include "sjppc32.c"
|
||||
@@ -428,43 +433,43 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w);
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, temporaries, generals, local_size);
|
||||
check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
compiler->has_locals = local_size > 0;
|
||||
|
||||
FAIL_IF(push_inst(compiler, MFLR | D(0)));
|
||||
if (compiler->has_locals)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM(-(int)(sizeof(sljit_w))) ));
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(ZERO_REG) | A(REAL_STACK_PTR) | IMM(-2 * (int)(sizeof(sljit_w))) ));
|
||||
if (generals >= 1)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_GENERAL_REG1) | A(REAL_STACK_PTR) | IMM(-3 * (int)(sizeof(sljit_w))) ));
|
||||
if (generals >= 2)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_GENERAL_REG2) | A(REAL_STACK_PTR) | IMM(-4 * (int)(sizeof(sljit_w))) ));
|
||||
if (generals >= 3)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_GENERAL_REG3) | A(REAL_STACK_PTR) | IMM(-5 * (int)(sizeof(sljit_w))) ));
|
||||
if (generals >= 4)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_GENERAL_EREG1) | A(REAL_STACK_PTR) | IMM(-6 * (int)(sizeof(sljit_w))) ));
|
||||
if (generals >= 5)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_GENERAL_EREG2) | A(REAL_STACK_PTR) | IMM(-7 * (int)(sizeof(sljit_w))) ));
|
||||
if (saveds >= 1)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG1) | A(REAL_STACK_PTR) | IMM(-3 * (int)(sizeof(sljit_w))) ));
|
||||
if (saveds >= 2)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG2) | A(REAL_STACK_PTR) | IMM(-4 * (int)(sizeof(sljit_w))) ));
|
||||
if (saveds >= 3)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG3) | A(REAL_STACK_PTR) | IMM(-5 * (int)(sizeof(sljit_w))) ));
|
||||
if (saveds >= 4)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG1) | A(REAL_STACK_PTR) | IMM(-6 * (int)(sizeof(sljit_w))) ));
|
||||
if (saveds >= 5)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG2) | A(REAL_STACK_PTR) | IMM(-7 * (int)(sizeof(sljit_w))) ));
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(REAL_STACK_PTR) | IMM(sizeof(sljit_w)) ));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(ZERO_REG) | A(0) | 0));
|
||||
if (args >= 1)
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(SLJIT_GENERAL_REG1) | B(SLJIT_TEMPORARY_REG1)));
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(SLJIT_SAVED_REG1) | B(SLJIT_TEMPORARY_REG1)));
|
||||
if (args >= 2)
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG2) | A(SLJIT_GENERAL_REG2) | B(SLJIT_TEMPORARY_REG2)));
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG2) | A(SLJIT_SAVED_REG2) | B(SLJIT_TEMPORARY_REG2)));
|
||||
if (args >= 3)
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG3) | A(SLJIT_GENERAL_REG3) | B(SLJIT_TEMPORARY_REG3)));
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG3) | A(SLJIT_SAVED_REG3) | B(SLJIT_TEMPORARY_REG3)));
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
compiler->local_size = (2 + generals + 2) * sizeof(sljit_w) + local_size;
|
||||
compiler->local_size = (2 + saveds + 2) * sizeof(sljit_w) + local_size;
|
||||
#else
|
||||
compiler->local_size = (2 + generals + 7 + 8) * sizeof(sljit_w) + local_size;
|
||||
compiler->local_size = (2 + saveds + 7 + 8) * sizeof(sljit_w) + local_size;
|
||||
#endif
|
||||
compiler->local_size = (compiler->local_size + 15) & ~0xf;
|
||||
|
||||
@@ -491,30 +496,29 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_fake_enter(compiler, args, temporaries, generals, local_size);
|
||||
check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
|
||||
compiler->has_locals = local_size > 0;
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
compiler->local_size = (2 + generals + 2) * sizeof(sljit_w) + local_size;
|
||||
compiler->local_size = (2 + saveds + 2) * sizeof(sljit_w) + local_size;
|
||||
#else
|
||||
compiler->local_size = (2 + generals + 7 + 8) * sizeof(sljit_w) + local_size;
|
||||
compiler->local_size = (2 + saveds + 7 + 8) * sizeof(sljit_w) + local_size;
|
||||
#endif
|
||||
compiler->local_size = (compiler->local_size + 15) & ~0xf;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, src, srcw);
|
||||
check_sljit_emit_return(compiler, op, src, srcw);
|
||||
|
||||
if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG)
|
||||
FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, SLJIT_RETURN_REG, 0, TMP_REG1, 0, src, srcw));
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
if (compiler->local_size <= SIMM_MAX)
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(REAL_STACK_PTR) | A(REAL_STACK_PTR) | IMM(compiler->local_size)));
|
||||
@@ -524,16 +528,16 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(REAL_STACK_PTR) | IMM(sizeof(sljit_w))));
|
||||
if (compiler->generals >= 5)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_GENERAL_EREG2) | A(REAL_STACK_PTR) | IMM(-7 * (int)(sizeof(sljit_w))) ));
|
||||
if (compiler->generals >= 4)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_GENERAL_EREG1) | A(REAL_STACK_PTR) | IMM(-6 * (int)(sizeof(sljit_w))) ));
|
||||
if (compiler->generals >= 3)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_GENERAL_REG3) | A(REAL_STACK_PTR) | IMM(-5 * (int)(sizeof(sljit_w))) ));
|
||||
if (compiler->generals >= 2)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_GENERAL_REG2) | A(REAL_STACK_PTR) | IMM(-4 * (int)(sizeof(sljit_w))) ));
|
||||
if (compiler->generals >= 1)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_GENERAL_REG1) | A(REAL_STACK_PTR) | IMM(-3 * (int)(sizeof(sljit_w))) ));
|
||||
if (compiler->saveds >= 5)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG2) | A(REAL_STACK_PTR) | IMM(-7 * (int)(sizeof(sljit_w))) ));
|
||||
if (compiler->saveds >= 4)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG1) | A(REAL_STACK_PTR) | IMM(-6 * (int)(sizeof(sljit_w))) ));
|
||||
if (compiler->saveds >= 3)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG3) | A(REAL_STACK_PTR) | IMM(-5 * (int)(sizeof(sljit_w))) ));
|
||||
if (compiler->saveds >= 2)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG2) | A(REAL_STACK_PTR) | IMM(-4 * (int)(sizeof(sljit_w))) ));
|
||||
if (compiler->saveds >= 1)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG1) | A(REAL_STACK_PTR) | IMM(-3 * (int)(sizeof(sljit_w))) ));
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(ZERO_REG) | A(REAL_STACK_PTR) | IMM(-2 * (int)(sizeof(sljit_w))) ));
|
||||
if (compiler->has_locals)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM(-(int)(sizeof(sljit_w))) ));
|
||||
@@ -893,7 +897,7 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
|
||||
int src1_r;
|
||||
int src2_r;
|
||||
int sugg_src2_r = TMP_REG2;
|
||||
int flags = inp_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
|
||||
int flags = inp_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_FORM6 | ALT_SIGN_EXT | ALT_SET_FLAGS);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
@@ -1028,12 +1032,38 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_op0(compiler, op);
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
switch (op) {
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_BREAKPOINT:
|
||||
case SLJIT_NOP:
|
||||
return push_inst(compiler, NOP);
|
||||
break;
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG1)));
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
|
||||
return push_inst(compiler, (GET_OPCODE(op) == SLJIT_UMUL ? MULHDU : MULHD) | D(SLJIT_TEMPORARY_REG2) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
|
||||
return push_inst(compiler, (GET_OPCODE(op) == SLJIT_UMUL ? MULHWU : MULHW) | D(SLJIT_TEMPORARY_REG2) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2));
|
||||
#endif
|
||||
case SLJIT_UDIV:
|
||||
case SLJIT_SDIV:
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG1)));
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
if (op & SLJIT_INT_OP) {
|
||||
FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
|
||||
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG1) | B(SLJIT_TEMPORARY_REG2)));
|
||||
return push_inst(compiler, SUBF | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG2) | B(TMP_REG1));
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVDU : DIVD) | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
|
||||
FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG1) | B(SLJIT_TEMPORARY_REG2)));
|
||||
return push_inst(compiler, SUBF | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG2) | B(TMP_REG1));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
|
||||
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG1) | B(SLJIT_TEMPORARY_REG2)));
|
||||
return push_inst(compiler, SUBF | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG2) | B(TMP_REG1));
|
||||
#endif
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
@@ -1138,6 +1168,14 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
|
||||
#define TEST_UH_IMM(src, srcw) \
|
||||
(((src) & SLJIT_IMM) && !((srcw) & ~0xffff0000))
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define TEST_ADD_IMM(src, srcw) \
|
||||
(((src) & SLJIT_IMM) && (srcw) <= SLJIT_W(0x7fff7fff) && (srcw) >= SLJIT_W(-0x80000000))
|
||||
#else
|
||||
#define TEST_ADD_IMM(src, srcw) \
|
||||
((src) & SLJIT_IMM)
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define TEST_UI_IMM(src, srcw) \
|
||||
(((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff))
|
||||
@@ -1177,7 +1215,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_ADD:
|
||||
if (!GET_FLAGS(op)) {
|
||||
if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
|
||||
if (TEST_SL_IMM(src2, src2w)) {
|
||||
compiler->imm = src2w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
@@ -1194,6 +1232,15 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
|
||||
compiler->imm = (src1w >> 16) & 0xffff;
|
||||
return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||
}
|
||||
/* Range between -1 and -32768 is covered above. */
|
||||
if (TEST_ADD_IMM(src2, src2w)) {
|
||||
compiler->imm = src2w & 0xffffffff;
|
||||
return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
if (TEST_ADD_IMM(src1, src1w)) {
|
||||
compiler->imm = src1w & 0xffffffff;
|
||||
return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||
}
|
||||
}
|
||||
if (!(GET_FLAGS(op) & (SLJIT_SET_E | SLJIT_SET_O))) {
|
||||
if (TEST_SL_IMM(src2, src2w)) {
|
||||
@@ -1211,7 +1258,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
|
||||
return emit_op(compiler, SLJIT_ADDC, inp_flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
|
||||
|
||||
case SLJIT_SUB:
|
||||
if (!GET_FLAGS(op)) {
|
||||
if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
|
||||
if (TEST_SL_IMM(src2, -src2w)) {
|
||||
compiler->imm = (-src2w) & 0xffff;
|
||||
return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
@@ -1224,25 +1271,37 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
|
||||
compiler->imm = ((-src2w) >> 16) & 0xffff;
|
||||
return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
}
|
||||
if (dst == SLJIT_UNUSED && !(GET_FLAGS(op) & ~(SLJIT_SET_E | SLJIT_SET_S))) {
|
||||
/* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
|
||||
if (TEST_SL_IMM(src2, src2w)) {
|
||||
compiler->imm = src2w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
if (GET_FLAGS(op) == SLJIT_SET_E && TEST_SL_IMM(src1, src1w)) {
|
||||
compiler->imm = src1w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||
/* Range between -1 and -32768 is covered above. */
|
||||
if (TEST_ADD_IMM(src2, -src2w)) {
|
||||
compiler->imm = -src2w & 0xffffffff;
|
||||
return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
}
|
||||
if (dst == SLJIT_UNUSED && GET_FLAGS(op) == SLJIT_SET_U) {
|
||||
/* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
|
||||
if (TEST_UL_IMM(src2, src2w)) {
|
||||
compiler->imm = src2w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
if (dst == SLJIT_UNUSED && (op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U)) && !(op & (SLJIT_SET_O | SLJIT_SET_C))) {
|
||||
if (!(op & SLJIT_SET_U)) {
|
||||
/* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
|
||||
if (TEST_SL_IMM(src2, src2w)) {
|
||||
compiler->imm = src2w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
if (GET_FLAGS(op) == SLJIT_SET_E && TEST_SL_IMM(src1, src1w)) {
|
||||
compiler->imm = src1w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||
}
|
||||
}
|
||||
return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
|
||||
if (!(op & (SLJIT_SET_E | SLJIT_SET_S))) {
|
||||
/* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
|
||||
if (TEST_UL_IMM(src2, src2w)) {
|
||||
compiler->imm = src2w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
|
||||
}
|
||||
if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= 0x7fff) {
|
||||
compiler->imm = src2w;
|
||||
return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
return emit_op(compiler, SLJIT_SUB, inp_flags | ((op & SLJIT_SET_U) ? ALT_FORM4 : 0) | ((op & (SLJIT_SET_E | SLJIT_SET_S)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
|
||||
}
|
||||
if (!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O))) {
|
||||
if (TEST_SL_IMM(src2, -src2w)) {
|
||||
@@ -1251,7 +1310,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
|
||||
}
|
||||
}
|
||||
/* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
|
||||
return emit_op(compiler, SLJIT_SUB, inp_flags | (!(op & SLJIT_SET_U) ? 0 : ALT_FORM5), dst, dstw, src1, src1w, src2, src2w);
|
||||
return emit_op(compiler, SLJIT_SUB, inp_flags | (!(op & SLJIT_SET_U) ? 0 : ALT_FORM6), dst, dstw, src1, src1w, src2, src2w);
|
||||
|
||||
case SLJIT_SUBC:
|
||||
return emit_op(compiler, SLJIT_SUBC, inp_flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
|
||||
@@ -1324,6 +1383,22 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
|
||||
{
|
||||
check_sljit_get_register_index(reg);
|
||||
return reg_map[reg];
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, int size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_op_custom(compiler, instruction, size);
|
||||
SLJIT_ASSERT(size == 4);
|
||||
|
||||
return push_inst(compiler, *(sljit_ins*)instruction);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Floating point operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
@@ -1475,19 +1550,19 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, in
|
||||
/* Other instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int generals, int local_size)
|
||||
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)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size);
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
|
||||
compiler->has_locals = local_size > 0;
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
compiler->local_size = (2 + generals + 2) * sizeof(sljit_w) + local_size;
|
||||
compiler->local_size = (2 + saveds + 2) * sizeof(sljit_w) + local_size;
|
||||
#else
|
||||
compiler->local_size = (2 + generals + 7 + 8) * sizeof(sljit_w) + local_size;
|
||||
compiler->local_size = (2 + saveds + 7 + 8) * sizeof(sljit_w) + local_size;
|
||||
#endif
|
||||
compiler->local_size = (compiler->local_size + 15) & ~0xf;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -63,23 +63,23 @@ static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
int size;
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, temporaries, generals, local_size);
|
||||
check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
compiler->args = args;
|
||||
compiler->flags_saved = 0;
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
size = 1 + (generals <= 3 ? generals : 3) + (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
|
||||
size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
|
||||
#else
|
||||
size = 1 + (generals <= 3 ? generals : 3) + (args > 0 ? (2 + args * 3) : 0);
|
||||
size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (2 + args * 3) : 0);
|
||||
#endif
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!buf);
|
||||
@@ -92,42 +92,42 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
||||
*buf++ = 0xc4 | (reg_map[TMP_REGISTER] << 3);
|
||||
}
|
||||
#endif
|
||||
if (generals > 2)
|
||||
PUSH_REG(reg_map[SLJIT_GENERAL_REG3]);
|
||||
if (generals > 1)
|
||||
PUSH_REG(reg_map[SLJIT_GENERAL_REG2]);
|
||||
if (generals > 0)
|
||||
PUSH_REG(reg_map[SLJIT_GENERAL_REG1]);
|
||||
if (saveds > 2)
|
||||
PUSH_REG(reg_map[SLJIT_SAVED_REG3]);
|
||||
if (saveds > 1)
|
||||
PUSH_REG(reg_map[SLJIT_SAVED_REG2]);
|
||||
if (saveds > 0)
|
||||
PUSH_REG(reg_map[SLJIT_SAVED_REG1]);
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (args > 0) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG1] << 3) | reg_map[SLJIT_TEMPORARY_REG3];
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[SLJIT_TEMPORARY_REG3];
|
||||
}
|
||||
if (args > 1) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG2] << 3) | reg_map[SLJIT_TEMPORARY_REG2];
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[SLJIT_TEMPORARY_REG2];
|
||||
}
|
||||
if (args > 2) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0x44 | (reg_map[SLJIT_GENERAL_REG3] << 3);
|
||||
*buf++ = 0x44 | (reg_map[SLJIT_SAVED_REG3] << 3);
|
||||
*buf++ = 0x24;
|
||||
*buf++ = sizeof(sljit_w) * (3 + 2); /* generals >= 3 as well. */
|
||||
*buf++ = sizeof(sljit_w) * (3 + 2); /* saveds >= 3 as well. */
|
||||
}
|
||||
#else
|
||||
if (args > 0) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0x40 | (reg_map[SLJIT_GENERAL_REG1] << 3) | reg_map[TMP_REGISTER];
|
||||
*buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REGISTER];
|
||||
*buf++ = sizeof(sljit_w) * 2;
|
||||
}
|
||||
if (args > 1) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0x40 | (reg_map[SLJIT_GENERAL_REG2] << 3) | reg_map[TMP_REGISTER];
|
||||
*buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REGISTER];
|
||||
*buf++ = sizeof(sljit_w) * 3;
|
||||
}
|
||||
if (args > 2) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0x40 | (reg_map[SLJIT_GENERAL_REG3] << 3) | reg_map[TMP_REGISTER];
|
||||
*buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REGISTER];
|
||||
*buf++ = sizeof(sljit_w) * 4;
|
||||
}
|
||||
#endif
|
||||
@@ -136,9 +136,9 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
||||
compiler->temporaries_start = local_size;
|
||||
if (temporaries > 3)
|
||||
local_size += (temporaries - 3) * sizeof(sljit_uw);
|
||||
compiler->generals_start = local_size;
|
||||
if (generals > 3)
|
||||
local_size += (generals - 3) * sizeof(sljit_uw);
|
||||
compiler->saveds_start = local_size;
|
||||
if (saveds > 3)
|
||||
local_size += (saveds - 3) * sizeof(sljit_uw);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (local_size > 1024) {
|
||||
@@ -152,47 +152,43 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
||||
return emit_non_cum_binary(compiler, 0x2b, 0x29, 0x5 << 3, 0x2d,
|
||||
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size);
|
||||
|
||||
/* Mov arguments to general registers. */
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_fake_enter(compiler, args, temporaries, generals, local_size);
|
||||
check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
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->generals_start = compiler->local_size;
|
||||
if (generals > 3)
|
||||
compiler->local_size += (generals - 3) * sizeof(sljit_uw);
|
||||
compiler->saveds_start = compiler->local_size;
|
||||
if (saveds > 3)
|
||||
compiler->local_size += (saveds - 3) * sizeof(sljit_uw);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
|
||||
{
|
||||
int size;
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, src, srcw);
|
||||
check_sljit_emit_return(compiler, op, src, srcw);
|
||||
SLJIT_ASSERT(compiler->args >= 0);
|
||||
|
||||
compiler->flags_saved = 0;
|
||||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||
|
||||
if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG)
|
||||
FAIL_IF(emit_mov(compiler, SLJIT_RETURN_REG, 0, src, srcw));
|
||||
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));
|
||||
|
||||
size = 2 + (compiler->generals <= 3 ? compiler->generals : 3);
|
||||
size = 2 + (compiler->saveds <= 3 ? compiler->saveds : 3);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (compiler->args > 2)
|
||||
size += 2;
|
||||
@@ -205,12 +201,12 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
||||
|
||||
INC_SIZE(size);
|
||||
|
||||
if (compiler->generals > 0)
|
||||
POP_REG(reg_map[SLJIT_GENERAL_REG1]);
|
||||
if (compiler->generals > 1)
|
||||
POP_REG(reg_map[SLJIT_GENERAL_REG2]);
|
||||
if (compiler->generals > 2)
|
||||
POP_REG(reg_map[SLJIT_GENERAL_REG3]);
|
||||
if (compiler->saveds > 0)
|
||||
POP_REG(reg_map[SLJIT_SAVED_REG1]);
|
||||
if (compiler->saveds > 1)
|
||||
POP_REG(reg_map[SLJIT_SAVED_REG2]);
|
||||
if (compiler->saveds > 2)
|
||||
POP_REG(reg_map[SLJIT_SAVED_REG3]);
|
||||
POP_REG(reg_map[TMP_REGISTER]);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (compiler->args > 2)
|
||||
@@ -435,23 +431,23 @@ static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type
|
||||
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 generals, int local_size)
|
||||
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_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size);
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
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->generals_start = compiler->local_size;
|
||||
if (generals > 3)
|
||||
compiler->local_size += (generals - 3) * sizeof(sljit_uw);
|
||||
compiler->saveds_start = compiler->local_size;
|
||||
if (saveds > 3)
|
||||
compiler->local_size += (saveds - 3) * sizeof(sljit_uw);
|
||||
|
||||
CHECK_EXTRA_REGS(dst, dstw, (void)0);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -86,24 +86,24 @@ static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_w addr, int type)
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
int size, pushed_size;
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, temporaries, generals, local_size);
|
||||
check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
compiler->flags_saved = 0;
|
||||
|
||||
size = generals;
|
||||
size = saveds;
|
||||
/* Including the return address saved by the call instruction. */
|
||||
pushed_size = (generals + 1) * sizeof(sljit_w);
|
||||
pushed_size = (saveds + 1) * sizeof(sljit_w);
|
||||
#ifndef _WIN64
|
||||
if (generals >= 2)
|
||||
size += generals - 1;
|
||||
if (saveds >= 2)
|
||||
size += saveds - 1;
|
||||
#else
|
||||
/* Saving the virtual stack pointer. */
|
||||
compiler->has_locals = local_size > 0;
|
||||
@@ -111,8 +111,8 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
||||
size += 2;
|
||||
pushed_size += sizeof(sljit_w);
|
||||
}
|
||||
if (generals >= 4)
|
||||
size += generals - 3;
|
||||
if (saveds >= 4)
|
||||
size += saveds - 3;
|
||||
if (temporaries >= 5) {
|
||||
size += (5 - 4) * 2;
|
||||
pushed_size += sizeof(sljit_w);
|
||||
@@ -124,37 +124,37 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(size);
|
||||
if (generals >= 5) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_EREG2] >= 8, general_ereg2_is_hireg);
|
||||
if (saveds >= 5) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG2] >= 8, saved_ereg2_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_GENERAL_EREG2]);
|
||||
PUSH_REG(reg_lmap[SLJIT_SAVED_EREG2]);
|
||||
}
|
||||
if (generals >= 4) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_EREG1] >= 8, general_ereg1_is_hireg);
|
||||
if (saveds >= 4) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG1] >= 8, saved_ereg1_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_GENERAL_EREG1]);
|
||||
PUSH_REG(reg_lmap[SLJIT_SAVED_EREG1]);
|
||||
}
|
||||
if (generals >= 3) {
|
||||
if (saveds >= 3) {
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG3] >= 8, general_reg3_is_hireg);
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] >= 8, saved_reg3_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG3] < 8, general_reg3_is_loreg);
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] < 8, saved_reg3_is_loreg);
|
||||
#endif
|
||||
PUSH_REG(reg_lmap[SLJIT_GENERAL_REG3]);
|
||||
PUSH_REG(reg_lmap[SLJIT_SAVED_REG3]);
|
||||
}
|
||||
if (generals >= 2) {
|
||||
if (saveds >= 2) {
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG2] >= 8, general_reg2_is_hireg);
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] >= 8, saved_reg2_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG2] < 8, general_reg2_is_loreg);
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] < 8, saved_reg2_is_loreg);
|
||||
#endif
|
||||
PUSH_REG(reg_lmap[SLJIT_GENERAL_REG2]);
|
||||
PUSH_REG(reg_lmap[SLJIT_SAVED_REG2]);
|
||||
}
|
||||
if (generals >= 1) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG1] < 8, general_reg1_is_loreg);
|
||||
PUSH_REG(reg_lmap[SLJIT_GENERAL_REG1]);
|
||||
if (saveds >= 1) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG1] < 8, saved_reg1_is_loreg);
|
||||
PUSH_REG(reg_lmap[SLJIT_SAVED_REG1]);
|
||||
}
|
||||
#ifdef _WIN64
|
||||
if (temporaries >= 5) {
|
||||
@@ -173,33 +173,33 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
||||
if (args > 0) {
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG1] << 3) | 0x7;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x7;
|
||||
}
|
||||
if (args > 1) {
|
||||
*buf++ = REX_W | REX_R;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_lmap[SLJIT_GENERAL_REG2] << 3) | 0x6;
|
||||
*buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG2] << 3) | 0x6;
|
||||
}
|
||||
if (args > 2) {
|
||||
*buf++ = REX_W | REX_R;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_lmap[SLJIT_GENERAL_REG3] << 3) | 0x2;
|
||||
*buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG3] << 3) | 0x2;
|
||||
}
|
||||
#else
|
||||
if (args > 0) {
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG1] << 3) | 0x1;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x1;
|
||||
}
|
||||
if (args > 1) {
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG2] << 3) | 0x2;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | 0x2;
|
||||
}
|
||||
if (args > 2) {
|
||||
*buf++ = REX_W | REX_B;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG3] << 3) | 0x0;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -269,21 +269,20 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Mov arguments to general registers. */
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
|
||||
{
|
||||
int pushed_size;
|
||||
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_fake_enter(compiler, args, temporaries, generals, local_size);
|
||||
check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->saveds = saveds;
|
||||
/* Including the return address saved by the call instruction. */
|
||||
pushed_size = (generals + 1) * sizeof(sljit_w);
|
||||
pushed_size = (saveds + 1) * sizeof(sljit_w);
|
||||
#ifdef _WIN64
|
||||
compiler->has_locals = local_size > 0;
|
||||
if (local_size > 0)
|
||||
@@ -297,20 +296,16 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler,
|
||||
#endif
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
|
||||
{
|
||||
int size;
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, src, srcw);
|
||||
check_sljit_emit_return(compiler, op, src, srcw);
|
||||
|
||||
compiler->flags_saved = 0;
|
||||
|
||||
if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG) {
|
||||
compiler->mode32 = 0;
|
||||
FAIL_IF(emit_mov(compiler, SLJIT_RETURN_REG, 0, src, srcw));
|
||||
}
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
if (compiler->local_size > 0) {
|
||||
if (compiler->local_size <= 127) {
|
||||
@@ -333,15 +328,15 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
||||
}
|
||||
}
|
||||
|
||||
size = 1 + compiler->generals;
|
||||
size = 1 + compiler->saveds;
|
||||
#ifndef _WIN64
|
||||
if (compiler->generals >= 2)
|
||||
size += compiler->generals - 1;
|
||||
if (compiler->saveds >= 2)
|
||||
size += compiler->saveds - 1;
|
||||
#else
|
||||
if (compiler->has_locals)
|
||||
size += 2;
|
||||
if (compiler->generals >= 4)
|
||||
size += compiler->generals - 3;
|
||||
if (compiler->saveds >= 4)
|
||||
size += compiler->saveds - 3;
|
||||
if (compiler->temporaries >= 5)
|
||||
size += (5 - 4) * 2;
|
||||
#endif
|
||||
@@ -360,27 +355,27 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
|
||||
POP_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
|
||||
}
|
||||
#endif
|
||||
if (compiler->generals >= 1)
|
||||
POP_REG(reg_map[SLJIT_GENERAL_REG1]);
|
||||
if (compiler->generals >= 2) {
|
||||
if (compiler->saveds >= 1)
|
||||
POP_REG(reg_map[SLJIT_SAVED_REG1]);
|
||||
if (compiler->saveds >= 2) {
|
||||
#ifndef _WIN64
|
||||
*buf++ = REX_B;
|
||||
#endif
|
||||
POP_REG(reg_lmap[SLJIT_GENERAL_REG2]);
|
||||
POP_REG(reg_lmap[SLJIT_SAVED_REG2]);
|
||||
}
|
||||
if (compiler->generals >= 3) {
|
||||
if (compiler->saveds >= 3) {
|
||||
#ifndef _WIN64
|
||||
*buf++ = REX_B;
|
||||
#endif
|
||||
POP_REG(reg_lmap[SLJIT_GENERAL_REG3]);
|
||||
POP_REG(reg_lmap[SLJIT_SAVED_REG3]);
|
||||
}
|
||||
if (compiler->generals >= 4) {
|
||||
if (compiler->saveds >= 4) {
|
||||
*buf++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_GENERAL_EREG1]);
|
||||
POP_REG(reg_lmap[SLJIT_SAVED_EREG1]);
|
||||
}
|
||||
if (compiler->generals >= 5) {
|
||||
if (compiler->saveds >= 5) {
|
||||
*buf++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_GENERAL_EREG2]);
|
||||
POP_REG(reg_lmap[SLJIT_SAVED_EREG2]);
|
||||
}
|
||||
|
||||
RET();
|
||||
@@ -508,7 +503,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
||||
inst_size += 4;
|
||||
}
|
||||
else if (flags & EX86_SHIFT_INS) {
|
||||
imma &= 0x3f;
|
||||
imma &= compiler->mode32 ? 0x1f : 0x3f;
|
||||
if (imma != 1) {
|
||||
inst_size ++;
|
||||
flags |= EX86_BYTE_ARG;
|
||||
@@ -676,15 +671,15 @@ static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type
|
||||
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 generals, int local_size)
|
||||
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_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size);
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
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);
|
||||
@@ -802,52 +797,36 @@ static int emit_mov_int(struct sljit_compiler *compiler, int sign,
|
||||
return SLJIT_SUCCESS; /* Empty instruction. */
|
||||
|
||||
if (src & SLJIT_IMM) {
|
||||
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
|
||||
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
|
||||
if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
|
||||
code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
|
||||
FAIL_IF(!code);
|
||||
*code = 0xc7;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
return emit_load_imm64(compiler, dst, srcw);
|
||||
}
|
||||
compiler->mode32 = 1;
|
||||
code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(int)srcw, dst, dstw);
|
||||
code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
|
||||
FAIL_IF(!code);
|
||||
*code = 0xc7;
|
||||
compiler->mode32 = 0;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_GENERAL_REG3) ? dst : TMP_REGISTER;
|
||||
dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_SAVED_REG3) ? dst : TMP_REGISTER;
|
||||
|
||||
if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_GENERAL_REG3))
|
||||
if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_SAVED_REG3))
|
||||
dst_r = src;
|
||||
else {
|
||||
if (sign) {
|
||||
code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
|
||||
FAIL_IF(!code);
|
||||
*code++ = 0x63;
|
||||
}
|
||||
else {
|
||||
if (dst_r == src) {
|
||||
compiler->mode32 = 1;
|
||||
code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, 0);
|
||||
FAIL_IF(!code);
|
||||
*code++ = 0x8b;
|
||||
compiler->mode32 = 0;
|
||||
}
|
||||
/* xor reg, reg. */
|
||||
code = emit_x86_instruction(compiler, 1, dst_r, 0, dst_r, 0);
|
||||
FAIL_IF(!code);
|
||||
*code++ = 0x33;
|
||||
if (dst_r != src) {
|
||||
compiler->mode32 = 1;
|
||||
code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
|
||||
FAIL_IF(!code);
|
||||
*code++ = 0x8b;
|
||||
compiler->mode32 = 0;
|
||||
}
|
||||
else {
|
||||
compiler->mode32 = 1;
|
||||
code = emit_x86_instruction(compiler, 1, src, 0, TMP_REGISTER, 0);
|
||||
FAIL_IF(!code);
|
||||
*code++ = 0x8b;
|
||||
compiler->mode32 = 0;
|
||||
}
|
||||
} else {
|
||||
compiler->mode32 = 1;
|
||||
FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw));
|
||||
compiler->mode32 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* 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:
|
||||
@@ -26,11 +26,7 @@
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
|
||||
{
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
return "x86-32";
|
||||
#else
|
||||
return "x86-64";
|
||||
#endif
|
||||
return "x86" SLJIT_CPUINFO;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -80,8 +76,8 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 2] = {
|
||||
p = SLJIT_MEM1(SLJIT_LOCALS_REG); \
|
||||
do; \
|
||||
} \
|
||||
else if (p >= SLJIT_GENERAL_EREG1 && p <= SLJIT_GENERAL_EREG2) { \
|
||||
w = compiler->generals_start + (p - SLJIT_GENERAL_EREG1) * sizeof(sljit_w); \
|
||||
else if (p >= SLJIT_SAVED_EREG1 && p <= SLJIT_SAVED_EREG2) { \
|
||||
w = compiler->saveds_start + (p - SLJIT_SAVED_EREG1) * sizeof(sljit_w); \
|
||||
p = SLJIT_MEM1(SLJIT_LOCALS_REG); \
|
||||
do; \
|
||||
}
|
||||
@@ -95,7 +91,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 2] = {
|
||||
|
||||
/* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present
|
||||
Note: avoid to use r12 and r13 for memory addessing
|
||||
therefore r12 is better for GENERAL_EREG than GENERAL_REG. */
|
||||
therefore r12 is better for SAVED_EREG than SAVED_REG. */
|
||||
#ifndef _WIN64
|
||||
/* 1st passed in rdi, 2nd argument passed in rsi, 3rd in rdx. */
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
||||
@@ -474,32 +470,6 @@ static void SLJIT_CALL sljit_touch_stack(sljit_w local_size)
|
||||
#include "sjx8664.c"
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_op0(compiler, op);
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
switch (op) {
|
||||
case SLJIT_BREAKPOINT:
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(1);
|
||||
*buf = 0xcc;
|
||||
break;
|
||||
case SLJIT_NOP:
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(1);
|
||||
*buf = 0x90;
|
||||
break;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int emit_mov(struct sljit_compiler *compiler,
|
||||
int dst, sljit_w dstw,
|
||||
int src, sljit_w srcw)
|
||||
@@ -568,6 +538,142 @@ static int emit_mov(struct sljit_compiler *compiler,
|
||||
#define EMIT_MOV(compiler, dst, dstw, src, srcw) \
|
||||
FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
int size;
|
||||
#endif
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_op0(compiler, op);
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_BREAKPOINT:
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(1);
|
||||
*buf = 0xcc;
|
||||
break;
|
||||
case SLJIT_NOP:
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(1);
|
||||
*buf = 0x90;
|
||||
break;
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
case SLJIT_UDIV:
|
||||
case SLJIT_SDIV:
|
||||
compiler->flags_saved = 0;
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#ifdef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(
|
||||
reg_map[SLJIT_TEMPORARY_REG1] == 0
|
||||
&& reg_map[SLJIT_TEMPORARY_REG2] == 2
|
||||
&& reg_map[TMP_REGISTER] > 7,
|
||||
invalid_register_assignment_for_div_mul);
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(
|
||||
reg_map[SLJIT_TEMPORARY_REG1] == 0
|
||||
&& reg_map[SLJIT_TEMPORARY_REG2] < 7
|
||||
&& reg_map[TMP_REGISTER] == 2,
|
||||
invalid_register_assignment_for_div_mul);
|
||||
#endif
|
||||
compiler->mode32 = op & SLJIT_INT_OP;
|
||||
#endif
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
if (op == SLJIT_UDIV) {
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
|
||||
EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG2, 0);
|
||||
buf = emit_x86_instruction(compiler, 1, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0);
|
||||
#else
|
||||
buf = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
|
||||
#endif
|
||||
FAIL_IF(!buf);
|
||||
*buf = 0x33;
|
||||
}
|
||||
|
||||
if (op == SLJIT_SDIV) {
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
|
||||
EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG2, 0);
|
||||
#endif
|
||||
|
||||
/* CDQ instruction */
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(1);
|
||||
*buf = 0x99;
|
||||
#else
|
||||
if (compiler->mode32) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(1);
|
||||
*buf = 0x99;
|
||||
} else {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(2);
|
||||
*buf++ = REX_W;
|
||||
*buf = 0x99;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(2);
|
||||
*buf++ = 0xf7;
|
||||
*buf = 0xc0 | ((op >= SLJIT_UDIV) ? reg_map[TMP_REGISTER] : reg_map[SLJIT_TEMPORARY_REG2]);
|
||||
#else
|
||||
#ifdef _WIN64
|
||||
size = (!compiler->mode32 || op >= SLJIT_UDIV) ? 3 : 2;
|
||||
#else
|
||||
size = (!compiler->mode32) ? 3 : 2;
|
||||
#endif
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(size);
|
||||
#ifdef _WIN64
|
||||
if (!compiler->mode32)
|
||||
*buf++ = REX_W | ((op >= SLJIT_UDIV) ? REX_B : 0);
|
||||
else if (op >= SLJIT_UDIV)
|
||||
*buf++ = REX_B;
|
||||
*buf++ = 0xf7;
|
||||
*buf = 0xc0 | ((op >= SLJIT_UDIV) ? reg_lmap[TMP_REGISTER] : reg_lmap[SLJIT_TEMPORARY_REG2]);
|
||||
#else
|
||||
if (!compiler->mode32)
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0xf7;
|
||||
*buf = 0xc0 | reg_map[SLJIT_TEMPORARY_REG2];
|
||||
#endif
|
||||
#endif
|
||||
switch (op) {
|
||||
case SLJIT_UMUL:
|
||||
*buf |= 4 << 3;
|
||||
break;
|
||||
case SLJIT_SMUL:
|
||||
*buf |= 5 << 3;
|
||||
break;
|
||||
case SLJIT_UDIV:
|
||||
*buf |= 6 << 3;
|
||||
break;
|
||||
case SLJIT_SDIV:
|
||||
*buf |= 7 << 3;
|
||||
break;
|
||||
}
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
|
||||
EMIT_MOV(compiler, SLJIT_TEMPORARY_REG2, 0, TMP_REGISTER, 0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#define ENCODE_PREFIX(prefix) \
|
||||
do { \
|
||||
code = (sljit_ub*)ensure_buf(compiler, 1 + 1); \
|
||||
@@ -853,6 +959,7 @@ static int emit_clz(struct sljit_compiler *compiler, int op,
|
||||
sljit_ub* code;
|
||||
int dst_r;
|
||||
|
||||
SLJIT_UNUSED_ARG(op);
|
||||
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
|
||||
/* Just set the zero flag. */
|
||||
EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
|
||||
@@ -1718,21 +1825,19 @@ static int emit_shift(struct sljit_compiler *compiler,
|
||||
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
|
||||
}
|
||||
else {
|
||||
/* This case is really difficult, since ecx can be used for
|
||||
addressing as well, and we must ensure to work even in that case. */
|
||||
/* This case is really difficult, since ecx itself may used for
|
||||
addressing, and we must ensure to work even in that case. */
|
||||
EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
|
||||
#else
|
||||
/* [esp - 4] is reserved for eflags. */
|
||||
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), -(int)(2 * sizeof(sljit_w)), SLJIT_PREF_SHIFT_REG, 0);
|
||||
#endif
|
||||
|
||||
EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
|
||||
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
|
||||
code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
|
||||
FAIL_IF(!code);
|
||||
*code |= mode;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);
|
||||
#else
|
||||
@@ -1745,6 +1850,41 @@ static int emit_shift(struct sljit_compiler *compiler,
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int emit_shift_with_flags(struct sljit_compiler *compiler,
|
||||
sljit_ub mode, int set_flags,
|
||||
int dst, sljit_w dstw,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w)
|
||||
{
|
||||
/* The CPU does not set flags if the shift count is 0. */
|
||||
if (src2 & SLJIT_IMM) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if ((src2w & 0x3f) != 0 || (compiler->mode32 && (src2w & 0x1f) != 0))
|
||||
return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
|
||||
#else
|
||||
if ((src2w & 0x1f) != 0)
|
||||
return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
|
||||
#endif
|
||||
if (!set_flags)
|
||||
return emit_mov(compiler, dst, dstw, src1, src1w);
|
||||
/* OR dst, src, 0 */
|
||||
return emit_cum_binary(compiler, 0x0b, 0x09, 0x1 << 3, 0x0d,
|
||||
dst, dstw, src1, src1w, SLJIT_IMM, 0);
|
||||
}
|
||||
|
||||
if (!set_flags)
|
||||
return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
|
||||
|
||||
if (!(dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS))
|
||||
FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0));
|
||||
|
||||
FAIL_IF(emit_shift(compiler,mode, dst, dstw, src1, src1w, src2, src2w));
|
||||
|
||||
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
|
||||
return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src1, sljit_w src1w,
|
||||
@@ -1824,19 +1964,46 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
|
||||
return emit_cum_binary(compiler, 0x33, 0x31, 0x6 << 3, 0x35,
|
||||
dst, dstw, src1, src1w, src2, src2w);
|
||||
case SLJIT_SHL:
|
||||
return emit_shift(compiler, 0x4 << 3,
|
||||
return emit_shift_with_flags(compiler, 0x4 << 3, GET_FLAGS(op),
|
||||
dst, dstw, src1, src1w, src2, src2w);
|
||||
case SLJIT_LSHR:
|
||||
return emit_shift(compiler, 0x5 << 3,
|
||||
return emit_shift_with_flags(compiler, 0x5 << 3, GET_FLAGS(op),
|
||||
dst, dstw, src1, src1w, src2, src2w);
|
||||
case SLJIT_ASHR:
|
||||
return emit_shift(compiler, 0x7 << 3,
|
||||
return emit_shift_with_flags(compiler, 0x7 << 3, GET_FLAGS(op),
|
||||
dst, dstw, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
|
||||
{
|
||||
check_sljit_get_register_index(reg);
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
if (reg == SLJIT_TEMPORARY_EREG1 || reg == SLJIT_TEMPORARY_EREG2
|
||||
|| reg == SLJIT_SAVED_EREG1 || reg == SLJIT_SAVED_EREG2)
|
||||
return -1;
|
||||
#endif
|
||||
return reg_map[reg];
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, int size)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_op_custom(compiler, instruction, size);
|
||||
SLJIT_ASSERT(size > 0 && size < 16);
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(size);
|
||||
SLJIT_MEMMOVE(buf, instruction, size);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Floating point operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
@@ -2582,7 +2749,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compil
|
||||
|
||||
*buf++ = 0x0f;
|
||||
*buf++ = 0xb6;
|
||||
if (dst >= SLJIT_GENERAL_REG1 && dst <= SLJIT_NO_REGISTERS)
|
||||
if (dst >= SLJIT_SAVED_REG1 && dst <= SLJIT_NO_REGISTERS)
|
||||
*buf = 0xC0 | (reg_map[dst] << 3);
|
||||
else {
|
||||
*buf = 0xC0;
|
||||
|
||||
Reference in New Issue
Block a user