Update PCRE2 to 10.38
[ChangeLog][Third-Party Code] PCRE2 has been updated to version 10.38. Change-Id: Ib6ab544790747a94a00b8eb516314ff3c57e4c79 Pick-to: 6.2 5.15 Reviewed-by: Lars Knoll <lars.knoll@qt.io>bb10
parent
f6fa78fd60
commit
b4e290a9ab
|
|
@ -5,7 +5,7 @@ Written by: Philip Hazel
|
|||
Email local part: Philip.Hazel
|
||||
Email domain: gmail.com
|
||||
|
||||
University of Cambridge Computing Service,
|
||||
Retired from University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2021 University of Cambridge
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ Written by: Philip Hazel
|
|||
Email local part: Philip.Hazel
|
||||
Email domain: gmail.com
|
||||
|
||||
University of Cambridge Computing Service,
|
||||
Retired from University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2021 University of Cambridge
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
"Description": "The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl 5.",
|
||||
"Homepage": "http://www.pcre.org/",
|
||||
"Version": "10.37",
|
||||
"DownloadLocation": "https://ftp.pcre.org/pub/pcre/pcre2-10.37.tar.bz2",
|
||||
"Version": "10.38",
|
||||
"DownloadLocation": "https://github.com/PhilipHazel/pcre2/releases/download/pcre2-10.38/pcre2-10.38.tar.bz2",
|
||||
"License": "BSD 3-clause \"New\" or \"Revised\" License",
|
||||
"LicenseId": "BSD-3-Clause",
|
||||
"LicenseFile": "LICENCE",
|
||||
|
|
@ -24,8 +24,8 @@ Copyright (c) 2010-2020 Zoltan Herczeg"
|
|||
"Path": "src/sljit",
|
||||
"Description": "The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl 5.",
|
||||
"Homepage": "http://www.pcre.org/",
|
||||
"Version": "10.37",
|
||||
"DownloadLocation": "https://ftp.pcre.org/pub/pcre/pcre2-10.37.tar.bz2",
|
||||
"Version": "10.38",
|
||||
"DownloadLocation": "https://github.com/PhilipHazel/pcre2/releases/download/pcre2-10.38/pcre2-10.38.tar.bz2",
|
||||
"License": "BSD 2-clause \"Simplified\" License",
|
||||
"LicenseId": "BSD-2-Clause",
|
||||
"LicenseFile": "LICENCE-SLJIT",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
/* This is the public header file for the PCRE library, second API, to be
|
||||
#included by applications that call PCRE2 functions.
|
||||
|
||||
Copyright (c) 2016-2020 University of Cambridge
|
||||
Copyright (c) 2016-2021 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
/* The current PCRE version information. */
|
||||
|
||||
#define PCRE2_MAJOR 10
|
||||
#define PCRE2_MINOR 37
|
||||
#define PCRE2_MINOR 38
|
||||
#define PCRE2_PRERELEASE
|
||||
#define PCRE2_DATE 2021-05-26
|
||||
#define PCRE2_DATE 2021-10-01
|
||||
|
||||
/* When an application links to a PCRE DLL in Windows, the symbols that are
|
||||
imported have to be identified as such. When building PCRE2, the appropriate
|
||||
|
|
@ -152,6 +152,7 @@ D is inspected during pcre2_dfa_match() execution
|
|||
#define PCRE2_EXTRA_MATCH_LINE 0x00000008u /* C */
|
||||
#define PCRE2_EXTRA_ESCAPED_CR_IS_LF 0x00000010u /* C */
|
||||
#define PCRE2_EXTRA_ALT_BSUX 0x00000020u /* C */
|
||||
#define PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK 0x00000040u /* C */
|
||||
|
||||
/* These are for pcre2_jit_compile(). */
|
||||
|
||||
|
|
@ -311,6 +312,7 @@ pcre2_pattern_convert(). */
|
|||
#define PCRE2_ERROR_SCRIPT_RUN_NOT_AVAILABLE 196
|
||||
#define PCRE2_ERROR_TOO_MANY_CAPTURES 197
|
||||
#define PCRE2_ERROR_CONDITION_ATOMIC_ASSERTION_EXPECTED 198
|
||||
#define PCRE2_ERROR_BACKSLASH_K_IN_LOOKAROUND 199
|
||||
|
||||
|
||||
/* "Expected" matching error codes: no match and partial match. */
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
|
|||
|
||||
Written by Philip Hazel
|
||||
Original API code Copyright (c) 1997-2012 University of Cambridge
|
||||
New API code Copyright (c) 2016-2020 University of Cambridge
|
||||
New API code Copyright (c) 2016-2021 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -137,7 +137,7 @@ static BOOL
|
|||
|
||||
static int
|
||||
check_lookbehinds(uint32_t *, uint32_t **, parsed_recurse_check *,
|
||||
compile_block *);
|
||||
compile_block *, int *);
|
||||
|
||||
|
||||
/*************************************************
|
||||
|
|
@ -782,12 +782,15 @@ are allowed. */
|
|||
#define PUBLIC_COMPILE_EXTRA_OPTIONS \
|
||||
(PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS| \
|
||||
PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES|PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL| \
|
||||
PCRE2_EXTRA_ESCAPED_CR_IS_LF|PCRE2_EXTRA_ALT_BSUX)
|
||||
PCRE2_EXTRA_ESCAPED_CR_IS_LF|PCRE2_EXTRA_ALT_BSUX| \
|
||||
PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK)
|
||||
|
||||
/* Compile time error code numbers. They are given names so that they can more
|
||||
easily be tracked. When a new number is added, the tables called eint1 and
|
||||
eint2 in pcre2posix.c may need to be updated, and a new error text must be
|
||||
added to compile_error_texts in pcre2_error.c. */
|
||||
added to compile_error_texts in pcre2_error.c. Also, the error codes in
|
||||
pcre2.h.in must be updated - their values are exactly 100 greater than these
|
||||
values. */
|
||||
|
||||
enum { ERR0 = COMPILE_ERROR_BASE,
|
||||
ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10,
|
||||
|
|
@ -799,7 +802,7 @@ enum { ERR0 = COMPILE_ERROR_BASE,
|
|||
ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70,
|
||||
ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, ERR80,
|
||||
ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88, ERR89, ERR90,
|
||||
ERR91, ERR92, ERR93, ERR94, ERR95, ERR96, ERR97, ERR98 };
|
||||
ERR91, ERR92, ERR93, ERR94, ERR95, ERR96, ERR97, ERR98, ERR99 };
|
||||
|
||||
/* This is a table of start-of-pattern options such as (*UTF) and settings such
|
||||
as (*LIMIT_MATCH=nnnn) and (*CRLF). For completeness and backward
|
||||
|
|
@ -7799,6 +7802,16 @@ for (;; pptr++)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* \K is forbidden in lookarounds since 10.38 because that's what Perl has
|
||||
done. However, there's an option, in case anyone was relying on it. */
|
||||
|
||||
if (cb->assert_depth > 0 && meta_arg == ESC_K &&
|
||||
(cb->cx->extra_options & PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK) == 0)
|
||||
{
|
||||
*errorcodeptr = ERR99;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For the rest (including \X when Unicode is supported - if not it's
|
||||
faulted at parse time), the OP value is the escape value when PCRE2_UCP is
|
||||
not set; if it is set, these escapes do not show up here because they are
|
||||
|
|
@ -9148,7 +9161,7 @@ for (;; pptr++)
|
|||
case META_LOOKAHEAD:
|
||||
case META_LOOKAHEADNOT:
|
||||
case META_LOOKAHEAD_NA:
|
||||
*errcodeptr = check_lookbehinds(pptr + 1, &pptr, recurses, cb);
|
||||
*errcodeptr = check_lookbehinds(pptr + 1, &pptr, recurses, cb, lcptr);
|
||||
if (*errcodeptr != 0) return -1;
|
||||
|
||||
/* Ignore any qualifiers that follow a lookahead assertion. */
|
||||
|
|
@ -9488,16 +9501,16 @@ Arguments
|
|||
retptr if not NULL, return the ket pointer here
|
||||
recurses chain of recurse_check to catch mutual recursion
|
||||
cb points to the compile block
|
||||
lcptr points to loop counter
|
||||
|
||||
Returns: 0 on success, or an errorcode (cb->erroroffset will be set)
|
||||
*/
|
||||
|
||||
static int
|
||||
check_lookbehinds(uint32_t *pptr, uint32_t **retptr,
|
||||
parsed_recurse_check *recurses, compile_block *cb)
|
||||
parsed_recurse_check *recurses, compile_block *cb, int *lcptr)
|
||||
{
|
||||
int errorcode = 0;
|
||||
int loopcount = 0;
|
||||
int nestlevel = 0;
|
||||
|
||||
cb->erroroffset = PCRE2_UNSET;
|
||||
|
|
@ -9623,7 +9636,7 @@ for (; *pptr != META_END; pptr++)
|
|||
case META_LOOKBEHIND:
|
||||
case META_LOOKBEHINDNOT:
|
||||
case META_LOOKBEHIND_NA:
|
||||
if (!set_lookbehind_lengths(&pptr, &errorcode, &loopcount, recurses, cb))
|
||||
if (!set_lookbehind_lengths(&pptr, &errorcode, lcptr, recurses, cb))
|
||||
return errorcode;
|
||||
break;
|
||||
}
|
||||
|
|
@ -10078,7 +10091,8 @@ lengths. */
|
|||
|
||||
if (has_lookbehind)
|
||||
{
|
||||
errorcode = check_lookbehinds(cb.parsed_pattern, NULL, NULL, &cb);
|
||||
int loopcount = 0;
|
||||
errorcode = check_lookbehinds(cb.parsed_pattern, NULL, NULL, &cb, &loopcount);
|
||||
if (errorcode != 0) goto HAD_CB_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
|
|||
|
||||
Written by Philip Hazel
|
||||
Original API code Copyright (c) 1997-2012 University of Cambridge
|
||||
New API code Copyright (c) 2016-2020 University of Cambridge
|
||||
New API code Copyright (c) 2016-2021 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -3256,8 +3256,8 @@ BOOL has_first_cu = FALSE;
|
|||
BOOL has_req_cu = FALSE;
|
||||
|
||||
#if PCRE2_CODE_UNIT_WIDTH == 8
|
||||
BOOL memchr_not_found_first_cu = FALSE;
|
||||
BOOL memchr_not_found_first_cu2 = FALSE;
|
||||
PCRE2_SPTR memchr_found_first_cu = NULL;
|
||||
PCRE2_SPTR memchr_found_first_cu2 = NULL;
|
||||
#endif
|
||||
|
||||
PCRE2_UCHAR first_cu = 0;
|
||||
|
|
@ -3648,13 +3648,7 @@ for (;;)
|
|||
}
|
||||
}
|
||||
|
||||
/* Not anchored. Advance to a unique first code unit if there is one. In
|
||||
8-bit mode, the use of memchr() gives a big speed up, even though we have
|
||||
to call it twice in caseless mode, in order to find the earliest occurrence
|
||||
of the character in either of its cases. If a call to memchr() that
|
||||
searches the rest of the subject fails to find one case, remember that in
|
||||
order not to keep on repeating the search. This can make a huge difference
|
||||
when the strings are very long and only one case is present. */
|
||||
/* Not anchored. Advance to a unique first code unit if there is one. */
|
||||
|
||||
else
|
||||
{
|
||||
|
|
@ -3662,43 +3656,68 @@ for (;;)
|
|||
{
|
||||
if (first_cu != first_cu2) /* Caseless */
|
||||
{
|
||||
/* In 16-bit and 32_bit modes we have to do our own search, so can
|
||||
look for both cases at once. */
|
||||
|
||||
#if PCRE2_CODE_UNIT_WIDTH != 8
|
||||
PCRE2_UCHAR smc;
|
||||
while (start_match < end_subject &&
|
||||
(smc = UCHAR21TEST(start_match)) != first_cu &&
|
||||
smc != first_cu2)
|
||||
smc != first_cu2)
|
||||
start_match++;
|
||||
#else
|
||||
/* In 8-bit mode, the use of memchr() gives a big speed up, even
|
||||
though we have to call it twice in order to find the earliest
|
||||
occurrence of the code unit in either of its cases. Caching is used
|
||||
to remember the positions of previously found code units. This can
|
||||
make a huge difference when the strings are very long and only one
|
||||
case is actually present. */
|
||||
|
||||
#else /* 8-bit code units */
|
||||
PCRE2_SPTR pp1 = NULL;
|
||||
PCRE2_SPTR pp2 = NULL;
|
||||
PCRE2_SIZE cu2size = end_subject - start_match;
|
||||
PCRE2_SIZE searchlength = end_subject - start_match;
|
||||
|
||||
if (!memchr_not_found_first_cu)
|
||||
/* If we haven't got a previously found position for first_cu, or if
|
||||
the current starting position is later, we need to do a search. If
|
||||
the code unit is not found, set it to the end. */
|
||||
|
||||
if (memchr_found_first_cu == NULL ||
|
||||
start_match > memchr_found_first_cu)
|
||||
{
|
||||
pp1 = memchr(start_match, first_cu, end_subject - start_match);
|
||||
if (pp1 == NULL) memchr_not_found_first_cu = TRUE;
|
||||
else cu2size = pp1 - start_match;
|
||||
pp1 = memchr(start_match, first_cu, searchlength);
|
||||
memchr_found_first_cu = (pp1 == NULL)? end_subject : pp1;
|
||||
}
|
||||
|
||||
/* If pp1 is not NULL, we have arranged to search only as far as pp1,
|
||||
to see if the other case is earlier, so we can set "not found" only
|
||||
when both searches have returned NULL. */
|
||||
/* If the start is before a previously found position, use the
|
||||
previous position, or NULL if a previous search failed. */
|
||||
|
||||
if (!memchr_not_found_first_cu2)
|
||||
else pp1 = (memchr_found_first_cu == end_subject)? NULL :
|
||||
memchr_found_first_cu;
|
||||
|
||||
/* Do the same thing for the other case. */
|
||||
|
||||
if (memchr_found_first_cu2 == NULL ||
|
||||
start_match > memchr_found_first_cu2)
|
||||
{
|
||||
pp2 = memchr(start_match, first_cu2, cu2size);
|
||||
memchr_not_found_first_cu2 = (pp2 == NULL && pp1 == NULL);
|
||||
pp2 = memchr(start_match, first_cu2, searchlength);
|
||||
memchr_found_first_cu2 = (pp2 == NULL)? end_subject : pp2;
|
||||
}
|
||||
|
||||
else pp2 = (memchr_found_first_cu2 == end_subject)? NULL :
|
||||
memchr_found_first_cu2;
|
||||
|
||||
/* Set the start to the end of the subject if neither case was found.
|
||||
Otherwise, use the earlier found point. */
|
||||
|
||||
if (pp1 == NULL)
|
||||
start_match = (pp2 == NULL)? end_subject : pp2;
|
||||
else
|
||||
start_match = (pp2 == NULL || pp1 < pp2)? pp1 : pp2;
|
||||
#endif
|
||||
|
||||
#endif /* 8-bit handling */
|
||||
}
|
||||
|
||||
/* The caseful case */
|
||||
/* The caseful case is much simpler. */
|
||||
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
|
|||
|
||||
Written by Philip Hazel
|
||||
Original API code Copyright (c) 1997-2012 University of Cambridge
|
||||
New API code Copyright (c) 2016-2019 University of Cambridge
|
||||
New API code Copyright (c) 2016-2021 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -186,6 +186,7 @@ static const unsigned char compile_error_texts[] =
|
|||
"script runs require Unicode support, which this version of PCRE2 does not have\0"
|
||||
"too many capturing groups (maximum 65535)\0"
|
||||
"atomic assertion expected after (?( or (?(?C)\0"
|
||||
"\\K is not allowed in lookarounds (but see PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK)\0"
|
||||
;
|
||||
|
||||
/* Match-time and UTF error texts are in the same format. */
|
||||
|
|
|
|||
|
|
@ -1236,15 +1236,16 @@ start:
|
|||
|
||||
return: current number of iterators enhanced with fast fail
|
||||
*/
|
||||
static int detect_early_fail(compiler_common *common, PCRE2_SPTR cc, int *private_data_start, sljit_s32 depth, int start)
|
||||
static int detect_early_fail(compiler_common *common, PCRE2_SPTR cc, int *private_data_start,
|
||||
sljit_s32 depth, int start, BOOL fast_forward_allowed)
|
||||
{
|
||||
PCRE2_SPTR begin = cc;
|
||||
PCRE2_SPTR next_alt;
|
||||
PCRE2_SPTR end;
|
||||
PCRE2_SPTR accelerated_start;
|
||||
BOOL prev_fast_forward_allowed;
|
||||
int result = 0;
|
||||
int count;
|
||||
BOOL fast_forward_allowed = TRUE;
|
||||
|
||||
SLJIT_ASSERT(*cc == OP_ONCE || *cc == OP_BRA || *cc == OP_CBRA);
|
||||
SLJIT_ASSERT(*cc != OP_CBRA || common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] != 0);
|
||||
|
|
@ -1476,6 +1477,7 @@ do
|
|||
case OP_CBRA:
|
||||
end = cc + GET(cc, 1);
|
||||
|
||||
prev_fast_forward_allowed = fast_forward_allowed;
|
||||
fast_forward_allowed = FALSE;
|
||||
if (depth >= 4)
|
||||
break;
|
||||
|
|
@ -1484,7 +1486,7 @@ do
|
|||
if (*end != OP_KET || (*cc == OP_CBRA && common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0))
|
||||
break;
|
||||
|
||||
count = detect_early_fail(common, cc, private_data_start, depth + 1, count);
|
||||
count = detect_early_fail(common, cc, private_data_start, depth + 1, count, prev_fast_forward_allowed);
|
||||
|
||||
if (PRIVATE_DATA(cc) != 0)
|
||||
common->private_data_ptrs[begin - common->start] = 1;
|
||||
|
|
@ -8135,7 +8137,7 @@ switch(type)
|
|||
}
|
||||
else
|
||||
OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
|
||||
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
|
||||
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
|
||||
|
||||
if (!common->endonly)
|
||||
compile_simple_assertion_matchingpath(common, OP_EODN, cc, backtracks);
|
||||
|
|
@ -8155,7 +8157,7 @@ switch(type)
|
|||
}
|
||||
else
|
||||
OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
|
||||
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
|
||||
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
|
||||
check_partial(common, FALSE);
|
||||
jump[0] = JUMP(SLJIT_JUMP);
|
||||
JUMPHERE(jump[1]);
|
||||
|
|
@ -8195,14 +8197,14 @@ switch(type)
|
|||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
|
||||
add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
|
||||
OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
|
||||
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
|
||||
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
|
||||
}
|
||||
else
|
||||
{
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
|
||||
add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
|
||||
OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
|
||||
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
|
||||
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
|
||||
}
|
||||
return cc;
|
||||
|
||||
|
|
@ -8221,7 +8223,7 @@ switch(type)
|
|||
jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);
|
||||
OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
|
||||
}
|
||||
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
|
||||
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
|
||||
jump[0] = JUMP(SLJIT_JUMP);
|
||||
JUMPHERE(jump[1]);
|
||||
|
||||
|
|
@ -9575,11 +9577,11 @@ free_stack(common, callout_arg_size);
|
|||
|
||||
/* Check return value. */
|
||||
OP2(SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
|
||||
add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER32));
|
||||
add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER));
|
||||
if (common->abort_label == NULL)
|
||||
add_jump(compiler, &common->abort, JUMP(SLJIT_NOT_EQUAL32) /* SIG_LESS */);
|
||||
add_jump(compiler, &common->abort, JUMP(SLJIT_NOT_EQUAL) /* SIG_LESS */);
|
||||
else
|
||||
JUMPTO(SLJIT_NOT_EQUAL32 /* SIG_LESS */, common->abort_label);
|
||||
JUMPTO(SLJIT_NOT_EQUAL /* SIG_LESS */, common->abort_label);
|
||||
return cc + callout_length;
|
||||
}
|
||||
|
||||
|
|
@ -11226,7 +11228,7 @@ early_fail_type = (early_fail_ptr & 0x7);
|
|||
early_fail_ptr >>= 3;
|
||||
|
||||
/* During recursion, these optimizations are disabled. */
|
||||
if (common->early_fail_start_ptr == 0)
|
||||
if (common->early_fail_start_ptr == 0 && common->fast_forward_bc_ptr == NULL)
|
||||
{
|
||||
early_fail_ptr = 0;
|
||||
early_fail_type = type_skip;
|
||||
|
|
@ -13657,7 +13659,7 @@ memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_s32));
|
|||
private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);
|
||||
|
||||
if ((re->overall_options & PCRE2_ANCHORED) == 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 && !common->has_skip_in_assert_back)
|
||||
detect_early_fail(common, common->start, &private_data_size, 0, 0);
|
||||
detect_early_fail(common, common->start, &private_data_size, 0, 0, TRUE);
|
||||
|
||||
set_private_data_ptrs(common, &private_data_size, ccend);
|
||||
|
||||
|
|
|
|||
|
|
@ -1356,8 +1356,6 @@ else
|
|||
sljit_emit_op_custom(compiler, instruction, 6);
|
||||
}
|
||||
|
||||
/* TODO: use sljit_set_current_flags */
|
||||
|
||||
/* VLGVB */
|
||||
instruction[0] = (sljit_u16)(0xe700 | (tmp1_reg_ind << 4) | data_ind);
|
||||
instruction[1] = 7;
|
||||
|
|
@ -1403,7 +1401,8 @@ else
|
|||
sljit_emit_op_custom(compiler, instruction, 6);
|
||||
}
|
||||
|
||||
/* TODO: use sljit_set_current_flags */
|
||||
sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW);
|
||||
JUMPTO(SLJIT_OVERFLOW, start);
|
||||
|
||||
/* VLGVB */
|
||||
instruction[0] = (sljit_u16)(0xe700 | (tmp1_reg_ind << 4) | data_ind);
|
||||
|
|
@ -1411,8 +1410,6 @@ instruction[1] = 7;
|
|||
instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);
|
||||
sljit_emit_op_custom(compiler, instruction, 6);
|
||||
|
||||
CMPTO(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 16, start);
|
||||
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
|
||||
|
||||
JUMPHERE(quit);
|
||||
|
|
@ -1549,8 +1546,6 @@ else
|
|||
sljit_emit_op_custom(compiler, instruction, 6);
|
||||
}
|
||||
|
||||
/* TODO: use sljit_set_current_flags */
|
||||
|
||||
/* VLGVB */
|
||||
instruction[0] = (sljit_u16)(0xe700 | (tmp3_reg_ind << 4) | data_ind);
|
||||
instruction[1] = 7;
|
||||
|
|
@ -1594,7 +1589,8 @@ else
|
|||
sljit_emit_op_custom(compiler, instruction, 6);
|
||||
}
|
||||
|
||||
/* TODO: use sljit_set_current_flags */
|
||||
sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW);
|
||||
JUMPTO(SLJIT_OVERFLOW, start);
|
||||
|
||||
/* VLGVB */
|
||||
instruction[0] = (sljit_u16)(0xe700 | (tmp3_reg_ind << 4) | data_ind);
|
||||
|
|
@ -1602,8 +1598,6 @@ instruction[1] = 7;
|
|||
instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);
|
||||
sljit_emit_op_custom(compiler, instruction, 6);
|
||||
|
||||
CMPTO(SLJIT_GREATER_EQUAL, TMP3, 0, SLJIT_IMM, 16, start);
|
||||
|
||||
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP3, 0);
|
||||
|
||||
JUMPHERE(quit);
|
||||
|
|
@ -1778,8 +1772,6 @@ instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));
|
|||
instruction[2] = (sljit_u16)((0xe << 8) | 0x81);
|
||||
sljit_emit_op_custom(compiler, instruction, 6);
|
||||
|
||||
/* TODO: use sljit_set_current_flags */
|
||||
|
||||
/* VLGVB */
|
||||
instruction[0] = (sljit_u16)(0xe700 | (tmp1_reg_ind << 4) | data1_ind);
|
||||
instruction[1] = 7;
|
||||
|
|
@ -1819,7 +1811,8 @@ instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));
|
|||
instruction[2] = (sljit_u16)((0xe << 8) | 0x81);
|
||||
sljit_emit_op_custom(compiler, instruction, 6);
|
||||
|
||||
/* TODO: use sljit_set_current_flags */
|
||||
sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW);
|
||||
JUMPTO(SLJIT_OVERFLOW, start);
|
||||
|
||||
/* VLGVB */
|
||||
instruction[0] = (sljit_u16)(0xe700 | (tmp2_reg_ind << 4) | data1_ind);
|
||||
|
|
@ -1827,8 +1820,6 @@ instruction[1] = 7;
|
|||
instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);
|
||||
sljit_emit_op_custom(compiler, instruction, 6);
|
||||
|
||||
CMPTO(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 16, start);
|
||||
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
|
||||
|
||||
JUMPHERE(quit);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
|
|||
|
||||
Written by Philip Hazel
|
||||
Original API code Copyright (c) 1997-2012 University of Cambridge
|
||||
New API code Copyright (c) 2015-2020 University of Cambridge
|
||||
New API code Copyright (c) 2015-2021 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -6117,8 +6117,8 @@ BOOL has_req_cu = FALSE;
|
|||
BOOL startline;
|
||||
|
||||
#if PCRE2_CODE_UNIT_WIDTH == 8
|
||||
BOOL memchr_not_found_first_cu;
|
||||
BOOL memchr_not_found_first_cu2;
|
||||
PCRE2_SPTR memchr_found_first_cu;
|
||||
PCRE2_SPTR memchr_found_first_cu2;
|
||||
#endif
|
||||
|
||||
PCRE2_UCHAR first_cu = 0;
|
||||
|
|
@ -6712,8 +6712,8 @@ start_partial = match_partial = NULL;
|
|||
mb->hitend = FALSE;
|
||||
|
||||
#if PCRE2_CODE_UNIT_WIDTH == 8
|
||||
memchr_not_found_first_cu = FALSE;
|
||||
memchr_not_found_first_cu2 = FALSE;
|
||||
memchr_found_first_cu = NULL;
|
||||
memchr_found_first_cu2 = NULL;
|
||||
#endif
|
||||
|
||||
for(;;)
|
||||
|
|
@ -6782,13 +6782,7 @@ for(;;)
|
|||
}
|
||||
}
|
||||
|
||||
/* Not anchored. Advance to a unique first code unit if there is one. In
|
||||
8-bit mode, the use of memchr() gives a big speed up, even though we have
|
||||
to call it twice in caseless mode, in order to find the earliest occurrence
|
||||
of the character in either of its cases. If a call to memchr() that
|
||||
searches the rest of the subject fails to find one case, remember that in
|
||||
order not to keep on repeating the search. This can make a huge difference
|
||||
when the strings are very long and only one case is present. */
|
||||
/* Not anchored. Advance to a unique first code unit if there is one. */
|
||||
|
||||
else
|
||||
{
|
||||
|
|
@ -6796,43 +6790,68 @@ for(;;)
|
|||
{
|
||||
if (first_cu != first_cu2) /* Caseless */
|
||||
{
|
||||
/* In 16-bit and 32_bit modes we have to do our own search, so can
|
||||
look for both cases at once. */
|
||||
|
||||
#if PCRE2_CODE_UNIT_WIDTH != 8
|
||||
PCRE2_UCHAR smc;
|
||||
while (start_match < end_subject &&
|
||||
(smc = UCHAR21TEST(start_match)) != first_cu &&
|
||||
smc != first_cu2)
|
||||
smc != first_cu2)
|
||||
start_match++;
|
||||
#else
|
||||
/* In 8-bit mode, the use of memchr() gives a big speed up, even
|
||||
though we have to call it twice in order to find the earliest
|
||||
occurrence of the code unit in either of its cases. Caching is used
|
||||
to remember the positions of previously found code units. This can
|
||||
make a huge difference when the strings are very long and only one
|
||||
case is actually present. */
|
||||
|
||||
#else /* 8-bit code units */
|
||||
PCRE2_SPTR pp1 = NULL;
|
||||
PCRE2_SPTR pp2 = NULL;
|
||||
PCRE2_SIZE cu2size = end_subject - start_match;
|
||||
PCRE2_SIZE searchlength = end_subject - start_match;
|
||||
|
||||
if (!memchr_not_found_first_cu)
|
||||
/* If we haven't got a previously found position for first_cu, or if
|
||||
the current starting position is later, we need to do a search. If
|
||||
the code unit is not found, set it to the end. */
|
||||
|
||||
if (memchr_found_first_cu == NULL ||
|
||||
start_match > memchr_found_first_cu)
|
||||
{
|
||||
pp1 = memchr(start_match, first_cu, end_subject - start_match);
|
||||
if (pp1 == NULL) memchr_not_found_first_cu = TRUE;
|
||||
else cu2size = pp1 - start_match;
|
||||
pp1 = memchr(start_match, first_cu, searchlength);
|
||||
memchr_found_first_cu = (pp1 == NULL)? end_subject : pp1;
|
||||
}
|
||||
|
||||
/* If pp1 is not NULL, we have arranged to search only as far as pp1,
|
||||
to see if the other case is earlier, so we can set "not found" only
|
||||
when both searches have returned NULL. */
|
||||
/* If the start is before a previously found position, use the
|
||||
previous position, or NULL if a previous search failed. */
|
||||
|
||||
if (!memchr_not_found_first_cu2)
|
||||
else pp1 = (memchr_found_first_cu == end_subject)? NULL :
|
||||
memchr_found_first_cu;
|
||||
|
||||
/* Do the same thing for the other case. */
|
||||
|
||||
if (memchr_found_first_cu2 == NULL ||
|
||||
start_match > memchr_found_first_cu2)
|
||||
{
|
||||
pp2 = memchr(start_match, first_cu2, cu2size);
|
||||
memchr_not_found_first_cu2 = (pp2 == NULL && pp1 == NULL);
|
||||
pp2 = memchr(start_match, first_cu2, searchlength);
|
||||
memchr_found_first_cu2 = (pp2 == NULL)? end_subject : pp2;
|
||||
}
|
||||
|
||||
else pp2 = (memchr_found_first_cu2 == end_subject)? NULL :
|
||||
memchr_found_first_cu2;
|
||||
|
||||
/* Set the start to the end of the subject if neither case was found.
|
||||
Otherwise, use the earlier found point. */
|
||||
|
||||
if (pp1 == NULL)
|
||||
start_match = (pp2 == NULL)? end_subject : pp2;
|
||||
else
|
||||
start_match = (pp2 == NULL || pp1 < pp2)? pp1 : pp2;
|
||||
#endif
|
||||
|
||||
#endif /* 8-bit handling */
|
||||
}
|
||||
|
||||
/* The caseful case */
|
||||
/* The caseful case is much simpler. */
|
||||
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -761,6 +761,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
|
|||
#define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \
|
||||
(SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS)
|
||||
|
||||
/********************************/
|
||||
/* CPU status flags management. */
|
||||
/********************************/
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
|
||||
|| (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
|| (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
|
||||
|| (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) \
|
||||
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
#define SLJIT_HAS_STATUS_FLAGS_STATE 1
|
||||
#endif
|
||||
|
||||
/*************************************/
|
||||
/* Debug and verbose related macros. */
|
||||
/*************************************/
|
||||
|
|
|
|||
|
|
@ -532,13 +532,21 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_la
|
|||
put_label->label = label;
|
||||
}
|
||||
|
||||
#define SLJIT_CURRENT_FLAGS_ALL \
|
||||
(SLJIT_CURRENT_FLAGS_I32_OP | SLJIT_CURRENT_FLAGS_ADD_SUB | SLJIT_CURRENT_FLAGS_COMPARE)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(current_flags);
|
||||
|
||||
#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
|
||||
compiler->status_flags_state = current_flags;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
if ((current_flags & ~(VARIABLE_FLAG_MASK | SLJIT_I32_OP | SLJIT_SET_Z)) == 0) {
|
||||
compiler->last_flags = 0;
|
||||
if ((current_flags & ~(VARIABLE_FLAG_MASK | SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_ALL)) == 0) {
|
||||
compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_I32_OP | SLJIT_SET_Z));
|
||||
}
|
||||
#endif
|
||||
|
|
@ -968,7 +976,7 @@ static const char* fop2_names[] = {
|
|||
};
|
||||
|
||||
#define JUMP_POSTFIX(type) \
|
||||
((type & 0xff) <= SLJIT_MUL_NOT_OVERFLOW ? ((type & SLJIT_I32_OP) ? "32" : "") \
|
||||
((type & 0xff) <= SLJIT_NOT_OVERFLOW ? ((type & SLJIT_I32_OP) ? "32" : "") \
|
||||
: ((type & 0xff) <= SLJIT_ORDERED_F64 ? ((type & SLJIT_F32_OP) ? ".f32" : ".f64") : ""))
|
||||
|
||||
static char* jump_names[] = {
|
||||
|
|
@ -978,7 +986,6 @@ static char* jump_names[] = {
|
|||
(char*)"sig_less", (char*)"sig_greater_equal",
|
||||
(char*)"sig_greater", (char*)"sig_less_equal",
|
||||
(char*)"overflow", (char*)"not_overflow",
|
||||
(char*)"mul_overflow", (char*)"mul_not_overflow",
|
||||
(char*)"carry", (char*)"",
|
||||
(char*)"equal", (char*)"not_equal",
|
||||
(char*)"less", (char*)"greater_equal",
|
||||
|
|
@ -1278,7 +1285,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler
|
|||
case SLJIT_MUL:
|
||||
CHECK_ARGUMENT(!(op & SLJIT_SET_Z));
|
||||
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
|
||||
|| GET_FLAG_TYPE(op) == SLJIT_MUL_OVERFLOW);
|
||||
|| GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);
|
||||
break;
|
||||
case SLJIT_ADD:
|
||||
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
|
||||
|
|
@ -1601,9 +1608,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compile
|
|||
CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
|
||||
else
|
||||
CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)
|
||||
|| ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)
|
||||
|| ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW));
|
||||
CHECK_ARGUMENT((type & SLJIT_I32_OP) == (compiler->last_flags & SLJIT_I32_OP));
|
||||
|| ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW));
|
||||
}
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
|
|
@ -1818,8 +1823,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com
|
|||
CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
|
||||
else
|
||||
CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)
|
||||
|| ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)
|
||||
|| ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW));
|
||||
|| ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW));
|
||||
|
||||
FUNCTION_CHECK_DST(dst, dstw, 0);
|
||||
|
||||
|
|
@ -1858,8 +1862,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compile
|
|||
CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
|
||||
else
|
||||
CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)
|
||||
|| ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)
|
||||
|| ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW));
|
||||
|| ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW));
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
|
|
|
|||
|
|
@ -412,6 +412,10 @@ struct sljit_compiler {
|
|||
/* Executable size for statistical purposes. */
|
||||
sljit_uw executable_size;
|
||||
|
||||
#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
|
||||
sljit_s32 status_flags_state;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
sljit_s32 args;
|
||||
sljit_s32 locals_offset;
|
||||
|
|
@ -460,7 +464,7 @@ struct sljit_compiler {
|
|||
|
||||
#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
/* Need to allocate register save area to make calls. */
|
||||
sljit_s32 have_save_area;
|
||||
sljit_s32 mode;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
|
|
@ -996,7 +1000,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
#define SLJIT_SUBC (SLJIT_OP2_BASE + 3)
|
||||
#define SLJIT_SUBC32 (SLJIT_SUBC | SLJIT_I32_OP)
|
||||
/* Note: integer mul
|
||||
Flags: MUL_OVERFLOW */
|
||||
Flags: OVERFLOW */
|
||||
#define SLJIT_MUL (SLJIT_OP2_BASE + 4)
|
||||
#define SLJIT_MUL32 (SLJIT_MUL | SLJIT_I32_OP)
|
||||
/* Flags: Z */
|
||||
|
|
@ -1141,89 +1145,69 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
|
|||
|
||||
/* Integer comparison types. */
|
||||
#define SLJIT_EQUAL 0
|
||||
#define SLJIT_EQUAL32 (SLJIT_EQUAL | SLJIT_I32_OP)
|
||||
#define SLJIT_ZERO 0
|
||||
#define SLJIT_ZERO32 (SLJIT_ZERO | SLJIT_I32_OP)
|
||||
#define SLJIT_ZERO SLJIT_EQUAL
|
||||
#define SLJIT_NOT_EQUAL 1
|
||||
#define SLJIT_NOT_EQUAL32 (SLJIT_NOT_EQUAL | SLJIT_I32_OP)
|
||||
#define SLJIT_NOT_ZERO 1
|
||||
#define SLJIT_NOT_ZERO32 (SLJIT_NOT_ZERO | SLJIT_I32_OP)
|
||||
#define SLJIT_NOT_ZERO SLJIT_NOT_EQUAL
|
||||
|
||||
#define SLJIT_LESS 2
|
||||
#define SLJIT_LESS32 (SLJIT_LESS | SLJIT_I32_OP)
|
||||
#define SLJIT_SET_LESS SLJIT_SET(SLJIT_LESS)
|
||||
#define SLJIT_GREATER_EQUAL 3
|
||||
#define SLJIT_GREATER_EQUAL32 (SLJIT_GREATER_EQUAL | SLJIT_I32_OP)
|
||||
#define SLJIT_SET_GREATER_EQUAL SLJIT_SET(SLJIT_GREATER_EQUAL)
|
||||
#define SLJIT_GREATER 4
|
||||
#define SLJIT_GREATER32 (SLJIT_GREATER | SLJIT_I32_OP)
|
||||
#define SLJIT_SET_GREATER SLJIT_SET(SLJIT_GREATER)
|
||||
#define SLJIT_LESS_EQUAL 5
|
||||
#define SLJIT_LESS_EQUAL32 (SLJIT_LESS_EQUAL | SLJIT_I32_OP)
|
||||
#define SLJIT_SET_LESS_EQUAL SLJIT_SET(SLJIT_LESS_EQUAL)
|
||||
#define SLJIT_SIG_LESS 6
|
||||
#define SLJIT_SIG_LESS32 (SLJIT_SIG_LESS | SLJIT_I32_OP)
|
||||
#define SLJIT_SET_SIG_LESS SLJIT_SET(SLJIT_SIG_LESS)
|
||||
#define SLJIT_SIG_GREATER_EQUAL 7
|
||||
#define SLJIT_SIG_GREATER_EQUAL32 (SLJIT_SIG_GREATER_EQUAL | SLJIT_I32_OP)
|
||||
#define SLJIT_SET_SIG_GREATER_EQUAL SLJIT_SET(SLJIT_SIG_GREATER_EQUAL)
|
||||
#define SLJIT_SIG_GREATER 8
|
||||
#define SLJIT_SIG_GREATER32 (SLJIT_SIG_GREATER | SLJIT_I32_OP)
|
||||
#define SLJIT_SET_SIG_GREATER SLJIT_SET(SLJIT_SIG_GREATER)
|
||||
#define SLJIT_SIG_LESS_EQUAL 9
|
||||
#define SLJIT_SIG_LESS_EQUAL32 (SLJIT_SIG_LESS_EQUAL | SLJIT_I32_OP)
|
||||
#define SLJIT_SET_SIG_LESS_EQUAL SLJIT_SET(SLJIT_SIG_LESS_EQUAL)
|
||||
|
||||
#define SLJIT_OVERFLOW 10
|
||||
#define SLJIT_OVERFLOW32 (SLJIT_OVERFLOW | SLJIT_I32_OP)
|
||||
#define SLJIT_SET_OVERFLOW SLJIT_SET(SLJIT_OVERFLOW)
|
||||
#define SLJIT_NOT_OVERFLOW 11
|
||||
#define SLJIT_NOT_OVERFLOW32 (SLJIT_NOT_OVERFLOW | SLJIT_I32_OP)
|
||||
|
||||
#define SLJIT_MUL_OVERFLOW 12
|
||||
#define SLJIT_MUL_OVERFLOW32 (SLJIT_MUL_OVERFLOW | SLJIT_I32_OP)
|
||||
#define SLJIT_SET_MUL_OVERFLOW SLJIT_SET(SLJIT_MUL_OVERFLOW)
|
||||
#define SLJIT_MUL_NOT_OVERFLOW 13
|
||||
#define SLJIT_MUL_NOT_OVERFLOW32 (SLJIT_MUL_NOT_OVERFLOW | SLJIT_I32_OP)
|
||||
|
||||
/* There is no SLJIT_CARRY or SLJIT_NOT_CARRY. */
|
||||
#define SLJIT_SET_CARRY SLJIT_SET(14)
|
||||
#define SLJIT_SET_CARRY SLJIT_SET(12)
|
||||
|
||||
/* Floating point comparison types. */
|
||||
#define SLJIT_EQUAL_F64 16
|
||||
#define SLJIT_EQUAL_F64 14
|
||||
#define SLJIT_EQUAL_F32 (SLJIT_EQUAL_F64 | SLJIT_F32_OP)
|
||||
#define SLJIT_SET_EQUAL_F SLJIT_SET(SLJIT_EQUAL_F64)
|
||||
#define SLJIT_NOT_EQUAL_F64 17
|
||||
#define SLJIT_NOT_EQUAL_F64 15
|
||||
#define SLJIT_NOT_EQUAL_F32 (SLJIT_NOT_EQUAL_F64 | SLJIT_F32_OP)
|
||||
#define SLJIT_SET_NOT_EQUAL_F SLJIT_SET(SLJIT_NOT_EQUAL_F64)
|
||||
#define SLJIT_LESS_F64 18
|
||||
#define SLJIT_LESS_F64 16
|
||||
#define SLJIT_LESS_F32 (SLJIT_LESS_F64 | SLJIT_F32_OP)
|
||||
#define SLJIT_SET_LESS_F SLJIT_SET(SLJIT_LESS_F64)
|
||||
#define SLJIT_GREATER_EQUAL_F64 19
|
||||
#define SLJIT_GREATER_EQUAL_F64 17
|
||||
#define SLJIT_GREATER_EQUAL_F32 (SLJIT_GREATER_EQUAL_F64 | SLJIT_F32_OP)
|
||||
#define SLJIT_SET_GREATER_EQUAL_F SLJIT_SET(SLJIT_GREATER_EQUAL_F64)
|
||||
#define SLJIT_GREATER_F64 20
|
||||
#define SLJIT_GREATER_F64 18
|
||||
#define SLJIT_GREATER_F32 (SLJIT_GREATER_F64 | SLJIT_F32_OP)
|
||||
#define SLJIT_SET_GREATER_F SLJIT_SET(SLJIT_GREATER_F64)
|
||||
#define SLJIT_LESS_EQUAL_F64 21
|
||||
#define SLJIT_LESS_EQUAL_F64 19
|
||||
#define SLJIT_LESS_EQUAL_F32 (SLJIT_LESS_EQUAL_F64 | SLJIT_F32_OP)
|
||||
#define SLJIT_SET_LESS_EQUAL_F SLJIT_SET(SLJIT_LESS_EQUAL_F64)
|
||||
#define SLJIT_UNORDERED_F64 22
|
||||
#define SLJIT_UNORDERED_F64 20
|
||||
#define SLJIT_UNORDERED_F32 (SLJIT_UNORDERED_F64 | SLJIT_F32_OP)
|
||||
#define SLJIT_SET_UNORDERED_F SLJIT_SET(SLJIT_UNORDERED_F64)
|
||||
#define SLJIT_ORDERED_F64 23
|
||||
#define SLJIT_ORDERED_F64 21
|
||||
#define SLJIT_ORDERED_F32 (SLJIT_ORDERED_F64 | SLJIT_F32_OP)
|
||||
#define SLJIT_SET_ORDERED_F SLJIT_SET(SLJIT_ORDERED_F64)
|
||||
|
||||
/* Unconditional jump types. */
|
||||
#define SLJIT_JUMP 24
|
||||
#define SLJIT_JUMP 22
|
||||
/* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */
|
||||
#define SLJIT_FAST_CALL 25
|
||||
#define SLJIT_FAST_CALL 23
|
||||
/* Called function must be declared with the SLJIT_FUNC attribute. */
|
||||
#define SLJIT_CALL 26
|
||||
#define SLJIT_CALL 24
|
||||
/* Called function must be declared with cdecl attribute.
|
||||
This is the default attribute for C functions. */
|
||||
#define SLJIT_CALL_CDECL 27
|
||||
#define SLJIT_CALL_CDECL 25
|
||||
|
||||
/* The target can be changed during runtime (see: sljit_set_jump_addr). */
|
||||
#define SLJIT_REWRITABLE_JUMP 0x1000
|
||||
|
|
@ -1534,8 +1518,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
|
|||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, sljit_s32 size);
|
||||
|
||||
/* Define the currently available CPU status flags. It is usually used after an
|
||||
sljit_emit_op_custom call to define which flags are set. */
|
||||
/* Flags were set by a 32 bit operation. */
|
||||
#define SLJIT_CURRENT_FLAGS_I32_OP SLJIT_I32_OP
|
||||
|
||||
/* Flags were set by an ADD, ADDC, SUB, SUBC, or NEG operation. */
|
||||
#define SLJIT_CURRENT_FLAGS_ADD_SUB 0x01
|
||||
|
||||
/* Flags were set by a SUB with unused destination.
|
||||
Must be combined with SLJIT_CURRENT_FLAGS_ADD_SUB. */
|
||||
#define SLJIT_CURRENT_FLAGS_COMPARE 0x02
|
||||
|
||||
/* Define the currently available CPU status flags. It is usually used after
|
||||
an sljit_emit_label or sljit_emit_op_custom operations to define which CPU
|
||||
status flags are available.
|
||||
|
||||
The current_flags must be a valid combination of SLJIT_SET_* and
|
||||
SLJIT_CURRENT_FLAGS_* constants. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler,
|
||||
sljit_s32 current_flags);
|
||||
|
|
|
|||
|
|
@ -1197,6 +1197,8 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
|||
|
||||
case SLJIT_ADD:
|
||||
SLJIT_ASSERT(!(flags & INV_IMM));
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
|
||||
if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED))
|
||||
return push_inst(compiler, CMN | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
|
||||
return push_inst(compiler, ADD | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
|
||||
|
|
@ -1207,6 +1209,8 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
|||
|
||||
case SLJIT_SUB:
|
||||
SLJIT_ASSERT(!(flags & INV_IMM));
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
|
||||
if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED))
|
||||
return push_inst(compiler, CMP | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
|
||||
return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SUB : RSB) | (flags & SET_FLAGS)
|
||||
|
|
@ -1220,6 +1224,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
|||
case SLJIT_MUL:
|
||||
SLJIT_ASSERT(!(flags & INV_IMM));
|
||||
SLJIT_ASSERT(!(src2 & SRC2_IMM));
|
||||
compiler->status_flags_state = 0;
|
||||
|
||||
if (!HAS_FLAGS(op))
|
||||
return push_inst(compiler, MUL | (reg_map[dst] << 16) | (reg_map[src2] << 8) | reg_map[src1]);
|
||||
|
|
@ -2153,16 +2158,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
|
|||
/* Conditional instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static sljit_uw get_cc(sljit_s32 type)
|
||||
static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
|
||||
{
|
||||
switch (type) {
|
||||
case SLJIT_EQUAL:
|
||||
case SLJIT_MUL_NOT_OVERFLOW:
|
||||
case SLJIT_EQUAL_F64:
|
||||
return 0x00000000;
|
||||
|
||||
case SLJIT_NOT_EQUAL:
|
||||
case SLJIT_MUL_OVERFLOW:
|
||||
case SLJIT_NOT_EQUAL_F64:
|
||||
return 0x10000000;
|
||||
|
||||
|
|
@ -2195,10 +2198,16 @@ static sljit_uw get_cc(sljit_s32 type)
|
|||
return 0xd0000000;
|
||||
|
||||
case SLJIT_OVERFLOW:
|
||||
if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
|
||||
return 0x10000000;
|
||||
|
||||
case SLJIT_UNORDERED_F64:
|
||||
return 0x60000000;
|
||||
|
||||
case SLJIT_NOT_OVERFLOW:
|
||||
if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
|
||||
return 0x00000000;
|
||||
|
||||
case SLJIT_ORDERED_F64:
|
||||
return 0x70000000;
|
||||
|
||||
|
|
@ -2242,7 +2251,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
if (type >= SLJIT_FAST_CALL)
|
||||
PTR_FAIL_IF(prepare_blx(compiler));
|
||||
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
|
||||
type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(type), 0));
|
||||
type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(compiler, type), 0));
|
||||
|
||||
if (jump->flags & SLJIT_REWRITABLE_JUMP) {
|
||||
jump->addr = compiler->size;
|
||||
|
|
@ -2260,7 +2269,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
if (type >= SLJIT_FAST_CALL)
|
||||
jump->flags |= IS_BL;
|
||||
PTR_FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
|
||||
PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(type)));
|
||||
PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(compiler, type)));
|
||||
jump->addr = compiler->size;
|
||||
#endif
|
||||
return jump;
|
||||
|
|
@ -2589,7 +2598,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
|||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
cc = get_cc(type & 0xff);
|
||||
cc = get_cc(compiler, type & 0xff);
|
||||
dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
|
||||
|
||||
if (op < SLJIT_ADD) {
|
||||
|
|
@ -2629,7 +2638,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
|
||||
dst_reg &= ~SLJIT_I32_OP;
|
||||
|
||||
cc = get_cc(type & 0xff);
|
||||
cc = get_cc(compiler, type & 0xff);
|
||||
|
||||
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
|
||||
tmp = get_imm(srcw);
|
||||
|
|
|
|||
|
|
@ -644,6 +644,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
|||
imm = -imm;
|
||||
/* Fall through. */
|
||||
case SLJIT_ADD:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
if (imm == 0) {
|
||||
CHECK_FLAGS(1 << 29);
|
||||
return push_inst(compiler, ((op == SLJIT_ADD ? ADDI : SUBI) ^ inv_bits) | RD(dst) | RN(reg));
|
||||
|
|
@ -781,6 +782,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
|||
break; /* Set flags. */
|
||||
case SLJIT_NEG:
|
||||
SLJIT_ASSERT(arg1 == TMP_REG1);
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
if (flags & SET_FLAGS)
|
||||
inv_bits |= 1 << 29;
|
||||
return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2));
|
||||
|
|
@ -789,17 +791,20 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
|||
return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2));
|
||||
case SLJIT_ADD:
|
||||
CHECK_FLAGS(1 << 29);
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
|
||||
case SLJIT_ADDC:
|
||||
CHECK_FLAGS(1 << 29);
|
||||
return push_inst(compiler, (ADC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
|
||||
case SLJIT_SUB:
|
||||
CHECK_FLAGS(1 << 29);
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
|
||||
case SLJIT_SUBC:
|
||||
CHECK_FLAGS(1 << 29);
|
||||
return push_inst(compiler, (SBC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
|
||||
case SLJIT_MUL:
|
||||
compiler->status_flags_state = 0;
|
||||
if (!(flags & SET_FLAGS))
|
||||
return push_inst(compiler, (MADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO));
|
||||
if (flags & INT_OP) {
|
||||
|
|
@ -1600,16 +1605,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
|
|||
/* Conditional instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static sljit_uw get_cc(sljit_s32 type)
|
||||
static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
|
||||
{
|
||||
switch (type) {
|
||||
case SLJIT_EQUAL:
|
||||
case SLJIT_MUL_NOT_OVERFLOW:
|
||||
case SLJIT_EQUAL_F64:
|
||||
return 0x1;
|
||||
|
||||
case SLJIT_NOT_EQUAL:
|
||||
case SLJIT_MUL_OVERFLOW:
|
||||
case SLJIT_NOT_EQUAL_F64:
|
||||
return 0x0;
|
||||
|
||||
|
|
@ -1642,10 +1645,16 @@ static sljit_uw get_cc(sljit_s32 type)
|
|||
return 0xc;
|
||||
|
||||
case SLJIT_OVERFLOW:
|
||||
if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
|
||||
return 0x0;
|
||||
|
||||
case SLJIT_UNORDERED_F64:
|
||||
return 0x7;
|
||||
|
||||
case SLJIT_NOT_OVERFLOW:
|
||||
if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
|
||||
return 0x1;
|
||||
|
||||
case SLJIT_ORDERED_F64:
|
||||
return 0x6;
|
||||
|
||||
|
|
@ -1685,7 +1694,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
|
||||
if (type < SLJIT_JUMP) {
|
||||
jump->flags |= IS_COND;
|
||||
PTR_FAIL_IF(push_inst(compiler, B_CC | (6 << 5) | get_cc(type)));
|
||||
PTR_FAIL_IF(push_inst(compiler, B_CC | (6 << 5) | get_cc(compiler, type)));
|
||||
}
|
||||
else if (type >= SLJIT_FAST_CALL)
|
||||
jump->flags |= IS_BL;
|
||||
|
|
@ -1799,7 +1808,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
|||
CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
cc = get_cc(type & 0xff);
|
||||
cc = get_cc(compiler, type & 0xff);
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
|
||||
|
||||
if (GET_OPCODE(op) < SLJIT_ADD) {
|
||||
|
|
@ -1854,7 +1863,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
srcw = 0;
|
||||
}
|
||||
|
||||
cc = get_cc(type & 0xff);
|
||||
cc = get_cc(compiler, type & 0xff);
|
||||
dst_reg &= ~SLJIT_I32_OP;
|
||||
|
||||
return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(dst_reg) | RM(src));
|
||||
|
|
|
|||
|
|
@ -610,6 +610,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
|||
Although some clever things could be done here, "NOT IMM" does not worth the efforts. */
|
||||
break;
|
||||
case SLJIT_ADD:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
nimm = -(sljit_sw)imm;
|
||||
if (IS_2_LO_REGS(reg, dst)) {
|
||||
if (imm <= 0x7)
|
||||
|
|
@ -643,6 +644,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
|||
break;
|
||||
case SLJIT_SUB:
|
||||
/* SUB operation can be replaced by ADD because of the negative carry flag. */
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
if (flags & ARG1_IMM) {
|
||||
if (imm == 0 && IS_2_LO_REGS(reg, dst))
|
||||
return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg));
|
||||
|
|
@ -801,6 +803,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
|||
FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2)));
|
||||
return SLJIT_SUCCESS;
|
||||
case SLJIT_ADD:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
if (IS_3_LO_REGS(dst, arg1, arg2))
|
||||
return push_inst16(compiler, ADDS | RD3(dst) | RN3(arg1) | RM3(arg2));
|
||||
if (dst == arg1 && !(flags & SET_FLAGS))
|
||||
|
|
@ -811,6 +814,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
|||
return push_inst16(compiler, ADCS | RD3(dst) | RN3(arg2));
|
||||
return push_inst32(compiler, ADC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
|
||||
case SLJIT_SUB:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
if (flags & UNUSED_RETURN) {
|
||||
if (IS_2_LO_REGS(arg1, arg2))
|
||||
return push_inst16(compiler, CMP | RD3(arg1) | RN3(arg2));
|
||||
|
|
@ -824,6 +828,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
|||
return push_inst16(compiler, SBCS | RD3(dst) | RN3(arg2));
|
||||
return push_inst32(compiler, SBC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
|
||||
case SLJIT_MUL:
|
||||
compiler->status_flags_state = 0;
|
||||
if (!(flags & SET_FLAGS))
|
||||
return push_inst32(compiler, MUL | RD4(dst) | RN4(arg1) | RM4(arg2));
|
||||
SLJIT_ASSERT(dst != TMP_REG2);
|
||||
|
|
@ -1760,16 +1765,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
|
|||
/* Conditional instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static sljit_uw get_cc(sljit_s32 type)
|
||||
static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
|
||||
{
|
||||
switch (type) {
|
||||
case SLJIT_EQUAL:
|
||||
case SLJIT_MUL_NOT_OVERFLOW:
|
||||
case SLJIT_EQUAL_F64:
|
||||
return 0x0;
|
||||
|
||||
case SLJIT_NOT_EQUAL:
|
||||
case SLJIT_MUL_OVERFLOW:
|
||||
case SLJIT_NOT_EQUAL_F64:
|
||||
return 0x1;
|
||||
|
||||
|
|
@ -1802,10 +1805,16 @@ static sljit_uw get_cc(sljit_s32 type)
|
|||
return 0xd;
|
||||
|
||||
case SLJIT_OVERFLOW:
|
||||
if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
|
||||
return 0x1;
|
||||
|
||||
case SLJIT_UNORDERED_F64:
|
||||
return 0x6;
|
||||
|
||||
case SLJIT_NOT_OVERFLOW:
|
||||
if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
|
||||
return 0x0;
|
||||
|
||||
case SLJIT_ORDERED_F64:
|
||||
return 0x7;
|
||||
|
||||
|
|
@ -1847,7 +1856,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
PTR_FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));
|
||||
if (type < SLJIT_JUMP) {
|
||||
jump->flags |= IS_COND;
|
||||
cc = get_cc(type);
|
||||
cc = get_cc(compiler, type);
|
||||
jump->flags |= cc << 8;
|
||||
PTR_FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
|
||||
}
|
||||
|
|
@ -2177,7 +2186,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
|||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
cc = get_cc(type & 0xff);
|
||||
cc = get_cc(compiler, type & 0xff);
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
|
||||
|
||||
if (op < SLJIT_ADD) {
|
||||
|
|
@ -2229,7 +2238,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
|
||||
dst_reg &= ~SLJIT_I32_OP;
|
||||
|
||||
cc = get_cc(type & 0xff);
|
||||
cc = get_cc(compiler, type & 0xff);
|
||||
|
||||
if (!(src & SLJIT_IMM)) {
|
||||
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
|||
case SLJIT_MUL:
|
||||
SLJIT_ASSERT(!(flags & SRC2_IMM));
|
||||
|
||||
if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
|
||||
if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) {
|
||||
#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_REV < 1 */
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
|||
case SLJIT_MUL:
|
||||
SLJIT_ASSERT(!(flags & SRC2_IMM));
|
||||
|
||||
if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
|
||||
if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) {
|
||||
#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_REV && SLJIT_MIPS_REV >= 1)
|
||||
|
|
|
|||
|
|
@ -1377,6 +1377,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_NEG:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
|
||||
|
||||
case SLJIT_CLZ:
|
||||
|
|
@ -1424,13 +1425,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
|||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_ADD:
|
||||
case SLJIT_ADDC:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
|
||||
|
||||
case SLJIT_SUB:
|
||||
case SLJIT_SUBC:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
|
||||
|
||||
case SLJIT_MUL:
|
||||
compiler->status_flags_state = 0;
|
||||
return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
|
||||
|
||||
case SLJIT_AND:
|
||||
|
|
@ -1860,7 +1864,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
case SLJIT_SIG_LESS:
|
||||
case SLJIT_SIG_GREATER:
|
||||
case SLJIT_OVERFLOW:
|
||||
case SLJIT_MUL_OVERFLOW:
|
||||
BR_Z(OTHER_FLAG);
|
||||
break;
|
||||
case SLJIT_GREATER_EQUAL:
|
||||
|
|
@ -1868,7 +1871,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
case SLJIT_SIG_GREATER_EQUAL:
|
||||
case SLJIT_SIG_LESS_EQUAL:
|
||||
case SLJIT_NOT_OVERFLOW:
|
||||
case SLJIT_MUL_NOT_OVERFLOW:
|
||||
BR_NZ(OTHER_FLAG);
|
||||
break;
|
||||
case SLJIT_NOT_EQUAL_F64:
|
||||
|
|
@ -2127,8 +2129,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
|||
FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
|
||||
src_ar = dst_ar;
|
||||
break;
|
||||
case SLJIT_MUL_OVERFLOW:
|
||||
case SLJIT_MUL_NOT_OVERFLOW:
|
||||
case SLJIT_OVERFLOW:
|
||||
case SLJIT_NOT_OVERFLOW:
|
||||
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB) {
|
||||
src_ar = OTHER_FLAG;
|
||||
break;
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
|
||||
src_ar = dst_ar;
|
||||
type ^= 0x1; /* Flip type bit for the XORI below. */
|
||||
|
|
@ -2219,7 +2225,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
case SLJIT_SIG_LESS:
|
||||
case SLJIT_SIG_GREATER:
|
||||
case SLJIT_OVERFLOW:
|
||||
case SLJIT_MUL_OVERFLOW:
|
||||
ins = MOVN | TA(OTHER_FLAG);
|
||||
break;
|
||||
case SLJIT_GREATER_EQUAL:
|
||||
|
|
@ -2227,7 +2232,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
case SLJIT_SIG_GREATER_EQUAL:
|
||||
case SLJIT_SIG_LESS_EQUAL:
|
||||
case SLJIT_NOT_OVERFLOW:
|
||||
case SLJIT_MUL_NOT_OVERFLOW:
|
||||
ins = MOVZ | TA(OTHER_FLAG);
|
||||
break;
|
||||
case SLJIT_EQUAL_F64:
|
||||
|
|
|
|||
|
|
@ -119,9 +119,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
|||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
SLJIT_ASSERT(!(flags & ALT_FORM4));
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
||||
if (flags & ALT_FORM4)
|
||||
if (flags & ALT_FORM5)
|
||||
return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
|
||||
|
||||
|
|
@ -143,24 +144,29 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
|||
}
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
if (flags & ALT_FORM3) {
|
||||
FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
|
||||
if (!(flags & ALT_FORM4))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
|
||||
if (!(flags & ALT_FORM4))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM3) {
|
||||
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||
return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM3) {
|
||||
if (flags & ALT_FORM4) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM4) {
|
||||
if (flags & ALT_FORM5) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm);
|
||||
}
|
||||
return push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2));
|
||||
}
|
||||
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
if (flags & ALT_FORM5)
|
||||
|
|
|
|||
|
|
@ -252,10 +252,17 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
|||
BIN_IMM_EXTS();
|
||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM4) {
|
||||
if (flags & ALT_FORM5)
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, CMPI | A(dst) | 0);
|
||||
}
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
||||
BIN_EXTS();
|
||||
if (flags & ALT_FORM4)
|
||||
if (flags & ALT_FORM5)
|
||||
return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
|
||||
|
||||
|
|
@ -278,6 +285,19 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
|||
}
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
if (flags & ALT_FORM3) {
|
||||
FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
|
||||
if (!(flags & ALT_FORM4))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
|
||||
if (!(flags & ALT_FORM4))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM3) {
|
||||
if (flags & ALT_SIGN_EXT) {
|
||||
FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
|
||||
src1 = TMP_REG1;
|
||||
|
|
@ -291,20 +311,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM3) {
|
||||
if (flags & ALT_FORM4) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM4) {
|
||||
if (flags & ALT_FORM5) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
|
||||
}
|
||||
return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
|
||||
}
|
||||
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
BIN_EXTS();
|
||||
|
|
|
|||
|
|
@ -1324,6 +1324,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
((src) & SLJIT_IMM)
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define TEST_ADD_FORM1(op) \
|
||||
(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
|
||||
|| (op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_I32_OP | SLJIT_SET_Z | SLJIT_SET_CARRY))
|
||||
#define TEST_SUB_FORM2(op) \
|
||||
((GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) \
|
||||
|| (op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_I32_OP | SLJIT_SET_Z))
|
||||
#define TEST_SUB_FORM3(op) \
|
||||
(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
|
||||
|| (op & (SLJIT_I32_OP | SLJIT_SET_Z)) == (SLJIT_I32_OP | SLJIT_SET_Z))
|
||||
#else
|
||||
#define TEST_ADD_FORM1(op) \
|
||||
(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
|
||||
#define TEST_SUB_FORM2(op) \
|
||||
(GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL)
|
||||
#define TEST_SUB_FORM3(op) \
|
||||
(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src1, sljit_sw src1w,
|
||||
|
|
@ -1362,7 +1381,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
|||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_ADD:
|
||||
if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
|
||||
if (TEST_ADD_FORM1(op))
|
||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
|
||||
|
||||
if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
|
||||
|
|
@ -1392,6 +1411,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
|||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
if ((op & (SLJIT_I32_OP | SLJIT_SET_Z)) == (SLJIT_I32_OP | SLJIT_SET_Z)) {
|
||||
if (TEST_SL_IMM(src2, src2w)) {
|
||||
compiler->imm = src2w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
if (TEST_SL_IMM(src1, src1w)) {
|
||||
compiler->imm = src1w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||
}
|
||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
|
||||
}
|
||||
#endif
|
||||
if (HAS_FLAGS(op)) {
|
||||
if (TEST_SL_IMM(src2, src2w)) {
|
||||
compiler->imm = src2w & 0xffff;
|
||||
|
|
@ -1402,7 +1435,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
|||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||
}
|
||||
}
|
||||
return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM4 : 0), dst, dstw, src1, src1w, src2, src2w);
|
||||
return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
|
||||
|
||||
case SLJIT_ADDC:
|
||||
return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
|
||||
|
|
@ -1424,18 +1457,36 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
|||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
|
||||
if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
|
||||
if (TEST_SL_IMM(src2, src2w)) {
|
||||
compiler->imm = src2w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
|
||||
if (TEST_SL_IMM(src2, -src2w)) {
|
||||
compiler->imm = (-src2w) & 0xffff;
|
||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
if (TEST_SL_IMM(src1, src1w)) {
|
||||
compiler->imm = src1w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||
if (TEST_SUB_FORM2(op)) {
|
||||
if ((src2 & SLJIT_IMM) && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) {
|
||||
compiler->imm = src2w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
if (TEST_SUB_FORM3(op))
|
||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
|
||||
|
||||
if (TEST_SL_IMM(src2, -src2w)) {
|
||||
compiler->imm = (-src2w) & 0xffff;
|
||||
return emit_op(compiler, SLJIT_ADD, flags | (!HAS_FLAGS(op) ? ALT_FORM2 : ALT_FORM3), dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
|
||||
if (TEST_SL_IMM(src1, src1w) && !(op & SLJIT_SET_Z)) {
|
||||
compiler->imm = src1w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||
}
|
||||
|
||||
if (!HAS_FLAGS(op)) {
|
||||
if (TEST_SH_IMM(src2, -src2w)) {
|
||||
compiler->imm = ((-src2w) >> 16) & 0xffff;
|
||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
|
|
@ -1447,18 +1498,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
|||
}
|
||||
}
|
||||
|
||||
if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) != GET_FLAG_TYPE(SLJIT_SET_CARRY)) {
|
||||
if (TEST_SL_IMM(src2, src2w)) {
|
||||
compiler->imm = src2w & 0xffff;
|
||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
if (TEST_SL_IMM(src2, -src2w)) {
|
||||
compiler->imm = (-src2w) & 0xffff;
|
||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||
}
|
||||
/* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
|
||||
return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
|
||||
|
||||
|
|
@ -1536,6 +1575,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#undef TEST_ADD_FORM1
|
||||
#undef TEST_SUB_FORM2
|
||||
#undef TEST_SUB_FORM3
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
|
|
@ -1941,11 +1984,9 @@ static sljit_ins get_bo_bi_flags(sljit_s32 type)
|
|||
return (4 << 21) | ((4 + 1) << 16);
|
||||
|
||||
case SLJIT_OVERFLOW:
|
||||
case SLJIT_MUL_OVERFLOW:
|
||||
return (12 << 21) | (3 << 16);
|
||||
|
||||
case SLJIT_NOT_OVERFLOW:
|
||||
case SLJIT_MUL_NOT_OVERFLOW:
|
||||
return (4 << 21) | (3 << 16);
|
||||
|
||||
case SLJIT_EQUAL_F64:
|
||||
|
|
@ -2143,12 +2184,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
|||
break;
|
||||
|
||||
case SLJIT_OVERFLOW:
|
||||
case SLJIT_MUL_OVERFLOW:
|
||||
cr_bit = 3;
|
||||
break;
|
||||
|
||||
case SLJIT_NOT_OVERFLOW:
|
||||
case SLJIT_MUL_NOT_OVERFLOW:
|
||||
cr_bit = 3;
|
||||
invert = 1;
|
||||
break;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -93,18 +93,21 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
|||
return push_inst(compiler, ADD | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS);
|
||||
|
||||
case SLJIT_ADD:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_ADDC:
|
||||
return push_inst(compiler, ADDC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_SUB:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
|
||||
return push_inst(compiler, SUB | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_SUBC:
|
||||
return push_inst(compiler, SUBC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_MUL:
|
||||
compiler->status_flags_state = 0;
|
||||
FAIL_IF(push_inst(compiler, SMUL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
if (!(flags & SET_FLAGS))
|
||||
return SLJIT_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -1275,16 +1275,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
|
|||
return label;
|
||||
}
|
||||
|
||||
static sljit_ins get_cc(sljit_s32 type)
|
||||
static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
|
||||
{
|
||||
switch (type) {
|
||||
case SLJIT_EQUAL:
|
||||
case SLJIT_MUL_NOT_OVERFLOW:
|
||||
case SLJIT_NOT_EQUAL_F64: /* Unordered. */
|
||||
return DA(0x1);
|
||||
|
||||
case SLJIT_NOT_EQUAL:
|
||||
case SLJIT_MUL_OVERFLOW:
|
||||
case SLJIT_EQUAL_F64:
|
||||
return DA(0x9);
|
||||
|
||||
|
|
@ -1317,10 +1315,16 @@ static sljit_ins get_cc(sljit_s32 type)
|
|||
return DA(0x2);
|
||||
|
||||
case SLJIT_OVERFLOW:
|
||||
if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
|
||||
return DA(0x9);
|
||||
|
||||
case SLJIT_UNORDERED_F64:
|
||||
return DA(0x7);
|
||||
|
||||
case SLJIT_NOT_OVERFLOW:
|
||||
if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
|
||||
return DA(0x1);
|
||||
|
||||
case SLJIT_ORDERED_F64:
|
||||
return DA(0xf);
|
||||
|
||||
|
|
@ -1347,7 +1351,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & ICC_IS_SET))
|
||||
jump->flags |= IS_MOVABLE;
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
PTR_FAIL_IF(push_inst(compiler, BICC | get_cc(type ^ 1) | 5, UNMOVABLE_INS));
|
||||
PTR_FAIL_IF(push_inst(compiler, BICC | get_cc(compiler, type ^ 1) | 5, UNMOVABLE_INS));
|
||||
#else
|
||||
#error "Implementation required"
|
||||
#endif
|
||||
|
|
@ -1357,7 +1361,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & FCC_IS_SET))
|
||||
jump->flags |= IS_MOVABLE;
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
PTR_FAIL_IF(push_inst(compiler, FBFCC | get_cc(type ^ 1) | 5, UNMOVABLE_INS));
|
||||
PTR_FAIL_IF(push_inst(compiler, FBFCC | get_cc(compiler, type ^ 1) | 5, UNMOVABLE_INS));
|
||||
#else
|
||||
#error "Implementation required"
|
||||
#endif
|
||||
|
|
@ -1474,9 +1478,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
|||
|
||||
type &= 0xff;
|
||||
if (type < SLJIT_EQUAL_F64)
|
||||
FAIL_IF(push_inst(compiler, BICC | get_cc(type) | 3, UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, BICC | get_cc(compiler, type) | 3, UNMOVABLE_INS));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, FBFCC | get_cc(type) | 3, UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, FBFCC | get_cc(compiler, type) | 3, UNMOVABLE_INS));
|
||||
|
||||
FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(1), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(0), UNMOVABLE_INS));
|
||||
|
|
|
|||
|
|
@ -411,11 +411,9 @@ static sljit_u8 get_jump_code(sljit_s32 type)
|
|||
return 0x8e /* jle */;
|
||||
|
||||
case SLJIT_OVERFLOW:
|
||||
case SLJIT_MUL_OVERFLOW:
|
||||
return 0x80 /* jo */;
|
||||
|
||||
case SLJIT_NOT_OVERFLOW:
|
||||
case SLJIT_MUL_NOT_OVERFLOW:
|
||||
return 0x81 /* jno */;
|
||||
|
||||
case SLJIT_UNORDERED_F64:
|
||||
|
|
|
|||
Loading…
Reference in New Issue