Merge branch 'pull-request/1047'

This commit is contained in:
Anatol Belski 2015-02-06 11:18:46 +01:00
commit 20a194a92c
57 changed files with 6578 additions and 4613 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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
--------------------------

View File

@ -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

View File

@ -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 */

View File

@ -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.

View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -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]);

View File

@ -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 */

View File

@ -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) \

View File

@ -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);

View File

@ -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();
}

View File

@ -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

View File

@ -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));

View File

@ -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)));

View File

@ -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))

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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));

View File

@ -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;

View File

@ -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));
}

View File

@ -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

View File

@ -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;
}

View File

@ -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)

View File

@ -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 --/

View File

@ -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 --/

View File

@ -32,4 +32,10 @@
/[[:blank:]]/WBZ
/\x{212a}+/i8SI
KKkk\x{212a}
/s+/i8SI
SSss\x{17f}
/-- End of testinput16 --/

View File

@ -19,4 +19,10 @@
/[[:blank:]]/WBZ
/\x{212a}+/i8SI
KKkk\x{212a}
/s+/i8SI
SSss\x{17f}
/-- End of testinput19 --/

View File

@ -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 --/

View File

@ -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 --/

View File

@ -835,4 +835,7 @@ of case for anything other than the ASCII letters. --/
/[Q-U]+/8iWBZ
/^s?c/mi8I
scat
/-- End of testinput7 --/

View File

@ -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 --/

View File

@ -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 --/

View File

@ -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 --/

View File

@ -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 --/

View File

@ -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 --/

View File

@ -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

View File

@ -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 --/

View File

@ -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

View File

@ -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

View File

@ -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 --/

View File

@ -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 --/

View File

@ -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 --/

View File

@ -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 --/

View File

@ -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 --/

View File

@ -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