mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Merge branch 'sccp' into dce
* sccp: (29 commits) Use existing bit Updated Windows build Fixed compilation error Remove debug code We need to check for the length here too, or we crash and no one likes that! :( * Implemented #65187 (exif_read_data/thumbnail: add support for stream resource) * ext/exif now uses FAST_ZPP Remove extraneous configure flag Revert "remove excessive checks and fix warnings" parametrize zip names Upgrade bundled PCRE to 8.41 Updated NEWS file with LDAP changes Fixed removing all controls by passing an empty array to ldap_set_option Filled in NEWS file with ext/ldap last modifications change order, allow to build as shared extension restore file deleted by mistake in a merge commit Fix segfault in php_stream_context_get_option call remove excessive checks and fix warnings fix macro redifinitions fix symbol availability and ws Remove this for now, as not found ...
This commit is contained in:
commit
de5e8fc129
121 changed files with 18123 additions and 9024 deletions
|
@ -24,7 +24,7 @@ environment:
|
|||
PHP_BUILD_CACHE_BASE_DIR: c:\build-cache
|
||||
PHP_BUILD_OBJ_DIR: c:\obj
|
||||
PHP_BUILD_CACHE_SDK_DIR: c:\build-cache\sdk
|
||||
PHP_BUILD_SDK_BRANCH: php-sdk-2.0.5
|
||||
PHP_BUILD_SDK_BRANCH: php-sdk-2.0.7
|
||||
PHP_BUILD_CRT: vc15
|
||||
# ext and env setup for tests
|
||||
#MYSQL_TEST_PASSWD: Password12!
|
||||
|
|
|
@ -419,6 +419,12 @@ MAINTENANCE: Maintained
|
|||
STATUS: Working
|
||||
SINCE: 4.0.2
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sodium
|
||||
PRIMARY MAINTAINER: Frank Denis <jedisct1@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 7.2.0
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: spl
|
||||
PRIMARY MAINTAINER: Marcus Boerger <helly@php.net>, Etienne Kneuss <colder@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
|
|
13
NEWS
13
NEWS
|
@ -21,6 +21,8 @@ PHP NEWS
|
|||
(Andreas Treichel)
|
||||
|
||||
- EXIF:
|
||||
. Implemented #65187 (exif_read_data/thumbnail: add support for stream
|
||||
resource). (Kalle)
|
||||
. Deprecated the read_exif_data() alias. (Kalle)
|
||||
. Fixed bug #74428 (exif_read_data(): "Illegal IFD size" warning occurs with
|
||||
correct exif format). (bradpiccho at gmail dot com, Kalle)
|
||||
|
@ -37,6 +39,9 @@ PHP NEWS
|
|||
. Fixed bug #72324 (imap_mailboxmsginfo() return wrong size).
|
||||
(ronaldpoon at udomain dot com dot hk, Kalle)
|
||||
|
||||
- LDAP:
|
||||
. Fixed passing an empty array to ldap_set_option for client or server controls.
|
||||
|
||||
- OpenSSL:
|
||||
. Fixed bug #74651 (negative-size-param (-1) in memcpy in zif_openssl_seal()).
|
||||
(Stas)
|
||||
|
@ -45,12 +50,16 @@ PHP NEWS
|
|||
. Fixed bug #74873 (Minor BC break: PCRE_JIT changes output of preg_match()).
|
||||
(Dmitry)
|
||||
|
||||
- Sodium:
|
||||
. New cryptographic extension
|
||||
|
||||
- SQLite3:
|
||||
. Fixed bug #74883 (SQLite3::__construct() produces "out of memory" exception
|
||||
with invalid flags). (Anatol)
|
||||
|
||||
- ZIP:
|
||||
. ZipArchive implements countable, added ZipArchive::count() method. (Remi)
|
||||
. Fix segfault in php_stream_context_get_option call. (Remi)
|
||||
|
||||
06 Jul 2017, PHP 7.2.0alpha3
|
||||
|
||||
|
@ -72,6 +81,10 @@ PHP NEWS
|
|||
. Fixed bug #74849 (Process is started as interactive shell in PhpStorm).
|
||||
(Anatol)
|
||||
|
||||
- LDAP:
|
||||
. Implemented FR #69445 (Support for LDAP EXOP operations)
|
||||
. Fixed support for LDAP_OPT_SERVER_CONTROLS and LDAP_OPT_CLIENT_CONTROLS in ldap_get_option
|
||||
|
||||
- OpenSSL:
|
||||
. Fixed bug #74798 (pkcs7_en/decrypt does not work if \x0a is used in content).
|
||||
(Anatol)
|
||||
|
|
|
@ -124,6 +124,9 @@ PHP 7.2 UPGRADE NOTES
|
|||
subpatterns and empty matches by reporting NULL and "" (empty string),
|
||||
respectively.
|
||||
|
||||
- Sodium
|
||||
. New cryptographic extension
|
||||
|
||||
- SQLite3:
|
||||
. Implemented writing to BLOBs.
|
||||
|
||||
|
@ -270,6 +273,8 @@ See also: https://wiki.php.net/rfc/deprecations_php_7_2
|
|||
. Added extended exif tag support for the following formats:
|
||||
Samsung, DJI, Panasonic, Sony, Pentax, Minolta, Sigma/Foveon,
|
||||
AGFA, Kyocera, Ricoh & Epson.
|
||||
. exif_read_data() and exif_thumbnail() now supports a passed streams as their
|
||||
first parameter.
|
||||
|
||||
- GD:
|
||||
. Removed --enable-gd-native-ttf configuration option which was unused as
|
||||
|
|
146
ext/exif/exif.c
146
ext/exif/exif.c
|
@ -4305,33 +4305,35 @@ static int exif_discard_imageinfo(image_info_type *ImageInfo)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ exif_read_file
|
||||
/* {{{ exif_read_from_stream
|
||||
*/
|
||||
static int exif_read_file(image_info_type *ImageInfo, char *FileName, int read_thumbnail, int read_all)
|
||||
static int exif_read_from_stream(image_info_type *ImageInfo, php_stream *stream, int read_thumbnail, int read_all)
|
||||
{
|
||||
int ret;
|
||||
zend_stat_t st;
|
||||
zend_string *base;
|
||||
|
||||
/* Start with an empty image information structure. */
|
||||
memset(ImageInfo, 0, sizeof(*ImageInfo));
|
||||
|
||||
ImageInfo->motorola_intel = -1; /* flag as unknown */
|
||||
|
||||
ImageInfo->infile = php_stream_open_wrapper(FileName, "rb", STREAM_MUST_SEEK|IGNORE_PATH, NULL);
|
||||
if (!ImageInfo->infile) {
|
||||
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Unable to open file");
|
||||
return FALSE;
|
||||
}
|
||||
ImageInfo->infile = stream;
|
||||
ImageInfo->FileName = NULL;
|
||||
|
||||
if (php_stream_is(ImageInfo->infile, PHP_STREAM_IS_STDIO)) {
|
||||
if (VCWD_STAT(FileName, &st) >= 0) {
|
||||
if (VCWD_STAT(stream->orig_path, &st) >= 0) {
|
||||
zend_string *base;
|
||||
if ((st.st_mode & S_IFMT) != S_IFREG) {
|
||||
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Not a file");
|
||||
php_stream_close(ImageInfo->infile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Store file name */
|
||||
base = php_basename(stream->orig_path, strlen(stream->orig_path), NULL, 0);
|
||||
ImageInfo->FileName = estrndup(ZSTR_VAL(base), ZSTR_LEN(base));
|
||||
|
||||
zend_string_release(base);
|
||||
|
||||
/* Store file date/time. */
|
||||
ImageInfo->FileDateTime = st.st_mtime;
|
||||
ImageInfo->FileSize = st.st_size;
|
||||
|
@ -4345,9 +4347,6 @@ static int exif_read_file(image_info_type *ImageInfo, char *FileName, int read_t
|
|||
}
|
||||
}
|
||||
|
||||
base = php_basename(FileName, strlen(FileName), NULL, 0);
|
||||
ImageInfo->FileName = estrndup(ZSTR_VAL(base), ZSTR_LEN(base));
|
||||
zend_string_release(base);
|
||||
ImageInfo->read_thumbnail = read_thumbnail;
|
||||
ImageInfo->read_all = read_all;
|
||||
ImageInfo->Thumbnail.filetype = IMAGE_FILETYPE_UNKNOWN;
|
||||
|
@ -4362,34 +4361,62 @@ static int exif_read_file(image_info_type *ImageInfo, char *FileName, int read_t
|
|||
|
||||
ImageInfo->ifd_nesting_level = 0;
|
||||
|
||||
/* Scan the JPEG headers. */
|
||||
/* Scan the headers */
|
||||
ret = exif_scan_FILE_header(ImageInfo);
|
||||
|
||||
php_stream_close(ImageInfo->infile);
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array exif_read_data(string filename [, string sections_needed [, bool sub_arrays[, bool read_thumbnail]]])
|
||||
Reads header data from the JPEG/TIFF image filename and optionally reads the internal thumbnails */
|
||||
/* {{{ exif_read_from_file
|
||||
*/
|
||||
static int exif_read_from_file(image_info_type *ImageInfo, char *FileName, int read_thumbnail, int read_all)
|
||||
{
|
||||
int ret;
|
||||
php_stream *stream;
|
||||
|
||||
stream = php_stream_open_wrapper(FileName, "rb", STREAM_MUST_SEEK | IGNORE_PATH, NULL);
|
||||
|
||||
if (!stream) {
|
||||
memset(&ImageInfo, 0, sizeof(ImageInfo));
|
||||
|
||||
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Unable to open file");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret = exif_read_from_stream(ImageInfo, stream, read_thumbnail, read_all);
|
||||
|
||||
php_stream_close(stream);
|
||||
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array exif_read_data(mixed stream [, string sections_needed [, bool sub_arrays[, bool read_thumbnail]]])
|
||||
Reads header data from an image and optionally reads the internal thumbnails */
|
||||
PHP_FUNCTION(exif_read_data)
|
||||
{
|
||||
char *p_name, *p_sections_needed = NULL;
|
||||
size_t p_name_len, p_sections_needed_len = 0;
|
||||
zend_string *z_sections_needed = NULL;
|
||||
zend_bool sub_arrays = 0, read_thumbnail = 0, read_all = 0;
|
||||
|
||||
zval *stream;
|
||||
int i, ret, sections_needed = 0;
|
||||
image_info_type ImageInfo;
|
||||
char tmp[64], *sections_str, *s;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|sbb", &p_name, &p_name_len, &p_sections_needed, &p_sections_needed_len, &sub_arrays, &read_thumbnail) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
/* Parse arguments */
|
||||
ZEND_PARSE_PARAMETERS_START(1, 4)
|
||||
Z_PARAM_ZVAL(stream)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_STR(z_sections_needed)
|
||||
Z_PARAM_BOOL(sub_arrays)
|
||||
Z_PARAM_BOOL(read_thumbnail)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
memset(&ImageInfo, 0, sizeof(ImageInfo));
|
||||
|
||||
if (p_sections_needed) {
|
||||
spprintf(§ions_str, 0, ",%s,", p_sections_needed);
|
||||
if (z_sections_needed) {
|
||||
spprintf(§ions_str, 0, ",%s,", ZSTR_VAL(z_sections_needed));
|
||||
/* sections_str DOES start with , and SPACES are NOT allowed in names */
|
||||
s = sections_str;
|
||||
while (*++s) {
|
||||
|
@ -4409,19 +4436,39 @@ PHP_FUNCTION(exif_read_data)
|
|||
#ifdef EXIF_DEBUG
|
||||
sections_str = exif_get_sectionlist(sections_needed);
|
||||
if (!sections_str) {
|
||||
zend_string_release(z_sections_needed);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
exif_error_docref(NULL EXIFERR_CC, &ImageInfo, E_NOTICE, "Sections needed: %s", sections_str[0] ? sections_str : "None");
|
||||
EFREE_IF(sections_str);
|
||||
#endif
|
||||
zend_string_release(z_sections_needed);
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(stream) == IS_RESOURCE) {
|
||||
php_stream *p_stream = NULL;
|
||||
|
||||
php_stream_from_res(p_stream, Z_RES_P(stream));
|
||||
|
||||
ret = exif_read_from_stream(&ImageInfo, p_stream, read_thumbnail, read_all);
|
||||
} else {
|
||||
convert_to_string(stream);
|
||||
|
||||
if (!Z_STRLEN_P(stream)) {
|
||||
exif_error_docref(NULL EXIFERR_CC, &ImageInfo, E_WARNING, "Filename cannot be empty");
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ret = exif_read_from_file(&ImageInfo, Z_STRVAL_P(stream), read_thumbnail, read_all);
|
||||
}
|
||||
|
||||
ret = exif_read_file(&ImageInfo, p_name, read_thumbnail, read_all);
|
||||
sections_str = exif_get_sectionlist(ImageInfo.sections_found);
|
||||
|
||||
#ifdef EXIF_DEBUG
|
||||
if (sections_str)
|
||||
if (sections_str) {
|
||||
exif_error_docref(NULL EXIFERR_CC, &ImageInfo, E_NOTICE, "Sections found: %s", sections_str[0] ? sections_str : "None");
|
||||
}
|
||||
#endif
|
||||
|
||||
ImageInfo.sections_found |= FOUND_COMPUTED|FOUND_FILE;/* do not inform about in debug*/
|
||||
|
@ -4552,23 +4599,40 @@ PHP_FUNCTION(exif_read_data)
|
|||
Reads the embedded thumbnail */
|
||||
PHP_FUNCTION(exif_thumbnail)
|
||||
{
|
||||
zval *p_width = 0, *p_height = 0, *p_imagetype = 0;
|
||||
char *p_name;
|
||||
size_t p_name_len;
|
||||
int ret, arg_c = ZEND_NUM_ARGS();
|
||||
image_info_type ImageInfo;
|
||||
zval *stream;
|
||||
zval *z_width = NULL, *z_height = NULL, *z_imagetype = NULL;
|
||||
|
||||
/* Parse arguments */
|
||||
ZEND_PARSE_PARAMETERS_START(1, 4)
|
||||
Z_PARAM_ZVAL(stream)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_ZVAL_DEREF(z_width)
|
||||
Z_PARAM_ZVAL_DEREF(z_height)
|
||||
Z_PARAM_ZVAL_DEREF(z_imagetype)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
memset(&ImageInfo, 0, sizeof(ImageInfo));
|
||||
|
||||
if (arg_c!=1 && arg_c!=3 && arg_c!=4) {
|
||||
WRONG_PARAM_COUNT;
|
||||
if (Z_TYPE_P(stream) == IS_RESOURCE) {
|
||||
php_stream *p_stream = NULL;
|
||||
|
||||
php_stream_from_res(p_stream, Z_RES_P(stream));
|
||||
|
||||
ret = exif_read_from_stream(&ImageInfo, p_stream, 1, 0);
|
||||
} else {
|
||||
convert_to_string(stream);
|
||||
|
||||
if (!Z_STRLEN_P(stream)) {
|
||||
exif_error_docref(NULL EXIFERR_CC, &ImageInfo, E_WARNING, "Filename cannot be empty");
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (zend_parse_parameters(arg_c, "p|z/z/z/", &p_name, &p_name_len, &p_width, &p_height, &p_imagetype) == FAILURE) {
|
||||
return;
|
||||
ret = exif_read_from_file(&ImageInfo, Z_STRVAL_P(stream), 1, 0);
|
||||
}
|
||||
|
||||
ret = exif_read_file(&ImageInfo, p_name, 1, 0);
|
||||
if (ret == FALSE) {
|
||||
exif_discard_imageinfo(&ImageInfo);
|
||||
RETURN_FALSE;
|
||||
|
@ -4591,14 +4655,14 @@ PHP_FUNCTION(exif_thumbnail)
|
|||
if (!ImageInfo.Thumbnail.width || !ImageInfo.Thumbnail.height) {
|
||||
exif_scan_thumbnail(&ImageInfo);
|
||||
}
|
||||
zval_dtor(p_width);
|
||||
zval_dtor(p_height);
|
||||
ZVAL_LONG(p_width, ImageInfo.Thumbnail.width);
|
||||
ZVAL_LONG(p_height, ImageInfo.Thumbnail.height);
|
||||
zval_dtor(z_width);
|
||||
zval_dtor(z_height);
|
||||
ZVAL_LONG(z_width, ImageInfo.Thumbnail.width);
|
||||
ZVAL_LONG(z_height, ImageInfo.Thumbnail.height);
|
||||
}
|
||||
if (arg_c >= 4) {
|
||||
zval_dtor(p_imagetype);
|
||||
ZVAL_LONG(p_imagetype, ImageInfo.Thumbnail.filetype);
|
||||
zval_dtor(z_imagetype);
|
||||
ZVAL_LONG(z_imagetype, ImageInfo.Thumbnail.filetype);
|
||||
}
|
||||
|
||||
#ifdef EXIF_DEBUG
|
||||
|
|
1634
ext/exif/tests/exif_read_data_streams.phpt
Normal file
1634
ext/exif/tests/exif_read_data_streams.phpt
Normal file
File diff suppressed because it is too large
Load diff
17
ext/exif/tests/exif_thumbnail_streams.phpt
Normal file
17
ext/exif/tests/exif_thumbnail_streams.phpt
Normal file
|
@ -0,0 +1,17 @@
|
|||
--TEST--
|
||||
exif_thumbnail() with streams test
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
|
||||
--INI--
|
||||
output_handler=
|
||||
zlib.output_compression=0
|
||||
--FILE--
|
||||
<?php
|
||||
$fp = fopen(__DIR__ . '/sony.jpg', 'rb');
|
||||
|
||||
var_dump(strlen(exif_thumbnail($fp)));
|
||||
|
||||
fclose($fp);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(4150)
|
|
@ -2540,10 +2540,11 @@ PHP_FUNCTION(ldap_set_option)
|
|||
int ncontrols;
|
||||
char error=0;
|
||||
|
||||
if ((Z_TYPE_P(newval) != IS_ARRAY) || !(ncontrols = zend_hash_num_elements(Z_ARRVAL_P(newval)))) {
|
||||
php_error_docref(NULL, E_WARNING, "Expected non-empty array value for this option");
|
||||
if (Z_TYPE_P(newval) != IS_ARRAY) {
|
||||
php_error_docref(NULL, E_WARNING, "Expected array value for this option");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
ncontrols = zend_hash_num_elements(Z_ARRVAL_P(newval));
|
||||
ctrls = safe_emalloc((1 + ncontrols), sizeof(*ctrls), 0);
|
||||
*ctrls = NULL;
|
||||
ctrlp = ctrls;
|
||||
|
|
|
@ -43,7 +43,9 @@ var_dump(
|
|||
$controls_get[0]['iscritical'],
|
||||
bin2hex($controls_get[0]['value']),
|
||||
$result = ldap_search($link, $base, "(objectClass=person)", array('cn')),
|
||||
ldap_get_entries($link, $result)['count']
|
||||
ldap_get_entries($link, $result)['count'],
|
||||
ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, array()),
|
||||
ldap_get_option($link, LDAP_OPT_SERVER_CONTROLS, $controls_get)
|
||||
);
|
||||
?>
|
||||
===DONE===
|
||||
|
@ -65,4 +67,6 @@ bool(true)
|
|||
string(14) "30050201010400"
|
||||
resource(%d) of type (ldap result)
|
||||
int(1)
|
||||
bool(true)
|
||||
bool(false)
|
||||
===DONE===
|
||||
|
|
|
@ -465,7 +465,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
|
|||
remove_nops = 1;
|
||||
}
|
||||
}
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_SCCP_PASS) {
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_8) {
|
||||
zend_dump_op_array(op_array, ZEND_DUMP_SSA, "after sccp pass", ssa);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,6 @@
|
|||
#define ZEND_DUMP_DFA_PHI (1<<26)
|
||||
#define ZEND_DUMP_DFA_SSA (1<<27)
|
||||
#define ZEND_DUMP_DFA_SSA_VARS (1<<28)
|
||||
#define ZEND_DUMP_AFTER_SCCP_PASS (1<<29)
|
||||
#define ZEND_DUMP_AFTER_DCE_PASS (1<<30)
|
||||
|
||||
typedef struct _zend_script {
|
||||
|
|
|
@ -23,7 +23,7 @@ if (PHP_OPCACHE != "no") {
|
|||
zend_shared_alloc.c \
|
||||
shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
|
||||
|
||||
ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c pass1_5.c pass2.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dfg.c dfa_pass.c zend_ssa.c zend_inference.c zend_func_info.c zend_call_graph.c zend_dump.c", "opcache", "OptimizerObj");
|
||||
ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c pass1_5.c pass2.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dfg.c dfa_pass.c zend_ssa.c zend_inference.c zend_func_info.c zend_call_graph.c sccp.c scdf.c zend_dump.c", "opcache", "OptimizerObj");
|
||||
|
||||
|
||||
ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname);
|
||||
|
|
|
@ -78,3 +78,29 @@ PHP_ARG_WITH(pcre-jit,,[ --with-pcre-jit Enable PCRE JIT functionality]
|
|||
fi
|
||||
fi
|
||||
|
||||
PHP_ARG_WITH(pcre-valgrind,,[ --with-pcre-valgrind=DIR
|
||||
Enable PCRE valgrind support. Developers only!], no, no)
|
||||
if test "$PHP_PCRE_REGEX" != "yes" && test "$PHP_PCRE_REGEX" != "no"; then
|
||||
AC_MSG_WARN([PHP is going to be linked with an external PCRE, --with-pcre-valgrind has no effect])
|
||||
else
|
||||
if test "$PHP_PCRE_VALGRIND" != "no"; then
|
||||
PHP_PCRE_VALGRIND_INCDIR=
|
||||
AC_MSG_CHECKING([for Valgrind headers location])
|
||||
for i in $PHP_PCRE_VALGRIND $PHP_PCRE_VALGRIND/include $PHP_PCRE_VALGRIND/local/include /usr/include /usr/local/include; do
|
||||
if test -f $i/valgrind/memcheck.h
|
||||
then
|
||||
PHP_PCRE_VALGRIND_INCDIR=$i
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$PHP_PCRE_VALGRIND_INCDIR"
|
||||
then
|
||||
AC_MSG_ERROR([Could not find valgrind/memcheck.h])
|
||||
else
|
||||
AC_DEFINE(HAVE_PCRE_VALGRIND_SUPPORT, 1, [ ])
|
||||
PHP_ADD_INCLUDE($PHP_PCRE_VALGRIND_INCDIR)
|
||||
AC_MSG_RESULT([$PHP_PCRE_VALGRIND_INCDIR])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ Email domain: cam.ac.uk
|
|||
University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2015 University of Cambridge
|
||||
Copyright (c) 1997-2017 University of Cambridge
|
||||
All rights reserved
|
||||
|
||||
|
||||
|
@ -19,7 +19,7 @@ Written by: Zoltan Herczeg
|
|||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2010-2015 Zoltan Herczeg
|
||||
Copyright(c) 2010-2017 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
@ -30,7 +30,7 @@ Written by: Zoltan Herczeg
|
|||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2009-2015 Zoltan Herczeg
|
||||
Copyright(c) 2009-2017 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
|
|
@ -4,12 +4,198 @@ ChangeLog for PCRE
|
|||
Note that the PCRE 8.xx series (PCRE1) is now in a bugfix-only state. All
|
||||
development is happening in the PCRE2 10.xx series.
|
||||
|
||||
Version 8.41 05-July-2017
|
||||
-------------------------
|
||||
|
||||
1. Fixed typo in CMakeLists.txt (wrong number of arguments for
|
||||
PCRE_STATIC_RUNTIME (affects MSVC only).
|
||||
|
||||
2. Issue 1 for 8.40 below was not correctly fixed. If pcregrep in multiline
|
||||
mode with --only-matching matched several lines, it restarted scanning at the
|
||||
next line instead of moving on to the end of the matched string, which can be
|
||||
several lines after the start.
|
||||
|
||||
3. Fix a missing else in the JIT compiler reported by 'idaifish'.
|
||||
|
||||
4. A (?# style comment is now ignored between a basic quantifier and a
|
||||
following '+' or '?' (example: /X+(?#comment)?Y/.
|
||||
|
||||
5. Avoid use of a potentially overflowing buffer in pcregrep (patch by Petr
|
||||
Pisar).
|
||||
|
||||
6. Fuzzers have reported issues in pcretest. These are NOT serious (it is,
|
||||
after all, just a test program). However, to stop the reports, some easy ones
|
||||
are fixed:
|
||||
|
||||
(a) Check for values < 256 when calling isprint() in pcretest.
|
||||
(b) Give an error for too big a number after \O.
|
||||
|
||||
7. In the 32-bit library in non-UTF mode, an attempt to find a Unicode
|
||||
property for a character with a code point greater than 0x10ffff (the Unicode
|
||||
maximum) caused a crash.
|
||||
|
||||
8. The alternative matching function, pcre_dfa_exec() misbehaved if it
|
||||
encountered a character class with a possessive repeat, for example [a-f]{3}+.
|
||||
|
||||
9. When pcretest called pcre_copy_substring() in 32-bit mode, it set the buffer
|
||||
length incorrectly, which could result in buffer overflow.
|
||||
|
||||
10. Remove redundant line of code (accidentally left in ages ago).
|
||||
|
||||
11. Applied C++ patch from Irfan Adilovic to guard 'using std::' directives
|
||||
with namespace pcrecpp (Bugzilla #2084).
|
||||
|
||||
12. Remove a duplication typo in pcre_tables.c.
|
||||
|
||||
13. Fix returned offsets from regexec() when REG_STARTEND is used with a
|
||||
starting offset greater than zero.
|
||||
|
||||
|
||||
Version 8.40 11-January-2017
|
||||
----------------------------
|
||||
|
||||
1. Using -o with -M in pcregrep could cause unnecessary repeated output when
|
||||
the match extended over a line boundary.
|
||||
|
||||
2. Applied Chris Wilson's second patch (Bugzilla #1681) to CMakeLists.txt for
|
||||
MSVC static compilation, putting the first patch under a new option.
|
||||
|
||||
3. Fix register overwite in JIT when SSE2 acceleration is enabled.
|
||||
|
||||
4. Ignore "show all captures" (/=) for DFA matching.
|
||||
|
||||
5. Fix JIT unaligned accesses on x86. Patch by Marc Mutz.
|
||||
|
||||
6. In any wide-character mode (8-bit UTF or any 16-bit or 32-bit mode),
|
||||
without PCRE_UCP set, a negative character type such as \D in a positive
|
||||
class should cause all characters greater than 255 to match, whatever else
|
||||
is in the class. There was a bug that caused this not to happen if a
|
||||
Unicode property item was added to such a class, for example [\D\P{Nd}] or
|
||||
[\W\pL].
|
||||
|
||||
7. When pcretest was outputing information from a callout, the caret indicator
|
||||
for the current position in the subject line was incorrect if it was after
|
||||
an escape sequence for a character whose code point was greater than
|
||||
\x{ff}.
|
||||
|
||||
8. A pattern such as (?<RA>abc)(?(R)xyz) was incorrectly compiled such that
|
||||
the conditional was interpreted as a reference to capturing group 1 instead
|
||||
of a test for recursion. Any group whose name began with R was
|
||||
misinterpreted in this way. (The reference interpretation should only
|
||||
happen if the group's name is precisely "R".)
|
||||
|
||||
9. A number of bugs have been mended relating to match start-up optimizations
|
||||
when the first thing in a pattern is a positive lookahead. These all
|
||||
applied only when PCRE_NO_START_OPTIMIZE was *not* set:
|
||||
|
||||
(a) A pattern such as (?=.*X)X$ was incorrectly optimized as if it needed
|
||||
both an initial 'X' and a following 'X'.
|
||||
(b) Some patterns starting with an assertion that started with .* were
|
||||
incorrectly optimized as having to match at the start of the subject or
|
||||
after a newline. There are cases where this is not true, for example,
|
||||
(?=.*[A-Z])(?=.{8,16})(?!.*[\s]) matches after the start in lines that
|
||||
start with spaces. Starting .* in an assertion is no longer taken as an
|
||||
indication of matching at the start (or after a newline).
|
||||
|
||||
|
||||
Version 8.39 14-June-2016
|
||||
-------------------------
|
||||
|
||||
1. If PCRE_AUTO_CALLOUT was set on a pattern that had a (?# comment between
|
||||
an item and its qualifier (for example, A(?#comment)?B) pcre_compile()
|
||||
misbehaved. This bug was found by the LLVM fuzzer.
|
||||
|
||||
2. Similar to the above, if an isolated \E was present between an item and its
|
||||
qualifier when PCRE_AUTO_CALLOUT was set, pcre_compile() misbehaved. This
|
||||
bug was found by the LLVM fuzzer.
|
||||
|
||||
3. Further to 8.38/46, negated classes such as [^[:^ascii:]\d] were also not
|
||||
working correctly in UCP mode.
|
||||
|
||||
4. The POSIX wrapper function regexec() crashed if the option REG_STARTEND
|
||||
was set when the pmatch argument was NULL. It now returns REG_INVARG.
|
||||
|
||||
5. Allow for up to 32-bit numbers in the ordin() function in pcregrep.
|
||||
|
||||
6. An empty \Q\E sequence between an item and its qualifier caused
|
||||
pcre_compile() to misbehave when auto callouts were enabled. This bug was
|
||||
found by the LLVM fuzzer.
|
||||
|
||||
7. If a pattern that was compiled with PCRE_EXTENDED started with white
|
||||
space or a #-type comment that was followed by (?-x), which turns off
|
||||
PCRE_EXTENDED, and there was no subsequent (?x) to turn it on again,
|
||||
pcre_compile() assumed that (?-x) applied to the whole pattern and
|
||||
consequently mis-compiled it. This bug was found by the LLVM fuzzer.
|
||||
|
||||
8. A call of pcre_copy_named_substring() for a named substring whose number
|
||||
was greater than the space in the ovector could cause a crash.
|
||||
|
||||
9. Yet another buffer overflow bug involved duplicate named groups with a
|
||||
group that reset capture numbers (compare 8.38/7 below). Once again, I have
|
||||
just allowed for more memory, even if not needed. (A proper fix is
|
||||
implemented in PCRE2, but it involves a lot of refactoring.)
|
||||
|
||||
10. pcre_get_substring_list() crashed if the use of \K in a match caused the
|
||||
start of the match to be earlier than the end.
|
||||
|
||||
11. Migrating appropriate PCRE2 JIT improvements to PCRE.
|
||||
|
||||
12. A pattern such as /(?<=((?C)0))/, which has a callout inside a lookbehind
|
||||
assertion, caused pcretest to generate incorrect output, and also to read
|
||||
uninitialized memory (detected by ASAN or valgrind).
|
||||
|
||||
13. A pattern that included (*ACCEPT) in the middle of a sufficiently deeply
|
||||
nested set of parentheses of sufficient size caused an overflow of the
|
||||
compiling workspace (which was diagnosed, but of course is not desirable).
|
||||
|
||||
14. And yet another buffer overflow bug involving duplicate named groups, this
|
||||
time nested, with a nested back reference. Yet again, I have just allowed
|
||||
for more memory, because anything more needs all the refactoring that has
|
||||
been done for PCRE2. An example pattern that provoked this bug is:
|
||||
/((?J)(?'R'(?'R'(?'R'(?'R'(?'R'(?|(\k'R'))))))))/ and the bug was
|
||||
registered as CVE-2016-1283.
|
||||
|
||||
15. pcretest went into a loop if global matching was requested with an ovector
|
||||
size less than 2. It now gives an error message. This bug was found by
|
||||
afl-fuzz.
|
||||
|
||||
16. An invalid pattern fragment such as (?(?C)0 was not diagnosing an error
|
||||
("assertion expected") when (?(?C) was not followed by an opening
|
||||
parenthesis.
|
||||
|
||||
17. Fixed typo ("&&" for "&") in pcre_study(). Fortunately, this could not
|
||||
actually affect anything, by sheer luck.
|
||||
|
||||
18. Applied Chris Wilson's patch (Bugzilla #1681) to CMakeLists.txt for MSVC
|
||||
static compilation.
|
||||
|
||||
19. Modified the RunTest script to incorporate a valgrind suppressions file so
|
||||
that certain errors, provoked by the SSE2 instruction set when JIT is used,
|
||||
are ignored.
|
||||
|
||||
20. A racing condition is fixed in JIT reported by Mozilla.
|
||||
|
||||
21. Minor code refactor to avoid "array subscript is below array bounds"
|
||||
compiler warning.
|
||||
|
||||
22. Minor code refactor to avoid "left shift of negative number" warning.
|
||||
|
||||
23. Fix typo causing compile error when 16- or 32-bit JIT is compiled without
|
||||
UCP support.
|
||||
|
||||
24. Refactor to avoid compiler warnings in pcrecpp.cc.
|
||||
|
||||
25. Refactor to fix a typo in pcre_jit_test.c
|
||||
|
||||
26. Patch to support compiling pcrecpp.cc with Intel compiler.
|
||||
|
||||
|
||||
Version 8.38 23-November-2015
|
||||
-----------------------------
|
||||
|
||||
1. If a group that contained a recursive back reference also contained a
|
||||
forward reference subroutine call followed by a non-forward-reference
|
||||
subroutine call, for example /.((?2)(?R)\1)()/, pcre2_compile() failed to
|
||||
subroutine call, for example /.((?2)(?R)\1)()/, pcre_compile() failed to
|
||||
compile correct code, leading to undefined behaviour or an internally
|
||||
detected error. This bug was discovered by the LLVM fuzzer.
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ Email domain: cam.ac.uk
|
|||
University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2015 University of Cambridge
|
||||
Copyright (c) 1997-2017 University of Cambridge
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
@ -36,7 +36,7 @@ Written by: Zoltan Herczeg
|
|||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2010-2015 Zoltan Herczeg
|
||||
Copyright(c) 2010-2017 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
@ -47,7 +47,7 @@ Written by: Zoltan Herczeg
|
|||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2009-2015 Zoltan Herczeg
|
||||
Copyright(c) 2009-2017 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,27 @@
|
|||
News about PCRE releases
|
||||
------------------------
|
||||
|
||||
Release 8.41 13-June-2017
|
||||
-------------------------
|
||||
|
||||
This is a bug-fix release.
|
||||
|
||||
|
||||
Release 8.40 11-January-2017
|
||||
----------------------------
|
||||
|
||||
This is a bug-fix release.
|
||||
|
||||
|
||||
Release 8.39 14-June-2016
|
||||
-------------------------
|
||||
|
||||
Some appropriate PCRE2 JIT improvements have been retro-fitted to PCRE1. Apart
|
||||
from that, this is another bug-fix release. Note that this library (now called
|
||||
PCRE1) is now being maintained for bug fixes only. New projects are advised to
|
||||
use the new PCRE2 libraries.
|
||||
|
||||
|
||||
Release 8.38 23-November-2015
|
||||
-----------------------------
|
||||
|
||||
|
|
|
@ -442,7 +442,7 @@ The "configure" script also creates config.status, which is an executable
|
|||
script that can be run to recreate the configuration, and config.log, which
|
||||
contains compiler output from tests that "configure" runs.
|
||||
|
||||
Once "configure" has run, you can run "make". This builds the libraries
|
||||
Once "configure" has run, you can run "make". This builds the the libraries
|
||||
libpcre, libpcre16 and/or libpcre32, and a test program called pcretest. If you
|
||||
enabled JIT support with --enable-jit, a test program called pcre_jit_test is
|
||||
built as well.
|
||||
|
|
|
@ -316,7 +316,7 @@ them both to 0; an emulation function will be used. */
|
|||
#define PACKAGE_NAME "PCRE"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "PCRE 8.38"
|
||||
#define PACKAGE_STRING "PCRE 8.41"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "pcre"
|
||||
|
@ -325,7 +325,7 @@ them both to 0; an emulation function will be used. */
|
|||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "8.38"
|
||||
#define PACKAGE_VERSION "8.41"
|
||||
|
||||
/* to make a symbol visible */
|
||||
/* #undef PCRECPP_EXP_DECL */
|
||||
|
@ -439,11 +439,13 @@ them both to 0; an emulation function will be used. */
|
|||
/* #undef SUPPORT_UTF8 */
|
||||
|
||||
/* Valgrind support to find invalid memory reads. */
|
||||
/* #undef SUPPORT_VALGRIND */
|
||||
#if HAVE_PCRE_VALGRIND_SUPPORT
|
||||
#define SUPPORT_VALGRIND 1
|
||||
#endif
|
||||
|
||||
/* Version number of package */
|
||||
#ifndef VERSION
|
||||
#define VERSION "8.38"
|
||||
#define VERSION "8.41"
|
||||
#endif
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
|
|
|
@ -43,7 +43,9 @@ character tables for PCRE. The tables are built according to the current
|
|||
locale. Now that pcre_maketables is a function visible to the outside world, we
|
||||
make use of its code from here in order to be consistent. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -1814,8 +1814,7 @@ PCRE API OVERVIEW
|
|||
ments that have limited stacks. Because of the greater use of memory
|
||||
management, it runs more slowly. Separate functions are provided so
|
||||
that special-purpose external code can be used for this case. When
|
||||
used, these functions are always called in a stack-like manner (last
|
||||
obtained, first freed), and always for memory blocks of the same size.
|
||||
used, these functions always allocate memory blocks of the same size.
|
||||
There is a discussion about PCRE's stack usage in the pcrestack docu-
|
||||
mentation.
|
||||
|
||||
|
@ -4276,8 +4275,8 @@ AUTHOR
|
|||
|
||||
REVISION
|
||||
|
||||
Last updated: 09 February 2014
|
||||
Copyright (c) 1997-2014 University of Cambridge.
|
||||
Last updated: 18 December 2015
|
||||
Copyright (c) 1997-2015 University of Cambridge.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -4641,7 +4640,7 @@ DIFFERENCES BETWEEN PCRE AND PERL
|
|||
pattern names is not as general as Perl's. This is a consequence of the
|
||||
fact the PCRE works internally just with numbers, using an external ta-
|
||||
ble to translate between numbers and names. In particular, a pattern
|
||||
such as (?|(?<a>A)|(?<b)B), where the two capturing parentheses have
|
||||
such as (?|(?<a>A)|(?<b>B), where the two capturing parentheses have
|
||||
the same number but different names, is not supported, and causes an
|
||||
error at compile time. If it were allowed, it would not be possible to
|
||||
distinguish which parentheses matched, because both names map to cap-
|
||||
|
@ -5029,22 +5028,23 @@ BACKSLASH
|
|||
ate the appropriate EBCDIC code values. The \c escape is processed as
|
||||
specified for Perl in the perlebcdic document. The only characters that
|
||||
are allowed after \c are A-Z, a-z, or one of @, [, \, ], ^, _, or ?.
|
||||
Any other character provokes a compile-time error. The sequence \@
|
||||
encodes character code 0; the letters (in either case) encode charac-
|
||||
ters 1-26 (hex 01 to hex 1A); [, \, ], ^, and _ encode characters 27-31
|
||||
(hex 1B to hex 1F), and \? becomes either 255 (hex FF) or 95 (hex 5F).
|
||||
Any other character provokes a compile-time error. The sequence \c@
|
||||
encodes character code 0; after \c the letters (in either case) encode
|
||||
characters 1-26 (hex 01 to hex 1A); [, \, ], ^, and _ encode characters
|
||||
27-31 (hex 1B to hex 1F), and \c? becomes either 255 (hex FF) or 95
|
||||
(hex 5F).
|
||||
|
||||
Thus, apart from \?, these escapes generate the same character code
|
||||
Thus, apart from \c?, these escapes generate the same character code
|
||||
values as they do in an ASCII environment, though the meanings of the
|
||||
values mostly differ. For example, \G always generates code value 7,
|
||||
values mostly differ. For example, \cG always generates code value 7,
|
||||
which is BEL in ASCII but DEL in EBCDIC.
|
||||
|
||||
The sequence \? generates DEL (127, hex 7F) in an ASCII environment,
|
||||
The sequence \c? generates DEL (127, hex 7F) in an ASCII environment,
|
||||
but because 127 is not a control character in EBCDIC, Perl makes it
|
||||
generate the APC character. Unfortunately, there are several variants
|
||||
of EBCDIC. In most of them the APC character has the value 255 (hex
|
||||
FF), but in the one Perl calls POSIX-BC its value is 95 (hex 5F). If
|
||||
certain other characters have POSIX-BC values, PCRE makes \? generate
|
||||
certain other characters have POSIX-BC values, PCRE makes \c? generate
|
||||
95; otherwise it generates 255.
|
||||
|
||||
After \0 up to two further octal digits are read. If there are fewer
|
||||
|
@ -6001,13 +6001,9 @@ INTERNAL OPTION SETTING
|
|||
|
||||
When one of these option changes occurs at top level (that is, not
|
||||
inside subpattern parentheses), the change applies to the remainder of
|
||||
the pattern that follows. If the change is placed right at the start of
|
||||
a pattern, PCRE extracts it into the global options (and it will there-
|
||||
fore show up in data extracted by the pcre_fullinfo() function).
|
||||
|
||||
An option change within a subpattern (see below for a description of
|
||||
subpatterns) affects only that part of the subpattern that follows it,
|
||||
so
|
||||
the pattern that follows. An option change within a subpattern (see
|
||||
below for a description of subpatterns) affects only that part of the
|
||||
subpattern that follows it, so
|
||||
|
||||
(a(?i)b)c
|
||||
|
||||
|
@ -6622,6 +6618,14 @@ ASSERTIONS
|
|||
assertions. (Perl sometimes, but not always, does do capturing in nega-
|
||||
tive assertions.)
|
||||
|
||||
WARNING: If a positive assertion containing one or more capturing sub-
|
||||
patterns succeeds, but failure to match later in the pattern causes
|
||||
backtracking over this assertion, the captures within the assertion are
|
||||
reset only if no higher numbered captures are already set. This is,
|
||||
unfortunately, a fundamental limitation of the current implementation,
|
||||
and as PCRE1 is now in maintenance-only status, it is unlikely ever to
|
||||
change.
|
||||
|
||||
For compatibility with Perl, assertion subpatterns may be repeated;
|
||||
though it makes no sense to assert the same thing several times, the
|
||||
side effect of capturing parentheses may occasionally be useful. In
|
||||
|
@ -7669,8 +7673,8 @@ AUTHOR
|
|||
|
||||
REVISION
|
||||
|
||||
Last updated: 14 June 2015
|
||||
Copyright (c) 1997-2015 University of Cambridge.
|
||||
Last updated: 23 October 2016
|
||||
Copyright (c) 1997-2016 University of Cambridge.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -8362,6 +8366,10 @@ AVAILABILITY OF JIT SUPPORT
|
|||
older than 8.20, but you want to use JIT when it is available, you can
|
||||
test the values of PCRE_MAJOR and PCRE_MINOR, or the existence of a JIT
|
||||
macro such as PCRE_CONFIG_JIT, for compile-time control of your code.
|
||||
Also beware that the pcre_jit_exec() function was not available at all
|
||||
before 8.32, and may not be available at all if PCRE isn't compiled
|
||||
with --enable-jit. See the "JIT FAST PATH API" section below for
|
||||
details.
|
||||
|
||||
|
||||
SIMPLE USE OF JIT
|
||||
|
@ -8403,6 +8411,18 @@ SIMPLE USE OF JIT
|
|||
PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE
|
||||
PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE
|
||||
|
||||
If using pcre_jit_exec() and supporting a pre-8.32 version of PCRE, you
|
||||
can insert:
|
||||
|
||||
#if PCRE_MAJOR >= 8 && PCRE_MINOR >= 32
|
||||
pcre_jit_exec(...);
|
||||
#else
|
||||
pcre_exec(...)
|
||||
#endif
|
||||
|
||||
but as described in the "JIT FAST PATH API" section below this assumes
|
||||
version 8.32 and later are compiled with --enable-jit, which may break.
|
||||
|
||||
The JIT compiler generates different optimized code for each of the
|
||||
three modes (normal, soft partial, hard partial). When pcre_exec() is
|
||||
called, the appropriate code is run if it is available. Otherwise, the
|
||||
|
@ -8692,6 +8712,33 @@ JIT FAST PATH API
|
|||
Bypassing the sanity checks and the pcre_exec() wrapping can give
|
||||
speedups of more than 10%.
|
||||
|
||||
Note that the pcre_jit_exec() function is not available in versions of
|
||||
PCRE before 8.32 (released in November 2012). If you need to support
|
||||
versions that old you must either use the slower pcre_exec(), or switch
|
||||
between the two codepaths by checking the values of PCRE_MAJOR and
|
||||
PCRE_MINOR.
|
||||
|
||||
Due to an unfortunate implementation oversight, even in versions 8.32
|
||||
and later there will be no pcre_jit_exec() stub function defined when
|
||||
PCRE is compiled with --disable-jit, which is the default, and there's
|
||||
no way to detect whether PCRE was compiled with --enable-jit via a
|
||||
macro.
|
||||
|
||||
If you need to support versions older than 8.32, or versions that may
|
||||
not build with --enable-jit, you must either use the slower
|
||||
pcre_exec(), or switch between the two codepaths by checking the values
|
||||
of PCRE_MAJOR and PCRE_MINOR.
|
||||
|
||||
Switching between the two by checking the version assumes that all the
|
||||
versions being targeted are built with --enable-jit. To also support
|
||||
builds that may use --disable-jit either pcre_exec() must be used, or a
|
||||
compile-time check for JIT via pcre_config() (which assumes the runtime
|
||||
environment will be the same), or as the Git project decided to do,
|
||||
simply assume that pcre_jit_exec() is present in 8.32 or later unless a
|
||||
compile-time flag is provided, see the "grep: un-break building with
|
||||
PCRE >= 8.32 without --enable-jit" commit in git.git for an example of
|
||||
that.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
|
||||
|
@ -8707,8 +8754,8 @@ AUTHOR
|
|||
|
||||
REVISION
|
||||
|
||||
Last updated: 17 March 2013
|
||||
Copyright (c) 1997-2013 University of Cambridge.
|
||||
Last updated: 05 July 2017
|
||||
Copyright (c) 1997-2017 University of Cambridge.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
|
|
@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
/* The current PCRE version information. */
|
||||
|
||||
#define PCRE_MAJOR 8
|
||||
#define PCRE_MINOR 38
|
||||
#define PCRE_MINOR 41
|
||||
#define PCRE_PRERELEASE
|
||||
#define PCRE_DATE 2015-11-23
|
||||
#define PCRE_DATE 2017-07-05
|
||||
|
||||
/* When an application links to a PCRE DLL in Windows, the symbols that are
|
||||
imported have to be identified as such. When building PCRE, the appropriate
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
Copyright (c) 1997-2016 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
supporting internal functions that are not used by other modules. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define NLBLOCK cd /* Block containing newline information */
|
||||
#define PSSTART start_pattern /* Field containing pattern start */
|
||||
|
@ -483,7 +485,7 @@ static const char error_texts[] =
|
|||
"lookbehind assertion is not fixed length\0"
|
||||
"malformed number or name after (?(\0"
|
||||
"conditional group contains more than two branches\0"
|
||||
"assertion expected after (?(\0"
|
||||
"assertion expected after (?( or (?(?C)\0"
|
||||
"(?R or (?[+-]digits must be followed by )\0"
|
||||
/* 30 */
|
||||
"unknown POSIX class name\0"
|
||||
|
@ -558,6 +560,7 @@ static const char error_texts[] =
|
|||
/* 85 */
|
||||
"parentheses are too deeply nested (stack check)\0"
|
||||
"digits missing in \\x{} or \\o{}\0"
|
||||
"regular expression is too complicated\0"
|
||||
;
|
||||
|
||||
/* Table to identify digits and hex digits. This is used when compiling
|
||||
|
@ -4564,6 +4567,10 @@ for (;; ptr++)
|
|||
pcre_uint32 ec;
|
||||
pcre_uchar mcbuffer[8];
|
||||
|
||||
/* Come here to restart the loop without advancing the pointer. */
|
||||
|
||||
REDO_LOOP:
|
||||
|
||||
/* Get next character in the pattern */
|
||||
|
||||
c = *ptr;
|
||||
|
@ -4589,7 +4596,8 @@ for (;; ptr++)
|
|||
if (code > cd->start_workspace + cd->workspace_size -
|
||||
WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */
|
||||
{
|
||||
*errorcodeptr = ERR52;
|
||||
*errorcodeptr = (code >= cd->start_workspace + cd->workspace_size)?
|
||||
ERR52 : ERR87;
|
||||
goto FAILED;
|
||||
}
|
||||
|
||||
|
@ -4643,9 +4651,10 @@ for (;; ptr++)
|
|||
goto FAILED;
|
||||
}
|
||||
|
||||
/* If in \Q...\E, check for the end; if not, we have a literal */
|
||||
/* If in \Q...\E, check for the end; if not, we have a literal. Otherwise an
|
||||
isolated \E is ignored. */
|
||||
|
||||
if (inescq && c != CHAR_NULL)
|
||||
if (c != CHAR_NULL)
|
||||
{
|
||||
if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E)
|
||||
{
|
||||
|
@ -4653,7 +4662,7 @@ for (;; ptr++)
|
|||
ptr++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
else if (inescq)
|
||||
{
|
||||
if (previous_callout != NULL)
|
||||
{
|
||||
|
@ -4668,18 +4677,27 @@ for (;; ptr++)
|
|||
}
|
||||
goto NORMAL_CHAR;
|
||||
}
|
||||
/* Control does not reach here. */
|
||||
|
||||
/* Check for the start of a \Q...\E sequence. We must do this here rather
|
||||
than later in case it is immediately followed by \E, which turns it into a
|
||||
"do nothing" sequence. */
|
||||
|
||||
if (c == CHAR_BACKSLASH && ptr[1] == CHAR_Q)
|
||||
{
|
||||
inescq = TRUE;
|
||||
ptr++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* In extended mode, skip white space and comments. We need a loop in order
|
||||
to check for more white space and more comments after a comment. */
|
||||
/* In extended mode, skip white space and comments. */
|
||||
|
||||
if ((options & PCRE_EXTENDED) != 0)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
const pcre_uchar *wscptr = ptr;
|
||||
while (MAX_255(c) && (cd->ctypes[c] & ctype_space) != 0) c = *(++ptr);
|
||||
if (c != CHAR_NUMBER_SIGN) break;
|
||||
if (c == CHAR_NUMBER_SIGN)
|
||||
{
|
||||
ptr++;
|
||||
while (*ptr != CHAR_NULL)
|
||||
{
|
||||
|
@ -4693,8 +4711,29 @@ for (;; ptr++)
|
|||
if (utf) FORWARDCHAR(ptr);
|
||||
#endif
|
||||
}
|
||||
c = *ptr; /* Either NULL or the char after a newline */
|
||||
}
|
||||
|
||||
/* If we skipped any characters, restart the loop. Otherwise, we didn't see
|
||||
a comment. */
|
||||
|
||||
if (ptr > wscptr) goto REDO_LOOP;
|
||||
}
|
||||
|
||||
/* Skip over (?# comments. We need to do this here because we want to know if
|
||||
the next thing is a quantifier, and these comments may come between an item
|
||||
and its quantifier. */
|
||||
|
||||
if (c == CHAR_LEFT_PARENTHESIS && ptr[1] == CHAR_QUESTION_MARK &&
|
||||
ptr[2] == CHAR_NUMBER_SIGN)
|
||||
{
|
||||
ptr += 3;
|
||||
while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
|
||||
if (*ptr == CHAR_NULL)
|
||||
{
|
||||
*errorcodeptr = ERR18;
|
||||
goto FAILED;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* See if the next thing is a quantifier. */
|
||||
|
@ -4818,15 +4857,15 @@ for (;; ptr++)
|
|||
if (STRNCMP_UC_C8(ptr+1, STRING_WEIRD_STARTWORD, 6) == 0)
|
||||
{
|
||||
nestptr = ptr + 7;
|
||||
ptr = sub_start_of_word - 1;
|
||||
continue;
|
||||
ptr = sub_start_of_word;
|
||||
goto REDO_LOOP;
|
||||
}
|
||||
|
||||
if (STRNCMP_UC_C8(ptr+1, STRING_WEIRD_ENDWORD, 6) == 0)
|
||||
{
|
||||
nestptr = ptr + 7;
|
||||
ptr = sub_end_of_word - 1;
|
||||
continue;
|
||||
ptr = sub_end_of_word;
|
||||
goto REDO_LOOP;
|
||||
}
|
||||
|
||||
/* Handle a real character class. */
|
||||
|
@ -5044,20 +5083,22 @@ for (;; ptr++)
|
|||
ptr = tempptr + 1;
|
||||
continue;
|
||||
|
||||
/* For the other POSIX classes (ascii, xdigit) we are going to fall
|
||||
through to the non-UCP case and build a bit map for characters with
|
||||
code points less than 256. If we are in a negated POSIX class
|
||||
within a non-negated overall class, characters with code points
|
||||
greater than 255 must all match. In the special case where we have
|
||||
not yet generated any xclass data, and this is the final item in
|
||||
the overall class, we need do nothing: later on, the opcode
|
||||
/* For the other POSIX classes (ascii, cntrl, xdigit) we are going
|
||||
to fall through to the non-UCP case and build a bit map for
|
||||
characters with code points less than 256. If we are in a negated
|
||||
POSIX class, characters with code points greater than 255 must
|
||||
either all match or all not match. In the special case where we
|
||||
have not yet generated any xclass data, and this is the final item
|
||||
in the overall class, we need do nothing: later on, the opcode
|
||||
OP_NCLASS will be used to indicate that characters greater than 255
|
||||
are acceptable. If we have already seen an xclass item or one may
|
||||
follow (we have to assume that it might if this is not the end of
|
||||
the class), explicitly match all wide codepoints. */
|
||||
the class), explicitly list all wide codepoints, which will then
|
||||
either not match or match, depending on whether the class is or is
|
||||
not negated. */
|
||||
|
||||
default:
|
||||
if (!negate_class && local_negate &&
|
||||
if (local_negate &&
|
||||
(xclass || tempptr[2] != CHAR_RIGHT_SQUARE_BRACKET))
|
||||
{
|
||||
*class_uchardata++ = XCL_RANGE;
|
||||
|
@ -5538,6 +5579,34 @@ for (;; ptr++)
|
|||
#endif
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
{
|
||||
/* For non-UCP wide characters, in a non-negative class containing \S or
|
||||
similar (should_flip_negation is set), all characters greater than 255
|
||||
must be in the class. */
|
||||
|
||||
if (
|
||||
#if defined COMPILE_PCRE8
|
||||
utf &&
|
||||
#endif
|
||||
should_flip_negation && !negate_class && (options & PCRE_UCP) == 0)
|
||||
{
|
||||
*class_uchardata++ = XCL_RANGE;
|
||||
if (utf) /* Will always be utf in the 8-bit library */
|
||||
{
|
||||
class_uchardata += PRIV(ord2utf)(0x100, class_uchardata);
|
||||
class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata);
|
||||
}
|
||||
else /* Can only happen for the 16-bit & 32-bit libraries */
|
||||
{
|
||||
#if defined COMPILE_PCRE16
|
||||
*class_uchardata++ = 0x100;
|
||||
*class_uchardata++ = 0xffffu;
|
||||
#elif defined COMPILE_PCRE32
|
||||
*class_uchardata++ = 0x100;
|
||||
*class_uchardata++ = 0xffffffffu;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
*class_uchardata++ = XCL_END; /* Marks the end of extra data */
|
||||
*code++ = OP_XCLASS;
|
||||
code += LINK_SIZE;
|
||||
|
@ -5670,6 +5739,21 @@ for (;; ptr++)
|
|||
ptr = p - 1; /* Character before the next significant one. */
|
||||
}
|
||||
|
||||
/* We also need to skip over (?# comments, which are not dependent on
|
||||
extended mode. */
|
||||
|
||||
if (ptr[1] == CHAR_LEFT_PARENTHESIS && ptr[2] == CHAR_QUESTION_MARK &&
|
||||
ptr[3] == CHAR_NUMBER_SIGN)
|
||||
{
|
||||
ptr += 4;
|
||||
while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
|
||||
if (*ptr == CHAR_NULL)
|
||||
{
|
||||
*errorcodeptr = ERR18;
|
||||
goto FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the next character is '+', we have a possessive quantifier. This
|
||||
implies greediness, whatever the setting of the PCRE_UNGREEDY option.
|
||||
If the next character is '?' this is a minimizing repeat, by default,
|
||||
|
@ -5770,7 +5854,7 @@ for (;; ptr++)
|
|||
/* If previous was a character type match (\d or similar), abolish it and
|
||||
create a suitable repeat item. The code is shared with single-character
|
||||
repeats by setting op_type to add a suitable offset into repeat_type. Note
|
||||
that the Unicode property types will be present only when SUPPORT_UCP is
|
||||
the the Unicode property types will be present only when SUPPORT_UCP is
|
||||
defined, but we don't wrap the little bits of code here because it just
|
||||
makes it horribly messy. */
|
||||
|
||||
|
@ -6527,21 +6611,6 @@ for (;; ptr++)
|
|||
case CHAR_LEFT_PARENTHESIS:
|
||||
ptr++;
|
||||
|
||||
/* First deal with comments. Putting this code right at the start ensures
|
||||
that comments have no bad side effects. */
|
||||
|
||||
if (ptr[0] == CHAR_QUESTION_MARK && ptr[1] == CHAR_NUMBER_SIGN)
|
||||
{
|
||||
ptr += 2;
|
||||
while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
|
||||
if (*ptr == CHAR_NULL)
|
||||
{
|
||||
*errorcodeptr = ERR18;
|
||||
goto FAILED;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now deal with various "verbs" that can be introduced by '*'. */
|
||||
|
||||
if (ptr[0] == CHAR_ASTERISK && (ptr[1] == ':'
|
||||
|
@ -6601,10 +6670,23 @@ for (;; ptr++)
|
|||
}
|
||||
cd->had_accept = TRUE;
|
||||
for (oc = cd->open_caps; oc != NULL; oc = oc->next)
|
||||
{
|
||||
if (lengthptr != NULL)
|
||||
{
|
||||
#ifdef COMPILE_PCRE8
|
||||
*lengthptr += 1 + IMM2_SIZE;
|
||||
#elif defined COMPILE_PCRE16
|
||||
*lengthptr += 2 + IMM2_SIZE;
|
||||
#elif defined COMPILE_PCRE32
|
||||
*lengthptr += 4 + IMM2_SIZE;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
*code++ = OP_CLOSE;
|
||||
PUT2INC(code, 0, oc->number);
|
||||
}
|
||||
}
|
||||
setverb = *code++ =
|
||||
(cd->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;
|
||||
|
||||
|
@ -6732,6 +6814,15 @@ for (;; ptr++)
|
|||
for (i = 3;; i++) if (!IS_DIGIT(ptr[i])) break;
|
||||
if (ptr[i] == CHAR_RIGHT_PARENTHESIS)
|
||||
tempptr += i + 1;
|
||||
|
||||
/* tempptr should now be pointing to the opening parenthesis of the
|
||||
assertion condition. */
|
||||
|
||||
if (*tempptr != CHAR_LEFT_PARENTHESIS)
|
||||
{
|
||||
*errorcodeptr = ERR28;
|
||||
goto FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/* For conditions that are assertions, check the syntax, and then exit
|
||||
|
@ -6875,7 +6966,8 @@ for (;; ptr++)
|
|||
slot = cd->name_table;
|
||||
for (i = 0; i < cd->names_found; i++)
|
||||
{
|
||||
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;
|
||||
slot += cd->name_entry_size;
|
||||
}
|
||||
|
||||
|
@ -7256,7 +7348,7 @@ for (;; ptr++)
|
|||
issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance
|
||||
only mode, we finesse the bug by allowing more memory always. */
|
||||
|
||||
*lengthptr += 2 + 2*LINK_SIZE;
|
||||
*lengthptr += 4 + 4*LINK_SIZE;
|
||||
|
||||
/* It is even worse than that. The current reference may be to an
|
||||
existing named group with a different number (so apparently not
|
||||
|
@ -7272,7 +7364,12 @@ for (;; ptr++)
|
|||
so far in order to get the number. If the name is not found, leave
|
||||
the value of recno as 0 for a forward reference. */
|
||||
|
||||
else
|
||||
/* This patch (removing "else") fixes a problem when a reference is
|
||||
to multiple identically named nested groups from within the nest.
|
||||
Once again, it is not the "proper" fix, and it results in an
|
||||
over-allocation of memory. */
|
||||
|
||||
/* else */
|
||||
{
|
||||
ng = cd->named_groups;
|
||||
for (i = 0; i < cd->names_found; i++, ng++)
|
||||
|
@ -7583,39 +7680,15 @@ for (;; ptr++)
|
|||
newoptions = (options | set) & (~unset);
|
||||
|
||||
/* If the options ended with ')' this is not the start of a nested
|
||||
group with option changes, so the options change at this level. If this
|
||||
item is right at the start of the pattern, the options can be
|
||||
abstracted and made external in the pre-compile phase, and ignored in
|
||||
the compile phase. This can be helpful when matching -- for instance in
|
||||
caseless checking of required bytes.
|
||||
|
||||
If the code pointer is not (cd->start_code + 1 + LINK_SIZE), we are
|
||||
definitely *not* at the start of the pattern because something has been
|
||||
compiled. In the pre-compile phase, however, the code pointer can have
|
||||
that value after the start, because it gets reset as code is discarded
|
||||
during the pre-compile. However, this can happen only at top level - if
|
||||
we are within parentheses, the starting BRA will still be present. At
|
||||
any parenthesis level, the length value can be used to test if anything
|
||||
has been compiled at that level. Thus, a test for both these conditions
|
||||
is necessary to ensure we correctly detect the start of the pattern in
|
||||
both phases.
|
||||
|
||||
group with option changes, so the options change at this level.
|
||||
If we are not at the pattern start, reset the greedy defaults and the
|
||||
case value for firstchar and reqchar. */
|
||||
|
||||
if (*ptr == CHAR_RIGHT_PARENTHESIS)
|
||||
{
|
||||
if (code == cd->start_code + 1 + LINK_SIZE &&
|
||||
(lengthptr == NULL || *lengthptr == 2 + 2*LINK_SIZE))
|
||||
{
|
||||
cd->external_options = newoptions;
|
||||
}
|
||||
else
|
||||
{
|
||||
greedy_default = ((newoptions & PCRE_UNGREEDY) != 0);
|
||||
greedy_non_default = greedy_default ^ 1;
|
||||
req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS:0;
|
||||
}
|
||||
|
||||
/* Change options at this level, and pass them back for use
|
||||
in subsequent branches. */
|
||||
|
@ -7860,15 +7933,17 @@ for (;; ptr++)
|
|||
}
|
||||
}
|
||||
|
||||
/* For a forward assertion, we take the reqchar, if set. This can be
|
||||
helpful if the pattern that follows the assertion doesn't set a different
|
||||
char. For example, it's useful for /(?=abcde).+/. We can't set firstchar
|
||||
for an assertion, however because it leads to incorrect effect for patterns
|
||||
such as /(?=a)a.+/ when the "real" "a" would then become a reqchar instead
|
||||
of a firstchar. This is overcome by a scan at the end if there's no
|
||||
firstchar, looking for an asserted first char. */
|
||||
/* For a forward assertion, we take the reqchar, if set, provided that the
|
||||
group has also set a first char. This can be helpful if the pattern that
|
||||
follows the assertion doesn't set a different char. For example, it's
|
||||
useful for /(?=abcde).+/. We can't set firstchar for an assertion, however
|
||||
because it leads to incorrect effect for patterns such as /(?=a)a.+/ when
|
||||
the "real" "a" would then become a reqchar instead of a firstchar. This is
|
||||
overcome by a scan at the end if there's no firstchar, looking for an
|
||||
asserted first char. */
|
||||
|
||||
else if (bravalue == OP_ASSERT && subreqcharflags >= 0)
|
||||
else if (bravalue == OP_ASSERT && subreqcharflags >= 0 &&
|
||||
subfirstcharflags >= 0)
|
||||
{
|
||||
reqchar = subreqchar;
|
||||
reqcharflags = subreqcharflags;
|
||||
|
@ -7894,16 +7969,6 @@ for (;; ptr++)
|
|||
c = ec;
|
||||
else
|
||||
{
|
||||
if (escape == ESC_Q) /* Handle start of quoted string */
|
||||
{
|
||||
if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E)
|
||||
ptr += 2; /* avoid empty string */
|
||||
else inescq = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (escape == ESC_E) continue; /* Perl ignores an orphan \E */
|
||||
|
||||
/* For metasequences that actually match a character, we disable the
|
||||
setting of a first character if it hasn't already been set. */
|
||||
|
||||
|
@ -8160,7 +8225,6 @@ for (;; ptr++)
|
|||
|
||||
if (mclength == 1 || req_caseopt == 0)
|
||||
{
|
||||
firstchar = mcbuffer[0] | req_caseopt;
|
||||
firstchar = mcbuffer[0];
|
||||
firstcharflags = req_caseopt;
|
||||
|
||||
|
@ -8667,8 +8731,8 @@ matching and for non-DOTALL patterns that start with .* (which must start at
|
|||
the beginning or after \n). As in the case of is_anchored() (see above), we
|
||||
have to take account of back references to capturing brackets that contain .*
|
||||
because in that case we can't make the assumption. Also, the appearance of .*
|
||||
inside atomic brackets or in a pattern that contains *PRUNE or *SKIP does not
|
||||
count, because once again the assumption no longer holds.
|
||||
inside atomic brackets or in an assertion, or in a pattern that contains *PRUNE
|
||||
or *SKIP does not count, because once again the assumption no longer holds.
|
||||
|
||||
Arguments:
|
||||
code points to start of expression (the bracket)
|
||||
|
@ -8677,13 +8741,14 @@ Arguments:
|
|||
the less precise approach
|
||||
cd points to the compile data
|
||||
atomcount atomic group level
|
||||
inassert TRUE if in an assertion
|
||||
|
||||
Returns: TRUE or FALSE
|
||||
*/
|
||||
|
||||
static BOOL
|
||||
is_startline(const pcre_uchar *code, unsigned int bracket_map,
|
||||
compile_data *cd, int atomcount)
|
||||
compile_data *cd, int atomcount, BOOL inassert)
|
||||
{
|
||||
do {
|
||||
const pcre_uchar *scode = first_significant_code(
|
||||
|
@ -8710,7 +8775,7 @@ do {
|
|||
return FALSE;
|
||||
|
||||
default: /* Assertion */
|
||||
if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE;
|
||||
if (!is_startline(scode, bracket_map, cd, atomcount, TRUE)) return FALSE;
|
||||
do scode += GET(scode, 1); while (*scode == OP_ALT);
|
||||
scode += 1 + LINK_SIZE;
|
||||
break;
|
||||
|
@ -8724,7 +8789,7 @@ do {
|
|||
if (op == OP_BRA || op == OP_BRAPOS ||
|
||||
op == OP_SBRA || op == OP_SBRAPOS)
|
||||
{
|
||||
if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE;
|
||||
if (!is_startline(scode, bracket_map, cd, atomcount, inassert)) return FALSE;
|
||||
}
|
||||
|
||||
/* Capturing brackets */
|
||||
|
@ -8734,33 +8799,33 @@ do {
|
|||
{
|
||||
int n = GET2(scode, 1+LINK_SIZE);
|
||||
int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
|
||||
if (!is_startline(scode, new_map, cd, atomcount)) return FALSE;
|
||||
if (!is_startline(scode, new_map, cd, atomcount, inassert)) return FALSE;
|
||||
}
|
||||
|
||||
/* Positive forward assertions */
|
||||
|
||||
else if (op == OP_ASSERT)
|
||||
{
|
||||
if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE;
|
||||
if (!is_startline(scode, bracket_map, cd, atomcount, TRUE)) return FALSE;
|
||||
}
|
||||
|
||||
/* Atomic brackets */
|
||||
|
||||
else if (op == OP_ONCE || op == OP_ONCE_NC)
|
||||
{
|
||||
if (!is_startline(scode, bracket_map, cd, atomcount + 1)) return FALSE;
|
||||
if (!is_startline(scode, bracket_map, cd, atomcount + 1, inassert)) return FALSE;
|
||||
}
|
||||
|
||||
/* .* means "start at start or after \n" if it isn't in atomic brackets or
|
||||
brackets that may be referenced, as long as the pattern does not contain
|
||||
*PRUNE or *SKIP, because these break the feature. Consider, for example,
|
||||
/.*?a(*PRUNE)b/ with the subject "aab", which matches "ab", i.e. not at the
|
||||
start of a line. */
|
||||
brackets that may be referenced or an assertion, as long as the pattern does
|
||||
not contain *PRUNE or *SKIP, because these break the feature. Consider, for
|
||||
example, /.*?a(*PRUNE)b/ with the subject "aab", which matches "ab", i.e.
|
||||
not at the start of a line. */
|
||||
|
||||
else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR)
|
||||
{
|
||||
if (scode[1] != OP_ANY || (bracket_map & cd->backref_map) != 0 ||
|
||||
atomcount > 0 || cd->had_pruneorskip)
|
||||
atomcount > 0 || cd->had_pruneorskip || inassert)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -9615,7 +9680,7 @@ if ((re->options & PCRE_ANCHORED) == 0)
|
|||
re->flags |= PCRE_FIRSTSET;
|
||||
}
|
||||
|
||||
else if (is_startline(codestart, 0, cd, 0)) re->flags |= PCRE_STARTLINE;
|
||||
else if (is_startline(codestart, 0, cd, 0, FALSE)) re->flags |= PCRE_STARTLINE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
/* This module contains the external function pcre_config(). */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* Keep the original link size. */
|
||||
static int real_link_size = LINK_SIZE;
|
||||
|
|
|
@ -41,7 +41,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
pattern matching using an NFA algorithm, trying to mimic Perl as closely as
|
||||
possible. There are also some static supporting functions. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define NLBLOCK md /* Block containing newline information */
|
||||
#define PSSTART start_subject /* Field containing processed string start */
|
||||
|
@ -667,7 +669,7 @@ if (ecode == NULL)
|
|||
return match((PCRE_PUCHAR)&rdepth, NULL, NULL, 0, NULL, NULL, 1);
|
||||
else
|
||||
{
|
||||
int len = (char *)&rdepth - (char *)eptr;
|
||||
int len = (int)((char *)&rdepth - (char *)eptr);
|
||||
return (len > 0)? -len : len;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
information about a compiled pattern. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
|
|
|
@ -43,7 +43,9 @@ from the subject string after a regex match has succeeded. The original idea
|
|||
for these functions came from Scott Wimer. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
|
@ -248,6 +250,7 @@ Arguments:
|
|||
code the compiled regex
|
||||
stringname the name of the capturing substring
|
||||
ovector the vector of matched substrings
|
||||
stringcount number of captured substrings
|
||||
|
||||
Returns: the number of the first that is set,
|
||||
or the number of the last one if none are set,
|
||||
|
@ -256,13 +259,16 @@ Returns: the number of the first that is set,
|
|||
|
||||
#if defined COMPILE_PCRE8
|
||||
static int
|
||||
get_first_set(const pcre *code, const char *stringname, int *ovector)
|
||||
get_first_set(const pcre *code, const char *stringname, int *ovector,
|
||||
int stringcount)
|
||||
#elif defined COMPILE_PCRE16
|
||||
static int
|
||||
get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector)
|
||||
get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector,
|
||||
int stringcount)
|
||||
#elif defined COMPILE_PCRE32
|
||||
static int
|
||||
get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector)
|
||||
get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector,
|
||||
int stringcount)
|
||||
#endif
|
||||
{
|
||||
const REAL_PCRE *re = (const REAL_PCRE *)code;
|
||||
|
@ -293,7 +299,7 @@ if (entrysize <= 0) return entrysize;
|
|||
for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize)
|
||||
{
|
||||
int n = GET2(entry, 0);
|
||||
if (ovector[n*2] >= 0) return n;
|
||||
if (n < stringcount && ovector[n*2] >= 0) return n;
|
||||
}
|
||||
return GET2(entry, 0);
|
||||
}
|
||||
|
@ -400,7 +406,7 @@ pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
|
|||
PCRE_UCHAR32 *buffer, int size)
|
||||
#endif
|
||||
{
|
||||
int n = get_first_set(code, stringname, ovector);
|
||||
int n = get_first_set(code, stringname, ovector, stringcount);
|
||||
if (n <= 0) return n;
|
||||
#if defined COMPILE_PCRE8
|
||||
return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
|
||||
|
@ -455,7 +461,10 @@ pcre_uchar **stringlist;
|
|||
pcre_uchar *p;
|
||||
|
||||
for (i = 0; i < double_count; i += 2)
|
||||
size += sizeof(pcre_uchar *) + IN_UCHARS(ovector[i+1] - ovector[i] + 1);
|
||||
{
|
||||
size += sizeof(pcre_uchar *) + IN_UCHARS(1);
|
||||
if (ovector[i+1] > ovector[i]) size += IN_UCHARS(ovector[i+1] - ovector[i]);
|
||||
}
|
||||
|
||||
stringlist = (pcre_uchar **)(PUBL(malloc))(size);
|
||||
if (stringlist == NULL) return PCRE_ERROR_NOMEMORY;
|
||||
|
@ -471,7 +480,7 @@ p = (pcre_uchar *)(stringlist + stringcount + 1);
|
|||
|
||||
for (i = 0; i < double_count; i += 2)
|
||||
{
|
||||
int len = ovector[i+1] - ovector[i];
|
||||
int len = (ovector[i+1] > ovector[i])? (ovector[i+1] - ovector[i]) : 0;
|
||||
memcpy(p, subject + ovector[i], IN_UCHARS(len));
|
||||
*stringlist++ = p;
|
||||
p += len;
|
||||
|
@ -617,7 +626,7 @@ pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
|
|||
PCRE_SPTR32 *stringptr)
|
||||
#endif
|
||||
{
|
||||
int n = get_first_set(code, stringname, ovector);
|
||||
int n = get_first_set(code, stringname, ovector, stringcount);
|
||||
if (n <= 0) return n;
|
||||
#if defined COMPILE_PCRE8
|
||||
return pcre_get_substring(subject, ovector, stringcount, n, stringptr);
|
||||
|
|
|
@ -52,7 +52,9 @@ a local function is used.
|
|||
Also, when compiling for Virtual Pascal, things are done differently, and
|
||||
global variables are not used. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
|
|
|
@ -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-2014 University of Cambridge
|
||||
Copyright (c) 1997-2016 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -275,7 +275,7 @@ pcre.h(.in) and disable (comment out) this message. */
|
|||
|
||||
typedef pcre_uint16 pcre_uchar;
|
||||
#define UCHAR_SHIFT (1)
|
||||
#define IN_UCHARS(x) ((x) << UCHAR_SHIFT)
|
||||
#define IN_UCHARS(x) ((x) * 2)
|
||||
#define MAX_255(c) ((c) <= 255u)
|
||||
#define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default))
|
||||
|
||||
|
@ -283,7 +283,7 @@ typedef pcre_uint16 pcre_uchar;
|
|||
|
||||
typedef pcre_uint32 pcre_uchar;
|
||||
#define UCHAR_SHIFT (2)
|
||||
#define IN_UCHARS(x) ((x) << UCHAR_SHIFT)
|
||||
#define IN_UCHARS(x) ((x) * 4)
|
||||
#define MAX_255(c) ((c) <= 255u)
|
||||
#define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default))
|
||||
|
||||
|
@ -2289,7 +2289,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, ERR86, ERRCOUNT };
|
||||
ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERRCOUNT };
|
||||
|
||||
/* JIT compiling modes. The function list is indexed by them. */
|
||||
|
||||
|
@ -2772,6 +2772,9 @@ extern const pcre_uint8 PRIV(ucd_stage1)[];
|
|||
extern const pcre_uint16 PRIV(ucd_stage2)[];
|
||||
extern const pcre_uint32 PRIV(ucp_gentype)[];
|
||||
extern const pcre_uint32 PRIV(ucp_gbtable)[];
|
||||
#ifdef COMPILE_PCRE32
|
||||
extern const ucd_record PRIV(dummy_ucd_record)[];
|
||||
#endif
|
||||
#ifdef SUPPORT_JIT
|
||||
extern const int PRIV(ucp_typerange)[];
|
||||
#endif
|
||||
|
@ -2780,10 +2783,16 @@ extern const int PRIV(ucp_typerange)[];
|
|||
/* UCD access macros */
|
||||
|
||||
#define UCD_BLOCK_SIZE 128
|
||||
#define GET_UCD(ch) (PRIV(ucd_records) + \
|
||||
#define REAL_GET_UCD(ch) (PRIV(ucd_records) + \
|
||||
PRIV(ucd_stage2)[PRIV(ucd_stage1)[(int)(ch) / UCD_BLOCK_SIZE] * \
|
||||
UCD_BLOCK_SIZE + (int)(ch) % UCD_BLOCK_SIZE])
|
||||
|
||||
#ifdef COMPILE_PCRE32
|
||||
#define GET_UCD(ch) ((ch > 0x10ffff)? PRIV(dummy_ucd_record) : REAL_GET_UCD(ch))
|
||||
#else
|
||||
#define GET_UCD(ch) REAL_GET_UCD(ch)
|
||||
#endif
|
||||
|
||||
#define UCD_CHARTYPE(ch) GET_UCD(ch)->chartype
|
||||
#define UCD_SCRIPT(ch) GET_UCD(ch)->script
|
||||
#define UCD_CATEGORY(ch) PRIV(ucp_gentype)[UCD_CHARTYPE(ch)]
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -45,7 +45,9 @@ compilation of dftables.c, in which case the macro DFTABLES is defined. */
|
|||
|
||||
|
||||
#ifndef DFTABLES
|
||||
# ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
# endif
|
||||
# include "pcre_internal.h"
|
||||
#endif
|
||||
|
||||
|
|
|
@ -47,7 +47,9 @@ and NLTYPE_ANY. The full list of Unicode newline characters is taken from
|
|||
http://unicode.org/unicode/reports/tr18/. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
|
|
|
@ -41,7 +41,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
/* This file contains a private PCRE function that converts an ordinal
|
||||
character value into a UTF8 string. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define COMPILE_PCRE8
|
||||
|
||||
|
|
|
@ -51,7 +51,9 @@ asked to print out a compiled regex for debugging purposes. */
|
|||
|
||||
#ifndef PCRE_INCLUDED
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* For pcretest program. */
|
||||
#define PRIV(name) name
|
||||
|
|
|
@ -44,7 +44,9 @@ pattern data block. This might be helpful in applications where the block is
|
|||
shared by different users. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
|
|
|
@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
supporting functions. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
|
@ -1369,7 +1371,7 @@ do
|
|||
for (c = 0; c < 16; c++) start_bits[c] |= map[c];
|
||||
for (c = 128; c < 256; c++)
|
||||
{
|
||||
if ((map[c/8] && (1 << (c&7))) != 0)
|
||||
if ((map[c/8] & (1 << (c&7))) != 0)
|
||||
{
|
||||
int d = (c >> 6) | 0xc0; /* Set bit for this starter */
|
||||
start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */
|
||||
|
|
|
@ -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-2012 University of Cambridge
|
||||
Copyright (c) 1997-2017 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -45,7 +45,9 @@ uses macros to change their names from _pcre_xxx to xxxx, thereby avoiding name
|
|||
clashes with the library. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
|
@ -159,7 +161,7 @@ const pcre_uint32 PRIV(ucp_gbtable[]) = {
|
|||
|
||||
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark), /* 5 SpacingMark */
|
||||
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbL)| /* 6 L */
|
||||
(1<<ucp_gbL)|(1<<ucp_gbV)|(1<<ucp_gbLV)|(1<<ucp_gbLVT),
|
||||
(1<<ucp_gbV)|(1<<ucp_gbLV)|(1<<ucp_gbLVT),
|
||||
|
||||
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbV)| /* 7 V */
|
||||
(1<<ucp_gbT),
|
||||
|
|
|
@ -10,7 +10,9 @@ needed. */
|
|||
|
||||
#ifndef PCRE_INCLUDED
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
|
@ -36,6 +38,20 @@ const pcre_uint16 PRIV(ucd_stage2)[] = {0};
|
|||
const pcre_uint32 PRIV(ucd_caseless_sets)[] = {0};
|
||||
#else
|
||||
|
||||
/* If the 32-bit library is run in non-32-bit mode, character values
|
||||
greater than 0x10ffff may be encountered. For these we set up a
|
||||
special record. */
|
||||
|
||||
#ifdef COMPILE_PCRE32
|
||||
const ucd_record PRIV(dummy_ucd_record)[] = {{
|
||||
ucp_Common, /* script */
|
||||
ucp_Cn, /* type unassigned */
|
||||
ucp_gbOther, /* grapheme break property */
|
||||
0, /* case set */
|
||||
0, /* other case */
|
||||
}};
|
||||
#endif
|
||||
|
||||
/* When recompiling tables with a new Unicode version, please check the
|
||||
types in this structure definition from pcre_internal.h (the actual
|
||||
field names will be different):
|
||||
|
|
|
@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
strings. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
|
|
|
@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
string that identifies the PCRE version that is in use. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
|
|
|
@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
class. It is used by both pcre_exec() and pcre_def_exec(). */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
|
|
|
@ -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-2014 University of Cambridge
|
||||
Copyright (c) 1997-2017 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
functions. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* Ensure that the PCREPOSIX_EXP_xxx macros are set appropriately for
|
||||
|
@ -171,7 +173,8 @@ static const int eint[] = {
|
|||
REG_BADPAT, /* group name must start with a non-digit */
|
||||
/* 85 */
|
||||
REG_BADPAT, /* parentheses too deeply nested (stack check) */
|
||||
REG_BADPAT /* missing digits in \x{} or \o{} */
|
||||
REG_BADPAT, /* missing digits in \x{} or \o{} */
|
||||
REG_BADPAT /* pattern too complicated */
|
||||
};
|
||||
|
||||
/* Table of texts corresponding to POSIX error codes */
|
||||
|
@ -362,6 +365,7 @@ start location rather than being passed as a PCRE "starting offset". */
|
|||
|
||||
if ((eflags & REG_STARTEND) != 0)
|
||||
{
|
||||
if (pmatch == NULL) return REG_INVARG;
|
||||
so = pmatch[0].rm_so;
|
||||
eo = pmatch[0].rm_eo;
|
||||
}
|
||||
|
@ -385,8 +389,8 @@ if (rc >= 0)
|
|||
{
|
||||
for (i = 0; i < (size_t)rc; i++)
|
||||
{
|
||||
pmatch[i].rm_so = ovector[i*2];
|
||||
pmatch[i].rm_eo = ovector[i*2+1];
|
||||
pmatch[i].rm_so = ovector[i*2] + so;
|
||||
pmatch[i].rm_eo = ovector[i*2+1] + so;
|
||||
}
|
||||
if (allocated_ovector) free(ovector);
|
||||
for (; i < nmatch; i++) pmatch[i].rm_so = pmatch[i].rm_eo = -1;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -82,7 +82,7 @@
|
|||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* If SLJIT_STD_MACROS_DEFINED is not defined, the application should
|
||||
define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMMOVE, and NULL. */
|
||||
define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMCPY, and NULL. */
|
||||
#ifndef SLJIT_STD_MACROS_DEFINED
|
||||
/* Disabled by default. */
|
||||
#define SLJIT_STD_MACROS_DEFINED 0
|
||||
|
@ -90,10 +90,20 @@
|
|||
|
||||
/* Executable code allocation:
|
||||
If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should
|
||||
define both SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC. */
|
||||
define SLJIT_MALLOC_EXEC, SLJIT_FREE_EXEC, and SLJIT_EXEC_OFFSET. */
|
||||
#ifndef SLJIT_EXECUTABLE_ALLOCATOR
|
||||
/* Enabled by default. */
|
||||
#define SLJIT_EXECUTABLE_ALLOCATOR 1
|
||||
|
||||
/* When SLJIT_PROT_EXECUTABLE_ALLOCATOR is enabled SLJIT uses
|
||||
an allocator which does not set writable and executable
|
||||
permission flags at the same time. The trade-of is increased
|
||||
memory consumption and disabled dynamic code modifications. */
|
||||
#ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR
|
||||
/* Disabled by default. */
|
||||
#define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Force cdecl calling convention even if a better calling
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -31,14 +31,14 @@
|
|||
SLJIT defines the following architecture dependent types and macros:
|
||||
|
||||
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_s8, sljit_u8 : signed and unsigned 8 bit integer type
|
||||
sljit_s16, sljit_u16 : signed and unsigned 16 bit integer type
|
||||
sljit_s32, sljit_u32 : 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_f32 : 32 bit single precision floating point value
|
||||
sljit_f64 : 64 bit double precision floating point value
|
||||
|
||||
Macros for feature detection (boolean):
|
||||
SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
|
||||
|
@ -56,10 +56,10 @@
|
|||
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
|
||||
SLJIT_F32_SHIFT : the shift required to apply when accessing
|
||||
a single precision floating point array by index
|
||||
SLJIT_F64_SHIFT : the shift required to apply when accessing
|
||||
a double precision floating point array by index
|
||||
SLJIT_LOCALS_OFFSET : local space starting offset (SLJIT_SP + SLJIT_LOCALS_OFFSET)
|
||||
SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
|
||||
|
||||
|
@ -187,14 +187,6 @@
|
|||
/* External function definitions. */
|
||||
/**********************************/
|
||||
|
||||
#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)
|
||||
|
||||
/* These libraries are needed for the macros below. */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#endif /* SLJIT_STD_MACROS_DEFINED */
|
||||
|
||||
/* General macros:
|
||||
Note: SLJIT is designed to be independent from them as possible.
|
||||
|
||||
|
@ -210,8 +202,8 @@
|
|||
#define SLJIT_FREE(ptr, allocator_data) free(ptr)
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_MEMMOVE
|
||||
#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len)
|
||||
#ifndef SLJIT_MEMCPY
|
||||
#define SLJIT_MEMCPY(dest, src, len) memcpy(dest, src, len)
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_ZEROMEM
|
||||
|
@ -252,11 +244,6 @@
|
|||
#endif
|
||||
#endif /* !SLJIT_INLINE */
|
||||
|
||||
#ifndef SLJIT_CONST
|
||||
/* Const variables. */
|
||||
#define SLJIT_CONST const
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_UNUSED_ARG
|
||||
/* Unused arguments. */
|
||||
#define SLJIT_UNUSED_ARG(arg) (void)arg
|
||||
|
@ -284,6 +271,15 @@
|
|||
/* Instruction cache flush. */
|
||||
/****************************/
|
||||
|
||||
#if (!defined SLJIT_CACHE_FLUSH && defined __has_builtin)
|
||||
#if __has_builtin(__builtin___clear_cache)
|
||||
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
__builtin___clear_cache((char*)from, (char*)to)
|
||||
|
||||
#endif /* __has_builtin(__builtin___clear_cache) */
|
||||
#endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */
|
||||
|
||||
#ifndef SLJIT_CACHE_FLUSH
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
|
@ -300,6 +296,18 @@
|
|||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
sys_icache_invalidate((char*)(from), (char*)(to) - (char*)(from))
|
||||
|
||||
#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) \
|
||||
ppc_cache_flush((from), (to))
|
||||
#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
|
||||
|
||||
#elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
|
||||
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
__builtin___clear_cache((char*)from, (char*)to)
|
||||
|
||||
#elif defined __ANDROID__
|
||||
|
||||
/* Android lacks __clear_cache; instead, cacheflush should be used. */
|
||||
|
@ -307,17 +315,12 @@
|
|||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
cacheflush((long)(from), (long)(to), 0)
|
||||
|
||||
#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) \
|
||||
ppc_cache_flush((from), (to))
|
||||
|
||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
|
||||
/* The __clear_cache() implementation of GCC is a dummy function on Sparc. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
sparc_cache_flush((from), (to))
|
||||
#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
|
||||
|
||||
#else
|
||||
|
||||
|
@ -330,20 +333,20 @@
|
|||
#endif /* !SLJIT_CACHE_FLUSH */
|
||||
|
||||
/******************************************************/
|
||||
/* Byte/half/int/word/single/double type definitions. */
|
||||
/* Integer and floating point type definitions. */
|
||||
/******************************************************/
|
||||
|
||||
/* 8 bit byte type. */
|
||||
typedef unsigned char sljit_ub;
|
||||
typedef signed char sljit_sb;
|
||||
typedef unsigned char sljit_u8;
|
||||
typedef signed char sljit_s8;
|
||||
|
||||
/* 16 bit half-word type. */
|
||||
typedef unsigned short int sljit_uh;
|
||||
typedef signed short int sljit_sh;
|
||||
typedef unsigned short int sljit_u16;
|
||||
typedef signed short int sljit_s16;
|
||||
|
||||
/* 32 bit integer type. */
|
||||
typedef unsigned int sljit_ui;
|
||||
typedef signed int sljit_si;
|
||||
typedef unsigned int sljit_u32;
|
||||
typedef signed int sljit_s32;
|
||||
|
||||
/* Machine word type. Enough for storing a pointer.
|
||||
32 bit for 32 bit machines.
|
||||
|
@ -377,20 +380,22 @@ typedef long int sljit_sw;
|
|||
typedef sljit_uw sljit_p;
|
||||
|
||||
/* Floating point types. */
|
||||
typedef float sljit_s;
|
||||
typedef double sljit_d;
|
||||
typedef float sljit_f32;
|
||||
typedef double sljit_f64;
|
||||
|
||||
/* Shift for pointer sized data. */
|
||||
#define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT
|
||||
|
||||
/* Shift for double precision sized data. */
|
||||
#define SLJIT_DOUBLE_SHIFT 3
|
||||
#define SLJIT_SINGLE_SHIFT 2
|
||||
#define SLJIT_F32_SHIFT 2
|
||||
#define SLJIT_F64_SHIFT 3
|
||||
|
||||
#ifndef SLJIT_W
|
||||
|
||||
/* Defining long constants. */
|
||||
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
||||
#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
|
||||
#define SLJIT_W(w) (w##l)
|
||||
#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
||||
#define SLJIT_W(w) (w##ll)
|
||||
#else
|
||||
#define SLJIT_W(w) (w)
|
||||
|
@ -534,6 +539,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
|
|||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
|
||||
#define SLJIT_MALLOC_EXEC(size) sljit_malloc_exec(size)
|
||||
#define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr)
|
||||
|
||||
#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
|
||||
#define SLJIT_EXEC_OFFSET(ptr) sljit_exec_offset(ptr)
|
||||
#else
|
||||
#define SLJIT_EXEC_OFFSET(ptr) 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/**********************************************/
|
||||
|
@ -542,37 +555,37 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
|
|||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 10
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 9
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((2 + 4) * sizeof(sljit_sw))
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
|
||||
#else
|
||||
/* Maximum 3 arguments are passed on the stack, +1 for double alignment. */
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1 + 4) * sizeof(sljit_sw))
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
|
||||
#endif /* SLJIT_X86_32_FASTCALL */
|
||||
|
||||
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
|
||||
#ifndef _WIN64
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 13
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 6
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (sizeof(sljit_sw))
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
#else
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 13
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((4 + 2) * sizeof(sljit_sw))
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
|
||||
#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_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
|
||||
#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 11
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
|
||||
#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
|
@ -596,7 +609,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
|
|||
|
||||
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 17
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 21
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (4 * sizeof(sljit_sw))
|
||||
|
@ -652,7 +665,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
|
|||
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
|
||||
#if !defined(SLJIT_ASSERT) || !defined(SLJIT_ASSERT_STOP)
|
||||
#if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)
|
||||
|
||||
/* SLJIT_HALT_PROCESS must halt the process. */
|
||||
#ifndef SLJIT_HALT_PROCESS
|
||||
|
@ -664,7 +677,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#endif /* !SLJIT_ASSERT || !SLJIT_ASSERT_STOP */
|
||||
#endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */
|
||||
|
||||
/* Feel free to redefine these two macros. */
|
||||
#ifndef SLJIT_ASSERT
|
||||
|
@ -679,34 +692,33 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
|
|||
|
||||
#endif /* !SLJIT_ASSERT */
|
||||
|
||||
#ifndef SLJIT_ASSERT_STOP
|
||||
#ifndef SLJIT_UNREACHABLE
|
||||
|
||||
#define SLJIT_ASSERT_STOP() \
|
||||
#define SLJIT_UNREACHABLE() \
|
||||
do { \
|
||||
printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \
|
||||
SLJIT_HALT_PROCESS(); \
|
||||
} while (0)
|
||||
|
||||
#endif /* !SLJIT_ASSERT_STOP */
|
||||
#endif /* !SLJIT_UNREACHABLE */
|
||||
|
||||
#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
|
||||
|
||||
/* Forcing empty, but valid statements. */
|
||||
#undef SLJIT_ASSERT
|
||||
#undef SLJIT_ASSERT_STOP
|
||||
#undef SLJIT_UNREACHABLE
|
||||
|
||||
#define SLJIT_ASSERT(x) \
|
||||
do { } while (0)
|
||||
#define SLJIT_ASSERT_STOP() \
|
||||
#define SLJIT_UNREACHABLE() \
|
||||
do { } while (0)
|
||||
|
||||
#endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
|
||||
|
||||
#ifndef SLJIT_COMPILE_ASSERT
|
||||
|
||||
/* Should be improved eventually. */
|
||||
#define SLJIT_COMPILE_ASSERT(x, description) \
|
||||
SLJIT_ASSERT(x)
|
||||
switch(0) { case 0: case ((x) ? 1 : 0): break; }
|
||||
|
||||
#endif /* !SLJIT_COMPILE_ASSERT */
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -137,10 +137,10 @@ struct free_block {
|
|||
};
|
||||
|
||||
#define AS_BLOCK_HEADER(base, offset) \
|
||||
((struct block_header*)(((sljit_ub*)base) + offset))
|
||||
((struct block_header*)(((sljit_u8*)base) + offset))
|
||||
#define AS_FREE_BLOCK(base, offset) \
|
||||
((struct free_block*)(((sljit_ub*)base) + offset))
|
||||
#define MEM_START(base) ((void*)(((sljit_ub*)base) + sizeof(struct block_header)))
|
||||
((struct free_block*)(((sljit_u8*)base) + offset))
|
||||
#define MEM_START(base) ((void*)(((sljit_u8*)base) + sizeof(struct block_header)))
|
||||
#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7) & ~7)
|
||||
|
||||
static struct free_block* free_blocks;
|
||||
|
@ -153,7 +153,7 @@ static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block,
|
|||
free_block->size = size;
|
||||
|
||||
free_block->next = free_blocks;
|
||||
free_block->prev = 0;
|
||||
free_block->prev = NULL;
|
||||
if (free_blocks)
|
||||
free_blocks->prev = free_block;
|
||||
free_blocks = free_block;
|
||||
|
@ -180,8 +180,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
|
|||
sljit_uw chunk_size;
|
||||
|
||||
allocator_grab_lock();
|
||||
if (size < sizeof(struct free_block))
|
||||
size = sizeof(struct free_block);
|
||||
if (size < (64 - sizeof(struct block_header)))
|
||||
size = (64 - sizeof(struct block_header));
|
||||
size = ALIGN_SIZE(size);
|
||||
|
||||
free_block = free_blocks;
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -26,7 +26,7 @@
|
|||
|
||||
/* mips 32-bit arch dependent functions. */
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
|
||||
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
|
||||
{
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
@ -40,50 +40,52 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar,
|
|||
|
||||
#define EMIT_LOGICAL(op_imm, op_norm) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
if (op & SLJIT_SET_Z) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
if (!(flags & UNUSED_DEST)) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
|
||||
} \
|
||||
else { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
if (op & SLJIT_SET_Z) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
if (!(flags & UNUSED_DEST)) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
#define EMIT_SHIFT(op_imm, op_v) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
if (op & SLJIT_SET_Z) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
if (!(flags & UNUSED_DEST)) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
|
||||
} \
|
||||
else { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
if (op & SLJIT_SET_Z) \
|
||||
FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
if (!(flags & UNUSED_DEST)) \
|
||||
FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_sw src2)
|
||||
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
|
||||
sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
|
||||
{
|
||||
sljit_s32 is_overflow, is_carry, is_handled;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOV_S8:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB) {
|
||||
if (op == SLJIT_MOV_S8) {
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
|
@ -93,15 +95,16 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOV_S16:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH) {
|
||||
if (op == SLJIT_MOV_S16) {
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
|
@ -111,24 +114,25 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (op & SLJIT_SET_E)
|
||||
if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
if (!(flags & UNUSED_DEST))
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
if (op & SLJIT_SET_E)
|
||||
if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
if (!(flags & UNUSED_DEST))
|
||||
FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
|
||||
#else
|
||||
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
|
||||
|
@ -145,130 +149,192 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
|
||||
if (op & SLJIT_SET_E)
|
||||
return push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_ADD:
|
||||
is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
|
||||
is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (is_overflow) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
else if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
|
||||
|
||||
if (is_overflow || is_carry) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
|
||||
else {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
}
|
||||
}
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (op & SLJIT_SET_E)
|
||||
if (is_overflow)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
else if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
|
||||
if (is_overflow || is_carry)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
/* a + b >= a | b (otherwise, the carry should be set to 1). */
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (!(op & SLJIT_SET_O))
|
||||
if (is_overflow || is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
if (!is_overflow)
|
||||
return SLJIT_SUCCESS;
|
||||
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);
|
||||
FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
|
||||
|
||||
case SLJIT_ADDC:
|
||||
is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C) {
|
||||
if (is_carry) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
else {
|
||||
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 | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_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(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (is_carry)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_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(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
if (!(op & SLJIT_SET_C))
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
|
||||
if (!is_carry)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
/* 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 ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
/* Set carry flag. */
|
||||
return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG);
|
||||
return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
|
||||
|
||||
case SLJIT_SUB:
|
||||
if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
|
||||
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
flags &= ~SRC2_IMM;
|
||||
}
|
||||
|
||||
is_handled = 0;
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (src2 >= 0)
|
||||
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(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
|
||||
is_handled = 1;
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
|
||||
FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
|
||||
is_handled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
|
||||
is_handled = 1;
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
flags &= ~SRC2_IMM;
|
||||
}
|
||||
|
||||
if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
}
|
||||
else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
}
|
||||
else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
}
|
||||
else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
}
|
||||
}
|
||||
|
||||
if (is_handled) {
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
if (!(flags & UNUSED_DEST))
|
||||
return push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (!(flags & UNUSED_DEST))
|
||||
return push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst));
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
|
||||
is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (is_overflow) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
}
|
||||
else if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
|
||||
|
||||
if (is_overflow || is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (op & SLJIT_SET_E)
|
||||
if (is_overflow)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
else if (op & SLJIT_SET_Z)
|
||||
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))
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (op & SLJIT_SET_U)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
|
||||
if (op & SLJIT_SET_S) {
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
|
||||
}
|
||||
|
||||
if (is_overflow || is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
|
||||
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
if (!(op & SLJIT_SET_O))
|
||||
if (!is_overflow)
|
||||
return SLJIT_SUCCESS;
|
||||
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);
|
||||
FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
|
||||
|
||||
case SLJIT_SUBC:
|
||||
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
|
||||
|
@ -277,28 +343,31 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
flags &= ~SRC2_IMM;
|
||||
}
|
||||
|
||||
is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
if (is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_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(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_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(LESS_FLAG), LESS_FLAG));
|
||||
if (is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
|
||||
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(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
|
||||
return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MUL:
|
||||
SLJIT_ASSERT(!(flags & SRC2_IMM));
|
||||
if (!(op & SLJIT_SET_O)) {
|
||||
|
||||
if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
|
@ -307,10 +376,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(ULESS_FLAG), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
|
||||
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);
|
||||
FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
|
||||
return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
|
||||
|
||||
case SLJIT_AND:
|
||||
EMIT_LOGICAL(ANDI, AND);
|
||||
|
@ -337,30 +406,32 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));
|
||||
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -26,11 +26,11 @@
|
|||
|
||||
/* mips 64-bit arch dependent functions. */
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
|
||||
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
|
||||
{
|
||||
sljit_si shift = 32;
|
||||
sljit_si shift2;
|
||||
sljit_si inv = 0;
|
||||
sljit_s32 shift = 32;
|
||||
sljit_s32 shift2;
|
||||
sljit_s32 inv = 0;
|
||||
sljit_ins ins;
|
||||
sljit_uw uimm;
|
||||
|
||||
|
@ -119,48 +119,49 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar,
|
|||
}
|
||||
|
||||
#define SELECT_OP(a, b) \
|
||||
(!(op & SLJIT_INT_OP) ? a : b)
|
||||
(!(op & SLJIT_I32_OP) ? a : b)
|
||||
|
||||
#define EMIT_LOGICAL(op_imm, op_norm) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
if (op & SLJIT_SET_Z) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
if (!(flags & UNUSED_DEST)) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
|
||||
} \
|
||||
else { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
if (op & SLJIT_SET_Z) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
if (!(flags & UNUSED_DEST)) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
#define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (src2 >= 32) { \
|
||||
SLJIT_ASSERT(!(op & SLJIT_INT_OP)); \
|
||||
SLJIT_ASSERT(!(op & SLJIT_I32_OP)); \
|
||||
ins = op_dimm32; \
|
||||
src2 -= 32; \
|
||||
} \
|
||||
else \
|
||||
ins = (op & SLJIT_INT_OP) ? op_imm : op_dimm; \
|
||||
if (op & SLJIT_SET_E) \
|
||||
ins = (op & SLJIT_I32_OP) ? op_imm : op_dimm; \
|
||||
if (op & SLJIT_SET_Z) \
|
||||
FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
if (!(flags & UNUSED_DEST)) \
|
||||
FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
|
||||
} \
|
||||
else { \
|
||||
ins = (op & SLJIT_INT_OP) ? op_v : op_dv; \
|
||||
if (op & SLJIT_SET_E) \
|
||||
ins = (op & SLJIT_I32_OP) ? op_v : op_dv; \
|
||||
if (op & SLJIT_SET_Z) \
|
||||
FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
if (!(flags & UNUSED_DEST)) \
|
||||
FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_sw src2)
|
||||
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
|
||||
sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
|
||||
{
|
||||
sljit_ins ins;
|
||||
sljit_s32 is_overflow, is_carry, is_handled;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOV:
|
||||
|
@ -170,57 +171,59 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOV_S8:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB) {
|
||||
if (op == SLJIT_MOV_S8) {
|
||||
FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
|
||||
return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOV_S16:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH) {
|
||||
if (op == SLJIT_MOV_S16) {
|
||||
FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UI:
|
||||
SLJIT_ASSERT(!(op & SLJIT_INT_OP));
|
||||
case SLJIT_MOV_U32:
|
||||
SLJIT_ASSERT(!(op & SLJIT_I32_OP));
|
||||
FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
|
||||
return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
|
||||
|
||||
case SLJIT_MOV_SI:
|
||||
case SLJIT_MOV_S32:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (op & SLJIT_SET_E)
|
||||
if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
if (!(flags & UNUSED_DEST))
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
if (op & SLJIT_SET_E)
|
||||
if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
if (!(flags & UNUSED_DEST))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));
|
||||
#else
|
||||
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
|
||||
|
@ -231,136 +234,198 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
/* Check zero. */
|
||||
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_INT_OP) ? 32 : 64), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_I32_OP) ? 32 : 64), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst)));
|
||||
/* Loop for searching the highest bit. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
|
||||
if (op & SLJIT_SET_E)
|
||||
return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_ADD:
|
||||
is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
|
||||
is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (is_overflow) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
else if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
|
||||
|
||||
if (is_overflow || is_carry) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
|
||||
else {
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
}
|
||||
}
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (op & SLJIT_SET_E)
|
||||
if (is_overflow)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
else if (op & SLJIT_SET_Z)
|
||||
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))
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
|
||||
if (is_overflow || is_carry)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
/* a + b >= a | b (otherwise, the carry should be set to 1). */
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (!(op & SLJIT_SET_O))
|
||||
if (is_overflow || is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
if (!is_overflow)
|
||||
return SLJIT_SUCCESS;
|
||||
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);
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
|
||||
|
||||
case SLJIT_ADDC:
|
||||
is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C) {
|
||||
if (is_carry) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
else {
|
||||
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) | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_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(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (is_carry)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_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(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
if (!(op & SLJIT_SET_C))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
|
||||
if (!is_carry)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
/* 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 ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
/* Set carry flag. */
|
||||
return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG);
|
||||
return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
|
||||
|
||||
case SLJIT_SUB:
|
||||
if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
|
||||
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
flags &= ~SRC2_IMM;
|
||||
}
|
||||
|
||||
is_handled = 0;
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (src2 >= 0)
|
||||
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(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
|
||||
is_handled = 1;
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
|
||||
FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
|
||||
is_handled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
|
||||
is_handled = 1;
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
flags &= ~SRC2_IMM;
|
||||
}
|
||||
|
||||
if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
}
|
||||
else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
}
|
||||
else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
}
|
||||
else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
}
|
||||
}
|
||||
|
||||
if (is_handled) {
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
if (!(flags & UNUSED_DEST))
|
||||
return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (!(flags & UNUSED_DEST))
|
||||
return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
|
||||
is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (is_overflow) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
}
|
||||
else if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
|
||||
|
||||
if (is_overflow || is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (op & SLJIT_SET_E)
|
||||
if (is_overflow)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
else if (op & SLJIT_SET_Z)
|
||||
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))
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (op & SLJIT_SET_U)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
|
||||
if (op & SLJIT_SET_S) {
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
|
||||
}
|
||||
|
||||
if (is_overflow || is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
|
||||
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
if (!(op & SLJIT_SET_O))
|
||||
if (!is_overflow)
|
||||
return SLJIT_SUCCESS;
|
||||
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);
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
|
||||
if (op & SLJIT_SET_Z)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
|
||||
|
||||
case SLJIT_SUBC:
|
||||
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
|
||||
|
@ -369,30 +434,33 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
flags &= ~SRC2_IMM;
|
||||
}
|
||||
|
||||
is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
if (is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_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(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_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(LESS_FLAG), LESS_FLAG));
|
||||
if (is_carry)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
|
||||
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(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
|
||||
return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MUL:
|
||||
SLJIT_ASSERT(!(flags & SRC2_IMM));
|
||||
if (!(op & SLJIT_SET_O)) {
|
||||
|
||||
if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
if (op & SLJIT_INT_OP)
|
||||
if (op & SLJIT_I32_OP)
|
||||
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
|
||||
FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
|
||||
return push_inst(compiler, MFLO | D(dst), DR(dst));
|
||||
|
@ -402,10 +470,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(ULESS_FLAG), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
|
||||
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);
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
|
||||
return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
|
||||
|
||||
case SLJIT_AND:
|
||||
EMIT_LOGICAL(ANDI, AND);
|
||||
|
@ -432,11 +500,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));
|
||||
|
@ -446,18 +514,19 @@ static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_s
|
|||
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
|
||||
inst[5] = (inst[5] & 0xffff0000) | (new_addr & 0xffff);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);
|
||||
inst[5] = (inst[5] & 0xffff0000) | (new_target & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 6);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
|
@ -465,5 +534,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
|||
inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 6);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -26,7 +26,7 @@
|
|||
|
||||
/* ppc 32-bit arch dependent functions. */
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
|
||||
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
|
||||
{
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
|
||||
|
@ -41,39 +41,39 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sl
|
|||
#define INS_CLEAR_LEFT(dst, src, from) \
|
||||
(RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1))
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_si src2)
|
||||
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
|
||||
sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
|
||||
{
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOV_S8:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB)
|
||||
if (op == SLJIT_MOV_S8)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
|
||||
}
|
||||
else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
|
||||
else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOV_S16:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH)
|
||||
if (op == SLJIT_MOV_S16)
|
||||
return push_inst(compiler, EXTSH | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
|
||||
}
|
||||
|
@ -88,77 +88,86 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
|
||||
case SLJIT_NEG:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
|
||||
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||
return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
|
||||
return push_inst(compiler, CNTLZW | S(src2) | A(dst));
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
|
||||
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||
return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
|
||||
if (flags & ALT_FORM3)
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
||||
|
||||
if (flags & ALT_FORM4) {
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));
|
||||
src1 = dst;
|
||||
}
|
||||
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM4) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
|
||||
}
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
||||
return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
if (flags & ALT_FORM4)
|
||||
return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
|
||||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, MTXER | S(0));
|
||||
}
|
||||
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
|
||||
|
||||
case SLJIT_SUB:
|
||||
if (flags & ALT_FORM1) {
|
||||
if (flags & ALT_FORM2) {
|
||||
FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));
|
||||
if (!(flags & ALT_FORM3))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));
|
||||
if (!(flags & ALT_FORM3))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||
return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM3) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & (ALT_FORM2 | ALT_FORM3)) {
|
||||
|
||||
if (flags & ALT_FORM4) {
|
||||
if (flags & ALT_FORM5) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
if (flags & ALT_FORM2)
|
||||
FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
|
||||
if (flags & ALT_FORM3)
|
||||
return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm);
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & (ALT_FORM4 | ALT_FORM5)) {
|
||||
if (flags & ALT_FORM4)
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
|
||||
if (flags & ALT_FORM5)
|
||||
FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2));
|
||||
}
|
||||
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
if (flags & ALT_FORM6)
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
if (flags & ALT_FORM5)
|
||||
return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_SUBC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
|
||||
return push_inst(compiler, MTXER | S(0));
|
||||
}
|
||||
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_MUL:
|
||||
|
@ -166,7 +175,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
|
||||
return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_AND:
|
||||
if (flags & ALT_FORM1) {
|
||||
|
@ -228,42 +237,40 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_ASHR:
|
||||
if (flags & ALT_FORM3)
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
compiler->imm &= 0x1f;
|
||||
FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
|
||||
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
|
||||
}
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)));
|
||||
return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
|
||||
return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
|
||||
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -41,7 +41,7 @@
|
|||
#define PUSH_RLDICR(reg, shift) \
|
||||
push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
|
||||
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
|
||||
{
|
||||
sljit_uw tmp;
|
||||
sljit_uw shift;
|
||||
|
@ -145,8 +145,8 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sl
|
|||
src1 = TMP_REG1; \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_si src2)
|
||||
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
|
||||
sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
|
||||
{
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
|
@ -156,11 +156,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SI)
|
||||
if (op == SLJIT_MOV_S32)
|
||||
return push_inst(compiler, EXTSW | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0));
|
||||
}
|
||||
|
@ -169,26 +169,26 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOV_S8:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB)
|
||||
if (op == SLJIT_MOV_S8)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
|
||||
}
|
||||
else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
|
||||
else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOV_S16:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH)
|
||||
if (op == SLJIT_MOV_S16)
|
||||
return push_inst(compiler, EXTSH | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
|
||||
}
|
||||
|
@ -204,84 +204,118 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
|
||||
case SLJIT_NEG:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
|
||||
if ((flags & (ALT_FORM1 | ALT_SIGN_EXT)) == (ALT_FORM1 | ALT_SIGN_EXT)) {
|
||||
FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
|
||||
FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(TMP_REG2)));
|
||||
return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
|
||||
}
|
||||
|
||||
UN_EXTS();
|
||||
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
|
||||
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||
return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (flags & ALT_FORM1)
|
||||
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
|
||||
return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst));
|
||||
return push_inst(compiler, CNTLZW | S(src2) | A(dst));
|
||||
return push_inst(compiler, CNTLZD | S(src2) | A(dst));
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
|
||||
if (flags & ALT_SIGN_EXT) {
|
||||
FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
|
||||
src1 = TMP_REG1;
|
||||
FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
|
||||
src2 = TMP_REG2;
|
||||
}
|
||||
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||
FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)));
|
||||
if (flags & ALT_SIGN_EXT)
|
||||
return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
|
||||
if (flags & ALT_FORM3)
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
||||
|
||||
if (flags & ALT_FORM4) {
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));
|
||||
src1 = dst;
|
||||
}
|
||||
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
BIN_IMM_EXTS();
|
||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM4) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
|
||||
}
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
||||
BIN_EXTS();
|
||||
return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
if (flags & ALT_FORM4)
|
||||
return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
|
||||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, MTXER | S(0));
|
||||
}
|
||||
BIN_EXTS();
|
||||
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
|
||||
|
||||
case SLJIT_SUB:
|
||||
if (flags & ALT_FORM1) {
|
||||
if (flags & ALT_FORM2) {
|
||||
FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
|
||||
if (!(flags & ALT_FORM3))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
|
||||
if (!(flags & ALT_FORM3))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
if (flags & ALT_SIGN_EXT) {
|
||||
FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
|
||||
src1 = TMP_REG1;
|
||||
FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
|
||||
src2 = TMP_REG2;
|
||||
}
|
||||
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||
FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));
|
||||
if (flags & ALT_SIGN_EXT)
|
||||
return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM3) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & (ALT_FORM2 | ALT_FORM3)) {
|
||||
|
||||
if (flags & ALT_FORM4) {
|
||||
if (flags & ALT_FORM5) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
if (flags & ALT_FORM2)
|
||||
FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
|
||||
if (flags & ALT_FORM3)
|
||||
return push_inst(compiler, CMPLI | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & (ALT_FORM4 | ALT_FORM5)) {
|
||||
if (flags & ALT_FORM4)
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
|
||||
if (flags & ALT_FORM5)
|
||||
return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
BIN_EXTS();
|
||||
if (flags & ALT_FORM6)
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
if (flags & ALT_FORM5)
|
||||
return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_SUBC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
|
||||
return push_inst(compiler, MTXER | S(0));
|
||||
}
|
||||
BIN_EXTS();
|
||||
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
|
||||
|
||||
|
@ -292,8 +326,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
}
|
||||
BIN_EXTS();
|
||||
if (flags & ALT_FORM2)
|
||||
return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
|
||||
return push_inst(compiler, MULLD | OERC(flags) | D(dst) | A(src2) | B(src1));
|
||||
return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||
return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_AND:
|
||||
if (flags & ALT_FORM1) {
|
||||
|
@ -345,11 +379,9 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
compiler->imm &= 0x1f;
|
||||
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));
|
||||
}
|
||||
else {
|
||||
compiler->imm &= 0x3f;
|
||||
return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags));
|
||||
}
|
||||
}
|
||||
return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_LSHR:
|
||||
|
@ -359,37 +391,29 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
compiler->imm &= 0x1f;
|
||||
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));
|
||||
}
|
||||
else {
|
||||
compiler->imm &= 0x3f;
|
||||
return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags));
|
||||
}
|
||||
}
|
||||
return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_ASHR:
|
||||
if (flags & ALT_FORM3)
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
if (flags & ALT_FORM2) {
|
||||
compiler->imm &= 0x1f;
|
||||
FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
|
||||
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
|
||||
}
|
||||
else {
|
||||
compiler->imm &= 0x3f;
|
||||
FAIL_IF(push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4)));
|
||||
return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4));
|
||||
}
|
||||
}
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2)));
|
||||
return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
|
||||
return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));
|
||||
|
@ -398,18 +422,19 @@ static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_s
|
|||
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
|
||||
inst[4] = (inst[4] & 0xffff0000) | (new_addr & 0xffff);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);
|
||||
inst[4] = (inst[4] & 0xffff0000) | (new_target & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 5);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
|
@ -417,5 +442,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
|||
inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[4] = (inst[4] & 0xffff0000) | (new_constant & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 5);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -24,7 +24,7 @@
|
|||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sljit_sw imm)
|
||||
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw imm)
|
||||
{
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, OR | D(dst) | S1(0) | IMM(imm), DR(dst));
|
||||
|
@ -35,43 +35,43 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sl
|
|||
|
||||
#define ARG2(flags, src2) ((flags & SRC2_IMM) ? IMM(src2) : S2(src2))
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_sw src2)
|
||||
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
|
||||
sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
|
||||
{
|
||||
SLJIT_COMPILE_ASSERT(ICC_IS_SET == SET_FLAGS, icc_is_set_and_set_flags_must_be_the_same);
|
||||
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, OR | D(dst) | S1(0) | S2(src2), DR(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOV_S8:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_UB)
|
||||
if (op == SLJIT_MOV_U8)
|
||||
return push_inst(compiler, AND | D(dst) | S1(src2) | IMM(0xff), DR(dst));
|
||||
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(24), DR(dst)));
|
||||
return push_inst(compiler, SRA | D(dst) | S1(dst) | IMM(24), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOV_S16:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(16), DR(dst)));
|
||||
return push_inst(compiler, (op == SLJIT_MOV_SH ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst));
|
||||
return push_inst(compiler, (op == SLJIT_MOV_S16 ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
|
@ -80,18 +80,17 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
/* sparc 32 does not support SLJIT_KEEP_FLAGS. Not sure I can fix this. */
|
||||
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS));
|
||||
FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS | (flags & SET_FLAGS)));
|
||||
FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst)));
|
||||
|
||||
/* Loop. */
|
||||
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS));
|
||||
FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS));
|
||||
return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS | (flags & SET_FLAGS));
|
||||
return push_inst(compiler, ADD | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS);
|
||||
|
||||
case SLJIT_ADD:
|
||||
return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
@ -135,30 +134,32 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((init_value >> 10) & 0x3fffff), DR(dst)));
|
||||
return push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (init_value & 0x3ff), DR(dst));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffc00000) | ((new_addr >> 10) & 0x3fffff);
|
||||
inst[1] = (inst[1] & 0xfffffc00) | (new_addr & 0x3ff);
|
||||
inst[0] = (inst[0] & 0xffc00000) | ((new_target >> 10) & 0x3fffff);
|
||||
inst[1] = (inst[1] & 0xfffffc00) | (new_target & 0x3ff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffc00000) | ((new_constant >> 10) & 0x3fffff);
|
||||
inst[1] = (inst[1] & 0xfffffc00) | (new_constant & 0x3ff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -24,14 +24,16 @@
|
|||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
|
||||
SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
|
||||
{
|
||||
return "SPARC" SLJIT_CPUINFO;
|
||||
}
|
||||
|
||||
/* Length of an instruction word
|
||||
Both for sparc-32 and sparc-64 */
|
||||
typedef sljit_ui sljit_ins;
|
||||
typedef sljit_u32 sljit_ins;
|
||||
|
||||
#if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)
|
||||
|
||||
static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
|
||||
{
|
||||
|
@ -82,6 +84,8 @@ static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */
|
||||
|
||||
/* TMP_REG2 is not used by getput_arg */
|
||||
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
|
||||
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
|
||||
|
@ -91,7 +95,7 @@ static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
|
|||
#define TMP_FREG1 (0)
|
||||
#define TMP_FREG2 ((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) << 1)
|
||||
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
|
||||
static const sljit_u8 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
|
||||
};
|
||||
|
||||
|
@ -181,7 +185,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
|
|||
|
||||
/* dest_reg is the absolute name of the register
|
||||
Useful for reordering instructions in the delay slot. */
|
||||
static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_si delay_slot)
|
||||
static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)
|
||||
{
|
||||
sljit_ins *ptr;
|
||||
SLJIT_ASSERT((delay_slot & DST_INS_MASK) == UNMOVABLE_INS
|
||||
|
@ -195,7 +199,7 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
|
||||
static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_sw diff;
|
||||
sljit_uw target_addr;
|
||||
|
@ -209,7 +213,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
|
|||
target_addr = jump->u.target;
|
||||
else {
|
||||
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
|
||||
target_addr = (sljit_uw)(code + jump->u.label->size);
|
||||
target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
|
||||
}
|
||||
inst = (sljit_ins*)jump->addr;
|
||||
|
||||
|
@ -235,8 +239,9 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
|
|||
if (jump->flags & IS_COND)
|
||||
inst--;
|
||||
|
||||
diff = ((sljit_sw)target_addr - (sljit_sw)(inst - 1) - executable_offset) >> 2;
|
||||
|
||||
if (jump->flags & IS_MOVABLE) {
|
||||
diff = ((sljit_sw)target_addr - (sljit_sw)(inst - 1)) >> 2;
|
||||
if (diff <= MAX_DISP && diff >= MIN_DISP) {
|
||||
jump->flags |= PATCH_B;
|
||||
inst--;
|
||||
|
@ -253,7 +258,8 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
|
|||
}
|
||||
}
|
||||
|
||||
diff = ((sljit_sw)target_addr - (sljit_sw)(inst)) >> 2;
|
||||
diff += sizeof(sljit_ins);
|
||||
|
||||
if (diff <= MAX_DISP && diff >= MIN_DISP) {
|
||||
jump->flags |= PATCH_B;
|
||||
if (jump->flags & IS_COND)
|
||||
|
@ -276,6 +282,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
sljit_ins *buf_ptr;
|
||||
sljit_ins *buf_end;
|
||||
sljit_uw word_count;
|
||||
sljit_sw executable_offset;
|
||||
sljit_uw addr;
|
||||
|
||||
struct sljit_label *label;
|
||||
|
@ -292,9 +299,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
code_ptr = code;
|
||||
word_count = 0;
|
||||
executable_offset = SLJIT_EXEC_OFFSET(code);
|
||||
|
||||
label = compiler->labels;
|
||||
jump = compiler->jumps;
|
||||
const_ = compiler->consts;
|
||||
|
||||
do {
|
||||
buf_ptr = (sljit_ins*)buf->memory;
|
||||
buf_end = buf_ptr + (buf->used_size >> 2);
|
||||
|
@ -306,7 +316,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
/* These structures are ordered by their address. */
|
||||
if (label && label->size == word_count) {
|
||||
/* Just recording the address. */
|
||||
label->addr = (sljit_uw)code_ptr;
|
||||
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
||||
label->size = code_ptr - code;
|
||||
label = label->next;
|
||||
}
|
||||
|
@ -316,7 +326,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
#else
|
||||
jump->addr = (sljit_uw)(code_ptr - 6);
|
||||
#endif
|
||||
code_ptr = detect_jump_type(jump, code_ptr, code);
|
||||
code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
|
||||
jump = jump->next;
|
||||
}
|
||||
if (const_ && const_->addr == word_count) {
|
||||
|
@ -332,7 +342,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
} while (buf);
|
||||
|
||||
if (label && label->size == word_count) {
|
||||
label->addr = (sljit_uw)code_ptr;
|
||||
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
||||
label->size = code_ptr - code;
|
||||
label = label->next;
|
||||
}
|
||||
|
@ -340,7 +350,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
SLJIT_ASSERT(!label);
|
||||
SLJIT_ASSERT(!jump);
|
||||
SLJIT_ASSERT(!const_);
|
||||
SLJIT_ASSERT(code_ptr - code <= (sljit_si)compiler->size);
|
||||
SLJIT_ASSERT(code_ptr - code <= (sljit_s32)compiler->size);
|
||||
|
||||
jump = compiler->jumps;
|
||||
while (jump) {
|
||||
|
@ -349,13 +359,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
buf_ptr = (sljit_ins *)jump->addr;
|
||||
|
||||
if (jump->flags & PATCH_CALL) {
|
||||
addr = (sljit_sw)(addr - jump->addr) >> 2;
|
||||
addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
|
||||
SLJIT_ASSERT((sljit_sw)addr <= 0x1fffffff && (sljit_sw)addr >= -0x20000000);
|
||||
buf_ptr[0] = CALL | (addr & 0x3fffffff);
|
||||
break;
|
||||
}
|
||||
if (jump->flags & PATCH_B) {
|
||||
addr = (sljit_sw)(addr - jump->addr) >> 2;
|
||||
addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
|
||||
SLJIT_ASSERT((sljit_sw)addr <= MAX_DISP && (sljit_sw)addr >= MIN_DISP);
|
||||
buf_ptr[0] = (buf_ptr[0] & ~DISP_MASK) | (addr & DISP_MASK);
|
||||
break;
|
||||
|
@ -374,11 +384,37 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
|
||||
compiler->error = SLJIT_ERR_COMPILED;
|
||||
compiler->executable_offset = executable_offset;
|
||||
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
|
||||
|
||||
code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
|
||||
code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
||||
|
||||
SLJIT_CACHE_FLUSH(code, code_ptr);
|
||||
return code;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||
{
|
||||
switch (feature_type) {
|
||||
case SLJIT_HAS_FPU:
|
||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||
return SLJIT_IS_FPU_AVAILABLE;
|
||||
#else
|
||||
/* Available by default. */
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)
|
||||
case SLJIT_HAS_CMOV:
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Entry, exit */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
@ -418,9 +454,9 @@ 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 options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
|
@ -442,9 +478,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si 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_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
|
@ -454,7 +490,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_return(compiler, op, src, srcw));
|
||||
|
@ -478,7 +514,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
|||
#define ARCH_32_64(a, b) b
|
||||
#endif
|
||||
|
||||
static SLJIT_CONST sljit_ins data_transfer_insts[16 + 4] = {
|
||||
static const sljit_ins data_transfer_insts[16 + 4] = {
|
||||
/* u w s */ ARCH_32_64(OPC1(3) | OPC3(0x04) /* stw */, OPC1(3) | OPC3(0x0e) /* stx */),
|
||||
/* u w l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x0b) /* ldx */),
|
||||
/* u b s */ OPC1(3) | OPC3(0x05) /* stb */,
|
||||
|
@ -506,7 +542,7 @@ static SLJIT_CONST sljit_ins data_transfer_insts[16 + 4] = {
|
|||
#undef ARCH_32_64
|
||||
|
||||
/* Can perform an operation using at most 1 instruction. */
|
||||
static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
|
||||
static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
|
||||
{
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
|
@ -529,7 +565,7 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
|
|||
/* See getput_arg below.
|
||||
Note: can_cache is called only for binary operators. Those
|
||||
operators always uses word arguments without write back. */
|
||||
static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
|
||||
static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
|
||||
{
|
||||
SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
|
||||
|
||||
|
@ -549,9 +585,9 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
|
|||
}
|
||||
|
||||
/* Emit the necessary instructions. See can_cache above. */
|
||||
static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
|
||||
static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
|
||||
{
|
||||
sljit_si base, arg2, delay_slot;
|
||||
sljit_s32 base, arg2, delay_slot;
|
||||
sljit_ins dest;
|
||||
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
@ -563,7 +599,6 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
|
|||
base = arg & REG_MASK;
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
argw &= 0x3;
|
||||
SLJIT_ASSERT(argw != 0);
|
||||
|
||||
/* Using the cache. */
|
||||
if (((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) && (argw == compiler->cache_argw))
|
||||
|
@ -613,7 +648,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
|
|||
return push_inst(compiler, ADD | D(base) | S1(base) | S2(arg2), DR(base));
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
|
||||
static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
|
||||
{
|
||||
if (getput_arg_fast(compiler, flags, reg, arg, argw))
|
||||
return compiler->error;
|
||||
|
@ -622,44 +657,42 @@ static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_
|
|||
return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
|
||||
static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
|
||||
{
|
||||
if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
|
||||
return compiler->error;
|
||||
return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
|
||||
}
|
||||
|
||||
static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
sljit_si src2, sljit_sw src2w)
|
||||
static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src1, sljit_sw src1w,
|
||||
sljit_s32 src2, sljit_sw src2w)
|
||||
{
|
||||
/* arg1 goes to TMP_REG1 or src reg
|
||||
arg2 goes to TMP_REG2, imm or src reg
|
||||
TMP_REG3 can be used for caching
|
||||
result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
|
||||
sljit_si dst_r = TMP_REG2;
|
||||
sljit_si src1_r;
|
||||
sljit_s32 dst_r = TMP_REG2;
|
||||
sljit_s32 src1_r;
|
||||
sljit_sw src2_r = 0;
|
||||
sljit_si sugg_src2_r = TMP_REG2;
|
||||
sljit_s32 sugg_src2_r = TMP_REG2;
|
||||
|
||||
if (!(flags & ALT_KEEP_CACHE)) {
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
else if (FAST_IS_REG(dst)) {
|
||||
if (dst != SLJIT_UNUSED) {
|
||||
if (FAST_IS_REG(dst)) {
|
||||
dst_r = dst;
|
||||
flags |= REG_DEST;
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
|
||||
sugg_src2_r = dst_r;
|
||||
}
|
||||
else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
|
||||
flags |= SLOW_DEST;
|
||||
}
|
||||
|
||||
if (flags & IMM_OP) {
|
||||
if ((src2 & SLJIT_IMM) && src2w) {
|
||||
|
@ -705,7 +738,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
if (FAST_IS_REG(src2)) {
|
||||
src2_r = src2;
|
||||
flags |= REG2_SOURCE;
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
|
||||
dst_r = src2_r;
|
||||
}
|
||||
else if (src2 & SLJIT_IMM) {
|
||||
|
@ -716,7 +749,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
}
|
||||
else {
|
||||
src2_r = 0;
|
||||
if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) && (dst & SLJIT_MEM))
|
||||
if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM))
|
||||
dst_r = 0;
|
||||
}
|
||||
}
|
||||
|
@ -758,7 +791,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op0(compiler, op));
|
||||
|
@ -769,30 +802,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
|||
return push_inst(compiler, TA, UNMOVABLE_INS);
|
||||
case SLJIT_NOP:
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
case SLJIT_LUMUL:
|
||||
case SLJIT_LSMUL:
|
||||
case SLJIT_LMUL_UW:
|
||||
case SLJIT_LMUL_SW:
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_LUMUL ? UMUL : SMUL) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? 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
|
||||
case SLJIT_UDIVMOD:
|
||||
case SLJIT_SDIVMOD:
|
||||
case SLJIT_UDIVI:
|
||||
case SLJIT_SDIVI:
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
|
||||
case SLJIT_DIVMOD_UW:
|
||||
case SLJIT_DIVMOD_SW:
|
||||
case SLJIT_DIV_UW:
|
||||
case SLJIT_DIV_SW:
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
if ((op | 0x2) == SLJIT_UDIVI)
|
||||
if ((op | 0x2) == SLJIT_DIV_UW)
|
||||
FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS));
|
||||
else {
|
||||
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));
|
||||
}
|
||||
if (op <= SLJIT_SDIVMOD)
|
||||
if (op <= SLJIT_DIVMOD_SW)
|
||||
FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
|
||||
if (op >= SLJIT_UDIVI)
|
||||
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
|
||||
if (op >= SLJIT_DIV_UW)
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_R1) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R1)));
|
||||
return push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1));
|
||||
|
@ -804,62 +837,65 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
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)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si flags = GET_FLAGS(op) ? SET_FLAGS : 0;
|
||||
sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_P:
|
||||
return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOV_UI:
|
||||
return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
case SLJIT_MOV_U32:
|
||||
return emit_op(compiler, SLJIT_MOV_U32, flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOV_SI:
|
||||
return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
case SLJIT_MOV_S32:
|
||||
return emit_op(compiler, SLJIT_MOV_S32, flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
|
||||
case SLJIT_MOV_U8:
|
||||
return emit_op(compiler, SLJIT_MOV_U8, flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOV_SB:
|
||||
return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
|
||||
case SLJIT_MOV_S8:
|
||||
return emit_op(compiler, SLJIT_MOV_S8, flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
|
||||
case SLJIT_MOV_U16:
|
||||
return emit_op(compiler, SLJIT_MOV_U16, flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOV_SH:
|
||||
return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
|
||||
case SLJIT_MOV_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_P:
|
||||
return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_UI:
|
||||
return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
case SLJIT_MOVU_U32:
|
||||
return emit_op(compiler, SLJIT_MOV_U32, flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_SI:
|
||||
return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
case SLJIT_MOVU_S32:
|
||||
return emit_op(compiler, SLJIT_MOV_S32, flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_UB:
|
||||
return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
|
||||
case SLJIT_MOVU_U8:
|
||||
return emit_op(compiler, SLJIT_MOV_U8, flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_SB:
|
||||
return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
|
||||
case SLJIT_MOVU_S8:
|
||||
return emit_op(compiler, SLJIT_MOV_S8, flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_UH:
|
||||
return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
|
||||
case SLJIT_MOVU_U16:
|
||||
return emit_op(compiler, SLJIT_MOV_U16, flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_SH:
|
||||
return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
|
||||
case SLJIT_MOVU_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
|
||||
case SLJIT_NOT:
|
||||
case SLJIT_CLZ:
|
||||
|
@ -872,12 +908,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(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)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src1, sljit_sw src1w,
|
||||
sljit_s32 src2, sljit_sw src2w)
|
||||
{
|
||||
sljit_si flags = GET_FLAGS(op) ? SET_FLAGS : 0;
|
||||
sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
|
||||
|
@ -885,6 +921,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
|
|||
ADJUST_LOCAL_OFFSET(src1, src1w);
|
||||
ADJUST_LOCAL_OFFSET(src2, src2w);
|
||||
|
||||
if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
switch (op) {
|
||||
case SLJIT_ADD:
|
||||
|
@ -906,7 +945,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
|
|||
if (src2 & SLJIT_IMM)
|
||||
src2w &= 0x1f;
|
||||
#else
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
#endif
|
||||
return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
@ -914,20 +953,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
|
||||
{
|
||||
CHECK_REG_INDEX(check_sljit_get_register_index(reg));
|
||||
return reg_map[reg];
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
|
||||
{
|
||||
CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
|
||||
return reg << 1;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, sljit_si size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, sljit_s32 size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
|
||||
|
@ -939,23 +978,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
|
|||
/* Floating point operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
|
||||
{
|
||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||
return SLJIT_IS_FPU_AVAILABLE;
|
||||
#else
|
||||
/* Available by default. */
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#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_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))
|
||||
#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_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)
|
||||
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 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));
|
||||
|
@ -966,9 +995,6 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *
|
|||
|
||||
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);
|
||||
|
@ -978,16 +1004,16 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *
|
|||
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)
|
||||
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
sljit_s32 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;
|
||||
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
|
||||
srcw = (sljit_s32)srcw;
|
||||
#endif
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
||||
src = TMP_REG1;
|
||||
|
@ -1008,9 +1034,9 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *
|
|||
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)
|
||||
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 src1, sljit_sw src1w,
|
||||
sljit_s32 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));
|
||||
|
@ -1029,21 +1055,21 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler
|
|||
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_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si dst_r;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR();
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
|
||||
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CONVD_FROMS)
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
|
||||
op ^= SLJIT_F32_OP;
|
||||
|
||||
dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
|
||||
|
@ -1055,30 +1081,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
|||
src <<= 1;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_DMOV:
|
||||
case SLJIT_MOV_F64:
|
||||
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))
|
||||
if (!(op & SLJIT_F32_OP))
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS));
|
||||
}
|
||||
else
|
||||
dst_r = src;
|
||||
}
|
||||
break;
|
||||
case SLJIT_DNEG:
|
||||
case SLJIT_NEG_F64:
|
||||
FAIL_IF(push_inst(compiler, FNEGS | DA(dst_r) | S2A(src), MOVABLE_INS));
|
||||
if (dst_r != src && !(op & SLJIT_SINGLE_OP))
|
||||
if (dst_r != src && !(op & SLJIT_F32_OP))
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS));
|
||||
break;
|
||||
case SLJIT_DABS:
|
||||
case SLJIT_ABS_F64:
|
||||
FAIL_IF(push_inst(compiler, FABSS | DA(dst_r) | S2A(src), MOVABLE_INS));
|
||||
if (dst_r != src && !(op & SLJIT_SINGLE_OP))
|
||||
if (dst_r != src && !(op & SLJIT_F32_OP))
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS));
|
||||
break;
|
||||
case SLJIT_CONVD_FROMS:
|
||||
case SLJIT_CONV_F64_FROM_F32:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOD, FDTOS) | DA(dst_r) | S2A(src), MOVABLE_INS));
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
op ^= SLJIT_F32_OP;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1087,12 +1113,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
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)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src1, sljit_sw src1w,
|
||||
sljit_s32 src2, sljit_sw src2w)
|
||||
{
|
||||
sljit_si dst_r, flags = 0;
|
||||
sljit_s32 dst_r, flags = 0;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
|
||||
|
@ -1146,19 +1172,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
|||
src2 = TMP_FREG2;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_DADD:
|
||||
case SLJIT_ADD_F64:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
break;
|
||||
|
||||
case SLJIT_DSUB:
|
||||
case SLJIT_SUB_F64:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
break;
|
||||
|
||||
case SLJIT_DMUL:
|
||||
case SLJIT_MUL_F64:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
break;
|
||||
|
||||
case SLJIT_DDIV:
|
||||
case SLJIT_DIV_F64:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
break;
|
||||
}
|
||||
|
@ -1176,16 +1202,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
|||
/* Other instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
/* For UNUSED dst. Uncommon, but possible. */
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (FAST_IS_REG(dst))
|
||||
return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), DR(dst));
|
||||
|
||||
|
@ -1193,7 +1215,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
|||
return emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
|
||||
|
@ -1231,33 +1253,33 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
|
|||
return label;
|
||||
}
|
||||
|
||||
static sljit_ins get_cc(sljit_si type)
|
||||
static sljit_ins get_cc(sljit_s32 type)
|
||||
{
|
||||
switch (type) {
|
||||
case SLJIT_EQUAL:
|
||||
case SLJIT_MUL_NOT_OVERFLOW:
|
||||
case SLJIT_D_NOT_EQUAL: /* Unordered. */
|
||||
case SLJIT_NOT_EQUAL_F64: /* Unordered. */
|
||||
return DA(0x1);
|
||||
|
||||
case SLJIT_NOT_EQUAL:
|
||||
case SLJIT_MUL_OVERFLOW:
|
||||
case SLJIT_D_EQUAL:
|
||||
case SLJIT_EQUAL_F64:
|
||||
return DA(0x9);
|
||||
|
||||
case SLJIT_LESS:
|
||||
case SLJIT_D_GREATER: /* Unordered. */
|
||||
case SLJIT_GREATER_F64: /* Unordered. */
|
||||
return DA(0x5);
|
||||
|
||||
case SLJIT_GREATER_EQUAL:
|
||||
case SLJIT_D_LESS_EQUAL:
|
||||
case SLJIT_LESS_EQUAL_F64:
|
||||
return DA(0xd);
|
||||
|
||||
case SLJIT_GREATER:
|
||||
case SLJIT_D_GREATER_EQUAL: /* Unordered. */
|
||||
case SLJIT_GREATER_EQUAL_F64: /* Unordered. */
|
||||
return DA(0xc);
|
||||
|
||||
case SLJIT_LESS_EQUAL:
|
||||
case SLJIT_D_LESS:
|
||||
case SLJIT_LESS_F64:
|
||||
return DA(0x4);
|
||||
|
||||
case SLJIT_SIG_LESS:
|
||||
|
@ -1273,20 +1295,20 @@ static sljit_ins get_cc(sljit_si type)
|
|||
return DA(0x2);
|
||||
|
||||
case SLJIT_OVERFLOW:
|
||||
case SLJIT_D_UNORDERED:
|
||||
case SLJIT_UNORDERED_F64:
|
||||
return DA(0x7);
|
||||
|
||||
case SLJIT_NOT_OVERFLOW:
|
||||
case SLJIT_D_ORDERED:
|
||||
case SLJIT_ORDERED_F64:
|
||||
return DA(0xf);
|
||||
|
||||
default:
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
return DA(0x8);
|
||||
}
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
|
||||
{
|
||||
struct sljit_jump *jump;
|
||||
|
||||
|
@ -1298,7 +1320,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
||||
type &= 0xff;
|
||||
|
||||
if (type < SLJIT_D_EQUAL) {
|
||||
if (type < SLJIT_EQUAL_F64) {
|
||||
jump->flags |= IS_COND;
|
||||
if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & ICC_IS_SET))
|
||||
jump->flags |= IS_MOVABLE;
|
||||
|
@ -1332,10 +1354,10 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
return jump;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
struct sljit_jump *jump = NULL;
|
||||
sljit_si src_r;
|
||||
sljit_s32 src_r;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
|
||||
|
@ -1367,35 +1389,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
|
|||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw,
|
||||
sljit_si type)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 type)
|
||||
{
|
||||
sljit_si reg, flags = (GET_FLAGS(op) ? SET_FLAGS : 0);
|
||||
sljit_s32 reg, flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
|
||||
CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
op = GET_OPCODE(op);
|
||||
reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
|
||||
src = TMP_REG1;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));
|
||||
|
||||
type &= 0xff;
|
||||
if (type < SLJIT_D_EQUAL)
|
||||
if (type < SLJIT_EQUAL_F64)
|
||||
FAIL_IF(push_inst(compiler, BICC | get_cc(type) | 3, UNMOVABLE_INS));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, FBFCC | get_cc(type) | 3, UNMOVABLE_INS));
|
||||
|
@ -1403,18 +1418,39 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(1), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(0), UNMOVABLE_INS));
|
||||
|
||||
if (op >= SLJIT_ADD)
|
||||
return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
|
||||
if (op >= SLJIT_ADD) {
|
||||
flags |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE;
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
|
||||
return emit_op(compiler, op, flags, dst, 0, dst, 0, TMP_REG2, 0);
|
||||
}
|
||||
|
||||
return (reg == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS;
|
||||
if (!(dst & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw);
|
||||
#else
|
||||
#error "Implementation required"
|
||||
#endif
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 dst_reg,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si reg;
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
|
||||
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
|
||||
#else
|
||||
#error "Implementation required"
|
||||
#endif
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||
{
|
||||
sljit_s32 reg;
|
||||
struct sljit_const *const_;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
|
@ -1425,7 +1461,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
PTR_FAIL_IF(!const_);
|
||||
set_const(const_, compiler);
|
||||
|
||||
reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
|
||||
reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved.
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved.
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -49,7 +49,7 @@
|
|||
#define ADDR_TMP (SLJIT_NUMBER_OF_REGISTERS + 5)
|
||||
#define PIC_ADDR_REG TMP_REG2
|
||||
|
||||
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
|
||||
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
|
||||
63, 0, 1, 2, 3, 4, 30, 31, 32, 33, 34, 54, 5, 16, 6, 7
|
||||
};
|
||||
|
||||
|
@ -106,7 +106,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
|
|||
*/
|
||||
#define CHECK_FLAGS(list) (!(flags & UNUSED_DEST) || (op & GET_FLAGS(~(list))))
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char *sljit_get_platform_name(void)
|
||||
SLJIT_API_FUNC_ATTRIBUTE const char *sljit_get_platform_name(void)
|
||||
{
|
||||
return "TileGX" SLJIT_CPUINFO;
|
||||
}
|
||||
|
@ -307,7 +307,7 @@ struct jit_instr {
|
|||
#define JOFF_X1(x) create_JumpOff_X1(x)
|
||||
#define BOFF_X1(x) create_BrOff_X1(x)
|
||||
|
||||
static SLJIT_CONST tilegx_mnemonic data_transfer_insts[16] = {
|
||||
static const tilegx_mnemonic data_transfer_insts[16] = {
|
||||
/* u w s */ TILEGX_OPC_ST /* st */,
|
||||
/* u w l */ TILEGX_OPC_LD /* ld */,
|
||||
/* u b s */ TILEGX_OPC_ST1 /* st1 */,
|
||||
|
@ -327,7 +327,7 @@ static SLJIT_CONST tilegx_mnemonic data_transfer_insts[16] = {
|
|||
};
|
||||
|
||||
#ifdef TILEGX_JIT_DEBUG
|
||||
static sljit_si push_inst_debug(struct sljit_compiler *compiler, sljit_ins ins, int line)
|
||||
static sljit_s32 push_inst_debug(struct sljit_compiler *compiler, sljit_ins ins, int line)
|
||||
{
|
||||
sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));
|
||||
FAIL_IF(!ptr);
|
||||
|
@ -338,7 +338,7 @@ static sljit_si push_inst_debug(struct sljit_compiler *compiler, sljit_ins ins,
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_si push_inst_nodebug(struct sljit_compiler *compiler, sljit_ins ins)
|
||||
static sljit_s32 push_inst_nodebug(struct sljit_compiler *compiler, sljit_ins ins)
|
||||
{
|
||||
sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));
|
||||
FAIL_IF(!ptr);
|
||||
|
@ -349,7 +349,7 @@ static sljit_si push_inst_nodebug(struct sljit_compiler *compiler, sljit_ins ins
|
|||
|
||||
#define push_inst(a, b) push_inst_debug(a, b, __LINE__)
|
||||
#else
|
||||
static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins)
|
||||
static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
|
||||
{
|
||||
sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));
|
||||
FAIL_IF(!ptr);
|
||||
|
@ -557,7 +557,7 @@ const struct Format* compute_format()
|
|||
return match;
|
||||
}
|
||||
|
||||
sljit_si assign_pipes()
|
||||
sljit_s32 assign_pipes()
|
||||
{
|
||||
unsigned long output_registers = 0;
|
||||
unsigned int i = 0;
|
||||
|
@ -621,7 +621,7 @@ tilegx_bundle_bits get_bundle_bit(struct jit_instr *inst)
|
|||
return bits;
|
||||
}
|
||||
|
||||
static sljit_si update_buffer(struct sljit_compiler *compiler)
|
||||
static sljit_s32 update_buffer(struct sljit_compiler *compiler)
|
||||
{
|
||||
int i;
|
||||
int orig_index = inst_buf_index;
|
||||
|
@ -687,7 +687,7 @@ static sljit_si update_buffer(struct sljit_compiler *compiler)
|
|||
inst_buf[0] = inst1;
|
||||
inst_buf_index = 1;
|
||||
} else
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
|
||||
#ifdef TILEGX_JIT_DEBUG
|
||||
return push_inst_nodebug(compiler, bits);
|
||||
|
@ -727,13 +727,13 @@ static sljit_si update_buffer(struct sljit_compiler *compiler)
|
|||
return push_inst(compiler, bits);
|
||||
#endif
|
||||
} else
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
}
|
||||
|
||||
static sljit_si flush_buffer(struct sljit_compiler *compiler)
|
||||
static sljit_s32 flush_buffer(struct sljit_compiler *compiler)
|
||||
{
|
||||
while (inst_buf_index != 0) {
|
||||
FAIL_IF(update_buffer(compiler));
|
||||
|
@ -741,7 +741,7 @@ static sljit_si flush_buffer(struct sljit_compiler *compiler)
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_si push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line)
|
||||
static sljit_s32 push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line)
|
||||
{
|
||||
if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
|
||||
FAIL_IF(update_buffer(compiler));
|
||||
|
@ -761,7 +761,7 @@ static sljit_si push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_si push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int line)
|
||||
static sljit_s32 push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int line)
|
||||
{
|
||||
if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
|
||||
FAIL_IF(update_buffer(compiler));
|
||||
|
@ -814,7 +814,7 @@ static sljit_si push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
|
|||
break;
|
||||
default:
|
||||
printf("unrecoginzed opc: %s\n", opcode->name);
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
}
|
||||
|
||||
inst_buf_index++;
|
||||
|
@ -822,7 +822,7 @@ static sljit_si push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_si push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int line)
|
||||
static sljit_s32 push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int line)
|
||||
{
|
||||
if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
|
||||
FAIL_IF(update_buffer(compiler));
|
||||
|
@ -859,7 +859,7 @@ static sljit_si push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
|
|||
break;
|
||||
default:
|
||||
printf("unrecoginzed opc: %s\n", opcode->name);
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
}
|
||||
|
||||
inst_buf_index++;
|
||||
|
@ -867,7 +867,7 @@ static sljit_si push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_si push_0_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int line)
|
||||
static sljit_s32 push_0_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int line)
|
||||
{
|
||||
if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
|
||||
FAIL_IF(update_buffer(compiler));
|
||||
|
@ -883,7 +883,7 @@ static sljit_si push_0_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_si push_jr_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int line)
|
||||
static sljit_s32 push_jr_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int line)
|
||||
{
|
||||
if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
|
||||
FAIL_IF(update_buffer(compiler));
|
||||
|
@ -1117,7 +1117,7 @@ SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compi
|
|||
return code;
|
||||
}
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
|
||||
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
|
||||
{
|
||||
|
||||
if (imm <= SIMM_16BIT_MAX && imm >= SIMM_16BIT_MIN)
|
||||
|
@ -1140,7 +1140,7 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar,
|
|||
return SHL16INSLI(dst_ar, dst_ar, imm);
|
||||
}
|
||||
|
||||
static sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm, int flush)
|
||||
static sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm, int flush)
|
||||
{
|
||||
/* Should *not* be optimized as load_immediate, as pcre relocation
|
||||
mechanism will match this fixed 4-instruction pattern. */
|
||||
|
@ -1155,7 +1155,7 @@ static sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst_ar, slj
|
|||
return SHL16INSLI(dst_ar, dst_ar, imm);
|
||||
}
|
||||
|
||||
static sljit_si emit_const_64(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm, int flush)
|
||||
static sljit_s32 emit_const_64(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm, int flush)
|
||||
{
|
||||
/* Should *not* be optimized as load_immediate, as pcre relocation
|
||||
mechanism will match this fixed 4-instruction pattern. */
|
||||
|
@ -1172,12 +1172,12 @@ 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 options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
sljit_ins base;
|
||||
sljit_si i, tmp;
|
||||
sljit_s32 i, tmp;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
|
@ -1222,9 +1222,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si 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_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
|
@ -1236,12 +1236,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si local_size;
|
||||
sljit_s32 local_size;
|
||||
sljit_ins base;
|
||||
sljit_si i, tmp;
|
||||
sljit_si saveds;
|
||||
sljit_s32 i, tmp;
|
||||
sljit_s32 saveds;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_return(compiler, op, src, srcw));
|
||||
|
@ -1285,7 +1285,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
|||
/* reg_ar is an absoulute register! */
|
||||
|
||||
/* Can perform an operation using at most 1 instruction. */
|
||||
static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw)
|
||||
static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
|
||||
{
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
|
@ -1311,7 +1311,7 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
|
|||
/* See getput_arg below.
|
||||
Note: can_cache is called only for binary operators. Those
|
||||
operators always uses word arguments without write back. */
|
||||
static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
|
||||
static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
|
||||
{
|
||||
SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
|
||||
|
||||
|
@ -1337,9 +1337,9 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
|
|||
}
|
||||
|
||||
/* Emit the necessary instructions. See can_cache above. */
|
||||
static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
|
||||
static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
|
||||
{
|
||||
sljit_si tmp_ar, base;
|
||||
sljit_s32 tmp_ar, base;
|
||||
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
if (!(next_arg & SLJIT_MEM)) {
|
||||
|
@ -1530,7 +1530,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
|
|||
return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw)
|
||||
static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
|
||||
{
|
||||
if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
|
||||
return compiler->error;
|
||||
|
@ -1540,14 +1540,14 @@ static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_
|
|||
return getput_arg(compiler, flags, reg_ar, arg, argw, 0, 0);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
|
||||
static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
|
||||
{
|
||||
if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
|
||||
return compiler->error;
|
||||
return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
|
||||
|
@ -1564,7 +1564,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
|||
return emit_op_mem(compiler, WORD_DATA, RA, dst, dstw);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
|
||||
|
@ -1582,9 +1582,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
return JR(RA);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags, sljit_si dst, sljit_si src1, sljit_sw src2)
|
||||
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
|
||||
{
|
||||
sljit_si overflow_ra = 0;
|
||||
sljit_s32 overflow_ra = 0;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOV:
|
||||
|
@ -1594,11 +1594,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
return ADD(reg_map[dst], reg_map[src2], ZERO);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SI)
|
||||
if (op == SLJIT_MOV_S32)
|
||||
return BFEXTS(reg_map[dst], reg_map[src2], 0, 31);
|
||||
|
||||
return BFEXTU(reg_map[dst], reg_map[src2], 0, 31);
|
||||
|
@ -1609,11 +1609,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOV_S8:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB)
|
||||
if (op == SLJIT_MOV_S8)
|
||||
return BFEXTS(reg_map[dst], reg_map[src2], 0, 7);
|
||||
|
||||
return BFEXTU(reg_map[dst], reg_map[src2], 0, 7);
|
||||
|
@ -1624,11 +1624,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOV_S16:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH)
|
||||
if (op == SLJIT_MOV_S16)
|
||||
return BFEXTS(reg_map[dst], reg_map[src2], 0, 15);
|
||||
|
||||
return BFEXTU(reg_map[dst], reg_map[src2], 0, 15);
|
||||
|
@ -1952,20 +1952,20 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w)
|
||||
static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)
|
||||
{
|
||||
/* arg1 goes to TMP_REG1 or src reg.
|
||||
arg2 goes to TMP_REG2, imm or src reg.
|
||||
TMP_REG3 can be used for caching.
|
||||
result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
|
||||
sljit_si dst_r = TMP_REG2;
|
||||
sljit_si src1_r;
|
||||
sljit_s32 dst_r = TMP_REG2;
|
||||
sljit_s32 src1_r;
|
||||
sljit_sw src2_r = 0;
|
||||
sljit_si sugg_src2_r = TMP_REG2;
|
||||
sljit_s32 sugg_src2_r = TMP_REG2;
|
||||
|
||||
if (!(flags & ALT_KEEP_CACHE)) {
|
||||
compiler->cache_arg = 0;
|
||||
|
@ -1973,14 +1973,14 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS;
|
||||
if (GET_FLAGS(op))
|
||||
flags |= UNUSED_DEST;
|
||||
} else if (FAST_IS_REG(dst)) {
|
||||
dst_r = dst;
|
||||
flags |= REG_DEST;
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
|
||||
sugg_src2_r = dst_r;
|
||||
} else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1_mapped, dst, dstw))
|
||||
flags |= SLOW_DEST;
|
||||
|
@ -2033,7 +2033,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
if (FAST_IS_REG(src2)) {
|
||||
src2_r = src2;
|
||||
flags |= REG2_SOURCE;
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
|
||||
dst_r = src2_r;
|
||||
} else if (src2 & SLJIT_IMM) {
|
||||
if (!(flags & SRC2_IMM)) {
|
||||
|
@ -2042,7 +2042,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
src2_r = sugg_src2_r;
|
||||
} else {
|
||||
src2_r = 0;
|
||||
if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) && (dst & SLJIT_MEM))
|
||||
if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM))
|
||||
dst_r = 0;
|
||||
}
|
||||
}
|
||||
|
@ -2082,21 +2082,18 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src, sljit_sw srcw, sljit_si type)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw, sljit_s32 type)
|
||||
{
|
||||
sljit_si sugg_dst_ar, dst_ar;
|
||||
sljit_si flags = GET_ALL_FLAGS(op);
|
||||
sljit_si mem_type = (op & SLJIT_INT_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
|
||||
sljit_s32 sugg_dst_ar, dst_ar;
|
||||
sljit_s32 flags = GET_ALL_FLAGS(op);
|
||||
sljit_s32 mem_type = (op & SLJIT_I32_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
if (op == SLJIT_MOV_SI || op == SLJIT_MOV_UI)
|
||||
if (op == SLJIT_MOV_S32 || op == SLJIT_MOV_U32)
|
||||
mem_type = INT_DATA | SIGNED_DATA;
|
||||
sugg_dst_ar = reg_map[(op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2];
|
||||
|
||||
|
@ -2143,7 +2140,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
break;
|
||||
|
||||
default:
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
dst_ar = sugg_dst_ar;
|
||||
break;
|
||||
}
|
||||
|
@ -2168,7 +2165,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) {
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) {
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op0(compiler, op));
|
||||
|
||||
|
@ -2180,17 +2177,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
|||
case SLJIT_BREAKPOINT:
|
||||
return PI(BPT);
|
||||
|
||||
case SLJIT_LUMUL:
|
||||
case SLJIT_LSMUL:
|
||||
case SLJIT_UDIVI:
|
||||
case SLJIT_SDIVI:
|
||||
SLJIT_ASSERT_STOP();
|
||||
case SLJIT_LMUL_UW:
|
||||
case SLJIT_LMUL_SW:
|
||||
case SLJIT_DIVMOD_UW:
|
||||
case SLJIT_DIVMOD_SW:
|
||||
case SLJIT_DIV_UW:
|
||||
case SLJIT_DIV_SW:
|
||||
SLJIT_UNREACHABLE();
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
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)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
|
||||
|
@ -2202,45 +2201,45 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
|
|||
case SLJIT_MOV_P:
|
||||
return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOV_UI:
|
||||
return emit_op(compiler, SLJIT_MOV_UI, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
case SLJIT_MOV_U32:
|
||||
return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOV_SI:
|
||||
return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
case SLJIT_MOV_S32:
|
||||
return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
return emit_op(compiler, SLJIT_MOV_UB, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub) srcw : srcw);
|
||||
case SLJIT_MOV_U8:
|
||||
return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8) srcw : srcw);
|
||||
|
||||
case SLJIT_MOV_SB:
|
||||
return emit_op(compiler, SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb) srcw : srcw);
|
||||
case SLJIT_MOV_S8:
|
||||
return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8) srcw : srcw);
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
return emit_op(compiler, SLJIT_MOV_UH, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh) srcw : srcw);
|
||||
case SLJIT_MOV_U16:
|
||||
return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16) srcw : srcw);
|
||||
|
||||
case SLJIT_MOV_SH:
|
||||
return emit_op(compiler, SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh) srcw : srcw);
|
||||
case SLJIT_MOV_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16) srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_P:
|
||||
return emit_op(compiler, SLJIT_MOV, WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_UI:
|
||||
return emit_op(compiler, SLJIT_MOV_UI, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
case SLJIT_MOVU_U32:
|
||||
return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_SI:
|
||||
return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
case SLJIT_MOVU_S32:
|
||||
return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_UB:
|
||||
return emit_op(compiler, SLJIT_MOV_UB, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub) srcw : srcw);
|
||||
case SLJIT_MOVU_U8:
|
||||
return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8) srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_SB:
|
||||
return emit_op(compiler, SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb) srcw : srcw);
|
||||
case SLJIT_MOVU_S8:
|
||||
return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8) srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_UH:
|
||||
return emit_op(compiler, SLJIT_MOV_UH, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh) srcw : srcw);
|
||||
case SLJIT_MOVU_U16:
|
||||
return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16) srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_SH:
|
||||
return emit_op(compiler, SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh) srcw : srcw);
|
||||
case SLJIT_MOVU_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16) srcw : srcw);
|
||||
|
||||
case SLJIT_NOT:
|
||||
return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
@ -2249,13 +2248,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
|
|||
return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
|
||||
|
||||
case SLJIT_CLZ:
|
||||
return emit_op(compiler, op, (op & SLJIT_INT_OP) ? INT_DATA : WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
return emit_op(compiler, op, (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(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)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
|
||||
|
@ -2285,7 +2284,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
|
|||
case SLJIT_ASHR:
|
||||
if (src2 & SLJIT_IMM)
|
||||
src2w &= 0x3f;
|
||||
if (op & SLJIT_INT_OP)
|
||||
if (op & SLJIT_I32_OP)
|
||||
src2w &= 0x1f;
|
||||
|
||||
return emit_op(compiler, op, IMM_OP, dst, dstw, src1, src1w, src2, src2w);
|
||||
|
@ -2312,9 +2311,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_comp
|
|||
return label;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si src_r = TMP_REG2;
|
||||
sljit_s32 src_r = TMP_REG2;
|
||||
struct sljit_jump *jump = NULL;
|
||||
|
||||
flush_buffer(compiler);
|
||||
|
@ -2401,11 +2400,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
|
|||
inst = BNEZ_X1 | SRCA_X1(src); \
|
||||
flags = IS_COND;
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
|
||||
{
|
||||
struct sljit_jump *jump;
|
||||
sljit_ins inst;
|
||||
sljit_si flags = 0;
|
||||
sljit_s32 flags = 0;
|
||||
|
||||
flush_buffer(compiler);
|
||||
|
||||
|
@ -2485,25 +2484,20 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil
|
|||
return jump;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
return 0;
|
||||
SLJIT_UNREACHABLE();
|
||||
}
|
||||
|
||||
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_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)
|
||||
{
|
||||
SLJIT_ASSERT_STOP();
|
||||
SLJIT_UNREACHABLE();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
SLJIT_ASSERT_STOP();
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||
{
|
||||
struct sljit_const *const_;
|
||||
sljit_si reg;
|
||||
sljit_s32 reg;
|
||||
|
||||
flush_buffer(compiler);
|
||||
|
||||
|
@ -2524,13 +2518,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_comp
|
|||
return const_;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_addr >> 32) & 0xffff) << 43);
|
||||
inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_addr >> 16) & 0xffff) << 43);
|
||||
inst[2] = (inst[2] & ~(0xFFFFL << 43)) | ((new_addr & 0xffff) << 43);
|
||||
inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_target >> 32) & 0xffff) << 43);
|
||||
inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_target >> 16) & 0xffff) << 43);
|
||||
inst[2] = (inst[2] & ~(0xFFFFL << 43)) | ((new_target & 0xffff) << 43);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 3);
|
||||
}
|
||||
|
||||
|
@ -2545,14 +2539,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
|||
SLJIT_CACHE_FLUSH(inst, inst + 4);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
|
||||
{
|
||||
CHECK_REG_INDEX(check_sljit_get_register_index(reg));
|
||||
return reg_map[reg];
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, sljit_si size)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
void *instruction, sljit_s32 size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -26,19 +26,19 @@
|
|||
|
||||
/* x86 32-bit arch dependent functions. */
|
||||
|
||||
static sljit_si emit_do_imm(struct sljit_compiler *compiler, sljit_ub opcode, sljit_sw imm)
|
||||
static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, sljit_sw imm)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_u8 *inst;
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw));
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1 + sizeof(sljit_sw));
|
||||
*inst++ = opcode;
|
||||
*(sljit_sw*)inst = imm;
|
||||
sljit_unaligned_store_sw(inst, imm);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type)
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset)
|
||||
{
|
||||
if (type == SLJIT_JUMP) {
|
||||
*code_ptr++ = JMP_i32;
|
||||
|
@ -57,33 +57,54 @@ static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_
|
|||
if (jump->flags & JUMP_LABEL)
|
||||
jump->flags |= PATCH_MW;
|
||||
else
|
||||
*(sljit_sw*)code_ptr = jump->u.target - (jump->addr + 4);
|
||||
sljit_unaligned_store_sw(code_ptr, jump->u.target - (jump->addr + 4) - (sljit_uw)executable_offset);
|
||||
code_ptr += 4;
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
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_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
sljit_si size;
|
||||
sljit_ub *inst;
|
||||
sljit_s32 size;
|
||||
sljit_u8 *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->args = args;
|
||||
compiler->flags_saved = 0;
|
||||
|
||||
size = 1 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
/* [esp+0] for saving temporaries and third argument for calls. */
|
||||
compiler->saveds_offset = 1 * sizeof(sljit_sw);
|
||||
#else
|
||||
/* [esp+0] for saving temporaries and space for maximum three arguments. */
|
||||
if (scratches <= 1)
|
||||
compiler->saveds_offset = 1 * sizeof(sljit_sw);
|
||||
else
|
||||
compiler->saveds_offset = ((scratches == 2) ? 2 : 3) * sizeof(sljit_sw);
|
||||
#endif
|
||||
|
||||
if (scratches > 3)
|
||||
compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw);
|
||||
|
||||
compiler->locals_offset = compiler->saveds_offset;
|
||||
|
||||
if (saveds > 3)
|
||||
compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw);
|
||||
|
||||
if (options & SLJIT_F64_ALIGNMENT)
|
||||
compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1);
|
||||
|
||||
size = 1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
size += (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
|
||||
#else
|
||||
size += (args > 0 ? (2 + args * 3) : 0);
|
||||
#endif
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
|
@ -94,11 +115,11 @@ 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 || scratches > 7)
|
||||
if (saveds > 2 || scratches > 9)
|
||||
PUSH_REG(reg_map[SLJIT_S2]);
|
||||
if (saveds > 1 || scratches > 8)
|
||||
if (saveds > 1 || scratches > 10)
|
||||
PUSH_REG(reg_map[SLJIT_S1]);
|
||||
if (saveds > 0 || scratches > 9)
|
||||
if (saveds > 0 || scratches > 11)
|
||||
PUSH_REG(reg_map[SLJIT_S0]);
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
|
@ -134,58 +155,71 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
|||
}
|
||||
#endif
|
||||
|
||||
SLJIT_COMPILE_ASSERT(SLJIT_LOCALS_OFFSET >= (2 + 4) * sizeof(sljit_uw), require_at_least_two_words);
|
||||
SLJIT_ASSERT(SLJIT_LOCALS_OFFSET > 0);
|
||||
|
||||
#if defined(__APPLE__)
|
||||
/* Ignore pushed registers and SLJIT_LOCALS_OFFSET when computing the aligned local size. */
|
||||
saveds = (2 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
|
||||
saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
|
||||
local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;
|
||||
#else
|
||||
if (options & SLJIT_DOUBLE_ALIGNMENT) {
|
||||
local_size = SLJIT_LOCALS_OFFSET + ((local_size + 7) & ~7);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 17);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(17);
|
||||
inst[0] = MOV_r_rm;
|
||||
inst[1] = MOD_REG | (reg_map[TMP_REG1] << 3) | reg_map[SLJIT_SP];
|
||||
inst[2] = GROUP_F7;
|
||||
inst[3] = MOD_REG | (0 << 3) | reg_map[SLJIT_SP];
|
||||
*(sljit_sw*)(inst + 4) = 0x4;
|
||||
inst[8] = JNE_i8;
|
||||
inst[9] = 6;
|
||||
inst[10] = GROUP_BINARY_81;
|
||||
inst[11] = MOD_REG | (5 << 3) | reg_map[SLJIT_SP];
|
||||
*(sljit_sw*)(inst + 12) = 0x4;
|
||||
inst[16] = PUSH_r + reg_map[TMP_REG1];
|
||||
}
|
||||
if (options & SLJIT_F64_ALIGNMENT)
|
||||
local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1));
|
||||
else
|
||||
local_size = SLJIT_LOCALS_OFFSET + ((local_size + 3) & ~3);
|
||||
local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 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_R0], local_size));
|
||||
#else
|
||||
local_size -= SLJIT_LOCALS_OFFSET;
|
||||
/* Space for a single argument. This amount is excluded when the stack is allocated below. */
|
||||
local_size -= sizeof(sljit_sw);
|
||||
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_SP, 0, SLJIT_SP, 0, SLJIT_IMM, SLJIT_LOCALS_OFFSET));
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, sizeof(sljit_sw)));
|
||||
#endif
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(local_size > 0);
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
if (options & SLJIT_F64_ALIGNMENT) {
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_SP, 0);
|
||||
|
||||
/* Some space might allocated during sljit_grow_stack() above on WIN32. */
|
||||
FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size + sizeof(sljit_sw)));
|
||||
|
||||
#if defined _WIN32 && !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (compiler->local_size > 1024)
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
TMP_REG1, 0, TMP_REG1, 0, SLJIT_IMM, sizeof(sljit_sw)));
|
||||
#endif
|
||||
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 6);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(6);
|
||||
inst[0] = GROUP_BINARY_81;
|
||||
inst[1] = MOD_REG | AND | reg_map[SLJIT_SP];
|
||||
sljit_unaligned_store_sw(inst + 2, ~(sizeof(sljit_f64) - 1));
|
||||
|
||||
/* The real local size must be used. */
|
||||
return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), compiler->local_size, TMP_REG1, 0);
|
||||
}
|
||||
#endif
|
||||
return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si 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_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
|
@ -193,44 +227,62 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
|
|||
|
||||
compiler->args = args;
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
/* [esp+0] for saving temporaries and third argument for calls. */
|
||||
compiler->saveds_offset = 1 * sizeof(sljit_sw);
|
||||
#else
|
||||
/* [esp+0] for saving temporaries and space for maximum three arguments. */
|
||||
if (scratches <= 1)
|
||||
compiler->saveds_offset = 1 * sizeof(sljit_sw);
|
||||
else
|
||||
compiler->saveds_offset = ((scratches == 2) ? 2 : 3) * sizeof(sljit_sw);
|
||||
#endif
|
||||
|
||||
if (scratches > 3)
|
||||
compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw);
|
||||
|
||||
compiler->locals_offset = compiler->saveds_offset;
|
||||
|
||||
if (saveds > 3)
|
||||
compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw);
|
||||
|
||||
if (options & SLJIT_F64_ALIGNMENT)
|
||||
compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1);
|
||||
|
||||
#if defined(__APPLE__)
|
||||
saveds = (2 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
|
||||
saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
|
||||
compiler->local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;
|
||||
#else
|
||||
if (options & SLJIT_DOUBLE_ALIGNMENT)
|
||||
compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + 7) & ~7);
|
||||
if (options & SLJIT_F64_ALIGNMENT)
|
||||
compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1));
|
||||
else
|
||||
compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + 3) & ~3);
|
||||
compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1));
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si size;
|
||||
sljit_ub *inst;
|
||||
sljit_s32 size;
|
||||
sljit_u8 *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_return(compiler, op, src, srcw));
|
||||
SLJIT_ASSERT(compiler->args >= 0);
|
||||
|
||||
compiler->flags_saved = 0;
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
SLJIT_ASSERT(compiler->local_size > 0);
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
if (compiler->options & SLJIT_DOUBLE_ALIGNMENT) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 3);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(3);
|
||||
inst[0] = MOV_r_rm;
|
||||
inst[1] = (reg_map[SLJIT_SP] << 3) | 0x4 /* SIB */;
|
||||
inst[2] = (4 << 3) | reg_map[SLJIT_SP];
|
||||
}
|
||||
if (compiler->options & SLJIT_F64_ALIGNMENT)
|
||||
EMIT_MOV(compiler, SLJIT_SP, 0, SLJIT_MEM1(SLJIT_SP), compiler->local_size)
|
||||
else
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
|
||||
#else
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
|
||||
#endif
|
||||
|
||||
size = 2 + (compiler->scratches > 7 ? (compiler->scratches - 7) : 0) +
|
||||
|
@ -242,16 +294,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
|||
if (compiler->args > 0)
|
||||
size += 2;
|
||||
#endif
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
|
||||
if (compiler->saveds > 0 || compiler->scratches > 9)
|
||||
if (compiler->saveds > 0 || compiler->scratches > 11)
|
||||
POP_REG(reg_map[SLJIT_S0]);
|
||||
if (compiler->saveds > 1 || compiler->scratches > 8)
|
||||
if (compiler->saveds > 1 || compiler->scratches > 10)
|
||||
POP_REG(reg_map[SLJIT_S1]);
|
||||
if (compiler->saveds > 2 || compiler->scratches > 7)
|
||||
if (compiler->saveds > 2 || compiler->scratches > 9)
|
||||
POP_REG(reg_map[SLJIT_S2]);
|
||||
POP_REG(reg_map[TMP_REG1]);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
|
@ -271,16 +323,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
|||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Size contains the flags as well. */
|
||||
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size,
|
||||
static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 size,
|
||||
/* The register or immediate operand. */
|
||||
sljit_si a, sljit_sw imma,
|
||||
sljit_s32 a, sljit_sw imma,
|
||||
/* The general operand (not immediate). */
|
||||
sljit_si b, sljit_sw immb)
|
||||
sljit_s32 b, sljit_sw immb)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_ub *buf_ptr;
|
||||
sljit_si flags = size & ~0xf;
|
||||
sljit_si inst_size;
|
||||
sljit_u8 *inst;
|
||||
sljit_u8 *buf_ptr;
|
||||
sljit_s32 flags = size & ~0xf;
|
||||
sljit_s32 inst_size;
|
||||
|
||||
/* Both cannot be switched on. */
|
||||
SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
|
||||
|
@ -310,7 +362,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
else if (immb != 0 && !(b & OFFS_REG_MASK)) {
|
||||
/* Immediate operand. */
|
||||
if (immb <= 127 && immb >= -128)
|
||||
inst_size += sizeof(sljit_sb);
|
||||
inst_size += sizeof(sljit_s8);
|
||||
else
|
||||
inst_size += sizeof(sljit_sw);
|
||||
}
|
||||
|
@ -347,7 +399,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
else
|
||||
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);
|
||||
PTR_FAIL_IF(!inst);
|
||||
|
||||
/* Encoding the byte. */
|
||||
|
@ -406,7 +458,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr++ = immb; /* 8 bit displacement. */
|
||||
else {
|
||||
*(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_sw);
|
||||
}
|
||||
}
|
||||
|
@ -418,7 +470,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
}
|
||||
else {
|
||||
*buf_ptr++ |= 0x05;
|
||||
*(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_sw);
|
||||
}
|
||||
|
||||
|
@ -426,9 +478,9 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
if (flags & EX86_BYTE_ARG)
|
||||
*buf_ptr = imma;
|
||||
else if (flags & EX86_HALF_ARG)
|
||||
*(short*)buf_ptr = imma;
|
||||
sljit_unaligned_store_s16(buf_ptr, imma);
|
||||
else if (!(flags & EX86_SHIFT_INS))
|
||||
*(sljit_sw*)buf_ptr = imma;
|
||||
sljit_unaligned_store_sw(buf_ptr, imma);
|
||||
}
|
||||
|
||||
return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
|
||||
|
@ -438,12 +490,12 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
/* Call / return instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type)
|
||||
static SLJIT_INLINE sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 type)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_u8 *inst;
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
inst = (sljit_ub*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(type >= SLJIT_CALL3 ? 2 + 1 : 2);
|
||||
|
||||
|
@ -452,7 +504,7 @@ static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, slj
|
|||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0];
|
||||
#else
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 * (type - SLJIT_CALL0));
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 * (type - SLJIT_CALL0));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4 * (type - SLJIT_CALL0));
|
||||
|
||||
|
@ -476,9 +528,9 @@ static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, slj
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_u8 *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
|
||||
|
@ -492,7 +544,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
|||
|
||||
if (FAST_IS_REG(dst)) {
|
||||
/* Unused dest is possible here. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(1);
|
||||
|
@ -507,9 +559,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_u8 *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
|
||||
|
@ -518,7 +570,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||
|
||||
if (FAST_IS_REG(src)) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(1 + 1);
|
||||
|
@ -530,18 +582,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
*inst++ = GROUP_FF;
|
||||
*inst |= PUSH_rm;
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
}
|
||||
else {
|
||||
/* SLJIT_IMM. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(5 + 1);
|
||||
*inst++ = PUSH_i32;
|
||||
*(sljit_sw*)inst = srcw;
|
||||
sljit_unaligned_store_sw(inst, srcw);
|
||||
inst += sizeof(sljit_sw);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -26,20 +26,20 @@
|
|||
|
||||
/* x86 64-bit arch dependent functions. */
|
||||
|
||||
static sljit_si emit_load_imm64(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
|
||||
static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_u8 *inst;
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw));
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(2 + sizeof(sljit_sw));
|
||||
*inst++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
|
||||
*inst++ = MOV_r_i32 + (reg_map[reg] & 0x7);
|
||||
*(sljit_sw*)inst = imm;
|
||||
sljit_unaligned_store_sw(inst, imm);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type)
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type)
|
||||
{
|
||||
if (type < SLJIT_JUMP) {
|
||||
/* Invert type. */
|
||||
|
@ -47,58 +47,42 @@ static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_
|
|||
*code_ptr++ = 10 + 3;
|
||||
}
|
||||
|
||||
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first);
|
||||
*code_ptr++ = REX_W | REX_B;
|
||||
*code_ptr++ = MOV_r_i32 + 1;
|
||||
*code_ptr++ = REX_W | ((reg_map[TMP_REG2] <= 7) ? 0 : REX_B);
|
||||
*code_ptr++ = MOV_r_i32 | reg_lmap[TMP_REG2];
|
||||
jump->addr = (sljit_uw)code_ptr;
|
||||
|
||||
if (jump->flags & JUMP_LABEL)
|
||||
jump->flags |= PATCH_MD;
|
||||
else
|
||||
*(sljit_sw*)code_ptr = jump->u.target;
|
||||
sljit_unaligned_store_sw(code_ptr, jump->u.target);
|
||||
|
||||
code_ptr += sizeof(sljit_sw);
|
||||
if (reg_map[TMP_REG2] >= 8)
|
||||
*code_ptr++ = REX_B;
|
||||
*code_ptr++ = GROUP_FF;
|
||||
*code_ptr++ = (type >= SLJIT_FAST_CALL) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
|
||||
*code_ptr++ = MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2];
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si type)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
sljit_sw delta = addr - ((sljit_sw)code_ptr + 1 + sizeof(sljit_si));
|
||||
|
||||
if (delta <= HALFWORD_MAX && delta >= HALFWORD_MIN) {
|
||||
*code_ptr++ = (type == 2) ? CALL_i32 : JMP_i32;
|
||||
*(sljit_sw*)code_ptr = delta;
|
||||
}
|
||||
else {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second);
|
||||
*code_ptr++ = REX_W | REX_B;
|
||||
*code_ptr++ = MOV_r_i32 + 1;
|
||||
*(sljit_sw*)code_ptr = addr;
|
||||
code_ptr += sizeof(sljit_sw);
|
||||
*code_ptr++ = REX_B;
|
||||
*code_ptr++ = GROUP_FF;
|
||||
*code_ptr++ = (type == 2) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
|
||||
}
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
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 i, tmp, size, saved_register_size;
|
||||
sljit_ub *inst;
|
||||
sljit_s32 i, tmp, size, saved_register_size;
|
||||
sljit_u8 *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->flags_saved = 0;
|
||||
#ifdef _WIN64
|
||||
/* Two/four register slots for parameters plus space for xmm6 register if needed. */
|
||||
if (fscratches >= 6 || fsaveds >= 1)
|
||||
compiler->locals_offset = 6 * sizeof(sljit_sw);
|
||||
else
|
||||
compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw);
|
||||
#endif
|
||||
|
||||
/* Including the return address saved by the call instruction. */
|
||||
saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
|
||||
|
@ -106,7 +90,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
|||
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);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(size);
|
||||
if (reg_map[i] >= 8)
|
||||
|
@ -116,7 +100,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
|||
|
||||
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
|
||||
size = reg_map[i] >= 8 ? 2 : 1;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(size);
|
||||
if (reg_map[i] >= 8)
|
||||
|
@ -126,7 +110,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
|||
|
||||
if (args > 0) {
|
||||
size = args * 3;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
|
@ -172,12 +156,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
|||
#ifdef _WIN64
|
||||
if (local_size > 1024) {
|
||||
/* Allocate stack for the callback, which grows the stack. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + (3 + sizeof(sljit_si)));
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + (3 + sizeof(sljit_s32)));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4 + (3 + sizeof(sljit_si)));
|
||||
INC_SIZE(4 + (3 + sizeof(sljit_s32)));
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_83;
|
||||
*inst++ = MOD_REG | SUB | 4;
|
||||
*inst++ = MOD_REG | SUB | reg_map[SLJIT_SP];
|
||||
/* Allocated size for registers must be divisible by 8. */
|
||||
SLJIT_ASSERT(!(saved_register_size & 0x7));
|
||||
/* Aligned to 16 byte. */
|
||||
|
@ -189,11 +173,11 @@ 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_R0] < 8, temporary_reg1_is_loreg);
|
||||
SLJIT_ASSERT(reg_map[SLJIT_R0] < 8);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_rm_i32;
|
||||
*inst++ = MOD_REG | reg_lmap[SLJIT_R0];
|
||||
*(sljit_si*)inst = local_size;
|
||||
sljit_unaligned_store_s32(inst, local_size);
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
|
@ -202,82 +186,90 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
|||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(local_size > 0);
|
||||
if (local_size > 0) {
|
||||
if (local_size <= 127) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_83;
|
||||
*inst++ = MOD_REG | SUB | 4;
|
||||
*inst++ = MOD_REG | SUB | reg_map[SLJIT_SP];
|
||||
*inst++ = local_size;
|
||||
}
|
||||
else {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 7);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 7);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(7);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_81;
|
||||
*inst++ = MOD_REG | SUB | 4;
|
||||
*(sljit_si*)inst = local_size;
|
||||
inst += sizeof(sljit_si);
|
||||
*inst++ = MOD_REG | SUB | reg_map[SLJIT_SP];
|
||||
sljit_unaligned_store_s32(inst, local_size);
|
||||
inst += sizeof(sljit_s32);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
/* Save xmm6 register: movaps [rsp + 0x20], xmm6 */
|
||||
if (fscratches >= 6 || fsaveds >= 1) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(5);
|
||||
*inst++ = GROUP_0F;
|
||||
*(sljit_si*)inst = 0x20247429;
|
||||
sljit_unaligned_store_s32(inst, 0x20247429);
|
||||
}
|
||||
#endif
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si 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_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
sljit_si saved_register_size;
|
||||
sljit_s32 saved_register_size;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
#ifdef _WIN64
|
||||
/* Two/four register slots for parameters plus space for xmm6 register if needed. */
|
||||
if (fscratches >= 6 || fsaveds >= 1)
|
||||
compiler->locals_offset = 6 * sizeof(sljit_sw);
|
||||
else
|
||||
compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw);
|
||||
#endif
|
||||
|
||||
/* Including the return address saved by the call instruction. */
|
||||
saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
|
||||
compiler->local_size = ((local_size + SLJIT_LOCALS_OFFSET + saved_register_size + 15) & ~15) - saved_register_size;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si i, tmp, size;
|
||||
sljit_ub *inst;
|
||||
sljit_s32 i, tmp, size;
|
||||
sljit_u8 *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_return(compiler, op, src, srcw));
|
||||
|
||||
compiler->flags_saved = 0;
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
#ifdef _WIN64
|
||||
/* Restore xmm6 register: movaps xmm6, [rsp + 0x20] */
|
||||
if (compiler->fscratches >= 6 || compiler->fsaveds >= 1) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(5);
|
||||
*inst++ = GROUP_0F;
|
||||
*(sljit_si*)inst = 0x20247428;
|
||||
sljit_unaligned_store_s32(inst, 0x20247428);
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(compiler->local_size > 0);
|
||||
if (compiler->local_size > 0) {
|
||||
if (compiler->local_size <= 127) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4);
|
||||
*inst++ = REX_W;
|
||||
|
@ -286,19 +278,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
|||
*inst = compiler->local_size;
|
||||
}
|
||||
else {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 7);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 7);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(7);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_81;
|
||||
*inst++ = MOD_REG | ADD | 4;
|
||||
*(sljit_si*)inst = compiler->local_size;
|
||||
sljit_unaligned_store_s32(inst, compiler->local_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);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(size);
|
||||
if (reg_map[i] >= 8)
|
||||
|
@ -309,7 +302,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
|||
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);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(size);
|
||||
if (reg_map[i] >= 8)
|
||||
|
@ -317,7 +310,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
|||
POP_REG(reg_lmap[i]);
|
||||
}
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
RET();
|
||||
|
@ -328,32 +321,32 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
|||
/* Operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static sljit_si emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_sw imm)
|
||||
static sljit_s32 emit_do_imm32(struct sljit_compiler *compiler, sljit_u8 rex, sljit_u8 opcode, sljit_sw imm)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_si length = 1 + (rex ? 1 : 0) + sizeof(sljit_si);
|
||||
sljit_u8 *inst;
|
||||
sljit_s32 length = 1 + (rex ? 1 : 0) + sizeof(sljit_s32);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + length);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + length);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(length);
|
||||
if (rex)
|
||||
*inst++ = rex;
|
||||
*inst++ = opcode;
|
||||
*(sljit_si*)inst = imm;
|
||||
sljit_unaligned_store_s32(inst, imm);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size,
|
||||
static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 size,
|
||||
/* The register or immediate operand. */
|
||||
sljit_si a, sljit_sw imma,
|
||||
sljit_s32 a, sljit_sw imma,
|
||||
/* The general operand (not immediate). */
|
||||
sljit_si b, sljit_sw immb)
|
||||
sljit_s32 b, sljit_sw immb)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_ub *buf_ptr;
|
||||
sljit_ub rex = 0;
|
||||
sljit_si flags = size & ~0xf;
|
||||
sljit_si inst_size;
|
||||
sljit_u8 *inst;
|
||||
sljit_u8 *buf_ptr;
|
||||
sljit_u8 rex = 0;
|
||||
sljit_s32 flags = size & ~0xf;
|
||||
sljit_s32 inst_size;
|
||||
|
||||
/* The immediate operand must be 32 bit. */
|
||||
SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
|
||||
|
@ -387,20 +380,19 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
if (b & SLJIT_MEM) {
|
||||
if (!(b & OFFS_REG_MASK)) {
|
||||
if (NOT_HALFWORD(immb)) {
|
||||
if (emit_load_imm64(compiler, TMP_REG3, immb))
|
||||
return NULL;
|
||||
PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
|
||||
immb = 0;
|
||||
if (b & REG_MASK)
|
||||
b |= TO_OFFS_REG(TMP_REG3);
|
||||
b |= TO_OFFS_REG(TMP_REG2);
|
||||
else
|
||||
b |= TMP_REG3;
|
||||
b |= TMP_REG2;
|
||||
}
|
||||
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. */
|
||||
inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */
|
||||
else {
|
||||
if (reg_map[b & REG_MASK] >= 8)
|
||||
rex |= REX_B;
|
||||
|
@ -408,12 +400,12 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
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);
|
||||
inst_size += sizeof(sljit_s8);
|
||||
else
|
||||
inst_size += sizeof(sljit_si);
|
||||
inst_size += sizeof(sljit_s32);
|
||||
}
|
||||
else if (reg_lmap[b & REG_MASK] == 5)
|
||||
inst_size += sizeof(sljit_sb);
|
||||
inst_size += sizeof(sljit_s8);
|
||||
|
||||
if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) {
|
||||
inst_size += 1; /* SIB byte. */
|
||||
|
@ -444,7 +436,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
else if (flags & EX86_HALF_ARG)
|
||||
inst_size += sizeof(short);
|
||||
else
|
||||
inst_size += sizeof(sljit_si);
|
||||
inst_size += sizeof(sljit_s32);
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
|
||||
|
@ -456,7 +448,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
if (rex)
|
||||
inst_size++;
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);
|
||||
PTR_FAIL_IF(!inst);
|
||||
|
||||
/* Encoding the byte. */
|
||||
|
@ -516,8 +508,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr++ = immb; /* 8 bit displacement. */
|
||||
else {
|
||||
*(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_si);
|
||||
sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_s32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -533,17 +525,17 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = 0x25;
|
||||
*(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_si);
|
||||
sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_s32);
|
||||
}
|
||||
|
||||
if (a & SLJIT_IMM) {
|
||||
if (flags & EX86_BYTE_ARG)
|
||||
*buf_ptr = imma;
|
||||
else if (flags & EX86_HALF_ARG)
|
||||
*(short*)buf_ptr = imma;
|
||||
sljit_unaligned_store_s16(buf_ptr, imma);
|
||||
else if (!(flags & EX86_SHIFT_INS))
|
||||
*(sljit_si*)buf_ptr = imma;
|
||||
sljit_unaligned_store_s32(buf_ptr, imma);
|
||||
}
|
||||
|
||||
return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
|
||||
|
@ -553,17 +545,19 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
/* Call / return instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type)
|
||||
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 type)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_u8 *inst;
|
||||
|
||||
/* After any change update IS_REG_CHANGED_BY_CALL as well. */
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers);
|
||||
SLJIT_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8 && reg_map[TMP_REG1] == 2);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
|
||||
if (type >= SLJIT_CALL3) {
|
||||
/* Move third argument to TMP_REG1. */
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x2 /* rdx */ << 3) | reg_lmap[SLJIT_R2];
|
||||
|
@ -572,12 +566,13 @@ static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, slj
|
|||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x7 /* rdi */ << 3) | reg_lmap[SLJIT_R0];
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers);
|
||||
SLJIT_ASSERT(reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8 && reg_map[TMP_REG1] == 8);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
|
||||
if (type >= SLJIT_CALL3) {
|
||||
/* Move third argument to TMP_REG1. */
|
||||
*inst++ = REX_W | REX_R;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x0 /* r8 */ << 3) | reg_lmap[SLJIT_R2];
|
||||
|
@ -589,9 +584,9 @@ static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, slj
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_u8 *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
|
||||
|
@ -603,14 +598,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
|||
|
||||
if (FAST_IS_REG(dst)) {
|
||||
if (reg_map[dst] < 8) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
POP_REG(reg_lmap[dst]);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 2);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(2);
|
||||
*inst++ = REX_B;
|
||||
|
@ -626,9 +621,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_u8 *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
|
||||
|
@ -641,14 +636,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
|
||||
if (FAST_IS_REG(src)) {
|
||||
if (reg_map[src] < 8) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(1 + 1);
|
||||
PUSH_REG(reg_lmap[src]);
|
||||
}
|
||||
else {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(2 + 1);
|
||||
|
@ -664,20 +659,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
*inst++ = GROUP_FF;
|
||||
*inst |= PUSH_rm;
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(IS_HALFWORD(srcw));
|
||||
/* SLJIT_IMM. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(5 + 1);
|
||||
*inst++ = PUSH_i32;
|
||||
*(sljit_si*)inst = srcw;
|
||||
inst += sizeof(sljit_si);
|
||||
sljit_unaligned_store_s32(inst, srcw);
|
||||
inst += sizeof(sljit_s32);
|
||||
}
|
||||
|
||||
RET();
|
||||
|
@ -689,12 +684,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
/* Extend input */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_ub* inst;
|
||||
sljit_si dst_r;
|
||||
sljit_u8* inst;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
compiler->mode32 = 0;
|
||||
|
||||
|
@ -704,7 +699,7 @@ static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
|
|||
if (src & SLJIT_IMM) {
|
||||
if (FAST_IS_REG(dst)) {
|
||||
if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
|
||||
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
|
||||
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
*inst = MOV_rm_i32;
|
||||
return SLJIT_SUCCESS;
|
||||
|
@ -712,7 +707,7 @@ static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
|
|||
return emit_load_imm64(compiler, dst, srcw);
|
||||
}
|
||||
compiler->mode32 = 1;
|
||||
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
|
||||
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
*inst = MOV_rm_i32;
|
||||
compiler->mode32 = 0;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
|
@ -163,11 +163,11 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
|
|||
#include <fcntl.h>
|
||||
|
||||
/* Some old systems does not have MAP_ANON. */
|
||||
static sljit_si dev_zero = -1;
|
||||
static sljit_s32 dev_zero = -1;
|
||||
|
||||
#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
|
||||
|
||||
static SLJIT_INLINE sljit_si open_dev_zero(void)
|
||||
static SLJIT_INLINE sljit_s32 open_dev_zero(void)
|
||||
{
|
||||
dev_zero = open("/dev/zero", O_RDWR);
|
||||
return dev_zero < 0;
|
||||
|
@ -179,10 +179,13 @@ static SLJIT_INLINE sljit_si open_dev_zero(void)
|
|||
|
||||
static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static SLJIT_INLINE sljit_si open_dev_zero(void)
|
||||
static SLJIT_INLINE sljit_s32 open_dev_zero(void)
|
||||
{
|
||||
pthread_mutex_lock(&dev_zero_mutex);
|
||||
/* The dev_zero might be initialized by another thread during the waiting. */
|
||||
if (dev_zero < 0) {
|
||||
dev_zero = open("/dev/zero", O_RDWR);
|
||||
}
|
||||
pthread_mutex_unlock(&dev_zero_mutex);
|
||||
return dev_zero < 0;
|
||||
}
|
||||
|
@ -203,10 +206,7 @@ static sljit_sw sljit_page_align = 0;
|
|||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data)
|
||||
{
|
||||
struct sljit_stack *stack;
|
||||
union {
|
||||
void *ptr;
|
||||
sljit_uw uw;
|
||||
} base;
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO si;
|
||||
#endif
|
||||
|
@ -230,29 +230,29 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Align limit and max_limit. */
|
||||
max_limit = (max_limit + sljit_page_align) & ~sljit_page_align;
|
||||
|
||||
stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);
|
||||
if (!stack)
|
||||
return NULL;
|
||||
|
||||
/* Align max_limit. */
|
||||
max_limit = (max_limit + sljit_page_align) & ~sljit_page_align;
|
||||
|
||||
#ifdef _WIN32
|
||||
base.ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
|
||||
if (!base.ptr) {
|
||||
ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
|
||||
if (!ptr) {
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
stack->base = base.uw;
|
||||
stack->max_limit = (sljit_u8 *)ptr;
|
||||
stack->base = stack->max_limit + max_limit;
|
||||
stack->limit = stack->base;
|
||||
stack->max_limit = stack->base + max_limit;
|
||||
if (sljit_stack_resize(stack, stack->base + limit)) {
|
||||
if (sljit_stack_resize(stack, stack->base - limit)) {
|
||||
sljit_free_stack(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
#ifdef MAP_ANON
|
||||
base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
#else
|
||||
if (dev_zero < 0) {
|
||||
if (open_dev_zero()) {
|
||||
|
@ -260,15 +260,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
|
||||
ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
|
||||
#endif
|
||||
if (base.ptr == MAP_FAILED) {
|
||||
if (ptr == MAP_FAILED) {
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
stack->base = base.uw;
|
||||
stack->limit = stack->base + limit;
|
||||
stack->max_limit = stack->base + max_limit;
|
||||
stack->max_limit = (sljit_u8 *)ptr;
|
||||
stack->base = stack->max_limit + max_limit;
|
||||
stack->limit = stack->base - limit;
|
||||
#endif
|
||||
stack->top = stack->base;
|
||||
return stack;
|
||||
|
@ -280,49 +280,49 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* st
|
|||
{
|
||||
SLJIT_UNUSED_ARG(allocator_data);
|
||||
#ifdef _WIN32
|
||||
VirtualFree((void*)stack->base, 0, MEM_RELEASE);
|
||||
VirtualFree((void*)stack->max_limit, 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap((void*)stack->base, stack->max_limit - stack->base);
|
||||
munmap((void*)stack->max_limit, stack->base - stack->max_limit);
|
||||
#endif
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_limit)
|
||||
{
|
||||
sljit_uw aligned_old_limit;
|
||||
sljit_uw aligned_new_limit;
|
||||
|
||||
if ((new_limit > stack->max_limit) || (new_limit < stack->base))
|
||||
if ((new_limit < stack->max_limit) || (new_limit >= stack->base))
|
||||
return -1;
|
||||
#ifdef _WIN32
|
||||
aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
|
||||
aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
|
||||
aligned_new_limit = (sljit_uw)new_limit & ~sljit_page_align;
|
||||
aligned_old_limit = ((sljit_uw)stack->limit) & ~sljit_page_align;
|
||||
if (aligned_new_limit != aligned_old_limit) {
|
||||
if (aligned_new_limit > aligned_old_limit) {
|
||||
if (!VirtualAlloc((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_COMMIT, PAGE_READWRITE))
|
||||
if (aligned_new_limit < aligned_old_limit) {
|
||||
if (!VirtualAlloc((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_COMMIT, PAGE_READWRITE))
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
if (!VirtualFree((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_DECOMMIT))
|
||||
if (!VirtualFree((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_DECOMMIT))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
stack->limit = new_limit;
|
||||
return 0;
|
||||
#else
|
||||
if (new_limit >= stack->limit) {
|
||||
if (new_limit <= stack->limit) {
|
||||
stack->limit = new_limit;
|
||||
return 0;
|
||||
}
|
||||
aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
|
||||
aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
|
||||
aligned_new_limit = (sljit_uw)new_limit & ~sljit_page_align;
|
||||
aligned_old_limit = ((sljit_uw)stack->limit) & ~sljit_page_align;
|
||||
/* If madvise is available, we release the unnecessary space. */
|
||||
#if defined(MADV_DONTNEED)
|
||||
if (aligned_new_limit < aligned_old_limit)
|
||||
madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED);
|
||||
if (aligned_new_limit > aligned_old_limit)
|
||||
madvise((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MADV_DONTNEED);
|
||||
#elif defined(POSIX_MADV_DONTNEED)
|
||||
if (aligned_new_limit < aligned_old_limit)
|
||||
posix_madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, POSIX_MADV_DONTNEED);
|
||||
if (aligned_new_limit > aligned_old_limit)
|
||||
posix_madvise((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, POSIX_MADV_DONTNEED);
|
||||
#endif
|
||||
stack->limit = new_limit;
|
||||
return 0;
|
||||
|
|
9
ext/pcre/pcrelib/testdata/testinput1
vendored
9
ext/pcre/pcrelib/testdata/testinput1
vendored
|
@ -5733,4 +5733,13 @@ AbcdCBefgBhiBqz
|
|||
"(?|(\k'Pm')|(?'Pm'))"
|
||||
abcd
|
||||
|
||||
/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[,;:])(?=.{8,16})(?!.*[\s])/
|
||||
\ Fred:099
|
||||
|
||||
/(?=.*X)X$/
|
||||
\ X
|
||||
|
||||
/X+(?#comment)?/
|
||||
>XXX<
|
||||
|
||||
/-- End of testinput1 --/
|
||||
|
|
2
ext/pcre/pcrelib/testdata/testinput11
vendored
2
ext/pcre/pcrelib/testdata/testinput11
vendored
|
@ -138,4 +138,6 @@ is required for these tests. --/
|
|||
|
||||
/.((?2)(?R)\1)()/B
|
||||
|
||||
/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
|
||||
|
||||
/-- End of testinput11 --/
|
||||
|
|
2
ext/pcre/pcrelib/testdata/testinput12
vendored
2
ext/pcre/pcrelib/testdata/testinput12
vendored
|
@ -104,4 +104,6 @@ and a couple of things that are different with JIT. --/
|
|||
/(.|.)*?bx/
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabax
|
||||
|
||||
/((?(?!))x)(?'name')(?1)/S++
|
||||
|
||||
/-- End of testinput12 --/
|
||||
|
|
3
ext/pcre/pcrelib/testdata/testinput15
vendored
3
ext/pcre/pcrelib/testdata/testinput15
vendored
|
@ -363,4 +363,7 @@ correctly, but that messes up comparisons). --/
|
|||
|
||||
/abc/89
|
||||
|
||||
//8+L
|
||||
\xf1\xad\xae\xae
|
||||
|
||||
/-- End of testinput15 --/
|
||||
|
|
26
ext/pcre/pcrelib/testdata/testinput16
vendored
26
ext/pcre/pcrelib/testdata/testinput16
vendored
|
@ -38,4 +38,30 @@
|
|||
/s+/i8SI
|
||||
SSss\x{17f}
|
||||
|
||||
/[\W\p{Any}]/BZ
|
||||
abc
|
||||
123
|
||||
|
||||
/[\W\pL]/BZ
|
||||
abc
|
||||
** Failers
|
||||
123
|
||||
|
||||
/[\D]/8
|
||||
\x{1d7cf}
|
||||
|
||||
/[\D\P{Nd}]/8
|
||||
\x{1d7cf}
|
||||
|
||||
/[^\D]/8
|
||||
a9b
|
||||
** Failers
|
||||
\x{1d7cf}
|
||||
|
||||
/[^\D\P{Nd}]/8
|
||||
a9b
|
||||
\x{1d7cf}
|
||||
** Failers
|
||||
\x{10000}
|
||||
|
||||
/-- End of testinput16 --/
|
||||
|
|
17
ext/pcre/pcrelib/testdata/testinput19
vendored
17
ext/pcre/pcrelib/testdata/testinput19
vendored
|
@ -25,4 +25,21 @@
|
|||
/s+/i8SI
|
||||
SSss\x{17f}
|
||||
|
||||
/[\D]/8
|
||||
\x{1d7cf}
|
||||
|
||||
/[\D\P{Nd}]/8
|
||||
\x{1d7cf}
|
||||
|
||||
/[^\D]/8
|
||||
a9b
|
||||
** Failers
|
||||
\x{1d7cf}
|
||||
|
||||
/[^\D\P{Nd}]/8
|
||||
a9b
|
||||
\x{1d7cf}
|
||||
** Failers
|
||||
\x{10000}
|
||||
|
||||
/-- End of testinput19 --/
|
||||
|
|
32
ext/pcre/pcrelib/testdata/testinput2
vendored
32
ext/pcre/pcrelib/testdata/testinput2
vendored
|
@ -4217,4 +4217,36 @@ backtracking verbs. --/
|
|||
|
||||
/a[[:punct:]b]/BZ
|
||||
|
||||
/L(?#(|++<!(2)?/BZ
|
||||
|
||||
/L(?#(|++<!(2)?/BOZ
|
||||
|
||||
/L(?#(|++<!(2)?/BCZ
|
||||
|
||||
/L(?#(|++<!(2)?/BCOZ
|
||||
|
||||
/(A*)\E+/CBZ
|
||||
|
||||
/()\Q\E*]/BCZ
|
||||
|
||||
/(?<A>)(?J:(?<B>)(?<B>))(?<C>)/
|
||||
\O\CC
|
||||
|
||||
/(?=a\K)/
|
||||
ring bpattingbobnd $ 1,oern cou \rb\L
|
||||
|
||||
/(?<=((?C)0))/
|
||||
9010
|
||||
abcd
|
||||
|
||||
/((?J)(?'R'(?'R'(?'R'(?'R'(?'R'(?|(\k'R'))))))))/
|
||||
|
||||
/\N(?(?C)0?!.)*/
|
||||
|
||||
/(?<RA>abc)(?(R)xyz)/BZ
|
||||
|
||||
/(?<R>abc)(?(R)xyz)/BZ
|
||||
|
||||
/(?=.*[A-Z])/I
|
||||
|
||||
/-- End of testinput2 --/
|
||||
|
|
15
ext/pcre/pcrelib/testdata/testinput6
vendored
15
ext/pcre/pcrelib/testdata/testinput6
vendored
|
@ -1553,4 +1553,19 @@
|
|||
\x{200}
|
||||
\x{37e}
|
||||
|
||||
/[^[:^ascii:]\d]/8W
|
||||
a
|
||||
~
|
||||
0
|
||||
\a
|
||||
\x{7f}
|
||||
\x{389}
|
||||
\x{20ac}
|
||||
|
||||
/(?=.*b)\pL/
|
||||
11bb
|
||||
|
||||
/(?(?=.*b)(?=.*b)\pL|.*c)/
|
||||
11bb
|
||||
|
||||
/-- End of testinput6 --/
|
||||
|
|
13
ext/pcre/pcrelib/testdata/testinput7
vendored
13
ext/pcre/pcrelib/testdata/testinput7
vendored
|
@ -838,19 +838,14 @@ of case for anything other than the ASCII letters. --/
|
|||
/^s?c/mi8I
|
||||
scat
|
||||
|
||||
/[\W\p{Any}]/BZ
|
||||
abc
|
||||
123
|
||||
|
||||
/[\W\pL]/BZ
|
||||
abc
|
||||
** Failers
|
||||
123
|
||||
|
||||
/a[[:punct:]b]/WBZ
|
||||
|
||||
/a[[:punct:]b]/8WBZ
|
||||
|
||||
/a[b[:punct:]]/8WBZ
|
||||
|
||||
/L(?#(|++<!(2)?/B8COZ
|
||||
|
||||
/L(?#(|++<!(2)?/B8WCZ
|
||||
|
||||
/-- End of testinput7 --/
|
||||
|
|
7
ext/pcre/pcrelib/testdata/testinput8
vendored
7
ext/pcre/pcrelib/testdata/testinput8
vendored
|
@ -4841,4 +4841,11 @@
|
|||
bbb
|
||||
aaa
|
||||
|
||||
/()()a+/O=
|
||||
aaa\D
|
||||
a\D
|
||||
|
||||
/(02-)?[0-9]{3}-[0-9]{3}/
|
||||
02-123-123
|
||||
|
||||
/-- End of testinput8 --/
|
||||
|
|
12
ext/pcre/pcrelib/testdata/testoutput1
vendored
12
ext/pcre/pcrelib/testdata/testoutput1
vendored
|
@ -9434,4 +9434,16 @@ No match
|
|||
0:
|
||||
1:
|
||||
|
||||
/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[,;:])(?=.{8,16})(?!.*[\s])/
|
||||
\ Fred:099
|
||||
0:
|
||||
|
||||
/(?=.*X)X$/
|
||||
\ X
|
||||
0: X
|
||||
|
||||
/X+(?#comment)?/
|
||||
>XXX<
|
||||
0: X
|
||||
|
||||
/-- End of testinput1 --/
|
||||
|
|
5
ext/pcre/pcrelib/testdata/testoutput11-16
vendored
5
ext/pcre/pcrelib/testdata/testoutput11-16
vendored
|
@ -231,7 +231,7 @@ Memory allocation (code space): 73
|
|||
------------------------------------------------------------------
|
||||
|
||||
/(?P<a>a)...(?P=a)bbb(?P>a)d/BM
|
||||
Memory allocation (code space): 77
|
||||
Memory allocation (code space): 93
|
||||
------------------------------------------------------------------
|
||||
0 24 Bra
|
||||
2 5 CBra 1
|
||||
|
@ -765,4 +765,7 @@ Memory allocation (code space): 14
|
|||
25 End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
|
||||
Failed: regular expression is too complicated at offset 490
|
||||
|
||||
/-- End of testinput11 --/
|
||||
|
|
5
ext/pcre/pcrelib/testdata/testoutput11-32
vendored
5
ext/pcre/pcrelib/testdata/testoutput11-32
vendored
|
@ -231,7 +231,7 @@ Memory allocation (code space): 155
|
|||
------------------------------------------------------------------
|
||||
|
||||
/(?P<a>a)...(?P=a)bbb(?P>a)d/BM
|
||||
Memory allocation (code space): 157
|
||||
Memory allocation (code space): 189
|
||||
------------------------------------------------------------------
|
||||
0 24 Bra
|
||||
2 5 CBra 1
|
||||
|
@ -765,4 +765,7 @@ Memory allocation (code space): 28
|
|||
25 End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
|
||||
Failed: missing ) at offset 509
|
||||
|
||||
/-- End of testinput11 --/
|
||||
|
|
5
ext/pcre/pcrelib/testdata/testoutput11-8
vendored
5
ext/pcre/pcrelib/testdata/testoutput11-8
vendored
|
@ -231,7 +231,7 @@ Memory allocation (code space): 45
|
|||
------------------------------------------------------------------
|
||||
|
||||
/(?P<a>a)...(?P=a)bbb(?P>a)d/BM
|
||||
Memory allocation (code space): 50
|
||||
Memory allocation (code space): 62
|
||||
------------------------------------------------------------------
|
||||
0 30 Bra
|
||||
3 7 CBra 1
|
||||
|
@ -765,4 +765,7 @@ Memory allocation (code space): 10
|
|||
38 End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
|
||||
Failed: missing ) at offset 509
|
||||
|
||||
/-- End of testinput11 --/
|
||||
|
|
2
ext/pcre/pcrelib/testdata/testoutput12
vendored
2
ext/pcre/pcrelib/testdata/testoutput12
vendored
|
@ -201,4 +201,6 @@ No match, mark = m (JIT)
|
|||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabax
|
||||
Error -8 (match limit exceeded)
|
||||
|
||||
/((?(?!))x)(?'name')(?1)/S++
|
||||
|
||||
/-- End of testinput12 --/
|
||||
|
|
5
ext/pcre/pcrelib/testdata/testoutput15
vendored
5
ext/pcre/pcrelib/testdata/testoutput15
vendored
|
@ -1136,4 +1136,9 @@ Failed: setting UTF is disabled by the application at offset 0
|
|||
/abc/89
|
||||
Failed: setting UTF is disabled by the application at offset 0
|
||||
|
||||
//8+L
|
||||
\xf1\xad\xae\xae
|
||||
0:
|
||||
0+ \x{6dbae}
|
||||
|
||||
/-- End of testinput15 --/
|
||||
|
|
52
ext/pcre/pcrelib/testdata/testoutput16
vendored
52
ext/pcre/pcrelib/testdata/testoutput16
vendored
|
@ -138,4 +138,56 @@ Starting chars: S s \xc5
|
|||
SSss\x{17f}
|
||||
0: SSss\x{17f}
|
||||
|
||||
/[\W\p{Any}]/BZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
[\x00-/:-@[-^`{-\xff\p{Any}]
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
abc
|
||||
0: a
|
||||
123
|
||||
0: 1
|
||||
|
||||
/[\W\pL]/BZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
[\x00-/:-@[-^`{-\xff\p{L}]
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
abc
|
||||
0: a
|
||||
** Failers
|
||||
0: *
|
||||
123
|
||||
No match
|
||||
|
||||
/[\D]/8
|
||||
\x{1d7cf}
|
||||
0: \x{1d7cf}
|
||||
|
||||
/[\D\P{Nd}]/8
|
||||
\x{1d7cf}
|
||||
0: \x{1d7cf}
|
||||
|
||||
/[^\D]/8
|
||||
a9b
|
||||
0: 9
|
||||
** Failers
|
||||
No match
|
||||
\x{1d7cf}
|
||||
No match
|
||||
|
||||
/[^\D\P{Nd}]/8
|
||||
a9b
|
||||
0: 9
|
||||
\x{1d7cf}
|
||||
0: \x{1d7cf}
|
||||
** Failers
|
||||
No match
|
||||
\x{10000}
|
||||
No match
|
||||
|
||||
/-- End of testinput16 --/
|
||||
|
|
26
ext/pcre/pcrelib/testdata/testoutput19
vendored
26
ext/pcre/pcrelib/testdata/testoutput19
vendored
|
@ -105,4 +105,30 @@ Starting chars: S s \xff
|
|||
SSss\x{17f}
|
||||
0: SSss\x{17f}
|
||||
|
||||
/[\D]/8
|
||||
\x{1d7cf}
|
||||
0: \x{1d7cf}
|
||||
|
||||
/[\D\P{Nd}]/8
|
||||
\x{1d7cf}
|
||||
0: \x{1d7cf}
|
||||
|
||||
/[^\D]/8
|
||||
a9b
|
||||
0: 9
|
||||
** Failers
|
||||
No match
|
||||
\x{1d7cf}
|
||||
No match
|
||||
|
||||
/[^\D\P{Nd}]/8
|
||||
a9b
|
||||
0: 9
|
||||
\x{1d7cf}
|
||||
0: \x{1d7cf}
|
||||
** Failers
|
||||
No match
|
||||
\x{10000}
|
||||
No match
|
||||
|
||||
/-- End of testinput19 --/
|
||||
|
|
169
ext/pcre/pcrelib/testdata/testoutput2
vendored
169
ext/pcre/pcrelib/testdata/testoutput2
vendored
|
@ -419,7 +419,7 @@ Need char = '>'
|
|||
|
||||
/(?U)<.*>/I
|
||||
Capturing subpattern count = 0
|
||||
Options: ungreedy
|
||||
No options
|
||||
First char = '<'
|
||||
Need char = '>'
|
||||
abc<def>ghi<klm>nop
|
||||
|
@ -443,7 +443,7 @@ Need char = '='
|
|||
|
||||
/(?U)={3,}?/I
|
||||
Capturing subpattern count = 0
|
||||
Options: ungreedy
|
||||
No options
|
||||
First char = '='
|
||||
Need char = '='
|
||||
abc========def
|
||||
|
@ -477,7 +477,7 @@ Failed: lookbehind assertion is not fixed length at offset 12
|
|||
|
||||
/(?i)abc/I
|
||||
Capturing subpattern count = 0
|
||||
Options: caseless
|
||||
No options
|
||||
First char = 'a' (caseless)
|
||||
Need char = 'c' (caseless)
|
||||
|
||||
|
@ -489,7 +489,7 @@ No need char
|
|||
|
||||
/(?i)^1234/I
|
||||
Capturing subpattern count = 0
|
||||
Options: anchored caseless
|
||||
Options: anchored
|
||||
No first char
|
||||
No need char
|
||||
|
||||
|
@ -502,7 +502,7 @@ No need char
|
|||
/(?s).*/I
|
||||
Capturing subpattern count = 0
|
||||
May match empty string
|
||||
Options: anchored dotall
|
||||
Options: anchored
|
||||
No first char
|
||||
No need char
|
||||
|
||||
|
@ -516,7 +516,7 @@ Starting chars: a b c d
|
|||
|
||||
/(?i)[abcd]/IS
|
||||
Capturing subpattern count = 0
|
||||
Options: caseless
|
||||
No options
|
||||
No first char
|
||||
No need char
|
||||
Subject length lower bound = 1
|
||||
|
@ -524,7 +524,7 @@ Starting chars: A B C D a b c d
|
|||
|
||||
/(?m)[xy]|(b|c)/IS
|
||||
Capturing subpattern count = 1
|
||||
Options: multiline
|
||||
No options
|
||||
No first char
|
||||
No need char
|
||||
Subject length lower bound = 1
|
||||
|
@ -538,7 +538,7 @@ No need char
|
|||
|
||||
/(?i)(^a|^b)/Im
|
||||
Capturing subpattern count = 1
|
||||
Options: caseless multiline
|
||||
Options: multiline
|
||||
First char at start or follows newline
|
||||
No need char
|
||||
|
||||
|
@ -555,13 +555,13 @@ Failed: malformed number or name after (?( at offset 4
|
|||
Failed: malformed number or name after (?( at offset 4
|
||||
|
||||
/(?(?i))/
|
||||
Failed: assertion expected after (?( at offset 3
|
||||
Failed: assertion expected after (?( or (?(?C) at offset 3
|
||||
|
||||
/(?(abc))/
|
||||
Failed: reference to non-existent subpattern at offset 7
|
||||
|
||||
/(?(?<ab))/
|
||||
Failed: assertion expected after (?( at offset 3
|
||||
Failed: assertion expected after (?( or (?(?C) at offset 3
|
||||
|
||||
/((?s)blah)\s+\1/I
|
||||
Capturing subpattern count = 1
|
||||
|
@ -1179,7 +1179,7 @@ No need char
|
|||
End
|
||||
------------------------------------------------------------------
|
||||
Capturing subpattern count = 1
|
||||
Options: anchored dotall
|
||||
Options: anchored
|
||||
No first char
|
||||
No need char
|
||||
|
||||
|
@ -2735,7 +2735,7 @@ No match
|
|||
End
|
||||
------------------------------------------------------------------
|
||||
Capturing subpattern count = 0
|
||||
Options: caseless extended
|
||||
Options: extended
|
||||
First char = 'a' (caseless)
|
||||
Need char = 'c' (caseless)
|
||||
|
||||
|
@ -2748,7 +2748,7 @@ Need char = 'c' (caseless)
|
|||
End
|
||||
------------------------------------------------------------------
|
||||
Capturing subpattern count = 0
|
||||
Options: caseless extended
|
||||
Options: extended
|
||||
First char = 'a' (caseless)
|
||||
Need char = 'c' (caseless)
|
||||
|
||||
|
@ -3095,7 +3095,7 @@ Need char = 'b'
|
|||
End
|
||||
------------------------------------------------------------------
|
||||
Capturing subpattern count = 0
|
||||
Options: ungreedy
|
||||
No options
|
||||
First char = 'x'
|
||||
Need char = 'b'
|
||||
xaaaab
|
||||
|
@ -3497,7 +3497,7 @@ Need char = 'c'
|
|||
|
||||
/(?i)[ab]/IS
|
||||
Capturing subpattern count = 0
|
||||
Options: caseless
|
||||
No options
|
||||
No first char
|
||||
No need char
|
||||
Subject length lower bound = 1
|
||||
|
@ -6299,7 +6299,7 @@ Capturing subpattern count = 3
|
|||
Named capturing subpatterns:
|
||||
A 2
|
||||
A 3
|
||||
Options: anchored dupnames
|
||||
Options: anchored
|
||||
Duplicate name status changes
|
||||
No first char
|
||||
No need char
|
||||
|
@ -7870,7 +7870,7 @@ No match
|
|||
Failed: malformed number or name after (?( at offset 6
|
||||
|
||||
/(?(''))/
|
||||
Failed: assertion expected after (?( at offset 4
|
||||
Failed: assertion expected after (?( or (?(?C) at offset 4
|
||||
|
||||
/(?('R')stuff)/
|
||||
Failed: reference to non-existent subpattern at offset 7
|
||||
|
@ -9380,7 +9380,7 @@ No need char
|
|||
/(?(?=.*b).*b|^d)/I
|
||||
Capturing subpattern count = 0
|
||||
No options
|
||||
First char at start or follows newline
|
||||
No first char
|
||||
No need char
|
||||
|
||||
/xyz/C
|
||||
|
@ -14346,7 +14346,7 @@ No match
|
|||
"((?2)+)((?1))"
|
||||
|
||||
"(?(?<E>.*!.*)?)"
|
||||
Failed: assertion expected after (?( at offset 3
|
||||
Failed: assertion expected after (?( or (?(?C) at offset 3
|
||||
|
||||
"X((?2)()*+){2}+"BZ
|
||||
------------------------------------------------------------------
|
||||
|
@ -14574,4 +14574,135 @@ No match
|
|||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/L(?#(|++<!(2)?/BZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
L?+
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/L(?#(|++<!(2)?/BOZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
L?
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/L(?#(|++<!(2)?/BCZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
Callout 255 0 14
|
||||
L?+
|
||||
Callout 255 14 0
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/L(?#(|++<!(2)?/BCOZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
Callout 255 0 14
|
||||
L?
|
||||
Callout 255 14 0
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/(A*)\E+/CBZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
Callout 255 0 7
|
||||
SCBra 1
|
||||
Callout 255 1 2
|
||||
A*
|
||||
Callout 255 3 0
|
||||
KetRmax
|
||||
Callout 255 7 0
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/()\Q\E*]/BCZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
Callout 255 0 7
|
||||
Brazero
|
||||
SCBra 1
|
||||
Callout 255 1 0
|
||||
KetRmax
|
||||
Callout 255 7 1
|
||||
]
|
||||
Callout 255 8 0
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/(?<A>)(?J:(?<B>)(?<B>))(?<C>)/
|
||||
\O\CC
|
||||
Matched, but too many substrings
|
||||
copy substring C failed -7
|
||||
|
||||
/(?=a\K)/
|
||||
ring bpattingbobnd $ 1,oern cou \rb\L
|
||||
Start of matched string is beyond its end - displaying from end to start.
|
||||
0: a
|
||||
0L
|
||||
|
||||
/(?<=((?C)0))/
|
||||
9010
|
||||
--->9010
|
||||
0 ^ 0
|
||||
0 ^ 0
|
||||
0:
|
||||
1: 0
|
||||
abcd
|
||||
--->abcd
|
||||
0 ^ 0
|
||||
0 ^ 0
|
||||
0 ^ 0
|
||||
0 ^ 0
|
||||
No match
|
||||
|
||||
/((?J)(?'R'(?'R'(?'R'(?'R'(?'R'(?|(\k'R'))))))))/
|
||||
|
||||
/\N(?(?C)0?!.)*/
|
||||
Failed: assertion expected after (?( or (?(?C) at offset 4
|
||||
|
||||
/(?<RA>abc)(?(R)xyz)/BZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
CBra 1
|
||||
abc
|
||||
Ket
|
||||
Cond
|
||||
Cond recurse any
|
||||
xyz
|
||||
Ket
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/(?<R>abc)(?(R)xyz)/BZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
CBra 1
|
||||
abc
|
||||
Ket
|
||||
Cond
|
||||
1 Cond ref
|
||||
xyz
|
||||
Ket
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/(?=.*[A-Z])/I
|
||||
Capturing subpattern count = 0
|
||||
May match empty string
|
||||
No options
|
||||
No first char
|
||||
No need char
|
||||
|
||||
/-- End of testinput2 --/
|
||||
|
|
24
ext/pcre/pcrelib/testdata/testoutput6
vendored
24
ext/pcre/pcrelib/testdata/testoutput6
vendored
|
@ -2557,4 +2557,28 @@ No match
|
|||
\x{37e}
|
||||
0: \x{37e}
|
||||
|
||||
/[^[:^ascii:]\d]/8W
|
||||
a
|
||||
0: a
|
||||
~
|
||||
0: ~
|
||||
0
|
||||
No match
|
||||
\a
|
||||
0: \x{07}
|
||||
\x{7f}
|
||||
0: \x{7f}
|
||||
\x{389}
|
||||
No match
|
||||
\x{20ac}
|
||||
No match
|
||||
|
||||
/(?=.*b)\pL/
|
||||
11bb
|
||||
0: b
|
||||
|
||||
/(?(?=.*b)(?=.*b)\pL|.*c)/
|
||||
11bb
|
||||
0: b
|
||||
|
||||
/-- End of testinput6 --/
|
||||
|
|
46
ext/pcre/pcrelib/testdata/testoutput7
vendored
46
ext/pcre/pcrelib/testdata/testoutput7
vendored
|
@ -2295,32 +2295,6 @@ Need char = 'c' (caseless)
|
|||
scat
|
||||
0: sc
|
||||
|
||||
/[\W\p{Any}]/BZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
[\x00-/:-@[-^`{-\xff\p{Any}]
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
abc
|
||||
0: a
|
||||
123
|
||||
0: 1
|
||||
|
||||
/[\W\pL]/BZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
[\x00-/:-@[-^`{-\xff\p{L}]
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
abc
|
||||
0: a
|
||||
** Failers
|
||||
0: *
|
||||
123
|
||||
No match
|
||||
|
||||
/a[[:punct:]b]/WBZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
|
@ -2348,4 +2322,24 @@ No match
|
|||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/L(?#(|++<!(2)?/B8COZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
Callout 255 0 14
|
||||
L?
|
||||
Callout 255 14 0
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/L(?#(|++<!(2)?/B8WCZ
|
||||
------------------------------------------------------------------
|
||||
Bra
|
||||
Callout 255 0 14
|
||||
L?+
|
||||
Callout 255 14 0
|
||||
Ket
|
||||
End
|
||||
------------------------------------------------------------------
|
||||
|
||||
/-- End of testinput7 --/
|
||||
|
|
14
ext/pcre/pcrelib/testdata/testoutput8
vendored
14
ext/pcre/pcrelib/testdata/testoutput8
vendored
|
@ -7791,4 +7791,18 @@ Matched, but offsets vector is too small to show all matches
|
|||
aaa
|
||||
No match
|
||||
|
||||
/()()a+/O=
|
||||
aaa\D
|
||||
** Show all captures ignored after DFA matching
|
||||
0: aaa
|
||||
1: aa
|
||||
2: a
|
||||
a\D
|
||||
** Show all captures ignored after DFA matching
|
||||
0: a
|
||||
|
||||
/(02-)?[0-9]{3}-[0-9]{3}/
|
||||
02-123-123
|
||||
0: 02-123-123
|
||||
|
||||
/-- End of testinput8 --/
|
||||
|
|
|
@ -175,6 +175,10 @@ static PHP_MINFO_FUNCTION(pcre)
|
|||
php_info_print_table_row(2, "PCRE JIT Support", "not compiled in" );
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PCRE_VALGRIND_SUPPORT
|
||||
php_info_print_table_row(2, "PCRE Valgrind Support", "enabled" );
|
||||
#endif
|
||||
|
||||
php_info_print_table_end();
|
||||
|
||||
DISPLAY_INI_ENTRIES();
|
||||
|
|
2
ext/sodium/CREDITS
Normal file
2
ext/sodium/CREDITS
Normal file
|
@ -0,0 +1,2 @@
|
|||
Sodium
|
||||
Frank Denis
|
13
ext/sodium/README.md
Normal file
13
ext/sodium/README.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
[](https://travis-ci.org/jedisct1/libsodium-php?branch=master)
|
||||
|
||||
libsodium-php
|
||||
=============
|
||||
|
||||
A simple, low-level PHP extension for
|
||||
[libsodium](https://github.com/jedisct1/libsodium).
|
||||
|
||||
Full documentation here:
|
||||
[Using Libsodium in PHP Projects](https://paragonie.com/book/pecl-libsodium),
|
||||
a guide to using the libsodium PHP extension for modern, secure, and
|
||||
fast cryptography.
|
||||
|
65
ext/sodium/config.m4
Normal file
65
ext/sodium/config.m4
Normal file
|
@ -0,0 +1,65 @@
|
|||
dnl $Id$
|
||||
dnl config.m4 for extension sodium
|
||||
|
||||
PHP_ARG_WITH(sodium, for sodium support,
|
||||
[ --with-sodium[=DIR] Include sodium support])
|
||||
|
||||
if test "$PHP_SODIUM" != "no"; then
|
||||
SEARCH_PATH="/usr/local /usr" # you might want to change this
|
||||
SEARCH_FOR="/include/sodium.h" # you most likely want to change this
|
||||
|
||||
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
|
||||
AC_MSG_CHECKING([for libsodium])
|
||||
|
||||
dnl user provided location
|
||||
if test -r $PHP_SODIUM/$SEARCH_FOR; then # path given as parameter
|
||||
LIBSODIUM_DIR=$PHP_SODIUM
|
||||
AC_MSG_RESULT([found in $PHP_SODIUM])
|
||||
|
||||
dnl pkg-config output
|
||||
elif test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libsodium; then
|
||||
LIBSODIUM_CFLAGS=`$PKG_CONFIG libsodium --cflags`
|
||||
LIBSODIUM_LIBS=`$PKG_CONFIG libsodium --libs`
|
||||
LIBSODIUM_VERSION=`$PKG_CONFIG libsodium --modversion`
|
||||
AC_MSG_RESULT(version $LIBSODIUM_VERSION found using pkg-config)
|
||||
PHP_EVAL_LIBLINE($LIBSODIUM_LIBS, SODIUM_SHARED_LIBADD)
|
||||
PHP_EVAL_INCLINE($LIBSODIUM_CFLAGS)
|
||||
|
||||
dnl search default path list
|
||||
else
|
||||
for i in $SEARCH_PATH ; do
|
||||
if test -r $i/$SEARCH_FOR; then
|
||||
LIBSODIUM_DIR=$i
|
||||
AC_MSG_RESULT(found in $i)
|
||||
fi
|
||||
done
|
||||
if test -z "$LIBSODIUM_DIR"; then
|
||||
AC_MSG_ERROR([Please install libsodium - See https://github.com/jedisct1/libsodium])
|
||||
fi
|
||||
fi
|
||||
|
||||
LIBNAME=sodium
|
||||
LIBSYMBOL=crypto_pwhash_scryptsalsa208sha256
|
||||
|
||||
if test -n "$LIBSODIUM_DIR"; then
|
||||
PHP_ADD_INCLUDE($LIBSODIUM_DIR/include)
|
||||
PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $LIBSODIUM_DIR/$PHP_LIBDIR, SODIUM_SHARED_LIBADD)
|
||||
fi
|
||||
|
||||
PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
|
||||
[
|
||||
AC_DEFINE(HAVE_LIBSODIUMLIB,1,[ ])
|
||||
],[
|
||||
AC_MSG_ERROR([wrong libsodium lib version or lib not found])
|
||||
],[
|
||||
])
|
||||
PHP_CHECK_LIBRARY($LIBNAME,crypto_aead_aes256gcm_encrypt,
|
||||
[
|
||||
AC_DEFINE(HAVE_CRYPTO_AEAD_AES256GCM,1,[ ])
|
||||
],[],[
|
||||
])
|
||||
|
||||
PHP_SUBST(SODIUM_SHARED_LIBADD)
|
||||
|
||||
PHP_NEW_EXTENSION(sodium, libsodium.c, $ext_shared)
|
||||
fi
|
15
ext/sodium/config.w32
Normal file
15
ext/sodium/config.w32
Normal file
|
@ -0,0 +1,15 @@
|
|||
// $Id$
|
||||
// vim:ft=javascript
|
||||
|
||||
ARG_WITH("sodium", "for libsodium support", "no");
|
||||
|
||||
if (PHP_SODIUM != "no") {
|
||||
if (CHECK_LIB("libsodium.lib", "sodium", PHP_SODIUM) && CHECK_HEADER_ADD_INCLUDE("sodium.h", "CFLAGS_SODIUM")) {
|
||||
EXTENSION("sodium", "libsodium.c");
|
||||
AC_DEFINE('HAVE_LIBSODIUMLIB', 1 , 'Have the Sodium library');
|
||||
AC_DEFINE("HAVE_CRYPTO_AEAD_AES256GCM", 1, "");
|
||||
PHP_INSTALL_HEADERS("ext/sodium/", "php_libsodium.h");
|
||||
} else {
|
||||
WARNING("libsodium not enabled; libraries and headers not found");
|
||||
}
|
||||
}
|
2684
ext/sodium/libsodium.c
Normal file
2684
ext/sodium/libsodium.c
Normal file
File diff suppressed because it is too large
Load diff
24
ext/sodium/libsodium.php
Normal file
24
ext/sodium/libsodium.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
$br = (php_sapi_name() == "cli")? "":"<br>";
|
||||
|
||||
if(!extension_loaded('libsodium')) {
|
||||
dl('libsodium.' . PHP_SHLIB_SUFFIX);
|
||||
}
|
||||
$module = 'libsodium';
|
||||
$functions = get_extension_funcs($module);
|
||||
echo "Functions available in the test extension:$br\n";
|
||||
foreach($functions as $func) {
|
||||
echo $func."$br\n";
|
||||
}
|
||||
echo "$br\n";
|
||||
$function = 'sodium_memzero';
|
||||
$exit = 0;
|
||||
if (extension_loaded($module)) {
|
||||
$str = $function($module);
|
||||
} else {
|
||||
$str = "Module $module is not compiled into PHP";
|
||||
$exit = 255;
|
||||
}
|
||||
echo "$str\n";
|
||||
exit($exit);
|
||||
?>
|
118
ext/sodium/php_libsodium.h
Normal file
118
ext/sodium/php_libsodium.h
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 7 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2017 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Frank Denis <jedisct1@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef PHP_LIBSODIUM_H
|
||||
#define PHP_LIBSODIUM_H
|
||||
|
||||
extern zend_module_entry sodium_module_entry;
|
||||
#define phpext_sodium_ptr &sodium_module_entry
|
||||
|
||||
#define PHP_SODIUM_VERSION PHP_VERSION
|
||||
|
||||
#ifdef ZTS
|
||||
# include "TSRM.h"
|
||||
#endif
|
||||
|
||||
PHP_MINIT_FUNCTION(sodium);
|
||||
PHP_MSHUTDOWN_FUNCTION(sodium);
|
||||
PHP_RINIT_FUNCTION(sodium);
|
||||
PHP_RSHUTDOWN_FUNCTION(sodium);
|
||||
PHP_MINFO_FUNCTION(sodium);
|
||||
|
||||
PHP_FUNCTION(sodium_crypto_aead_aes256gcm_is_available);
|
||||
PHP_FUNCTION(sodium_crypto_aead_aes256gcm_decrypt);
|
||||
PHP_FUNCTION(sodium_crypto_aead_aes256gcm_encrypt);
|
||||
PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_decrypt);
|
||||
PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_encrypt);
|
||||
PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_ietf_decrypt);
|
||||
PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_ietf_encrypt);
|
||||
PHP_FUNCTION(sodium_crypto_aead_xchacha20poly1305_ietf_decrypt);
|
||||
PHP_FUNCTION(sodium_crypto_aead_xchacha20poly1305_ietf_encrypt);
|
||||
PHP_FUNCTION(sodium_crypto_auth);
|
||||
PHP_FUNCTION(sodium_crypto_auth_verify);
|
||||
PHP_FUNCTION(sodium_crypto_box);
|
||||
PHP_FUNCTION(sodium_crypto_box_keypair);
|
||||
PHP_FUNCTION(sodium_crypto_box_seed_keypair);
|
||||
PHP_FUNCTION(sodium_crypto_box_keypair_from_secretkey_and_publickey);
|
||||
PHP_FUNCTION(sodium_crypto_box_open);
|
||||
PHP_FUNCTION(sodium_crypto_box_publickey);
|
||||
PHP_FUNCTION(sodium_crypto_box_publickey_from_secretkey);
|
||||
PHP_FUNCTION(sodium_crypto_box_seal);
|
||||
PHP_FUNCTION(sodium_crypto_box_seal_open);
|
||||
PHP_FUNCTION(sodium_crypto_box_secretkey);
|
||||
PHP_FUNCTION(sodium_crypto_generichash);
|
||||
PHP_FUNCTION(sodium_crypto_generichash_final);
|
||||
PHP_FUNCTION(sodium_crypto_generichash_init);
|
||||
PHP_FUNCTION(sodium_crypto_generichash_update);
|
||||
PHP_FUNCTION(sodium_crypto_kx);
|
||||
PHP_FUNCTION(sodium_crypto_pwhash);
|
||||
PHP_FUNCTION(sodium_crypto_pwhash_str);
|
||||
PHP_FUNCTION(sodium_crypto_pwhash_str_verify);
|
||||
PHP_FUNCTION(sodium_crypto_pwhash_scryptsalsa208sha256);
|
||||
PHP_FUNCTION(sodium_crypto_pwhash_scryptsalsa208sha256_str);
|
||||
PHP_FUNCTION(sodium_crypto_pwhash_scryptsalsa208sha256_str_verify);
|
||||
PHP_FUNCTION(sodium_crypto_scalarmult);
|
||||
PHP_FUNCTION(sodium_crypto_scalarmult_base);
|
||||
PHP_FUNCTION(sodium_crypto_secretbox);
|
||||
PHP_FUNCTION(sodium_crypto_secretbox_open);
|
||||
PHP_FUNCTION(sodium_crypto_shorthash);
|
||||
PHP_FUNCTION(sodium_crypto_sign);
|
||||
PHP_FUNCTION(sodium_crypto_sign_detached);
|
||||
PHP_FUNCTION(sodium_crypto_sign_ed25519_pk_to_curve25519);
|
||||
PHP_FUNCTION(sodium_crypto_sign_ed25519_sk_to_curve25519);
|
||||
PHP_FUNCTION(sodium_crypto_sign_keypair);
|
||||
PHP_FUNCTION(sodium_crypto_sign_keypair_from_secretkey_and_publickey);
|
||||
PHP_FUNCTION(sodium_crypto_sign_open);
|
||||
PHP_FUNCTION(sodium_crypto_sign_publickey);
|
||||
PHP_FUNCTION(sodium_crypto_sign_publickey_from_secretkey);
|
||||
PHP_FUNCTION(sodium_crypto_sign_secretkey);
|
||||
PHP_FUNCTION(sodium_crypto_sign_seed_keypair);
|
||||
PHP_FUNCTION(sodium_crypto_sign_verify_detached);
|
||||
PHP_FUNCTION(sodium_crypto_stream);
|
||||
PHP_FUNCTION(sodium_crypto_stream_xor);
|
||||
PHP_FUNCTION(sodium_randombytes_buf);
|
||||
PHP_FUNCTION(sodium_randombytes_random16);
|
||||
PHP_FUNCTION(sodium_randombytes_uniform);
|
||||
PHP_FUNCTION(sodium_bin2hex);
|
||||
PHP_FUNCTION(sodium_compare);
|
||||
PHP_FUNCTION(sodium_hex2bin);
|
||||
PHP_FUNCTION(sodium_increment);
|
||||
PHP_FUNCTION(sodium_add);
|
||||
PHP_FUNCTION(sodium_memcmp);
|
||||
PHP_FUNCTION(sodium_memzero);
|
||||
|
||||
#ifndef crypto_kx_BYTES
|
||||
#define crypto_kx_BYTES crypto_scalarmult_BYTES
|
||||
#endif
|
||||
#ifndef crypto_kx_PUBLICKEYBYTES
|
||||
#define crypto_kx_PUBLICKEYBYTES crypto_scalarmult_SCALARBYTES
|
||||
#endif
|
||||
#ifndef crypto_kx_SECRETKEYBYTES
|
||||
#define crypto_kx_SECRETKEYBYTES crypto_scalarmult_SCALARBYTES
|
||||
#endif
|
||||
|
||||
#endif /* PHP_LIBSODIUM_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: noet sw=4 ts=4 fdm=marker
|
||||
* vim<600: noet sw=4 ts=4
|
||||
*/
|
135
ext/sodium/tests/crypto_aead.phpt
Normal file
135
ext/sodium/tests/crypto_aead.phpt
Normal file
|
@ -0,0 +1,135 @@
|
|||
--TEST--
|
||||
Check for libsodium AEAD
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded("sodium")) print "skip extension not loaded";
|
||||
if (!defined('SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES')) print "skip libsodium without AESGCM";
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
echo "aead_chacha20poly1305:\n";
|
||||
|
||||
$msg = random_bytes(random_int(1, 1000));
|
||||
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES);
|
||||
$key = random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES);
|
||||
$ad = random_bytes(random_int(1, 1000));
|
||||
|
||||
$ciphertext = sodium_crypto_aead_chacha20poly1305_encrypt($msg, $ad, $nonce, $key);
|
||||
$msg2 = sodium_crypto_aead_chacha20poly1305_decrypt($ciphertext, $ad, $nonce, $key);
|
||||
var_dump($ciphertext !== $msg);
|
||||
var_dump($msg === $msg2);
|
||||
var_dump(sodium_crypto_aead_chacha20poly1305_decrypt($ciphertext, 'x' . $ad, $nonce, $key));
|
||||
try {
|
||||
// Switched order
|
||||
$msg2 = sodium_crypto_aead_chacha20poly1305_decrypt($ciphertext, $ad, $key, $nonce);
|
||||
var_dump(false);
|
||||
} catch (SodiumException $ex) {
|
||||
var_dump(true);
|
||||
}
|
||||
|
||||
echo "aead_chacha20poly1305_ietf:\n";
|
||||
|
||||
if (SODIUM_LIBRARY_MAJOR_VERSION > 7 ||
|
||||
(SODIUM_LIBRARY_MAJOR_VERSION == 7 &&
|
||||
SODIUM_LIBRARY_MINOR_VERSION >= 6)) {
|
||||
$msg = random_bytes(random_int(1, 1000));
|
||||
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES);
|
||||
$key = random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES);
|
||||
$ad = random_bytes(random_int(1, 1000));
|
||||
|
||||
$ciphertext = sodium_crypto_aead_chacha20poly1305_ietf_encrypt($msg, $ad, $nonce, $key);
|
||||
$msg2 = sodium_crypto_aead_chacha20poly1305_ietf_decrypt($ciphertext, $ad, $nonce, $key);
|
||||
var_dump($ciphertext !== $msg);
|
||||
var_dump($msg === $msg2);
|
||||
var_dump(sodium_crypto_aead_chacha20poly1305_ietf_decrypt($ciphertext, 'x' . $ad, $nonce, $key));
|
||||
try {
|
||||
// Switched order
|
||||
$msg2 = sodium_crypto_aead_chacha20poly1305_ietf_decrypt($ciphertext, $ad, $key, $nonce);
|
||||
var_dump(false);
|
||||
} catch (SodiumException $ex) {
|
||||
var_dump(true);
|
||||
}
|
||||
} else {
|
||||
var_dump(true);
|
||||
var_dump(true);
|
||||
var_dump(false);
|
||||
var_dump(true);
|
||||
}
|
||||
|
||||
echo "aead_xchacha20poly1305_ietf:\n";
|
||||
|
||||
if (SODIUM_LIBRARY_MAJOR_VERSION > 9 ||
|
||||
(SODIUM_LIBRARY_MAJOR_VERSION == 9 &&
|
||||
SODIUM_LIBRARY_MINOR_VERSION >= 4)) {
|
||||
$msg = random_bytes(random_int(1, 1000));
|
||||
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES);
|
||||
$key = random_bytes(SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES);
|
||||
$ad = random_bytes(random_int(1, 1000));
|
||||
|
||||
$ciphertext = sodium_crypto_aead_xchacha20poly1305_ietf_encrypt($msg, $ad, $nonce, $key);
|
||||
$msg2 = sodium_crypto_aead_xchacha20poly1305_ietf_decrypt($ciphertext, $ad, $nonce, $key);
|
||||
var_dump($ciphertext !== $msg);
|
||||
var_dump($msg === $msg2);
|
||||
var_dump(sodium_crypto_aead_xchacha20poly1305_ietf_decrypt($ciphertext, 'x' . $ad, $nonce, $key));
|
||||
try {
|
||||
// Switched order
|
||||
$msg2 = sodium_crypto_aead_xchacha20poly1305_ietf_decrypt($ciphertext, $ad, $key, $nonce);
|
||||
var_dump(false);
|
||||
} catch (SodiumException $ex) {
|
||||
var_dump(true);
|
||||
}
|
||||
} else {
|
||||
var_dump(true);
|
||||
var_dump(true);
|
||||
var_dump(false);
|
||||
var_dump(true);
|
||||
}
|
||||
|
||||
echo "aead_aes256gcm:\n";
|
||||
|
||||
$msg = random_bytes(random_int(1, 1000));
|
||||
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES);
|
||||
$key = random_bytes(SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES);
|
||||
$ad = random_bytes(random_int(1, 1000));
|
||||
|
||||
if (sodium_crypto_aead_aes256gcm_is_available()) {
|
||||
$ciphertext = sodium_crypto_aead_aes256gcm_encrypt($msg, $ad, $nonce, $key);
|
||||
$msg2 = sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $ad, $nonce, $key);
|
||||
var_dump($ciphertext !== $msg);
|
||||
var_dump($msg === $msg2);
|
||||
var_dump(sodium_crypto_aead_aes256gcm_decrypt($ciphertext, 'x' . $ad, $nonce, $key));
|
||||
try {
|
||||
// Switched order
|
||||
$msg2 = sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $ad, $key, $nonce);
|
||||
var_dump(false);
|
||||
} catch (SodiumException $ex) {
|
||||
var_dump(true);
|
||||
}
|
||||
} else {
|
||||
var_dump(true);
|
||||
var_dump(true);
|
||||
var_dump(false);
|
||||
var_dump(true);
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
aead_chacha20poly1305:
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
aead_chacha20poly1305_ietf:
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
aead_xchacha20poly1305_ietf:
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
aead_aes256gcm:
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
47
ext/sodium/tests/crypto_auth.phpt
Normal file
47
ext/sodium/tests/crypto_auth.phpt
Normal file
|
@ -0,0 +1,47 @@
|
|||
--TEST--
|
||||
Check for libsodium auth
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("sodium")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$msg = random_bytes(1000);
|
||||
$key = random_bytes(SODIUM_CRYPTO_AUTH_KEYBYTES);
|
||||
$mac = sodium_crypto_auth($msg, $key);
|
||||
|
||||
// This should validate
|
||||
var_dump(sodium_crypto_auth_verify($mac, $msg, $key));
|
||||
|
||||
$bad_key = random_bytes(SODIUM_CRYPTO_AUTH_KEYBYTES - 1);
|
||||
try {
|
||||
$mac = sodium_crypto_auth($msg, $bad_key);
|
||||
echo 'Fail!', PHP_EOL;
|
||||
} catch (SodiumException $ex) {
|
||||
echo $ex->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
// Flip the first bit
|
||||
$badmsg = $msg;
|
||||
$badmsg[0] = \chr(\ord($badmsg[0]) ^ 0x80);
|
||||
var_dump(sodium_crypto_auth_verify($mac, $badmsg, $key));
|
||||
|
||||
// Let's flip a bit pseudo-randomly
|
||||
$badmsg = $msg;
|
||||
$badmsg[$i=mt_rand(0, 999)] = \chr(
|
||||
\ord($msg[$i]) ^ (
|
||||
1 << mt_rand(0, 7)
|
||||
)
|
||||
);
|
||||
|
||||
var_dump(sodium_crypto_auth_verify($mac, $badmsg, $key));
|
||||
|
||||
// Now let's change a bit in the MAC
|
||||
$badmac = $mac;
|
||||
$badmac[0] = \chr(\ord($badmac[0]) ^ 0x80);
|
||||
var_dump(sodium_crypto_auth_verify($badmac, $msg, $key));
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
crypto_auth(): key must be CRYPTO_AUTH_KEYBYTES bytes
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
150
ext/sodium/tests/crypto_box.phpt
Normal file
150
ext/sodium/tests/crypto_box.phpt
Normal file
|
@ -0,0 +1,150 @@
|
|||
--TEST--
|
||||
Check for libsodium box
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("sodium")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$keypair = sodium_crypto_box_keypair();
|
||||
var_dump(strlen($keypair) === SODIUM_CRYPTO_BOX_KEYPAIRBYTES);
|
||||
$sk = sodium_crypto_box_secretkey($keypair);
|
||||
var_dump(strlen($sk) === SODIUM_CRYPTO_BOX_SECRETKEYBYTES);
|
||||
$pk = sodium_crypto_box_publickey($keypair);
|
||||
var_dump(strlen($pk) === SODIUM_CRYPTO_BOX_PUBLICKEYBYTES);
|
||||
var_dump($pk !== $sk);
|
||||
$pk2 = sodium_crypto_box_publickey_from_secretkey($sk);
|
||||
var_dump($pk === $pk2);
|
||||
$pk2 = sodium_crypto_scalarmult_base($sk);
|
||||
var_dump($pk === $pk2);
|
||||
$keypair2 = sodium_crypto_box_keypair_from_secretkey_and_publickey($sk, $pk);
|
||||
var_dump($keypair === $keypair2);
|
||||
|
||||
$seed_x = str_repeat('x', SODIUM_CRYPTO_BOX_SEEDBYTES);
|
||||
$seed_y = str_repeat('y', SODIUM_CRYPTO_BOX_SEEDBYTES);
|
||||
$alice_box_kp = sodium_crypto_box_seed_keypair($seed_x);
|
||||
$bob_box_kp = sodium_crypto_box_seed_keypair($seed_y);
|
||||
$message_nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);
|
||||
|
||||
$alice_box_secretkey = sodium_crypto_box_secretkey($alice_box_kp);
|
||||
$bob_box_publickey = sodium_crypto_box_publickey($bob_box_kp);
|
||||
|
||||
$alice_to_bob_kp = sodium_crypto_box_keypair_from_secretkey_and_publickey(
|
||||
$alice_box_secretkey,
|
||||
$bob_box_publickey
|
||||
);
|
||||
|
||||
$msg = "Here is another message, to be signed using Alice's secret key, and " .
|
||||
"to be encrypted using Bob's public key. The keys will always be the same " .
|
||||
"since they are derived from a fixed seeds";
|
||||
|
||||
$ciphertext = sodium_crypto_box(
|
||||
$msg,
|
||||
$message_nonce,
|
||||
$alice_to_bob_kp
|
||||
);
|
||||
|
||||
try {
|
||||
$ciphertext = sodium_crypto_box(
|
||||
$msg,
|
||||
$message_nonce,
|
||||
substr($alice_to_bob_kp, 1)
|
||||
);
|
||||
} catch (SodiumException $ex) {
|
||||
echo $ex->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
sodium_memzero($alice_box_kp);
|
||||
sodium_memzero($bob_box_kp);
|
||||
|
||||
$alice_box_kp = sodium_crypto_box_seed_keypair($seed_x);
|
||||
$bob_box_kp = sodium_crypto_box_seed_keypair($seed_y);
|
||||
|
||||
$alice_box_publickey = sodium_crypto_box_publickey($alice_box_kp);
|
||||
$bob_box_secretkey = sodium_crypto_box_secretkey($bob_box_kp);
|
||||
|
||||
$bob_to_alice_kp = sodium_crypto_box_keypair_from_secretkey_and_publickey(
|
||||
$bob_box_secretkey,
|
||||
$alice_box_publickey
|
||||
);
|
||||
|
||||
$plaintext = sodium_crypto_box_open(
|
||||
$ciphertext,
|
||||
$message_nonce,
|
||||
$bob_to_alice_kp
|
||||
);
|
||||
|
||||
var_dump($msg === $plaintext);
|
||||
|
||||
$alice_kp = sodium_crypto_box_keypair();
|
||||
$alice_secretkey = sodium_crypto_box_secretkey($alice_kp);
|
||||
$alice_publickey = sodium_crypto_box_publickey($alice_kp);
|
||||
|
||||
$bob_kp = sodium_crypto_box_keypair();
|
||||
$bob_secretkey = sodium_crypto_box_secretkey($bob_kp);
|
||||
$bob_publickey = sodium_crypto_box_publickey($bob_kp);
|
||||
|
||||
$alice_to_bob_kp = sodium_crypto_box_keypair_from_secretkey_and_publickey
|
||||
($alice_secretkey, $bob_publickey);
|
||||
|
||||
$bob_to_alice_kp = sodium_crypto_box_keypair_from_secretkey_and_publickey
|
||||
($bob_secretkey, $alice_publickey);
|
||||
|
||||
$alice_to_bob_message_nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);
|
||||
|
||||
$alice_to_bob_ciphertext = sodium_crypto_box('Hi, this is Alice',
|
||||
$alice_to_bob_message_nonce,
|
||||
$alice_to_bob_kp);
|
||||
|
||||
$alice_message_decrypted_by_bob = sodium_crypto_box_open($alice_to_bob_ciphertext,
|
||||
$alice_to_bob_message_nonce,
|
||||
$bob_to_alice_kp);
|
||||
|
||||
$bob_to_alice_message_nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);
|
||||
|
||||
$bob_to_alice_ciphertext = sodium_crypto_box('Hi Alice! This is Bob',
|
||||
$bob_to_alice_message_nonce,
|
||||
$bob_to_alice_kp);
|
||||
|
||||
$bob_message_decrypted_by_alice = sodium_crypto_box_open($bob_to_alice_ciphertext,
|
||||
$bob_to_alice_message_nonce,
|
||||
$alice_to_bob_kp);
|
||||
|
||||
var_dump($alice_message_decrypted_by_bob);
|
||||
var_dump($bob_message_decrypted_by_alice);
|
||||
|
||||
if (SODIUM_LIBRARY_MAJOR_VERSION > 7 ||
|
||||
(SODIUM_LIBRARY_MAJOR_VERSION == 7 &&
|
||||
SODIUM_LIBRARY_MINOR_VERSION >= 5)) {
|
||||
$anonymous_message_to_alice = sodium_crypto_box_seal('Anonymous message',
|
||||
$alice_publickey);
|
||||
|
||||
$decrypted_message = sodium_crypto_box_seal_open($anonymous_message_to_alice,
|
||||
$alice_kp);
|
||||
} else {
|
||||
$decrypted_message = 'Anonymous message';
|
||||
}
|
||||
var_dump($decrypted_message);
|
||||
|
||||
$msg = sodium_hex2bin(
|
||||
'7375f4094f1151640bd853cb13dbc1a0ee9e13b0287a89d34fa2f6732be9de13f88457553d'.
|
||||
'768347116522d6d32c9cb353ef07aa7c83bd129b2bb5db35b28334c935b24f2639405a0604'
|
||||
);
|
||||
$kp = sodium_hex2bin(
|
||||
'36a6c2b96a650d80bf7e025e0f58f3d636339575defb370801a54213bd54582d'.
|
||||
'5aecbcf7866e7a4d58a6c1317e2b955f54ecbe2fcbbf7d262c10636ed524480c'
|
||||
);
|
||||
var_dump(sodium_crypto_box_seal_open($msg, $kp));
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
crypto_box(): keypair size should be CRYPTO_BOX_KEYPAIRBYTES bytes
|
||||
bool(true)
|
||||
string(17) "Hi, this is Alice"
|
||||
string(21) "Hi Alice! This is Bob"
|
||||
string(17) "Anonymous message"
|
||||
string(26) "This is for your eyes only"
|
61
ext/sodium/tests/crypto_generichash.phpt
Normal file
61
ext/sodium/tests/crypto_generichash.phpt
Normal file
|
@ -0,0 +1,61 @@
|
|||
--TEST--
|
||||
Check for libsodium generichash
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("sodium")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$q = sodium_crypto_generichash('msg');
|
||||
var_dump(bin2hex($q));
|
||||
$q = sodium_crypto_generichash('msg', '0123456789abcdef');
|
||||
var_dump(bin2hex($q));
|
||||
$q = sodium_crypto_generichash('msg', '0123456789abcdef', 64);
|
||||
var_dump(bin2hex($q));
|
||||
$q = sodium_crypto_generichash('msg', '0123456789abcdef0123456789abcdef', 64);
|
||||
var_dump(bin2hex($q));
|
||||
$state = sodium_crypto_generichash_init();
|
||||
$q = sodium_crypto_generichash_final($state);
|
||||
var_dump(bin2hex($q));
|
||||
$state = sodium_crypto_generichash_init();
|
||||
sodium_crypto_generichash_update($state, 'm');
|
||||
sodium_crypto_generichash_update($state, 'sg');
|
||||
$q = sodium_crypto_generichash_final($state);
|
||||
var_dump(bin2hex($q));
|
||||
$state = sodium_crypto_generichash_init('0123456789abcdef');
|
||||
sodium_crypto_generichash_update($state, 'm');
|
||||
sodium_crypto_generichash_update($state, 'sg');
|
||||
$q = sodium_crypto_generichash_final($state);
|
||||
var_dump(bin2hex($q));
|
||||
$state = sodium_crypto_generichash_init('0123456789abcdef', 64);
|
||||
sodium_crypto_generichash_update($state, 'm');
|
||||
sodium_crypto_generichash_update($state, 'sg');
|
||||
$state2 = '' . $state;
|
||||
$q = sodium_crypto_generichash_final($state, 64);
|
||||
var_dump(bin2hex($q));
|
||||
sodium_crypto_generichash_update($state2, '2');
|
||||
$q = sodium_crypto_generichash_final($state2, 64);
|
||||
$exp = bin2hex($q);
|
||||
var_dump($exp);
|
||||
$act = bin2hex(
|
||||
sodium_crypto_generichash('msg2', '0123456789abcdef', 64)
|
||||
);
|
||||
var_dump($act);
|
||||
var_dump($exp === $act);
|
||||
try {
|
||||
$hash = sodium_crypto_generichash('test', '', 128);
|
||||
} catch (SodiumException $ex) {
|
||||
var_dump(true);
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
string(64) "96a7ed8861db0abc006f473f9e64687875f3d9df8e723adae9f53a02b2aec378"
|
||||
string(64) "ba03e32a94ece425a77b350f029e0a3d37e6383158aa7cefa2b1b9470a7fcb7a"
|
||||
string(128) "8ccd640462e7380010c5722d7f3c2354781d1360430197ff233509c27353fd2597c8d689bfe769467056a0655b3faba6af4e4ade248558f7c53538c4d5b94806"
|
||||
string(128) "30f0e5f1e3beb7e0340976ac05a94043cce082d870e28e03c906e8fe9a88786271c6ba141eee2885e7444a870fac498cc78a13b0c53aefaec01bf38ebfe73b3f"
|
||||
string(64) "0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8"
|
||||
string(64) "96a7ed8861db0abc006f473f9e64687875f3d9df8e723adae9f53a02b2aec378"
|
||||
string(64) "ba03e32a94ece425a77b350f029e0a3d37e6383158aa7cefa2b1b9470a7fcb7a"
|
||||
string(128) "8ccd640462e7380010c5722d7f3c2354781d1360430197ff233509c27353fd2597c8d689bfe769467056a0655b3faba6af4e4ade248558f7c53538c4d5b94806"
|
||||
string(128) "9ef702f51114c9dc2cc7521746e8beebe0a3ca9bb29ec729e16682ca982e7f69ff70235a46659a9a6c28f92fbd990288301b9a6b5517f1f2ba6518074af19a5a"
|
||||
string(128) "9ef702f51114c9dc2cc7521746e8beebe0a3ca9bb29ec729e16682ca982e7f69ff70235a46659a9a6c28f92fbd990288301b9a6b5517f1f2ba6518074af19a5a"
|
||||
bool(true)
|
||||
bool(true)
|
21
ext/sodium/tests/crypto_hex.phpt
Normal file
21
ext/sodium/tests/crypto_hex.phpt
Normal file
|
@ -0,0 +1,21 @@
|
|||
--TEST--
|
||||
Check for libsodium bin2hex
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("sodium")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$bin = random_bytes(random_int(1, 1000));
|
||||
$hex = sodium_bin2hex($bin);
|
||||
$phphex = bin2hex($bin);
|
||||
var_dump(strcasecmp($hex, $phphex));
|
||||
|
||||
$bin2 = sodium_hex2bin($hex);
|
||||
var_dump($bin2 === $bin);
|
||||
|
||||
$bin2 = sodium_hex2bin('[' . $hex .']', '[]');
|
||||
var_dump($bin2 === $bin);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(0)
|
||||
bool(true)
|
||||
bool(true)
|
37
ext/sodium/tests/crypto_kx.phpt
Normal file
37
ext/sodium/tests/crypto_kx.phpt
Normal file
|
@ -0,0 +1,37 @@
|
|||
--TEST--
|
||||
Check for libsodium-based key exchange
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("sodium")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$client_secretkey = sodium_hex2bin("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a");
|
||||
$client_publickey = sodium_crypto_box_publickey_from_secretkey($client_secretkey);
|
||||
|
||||
$server_secretkey = sodium_hex2bin("948f00e90a246fb5909f8648c2ac6f21515771235523266439e0d775ba0c3671");
|
||||
$server_publickey = sodium_crypto_box_publickey_from_secretkey($server_secretkey);
|
||||
|
||||
$shared_key_computed_by_client =
|
||||
sodium_crypto_kx($client_secretkey, $server_publickey,
|
||||
$client_publickey, $server_publickey);
|
||||
|
||||
$shared_key_computed_by_server =
|
||||
sodium_crypto_kx($server_secretkey, $client_publickey,
|
||||
$client_publickey, $server_publickey);
|
||||
|
||||
var_dump(sodium_bin2hex($shared_key_computed_by_client));
|
||||
var_dump(sodium_bin2hex($shared_key_computed_by_server));
|
||||
try {
|
||||
sodium_crypto_kx(
|
||||
substr($client_secretkey, 1),
|
||||
$server_publickey,
|
||||
$client_publickey,
|
||||
$server_publickey
|
||||
);
|
||||
} catch (SodiumException $ex) {
|
||||
var_dump(true);
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
string(64) "509a1580c2ee30c565317e29e0fea0b1c232e0ef3a7871d91dc64814b19a3bd2"
|
||||
string(64) "509a1580c2ee30c565317e29e0fea0b1c232e0ef3a7871d91dc64814b19a3bd2"
|
||||
bool(true)
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue