commit 5273d146f6484f74608e8d49f53938186584b90a Author: MSVSphere Packaging Team Date: Mon Oct 7 21:06:34 2024 +0300 import pcre-8.44-4.el9 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..098c7e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/pcre-8.44.tar.bz2 +SOURCES/pcre-8.44.tar.bz2.sig diff --git a/.pcre.metadata b/.pcre.metadata new file mode 100644 index 0000000..e82ac29 --- /dev/null +++ b/.pcre.metadata @@ -0,0 +1,2 @@ +8179b083053fce9b4a766513fa1f14807aabee42 SOURCES/pcre-8.44.tar.bz2 +b43d3d5bcd1d534c18134821d767c367d37ef929 SOURCES/pcre-8.44.tar.bz2.sig diff --git a/SOURCES/0001-Fix-the-possible-array-overrun-when-the-OP_TABLE_LEN.patch b/SOURCES/0001-Fix-the-possible-array-overrun-when-the-OP_TABLE_LEN.patch new file mode 100644 index 0000000..69d3507 --- /dev/null +++ b/SOURCES/0001-Fix-the-possible-array-overrun-when-the-OP_TABLE_LEN.patch @@ -0,0 +1,39 @@ +From bc21e89823bb3b1550e03489345864dfe1515e2c Mon Sep 17 00:00:00 2001 +From: Lukas Javorsky +Date: Tue, 16 Apr 2024 10:13:35 +0000 +Subject: [PATCH] Fix the possible array overrun when the OP_TABLE_LENGTH + +When the *code pointer holds value of 162 (OP_TABLE_LENGTH) it could +possibly overrun the priv_OP_lengths[] array. By adding this condition +it's not being overrun and the 0 values is added instead. It would most +likely be 0 when overrun as the array is alligned to the lowest byte +with zeros + +--- + pcre_printint.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/pcre_printint.c b/pcre_printint.c +index 60dcb55..e1e419b 100644 +--- a/pcre_printint.c ++++ b/pcre_printint.c +@@ -825,8 +825,14 @@ for(;;) + fprintf(f, " %s %s", flag, priv_OP_names[*code]); + break; + } +- +- code += priv_OP_lengths[*code] + extra; ++ if (*code >= OP_TABLE_LENGTH){ ++ // Use 0 because it would most likely be 0 when the priv_OP_lengths is overrun. ++ // Allocator would have allign the size of this array ++ code += 0 + extra; ++ } ++ else { ++ code += priv_OP_lengths[*code] + extra; ++ } + fprintf(f, "\n"); + } + } +-- +2.44.0 + diff --git a/SOURCES/0002-Fix-UNINIT-SAST-report-for-the-mark-values.patch b/SOURCES/0002-Fix-UNINIT-SAST-report-for-the-mark-values.patch new file mode 100644 index 0000000..ca598b4 --- /dev/null +++ b/SOURCES/0002-Fix-UNINIT-SAST-report-for-the-mark-values.patch @@ -0,0 +1,44 @@ +From 3f53de7ff720b40f547a2d55532a73b2b570ab40 Mon Sep 17 00:00:00 2001 +From: Lukas Javorsky +Date: Tue, 16 Apr 2024 10:28:58 +0000 +Subject: [PATCH] Fix UNINIT SAST report for the mark* values + +These values are initialized if the re* values is true, thus we can add +it to the condition, so there is no possibility that the mark* values +are not initialized +--- + pcre_jit_test.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/pcre_jit_test.c b/pcre_jit_test.c +index 034cb52..e3e4a3e 100644 +--- a/pcre_jit_test.c ++++ b/pcre_jit_test.c +@@ -1687,21 +1687,21 @@ static int regression_tests(void) + + if (is_successful) { + #ifdef SUPPORT_PCRE8 +- if (mark8_1 != mark8_2) { ++ if (re8 && (mark8_1 != mark8_2)) { + printf("8 bit: Mark value mismatch: [%d] '%s' @ '%s'\n", + total, current->pattern, current->input); + is_successful = 0; + } + #endif + #ifdef SUPPORT_PCRE16 +- if (mark16_1 != mark16_2) { ++ if (re16 && (mark16_1 != mark16_2)) { + printf("16 bit: Mark value mismatch: [%d] '%s' @ '%s'\n", + total, current->pattern, current->input); + is_successful = 0; + } + #endif + #ifdef SUPPORT_PCRE32 +- if (mark32_1 != mark32_2) { ++ if (re32 && (mark32_1 != mark32_2)) { + printf("32 bit: Mark value mismatch: [%d] '%s' @ '%s'\n", + total, current->pattern, current->input); + is_successful = 0; +-- +2.44.0 + diff --git a/SOURCES/Public-Key b/SOURCES/Public-Key new file mode 100644 index 0000000..95dbb71 --- /dev/null +++ b/SOURCES/Public-Key @@ -0,0 +1,39 @@ +This is Philip Hazel's public GPG key. + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.0 (SunOS) + +mQEMBD2z9g0BCACpGWJ4K2mjR6K9nv7/K+HLjJtDO0E0ckudeNjg2JvnuUU7m1bK +87nSklHTSMNiqmuVU5hFAuGiMGBMj31GPpce3VbABdm6TmAJB8ZndvJXyf8lC7Ko +5iZX/gCYU6817UI5pFwYR3MTIUSSxTGqk1y62pYLKUq9keSU5Cew4q1KMwl46Bn3 +SwlfQeST4WGwL2w9b8mWNltBBY23bgzwYu7vFBD4GQnfzJsvMC9lj825wob2nKy5 +CL4bY6tiYUqALzDYaIVCBqJ1Ky1rpPzRcDZUeeF8Ta3njh18Y0KzPEj+Xu5Ksexg +7LUy/2wFzVRtJgqvAFZo43KIOptsj/63zxJjAAkBAbQhUGhpbGlwIEhhemVsIDxw +aDEwQGN1cy5jYW0uYWMudWs+iQEyBBMBAgAcBQI9s/YNAhsDBAsHAwIDFQIDAxYC +AQIeAQIXgAAKCRCXZuCE+w9D2JbrCACBHrxybV+9t3TGR3+uk2QnUuct90a+udcB +cbWgKQgX345ZgwIfyoPKAbG84mN/+SFUN/Ie4ZHZxVsbN//l2P/Osx0CNQBfem4e +HUWegkFGzC5DxQhN5nsJ/GR6pnxG1l/DbNhupNY73oTajWFdi7K8jYfamU/zS/Da +VCwUKxWtGqyEqOxvbdqcjsnTMmLVfXtefx7CbKyhaClPP8Pe4FL+eqyfHJF7uywK +VWlUNmQa4E+ZAK8tkoK9sZAc0ImWwZMumiKZDEpr2D8Ty+Gg2umTS2OMIcbY8QF1 +r6DeubFabdPIe1kn0BGXtdAurhbdJCIbcAEQS0eEeWC4A4LiDprntB1QaGlsaXAg +SGF6ZWwgPHBoMTBAY2FtLmFjLnVrPokBMgQTAQIAHAUCPbaC8QIbAwQLBwMCAxUC +AwMWAgECHgECF4AACgkQl2bghPsPQ9ho5Qf+I2HUhZeXOUneeqSa+cITsIELJMrZ +UWcydY1z+L68yOqURVHB1jF4aC6QSlq0pLjozwF6KfZO5AfN9FvkRQ0DzCEXH48W +OXqzbjzgNxRMdaP5+49Axl0UQuhupGJg66T4FiGnSVBhK8kTURPCSpLLgkCJqNcY +t5zuNwk3e7JvleT59EVpk/kw3a5p9oeKYBln57pHwq+HdPLSCdkedQBKdsbNrazy +qduYEXen4ogsIoTpA9lLH1Xsi9wL+soLAlWXtl/GNa1h7Jpwn41zp1hqIZe1ebIM +dSGbtMEaGJlqgDauYJSl0lkVgaPtZCTmfAf57TsGfD0IckN2XNGLuwb6DLkBCwQ9 +s/eJAQgAuXq2I1VTDB108O0NAB6QKfA2gMHafoj3OcwEUHnJgXrHqjYOpFr0r5lC +YjwMRMvHO7r4jgtwKjGACI/1IE2hiGXkKFOWZFkCf7Qjoi13a78myC/VRwe4uEIs +xdz++w8WfzuC1sYw8d/rlybVzHTfTsKfmFOQamuyLCTm3Kdx/wZyGM7JMmgVn2zF +HWasdID0n7QJFZGR3yEfqis5zq1t3w28AaXlTZG7QtFj9V0cWIhZRjjjVe1biPA8 +Btp+eFkmcat79N9hHbiEiAY3u2qmQCcn1fiBBC0Og09cY4dRyX0/bXUo4n8lHysp +JcL/sIZ7Ahd1LOfg9h+yQfoaey78LQAGKYkBHwQYAQIACQUCPbP3iQIbDAAKCRCX +ZuCE+w9D2P0BCACXsbwFerd4wlnt8PxxQlRGXi1t4EGBFf2zSdgQvIXJ3ntPzcDU ++8hnIWQJhCTZ3PfVmoqB6ZOM1RWI/IcP6b4qVb6vJGI/VxRICraAczw+4bdFxFiB +n2+SyD4MxZg8t66FcH3fHugQqsApHTmtKmahv5BXB+0dPmP/BRUmzxYUv8hdnhHl +91S4R4BDu84DvKYyJK9jlqUl06pvqXrBSNsbWKgAJnmnDe8FaLUk+p0IXeMSavUn +T5E26MRIioxAz/G4FZI8IdO92GHTz82O7/mQMhveAdpspDvpV3M4wnldU425GlxZ +nmq1bbjAU4QVuIS9nkk2GrGx5+N6cYMy8JqG +=EHsz +-----END PGP PUBLIC KEY BLOCK----- diff --git a/SOURCES/pcre-8.21-multilib.patch b/SOURCES/pcre-8.21-multilib.patch new file mode 100644 index 0000000..345e624 --- /dev/null +++ b/SOURCES/pcre-8.21-multilib.patch @@ -0,0 +1,37 @@ +From 1d5ce3e2e6341b01609aefab20786a8638fee17a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= +Date: Tue, 6 Dec 2011 18:44:11 +0100 +Subject: [PATCH] Fix multilib + +Do not set RPATH nor add explicit -L path to compiler. +--- + pcre-config.in | 12 ------------ + 1 files changed, 0 insertions(+), 12 deletions(-) + +diff --git a/pcre-config.in b/pcre-config.in +index ccbf210..aeee182 100644 +--- a/pcre-config.in ++++ b/pcre-config.in +@@ -16,19 +16,7 @@ if test $# -eq 0; then + fi + + libR= +-case `uname -s` in +- *SunOS*) +- libR=" -R@libdir@" +- ;; +- *BSD*) +- libR=" -Wl,-R@libdir@" +- ;; +-esac +- + libS= +-if test @libdir@ != /usr/lib ; then +- libS=-L@libdir@ +-fi + + while test $# -gt 0; do + case "$1" in +-- +1.7.7.4 + diff --git a/SOURCES/pcre-8.32-refused_spelling_terminated.patch b/SOURCES/pcre-8.32-refused_spelling_terminated.patch new file mode 100644 index 0000000..32c9f7e --- /dev/null +++ b/SOURCES/pcre-8.32-refused_spelling_terminated.patch @@ -0,0 +1,48 @@ +From 6f8b68f2740f3100154342338ed3d26e676dae69 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= +Date: Mon, 7 Feb 2011 11:37:09 +0100 +Subject: [PATCH] Fix spelling in pcretest(1) manual + +I kept some non-dictionary words to be consistent. +Credits to John Bradshaw. + +Spelling refused by upstream : + +I have applied these patches, except for "termi-nated", because my +Collins dictionary of spelling and word division shows "termin-ate" and +"termin-ating". I do know that there is a cultural difference between +British and American hyphenation conventions; I try to follow the +British ones, as exemplified in the Collins. +--- + doc/pcretest.1 | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/doc/pcretest.1 b/doc/pcretest.1 +index 41ef6ac..258a62f 100644 +--- a/doc/pcretest.1 ++++ b/doc/pcretest.1 +@@ -601,8 +601,8 @@ recognized: + after a successful match (number less than 32) + .\" JOIN + \eCname call pcre[16|32]_copy_named_substring() for substring +- "name" after a successful match (name termin- +- ated by next non alphanumeric character) ++ "name" after a successful match (name terminated ++ by next non alphanumeric character) + .\" JOIN + \eC+ show the current captured substrings at callout + time +@@ -623,8 +623,8 @@ recognized: + after a successful match (number less than 32) + .\" JOIN + \eGname call pcre[16|32]_get_named_substring() for substring +- "name" after a successful match (name termin- +- ated by next non-alphanumeric character) ++ "name" after a successful match (name terminated ++ by next non-alphanumeric character) + .\" JOIN + \eJdd set up a JIT stack of dd kilobytes maximum (any + number of digits) +-- +1.7.11.7 + diff --git a/SOURCES/pcre-8.41-fix_stack_estimator.patch b/SOURCES/pcre-8.41-fix_stack_estimator.patch new file mode 100644 index 0000000..cf388bf --- /dev/null +++ b/SOURCES/pcre-8.41-fix_stack_estimator.patch @@ -0,0 +1,24 @@ +Fix recursion stack estimator + +Due to inlining match() by recent GCC, the stack estimator reported 4-bytes +stack consumption. + +Author: Sergei Golubchik + + +diff --git a/pcre/pcre_exec.c b/pcre/pcre_exec.c +--- a/pcre/pcre_exec.c ++++ b/pcre/pcre_exec.c +@@ -509,6 +509,12 @@ + (e.g. stopped by repeated call or recursion limit) + */ + ++#ifdef __GNUC__ ++static int ++match(REGISTER PCRE_PUCHAR eptr, REGISTER const pcre_uchar *ecode, ++ PCRE_PUCHAR mstart, int offset_top, match_data *md, eptrblock *eptrb, ++ unsigned int rdepth) __attribute__((noinline,noclone)); ++#endif + static int + match(REGISTER PCRE_PUCHAR eptr, REGISTER const pcre_uchar *ecode, + PCRE_PUCHAR mstart, int offset_top, match_data *md, eptrblock *eptrb, diff --git a/SOURCES/pcre-8.42-Declare-POSIX-regex-function-names-as-macros-to-PCRE.patch b/SOURCES/pcre-8.42-Declare-POSIX-regex-function-names-as-macros-to-PCRE.patch new file mode 100644 index 0000000..c6ae004 --- /dev/null +++ b/SOURCES/pcre-8.42-Declare-POSIX-regex-function-names-as-macros-to-PCRE.patch @@ -0,0 +1,161 @@ +From f1e9a32ee7fad2263636a51536ce0f9f13f09949 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= +Date: Wed, 23 Jan 2019 10:16:20 +0100 +Subject: [PATCH] Declare POSIX regex function names as macros to PCRE + functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +POSIX regex libraries differ in regex_t size. If a program includes +, but is not linked to pcreposix library at run-time +(either in effect of --as-needed or a lazy binding in dlopen) +other implementation touches memory out of the structure and the +program can crash. + +That means once a program includes , it must link to the +pcreposix library. + +This patch replaces the POSIX regex declaration with macros to the +PCRE uniqely-named function. This ensures that the PCRE's regex_t +structure is always handled by the PCRE functions. + +This patch still preserves the POSIX regex definitions in order to +preseve ABI with application compiled before this change. The +definition can be removed in the future. + +Signed-off-by: Petr Písař +--- + pcreposix.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- + pcreposix.h | 20 ++++++++++++++------ + 2 files changed, 59 insertions(+), 11 deletions(-) + +diff --git a/pcreposix.c b/pcreposix.c +index a76d6bf..3f2f3ef 100644 +--- a/pcreposix.c ++++ b/pcreposix.c +@@ -39,7 +39,10 @@ POSSIBILITY OF SUCH DAMAGE. + + + /* This module is a wrapper that provides a POSIX API to the underlying PCRE +-functions. */ ++functions. The operative functions are called pcre_regcomp(), etc., with ++wrappers that use the plain POSIX names. This makes it easier for an ++application to be sure it gets the PCRE versions in the presence of other ++POSIX regex libraries. */ + + + #ifdef HAVE_CONFIG_H +@@ -204,12 +207,49 @@ static const char *const pstring[] = { + + + /************************************************* +-* Translate error code to string * ++* Wrappers with traditional POSIX names * + *************************************************/ + ++/* Keep defining them to preseve ABI with application linked to pcreposix ++ * library before they were changed into macros. */ ++ ++#undef regerror + PCREPOSIX_EXP_DEFN size_t PCRE_CALL_CONVENTION + regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) + { ++return pcre_regerror(errcode, preg, errbuf, errbuf_size); ++} ++ ++#undef regfree ++PCREPOSIX_EXP_DEFN void PCRE_CALL_CONVENTION ++regfree(regex_t *preg) ++{ ++pcre_regfree(preg); ++} ++ ++#undef regcomp ++PCREPOSIX_EXP_DEFN int PCRE_CALL_CONVENTION ++regcomp(regex_t *preg, const char *pattern, int cflags) ++{ ++return pcre_regcomp(preg, pattern, cflags); ++} ++ ++#undef regexec ++PCREPOSIX_EXP_DEFN int PCRE_CALL_CONVENTION ++regexec(const regex_t *preg, const char *string, size_t nmatch, ++ regmatch_t pmatch[], int eflags) ++{ ++return pcre_regexec(preg, string, nmatch, pmatch, eflags); ++} ++ ++ ++/************************************************* ++* Translate error code to string * ++*************************************************/ ++ ++PCREPOSIX_EXP_DEFN size_t PCRE_CALL_CONVENTION ++pcre_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) ++{ + const char *message, *addmessage; + size_t length, addlength; + +@@ -243,7 +283,7 @@ return length + addlength; + *************************************************/ + + PCREPOSIX_EXP_DEFN void PCRE_CALL_CONVENTION +-regfree(regex_t *preg) ++pcre_regfree(regex_t *preg) + { + (PUBL(free))(preg->re_pcre); + } +@@ -266,7 +306,7 @@ Returns: 0 on success + */ + + PCREPOSIX_EXP_DEFN int PCRE_CALL_CONVENTION +-regcomp(regex_t *preg, const char *pattern, int cflags) ++pcre_regcomp(regex_t *preg, const char *pattern, int cflags) + { + const char *errorptr; + int erroffset; +@@ -320,7 +360,7 @@ be set. When this is the case, the nmatch and pmatch arguments are ignored, and + the only result is yes/no/error. */ + + PCREPOSIX_EXP_DEFN int PCRE_CALL_CONVENTION +-regexec(const regex_t *preg, const char *string, size_t nmatch, ++pcre_regexec(const regex_t *preg, const char *string, size_t nmatch, + regmatch_t pmatch[], int eflags) + { + int rc, so, eo; +diff --git a/pcreposix.h b/pcreposix.h +index c77c0b0..6f108b8 100644 +--- a/pcreposix.h ++++ b/pcreposix.h +@@ -131,13 +131,21 @@ file. */ + # endif + #endif + +-/* The functions */ +- +-PCREPOSIX_EXP_DECL int regcomp(regex_t *, const char *, int); +-PCREPOSIX_EXP_DECL int regexec(const regex_t *, const char *, size_t, ++/* The functions. The actual code is in functions with pcre_xxx names for ++uniqueness. POSIX names are provided for API compatibility with POSIX regex ++functions. It's done this way to ensure to they are always get from the ++PCRE library and not by accident from elsewhere. (regex_t differs in size ++elsewhere.) */ ++ ++PCREPOSIX_EXP_DECL int pcre_regcomp(regex_t *, const char *, int); ++#define regcomp pcre_regcomp ++PCREPOSIX_EXP_DECL int pcre_regexec(const regex_t *, const char *, size_t, + regmatch_t *, int); +-PCREPOSIX_EXP_DECL size_t regerror(int, const regex_t *, char *, size_t); +-PCREPOSIX_EXP_DECL void regfree(regex_t *); ++#define regexec pcre_regexec ++PCREPOSIX_EXP_DECL size_t pcre_regerror(int, const regex_t *, char *, size_t); ++#define regerror pcre_regerror ++PCREPOSIX_EXP_DECL void pcre_regfree(regex_t *); ++#define regfree pcre_regfree + + #ifdef __cplusplus + } /* extern "C" */ +-- +2.17.2 + diff --git a/SOURCES/pcre-8.44-Inicialize-name-table-memory-region.patch b/SOURCES/pcre-8.44-Inicialize-name-table-memory-region.patch new file mode 100644 index 0000000..747ac05 --- /dev/null +++ b/SOURCES/pcre-8.44-Inicialize-name-table-memory-region.patch @@ -0,0 +1,44 @@ +From f0bb9e8baf3157e0a84f484f194984295b2db23a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= +Date: Mon, 19 Oct 2020 16:15:14 +0200 +Subject: [PATCH] Inicialize name table memory region +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Name table entry values are accessed past their ends in add_name() +when comparing the values. Also a size of the entries could grow +later. It's safer to initialize just after the allocation than to hunt +the gaps later. + +Reproducer: + +pcre_compile2("(?)(?)", PCRE_NO_AUTO_CAPTURE | PCRE_CASELESS, &ec, &eb, &eo, NULL); + +built with clang++ -fsanitize=memory -fsanitize=fuzzer-no-link. + +https://bugs.exim.org/show_bug.cgi?id=2661 +Signed-off-by: Petr Písař +--- + pcre_compile.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/pcre_compile.c b/pcre_compile.c +index 3be0fbf..75309e0 100644 +--- a/pcre_compile.c ++++ b/pcre_compile.c +@@ -9423,6 +9423,11 @@ if (re == NULL) + goto PCRE_EARLY_ERROR_RETURN; + } + ++/* Initialize the memory. Name table entry values are accessed past their ends ++ * (e.g. in add_name()) when comparing the values. Also a size of the entry can ++ * grow later. It's safer to initialize here than to hunt the gaps later. */ ++memset(re, 0, size); ++ + /* Put in the magic number, and save the sizes, initial options, internal + flags, and character table pointer. NULL is used for the default character + tables. The nullpad field is at the end; it's there to help in the case when a +-- +2.25.4 + diff --git a/SOURCES/pcre-8.44-JIT-compiler-update-for-Intel-CET.patch b/SOURCES/pcre-8.44-JIT-compiler-update-for-Intel-CET.patch new file mode 100644 index 0000000..b71c1ca --- /dev/null +++ b/SOURCES/pcre-8.44-JIT-compiler-update-for-Intel-CET.patch @@ -0,0 +1,2645 @@ +From 52a4bebc87f000f1df3cf10ec8e4533dc9acad92 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Sun, 20 Dec 2020 13:32:56 -0800 +Subject: [PATCH] JIT compiler update for Intel CET +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Petr Pisar: Ported to 8.44 tarball from +. + +Signed-off-by: Petr Písař +--- + pcre_jit_compile.c | 43 ++++--- + sljit/sljitConfig.h | 17 ++- + sljit/sljitConfigInternal.h | 67 ++++++++-- + sljit/sljitExecAllocator.c | 17 ++- + sljit/sljitLir.c | 95 +++++++++------ + sljit/sljitLir.h | 92 ++++++++++---- + sljit/sljitNativeARM_32.c | 64 ++++++---- + sljit/sljitNativeARM_64.c | 75 +++++++----- + sljit/sljitNativeARM_T2_32.c | 56 +++++---- + sljit/sljitNativeMIPS_32.c | 31 ++--- + sljit/sljitNativeMIPS_64.c | 21 ++-- + sljit/sljitNativeMIPS_common.c | 184 +++++++++++++++------------- + sljit/sljitNativePPC_common.c | 56 +++++---- + sljit/sljitNativeSPARC_common.c | 54 ++++++--- + sljit/sljitNativeTILEGX_64.c | 44 ++++--- + sljit/sljitNativeX86_32.c | 50 ++++++-- + sljit/sljitNativeX86_64.c | 28 ++++- + sljit/sljitNativeX86_common.c | 209 ++++++++++++++++++++++++++++++-- + sljit/sljitUtils.c | 157 +++++++++++++++++------- + 19 files changed, 953 insertions(+), 407 deletions(-) + +diff --git a/pcre_jit_compile.c b/pcre_jit_compile.c +index 4dcf8fc..9e67a20 100644 +--- a/pcre_jit_compile.c ++++ b/pcre_jit_compile.c +@@ -549,6 +549,8 @@ the start pointers when the end of the capturing group has not yet reached. */ + sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw)) + #define OP2(op, dst, dstw, src1, src1w, src2, src2w) \ + sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w)) ++#define OP_SRC(op, src, srcw) \ ++ sljit_emit_op_src(compiler, (op), (src), (srcw)) + #define LABEL() \ + sljit_emit_label(compiler) + #define JUMP(type) \ +@@ -3230,7 +3232,7 @@ jump = JUMP(SLJIT_NOT_ZERO); + /* Two byte sequence. */ + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2)); +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + + JUMPHERE(jump); + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); +@@ -3244,7 +3246,7 @@ jump = JUMP(SLJIT_NOT_ZERO); + /* Three byte sequence. */ + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3)); +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + + /* Four byte sequence. */ + JUMPHERE(jump); +@@ -3255,7 +3257,7 @@ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3)); + OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(4)); +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + } + + static void do_utfreadchar16(compiler_common *common) +@@ -3277,7 +3279,7 @@ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); + jump = JUMP(SLJIT_NOT_ZERO); + /* Two byte sequence. */ + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + + JUMPHERE(jump); + OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400); +@@ -3291,7 +3293,7 @@ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); + /* Three byte sequence. */ + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + } + + static void do_utfreadtype8(compiler_common *common) +@@ -3316,18 +3318,18 @@ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); + OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + + JUMPHERE(compare); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + + /* We only have types for characters less than 256. */ + JUMPHERE(jump); + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + } + + #endif /* COMPILE_PCRE8 */ +@@ -3378,7 +3380,7 @@ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2)); + OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + } + #endif + +@@ -4868,7 +4870,7 @@ JUMPHERE(jump); + jump = CMP(SLJIT_NOT_ZERO /* SIG_LESS */, TMP2, 0, SLJIT_IMM, 0); + /* End of reverting values. */ + OP1(SLJIT_MOV, STACK_TOP, 0, TMP3, 0); +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + + JUMPHERE(jump); + OP1(SLJIT_NEG, TMP2, 0, TMP2, 0); +@@ -4984,7 +4986,7 @@ else + set_jumps(skipread_list, LABEL()); + + OP2(SLJIT_XOR | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); +-sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); ++OP_SRC(SLJIT_FAST_RETURN, SLJIT_MEM1(SLJIT_SP), LOCALS0); + } + + static BOOL check_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks) +@@ -5163,7 +5165,7 @@ if (common->utf) + #endif + #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + } + + static void check_hspace(compiler_common *common) +@@ -5202,7 +5204,7 @@ if (common->utf) + #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); + +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + } + + static void check_vspace(compiler_common *common) +@@ -5230,7 +5232,7 @@ if (common->utf) + #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); + +-sljit_emit_fast_return(compiler, RETURN_ADDR, 0); ++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); + } + + static void do_casefulcmp(compiler_common *common) +@@ -5310,7 +5312,7 @@ if (char1_reg == STR_END) + OP1(SLJIT_MOV, char2_reg, 0, RETURN_ADDR, 0); + } + +-sljit_emit_fast_return(compiler, TMP1, 0); ++OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); + } + + static void do_caselesscmp(compiler_common *common) +@@ -5408,7 +5410,7 @@ if (char2_reg == STACK_TOP) + } + + OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); +-sljit_emit_fast_return(compiler, TMP1, 0); ++OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); + } + + #if defined SUPPORT_UTF && defined SUPPORT_UCP +@@ -10221,6 +10223,7 @@ else if (has_alternatives) + return; + sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)next_update_addr); + add_label_addr(common, next_update_addr++); ++ sljit_emit_op0(compiler, SLJIT_ENDBR); + } + else + { +@@ -10352,7 +10355,10 @@ if (has_alternatives) + if (opcode != OP_ONCE) + { + if (alt_max > 4) ++ { + add_label_addr(common, next_update_addr++); ++ sljit_emit_op0(compiler, SLJIT_ENDBR); ++ } + else + { + if (alt_count != 2 * sizeof(sljit_uw)) +@@ -10960,7 +10966,7 @@ else + OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP2, 0); + } +-sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), STACK(-1)); ++OP_SRC(SLJIT_FAST_RETURN, SLJIT_MEM1(STACK_TOP), STACK(-1)); + } + + #undef COMPILE_BACKTRACKINGPATH +@@ -11308,6 +11314,7 @@ if (common->forced_quit != NULL) + set_jumps(common->forced_quit, common->forced_quit_label); + if (minlength_check_failed != NULL) + SET_LABEL(minlength_check_failed, common->forced_quit_label); ++sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); + sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); + + if (mode != JIT_COMPILE) +@@ -11433,7 +11440,7 @@ OP1(SLJIT_MOV, TMP2, 0, STACK_LIMIT, 0); + OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_RETURN_REG, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); +-sljit_emit_fast_return(compiler, TMP1, 0); ++OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); + + /* Allocation failed. */ + JUMPHERE(jump); +diff --git a/sljit/sljitConfig.h b/sljit/sljitConfig.h +index d54b5e6..4560450 100644 +--- a/sljit/sljitConfig.h ++++ b/sljit/sljitConfig.h +@@ -27,6 +27,10 @@ + #ifndef _SLJIT_CONFIG_H_ + #define _SLJIT_CONFIG_H_ + ++#ifdef __cplusplus ++extern "C" { ++#endif ++ + /* --------------------------------------------------------------------- */ + /* Custom defines */ + /* --------------------------------------------------------------------- */ +@@ -65,12 +69,19 @@ + #define SLJIT_UTIL_GLOBAL_LOCK 1 + #endif + +-/* Implements a stack like data structure (by using mmap / VirtualAlloc). */ ++/* Implements a stack like data structure (by using mmap / VirtualAlloc */ ++/* or a custom allocator). */ + #ifndef SLJIT_UTIL_STACK + /* Enabled by default */ + #define SLJIT_UTIL_STACK 1 + #endif + ++/* Uses user provided allocator to allocate the stack (see SLJIT_UTIL_STACK) */ ++#ifndef SLJIT_UTIL_SIMPLE_STACK_ALLOCATION ++/* Disabled by default */ ++#define SLJIT_UTIL_SIMPLE_STACK_ALLOCATION 0 ++#endif ++ + /* Single threaded application. Does not require any locks. */ + #ifndef SLJIT_SINGLE_THREADED + /* Disabled by default. */ +@@ -144,4 +155,8 @@ + + /* For further configurations, see the beginning of sljitConfigInternal.h */ + ++#ifdef __cplusplus ++} /* extern "C" */ ++#endif ++ + #endif +diff --git a/sljit/sljitConfigInternal.h b/sljit/sljitConfigInternal.h +index acba9da..c81b6a4 100644 +--- a/sljit/sljitConfigInternal.h ++++ b/sljit/sljitConfigInternal.h +@@ -27,6 +27,20 @@ + #ifndef _SLJIT_CONFIG_INTERNAL_H_ + #define _SLJIT_CONFIG_INTERNAL_H_ + ++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ ++ || (defined SLJIT_DEBUG && SLJIT_DEBUG && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE))) ++#include ++#endif ++ ++#if (defined SLJIT_DEBUG && SLJIT_DEBUG \ ++ && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) || !defined(SLJIT_HALT_PROCESS))) ++#include ++#endif ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ + /* + SLJIT defines the following architecture dependent types and macros: + +@@ -191,6 +205,24 @@ + #define SLJIT_CONFIG_SPARC 1 + #endif + ++/***********************************************************/ ++/* Intel Control-flow Enforcement Technology (CET) spport. */ ++/***********************************************************/ ++ ++#ifdef SLJIT_CONFIG_X86 ++#if defined(__CET__) ++#define SLJIT_CONFIG_X86_CET 1 ++#endif ++#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) ++#if defined(__GNUC__) ++#if !defined (__SHSTK__) ++#error "-mshstk is needed to compile with -fcf-protection" ++#endif ++#include ++#endif ++#endif ++#endif ++ + /**********************************/ + /* External function definitions. */ + /**********************************/ +@@ -287,7 +319,7 @@ + #if __has_builtin(__builtin___clear_cache) + + #define SLJIT_CACHE_FLUSH(from, to) \ +- __builtin___clear_cache((char*)from, (char*)to) ++ __builtin___clear_cache((char*)(from), (char*)(to)) + + #endif /* __has_builtin(__builtin___clear_cache) */ + #endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */ +@@ -318,7 +350,7 @@ + #elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) + + #define SLJIT_CACHE_FLUSH(from, to) \ +- __builtin___clear_cache((char*)from, (char*)to) ++ __builtin___clear_cache((char*)(from), (char*)(to)) + + #elif defined __ANDROID__ + +@@ -451,6 +483,25 @@ typedef double sljit_f64; + #define SLJIT_BIG_ENDIAN 1 + #endif + ++#ifndef SLJIT_MIPS_REV ++ ++/* Auto detecting mips revision. */ ++#if (defined __mips_isa_rev) && (__mips_isa_rev >= 6) ++#define SLJIT_MIPS_REV 6 ++#elif (defined __mips_isa_rev && __mips_isa_rev >= 1) \ ++ || (defined __clang__ && defined _MIPS_ARCH_OCTEON) \ ++ || (defined __clang__ && defined _MIPS_ARCH_P5600) ++/* clang either forgets to define (clang-7) __mips_isa_rev at all ++ * or sets it to zero (clang-8,-9) for -march=octeon (MIPS64 R2+) ++ * and -march=p5600 (MIPS32 R5). ++ * It also sets the __mips macro to 64 or 32 for -mipsN when N <= 5 ++ * (should be set to N exactly) so we cannot rely on this too. ++ */ ++#define SLJIT_MIPS_REV 1 ++#endif ++ ++#endif /* !SLJIT_MIPS_REV */ ++ + #elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) + + #define SLJIT_BIG_ENDIAN 1 +@@ -679,24 +730,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); + /* Debug and verbose related macros. */ + /*************************************/ + +-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) +-#include +-#endif +- + #if (defined SLJIT_DEBUG && SLJIT_DEBUG) + + #if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) + + /* SLJIT_HALT_PROCESS must halt the process. */ + #ifndef SLJIT_HALT_PROCESS +-#include +- + #define SLJIT_HALT_PROCESS() \ + abort(); + #endif /* !SLJIT_HALT_PROCESS */ + +-#include +- + #endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */ + + /* Feel free to redefine these two macros. */ +@@ -742,4 +785,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); + + #endif /* !SLJIT_COMPILE_ASSERT */ + ++#ifdef __cplusplus ++} /* extern "C" */ ++#endif ++ + #endif +diff --git a/sljit/sljitExecAllocator.c b/sljit/sljitExecAllocator.c +index 92ddb94..7653907 100644 +--- a/sljit/sljitExecAllocator.c ++++ b/sljit/sljitExecAllocator.c +@@ -106,10 +106,10 @@ static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) + + static SLJIT_INLINE int get_map_jit_flag() + { ++/* On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a version ++ of macOS where it's OK to have more than one JIT block. ++ On non-macOS systems, returns MAP_JIT if it is defined. */ + #if TARGET_OS_OSX +- /* On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a version +- of macOS where it's OK to have more than one JIT block. On non-macOS systems, returns +- MAP_JIT if it is defined. */ + static int map_jit_flag = -1; + + /* The following code is thread safe because multiple initialization +@@ -124,12 +124,19 @@ static SLJIT_INLINE int get_map_jit_flag() + /* Kernel version for 10.14.0 (Mojave) */ + if (atoi(name.release) >= 18) { + /* Only use MAP_JIT if a hardened runtime is used, because MAP_JIT is incompatible with fork(). */ +- void *ptr = mmap(NULL, getpagesize(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); ++ ++ /* mirroring page size detection from sljit_allocate_stack */ ++ long page_size = sysconf(_SC_PAGESIZE); ++ /* Should never happen */ ++ if (page_size < 0) ++ page_size = 4096; ++ ++ void *ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0); + + if (ptr == MAP_FAILED) { + map_jit_flag = MAP_JIT; + } else { +- munmap(ptr, getpagesize()); ++ munmap(ptr, page_size); + } + } + } +diff --git a/sljit/sljitLir.c b/sljit/sljitLir.c +index 9bab0c3..86772cc 100644 +--- a/sljit/sljitLir.c ++++ b/sljit/sljitLir.c +@@ -926,7 +926,8 @@ static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, s + + static const char* op0_names[] = { + (char*)"breakpoint", (char*)"nop", (char*)"lmul.uw", (char*)"lmul.sw", +- (char*)"divmod.u", (char*)"divmod.s", (char*)"div.u", (char*)"div.s" ++ (char*)"divmod.u", (char*)"divmod.s", (char*)"div.u", (char*)"div.s", ++ (char*)"endbr", (char*)"skip_frames_before_return" + }; + + static const char* op1_names[] = { +@@ -943,6 +944,12 @@ static const char* op2_names[] = { + (char*)"shl", (char*)"lshr", (char*)"ashr", + }; + ++static const char* op_src_names[] = { ++ (char*)"fast_return", (char*)"skip_frames_before_fast_return", ++ (char*)"prefetch_l1", (char*)"prefetch_l2", ++ (char*)"prefetch_l3", (char*)"prefetch_once", ++}; ++ + static const char* fop1_names[] = { + (char*)"mov", (char*)"conv", (char*)"conv", (char*)"conv", + (char*)"conv", (char*)"conv", (char*)"cmp", (char*)"neg", +@@ -1152,37 +1159,21 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_enter(struct sljit_c + CHECK_RETURN_OK; + } + +-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) +-{ +-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) +- FUNCTION_CHECK_SRC(src, srcw); +- CHECK_ARGUMENT(src != SLJIT_IMM); +- compiler->last_flags = 0; +-#endif +-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) +- if (SLJIT_UNLIKELY(!!compiler->verbose)) { +- fprintf(compiler->verbose, " fast_return "); +- sljit_verbose_param(compiler, src, srcw); +- fprintf(compiler->verbose, "\n"); +- } +-#endif +- CHECK_RETURN_OK; +-} +- + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) + { + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW) +- || ((op & ~SLJIT_I32_OP) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_I32_OP) <= SLJIT_DIV_SW)); +- CHECK_ARGUMENT(op < SLJIT_LMUL_UW || compiler->scratches >= 2); +- if (op >= SLJIT_LMUL_UW) ++ || ((op & ~SLJIT_I32_OP) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_I32_OP) <= SLJIT_DIV_SW) ++ || (op >= SLJIT_ENDBR && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN)); ++ CHECK_ARGUMENT(GET_OPCODE(op) < SLJIT_LMUL_UW || GET_OPCODE(op) >= SLJIT_ENDBR || compiler->scratches >= 2); ++ if ((GET_OPCODE(op) >= SLJIT_LMUL_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN) + compiler->last_flags = 0; + #endif + #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) + { + fprintf(compiler->verbose, " %s", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]); +- if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW) { ++ if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) { + fprintf(compiler->verbose, (op & SLJIT_I32_OP) ? "32" : "w"); + } + fprintf(compiler->verbose, "\n"); +@@ -1224,7 +1215,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler + break; + } + +- FUNCTION_CHECK_DST(dst, dstw, 1); ++ FUNCTION_CHECK_DST(dst, dstw, HAS_FLAGS(op)); + FUNCTION_CHECK_SRC(src, srcw); + + if (GET_OPCODE(op) >= SLJIT_NOT) { +@@ -1304,7 +1295,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler + break; + } + +- FUNCTION_CHECK_DST(dst, dstw, 1); ++ FUNCTION_CHECK_DST(dst, dstw, HAS_FLAGS(op)); + FUNCTION_CHECK_SRC(src1, src1w); + FUNCTION_CHECK_SRC(src2, src2w); + compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z)); +@@ -1325,6 +1316,33 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler + CHECK_RETURN_OK; + } + ++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, ++ sljit_s32 src, sljit_sw srcw) ++{ ++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) ++ CHECK_ARGUMENT(op >= SLJIT_FAST_RETURN && op <= SLJIT_PREFETCH_ONCE); ++ FUNCTION_CHECK_SRC(src, srcw); ++ ++ if (op == SLJIT_FAST_RETURN || op == SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN) ++ { ++ CHECK_ARGUMENT(src != SLJIT_IMM); ++ compiler->last_flags = 0; ++ } ++ else if (op >= SLJIT_PREFETCH_L1 && op <= SLJIT_PREFETCH_ONCE) ++ { ++ CHECK_ARGUMENT(src & SLJIT_MEM); ++ } ++#endif ++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) ++ if (SLJIT_UNLIKELY(!!compiler->verbose)) { ++ fprintf(compiler->verbose, " %s ", op_src_names[op - SLJIT_OP_SRC_BASE]); ++ sljit_verbose_param(compiler, src, srcw); ++ fprintf(compiler->verbose, "\n"); ++ } ++#endif ++ CHECK_RETURN_OK; ++} ++ + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 reg) + { + SLJIT_UNUSED_ARG(reg); +@@ -2016,7 +2034,7 @@ static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *comp + #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ + || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ + || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ +- || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)) ++ || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)) + + static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, +@@ -2381,15 +2399,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * + return SLJIT_ERR_UNSUPPORTED; + } + +-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) +-{ +- SLJIT_UNUSED_ARG(compiler); +- SLJIT_UNUSED_ARG(src); +- SLJIT_UNUSED_ARG(srcw); +- SLJIT_UNREACHABLE(); +- return SLJIT_ERR_UNSUPPORTED; +-} +- + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) + { + SLJIT_UNUSED_ARG(compiler); +@@ -2429,6 +2438,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile + return SLJIT_ERR_UNSUPPORTED; + } + ++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, ++ sljit_s32 src, sljit_sw srcw) ++{ ++ SLJIT_UNUSED_ARG(compiler); ++ SLJIT_UNUSED_ARG(op); ++ SLJIT_UNUSED_ARG(src); ++ SLJIT_UNUSED_ARG(srcw); ++ SLJIT_UNREACHABLE(); ++ return SLJIT_ERR_UNSUPPORTED; ++} ++ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) + { + SLJIT_UNREACHABLE(); +@@ -2549,6 +2569,13 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw + SLJIT_UNREACHABLE(); + } + ++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label) ++{ ++ SLJIT_UNUSED_ARG(put_label); ++ SLJIT_UNUSED_ARG(label); ++ SLJIT_UNREACHABLE(); ++} ++ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) + { + SLJIT_UNUSED_ARG(compiler); +diff --git a/sljit/sljitLir.h b/sljit/sljitLir.h +index 836d25c..aef90e6 100644 +--- a/sljit/sljitLir.h ++++ b/sljit/sljitLir.h +@@ -80,6 +80,10 @@ of sljitConfigInternal.h */ + + #include "sljitConfigInternal.h" + ++#ifdef __cplusplus ++extern "C" { ++#endif ++ + /* --------------------------------------------------------------------- */ + /* Error codes */ + /* --------------------------------------------------------------------- */ +@@ -154,10 +158,10 @@ of sljitConfigInternal.h */ + */ + + /* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1 +- or sljit_emit_op2 operations the result is discarded. If no status +- flags are set, no instructions are emitted for these operations. Data +- prefetch is a special exception, see SLJIT_MOV operation. Other SLJIT +- operations do not support SLJIT_UNUSED as a destination operand. */ ++ or sljit_emit_op2 operations the result is discarded. Some status ++ flags must be set when the destination is SLJIT_UNUSED, because the ++ operation would have no effect otherwise. Other SLJIT operations do ++ not support SLJIT_UNUSED as a destination operand. */ + #define SLJIT_UNUSED 0 + + /* Scratch registers. */ +@@ -571,6 +575,8 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler + #define SLJIT_HAS_CLZ 2 + /* [Emulated] Conditional move is supported. */ + #define SLJIT_HAS_CMOV 3 ++/* [Emulated] Conditional move is supported. */ ++#define SLJIT_HAS_PREFETCH 4 + + #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) + /* [Not emulated] SSE2 support is available on x86. */ +@@ -658,10 +664,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp + sljit_s32 src, sljit_sw srcw); + + /* Generating entry and exit points for fast call functions (see SLJIT_FAST_CALL). +- Both sljit_emit_fast_enter and sljit_emit_fast_return functions preserve the ++ Both sljit_emit_fast_enter and SLJIT_FAST_RETURN operations preserve the + values of all registers and stack frame. The return address is stored in the + dst argument of sljit_emit_fast_enter, and this return address can be passed +- to sljit_emit_fast_return to continue the execution after the fast call. ++ to SLJIT_FAST_RETURN to continue the execution after the fast call. + + Fast calls are cheap operations (usually only a single call instruction is + emitted) but they do not preserve any registers. However the callee function +@@ -669,16 +675,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp + efficiently exploited by various optimizations. Registers can be saved + manually by the callee function if needed. + +- Although returning to different address by sljit_emit_fast_return is possible, ++ Although returning to different address by SLJIT_FAST_RETURN is possible, + this address usually cannot be predicted by the return address predictor of +- modern CPUs which may reduce performance. Furthermore using sljit_emit_ijump +- to return is also inefficient since return address prediction is usually +- triggered by a specific form of ijump. ++ modern CPUs which may reduce performance. Furthermore certain security ++ enhancement technologies such as Intel Control-flow Enforcement Technology ++ (CET) may disallow returning to a different address. + + Flags: - (does not modify flags). */ + + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw); +-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw); + + /* + Source and destination operands for arithmetical instructions +@@ -887,6 +892,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler + the behaviour is undefined. */ + #define SLJIT_DIV_SW (SLJIT_OP0_BASE + 7) + #define SLJIT_DIV_S32 (SLJIT_DIV_SW | SLJIT_I32_OP) ++/* Flags: - (does not modify flags) ++ ENDBR32 instruction for x86-32 and ENDBR64 instruction for x86-64 ++ when Intel Control-flow Enforcement Technology (CET) is enabled. ++ No instruction for other architectures. */ ++#define SLJIT_ENDBR (SLJIT_OP0_BASE + 8) ++/* Flags: - (may destroy flags) ++ Skip stack frames before return. */ ++#define SLJIT_SKIP_FRAMES_BEFORE_RETURN (SLJIT_OP0_BASE + 9) + + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op); + +@@ -904,15 +917,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + U32 - unsigned int (32 bit) data transfer + S32 - signed int (32 bit) data transfer + P - pointer (sljit_p) data transfer +- +- If the destination of a MOV instruction is SLJIT_UNUSED and the source +- operand is a memory address the compiler emits a prefetch instruction +- if this instruction is supported by the current CPU. Higher data sizes +- bring the data closer to the core: a MOV with word size loads the data +- into a higher level cache than a byte size. Otherwise the type does not +- affect the prefetch instruction. Furthermore a prefetch instruction +- never fails, so it can be used to prefetch a data from an address and +- check whether that address is NULL afterwards. + */ + + /* Flags: - (does not modify flags) */ +@@ -1017,8 +1021,46 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w); + ++/* Starting index of opcodes for sljit_emit_op2. */ ++#define SLJIT_OP_SRC_BASE 128 ++ ++/* Note: src cannot be an immedate value ++ Flags: - (does not modify flags) */ ++#define SLJIT_FAST_RETURN (SLJIT_OP_SRC_BASE + 0) ++/* Skip stack frames before fast return. ++ Note: src cannot be an immedate value ++ Flags: may destroy flags. */ ++#define SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN (SLJIT_OP_SRC_BASE + 1) ++/* Prefetch value into the level 1 data cache ++ Note: if the target CPU does not support data prefetch, ++ no instructions are emitted. ++ Note: this instruction never fails, even if the memory address is invalid. ++ Flags: - (does not modify flags) */ ++#define SLJIT_PREFETCH_L1 (SLJIT_OP_SRC_BASE + 2) ++/* Prefetch value into the level 2 data cache ++ Note: same as SLJIT_PREFETCH_L1 if the target CPU ++ does not support this instruction form. ++ Note: this instruction never fails, even if the memory address is invalid. ++ Flags: - (does not modify flags) */ ++#define SLJIT_PREFETCH_L2 (SLJIT_OP_SRC_BASE + 3) ++/* Prefetch value into the level 3 data cache ++ Note: same as SLJIT_PREFETCH_L2 if the target CPU ++ does not support this instruction form. ++ Note: this instruction never fails, even if the memory address is invalid. ++ Flags: - (does not modify flags) */ ++#define SLJIT_PREFETCH_L3 (SLJIT_OP_SRC_BASE + 4) ++/* Prefetch a value which is only used once (and can be discarded afterwards) ++ Note: same as SLJIT_PREFETCH_L1 if the target CPU ++ does not support this instruction form. ++ Note: this instruction never fails, even if the memory address is invalid. ++ Flags: - (does not modify flags) */ ++#define SLJIT_PREFETCH_ONCE (SLJIT_OP_SRC_BASE + 5) ++ ++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, ++ sljit_s32 src, sljit_sw srcw); ++ + /* Starting index of opcodes for sljit_emit_fop1. */ +-#define SLJIT_FOP1_BASE 128 ++#define SLJIT_FOP1_BASE 160 + + /* Flags: - (does not modify flags) */ + #define SLJIT_MOV_F64 (SLJIT_FOP1_BASE + 0) +@@ -1057,7 +1099,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil + sljit_s32 src, sljit_sw srcw); + + /* Starting index of opcodes for sljit_emit_fop2. */ +-#define SLJIT_FOP2_BASE 160 ++#define SLJIT_FOP2_BASE 192 + + /* Flags: - (does not modify flags) */ + #define SLJIT_ADD_F64 (SLJIT_FOP2_BASE + 0) +@@ -1161,7 +1203,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi + + /* Unconditional jump types. */ + #define SLJIT_JUMP 24 +- /* Fast calling method. See sljit_emit_fast_enter / sljit_emit_fast_return. */ ++ /* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */ + #define SLJIT_FAST_CALL 25 + /* Called function must be declared with the SLJIT_FUNC attribute. */ + #define SLJIT_CALL 26 +@@ -1490,4 +1532,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c + SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, + sljit_s32 current_flags); + ++#ifdef __cplusplus ++} /* extern "C" */ ++#endif ++ + #endif /* _SLJIT_LIR_H_ */ +diff --git a/sljit/sljitNativeARM_32.c b/sljit/sljitNativeARM_32.c +index 8da0d09..24ef02a 100644 +--- a/sljit/sljitNativeARM_32.c ++++ b/sljit/sljitNativeARM_32.c +@@ -872,6 +872,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) + + case SLJIT_HAS_CLZ: + case SLJIT_HAS_CMOV: ++#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) ++ case SLJIT_HAS_PREFETCH: ++#endif + return 1; + + default: +@@ -1678,6 +1681,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */); + } + return SLJIT_SUCCESS; ++ case SLJIT_ENDBR: ++ case SLJIT_SKIP_FRAMES_BEFORE_RETURN: ++ return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; +@@ -1692,14 +1698,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src, srcw); + +- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { +-#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) +- if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) +- return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1); +-#endif +- return SLJIT_SUCCESS; +- } +- + switch (GET_OPCODE(op)) { + case SLJIT_MOV: + case SLJIT_MOV_U32: +@@ -1781,6 +1779,40 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile + return SLJIT_SUCCESS; + } + ++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, ++ sljit_s32 src, sljit_sw srcw) ++{ ++ CHECK_ERROR(); ++ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); ++ ADJUST_LOCAL_OFFSET(src, srcw); ++ ++ switch (op) { ++ case SLJIT_FAST_RETURN: ++ SLJIT_ASSERT(reg_map[TMP_REG2] == 14); ++ ++ if (FAST_IS_REG(src)) ++ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src))); ++ else ++ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1)); ++ ++ return push_inst(compiler, BX | RM(TMP_REG2)); ++ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: ++ return SLJIT_SUCCESS; ++ case SLJIT_PREFETCH_L1: ++ case SLJIT_PREFETCH_L2: ++ case SLJIT_PREFETCH_L3: ++ case SLJIT_PREFETCH_ONCE: ++#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) ++ SLJIT_ASSERT(src & SLJIT_MEM); ++ return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1); ++#else /* !SLJIT_CONFIG_ARM_V7 */ ++ return SLJIT_SUCCESS; ++#endif /* SLJIT_CONFIG_ARM_V7 */ ++ } ++ ++ return SLJIT_SUCCESS; ++} ++ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) + { + CHECK_REG_INDEX(check_sljit_get_register_index(reg)); +@@ -2043,22 +2075,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * + return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1); + } + +-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) +-{ +- CHECK_ERROR(); +- CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); +- ADJUST_LOCAL_OFFSET(src, srcw); +- +- SLJIT_ASSERT(reg_map[TMP_REG2] == 14); +- +- if (FAST_IS_REG(src)) +- FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src))); +- else +- FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1)); +- +- return push_inst(compiler, BX | RM(TMP_REG2)); +-} +- + /* --------------------------------------------------------------------- */ + /* Conditional instructions */ + /* --------------------------------------------------------------------- */ +diff --git a/sljit/sljitNativeARM_64.c b/sljit/sljitNativeARM_64.c +index e15b345..b86fc64 100644 +--- a/sljit/sljitNativeARM_64.c ++++ b/sljit/sljitNativeARM_64.c +@@ -396,6 +396,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) + + case SLJIT_HAS_CLZ: + case SLJIT_HAS_CMOV: ++ case SLJIT_HAS_PREFETCH: + return 1; + + default: +@@ -1154,6 +1155,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + case SLJIT_DIV_UW: + case SLJIT_DIV_SW: + return push_inst(compiler, ((op == SLJIT_DIV_UW ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)); ++ case SLJIT_ENDBR: ++ case SLJIT_SKIP_FRAMES_BEFORE_RETURN: ++ return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; +@@ -1171,23 +1175,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src, srcw); + +- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { +- if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) { +- SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4); +- +- if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8) +- dst = 5; +- else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16) +- dst = 3; +- else +- dst = 1; +- +- /* Signed word sized load is the prefetch instruction. */ +- return emit_op_mem(compiler, WORD_SIZE | SIGNED, dst, src, srcw, TMP_REG1); +- } +- return SLJIT_SUCCESS; +- } +- + dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; + + op = GET_OPCODE(op); +@@ -1327,6 +1314,46 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile + return SLJIT_SUCCESS; + } + ++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, ++ sljit_s32 src, sljit_sw srcw) ++{ ++ CHECK_ERROR(); ++ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); ++ ADJUST_LOCAL_OFFSET(src, srcw); ++ ++ switch (op) { ++ case SLJIT_FAST_RETURN: ++ if (FAST_IS_REG(src)) ++ FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src))); ++ else ++ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1)); ++ ++ return push_inst(compiler, RET | RN(TMP_LR)); ++ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: ++ return SLJIT_SUCCESS; ++ case SLJIT_PREFETCH_L1: ++ case SLJIT_PREFETCH_L2: ++ case SLJIT_PREFETCH_L3: ++ case SLJIT_PREFETCH_ONCE: ++ SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4); ++ ++ /* The reg_map[op] should provide the appropriate constant. */ ++ if (op == SLJIT_PREFETCH_L1) ++ op = 1; ++ else if (op == SLJIT_PREFETCH_L2) ++ op = 3; ++ else if (op == SLJIT_PREFETCH_L3) ++ op = 5; ++ else ++ op = 2; ++ ++ /* Signed word sized load is the prefetch instruction. */ ++ return emit_op_mem(compiler, WORD_SIZE | SIGNED, op, src, srcw, TMP_REG1); ++ } ++ ++ return SLJIT_SUCCESS; ++} ++ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) + { + CHECK_REG_INDEX(check_sljit_get_register_index(reg)); +@@ -1578,20 +1605,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * + return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_LR, dst, dstw, TMP_REG1); + } + +-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) +-{ +- CHECK_ERROR(); +- CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); +- ADJUST_LOCAL_OFFSET(src, srcw); +- +- if (FAST_IS_REG(src)) +- FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src))); +- else +- FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1)); +- +- return push_inst(compiler, RET | RN(TMP_LR)); +-} +- + /* --------------------------------------------------------------------- */ + /* Conditional instructions */ + /* --------------------------------------------------------------------- */ +diff --git a/sljit/sljitNativeARM_T2_32.c b/sljit/sljitNativeARM_T2_32.c +index cdfe4a4..a26f48f 100644 +--- a/sljit/sljitNativeARM_T2_32.c ++++ b/sljit/sljitNativeARM_T2_32.c +@@ -480,6 +480,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) + + case SLJIT_HAS_CLZ: + case SLJIT_HAS_CMOV: ++ case SLJIT_HAS_PREFETCH: + return 1; + + default: +@@ -1328,6 +1329,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + } + return SLJIT_SUCCESS; + #endif /* __ARM_FEATURE_IDIV || __ARM_ARCH_EXT_IDIV__ */ ++ case SLJIT_ENDBR: ++ case SLJIT_SKIP_FRAMES_BEFORE_RETURN: ++ return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; +@@ -1345,13 +1349,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src, srcw); + +- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { +- /* Since TMP_PC has index 15, IS_2_LO_REGS and IS_3_LO_REGS checks always fail. */ +- if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) +- return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1); +- return SLJIT_SUCCESS; +- } +- + dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; + + op = GET_OPCODE(op); +@@ -1475,6 +1472,35 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile + return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG2); + } + ++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, ++ sljit_s32 src, sljit_sw srcw) ++{ ++ CHECK_ERROR(); ++ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); ++ ADJUST_LOCAL_OFFSET(src, srcw); ++ ++ switch (op) { ++ case SLJIT_FAST_RETURN: ++ SLJIT_ASSERT(reg_map[TMP_REG2] == 14); ++ ++ if (FAST_IS_REG(src)) ++ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src))); ++ else ++ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2)); ++ ++ return push_inst16(compiler, BX | RN3(TMP_REG2)); ++ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: ++ return SLJIT_SUCCESS; ++ case SLJIT_PREFETCH_L1: ++ case SLJIT_PREFETCH_L2: ++ case SLJIT_PREFETCH_L3: ++ case SLJIT_PREFETCH_ONCE: ++ return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1); ++ } ++ ++ return SLJIT_SUCCESS; ++} ++ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) + { + CHECK_REG_INDEX(check_sljit_get_register_index(reg)); +@@ -1728,22 +1754,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * + return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1); + } + +-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) +-{ +- CHECK_ERROR(); +- CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); +- ADJUST_LOCAL_OFFSET(src, srcw); +- +- SLJIT_ASSERT(reg_map[TMP_REG2] == 14); +- +- if (FAST_IS_REG(src)) +- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src))); +- else +- FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2)); +- +- return push_inst16(compiler, BX | RN3(TMP_REG2)); +-} +- + /* --------------------------------------------------------------------- */ + /* Conditional instructions */ + /* --------------------------------------------------------------------- */ +diff --git a/sljit/sljitNativeMIPS_32.c b/sljit/sljitNativeMIPS_32.c +index 16dec05..777627b 100644 +--- a/sljit/sljitNativeMIPS_32.c ++++ b/sljit/sljitNativeMIPS_32.c +@@ -86,12 +86,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + if (op == SLJIT_MOV_S8) { +-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst)); +-#else ++#else /* SLJIT_MIPS_REV < 1 */ + FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst))); + return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst)); +-#endif ++#endif /* SLJIT_MIPS_REV >= 1 */ + } + return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); + } +@@ -105,12 +105,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + if (op == SLJIT_MOV_S16) { +-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst)); +-#else ++#else /* SLJIT_MIPS_REV < 1 */ + FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst))); + return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst)); +-#endif ++#endif /* SLJIT_MIPS_REV >= 1 */ + } + return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); + } +@@ -129,12 +129,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl + + case SLJIT_CLZ: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); +-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); + if (!(flags & UNUSED_DEST)) + FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst))); +-#else ++#else /* SLJIT_MIPS_REV < 1 */ + if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { + FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG)); + return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG); +@@ -149,7 +149,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl + FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst))); + FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); +-#endif ++#endif /* SLJIT_MIPS_REV >= 1 */ + return SLJIT_SUCCESS; + + case SLJIT_ADD: +@@ -368,21 +368,22 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl + SLJIT_ASSERT(!(flags & SRC2_IMM)); + + if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) { +-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) || (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); +-#else /* !SLJIT_MIPS_R1 && !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 1 */ + FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); + return push_inst(compiler, MFLO | D(dst), DR(dst)); +-#endif /* SLJIT_MIPS_R1 || SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 1 */ + } +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++ ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + FAIL_IF(push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst))); + FAIL_IF(push_inst(compiler, MUH | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); +-#else /* !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 6 */ + FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); + return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); + +diff --git a/sljit/sljitNativeMIPS_64.c b/sljit/sljitNativeMIPS_64.c +index a6a2bcc..479244d 100644 +--- a/sljit/sljitNativeMIPS_64.c ++++ b/sljit/sljitNativeMIPS_64.c +@@ -220,12 +220,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl + + case SLJIT_CLZ: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); +-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); + if (!(flags & UNUSED_DEST)) + FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst))); +-#else ++#else /* SLJIT_MIPS_REV < 1 */ + if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { + FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG)); + return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG); +@@ -240,7 +240,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst))); + FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); +-#endif ++#endif /* SLJIT_MIPS_REV >= 1 */ + return SLJIT_SUCCESS; + + case SLJIT_ADD: +@@ -459,26 +459,27 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl + SLJIT_ASSERT(!(flags & SRC2_IMM)); + + if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) { +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)); +-#elif (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) ++#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + if (op & SLJIT_I32_OP) + return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); + FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS)); + return push_inst(compiler, MFLO | D(dst), DR(dst)); +-#else /* !SLJIT_MIPS_R6 && !SLJIT_MIPS_R1 */ ++#else /* SLJIT_MIPS_REV < 1 */ + FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); + return push_inst(compiler, MFLO | D(dst), DR(dst)); +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + } +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++ ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst))); + FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); +-#else /* !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 6 */ + FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); + return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); + +diff --git a/sljit/sljitNativeMIPS_common.c b/sljit/sljitNativeMIPS_common.c +index 7d1d087..7628be6 100644 +--- a/sljit/sljitNativeMIPS_common.c ++++ b/sljit/sljitNativeMIPS_common.c +@@ -25,15 +25,16 @@ + */ + + /* Latest MIPS architecture. */ +-/* Automatically detect SLJIT_MIPS_R1 */ + +-#if (defined __mips_isa_rev) && (__mips_isa_rev >= 6) +-#define SLJIT_MIPS_R6 1 ++#ifndef __mips_hard_float ++/* Disable automatic detection, covers both -msoft-float and -mno-float */ ++#undef SLJIT_IS_FPU_AVAILABLE ++#define SLJIT_IS_FPU_AVAILABLE 0 + #endif + + SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) + { +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + + #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + return "MIPS32-R6" SLJIT_CPUINFO; +@@ -41,7 +42,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) + return "MIPS64-R6" SLJIT_CPUINFO; + #endif /* SLJIT_CONFIG_MIPS_32 */ + +-#elif (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) ++#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + + #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + return "MIPS32-R1" SLJIT_CPUINFO; +@@ -49,9 +50,9 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) + return "MIPS64-R1" SLJIT_CPUINFO; + #endif /* SLJIT_CONFIG_MIPS_32 */ + +-#else /* SLJIT_MIPS_R1 */ ++#else /* SLJIT_MIPS_REV < 1 */ + return "MIPS III" SLJIT_CPUINFO; +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + } + + /* Length of an instruction word +@@ -117,11 +118,11 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { + #define FR(dr) (freg_map[dr]) + #define HI(opcode) ((opcode) << 26) + #define LO(opcode) (opcode) +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + /* CMP.cond.fmt */ + /* S = (20 << 21) D = (21 << 21) */ + #define CMP_FMT_S (20 << 21) +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + /* S = (16 << 21) D = (17 << 21) */ + #define FMT_S (16 << 21) + #define FMT_D (17 << 21) +@@ -134,13 +135,13 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { + #define ANDI (HI(12)) + #define B (HI(4)) + #define BAL (HI(1) | (17 << 16)) +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + #define BC1EQZ (HI(17) | (9 << 21) | FT(TMP_FREG3)) + #define BC1NEZ (HI(17) | (13 << 21) | FT(TMP_FREG3)) +-#else /* !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 6 */ + #define BC1F (HI(17) | (8 << 21)) + #define BC1T (HI(17) | (8 << 21) | (1 << 16)) +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + #define BEQ (HI(4)) + #define BGEZ (HI(1) | (1 << 16)) + #define BGTZ (HI(7)) +@@ -149,23 +150,23 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { + #define BNE (HI(5)) + #define BREAK (HI(0) | LO(13)) + #define CFC1 (HI(17) | (2 << 21)) +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + #define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3)) + #define C_ULE_S (HI(17) | CMP_FMT_S | LO(7)) + #define C_ULT_S (HI(17) | CMP_FMT_S | LO(5)) + #define C_UN_S (HI(17) | CMP_FMT_S | LO(1)) + #define C_FD (FD(TMP_FREG3)) +-#else /* !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 6 */ + #define C_UEQ_S (HI(17) | FMT_S | LO(51)) + #define C_ULE_S (HI(17) | FMT_S | LO(55)) + #define C_ULT_S (HI(17) | FMT_S | LO(53)) + #define C_UN_S (HI(17) | FMT_S | LO(49)) + #define C_FD (0) +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + #define CVT_S_S (HI(17) | FMT_S | LO(32)) + #define DADDIU (HI(25)) + #define DADDU (HI(0) | LO(45)) +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + #define DDIV (HI(0) | (2 << 6) | LO(30)) + #define DDIVU (HI(0) | (2 << 6) | LO(31)) + #define DMOD (HI(0) | (3 << 6) | LO(30)) +@@ -176,14 +177,14 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { + #define DMUHU (HI(0) | (3 << 6) | LO(29)) + #define DMUL (HI(0) | (2 << 6) | LO(28)) + #define DMULU (HI(0) | (2 << 6) | LO(29)) +-#else /* !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 6 */ + #define DDIV (HI(0) | LO(30)) + #define DDIVU (HI(0) | LO(31)) + #define DIV (HI(0) | LO(26)) + #define DIVU (HI(0) | LO(27)) + #define DMULT (HI(0) | LO(28)) + #define DMULTU (HI(0) | LO(29)) +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + #define DIV_S (HI(17) | FMT_S | LO(3)) + #define DSLL (HI(0) | LO(56)) + #define DSLL32 (HI(0) | LO(60)) +@@ -198,33 +199,33 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { + #define J (HI(2)) + #define JAL (HI(3)) + #define JALR (HI(0) | LO(9)) +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + #define JR (HI(0) | LO(9)) +-#else /* !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 6 */ + #define JR (HI(0) | LO(8)) +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + #define LD (HI(55)) + #define LUI (HI(15)) + #define LW (HI(35)) + #define MFC1 (HI(17)) +-#if !(defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +-#define MFHI (HI(0) | LO(16)) +-#define MFLO (HI(0) | LO(18)) +-#else /* SLJIT_MIPS_R6 */ ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + #define MOD (HI(0) | (3 << 6) | LO(26)) + #define MODU (HI(0) | (3 << 6) | LO(27)) +-#endif /* !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 6 */ ++#define MFHI (HI(0) | LO(16)) ++#define MFLO (HI(0) | LO(18)) ++#endif /* SLJIT_MIPS_REV >= 6 */ + #define MOV_S (HI(17) | FMT_S | LO(6)) + #define MTC1 (HI(17) | (4 << 21)) +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + #define MUH (HI(0) | (3 << 6) | LO(24)) + #define MUHU (HI(0) | (3 << 6) | LO(25)) + #define MUL (HI(0) | (2 << 6) | LO(24)) + #define MULU (HI(0) | (2 << 6) | LO(25)) +-#else /* !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 6 */ + #define MULT (HI(0) | LO(24)) + #define MULTU (HI(0) | LO(25)) +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + #define MUL_S (HI(17) | FMT_S | LO(2)) + #define NEG_S (HI(17) | FMT_S | LO(7)) + #define NOP (HI(0) | LO(0)) +@@ -251,23 +252,23 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { + #define XOR (HI(0) | LO(38)) + #define XORI (HI(14)) + +-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) || (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + #define CLZ (HI(28) | LO(32)) +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + #define DCLZ (LO(18)) +-#else /* !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 6 */ + #define DCLZ (HI(28) | LO(36)) + #define MOVF (HI(0) | (0 << 16) | LO(1)) + #define MOVN (HI(0) | LO(11)) + #define MOVT (HI(0) | (1 << 16) | LO(1)) + #define MOVZ (HI(0) | LO(10)) + #define MUL (HI(28) | LO(2)) +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + #define PREF (HI(51)) + #define PREFX (HI(19) | LO(15)) + #define SEB (HI(31) | (16 << 6) | LO(32)) + #define SEH (HI(31) | (24 << 6) | LO(32)) +-#endif ++#endif /* SLJIT_MIPS_REV >= 1 */ + + #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + #define ADDU_W ADDU +@@ -303,10 +304,10 @@ static SLJIT_INLINE sljit_ins invert_branch(sljit_s32 flags) + { + if (flags & IS_BIT26_COND) + return (1 << 26); +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + if (flags & IS_BIT23_COND) + return (1 << 23); +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + return (1 << 16); + } + +@@ -684,11 +685,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) + #error "FIR check is not implemented for this architecture" + #endif + +-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + case SLJIT_HAS_CLZ: + case SLJIT_HAS_CMOV: ++ case SLJIT_HAS_PREFETCH: + return 1; +-#endif ++#endif /* SLJIT_MIPS_REV >= 1 */ + + default: + return fir; +@@ -1230,7 +1232,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + return push_inst(compiler, NOP, UNMOVABLE_INS); + case SLJIT_LMUL_UW: + case SLJIT_LMUL_SW: +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3))); + FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1))); +@@ -1240,7 +1242,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + #endif /* SLJIT_CONFIG_MIPS_64 */ + FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0))); + return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1)); +-#else /* !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 6 */ + #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + #else /* !SLJIT_CONFIG_MIPS_64 */ +@@ -1248,13 +1250,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + #endif /* SLJIT_CONFIG_MIPS_64 */ + FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); + return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + case SLJIT_DIVMOD_UW: + case SLJIT_DIVMOD_SW: + case SLJIT_DIV_UW: + case SLJIT_DIV_SW: + SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments); +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (int_op) { + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3))); +@@ -1270,11 +1272,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + #endif /* SLJIT_CONFIG_MIPS_64 */ + FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0))); + return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1)); +-#else /* !SLJIT_MIPS_R6 */ +-#if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) ++#else /* SLJIT_MIPS_REV < 6 */ ++#if !(defined SLJIT_MIPS_REV) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +-#endif /* !SLJIT_MIPS_R1 */ ++#endif /* !SLJIT_MIPS_REV */ + #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (int_op) + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); +@@ -1285,13 +1287,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + #endif /* SLJIT_CONFIG_MIPS_64 */ + FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); + return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ ++ case SLJIT_ENDBR: ++ case SLJIT_SKIP_FRAMES_BEFORE_RETURN: ++ return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; + } + +-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) + { +@@ -1312,7 +1317,7 @@ static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, + + return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS); + } +-#endif ++#endif /* SLJIT_MIPS_REV >= 1 */ + + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, +@@ -1329,14 +1334,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src, srcw); + +- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { +-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +- if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) +- return emit_prefetch(compiler, src, srcw); +-#endif +- return SLJIT_SUCCESS; +- } +- + #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT) + flags |= INT_DATA | SIGNED_DATA; +@@ -1463,6 +1460,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile + #endif + } + ++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, ++ sljit_s32 src, sljit_sw srcw) ++{ ++ CHECK_ERROR(); ++ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); ++ ADJUST_LOCAL_OFFSET(src, srcw); ++ ++ switch (op) { ++ case SLJIT_FAST_RETURN: ++ if (FAST_IS_REG(src)) ++ FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG)); ++ else ++ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw)); ++ ++ FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS)); ++ return push_inst(compiler, NOP, UNMOVABLE_INS); ++ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: ++ return SLJIT_SUCCESS; ++ case SLJIT_PREFETCH_L1: ++ case SLJIT_PREFETCH_L2: ++ case SLJIT_PREFETCH_L3: ++ case SLJIT_PREFETCH_ONCE: ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) ++ return emit_prefetch(compiler, src, srcw); ++#else /* SLJIT_MIPS_REV < 1 */ ++ return SLJIT_SUCCESS; ++#endif /* SLJIT_MIPS_REV >= 1 */ ++ } ++ ++ return SLJIT_SUCCESS; ++} ++ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) + { + CHECK_REG_INDEX(check_sljit_get_register_index(reg)); +@@ -1732,25 +1761,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * + ADJUST_LOCAL_OFFSET(dst, dstw); + + if (FAST_IS_REG(dst)) +- return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), DR(dst)); ++ return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS); + + /* Memory. */ +- return emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw); +-} +- +-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) +-{ +- CHECK_ERROR(); +- CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); +- ADJUST_LOCAL_OFFSET(src, srcw); +- +- if (FAST_IS_REG(src)) +- FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG)); +- else +- FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw)); +- +- FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS)); +- return push_inst(compiler, NOP, UNMOVABLE_INS); ++ FAIL_IF(emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw)); ++ compiler->delay_slot = UNMOVABLE_INS; ++ return SLJIT_SUCCESS; + } + + /* --------------------------------------------------------------------- */ +@@ -1790,7 +1806,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi + flags = IS_BIT26_COND; \ + delay_check = src; + +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + + #define BR_T() \ + inst = BC1NEZ; \ +@@ -1801,7 +1817,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi + flags = IS_BIT23_COND; \ + delay_check = FCSR_FCC; + +-#else /* !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 6 */ + + #define BR_T() \ + inst = BC1T | JUMP_LENGTH; \ +@@ -1812,7 +1828,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi + flags = IS_BIT16_COND; \ + delay_check = FCSR_FCC; + +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + + SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) + { +@@ -2123,11 +2139,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co + case SLJIT_GREATER_EQUAL_F64: + case SLJIT_UNORDERED_F64: + case SLJIT_ORDERED_F64: +-#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar)); +-#else /* !SLJIT_MIPS_R6 */ ++#else /* SLJIT_MIPS_REV < 6 */ + FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar)); +-#endif /* SLJIT_MIPS_R6 */ ++#endif /* SLJIT_MIPS_REV >= 6 */ + FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar)); + FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar)); + src_ar = dst_ar; +@@ -2167,14 +2183,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) + { +-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + sljit_ins ins; +-#endif ++#endif /* SLJIT_MIPS_REV >= 1 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + +-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) ++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + + if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { + #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) +@@ -2231,9 +2247,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil + + return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg)); + +-#else ++#else /* SLJIT_MIPS_REV < 1 */ + return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); +-#endif ++#endif /* SLJIT_MIPS_REV >= 1 */ + } + + SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) +diff --git a/sljit/sljitNativePPC_common.c b/sljit/sljitNativePPC_common.c +index e827514..17bf9a9 100644 +--- a/sljit/sljitNativePPC_common.c ++++ b/sljit/sljitNativePPC_common.c +@@ -627,6 +627,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) + #endif + + case SLJIT_HAS_CLZ: ++ case SLJIT_HAS_PREFETCH: + return 1; + + default: +@@ -1158,6 +1159,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + #else + return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); + #endif ++ case SLJIT_ENDBR: ++ case SLJIT_SKIP_FRAMES_BEFORE_RETURN: ++ return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; +@@ -1203,13 +1207,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src, srcw); + +- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { +- if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) +- return emit_prefetch(compiler, src, srcw); +- +- return SLJIT_SUCCESS; +- } +- + op = GET_OPCODE(op); + if ((src & SLJIT_IMM) && srcw == 0) + src = TMP_ZERO; +@@ -1536,6 +1533,35 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile + return SLJIT_SUCCESS; + } + ++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, ++ sljit_s32 src, sljit_sw srcw) ++{ ++ CHECK_ERROR(); ++ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); ++ ADJUST_LOCAL_OFFSET(src, srcw); ++ ++ switch (op) { ++ case SLJIT_FAST_RETURN: ++ if (FAST_IS_REG(src)) ++ FAIL_IF(push_inst(compiler, MTLR | S(src))); ++ else { ++ FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); ++ FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2))); ++ } ++ ++ return push_inst(compiler, BLR); ++ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: ++ return SLJIT_SUCCESS; ++ case SLJIT_PREFETCH_L1: ++ case SLJIT_PREFETCH_L2: ++ case SLJIT_PREFETCH_L3: ++ case SLJIT_PREFETCH_ONCE: ++ return emit_prefetch(compiler, src, srcw); ++ } ++ ++ return SLJIT_SUCCESS; ++} ++ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) + { + CHECK_REG_INDEX(check_sljit_get_register_index(reg)); +@@ -1854,22 +1880,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * + return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); + } + +-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) +-{ +- CHECK_ERROR(); +- CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); +- ADJUST_LOCAL_OFFSET(src, srcw); +- +- if (FAST_IS_REG(src)) +- FAIL_IF(push_inst(compiler, MTLR | S(src))); +- else { +- FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); +- FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2))); +- } +- +- return push_inst(compiler, BLR); +-} +- + /* --------------------------------------------------------------------- */ + /* Conditional instructions */ + /* --------------------------------------------------------------------- */ +diff --git a/sljit/sljitNativeSPARC_common.c b/sljit/sljitNativeSPARC_common.c +index bfa4ece..4c95350 100644 +--- a/sljit/sljitNativeSPARC_common.c ++++ b/sljit/sljitNativeSPARC_common.c +@@ -872,6 +872,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + #else + #error "Implementation required" + #endif ++ case SLJIT_ENDBR: ++ case SLJIT_SKIP_FRAMES_BEFORE_RETURN: ++ return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; +@@ -888,9 +891,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src, srcw); + +- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) +- return SLJIT_SUCCESS; +- + op = GET_OPCODE(op); + switch (op) { + case SLJIT_MOV: +@@ -971,6 +971,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile + return SLJIT_SUCCESS; + } + ++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, ++ sljit_s32 src, sljit_sw srcw) ++{ ++ CHECK_ERROR(); ++ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); ++ ADJUST_LOCAL_OFFSET(src, srcw); ++ ++ switch (op) { ++ case SLJIT_FAST_RETURN: ++ if (FAST_IS_REG(src)) ++ FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK))); ++ else ++ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw)); ++ ++ FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS)); ++ return push_inst(compiler, NOP, UNMOVABLE_INS); ++ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: ++ case SLJIT_PREFETCH_L1: ++ case SLJIT_PREFETCH_L2: ++ case SLJIT_PREFETCH_L3: ++ case SLJIT_PREFETCH_ONCE: ++ return SLJIT_SUCCESS; ++ } ++ ++ return SLJIT_SUCCESS; ++} ++ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) + { + CHECK_REG_INDEX(check_sljit_get_register_index(reg)); +@@ -1215,25 +1242,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * + ADJUST_LOCAL_OFFSET(dst, dstw); + + if (FAST_IS_REG(dst)) +- return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), DR(dst)); ++ return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), UNMOVABLE_INS); + + /* Memory. */ +- return emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw); +-} +- +-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) +-{ +- CHECK_ERROR(); +- CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); +- ADJUST_LOCAL_OFFSET(src, srcw); +- +- if (FAST_IS_REG(src)) +- FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK))); +- else +- FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw)); +- +- FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS)); +- return push_inst(compiler, NOP, UNMOVABLE_INS); ++ FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw)); ++ compiler->delay_slot = UNMOVABLE_INS; ++ return SLJIT_SUCCESS; + } + + /* --------------------------------------------------------------------- */ +diff --git a/sljit/sljitNativeTILEGX_64.c b/sljit/sljitNativeTILEGX_64.c +index 003f43a..d69ecd6 100644 +--- a/sljit/sljitNativeTILEGX_64.c ++++ b/sljit/sljitNativeTILEGX_64.c +@@ -1564,24 +1564,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * + return emit_op_mem(compiler, WORD_DATA, RA, dst, dstw); + } + +-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) +-{ +- CHECK_ERROR(); +- CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); +- ADJUST_LOCAL_OFFSET(src, srcw); +- +- if (FAST_IS_REG(src)) +- FAIL_IF(ADD(RA, reg_map[src], ZERO)); +- +- else if (src & SLJIT_MEM) +- FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RA, src, srcw)); +- +- else if (src & SLJIT_IMM) +- FAIL_IF(load_immediate(compiler, RA, srcw)); +- +- return JR(RA); +-} +- + static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2) + { + sljit_s32 overflow_ra = 0; +@@ -2184,6 +2166,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + case SLJIT_DIV_UW: + case SLJIT_DIV_SW: + SLJIT_UNREACHABLE(); ++ case SLJIT_ENDBR: ++ case SLJIT_SKIP_FRAMES_BEFORE_RETURN: ++ return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; +@@ -2293,6 +2278,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile + return SLJIT_SUCCESS; + } + ++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, ++ sljit_s32 src, sljit_sw srcw) ++{ ++ CHECK_ERROR(); ++ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); ++ ADJUST_LOCAL_OFFSET(src, srcw); ++ ++ switch (op) { ++ case SLJIT_FAST_RETURN: ++ if (FAST_IS_REG(src)) ++ FAIL_IF(ADD(RA, reg_map[src], ZERO)); ++ ++ else ++ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RA, src, srcw)); ++ ++ return JR(RA); ++ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: ++ return SLJIT_SUCCESS; ++ } ++ ++ return SLJIT_SUCCESS; ++} ++ + SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_compiler *compiler) + { + struct sljit_label *label; +diff --git a/sljit/sljitNativeX86_32.c b/sljit/sljitNativeX86_32.c +index 34a3a3d..79a7e8b 100644 +--- a/sljit/sljitNativeX86_32.c ++++ b/sljit/sljitNativeX86_32.c +@@ -76,6 +76,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + ++ /* Emit ENDBR32 at function entry if needed. */ ++ FAIL_IF(emit_endbranch(compiler)); ++ + args = get_arg_count(arg_types); + compiler->args = args; + +@@ -307,14 +310,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp + SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size)); + #endif + +- size = 2 + (compiler->scratches > 7 ? (compiler->scratches - 7) : 0) + ++ size = 2 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) + + (compiler->saveds <= 3 ? compiler->saveds : 3); + #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + if (compiler->args > 2) + size += 2; +-#else +- if (compiler->args > 0) +- size += 2; + #endif + inst = (sljit_u8*)ensure_buf(compiler, 1 + size); + FAIL_IF(!inst); +@@ -367,6 +367,8 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 + SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3) + && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66) + && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66)); ++ /* We don't support (%ebp). */ ++ SLJIT_ASSERT(!(b & SLJIT_MEM) || immb || reg_map[b & REG_MASK] != 5); + + size &= 0xf; + inst_size = size; +@@ -863,14 +865,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * + return SLJIT_SUCCESS; + } + +-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) ++static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) + { + sljit_u8 *inst; + +- CHECK_ERROR(); +- CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); +- ADJUST_LOCAL_OFFSET(src, srcw); +- + CHECK_EXTRA_REGS(src, srcw, (void)0); + + if (FAST_IS_REG(src)) { +@@ -894,3 +892,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler + RET(); + return SLJIT_SUCCESS; + } ++ ++static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler) ++{ ++ sljit_s32 size, saved_size; ++ sljit_s32 has_f64_aligment; ++ ++ /* Don't adjust shadow stack if it isn't enabled. */ ++ if (!cpu_has_shadow_stack ()) ++ return SLJIT_SUCCESS; ++ ++ SLJIT_ASSERT(compiler->args >= 0); ++ SLJIT_ASSERT(compiler->local_size > 0); ++ ++#if !defined(__APPLE__) ++ has_f64_aligment = compiler->options & SLJIT_F64_ALIGNMENT; ++#else ++ has_f64_aligment = 0; ++#endif ++ ++ size = compiler->local_size; ++ saved_size = (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) + (compiler->saveds <= 3 ? compiler->saveds : 3)) * sizeof(sljit_uw); ++ if (has_f64_aligment) { ++ /* mov TMP_REG1, [esp + local_size]. */ ++ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), size); ++ /* mov TMP_REG1, [TMP_REG1+ saved_size]. */ ++ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), saved_size); ++ /* Move return address to [esp]. */ ++ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, TMP_REG1, 0); ++ size = 0; ++ } else ++ size += saved_size; ++ ++ return adjust_shadow_stack(compiler, SLJIT_UNUSED, 0, SLJIT_SP, size); ++} +diff --git a/sljit/sljitNativeX86_64.c b/sljit/sljitNativeX86_64.c +index 5758711..e85b56a 100644 +--- a/sljit/sljitNativeX86_64.c ++++ b/sljit/sljitNativeX86_64.c +@@ -135,6 +135,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + ++ /* Emit ENDBR64 at function entry if needed. */ ++ FAIL_IF(emit_endbranch(compiler)); ++ + compiler->mode32 = 0; + + #ifdef _WIN64 +@@ -796,14 +799,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * + return SLJIT_SUCCESS; + } + +-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) ++static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) + { + sljit_u8 *inst; + +- CHECK_ERROR(); +- CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); +- ADJUST_LOCAL_OFFSET(src, srcw); +- + if (FAST_IS_REG(src)) { + if (reg_map[src] < 8) { + inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1); +@@ -898,3 +897,22 @@ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign, + + return SLJIT_SUCCESS; + } ++ ++static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler) ++{ ++ sljit_s32 tmp, size; ++ ++ /* Don't adjust shadow stack if it isn't enabled. */ ++ if (!cpu_has_shadow_stack ()) ++ return SLJIT_SUCCESS; ++ ++ size = compiler->local_size; ++ tmp = compiler->scratches; ++ if (tmp >= SLJIT_FIRST_SAVED_REG) ++ size += (tmp - SLJIT_FIRST_SAVED_REG + 1) * sizeof(sljit_uw); ++ tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG; ++ if (SLJIT_S0 >= tmp) ++ size += (SLJIT_S0 - tmp + 1) * sizeof(sljit_uw); ++ ++ return adjust_shadow_stack(compiler, SLJIT_UNUSED, 0, SLJIT_SP, size); ++} +diff --git a/sljit/sljitNativeX86_common.c b/sljit/sljitNativeX86_common.c +index 6296da5..eea9510 100644 +--- a/sljit/sljitNativeX86_common.c ++++ b/sljit/sljitNativeX86_common.c +@@ -657,6 +657,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) + get_cpu_features(); + return cpu_has_cmov; + ++ case SLJIT_HAS_PREFETCH: ++ return 1; ++ + case SLJIT_HAS_SSE2: + #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) + if (cpu_has_sse2 == -1) +@@ -702,6 +705,165 @@ static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler, + static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler, + sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw); + ++static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler, ++ sljit_s32 src1, sljit_sw src1w, ++ sljit_s32 src2, sljit_sw src2w); ++ ++static SLJIT_INLINE sljit_s32 emit_endbranch(struct sljit_compiler *compiler) ++{ ++#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) ++ /* Emit endbr32/endbr64 when CET is enabled. */ ++ sljit_u8 *inst; ++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); ++ FAIL_IF(!inst); ++ INC_SIZE(4); ++ *inst++ = 0xf3; ++ *inst++ = 0x0f; ++ *inst++ = 0x1e; ++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) ++ *inst = 0xfb; ++#else ++ *inst = 0xfa; ++#endif ++#else ++ (void)compiler; ++#endif ++ return SLJIT_SUCCESS; ++} ++ ++static SLJIT_INLINE sljit_s32 emit_rdssp(struct sljit_compiler *compiler, sljit_s32 reg) ++{ ++#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) ++ sljit_u8 *inst; ++ sljit_s32 size; ++ ++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) ++ size = 5; ++#else ++ size = 4; ++#endif ++ ++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size); ++ FAIL_IF(!inst); ++ INC_SIZE(size); ++ *inst++ = 0xf3; ++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) ++ *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B); ++#endif ++ *inst++ = 0x0f; ++ *inst++ = 0x1e; ++ *inst = (0x3 << 6) | (0x1 << 3) | (reg_map[reg] & 0x7); ++#else ++ (void)compiler; ++#endif ++ return SLJIT_SUCCESS; ++} ++ ++static SLJIT_INLINE sljit_s32 emit_incssp(struct sljit_compiler *compiler, sljit_s32 reg) ++{ ++#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) ++ sljit_u8 *inst; ++ sljit_s32 size; ++ ++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) ++ size = 5; ++#else ++ size = 4; ++#endif ++ ++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size); ++ FAIL_IF(!inst); ++ INC_SIZE(size); ++ *inst++ = 0xf3; ++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) ++ *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B); ++#endif ++ *inst++ = 0x0f; ++ *inst++ = 0xae; ++ *inst = (0x3 << 6) | (0x5 << 3) | (reg_map[reg] & 0x7); ++#else ++ (void)compiler; ++#endif ++ return SLJIT_SUCCESS; ++} ++ ++static SLJIT_INLINE sljit_s32 cpu_has_shadow_stack(void) ++{ ++#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) ++ return _get_ssp() != 0; ++#else ++ return 0; ++#endif ++} ++ ++static SLJIT_INLINE sljit_s32 adjust_shadow_stack(struct sljit_compiler *compiler, ++ sljit_s32 src, sljit_sw srcw, sljit_s32 base, sljit_sw disp) ++{ ++#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) ++ sljit_u8 *inst; ++ ++ sljit_s32 size_before_rdssp_inst = compiler->size; ++ ++ /* Generate "RDSSP TMP_REG1". */ ++ FAIL_IF(emit_rdssp(compiler, TMP_REG1)); ++ ++ /* Load return address on shadow stack into TMP_REG1. */ ++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) ++ SLJIT_ASSERT(reg_map[TMP_REG1] == 5); ++ ++ /* Hand code unsupported "mov 0x0(%ebp),%ebp". */ ++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3); ++ FAIL_IF(!inst); ++ INC_SIZE(3); ++ *inst++ = 0x8b; ++ *inst++ = 0x6d; ++ *inst = 0; ++#else /* !SLJIT_CONFIG_X86_32 */ ++ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), 0); ++#endif /* SLJIT_CONFIG_X86_32 */ ++ ++ if (src == SLJIT_UNUSED) { ++ /* Return address is on stack. */ ++ src = SLJIT_MEM1(base); ++ srcw = disp; ++ } ++ ++ /* Compare return address against TMP_REG1. */ ++ FAIL_IF(emit_cmp_binary (compiler, TMP_REG1, 0, src, srcw)); ++ ++ /* Generate JZ to skip shadow stack ajdustment when shadow ++ stack matches normal stack. */ ++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); ++ FAIL_IF(!inst); ++ INC_SIZE(2); ++ *inst++ = get_jump_code(SLJIT_EQUAL) - 0x10; ++ sljit_uw size_jz_after_cmp_inst = compiler->size; ++ sljit_u8 *jz_after_cmp_inst = inst; ++ ++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) ++ /* REX_W is not necessary. */ ++ compiler->mode32 = 1; ++#endif ++ /* Load 1 into TMP_REG1. */ ++ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1); ++ ++ /* Generate "INCSSP TMP_REG1". */ ++ FAIL_IF(emit_incssp(compiler, TMP_REG1)); ++ ++ /* Jump back to "RDSSP TMP_REG1" to check shadow stack again. */ ++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); ++ FAIL_IF(!inst); ++ INC_SIZE(2); ++ *inst++ = JMP_i8; ++ *inst = size_before_rdssp_inst - compiler->size; ++ ++ *jz_after_cmp_inst = compiler->size - size_jz_after_cmp_inst; ++#else /* SLJIT_CONFIG_X86_CET */ ++ SLJIT_UNUSED_ARG(compiler); ++#endif /* SLJIT_CONFIG_X86_CET */ ++ return SLJIT_SUCCESS; ++} ++ + #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + #include "sljitNativeX86_32.c" + #else +@@ -905,6 +1067,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile + EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); + #endif + break; ++ case SLJIT_ENDBR: ++ return emit_endbranch(compiler); ++ case SLJIT_SKIP_FRAMES_BEFORE_RETURN: ++ return skip_frames_before_return(compiler); + } + + return SLJIT_SUCCESS; +@@ -1074,12 +1240,12 @@ static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 op, + *inst++ = GROUP_0F; + *inst++ = PREFETCH; + +- if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8) +- *inst |= (3 << 3); +- else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16) +- *inst |= (2 << 3); +- else ++ if (op == SLJIT_PREFETCH_L1) + *inst |= (1 << 3); ++ else if (op == SLJIT_PREFETCH_L2) ++ *inst |= (2 << 3); ++ else if (op == SLJIT_PREFETCH_L3) ++ *inst |= (3 << 3); + + return SLJIT_SUCCESS; + } +@@ -1284,12 +1450,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile + compiler->mode32 = op_flags & SLJIT_I32_OP; + #endif + +- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { +- if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) +- return emit_prefetch(compiler, op, src, srcw); +- return SLJIT_SUCCESS; +- } +- + op = GET_OPCODE(op); + + if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) { +@@ -2186,6 +2346,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile + return SLJIT_SUCCESS; + } + ++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, ++ sljit_s32 src, sljit_sw srcw) ++{ ++ CHECK_ERROR(); ++ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); ++ ADJUST_LOCAL_OFFSET(src, srcw); ++ ++ CHECK_EXTRA_REGS(src, srcw, (void)0); ++ ++ switch (op) { ++ case SLJIT_FAST_RETURN: ++ return emit_fast_return(compiler, src, srcw); ++ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: ++ /* Don't adjust shadow stack if it isn't enabled. */ ++ if (!cpu_has_shadow_stack ()) ++ return SLJIT_SUCCESS; ++ return adjust_shadow_stack(compiler, src, srcw, SLJIT_UNUSED, 0); ++ case SLJIT_PREFETCH_L1: ++ case SLJIT_PREFETCH_L2: ++ case SLJIT_PREFETCH_L3: ++ case SLJIT_PREFETCH_ONCE: ++ return emit_prefetch(compiler, op, src, srcw); ++ } ++ ++ return SLJIT_SUCCESS; ++} ++ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) + { + CHECK_REG_INDEX(check_sljit_get_register_index(reg)); +diff --git a/sljit/sljitUtils.c b/sljit/sljitUtils.c +index 857492a..972cad9 100644 +--- a/sljit/sljitUtils.c ++++ b/sljit/sljitUtils.c +@@ -152,15 +152,23 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void) + + #ifdef _WIN32 + #include "windows.h" +-#else ++#else /* !_WIN32 */ + /* Provides mmap function. */ + #include + #include ++ + #ifndef MAP_ANON + #ifdef MAP_ANONYMOUS + #define MAP_ANON MAP_ANONYMOUS +-#endif +-#endif ++#endif /* MAP_ANONYMOUS */ ++#endif /* !MAP_ANON */ ++ ++#ifndef MADV_DONTNEED ++#ifdef POSIX_MADV_DONTNEED ++#define MADV_DONTNEED POSIX_MADV_DONTNEED ++#endif /* POSIX_MADV_DONTNEED */ ++#endif /* !MADV_DONTNEED */ ++ + /* For detecting the page size. */ + #include + +@@ -198,35 +206,83 @@ static SLJIT_INLINE sljit_s32 open_dev_zero(void) + + #endif /* SLJIT_SINGLE_THREADED */ + +-#endif ++#endif /* !MAP_ANON */ + +-#endif ++#endif /* _WIN32 */ + + #endif /* SLJIT_UTIL_STACK || SLJIT_EXECUTABLE_ALLOCATOR */ + + #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) + +-/* Planning to make it even more clever in the future. */ +-static sljit_sw sljit_page_align = 0; ++#if (defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION) + + SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data) + { + struct sljit_stack *stack; + void *ptr; +-#ifdef _WIN32 +- SYSTEM_INFO si; +-#endif + + SLJIT_UNUSED_ARG(allocator_data); ++ + if (start_size > max_size || start_size < 1) + return NULL; + ++ stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data); ++ if (stack == NULL) ++ return NULL; ++ ++ ptr = SLJIT_MALLOC(max_size, allocator_data); ++ if (ptr == NULL) { ++ SLJIT_FREE(stack, allocator_data); ++ return NULL; ++ } ++ ++ stack->min_start = (sljit_u8 *)ptr; ++ stack->end = stack->min_start + max_size; ++ stack->start = stack->end - start_size; ++ stack->top = stack->end; ++ return stack; ++} ++ ++SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data) ++{ ++ SLJIT_UNUSED_ARG(allocator_data); ++ SLJIT_FREE((void*)stack->min_start, allocator_data); ++ SLJIT_FREE(stack, allocator_data); ++} ++ ++SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start) ++{ ++ if ((new_start < stack->min_start) || (new_start >= stack->end)) ++ return NULL; ++ stack->start = new_start; ++ return new_start; ++} ++ ++#else /* !SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */ ++ + #ifdef _WIN32 ++ ++SLJIT_INLINE static sljit_sw get_page_alignment(void) { ++ SYSTEM_INFO si; ++ static sljit_sw sljit_page_align; + if (!sljit_page_align) { + GetSystemInfo(&si); + sljit_page_align = si.dwPageSize - 1; + } +-#else ++ return sljit_page_align; ++} ++ ++SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data) ++{ ++ SLJIT_UNUSED_ARG(allocator_data); ++ VirtualFree((void*)stack->min_start, 0, MEM_RELEASE); ++ SLJIT_FREE(stack, allocator_data); ++} ++ ++#else /* ! defined _WIN32 */ ++ ++SLJIT_INLINE static sljit_sw get_page_alignment(void) { ++ static sljit_sw sljit_page_align; + if (!sljit_page_align) { + sljit_page_align = sysconf(_SC_PAGESIZE); + /* Should never happen. */ +@@ -234,14 +290,36 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(slj + sljit_page_align = 4096; + sljit_page_align--; + } +-#endif ++ return sljit_page_align; ++} ++ ++SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data) ++{ ++ SLJIT_UNUSED_ARG(allocator_data); ++ munmap((void*)stack->min_start, stack->end - stack->min_start); ++ SLJIT_FREE(stack, allocator_data); ++} ++ ++#endif /* defined _WIN32 */ ++ ++SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data) ++{ ++ struct sljit_stack *stack; ++ void *ptr; ++ sljit_sw page_align; ++ ++ SLJIT_UNUSED_ARG(allocator_data); ++ ++ if (start_size > max_size || start_size < 1) ++ return NULL; + + stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data); +- if (!stack) ++ if (stack == NULL) + return NULL; + + /* Align max_size. */ +- max_size = (max_size + sljit_page_align) & ~sljit_page_align; ++ page_align = get_page_alignment(); ++ max_size = (max_size + page_align) & ~page_align; + + #ifdef _WIN32 + ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE); +@@ -258,18 +336,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(slj + sljit_free_stack(stack, allocator_data); + return NULL; + } +-#else ++#else /* !_WIN32 */ + #ifdef MAP_ANON + ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); +-#else ++#else /* !MAP_ANON */ + if (dev_zero < 0) { +- if (open_dev_zero()) { ++ if (open_dev_zero() != 0) { + SLJIT_FREE(stack, allocator_data); + return NULL; + } + } + ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0); +-#endif ++#endif /* MAP_ANON */ + if (ptr == MAP_FAILED) { + SLJIT_FREE(stack, allocator_data); + return NULL; +@@ -277,35 +355,28 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(slj + stack->min_start = (sljit_u8 *)ptr; + stack->end = stack->min_start + max_size; + stack->start = stack->end - start_size; +-#endif ++#endif /* _WIN32 */ ++ + stack->top = stack->end; + return stack; + } + +-#undef PAGE_ALIGN +- +-SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data) +-{ +- SLJIT_UNUSED_ARG(allocator_data); +-#ifdef _WIN32 +- VirtualFree((void*)stack->min_start, 0, MEM_RELEASE); +-#else +- munmap((void*)stack->min_start, stack->end - stack->min_start); +-#endif +- SLJIT_FREE(stack, allocator_data); +-} +- + SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start) + { ++#if defined _WIN32 || defined(MADV_DONTNEED) + sljit_uw aligned_old_start; + sljit_uw aligned_new_start; ++ sljit_sw page_align; ++#endif + + if ((new_start < stack->min_start) || (new_start >= stack->end)) + return NULL; + + #ifdef _WIN32 +- aligned_new_start = (sljit_uw)new_start & ~sljit_page_align; +- aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align; ++ page_align = get_page_alignment(); ++ ++ aligned_new_start = (sljit_uw)new_start & ~page_align; ++ aligned_old_start = ((sljit_uw)stack->start) & ~page_align; + if (aligned_new_start != aligned_old_start) { + if (aligned_new_start < aligned_old_start) { + if (!VirtualAlloc((void*)aligned_new_start, aligned_old_start - aligned_new_start, MEM_COMMIT, PAGE_READWRITE)) +@@ -316,24 +387,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_st + return NULL; + } + } +-#else ++#elif defined(MADV_DONTNEED) + if (stack->start < new_start) { +- aligned_new_start = (sljit_uw)new_start & ~sljit_page_align; +- aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align; ++ page_align = get_page_alignment(); ++ ++ aligned_new_start = (sljit_uw)new_start & ~page_align; ++ aligned_old_start = ((sljit_uw)stack->start) & ~page_align; + /* If madvise is available, we release the unnecessary space. */ +-#if defined(MADV_DONTNEED) + if (aligned_new_start > aligned_old_start) + madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_DONTNEED); +-#elif defined(POSIX_MADV_DONTNEED) +- if (aligned_new_start > aligned_old_start) +- posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED); +-#endif + } +-#endif ++#endif /* _WIN32 */ ++ + stack->start = new_start; + return new_start; + } + ++#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */ ++ + #endif /* SLJIT_UTIL_STACK */ + + #endif +-- +2.26.2 + diff --git a/SOURCES/pcre-8.44-Pass-mshstk-to-the-compiler-when-Intel-CET-is-enable.patch b/SOURCES/pcre-8.44-Pass-mshstk-to-the-compiler-when-Intel-CET-is-enable.patch new file mode 100644 index 0000000..adff725 --- /dev/null +++ b/SOURCES/pcre-8.44-Pass-mshstk-to-the-compiler-when-Intel-CET-is-enable.patch @@ -0,0 +1,98 @@ +From 70fcff23652339438cabef86f2d3d9c645678687 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Sun, 20 Dec 2020 13:55:40 -0800 +Subject: [PATCH 2/2] Pass -mshstk to the compiler when Intel CET is enable + +Copied from PCRE2. +--- + CMakeLists.txt | 18 ++++++++++++++++++ + Makefile.am | 3 +++ + configure.ac | 15 +++++++++++++++ + 3 files changed, 36 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 858a34b..74c27e9 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -112,6 +112,24 @@ CHECK_FUNCTION_EXISTS(_strtoi64 HAVE__STRTOI64) + CHECK_TYPE_SIZE("long long" LONG_LONG) + CHECK_TYPE_SIZE("unsigned long long" UNSIGNED_LONG_LONG) + ++# Check whether Intel CET is enabled, and if so, adjust compiler flags. This ++# code was written by PH, trying to imitate the logic from the autotools ++# configuration. ++ ++CHECK_C_SOURCE_COMPILES( ++ "#ifndef __CET__ ++ #error CET is not enabled ++ #endif ++ int main() { return 0; }" ++ INTEL_CET_ENABLED ++) ++ ++IF (INTEL_CET_ENABLED) ++ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mshstk") ++ENDIF(INTEL_CET_ENABLED) ++ ++ ++ + # User-configurable options + # + # (Note: CMakeSetup displays these in alphabetical order, regardless of +diff --git a/Makefile.am b/Makefile.am +index 22b6947..984c686 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -250,6 +250,7 @@ libpcre_la_SOURCES = \ + + libpcre_la_CFLAGS = \ + $(VISIBILITY_CFLAGS) \ ++ $(CET_CFLAGS) \ + $(AM_CFLAGS) + + libpcre_la_LIBADD = +@@ -289,6 +290,7 @@ libpcre16_la_SOURCES = \ + + libpcre16_la_CFLAGS = \ + $(VISIBILITY_CFLAGS) \ ++ $(CET_CFLAGS) \ + $(AM_CFLAGS) + + libpcre16_la_LIBADD = +@@ -328,6 +330,7 @@ libpcre32_la_SOURCES = \ + + libpcre32_la_CFLAGS = \ + $(VISIBILITY_CFLAGS) \ ++ $(CET_CFLAGS) \ + $(AM_CFLAGS) + + libpcre32_la_LIBADD = +diff --git a/configure.ac b/configure.ac +index 6a3e5f3..15f37d1 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1043,6 +1043,21 @@ fi # enable_coverage + + AM_CONDITIONAL([WITH_GCOV],[test "x$enable_coverage" = "xyes"]) + ++AC_MSG_CHECKING([whether Intel CET is enabled]) ++AC_LANG_PUSH([C]) ++AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, ++ [[#ifndef __CET__ ++# error CET is not enabled ++#endif]])], ++ [intel_cet_enabled=yes], ++ [intel_cet_enabled=no]) ++AC_MSG_RESULT([$intel_cet_enabled]) ++if test "$intel_cet_enabled" = yes; then ++ CET_CFLAGS="-mshstk" ++ AC_SUBST([CET_CFLAGS]) ++fi ++AC_LANG_POP([C]) ++ + # Produce these files, in addition to config.h. + AC_CONFIG_FILES( + Makefile +-- +2.29.2 + diff --git a/SPECS/pcre.spec b/SPECS/pcre.spec new file mode 100644 index 0000000..f0049a5 --- /dev/null +++ b/SPECS/pcre.spec @@ -0,0 +1,969 @@ +# Is this a stable/testing release: +#%%global rcversion RC1 +Name: pcre +Version: 8.44 +Release: %{?rcversion:0.}4%{?rcversion:.%rcversion}%{?dist} +%global myversion %{version}%{?rcversion:-%rcversion} +Summary: Perl-compatible regular expression library +## Source package only: +# INSTALL: FSFAP +# install-sh: MIT and Public Domain +# ltmain.sh: (GPLv2+ or BSD) and (GPLv3+ or MIT) +# missing: GPLv2+ or BSD +# compile: GPLv2+ or BSD +# config.sub: GPLv3+ or BSD +# m4/ax_pthread.m4: GPLv3+ with exception +# m4/libtool.m4: GPLv2+ or BSD +# m4/ltversion.m4: FSFULLR +# m4/pcre_visibility.m4: FSFULLR +# m4/lt~obsolete.m4: FSFULLR +# m4/ltsugar.m4: FSFULLR +# m4/ltoptions.m4: FSFULLR +# aclocal.m4: (GPLv2+ or BSD) and FSFULLR +# Makefile.in: FSFULLR +# configure: FSFUL +# test-driver: GPLv2+ with exception +# testdata: Public Domain (see LICENSE file) +## Binary packages: +# other files: BSD +License: BSD +URL: https://www.pcre.org/ +Source0: https://ftp.pcre.org/pub/%{name}/%{?rcversion:Testing/}%{name}-%{myversion}.tar.bz2 +Source1: https://ftp.pcre.org/pub/%{name}/%{?rcversion:Testing/}%{name}-%{myversion}.tar.bz2.sig +Source2: https://ftp.pcre.org/pub/pcre/Public-Key +# Do no set RPATH if libdir is not /usr/lib +Patch0: pcre-8.21-multilib.patch +# Refused by upstream, bug #675477 +Patch1: pcre-8.32-refused_spelling_terminated.patch +# Fix recursion stack estimator, upstream bug #2173, refused by upstream +Patch2: pcre-8.41-fix_stack_estimator.patch +# Link applications to PCRE-specific symbols when using POSIX API, bug #1667614, +# upstream bug 1830, partially borrowed from PCRE2, proposed to upstream, +# This amends ABI, application built with this patch cannot run with +# previous libpcreposix builds. +Patch3: pcre-8.42-Declare-POSIX-regex-function-names-as-macros-to-PCRE.patch +# Fix reading an uninitialized memory when populating a name table, +# upstream bug #2661, proposed to the upstream +Patch4: pcre-8.44-Inicialize-name-table-memory-region.patch +# Implement CET, bug #1909554, proposed to the upstream +# +Patch5: pcre-8.44-JIT-compiler-update-for-Intel-CET.patch +Patch6: pcre-8.44-Pass-mshstk-to-the-compiler-when-Intel-CET-is-enable.patch +# SAST reports RHEL-32488 and RHEL-32492 fixed +Patch7: 0001-Fix-the-possible-array-overrun-when-the-OP_TABLE_LEN.patch +Patch8: 0002-Fix-UNINIT-SAST-report-for-the-mark-values.patch +BuildRequires: readline-devel +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: coreutils +BuildRequires: gcc +BuildRequires: gcc-c++ +# glibc-common for iconv +BuildRequires: glibc-common +BuildRequires: gnupg2 +BuildRequires: libtool +BuildRequires: make +# perl not used because config.h.generic is pregenerated +# Tests: +BuildRequires: bash +BuildRequires: diffutils +BuildRequires: grep + +%description +PCRE, Perl-compatible regular expression, library has its own native API, but +a set of wrapper functions that are based on the POSIX API are also supplied +in the libpcreposix library. Note that this just provides a POSIX calling +interface to PCRE: the regular expressions themselves still follow Perl syntax +and semantics. This package provides support for strings in 8-bit and UTF-8 +encodings. Detailed change log is provided by %{name}-doc package. + +%package utf16 +Summary: UTF-16 variant of PCRE +Conflicts: %{name}%{?_isa} < 8.38-12 + +%description utf16 +This is Perl-compatible regular expression library working on UTF-16 strings. +Detailed change log is provided by %{name}-doc package. + +%package utf32 +Summary: UTF-32 variant of PCRE +Conflicts: %{name}%{?_isa} < 8.38-12 + +%description utf32 +This is Perl-compatible regular expression library working on UTF-32 strings. +Detailed change log is provided by %{name}-doc package. + +%package cpp +Summary: C++ bindings for PCRE +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description cpp +This is C++ bindings for the Perl-compatible regular expression library. +Detailed change log is provided by %{name}-doc package. + +%package doc +Summary: Change log for %{name} +BuildArch: noarch + +%description doc +These are large documentation files about PCRE. + +%package devel +Summary: Development files for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: %{name}-cpp%{?_isa} = %{version}-%{release} +Requires: %{name}-utf16%{?_isa} = %{version}-%{release} +Requires: %{name}-utf32%{?_isa} = %{version}-%{release} + +%description devel +Development files (Headers, libraries for dynamic linking, etc) for %{name}. + +%package static +Summary: Static library for %{name} +Requires: %{name}-devel%{_isa} = %{version}-%{release} + +%description static +Library for static linking for %{name}. + +%package tools +Summary: Auxiliary utilities for %{name} +Requires: %{name}%{_isa} = %{version}-%{release} + +%description tools +Utilities demonstrating PCRE capabilities like pcregrep or pcretest. + +%prep +%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' +%setup -q -n %{name}-%{myversion} +%patch0 -p1 +%patch1 -p1 +%patch2 -p2 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +# Because of the multilib patch +libtoolize --copy --force +autoreconf -vif +# One contributor's name is non-UTF-8 +for F in ChangeLog; do + iconv -f latin1 -t utf8 "$F" >"${F}.utf8" + touch --reference "$F" "${F}.utf8" + mv "${F}.utf8" "$F" +done + +%build +# There is a strict-aliasing problem on PPC64, bug #881232 +%ifarch ppc64 +%global optflags %{optflags} -fno-strict-aliasing +%endif +%configure \ +%ifarch s390 s390x sparc64 sparcv9 riscv64 + --disable-jit \ +%else + --enable-jit \ +%endif + --enable-pcretest-libreadline \ + --enable-utf \ + --enable-unicode-properties \ + --enable-pcre8 \ + --enable-pcre16 \ + --enable-pcre32 \ + --disable-silent-rules +%{make_build} + +%install +%{make_install} +# Get rid of unneeded *.la files +rm -f $RPM_BUILD_ROOT%{_libdir}/*.la +# These are handled by %%doc in %%files +rm -rf $RPM_BUILD_ROOT%{_docdir}/pcre + +%check +%ifarch s390 s390x ppc +# larger stack is needed on s390, ppc +ulimit -s 10240 +%endif +make %{?_smp_mflags} check VERBOSE=yes + +%files +%{_libdir}/libpcre.so.1 +%{_libdir}/libpcre.so.1.* +%{_libdir}/libpcreposix.so.0 +%{_libdir}/libpcreposix.so.0.* +%license COPYING LICENCE +%doc AUTHORS NEWS + +%files utf16 +%{_libdir}/libpcre16.so.0 +%{_libdir}/libpcre16.so.0.* +%license COPYING LICENCE +%doc AUTHORS NEWS + +%files utf32 +%{_libdir}/libpcre32.so.0 +%{_libdir}/libpcre32.so.0.* +%license COPYING LICENCE +%doc AUTHORS NEWS + +%files cpp +%{_libdir}/libpcrecpp.so.0 +%{_libdir}/libpcrecpp.so.0.* + +%files doc +%doc ChangeLog + +%files devel +%{_libdir}/*.so +%{_libdir}/pkgconfig/* +%{_includedir}/*.h +%{_mandir}/man1/pcre-config.* +%{_mandir}/man3/* +%{_bindir}/pcre-config +%doc doc/*.txt doc/html +%doc README HACKING pcredemo.c + +%files static +%{_libdir}/*.a +%license COPYING LICENCE + +%files tools +%{_bindir}/pcregrep +%{_bindir}/pcretest +%{_mandir}/man1/pcregrep.* +%{_mandir}/man1/pcretest.* + +%changelog +* Wed Apr 17 2024 Lukas Javorsky - 8.44.3-4 +- Fix the SAST reports described in RHEL-32492 and RHEL-32488 + +* Mon Aug 09 2021 Mohan Boddu - 8.44-3.3 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Fri Apr 16 2021 Mohan Boddu - 8.44-3.2 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Tue Jan 26 2021 Fedora Release Engineering - 8.44-3.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Mon Jan 11 2021 Petr Pisar - 8.44-3 +- Implement CET (bug #1909554) + +* Mon Oct 19 2020 Petr Pisar - 8.44-2 +- Fix reading an uninitialized memory when populating a name table + (upstream bug #2661) + +* Tue Jul 28 2020 Fedora Release Engineering - 8.44-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Fri Feb 14 2020 Petr Pisar - 8.44-1 +- 8.44 bump + +* Wed Feb 12 2020 Petr Pisar - 8.43-3 +- Make erroroffset initializion in a POSIX wrapper thread-safe + (upstream bug #2447) +- Fix an integer overflow when parsing numbers after "(?C" (upstream bug #2463) +- Fix shifting integer bits and a NULL pointer dereferce in pcretest tool + (upstream bug #2380) + +* Wed Jan 29 2020 Fedora Release Engineering - 8.43-2.2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Fri Jul 26 2019 Fedora Release Engineering - 8.43-2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Fri May 24 2019 Petr Pisar - 8.43-2 +- Add (*LF) to a list of start-of-pattern options in the C++ wrapper + (upstream bug #2400) + +* Mon Feb 25 2019 Petr Pisar - 8.43-1 +- 8.43 bump + +* Sun Feb 17 2019 Igor Gnatenko - 8.43-0.1.RC1.2 +- Rebuild for readline 8.0 + +* Fri Feb 01 2019 Fedora Release Engineering - 8.43-0.1.RC1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Mon Jan 28 2019 Petr Pisar - 8.43-0.1.RC1 +- 8.43-RC1 bump + +* Wed Jan 23 2019 Petr Pisar - 8.42-7 +- Link applications to PCRE-specific symbols when using POSIX API (bug #1667614) + +* Thu Jan 03 2019 Petr Pisar - 8.42-6 +- Fix OpenPOWER 64-bit ELFv2 ABI detection in JIT compiler (upstream bug #2353) +- Fix an undefined behavior in aarch64 JIT compiler (upstream bug #2355) + +* Thu Nov 01 2018 Petr Pisar - 8.42-5 +- Fix a subject buffer overread in JIT when UTF is disabled and \X or \R has + a greater than 1 fixed quantifier +- Fix matching a zero-repeated subroutine call at a start of a pattern + (upstream bug #2332) + +* Mon Sep 03 2018 Petr Pisar - 8.42-4 +- Fix anchoring in conditionals with only one branch (upstream bug #2307) + +* Mon Aug 20 2018 Petr Pisar - 8.42-3 +- Fix autopossessifying a repeated negative class with no characters less than + 256 that is followed by a positive class with only characters less than 256 + (upstream bug #2300) + +* Fri Jul 13 2018 Fedora Release Engineering - 8.42-2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Thu Jun 28 2018 Petr Pisar - 8.42-2 +- Fix handling UTF and start-of-pattern options in C++ wrapper + (upstream bug #2283) +- Fix an error message and locale handling in pcregrep tool + +* Tue Mar 20 2018 Petr Pisar - 8.42-1 +- 8.42 bump + +* Mon Feb 26 2018 Petr Pisar - 8.42-0.2.RC1 +- Fix compiler warnings in pcregrep + +* Fri Feb 23 2018 Petr Pisar - 8.42-0.1.RC1 +- 8.42-RC1 bump + +* Tue Feb 20 2018 Petr Pisar - 8.41-6 +- Fix returning unset groups in POSIX interface if REG_STARTEND has a non-zero + starting offset (upstream bug #2244) + +* Thu Feb 08 2018 Fedora Release Engineering - 8.41-5.2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Sat Feb 03 2018 Igor Gnatenko - 8.41-5.1 +- Switch to %%ldconfig_scriptlets + +* Tue Jan 30 2018 Petr Pisar - 8.41-5 +- Fix out-of-bounds read for partial matching of /./ against an empty string + when the newline type is CRLF (upstream bug #2226) + +* Fri Jan 12 2018 Petr Pisar - 8.41-4 +- Allow pcregrep match counter to handle values larger than 2147483647 + (upstream bug #2208) +- Fix incorrect first matching character when a backreference with zero minimum + repeat starts a pattern (upstream bug #2209) + +* Thu Nov 02 2017 Petr Pisar - 8.41-3 +- Accept files names longer than 128 bytes in recursive mode of pcregrep + (upstream bug #2177) + +* Mon Oct 09 2017 Petr Pisar - 8.41-2 +- Fix recursion stack estimator (upstream bug #2173) + +* Thu Aug 03 2017 Fedora Release Engineering - 8.41-1.2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 8.41-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Fri Jul 07 2017 Petr Pisar - 8.41-1 +- 8.41 bump + +* Wed Jun 14 2017 Petr Pisar - 8.41-0.1.RC1 +- 8.41 RC1 bump + +* Fri Apr 21 2017 Petr Pisar - 8.40-7 +- Fix a buffer overflow in pcretest tool when copying a string in UTF-32 mode +- Fix CVE-2017-7186 in JIT mode (a crash when finding a Unicode property for + a character with a code point greater than 0x10ffff in UTF-32 library while + UTF mode is disabled) (bug #1434504) + +* Mon Mar 27 2017 Petr Pisar - 8.40-6 +- Fix DFA match for a possessively repeated character class (upstream bug #2086) + +* Mon Feb 27 2017 Petr Pisar - 8.40-5 +- Fix a crash in pcretest when \O directive was supplied with too big number + (upstream bug #2044) +- Document pcretest input cannot contain binary zeroes (upstream bug #2045) +- Fix CVE-2017-7244 (a crash when finding a Unicode property for a character + with a code point greater than 0x10ffff in UTF-32 library while UTF mode is + disabled) (upstream bug #2052) + +* Thu Feb 23 2017 Petr Pisar - 8.40-4 +- Fix a crash in pcretest when printing non-ASCII characters + (upstream bug #2043) + +* Tue Feb 21 2017 Petr Pisar - 8.40-3 +- Fix parsing comments between quantifiers (upstream bug #2019) + +* Tue Feb 14 2017 Petr Pisar - 8.40-2 +- Fix pcregrep multi-line matching --only-matching option (upstream bug #1848) +- Fix CVE-2017-6004 (a crash in JIT compilation) (upstream bug #2035) +- Fix a potenial buffer overflow in formatting a pcregrep error message + (upstream bug #2037) + +* Sat Feb 11 2017 Fedora Release Engineering - 8.40-1.2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Jan 12 2017 Igor Gnatenko - 8.40-1.1 +- Rebuild for readline 7.x + +* Thu Jan 12 2017 Petr Pisar - 8.40-1 +- 8.40 bump + +* Mon Dec 12 2016 Petr Pisar - 8.40-0.1.RC1 +- 8.40-RC1 bump + +* Mon Oct 24 2016 Petr Pisar - 8.39-6 +- Document assert capture limitation (upstream bug #1887) + +* Wed Oct 19 2016 Petr Pisar - 8.39-5 +- Fix internal option documentation in pcrepattern(3) (upstream bug #1875) +- Fix optimization bugs for patterns starting with lookaheads + (upstream bug #1882) + +* Fri Oct 14 2016 Petr Pisar - 8.39-4 +- Fix displaying position in pcretest callout with an escape sequence greater + than \x{ff} +- Fix pcrepattern(3) documentation +- Fix miscopmilation of conditionals when a group name start with "R" + (upstream bug #1873) + +* Tue Aug 30 2016 Petr Pisar - 8.39-3 +- Fix register overwite in JIT when SSE2 acceleration is enabled +- Fix matching characters above 255 when a negative character type was used + without enabled UCP in a positive class (upstream bug #1866) + +* Mon Jun 20 2016 Petr Pisar - 8.39-2 +- Fix repeated pcregrep output if -o with -M options were used and the match + extended over a line boundary (upstream bug #1848) + +* Tue Jun 14 2016 Petr Pisar - 8.39-1 +- 8.39 bump + +* Tue May 24 2016 Petr Pisar - 8.39-0.1.RC1 +- 8.39-RC1 bump + +* Thu Apr 07 2016 Petr Pisar - 8.38-14 +- Separate pcre-cpp subpackage for C++ bindings, thanks to Yaakov Selkowitz + (bug #1324580) +- Correct pcre-devel dependencies +- Remove rich dependency from pcre-doc + +* Mon Mar 07 2016 Petr Pisar - 8.38-13 +- Remove useless dependencies between UTF variants + +* Mon Mar 07 2016 Petr Pisar - 8.38-12 +- Move UTF-16 and UTF-32 libraries into pcre-ut16 and pcre-32 subpackages + +* Mon Mar 07 2016 Petr Pisar - 8.38-11 +- Ship ChangeLog in pcre-doc package + +* Sat Mar 5 2016 Peter Robinson 8.38-10 +- Don't ship ChangeLog, details covered in NEWS +- Ship README in devel as it covers API and build, not general info + +* Mon Feb 29 2016 Petr Pisar - 8.38-9 +- Fix a non-diagnosis of missing assection after (?(?C) that could corrupt + process stack (upstream bug #1780) +- Fix a typo in pcre_study() + +* Mon Feb 29 2016 Petr Pisar - 8.38-8 +- Fix CVE-2016-1283 (a heap buffer overflow in handling of nested duplicate + named groups with a nested back reference) (bug #1295386) +- Fix a heap buffer overflow in pcretest causing infinite loop when matching + globally with an ovector less than 2 (bug #1312786) + +* Thu Feb 11 2016 Petr Pisar - 8.38-7 +- Fix pcretest for expressions with a callout inside a look-behind assertion + (upstream bug #1783) +- Fix CVE-2016-3191 (workspace overflow for (*ACCEPT) with deeply nested + parentheses) (upstream bug #1791) + +* Thu Feb 04 2016 Fedora Release Engineering - 8.38-6.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Tue Dec 08 2015 Petr Pisar - 8.38-6 +- Fix a crash in pcre_get_substring_list() if the use of \K caused the start + of the match to be earlier than the end (upstream bug #1744) + +* Mon Dec 07 2015 Petr Pisar - 8.38-5 +- Fix possible crash in pcre_copy_named_substring() if a named substring has + number greater than the space in the ovector (upstream bug #1741) +- Fix a buffer overflow when compiling an expression with named groups with + a group that reset capture numbers (upstream bug #1742) + +* Fri Dec 04 2015 Petr Pisar - 8.38-4 +- Fix compiling expressions with global extended modifier that is disabled by + local no-extended option at the start of the expression just after + a whitespace + +* Tue Dec 01 2015 Petr Pisar - 8.38-3 +- Fix compiling expressions with negated classes in UCP mode + (upstream bug #1732) +- Fix compiling expressions with an isolated \E between an item and its + qualifier with auto-callouts (upstream bug #1724) +- Fix crash in regexec() if REG_STARTEND option is set and pmatch argument is + NULL (upstream bug #1727) +- Fix a stack overflow when formatting a 32-bit integer in pcregrep tool + (upstream bug #1728) +- Fix compiling expressions with an empty \Q\E sequence between an item and + its qualifier with auto-callouts (upstream bug #1735) + +* Fri Nov 27 2015 Petr Pisar - 8.38-2 +- Fix compiling comments with auto-callouts + +* Tue Nov 24 2015 Petr Pisar - 8.38-1 +- 8.38 bump + +* Wed Nov 18 2015 Petr Pisar - 8.38-0.2.RC1 +- Fix crash when compiling an expression with long (*MARK) or (*THEN) names +- Fix compiling a POSIX character class followed by a single ASCII character + in a class item while UCP mode is active (upstream bug #1717) +- Fix mismatching characters in the range 128-255 against [:punct:] in UCP + mode (upstream bug #1718) + +* Thu Oct 29 2015 Petr Pisar - 8.38-0.1.RC1 +- 8.38-RC1 bump + +* Mon Oct 12 2015 Petr Pisar - 8.37-5 +- Fix compiling classes with a negative escape and a property escape + (upstream bug #1697) + +* Tue Aug 25 2015 Petr Pisar - 8.37-4 +- Fix CVE-2015-8381 (a heap overflow when compiling certain expression with + named references) (bug #1256452) + +* Thu Aug 06 2015 Petr Pisar - 8.37-3 +- Fix a buffer overflow with duplicated named groups with a reference between + their definition, with a group that reset capture numbers +- Fix a buffer overflow with a forward reference by name to a group whose + number is the same as the current group +- Fix CVE-2015-8385 (a buffer overflow with duplicated named groups and an + occurrence of "(?|") (bug #1250946) + +* Wed Jul 01 2015 Petr Pisar - 8.37-2 +- Fix CVE-2015-3210 (heap overflow when compiling an expression with named + recursive back reference and the name is duplicated) (bug #1236659) +- Fix CVE-2015-5073 (heap overflow when compiling an expression with an + forward reference within backward asserion with excessive closing + paranthesis) (bug #1237224) + +* Thu Jun 18 2015 Fedora Release Engineering - 8.37-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Tue Apr 28 2015 Petr Pisar - 8.37-1 +- 8.37 bump + +* Thu Apr 23 2015 Petr Pisar - 8.37-0.2.RC1 +- Fix static linking (bug #1214494) +- Package pcredemo.c as a documentation for pcre-devel +- Fix JIT on AArch64 + +* Wed Apr 22 2015 Petr Pisar - 8.37-0.1.RC1 +- 8.37 RC1 bump + +* Thu Apr 09 2015 Petr Pisar - 8.36-5 +- Fix computing size for pattern with a negated special calss in on-UCP mode + (bug #1210383) +- Fix compilation of a pattern with mutual recursion nested inside other group + (bug #1210393) +- Fix compilation of a parenthesized comment (bug #1210410) +- Fix compliation of mutual recursion inside a lookbehind assertion + (bug #1210417) +- Fix pcregrep loop when \K is used in a lookbehind assertion (bug #1210423) +- Fix pcretest loop when \K is used in a lookbehind assertion (bug #1210423) +- Fix backtracking for \C\X* in UTF-8 mode (bug #1210576) + +* Thu Mar 26 2015 Petr Pisar - 8.36-4 +- Fix computing size of JIT read-only data (bug #1206131) + +* Thu Feb 19 2015 David Tardon - 8.36-3.1 +- rebuild for C++ stdlib API changes in gcc5 + +* Thu Nov 20 2014 Petr Pisar - 8.36-3 +- Fix CVE-2014-8964 (unused memory usage on zero-repeat assertion condition) + (bug #1165626) + +* Fri Nov 07 2014 Petr Pisar - 8.36-2 +- Reset non-matched groups within capturing group up to forced match + (bug #1161587) + +* Tue Oct 07 2014 Petr Pisar - 8.36-1 +- 8.36 bump + +* Tue Sep 16 2014 Petr Pisar - 8.36-0.1.RC1 +- 8.36 RC1 bump +- Enable JIT on aarch64 + +* Sun Aug 17 2014 Fedora Release Engineering - 8.35-6.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Mon Aug 11 2014 Petr Pisar - 8.35-6 +- Fix compile-time loop for recursive reference within a group with an + indefinite repeat (bug #1128577) + +* Wed Jul 30 2014 Tom Callaway - 8.35-5 +- fix license handling + +* Mon Jul 14 2014 Petr Pisar - 8.35-4 +- Fix empty-matching possessive zero-repeat groups in interpreted mode + (bug #1119241) +- Fix memory leaks in pcregrep (bug #1119257) +- Fix compiler crash for zero-repeated groups with a recursive back reference + (bug #1119272) + +* Thu Jun 19 2014 Petr Pisar - 8.35-3 +- Fix bad starting data when char with more than one other case follows + circumflex in multiline UTF mode (bug #1110620) +- Fix not including VT in starting characters for \s if pcre_study() is used + (bug #1111045) +- Fix character class with a literal quotation (bug #1111054) + +* Fri Jun 06 2014 Fedora Release Engineering - 8.35-2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Fri Apr 11 2014 Petr Pisar - 8.35-2 +- Do no rely on wrapping signed integer while parsing {min,max} expression + (bug #1086630) + +* Wed Apr 09 2014 Petr Pisar - 8.35-1 +- 8.35 bump +- Run tests in parallel + +* Fri Mar 14 2014 Petr Pisar - 8.35-0.1.RC1 +- 8.35-RC1 bump + +* Tue Mar 11 2014 Petr Pisar - 8.34-4 +- Fix max/min quantifiers in ungreedy mode (bug #1074500) + +* Tue Jan 21 2014 Dan Horák - 8.34-3 +- enlarge stack for tests on s390x + +* Thu Jan 09 2014 Petr Pisar - 8.34-2 +- Fix jitted range check (bug #1048097) + +* Mon Dec 16 2013 Petr Pisar - 8.34-1 +- 8.34 bump + +* Wed Oct 16 2013 Petr Pisar - 8.33-3 +- Disable strict-aliasing on PPC64 (bug #881232) + +* Sat Aug 03 2013 Fedora Release Engineering - 8.33-2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Mon Jun 03 2013 Petr Pisar - 8.33-2 +- Disable unsupported JIT on aarch64 (bug #969693) + +* Thu May 30 2013 Petr Pisar - 8.33-1 +- 8.33 bump + +* Thu May 16 2013 Petr Pisar - 8.33-0.3.RC1 +- Fix passing too small output vector to pcre_dfa_exec (bug #963284) + +* Mon May 13 2013 Petr Pisar - 8.33-0.2.RC1 +- Fix bad handling of empty lines in pcregrep tool (bug #961789) +- Fix possible pcretest crash with a data line longer than 65536 bytes + +* Thu May 02 2013 Petr Pisar - 8.33-0.1.RC1 +- 8.33-RC1 bump + +* Mon Jan 28 2013 Petr Pisar - 8.32-4 +- Fix forward search in JIT when link size is 3 or greater +- Fix buffer over-read in UTF-16 and UTF-32 modes with JIT + +* Fri Jan 25 2013 Peter Robinson 8.32-3 +- Adjust autoreconf to fix FTBFS on F-19 + +* Mon Jan 07 2013 Petr Pisar - 8.32-2 +- Make inter-subpackage dependencies architecture specific (bug #892187) + +* Fri Nov 30 2012 Petr Pisar - 8.32-1 +- 8.32 bump + +* Thu Nov 29 2012 Petr Pisar - 8.32-0.2.RC1 +- Inter-depend sub-packages to prevent from mixing different versions + +* Tue Nov 13 2012 Petr Pisar - 8.32-0.1.RC1 +- 8.32-RC1 bump + +* Mon Sep 03 2012 Petr Pisar - 8.31-2 +- Set re_nsub in regcomp() properly (bug #853990) + +* Fri Jul 20 2012 Fedora Release Engineering - 8.31-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Fri Jul 13 2012 Petr Pisar - 8.31-1 +- 8.31 bump + +* Tue Jun 05 2012 Petr Pisar - 8.31-0.1.RC1 +- 8.31-RC1 bump + +* Sat May 12 2012 Tom Callaway - 8.30-7 +- disable jit for sparcv9 and sparc64 + +* Fri May 11 2012 Petr Pisar - 8.30-6 +- Fix spelling in manual pages (bug #820978) + +* Mon Apr 23 2012 Petr Pisar - 8.30-5 +- Possessify high ASCII (bug #815217) +- Fix ovector overflow (bug #815214) + +* Fri Apr 20 2012 Petr Pisar - 8.30-4 +- Possesify \s*\R (bug #813237) + +* Thu Apr 05 2012 Petr Pisar - 8.30-3 +- Fix look-behind assertion in UTF-8 JIT mode (bug #810314) + +* Tue Feb 28 2012 Petr Pisar - 8.30-2 +- Remove old libpcre.so.0 from distribution +- Move library to /usr + +* Thu Feb 09 2012 Petr Pisar - 8.30-1 +- 8.30 bump +- Add old libpcre.so.0 to preserve compatibility temporarily + +* Fri Jan 27 2012 Petr Pisar - 8.30-0.1.RC1 +- 8.30 Relase candidate 1 with UTF-16 support and *API change* +- Enable UTF-16 variant of PCRE library +- The pcre_info() function has been removed from pcre library. +- Loading compiled pattern does not fix endianity anymore. Instead an errror + is returned and the application can use pcre_pattern_to_host_byte_order() to + convert the pattern. +- Surrogates (0xD800---0xDFFF) are forbidden in UTF-8 mode now. + +* Fri Jan 13 2012 Fedora Release Engineering - 8.21-2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Mon Jan 02 2012 Petr Pisar - 8.21-2 +- Fix unmatched subpattern to not become wildcard (bug #769597) +- Fix NULL pointer derefernce in pcre_free_study() (upstream bug #1186) + +* Mon Dec 12 2011 Petr Pisar - 8.21-1 +- 8.21 bump + +* Thu Dec 08 2011 Karsten Hopp 8.21-0.2.RC1 +- ppc needs a larger stack similar to s390 + +* Tue Dec 06 2011 Petr Pisar - 8.21-0.1.RC1 +- 8.21-RC1 bump + +* Fri Dec 02 2011 Petr Pisar - 8.20-7 +- Fix case-less match if cases differ in encoding length (bug #756675) + +* Fri Nov 25 2011 Petr Pisar - 8.20-6 +- Fix cache-flush in JIT on PPC + +* Tue Nov 22 2011 Petr Pisar - 8.20-5 +- Fix repeated forward reference (bug #755969) + +* Wed Nov 16 2011 Petr Pisar - 8.20-4 +- Fix other look-behind regressions + +* Tue Nov 15 2011 Petr Pisar - 8.20-3 +- Fix look-behind regression in 8.20 + +* Tue Nov 15 2011 Dan Horák - 8.20-2 +- fix build on s390(x) - disable jit and use larger stack for tests + +* Fri Oct 21 2011 Petr Pisar - 8.20-1 +- 8.20 bump + +* Tue Oct 11 2011 Petr Pisar - 8.20-0.1.RC3 +- 8.20-RC3 bump + +* Fri Sep 23 2011 Petr Pisar - 8.20-0.1.RC2 +- 8.20-RC2 bump + +* Mon Sep 12 2011 Petr Pisar - 8.20-0.1.RC1 +- 8.20-RC1 bump with JIT + +* Tue Sep 06 2011 Petr Pisar - 8.13-4 +- Fix infinite matching PRUNE (bug #735720) + +* Mon Aug 22 2011 Petr Pisar - 8.13-3 +- Fix parsing named class in expression (bug #732368) + +* Thu Aug 18 2011 Petr Pisar - 8.13-2 +- Separate utilities from libraries +- Move pcre-config(1) manual to pcre-devel sub-package +- Remove explicit defattr from spec code +- Compile pcretest with readline support + +* Thu Aug 18 2011 Petr Pisar - 8.13-1 +- 8.13 bump: Bug-fix version, Unicode tables updated to 6.0.0, new pcregrep + option --buffer-size to adjust to long lines, new feature is passing of + *MARK information to callouts. +- Should fix crash back-tracking over unicode sequence (bug #691319) + +* Mon May 09 2011 Petr Pisar - 8.12-4 +- Fix caseless reference matching in UTF-8 mode when the upper/lower case + characters have different lengths (bug #702623) + +* Mon May 09 2011 Petr Pisar - 8.12-3 +- Fix typos in manual pages (bugs #675476, #675477) +- Clean spec file up + +* Tue Feb 08 2011 Fedora Release Engineering - 8.12-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Mon Jan 17 2011 Petr Pisar - 8.12-1 +- 8.12 bump +- Remove accepted pcre-8.11-Fix-typo-in-pcreprecompile-3.patch + +* Mon Dec 13 2010 Petr Pisar - 8.11-1 +- 8.11 bump +- See ChangeLog for changes. Namely changes have been made to the way + PCRE_PARTIAL_HARD affects the matching of $, \z, \Z, \b, and \B. +- Fix typo in pcreprecompile(3) manual +- Document why shared library is not under /usr + +* Mon Jul 12 2010 Petr Pisar - 8.10-1 +- 8.10 bump (bug #612635) +- Add LICENCE to static subpackage because COPYING refers to it +- Remove useless rpath by using new libtool (simple sed does not work anymore + because tests need to link against just-compiled library in %%check phase) + +* Thu Jul 08 2010 Petr Pisar - 7.8-4 +- Add COPYING to static subpackage +- Remove useless rpath + +* Sat Jul 25 2009 Fedora Release Engineering - 7.8-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Thu Feb 26 2009 Fedora Release Engineering - 7.8-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Wed Oct 1 2008 Lubomir Rintel - 7.8-1 +- Update to 7.8, drop upstreamed patches +- Fix destination of documentation (#427763) +- Use buildroot macro consistently +- Separate the static library, as per current Guidelines +- Satisfy rpmlint + +* Fri Jul 4 2008 Tomas Hoger - 7.3-4 +- Apply Tavis Ormandy's patch for CVE-2008-2371. + +* Tue Feb 12 2008 Tomas Hoger - 7.3-3 +- Backport patch from upstream pcre 7.6 to address buffer overflow + caused by "a character class containing a very large number of + characters with codepoints greater than 255 (in UTF-8 mode)" + CVE-2008-0674, #431660 +- Try re-enabling make check again. + +* Fri Nov 16 2007 Stepan Kasal - 7.3-2 +- Remove obsolete ``reqs'' +- add dist tag +- update BuildRoot + +* Mon Sep 17 2007 Than Ngo - 7.3-1 +- bz292501, update to 7.3 + +* Mon Jan 22 2007 Than Ngo - 7.0-1 +- 7.0 + +* Mon Nov 27 2006 Than Ngo - 6.7-1 +- update to 6.7 +- fix #217303, enable-unicode-properties +- sane stack limit + +* Wed Jul 12 2006 Jesse Keating - 6.6-1.1 +- rebuild + +* Tue May 09 2006 Than Ngo 6.6-1 +- update to 6.6 +- fix multilib problem + +* Fri Feb 10 2006 Jesse Keating - 6.3-1.2.1 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 6.3-1.2 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Wed Aug 24 2005 Than Ngo 6.3-1 +- update to 6.3 + +* Fri Mar 4 2005 Joe Orton 5.0-4 +- rebuild + +* Fri Feb 11 2005 Joe Orton 5.0-3 +- don't print $libdir in 'pcre-config --libs' output + +* Thu Nov 18 2004 Joe Orton 5.0-2 +- include LICENCE, AUTHORS in docdir +- run make check +- move %%configure to %%build + +* Thu Nov 18 2004 Than Ngo 5.0-1 +- update to 5.0 +- change License: BSD +- fix header location #64248 + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Tue Mar 23 2004 Than Ngo 4.5-2 +- add the correct pcre license, #118781 + +* Fri Mar 12 2004 Than Ngo 4.5-1 +- update to 4.5 + +* Tue Mar 02 2004 Elliot Lee +- rebuilt + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Fri Sep 26 2003 Harald Hoyer 4.4-1 +- 4.4 + +* Wed Jun 04 2003 Elliot Lee +- rebuilt + +* Wed May 7 2003 Than Ngo 4.2-1 +- update to 4.2 + +* Wed Jan 22 2003 Tim Powers +- rebuilt + +* Tue Jan 21 2003 Than Ngo 3.9-9 +- build with utf8, bug #81504 + +* Fri Nov 22 2002 Elliot Lee 3.9-8 +- Really remove .la files + +* Fri Oct 11 2002 Than Ngo 3.9-7 +- remove .la + +* Thu Oct 10 2002 Than Ngo 3.9-7 +- Typo bug + +* Wed Oct 9 2002 Than Ngo 3.9-6 +- Added missing so symlink + +* Thu Sep 19 2002 Than Ngo 3.9-5.1 +- Fixed to build s390/s390x/x86_64 + +* Thu Jun 27 2002 Bernhard Rosenkraenzer 3.9-5 +- Fix #65009 + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Thu May 23 2002 Tim Powers +- automated rebuild + +* Mon Mar 4 2002 Bernhard Rosenkraenzer 3.9-2 +- rebuild + +* Fri Jan 11 2002 Bernhard Rosenkraenzer 3.9-1 +- Update to 3.9 + +* Wed Nov 14 2001 Bernhard Rosenkraenzer 3.7-1 +- Update to 3.7 + +* Thu May 17 2001 Bernhard Rosenkraenzer 3.4-2 +- Move libpcre to /lib, grep uses it these days (#41104) + +* Wed Apr 18 2001 Bernhard Rosenkraenzer +- Move this to a separate package, used to be in kdesupport, but it's + generally useful...