mirror of
https://github.com/php/php-src.git
synced 2024-10-01 23:06:11 +00:00
Merge branch 'pull-request/1047'
This commit is contained in:
commit
20a194a92c
@ -1,6 +1,104 @@
|
||||
ChangeLog for PCRE
|
||||
------------------
|
||||
|
||||
Version 8.36 26-September-2014
|
||||
------------------------------
|
||||
|
||||
1. Got rid of some compiler warnings in the C++ modules that were shown up by
|
||||
-Wmissing-field-initializers and -Wunused-parameter.
|
||||
|
||||
2. The tests for quantifiers being too big (greater than 65535) were being
|
||||
applied after reading the number, and stupidly assuming that integer
|
||||
overflow would give a negative number. The tests are now applied as the
|
||||
numbers are read.
|
||||
|
||||
3. Tidy code in pcre_exec.c where two branches that used to be different are
|
||||
now the same.
|
||||
|
||||
4. The JIT compiler did not generate match limit checks for certain
|
||||
bracketed expressions with quantifiers. This may lead to exponential
|
||||
backtracking, instead of returning with PCRE_ERROR_MATCHLIMIT. This
|
||||
issue should be resolved now.
|
||||
|
||||
5. Fixed an issue, which occures when nested alternatives are optimized
|
||||
with table jumps.
|
||||
|
||||
6. Inserted two casts and changed some ints to size_t in the light of some
|
||||
reported 64-bit compiler warnings (Bugzilla 1477).
|
||||
|
||||
7. Fixed a bug concerned with zero-minimum possessive groups that could match
|
||||
an empty string, which sometimes were behaving incorrectly in the
|
||||
interpreter (though correctly in the JIT matcher). This pcretest input is
|
||||
an example:
|
||||
|
||||
'\A(?:[^"]++|"(?:[^"]*+|"")*+")++'
|
||||
NON QUOTED "QUOT""ED" AFTER "NOT MATCHED
|
||||
|
||||
the interpreter was reporting a match of 'NON QUOTED ' only, whereas the
|
||||
JIT matcher and Perl both matched 'NON QUOTED "QUOT""ED" AFTER '. The test
|
||||
for an empty string was breaking the inner loop and carrying on at a lower
|
||||
level, when possessive repeated groups should always return to a higher
|
||||
level as they have no backtrack points in them. The empty string test now
|
||||
occurs at the outer level.
|
||||
|
||||
8. Fixed a bug that was incorrectly auto-possessifying \w+ in the pattern
|
||||
^\w+(?>\s*)(?<=\w) which caused it not to match "test test".
|
||||
|
||||
9. Give a compile-time error for \o{} (as Perl does) and for \x{} (which Perl
|
||||
doesn't).
|
||||
|
||||
10. Change 8.34/15 introduced a bug that caused the amount of memory needed
|
||||
to hold a pattern to be incorrectly computed (too small) when there were
|
||||
named back references to duplicated names. This could cause "internal
|
||||
error: code overflow" or "double free or corruption" or other memory
|
||||
handling errors.
|
||||
|
||||
11. When named subpatterns had the same prefixes, back references could be
|
||||
confused. For example, in this pattern:
|
||||
|
||||
/(?P<Name>a)?(?P<Name2>b)?(?(<Name>)c|d)*l/
|
||||
|
||||
the reference to 'Name' was incorrectly treated as a reference to a
|
||||
duplicate name.
|
||||
|
||||
12. A pattern such as /^s?c/mi8 where the optional character has more than
|
||||
one "other case" was incorrectly compiled such that it would only try to
|
||||
match starting at "c".
|
||||
|
||||
13. When a pattern starting with \s was studied, VT was not included in the
|
||||
list of possible starting characters; this should have been part of the
|
||||
8.34/18 patch.
|
||||
|
||||
14. If a character class started [\Qx]... where x is any character, the class
|
||||
was incorrectly terminated at the ].
|
||||
|
||||
15. If a pattern that started with a caseless match for a character with more
|
||||
than one "other case" was studied, PCRE did not set up the starting code
|
||||
unit bit map for the list of possible characters. Now it does. This is an
|
||||
optimization improvement, not a bug fix.
|
||||
|
||||
16. The Unicode data tables have been updated to Unicode 7.0.0.
|
||||
|
||||
17. Fixed a number of memory leaks in pcregrep.
|
||||
|
||||
18. Avoid a compiler warning (from some compilers) for a function call with
|
||||
a cast that removes "const" from an lvalue by using an intermediate
|
||||
variable (to which the compiler does not object).
|
||||
|
||||
19. Incorrect code was compiled if a group that contained an internal recursive
|
||||
back reference was optional (had quantifier with a minimum of zero). This
|
||||
example compiled incorrect code: /(((a\2)|(a*)\g<-1>))*/ and other examples
|
||||
caused segmentation faults because of stack overflows at compile time.
|
||||
|
||||
20. A pattern such as /((?(R)a|(?1)))+/, which contains a recursion within a
|
||||
group that is quantified with an indefinite repeat, caused a compile-time
|
||||
loop which used up all the system stack and provoked a segmentation fault.
|
||||
This was not the same bug as 19 above.
|
||||
|
||||
21. Add PCRECPP_EXP_DECL declaration to operator<< in pcre_stringpiece.h.
|
||||
Patch by Mike Frysinger.
|
||||
|
||||
|
||||
Version 8.35 04-April-2014
|
||||
--------------------------
|
||||
|
||||
@ -27,9 +125,9 @@ Version 8.35 04-April-2014
|
||||
|
||||
6. Improve character range checks in JIT. Characters are read by an inprecise
|
||||
function now, which returns with an unknown value if the character code is
|
||||
above a certain treshold (e.g: 256). The only limitation is that the value
|
||||
must be bigger than the treshold as well. This function is useful, when
|
||||
the characters above the treshold are handled in the same way.
|
||||
above a certain threshold (e.g: 256). The only limitation is that the value
|
||||
must be bigger than the threshold as well. This function is useful when
|
||||
the characters above the threshold are handled in the same way.
|
||||
|
||||
7. The macros whose names start with RAWUCHAR are placeholders for a future
|
||||
mode in which only the bottom 21 bits of 32-bit data items are used. To
|
||||
@ -1544,7 +1642,7 @@ Version 8.10 25-Jun-2010
|
||||
|
||||
7. Minor change to pcretest.c to avoid a compiler warning.
|
||||
|
||||
8. Added four artificial Unicode properties to help with an option to make
|
||||
8. Added four artifical Unicode properties to help with an option to make
|
||||
\s etc use properties (see next item). The new properties are: Xan
|
||||
(alphanumeric), Xsp (Perl space), Xps (POSIX space), and Xwd (word).
|
||||
|
||||
@ -4169,7 +4267,7 @@ Version 4.3 21-May-03
|
||||
(i) The utf8_table... variables are now declared "const".
|
||||
|
||||
(ii) The code for \cx, which used the "case flipping" table to upper case
|
||||
lower case letters, now just subtracts 32. This is ASCII-specific,
|
||||
lower case letters, now just substracts 32. This is ASCII-specific,
|
||||
but the whole concept of \cx is ASCII-specific, so it seems
|
||||
reasonable.
|
||||
|
||||
@ -5431,7 +5529,7 @@ by an auxiliary program - but can then be edited by hand if required. There are
|
||||
now no calls to isalnum(), isspace(), isdigit(), isxdigit(), tolower() or
|
||||
toupper() in the code.
|
||||
|
||||
7. Turn the malloc/free functions variables into pcre_malloc and pcre_free and
|
||||
7. Turn the malloc/free funtions variables into pcre_malloc and pcre_free and
|
||||
make them global. Abolish the function for setting them, as the caller can now
|
||||
set them directly.
|
||||
|
||||
|
@ -360,7 +360,7 @@ reference number if the reference is to a unique capturing group (either by
|
||||
number or by name). When named groups are used, there may be more than one
|
||||
group with the same name. In this case, a reference by name generates OP_DNREF
|
||||
or OP_DNREFI. These are followed by two counts: the index (not the byte offset)
|
||||
in the group name table of the first entry for the required name, followed by
|
||||
in the group name table of the first entry for the requred name, followed by
|
||||
the number of groups with the same name.
|
||||
|
||||
|
||||
|
@ -1,6 +1,13 @@
|
||||
News about PCRE releases
|
||||
------------------------
|
||||
|
||||
Release 8.36 26-September-2014
|
||||
------------------------------
|
||||
|
||||
This is primarily a bug-fix release. However, in addition, the Unicode data
|
||||
tables have been updated to Unicode 7.0.0.
|
||||
|
||||
|
||||
Release 8.35 04-April-2014
|
||||
--------------------------
|
||||
|
||||
|
@ -45,14 +45,16 @@ the 16-bit library, which processes strings of 16-bit values, and one for the
|
||||
32-bit library, which processes strings of 32-bit values. The distribution also
|
||||
includes a set of C++ wrapper functions (see the pcrecpp man page for details),
|
||||
courtesy of Google Inc., which can be used to call the 8-bit PCRE library from
|
||||
C++.
|
||||
C++. Other C++ wrappers have been created from time to time. See, for example:
|
||||
https://github.com/YasserAsmi/regexp, which aims to be simple and similar in
|
||||
style to the C API.
|
||||
|
||||
In addition, there is a set of C wrapper functions (again, just for the 8-bit
|
||||
library) that are based on the POSIX regular expression API (see the pcreposix
|
||||
man page). These end up in the library called libpcreposix. Note that this just
|
||||
provides a POSIX calling interface to PCRE; the regular expressions themselves
|
||||
still follow Perl syntax and semantics. The POSIX API is restricted, and does
|
||||
not give full access to all of PCRE's facilities.
|
||||
The distribution also contains a set of C wrapper functions (again, just for
|
||||
the 8-bit library) that are based on the POSIX regular expression API (see the
|
||||
pcreposix man page). These end up in the library called libpcreposix. Note that
|
||||
this just provides a POSIX calling interface to PCRE; the regular expressions
|
||||
themselves still follow Perl syntax and semantics. The POSIX API is restricted,
|
||||
and does not give full access to all of PCRE's facilities.
|
||||
|
||||
The header file for the POSIX-style functions is called pcreposix.h. The
|
||||
official POSIX name is regex.h, but I did not want to risk possible problems
|
||||
@ -392,7 +394,7 @@ library. They are also documented in the pcrebuild man page.
|
||||
avoided by linking with libedit (which has a BSD licence) instead.
|
||||
|
||||
Enabling libreadline causes the -lreadline option to be added to the pcretest
|
||||
build. In many operating environments with a system-installed readline
|
||||
build. In many operating environments with a sytem-installed readline
|
||||
library this is sufficient. However, in some environments (e.g. if an
|
||||
unmodified distribution version of readline is in use), it may be necessary
|
||||
to specify something like LIBS="-lncurses" as well. This is because, to quote
|
||||
@ -988,4 +990,4 @@ pcre_xxx, one with the name pcre16_xx, and a third with the name pcre32_xxx.
|
||||
Philip Hazel
|
||||
Email local part: ph10
|
||||
Email domain: cam.ac.uk
|
||||
Last updated: 17 January 2014
|
||||
Last updated: 24 October 2014
|
||||
|
@ -262,7 +262,7 @@ sure both macros are undefined; an emulation function will then be used. */
|
||||
#define PACKAGE_NAME "PCRE"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "PCRE 8.35"
|
||||
#define PACKAGE_STRING "PCRE 8.36"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "pcre"
|
||||
@ -271,7 +271,7 @@ sure both macros are undefined; an emulation function will then be used. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "8.35"
|
||||
#define PACKAGE_VERSION "8.36"
|
||||
|
||||
/* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested
|
||||
parentheses (of any kind) in a pattern. This limits the amount of system
|
||||
@ -322,7 +322,7 @@ sure both macros are undefined; an emulation function will then be used. */
|
||||
/* #undef STDC_HEADERS */
|
||||
|
||||
/* Define to any value to enable support for Just-In-Time compiling. */
|
||||
#define SUPPORT_JIT
|
||||
/* #undef SUPPORT_JIT */
|
||||
|
||||
/* Define to any value to allow pcregrep to be linked with libbz2, so that it
|
||||
is able to handle .bz2 files. */
|
||||
@ -348,7 +348,7 @@ sure both macros are undefined; an emulation function will then be used. */
|
||||
/* #undef SUPPORT_PCRE8 */
|
||||
|
||||
/* Define to any value to enable JIT support in pcregrep. */
|
||||
#define SUPPORT_PCREGREP_JIT
|
||||
/* #undef SUPPORT_PCREGREP_JIT */
|
||||
|
||||
/* Define to any value to enable support for Unicode properties. */
|
||||
/* #undef SUPPORT_UCP */
|
||||
@ -363,7 +363,7 @@ sure both macros are undefined; an emulation function will then be used. */
|
||||
/* #undef SUPPORT_VALGRIND */
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "8.35"
|
||||
#define VERSION "8.36"
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
@ -1242,7 +1242,7 @@ PCRETEST OPTION FOR LIBREADLINE SUPPORT
|
||||
pcretest linked in this way, there may be licensing issues.
|
||||
|
||||
Setting this option causes the -lreadline option to be added to the
|
||||
pcretest build. In many operating environments with a system-installed
|
||||
pcretest build. In many operating environments with a sytem-installed
|
||||
libreadline this is sufficient. However, in some environments (e.g. if
|
||||
an unmodified distribution version of readline is in use), some extra
|
||||
configuration may be necessary. The INSTALL file for libreadline says
|
||||
@ -5326,21 +5326,25 @@ BACKSLASH
|
||||
Those that are not part of an identified script are lumped together as
|
||||
"Common". The current list of scripts is:
|
||||
|
||||
Arabic, Armenian, Avestan, Balinese, Bamum, Batak, Bengali, Bopomofo,
|
||||
Brahmi, Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Chakma,
|
||||
Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot, Cyrillic, Deseret,
|
||||
Devanagari, Egyptian_Hieroglyphs, Ethiopic, Georgian, Glagolitic,
|
||||
Gothic, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hira-
|
||||
gana, Imperial_Aramaic, Inherited, Inscriptional_Pahlavi, Inscrip-
|
||||
tional_Parthian, Javanese, Kaithi, Kannada, Katakana, Kayah_Li,
|
||||
Kharoshthi, Khmer, Lao, Latin, Lepcha, Limbu, Linear_B, Lisu, Lycian,
|
||||
Lydian, Malayalam, Mandaic, Meetei_Mayek, Meroitic_Cursive,
|
||||
Meroitic_Hieroglyphs, Miao, Mongolian, Myanmar, New_Tai_Lue, Nko,
|
||||
Ogham, Old_Italic, Old_Persian, Old_South_Arabian, Old_Turkic,
|
||||
Ol_Chiki, Oriya, Osmanya, Phags_Pa, Phoenician, Rejang, Runic, Samari-
|
||||
tan, Saurashtra, Sharada, Shavian, Sinhala, Sora_Sompeng, Sundanese,
|
||||
Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet,
|
||||
Takri, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Ugaritic, Vai,
|
||||
Arabic, Armenian, Avestan, Balinese, Bamum, Bassa_Vah, Batak, Bengali,
|
||||
Bopomofo, Brahmi, Braille, Buginese, Buhid, Canadian_Aboriginal, Car-
|
||||
ian, Caucasian_Albanian, Chakma, Cham, Cherokee, Common, Coptic, Cunei-
|
||||
form, Cypriot, Cyrillic, Deseret, Devanagari, Duployan, Egyptian_Hiero-
|
||||
glyphs, Elbasan, Ethiopic, Georgian, Glagolitic, Gothic, Grantha,
|
||||
Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana,
|
||||
Imperial_Aramaic, Inherited, Inscriptional_Pahlavi, Inscrip-
|
||||
tional_Parthian, Javanese, Kaithi, Kannada, Katakana, Kayah_Li,
|
||||
Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin, Lepcha, Limbu, Lin-
|
||||
ear_A, Linear_B, Lisu, Lycian, Lydian, Mahajani, Malayalam, Mandaic,
|
||||
Manichaean, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive,
|
||||
Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro, Myanmar, Nabataean,
|
||||
New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_North_Arabian,
|
||||
Old_Permic, Old_Persian, Old_South_Arabian, Old_Turkic, Oriya, Osmanya,
|
||||
Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician,
|
||||
Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Sha-
|
||||
vian, Siddham, Sinhala, Sora_Sompeng, Sundanese, Syloti_Nagri, Syriac,
|
||||
Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet, Takri, Tamil, Telugu,
|
||||
Thaana, Thai, Tibetan, Tifinagh, Tirhuta, Ugaritic, Vai, Warang_Citi,
|
||||
Yi.
|
||||
|
||||
Each character has exactly one Unicode general category property, spec-
|
||||
@ -7777,21 +7781,25 @@ PCRE SPECIAL CATEGORY PROPERTIES FOR \p and \P
|
||||
|
||||
SCRIPT NAMES FOR \p AND \P
|
||||
|
||||
Arabic, Armenian, Avestan, Balinese, Bamum, Batak, Bengali, Bopomofo,
|
||||
Brahmi, Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Chakma,
|
||||
Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot, Cyrillic, Deseret,
|
||||
Devanagari, Egyptian_Hieroglyphs, Ethiopic, Georgian, Glagolitic,
|
||||
Gothic, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hira-
|
||||
gana, Imperial_Aramaic, Inherited, Inscriptional_Pahlavi, Inscrip-
|
||||
tional_Parthian, Javanese, Kaithi, Kannada, Katakana, Kayah_Li,
|
||||
Kharoshthi, Khmer, Lao, Latin, Lepcha, Limbu, Linear_B, Lisu, Lycian,
|
||||
Lydian, Malayalam, Mandaic, Meetei_Mayek, Meroitic_Cursive,
|
||||
Meroitic_Hieroglyphs, Miao, Mongolian, Myanmar, New_Tai_Lue, Nko,
|
||||
Ogham, Old_Italic, Old_Persian, Old_South_Arabian, Old_Turkic,
|
||||
Ol_Chiki, Oriya, Osmanya, Phags_Pa, Phoenician, Rejang, Runic, Samari-
|
||||
tan, Saurashtra, Sharada, Shavian, Sinhala, Sora_Sompeng, Sundanese,
|
||||
Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet,
|
||||
Takri, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Ugaritic, Vai,
|
||||
Arabic, Armenian, Avestan, Balinese, Bamum, Bassa_Vah, Batak, Bengali,
|
||||
Bopomofo, Brahmi, Braille, Buginese, Buhid, Canadian_Aboriginal, Car-
|
||||
ian, Caucasian_Albanian, Chakma, Cham, Cherokee, Common, Coptic, Cunei-
|
||||
form, Cypriot, Cyrillic, Deseret, Devanagari, Duployan, Egyptian_Hiero-
|
||||
glyphs, Elbasan, Ethiopic, Georgian, Glagolitic, Gothic, Grantha,
|
||||
Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana,
|
||||
Imperial_Aramaic, Inherited, Inscriptional_Pahlavi, Inscrip-
|
||||
tional_Parthian, Javanese, Kaithi, Kannada, Katakana, Kayah_Li,
|
||||
Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin, Lepcha, Limbu, Lin-
|
||||
ear_A, Linear_B, Lisu, Lycian, Lydian, Mahajani, Malayalam, Mandaic,
|
||||
Manichaean, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive,
|
||||
Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro, Myanmar, Nabataean,
|
||||
New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_North_Arabian,
|
||||
Old_Permic, Old_Persian, Old_South_Arabian, Old_Turkic, Oriya, Osmanya,
|
||||
Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician,
|
||||
Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Sha-
|
||||
vian, Siddham, Sinhala, Sora_Sompeng, Sundanese, Syloti_Nagri, Syriac,
|
||||
Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet, Takri, Tamil, Telugu,
|
||||
Thaana, Thai, Tibetan, Tifinagh, Tirhuta, Ugaritic, Vai, Warang_Citi,
|
||||
Yi.
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
/* This is the public header file for the PCRE library, to be #included by
|
||||
applications that call the PCRE functions.
|
||||
|
||||
Copyright (c) 1997-2015 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
/* The current PCRE version information. */
|
||||
|
||||
#define PCRE_MAJOR 8
|
||||
#define PCRE_MINOR 35
|
||||
#define PCRE_PRERELEASE
|
||||
#define PCRE_DATE 2014-04-04
|
||||
#define PCRE_MINOR 36
|
||||
#define PCRE_PRERELEASE
|
||||
#define PCRE_DATE 2014-09-26
|
||||
|
||||
/* When an application links to a PCRE DLL in Windows, the symbols that are
|
||||
imported have to be identified as such. When building PCRE, the appropriate
|
||||
|
@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2015 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -45,8 +45,8 @@ supporting internal functions that are not used by other modules. */
|
||||
#include "config.h"
|
||||
|
||||
#define NLBLOCK cd /* Block containing newline information */
|
||||
#define PSSTART start_pattern /* Field containing processed string start */
|
||||
#define PSEND end_pattern /* Field containing processed string end */
|
||||
#define PSSTART start_pattern /* Field containing pattern start */
|
||||
#define PSEND end_pattern /* Field containing pattern end */
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
@ -547,6 +547,7 @@ static const char error_texts[] =
|
||||
"group name must start with a non-digit\0"
|
||||
/* 85 */
|
||||
"parentheses are too deeply nested (stack check)\0"
|
||||
"digits missing in \\x{} or \\o{}\0"
|
||||
;
|
||||
|
||||
/* Table to identify digits and hex digits. This is used when compiling
|
||||
@ -1257,6 +1258,7 @@ else
|
||||
|
||||
case CHAR_o:
|
||||
if (ptr[1] != CHAR_LEFT_CURLY_BRACKET) *errorcodeptr = ERR81; else
|
||||
if (ptr[2] == CHAR_RIGHT_CURLY_BRACKET) *errorcodeptr = ERR86; else
|
||||
{
|
||||
ptr += 2;
|
||||
c = 0;
|
||||
@ -1326,6 +1328,11 @@ else
|
||||
if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
|
||||
{
|
||||
ptr += 2;
|
||||
if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
|
||||
{
|
||||
*errorcodeptr = ERR86;
|
||||
break;
|
||||
}
|
||||
c = 0;
|
||||
overflow = FALSE;
|
||||
while (MAX_255(*ptr) && (digitab[*ptr] & ctype_xdigit) != 0)
|
||||
@ -1581,29 +1588,29 @@ read_repeat_counts(const pcre_uchar *p, int *minp, int *maxp, int *errorcodeptr)
|
||||
int min = 0;
|
||||
int max = -1;
|
||||
|
||||
/* Read the minimum value and do a paranoid check: a negative value indicates
|
||||
an integer overflow. */
|
||||
|
||||
while (IS_DIGIT(*p)) min = min * 10 + (int)(*p++ - CHAR_0);
|
||||
if (min < 0 || min > 65535)
|
||||
while (IS_DIGIT(*p))
|
||||
{
|
||||
*errorcodeptr = ERR5;
|
||||
return p;
|
||||
min = min * 10 + (int)(*p++ - CHAR_0);
|
||||
if (min > 65535)
|
||||
{
|
||||
*errorcodeptr = ERR5;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the maximum value if there is one, and again do a paranoid on its size.
|
||||
Also, max must not be less than min. */
|
||||
|
||||
if (*p == CHAR_RIGHT_CURLY_BRACKET) max = min; else
|
||||
{
|
||||
if (*(++p) != CHAR_RIGHT_CURLY_BRACKET)
|
||||
{
|
||||
max = 0;
|
||||
while(IS_DIGIT(*p)) max = max * 10 + (int)(*p++ - CHAR_0);
|
||||
if (max < 0 || max > 65535)
|
||||
while(IS_DIGIT(*p))
|
||||
{
|
||||
*errorcodeptr = ERR5;
|
||||
return p;
|
||||
max = max * 10 + (int)(*p++ - CHAR_0);
|
||||
if (max > 65535)
|
||||
{
|
||||
*errorcodeptr = ERR5;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
if (max < min)
|
||||
{
|
||||
@ -1613,9 +1620,6 @@ if (*p == CHAR_RIGHT_CURLY_BRACKET) max = min; else
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in the required variables, and pass back the pointer to the terminating
|
||||
'}'. */
|
||||
|
||||
*minp = min;
|
||||
*maxp = max;
|
||||
return p;
|
||||
@ -2368,6 +2372,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
|
||||
if (c == OP_RECURSE)
|
||||
{
|
||||
const pcre_uchar *scode = cd->start_code + GET(code, 1);
|
||||
const pcre_uchar *endgroup = scode;
|
||||
BOOL empty_branch;
|
||||
|
||||
/* Test for forward reference or uncompleted reference. This is disabled
|
||||
@ -2382,20 +2387,16 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
|
||||
if (GET(scode, 1) == 0) return TRUE; /* Unclosed */
|
||||
}
|
||||
|
||||
/* If we are scanning a completed pattern, there are no forward references
|
||||
and all groups are complete. We need to detect whether this is a recursive
|
||||
call, as otherwise there will be an infinite loop. If it is a recursion,
|
||||
just skip over it. Simple recursions are easily detected. For mutual
|
||||
recursions we keep a chain on the stack. */
|
||||
/* If the reference is to a completed group, we need to detect whether this
|
||||
is a recursive call, as otherwise there will be an infinite loop. If it is
|
||||
a recursion, just skip over it. Simple recursions are easily detected. For
|
||||
mutual recursions we keep a chain on the stack. */
|
||||
|
||||
do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT);
|
||||
if (code >= scode && code <= endgroup) continue; /* Simple recursion */
|
||||
else
|
||||
{
|
||||
recurse_check *r = recurses;
|
||||
const pcre_uchar *endgroup = scode;
|
||||
|
||||
do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT);
|
||||
if (code >= scode && code <= endgroup) continue; /* Simple recursion */
|
||||
|
||||
for (r = recurses; r != NULL; r = r->prev)
|
||||
if (r->group == scode) break;
|
||||
if (r != NULL) continue; /* Mutual recursion */
|
||||
@ -3036,7 +3037,7 @@ switch(c)
|
||||
end += 1 + 2 * IMM2_SIZE;
|
||||
break;
|
||||
}
|
||||
list[2] = end - code;
|
||||
list[2] = (pcre_uint32)(end - code);
|
||||
return end;
|
||||
}
|
||||
return NULL; /* Opcode not accepted */
|
||||
@ -3077,6 +3078,7 @@ const pcre_uint8 *class_bitset;
|
||||
const pcre_uint8 *set1, *set2, *set_end;
|
||||
pcre_uint32 chr;
|
||||
BOOL accepted, invert_bits;
|
||||
BOOL entered_a_group = FALSE;
|
||||
|
||||
/* Note: the base_list[1] contains whether the current opcode has greedy
|
||||
(represented by a non-zero value) quantifier. This is a different from
|
||||
@ -3130,8 +3132,10 @@ for(;;)
|
||||
case OP_ONCE:
|
||||
case OP_ONCE_NC:
|
||||
/* Atomic sub-patterns and assertions can always auto-possessify their
|
||||
last iterator. */
|
||||
return TRUE;
|
||||
last iterator. However, if the group was entered as a result of checking
|
||||
a previous iterator, this is not possible. */
|
||||
|
||||
return !entered_a_group;
|
||||
}
|
||||
|
||||
code += PRIV(OP_lengths)[c];
|
||||
@ -3150,6 +3154,8 @@ for(;;)
|
||||
code = next_code + 1 + LINK_SIZE;
|
||||
next_code += GET(next_code, 1);
|
||||
}
|
||||
|
||||
entered_a_group = TRUE;
|
||||
continue;
|
||||
|
||||
case OP_BRAZERO:
|
||||
@ -3169,6 +3175,9 @@ for(;;)
|
||||
|
||||
code += PRIV(OP_lengths)[c];
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for a supported opcode, and load its properties. */
|
||||
@ -3407,8 +3416,7 @@ for(;;)
|
||||
rightop >= FIRST_AUTOTAB_OP && rightop <= LAST_AUTOTAB_RIGHT_OP &&
|
||||
autoposstab[leftop - FIRST_AUTOTAB_OP][rightop - FIRST_AUTOTAB_OP];
|
||||
|
||||
if (!accepted)
|
||||
return FALSE;
|
||||
if (!accepted) return FALSE;
|
||||
|
||||
if (list[1] == 0) return TRUE;
|
||||
/* Might be an empty repeat. */
|
||||
@ -4681,7 +4689,8 @@ for (;; ptr++)
|
||||
previous = NULL;
|
||||
if ((options & PCRE_MULTILINE) != 0)
|
||||
{
|
||||
if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
|
||||
if (firstcharflags == REQ_UNSET)
|
||||
zerofirstcharflags = firstcharflags = REQ_NONE;
|
||||
*code++ = OP_CIRCM;
|
||||
}
|
||||
else *code++ = OP_CIRC;
|
||||
@ -4861,7 +4870,7 @@ for (;; ptr++)
|
||||
if (lengthptr != NULL && class_uchardata > class_uchardata_base)
|
||||
{
|
||||
xclass = TRUE;
|
||||
*lengthptr += class_uchardata - class_uchardata_base;
|
||||
*lengthptr += (int)(class_uchardata - class_uchardata_base);
|
||||
class_uchardata = class_uchardata_base;
|
||||
}
|
||||
#endif
|
||||
@ -5311,7 +5320,7 @@ for (;; ptr++)
|
||||
whatever repeat count may follow. In the case of reqchar, save the
|
||||
previous value for reinstating. */
|
||||
|
||||
if (class_one_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
|
||||
if (!inescq && class_one_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
|
||||
{
|
||||
ptr++;
|
||||
zeroreqchar = reqchar;
|
||||
@ -6006,8 +6015,8 @@ for (;; ptr++)
|
||||
while (cd->hwm > cd->start_workspace + cd->workspace_size -
|
||||
WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm))
|
||||
{
|
||||
int save_offset = save_hwm - cd->start_workspace;
|
||||
int this_offset = this_hwm - cd->start_workspace;
|
||||
size_t save_offset = save_hwm - cd->start_workspace;
|
||||
size_t this_offset = this_hwm - cd->start_workspace;
|
||||
*errorcodeptr = expand_workspace(cd);
|
||||
if (*errorcodeptr != 0) goto FAILED;
|
||||
save_hwm = (pcre_uchar *)cd->start_workspace + save_offset;
|
||||
@ -6088,8 +6097,8 @@ for (;; ptr++)
|
||||
while (cd->hwm > cd->start_workspace + cd->workspace_size -
|
||||
WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm))
|
||||
{
|
||||
int save_offset = save_hwm - cd->start_workspace;
|
||||
int this_offset = this_hwm - cd->start_workspace;
|
||||
size_t save_offset = save_hwm - cd->start_workspace;
|
||||
size_t this_offset = this_hwm - cd->start_workspace;
|
||||
*errorcodeptr = expand_workspace(cd);
|
||||
if (*errorcodeptr != 0) goto FAILED;
|
||||
save_hwm = (pcre_uchar *)cd->start_workspace + save_offset;
|
||||
@ -6687,7 +6696,8 @@ for (;; ptr++)
|
||||
ptr++;
|
||||
}
|
||||
namelen = (int)(ptr - name);
|
||||
if (lengthptr != NULL) *lengthptr += IMM2_SIZE;
|
||||
if (lengthptr != NULL && (options & PCRE_DUPNAMES) != 0)
|
||||
*lengthptr += IMM2_SIZE;
|
||||
}
|
||||
|
||||
/* Check the terminator */
|
||||
@ -6748,9 +6758,11 @@ for (;; ptr++)
|
||||
for (; i < cd->names_found; i++)
|
||||
{
|
||||
slot += cd->name_entry_size;
|
||||
if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) != 0) break;
|
||||
if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) != 0 ||
|
||||
(slot+IMM2_SIZE)[namelen] != 0) break;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count > 1)
|
||||
{
|
||||
PUT2(code, 2+LINK_SIZE, offset);
|
||||
@ -7099,6 +7111,12 @@ for (;; ptr++)
|
||||
/* Count named back references. */
|
||||
|
||||
if (!is_recurse) cd->namedrefcount++;
|
||||
|
||||
/* If duplicate names are permitted, we have to allow for a named
|
||||
reference to a duplicated name (this cannot be determined until the
|
||||
second pass). This needs an extra 16-bit data item. */
|
||||
|
||||
if ((options & PCRE_DUPNAMES) != 0) *lengthptr += IMM2_SIZE;
|
||||
}
|
||||
|
||||
/* In the real compile, search the name table. We check the name
|
||||
@ -7145,6 +7163,8 @@ for (;; ptr++)
|
||||
for (i++; i < cd->names_found; i++)
|
||||
{
|
||||
if (STRCMP_UC_UC(slot + IMM2_SIZE, cslot + IMM2_SIZE) != 0) break;
|
||||
|
||||
|
||||
count++;
|
||||
cslot += cd->name_entry_size;
|
||||
}
|
||||
@ -8242,12 +8262,16 @@ for (;;)
|
||||
|
||||
/* If it was a capturing subpattern, check to see if it contained any
|
||||
recursive back references. If so, we must wrap it in atomic brackets.
|
||||
In any event, remove the block from the chain. */
|
||||
Because we are moving code along, we must ensure that any pending recursive
|
||||
references are updated. In any event, remove the block from the chain. */
|
||||
|
||||
if (capnumber > 0)
|
||||
{
|
||||
if (cd->open_caps->flag)
|
||||
{
|
||||
*code = OP_END;
|
||||
adjust_recurse(start_bracket, 1 + LINK_SIZE,
|
||||
(options & PCRE_UTF8) != 0, cd, cd->hwm);
|
||||
memmove(start_bracket + 1 + LINK_SIZE, start_bracket,
|
||||
IN_UCHARS(code - start_bracket));
|
||||
*start_bracket = OP_ONCE;
|
||||
@ -9252,11 +9276,18 @@ subpattern. */
|
||||
|
||||
if (errorcode == 0 && re->top_backref > re->top_bracket) errorcode = ERR15;
|
||||
|
||||
/* Unless disabled, check whether single character iterators can be
|
||||
auto-possessified. The function overwrites the appropriate opcode values. */
|
||||
/* Unless disabled, check whether any single character iterators can be
|
||||
auto-possessified. The function overwrites the appropriate opcode values, so
|
||||
the type of the pointer must be cast. NOTE: the intermediate variable "temp" is
|
||||
used in this code because at least one compiler gives a warning about loss of
|
||||
"const" attribute if the cast (pcre_uchar *)codestart is used directly in the
|
||||
function call. */
|
||||
|
||||
if ((options & PCRE_NO_AUTO_POSSESS) == 0)
|
||||
auto_possessify((pcre_uchar *)codestart, utf, cd);
|
||||
{
|
||||
pcre_uchar *temp = (pcre_uchar *)codestart;
|
||||
auto_possessify(temp, utf, cd);
|
||||
}
|
||||
|
||||
/* If there were any lookbehind assertions that contained OP_RECURSE
|
||||
(recursions or subroutine calls), a flag is set for them to be checked here,
|
||||
|
@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2015 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -1038,7 +1038,7 @@ for (;;)
|
||||
the result of a recursive call to match() whatever happened so it was
|
||||
possible to reduce stack usage by turning this into a tail recursion,
|
||||
except in the case of a possibly empty group. However, now that there is
|
||||
the possibility of (*THEN) occurring in the final alternative, this
|
||||
the possiblity of (*THEN) occurring in the final alternative, this
|
||||
optimization is no longer always possible.
|
||||
|
||||
We can optimize if we know there are no (*THEN)s in the pattern; at present
|
||||
@ -1165,11 +1165,16 @@ for (;;)
|
||||
if (rrc == MATCH_KETRPOS)
|
||||
{
|
||||
offset_top = md->end_offset_top;
|
||||
eptr = md->end_match_ptr;
|
||||
ecode = md->start_code + code_offset;
|
||||
save_capture_last = md->capture_last;
|
||||
matched_once = TRUE;
|
||||
mstart = md->start_match_ptr; /* In case \K changed it */
|
||||
if (eptr == md->end_match_ptr) /* Matched an empty string */
|
||||
{
|
||||
do ecode += GET(ecode, 1); while (*ecode == OP_ALT);
|
||||
break;
|
||||
}
|
||||
eptr = md->end_match_ptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1239,10 +1244,15 @@ for (;;)
|
||||
if (rrc == MATCH_KETRPOS)
|
||||
{
|
||||
offset_top = md->end_offset_top;
|
||||
eptr = md->end_match_ptr;
|
||||
ecode = md->start_code + code_offset;
|
||||
matched_once = TRUE;
|
||||
mstart = md->start_match_ptr; /* In case \K reset it */
|
||||
if (eptr == md->end_match_ptr) /* Matched an empty string */
|
||||
{
|
||||
do ecode += GET(ecode, 1); while (*ecode == OP_ALT);
|
||||
break;
|
||||
}
|
||||
eptr = md->end_match_ptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1977,6 +1987,19 @@ for (;;)
|
||||
}
|
||||
}
|
||||
|
||||
/* OP_KETRPOS is a possessive repeating ket. Remember the current position,
|
||||
and return the MATCH_KETRPOS. This makes it possible to do the repeats one
|
||||
at a time from the outer level, thus saving stack. This must precede the
|
||||
empty string test - in this case that test is done at the outer level. */
|
||||
|
||||
if (*ecode == OP_KETRPOS)
|
||||
{
|
||||
md->start_match_ptr = mstart; /* In case \K reset it */
|
||||
md->end_match_ptr = eptr;
|
||||
md->end_offset_top = offset_top;
|
||||
RRETURN(MATCH_KETRPOS);
|
||||
}
|
||||
|
||||
/* For an ordinary non-repeating ket, just continue at this level. This
|
||||
also happens for a repeating ket if no characters were matched in the
|
||||
group. This is the forcible breaking of infinite loops as implemented in
|
||||
@ -1999,18 +2022,6 @@ for (;;)
|
||||
break;
|
||||
}
|
||||
|
||||
/* OP_KETRPOS is a possessive repeating ket. Remember the current position,
|
||||
and return the MATCH_KETRPOS. This makes it possible to do the repeats one
|
||||
at a time from the outer level, thus saving stack. */
|
||||
|
||||
if (*ecode == OP_KETRPOS)
|
||||
{
|
||||
md->start_match_ptr = mstart; /* In case \K reset it */
|
||||
md->end_match_ptr = eptr;
|
||||
md->end_offset_top = offset_top;
|
||||
RRETURN(MATCH_KETRPOS);
|
||||
}
|
||||
|
||||
/* The normal repeating kets try the rest of the pattern or restart from
|
||||
the preceding bracket, in the appropriate order. In the second case, we can
|
||||
use tail recursion to avoid using another stack frame, unless we have an
|
||||
@ -5679,54 +5690,25 @@ for (;;)
|
||||
switch(ctype)
|
||||
{
|
||||
case OP_ANY:
|
||||
if (max < INT_MAX)
|
||||
for (i = min; i < max; i++)
|
||||
{
|
||||
for (i = min; i < max; i++)
|
||||
if (eptr >= md->end_subject)
|
||||
{
|
||||
if (eptr >= md->end_subject)
|
||||
{
|
||||
SCHECK_PARTIAL();
|
||||
break;
|
||||
}
|
||||
if (IS_NEWLINE(eptr)) break;
|
||||
if (md->partial != 0 && /* Take care with CRLF partial */
|
||||
eptr + 1 >= md->end_subject &&
|
||||
NLBLOCK->nltype == NLTYPE_FIXED &&
|
||||
NLBLOCK->nllen == 2 &&
|
||||
UCHAR21(eptr) == NLBLOCK->nl[0])
|
||||
{
|
||||
md->hitend = TRUE;
|
||||
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
|
||||
}
|
||||
eptr++;
|
||||
ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
|
||||
SCHECK_PARTIAL();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle unlimited UTF-8 repeat */
|
||||
|
||||
else
|
||||
{
|
||||
for (i = min; i < max; i++)
|
||||
if (IS_NEWLINE(eptr)) break;
|
||||
if (md->partial != 0 && /* Take care with CRLF partial */
|
||||
eptr + 1 >= md->end_subject &&
|
||||
NLBLOCK->nltype == NLTYPE_FIXED &&
|
||||
NLBLOCK->nllen == 2 &&
|
||||
UCHAR21(eptr) == NLBLOCK->nl[0])
|
||||
{
|
||||
if (eptr >= md->end_subject)
|
||||
{
|
||||
SCHECK_PARTIAL();
|
||||
break;
|
||||
}
|
||||
if (IS_NEWLINE(eptr)) break;
|
||||
if (md->partial != 0 && /* Take care with CRLF partial */
|
||||
eptr + 1 >= md->end_subject &&
|
||||
NLBLOCK->nltype == NLTYPE_FIXED &&
|
||||
NLBLOCK->nllen == 2 &&
|
||||
UCHAR21(eptr) == NLBLOCK->nl[0])
|
||||
{
|
||||
md->hitend = TRUE;
|
||||
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
|
||||
}
|
||||
eptr++;
|
||||
ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
|
||||
md->hitend = TRUE;
|
||||
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
|
||||
}
|
||||
eptr++;
|
||||
ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -6517,7 +6499,7 @@ tables = re->tables;
|
||||
|
||||
if (extra_data != NULL)
|
||||
{
|
||||
register unsigned int flags = extra_data->flags;
|
||||
unsigned long int flags = extra_data->flags;
|
||||
if ((flags & PCRE_EXTRA_STUDY_DATA) != 0)
|
||||
study = (const pcre_study_data *)extra_data->study_data;
|
||||
if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0)
|
||||
|
@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2015 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -7,7 +7,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2015 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -2281,7 +2281,7 @@ enum { ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9,
|
||||
ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59,
|
||||
ERR60, 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, ERRCOUNT };
|
||||
ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERRCOUNT };
|
||||
|
||||
/* JIT compiling modes. The function list is indexed by them. */
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -68,7 +68,7 @@ appropriately for an application, not for building PCRE. */
|
||||
#include "pcre.h"
|
||||
#include "pcre_internal.h"
|
||||
|
||||
/* These are the functions that are contained within. It doesn't seem worth
|
||||
/* These are the funtions that are contained within. It doesn't seem worth
|
||||
having a separate .h file just for this. */
|
||||
|
||||
#endif /* PCRE_INCLUDED */
|
||||
|
@ -861,7 +861,6 @@ do
|
||||
case OP_NOTUPTOI:
|
||||
case OP_NOT_HSPACE:
|
||||
case OP_NOT_VSPACE:
|
||||
case OP_PROP:
|
||||
case OP_PRUNE:
|
||||
case OP_PRUNE_ARG:
|
||||
case OP_RECURSE:
|
||||
@ -879,6 +878,31 @@ do
|
||||
case OP_THEN_ARG:
|
||||
return SSB_FAIL;
|
||||
|
||||
/* A "real" property test implies no starting bits, but the fake property
|
||||
PT_CLIST identifies a list of characters. These lists are short, as they
|
||||
are used for characters with more than one "other case", so there is no
|
||||
point in recognizing them for OP_NOTPROP. */
|
||||
|
||||
case OP_PROP:
|
||||
if (tcode[1] != PT_CLIST) return SSB_FAIL;
|
||||
{
|
||||
const pcre_uint32 *p = PRIV(ucd_caseless_sets) + tcode[2];
|
||||
while ((c = *p++) < NOTACHAR)
|
||||
{
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
|
||||
if (utf)
|
||||
{
|
||||
pcre_uchar buff[6];
|
||||
(void)PRIV(ord2utf)(c, buff);
|
||||
c = buff[0];
|
||||
}
|
||||
#endif
|
||||
if (c > 0xff) SET_BIT(0xff); else SET_BIT(c);
|
||||
}
|
||||
}
|
||||
try_next = FALSE;
|
||||
break;
|
||||
|
||||
/* We can ignore word boundary tests. */
|
||||
|
||||
case OP_WORD_BOUNDARY:
|
||||
@ -988,7 +1012,7 @@ do
|
||||
tcode = set_table_bit(start_bits, tcode + 1, TRUE, cd, utf);
|
||||
break;
|
||||
|
||||
/* Single-char up to sets the bit and tries the next */
|
||||
/* Single-char upto sets the bit and tries the next */
|
||||
|
||||
case OP_UPTO:
|
||||
case OP_MINUPTO:
|
||||
@ -1104,24 +1128,17 @@ do
|
||||
try_next = FALSE;
|
||||
break;
|
||||
|
||||
/* The cbit_space table has vertical tab as whitespace; we have to
|
||||
ensure it is set as not whitespace. Luckily, the code value is the same
|
||||
(0x0b) in ASCII and EBCDIC, so we can just adjust the appropriate bit. */
|
||||
/* The cbit_space table has vertical tab as whitespace; we no longer
|
||||
have to play fancy tricks because Perl added VT to its whitespace at
|
||||
release 5.18. PCRE added it at release 8.34. */
|
||||
|
||||
case OP_NOT_WHITESPACE:
|
||||
set_nottype_bits(start_bits, cbit_space, table_limit, cd);
|
||||
start_bits[1] |= 0x08;
|
||||
try_next = FALSE;
|
||||
break;
|
||||
|
||||
/* The cbit_space table has vertical tab as whitespace; we have to not
|
||||
set it from the table. Luckily, the code value is the same (0x0b) in
|
||||
ASCII and EBCDIC, so we can just adjust the appropriate bit. */
|
||||
|
||||
case OP_WHITESPACE:
|
||||
c = start_bits[1]; /* Save in case it was already set */
|
||||
set_type_bits(start_bits, cbit_space, table_limit, cd);
|
||||
start_bits[1] = (start_bits[1] & ~0x08) | c;
|
||||
try_next = FALSE;
|
||||
break;
|
||||
|
||||
|
@ -211,6 +211,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
||||
#define STRING_Avestan0 STR_A STR_v STR_e STR_s STR_t STR_a STR_n "\0"
|
||||
#define STRING_Balinese0 STR_B STR_a STR_l STR_i STR_n STR_e STR_s STR_e "\0"
|
||||
#define STRING_Bamum0 STR_B STR_a STR_m STR_u STR_m "\0"
|
||||
#define STRING_Bassa_Vah0 STR_B STR_a STR_s STR_s STR_a STR_UNDERSCORE STR_V STR_a STR_h "\0"
|
||||
#define STRING_Batak0 STR_B STR_a STR_t STR_a STR_k "\0"
|
||||
#define STRING_Bengali0 STR_B STR_e STR_n STR_g STR_a STR_l STR_i "\0"
|
||||
#define STRING_Bopomofo0 STR_B STR_o STR_p STR_o STR_m STR_o STR_f STR_o "\0"
|
||||
@ -221,6 +222,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
||||
#define STRING_C0 STR_C "\0"
|
||||
#define STRING_Canadian_Aboriginal0 STR_C STR_a STR_n STR_a STR_d STR_i STR_a STR_n STR_UNDERSCORE STR_A STR_b STR_o STR_r STR_i STR_g STR_i STR_n STR_a STR_l "\0"
|
||||
#define STRING_Carian0 STR_C STR_a STR_r STR_i STR_a STR_n "\0"
|
||||
#define STRING_Caucasian_Albanian0 STR_C STR_a STR_u STR_c STR_a STR_s STR_i STR_a STR_n STR_UNDERSCORE STR_A STR_l STR_b STR_a STR_n STR_i STR_a STR_n "\0"
|
||||
#define STRING_Cc0 STR_C STR_c "\0"
|
||||
#define STRING_Cf0 STR_C STR_f "\0"
|
||||
#define STRING_Chakma0 STR_C STR_h STR_a STR_k STR_m STR_a "\0"
|
||||
@ -236,11 +238,14 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
||||
#define STRING_Cyrillic0 STR_C STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0"
|
||||
#define STRING_Deseret0 STR_D STR_e STR_s STR_e STR_r STR_e STR_t "\0"
|
||||
#define STRING_Devanagari0 STR_D STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0"
|
||||
#define STRING_Duployan0 STR_D STR_u STR_p STR_l STR_o STR_y STR_a STR_n "\0"
|
||||
#define STRING_Egyptian_Hieroglyphs0 STR_E STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
|
||||
#define STRING_Elbasan0 STR_E STR_l STR_b STR_a STR_s STR_a STR_n "\0"
|
||||
#define STRING_Ethiopic0 STR_E STR_t STR_h STR_i STR_o STR_p STR_i STR_c "\0"
|
||||
#define STRING_Georgian0 STR_G STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0"
|
||||
#define STRING_Glagolitic0 STR_G STR_l STR_a STR_g STR_o STR_l STR_i STR_t STR_i STR_c "\0"
|
||||
#define STRING_Gothic0 STR_G STR_o STR_t STR_h STR_i STR_c "\0"
|
||||
#define STRING_Grantha0 STR_G STR_r STR_a STR_n STR_t STR_h STR_a "\0"
|
||||
#define STRING_Greek0 STR_G STR_r STR_e STR_e STR_k "\0"
|
||||
#define STRING_Gujarati0 STR_G STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0"
|
||||
#define STRING_Gurmukhi0 STR_G STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0"
|
||||
@ -260,12 +265,15 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
||||
#define STRING_Kayah_Li0 STR_K STR_a STR_y STR_a STR_h STR_UNDERSCORE STR_L STR_i "\0"
|
||||
#define STRING_Kharoshthi0 STR_K STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0"
|
||||
#define STRING_Khmer0 STR_K STR_h STR_m STR_e STR_r "\0"
|
||||
#define STRING_Khojki0 STR_K STR_h STR_o STR_j STR_k STR_i "\0"
|
||||
#define STRING_Khudawadi0 STR_K STR_h STR_u STR_d STR_a STR_w STR_a STR_d STR_i "\0"
|
||||
#define STRING_L0 STR_L "\0"
|
||||
#define STRING_L_AMPERSAND0 STR_L STR_AMPERSAND "\0"
|
||||
#define STRING_Lao0 STR_L STR_a STR_o "\0"
|
||||
#define STRING_Latin0 STR_L STR_a STR_t STR_i STR_n "\0"
|
||||
#define STRING_Lepcha0 STR_L STR_e STR_p STR_c STR_h STR_a "\0"
|
||||
#define STRING_Limbu0 STR_L STR_i STR_m STR_b STR_u "\0"
|
||||
#define STRING_Linear_A0 STR_L STR_i STR_n STR_e STR_a STR_r STR_UNDERSCORE STR_A "\0"
|
||||
#define STRING_Linear_B0 STR_L STR_i STR_n STR_e STR_a STR_r STR_UNDERSCORE STR_B "\0"
|
||||
#define STRING_Lisu0 STR_L STR_i STR_s STR_u "\0"
|
||||
#define STRING_Ll0 STR_L STR_l "\0"
|
||||
@ -276,18 +284,24 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
||||
#define STRING_Lycian0 STR_L STR_y STR_c STR_i STR_a STR_n "\0"
|
||||
#define STRING_Lydian0 STR_L STR_y STR_d STR_i STR_a STR_n "\0"
|
||||
#define STRING_M0 STR_M "\0"
|
||||
#define STRING_Mahajani0 STR_M STR_a STR_h STR_a STR_j STR_a STR_n STR_i "\0"
|
||||
#define STRING_Malayalam0 STR_M STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0"
|
||||
#define STRING_Mandaic0 STR_M STR_a STR_n STR_d STR_a STR_i STR_c "\0"
|
||||
#define STRING_Manichaean0 STR_M STR_a STR_n STR_i STR_c STR_h STR_a STR_e STR_a STR_n "\0"
|
||||
#define STRING_Mc0 STR_M STR_c "\0"
|
||||
#define STRING_Me0 STR_M STR_e "\0"
|
||||
#define STRING_Meetei_Mayek0 STR_M STR_e STR_e STR_t STR_e STR_i STR_UNDERSCORE STR_M STR_a STR_y STR_e STR_k "\0"
|
||||
#define STRING_Mende_Kikakui0 STR_M STR_e STR_n STR_d STR_e STR_UNDERSCORE STR_K STR_i STR_k STR_a STR_k STR_u STR_i "\0"
|
||||
#define STRING_Meroitic_Cursive0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_C STR_u STR_r STR_s STR_i STR_v STR_e "\0"
|
||||
#define STRING_Meroitic_Hieroglyphs0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
|
||||
#define STRING_Miao0 STR_M STR_i STR_a STR_o "\0"
|
||||
#define STRING_Mn0 STR_M STR_n "\0"
|
||||
#define STRING_Modi0 STR_M STR_o STR_d STR_i "\0"
|
||||
#define STRING_Mongolian0 STR_M STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0"
|
||||
#define STRING_Mro0 STR_M STR_r STR_o "\0"
|
||||
#define STRING_Myanmar0 STR_M STR_y STR_a STR_n STR_m STR_a STR_r "\0"
|
||||
#define STRING_N0 STR_N "\0"
|
||||
#define STRING_Nabataean0 STR_N STR_a STR_b STR_a STR_t STR_a STR_e STR_a STR_n "\0"
|
||||
#define STRING_Nd0 STR_N STR_d "\0"
|
||||
#define STRING_New_Tai_Lue0 STR_N STR_e STR_w STR_UNDERSCORE STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_u STR_e "\0"
|
||||
#define STRING_Nko0 STR_N STR_k STR_o "\0"
|
||||
@ -296,12 +310,17 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
||||
#define STRING_Ogham0 STR_O STR_g STR_h STR_a STR_m "\0"
|
||||
#define STRING_Ol_Chiki0 STR_O STR_l STR_UNDERSCORE STR_C STR_h STR_i STR_k STR_i "\0"
|
||||
#define STRING_Old_Italic0 STR_O STR_l STR_d STR_UNDERSCORE STR_I STR_t STR_a STR_l STR_i STR_c "\0"
|
||||
#define STRING_Old_North_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_N STR_o STR_r STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0"
|
||||
#define STRING_Old_Permic0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_m STR_i STR_c "\0"
|
||||
#define STRING_Old_Persian0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_s STR_i STR_a STR_n "\0"
|
||||
#define STRING_Old_South_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_u STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0"
|
||||
#define STRING_Old_Turkic0 STR_O STR_l STR_d STR_UNDERSCORE STR_T STR_u STR_r STR_k STR_i STR_c "\0"
|
||||
#define STRING_Oriya0 STR_O STR_r STR_i STR_y STR_a "\0"
|
||||
#define STRING_Osmanya0 STR_O STR_s STR_m STR_a STR_n STR_y STR_a "\0"
|
||||
#define STRING_P0 STR_P "\0"
|
||||
#define STRING_Pahawh_Hmong0 STR_P STR_a STR_h STR_a STR_w STR_h STR_UNDERSCORE STR_H STR_m STR_o STR_n STR_g "\0"
|
||||
#define STRING_Palmyrene0 STR_P STR_a STR_l STR_m STR_y STR_r STR_e STR_n STR_e "\0"
|
||||
#define STRING_Pau_Cin_Hau0 STR_P STR_a STR_u STR_UNDERSCORE STR_C STR_i STR_n STR_UNDERSCORE STR_H STR_a STR_u "\0"
|
||||
#define STRING_Pc0 STR_P STR_c "\0"
|
||||
#define STRING_Pd0 STR_P STR_d "\0"
|
||||
#define STRING_Pe0 STR_P STR_e "\0"
|
||||
@ -311,6 +330,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
||||
#define STRING_Pi0 STR_P STR_i "\0"
|
||||
#define STRING_Po0 STR_P STR_o "\0"
|
||||
#define STRING_Ps0 STR_P STR_s "\0"
|
||||
#define STRING_Psalter_Pahlavi0 STR_P STR_s STR_a STR_l STR_t STR_e STR_r STR_UNDERSCORE STR_P STR_a STR_h STR_l STR_a STR_v STR_i "\0"
|
||||
#define STRING_Rejang0 STR_R STR_e STR_j STR_a STR_n STR_g "\0"
|
||||
#define STRING_Runic0 STR_R STR_u STR_n STR_i STR_c "\0"
|
||||
#define STRING_S0 STR_S "\0"
|
||||
@ -319,6 +339,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
||||
#define STRING_Sc0 STR_S STR_c "\0"
|
||||
#define STRING_Sharada0 STR_S STR_h STR_a STR_r STR_a STR_d STR_a "\0"
|
||||
#define STRING_Shavian0 STR_S STR_h STR_a STR_v STR_i STR_a STR_n "\0"
|
||||
#define STRING_Siddham0 STR_S STR_i STR_d STR_d STR_h STR_a STR_m "\0"
|
||||
#define STRING_Sinhala0 STR_S STR_i STR_n STR_h STR_a STR_l STR_a "\0"
|
||||
#define STRING_Sk0 STR_S STR_k "\0"
|
||||
#define STRING_Sm0 STR_S STR_m "\0"
|
||||
@ -339,8 +360,10 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
||||
#define STRING_Thai0 STR_T STR_h STR_a STR_i "\0"
|
||||
#define STRING_Tibetan0 STR_T STR_i STR_b STR_e STR_t STR_a STR_n "\0"
|
||||
#define STRING_Tifinagh0 STR_T STR_i STR_f STR_i STR_n STR_a STR_g STR_h "\0"
|
||||
#define STRING_Tirhuta0 STR_T STR_i STR_r STR_h STR_u STR_t STR_a "\0"
|
||||
#define STRING_Ugaritic0 STR_U STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0"
|
||||
#define STRING_Vai0 STR_V STR_a STR_i "\0"
|
||||
#define STRING_Warang_Citi0 STR_W STR_a STR_r STR_a STR_n STR_g STR_UNDERSCORE STR_C STR_i STR_t STR_i "\0"
|
||||
#define STRING_Xan0 STR_X STR_a STR_n "\0"
|
||||
#define STRING_Xps0 STR_X STR_p STR_s "\0"
|
||||
#define STRING_Xsp0 STR_X STR_s STR_p "\0"
|
||||
@ -359,6 +382,7 @@ const char PRIV(utt_names)[] =
|
||||
STRING_Avestan0
|
||||
STRING_Balinese0
|
||||
STRING_Bamum0
|
||||
STRING_Bassa_Vah0
|
||||
STRING_Batak0
|
||||
STRING_Bengali0
|
||||
STRING_Bopomofo0
|
||||
@ -369,6 +393,7 @@ const char PRIV(utt_names)[] =
|
||||
STRING_C0
|
||||
STRING_Canadian_Aboriginal0
|
||||
STRING_Carian0
|
||||
STRING_Caucasian_Albanian0
|
||||
STRING_Cc0
|
||||
STRING_Cf0
|
||||
STRING_Chakma0
|
||||
@ -384,11 +409,14 @@ const char PRIV(utt_names)[] =
|
||||
STRING_Cyrillic0
|
||||
STRING_Deseret0
|
||||
STRING_Devanagari0
|
||||
STRING_Duployan0
|
||||
STRING_Egyptian_Hieroglyphs0
|
||||
STRING_Elbasan0
|
||||
STRING_Ethiopic0
|
||||
STRING_Georgian0
|
||||
STRING_Glagolitic0
|
||||
STRING_Gothic0
|
||||
STRING_Grantha0
|
||||
STRING_Greek0
|
||||
STRING_Gujarati0
|
||||
STRING_Gurmukhi0
|
||||
@ -408,12 +436,15 @@ const char PRIV(utt_names)[] =
|
||||
STRING_Kayah_Li0
|
||||
STRING_Kharoshthi0
|
||||
STRING_Khmer0
|
||||
STRING_Khojki0
|
||||
STRING_Khudawadi0
|
||||
STRING_L0
|
||||
STRING_L_AMPERSAND0
|
||||
STRING_Lao0
|
||||
STRING_Latin0
|
||||
STRING_Lepcha0
|
||||
STRING_Limbu0
|
||||
STRING_Linear_A0
|
||||
STRING_Linear_B0
|
||||
STRING_Lisu0
|
||||
STRING_Ll0
|
||||
@ -424,18 +455,24 @@ const char PRIV(utt_names)[] =
|
||||
STRING_Lycian0
|
||||
STRING_Lydian0
|
||||
STRING_M0
|
||||
STRING_Mahajani0
|
||||
STRING_Malayalam0
|
||||
STRING_Mandaic0
|
||||
STRING_Manichaean0
|
||||
STRING_Mc0
|
||||
STRING_Me0
|
||||
STRING_Meetei_Mayek0
|
||||
STRING_Mende_Kikakui0
|
||||
STRING_Meroitic_Cursive0
|
||||
STRING_Meroitic_Hieroglyphs0
|
||||
STRING_Miao0
|
||||
STRING_Mn0
|
||||
STRING_Modi0
|
||||
STRING_Mongolian0
|
||||
STRING_Mro0
|
||||
STRING_Myanmar0
|
||||
STRING_N0
|
||||
STRING_Nabataean0
|
||||
STRING_Nd0
|
||||
STRING_New_Tai_Lue0
|
||||
STRING_Nko0
|
||||
@ -444,12 +481,17 @@ const char PRIV(utt_names)[] =
|
||||
STRING_Ogham0
|
||||
STRING_Ol_Chiki0
|
||||
STRING_Old_Italic0
|
||||
STRING_Old_North_Arabian0
|
||||
STRING_Old_Permic0
|
||||
STRING_Old_Persian0
|
||||
STRING_Old_South_Arabian0
|
||||
STRING_Old_Turkic0
|
||||
STRING_Oriya0
|
||||
STRING_Osmanya0
|
||||
STRING_P0
|
||||
STRING_Pahawh_Hmong0
|
||||
STRING_Palmyrene0
|
||||
STRING_Pau_Cin_Hau0
|
||||
STRING_Pc0
|
||||
STRING_Pd0
|
||||
STRING_Pe0
|
||||
@ -459,6 +501,7 @@ const char PRIV(utt_names)[] =
|
||||
STRING_Pi0
|
||||
STRING_Po0
|
||||
STRING_Ps0
|
||||
STRING_Psalter_Pahlavi0
|
||||
STRING_Rejang0
|
||||
STRING_Runic0
|
||||
STRING_S0
|
||||
@ -467,6 +510,7 @@ const char PRIV(utt_names)[] =
|
||||
STRING_Sc0
|
||||
STRING_Sharada0
|
||||
STRING_Shavian0
|
||||
STRING_Siddham0
|
||||
STRING_Sinhala0
|
||||
STRING_Sk0
|
||||
STRING_Sm0
|
||||
@ -487,8 +531,10 @@ const char PRIV(utt_names)[] =
|
||||
STRING_Thai0
|
||||
STRING_Tibetan0
|
||||
STRING_Tifinagh0
|
||||
STRING_Tirhuta0
|
||||
STRING_Ugaritic0
|
||||
STRING_Vai0
|
||||
STRING_Warang_Citi0
|
||||
STRING_Xan0
|
||||
STRING_Xps0
|
||||
STRING_Xsp0
|
||||
@ -507,146 +553,169 @@ const ucp_type_table PRIV(utt)[] = {
|
||||
{ 20, PT_SC, ucp_Avestan },
|
||||
{ 28, PT_SC, ucp_Balinese },
|
||||
{ 37, PT_SC, ucp_Bamum },
|
||||
{ 43, PT_SC, ucp_Batak },
|
||||
{ 49, PT_SC, ucp_Bengali },
|
||||
{ 57, PT_SC, ucp_Bopomofo },
|
||||
{ 66, PT_SC, ucp_Brahmi },
|
||||
{ 73, PT_SC, ucp_Braille },
|
||||
{ 81, PT_SC, ucp_Buginese },
|
||||
{ 90, PT_SC, ucp_Buhid },
|
||||
{ 96, PT_GC, ucp_C },
|
||||
{ 98, PT_SC, ucp_Canadian_Aboriginal },
|
||||
{ 118, PT_SC, ucp_Carian },
|
||||
{ 125, PT_PC, ucp_Cc },
|
||||
{ 128, PT_PC, ucp_Cf },
|
||||
{ 131, PT_SC, ucp_Chakma },
|
||||
{ 138, PT_SC, ucp_Cham },
|
||||
{ 143, PT_SC, ucp_Cherokee },
|
||||
{ 152, PT_PC, ucp_Cn },
|
||||
{ 155, PT_PC, ucp_Co },
|
||||
{ 158, PT_SC, ucp_Common },
|
||||
{ 165, PT_SC, ucp_Coptic },
|
||||
{ 172, PT_PC, ucp_Cs },
|
||||
{ 175, PT_SC, ucp_Cuneiform },
|
||||
{ 185, PT_SC, ucp_Cypriot },
|
||||
{ 193, PT_SC, ucp_Cyrillic },
|
||||
{ 202, PT_SC, ucp_Deseret },
|
||||
{ 210, PT_SC, ucp_Devanagari },
|
||||
{ 221, PT_SC, ucp_Egyptian_Hieroglyphs },
|
||||
{ 242, PT_SC, ucp_Ethiopic },
|
||||
{ 251, PT_SC, ucp_Georgian },
|
||||
{ 260, PT_SC, ucp_Glagolitic },
|
||||
{ 271, PT_SC, ucp_Gothic },
|
||||
{ 278, PT_SC, ucp_Greek },
|
||||
{ 284, PT_SC, ucp_Gujarati },
|
||||
{ 293, PT_SC, ucp_Gurmukhi },
|
||||
{ 302, PT_SC, ucp_Han },
|
||||
{ 306, PT_SC, ucp_Hangul },
|
||||
{ 313, PT_SC, ucp_Hanunoo },
|
||||
{ 321, PT_SC, ucp_Hebrew },
|
||||
{ 328, PT_SC, ucp_Hiragana },
|
||||
{ 337, PT_SC, ucp_Imperial_Aramaic },
|
||||
{ 354, PT_SC, ucp_Inherited },
|
||||
{ 364, PT_SC, ucp_Inscriptional_Pahlavi },
|
||||
{ 386, PT_SC, ucp_Inscriptional_Parthian },
|
||||
{ 409, PT_SC, ucp_Javanese },
|
||||
{ 418, PT_SC, ucp_Kaithi },
|
||||
{ 425, PT_SC, ucp_Kannada },
|
||||
{ 433, PT_SC, ucp_Katakana },
|
||||
{ 442, PT_SC, ucp_Kayah_Li },
|
||||
{ 451, PT_SC, ucp_Kharoshthi },
|
||||
{ 462, PT_SC, ucp_Khmer },
|
||||
{ 468, PT_GC, ucp_L },
|
||||
{ 470, PT_LAMP, 0 },
|
||||
{ 473, PT_SC, ucp_Lao },
|
||||
{ 477, PT_SC, ucp_Latin },
|
||||
{ 483, PT_SC, ucp_Lepcha },
|
||||
{ 490, PT_SC, ucp_Limbu },
|
||||
{ 496, PT_SC, ucp_Linear_B },
|
||||
{ 505, PT_SC, ucp_Lisu },
|
||||
{ 510, PT_PC, ucp_Ll },
|
||||
{ 513, PT_PC, ucp_Lm },
|
||||
{ 516, PT_PC, ucp_Lo },
|
||||
{ 519, PT_PC, ucp_Lt },
|
||||
{ 522, PT_PC, ucp_Lu },
|
||||
{ 525, PT_SC, ucp_Lycian },
|
||||
{ 532, PT_SC, ucp_Lydian },
|
||||
{ 539, PT_GC, ucp_M },
|
||||
{ 541, PT_SC, ucp_Malayalam },
|
||||
{ 551, PT_SC, ucp_Mandaic },
|
||||
{ 559, PT_PC, ucp_Mc },
|
||||
{ 562, PT_PC, ucp_Me },
|
||||
{ 565, PT_SC, ucp_Meetei_Mayek },
|
||||
{ 578, PT_SC, ucp_Meroitic_Cursive },
|
||||
{ 595, PT_SC, ucp_Meroitic_Hieroglyphs },
|
||||
{ 616, PT_SC, ucp_Miao },
|
||||
{ 621, PT_PC, ucp_Mn },
|
||||
{ 624, PT_SC, ucp_Mongolian },
|
||||
{ 634, PT_SC, ucp_Myanmar },
|
||||
{ 642, PT_GC, ucp_N },
|
||||
{ 644, PT_PC, ucp_Nd },
|
||||
{ 647, PT_SC, ucp_New_Tai_Lue },
|
||||
{ 659, PT_SC, ucp_Nko },
|
||||
{ 663, PT_PC, ucp_Nl },
|
||||
{ 666, PT_PC, ucp_No },
|
||||
{ 669, PT_SC, ucp_Ogham },
|
||||
{ 675, PT_SC, ucp_Ol_Chiki },
|
||||
{ 684, PT_SC, ucp_Old_Italic },
|
||||
{ 695, PT_SC, ucp_Old_Persian },
|
||||
{ 707, PT_SC, ucp_Old_South_Arabian },
|
||||
{ 725, PT_SC, ucp_Old_Turkic },
|
||||
{ 736, PT_SC, ucp_Oriya },
|
||||
{ 742, PT_SC, ucp_Osmanya },
|
||||
{ 750, PT_GC, ucp_P },
|
||||
{ 752, PT_PC, ucp_Pc },
|
||||
{ 755, PT_PC, ucp_Pd },
|
||||
{ 758, PT_PC, ucp_Pe },
|
||||
{ 761, PT_PC, ucp_Pf },
|
||||
{ 764, PT_SC, ucp_Phags_Pa },
|
||||
{ 773, PT_SC, ucp_Phoenician },
|
||||
{ 784, PT_PC, ucp_Pi },
|
||||
{ 787, PT_PC, ucp_Po },
|
||||
{ 790, PT_PC, ucp_Ps },
|
||||
{ 793, PT_SC, ucp_Rejang },
|
||||
{ 800, PT_SC, ucp_Runic },
|
||||
{ 806, PT_GC, ucp_S },
|
||||
{ 808, PT_SC, ucp_Samaritan },
|
||||
{ 818, PT_SC, ucp_Saurashtra },
|
||||
{ 829, PT_PC, ucp_Sc },
|
||||
{ 832, PT_SC, ucp_Sharada },
|
||||
{ 840, PT_SC, ucp_Shavian },
|
||||
{ 848, PT_SC, ucp_Sinhala },
|
||||
{ 856, PT_PC, ucp_Sk },
|
||||
{ 859, PT_PC, ucp_Sm },
|
||||
{ 862, PT_PC, ucp_So },
|
||||
{ 865, PT_SC, ucp_Sora_Sompeng },
|
||||
{ 878, PT_SC, ucp_Sundanese },
|
||||
{ 888, PT_SC, ucp_Syloti_Nagri },
|
||||
{ 901, PT_SC, ucp_Syriac },
|
||||
{ 908, PT_SC, ucp_Tagalog },
|
||||
{ 916, PT_SC, ucp_Tagbanwa },
|
||||
{ 925, PT_SC, ucp_Tai_Le },
|
||||
{ 932, PT_SC, ucp_Tai_Tham },
|
||||
{ 941, PT_SC, ucp_Tai_Viet },
|
||||
{ 950, PT_SC, ucp_Takri },
|
||||
{ 956, PT_SC, ucp_Tamil },
|
||||
{ 962, PT_SC, ucp_Telugu },
|
||||
{ 969, PT_SC, ucp_Thaana },
|
||||
{ 976, PT_SC, ucp_Thai },
|
||||
{ 981, PT_SC, ucp_Tibetan },
|
||||
{ 989, PT_SC, ucp_Tifinagh },
|
||||
{ 998, PT_SC, ucp_Ugaritic },
|
||||
{ 1007, PT_SC, ucp_Vai },
|
||||
{ 1011, PT_ALNUM, 0 },
|
||||
{ 1015, PT_PXSPACE, 0 },
|
||||
{ 1019, PT_SPACE, 0 },
|
||||
{ 1023, PT_UCNC, 0 },
|
||||
{ 1027, PT_WORD, 0 },
|
||||
{ 1031, PT_SC, ucp_Yi },
|
||||
{ 1034, PT_GC, ucp_Z },
|
||||
{ 1036, PT_PC, ucp_Zl },
|
||||
{ 1039, PT_PC, ucp_Zp },
|
||||
{ 1042, PT_PC, ucp_Zs }
|
||||
{ 43, PT_SC, ucp_Bassa_Vah },
|
||||
{ 53, PT_SC, ucp_Batak },
|
||||
{ 59, PT_SC, ucp_Bengali },
|
||||
{ 67, PT_SC, ucp_Bopomofo },
|
||||
{ 76, PT_SC, ucp_Brahmi },
|
||||
{ 83, PT_SC, ucp_Braille },
|
||||
{ 91, PT_SC, ucp_Buginese },
|
||||
{ 100, PT_SC, ucp_Buhid },
|
||||
{ 106, PT_GC, ucp_C },
|
||||
{ 108, PT_SC, ucp_Canadian_Aboriginal },
|
||||
{ 128, PT_SC, ucp_Carian },
|
||||
{ 135, PT_SC, ucp_Caucasian_Albanian },
|
||||
{ 154, PT_PC, ucp_Cc },
|
||||
{ 157, PT_PC, ucp_Cf },
|
||||
{ 160, PT_SC, ucp_Chakma },
|
||||
{ 167, PT_SC, ucp_Cham },
|
||||
{ 172, PT_SC, ucp_Cherokee },
|
||||
{ 181, PT_PC, ucp_Cn },
|
||||
{ 184, PT_PC, ucp_Co },
|
||||
{ 187, PT_SC, ucp_Common },
|
||||
{ 194, PT_SC, ucp_Coptic },
|
||||
{ 201, PT_PC, ucp_Cs },
|
||||
{ 204, PT_SC, ucp_Cuneiform },
|
||||
{ 214, PT_SC, ucp_Cypriot },
|
||||
{ 222, PT_SC, ucp_Cyrillic },
|
||||
{ 231, PT_SC, ucp_Deseret },
|
||||
{ 239, PT_SC, ucp_Devanagari },
|
||||
{ 250, PT_SC, ucp_Duployan },
|
||||
{ 259, PT_SC, ucp_Egyptian_Hieroglyphs },
|
||||
{ 280, PT_SC, ucp_Elbasan },
|
||||
{ 288, PT_SC, ucp_Ethiopic },
|
||||
{ 297, PT_SC, ucp_Georgian },
|
||||
{ 306, PT_SC, ucp_Glagolitic },
|
||||
{ 317, PT_SC, ucp_Gothic },
|
||||
{ 324, PT_SC, ucp_Grantha },
|
||||
{ 332, PT_SC, ucp_Greek },
|
||||
{ 338, PT_SC, ucp_Gujarati },
|
||||
{ 347, PT_SC, ucp_Gurmukhi },
|
||||
{ 356, PT_SC, ucp_Han },
|
||||
{ 360, PT_SC, ucp_Hangul },
|
||||
{ 367, PT_SC, ucp_Hanunoo },
|
||||
{ 375, PT_SC, ucp_Hebrew },
|
||||
{ 382, PT_SC, ucp_Hiragana },
|
||||
{ 391, PT_SC, ucp_Imperial_Aramaic },
|
||||
{ 408, PT_SC, ucp_Inherited },
|
||||
{ 418, PT_SC, ucp_Inscriptional_Pahlavi },
|
||||
{ 440, PT_SC, ucp_Inscriptional_Parthian },
|
||||
{ 463, PT_SC, ucp_Javanese },
|
||||
{ 472, PT_SC, ucp_Kaithi },
|
||||
{ 479, PT_SC, ucp_Kannada },
|
||||
{ 487, PT_SC, ucp_Katakana },
|
||||
{ 496, PT_SC, ucp_Kayah_Li },
|
||||
{ 505, PT_SC, ucp_Kharoshthi },
|
||||
{ 516, PT_SC, ucp_Khmer },
|
||||
{ 522, PT_SC, ucp_Khojki },
|
||||
{ 529, PT_SC, ucp_Khudawadi },
|
||||
{ 539, PT_GC, ucp_L },
|
||||
{ 541, PT_LAMP, 0 },
|
||||
{ 544, PT_SC, ucp_Lao },
|
||||
{ 548, PT_SC, ucp_Latin },
|
||||
{ 554, PT_SC, ucp_Lepcha },
|
||||
{ 561, PT_SC, ucp_Limbu },
|
||||
{ 567, PT_SC, ucp_Linear_A },
|
||||
{ 576, PT_SC, ucp_Linear_B },
|
||||
{ 585, PT_SC, ucp_Lisu },
|
||||
{ 590, PT_PC, ucp_Ll },
|
||||
{ 593, PT_PC, ucp_Lm },
|
||||
{ 596, PT_PC, ucp_Lo },
|
||||
{ 599, PT_PC, ucp_Lt },
|
||||
{ 602, PT_PC, ucp_Lu },
|
||||
{ 605, PT_SC, ucp_Lycian },
|
||||
{ 612, PT_SC, ucp_Lydian },
|
||||
{ 619, PT_GC, ucp_M },
|
||||
{ 621, PT_SC, ucp_Mahajani },
|
||||
{ 630, PT_SC, ucp_Malayalam },
|
||||
{ 640, PT_SC, ucp_Mandaic },
|
||||
{ 648, PT_SC, ucp_Manichaean },
|
||||
{ 659, PT_PC, ucp_Mc },
|
||||
{ 662, PT_PC, ucp_Me },
|
||||
{ 665, PT_SC, ucp_Meetei_Mayek },
|
||||
{ 678, PT_SC, ucp_Mende_Kikakui },
|
||||
{ 692, PT_SC, ucp_Meroitic_Cursive },
|
||||
{ 709, PT_SC, ucp_Meroitic_Hieroglyphs },
|
||||
{ 730, PT_SC, ucp_Miao },
|
||||
{ 735, PT_PC, ucp_Mn },
|
||||
{ 738, PT_SC, ucp_Modi },
|
||||
{ 743, PT_SC, ucp_Mongolian },
|
||||
{ 753, PT_SC, ucp_Mro },
|
||||
{ 757, PT_SC, ucp_Myanmar },
|
||||
{ 765, PT_GC, ucp_N },
|
||||
{ 767, PT_SC, ucp_Nabataean },
|
||||
{ 777, PT_PC, ucp_Nd },
|
||||
{ 780, PT_SC, ucp_New_Tai_Lue },
|
||||
{ 792, PT_SC, ucp_Nko },
|
||||
{ 796, PT_PC, ucp_Nl },
|
||||
{ 799, PT_PC, ucp_No },
|
||||
{ 802, PT_SC, ucp_Ogham },
|
||||
{ 808, PT_SC, ucp_Ol_Chiki },
|
||||
{ 817, PT_SC, ucp_Old_Italic },
|
||||
{ 828, PT_SC, ucp_Old_North_Arabian },
|
||||
{ 846, PT_SC, ucp_Old_Permic },
|
||||
{ 857, PT_SC, ucp_Old_Persian },
|
||||
{ 869, PT_SC, ucp_Old_South_Arabian },
|
||||
{ 887, PT_SC, ucp_Old_Turkic },
|
||||
{ 898, PT_SC, ucp_Oriya },
|
||||
{ 904, PT_SC, ucp_Osmanya },
|
||||
{ 912, PT_GC, ucp_P },
|
||||
{ 914, PT_SC, ucp_Pahawh_Hmong },
|
||||
{ 927, PT_SC, ucp_Palmyrene },
|
||||
{ 937, PT_SC, ucp_Pau_Cin_Hau },
|
||||
{ 949, PT_PC, ucp_Pc },
|
||||
{ 952, PT_PC, ucp_Pd },
|
||||
{ 955, PT_PC, ucp_Pe },
|
||||
{ 958, PT_PC, ucp_Pf },
|
||||
{ 961, PT_SC, ucp_Phags_Pa },
|
||||
{ 970, PT_SC, ucp_Phoenician },
|
||||
{ 981, PT_PC, ucp_Pi },
|
||||
{ 984, PT_PC, ucp_Po },
|
||||
{ 987, PT_PC, ucp_Ps },
|
||||
{ 990, PT_SC, ucp_Psalter_Pahlavi },
|
||||
{ 1006, PT_SC, ucp_Rejang },
|
||||
{ 1013, PT_SC, ucp_Runic },
|
||||
{ 1019, PT_GC, ucp_S },
|
||||
{ 1021, PT_SC, ucp_Samaritan },
|
||||
{ 1031, PT_SC, ucp_Saurashtra },
|
||||
{ 1042, PT_PC, ucp_Sc },
|
||||
{ 1045, PT_SC, ucp_Sharada },
|
||||
{ 1053, PT_SC, ucp_Shavian },
|
||||
{ 1061, PT_SC, ucp_Siddham },
|
||||
{ 1069, PT_SC, ucp_Sinhala },
|
||||
{ 1077, PT_PC, ucp_Sk },
|
||||
{ 1080, PT_PC, ucp_Sm },
|
||||
{ 1083, PT_PC, ucp_So },
|
||||
{ 1086, PT_SC, ucp_Sora_Sompeng },
|
||||
{ 1099, PT_SC, ucp_Sundanese },
|
||||
{ 1109, PT_SC, ucp_Syloti_Nagri },
|
||||
{ 1122, PT_SC, ucp_Syriac },
|
||||
{ 1129, PT_SC, ucp_Tagalog },
|
||||
{ 1137, PT_SC, ucp_Tagbanwa },
|
||||
{ 1146, PT_SC, ucp_Tai_Le },
|
||||
{ 1153, PT_SC, ucp_Tai_Tham },
|
||||
{ 1162, PT_SC, ucp_Tai_Viet },
|
||||
{ 1171, PT_SC, ucp_Takri },
|
||||
{ 1177, PT_SC, ucp_Tamil },
|
||||
{ 1183, PT_SC, ucp_Telugu },
|
||||
{ 1190, PT_SC, ucp_Thaana },
|
||||
{ 1197, PT_SC, ucp_Thai },
|
||||
{ 1202, PT_SC, ucp_Tibetan },
|
||||
{ 1210, PT_SC, ucp_Tifinagh },
|
||||
{ 1219, PT_SC, ucp_Tirhuta },
|
||||
{ 1227, PT_SC, ucp_Ugaritic },
|
||||
{ 1236, PT_SC, ucp_Vai },
|
||||
{ 1240, PT_SC, ucp_Warang_Citi },
|
||||
{ 1252, PT_ALNUM, 0 },
|
||||
{ 1256, PT_PXSPACE, 0 },
|
||||
{ 1260, PT_SPACE, 0 },
|
||||
{ 1264, PT_UCNC, 0 },
|
||||
{ 1268, PT_WORD, 0 },
|
||||
{ 1272, PT_SC, ucp_Yi },
|
||||
{ 1275, PT_GC, ucp_Z },
|
||||
{ 1277, PT_PC, ucp_Zl },
|
||||
{ 1280, PT_PC, ucp_Zp },
|
||||
{ 1283, PT_PC, ucp_Zs }
|
||||
};
|
||||
|
||||
const int PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -144,7 +144,7 @@ if (rc < 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Match succeeded */
|
||||
/* Match succeded */
|
||||
|
||||
printf("\nMatch succeeded at offset %d\n", ovector[0]);
|
||||
|
||||
@ -362,7 +362,7 @@ for (;;)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Match succeeded */
|
||||
/* Match succeded */
|
||||
|
||||
printf("\nMatch succeeded again at offset %d\n", ovector[0]);
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2015 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -170,7 +170,8 @@ static const int eint[] = {
|
||||
REG_BADPAT, /* invalid range in character class */
|
||||
REG_BADPAT, /* group name must start with a non-digit */
|
||||
/* 85 */
|
||||
REG_BADPAT /* parentheses too deeply nested (stack check) */
|
||||
REG_BADPAT, /* parentheses too deeply nested (stack check) */
|
||||
REG_BADPAT /* missing digits in \x{} or \o{} */
|
||||
};
|
||||
|
||||
/* Table of texts corresponding to POSIX error codes */
|
||||
|
@ -28,30 +28,43 @@
|
||||
#define _SLJIT_CONFIG_INTERNAL_H_
|
||||
|
||||
/*
|
||||
SLJIT defines the following macros depending on the target architecture:
|
||||
SLJIT defines the following architecture dependent types and macros:
|
||||
|
||||
Feature detection (boolean) macros:
|
||||
SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
|
||||
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
|
||||
SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index
|
||||
SLJIT_DOUBLE_SHIFT : the shift required to apply when accessing a double array by index
|
||||
SLJIT_LITTLE_ENDIAN : little endian architecture
|
||||
SLJIT_BIG_ENDIAN : big endian architecture
|
||||
SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!)
|
||||
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET() for more information
|
||||
SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
|
||||
Types:
|
||||
sljit_sb, sljit_ub : signed and unsigned 8 bit byte
|
||||
sljit_sh, sljit_uh : signed and unsigned 16 bit half-word (short) type
|
||||
sljit_si, sljit_ui : signed and unsigned 32 bit integer type
|
||||
sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer
|
||||
sljit_p : unsgined pointer value (usually the same as sljit_uw, but
|
||||
some 64 bit ABIs may use 32 bit pointers)
|
||||
sljit_s : single precision floating point value
|
||||
sljit_d : double precision floating point value
|
||||
|
||||
Types and useful macros:
|
||||
sljit_sb, sljit_ub : signed and unsigned 8 bit byte
|
||||
sljit_sh, sljit_uh : signed and unsigned 16 bit half-word (short) type
|
||||
sljit_si, sljit_ui : signed and unsigned 32 bit integer type
|
||||
sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer
|
||||
sljit_p : unsgined pointer value (usually the same as sljit_uw, but
|
||||
some 64 bit ABIs may use 32 bit pointers)
|
||||
sljit_s : single precision floating point value
|
||||
sljit_d : double precision floating point value
|
||||
SLJIT_CALL : C calling convention define for both calling JIT form C and C callbacks for JIT
|
||||
SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (compiler independent helper)
|
||||
Macros for feature detection (boolean):
|
||||
SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
|
||||
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
|
||||
SLJIT_LITTLE_ENDIAN : little endian architecture
|
||||
SLJIT_BIG_ENDIAN : big endian architecture
|
||||
SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!)
|
||||
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET() for more information
|
||||
|
||||
Constants:
|
||||
SLJIT_NUMBER_OF_REGISTERS : number of available registers
|
||||
SLJIT_NUMBER_OF_SCRATCH_REGISTERS : number of available scratch registers
|
||||
SLJIT_NUMBER_OF_SAVED_REGISTERS : number of available saved registers
|
||||
SLJIT_NUMBER_OF_FLOAT_REGISTERS : number of available floating point registers
|
||||
SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS : number of available floating point scratch registers
|
||||
SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS : number of available floating point saved registers
|
||||
SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index
|
||||
SLJIT_DOUBLE_SHIFT : the shift required to apply when accessing
|
||||
a double precision floating point array by index
|
||||
SLJIT_SINGLE_SHIFT : the shift required to apply when accessing
|
||||
a single precision floating point array by index
|
||||
SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
|
||||
|
||||
Other macros:
|
||||
SLJIT_CALL : C calling convention define for both calling JIT form C and C callbacks for JIT
|
||||
SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (compiler independent helper)
|
||||
*/
|
||||
|
||||
#if !((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
@ -142,6 +155,70 @@
|
||||
#undef SLJIT_EXECUTABLE_ALLOCATOR
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
||||
#define SLJIT_CONFIG_ARM_32 1
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#define SLJIT_CONFIG_X86 1
|
||||
#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
#define SLJIT_CONFIG_ARM 1
|
||||
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define SLJIT_CONFIG_PPC 1
|
||||
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
#define SLJIT_CONFIG_MIPS 1
|
||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) || (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)
|
||||
#define SLJIT_CONFIG_SPARC 1
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 10
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
|
||||
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#ifndef _WIN64
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 6
|
||||
#else
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#endif /* _WIN64 */
|
||||
#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 11
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 11
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
|
||||
#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 23
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10
|
||||
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 22
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 17
|
||||
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 17
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 18
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 14
|
||||
#elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 0
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 0
|
||||
#endif
|
||||
|
||||
#define SLJIT_NUMBER_OF_SCRATCH_REGISTERS \
|
||||
(SLJIT_NUMBER_OF_REGISTERS - SLJIT_NUMBER_OF_SAVED_REGISTERS)
|
||||
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 6
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && (defined _WIN64)
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 1
|
||||
#else
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
|
||||
#endif
|
||||
|
||||
#define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \
|
||||
(SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS)
|
||||
|
||||
#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)
|
||||
|
||||
/* These libraries are needed for the macros below. */
|
||||
@ -219,7 +296,7 @@
|
||||
|
||||
#ifndef SLJIT_CACHE_FLUSH
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
|
||||
/* Not required to implement on archs with unified caches. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to)
|
||||
@ -240,7 +317,7 @@
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
cacheflush((long)(from), (long)(to), 0)
|
||||
|
||||
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
@ -314,6 +391,7 @@ typedef double sljit_d;
|
||||
|
||||
/* Shift for double precision sized data. */
|
||||
#define SLJIT_DOUBLE_SHIFT 3
|
||||
#define SLJIT_SINGLE_SHIFT 2
|
||||
|
||||
#ifndef SLJIT_W
|
||||
|
||||
@ -418,22 +496,12 @@ typedef double sljit_d;
|
||||
#endif
|
||||
#endif /* SLJIT_RETURN_ADDRESS_OFFSET */
|
||||
|
||||
#ifndef SLJIT_SSE2
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
/* Turn on SSE2 support on x86. */
|
||||
#define SLJIT_SSE2 1
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
/* Auto detect SSE2 support using CPUID.
|
||||
On 64 bit x86 cpus, sse2 must be present. */
|
||||
#define SLJIT_DETECT_SSE2 1
|
||||
#endif
|
||||
|
||||
#endif /* (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) */
|
||||
|
||||
#endif /* !SLJIT_SSE2 */
|
||||
|
||||
#ifndef SLJIT_UNALIGNED
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
|
@ -298,7 +298,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
|
||||
free_block = free_blocks;
|
||||
while (free_block) {
|
||||
next_free_block = free_block->next;
|
||||
if (!free_block->header.prev_size &&
|
||||
if (!free_block->header.prev_size &&
|
||||
AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) {
|
||||
total_size -= free_block->size;
|
||||
sljit_remove_free_block(free_block);
|
||||
|
@ -117,7 +117,7 @@
|
||||
#define JUMP_ADDR 0x2
|
||||
/* SLJIT_REWRITABLE_JUMP is 0x1000. */
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
# define PATCH_MB 0x4
|
||||
# define PATCH_MW 0x8
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
@ -162,7 +162,7 @@
|
||||
# define PATCH_ABS64 0x100
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
# define IS_COND 0x004
|
||||
# define IS_CALL 0x008
|
||||
# define PATCH_B 0x010
|
||||
@ -174,7 +174,7 @@
|
||||
# define REMOVE_COND 0x100
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
# define IS_MOVABLE 0x004
|
||||
# define IS_JAL 0x008
|
||||
# define IS_CALL 0x010
|
||||
@ -229,13 +229,25 @@
|
||||
# define FCC_IS_SET (1 << 24)
|
||||
#endif
|
||||
|
||||
/* Stack management. */
|
||||
|
||||
#define GET_SAVED_REGISTERS_SIZE(scratches, saveds, extra) \
|
||||
(((scratches < SLJIT_NUMBER_OF_SCRATCH_REGISTERS ? 0 : (scratches - SLJIT_NUMBER_OF_SCRATCH_REGISTERS)) + \
|
||||
(saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? saveds : SLJIT_NUMBER_OF_SAVED_REGISTERS) + \
|
||||
extra) * sizeof(sljit_sw))
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
#define SLJIT_HAS_VARIABLE_LOCALS_OFFSET 1
|
||||
#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
#define FIXED_LOCALS_OFFSET (3 * sizeof(sljit_sw))
|
||||
#endif
|
||||
#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
#define FIXED_LOCALS_OFFSET ((2 + 4) * sizeof(sljit_sw))
|
||||
#else
|
||||
/* Maximum 3 arguments are passed on the stack. */
|
||||
#define FIXED_LOCALS_OFFSET ((3 + 4) * sizeof(sljit_sw))
|
||||
#endif
|
||||
|
||||
#endif /* SLJIT_CONFIG_X86_32 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
|
||||
#ifdef _WIN64
|
||||
@ -254,7 +266,7 @@
|
||||
#ifdef _AIX
|
||||
#define FIXED_LOCALS_OFFSET ((6 + 8) * sizeof(sljit_sw))
|
||||
#else
|
||||
#define FIXED_LOCALS_OFFSET (2 * sizeof(sljit_sw))
|
||||
#define FIXED_LOCALS_OFFSET (3 * sizeof(sljit_sw))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -281,13 +293,13 @@
|
||||
#if (defined SLJIT_HAS_VARIABLE_LOCALS_OFFSET && SLJIT_HAS_VARIABLE_LOCALS_OFFSET)
|
||||
|
||||
#define ADJUST_LOCAL_OFFSET(p, i) \
|
||||
if ((p) == (SLJIT_MEM1(SLJIT_LOCALS_REG))) \
|
||||
if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
|
||||
(i) += compiler->locals_offset;
|
||||
|
||||
#elif (defined SLJIT_HAS_FIXED_LOCALS_OFFSET && SLJIT_HAS_FIXED_LOCALS_OFFSET)
|
||||
|
||||
#define ADJUST_LOCAL_OFFSET(p, i) \
|
||||
if ((p) == (SLJIT_MEM1(SLJIT_LOCALS_REG))) \
|
||||
if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
|
||||
(i) += FIXED_LOCALS_OFFSET;
|
||||
|
||||
#else
|
||||
@ -307,15 +319,11 @@
|
||||
#include "sljitExecAllocator.c"
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) && !(defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
#error SLJIT_SSE2_AUTO cannot be enabled without SLJIT_SSE2
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Public functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || ((defined SLJIT_SSE2 && SLJIT_SSE2) && ((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)))
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
#define SLJIT_NEEDS_COMPILER_INIT 1
|
||||
static sljit_si compiler_initialized = 0;
|
||||
/* A thread safe initialization. */
|
||||
@ -365,6 +373,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
|
||||
|
||||
compiler->scratches = -1;
|
||||
compiler->saveds = -1;
|
||||
compiler->fscratches = -1;
|
||||
compiler->fsaveds = -1;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
compiler->args = -1;
|
||||
@ -382,7 +392,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
|
||||
compiler->cpool_diff = 0xffffffff;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
compiler->delay_slot = UNMOVABLE_INS;
|
||||
#endif
|
||||
|
||||
@ -593,10 +603,6 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
||||
case SLJIT_MUL: \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))); \
|
||||
break; \
|
||||
case SLJIT_CMPD: \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
|
||||
SLJIT_ASSERT((op & (SLJIT_SET_E | SLJIT_SET_S))); \
|
||||
break; \
|
||||
case SLJIT_ADD: \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_U | SLJIT_SET_S))); \
|
||||
break; \
|
||||
@ -625,10 +631,30 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
||||
break; \
|
||||
}
|
||||
|
||||
#define FUNCTION_CHECK_FOP() \
|
||||
SLJIT_ASSERT(!GET_FLAGS(op) || !(op & SLJIT_KEEP_FLAGS)); \
|
||||
switch (GET_OPCODE(op)) { \
|
||||
case SLJIT_CMPD: \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
|
||||
SLJIT_ASSERT((op & (SLJIT_SET_E | SLJIT_SET_S))); \
|
||||
break; \
|
||||
default: \
|
||||
/* Only SLJIT_INT_OP or SLJIT_SINGLE_OP is allowed. */ \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define FUNCTION_CHECK_IS_REG(r) \
|
||||
((r) == SLJIT_UNUSED || \
|
||||
((r) >= SLJIT_SCRATCH_REG1 && (r) <= SLJIT_SCRATCH_REG1 - 1 + compiler->scratches) || \
|
||||
((r) >= SLJIT_SAVED_REG1 && (r) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds))
|
||||
((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) || \
|
||||
((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0))
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
#define FUNCTION_ASSERT_IF_VIRTUAL(p) \
|
||||
SLJIT_ASSERT((p) < SLJIT_R3 || (p) > SLJIT_R6);
|
||||
#else
|
||||
#define FUNCTION_ASSERT_IF_VIRTUAL(p)
|
||||
#endif
|
||||
|
||||
#define FUNCTION_CHECK_SRC(p, i) \
|
||||
SLJIT_ASSERT(compiler->scratches != -1 && compiler->saveds != -1); \
|
||||
@ -636,12 +662,14 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
||||
SLJIT_ASSERT((i) == 0 && (p) != SLJIT_UNUSED); \
|
||||
else if ((p) == SLJIT_IMM) \
|
||||
; \
|
||||
else if ((p) == (SLJIT_MEM1(SLJIT_LOCALS_REG))) \
|
||||
else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
|
||||
SLJIT_ASSERT((i) >= 0 && (i) < compiler->logical_local_size); \
|
||||
else if ((p) & SLJIT_MEM) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & REG_MASK)); \
|
||||
FUNCTION_ASSERT_IF_VIRTUAL((p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
|
||||
FUNCTION_ASSERT_IF_VIRTUAL(OFFS_REG(p)); \
|
||||
SLJIT_ASSERT(!((i) & ~0x3)); \
|
||||
} \
|
||||
SLJIT_ASSERT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
|
||||
@ -653,12 +681,14 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
||||
SLJIT_ASSERT(compiler->scratches != -1 && compiler->saveds != -1); \
|
||||
if (FUNCTION_CHECK_IS_REG(p)) \
|
||||
SLJIT_ASSERT((i) == 0); \
|
||||
else if ((p) == (SLJIT_MEM1(SLJIT_LOCALS_REG))) \
|
||||
else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
|
||||
SLJIT_ASSERT((i) >= 0 && (i) < compiler->logical_local_size); \
|
||||
else if ((p) & SLJIT_MEM) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & REG_MASK)); \
|
||||
FUNCTION_ASSERT_IF_VIRTUAL((p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
|
||||
FUNCTION_ASSERT_IF_VIRTUAL(OFFS_REG(p)); \
|
||||
SLJIT_ASSERT(!((i) & ~0x3)); \
|
||||
} \
|
||||
SLJIT_ASSERT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
|
||||
@ -667,13 +697,19 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
||||
SLJIT_ASSERT_STOP();
|
||||
|
||||
#define FUNCTION_FCHECK(p, i) \
|
||||
if ((p) >= SLJIT_FLOAT_REG1 && (p) <= SLJIT_FLOAT_REG6) \
|
||||
SLJIT_ASSERT(compiler->fscratches != -1 && compiler->fsaveds != -1); \
|
||||
if (((p) >= SLJIT_FR0 && (p) < (SLJIT_FR0 + compiler->fscratches)) || \
|
||||
((p) > (SLJIT_FS0 - compiler->fsaveds) && (p) <= SLJIT_FS0)) \
|
||||
SLJIT_ASSERT(i == 0); \
|
||||
else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
|
||||
SLJIT_ASSERT((i) >= 0 && (i) < compiler->logical_local_size); \
|
||||
else if ((p) & SLJIT_MEM) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & REG_MASK)); \
|
||||
FUNCTION_ASSERT_IF_VIRTUAL((p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
|
||||
SLJIT_ASSERT(((p) & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_LOCALS_REG) && !(i & ~0x3)); \
|
||||
FUNCTION_ASSERT_IF_VIRTUAL(OFFS_REG(p)); \
|
||||
SLJIT_ASSERT(((p) & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_SP) && !(i & ~0x3)); \
|
||||
} else \
|
||||
SLJIT_ASSERT(OFFS_REG(p) == 0); \
|
||||
SLJIT_ASSERT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
|
||||
@ -683,8 +719,8 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
||||
|
||||
#define FUNCTION_CHECK_OP1() \
|
||||
if (GET_OPCODE(op) >= SLJIT_MOVU && GET_OPCODE(op) <= SLJIT_MOVU_P) { \
|
||||
SLJIT_ASSERT(!(src & SLJIT_MEM) || (src & REG_MASK) != SLJIT_LOCALS_REG); \
|
||||
SLJIT_ASSERT(!(dst & SLJIT_MEM) || (dst & REG_MASK) != SLJIT_LOCALS_REG); \
|
||||
SLJIT_ASSERT(!(src & SLJIT_MEM) || (src & REG_MASK) != SLJIT_SP); \
|
||||
SLJIT_ASSERT(!(dst & SLJIT_MEM) || (dst & REG_MASK) != SLJIT_SP); \
|
||||
if ((src & SLJIT_MEM) && (src & REG_MASK)) \
|
||||
SLJIT_ASSERT((dst & REG_MASK) != (src & REG_MASK) && OFFS_REG(dst) != (src & REG_MASK)); \
|
||||
}
|
||||
@ -698,17 +734,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp
|
||||
compiler->verbose = verbose;
|
||||
}
|
||||
|
||||
static char* reg_names[] = {
|
||||
(char*)"unused", (char*)"s1", (char*)"s2", (char*)"s3",
|
||||
(char*)"se1", (char*)"se2", (char*)"p1", (char*)"p2",
|
||||
(char*)"p3", (char*)"pe1", (char*)"pe2", (char*)"lc"
|
||||
};
|
||||
|
||||
static char* freg_names[] = {
|
||||
(char*)"unused", (char*)"f1", (char*)"f2", (char*)"f3",
|
||||
(char*)"f4", (char*)"f5", (char*)"f6"
|
||||
};
|
||||
|
||||
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
||||
#ifdef _WIN64
|
||||
# define SLJIT_PRINT_D "I64"
|
||||
@ -719,66 +744,89 @@ static char* freg_names[] = {
|
||||
# define SLJIT_PRINT_D ""
|
||||
#endif
|
||||
|
||||
#define sljit_verbose_param(p, i) \
|
||||
#define sljit_verbose_reg(compiler, r) \
|
||||
do { \
|
||||
if ((r) < (SLJIT_R0 + compiler->scratches)) \
|
||||
fprintf(compiler->verbose, "r%d", (r) - SLJIT_R0); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - (r)); \
|
||||
} while (0)
|
||||
|
||||
#define sljit_verbose_param(compiler, p, i) \
|
||||
if ((p) & SLJIT_IMM) \
|
||||
fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i)); \
|
||||
else if ((p) & SLJIT_MEM) { \
|
||||
if ((p) & REG_MASK) { \
|
||||
if (i) { \
|
||||
if ((p) & OFFS_REG_MASK) \
|
||||
fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & REG_MASK], reg_names[OFFS_REG(p)], 1 << (i)); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[%s + #%" SLJIT_PRINT_D "d]", reg_names[(p) & REG_MASK], (i)); \
|
||||
} \
|
||||
else { \
|
||||
if ((p) & OFFS_REG_MASK) \
|
||||
fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & REG_MASK], reg_names[OFFS_REG(p)]); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[%s]", reg_names[(p) & REG_MASK]); \
|
||||
fputc('[', compiler->verbose); \
|
||||
sljit_verbose_reg(compiler, (p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
fprintf(compiler->verbose, " + "); \
|
||||
sljit_verbose_reg(compiler, OFFS_REG(p)); \
|
||||
if (i) \
|
||||
fprintf(compiler->verbose, " * %d", 1 << (i)); \
|
||||
} \
|
||||
else if (i) \
|
||||
fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i)); \
|
||||
fputc(']', compiler->verbose); \
|
||||
} \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); \
|
||||
} else \
|
||||
fprintf(compiler->verbose, "%s", reg_names[p]);
|
||||
#define sljit_verbose_fparam(p, i) \
|
||||
} else if (p) \
|
||||
sljit_verbose_reg(compiler, p); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "unused");
|
||||
|
||||
#define sljit_verbose_fparam(compiler, p, i) \
|
||||
if ((p) & SLJIT_MEM) { \
|
||||
if ((p) & REG_MASK) { \
|
||||
if (i) { \
|
||||
if ((p) & OFFS_REG_MASK) \
|
||||
fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & REG_MASK], reg_names[OFFS_REG(p)], 1 << (i)); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[%s + #%" SLJIT_PRINT_D "d]", reg_names[(p) & REG_MASK], (i)); \
|
||||
} \
|
||||
else { \
|
||||
if ((p) & OFFS_REG_MASK) \
|
||||
fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & REG_MASK], reg_names[OFFS_REG(p)]); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[%s]", reg_names[(p) & REG_MASK]); \
|
||||
fputc('[', compiler->verbose); \
|
||||
sljit_verbose_reg(compiler, (p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
fprintf(compiler->verbose, " + "); \
|
||||
sljit_verbose_reg(compiler, OFFS_REG(p)); \
|
||||
if (i) \
|
||||
fprintf(compiler->verbose, "%d", 1 << (i)); \
|
||||
} \
|
||||
else if (i) \
|
||||
fprintf(compiler->verbose, "%" SLJIT_PRINT_D "d", (i)); \
|
||||
fputc(']', compiler->verbose); \
|
||||
} \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); \
|
||||
} else \
|
||||
fprintf(compiler->verbose, "%s", freg_names[p]);
|
||||
} \
|
||||
else { \
|
||||
if ((p) < (SLJIT_FR0 + compiler->fscratches)) \
|
||||
fprintf(compiler->verbose, "fr%d", (p) - SLJIT_FR0); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - (p)); \
|
||||
}
|
||||
|
||||
static SLJIT_CONST char* op_names[] = {
|
||||
/* op0 */
|
||||
static SLJIT_CONST char* op0_names[] = {
|
||||
(char*)"breakpoint", (char*)"nop",
|
||||
(char*)"umul", (char*)"smul", (char*)"udiv", (char*)"sdiv",
|
||||
/* op1 */
|
||||
};
|
||||
|
||||
static SLJIT_CONST char* op1_names[] = {
|
||||
(char*)"mov", (char*)"mov.ub", (char*)"mov.sb", (char*)"mov.uh",
|
||||
(char*)"mov.sh", (char*)"mov.ui", (char*)"mov.si", (char*)"mov.p",
|
||||
(char*)"movu", (char*)"movu.ub", (char*)"movu.sb", (char*)"movu.uh",
|
||||
(char*)"movu.sh", (char*)"movu.ui", (char*)"movu.si", (char*)"movu.p",
|
||||
(char*)"not", (char*)"neg", (char*)"clz",
|
||||
/* op2 */
|
||||
};
|
||||
|
||||
static SLJIT_CONST char* op2_names[] = {
|
||||
(char*)"add", (char*)"addc", (char*)"sub", (char*)"subc",
|
||||
(char*)"mul", (char*)"and", (char*)"or", (char*)"xor",
|
||||
(char*)"shl", (char*)"lshr", (char*)"ashr",
|
||||
/* fop1 */
|
||||
(char*)"cmp", (char*)"mov", (char*)"neg", (char*)"abs",
|
||||
/* fop2 */
|
||||
};
|
||||
|
||||
static SLJIT_CONST char* fop1_names[] = {
|
||||
(char*)"mov", (char*)"conv", (char*)"conv", (char*)"conv",
|
||||
(char*)"conv", (char*)"conv", (char*)"cmp", (char*)"neg",
|
||||
(char*)"abs",
|
||||
};
|
||||
|
||||
static SLJIT_CONST char* fop2_names[] = {
|
||||
(char*)"add", (char*)"sub", (char*)"mul", (char*)"div"
|
||||
};
|
||||
|
||||
@ -823,33 +871,49 @@ static SLJIT_INLINE void check_sljit_generate_code(struct sljit_compiler *compil
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
static SLJIT_INLINE void check_sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
/* If debug and verbose are disabled, all arguments are unused. */
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(options);
|
||||
SLJIT_UNUSED_ARG(args);
|
||||
SLJIT_UNUSED_ARG(scratches);
|
||||
SLJIT_UNUSED_ARG(saveds);
|
||||
SLJIT_UNUSED_ARG(fscratches);
|
||||
SLJIT_UNUSED_ARG(fsaveds);
|
||||
SLJIT_UNUSED_ARG(local_size);
|
||||
|
||||
SLJIT_ASSERT(options == 0);
|
||||
SLJIT_ASSERT(args >= 0 && args <= 3);
|
||||
SLJIT_ASSERT(scratches >= 0 && scratches <= SLJIT_NO_TMP_REGISTERS);
|
||||
SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS);
|
||||
SLJIT_ASSERT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
SLJIT_ASSERT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
SLJIT_ASSERT(args <= saveds);
|
||||
SLJIT_ASSERT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
SLJIT_ASSERT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
SLJIT_ASSERT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose))
|
||||
fprintf(compiler->verbose, " enter args=%d scratches=%d saveds=%d local_size=%d\n", args, scratches, saveds, local_size);
|
||||
fprintf(compiler->verbose, " enter options:none args:%d scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n",
|
||||
args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
static SLJIT_INLINE void check_sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
/* If debug and verbose are disabled, all arguments are unused. */
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(options);
|
||||
SLJIT_UNUSED_ARG(args);
|
||||
SLJIT_UNUSED_ARG(scratches);
|
||||
SLJIT_UNUSED_ARG(saveds);
|
||||
SLJIT_UNUSED_ARG(fscratches);
|
||||
SLJIT_UNUSED_ARG(fsaveds);
|
||||
SLJIT_UNUSED_ARG(local_size);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
@ -859,14 +923,20 @@ static SLJIT_INLINE void check_sljit_set_context(struct sljit_compiler *compiler
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(options == 0);
|
||||
SLJIT_ASSERT(args >= 0 && args <= 3);
|
||||
SLJIT_ASSERT(scratches >= 0 && scratches <= SLJIT_NO_TMP_REGISTERS);
|
||||
SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS);
|
||||
SLJIT_ASSERT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
SLJIT_ASSERT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
SLJIT_ASSERT(args <= saveds);
|
||||
SLJIT_ASSERT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
SLJIT_ASSERT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
SLJIT_ASSERT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose))
|
||||
fprintf(compiler->verbose, " set_context args=%d scratches=%d saveds=%d local_size=%d\n", args, scratches, saveds, local_size);
|
||||
fprintf(compiler->verbose, " set_context options:none args:%d scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n",
|
||||
args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -891,8 +961,8 @@ static SLJIT_INLINE void check_sljit_emit_return(struct sljit_compiler *compiler
|
||||
if (op == SLJIT_UNUSED)
|
||||
fprintf(compiler->verbose, " return\n");
|
||||
else {
|
||||
fprintf(compiler->verbose, " return %s ", op_names[op]);
|
||||
sljit_verbose_param(src, srcw);
|
||||
fprintf(compiler->verbose, " return.%s ", op1_names[op - SLJIT_OP1_BASE]);
|
||||
sljit_verbose_param(compiler, src, srcw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
}
|
||||
@ -912,7 +982,7 @@ static SLJIT_INLINE void check_sljit_emit_fast_enter(struct sljit_compiler *comp
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " fast_enter ");
|
||||
sljit_verbose_param(dst, dstw);
|
||||
sljit_verbose_param(compiler, dst, dstw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
@ -931,7 +1001,7 @@ static SLJIT_INLINE void check_sljit_emit_fast_return(struct sljit_compiler *com
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " fast_return ");
|
||||
sljit_verbose_param(src, srcw);
|
||||
sljit_verbose_param(compiler, src, srcw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
@ -945,9 +1015,10 @@ static SLJIT_INLINE void check_sljit_emit_op0(struct sljit_compiler *compiler, s
|
||||
|
||||
SLJIT_ASSERT((op >= SLJIT_BREAKPOINT && op <= SLJIT_SMUL)
|
||||
|| ((op & ~SLJIT_INT_OP) >= SLJIT_UDIV && (op & ~SLJIT_INT_OP) <= SLJIT_SDIV));
|
||||
SLJIT_ASSERT(op < SLJIT_UMUL || compiler->scratches >= 2);
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose))
|
||||
fprintf(compiler->verbose, " %s%s\n", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)]);
|
||||
fprintf(compiler->verbose, " %s%s\n", !(op & SLJIT_INT_OP) ? "" : "i", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -979,12 +1050,12 @@ static SLJIT_INLINE void check_sljit_emit_op1(struct sljit_compiler *compiler, s
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)],
|
||||
fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE],
|
||||
!(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_U) ? "" : ".u", !(op & SLJIT_SET_S) ? "" : ".s",
|
||||
!(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
|
||||
sljit_verbose_param(dst, dstw);
|
||||
sljit_verbose_param(compiler, dst, dstw);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_param(src, srcw);
|
||||
sljit_verbose_param(compiler, src, srcw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
@ -1021,14 +1092,14 @@ static SLJIT_INLINE void check_sljit_emit_op2(struct sljit_compiler *compiler, s
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)],
|
||||
fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],
|
||||
!(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_U) ? "" : ".u", !(op & SLJIT_SET_S) ? "" : ".s",
|
||||
!(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
|
||||
sljit_verbose_param(dst, dstw);
|
||||
sljit_verbose_param(compiler, dst, dstw);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_param(src1, src1w);
|
||||
sljit_verbose_param(compiler, src1, src1w);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_param(src2, src2w);
|
||||
sljit_verbose_param(compiler, src2, src2w);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
@ -1037,13 +1108,13 @@ static SLJIT_INLINE void check_sljit_emit_op2(struct sljit_compiler *compiler, s
|
||||
static SLJIT_INLINE void check_sljit_get_register_index(sljit_si reg)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(reg);
|
||||
SLJIT_ASSERT(reg > 0 && reg <= SLJIT_NO_REGISTERS);
|
||||
SLJIT_ASSERT(reg > 0 && reg <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_get_float_register_index(sljit_si reg)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(reg);
|
||||
SLJIT_ASSERT(reg > 0 && reg <= SLJIT_NO_FLOAT_REGISTERS);
|
||||
SLJIT_ASSERT(reg > 0 && reg <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
@ -1055,6 +1126,32 @@ static SLJIT_INLINE void check_sljit_emit_op_custom(struct sljit_compiler *compi
|
||||
SLJIT_ASSERT(instruction);
|
||||
}
|
||||
|
||||
#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \
|
||||
SLJIT_ASSERT(sljit_is_fpu_available()); \
|
||||
SLJIT_COMPILE_ASSERT(!(SLJIT_CONVW_FROMD & 0x1) && !(SLJIT_CONVD_FROMW & 0x1), \
|
||||
invalid_float_opcodes); \
|
||||
if (GET_OPCODE(op) >= SLJIT_CONVW_FROMD && GET_OPCODE(op) <= SLJIT_CMPD) { \
|
||||
if (GET_OPCODE(op) == SLJIT_CMPD) { \
|
||||
check_sljit_emit_fop1_cmp(compiler, op, dst, dstw, src, srcw); \
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw); \
|
||||
ADJUST_LOCAL_OFFSET(src, srcw); \
|
||||
return sljit_emit_fop1_cmp(compiler, op, dst, dstw, src, srcw); \
|
||||
} \
|
||||
if ((GET_OPCODE(op) | 0x1) == SLJIT_CONVI_FROMD) { \
|
||||
check_sljit_emit_fop1_convw_fromd(compiler, op, dst, dstw, src, srcw); \
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw); \
|
||||
ADJUST_LOCAL_OFFSET(src, srcw); \
|
||||
return sljit_emit_fop1_convw_fromd(compiler, op, dst, dstw, src, srcw); \
|
||||
} \
|
||||
check_sljit_emit_fop1_convd_fromw(compiler, op, dst, dstw, src, srcw); \
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw); \
|
||||
ADJUST_LOCAL_OFFSET(src, srcw); \
|
||||
return sljit_emit_fop1_convd_fromw(compiler, op, dst, dstw, src, srcw); \
|
||||
} \
|
||||
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw); \
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw); \
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
@ -1074,20 +1171,134 @@ static SLJIT_INLINE void check_sljit_emit_fop1(struct sljit_compiler *compiler,
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(sljit_is_fpu_available());
|
||||
SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_CMPD && GET_OPCODE(op) <= SLJIT_ABSD);
|
||||
SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_MOVD && GET_OPCODE(op) <= SLJIT_ABSD);
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
FUNCTION_CHECK_OP();
|
||||
FUNCTION_CHECK_FOP();
|
||||
FUNCTION_FCHECK(src, srcw);
|
||||
FUNCTION_FCHECK(dst, dstw);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %s%s%s%s ", op_names[GET_OPCODE(op)], (op & SLJIT_SINGLE_OP) ? "s" : "d",
|
||||
!(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_S) ? "" : ".s");
|
||||
sljit_verbose_fparam(dst, dstw);
|
||||
fprintf(compiler->verbose, " %s%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
|
||||
(GET_OPCODE(op) == SLJIT_CONVD_FROMS)
|
||||
? ((op & SLJIT_SINGLE_OP) ? "s.fromd" : "d.froms")
|
||||
: ((op & SLJIT_SINGLE_OP) ? "s" : "d"));
|
||||
sljit_verbose_fparam(compiler, dst, dstw);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_fparam(src, srcw);
|
||||
sljit_verbose_fparam(compiler, src, srcw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
/* If debug and verbose are disabled, all arguments are unused. */
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(op);
|
||||
SLJIT_UNUSED_ARG(src1);
|
||||
SLJIT_UNUSED_ARG(src1w);
|
||||
SLJIT_UNUSED_ARG(src2);
|
||||
SLJIT_UNUSED_ARG(src2w);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
|
||||
compiler->skip_checks = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(GET_OPCODE(op) == SLJIT_CMPD);
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
FUNCTION_CHECK_FOP();
|
||||
FUNCTION_FCHECK(src1, src1w);
|
||||
FUNCTION_FCHECK(src2, src2w);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %s%s%s%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE], (op & SLJIT_SINGLE_OP) ? "s" : "d",
|
||||
!(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_S) ? "" : ".s");
|
||||
sljit_verbose_fparam(compiler, src1, src1w);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_fparam(compiler, src2, src2w);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
/* If debug and verbose are disabled, all arguments are unused. */
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(op);
|
||||
SLJIT_UNUSED_ARG(dst);
|
||||
SLJIT_UNUSED_ARG(dstw);
|
||||
SLJIT_UNUSED_ARG(src);
|
||||
SLJIT_UNUSED_ARG(srcw);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
|
||||
compiler->skip_checks = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_CONVW_FROMD && GET_OPCODE(op) <= SLJIT_CONVI_FROMD);
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
FUNCTION_CHECK_FOP();
|
||||
FUNCTION_FCHECK(src, srcw);
|
||||
FUNCTION_CHECK_DST(dst, dstw);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
|
||||
(GET_OPCODE(op) == SLJIT_CONVI_FROMD) ? "i" : "w",
|
||||
(op & SLJIT_SINGLE_OP) ? "s" : "d");
|
||||
sljit_verbose_param(compiler, dst, dstw);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_fparam(compiler, src, srcw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void check_sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
/* If debug and verbose are disabled, all arguments are unused. */
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(op);
|
||||
SLJIT_UNUSED_ARG(dst);
|
||||
SLJIT_UNUSED_ARG(dstw);
|
||||
SLJIT_UNUSED_ARG(src);
|
||||
SLJIT_UNUSED_ARG(srcw);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
|
||||
compiler->skip_checks = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_CONVD_FROMW && GET_OPCODE(op) <= SLJIT_CONVD_FROMI);
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
FUNCTION_CHECK_FOP();
|
||||
FUNCTION_CHECK_SRC(src, srcw);
|
||||
FUNCTION_FCHECK(dst, dstw);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
|
||||
(op & SLJIT_SINGLE_OP) ? "s" : "d",
|
||||
(GET_OPCODE(op) == SLJIT_CONVD_FROMI) ? "i" : "w");
|
||||
sljit_verbose_fparam(compiler, dst, dstw);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_param(compiler, src, srcw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
@ -1111,19 +1322,19 @@ static SLJIT_INLINE void check_sljit_emit_fop2(struct sljit_compiler *compiler,
|
||||
SLJIT_ASSERT(sljit_is_fpu_available());
|
||||
SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_ADDD && GET_OPCODE(op) <= SLJIT_DIVD);
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
FUNCTION_CHECK_OP();
|
||||
FUNCTION_CHECK_FOP();
|
||||
FUNCTION_FCHECK(src1, src1w);
|
||||
FUNCTION_FCHECK(src2, src2w);
|
||||
FUNCTION_FCHECK(dst, dstw);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %s%s ", op_names[GET_OPCODE(op)], (op & SLJIT_SINGLE_OP) ? "s" : "d");
|
||||
sljit_verbose_fparam(dst, dstw);
|
||||
fprintf(compiler->verbose, " %s%s ", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE], (op & SLJIT_SINGLE_OP) ? "s" : "d");
|
||||
sljit_verbose_fparam(compiler, dst, dstw);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_fparam(src1, src1w);
|
||||
sljit_verbose_fparam(compiler, src1, src1w);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_fparam(src2, src2w);
|
||||
sljit_verbose_fparam(compiler, src2, src2w);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
@ -1181,9 +1392,9 @@ static SLJIT_INLINE void check_sljit_emit_cmp(struct sljit_compiler *compiler, s
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %scmp%s.%s ", !(type & SLJIT_INT_OP) ? "" : "i", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);
|
||||
sljit_verbose_param(src1, src1w);
|
||||
sljit_verbose_param(compiler, src1, src1w);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_param(src2, src2w);
|
||||
sljit_verbose_param(compiler, src2, src2w);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
@ -1211,9 +1422,9 @@ static SLJIT_INLINE void check_sljit_emit_fcmp(struct sljit_compiler *compiler,
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %scmp%s.%s ", (type & SLJIT_SINGLE_OP) ? "s" : "d",
|
||||
!(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);
|
||||
sljit_verbose_fparam(src1, src1w);
|
||||
sljit_verbose_fparam(compiler, src1, src1w);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_fparam(src2, src2w);
|
||||
sljit_verbose_fparam(compiler, src2, src2w);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
@ -1241,7 +1452,7 @@ static SLJIT_INLINE void check_sljit_emit_ijump(struct sljit_compiler *compiler,
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " ijump.%s ", jump_names[type]);
|
||||
sljit_verbose_param(src, srcw);
|
||||
sljit_verbose_param(compiler, src, srcw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
@ -1277,11 +1488,12 @@ static SLJIT_INLINE void check_sljit_emit_op_flags(struct sljit_compiler *compil
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %sflags.%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i",
|
||||
op_names[GET_OPCODE(op)], !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
|
||||
sljit_verbose_param(dst, dstw);
|
||||
GET_OPCODE(op) >= SLJIT_OP2_BASE ? op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE] : op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE],
|
||||
!(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
|
||||
sljit_verbose_param(compiler, dst, dstw);
|
||||
if (src != SLJIT_UNUSED) {
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_param(src, srcw);
|
||||
sljit_verbose_param(compiler, src, srcw);
|
||||
}
|
||||
fprintf(compiler->verbose, ", %s\n", jump_names[type]);
|
||||
}
|
||||
@ -1301,7 +1513,7 @@ static SLJIT_INLINE void check_sljit_get_local_base(struct sljit_compiler *compi
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " local_base ");
|
||||
sljit_verbose_param(dst, dstw);
|
||||
sljit_verbose_param(compiler, dst, dstw);
|
||||
fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", offset);
|
||||
}
|
||||
#endif
|
||||
@ -1321,7 +1533,7 @@ static SLJIT_INLINE void check_sljit_emit_const(struct sljit_compiler *compiler,
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " const ");
|
||||
sljit_verbose_param(dst, dstw);
|
||||
sljit_verbose_param(compiler, dst, dstw);
|
||||
fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", init_value);
|
||||
}
|
||||
#endif
|
||||
@ -1374,9 +1586,7 @@ static SLJIT_INLINE sljit_si emit_mov_before_return(struct sljit_compiler *compi
|
||||
|
||||
#define SLJIT_CPUINFO SLJIT_CPUINFO_PART1 SLJIT_CPUINFO_PART2 SLJIT_CPUINFO_PART3
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
# include "sljitNativeX86_common.c"
|
||||
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
# include "sljitNativeX86_common.c"
|
||||
#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
# include "sljitNativeARM_32.c"
|
||||
@ -1386,21 +1596,17 @@ static SLJIT_INLINE sljit_si emit_mov_before_return(struct sljit_compiler *compi
|
||||
# include "sljitNativeARM_T2_32.c"
|
||||
#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
# include "sljitNativeARM_64.c"
|
||||
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
# include "sljitNativePPC_common.c"
|
||||
#elif (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
# include "sljitNativePPC_common.c"
|
||||
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
# include "sljitNativeMIPS_common.c"
|
||||
#elif (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
# include "sljitNativeMIPS_common.c"
|
||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)
|
||||
# include "sljitNativeSPARC_common.c"
|
||||
#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
|
||||
# include "sljitNativeTILEGX_64.c"
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
#if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
@ -1428,7 +1634,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
|
||||
#endif
|
||||
|
||||
if (SLJIT_UNLIKELY((src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM))) {
|
||||
/* Immediate is preferred as second argument by most architectures. */
|
||||
/* Immediate is prefered as second argument by most architectures. */
|
||||
switch (condition) {
|
||||
case SLJIT_C_LESS:
|
||||
condition = SLJIT_C_GREATER;
|
||||
@ -1508,20 +1714,20 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
|
||||
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) && !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
check_sljit_get_local_base(compiler, dst, dstw, offset);
|
||||
|
||||
ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_LOCALS_REG), offset);
|
||||
ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
if (offset != 0)
|
||||
return sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, SLJIT_IMM, offset);
|
||||
return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_LOCALS_REG, 0);
|
||||
return sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
|
||||
return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1577,23 +1783,33 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
|
||||
SLJIT_ASSERT_STOP();
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(options);
|
||||
SLJIT_UNUSED_ARG(args);
|
||||
SLJIT_UNUSED_ARG(scratches);
|
||||
SLJIT_UNUSED_ARG(saveds);
|
||||
SLJIT_UNUSED_ARG(fscratches);
|
||||
SLJIT_UNUSED_ARG(fsaveds);
|
||||
SLJIT_UNUSED_ARG(local_size);
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(options);
|
||||
SLJIT_UNUSED_ARG(args);
|
||||
SLJIT_UNUSED_ARG(scratches);
|
||||
SLJIT_UNUSED_ARG(saveds);
|
||||
SLJIT_UNUSED_ARG(fscratches);
|
||||
SLJIT_UNUSED_ARG(fsaveds);
|
||||
SLJIT_UNUSED_ARG(local_size);
|
||||
SLJIT_ASSERT_STOP();
|
||||
}
|
||||
|
@ -56,8 +56,6 @@
|
||||
Disadvantages:
|
||||
- No automatic register allocation, and temporary results are
|
||||
not stored on the stack. (hence the name comes)
|
||||
- Limited number of registers (only 6+4 integer registers, max 3+2
|
||||
scratch, max 3+2 saved and 6 floating point registers)
|
||||
In practice:
|
||||
- This approach is very effective for interpreters
|
||||
- One of the saved registers typically points to a stack interface
|
||||
@ -90,7 +88,7 @@ of sljitConfigInternal.h */
|
||||
#define SLJIT_SUCCESS 0
|
||||
/* After the call of sljit_generate_code(), the error code of the compiler
|
||||
is set to this value to avoid future sljit calls (in debug mode at least).
|
||||
The compiler should be freed after sljit_generate_code(). */
|
||||
The complier should be freed after sljit_generate_code(). */
|
||||
#define SLJIT_ERR_COMPILED 1
|
||||
/* Cannot allocate non executable memory. */
|
||||
#define SLJIT_ERR_ALLOC_FAILED 2
|
||||
@ -104,76 +102,169 @@ of sljitConfigInternal.h */
|
||||
/* Registers */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
Scratch (R) registers: registers whose may not preserve their values
|
||||
across function calls.
|
||||
|
||||
Saved (S) registers: registers whose preserve their values across
|
||||
function calls.
|
||||
|
||||
The scratch and saved register sets are overlap. The last scratch register
|
||||
is the first saved register, the one before the last is the second saved
|
||||
register, and so on.
|
||||
|
||||
If an architecture provides two scratch and three saved registers,
|
||||
its scratch and saved register sets are the following:
|
||||
|
||||
R0 | [S4] | R0 and S4 represent the same physical register
|
||||
R1 | [S3] | R1 and S3 represent the same physical register
|
||||
[R2] | S2 | R2 and S2 represent the same physical register
|
||||
[R3] | S1 | R3 and S1 represent the same physical register
|
||||
[R4] | S0 | R4 and S0 represent the same physical register
|
||||
|
||||
Note: SLJIT_NUMBER_OF_SCRATCH_REGISTERS would be 2 and
|
||||
SLJIT_NUMBER_OF_SAVED_REGISTERS would be 3 for this architecture.
|
||||
|
||||
Note: On all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 10
|
||||
and SLJIT_NUMBER_OF_SAVED_REGISTERS >= 5. However, 4 registers
|
||||
are virtual on x86-32. See below.
|
||||
|
||||
The purpose of this definition is convenience. Although a register
|
||||
is either scratch register or saved register, SLJIT allows accessing
|
||||
them from the other set. For example, four registers can be used as
|
||||
scratch registers and the fifth one as saved register on the architecture
|
||||
above. Of course the last two scratch registers (R2 and R3) from this
|
||||
four will be saved on the stack, because they are defined as saved
|
||||
registers in the application binary interface. Still R2 and R3 can be
|
||||
used for referencing to these registers instead of S2 and S1, which
|
||||
makes easier to write platform independent code. Scratch registers
|
||||
can be saved registers in a similar way, but these extra saved
|
||||
registers will not be preserved across function calls! Hence the
|
||||
application must save them on those platforms, where the number of
|
||||
saved registers is too low. This can be done by copy them onto
|
||||
the stack and restore them after a function call.
|
||||
|
||||
Note: To emphasize that registers assigned to R2-R4 are saved
|
||||
registers, they are enclosed by square brackets. S3-S4
|
||||
are marked in a similar way.
|
||||
|
||||
Note: sljit_emit_enter and sljit_set_context defines whether a register
|
||||
is S or R register. E.g: when 3 scratches and 1 saved is mapped
|
||||
by sljit_emit_enter, the allowed register set will be: R0-R2 and
|
||||
S0. Although S2 is mapped to the same position as R2, it does not
|
||||
available in the current configuration. Furthermore the R3 (S1)
|
||||
register does not available as well.
|
||||
*/
|
||||
|
||||
/* When SLJIT_UNUSED is specified as destination, the result is discarded. */
|
||||
#define SLJIT_UNUSED 0
|
||||
|
||||
/* Scratch (temporary) registers whose may not preserve their values
|
||||
across function calls. */
|
||||
#define SLJIT_SCRATCH_REG1 1
|
||||
#define SLJIT_SCRATCH_REG2 2
|
||||
#define SLJIT_SCRATCH_REG3 3
|
||||
/* Note: extra registers cannot be used for memory addressing. */
|
||||
/* Note: on x86-32, these registers are emulated (using stack
|
||||
loads & stores). */
|
||||
#define SLJIT_TEMPORARY_EREG1 4
|
||||
#define SLJIT_TEMPORARY_EREG2 5
|
||||
/* Scratch registers. */
|
||||
#define SLJIT_R0 1
|
||||
#define SLJIT_R1 2
|
||||
#define SLJIT_R2 3
|
||||
/* Note: on x86-32, R3 - R6 (same as S3 - S6) are emulated (they
|
||||
are allocated on the stack). These registers are called virtual
|
||||
and cannot be used for memory addressing (cannot be part of
|
||||
any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such
|
||||
limitation on other CPUs. See sljit_get_register_index(). */
|
||||
#define SLJIT_R3 4
|
||||
#define SLJIT_R4 5
|
||||
#define SLJIT_R5 6
|
||||
#define SLJIT_R6 7
|
||||
#define SLJIT_R7 8
|
||||
#define SLJIT_R8 9
|
||||
#define SLJIT_R9 10
|
||||
/* All R registers provided by the architecture can be accessed by SLJIT_R(i)
|
||||
The i parameter must be >= 0 and < SLJIT_NUMBER_OF_REGISTERS. */
|
||||
#define SLJIT_R(i) (1 + (i))
|
||||
|
||||
/* Saved registers whose preserve their values across function calls. */
|
||||
#define SLJIT_SAVED_REG1 6
|
||||
#define SLJIT_SAVED_REG2 7
|
||||
#define SLJIT_SAVED_REG3 8
|
||||
/* Note: extra registers cannot be used for memory addressing. */
|
||||
/* Note: on x86-32, these registers are emulated (using stack
|
||||
loads & stores). */
|
||||
#define SLJIT_SAVED_EREG1 9
|
||||
#define SLJIT_SAVED_EREG2 10
|
||||
/* Saved registers. */
|
||||
#define SLJIT_S0 (SLJIT_NUMBER_OF_REGISTERS)
|
||||
#define SLJIT_S1 (SLJIT_NUMBER_OF_REGISTERS - 1)
|
||||
#define SLJIT_S2 (SLJIT_NUMBER_OF_REGISTERS - 2)
|
||||
/* Note: on x86-32, S3 - S6 (same as R3 - R6) are emulated (they
|
||||
are allocated on the stack). These registers are called virtual
|
||||
and cannot be used for memory addressing (cannot be part of
|
||||
any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such
|
||||
limitation on other CPUs. See sljit_get_register_index(). */
|
||||
#define SLJIT_S3 (SLJIT_NUMBER_OF_REGISTERS - 3)
|
||||
#define SLJIT_S4 (SLJIT_NUMBER_OF_REGISTERS - 4)
|
||||
#define SLJIT_S5 (SLJIT_NUMBER_OF_REGISTERS - 5)
|
||||
#define SLJIT_S6 (SLJIT_NUMBER_OF_REGISTERS - 6)
|
||||
#define SLJIT_S7 (SLJIT_NUMBER_OF_REGISTERS - 7)
|
||||
#define SLJIT_S8 (SLJIT_NUMBER_OF_REGISTERS - 8)
|
||||
#define SLJIT_S9 (SLJIT_NUMBER_OF_REGISTERS - 9)
|
||||
/* All S registers provided by the architecture can be accessed by SLJIT_S(i)
|
||||
The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_REGISTERS. */
|
||||
#define SLJIT_S(i) (SLJIT_NUMBER_OF_REGISTERS - (i))
|
||||
|
||||
/* Read-only register (cannot be the destination of an operation).
|
||||
Only SLJIT_MEM1(SLJIT_LOCALS_REG) addressing mode is allowed since
|
||||
several ABIs has certain limitations about the stack layout. However
|
||||
sljit_get_local_base() can be used to obtain the offset of a value
|
||||
on the stack. */
|
||||
#define SLJIT_LOCALS_REG 11
|
||||
/* Registers >= SLJIT_FIRST_SAVED_REG are saved registers. */
|
||||
#define SLJIT_FIRST_SAVED_REG (SLJIT_S0 - SLJIT_NUMBER_OF_SAVED_REGISTERS + 1)
|
||||
|
||||
/* Number of registers. */
|
||||
#define SLJIT_NO_TMP_REGISTERS 5
|
||||
#define SLJIT_NO_GEN_REGISTERS 5
|
||||
#define SLJIT_NO_REGISTERS 11
|
||||
/* The SLJIT_SP provides direct access to the linear stack space allocated by
|
||||
sljit_emit_enter. It can only be used in the following form: SLJIT_MEM1(SLJIT_SP).
|
||||
The immediate offset is extended by the relative stack offset automatically.
|
||||
The sljit_get_local_base can be used to obtain the absolute offset. */
|
||||
#define SLJIT_SP (SLJIT_NUMBER_OF_REGISTERS + 1)
|
||||
|
||||
/* Return with machine word. */
|
||||
|
||||
#define SLJIT_RETURN_REG SLJIT_SCRATCH_REG1
|
||||
#define SLJIT_RETURN_REG SLJIT_R0
|
||||
|
||||
/* x86 prefers specific registers for special purposes. In case of shift
|
||||
by register it supports only SLJIT_SCRATCH_REG3 for shift argument
|
||||
by register it supports only SLJIT_R2 for shift argument
|
||||
(which is the src2 argument of sljit_emit_op2). If another register is
|
||||
used, sljit must exchange data between registers which cause a minor
|
||||
slowdown. Other architectures has no such limitation. */
|
||||
|
||||
#define SLJIT_PREF_SHIFT_REG SLJIT_SCRATCH_REG3
|
||||
#define SLJIT_PREF_SHIFT_REG SLJIT_R2
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Floating point registers */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Each floating point register can store a double or single precision
|
||||
value. The FR and FS register sets are overlap in the same way as R
|
||||
and S register sets. See above. */
|
||||
|
||||
/* Note: SLJIT_UNUSED as destination is not valid for floating point
|
||||
operations, since they cannot be used for setting flags. */
|
||||
operations, since they cannot be used for setting flags. */
|
||||
|
||||
/* Floating point operations are performed on double or
|
||||
single precision values. */
|
||||
/* Floating point scratch registers. */
|
||||
#define SLJIT_FR0 1
|
||||
#define SLJIT_FR1 2
|
||||
#define SLJIT_FR2 3
|
||||
#define SLJIT_FR3 4
|
||||
#define SLJIT_FR4 5
|
||||
#define SLJIT_FR5 6
|
||||
/* All FR registers provided by the architecture can be accessed by SLJIT_FR(i)
|
||||
The i parameter must be >= 0 and < SLJIT_NUMBER_OF_FLOAT_REGISTERS. */
|
||||
#define SLJIT_FR(i) (1 + (i))
|
||||
|
||||
#define SLJIT_FLOAT_REG1 1
|
||||
#define SLJIT_FLOAT_REG2 2
|
||||
#define SLJIT_FLOAT_REG3 3
|
||||
#define SLJIT_FLOAT_REG4 4
|
||||
#define SLJIT_FLOAT_REG5 5
|
||||
#define SLJIT_FLOAT_REG6 6
|
||||
/* Floating point saved registers. */
|
||||
#define SLJIT_FS0 (SLJIT_NUMBER_OF_FLOAT_REGISTERS)
|
||||
#define SLJIT_FS1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 1)
|
||||
#define SLJIT_FS2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2)
|
||||
#define SLJIT_FS3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 3)
|
||||
#define SLJIT_FS4 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 4)
|
||||
#define SLJIT_FS5 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 5)
|
||||
/* All S registers provided by the architecture can be accessed by SLJIT_FS(i)
|
||||
The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS. */
|
||||
#define SLJIT_FS(i) (SLJIT_NUMBER_OF_FLOAT_REGISTERS - (i))
|
||||
|
||||
#define SLJIT_NO_FLOAT_REGISTERS 6
|
||||
/* Float registers >= SLJIT_FIRST_SAVED_FLOAT_REG are saved registers. */
|
||||
#define SLJIT_FIRST_SAVED_FLOAT_REG (SLJIT_FS0 - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS + 1)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Main structures and functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
The following structures are private, and can be changed in the
|
||||
future. Keeping them here allows code inlining.
|
||||
*/
|
||||
|
||||
struct sljit_memory_fragment {
|
||||
struct sljit_memory_fragment *next;
|
||||
sljit_uw used_size;
|
||||
@ -205,6 +296,7 @@ struct sljit_const {
|
||||
|
||||
struct sljit_compiler {
|
||||
sljit_si error;
|
||||
sljit_si options;
|
||||
|
||||
struct sljit_label *labels;
|
||||
struct sljit_jump *jumps;
|
||||
@ -216,10 +308,14 @@ struct sljit_compiler {
|
||||
struct sljit_memory_fragment *buf;
|
||||
struct sljit_memory_fragment *abuf;
|
||||
|
||||
/* Used local registers. */
|
||||
/* Used scratch registers. */
|
||||
sljit_si scratches;
|
||||
/* Used saved registers. */
|
||||
sljit_si saveds;
|
||||
/* Used float scratch registers. */
|
||||
sljit_si fscratches;
|
||||
/* Used float saved registers. */
|
||||
sljit_si fsaveds;
|
||||
/* Local stack size. */
|
||||
sljit_si local_size;
|
||||
/* Code size. */
|
||||
@ -229,16 +325,13 @@ struct sljit_compiler {
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
sljit_si args;
|
||||
sljit_si locals_offset;
|
||||
sljit_si scratches_start;
|
||||
sljit_si saveds_start;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
sljit_si mode32;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
sljit_si flags_saved;
|
||||
#endif
|
||||
|
||||
@ -271,13 +364,13 @@ struct sljit_compiler {
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
sljit_sw imm;
|
||||
sljit_si cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
sljit_si delay_slot;
|
||||
sljit_si cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
@ -361,46 +454,64 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
|
||||
error, they return with SLJIT_SUCCESS. */
|
||||
|
||||
/*
|
||||
The executable code is basically a function call from the viewpoint of
|
||||
the C language. The function calls must obey to the ABI (Application
|
||||
Binary Interface) of the platform, which specify the purpose of machine
|
||||
registers and stack handling among other things. The sljit_emit_enter
|
||||
function emits the necessary instructions for setting up a new context
|
||||
for the executable code and moves function arguments to the saved
|
||||
registers. The number of arguments are specified in the "args"
|
||||
parameter and the first argument goes to SLJIT_SAVED_REG1, the second
|
||||
goes to SLJIT_SAVED_REG2 and so on. The number of scratch and
|
||||
saved registers are passed in "scratches" and "saveds" arguments
|
||||
respectively. Since the saved registers contains the arguments,
|
||||
"args" must be less or equal than "saveds". The sljit_emit_enter
|
||||
is also capable of allocating a stack space for local variables. The
|
||||
"local_size" argument contains the size in bytes of this local area
|
||||
and its staring address is stored in SLJIT_LOCALS_REG. However
|
||||
the SLJIT_LOCALS_REG is not necessary the machine stack pointer.
|
||||
The memory bytes between SLJIT_LOCALS_REG (inclusive) and
|
||||
SLJIT_LOCALS_REG + local_size (exclusive) can be modified freely
|
||||
until the function returns. The stack space is uninitialized.
|
||||
The executable code is a function call from the viewpoint of the C
|
||||
language. The function calls must obey to the ABI (Application
|
||||
Binary Interface) of the platform, which specify the purpose of
|
||||
all machine registers and stack handling among other things. The
|
||||
sljit_emit_enter function emits the necessary instructions for
|
||||
setting up a new context for the executable code and moves function
|
||||
arguments to the saved registers. Furthermore the options argument
|
||||
can be used to pass configuration options to the compiler. Currently
|
||||
there are no options, so it must be set to 0.
|
||||
|
||||
The number of sljit_sw arguments passed to the generated function
|
||||
are specified in the "args" parameter. The number of arguments must
|
||||
be less than or equal to 3. The first argument goes to SLJIT_S0,
|
||||
the second goes to SLJIT_S1 and so on. The register set used by
|
||||
the function must be declared as well. The number of scratch and
|
||||
saved registers used by the function must be passed to sljit_emit_enter.
|
||||
Only R registers between R0 and "scratches" argument can be used
|
||||
later. E.g. if "scratches" is set to 2, the register set will be
|
||||
limited to R0 and R1. The S registers and the floating point
|
||||
registers ("fscratches" and "fsaveds") are specified in a similar
|
||||
way. The sljit_emit_enter is also capable of allocating a stack
|
||||
space for local variables. The "local_size" argument contains the
|
||||
size in bytes of this local area and its staring address is stored
|
||||
in SLJIT_SP. The memory area between SLJIT_SP (inclusive) and
|
||||
SLJIT_SP + local_size (exclusive) can be modified freely until
|
||||
the function returns. The stack space is not initialized.
|
||||
|
||||
Note: the following conditions must met:
|
||||
0 <= scratches <= SLJIT_NUMBER_OF_REGISTERS
|
||||
0 <= saveds <= SLJIT_NUMBER_OF_REGISTERS
|
||||
scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS
|
||||
0 <= fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS
|
||||
0 <= fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS
|
||||
fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS
|
||||
|
||||
Note: every call of sljit_emit_enter and sljit_set_context
|
||||
overwrites the previous context. */
|
||||
overwrites the previous context.
|
||||
*/
|
||||
|
||||
#define SLJIT_MAX_LOCAL_SIZE 65536
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size);
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size);
|
||||
|
||||
/* The machine code has a context (which contains the local stack space size,
|
||||
number of used registers, etc.) which initialized by sljit_emit_enter. Several
|
||||
functions (like sljit_emit_return) requres this context to be able to generate
|
||||
the appropriate code. However, some code fragments (like inline cache) may have
|
||||
no normal entry point so their context is unknown for the compiler. Using the
|
||||
function below we can specify their context.
|
||||
no normal entry point so their context is unknown for the compiler. Their context
|
||||
can be provided to the compiler by the sljit_set_context function.
|
||||
|
||||
Note: every call of sljit_emit_enter and sljit_set_context overwrites
|
||||
the previous context. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size);
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size);
|
||||
|
||||
/* Return from machine code. The op argument can be SLJIT_UNUSED which means the
|
||||
function does not return with anything or any opcode between SLJIT_MOV and
|
||||
@ -549,37 +660,43 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
||||
the instruction does not set flags (See: SLJIT_KEEP_FLAGS).
|
||||
- flag combinations: '|' means 'logical or'. */
|
||||
|
||||
/* Starting index of opcodes for sljit_emit_op0. */
|
||||
#define SLJIT_OP0_BASE 0
|
||||
|
||||
/* Flags: - (never set any flags)
|
||||
Note: breakpoint instruction is not supported by all architectures (namely ppc)
|
||||
It falls back to SLJIT_NOP in those cases. */
|
||||
#define SLJIT_BREAKPOINT 0
|
||||
#define SLJIT_BREAKPOINT (SLJIT_OP0_BASE + 0)
|
||||
/* Flags: - (never set any flags)
|
||||
Note: may or may not cause an extra cycle wait
|
||||
it can even decrease the runtime in a few cases. */
|
||||
#define SLJIT_NOP 1
|
||||
#define SLJIT_NOP (SLJIT_OP0_BASE + 1)
|
||||
/* Flags: - (may destroy flags)
|
||||
Unsigned multiplication of SLJIT_SCRATCH_REG1 and SLJIT_SCRATCH_REG2.
|
||||
Result goes to SLJIT_SCRATCH_REG2:SLJIT_SCRATCH_REG1 (high:low) word */
|
||||
#define SLJIT_UMUL 2
|
||||
Unsigned multiplication of SLJIT_R0 and SLJIT_R1.
|
||||
Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */
|
||||
#define SLJIT_UMUL (SLJIT_OP0_BASE + 2)
|
||||
/* Flags: - (may destroy flags)
|
||||
Signed multiplication of SLJIT_SCRATCH_REG1 and SLJIT_SCRATCH_REG2.
|
||||
Result goes to SLJIT_SCRATCH_REG2:SLJIT_SCRATCH_REG1 (high:low) word */
|
||||
#define SLJIT_SMUL 3
|
||||
Signed multiplication of SLJIT_R0 and SLJIT_R1.
|
||||
Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */
|
||||
#define SLJIT_SMUL (SLJIT_OP0_BASE + 3)
|
||||
/* Flags: I - (may destroy flags)
|
||||
Unsigned divide of the value in SLJIT_SCRATCH_REG1 by the value in SLJIT_SCRATCH_REG2.
|
||||
The result is placed in SLJIT_SCRATCH_REG1 and the remainder goes to SLJIT_SCRATCH_REG2.
|
||||
Note: if SLJIT_SCRATCH_REG2 contains 0, the behaviour is undefined. */
|
||||
#define SLJIT_UDIV 4
|
||||
Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
|
||||
The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1.
|
||||
Note: if SLJIT_R1 contains 0, the behaviour is undefined. */
|
||||
#define SLJIT_UDIV (SLJIT_OP0_BASE + 4)
|
||||
#define SLJIT_IUDIV (SLJIT_UDIV | SLJIT_INT_OP)
|
||||
/* Flags: I - (may destroy flags)
|
||||
Signed divide of the value in SLJIT_SCRATCH_REG1 by the value in SLJIT_SCRATCH_REG2.
|
||||
The result is placed in SLJIT_SCRATCH_REG1 and the remainder goes to SLJIT_SCRATCH_REG2.
|
||||
Note: if SLJIT_SCRATCH_REG2 contains 0, the behaviour is undefined. */
|
||||
#define SLJIT_SDIV 5
|
||||
Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
|
||||
The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1.
|
||||
Note: if SLJIT_R1 contains 0, the behaviour is undefined. */
|
||||
#define SLJIT_SDIV (SLJIT_OP0_BASE + 5)
|
||||
#define SLJIT_ISDIV (SLJIT_SDIV | SLJIT_INT_OP)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op);
|
||||
|
||||
/* Starting index of opcodes for sljit_emit_op1. */
|
||||
#define SLJIT_OP1_BASE 32
|
||||
|
||||
/* Notes for MOV instructions:
|
||||
U = Mov with update (pre form). If source or destination defined as SLJIT_MEM1(r1)
|
||||
or SLJIT_MEM2(r1, r2), r1 is increased by the sum of r2 and the constant argument
|
||||
@ -592,115 +709,118 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
P = pointer (sljit_p) size */
|
||||
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV 6
|
||||
#define SLJIT_MOV (SLJIT_OP1_BASE + 0)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOV_UB 7
|
||||
#define SLJIT_MOV_UB (SLJIT_OP1_BASE + 1)
|
||||
#define SLJIT_IMOV_UB (SLJIT_MOV_UB | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOV_SB 8
|
||||
#define SLJIT_MOV_SB (SLJIT_OP1_BASE + 2)
|
||||
#define SLJIT_IMOV_SB (SLJIT_MOV_SB | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOV_UH 9
|
||||
#define SLJIT_MOV_UH (SLJIT_OP1_BASE + 3)
|
||||
#define SLJIT_IMOV_UH (SLJIT_MOV_UH | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOV_SH 10
|
||||
#define SLJIT_MOV_SH (SLJIT_OP1_BASE + 4)
|
||||
#define SLJIT_IMOV_SH (SLJIT_MOV_SH | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags)
|
||||
Note: see SLJIT_INT_OP for further details. */
|
||||
#define SLJIT_MOV_UI 11
|
||||
#define SLJIT_MOV_UI (SLJIT_OP1_BASE + 5)
|
||||
/* No SLJIT_INT_OP form, since it is the same as SLJIT_IMOV. */
|
||||
/* Flags: I - (never set any flags)
|
||||
Note: see SLJIT_INT_OP for further details. */
|
||||
#define SLJIT_MOV_SI 12
|
||||
#define SLJIT_MOV_SI (SLJIT_OP1_BASE + 6)
|
||||
#define SLJIT_IMOV (SLJIT_MOV_SI | SLJIT_INT_OP)
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_P 13
|
||||
#define SLJIT_MOV_P (SLJIT_OP1_BASE + 7)
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU 14
|
||||
#define SLJIT_MOVU (SLJIT_OP1_BASE + 8)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOVU_UB 15
|
||||
#define SLJIT_MOVU_UB (SLJIT_OP1_BASE + 9)
|
||||
#define SLJIT_IMOVU_UB (SLJIT_MOVU_UB | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOVU_SB 16
|
||||
#define SLJIT_MOVU_SB (SLJIT_OP1_BASE + 10)
|
||||
#define SLJIT_IMOVU_SB (SLJIT_MOVU_SB | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOVU_UH 17
|
||||
#define SLJIT_MOVU_UH (SLJIT_OP1_BASE + 11)
|
||||
#define SLJIT_IMOVU_UH (SLJIT_MOVU_UH | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags) */
|
||||
#define SLJIT_MOVU_SH 18
|
||||
#define SLJIT_MOVU_SH (SLJIT_OP1_BASE + 12)
|
||||
#define SLJIT_IMOVU_SH (SLJIT_MOVU_SH | SLJIT_INT_OP)
|
||||
/* Flags: I - (never set any flags)
|
||||
Note: see SLJIT_INT_OP for further details. */
|
||||
#define SLJIT_MOVU_UI 19
|
||||
#define SLJIT_MOVU_UI (SLJIT_OP1_BASE + 13)
|
||||
/* No SLJIT_INT_OP form, since it is the same as SLJIT_IMOVU. */
|
||||
/* Flags: I - (never set any flags)
|
||||
Note: see SLJIT_INT_OP for further details. */
|
||||
#define SLJIT_MOVU_SI 20
|
||||
#define SLJIT_MOVU_SI (SLJIT_OP1_BASE + 14)
|
||||
#define SLJIT_IMOVU (SLJIT_MOVU_SI | SLJIT_INT_OP)
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_P 21
|
||||
#define SLJIT_MOVU_P (SLJIT_OP1_BASE + 15)
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_NOT 22
|
||||
#define SLJIT_NOT (SLJIT_OP1_BASE + 16)
|
||||
#define SLJIT_INOT (SLJIT_NOT | SLJIT_INT_OP)
|
||||
/* Flags: I | E | O | K */
|
||||
#define SLJIT_NEG 23
|
||||
#define SLJIT_NEG (SLJIT_OP1_BASE + 17)
|
||||
#define SLJIT_INEG (SLJIT_NEG | SLJIT_INT_OP)
|
||||
/* Count leading zeroes
|
||||
Flags: I | E | K
|
||||
Important note! Sparc 32 does not support K flag, since
|
||||
the required popc instruction is introduced only in sparc 64. */
|
||||
#define SLJIT_CLZ 24
|
||||
#define SLJIT_CLZ (SLJIT_OP1_BASE + 18)
|
||||
#define SLJIT_ICLZ (SLJIT_CLZ | SLJIT_INT_OP)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw);
|
||||
|
||||
/* Starting index of opcodes for sljit_emit_op2. */
|
||||
#define SLJIT_OP2_BASE 96
|
||||
|
||||
/* Flags: I | E | O | C | K */
|
||||
#define SLJIT_ADD 25
|
||||
#define SLJIT_ADD (SLJIT_OP2_BASE + 0)
|
||||
#define SLJIT_IADD (SLJIT_ADD | SLJIT_INT_OP)
|
||||
/* Flags: I | C | K */
|
||||
#define SLJIT_ADDC 26
|
||||
#define SLJIT_ADDC (SLJIT_OP2_BASE + 1)
|
||||
#define SLJIT_IADDC (SLJIT_ADDC | SLJIT_INT_OP)
|
||||
/* Flags: I | E | U | S | O | C | K */
|
||||
#define SLJIT_SUB 27
|
||||
#define SLJIT_SUB (SLJIT_OP2_BASE + 2)
|
||||
#define SLJIT_ISUB (SLJIT_SUB | SLJIT_INT_OP)
|
||||
/* Flags: I | C | K */
|
||||
#define SLJIT_SUBC 28
|
||||
#define SLJIT_SUBC (SLJIT_OP2_BASE + 3)
|
||||
#define SLJIT_ISUBC (SLJIT_SUBC | SLJIT_INT_OP)
|
||||
/* Note: integer mul
|
||||
Flags: I | O (see SLJIT_C_MUL_*) | K */
|
||||
#define SLJIT_MUL 29
|
||||
#define SLJIT_MUL (SLJIT_OP2_BASE + 4)
|
||||
#define SLJIT_IMUL (SLJIT_MUL | SLJIT_INT_OP)
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_AND 30
|
||||
#define SLJIT_AND (SLJIT_OP2_BASE + 5)
|
||||
#define SLJIT_IAND (SLJIT_AND | SLJIT_INT_OP)
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_OR 31
|
||||
#define SLJIT_OR (SLJIT_OP2_BASE + 6)
|
||||
#define SLJIT_IOR (SLJIT_OR | SLJIT_INT_OP)
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_XOR 32
|
||||
#define SLJIT_XOR (SLJIT_OP2_BASE + 7)
|
||||
#define SLJIT_IXOR (SLJIT_XOR | SLJIT_INT_OP)
|
||||
/* Flags: I | E | K
|
||||
Let bit_length be the length of the shift operation: 32 or 64.
|
||||
If src2 is immediate, src2w is masked by (bit_length - 1).
|
||||
Otherwise, if the content of src2 is outside the range from 0
|
||||
to bit_length - 1, the operation is undefined. */
|
||||
#define SLJIT_SHL 33
|
||||
to bit_length - 1, the result is undefined. */
|
||||
#define SLJIT_SHL (SLJIT_OP2_BASE + 8)
|
||||
#define SLJIT_ISHL (SLJIT_SHL | SLJIT_INT_OP)
|
||||
/* Flags: I | E | K
|
||||
Let bit_length be the length of the shift operation: 32 or 64.
|
||||
If src2 is immediate, src2w is masked by (bit_length - 1).
|
||||
Otherwise, if the content of src2 is outside the range from 0
|
||||
to bit_length - 1, the operation is undefined. */
|
||||
#define SLJIT_LSHR 34
|
||||
to bit_length - 1, the result is undefined. */
|
||||
#define SLJIT_LSHR (SLJIT_OP2_BASE + 9)
|
||||
#define SLJIT_ILSHR (SLJIT_LSHR | SLJIT_INT_OP)
|
||||
/* Flags: I | E | K
|
||||
Let bit_length be the length of the shift operation: 32 or 64.
|
||||
If src2 is immediate, src2w is masked by (bit_length - 1).
|
||||
Otherwise, if the content of src2 is outside the range from 0
|
||||
to bit_length - 1, the operation is undefined. */
|
||||
#define SLJIT_ASHR 35
|
||||
to bit_length - 1, the result is undefined. */
|
||||
#define SLJIT_ASHR (SLJIT_OP2_BASE + 10)
|
||||
#define SLJIT_IASHR (SLJIT_ASHR | SLJIT_INT_OP)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
|
||||
@ -709,15 +829,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
|
||||
sljit_si src2, sljit_sw src2w);
|
||||
|
||||
/* The following function is a helper function for sljit_emit_op_custom.
|
||||
It returns with the real machine register index of any SLJIT_SCRATCH
|
||||
SLJIT_SAVED or SLJIT_LOCALS register.
|
||||
Note: it returns with -1 for virtual registers (all EREGs on x86-32). */
|
||||
It returns with the real machine register index ( >=0 ) of any SLJIT_R,
|
||||
SLJIT_S and SLJIT_SP registers.
|
||||
|
||||
Note: it returns with -1 for virtual registers (only on x86-32). */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg);
|
||||
|
||||
/* The following function is a helper function for sljit_emit_op_custom.
|
||||
It returns with the real machine register index of any SLJIT_FLOAT register.
|
||||
Note: the index is divided by 2 on ARM 32 bit architectures. */
|
||||
|
||||
Note: the index is always an even number on ARM (except ARM-64), MIPS, and SPARC. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg);
|
||||
|
||||
@ -738,37 +860,61 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void);
|
||||
|
||||
/* Note: dst is the left and src is the right operand for SLJIT_FCMP.
|
||||
Note: NaN check is always performed. If SLJIT_C_FLOAT_UNORDERED is set,
|
||||
the comparison result is unpredictable.
|
||||
/* Starting index of opcodes for sljit_emit_fop1. */
|
||||
#define SLJIT_FOP1_BASE 128
|
||||
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_MOVD (SLJIT_FOP1_BASE + 0)
|
||||
#define SLJIT_MOVS (SLJIT_MOVD | SLJIT_SINGLE_OP)
|
||||
/* Convert opcodes: CONV[DST_TYPE].FROM[SRC_TYPE]
|
||||
SRC/DST TYPE can be: D - double, S - single, W - signed word, I - signed int
|
||||
Rounding mode when the destination is W or I: round towards zero. */
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_CONVD_FROMS (SLJIT_FOP1_BASE + 1)
|
||||
#define SLJIT_CONVS_FROMD (SLJIT_CONVD_FROMS | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_CONVW_FROMD (SLJIT_FOP1_BASE + 2)
|
||||
#define SLJIT_CONVW_FROMS (SLJIT_CONVW_FROMD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_CONVI_FROMD (SLJIT_FOP1_BASE + 3)
|
||||
#define SLJIT_CONVI_FROMS (SLJIT_CONVI_FROMD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_CONVD_FROMW (SLJIT_FOP1_BASE + 4)
|
||||
#define SLJIT_CONVS_FROMW (SLJIT_CONVD_FROMW | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_CONVD_FROMI (SLJIT_FOP1_BASE + 5)
|
||||
#define SLJIT_CONVS_FROMI (SLJIT_CONVD_FROMI | SLJIT_SINGLE_OP)
|
||||
/* Note: dst is the left and src is the right operand for SLJIT_CMPD.
|
||||
Note: NaN check is always performed. If SLJIT_C_FLOAT_UNORDERED flag
|
||||
is set, the comparison result is unpredictable.
|
||||
Flags: SP | E | S (see SLJIT_C_FLOAT_*) */
|
||||
#define SLJIT_CMPD 36
|
||||
#define SLJIT_CMPD (SLJIT_FOP1_BASE + 6)
|
||||
#define SLJIT_CMPS (SLJIT_CMPD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_MOVD 37
|
||||
#define SLJIT_MOVS (SLJIT_MOVD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_NEGD 38
|
||||
#define SLJIT_NEGD (SLJIT_FOP1_BASE + 7)
|
||||
#define SLJIT_NEGS (SLJIT_NEGD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_ABSD 39
|
||||
#define SLJIT_ABSD (SLJIT_FOP1_BASE + 8)
|
||||
#define SLJIT_ABSS (SLJIT_ABSD | SLJIT_SINGLE_OP)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw);
|
||||
|
||||
/* Starting index of opcodes for sljit_emit_fop2. */
|
||||
#define SLJIT_FOP2_BASE 160
|
||||
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_ADDD 40
|
||||
#define SLJIT_ADDD (SLJIT_FOP2_BASE + 0)
|
||||
#define SLJIT_ADDS (SLJIT_ADDD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_SUBD 41
|
||||
#define SLJIT_SUBD (SLJIT_FOP2_BASE + 1)
|
||||
#define SLJIT_SUBS (SLJIT_SUBD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_MULD 42
|
||||
#define SLJIT_MULD (SLJIT_FOP2_BASE + 2)
|
||||
#define SLJIT_MULS (SLJIT_MULD | SLJIT_SINGLE_OP)
|
||||
/* Flags: SP - (never set any flags) */
|
||||
#define SLJIT_DIVD 43
|
||||
#define SLJIT_DIVD (SLJIT_FOP2_BASE + 3)
|
||||
#define SLJIT_DIVS (SLJIT_DIVD | SLJIT_SINGLE_OP)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
|
||||
@ -888,7 +1034,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
||||
sljit_si src, sljit_sw srcw,
|
||||
sljit_si type);
|
||||
|
||||
/* Copies the base address of SLJIT_LOCALS_REG+offset to dst.
|
||||
/* Copies the base address of SLJIT_SP + offset to dst.
|
||||
Flags: - (never set any flags) */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset);
|
||||
|
||||
@ -898,7 +1044,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
||||
|
||||
/* After the code generation the address for label, jump and const instructions
|
||||
are computed. Since these structures are freed by sljit_free_compiler, the
|
||||
addresses must be preserved by the user program elsewhere. */
|
||||
addresses must be preserved by the user program elsewere. */
|
||||
static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->addr; }
|
||||
static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; }
|
||||
static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { return const_->addr; }
|
||||
@ -912,7 +1058,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#define SLJIT_MAJOR_VERSION 0
|
||||
#define SLJIT_MINOR_VERSION 91
|
||||
#define SLJIT_MINOR_VERSION 92
|
||||
|
||||
/* Get the human readable name of the platform. Can be useful on platforms
|
||||
like ARM, where ARM and Thumb2 functions can be mixed, and
|
||||
|
@ -36,13 +36,13 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
|
||||
}
|
||||
|
||||
/* Last register + 1. */
|
||||
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
|
||||
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
|
||||
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
|
||||
#define TMP_PC (SLJIT_NO_REGISTERS + 4)
|
||||
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
|
||||
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
|
||||
#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
|
||||
#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 5)
|
||||
|
||||
#define TMP_FREG1 (0)
|
||||
#define TMP_FREG2 (SLJIT_FLOAT_REG6 + 1)
|
||||
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
|
||||
|
||||
/* In ARM instruction words.
|
||||
Cache lines are usually 32 byte aligned. */
|
||||
@ -55,8 +55,8 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
|
||||
(((max_diff) / (sljit_si)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1))
|
||||
|
||||
/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
|
||||
0, 0, 1, 2, 10, 11, 4, 5, 6, 7, 8, 13, 3, 12, 14, 15
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
|
||||
0, 0, 1, 2, 11, 10, 9, 8, 7, 6, 5, 4, 13, 3, 12, 14, 15
|
||||
};
|
||||
|
||||
#define RM(rm) (reg_map[rm])
|
||||
@ -102,8 +102,12 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
|
||||
#define VABS_F32 0xeeb00ac0
|
||||
#define VADD_F32 0xee300a00
|
||||
#define VCMP_F32 0xeeb40a40
|
||||
#define VCVT_F32_S32 0xeeb80ac0
|
||||
#define VCVT_F64_F32 0xeeb70ac0
|
||||
#define VCVT_S32_F32 0xeebd0ac0
|
||||
#define VDIV_F32 0xee800a00
|
||||
#define VMOV_F32 0xeeb00a40
|
||||
#define VMOV 0xee000a10
|
||||
#define VMRS 0xeef1fa10
|
||||
#define VMUL_F32 0xee200a00
|
||||
#define VNEG_F32 0xeeb10a40
|
||||
@ -304,7 +308,7 @@ static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_
|
||||
return counter;
|
||||
}
|
||||
|
||||
/* In some rare occasions we may need future patches. The probability is close to 0 in practice. */
|
||||
/* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */
|
||||
struct future_patch {
|
||||
struct future_patch* next;
|
||||
sljit_si index;
|
||||
@ -810,9 +814,6 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||
#define SIGNED_DATA 0x40
|
||||
#define LOAD_DATA 0x80
|
||||
|
||||
#define EMIT_INSTRUCTION(inst) \
|
||||
FAIL_IF(push_inst(compiler, (inst)))
|
||||
|
||||
/* Condition: AL. */
|
||||
#define EMIT_DATA_PROCESS_INS(opcode, set_flags, dst, src1, src2) \
|
||||
(0xe0000000 | ((opcode) << 21) | (set_flags) | RD(dst) | RN(src1) | (src2))
|
||||
@ -822,16 +823,21 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w);
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_si size;
|
||||
sljit_si size, i, tmp;
|
||||
sljit_uw push;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
@ -839,67 +845,58 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
||||
/* Push saved registers, temporary registers
|
||||
stmdb sp!, {..., lr} */
|
||||
push = PUSH | (1 << 14);
|
||||
if (scratches >= 5)
|
||||
push |= 1 << 11;
|
||||
if (scratches >= 4)
|
||||
push |= 1 << 10;
|
||||
if (saveds >= 5)
|
||||
push |= 1 << 8;
|
||||
if (saveds >= 4)
|
||||
push |= 1 << 7;
|
||||
if (saveds >= 3)
|
||||
push |= 1 << 6;
|
||||
if (saveds >= 2)
|
||||
push |= 1 << 5;
|
||||
if (saveds >= 1)
|
||||
push |= 1 << 4;
|
||||
EMIT_INSTRUCTION(push);
|
||||
|
||||
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = SLJIT_S0; i >= tmp; i--)
|
||||
push |= 1 << reg_map[i];
|
||||
|
||||
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
|
||||
push |= 1 << reg_map[i];
|
||||
|
||||
FAIL_IF(push_inst(compiler, push));
|
||||
|
||||
/* Stack must be aligned to 8 bytes: */
|
||||
size = (1 + saveds) * sizeof(sljit_uw);
|
||||
if (scratches >= 4)
|
||||
size += (scratches - 3) * sizeof(sljit_uw);
|
||||
local_size += size;
|
||||
local_size = (local_size + 7) & ~7;
|
||||
local_size -= size;
|
||||
size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
|
||||
local_size = ((size + local_size + 7) & ~7) - size;
|
||||
compiler->local_size = local_size;
|
||||
if (local_size > 0)
|
||||
FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size));
|
||||
FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size));
|
||||
|
||||
if (args >= 1)
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG1, SLJIT_UNUSED, RM(SLJIT_SCRATCH_REG1)));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_S0, SLJIT_UNUSED, RM(SLJIT_R0))));
|
||||
if (args >= 2)
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG2, SLJIT_UNUSED, RM(SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_S1, SLJIT_UNUSED, RM(SLJIT_R1))));
|
||||
if (args >= 3)
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG3, SLJIT_UNUSED, RM(SLJIT_SCRATCH_REG3)));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_S2, SLJIT_UNUSED, RM(SLJIT_R2))));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_si size;
|
||||
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
size = (1 + saveds) * sizeof(sljit_uw);
|
||||
if (scratches >= 4)
|
||||
size += (scratches - 3) * sizeof(sljit_uw);
|
||||
local_size += size;
|
||||
local_size = (local_size + 7) & ~7;
|
||||
local_size -= size;
|
||||
compiler->local_size = local_size;
|
||||
size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
|
||||
compiler->local_size = ((size + local_size + 7) & ~7) - size;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si i, tmp;
|
||||
sljit_uw pop;
|
||||
|
||||
CHECK_ERROR();
|
||||
@ -908,25 +905,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
if (compiler->local_size > 0)
|
||||
FAIL_IF(emit_op(compiler, SLJIT_ADD, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size));
|
||||
FAIL_IF(emit_op(compiler, SLJIT_ADD, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
|
||||
|
||||
pop = POP | (1 << 15);
|
||||
/* Push saved registers, temporary registers
|
||||
ldmia sp!, {..., pc} */
|
||||
if (compiler->scratches >= 5)
|
||||
pop |= 1 << 11;
|
||||
if (compiler->scratches >= 4)
|
||||
pop |= 1 << 10;
|
||||
if (compiler->saveds >= 5)
|
||||
pop |= 1 << 8;
|
||||
if (compiler->saveds >= 4)
|
||||
pop |= 1 << 7;
|
||||
if (compiler->saveds >= 3)
|
||||
pop |= 1 << 6;
|
||||
if (compiler->saveds >= 2)
|
||||
pop |= 1 << 5;
|
||||
if (compiler->saveds >= 1)
|
||||
pop |= 1 << 4;
|
||||
pop = POP | (1 << 15);
|
||||
|
||||
tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = SLJIT_S0; i >= tmp; i--)
|
||||
pop |= 1 << reg_map[i];
|
||||
|
||||
for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
|
||||
pop |= 1 << reg_map[i];
|
||||
|
||||
return push_inst(compiler, pop);
|
||||
}
|
||||
@ -1031,7 +1021,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
if (op == SLJIT_MOV_UB)
|
||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(AND_DP, 0, dst, src2, SRC2_IMM | 0xff));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2]));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2])));
|
||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_UB ? 0x20 : 0x40) | reg_map[dst]));
|
||||
#else
|
||||
return push_inst(compiler, (op == SLJIT_MOV_UB ? UXTB : SXTB) | RD(dst) | RM(src2));
|
||||
@ -1050,7 +1040,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
|
||||
if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2]));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2])));
|
||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_UH ? 0x20 : 0x40) | reg_map[dst]));
|
||||
#else
|
||||
return push_inst(compiler, (op == SLJIT_MOV_UH ? UXTH : SXTH) | RD(dst) | RM(src2));
|
||||
@ -1205,7 +1195,7 @@ static sljit_si generate_int(struct sljit_compiler *compiler, sljit_si reg, slji
|
||||
sljit_uw imm2;
|
||||
sljit_si rol;
|
||||
|
||||
/* Step1: Search a zero byte (8 continuous zero bit). */
|
||||
/* Step1: Search a zero byte (8 continous zero bit). */
|
||||
mask = 0xff000000;
|
||||
rol = 8;
|
||||
while(1) {
|
||||
@ -1303,8 +1293,8 @@ static sljit_si generate_int(struct sljit_compiler *compiler, sljit_si reg, slji
|
||||
return 0;
|
||||
}
|
||||
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(positive ? MOV_DP : MVN_DP, 0, reg, SLJIT_UNUSED, imm1));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(positive ? ORR_DP : BIC_DP, 0, reg, reg, imm2));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(positive ? MOV_DP : MVN_DP, 0, reg, SLJIT_UNUSED, imm1)));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(positive ? ORR_DP : BIC_DP, 0, reg, reg, imm2)));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
@ -1320,16 +1310,12 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sl
|
||||
|
||||
/* Create imm by 1 inst. */
|
||||
tmp = get_imm(imm);
|
||||
if (tmp) {
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, tmp));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
if (tmp)
|
||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, tmp));
|
||||
|
||||
tmp = get_imm(~imm);
|
||||
if (tmp) {
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, tmp));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
if (tmp)
|
||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, tmp));
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
/* Create imm by 2 inst. */
|
||||
@ -1369,14 +1355,14 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_fl
|
||||
if (imm) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, imm));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, imm)));
|
||||
return -1;
|
||||
}
|
||||
imm = get_imm(~argw);
|
||||
if (imm) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, imm));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, imm)));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -1394,8 +1380,8 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_fl
|
||||
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK,
|
||||
RM(OFFS_REG(arg)) | (IS_TYPE1_TRANSFER(inp_flags) ? SRC2_IMM : 0) | ((argw & 0x3) << 7)));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK,
|
||||
RM(OFFS_REG(arg)) | (IS_TYPE1_TRANSFER(inp_flags) ? SRC2_IMM : 0) | ((argw & 0x3) << 7))));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1403,13 +1389,13 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_fl
|
||||
if (argw >= 0 && argw <= 0xfff) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, argw));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, argw)));
|
||||
return -1;
|
||||
}
|
||||
if (argw < 0 && argw >= -0xfff) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, -argw));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, -argw)));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -1417,14 +1403,14 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_fl
|
||||
if (argw >= 0 && argw <= 0xff) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw)));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw))));
|
||||
return -1;
|
||||
}
|
||||
if (argw < 0 && argw >= -0xff) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
argw = -argw;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw)));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw))));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -1477,7 +1463,7 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
|
||||
/* This can only happen for stores */ \
|
||||
/* since ldr reg, [reg, ...]! has no meaning */ \
|
||||
SLJIT_ASSERT(!(inp_flags & LOAD_DATA)); \
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(reg))); \
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(reg)))); \
|
||||
reg = TMP_REG3; \
|
||||
} \
|
||||
}
|
||||
@ -1537,9 +1523,8 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
||||
SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00));
|
||||
if (inp_flags & WRITE_BACK)
|
||||
tmp_r = arg & REG_MASK;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7)));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, 0, reg, tmp_r, TYPE2_TRANSFER_IMM(0)));
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7))));
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, 0, reg, tmp_r, TYPE2_TRANSFER_IMM(0)));
|
||||
}
|
||||
|
||||
imm = (sljit_uw)(argw - compiler->cache_argw);
|
||||
@ -1558,7 +1543,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
||||
imm = get_imm(argw & ~max_delta);
|
||||
if (imm) {
|
||||
TEST_WRITE_BACK();
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, imm));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, imm)));
|
||||
GETPUT_ARG_DATA_TRANSFER(1, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
@ -1567,15 +1552,14 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
||||
if (imm) {
|
||||
argw = -argw;
|
||||
TEST_WRITE_BACK();
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, tmp_r, arg & REG_MASK, imm));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, tmp_r, arg & REG_MASK, imm)));
|
||||
GETPUT_ARG_DATA_TRANSFER(0, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) {
|
||||
TEST_WRITE_BACK();
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
|
||||
}
|
||||
|
||||
if (argw == next_argw && (next_arg & SLJIT_MEM)) {
|
||||
@ -1586,15 +1570,14 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
||||
compiler->cache_argw = argw;
|
||||
|
||||
TEST_WRITE_BACK();
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
|
||||
}
|
||||
|
||||
imm = (sljit_uw)(argw - next_argw);
|
||||
if (arg == next_arg && !(inp_flags & WRITE_BACK) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
|
||||
SLJIT_ASSERT(inp_flags & LOAD_DATA);
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & REG_MASK]));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & REG_MASK])));
|
||||
|
||||
compiler->cache_arg = arg;
|
||||
compiler->cache_argw = argw;
|
||||
@ -1610,8 +1593,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
||||
}
|
||||
|
||||
FAIL_IF(load_immediate(compiler, tmp_r, argw));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0)));
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0)));
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
|
||||
@ -1843,31 +1825,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
op = GET_OPCODE(op);
|
||||
switch (op) {
|
||||
case SLJIT_BREAKPOINT:
|
||||
EMIT_INSTRUCTION(BKPT);
|
||||
FAIL_IF(push_inst(compiler, BKPT));
|
||||
break;
|
||||
case SLJIT_NOP:
|
||||
EMIT_INSTRUCTION(NOP);
|
||||
FAIL_IF(push_inst(compiler, NOP));
|
||||
break;
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||
return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
|
||||
| (reg_map[SLJIT_SCRATCH_REG2] << 16)
|
||||
| (reg_map[SLJIT_SCRATCH_REG1] << 12)
|
||||
| (reg_map[SLJIT_SCRATCH_REG1] << 8)
|
||||
| reg_map[SLJIT_SCRATCH_REG2]);
|
||||
| (reg_map[SLJIT_R1] << 16)
|
||||
| (reg_map[SLJIT_R0] << 12)
|
||||
| (reg_map[SLJIT_R0] << 8)
|
||||
| reg_map[SLJIT_R1]);
|
||||
#else
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, RM(SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, RM(SLJIT_R1))));
|
||||
return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
|
||||
| (reg_map[SLJIT_SCRATCH_REG2] << 16)
|
||||
| (reg_map[SLJIT_SCRATCH_REG1] << 12)
|
||||
| (reg_map[SLJIT_SCRATCH_REG1] << 8)
|
||||
| (reg_map[SLJIT_R1] << 16)
|
||||
| (reg_map[SLJIT_R0] << 12)
|
||||
| (reg_map[SLJIT_R0] << 8)
|
||||
| reg_map[TMP_REG1]);
|
||||
#endif
|
||||
case SLJIT_UDIV:
|
||||
case SLJIT_SDIV:
|
||||
if (compiler->scratches >= 3)
|
||||
EMIT_INSTRUCTION(0xe52d2008 /* str r2, [sp, #-8]! */);
|
||||
FAIL_IF(push_inst(compiler, 0xe52d2008 /* str r2, [sp, #-8]! */));
|
||||
#if defined(__GNUC__)
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
|
||||
(op == SLJIT_UDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
|
||||
@ -1995,7 +1977,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
|
||||
{
|
||||
check_sljit_get_float_register_index(reg);
|
||||
return reg;
|
||||
return reg << 1;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
@ -2064,7 +2046,7 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7)));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7))));
|
||||
arg = SLJIT_MEM | TMP_REG1;
|
||||
argw = 0;
|
||||
}
|
||||
@ -2097,13 +2079,13 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
|
||||
}
|
||||
imm = get_imm(argw & ~0x3fc);
|
||||
if (imm) {
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, imm));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, imm)));
|
||||
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, (argw & 0x3fc) >> 2));
|
||||
}
|
||||
imm = get_imm(-argw & ~0x3fc);
|
||||
if (imm) {
|
||||
argw = -argw;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & REG_MASK, imm));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & REG_MASK, imm)));
|
||||
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG1, reg, (argw & 0x3fc) >> 2));
|
||||
}
|
||||
}
|
||||
@ -2112,7 +2094,7 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
|
||||
compiler->cache_argw = argw;
|
||||
if (arg & REG_MASK) {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, argw));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, arg & REG_MASK, reg_map[TMP_REG1]));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, arg & REG_MASK, reg_map[TMP_REG1])));
|
||||
}
|
||||
else
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
|
||||
@ -2120,60 +2102,114 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
|
||||
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, 0));
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src, srcw));
|
||||
src = TMP_FREG1;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_SINGLE_OP, TMP_FREG1, src, 0)));
|
||||
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (FAST_IS_REG(dst))
|
||||
return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | (TMP_FREG1 << 16));
|
||||
|
||||
/* Store the integer value from a VFP register. */
|
||||
return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, VMOV | RD(src) | (TMP_FREG1 << 16)));
|
||||
else if (src & SLJIT_MEM) {
|
||||
/* Load the integer value into a VFP register. */
|
||||
FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));
|
||||
}
|
||||
else {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
||||
FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | (TMP_FREG1 << 16)));
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F32_S32, op & SLJIT_SINGLE_OP, dst_r, TMP_FREG1, 0)));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
if (src1 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));
|
||||
src1 = TMP_FREG1;
|
||||
}
|
||||
|
||||
if (src2 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));
|
||||
src2 = TMP_FREG2;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_SINGLE_OP, src1, src2, 0)));
|
||||
return push_inst(compiler, VMRS);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_fr;
|
||||
sljit_si dst_r;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100), float_transfer_bit_error);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
if (GET_OPCODE(op) != SLJIT_CONVD_FROMS)
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CMPD) {
|
||||
if (dst & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, dst, dstw));
|
||||
dst = TMP_FREG1;
|
||||
}
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src, srcw));
|
||||
src = TMP_FREG2;
|
||||
}
|
||||
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_SINGLE_OP, dst, src, 0));
|
||||
EMIT_INSTRUCTION(VMRS);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100), float_transfer_bit_error);
|
||||
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
|
||||
|
||||
dst_fr = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_fr, src, srcw));
|
||||
src = dst_fr;
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_r, src, srcw));
|
||||
src = dst_r;
|
||||
}
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOVD:
|
||||
if (src != dst_fr && dst_fr != TMP_FREG1)
|
||||
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_SINGLE_OP, dst_fr, src, 0));
|
||||
break;
|
||||
case SLJIT_NEGD:
|
||||
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_SINGLE_OP, dst_fr, src, 0));
|
||||
break;
|
||||
case SLJIT_ABSD:
|
||||
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_SINGLE_OP, dst_fr, src, 0));
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst_fr == TMP_FREG1) {
|
||||
if (GET_OPCODE(op) == SLJIT_MOVD)
|
||||
dst_fr = src;
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), dst_fr, dst, dstw));
|
||||
case SLJIT_MOVD:
|
||||
if (src != dst_r) {
|
||||
if (dst_r != TMP_FREG1)
|
||||
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_SINGLE_OP, dst_r, src, 0)));
|
||||
else
|
||||
dst_r = src;
|
||||
}
|
||||
break;
|
||||
case SLJIT_NEGD:
|
||||
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_SINGLE_OP, dst_r, src, 0)));
|
||||
break;
|
||||
case SLJIT_ABSD:
|
||||
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_SINGLE_OP, dst_r, src, 0)));
|
||||
break;
|
||||
case SLJIT_CONVD_FROMS:
|
||||
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F64_F32, op & SLJIT_SINGLE_OP, dst_r, src, 0)));
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), dst_r, dst, dstw);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2182,16 +2218,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
sljit_si dst_fr;
|
||||
sljit_si dst_r;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
ADJUST_LOCAL_OFFSET(src1, src1w);
|
||||
ADJUST_LOCAL_OFFSET(src2, src2w);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
|
||||
dst_fr = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (src2 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));
|
||||
@ -2205,23 +2244,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_ADDD:
|
||||
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_SINGLE_OP, dst_fr, src2, src1));
|
||||
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_SINGLE_OP, dst_r, src2, src1)));
|
||||
break;
|
||||
|
||||
case SLJIT_SUBD:
|
||||
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_SINGLE_OP, dst_fr, src2, src1));
|
||||
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_SINGLE_OP, dst_r, src2, src1)));
|
||||
break;
|
||||
|
||||
case SLJIT_MULD:
|
||||
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_SINGLE_OP, dst_fr, src2, src1));
|
||||
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_SINGLE_OP, dst_r, src2, src1)));
|
||||
break;
|
||||
|
||||
case SLJIT_DIVD:
|
||||
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_SINGLE_OP, dst_fr, src2, src1));
|
||||
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_SINGLE_OP, dst_r, src2, src1)));
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst_fr == TMP_FREG1)
|
||||
if (dst_r == TMP_FREG1)
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
@ -2252,7 +2291,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
||||
if (getput_arg_fast(compiler, WORD_DATA, TMP_REG3, dst, dstw))
|
||||
return compiler->error;
|
||||
/* TMP_REG3 is used for caching. */
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG2, SLJIT_UNUSED, RM(TMP_REG3)));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG2, SLJIT_UNUSED, RM(TMP_REG3))));
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
return getput_arg(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0);
|
||||
@ -2265,7 +2304,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if (FAST_IS_REG(src))
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src)));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src))));
|
||||
else if (src & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, WORD_DATA | LOAD_DATA, TMP_REG3, src, srcw))
|
||||
FAIL_IF(compiler->error);
|
||||
@ -2273,7 +2312,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
FAIL_IF(getput_arg(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, 0, 0));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(TMP_REG2))));
|
||||
}
|
||||
}
|
||||
else if (src & SLJIT_IMM)
|
||||
@ -2454,14 +2493,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
if (op < SLJIT_ADD) {
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 0));
|
||||
EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc);
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 0)));
|
||||
FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc));
|
||||
return (dst_r == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
ins = (op == SLJIT_AND ? AND_DP : (op == SLJIT_OR ? ORR_DP : EOR_DP));
|
||||
if ((op == SLJIT_OR || op == SLJIT_XOR) && FAST_IS_REG(dst) && dst == src) {
|
||||
EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ins, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc);
|
||||
FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc));
|
||||
/* The condition must always be set, even if the ORR/EOR is not executed above. */
|
||||
return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst))) : SLJIT_SUCCESS;
|
||||
}
|
||||
@ -2478,8 +2517,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 1) & ~COND_MASK) | cc);
|
||||
EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000));
|
||||
FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 1) & ~COND_MASK) | cc));
|
||||
FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)));
|
||||
if (dst_r == TMP_REG2)
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0));
|
||||
|
||||
|
@ -34,18 +34,18 @@ typedef sljit_ui sljit_ins;
|
||||
|
||||
#define TMP_ZERO 0
|
||||
|
||||
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
|
||||
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
|
||||
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
|
||||
#define TMP_REG4 (SLJIT_NO_REGISTERS + 4)
|
||||
#define TMP_LR (SLJIT_NO_REGISTERS + 5)
|
||||
#define TMP_SP (SLJIT_NO_REGISTERS + 6)
|
||||
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
|
||||
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
|
||||
#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
|
||||
#define TMP_REG4 (SLJIT_NUMBER_OF_REGISTERS + 5)
|
||||
#define TMP_LR (SLJIT_NUMBER_OF_REGISTERS + 6)
|
||||
#define TMP_SP (SLJIT_NUMBER_OF_REGISTERS + 7)
|
||||
|
||||
#define TMP_FREG1 (0)
|
||||
#define TMP_FREG2 (SLJIT_FLOAT_REG6 + 1)
|
||||
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
|
||||
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 7] = {
|
||||
31, 0, 1, 2, 3, 4, 19, 20, 21, 22, 23, 29, 9, 10, 11, 12, 30, 31
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {
|
||||
31, 0, 1, 2, 3, 4, 5, 6, 7, 13, 14, 15, 16, 17, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 29, 9, 10, 11, 12, 30, 31
|
||||
};
|
||||
|
||||
#define W_OP (1 << 31)
|
||||
@ -83,6 +83,8 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 7] = {
|
||||
#define FABS 0x1e60c000
|
||||
#define FADD 0x1e602800
|
||||
#define FCMP 0x1e602000
|
||||
#define FCVT 0x1e224000
|
||||
#define FCVTZS 0x9e780000
|
||||
#define FDIV 0x1e601800
|
||||
#define FMOV 0x1e604000
|
||||
#define FMUL 0x1e600800
|
||||
@ -104,6 +106,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 7] = {
|
||||
#define RET 0xd65f0000
|
||||
#define SBC 0xda000000
|
||||
#define SBFM 0x93000000
|
||||
#define SCVTF 0x9e620000
|
||||
#define SDIV 0x9ac00c00
|
||||
#define SMADDL 0x9b200000
|
||||
#define SMULH 0x9b403c00
|
||||
@ -1058,17 +1061,24 @@ static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit
|
||||
/* Entry, exit */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
|
||||
sljit_si i, tmp, offs, prev;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
compiler->locals_offset = (2 + saveds) * sizeof(sljit_sw);
|
||||
compiler->locals_offset = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
|
||||
local_size = (compiler->locals_offset + local_size + 15) & ~15;
|
||||
compiler->local_size = local_size;
|
||||
|
||||
@ -1086,64 +1096,98 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
||||
FAIL_IF(push_inst(compiler, STP_PRE | 29 | RT2(TMP_LR) | RN(TMP_SP) | (0x40 << 15)));
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_LOCALS_REG) | RN(TMP_SP)));
|
||||
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_SP)));
|
||||
|
||||
if (saveds >= 2)
|
||||
FAIL_IF(push_inst(compiler, STP | RT(SLJIT_SAVED_REG1) | RT2(SLJIT_SAVED_REG2) | RN(TMP_SP) | (2 << 15)));
|
||||
if (saveds >= 4)
|
||||
FAIL_IF(push_inst(compiler, STP | RT(SLJIT_SAVED_REG3) | RT2(SLJIT_SAVED_EREG1) | RN(TMP_SP) | (4 << 15)));
|
||||
if (saveds == 1)
|
||||
FAIL_IF(push_inst(compiler, STRI | RT(SLJIT_SAVED_REG1) | RN(TMP_SP) | (2 << 10)));
|
||||
if (saveds == 3)
|
||||
FAIL_IF(push_inst(compiler, STRI | RT(SLJIT_SAVED_REG3) | RN(TMP_SP) | (4 << 10)));
|
||||
if (saveds == 5)
|
||||
FAIL_IF(push_inst(compiler, STRI | RT(SLJIT_SAVED_EREG2) | RN(TMP_SP) | (6 << 10)));
|
||||
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
offs = 2 << 15;
|
||||
prev = -1;
|
||||
for (i = SLJIT_S0; i >= tmp; i--) {
|
||||
if (prev == -1) {
|
||||
prev = i;
|
||||
continue;
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
|
||||
offs += 2 << 15;
|
||||
prev = -1;
|
||||
}
|
||||
|
||||
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
|
||||
if (prev == -1) {
|
||||
prev = i;
|
||||
continue;
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
|
||||
offs += 2 << 15;
|
||||
prev = -1;
|
||||
}
|
||||
|
||||
if (prev != -1)
|
||||
FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(TMP_SP) | (offs >> 5)));
|
||||
|
||||
if (args >= 1)
|
||||
FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_SAVED_REG1) | RN(TMP_ZERO) | RM(SLJIT_SCRATCH_REG1)));
|
||||
FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0) | RN(TMP_ZERO) | RM(SLJIT_R0)));
|
||||
if (args >= 2)
|
||||
FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_SAVED_REG2) | RN(TMP_ZERO) | RM(SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S1) | RN(TMP_ZERO) | RM(SLJIT_R1)));
|
||||
if (args >= 3)
|
||||
FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_SAVED_REG3) | RN(TMP_ZERO) | RM(SLJIT_SCRATCH_REG3)));
|
||||
FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S2) | RN(TMP_ZERO) | RM(SLJIT_R2)));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
compiler->locals_offset = (2 + saveds) * sizeof(sljit_sw);
|
||||
compiler->locals_offset = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
|
||||
compiler->local_size = (compiler->locals_offset + local_size + 15) & ~15;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si saveds, local_size;
|
||||
sljit_si local_size;
|
||||
sljit_si i, tmp, offs, prev;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, op, src, srcw);
|
||||
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
saveds = compiler->saveds;
|
||||
tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
offs = 2 << 15;
|
||||
prev = -1;
|
||||
for (i = SLJIT_S0; i >= tmp; i--) {
|
||||
if (prev == -1) {
|
||||
prev = i;
|
||||
continue;
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
|
||||
offs += 2 << 15;
|
||||
prev = -1;
|
||||
}
|
||||
|
||||
if (saveds >= 2)
|
||||
FAIL_IF(push_inst(compiler, LDP | RT(SLJIT_SAVED_REG1) | RT2(SLJIT_SAVED_REG2) | RN(TMP_SP) | (2 << 15)));
|
||||
if (saveds >= 4)
|
||||
FAIL_IF(push_inst(compiler, LDP | RT(SLJIT_SAVED_REG3) | RT2(SLJIT_SAVED_EREG1) | RN(TMP_SP) | (4 << 15)));
|
||||
if (saveds == 1)
|
||||
FAIL_IF(push_inst(compiler, LDRI | RT(SLJIT_SAVED_REG1) | RN(TMP_SP) | (2 << 10)));
|
||||
if (saveds == 3)
|
||||
FAIL_IF(push_inst(compiler, LDRI | RT(SLJIT_SAVED_REG3) | RN(TMP_SP) | (4 << 10)));
|
||||
if (saveds == 5)
|
||||
FAIL_IF(push_inst(compiler, LDRI | RT(SLJIT_SAVED_EREG2) | RN(TMP_SP) | (6 << 10)));
|
||||
for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
|
||||
if (prev == -1) {
|
||||
prev = i;
|
||||
continue;
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
|
||||
offs += 2 << 15;
|
||||
prev = -1;
|
||||
}
|
||||
|
||||
if (prev != -1)
|
||||
FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(TMP_SP) | (offs >> 5)));
|
||||
|
||||
local_size = compiler->local_size;
|
||||
|
||||
@ -1184,15 +1228,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
return push_inst(compiler, NOP);
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_SCRATCH_REG1)));
|
||||
FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_SCRATCH_REG1) | RN(SLJIT_SCRATCH_REG1) | RM(SLJIT_SCRATCH_REG2) | RT2(TMP_ZERO)));
|
||||
return push_inst(compiler, (op == SLJIT_SMUL ? SMULH : UMULH) | RD(SLJIT_SCRATCH_REG2) | RN(TMP_REG1) | RM(SLJIT_SCRATCH_REG2));
|
||||
FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0)));
|
||||
FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO)));
|
||||
return push_inst(compiler, (op == SLJIT_SMUL ? SMULH : UMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));
|
||||
case SLJIT_UDIV:
|
||||
case SLJIT_SDIV:
|
||||
FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_SCRATCH_REG1)));
|
||||
FAIL_IF(push_inst(compiler, ((op == SLJIT_SDIV ? SDIV : UDIV) ^ inv_bits) | RD(SLJIT_SCRATCH_REG1) | RN(SLJIT_SCRATCH_REG1) | RM(SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_SCRATCH_REG2) | RN(SLJIT_SCRATCH_REG1) | RM(SLJIT_SCRATCH_REG2) | RT2(TMP_ZERO)));
|
||||
return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_SCRATCH_REG2) | RN(TMP_REG1) | RM(SLJIT_SCRATCH_REG2));
|
||||
FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0)));
|
||||
FAIL_IF(push_inst(compiler, ((op == SLJIT_SDIV ? SDIV : UDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)));
|
||||
FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO)));
|
||||
return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
@ -1524,41 +1568,107 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
|
||||
return push_inst(compiler, STR_FI | ins_bits | VT(reg) | RN(TMP_REG3));
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
|
||||
sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CONVI_FROMD)
|
||||
inv_bits |= (1 << 31);
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src, srcw);
|
||||
src = TMP_FREG1;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, (FCVTZS ^ inv_bits) | RD(dst_r) | VN(src)));
|
||||
|
||||
if (dst_r == TMP_REG1 && dst != SLJIT_UNUSED)
|
||||
return emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONVI_FROMD) ? INT_SIZE : WORD_SIZE) | STORE, TMP_REG1, dst, dstw);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CONVD_FROMI)
|
||||
inv_bits |= (1 << 31);
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONVD_FROMI) ? INT_SIZE : WORD_SIZE), TMP_REG1, src, srcw);
|
||||
src = TMP_REG1;
|
||||
} else if (src & SLJIT_IMM) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (GET_OPCODE(op) == SLJIT_CONVD_FROMI)
|
||||
srcw = (sljit_si)srcw;
|
||||
#endif
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, (SCVTF ^ inv_bits) | VD(dst_r) | RN(src)));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_fop_mem(compiler, ((op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE) | STORE, TMP_FREG1, dst, dstw);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
sljit_si mem_flags = (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE;
|
||||
sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0;
|
||||
|
||||
if (src1 & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w);
|
||||
src1 = TMP_FREG1;
|
||||
}
|
||||
|
||||
if (src2 & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w);
|
||||
src2 = TMP_FREG2;
|
||||
}
|
||||
|
||||
return push_inst(compiler, (FCMP ^ inv_bits) | VN(src1) | VM(src2));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_r, mem_flags = (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE;
|
||||
sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0;
|
||||
sljit_ins inv_bits;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CMPD) {
|
||||
if (dst & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, mem_flags, TMP_FREG1, dst, dstw);
|
||||
dst = TMP_FREG1;
|
||||
}
|
||||
if (src & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, mem_flags, TMP_FREG2, src, srcw);
|
||||
src = TMP_FREG2;
|
||||
}
|
||||
return push_inst(compiler, (FCMP ^ inv_bits) | VN(dst) | VM(src));
|
||||
}
|
||||
SLJIT_COMPILE_ASSERT((INT_SIZE ^ 0x100) == WORD_SIZE, must_be_one_bit_difference);
|
||||
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
|
||||
|
||||
inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
dst_r = (dst <= REG_MASK) ? dst : TMP_FREG1;
|
||||
if (src & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, mem_flags, dst_r, src, srcw);
|
||||
emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONVD_FROMS) ? (mem_flags ^ 0x100) : mem_flags, dst_r, src, srcw);
|
||||
src = dst_r;
|
||||
}
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOVD:
|
||||
if (src != dst_r)
|
||||
FAIL_IF(push_inst(compiler, (FMOV ^ inv_bits) | VD(dst_r) | VN(src)));
|
||||
if (src != dst_r) {
|
||||
if (dst_r != TMP_FREG1)
|
||||
FAIL_IF(push_inst(compiler, (FMOV ^ inv_bits) | VD(dst_r) | VN(src)));
|
||||
else
|
||||
dst_r = src;
|
||||
}
|
||||
break;
|
||||
case SLJIT_NEGD:
|
||||
FAIL_IF(push_inst(compiler, (FNEG ^ inv_bits) | VD(dst_r) | VN(src)));
|
||||
@ -1566,11 +1676,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
||||
case SLJIT_ABSD:
|
||||
FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src)));
|
||||
break;
|
||||
case SLJIT_CONVD_FROMS:
|
||||
FAIL_IF(push_inst(compiler, FCVT | ((op & SLJIT_SINGLE_OP) ? (1 << 22) : (1 << 15)) | VD(dst_r) | VN(src)));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(dst & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS;
|
||||
return emit_fop_mem(compiler, mem_flags | STORE, TMP_FREG1, dst, dstw);
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_fop_mem(compiler, mem_flags | STORE, dst_r, dst, dstw);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
|
||||
@ -1583,11 +1696,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
ADJUST_LOCAL_OFFSET(src1, src1w);
|
||||
ADJUST_LOCAL_OFFSET(src2, src2w);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
dst_r = (dst <= REG_MASK) ? dst : TMP_FREG1;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
if (src1 & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w);
|
||||
src1 = TMP_FREG1;
|
||||
@ -1631,7 +1747,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (dst <= REG_MASK)
|
||||
if (FAST_IS_REG(dst))
|
||||
return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(TMP_LR));
|
||||
|
||||
/* Memory. */
|
||||
@ -1644,7 +1760,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
||||
check_sljit_emit_fast_return(compiler, src, srcw);
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if (src <= REG_MASK)
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src)));
|
||||
else if (src & SLJIT_MEM)
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw));
|
||||
@ -1833,7 +1949,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
cc = get_cc(type);
|
||||
dst_r = (dst <= REG_MASK) ? dst : TMP_REG1;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
|
||||
|
||||
if (GET_OPCODE(op) < SLJIT_ADD) {
|
||||
FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(dst_r) | RN(TMP_ZERO) | RM(TMP_ZERO)));
|
||||
|
@ -33,17 +33,17 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
|
||||
typedef sljit_ui sljit_ins;
|
||||
|
||||
/* Last register + 1. */
|
||||
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
|
||||
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
|
||||
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
|
||||
#define TMP_PC (SLJIT_NO_REGISTERS + 4)
|
||||
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
|
||||
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
|
||||
#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
|
||||
#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 5)
|
||||
|
||||
#define TMP_FREG1 (0)
|
||||
#define TMP_FREG2 (SLJIT_FLOAT_REG6 + 1)
|
||||
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
|
||||
|
||||
/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
|
||||
0, 0, 1, 2, 12, 5, 6, 7, 8, 10, 11, 13, 3, 4, 14, 15
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
|
||||
0, 0, 1, 2, 12, 11, 10, 9, 8, 7, 6, 5, 13, 3, 4, 14, 15
|
||||
};
|
||||
|
||||
#define COPY_BITS(src, from, to, bits) \
|
||||
@ -138,9 +138,9 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
|
||||
#define ORRI 0xf0400000
|
||||
#define ORRS 0x4300
|
||||
#define ORR_W 0xea400000
|
||||
#define POP 0xbd00
|
||||
#define POP 0xbc00
|
||||
#define POP_W 0xe8bd0000
|
||||
#define PUSH 0xb500
|
||||
#define PUSH 0xb400
|
||||
#define PUSH_W 0xe92d0000
|
||||
#define RSB_WI 0xf1c00000
|
||||
#define RSBSI 0x4240
|
||||
@ -169,8 +169,12 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
|
||||
#define VABS_F32 0xeeb00ac0
|
||||
#define VADD_F32 0xee300a00
|
||||
#define VCMP_F32 0xeeb40a40
|
||||
#define VCVT_F32_S32 0xeeb80ac0
|
||||
#define VCVT_F64_F32 0xeeb70ac0
|
||||
#define VCVT_S32_F32 0xeebd0ac0
|
||||
#define VDIV_F32 0xee800a00
|
||||
#define VMOV_F32 0xeeb00a40
|
||||
#define VMOV 0xee000a10
|
||||
#define VMRS 0xeef1fa10
|
||||
#define VMUL_F32 0xee200a00
|
||||
#define VNEG_F32 0xeeb10a40
|
||||
@ -956,7 +960,7 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
|
||||
}
|
||||
|
||||
/* SP based immediate. */
|
||||
if (SLJIT_UNLIKELY(arg == SLJIT_LOCALS_REG) && OFFSET_CHECK(0xff, 2) && IS_WORD_SIZE(flags) && reg_map[reg] <= 7) {
|
||||
if (SLJIT_UNLIKELY(arg == SLJIT_SP) && OFFSET_CHECK(0xff, 2) && IS_WORD_SIZE(flags) && reg_map[reg] <= 7) {
|
||||
FAIL_IF(push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2)));
|
||||
return -1;
|
||||
}
|
||||
@ -1123,82 +1127,84 @@ static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit
|
||||
/* Entry, exit */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_si size;
|
||||
sljit_si size, i, tmp;
|
||||
sljit_ins push;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
push = (1 << 4);
|
||||
if (saveds >= 5)
|
||||
push |= 1 << 11;
|
||||
if (saveds >= 4)
|
||||
push |= 1 << 10;
|
||||
if (saveds >= 3)
|
||||
push |= 1 << 8;
|
||||
if (saveds >= 2)
|
||||
push |= 1 << 7;
|
||||
if (saveds >= 1)
|
||||
push |= 1 << 6;
|
||||
if (scratches >= 5)
|
||||
push |= 1 << 5;
|
||||
FAIL_IF(saveds >= 3
|
||||
? push_inst32(compiler, PUSH_W | (1 << 14) | push)
|
||||
: push_inst16(compiler, PUSH | push));
|
||||
|
||||
/* Stack must be aligned to 8 bytes: */
|
||||
size = (3 + saveds) * sizeof(sljit_uw);
|
||||
local_size += size;
|
||||
local_size = (local_size + 7) & ~7;
|
||||
local_size -= size;
|
||||
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = SLJIT_S0; i >= tmp; i--)
|
||||
push |= 1 << reg_map[i];
|
||||
|
||||
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
|
||||
push |= 1 << reg_map[i];
|
||||
|
||||
FAIL_IF((push & 0xff00)
|
||||
? push_inst32(compiler, PUSH_W | (1 << 14) | push)
|
||||
: push_inst16(compiler, PUSH | (1 << 8) | push));
|
||||
|
||||
/* Stack must be aligned to 8 bytes: (LR, R4) */
|
||||
size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
|
||||
local_size = ((size + local_size + 7) & ~7) - size;
|
||||
compiler->local_size = local_size;
|
||||
if (local_size > 0) {
|
||||
if (local_size <= (127 << 2))
|
||||
FAIL_IF(push_inst16(compiler, SUB_SP | (local_size >> 2)));
|
||||
else
|
||||
FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_LOCALS_REG, SLJIT_LOCALS_REG, local_size));
|
||||
FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, local_size));
|
||||
}
|
||||
|
||||
if (args >= 1)
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG1, SLJIT_SCRATCH_REG1)));
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S0, SLJIT_R0)));
|
||||
if (args >= 2)
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG2, SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S1, SLJIT_R1)));
|
||||
if (args >= 3)
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG3, SLJIT_SCRATCH_REG3)));
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S2, SLJIT_R2)));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_si size;
|
||||
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
size = (3 + saveds) * sizeof(sljit_uw);
|
||||
local_size += size;
|
||||
local_size = (local_size + 7) & ~7;
|
||||
local_size -= size;
|
||||
compiler->local_size = local_size;
|
||||
size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
|
||||
compiler->local_size = ((size + local_size + 7) & ~7) - size;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si i, tmp;
|
||||
sljit_ins pop;
|
||||
|
||||
CHECK_ERROR();
|
||||
@ -1210,25 +1216,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
||||
if (compiler->local_size <= (127 << 2))
|
||||
FAIL_IF(push_inst16(compiler, ADD_SP | (compiler->local_size >> 2)));
|
||||
else
|
||||
FAIL_IF(emit_op_imm(compiler, SLJIT_ADD | ARG2_IMM, SLJIT_LOCALS_REG, SLJIT_LOCALS_REG, compiler->local_size));
|
||||
FAIL_IF(emit_op_imm(compiler, SLJIT_ADD | ARG2_IMM, SLJIT_SP, SLJIT_SP, compiler->local_size));
|
||||
}
|
||||
|
||||
pop = (1 << 4);
|
||||
if (compiler->saveds >= 5)
|
||||
pop |= 1 << 11;
|
||||
if (compiler->saveds >= 4)
|
||||
pop |= 1 << 10;
|
||||
if (compiler->saveds >= 3)
|
||||
pop |= 1 << 8;
|
||||
if (compiler->saveds >= 2)
|
||||
pop |= 1 << 7;
|
||||
if (compiler->saveds >= 1)
|
||||
pop |= 1 << 6;
|
||||
if (compiler->scratches >= 5)
|
||||
pop |= 1 << 5;
|
||||
return compiler->saveds >= 3
|
||||
|
||||
tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = SLJIT_S0; i >= tmp; i--)
|
||||
pop |= 1 << reg_map[i];
|
||||
|
||||
for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
|
||||
pop |= 1 << reg_map[i];
|
||||
|
||||
return (pop & 0xff00)
|
||||
? push_inst32(compiler, POP_W | (1 << 15) | pop)
|
||||
: push_inst16(compiler, POP | pop);
|
||||
: push_inst16(compiler, POP | (1 << 8) | pop);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -1264,10 +1266,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
return push_inst32(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
|
||||
| (reg_map[SLJIT_SCRATCH_REG2] << 8)
|
||||
| (reg_map[SLJIT_SCRATCH_REG1] << 12)
|
||||
| (reg_map[SLJIT_SCRATCH_REG1] << 16)
|
||||
| reg_map[SLJIT_SCRATCH_REG2]);
|
||||
| (reg_map[SLJIT_R1] << 8)
|
||||
| (reg_map[SLJIT_R0] << 12)
|
||||
| (reg_map[SLJIT_R0] << 16)
|
||||
| reg_map[SLJIT_R1]);
|
||||
case SLJIT_UDIV:
|
||||
case SLJIT_SDIV:
|
||||
if (compiler->scratches >= 4) {
|
||||
@ -1512,7 +1514,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
|
||||
{
|
||||
check_sljit_get_float_register_index(reg);
|
||||
return reg;
|
||||
return reg << 1;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
@ -1607,6 +1609,69 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
|
||||
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg));
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src, srcw));
|
||||
src = TMP_FREG1;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_SINGLE_OP) | DD4(TMP_FREG1) | DM4(src)));
|
||||
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (FAST_IS_REG(dst))
|
||||
return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | DN4(TMP_FREG1));
|
||||
|
||||
/* Store the integer value from a VFP register. */
|
||||
return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | DN4(TMP_FREG1)));
|
||||
else if (src & SLJIT_MEM) {
|
||||
/* Load the integer value into a VFP register. */
|
||||
FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));
|
||||
}
|
||||
else {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
||||
FAIL_IF(push_inst32(compiler, VMOV | RT4(TMP_REG1) | DN4(TMP_FREG1)));
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst32(compiler, VCVT_F32_S32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(TMP_FREG1)));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
if (src1 & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
|
||||
src1 = TMP_FREG1;
|
||||
}
|
||||
|
||||
if (src2 & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w);
|
||||
src2 = TMP_FREG2;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_SINGLE_OP) | DD4(src1) | DM4(src2)));
|
||||
return push_inst32(compiler, VMRS);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
@ -1614,27 +1679,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
||||
sljit_si dst_r;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100), float_transfer_bit_error);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
if (GET_OPCODE(op) != SLJIT_CONVD_FROMS)
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CMPD) {
|
||||
if (dst & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, dst, dstw);
|
||||
dst = TMP_FREG1;
|
||||
}
|
||||
if (src & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src, srcw);
|
||||
src = TMP_FREG2;
|
||||
}
|
||||
FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst) | DM4(src)));
|
||||
return push_inst32(compiler, VMRS);
|
||||
}
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100), float_transfer_bit_error);
|
||||
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
|
||||
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
dst_r = (dst <= REG_MASK) ? dst : TMP_FREG1;
|
||||
if (src & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_r, src, srcw);
|
||||
src = dst_r;
|
||||
@ -1642,8 +1696,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOVD:
|
||||
if (src != dst_r)
|
||||
FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
|
||||
if (src != dst_r) {
|
||||
if (dst_r != TMP_FREG1)
|
||||
FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
|
||||
else
|
||||
dst_r = src;
|
||||
}
|
||||
break;
|
||||
case SLJIT_NEGD:
|
||||
FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
|
||||
@ -1651,11 +1709,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
||||
case SLJIT_ABSD:
|
||||
FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
|
||||
break;
|
||||
case SLJIT_CONVD_FROMS:
|
||||
FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(dst & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS;
|
||||
return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), dst_r, dst, dstw);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
|
||||
@ -1667,12 +1729,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
ADJUST_LOCAL_OFFSET(src1, src1w);
|
||||
ADJUST_LOCAL_OFFSET(src2, src2w);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
|
||||
dst_r = (dst <= REG_MASK) ? dst : TMP_FREG1;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
if (src1 & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
|
||||
src1 = TMP_FREG1;
|
||||
@ -1718,7 +1783,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (dst <= REG_MASK)
|
||||
if (FAST_IS_REG(dst))
|
||||
return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3));
|
||||
|
||||
/* Memory. */
|
||||
@ -1737,7 +1802,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
||||
check_sljit_emit_fast_return(compiler, src, srcw);
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if (src <= REG_MASK)
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src)));
|
||||
else if (src & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG3, src, srcw))
|
||||
|
@ -84,7 +84,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB) {
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
|
||||
@ -102,7 +102,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH) {
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
@ -125,7 +125,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
@ -154,9 +154,9 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
@ -174,7 +174,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
@ -189,8 +189,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (!(op & SLJIT_SET_O))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, SLL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
|
||||
|
||||
@ -198,21 +198,21 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
else {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
}
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
} else {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
if (!(op & SLJIT_SET_C))
|
||||
@ -221,7 +221,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
/* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
/* Set carry flag. */
|
||||
return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG);
|
||||
return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG);
|
||||
|
||||
case SLJIT_SUB:
|
||||
if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
|
||||
@ -233,9 +233,9 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
|
||||
@ -247,7 +247,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
|
||||
@ -265,8 +265,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
|
||||
if (!(op & SLJIT_SET_O))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
|
||||
|
||||
@ -279,27 +279,27 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2));
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(LESS_FLAG), LESS_FLAG));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
|
||||
return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MUL:
|
||||
SLJIT_ASSERT(!(flags & SRC2_IMM));
|
||||
if (!(op & SLJIT_SET_O)) {
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
|
||||
@ -307,10 +307,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
#endif
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, MFHI | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, MFHI | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(TMP_EREG2) | SH_IMM(31), TMP_EREG2));
|
||||
return push_inst(compiler, SUBU | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
|
||||
FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(UGREATER_FLAG) | SH_IMM(31), UGREATER_FLAG));
|
||||
return push_inst(compiler, SUBU | SA(ULESS_FLAG) | TA(UGREATER_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_AND:
|
||||
EMIT_LOGICAL(ANDI, AND);
|
||||
|
@ -217,7 +217,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
@ -246,9 +246,9 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
@ -266,7 +266,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
@ -281,8 +281,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (!(op & SLJIT_SET_O))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, SELECT_OP(DSRL32, SLL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
|
||||
|
||||
@ -290,21 +290,21 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
else {
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
}
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
} else {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
if (!(op & SLJIT_SET_C))
|
||||
@ -313,7 +313,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
/* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
/* Set carry flag. */
|
||||
return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG);
|
||||
return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG);
|
||||
|
||||
case SLJIT_SUB:
|
||||
if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
|
||||
@ -325,9 +325,9 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
|
||||
@ -339,7 +339,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
|
||||
@ -357,8 +357,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
|
||||
if (!(op & SLJIT_SET_O))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
|
||||
|
||||
@ -371,27 +371,27 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2));
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(LESS_FLAG), LESS_FLAG));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
|
||||
return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MUL:
|
||||
SLJIT_ASSERT(!(flags & SRC2_IMM));
|
||||
if (!(op & SLJIT_SET_O)) {
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
if (op & SLJIT_INT_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));
|
||||
@ -402,10 +402,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
#endif
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, MFHI | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, MFHI | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(TMP_EREG2) | SH_IMM(31), TMP_EREG2));
|
||||
return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(UGREATER_FLAG) | SH_IMM(31), UGREATER_FLAG));
|
||||
return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(ULESS_FLAG) | TA(UGREATER_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_AND:
|
||||
EMIT_LOGICAL(ANDI, AND);
|
||||
|
@ -25,13 +25,17 @@
|
||||
*/
|
||||
|
||||
/* Latest MIPS architecture. */
|
||||
/* Automatically detect SLJIT_MIPS_32_64 */
|
||||
/* Automatically detect SLJIT_MIPS_R1 */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
|
||||
{
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
return "MIPS V" SLJIT_CPUINFO;
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
return "MIPS32-R1" SLJIT_CPUINFO;
|
||||
#else
|
||||
return "MIPS64-R1" SLJIT_CPUINFO;
|
||||
#endif
|
||||
#else /* SLJIT_MIPS_R1 */
|
||||
return "MIPS III" SLJIT_CPUINFO;
|
||||
#endif
|
||||
}
|
||||
@ -40,35 +44,32 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
|
||||
Both for mips-32 and mips-64 */
|
||||
typedef sljit_ui sljit_ins;
|
||||
|
||||
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
|
||||
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
|
||||
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
|
||||
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
|
||||
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
|
||||
#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
|
||||
|
||||
/* For position independent code, t9 must contain the function address. */
|
||||
#define PIC_ADDR_REG TMP_REG2
|
||||
|
||||
/* TMP_EREGs are used mainly for arithmetic operations. */
|
||||
#define TMP_EREG1 15
|
||||
#define TMP_EREG2 24
|
||||
/* Floating point status register. */
|
||||
#define FCSR_REG 31
|
||||
/* Return address register. */
|
||||
#define RETURN_ADDR_REG 31
|
||||
|
||||
/* Flags are keept in volatile registers. */
|
||||
#define EQUAL_FLAG 7
|
||||
/* Flags are kept in volatile registers. */
|
||||
#define EQUAL_FLAG 12
|
||||
/* And carry flag as well. */
|
||||
#define ULESS_FLAG 10
|
||||
#define UGREATER_FLAG 11
|
||||
#define LESS_FLAG 12
|
||||
#define GREATER_FLAG 13
|
||||
#define OVERFLOW_FLAG 14
|
||||
#define ULESS_FLAG 13
|
||||
#define UGREATER_FLAG 14
|
||||
#define LESS_FLAG 15
|
||||
#define GREATER_FLAG 31
|
||||
#define OVERFLOW_FLAG 1
|
||||
|
||||
#define TMP_FREG1 (0)
|
||||
#define TMP_FREG2 ((SLJIT_FLOAT_REG6 + 1) << 1)
|
||||
#define TMP_FREG2 ((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) << 1)
|
||||
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
||||
0, 2, 5, 6, 3, 8, 16, 17, 18, 19, 20, 29, 4, 25, 9
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||
0, 2, 5, 6, 7, 8, 9, 10, 11, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 3, 25, 4
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -92,10 +93,10 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
||||
#define HI(opcode) ((opcode) << 26)
|
||||
#define LO(opcode) (opcode)
|
||||
/* S = (16 << 21) D = (17 << 21) */
|
||||
#define FMT_SD (16 << 21)
|
||||
#define FMT_S (16 << 21)
|
||||
|
||||
#define ABS_fmt (HI(17) | FMT_SD | LO(5))
|
||||
#define ADD_fmt (HI(17) | FMT_SD | LO(0))
|
||||
#define ABS_S (HI(17) | FMT_S | LO(5))
|
||||
#define ADD_S (HI(17) | FMT_S | LO(0))
|
||||
#define ADDIU (HI(9))
|
||||
#define ADDU (HI(0) | LO(33))
|
||||
#define AND (HI(0) | LO(36))
|
||||
@ -112,17 +113,18 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
||||
#define BNE (HI(5))
|
||||
#define BREAK (HI(0) | LO(13))
|
||||
#define CFC1 (HI(17) | (2 << 21))
|
||||
#define C_UN_fmt (HI(17) | FMT_SD | LO(49))
|
||||
#define C_UEQ_fmt (HI(17) | FMT_SD | LO(51))
|
||||
#define C_ULE_fmt (HI(17) | FMT_SD | LO(55))
|
||||
#define C_ULT_fmt (HI(17) | FMT_SD | LO(53))
|
||||
#define C_UN_S (HI(17) | FMT_S | LO(49))
|
||||
#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 CVT_S_S (HI(17) | FMT_S | LO(32))
|
||||
#define DADDIU (HI(25))
|
||||
#define DADDU (HI(0) | LO(45))
|
||||
#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 DIV_fmt (HI(17) | FMT_SD | LO(3))
|
||||
#define DIV_S (HI(17) | FMT_S | LO(3))
|
||||
#define DMULT (HI(0) | LO(28))
|
||||
#define DMULTU (HI(0) | LO(29))
|
||||
#define DSLL (HI(0) | LO(56))
|
||||
@ -142,13 +144,15 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
||||
#define LD (HI(55))
|
||||
#define LUI (HI(15))
|
||||
#define LW (HI(35))
|
||||
#define MFC1 (HI(17))
|
||||
#define MFHI (HI(0) | LO(16))
|
||||
#define MFLO (HI(0) | LO(18))
|
||||
#define MOV_fmt (HI(17) | FMT_SD | LO(6))
|
||||
#define MUL_fmt (HI(17) | FMT_SD | LO(2))
|
||||
#define MOV_S (HI(17) | FMT_S | LO(6))
|
||||
#define MTC1 (HI(17) | (4 << 21))
|
||||
#define MUL_S (HI(17) | FMT_S | LO(2))
|
||||
#define MULT (HI(0) | LO(24))
|
||||
#define MULTU (HI(0) | LO(25))
|
||||
#define NEG_fmt (HI(17) | FMT_SD | LO(7))
|
||||
#define NEG_S (HI(17) | FMT_S | LO(7))
|
||||
#define NOP (HI(0) | LO(0))
|
||||
#define NOR (HI(0) | LO(39))
|
||||
#define OR (HI(0) | LO(37))
|
||||
@ -164,13 +168,14 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
||||
#define SRLV (HI(0) | LO(6))
|
||||
#define SRA (HI(0) | LO(3))
|
||||
#define SRAV (HI(0) | LO(7))
|
||||
#define SUB_fmt (HI(17) | FMT_SD | LO(1))
|
||||
#define SUB_S (HI(17) | FMT_S | LO(1))
|
||||
#define SUBU (HI(0) | LO(35))
|
||||
#define SW (HI(43))
|
||||
#define TRUNC_W_S (HI(17) | FMT_S | LO(13))
|
||||
#define XOR (HI(0) | LO(38))
|
||||
#define XORI (HI(14))
|
||||
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
#define CLZ (HI(28) | LO(32))
|
||||
#define DCLZ (HI(28) | LO(36))
|
||||
#define MUL (HI(28) | LO(2))
|
||||
@ -495,6 +500,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||
/* Separates integer and floating point registers */
|
||||
#define GPR_REG 0x0f
|
||||
#define DOUBLE_DATA 0x10
|
||||
#define SINGLE_DATA 0x12
|
||||
|
||||
#define MEM_MASK 0x1f
|
||||
|
||||
@ -532,20 +538,26 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||
#include "sljitNativeMIPS_64.c"
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_ins base;
|
||||
sljit_si i, tmp, offs;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
local_size += (saveds + 1 + 4) * sizeof(sljit_sw);
|
||||
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + FIXED_LOCALS_OFFSET;
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
local_size = (local_size + 15) & ~0xf;
|
||||
#else
|
||||
@ -555,51 +567,58 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
||||
|
||||
if (local_size <= SIMM_MAX) {
|
||||
/* Frequent case. */
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_LOCALS_REG) | T(SLJIT_LOCALS_REG) | IMM(-local_size), DR(SLJIT_LOCALS_REG)));
|
||||
base = S(SLJIT_LOCALS_REG);
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));
|
||||
base = S(SLJIT_SP);
|
||||
}
|
||||
else {
|
||||
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_LOCALS_REG) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_LOCALS_REG) | T(TMP_REG1) | D(SLJIT_LOCALS_REG), DR(SLJIT_LOCALS_REG)));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(TMP_REG1) | D(SLJIT_SP), DR(SLJIT_SP)));
|
||||
base = S(TMP_REG2);
|
||||
local_size = 0;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(local_size - 1 * (sljit_si)sizeof(sljit_sw)), MOVABLE_INS));
|
||||
if (saveds >= 1)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG1) | IMM(local_size - 2 * (sljit_si)sizeof(sljit_sw)), MOVABLE_INS));
|
||||
if (saveds >= 2)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG2) | IMM(local_size - 3 * (sljit_si)sizeof(sljit_sw)), MOVABLE_INS));
|
||||
if (saveds >= 3)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG3) | IMM(local_size - 4 * (sljit_si)sizeof(sljit_sw)), MOVABLE_INS));
|
||||
if (saveds >= 4)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_EREG1) | IMM(local_size - 5 * (sljit_si)sizeof(sljit_sw)), MOVABLE_INS));
|
||||
if (saveds >= 5)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_EREG2) | IMM(local_size - 6 * (sljit_si)sizeof(sljit_sw)), MOVABLE_INS));
|
||||
offs = local_size - (sljit_sw)(sizeof(sljit_sw));
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offs), MOVABLE_INS));
|
||||
|
||||
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = SLJIT_S0; i >= tmp; i--) {
|
||||
offs -= (sljit_si)(sizeof(sljit_sw));
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));
|
||||
}
|
||||
|
||||
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
|
||||
offs -= (sljit_si)(sizeof(sljit_sw));
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));
|
||||
}
|
||||
|
||||
if (args >= 1)
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(4) | TA(0) | D(SLJIT_SAVED_REG1), DR(SLJIT_SAVED_REG1)));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(4) | TA(0) | D(SLJIT_S0), DR(SLJIT_S0)));
|
||||
if (args >= 2)
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(5) | TA(0) | D(SLJIT_SAVED_REG2), DR(SLJIT_SAVED_REG2)));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(5) | TA(0) | D(SLJIT_S1), DR(SLJIT_S1)));
|
||||
if (args >= 3)
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(6) | TA(0) | D(SLJIT_SAVED_REG3), DR(SLJIT_SAVED_REG3)));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(6) | TA(0) | D(SLJIT_S2), DR(SLJIT_S2)));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
local_size += (saveds + 1 + 4) * sizeof(sljit_sw);
|
||||
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + FIXED_LOCALS_OFFSET;
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
compiler->local_size = (local_size + 15) & ~0xf;
|
||||
#else
|
||||
@ -609,7 +628,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si local_size;
|
||||
sljit_si local_size, i, tmp, offs;
|
||||
sljit_ins base;
|
||||
|
||||
CHECK_ERROR();
|
||||
@ -619,31 +638,36 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
||||
|
||||
local_size = compiler->local_size;
|
||||
if (local_size <= SIMM_MAX)
|
||||
base = S(SLJIT_LOCALS_REG);
|
||||
base = S(SLJIT_SP);
|
||||
else {
|
||||
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_LOCALS_REG) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
base = S(TMP_REG1);
|
||||
local_size = 0;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - 1 * (sljit_si)sizeof(sljit_sw)), RETURN_ADDR_REG));
|
||||
if (compiler->saveds >= 5)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_EREG2) | IMM(local_size - 6 * (sljit_si)sizeof(sljit_sw)), DR(SLJIT_SAVED_EREG2)));
|
||||
if (compiler->saveds >= 4)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_EREG1) | IMM(local_size - 5 * (sljit_si)sizeof(sljit_sw)), DR(SLJIT_SAVED_EREG1)));
|
||||
if (compiler->saveds >= 3)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG3) | IMM(local_size - 4 * (sljit_si)sizeof(sljit_sw)), DR(SLJIT_SAVED_REG3)));
|
||||
if (compiler->saveds >= 2)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG2) | IMM(local_size - 3 * (sljit_si)sizeof(sljit_sw)), DR(SLJIT_SAVED_REG2)));
|
||||
if (compiler->saveds >= 1)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG1) | IMM(local_size - 2 * (sljit_si)sizeof(sljit_sw)), DR(SLJIT_SAVED_REG1)));
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - (sljit_si)sizeof(sljit_sw)), RETURN_ADDR_REG));
|
||||
offs = local_size - (sljit_si)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
|
||||
|
||||
tmp = compiler->scratches;
|
||||
for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(i) | IMM(offs), DR(i)));
|
||||
offs += (sljit_si)(sizeof(sljit_sw));
|
||||
}
|
||||
|
||||
tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = tmp; i <= SLJIT_S0; i++) {
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(i) | IMM(offs), DR(i)));
|
||||
offs += (sljit_si)(sizeof(sljit_sw));
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(offs == local_size - (sljit_sw)(sizeof(sljit_sw)));
|
||||
|
||||
FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
if (compiler->local_size <= SIMM_MAX)
|
||||
return push_inst(compiler, ADDIU_W | S(SLJIT_LOCALS_REG) | T(SLJIT_LOCALS_REG) | IMM(compiler->local_size), UNMOVABLE_INS);
|
||||
return push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(compiler->local_size), UNMOVABLE_INS);
|
||||
else
|
||||
return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_LOCALS_REG), UNMOVABLE_INS);
|
||||
return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_SP), UNMOVABLE_INS);
|
||||
}
|
||||
|
||||
#undef STACK_STORE
|
||||
@ -1038,30 +1062,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? DMULTU : DMULT) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? MULTU : MULT) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
|
||||
#endif
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_SCRATCH_REG1), DR(SLJIT_SCRATCH_REG1)));
|
||||
return push_inst(compiler, MFHI | D(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2));
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
|
||||
return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
|
||||
case SLJIT_UDIV:
|
||||
case SLJIT_SDIV:
|
||||
#if !(defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
#if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
if (int_op)
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DDIVU : DDIV) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
|
||||
#endif
|
||||
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_SCRATCH_REG1), DR(SLJIT_SCRATCH_REG1)));
|
||||
return push_inst(compiler, MFHI | D(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2));
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
|
||||
return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
@ -1278,83 +1302,164 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
|
||||
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 7))
|
||||
#define FMT(op) (((op & SLJIT_SINGLE_OP) ^ SLJIT_SINGLE_OP) << (21 - 8))
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# define flags 0
|
||||
#else
|
||||
sljit_si flags = (GET_OPCODE(op) == SLJIT_CONVW_FROMD) << 21;
|
||||
#endif
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
|
||||
src = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
src <<= 1;
|
||||
|
||||
FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
|
||||
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (FAST_IS_REG(dst))
|
||||
return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS);
|
||||
|
||||
/* Store the integer value from a VFP register. */
|
||||
return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, TMP_FREG1, dst, dstw, 0, 0);
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# undef is_long
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# define flags 0
|
||||
#else
|
||||
sljit_si flags = (GET_OPCODE(op) == SLJIT_CONVD_FROMW) << 21;
|
||||
#endif
|
||||
|
||||
sljit_si dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
|
||||
else if (src & SLJIT_MEM) {
|
||||
/* Load the integer value into a VFP register. */
|
||||
FAIL_IF(emit_op_mem2(compiler, ((flags) ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
|
||||
}
|
||||
else {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (GET_OPCODE(op) == SLJIT_CONVD_FROMI)
|
||||
srcw = (sljit_si)srcw;
|
||||
#endif
|
||||
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
|
||||
FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | (((op & SLJIT_SINGLE_OP) ^ SLJIT_SINGLE_OP) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# undef flags
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
if (src1 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
|
||||
src1 = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
src1 <<= 1;
|
||||
|
||||
if (src2 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
|
||||
src2 = TMP_FREG2;
|
||||
}
|
||||
else
|
||||
src2 <<= 1;
|
||||
|
||||
/* src2 and src1 are swapped. */
|
||||
if (op & SLJIT_SET_E) {
|
||||
FAIL_IF(push_inst(compiler, C_UEQ_S | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, CFC1 | TA(EQUAL_FLAG) | DA(FCSR_REG), EQUAL_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(EQUAL_FLAG) | DA(EQUAL_FLAG) | SH_IMM(23), EQUAL_FLAG));
|
||||
FAIL_IF(push_inst(compiler, ANDI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG));
|
||||
}
|
||||
if (op & SLJIT_SET_S) {
|
||||
/* Mixing the instructions for the two checks. */
|
||||
FAIL_IF(push_inst(compiler, C_ULT_S | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, CFC1 | TA(ULESS_FLAG) | DA(FCSR_REG), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, C_ULT_S | FMT(op) | FT(src1) | FS(src2), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(ULESS_FLAG) | DA(ULESS_FLAG) | SH_IMM(23), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, ANDI | SA(ULESS_FLAG) | TA(ULESS_FLAG) | IMM(1), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, CFC1 | TA(UGREATER_FLAG) | DA(FCSR_REG), UGREATER_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(UGREATER_FLAG) | DA(UGREATER_FLAG) | SH_IMM(23), UGREATER_FLAG));
|
||||
FAIL_IF(push_inst(compiler, ANDI | SA(UGREATER_FLAG) | TA(UGREATER_FLAG) | IMM(1), UGREATER_FLAG));
|
||||
}
|
||||
return push_inst(compiler, C_UN_S | FMT(op) | FT(src2) | FS(src1), FCSR_FCC);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_fr;
|
||||
sljit_si dst_r;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CMPD) {
|
||||
if (dst & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, dst, dstw, src, srcw));
|
||||
dst = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
dst <<= 1;
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
|
||||
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src, srcw, 0, 0));
|
||||
src = TMP_FREG2;
|
||||
}
|
||||
else
|
||||
src <<= 1;
|
||||
if (GET_OPCODE(op) == SLJIT_CONVD_FROMS)
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
|
||||
/* src and dst are swapped. */
|
||||
if (op & SLJIT_SET_E) {
|
||||
FAIL_IF(push_inst(compiler, C_UEQ_fmt | FMT(op) | FT(src) | FS(dst), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, CFC1 | TA(EQUAL_FLAG) | DA(FCSR_REG), EQUAL_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(EQUAL_FLAG) | DA(EQUAL_FLAG) | SH_IMM(23), EQUAL_FLAG));
|
||||
FAIL_IF(push_inst(compiler, ANDI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG));
|
||||
}
|
||||
if (op & SLJIT_SET_S) {
|
||||
/* Mixing the instructions for the two checks. */
|
||||
FAIL_IF(push_inst(compiler, C_ULT_fmt | FMT(op) | FT(src) | FS(dst), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, CFC1 | TA(ULESS_FLAG) | DA(FCSR_REG), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, C_ULT_fmt | FMT(op) | FT(dst) | FS(src), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(ULESS_FLAG) | DA(ULESS_FLAG) | SH_IMM(23), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, ANDI | SA(ULESS_FLAG) | TA(ULESS_FLAG) | IMM(1), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, CFC1 | TA(UGREATER_FLAG) | DA(FCSR_REG), UGREATER_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(UGREATER_FLAG) | DA(UGREATER_FLAG) | SH_IMM(23), UGREATER_FLAG));
|
||||
FAIL_IF(push_inst(compiler, ANDI | SA(UGREATER_FLAG) | TA(UGREATER_FLAG) | IMM(1), UGREATER_FLAG));
|
||||
}
|
||||
return push_inst(compiler, C_UN_fmt | FMT(op) | FT(src) | FS(dst), FCSR_FCC);
|
||||
}
|
||||
|
||||
dst_fr = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_fr, src, srcw, dst, dstw));
|
||||
src = dst_fr;
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));
|
||||
src = dst_r;
|
||||
}
|
||||
else
|
||||
src <<= 1;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOVD:
|
||||
if (src != dst_fr && dst_fr != TMP_FREG1)
|
||||
FAIL_IF(push_inst(compiler, MOV_fmt | FMT(op) | FS(src) | FD(dst_fr), MOVABLE_INS));
|
||||
break;
|
||||
case SLJIT_NEGD:
|
||||
FAIL_IF(push_inst(compiler, NEG_fmt | FMT(op) | FS(src) | FD(dst_fr), MOVABLE_INS));
|
||||
break;
|
||||
case SLJIT_ABSD:
|
||||
FAIL_IF(push_inst(compiler, ABS_fmt | FMT(op) | FS(src) | FD(dst_fr), MOVABLE_INS));
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst_fr == TMP_FREG1) {
|
||||
if (GET_OPCODE(op) == SLJIT_MOVD)
|
||||
dst_fr = src;
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_fr, dst, dstw, 0, 0));
|
||||
case SLJIT_MOVD:
|
||||
if (src != dst_r) {
|
||||
if (dst_r != TMP_FREG1)
|
||||
FAIL_IF(push_inst(compiler, MOV_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
|
||||
else
|
||||
dst_r = src;
|
||||
}
|
||||
break;
|
||||
case SLJIT_NEGD:
|
||||
FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
|
||||
break;
|
||||
case SLJIT_ABSD:
|
||||
FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
|
||||
break;
|
||||
case SLJIT_CONVD_FROMS:
|
||||
FAIL_IF(push_inst(compiler, CVT_S_S | ((op & SLJIT_SINGLE_OP) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1363,15 +1468,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
sljit_si dst_fr, flags = 0;
|
||||
sljit_si dst_r, flags = 0;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
ADJUST_LOCAL_OFFSET(src1, src1w);
|
||||
ADJUST_LOCAL_OFFSET(src2, src2w);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
dst_fr = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG2;
|
||||
dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG2;
|
||||
|
||||
if (src1 & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
|
||||
@ -1415,23 +1523,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_ADDD:
|
||||
FAIL_IF(push_inst(compiler, ADD_fmt | FMT(op) | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
|
||||
break;
|
||||
|
||||
case SLJIT_SUBD:
|
||||
FAIL_IF(push_inst(compiler, SUB_fmt | FMT(op) | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
|
||||
break;
|
||||
|
||||
case SLJIT_MULD:
|
||||
FAIL_IF(push_inst(compiler, MUL_fmt | FMT(op) | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
|
||||
break;
|
||||
|
||||
case SLJIT_DIVD:
|
||||
FAIL_IF(push_inst(compiler, DIV_fmt | FMT(op) | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst_fr == TMP_FREG2)
|
||||
if (dst_r == TMP_FREG2)
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
@ -1613,7 +1721,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
||||
PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
jump->addr = compiler->size;
|
||||
/* A NOP if type < CALL1. */
|
||||
PTR_FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SCRATCH_REG1) | TA(0) | DA(4), UNMOVABLE_INS));
|
||||
PTR_FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_R0) | TA(0) | DA(4), UNMOVABLE_INS));
|
||||
}
|
||||
return jump;
|
||||
}
|
||||
@ -1794,36 +1902,36 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
|
||||
|
||||
switch (type & 0xff) {
|
||||
case SLJIT_C_FLOAT_EQUAL:
|
||||
inst = C_UEQ_fmt;
|
||||
inst = C_UEQ_S;
|
||||
if_true = 1;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_NOT_EQUAL:
|
||||
inst = C_UEQ_fmt;
|
||||
inst = C_UEQ_S;
|
||||
if_true = 0;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_LESS:
|
||||
inst = C_ULT_fmt;
|
||||
inst = C_ULT_S;
|
||||
if_true = 1;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_GREATER_EQUAL:
|
||||
inst = C_ULT_fmt;
|
||||
inst = C_ULT_S;
|
||||
if_true = 0;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_GREATER:
|
||||
inst = C_ULE_fmt;
|
||||
inst = C_ULE_S;
|
||||
if_true = 0;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_LESS_EQUAL:
|
||||
inst = C_ULE_fmt;
|
||||
inst = C_ULE_S;
|
||||
if_true = 1;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_UNORDERED:
|
||||
inst = C_UN_fmt;
|
||||
inst = C_UN_S;
|
||||
if_true = 1;
|
||||
break;
|
||||
case SLJIT_C_FLOAT_ORDERED:
|
||||
default: /* Make compilers happy. */
|
||||
inst = C_UN_fmt;
|
||||
inst = C_UN_S;
|
||||
if_true = 0;
|
||||
break;
|
||||
}
|
||||
@ -1874,12 +1982,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
/* We need an extra instruction in any case. */
|
||||
return push_inst(compiler, ADDU_W | S(SLJIT_SCRATCH_REG1) | TA(0) | DA(4), UNMOVABLE_INS);
|
||||
return push_inst(compiler, ADDU_W | S(SLJIT_R0) | TA(0) | DA(4), UNMOVABLE_INS);
|
||||
}
|
||||
|
||||
/* Register input. */
|
||||
if (type >= SLJIT_CALL1)
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SCRATCH_REG1) | TA(0) | DA(4), 4));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_R0) | TA(0) | DA(4), 4));
|
||||
FAIL_IF(push_inst(compiler, JALR | S(src_r) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
return push_inst(compiler, ADDU_W | S(src_r) | TA(0) | D(PIC_ADDR_REG), UNMOVABLE_INS);
|
||||
}
|
||||
|
@ -87,22 +87,22 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
|
||||
#endif /* _AIX */
|
||||
}
|
||||
|
||||
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
|
||||
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
|
||||
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
|
||||
#define TMP_ZERO (SLJIT_NO_REGISTERS + 4)
|
||||
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
|
||||
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
|
||||
#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
|
||||
#define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 5)
|
||||
|
||||
#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
|
||||
#define TMP_CALL_REG (SLJIT_NO_REGISTERS + 5)
|
||||
#define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 6)
|
||||
#else
|
||||
#define TMP_CALL_REG TMP_REG2
|
||||
#endif
|
||||
|
||||
#define TMP_FREG1 (0)
|
||||
#define TMP_FREG2 (SLJIT_FLOAT_REG6 + 1)
|
||||
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
|
||||
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 6] = {
|
||||
0, 3, 4, 5, 6, 7, 30, 29, 28, 27, 26, 1, 8, 9, 10, 31, 12
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
|
||||
0, 3, 4, 5, 6, 7, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 8, 9, 10, 31, 12
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -114,6 +114,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 6] = {
|
||||
#define B(b) (reg_map[b] << 11)
|
||||
#define C(c) (reg_map[c] << 6)
|
||||
#define FD(fd) ((fd) << 21)
|
||||
#define FS(fs) ((fs) << 21)
|
||||
#define FA(fa) ((fa) << 16)
|
||||
#define FB(fb) ((fb) << 11)
|
||||
#define FC(fc) ((fc) << 6)
|
||||
@ -159,13 +160,17 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 6] = {
|
||||
#define FABS (HI(63) | LO(264))
|
||||
#define FADD (HI(63) | LO(21))
|
||||
#define FADDS (HI(59) | LO(21))
|
||||
#define FCFID (HI(63) | LO(846))
|
||||
#define FCMPU (HI(63) | LO(0))
|
||||
#define FCTIDZ (HI(63) | LO(815))
|
||||
#define FCTIWZ (HI(63) | LO(15))
|
||||
#define FDIV (HI(63) | LO(18))
|
||||
#define FDIVS (HI(59) | LO(18))
|
||||
#define FMR (HI(63) | LO(72))
|
||||
#define FMUL (HI(63) | LO(25))
|
||||
#define FMULS (HI(59) | LO(25))
|
||||
#define FNEG (HI(63) | LO(40))
|
||||
#define FRSP (HI(63) | LO(12))
|
||||
#define FSUB (HI(63) | LO(20))
|
||||
#define FSUBS (HI(59) | LO(20))
|
||||
#define LD (HI(58) | 0)
|
||||
@ -202,6 +207,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 6] = {
|
||||
#define STD (HI(62) | 0)
|
||||
#define STDU (HI(62) | 1)
|
||||
#define STDUX (HI(31) | LO(181))
|
||||
#define STFIWX (HI(31) | LO(983))
|
||||
#define STW (HI(36))
|
||||
#define STWU (HI(37))
|
||||
#define STWUX (HI(31) | LO(183))
|
||||
@ -565,118 +571,136 @@ ALT_FORM6 0x200000 */
|
||||
#define STACK_LOAD LD
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
|
||||
sljit_si i, tmp, offs;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
FAIL_IF(push_inst(compiler, MFLR | D(0)));
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(SLJIT_LOCALS_REG) | IMM(-(sljit_si)(sizeof(sljit_sw))) ));
|
||||
if (saveds >= 1)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG1) | A(SLJIT_LOCALS_REG) | IMM(-2 * (sljit_si)(sizeof(sljit_sw))) ));
|
||||
if (saveds >= 2)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG2) | A(SLJIT_LOCALS_REG) | IMM(-3 * (sljit_si)(sizeof(sljit_sw))) ));
|
||||
if (saveds >= 3)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG3) | A(SLJIT_LOCALS_REG) | IMM(-4 * (sljit_si)(sizeof(sljit_sw))) ));
|
||||
if (saveds >= 4)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG1) | A(SLJIT_LOCALS_REG) | IMM(-5 * (sljit_si)(sizeof(sljit_sw))) ));
|
||||
if (saveds >= 5)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG2) | A(SLJIT_LOCALS_REG) | IMM(-6 * (sljit_si)(sizeof(sljit_sw))) ));
|
||||
offs = -(sljit_si)(sizeof(sljit_sw));
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
|
||||
|
||||
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = SLJIT_S0; i >= tmp; i--) {
|
||||
offs -= (sljit_si)(sizeof(sljit_sw));
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
|
||||
}
|
||||
|
||||
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
|
||||
offs -= (sljit_si)(sizeof(sljit_sw));
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(offs == -(sljit_si)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1));
|
||||
|
||||
#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_LOCALS_REG) | IMM(2 * sizeof(sljit_sw)) ));
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_LOCALS_REG) | IMM(sizeof(sljit_sw)) ));
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
|
||||
#endif
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
|
||||
if (args >= 1)
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG1) | A(SLJIT_SAVED_REG1) | B(SLJIT_SCRATCH_REG1)));
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(SLJIT_S0) | B(SLJIT_R0)));
|
||||
if (args >= 2)
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG2) | A(SLJIT_SAVED_REG2) | B(SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_R1) | A(SLJIT_S1) | B(SLJIT_R1)));
|
||||
if (args >= 3)
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG3) | A(SLJIT_SAVED_REG3) | B(SLJIT_SCRATCH_REG3)));
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_R2) | A(SLJIT_S2) | B(SLJIT_R2)));
|
||||
|
||||
#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
|
||||
compiler->local_size = (1 + saveds + 6 + 8) * sizeof(sljit_sw) + local_size;
|
||||
#else
|
||||
compiler->local_size = (1 + saveds + 2) * sizeof(sljit_sw) + local_size;
|
||||
#endif
|
||||
compiler->local_size = (compiler->local_size + 15) & ~0xf;
|
||||
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + FIXED_LOCALS_OFFSET;
|
||||
local_size = (local_size + 15) & ~0xf;
|
||||
compiler->local_size = local_size;
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
if (compiler->local_size <= SIMM_MAX)
|
||||
FAIL_IF(push_inst(compiler, STWU | S(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | IMM(-compiler->local_size)));
|
||||
if (local_size <= SIMM_MAX)
|
||||
FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
|
||||
else {
|
||||
FAIL_IF(load_immediate(compiler, 0, -compiler->local_size));
|
||||
FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | B(0)));
|
||||
FAIL_IF(load_immediate(compiler, 0, -local_size));
|
||||
FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));
|
||||
}
|
||||
#else
|
||||
if (compiler->local_size <= SIMM_MAX)
|
||||
FAIL_IF(push_inst(compiler, STDU | S(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | IMM(-compiler->local_size)));
|
||||
if (local_size <= SIMM_MAX)
|
||||
FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
|
||||
else {
|
||||
FAIL_IF(load_immediate(compiler, 0, -compiler->local_size));
|
||||
FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | B(0)));
|
||||
FAIL_IF(load_immediate(compiler, 0, -local_size));
|
||||
FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));
|
||||
}
|
||||
#endif
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
|
||||
compiler->local_size = (1 + saveds + 6 + 8) * sizeof(sljit_sw) + local_size;
|
||||
#else
|
||||
compiler->local_size = (1 + saveds + 2) * sizeof(sljit_sw) + local_size;
|
||||
#endif
|
||||
compiler->local_size = (compiler->local_size + 15) & ~0xf;
|
||||
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + FIXED_LOCALS_OFFSET;
|
||||
compiler->local_size = (local_size + 15) & ~0xf;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si i, tmp, offs;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, op, src, srcw);
|
||||
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
if (compiler->local_size <= SIMM_MAX)
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | IMM(compiler->local_size)));
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_SP) | A(SLJIT_SP) | IMM(compiler->local_size)));
|
||||
else {
|
||||
FAIL_IF(load_immediate(compiler, 0, compiler->local_size));
|
||||
FAIL_IF(push_inst(compiler, ADD | D(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | B(0)));
|
||||
FAIL_IF(push_inst(compiler, ADD | D(SLJIT_SP) | A(SLJIT_SP) | B(0)));
|
||||
}
|
||||
|
||||
#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_LOCALS_REG) | IMM(2 * sizeof(sljit_sw))));
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_LOCALS_REG) | IMM(sizeof(sljit_sw))));
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
|
||||
#endif
|
||||
if (compiler->saveds >= 5)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG2) | A(SLJIT_LOCALS_REG) | IMM(-6 * (sljit_si)(sizeof(sljit_sw))) ));
|
||||
if (compiler->saveds >= 4)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG1) | A(SLJIT_LOCALS_REG) | IMM(-5 * (sljit_si)(sizeof(sljit_sw))) ));
|
||||
if (compiler->saveds >= 3)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG3) | A(SLJIT_LOCALS_REG) | IMM(-4 * (sljit_si)(sizeof(sljit_sw))) ));
|
||||
if (compiler->saveds >= 2)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG2) | A(SLJIT_LOCALS_REG) | IMM(-3 * (sljit_si)(sizeof(sljit_sw))) ));
|
||||
if (compiler->saveds >= 1)
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG1) | A(SLJIT_LOCALS_REG) | IMM(-2 * (sljit_si)(sizeof(sljit_sw))) ));
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(TMP_ZERO) | A(SLJIT_LOCALS_REG) | IMM(-(sljit_si)(sizeof(sljit_sw))) ));
|
||||
|
||||
offs = -(sljit_si)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
|
||||
|
||||
tmp = compiler->scratches;
|
||||
for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
|
||||
offs += (sljit_si)(sizeof(sljit_sw));
|
||||
}
|
||||
|
||||
tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = tmp; i <= SLJIT_S0; i++) {
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
|
||||
offs += (sljit_si)(sizeof(sljit_sw));
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | D(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
|
||||
SLJIT_ASSERT(offs == -(sljit_sw)(sizeof(sljit_sw)));
|
||||
|
||||
FAIL_IF(push_inst(compiler, MTLR | S(0)));
|
||||
FAIL_IF(push_inst(compiler, BLR));
|
||||
@ -731,7 +755,7 @@ static SLJIT_CONST sljit_ins data_transfer_insts[64 + 8] = {
|
||||
|
||||
/* Byte. */
|
||||
|
||||
/* u b n i s */ HI(38) /* stb */,
|
||||
/* u b n i s */ HI(38) /* stb */,
|
||||
/* u b n i l */ HI(34) /* lbz */,
|
||||
/* u b n x s */ HI(31) | LO(215) /* stbx */,
|
||||
/* u b n x l */ HI(31) | LO(87) /* lbzx */,
|
||||
@ -999,12 +1023,12 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
||||
tmp_r = arg;
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(arg) | A(arg) | IMM(high_short >> 16)));
|
||||
}
|
||||
else if (compiler->cache_arg != arg || high_short != compiler->cache_argw) {
|
||||
else if (compiler->cache_arg != (SLJIT_MEM | arg) || high_short != compiler->cache_argw) {
|
||||
if ((next_arg & SLJIT_MEM) && !(next_arg & OFFS_REG_MASK)) {
|
||||
next_high_short = (sljit_si)(next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff;
|
||||
if (high_short == next_high_short) {
|
||||
compiler->cache_arg = SLJIT_IMM | arg;
|
||||
compiler->cache_argw = next_high_short;
|
||||
compiler->cache_arg = SLJIT_MEM | arg;
|
||||
compiler->cache_argw = high_short;
|
||||
tmp_r = TMP_REG3;
|
||||
}
|
||||
}
|
||||
@ -1250,30 +1274,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
return push_inst(compiler, NOP);
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG1)));
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
|
||||
return push_inst(compiler, (op == SLJIT_UMUL ? MULHDU : MULHD) | D(SLJIT_SCRATCH_REG2) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2));
|
||||
FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
|
||||
return push_inst(compiler, (op == SLJIT_UMUL ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
|
||||
return push_inst(compiler, (op == SLJIT_UMUL ? MULHWU : MULHW) | D(SLJIT_SCRATCH_REG2) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2));
|
||||
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
|
||||
return push_inst(compiler, (op == SLJIT_UMUL ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
|
||||
#endif
|
||||
case SLJIT_UDIV:
|
||||
case SLJIT_SDIV:
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG1)));
|
||||
FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
if (int_op) {
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG1) | B(SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
|
||||
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
|
||||
} else {
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVDU : DIVD) | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG1) | B(SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVDU : DIVD) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
|
||||
FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
|
||||
}
|
||||
return push_inst(compiler, SUBF | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG2) | B(TMP_REG1));
|
||||
return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG1) | B(SLJIT_SCRATCH_REG2)));
|
||||
return push_inst(compiler, SUBF | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG2) | B(TMP_REG1));
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
|
||||
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
|
||||
return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1685,59 +1709,233 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
|
||||
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 6))
|
||||
#define SELECT_FOP(op, single, double) ((op & SLJIT_SINGLE_OP) ? single : double)
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw))
|
||||
#else
|
||||
#define FLOAT_TMP_MEM_OFFSET (2 * sizeof(sljit_sw))
|
||||
|
||||
#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
|
||||
#define FLOAT_TMP_MEM_OFFSET_LOW (2 * sizeof(sljit_sw))
|
||||
#define FLOAT_TMP_MEM_OFFSET_HI (3 * sizeof(sljit_sw))
|
||||
#else
|
||||
#define FLOAT_TMP_MEM_OFFSET_LOW (3 * sizeof(sljit_sw))
|
||||
#define FLOAT_TMP_MEM_OFFSET_HI (2 * sizeof(sljit_sw))
|
||||
#endif
|
||||
|
||||
#endif /* SLJIT_CONFIG_PPC_64 */
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
if (src & SLJIT_MEM) {
|
||||
/* We can ignore the temporary data store on the stack from caching point of view. */
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
|
||||
src = TMP_FREG1;
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
op = GET_OPCODE(op);
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_CONVI_FROMD ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
|
||||
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (op == SLJIT_CONVW_FROMD) {
|
||||
if (FAST_IS_REG(dst)) {
|
||||
FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0));
|
||||
return emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0);
|
||||
}
|
||||
return emit_op_mem2(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, 0, 0);
|
||||
}
|
||||
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
|
||||
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
#endif
|
||||
|
||||
if (FAST_IS_REG(dst)) {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, FLOAT_TMP_MEM_OFFSET));
|
||||
FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));
|
||||
return emit_op_mem2(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0);
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(dst & SLJIT_MEM);
|
||||
|
||||
if (dst & OFFS_REG_MASK) {
|
||||
dstw &= 0x3;
|
||||
if (dstw) {
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | (dstw << 11) | ((31 - dstw) << 1)));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1)));
|
||||
#endif
|
||||
dstw = TMP_REG1;
|
||||
}
|
||||
else
|
||||
dstw = OFFS_REG(dst);
|
||||
}
|
||||
else {
|
||||
if ((dst & REG_MASK) && !dstw) {
|
||||
dstw = dst & REG_MASK;
|
||||
dst = 0;
|
||||
}
|
||||
else {
|
||||
/* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));
|
||||
dstw = TMP_REG1;
|
||||
}
|
||||
}
|
||||
|
||||
return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
|
||||
sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (src & SLJIT_IMM) {
|
||||
if (GET_OPCODE(op) == SLJIT_CONVD_FROMI)
|
||||
srcw = (sljit_si)srcw;
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
else if (GET_OPCODE(op) == SLJIT_CONVD_FROMI) {
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));
|
||||
else
|
||||
FAIL_IF(emit_op_mem2(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
if (FAST_IS_REG(src)) {
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
|
||||
FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, dst, dstw));
|
||||
}
|
||||
else
|
||||
FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
|
||||
|
||||
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
|
||||
if (op & SLJIT_SINGLE_OP)
|
||||
return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#else
|
||||
|
||||
sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
sljit_si invert_sign = 1;
|
||||
|
||||
if (src & SLJIT_IMM) {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ 0x80000000));
|
||||
src = TMP_REG1;
|
||||
invert_sign = 0;
|
||||
}
|
||||
else if (!FAST_IS_REG(src)) {
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
/* First, a special double floating point value is constructed: (2^53 + (input xor (2^31)))
|
||||
The double precision format has exactly 53 bit precision, so the lower 32 bit represents
|
||||
the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000
|
||||
to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating
|
||||
point value, we need to substract 2^53 + 2^31 from the constructed value. */
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
|
||||
if (invert_sign)
|
||||
FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI));
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));
|
||||
FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW));
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
|
||||
FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW));
|
||||
|
||||
FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
|
||||
if (op & SLJIT_SINGLE_OP)
|
||||
return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
if (src1 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
|
||||
src1 = TMP_FREG1;
|
||||
}
|
||||
|
||||
if (src2 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
|
||||
src2 = TMP_FREG2;
|
||||
}
|
||||
|
||||
return push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_fr;
|
||||
sljit_si dst_r;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CMPD) {
|
||||
if (dst & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, dst, dstw, src, srcw));
|
||||
dst = TMP_FREG1;
|
||||
}
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
|
||||
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src, srcw, 0, 0));
|
||||
src = TMP_FREG2;
|
||||
}
|
||||
if (GET_OPCODE(op) == SLJIT_CONVD_FROMS)
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
|
||||
return push_inst(compiler, FCMPU | CRD(4) | FA(dst) | FB(src));
|
||||
}
|
||||
|
||||
dst_fr = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_fr, src, srcw, dst, dstw));
|
||||
src = dst_fr;
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));
|
||||
src = dst_r;
|
||||
}
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOVD:
|
||||
if (src != dst_fr && dst_fr != TMP_FREG1)
|
||||
FAIL_IF(push_inst(compiler, FMR | FD(dst_fr) | FB(src)));
|
||||
break;
|
||||
case SLJIT_NEGD:
|
||||
FAIL_IF(push_inst(compiler, FNEG | FD(dst_fr) | FB(src)));
|
||||
break;
|
||||
case SLJIT_ABSD:
|
||||
FAIL_IF(push_inst(compiler, FABS | FD(dst_fr) | FB(src)));
|
||||
case SLJIT_CONVD_FROMS:
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
if (op & SLJIT_SINGLE_OP) {
|
||||
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
case SLJIT_MOVD:
|
||||
if (src != dst_r) {
|
||||
if (dst_r != TMP_FREG1)
|
||||
FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));
|
||||
else
|
||||
dst_r = src;
|
||||
}
|
||||
break;
|
||||
case SLJIT_NEGD:
|
||||
FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));
|
||||
break;
|
||||
case SLJIT_ABSD:
|
||||
FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst_fr == TMP_FREG1) {
|
||||
if (GET_OPCODE(op) == SLJIT_MOVD)
|
||||
dst_fr = src;
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_fr, dst, dstw, 0, 0));
|
||||
}
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1746,15 +1944,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
sljit_si dst_fr, flags = 0;
|
||||
sljit_si dst_r, flags = 0;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
ADJUST_LOCAL_OFFSET(src1, src1w);
|
||||
ADJUST_LOCAL_OFFSET(src2, src2w);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
dst_fr = FAST_IS_REG(dst) ? dst : TMP_FREG2;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
|
||||
|
||||
if (src1 & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
|
||||
@ -1794,23 +1995,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_ADDD:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_fr) | FA(src1) | FB(src2)));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));
|
||||
break;
|
||||
|
||||
case SLJIT_SUBD:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_fr) | FA(src1) | FB(src2)));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));
|
||||
break;
|
||||
|
||||
case SLJIT_MULD:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_fr) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
|
||||
break;
|
||||
|
||||
case SLJIT_DIVD:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_fr) | FA(src1) | FB(src2)));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst_fr == TMP_FREG2)
|
||||
if (dst_r == TMP_FREG2)
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
|
@ -110,8 +110,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
if (!(flags & SET_FLAGS))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(dst) | IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, RDY | D(TMP_REG4), DR(TMP_REG4)));
|
||||
return push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(TMP_REG4), MOVABLE_INS | SET_FLAGS);
|
||||
FAIL_IF(push_inst(compiler, RDY | D(TMP_LINK), DR(TMP_LINK)));
|
||||
return push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(TMP_LINK), MOVABLE_INS | SET_FLAGS);
|
||||
|
||||
case SLJIT_AND:
|
||||
return push_inst(compiler, AND | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
@ -83,17 +83,16 @@ static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
|
||||
}
|
||||
|
||||
/* TMP_REG2 is not used by getput_arg */
|
||||
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
|
||||
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
|
||||
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
|
||||
#define TMP_REG4 (SLJIT_NO_REGISTERS + 4)
|
||||
#define TMP_LINK (SLJIT_NO_REGISTERS + 5)
|
||||
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
|
||||
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
|
||||
#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
|
||||
#define TMP_LINK (SLJIT_NUMBER_OF_REGISTERS + 5)
|
||||
|
||||
#define TMP_FREG1 (0)
|
||||
#define TMP_FREG2 ((SLJIT_FLOAT_REG6 + 1) << 1)
|
||||
#define TMP_FREG2 ((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) << 1)
|
||||
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 7] = {
|
||||
0, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 14, 1, 24, 25, 26, 15
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
|
||||
0, 8, 9, 10, 13, 29, 28, 27, 23, 22, 21, 20, 19, 18, 17, 16, 26, 25, 24, 14, 1, 11, 12, 15
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -128,10 +127,16 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 7] = {
|
||||
#define FCMPS (OPC1(0x2) | OPC3(0x35) | DOP(0x51))
|
||||
#define FDIVD (OPC1(0x2) | OPC3(0x34) | DOP(0x4e))
|
||||
#define FDIVS (OPC1(0x2) | OPC3(0x34) | DOP(0x4d))
|
||||
#define FDTOI (OPC1(0x2) | OPC3(0x34) | DOP(0xd2))
|
||||
#define FDTOS (OPC1(0x2) | OPC3(0x34) | DOP(0xc6))
|
||||
#define FITOD (OPC1(0x2) | OPC3(0x34) | DOP(0xc8))
|
||||
#define FITOS (OPC1(0x2) | OPC3(0x34) | DOP(0xc4))
|
||||
#define FMOVS (OPC1(0x2) | OPC3(0x34) | DOP(0x01))
|
||||
#define FMULD (OPC1(0x2) | OPC3(0x34) | DOP(0x4a))
|
||||
#define FMULS (OPC1(0x2) | OPC3(0x34) | DOP(0x49))
|
||||
#define FNEGS (OPC1(0x2) | OPC3(0x34) | DOP(0x05))
|
||||
#define FSTOD (OPC1(0x2) | OPC3(0x34) | DOP(0xc9))
|
||||
#define FSTOI (OPC1(0x2) | OPC3(0x34) | DOP(0xd1))
|
||||
#define FSUBD (OPC1(0x2) | OPC3(0x34) | DOP(0x46))
|
||||
#define FSUBS (OPC1(0x2) | OPC3(0x34) | DOP(0x45))
|
||||
#define JMPL (OPC1(0x2) | OPC3(0x38))
|
||||
@ -388,6 +393,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||
/* Separates integer and floating point registers */
|
||||
#define GPR_REG 0x0f
|
||||
#define DOUBLE_DATA 0x10
|
||||
#define SINGLE_DATA 0x12
|
||||
|
||||
#define MEM_MASK 0x1f
|
||||
|
||||
@ -412,52 +418,55 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||
#include "sljitNativeSPARC_64.c"
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
local_size += 23 * sizeof(sljit_sw);
|
||||
local_size = (local_size + 7) & ~0x7;
|
||||
local_size = (local_size + FIXED_LOCALS_OFFSET + 7) & ~0x7;
|
||||
compiler->local_size = local_size;
|
||||
|
||||
if (local_size <= SIMM_MAX) {
|
||||
FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_LOCALS_REG) | S1(SLJIT_LOCALS_REG) | IMM(-local_size), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_SP) | S1(SLJIT_SP) | IMM(-local_size), UNMOVABLE_INS));
|
||||
}
|
||||
else {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, -local_size));
|
||||
FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_LOCALS_REG) | S1(SLJIT_LOCALS_REG) | S2(TMP_REG1), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_SP) | S1(SLJIT_SP) | S2(TMP_REG1), UNMOVABLE_INS));
|
||||
}
|
||||
|
||||
if (args >= 1)
|
||||
FAIL_IF(push_inst(compiler, OR | D(SLJIT_SAVED_REG1) | S1(0) | S2A(24), DR(SLJIT_SAVED_REG1)));
|
||||
if (args >= 2)
|
||||
FAIL_IF(push_inst(compiler, OR | D(SLJIT_SAVED_REG2) | S1(0) | S2A(25), DR(SLJIT_SAVED_REG2)));
|
||||
if (args >= 3)
|
||||
FAIL_IF(push_inst(compiler, OR | D(SLJIT_SAVED_REG3) | S1(0) | S2A(26), DR(SLJIT_SAVED_REG3)));
|
||||
/* Arguments are in their appropriate registers. */
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
local_size += 23 * sizeof(sljit_sw);
|
||||
compiler->local_size = (local_size + 7) & ~0x7;
|
||||
compiler->local_size = (local_size + FIXED_LOCALS_OFFSET + 7) & ~0x7;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
@ -467,11 +476,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
||||
|
||||
if (op != SLJIT_MOV || !FAST_IS_REG(src)) {
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
src = SLJIT_SCRATCH_REG1;
|
||||
src = SLJIT_R0;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, JMPL | D(0) | S1A(31) | IMM(8), UNMOVABLE_INS));
|
||||
return push_inst(compiler, RESTORE | D(SLJIT_SCRATCH_REG1) | S1(src) | S2(0), UNMOVABLE_INS);
|
||||
return push_inst(compiler, RESTORE | D(SLJIT_R0) | S1(src) | S2(0), UNMOVABLE_INS);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -778,8 +787,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? UMUL : SMUL) | D(SLJIT_SCRATCH_REG1) | S1(SLJIT_SCRATCH_REG1) | S2(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG1)));
|
||||
return push_inst(compiler, RDY | D(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2));
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? UMUL : SMUL) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
|
||||
return push_inst(compiler, RDY | D(SLJIT_R1), DR(SLJIT_R1));
|
||||
#else
|
||||
#error "Implementation required"
|
||||
#endif
|
||||
@ -789,13 +798,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
if (op == SLJIT_UDIV)
|
||||
FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS));
|
||||
else {
|
||||
FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_SCRATCH_REG1) | IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_R0) | IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, WRY | S1(TMP_REG1), MOVABLE_INS));
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_SCRATCH_REG1), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? UDIV : SDIV) | D(SLJIT_SCRATCH_REG1) | S1(SLJIT_SCRATCH_REG1) | S2(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG1)));
|
||||
FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_SCRATCH_REG2) | S1(SLJIT_SCRATCH_REG1) | S2(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst(compiler, SUB | D(SLJIT_SCRATCH_REG2) | S1(TMP_REG2) | S2(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2)));
|
||||
FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
|
||||
FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_R1) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R1)));
|
||||
FAIL_IF(push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1)));
|
||||
return SLJIT_SUCCESS;
|
||||
#else
|
||||
#error "Implementation required"
|
||||
@ -953,73 +962,139 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
|
||||
|
||||
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 7))
|
||||
#define SELECT_FOP(op, single, double) ((op & SLJIT_SINGLE_OP) ? single : double)
|
||||
#define FLOAT_TMP_MEM_OFFSET (22 * sizeof(sljit_sw))
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
|
||||
src = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
src <<= 1;
|
||||
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOI, FDTOI) | DA(TMP_FREG1) | S2A(src), MOVABLE_INS));
|
||||
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (FAST_IS_REG(dst)) {
|
||||
FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
|
||||
return emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET);
|
||||
}
|
||||
|
||||
/* Store the integer value from a VFP register. */
|
||||
return emit_op_mem2(compiler, SINGLE_DATA, TMP_FREG1, dst, dstw, 0, 0);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
|
||||
if (src & SLJIT_IMM) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (GET_OPCODE(op) == SLJIT_CONVD_FROMI)
|
||||
srcw = (sljit_si)srcw;
|
||||
#endif
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
||||
src = TMP_REG1;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
if (FAST_IS_REG(src)) {
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
|
||||
src = SLJIT_MEM1(SLJIT_SP);
|
||||
srcw = FLOAT_TMP_MEM_OFFSET;
|
||||
}
|
||||
|
||||
FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FITOS, FITOD) | DA(dst_r) | S2A(TMP_FREG1), MOVABLE_INS));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
if (src1 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
|
||||
src1 = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
src1 <<= 1;
|
||||
|
||||
if (src2 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
|
||||
src2 = TMP_FREG2;
|
||||
}
|
||||
else
|
||||
src2 <<= 1;
|
||||
|
||||
return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | S1A(src1) | S2A(src2), FCC_IS_SET | MOVABLE_INS);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_fr;
|
||||
sljit_si dst_r;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CMPD) {
|
||||
if (dst & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, dst, dstw, src, srcw));
|
||||
dst = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
dst <<= 1;
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
|
||||
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src, srcw, 0, 0));
|
||||
src = TMP_FREG2;
|
||||
}
|
||||
else
|
||||
src <<= 1;
|
||||
if (GET_OPCODE(op) == SLJIT_CONVD_FROMS)
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
|
||||
return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | S1A(dst) | S2A(src), FCC_IS_SET | MOVABLE_INS);
|
||||
}
|
||||
|
||||
dst_fr = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_fr, src, srcw, dst, dstw));
|
||||
src = dst_fr;
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));
|
||||
src = dst_r;
|
||||
}
|
||||
else
|
||||
src <<= 1;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOVD:
|
||||
if (src != dst_fr && dst_fr != TMP_FREG1) {
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_fr) | S2A(src), MOVABLE_INS));
|
||||
case SLJIT_MOVD:
|
||||
if (src != dst_r) {
|
||||
if (dst_r != TMP_FREG1) {
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r) | S2A(src), MOVABLE_INS));
|
||||
if (!(op & SLJIT_SINGLE_OP))
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_fr | 1) | S2A(src | 1), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS));
|
||||
}
|
||||
break;
|
||||
case SLJIT_NEGD:
|
||||
FAIL_IF(push_inst(compiler, FNEGS | DA(dst_fr) | S2A(src), MOVABLE_INS));
|
||||
if (dst_fr != src && !(op & SLJIT_SINGLE_OP))
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_fr | 1) | S2A(src | 1), MOVABLE_INS));
|
||||
break;
|
||||
case SLJIT_ABSD:
|
||||
FAIL_IF(push_inst(compiler, FABSS | DA(dst_fr) | S2A(src), MOVABLE_INS));
|
||||
if (dst_fr != src && !(op & SLJIT_SINGLE_OP))
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_fr | 1) | S2A(src | 1), MOVABLE_INS));
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst_fr == TMP_FREG1) {
|
||||
if (GET_OPCODE(op) == SLJIT_MOVD)
|
||||
dst_fr = src;
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_fr, dst, dstw, 0, 0));
|
||||
else
|
||||
dst_r = src;
|
||||
}
|
||||
break;
|
||||
case SLJIT_NEGD:
|
||||
FAIL_IF(push_inst(compiler, FNEGS | DA(dst_r) | S2A(src), MOVABLE_INS));
|
||||
if (dst_r != src && !(op & SLJIT_SINGLE_OP))
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS));
|
||||
break;
|
||||
case SLJIT_ABSD:
|
||||
FAIL_IF(push_inst(compiler, FABSS | DA(dst_r) | S2A(src), MOVABLE_INS));
|
||||
if (dst_r != src && !(op & SLJIT_SINGLE_OP))
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS));
|
||||
break;
|
||||
case SLJIT_CONVD_FROMS:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOD, FDTOS) | DA(dst_r) | S2A(src), MOVABLE_INS));
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1028,15 +1103,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
sljit_si dst_fr, flags = 0;
|
||||
sljit_si dst_r, flags = 0;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
ADJUST_LOCAL_OFFSET(src1, src1w);
|
||||
ADJUST_LOCAL_OFFSET(src2, src2w);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
dst_fr = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG2;
|
||||
dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG2;
|
||||
|
||||
if (src1 & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
|
||||
@ -1080,23 +1158,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_ADDD:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | DA(dst_fr) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
break;
|
||||
|
||||
case SLJIT_SUBD:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | DA(dst_fr) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
break;
|
||||
|
||||
case SLJIT_MULD:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | DA(dst_fr) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
break;
|
||||
|
||||
case SLJIT_DIVD:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | DA(dst_fr) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst_fr == TMP_FREG2)
|
||||
if (dst_r == TMP_FREG2)
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
|
@ -120,7 +120,7 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char *sljit_get_platform_name(void)
|
||||
typedef sljit_uw sljit_ins;
|
||||
|
||||
struct jit_instr {
|
||||
const struct tilegx_opcode* opcode;
|
||||
const struct tilegx_opcode* opcode;
|
||||
tilegx_pipeline pipe;
|
||||
unsigned long input_registers;
|
||||
unsigned long output_registers;
|
||||
@ -896,7 +896,7 @@ static sljit_si push_jr_buffer(struct sljit_compiler *compiler, tilegx_mnemonic
|
||||
inst_buf[inst_buf_index].output_registers = 0;
|
||||
inst_buf[inst_buf_index].line = line;
|
||||
inst_buf_index++;
|
||||
|
||||
|
||||
return flush_buffer(compiler);
|
||||
}
|
||||
|
||||
@ -1173,16 +1173,21 @@ static sljit_si emit_const_64(struct sljit_compiler *compiler, sljit_si dst_ar,
|
||||
return SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_ins base;
|
||||
sljit_ins bundle = 0;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
@ -1233,13 +1238,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
@ -1817,7 +1827,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
else {
|
||||
/* Rare ocasion. */
|
||||
FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));
|
||||
|
||||
|
||||
overflow_ra = TMP_EREG2;
|
||||
}
|
||||
}
|
||||
@ -1843,7 +1853,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
||||
if (src1 != dst)
|
||||
overflow_ra = reg_map[src1];
|
||||
else {
|
||||
/* Rare occasion. */
|
||||
/* Rare ocasion. */
|
||||
FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));
|
||||
overflow_ra = TMP_EREG2;
|
||||
}
|
||||
@ -2370,7 +2380,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
|
||||
FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
|
||||
}
|
||||
|
||||
FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_SCRATCH_REG1], ZERO));
|
||||
FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_R0], ZERO));
|
||||
|
||||
FAIL_IF(ADDI_SOLO(54, 54, -16));
|
||||
|
||||
@ -2381,7 +2391,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
|
||||
|
||||
/* Register input. */
|
||||
if (type >= SLJIT_CALL1)
|
||||
FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_SCRATCH_REG1], ZERO));
|
||||
FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_R0], ZERO));
|
||||
|
||||
FAIL_IF(ADD_SOLO(reg_map[PIC_ADDR_REG], reg_map[src_r], ZERO));
|
||||
|
||||
@ -2511,7 +2521,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil
|
||||
SLJIT_ASSERT(reg_map[PIC_ADDR_REG] == 16 && PIC_ADDR_REG == TMP_REG2);
|
||||
/* Cannot be optimized out if type is >= CALL0. */
|
||||
jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? SLJIT_REWRITABLE_JUMP : 0);
|
||||
PTR_FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_SCRATCH_REG1], ZERO));
|
||||
PTR_FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_R0], ZERO));
|
||||
jump->addr = compiler->size;
|
||||
PTR_FAIL_IF(JALR_SOLO(TMP_REG2_mapped));
|
||||
}
|
||||
|
@ -63,27 +63,32 @@ static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_si size;
|
||||
sljit_si locals_offset;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
compiler->args = args;
|
||||
compiler->flags_saved = 0;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
size = 1 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
|
||||
size += (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
|
||||
#else
|
||||
size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (2 + args * 3) : 0);
|
||||
size += (args > 0 ? (2 + args * 3) : 0);
|
||||
#endif
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
@ -96,76 +101,66 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
||||
*inst++ = MOD_REG | (reg_map[TMP_REG1] << 3) | 0x4 /* esp */;
|
||||
}
|
||||
#endif
|
||||
if (saveds > 2)
|
||||
PUSH_REG(reg_map[SLJIT_SAVED_REG3]);
|
||||
if (saveds > 1)
|
||||
PUSH_REG(reg_map[SLJIT_SAVED_REG2]);
|
||||
if (saveds > 0)
|
||||
PUSH_REG(reg_map[SLJIT_SAVED_REG1]);
|
||||
if (saveds > 2 || scratches > 7)
|
||||
PUSH_REG(reg_map[SLJIT_S2]);
|
||||
if (saveds > 1 || scratches > 8)
|
||||
PUSH_REG(reg_map[SLJIT_S1]);
|
||||
if (saveds > 0 || scratches > 9)
|
||||
PUSH_REG(reg_map[SLJIT_S0]);
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (args > 0) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[SLJIT_SCRATCH_REG3];
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_S0] << 3) | reg_map[SLJIT_R2];
|
||||
}
|
||||
if (args > 1) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[SLJIT_SCRATCH_REG2];
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_S1] << 3) | reg_map[SLJIT_R1];
|
||||
}
|
||||
if (args > 2) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x4 /* esp */;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | 0x4 /* esp */;
|
||||
*inst++ = 0x24;
|
||||
*inst++ = sizeof(sljit_sw) * (3 + 2); /* saveds >= 3 as well. */
|
||||
}
|
||||
#else
|
||||
if (args > 0) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REG1];
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_S0] << 3) | reg_map[TMP_REG1];
|
||||
*inst++ = sizeof(sljit_sw) * 2;
|
||||
}
|
||||
if (args > 1) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REG1];
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_S1] << 3) | reg_map[TMP_REG1];
|
||||
*inst++ = sizeof(sljit_sw) * 3;
|
||||
}
|
||||
if (args > 2) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REG1];
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | reg_map[TMP_REG1];
|
||||
*inst++ = sizeof(sljit_sw) * 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
locals_offset = 2 * sizeof(sljit_uw);
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(FIXED_LOCALS_OFFSET >= 2 * sizeof(sljit_uw), require_at_least_two_words);
|
||||
locals_offset = FIXED_LOCALS_OFFSET;
|
||||
#endif
|
||||
compiler->scratches_start = locals_offset;
|
||||
if (scratches > 3)
|
||||
locals_offset += (scratches - 3) * sizeof(sljit_uw);
|
||||
compiler->saveds_start = locals_offset;
|
||||
if (saveds > 3)
|
||||
locals_offset += (saveds - 3) * sizeof(sljit_uw);
|
||||
compiler->locals_offset = locals_offset;
|
||||
SLJIT_COMPILE_ASSERT(FIXED_LOCALS_OFFSET >= (2 + 4) * sizeof(sljit_uw), require_at_least_two_words);
|
||||
#if defined(__APPLE__)
|
||||
saveds = (2 + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
|
||||
local_size = ((locals_offset + saveds + local_size + 15) & ~15) - saveds;
|
||||
/* Ignore pushed registers and FIXED_LOCALS_OFFSET when
|
||||
computing the aligned local size. */
|
||||
saveds = (2 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
|
||||
local_size = ((FIXED_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;
|
||||
#else
|
||||
local_size = locals_offset + ((local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1));
|
||||
local_size = FIXED_LOCALS_OFFSET + ((local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1));
|
||||
#endif
|
||||
|
||||
compiler->local_size = local_size;
|
||||
#ifdef _WIN32
|
||||
if (local_size > 1024) {
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_SCRATCH_REG1], local_size));
|
||||
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size));
|
||||
#else
|
||||
local_size -= FIXED_LOCALS_OFFSET;
|
||||
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_SCRATCH_REG1], local_size));
|
||||
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size));
|
||||
FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
|
||||
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, FIXED_LOCALS_OFFSET));
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, FIXED_LOCALS_OFFSET));
|
||||
#endif
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
|
||||
}
|
||||
@ -173,40 +168,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
||||
|
||||
SLJIT_ASSERT(local_size > 0);
|
||||
return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
|
||||
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size);
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_si locals_offset;
|
||||
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
compiler->args = args;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
locals_offset = 2 * sizeof(sljit_uw);
|
||||
#else
|
||||
locals_offset = FIXED_LOCALS_OFFSET;
|
||||
#endif
|
||||
compiler->scratches_start = locals_offset;
|
||||
if (scratches > 3)
|
||||
locals_offset += (scratches - 3) * sizeof(sljit_uw);
|
||||
compiler->saveds_start = locals_offset;
|
||||
if (saveds > 3)
|
||||
locals_offset += (saveds - 3) * sizeof(sljit_uw);
|
||||
compiler->locals_offset = locals_offset;
|
||||
#if defined(__APPLE__)
|
||||
saveds = (2 + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
|
||||
compiler->local_size = ((locals_offset + saveds + local_size + 15) & ~15) - saveds;
|
||||
saveds = (2 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
|
||||
compiler->local_size = ((FIXED_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;
|
||||
#else
|
||||
compiler->local_size = locals_offset + ((local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1));
|
||||
compiler->local_size = FIXED_LOCALS_OFFSET + ((local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -224,9 +210,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
||||
|
||||
SLJIT_ASSERT(compiler->local_size > 0);
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size));
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
|
||||
|
||||
size = 2 + (compiler->saveds <= 3 ? compiler->saveds : 3);
|
||||
size = 2 + (compiler->scratches > 7 ? (compiler->scratches - 7) : 0) +
|
||||
(compiler->saveds <= 3 ? compiler->saveds : 3);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (compiler->args > 2)
|
||||
size += 2;
|
||||
@ -239,12 +226,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
||||
|
||||
INC_SIZE(size);
|
||||
|
||||
if (compiler->saveds > 0)
|
||||
POP_REG(reg_map[SLJIT_SAVED_REG1]);
|
||||
if (compiler->saveds > 1)
|
||||
POP_REG(reg_map[SLJIT_SAVED_REG2]);
|
||||
if (compiler->saveds > 2)
|
||||
POP_REG(reg_map[SLJIT_SAVED_REG3]);
|
||||
if (compiler->saveds > 0 || compiler->scratches > 9)
|
||||
POP_REG(reg_map[SLJIT_S0]);
|
||||
if (compiler->saveds > 1 || compiler->scratches > 8)
|
||||
POP_REG(reg_map[SLJIT_S1]);
|
||||
if (compiler->saveds > 2 || compiler->scratches > 7)
|
||||
POP_REG(reg_map[SLJIT_S2]);
|
||||
POP_REG(reg_map[TMP_REG1]);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (compiler->args > 2)
|
||||
@ -280,21 +267,17 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
||||
SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
|
||||
/* Both size flags cannot be switched on. */
|
||||
SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
/* SSE2 and immediate is not possible. */
|
||||
SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
|
||||
SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
|
||||
&& (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
|
||||
&& (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
|
||||
#endif
|
||||
|
||||
size &= 0xf;
|
||||
inst_size = size;
|
||||
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
|
||||
inst_size++;
|
||||
#endif
|
||||
if (flags & EX86_PREF_66)
|
||||
inst_size++;
|
||||
|
||||
@ -311,8 +294,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
||||
inst_size += sizeof(sljit_sw);
|
||||
}
|
||||
|
||||
if ((b & REG_MASK) == SLJIT_LOCALS_REG && !(b & OFFS_REG_MASK))
|
||||
b |= TO_OFFS_REG(SLJIT_LOCALS_REG);
|
||||
if ((b & REG_MASK) == SLJIT_SP && !(b & OFFS_REG_MASK))
|
||||
b |= TO_OFFS_REG(SLJIT_SP);
|
||||
|
||||
if ((b & OFFS_REG_MASK) != SLJIT_UNUSED)
|
||||
inst_size += 1; /* SIB byte. */
|
||||
@ -348,12 +331,10 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
||||
|
||||
/* Encoding the byte. */
|
||||
INC_SIZE(inst_size);
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (flags & EX86_PREF_F2)
|
||||
*inst++ = 0xf2;
|
||||
if (flags & EX86_PREF_F3)
|
||||
*inst++ = 0xf3;
|
||||
#endif
|
||||
if (flags & EX86_PREF_66)
|
||||
*inst++ = 0x66;
|
||||
|
||||
@ -366,15 +347,10 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
||||
|
||||
if ((a & SLJIT_IMM) || (a == 0))
|
||||
*buf_ptr = 0;
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
else if (!(flags & EX86_SSE2))
|
||||
else if (!(flags & EX86_SSE2_OP1))
|
||||
*buf_ptr = reg_map[a] << 3;
|
||||
else
|
||||
*buf_ptr = a << 3;
|
||||
#else
|
||||
else
|
||||
*buf_ptr = reg_map[a] << 3;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if (a & SLJIT_IMM) {
|
||||
@ -388,13 +364,9 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
||||
}
|
||||
|
||||
if (!(b & SLJIT_MEM))
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
*buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2)) ? reg_map[b] : b);
|
||||
#else
|
||||
*buf_ptr++ |= MOD_REG + reg_map[b];
|
||||
#endif
|
||||
*buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_map[b] : b);
|
||||
else if ((b & REG_MASK) != SLJIT_UNUSED) {
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_LOCALS_REG)) {
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {
|
||||
if (immb != 0) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr |= 0x40;
|
||||
@ -455,28 +427,28 @@ static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, slj
|
||||
INC_SIZE(type >= SLJIT_CALL3 ? 2 + 1 : 2);
|
||||
|
||||
if (type >= SLJIT_CALL3)
|
||||
PUSH_REG(reg_map[SLJIT_SCRATCH_REG3]);
|
||||
PUSH_REG(reg_map[SLJIT_R2]);
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SCRATCH_REG3] << 3) | reg_map[SLJIT_SCRATCH_REG1];
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0];
|
||||
#else
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 * (type - SLJIT_CALL0));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4 * (type - SLJIT_CALL0));
|
||||
|
||||
*inst++ = MOV_rm_r;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SCRATCH_REG1] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_LOCALS_REG];
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_R0] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_SP];
|
||||
*inst++ = 0;
|
||||
if (type >= SLJIT_CALL2) {
|
||||
*inst++ = MOV_rm_r;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SCRATCH_REG2] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_LOCALS_REG];
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_R1] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_SP];
|
||||
*inst++ = sizeof(sljit_sw);
|
||||
}
|
||||
if (type >= SLJIT_CALL3) {
|
||||
*inst++ = MOV_rm_r;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SCRATCH_REG3] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_LOCALS_REG];
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_R2] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_SP];
|
||||
*inst++ = 2 * sizeof(sljit_sw);
|
||||
}
|
||||
#endif
|
||||
|
@ -87,118 +87,95 @@ static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_si size, pushed_size;
|
||||
sljit_si i, tmp, size, saved_register_size;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
compiler->flags_saved = 0;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
size = saveds;
|
||||
/* Including the return address saved by the call instruction. */
|
||||
pushed_size = (saveds + 1) * sizeof(sljit_sw);
|
||||
#ifndef _WIN64
|
||||
if (saveds >= 2)
|
||||
size += saveds - 1;
|
||||
#else
|
||||
if (saveds >= 4)
|
||||
size += saveds - 3;
|
||||
if (scratches >= 5) {
|
||||
size += (5 - 4) * 2;
|
||||
pushed_size += sizeof(sljit_sw);
|
||||
saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
|
||||
|
||||
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = SLJIT_S0; i >= tmp; i--) {
|
||||
size = reg_map[i] >= 8 ? 2 : 1;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(size);
|
||||
if (reg_map[i] >= 8)
|
||||
*inst++ = REX_B;
|
||||
PUSH_REG(reg_lmap[i]);
|
||||
}
|
||||
#endif
|
||||
size += args * 3;
|
||||
if (size > 0) {
|
||||
|
||||
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
|
||||
size = reg_map[i] >= 8 ? 2 : 1;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(size);
|
||||
if (reg_map[i] >= 8)
|
||||
*inst++ = REX_B;
|
||||
PUSH_REG(reg_lmap[i]);
|
||||
}
|
||||
|
||||
if (args > 0) {
|
||||
size = args * 3;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
if (saveds >= 5) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG2] >= 8, saved_ereg2_is_hireg);
|
||||
*inst++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_SAVED_EREG2]);
|
||||
}
|
||||
if (saveds >= 4) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG1] >= 8, saved_ereg1_is_hireg);
|
||||
*inst++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_SAVED_EREG1]);
|
||||
}
|
||||
if (saveds >= 3) {
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] >= 8, saved_reg3_is_hireg);
|
||||
*inst++ = REX_B;
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] < 8, saved_reg3_is_loreg);
|
||||
#endif
|
||||
PUSH_REG(reg_lmap[SLJIT_SAVED_REG3]);
|
||||
}
|
||||
if (saveds >= 2) {
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] >= 8, saved_reg2_is_hireg);
|
||||
*inst++ = REX_B;
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] < 8, saved_reg2_is_loreg);
|
||||
#endif
|
||||
PUSH_REG(reg_lmap[SLJIT_SAVED_REG2]);
|
||||
}
|
||||
if (saveds >= 1) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG1] < 8, saved_reg1_is_loreg);
|
||||
PUSH_REG(reg_lmap[SLJIT_SAVED_REG1]);
|
||||
}
|
||||
#ifdef _WIN64
|
||||
if (scratches >= 5) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_EREG2] >= 8, temporary_ereg2_is_hireg);
|
||||
*inst++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN64
|
||||
if (args > 0) {
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x7 /* rdi */;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x7 /* rdi */;
|
||||
}
|
||||
if (args > 1) {
|
||||
*inst++ = REX_W | REX_R;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_lmap[SLJIT_SAVED_REG2] << 3) | 0x6 /* rsi */;
|
||||
*inst++ = MOD_REG | (reg_lmap[SLJIT_S1] << 3) | 0x6 /* rsi */;
|
||||
}
|
||||
if (args > 2) {
|
||||
*inst++ = REX_W | REX_R;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_lmap[SLJIT_SAVED_REG3] << 3) | 0x2 /* rdx */;
|
||||
*inst++ = MOD_REG | (reg_lmap[SLJIT_S2] << 3) | 0x2 /* rdx */;
|
||||
}
|
||||
#else
|
||||
if (args > 0) {
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x1 /* rcx */;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x1 /* rcx */;
|
||||
}
|
||||
if (args > 1) {
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG2] << 3) | 0x2 /* rdx */;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_S1] << 3) | 0x2 /* rdx */;
|
||||
}
|
||||
if (args > 2) {
|
||||
*inst++ = REX_W | REX_B;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x0 /* r8 */;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_S2] << 3) | 0x0 /* r8 */;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
local_size = ((local_size + FIXED_LOCALS_OFFSET + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
|
||||
local_size = ((local_size + FIXED_LOCALS_OFFSET + saved_register_size + 16 - 1) & ~(16 - 1)) - saved_register_size;
|
||||
compiler->local_size = local_size;
|
||||
|
||||
#ifdef _WIN64
|
||||
if (local_size > 1024) {
|
||||
/* Allocate stack for the callback, which grows the stack. */
|
||||
@ -208,9 +185,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_83;
|
||||
*inst++ = MOD_REG | SUB | 4;
|
||||
/* Pushed size must be divisible by 8. */
|
||||
SLJIT_ASSERT(!(pushed_size & 0x7));
|
||||
if (pushed_size & 0x8) {
|
||||
/* Allocated size for registers must be divisible by 8. */
|
||||
SLJIT_ASSERT(!(saved_register_size & 0x7));
|
||||
/* Aligned to 16 byte. */
|
||||
if (saved_register_size & 0x8) {
|
||||
*inst++ = 5 * sizeof(sljit_sw);
|
||||
local_size -= 5 * sizeof(sljit_sw);
|
||||
} else {
|
||||
@ -218,10 +196,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
||||
local_size -= 4 * sizeof(sljit_sw);
|
||||
}
|
||||
/* Second instruction */
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG1] < 8, temporary_reg1_is_loreg);
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R0] < 8, temporary_reg1_is_loreg);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_rm_i32;
|
||||
*inst++ = MOD_REG | reg_lmap[SLJIT_SCRATCH_REG1];
|
||||
*inst++ = MOD_REG | reg_lmap[SLJIT_R0];
|
||||
*(sljit_si*)inst = local_size;
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->skip_checks = 1;
|
||||
@ -229,6 +207,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(local_size > 0);
|
||||
if (local_size <= 127) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
@ -249,43 +228,47 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
||||
*(sljit_si*)inst = local_size;
|
||||
inst += sizeof(sljit_si);
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
/* Save xmm6 with MOVAPS instruction. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(5);
|
||||
*inst++ = GROUP_0F;
|
||||
*(sljit_si*)inst = 0x20247429;
|
||||
/* Save xmm6 register: movaps [rsp + 0x20], xmm6 */
|
||||
if (fscratches >= 6 || fsaveds >= 1) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(5);
|
||||
*inst++ = GROUP_0F;
|
||||
*(sljit_si*)inst = 0x20247429;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_si pushed_size;
|
||||
sljit_si saved_register_size;
|
||||
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
|
||||
check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->options = options;
|
||||
compiler->scratches = scratches;
|
||||
compiler->saveds = saveds;
|
||||
compiler->fscratches = fscratches;
|
||||
compiler->fsaveds = fsaveds;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->logical_local_size = local_size;
|
||||
#endif
|
||||
|
||||
/* Including the return address saved by the call instruction. */
|
||||
pushed_size = (saveds + 1) * sizeof(sljit_sw);
|
||||
#ifdef _WIN64
|
||||
if (scratches >= 5)
|
||||
pushed_size += sizeof(sljit_sw);
|
||||
#endif
|
||||
compiler->local_size = ((local_size + FIXED_LOCALS_OFFSET + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
|
||||
saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
|
||||
compiler->local_size = ((local_size + FIXED_LOCALS_OFFSET + saved_register_size + 16 - 1) & ~(16 - 1)) - saved_register_size;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si size;
|
||||
sljit_si i, tmp, size;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
@ -295,13 +278,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
#ifdef _WIN64
|
||||
/* Restore xmm6 with MOVAPS instruction. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(5);
|
||||
*inst++ = GROUP_0F;
|
||||
*(sljit_si*)inst = 0x20247428;
|
||||
/* Restore xmm6 register: movaps xmm6, [rsp + 0x20] */
|
||||
if (compiler->fscratches >= 6 || compiler->fsaveds >= 1) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(5);
|
||||
*inst++ = GROUP_0F;
|
||||
*(sljit_si*)inst = 0x20247428;
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(compiler->local_size > 0);
|
||||
if (compiler->local_size <= 127) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
@ -322,50 +308,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
||||
*(sljit_si*)inst = compiler->local_size;
|
||||
}
|
||||
|
||||
size = 1 + compiler->saveds;
|
||||
#ifndef _WIN64
|
||||
if (compiler->saveds >= 2)
|
||||
size += compiler->saveds - 1;
|
||||
#else
|
||||
if (compiler->saveds >= 4)
|
||||
size += compiler->saveds - 3;
|
||||
if (compiler->scratches >= 5)
|
||||
size += (5 - 4) * 2;
|
||||
#endif
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
tmp = compiler->scratches;
|
||||
for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
|
||||
size = reg_map[i] >= 8 ? 2 : 1;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(size);
|
||||
if (reg_map[i] >= 8)
|
||||
*inst++ = REX_B;
|
||||
POP_REG(reg_lmap[i]);
|
||||
}
|
||||
|
||||
tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = tmp; i <= SLJIT_S0; i++) {
|
||||
size = reg_map[i] >= 8 ? 2 : 1;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(size);
|
||||
if (reg_map[i] >= 8)
|
||||
*inst++ = REX_B;
|
||||
POP_REG(reg_lmap[i]);
|
||||
}
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
|
||||
#ifdef _WIN64
|
||||
if (compiler->scratches >= 5) {
|
||||
*inst++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
|
||||
}
|
||||
#endif
|
||||
if (compiler->saveds >= 1)
|
||||
POP_REG(reg_map[SLJIT_SAVED_REG1]);
|
||||
if (compiler->saveds >= 2) {
|
||||
#ifndef _WIN64
|
||||
*inst++ = REX_B;
|
||||
#endif
|
||||
POP_REG(reg_lmap[SLJIT_SAVED_REG2]);
|
||||
}
|
||||
if (compiler->saveds >= 3) {
|
||||
#ifndef _WIN64
|
||||
*inst++ = REX_B;
|
||||
#endif
|
||||
POP_REG(reg_lmap[SLJIT_SAVED_REG3]);
|
||||
}
|
||||
if (compiler->saveds >= 4) {
|
||||
*inst++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_SAVED_EREG1]);
|
||||
}
|
||||
if (compiler->saveds >= 5) {
|
||||
*inst++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_SAVED_EREG2]);
|
||||
}
|
||||
|
||||
INC_SIZE(1);
|
||||
RET();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
@ -409,72 +376,67 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
||||
SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
|
||||
/* Both size flags cannot be switched on. */
|
||||
SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
/* SSE2 and immediate is not possible. */
|
||||
SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
|
||||
SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
|
||||
&& (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
|
||||
&& (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
|
||||
#endif
|
||||
|
||||
size &= 0xf;
|
||||
inst_size = size;
|
||||
|
||||
if ((b & SLJIT_MEM) && !(b & OFFS_REG_MASK) && NOT_HALFWORD(immb)) {
|
||||
if (emit_load_imm64(compiler, TMP_REG3, immb))
|
||||
return NULL;
|
||||
immb = 0;
|
||||
if (b & REG_MASK)
|
||||
b |= TO_OFFS_REG(TMP_REG3);
|
||||
else
|
||||
b |= TMP_REG3;
|
||||
}
|
||||
|
||||
if (!compiler->mode32 && !(flags & EX86_NO_REXW))
|
||||
rex |= REX_W;
|
||||
else if (flags & EX86_REX)
|
||||
rex |= REX;
|
||||
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
|
||||
inst_size++;
|
||||
#endif
|
||||
if (flags & EX86_PREF_66)
|
||||
inst_size++;
|
||||
|
||||
/* Calculate size of b. */
|
||||
inst_size += 1; /* mod r/m byte. */
|
||||
if (b & SLJIT_MEM) {
|
||||
if (!(b & OFFS_REG_MASK)) {
|
||||
if (NOT_HALFWORD(immb)) {
|
||||
if (emit_load_imm64(compiler, TMP_REG3, immb))
|
||||
return NULL;
|
||||
immb = 0;
|
||||
if (b & REG_MASK)
|
||||
b |= TO_OFFS_REG(TMP_REG3);
|
||||
else
|
||||
b |= TMP_REG3;
|
||||
}
|
||||
else if (reg_lmap[b & REG_MASK] == 4)
|
||||
b |= TO_OFFS_REG(SLJIT_SP);
|
||||
}
|
||||
|
||||
if ((b & REG_MASK) == SLJIT_UNUSED)
|
||||
inst_size += 1 + sizeof(sljit_si); /* SIB byte required to avoid RIP based addressing. */
|
||||
else {
|
||||
if (reg_map[b & REG_MASK] >= 8)
|
||||
rex |= REX_B;
|
||||
if (immb != 0 && !(b & OFFS_REG_MASK)) {
|
||||
|
||||
if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) {
|
||||
/* Immediate operand. */
|
||||
if (immb <= 127 && immb >= -128)
|
||||
inst_size += sizeof(sljit_sb);
|
||||
else
|
||||
inst_size += sizeof(sljit_si);
|
||||
}
|
||||
}
|
||||
else if (reg_lmap[b & REG_MASK] == 5)
|
||||
inst_size += sizeof(sljit_sb);
|
||||
|
||||
if ((b & REG_MASK) == SLJIT_LOCALS_REG && !(b & OFFS_REG_MASK))
|
||||
b |= TO_OFFS_REG(SLJIT_LOCALS_REG);
|
||||
|
||||
if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) {
|
||||
inst_size += 1; /* SIB byte. */
|
||||
if (reg_map[OFFS_REG(b)] >= 8)
|
||||
rex |= REX_X;
|
||||
if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) {
|
||||
inst_size += 1; /* SIB byte. */
|
||||
if (reg_map[OFFS_REG(b)] >= 8)
|
||||
rex |= REX_X;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
else if (!(flags & EX86_SSE2) && reg_map[b] >= 8)
|
||||
else if (!(flags & EX86_SSE2_OP2) && reg_map[b] >= 8)
|
||||
rex |= REX_B;
|
||||
#else
|
||||
else if (reg_map[b] >= 8)
|
||||
rex |= REX_B;
|
||||
#endif
|
||||
|
||||
if (a & SLJIT_IMM) {
|
||||
if (flags & EX86_BIN_INS) {
|
||||
@ -500,13 +462,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
||||
else {
|
||||
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
|
||||
/* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (!(flags & EX86_SSE2) && reg_map[a] >= 8)
|
||||
if (!(flags & EX86_SSE2_OP1) && reg_map[a] >= 8)
|
||||
rex |= REX_R;
|
||||
#else
|
||||
if (reg_map[a] >= 8)
|
||||
rex |= REX_R;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rex)
|
||||
@ -517,12 +474,10 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
||||
|
||||
/* Encoding the byte. */
|
||||
INC_SIZE(inst_size);
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (flags & EX86_PREF_F2)
|
||||
*inst++ = 0xf2;
|
||||
if (flags & EX86_PREF_F3)
|
||||
*inst++ = 0xf3;
|
||||
#endif
|
||||
if (flags & EX86_PREF_66)
|
||||
*inst++ = 0x66;
|
||||
if (rex)
|
||||
@ -536,15 +491,10 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
||||
|
||||
if ((a & SLJIT_IMM) || (a == 0))
|
||||
*buf_ptr = 0;
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
else if (!(flags & EX86_SSE2))
|
||||
else if (!(flags & EX86_SSE2_OP1))
|
||||
*buf_ptr = reg_lmap[a] << 3;
|
||||
else
|
||||
*buf_ptr = a << 3;
|
||||
#else
|
||||
else
|
||||
*buf_ptr = reg_lmap[a] << 3;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if (a & SLJIT_IMM) {
|
||||
@ -558,14 +508,10 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
||||
}
|
||||
|
||||
if (!(b & SLJIT_MEM))
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
*buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2)) ? reg_lmap[b] : b);
|
||||
#else
|
||||
*buf_ptr++ |= MOD_REG + reg_lmap[b];
|
||||
#endif
|
||||
*buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_lmap[b] : b);
|
||||
else if ((b & REG_MASK) != SLJIT_UNUSED) {
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_LOCALS_REG)) {
|
||||
if (immb != 0) {
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {
|
||||
if (immb != 0 || reg_lmap[b & REG_MASK] == 5) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr |= 0x40;
|
||||
else
|
||||
@ -579,7 +525,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
||||
*buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3);
|
||||
}
|
||||
|
||||
if (immb != 0) {
|
||||
if (immb != 0 || reg_lmap[b & REG_MASK] == 5) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr++ = immb; /* 8 bit displacement. */
|
||||
else {
|
||||
@ -589,8 +535,12 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (reg_lmap[b & REG_MASK] == 5)
|
||||
*buf_ptr |= 0x40;
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6);
|
||||
if (reg_lmap[b & REG_MASK] == 5)
|
||||
*buf_ptr++ = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -621,7 +571,7 @@ static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, slj
|
||||
sljit_ub *inst;
|
||||
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG2] == 6 && reg_map[SLJIT_SCRATCH_REG1] < 8 && reg_map[SLJIT_SCRATCH_REG3] < 8, args_registers);
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!inst);
|
||||
@ -629,13 +579,13 @@ static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, slj
|
||||
if (type >= SLJIT_CALL3) {
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x2 /* rdx */ << 3) | reg_lmap[SLJIT_SCRATCH_REG3];
|
||||
*inst++ = MOD_REG | (0x2 /* rdx */ << 3) | reg_lmap[SLJIT_R2];
|
||||
}
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x7 /* rdi */ << 3) | reg_lmap[SLJIT_SCRATCH_REG1];
|
||||
*inst++ = MOD_REG | (0x7 /* rdi */ << 3) | reg_lmap[SLJIT_R0];
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG2] == 2 && reg_map[SLJIT_SCRATCH_REG1] < 8 && reg_map[SLJIT_SCRATCH_REG3] < 8, args_registers);
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!inst);
|
||||
@ -643,11 +593,11 @@ static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, slj
|
||||
if (type >= SLJIT_CALL3) {
|
||||
*inst++ = REX_W | REX_R;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x0 /* r8 */ << 3) | reg_lmap[SLJIT_SCRATCH_REG3];
|
||||
*inst++ = MOD_REG | (0x0 /* r8 */ << 3) | reg_lmap[SLJIT_R2];
|
||||
}
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x1 /* rcx */ << 3) | reg_lmap[SLJIT_SCRATCH_REG1];
|
||||
*inst++ = MOD_REG | (0x1 /* rcx */ << 3) | reg_lmap[SLJIT_R0];
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
@ -64,51 +64,46 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
|
||||
/* Last register + 1. */
|
||||
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
|
||||
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
|
||||
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 2] = {
|
||||
0, 0, 2, 1, 0, 0, 3, 6, 7, 0, 0, 4, 5
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {
|
||||
0, 0, 2, 1, 0, 0, 0, 0, 7, 6, 3, 4, 5
|
||||
};
|
||||
|
||||
#define CHECK_EXTRA_REGS(p, w, do) \
|
||||
if (p >= SLJIT_TEMPORARY_EREG1 && p <= SLJIT_TEMPORARY_EREG2) { \
|
||||
w = compiler->scratches_start + (p - SLJIT_TEMPORARY_EREG1) * sizeof(sljit_sw); \
|
||||
p = SLJIT_MEM1(SLJIT_LOCALS_REG); \
|
||||
do; \
|
||||
} \
|
||||
else if (p >= SLJIT_SAVED_EREG1 && p <= SLJIT_SAVED_EREG2) { \
|
||||
w = compiler->saveds_start + (p - SLJIT_SAVED_EREG1) * sizeof(sljit_sw); \
|
||||
p = SLJIT_MEM1(SLJIT_LOCALS_REG); \
|
||||
if (p >= SLJIT_R3 && p <= SLJIT_R6) { \
|
||||
w = FIXED_LOCALS_OFFSET + ((p) - (SLJIT_R3 + 4)) * sizeof(sljit_sw); \
|
||||
p = SLJIT_MEM1(SLJIT_SP); \
|
||||
do; \
|
||||
}
|
||||
|
||||
#else /* SLJIT_CONFIG_X86_32 */
|
||||
|
||||
/* Last register + 1. */
|
||||
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
|
||||
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
|
||||
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
|
||||
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
|
||||
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
|
||||
#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
|
||||
|
||||
/* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present
|
||||
Note: avoid to use r12 and r13 for memory addessing
|
||||
therefore r12 is better for SAVED_EREG than SAVED_REG. */
|
||||
#ifndef _WIN64
|
||||
/* 1st passed in rdi, 2nd argument passed in rsi, 3rd in rdx. */
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
||||
0, 0, 6, 1, 8, 11, 3, 15, 14, 13, 12, 4, 2, 7, 9
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||
0, 0, 6, 1, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 7, 9
|
||||
};
|
||||
/* low-map. reg_map & 0x7. */
|
||||
static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
|
||||
0, 0, 6, 1, 0, 3, 3, 7, 6, 5, 4, 4, 2, 7, 1
|
||||
static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||
0, 0, 6, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 7, 1
|
||||
};
|
||||
#else
|
||||
/* 1st passed in rcx, 2nd argument passed in rdx, 3rd in r8. */
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
||||
0, 0, 2, 1, 11, 13, 3, 6, 7, 14, 15, 4, 10, 8, 9
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||
0, 0, 2, 1, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 10, 8, 9
|
||||
};
|
||||
/* low-map. reg_map & 0x7. */
|
||||
static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
|
||||
0, 0, 2, 1, 3, 5, 3, 6, 7, 6, 7, 4, 2, 0, 1
|
||||
static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||
0, 0, 2, 1, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 2, 0, 1
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -133,9 +128,7 @@ static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
|
||||
|
||||
#endif /* SLJIT_CONFIG_X86_32 */
|
||||
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
#define TMP_FREG (0)
|
||||
#endif
|
||||
|
||||
/* Size flags for emit_x86_instruction: */
|
||||
#define EX86_BIN_INS 0x0010
|
||||
@ -145,12 +138,11 @@ static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
|
||||
#define EX86_BYTE_ARG 0x0100
|
||||
#define EX86_HALF_ARG 0x0200
|
||||
#define EX86_PREF_66 0x0400
|
||||
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
#define EX86_SSE2 0x0800
|
||||
#define EX86_PREF_F2 0x1000
|
||||
#define EX86_PREF_F3 0x2000
|
||||
#endif
|
||||
#define EX86_PREF_F2 0x0800
|
||||
#define EX86_PREF_F3 0x1000
|
||||
#define EX86_SSE2_OP1 0x2000
|
||||
#define EX86_SSE2_OP2 0x4000
|
||||
#define EX86_SSE2 (EX86_SSE2_OP1 | EX86_SSE2_OP2)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Instrucion forms */
|
||||
@ -179,6 +171,9 @@ static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
|
||||
#define CMP_EAX_i32 0x3d
|
||||
#define CMP_r_rm 0x3b
|
||||
#define CMP_rm_r 0x39
|
||||
#define CVTPD2PS_x_xm 0x5a
|
||||
#define CVTSI2SD_x_rm 0x2a
|
||||
#define CVTTSD2SI_r_xm 0x2c
|
||||
#define DIV (/* GROUP_F7 */ 6 << 3)
|
||||
#define DIVSD_x_xm 0x5e
|
||||
#define INT3 0xcc
|
||||
@ -239,6 +234,7 @@ static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
|
||||
#define TEST_EAX_i32 0xa9
|
||||
#define TEST_rm_r 0x85
|
||||
#define UCOMISD_x_xm 0x2e
|
||||
#define UNPCKLPD_x_xm 0x14
|
||||
#define XCHG_EAX_r 0x90
|
||||
#define XCHG_r_rm 0x87
|
||||
#define XOR (/* BINARY */ 6 << 3)
|
||||
@ -271,7 +267,7 @@ static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
|
||||
/* Multithreading does not affect these static variables, since they store
|
||||
built-in CPU features. Therefore they can be overwritten by different threads
|
||||
if they detect the CPU features in the same time. */
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2) && (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
|
||||
#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
|
||||
static sljit_si cpu_has_sse2 = -1;
|
||||
#endif
|
||||
static sljit_si cpu_has_cmov = -1;
|
||||
@ -325,7 +321,7 @@ static void get_cpu_features(void)
|
||||
|
||||
#endif /* _MSC_VER && _MSC_VER >= 1400 */
|
||||
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2) && (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
|
||||
#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
|
||||
cpu_has_sse2 = (features >> 26) & 0x1;
|
||||
#endif
|
||||
cpu_has_cmov = (features >> 15) & 0x1;
|
||||
@ -751,14 +747,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#ifdef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(
|
||||
reg_map[SLJIT_SCRATCH_REG1] == 0
|
||||
&& reg_map[SLJIT_SCRATCH_REG2] == 2
|
||||
reg_map[SLJIT_R0] == 0
|
||||
&& reg_map[SLJIT_R1] == 2
|
||||
&& reg_map[TMP_REG1] > 7,
|
||||
invalid_register_assignment_for_div_mul);
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(
|
||||
reg_map[SLJIT_SCRATCH_REG1] == 0
|
||||
&& reg_map[SLJIT_SCRATCH_REG2] < 7
|
||||
reg_map[SLJIT_R0] == 0
|
||||
&& reg_map[SLJIT_R1] < 7
|
||||
&& reg_map[TMP_REG1] == 2,
|
||||
invalid_register_assignment_for_div_mul);
|
||||
#endif
|
||||
@ -768,8 +764,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
op = GET_OPCODE(op);
|
||||
if (op == SLJIT_UDIV) {
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_SCRATCH_REG2, 0);
|
||||
inst = emit_x86_instruction(compiler, 1, SLJIT_SCRATCH_REG2, 0, SLJIT_SCRATCH_REG2, 0);
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);
|
||||
inst = emit_x86_instruction(compiler, 1, SLJIT_R1, 0, SLJIT_R1, 0);
|
||||
#else
|
||||
inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0);
|
||||
#endif
|
||||
@ -779,7 +775,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
|
||||
if (op == SLJIT_SDIV) {
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_SCRATCH_REG2, 0);
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
@ -808,7 +804,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(2);
|
||||
*inst++ = GROUP_F7;
|
||||
*inst = MOD_REG | ((op >= SLJIT_UDIV) ? reg_map[TMP_REG1] : reg_map[SLJIT_SCRATCH_REG2]);
|
||||
*inst = MOD_REG | ((op >= SLJIT_UDIV) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);
|
||||
#else
|
||||
#ifdef _WIN64
|
||||
size = (!compiler->mode32 || op >= SLJIT_UDIV) ? 3 : 2;
|
||||
@ -824,12 +820,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
else if (op >= SLJIT_UDIV)
|
||||
*inst++ = REX_B;
|
||||
*inst++ = GROUP_F7;
|
||||
*inst = MOD_REG | ((op >= SLJIT_UDIV) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_SCRATCH_REG2]);
|
||||
*inst = MOD_REG | ((op >= SLJIT_UDIV) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);
|
||||
#else
|
||||
if (!compiler->mode32)
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_F7;
|
||||
*inst = MOD_REG | reg_map[SLJIT_SCRATCH_REG2];
|
||||
*inst = MOD_REG | reg_map[SLJIT_R1];
|
||||
#endif
|
||||
#endif
|
||||
switch (op) {
|
||||
@ -847,7 +843,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
||||
break;
|
||||
}
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
|
||||
EMIT_MOV(compiler, SLJIT_SCRATCH_REG2, 0, TMP_REG1, 0);
|
||||
EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -956,22 +952,22 @@ static sljit_si emit_mov_byte(struct sljit_compiler *compiler, sljit_si sign,
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
if (dst_r == TMP_REG1) {
|
||||
/* Find a non-used register, whose reg_map[src] < 4. */
|
||||
if ((dst & REG_MASK) == SLJIT_SCRATCH_REG1) {
|
||||
if ((dst & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SCRATCH_REG2))
|
||||
work_r = SLJIT_SCRATCH_REG3;
|
||||
if ((dst & REG_MASK) == SLJIT_R0) {
|
||||
if ((dst & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_R1))
|
||||
work_r = SLJIT_R2;
|
||||
else
|
||||
work_r = SLJIT_SCRATCH_REG2;
|
||||
work_r = SLJIT_R1;
|
||||
}
|
||||
else {
|
||||
if ((dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_SCRATCH_REG1))
|
||||
work_r = SLJIT_SCRATCH_REG1;
|
||||
else if ((dst & REG_MASK) == SLJIT_SCRATCH_REG2)
|
||||
work_r = SLJIT_SCRATCH_REG3;
|
||||
if ((dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R0))
|
||||
work_r = SLJIT_R0;
|
||||
else if ((dst & REG_MASK) == SLJIT_R1)
|
||||
work_r = SLJIT_R2;
|
||||
else
|
||||
work_r = SLJIT_SCRATCH_REG2;
|
||||
work_r = SLJIT_R1;
|
||||
}
|
||||
|
||||
if (work_r == SLJIT_SCRATCH_REG1) {
|
||||
if (work_r == SLJIT_R0) {
|
||||
ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REG1]);
|
||||
}
|
||||
else {
|
||||
@ -984,7 +980,7 @@ static sljit_si emit_mov_byte(struct sljit_compiler *compiler, sljit_si sign,
|
||||
FAIL_IF(!inst);
|
||||
*inst = MOV_rm8_r8;
|
||||
|
||||
if (work_r == SLJIT_SCRATCH_REG1) {
|
||||
if (work_r == SLJIT_R0) {
|
||||
ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REG1]);
|
||||
}
|
||||
else {
|
||||
@ -1179,12 +1175,12 @@ static sljit_si emit_clz(struct sljit_compiler *compiler, sljit_si op_flags,
|
||||
dst_r = dst;
|
||||
else {
|
||||
/* Find an unused temporary register. */
|
||||
if ((dst & REG_MASK) != SLJIT_SCRATCH_REG1 && (dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_SCRATCH_REG1))
|
||||
dst_r = SLJIT_SCRATCH_REG1;
|
||||
else if ((dst & REG_MASK) != SLJIT_SCRATCH_REG2 && (dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_SCRATCH_REG2))
|
||||
dst_r = SLJIT_SCRATCH_REG2;
|
||||
if ((dst & REG_MASK) != SLJIT_R0 && (dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R0))
|
||||
dst_r = SLJIT_R0;
|
||||
else if ((dst & REG_MASK) != SLJIT_R1 && (dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R1))
|
||||
dst_r = SLJIT_R1;
|
||||
else
|
||||
dst_r = SLJIT_SCRATCH_REG3;
|
||||
dst_r = SLJIT_R2;
|
||||
EMIT_MOV(compiler, dst, dstw, dst_r, 0);
|
||||
}
|
||||
EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, 32 + 31);
|
||||
@ -1340,7 +1336,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI || op == SLJIT_MOV_P) || (src & SLJIT_MEM))) {
|
||||
SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_LOCALS_REG));
|
||||
SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_SP));
|
||||
dst = TMP_REG1;
|
||||
}
|
||||
#endif
|
||||
@ -1378,7 +1374,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REG1)
|
||||
return emit_mov(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), dstw, TMP_REG1, 0);
|
||||
return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), dstw, TMP_REG1, 0);
|
||||
#endif
|
||||
|
||||
if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & REG_MASK) && (dstw != 0 || (dst & OFFS_REG_MASK) != 0)) {
|
||||
@ -1470,9 +1466,9 @@ static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
|
||||
if (dst == src1 && dstw == src1w) {
|
||||
if (src2 & SLJIT_IMM) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if ((dst == SLJIT_SCRATCH_REG1) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
|
||||
if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
|
||||
#else
|
||||
if ((dst == SLJIT_SCRATCH_REG1) && (src2w > 127 || src2w < -128)) {
|
||||
if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128)) {
|
||||
#endif
|
||||
BINARY_EAX_IMM(op_eax_imm, src2w);
|
||||
}
|
||||
@ -1504,9 +1500,9 @@ static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
|
||||
if (dst == src2 && dstw == src2w) {
|
||||
if (src1 & SLJIT_IMM) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if ((dst == SLJIT_SCRATCH_REG1) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
|
||||
if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
|
||||
#else
|
||||
if ((dst == SLJIT_SCRATCH_REG1) && (src1w > 127 || src1w < -128)) {
|
||||
if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128)) {
|
||||
#endif
|
||||
BINARY_EAX_IMM(op_eax_imm, src1w);
|
||||
}
|
||||
@ -1586,9 +1582,9 @@ static sljit_si emit_non_cum_binary(struct sljit_compiler *compiler,
|
||||
if (dst == src1 && dstw == src1w) {
|
||||
if (src2 & SLJIT_IMM) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if ((dst == SLJIT_SCRATCH_REG1) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
|
||||
if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
|
||||
#else
|
||||
if ((dst == SLJIT_SCRATCH_REG1) && (src2w > 127 || src2w < -128)) {
|
||||
if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128)) {
|
||||
#endif
|
||||
BINARY_EAX_IMM(op_eax_imm, src2w);
|
||||
}
|
||||
@ -1840,9 +1836,9 @@ static sljit_si emit_cmp_binary(struct sljit_compiler *compiler,
|
||||
sljit_ub* inst;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (src1 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
|
||||
if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
|
||||
#else
|
||||
if (src1 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {
|
||||
if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {
|
||||
#endif
|
||||
BINARY_EAX_IMM(CMP_EAX_i32, src2w);
|
||||
return SLJIT_SUCCESS;
|
||||
@ -1891,18 +1887,18 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler,
|
||||
sljit_ub* inst;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (src1 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
|
||||
if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
|
||||
#else
|
||||
if (src1 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {
|
||||
if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {
|
||||
#endif
|
||||
BINARY_EAX_IMM(TEST_EAX_i32, src2w);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (src2 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
|
||||
if (src2 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
|
||||
#else
|
||||
if (src2 == SLJIT_SCRATCH_REG1 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) {
|
||||
if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) {
|
||||
#endif
|
||||
BINARY_EAX_IMM(TEST_EAX_i32, src1w);
|
||||
return SLJIT_SUCCESS;
|
||||
@ -2064,7 +2060,7 @@ static sljit_si emit_shift(struct sljit_compiler *compiler,
|
||||
EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
|
||||
#else
|
||||
/* [esp+0] contains the flags. */
|
||||
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), sizeof(sljit_sw), SLJIT_PREF_SHIFT_REG, 0);
|
||||
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_PREF_SHIFT_REG, 0);
|
||||
#endif
|
||||
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
|
||||
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
|
||||
@ -2073,7 +2069,7 @@ static sljit_si emit_shift(struct sljit_compiler *compiler,
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);
|
||||
#else
|
||||
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), sizeof(sljit_sw));
|
||||
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));
|
||||
#endif
|
||||
EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
|
||||
}
|
||||
@ -2215,8 +2211,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
|
||||
{
|
||||
check_sljit_get_register_index(reg);
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
if (reg == SLJIT_TEMPORARY_EREG1 || reg == SLJIT_TEMPORARY_EREG2
|
||||
|| reg == SLJIT_SAVED_EREG1 || reg == SLJIT_SAVED_EREG2)
|
||||
if (reg >= SLJIT_R3 && reg <= SLJIT_R6)
|
||||
return -1;
|
||||
#endif
|
||||
return reg_map[reg];
|
||||
@ -2248,8 +2243,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
|
||||
/* Floating point operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
|
||||
/* Alignment + 2 * 16 bytes. */
|
||||
static sljit_si sse2_data[3 + (4 + 4) * 2];
|
||||
static sljit_si *sse2_buffer;
|
||||
@ -2267,27 +2260,19 @@ static void init_compiler(void)
|
||||
sse2_buffer[13] = 0x7fffffff;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
|
||||
{
|
||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||
return SLJIT_IS_FPU_AVAILABLE;
|
||||
#elif (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
|
||||
#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
|
||||
if (cpu_has_sse2 == -1)
|
||||
get_cpu_features();
|
||||
return cpu_has_sse2;
|
||||
#else /* SLJIT_DETECT_SSE2 */
|
||||
return 1;
|
||||
#endif /* SLJIT_DETECT_SSE2 */
|
||||
#else /* SLJIT_SSE2 */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
|
||||
static sljit_si emit_sse2(struct sljit_compiler *compiler, sljit_ub opcode,
|
||||
sljit_si single, sljit_si xmm1, sljit_si xmm2, sljit_sw xmm2w)
|
||||
{
|
||||
@ -2324,31 +2309,89 @@ static SLJIT_INLINE sljit_si emit_sse2_store(struct sljit_compiler *compiler,
|
||||
return emit_sse2(compiler, MOVSD_xm_x, single, src, dst, dstw);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
|
||||
sljit_ub *inst;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (GET_OPCODE(op) == SLJIT_CONVW_FROMD)
|
||||
compiler->mode32 = 0;
|
||||
#endif
|
||||
|
||||
inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_SINGLE_OP) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP2, dst_r, 0, src, srcw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = GROUP_0F;
|
||||
*inst = CVTTSD2SI_r_xm;
|
||||
|
||||
if (dst_r == TMP_REG1 && dst != SLJIT_UNUSED)
|
||||
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;
|
||||
sljit_ub *inst;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (GET_OPCODE(op) == SLJIT_CONVD_FROMW)
|
||||
compiler->mode32 = 0;
|
||||
#endif
|
||||
|
||||
if (src & SLJIT_IMM) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (GET_OPCODE(op) == SLJIT_CONVD_FROMI)
|
||||
srcw = (sljit_si)srcw;
|
||||
#endif
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
|
||||
src = TMP_REG1;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_SINGLE_OP) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP1, dst_r, 0, src, srcw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = GROUP_0F;
|
||||
*inst = CVTSI2SD_x_rm;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
compiler->mode32 = 1;
|
||||
#endif
|
||||
if (dst_r == TMP_FREG)
|
||||
return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
compiler->flags_saved = 0;
|
||||
if (!FAST_IS_REG(src1)) {
|
||||
FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, TMP_FREG, src1, src1w));
|
||||
src1 = TMP_FREG;
|
||||
}
|
||||
return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_SINGLE_OP), src1, src2, src2w);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_r;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
compiler->mode32 = 1;
|
||||
#endif
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CMPD) {
|
||||
compiler->flags_saved = 0;
|
||||
if (FAST_IS_REG(dst))
|
||||
dst_r = dst;
|
||||
else {
|
||||
dst_r = TMP_FREG;
|
||||
FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, dst, dstw));
|
||||
}
|
||||
return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_SINGLE_OP), dst_r, src, srcw);
|
||||
}
|
||||
CHECK_ERROR();
|
||||
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
|
||||
|
||||
if (op == SLJIT_MOVD) {
|
||||
if (GET_OPCODE(op) == SLJIT_MOVD) {
|
||||
if (FAST_IS_REG(dst))
|
||||
return emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst, src, srcw);
|
||||
if (FAST_IS_REG(src))
|
||||
@ -2357,6 +2400,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
||||
return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
|
||||
}
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CONVD_FROMS) {
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;
|
||||
if (FAST_IS_REG(src)) {
|
||||
/* We overwrite the high bits of source. From SLJIT point of view,
|
||||
this is not an issue.
|
||||
Note: In SSE3, we could also use MOVDDUP and MOVSLDUP. */
|
||||
FAIL_IF(emit_sse2_logic(compiler, UNPCKLPD_x_xm, op & SLJIT_SINGLE_OP, src, src, 0));
|
||||
}
|
||||
else {
|
||||
FAIL_IF(emit_sse2_load(compiler, !(op & SLJIT_SINGLE_OP), TMP_FREG, src, srcw));
|
||||
src = TMP_FREG;
|
||||
}
|
||||
|
||||
FAIL_IF(emit_sse2_logic(compiler, CVTPD2PS_x_xm, op & SLJIT_SINGLE_OP, dst_r, src, 0));
|
||||
if (dst_r == TMP_FREG)
|
||||
return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (SLOW_IS_REG(dst)) {
|
||||
dst_r = dst;
|
||||
if (dst != src)
|
||||
@ -2391,6 +2453,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
ADJUST_LOCAL_OFFSET(src1, src1w);
|
||||
ADJUST_LOCAL_OFFSET(src2, src2w);
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
compiler->mode32 = 1;
|
||||
@ -2440,33 +2505,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
/* Should cause an assertion fail. */
|
||||
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
|
||||
compiler->error = SLJIT_ERR_UNSUPPORTED;
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
/* Should cause an assertion fail. */
|
||||
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
|
||||
compiler->error = SLJIT_ERR_UNSUPPORTED;
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Conditional instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -2557,16 +2595,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
|
||||
if (type >= SLJIT_CALL1) {
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (src == SLJIT_SCRATCH_REG3) {
|
||||
if (src == SLJIT_R2) {
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
|
||||
src = TMP_REG1;
|
||||
}
|
||||
if (src == SLJIT_MEM1(SLJIT_LOCALS_REG) && type >= SLJIT_CALL3)
|
||||
if (src == SLJIT_MEM1(SLJIT_SP) && type >= SLJIT_CALL3)
|
||||
srcw += sizeof(sljit_sw);
|
||||
#endif
|
||||
#endif
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && defined(_WIN64)
|
||||
if (src == SLJIT_SCRATCH_REG3) {
|
||||
if (src == SLJIT_R2) {
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
|
||||
src = TMP_REG1;
|
||||
}
|
||||
@ -2732,8 +2770,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
||||
}
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && dst == src && reg_map[dst] <= 4) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG1] == 0, scratch_reg1_must_be_eax);
|
||||
if (dst != SLJIT_SCRATCH_REG1) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R0] == 0, scratch_reg1_must_be_eax);
|
||||
if (dst != SLJIT_R0) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 2 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1 + 3 + 2 + 1);
|
||||
@ -2802,23 +2840,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *co
|
||||
compiler->mode32 = 0;
|
||||
#endif
|
||||
|
||||
ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_LOCALS_REG), offset);
|
||||
ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (NOT_HALFWORD(offset)) {
|
||||
FAIL_IF(emit_load_imm64(compiler, TMP_REG1, offset));
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
SLJIT_ASSERT(emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED);
|
||||
SLJIT_ASSERT(emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED);
|
||||
return compiler->error;
|
||||
#else
|
||||
return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REG1, 0);
|
||||
return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (offset != 0)
|
||||
return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, SLJIT_IMM, offset);
|
||||
return emit_mov(compiler, dst, dstw, SLJIT_LOCALS_REG, 0);
|
||||
return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
|
||||
return emit_mov(compiler, dst, dstw, SLJIT_SP, 0);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
|
||||
|
56
ext/pcre/pcrelib/testdata/testinput1
vendored
56
ext/pcre/pcrelib/testdata/testinput1
vendored
@ -111,7 +111,7 @@
|
||||
bababbc
|
||||
babababc
|
||||
|
||||
/^\ca\cA\c[\c{\c:/
|
||||
/^\ca\cA\c[;\c:/
|
||||
\x01\x01\e;z
|
||||
|
||||
/^[ab\]cde]/
|
||||
@ -4937,6 +4937,12 @@ however, we need the complication for Perl. ---/
|
||||
|
||||
/((?(R1)a+|(?1)b))/
|
||||
aaaabcde
|
||||
|
||||
/((?(R)a|(?1)))*/
|
||||
aaa
|
||||
|
||||
/((?(R)a|(?1)))+/
|
||||
aaa
|
||||
|
||||
/a(*:any
|
||||
name)/K
|
||||
@ -5666,4 +5672,52 @@ AbcdCBefgBhiBqz
|
||||
/(a\Kb)*/+
|
||||
ababc
|
||||
|
||||
/(?:x|(?:(xx|yy)+|x|x|x|x|x)|a|a|a)bc/
|
||||
acb
|
||||
|
||||
'\A(?:[^\"]++|\"(?:[^\"]*+|\"\")*+\")++'
|
||||
NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED
|
||||
|
||||
'\A(?:[^\"]++|\"(?:[^\"]++|\"\")*+\")++'
|
||||
NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED
|
||||
|
||||
'\A(?:[^\"]++|\"(?:[^\"]++|\"\")++\")++'
|
||||
NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED
|
||||
|
||||
'\A([^\"1]++|[\"2]([^\"3]*+|[\"4][\"5])*+[\"6])++'
|
||||
NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED
|
||||
|
||||
/^\w+(?>\s*)(?<=\w)/
|
||||
test test
|
||||
|
||||
/(?P<same>a)(?P<same>b)/gJ
|
||||
abbaba
|
||||
|
||||
/(?P<same>a)(?P<same>b)(?P=same)/gJ
|
||||
abbaba
|
||||
|
||||
/(?P=same)?(?P<same>a)(?P<same>b)/gJ
|
||||
abbaba
|
||||
|
||||
/(?:(?P=same)?(?:(?P<same>a)|(?P<same>b))(?P=same))+/gJ
|
||||
bbbaaabaabb
|
||||
|
||||
/(?:(?P=same)?(?:(?P=same)(?P<same>a)(?P=same)|(?P=same)?(?P<same>b)(?P=same)){2}(?P=same)(?P<same>c)(?P=same)){2}(?P<same>z)?/gJ
|
||||
bbbaaaccccaaabbbcc
|
||||
|
||||
/(?P<Name>a)?(?P<Name2>b)?(?(<Name>)c|d)*l/
|
||||
acl
|
||||
bdl
|
||||
adl
|
||||
bcl
|
||||
|
||||
/\sabc/
|
||||
\x{0b}abc
|
||||
|
||||
/[\Qa]\E]+/
|
||||
aa]]
|
||||
|
||||
/[\Q]a\E]+/
|
||||
aa]]
|
||||
|
||||
/-- End of testinput1 --/
|
||||
|
2
ext/pcre/pcrelib/testdata/testinput11
vendored
2
ext/pcre/pcrelib/testdata/testinput11
vendored
@ -132,4 +132,6 @@ is required for these tests. --/
|
||||
|
||||
/abc(d|e)(*THEN)x(123(*THEN)4|567(b|q)(*THEN)xx)/B
|
||||
|
||||
/(((a\2)|(a*)\g<-1>))*a?/B
|
||||
|
||||
/-- End of testinput11 --/
|
||||
|
6
ext/pcre/pcrelib/testdata/testinput16
vendored
6
ext/pcre/pcrelib/testdata/testinput16
vendored
@ -32,4 +32,10 @@
|
||||
|
||||
/[[:blank:]]/WBZ
|
||||
|
||||
/\x{212a}+/i8SI
|
||||
KKkk\x{212a}
|
||||
|
||||
/s+/i8SI
|
||||
SSss\x{17f}
|
||||
|
||||
/-- End of testinput16 --/
|
||||
|
6
ext/pcre/pcrelib/testdata/testinput19
vendored
6
ext/pcre/pcrelib/testdata/testinput19
vendored
@ -19,4 +19,10 @@
|
||||
|
||||
/[[:blank:]]/WBZ
|
||||
|
||||
/\x{212a}+/i8SI
|
||||
KKkk\x{212a}
|
||||
|
||||
/s+/i8SI
|
||||
SSss\x{17f}
|
||||
|
||||
/-- End of testinput19 --/
|
||||
|
16
ext/pcre/pcrelib/testdata/testinput2
vendored
16
ext/pcre/pcrelib/testdata/testinput2
vendored
@ -4035,6 +4035,8 @@ backtracking verbs. --/
|
||||
|
||||
/(?(R&6yh)abc)/
|
||||
|
||||
/(((a\2)|(a*)\g<-1>))*a?/BZ
|
||||
|
||||
/-- Test the ugly "start or end of word" compatibility syntax --/
|
||||
|
||||
/[[:<:]]red[[:>:]]/BZ
|
||||
@ -4062,4 +4064,18 @@ backtracking verbs. --/
|
||||
|
||||
/(((((a)))))/Q
|
||||
|
||||
/^\w+(?>\s*)(?<=\w)/BZ
|
||||
|
||||
/\othing/
|
||||
|
||||
/\o{}/
|
||||
|
||||
/\o{whatever}/
|
||||
|
||||
/\xthing/
|
||||
|
||||
/\x{}/
|
||||
|
||||
/\x{whatever}/
|
||||
|
||||
/-- End of testinput2 --/
|
||||
|
5
ext/pcre/pcrelib/testdata/testinput6
vendored
5
ext/pcre/pcrelib/testdata/testinput6
vendored
@ -421,8 +421,8 @@
|
||||
/^[\p{Arabic}]/8
|
||||
\x{06e9}
|
||||
\x{060b}
|
||||
\x{061c}
|
||||
** Failers
|
||||
\x{061c}
|
||||
X\x{06e9}
|
||||
|
||||
/^[\P{Yi}]/8
|
||||
@ -1493,4 +1493,7 @@
|
||||
/[q-u]+/8iW
|
||||
Ss\x{17f}
|
||||
|
||||
/^s?c/mi8
|
||||
scat
|
||||
|
||||
/-- End of testinput6 --/
|
||||
|
3
ext/pcre/pcrelib/testdata/testinput7
vendored
3
ext/pcre/pcrelib/testdata/testinput7
vendored
@ -835,4 +835,7 @@ of case for anything other than the ASCII letters. --/
|
||||
|
||||
/[Q-U]+/8iWBZ
|
||||
|
||||
/^s?c/mi8I
|
||||
scat
|
||||
|
||||
/-- End of testinput7 --/
|
||||
|
6
ext/pcre/pcrelib/testdata/testinput8
vendored
6
ext/pcre/pcrelib/testdata/testinput8
vendored
@ -4831,4 +4831,10 @@
|
||||
/[ab]{2,}?/
|
||||
aaaa
|
||||
|
||||
'\A(?:[^\"]++|\"(?:[^\"]*+|\"\")*+\")++'
|
||||
NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED
|
||||
|
||||
'\A(?:[^\"]++|\"(?:[^\"]++|\"\")*+\")++'
|
||||
NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED
|
||||
|
||||
/-- End of testinput8 --/
|
||||
|
100
ext/pcre/pcrelib/testdata/testoutput1
vendored
100
ext/pcre/pcrelib/testdata/testoutput1
vendored
@ -223,7 +223,7 @@ No match
|
||||
babababc
|
||||
No match
|
||||
|
||||
/^\ca\cA\c[\c{\c:/
|
||||
/^\ca\cA\c[;\c:/
|
||||
\x01\x01\e;z
|
||||
0: \x01\x01\x1b;z
|
||||
|
||||
@ -8234,6 +8234,16 @@ MK: M
|
||||
aaaabcde
|
||||
0: aaaab
|
||||
1: aaaab
|
||||
|
||||
/((?(R)a|(?1)))*/
|
||||
aaa
|
||||
0: aaa
|
||||
1: a
|
||||
|
||||
/((?(R)a|(?1)))+/
|
||||
aaa
|
||||
0: aaa
|
||||
1: a
|
||||
|
||||
/a(*:any
|
||||
name)/K
|
||||
@ -9313,4 +9323,92 @@ No match
|
||||
0+ c
|
||||
1: ab
|
||||
|
||||
/(?:x|(?:(xx|yy)+|x|x|x|x|x)|a|a|a)bc/
|
||||
acb
|
||||
No match
|
||||
|
||||
'\A(?:[^\"]++|\"(?:[^\"]*+|\"\")*+\")++'
|
||||
NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED
|
||||
0: NON QUOTED "QUOT""ED" AFTER
|
||||
|
||||
'\A(?:[^\"]++|\"(?:[^\"]++|\"\")*+\")++'
|
||||
NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED
|
||||
0: NON QUOTED "QUOT""ED" AFTER
|
||||
|
||||
'\A(?:[^\"]++|\"(?:[^\"]++|\"\")++\")++'
|
||||
NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED
|
||||
0: NON QUOTED "QUOT""ED" AFTER
|
||||
|
||||
'\A([^\"1]++|[\"2]([^\"3]*+|[\"4][\"5])*+[\"6])++'
|
||||
NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED
|
||||
0: NON QUOTED "QUOT""ED" AFTER
|
||||
1: AFTER
|
||||
2:
|
||||
|
||||
/^\w+(?>\s*)(?<=\w)/
|
||||
test test
|
||||
0: tes
|
||||
|
||||
/(?P<same>a)(?P<same>b)/gJ
|
||||
abbaba
|
||||
0: ab
|
||||
1: a
|
||||
2: b
|
||||
0: ab
|
||||
1: a
|
||||
2: b
|
||||
|
||||
/(?P<same>a)(?P<same>b)(?P=same)/gJ
|
||||
abbaba
|
||||
0: aba
|
||||
1: a
|
||||
2: b
|
||||
|
||||
/(?P=same)?(?P<same>a)(?P<same>b)/gJ
|
||||
abbaba
|
||||
0: ab
|
||||
1: a
|
||||
2: b
|
||||
0: ab
|
||||
1: a
|
||||
2: b
|
||||
|
||||
/(?:(?P=same)?(?:(?P<same>a)|(?P<same>b))(?P=same))+/gJ
|
||||
bbbaaabaabb
|
||||
0: bbbaaaba
|
||||
1: a
|
||||
2: b
|
||||
0: bb
|
||||
1: <unset>
|
||||
2: b
|
||||
|
||||
/(?:(?P=same)?(?:(?P=same)(?P<same>a)(?P=same)|(?P=same)?(?P<same>b)(?P=same)){2}(?P=same)(?P<same>c)(?P=same)){2}(?P<same>z)?/gJ
|
||||
bbbaaaccccaaabbbcc
|
||||
No match
|
||||
|
||||
/(?P<Name>a)?(?P<Name2>b)?(?(<Name>)c|d)*l/
|
||||
acl
|
||||
0: acl
|
||||
1: a
|
||||
bdl
|
||||
0: bdl
|
||||
1: <unset>
|
||||
2: b
|
||||
adl
|
||||
0: dl
|
||||
bcl
|
||||
0: l
|
||||
|
||||
/\sabc/
|
||||
\x{0b}abc
|
||||
0: \x0babc
|
||||
|
||||
/[\Qa]\E]+/
|
||||
aa]]
|
||||
0: aa]]
|
||||
|
||||
/[\Q]a\E]+/
|
||||
aa]]
|
||||
0: aa]]
|
||||
|
||||
/-- End of testinput1 --/
|
||||
|
24
ext/pcre/pcrelib/testdata/testoutput11-16
vendored
24
ext/pcre/pcrelib/testdata/testoutput11-16
vendored
@ -709,4 +709,28 @@ Memory allocation (code space): 14
|
||||
62 End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/(((a\2)|(a*)\g<-1>))*a?/B
|
||||
------------------------------------------------------------------
|
||||
0 39 Bra
|
||||
2 Brazero
|
||||
3 32 SCBra 1
|
||||
6 27 Once
|
||||
8 12 CBra 2
|
||||
11 7 CBra 3
|
||||
14 a
|
||||
16 \2
|
||||
18 7 Ket
|
||||
20 11 Alt
|
||||
22 5 CBra 4
|
||||
25 a*
|
||||
27 5 Ket
|
||||
29 22 Recurse
|
||||
31 23 Ket
|
||||
33 27 Ket
|
||||
35 32 KetRmax
|
||||
37 a?+
|
||||
39 39 Ket
|
||||
41 End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/-- End of testinput11 --/
|
||||
|
24
ext/pcre/pcrelib/testdata/testoutput11-32
vendored
24
ext/pcre/pcrelib/testdata/testoutput11-32
vendored
@ -709,4 +709,28 @@ Memory allocation (code space): 28
|
||||
62 End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/(((a\2)|(a*)\g<-1>))*a?/B
|
||||
------------------------------------------------------------------
|
||||
0 39 Bra
|
||||
2 Brazero
|
||||
3 32 SCBra 1
|
||||
6 27 Once
|
||||
8 12 CBra 2
|
||||
11 7 CBra 3
|
||||
14 a
|
||||
16 \2
|
||||
18 7 Ket
|
||||
20 11 Alt
|
||||
22 5 CBra 4
|
||||
25 a*
|
||||
27 5 Ket
|
||||
29 22 Recurse
|
||||
31 23 Ket
|
||||
33 27 Ket
|
||||
35 32 KetRmax
|
||||
37 a?+
|
||||
39 39 Ket
|
||||
41 End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/-- End of testinput11 --/
|
||||
|
24
ext/pcre/pcrelib/testdata/testoutput11-8
vendored
24
ext/pcre/pcrelib/testdata/testoutput11-8
vendored
@ -709,4 +709,28 @@ Memory allocation (code space): 10
|
||||
76 End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/(((a\2)|(a*)\g<-1>))*a?/B
|
||||
------------------------------------------------------------------
|
||||
0 57 Bra
|
||||
3 Brazero
|
||||
4 48 SCBra 1
|
||||
9 40 Once
|
||||
12 18 CBra 2
|
||||
17 10 CBra 3
|
||||
22 a
|
||||
24 \2
|
||||
27 10 Ket
|
||||
30 16 Alt
|
||||
33 7 CBra 4
|
||||
38 a*
|
||||
40 7 Ket
|
||||
43 33 Recurse
|
||||
46 34 Ket
|
||||
49 40 Ket
|
||||
52 48 KetRmax
|
||||
55 a?+
|
||||
57 57 Ket
|
||||
60 End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/-- End of testinput11 --/
|
||||
|
20
ext/pcre/pcrelib/testdata/testoutput15
vendored
20
ext/pcre/pcrelib/testdata/testoutput15
vendored
@ -871,7 +871,7 @@ Options: utf
|
||||
No first char
|
||||
Need char = 'x'
|
||||
Subject length lower bound = 5
|
||||
Starting chars: \x09 \x0a \x0c \x0d \x20 \xc2
|
||||
Starting chars: \x09 \x0a \x0b \x0c \x0d \x20 \xc2
|
||||
AB\x{85}xxx\x{a0}XYZ
|
||||
0: \x{85}xxx\x{a0}
|
||||
AB\x{a0}xxx\x{85}XYZ
|
||||
@ -883,15 +883,15 @@ Options: utf
|
||||
No first char
|
||||
Need char = ' '
|
||||
Subject length lower bound = 3
|
||||
Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0b \x0e
|
||||
\x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d
|
||||
\x1e \x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @
|
||||
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e
|
||||
f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \xc0 \xc1 \xc2 \xc3
|
||||
\xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2
|
||||
\xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1
|
||||
\xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0
|
||||
\xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff
|
||||
Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0e \x0f
|
||||
\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e
|
||||
\x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C
|
||||
D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h
|
||||
i j k l m n o p q r s t u v w x y z { | } ~ \x7f \xc0 \xc1 \xc2 \xc3 \xc4
|
||||
\xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3
|
||||
\xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2
|
||||
\xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1
|
||||
\xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff
|
||||
\x{a2} \x{84}
|
||||
0: \x{a2} \x{84}
|
||||
A Z
|
||||
|
20
ext/pcre/pcrelib/testdata/testoutput16
vendored
20
ext/pcre/pcrelib/testdata/testoutput16
vendored
@ -118,4 +118,24 @@ Starting chars: \x0a \x0b \x0c \x0d \x85
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/\x{212a}+/i8SI
|
||||
Capturing subpattern count = 0
|
||||
Options: caseless utf
|
||||
No first char
|
||||
No need char
|
||||
Subject length lower bound = 1
|
||||
Starting chars: K k \xe2
|
||||
KKkk\x{212a}
|
||||
0: KKkk\x{212a}
|
||||
|
||||
/s+/i8SI
|
||||
Capturing subpattern count = 0
|
||||
Options: caseless utf
|
||||
No first char
|
||||
No need char
|
||||
Subject length lower bound = 1
|
||||
Starting chars: S s \xc5
|
||||
SSss\x{17f}
|
||||
0: SSss\x{17f}
|
||||
|
||||
/-- End of testinput16 --/
|
||||
|
30
ext/pcre/pcrelib/testdata/testoutput18-16
vendored
30
ext/pcre/pcrelib/testdata/testoutput18-16
vendored
@ -752,7 +752,7 @@ Options: utf
|
||||
No first char
|
||||
Need char = 'x'
|
||||
Subject length lower bound = 5
|
||||
Starting chars: \x09 \x0a \x0c \x0d \x20 \x85 \xa0
|
||||
Starting chars: \x09 \x0a \x0b \x0c \x0d \x20 \x85 \xa0
|
||||
AB\x{85}xxx\x{a0}XYZ
|
||||
0: \x{85}xxx\x{a0}
|
||||
AB\x{a0}xxx\x{85}XYZ
|
||||
@ -764,20 +764,20 @@ Options: utf
|
||||
No first char
|
||||
Need char = ' '
|
||||
Subject length lower bound = 3
|
||||
Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0b \x0e
|
||||
\x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d
|
||||
\x1e \x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @
|
||||
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e
|
||||
f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83
|
||||
\x84 \x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93
|
||||
\x94 \x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa1 \xa2 \xa3
|
||||
\xa4 \xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2
|
||||
\xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xc0 \xc1
|
||||
\xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0
|
||||
\xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf
|
||||
\xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee
|
||||
\xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd
|
||||
\xfe \xff
|
||||
Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0e \x0f
|
||||
\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e
|
||||
\x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C
|
||||
D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h
|
||||
i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84
|
||||
\x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94
|
||||
\x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa1 \xa2 \xa3 \xa4
|
||||
\xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2 \xb3
|
||||
\xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xc0 \xc1 \xc2
|
||||
\xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1
|
||||
\xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0
|
||||
\xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef
|
||||
\xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe
|
||||
\xff
|
||||
\x{a2} \x{84}
|
||||
0: \x{a2} \x{84}
|
||||
A Z
|
||||
|
30
ext/pcre/pcrelib/testdata/testoutput18-32
vendored
30
ext/pcre/pcrelib/testdata/testoutput18-32
vendored
@ -749,7 +749,7 @@ Options: utf
|
||||
No first char
|
||||
Need char = 'x'
|
||||
Subject length lower bound = 5
|
||||
Starting chars: \x09 \x0a \x0c \x0d \x20 \x85 \xa0
|
||||
Starting chars: \x09 \x0a \x0b \x0c \x0d \x20 \x85 \xa0
|
||||
AB\x{85}xxx\x{a0}XYZ
|
||||
0: \x{85}xxx\x{a0}
|
||||
AB\x{a0}xxx\x{85}XYZ
|
||||
@ -761,20 +761,20 @@ Options: utf
|
||||
No first char
|
||||
Need char = ' '
|
||||
Subject length lower bound = 3
|
||||
Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0b \x0e
|
||||
\x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d
|
||||
\x1e \x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @
|
||||
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e
|
||||
f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83
|
||||
\x84 \x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93
|
||||
\x94 \x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa1 \xa2 \xa3
|
||||
\xa4 \xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2
|
||||
\xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xc0 \xc1
|
||||
\xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0
|
||||
\xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf
|
||||
\xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee
|
||||
\xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd
|
||||
\xfe \xff
|
||||
Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0e \x0f
|
||||
\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e
|
||||
\x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C
|
||||
D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h
|
||||
i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84
|
||||
\x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94
|
||||
\x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa1 \xa2 \xa3 \xa4
|
||||
\xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2 \xb3
|
||||
\xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xc0 \xc1 \xc2
|
||||
\xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1
|
||||
\xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0
|
||||
\xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef
|
||||
\xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe
|
||||
\xff
|
||||
\x{a2} \x{84}
|
||||
0: \x{a2} \x{84}
|
||||
A Z
|
||||
|
20
ext/pcre/pcrelib/testdata/testoutput19
vendored
20
ext/pcre/pcrelib/testdata/testoutput19
vendored
@ -85,4 +85,24 @@ No starting char list
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/\x{212a}+/i8SI
|
||||
Capturing subpattern count = 0
|
||||
Options: caseless utf
|
||||
No first char
|
||||
No need char
|
||||
Subject length lower bound = 1
|
||||
Starting chars: K k \xff
|
||||
KKkk\x{212a}
|
||||
0: KKkk\x{212a}
|
||||
|
||||
/s+/i8SI
|
||||
Capturing subpattern count = 0
|
||||
Options: caseless utf
|
||||
No first char
|
||||
No need char
|
||||
Subject length lower bound = 1
|
||||
Starting chars: S s \xff
|
||||
SSss\x{17f}
|
||||
0: SSss\x{17f}
|
||||
|
||||
/-- End of testinput19 --/
|
||||
|
63
ext/pcre/pcrelib/testdata/testoutput2
vendored
63
ext/pcre/pcrelib/testdata/testoutput2
vendored
@ -5821,13 +5821,13 @@ No match
|
||||
No match
|
||||
|
||||
/a{11111111111111111111}/I
|
||||
Failed: number too big in {} quantifier at offset 22
|
||||
Failed: number too big in {} quantifier at offset 8
|
||||
|
||||
/(){64294967295}/I
|
||||
Failed: number too big in {} quantifier at offset 14
|
||||
Failed: number too big in {} quantifier at offset 9
|
||||
|
||||
/(){2,4294967295}/I
|
||||
Failed: number too big in {} quantifier at offset 15
|
||||
Failed: number too big in {} quantifier at offset 11
|
||||
|
||||
"(?i:a)(?i:b)(?i:c)(?i:d)(?i:e)(?i:f)(?i:g)(?i:h)(?i:i)(?i:j)(k)(?i:l)A\1B"I
|
||||
Capturing subpattern count = 1
|
||||
@ -14093,6 +14093,30 @@ Failed: malformed number or name after (?( at offset 4
|
||||
/(?(R&6yh)abc)/
|
||||
Failed: group name must start with a non-digit at offset 5
|
||||
|
||||
/(((a\2)|(a*)\g<-1>))*a?/BZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
Brazero
|
||||
SCBra 1
|
||||
Once
|
||||
CBra 2
|
||||
CBra 3
|
||||
a
|
||||
\2
|
||||
Ket
|
||||
Alt
|
||||
CBra 4
|
||||
a*
|
||||
Ket
|
||||
Recurse
|
||||
Ket
|
||||
Ket
|
||||
KetRmax
|
||||
a?+
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/-- Test the ugly "start or end of word" compatibility syntax --/
|
||||
|
||||
/[[:<:]]red[[:>:]]/BZ
|
||||
@ -14149,4 +14173,37 @@ Failed: parentheses are too deeply nested (stack check) at offset 0
|
||||
/(((((a)))))/Q
|
||||
** Missing 0 or 1 after /Q
|
||||
|
||||
/^\w+(?>\s*)(?<=\w)/BZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
^
|
||||
\w+
|
||||
Once_NC
|
||||
\s*+
|
||||
Ket
|
||||
AssertB
|
||||
Reverse
|
||||
\w
|
||||
Ket
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/\othing/
|
||||
Failed: missing opening brace after \o at offset 1
|
||||
|
||||
/\o{}/
|
||||
Failed: digits missing in \x{} or \o{} at offset 1
|
||||
|
||||
/\o{whatever}/
|
||||
Failed: non-octal character in \o{} (closing brace missing?) at offset 3
|
||||
|
||||
/\xthing/
|
||||
|
||||
/\x{}/
|
||||
Failed: digits missing in \x{} or \o{} at offset 3
|
||||
|
||||
/\x{whatever}/
|
||||
Failed: non-hex character in \x{} (closing brace missing?) at offset 3
|
||||
|
||||
/-- End of testinput2 --/
|
||||
|
8
ext/pcre/pcrelib/testdata/testoutput6
vendored
8
ext/pcre/pcrelib/testdata/testoutput6
vendored
@ -719,9 +719,9 @@ No match
|
||||
0: \x{6e9}
|
||||
\x{060b}
|
||||
0: \x{60b}
|
||||
\x{061c}
|
||||
0: \x{61c}
|
||||
** Failers
|
||||
No match
|
||||
\x{061c}
|
||||
No match
|
||||
X\x{06e9}
|
||||
No match
|
||||
@ -2457,4 +2457,8 @@ No match
|
||||
Ss\x{17f}
|
||||
0: Ss\x{17f}
|
||||
|
||||
/^s?c/mi8
|
||||
scat
|
||||
0: sc
|
||||
|
||||
/-- End of testinput6 --/
|
||||
|
8
ext/pcre/pcrelib/testdata/testoutput7
vendored
8
ext/pcre/pcrelib/testdata/testoutput7
vendored
@ -2287,4 +2287,12 @@ No match
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/^s?c/mi8I
|
||||
Capturing subpattern count = 0
|
||||
Options: caseless multiline utf
|
||||
First char at start or follows newline
|
||||
Need char = 'c' (caseless)
|
||||
scat
|
||||
0: sc
|
||||
|
||||
/-- End of testinput7 --/
|
||||
|
8
ext/pcre/pcrelib/testdata/testoutput8
vendored
8
ext/pcre/pcrelib/testdata/testoutput8
vendored
@ -7777,4 +7777,12 @@ Matched, but offsets vector is too small to show all matches
|
||||
1: aaa
|
||||
2: aa
|
||||
|
||||
'\A(?:[^\"]++|\"(?:[^\"]*+|\"\")*+\")++'
|
||||
NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED
|
||||
0: NON QUOTED "QUOT""ED" AFTER
|
||||
|
||||
'\A(?:[^\"]++|\"(?:[^\"]++|\"\")*+\")++'
|
||||
NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED
|
||||
0: NON QUOTED "QUOT""ED" AFTER
|
||||
|
||||
/-- End of testinput8 --/
|
||||
|
@ -192,7 +192,31 @@ enum {
|
||||
ucp_Miao,
|
||||
ucp_Sharada,
|
||||
ucp_Sora_Sompeng,
|
||||
ucp_Takri
|
||||
ucp_Takri,
|
||||
/* New for Unicode 7.0.0: */
|
||||
ucp_Bassa_Vah,
|
||||
ucp_Caucasian_Albanian,
|
||||
ucp_Duployan,
|
||||
ucp_Elbasan,
|
||||
ucp_Grantha,
|
||||
ucp_Khojki,
|
||||
ucp_Khudawadi,
|
||||
ucp_Linear_A,
|
||||
ucp_Mahajani,
|
||||
ucp_Manichaean,
|
||||
ucp_Mende_Kikakui,
|
||||
ucp_Modi,
|
||||
ucp_Mro,
|
||||
ucp_Nabataean,
|
||||
ucp_Old_North_Arabian,
|
||||
ucp_Old_Permic,
|
||||
ucp_Pahawh_Hmong,
|
||||
ucp_Palmyrene,
|
||||
ucp_Psalter_Pahlavi,
|
||||
ucp_Pau_Cin_Hau,
|
||||
ucp_Siddham,
|
||||
ucp_Tirhuta,
|
||||
ucp_Warang_Citi
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user