2012-02-08 01:25 UTC+0100 Viktor Szakats (harbour syenar.net)
* src/3rd/pcre/Makefile
+ added translation for JIT files from PCRE package
PCRE JIT is work of Zoltan Herczeg (hzmester/at/freemail.hu)
ARM v5/v7/thumb2, MIPS 32, x86/x64, PPC32/64 CPU
platforms are currently supported.
+ enabled PCRE JIT for mingw and msvc/x86/x64 (mainstream)
compilers. Some alternate C compilers like bcc and
watcom are not supported, others not tested. Enable
those which work.
+ enabled PCRE JIT for linux and darwin (EXPERIMENTAL).
Please test and adjust platform/compiler filters as
required.
; fallouts are possible because this is brand new code
never tested on Harbour platforms.
; TODO: to enable JIT on more platforms
(*nixes, MS-DOS, etc). (Cygwin fails)
* src/3rd/pcre/pcrejitc.c
* src/3rd/pcre/pcre.dif
+ manual patch for sjlir.c inclusion
(to be determined why hb3rdpat didn't apply this automatically)
+ src/3rd/pcre/sjmipsc.c
+ src/3rd/pcre/sjexeca.c
+ src/3rd/pcre/sjppcc.c
+ src/3rd/pcre/sjlir.c
+ src/3rd/pcre/sjx86c.c
+ src/3rd/pcre/sjconf.h
+ src/3rd/pcre/sjx8632.c
+ src/3rd/pcre/sjarmv5.c
+ src/3rd/pcre/sjlir.h
+ src/3rd/pcre/sjppc64.c
+ src/3rd/pcre/sjarmth2.c
+ src/3rd/pcre/sjutils.c
+ src/3rd/pcre/sjconfi.h
+ src/3rd/pcre/sjmips32.c
+ src/3rd/pcre/sjppc32.c
+ src/3rd/pcre/sjx8664.c
+ added PCRE JIT sources
This commit is contained in:
@@ -16,6 +16,47 @@
|
||||
The license applies to all entries newer than 2009-04-28.
|
||||
*/
|
||||
|
||||
2012-02-08 01:25 UTC+0100 Viktor Szakats (harbour syenar.net)
|
||||
* src/3rd/pcre/Makefile
|
||||
+ added translation for JIT files from PCRE package
|
||||
PCRE JIT is work of Zoltan Herczeg (hzmester/at/freemail.hu)
|
||||
ARM v5/v7/thumb2, MIPS 32, x86/x64, PPC32/64 CPU
|
||||
platforms are currently supported.
|
||||
+ enabled PCRE JIT for mingw and msvc/x86/x64 (mainstream)
|
||||
compilers. Some alternate C compilers like bcc and
|
||||
watcom are not supported, others not tested. Enable
|
||||
those which work.
|
||||
+ enabled PCRE JIT for linux and darwin (EXPERIMENTAL).
|
||||
Please test and adjust platform/compiler filters as
|
||||
required.
|
||||
; fallouts are possible because this is brand new code
|
||||
never tested on Harbour platforms.
|
||||
; TODO: to enable JIT on more platforms
|
||||
(*nixes, MS-DOS, etc). (Cygwin fails)
|
||||
|
||||
* src/3rd/pcre/pcrejitc.c
|
||||
* src/3rd/pcre/pcre.dif
|
||||
+ manual patch for sjlir.c inclusion
|
||||
(to be determined why hb3rdpat didn't apply this automatically)
|
||||
|
||||
+ src/3rd/pcre/sjmipsc.c
|
||||
+ src/3rd/pcre/sjexeca.c
|
||||
+ src/3rd/pcre/sjppcc.c
|
||||
+ src/3rd/pcre/sjlir.c
|
||||
+ src/3rd/pcre/sjx86c.c
|
||||
+ src/3rd/pcre/sjconf.h
|
||||
+ src/3rd/pcre/sjx8632.c
|
||||
+ src/3rd/pcre/sjarmv5.c
|
||||
+ src/3rd/pcre/sjlir.h
|
||||
+ src/3rd/pcre/sjppc64.c
|
||||
+ src/3rd/pcre/sjarmth2.c
|
||||
+ src/3rd/pcre/sjutils.c
|
||||
+ src/3rd/pcre/sjconfi.h
|
||||
+ src/3rd/pcre/sjmips32.c
|
||||
+ src/3rd/pcre/sjppc32.c
|
||||
+ src/3rd/pcre/sjx8664.c
|
||||
+ added PCRE JIT sources
|
||||
|
||||
2012-02-08 00:05 UTC+0100 Viktor Szakats (harbour syenar.net)
|
||||
* src/3rd/zlib/zlib.dif
|
||||
* src/3rd/zlib/Makefile
|
||||
|
||||
@@ -48,6 +48,14 @@ ifneq ($(HB_HAS_PCRE_LOCAL),)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(HB_COMPILER),mingw mingw64 msvc mvc64),)
|
||||
HB_CFLAGS += -DSUPPORT_JIT
|
||||
else
|
||||
ifneq ($(filter $(HB_PLATFORM),darwin linux),)
|
||||
HB_CFLAGS += -DSUPPORT_JIT
|
||||
endif
|
||||
endif
|
||||
|
||||
HB_CFLAGS += -DHAVE_CONFIG_H
|
||||
|
||||
# workaround for problems in sunpro x86 PIC builds exploited by hbpcre library code
|
||||
@@ -78,29 +86,45 @@ endif
|
||||
# DIFF pcre.dif
|
||||
#
|
||||
# MAP LICENCE
|
||||
# MAP config.h.generic config.h
|
||||
# MAP pcre.h.generic pcre.h
|
||||
# MAP pcre_internal.h pcreinal.h
|
||||
# MAP config.h.generic config.h
|
||||
# MAP pcre.h.generic pcre.h
|
||||
# MAP pcre_internal.h pcreinal.h
|
||||
# MAP ucp.h
|
||||
# MAP pcre_chartables.c.dist chartabs.c
|
||||
# MAP pcre_compile.c pcrecomp.c
|
||||
# MAP pcre_config.c pcreconf.c
|
||||
# MAP pcre_dfa_exec.c pcredfa.c
|
||||
# MAP pcre_exec.c pcreexec.c
|
||||
# MAP pcre_fullinfo.c pcrefinf.c
|
||||
# MAP pcre_get.c pcreget.c
|
||||
# MAP pcre_globals.c pcreglob.c
|
||||
# MAP pcre_info.c pcreinfo.c
|
||||
# MAP pcre_jit_compile.c pcrejitc.c
|
||||
# MAP pcre_maketables.c pcremktb.c
|
||||
# MAP pcre_newline.c pcrenewl.c
|
||||
# MAP pcre_ord2utf8.c pcreoutf.c
|
||||
# MAP pcre_printint.src pcreprni.h
|
||||
# MAP pcre_refcount.c pcrerefc.c
|
||||
# MAP pcre_study.c pcrestud.c
|
||||
# MAP pcre_tables.c pcretabs.c
|
||||
# MAP pcre_try_flipped.c pcretryf.c
|
||||
# MAP pcre_ucd.c pcreucd.c
|
||||
# MAP pcre_valid_utf8.c pcrevutf.c
|
||||
# MAP pcre_version.c pcrever.c
|
||||
# MAP pcre_xclass.c pcrexcls.c
|
||||
# MAP pcre_chartables.c.dist chartabs.c
|
||||
# MAP pcre_compile.c pcrecomp.c
|
||||
# MAP pcre_config.c pcreconf.c
|
||||
# MAP pcre_dfa_exec.c pcredfa.c
|
||||
# MAP pcre_exec.c pcreexec.c
|
||||
# MAP pcre_fullinfo.c pcrefinf.c
|
||||
# MAP pcre_get.c pcreget.c
|
||||
# MAP pcre_globals.c pcreglob.c
|
||||
# MAP pcre_info.c pcreinfo.c
|
||||
# MAP pcre_jit_compile.c pcrejitc.c
|
||||
# MAP pcre_maketables.c pcremktb.c
|
||||
# MAP pcre_newline.c pcrenewl.c
|
||||
# MAP pcre_ord2utf8.c pcreoutf.c
|
||||
# MAP pcre_printint.src pcreprni.h
|
||||
# MAP pcre_refcount.c pcrerefc.c
|
||||
# MAP pcre_study.c pcrestud.c
|
||||
# MAP pcre_tables.c pcretabs.c
|
||||
# MAP pcre_try_flipped.c pcretryf.c
|
||||
# MAP pcre_ucd.c pcreucd.c
|
||||
# MAP pcre_valid_utf8.c pcrevutf.c
|
||||
# MAP pcre_version.c pcrever.c
|
||||
# MAP pcre_xclass.c pcrexcls.c
|
||||
# MAP sljit/sljitConfig.h sjconf.h
|
||||
# MAP sljit/sljitConfigInternal.h sjconfi.h
|
||||
# MAP sljit/sljitExecAllocator.c sjexeca.c
|
||||
# MAP sljit/sljitLir.c sjlir.c
|
||||
# MAP sljit/sljitLir.h sjlir.h
|
||||
# MAP sljit/sljitNativeARM_Thumb2.c sjarmth2.c
|
||||
# MAP sljit/sljitNativeARM_v5.c sjarmv5.c
|
||||
# MAP sljit/sljitNativeMIPS_32.c sjmips32.c
|
||||
# MAP sljit/sljitNativeMIPS_common.c sjmipsc.c
|
||||
# MAP sljit/sljitNativePPC_32.c sjppc32.c
|
||||
# MAP sljit/sljitNativePPC_64.c sjppc64.c
|
||||
# MAP sljit/sljitNativePPC_common.c sjppcc.c
|
||||
# MAP sljit/sljitNativeX86_32.c sjx8632.c
|
||||
# MAP sljit/sljitNativeX86_64.c sjx8664.c
|
||||
# MAP sljit/sljitNativeX86_common.c sjx86c.c
|
||||
# MAP sljit/sljitUtils.c sjutils.c
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
diff -urN pcre.orig\pcrefinf.c pcre\pcrefinf.c
|
||||
--- pcre.orig\pcrefinf.c Tue Feb 07 22:22:32 2012
|
||||
+++ pcre\pcrefinf.c Tue Feb 07 22:22:32 2012
|
||||
--- pcre.orig\pcrefinf.c Wed Feb 08 01:29:30 2012
|
||||
+++ pcre\pcrefinf.c Wed Feb 08 01:29:30 2012
|
||||
@@ -139,7 +139,7 @@
|
||||
case PCRE_INFO_MINLENGTH:
|
||||
*((int *)where) =
|
||||
@@ -11,8 +11,8 @@ diff -urN pcre.orig\pcrefinf.c pcre\pcrefinf.c
|
||||
|
||||
case PCRE_INFO_JIT:
|
||||
diff -urN pcre.orig\pcreglob.c pcre\pcreglob.c
|
||||
--- pcre.orig\pcreglob.c Tue Feb 07 22:22:32 2012
|
||||
+++ pcre\pcreglob.c Tue Feb 07 22:22:32 2012
|
||||
--- pcre.orig\pcreglob.c Wed Feb 08 01:29:30 2012
|
||||
+++ pcre\pcreglob.c Wed Feb 08 01:29:30 2012
|
||||
@@ -74,11 +74,17 @@
|
||||
PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL;
|
||||
|
||||
@@ -31,3 +31,15 @@ diff -urN pcre.orig\pcreglob.c pcre\pcreglob.c
|
||||
#endif
|
||||
|
||||
/* End of pcre_globals.c */
|
||||
diff -urN pcre.orig\pcrejitc.c pcre\pcrejitc.c
|
||||
--- pcre.orig\pcrejitc.c Wed Feb 08 01:29:30 2012
|
||||
+++ pcre\pcrejitc.c Wed Feb 08 01:29:30 2012
|
||||
@@ -59,7 +59,7 @@
|
||||
#define SLJIT_VERBOSE 0
|
||||
#define SLJIT_DEBUG 0
|
||||
|
||||
-#include "sljit/sljitLir.c"
|
||||
+#include "sjlir.c"
|
||||
|
||||
#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
|
||||
#error "Unsupported architecture"
|
||||
|
||||
@@ -59,7 +59,7 @@ system files. */
|
||||
#define SLJIT_VERBOSE 0
|
||||
#define SLJIT_DEBUG 0
|
||||
|
||||
#include "sljit/sljitLir.c"
|
||||
#include "sjlir.c"
|
||||
|
||||
#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
|
||||
#error "Unsupported architecture"
|
||||
|
||||
1835
harbour/src/3rd/pcre/sjarmth2.c
Normal file
1835
harbour/src/3rd/pcre/sjarmth2.c
Normal file
File diff suppressed because it is too large
Load Diff
2362
harbour/src/3rd/pcre/sjarmv5.c
Normal file
2362
harbour/src/3rd/pcre/sjarmv5.c
Normal file
File diff suppressed because it is too large
Load Diff
96
harbour/src/3rd/pcre/sjconf.h
Normal file
96
harbour/src/3rd/pcre/sjconf.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 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:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SLJIT_CONFIG_H_
|
||||
#define _SLJIT_CONFIG_H_
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Architecture */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Architecture selection */
|
||||
/* #define SLJIT_CONFIG_X86_32 1 */
|
||||
/* #define SLJIT_CONFIG_X86_64 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_V5 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_V7 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_THUMB2 1 */
|
||||
/* #define SLJIT_CONFIG_PPC_32 1 */
|
||||
/* #define SLJIT_CONFIG_PPC_64 1 */
|
||||
/* #define SLJIT_CONFIG_MIPS_32 1 */
|
||||
|
||||
/* #define SLJIT_CONFIG_AUTO 1 */
|
||||
/* #define SLJIT_CONFIG_UNSUPPORTED 1 */
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Utilities */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Useful for thread-safe compiling of global functions. */
|
||||
#ifndef SLJIT_UTIL_GLOBAL_LOCK
|
||||
/* Enabled by default */
|
||||
#define SLJIT_UTIL_GLOBAL_LOCK 1
|
||||
#endif
|
||||
|
||||
/* Implements a stack like data structure (by using mmap / VirtualAlloc). */
|
||||
#ifndef SLJIT_UTIL_STACK
|
||||
/* Enabled by default */
|
||||
#define SLJIT_UTIL_STACK 1
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Configuration */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* If SLJIT_STD_MACROS_DEFINED is not defined, the application should
|
||||
define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMMOVE, and NULL. */
|
||||
#ifndef SLJIT_STD_MACROS_DEFINED
|
||||
/* Disabled by default. */
|
||||
#define SLJIT_STD_MACROS_DEFINED 0
|
||||
#endif
|
||||
|
||||
/* Executable code allocation:
|
||||
If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should
|
||||
define both SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC. */
|
||||
#ifndef SLJIT_EXECUTABLE_ALLOCATOR
|
||||
/* Enabled by default. */
|
||||
#define SLJIT_EXECUTABLE_ALLOCATOR 1
|
||||
#endif
|
||||
|
||||
/* Debug checks (assertions, etc.). */
|
||||
#ifndef SLJIT_DEBUG
|
||||
/* Enabled by default */
|
||||
#define SLJIT_DEBUG 1
|
||||
#endif
|
||||
|
||||
/* Verbose operations */
|
||||
#ifndef SLJIT_VERBOSE
|
||||
/* Enabled by default */
|
||||
#define SLJIT_VERBOSE 1
|
||||
#endif
|
||||
|
||||
/* See the beginning of sljitConfigInternal.h */
|
||||
|
||||
#endif
|
||||
415
harbour/src/3rd/pcre/sjconfi.h
Normal file
415
harbour/src/3rd/pcre/sjconfi.h
Normal file
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 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:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SLJIT_CONFIG_INTERNAL_H_
|
||||
#define _SLJIT_CONFIG_INTERNAL_H_
|
||||
|
||||
/*
|
||||
SLJIT defines the following variables itself depending on the configuration:
|
||||
sljit_b, sljit_ub : signed and unsigned 8 bit byte
|
||||
sljit_h, sljit_uh : signed and unsigned 16 bit half-word (short) type
|
||||
sljit_i, sljit_ui : signed and unsigned 32 bit integer type
|
||||
sljit_w, sljit_uw : signed and unsigned machine word, enough to store a pointer (same as intptr_t)
|
||||
SLJIT_CALL : C calling convention for both calling JIT and C callbacks from JIT
|
||||
SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
|
||||
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
|
||||
SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_w/sljit_uw array by index
|
||||
SLJIT_FLOAT_SHIFT : the shift required to apply when accessing a double array by index
|
||||
SLJIT_BIG_ENDIAN : big endian architecture
|
||||
SLJIT_LITTLE_ENDIAN : little endian architecture
|
||||
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET()
|
||||
SLJIT_W : for defining 64 bit constants on 64 bit architectures (compiler workaround)
|
||||
SLJIT_UNALIGNED : allows unaligned memory accesses for integer arithmetic (only!)
|
||||
*/
|
||||
|
||||
#if !((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
|| (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|
||||
|| (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \
|
||||
|| (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|
||||
|| (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|
||||
|| (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|
||||
|| (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED))
|
||||
#error "An architecture must be selected"
|
||||
#endif
|
||||
|
||||
/* Sanity check. */
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
+ (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|
||||
+ (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \
|
||||
+ (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
+ (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|
||||
+ (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
+ (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
+ (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|
||||
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|
||||
+ (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
|
||||
#error "Multiple architectures are selected"
|
||||
#endif
|
||||
|
||||
/* Auto select option (requires compiler support) */
|
||||
#if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#if defined(__i386__) || defined(__i386)
|
||||
#define SLJIT_CONFIG_X86_32 1
|
||||
#elif defined(__x86_64__)
|
||||
#define SLJIT_CONFIG_X86_64 1
|
||||
#elif defined(__arm__) || defined(__ARM__)
|
||||
#ifdef __thumb2__
|
||||
#define SLJIT_CONFIG_ARM_THUMB2 1
|
||||
#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__)
|
||||
#define SLJIT_CONFIG_ARM_V7 1
|
||||
#else
|
||||
#define SLJIT_CONFIG_ARM_V5 1
|
||||
#endif
|
||||
#elif defined(__ppc64__) || defined(__powerpc64__)
|
||||
#define SLJIT_CONFIG_PPC_64 1
|
||||
#elif defined(__ppc__) || defined(__powerpc__)
|
||||
#define SLJIT_CONFIG_PPC_32 1
|
||||
#elif defined(__mips__)
|
||||
#define SLJIT_CONFIG_MIPS_32 1
|
||||
#else
|
||||
/* Unsupported architecture */
|
||||
#define SLJIT_CONFIG_UNSUPPORTED 1
|
||||
#endif
|
||||
|
||||
#else /* !_WIN32 */
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define SLJIT_CONFIG_X86_64 1
|
||||
#elif defined(_ARM_)
|
||||
#define SLJIT_CONFIG_ARM_V5 1
|
||||
#else
|
||||
#define SLJIT_CONFIG_X86_32 1
|
||||
#endif
|
||||
|
||||
#endif /* !WIN32 */
|
||||
#endif /* SLJIT_CONFIG_AUTO */
|
||||
|
||||
#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
|
||||
#undef SLJIT_EXECUTABLE_ALLOCATOR
|
||||
#endif
|
||||
|
||||
#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 /* STD_MACROS_DEFINED */
|
||||
|
||||
/* General macros:
|
||||
Note: SLJIT is designed to be independent from them as possible.
|
||||
|
||||
In release mode (SLJIT_DEBUG is not defined) only the following macros are needed:
|
||||
*/
|
||||
|
||||
#ifndef SLJIT_MALLOC
|
||||
#define SLJIT_MALLOC(size) malloc(size)
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_FREE
|
||||
#define SLJIT_FREE(ptr) free(ptr)
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_MEMMOVE
|
||||
#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len)
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_ZEROMEM
|
||||
#define SLJIT_ZEROMEM(dest, len) memset(dest, 0, len)
|
||||
#endif
|
||||
|
||||
#if !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY)
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
#define SLJIT_LIKELY(x) __builtin_expect((x), 1)
|
||||
#define SLJIT_UNLIKELY(x) __builtin_expect((x), 0)
|
||||
#else
|
||||
#define SLJIT_LIKELY(x) (x)
|
||||
#define SLJIT_UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
#endif /* !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) */
|
||||
|
||||
#ifndef SLJIT_INLINE
|
||||
/* Inline functions. */
|
||||
#define SLJIT_INLINE __inline
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_CONST
|
||||
/* Const variables. */
|
||||
#define SLJIT_CONST const
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_UNUSED_ARG
|
||||
/* Unused arguments. */
|
||||
#define SLJIT_UNUSED_ARG(arg) (void)arg
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC)
|
||||
/* Static ABI functions. For all-in-one programs. */
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/* Disable unused warnings in gcc. */
|
||||
#define SLJIT_API_FUNC_ATTRIBUTE static __attribute__((unused))
|
||||
#else
|
||||
#define SLJIT_API_FUNC_ATTRIBUTE static
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define SLJIT_API_FUNC_ATTRIBUTE
|
||||
#endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */
|
||||
|
||||
#ifndef SLJIT_CACHE_FLUSH
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
|
||||
/* 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_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
|
||||
/* Not required to implement on archs with unified caches. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to)
|
||||
|
||||
#else
|
||||
|
||||
/* Calls __ARM_NR_cacheflush on ARM-Linux. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
__clear_cache((char*)(from), (char*)(to))
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !SLJIT_CACHE_FLUSH */
|
||||
|
||||
/* 8 bit byte type. */
|
||||
typedef unsigned char sljit_ub;
|
||||
typedef signed char sljit_b;
|
||||
|
||||
/* 16 bit half-word type. */
|
||||
typedef unsigned short int sljit_uh;
|
||||
typedef signed short int sljit_h;
|
||||
|
||||
/* 32 bit integer type. */
|
||||
typedef unsigned int sljit_ui;
|
||||
typedef signed int sljit_i;
|
||||
|
||||
/* Machine word type. Can encapsulate a pointer.
|
||||
32 bit for 32 bit machines.
|
||||
64 bit for 64 bit machines. */
|
||||
#if !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define SLJIT_32BIT_ARCHITECTURE 1
|
||||
#define SLJIT_WORD_SHIFT 2
|
||||
typedef unsigned int sljit_uw;
|
||||
typedef int sljit_w;
|
||||
#else
|
||||
#define SLJIT_64BIT_ARCHITECTURE 1
|
||||
#define SLJIT_WORD_SHIFT 3
|
||||
#ifdef _WIN32
|
||||
typedef unsigned __int64 sljit_uw;
|
||||
typedef __int64 sljit_w;
|
||||
#else
|
||||
typedef unsigned long int sljit_uw;
|
||||
typedef long int sljit_w;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Double precision. */
|
||||
#define SLJIT_FLOAT_SHIFT 3
|
||||
|
||||
#ifndef SLJIT_W
|
||||
|
||||
/* Defining long constants. */
|
||||
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
||||
#define SLJIT_W(w) (w##ll)
|
||||
#else
|
||||
#define SLJIT_W(w) (w)
|
||||
#endif
|
||||
|
||||
#endif /* !SLJIT_W */
|
||||
|
||||
#ifndef SLJIT_CALL
|
||||
|
||||
/* ABI (Application Binary Interface) types. */
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
|
||||
#if defined(__GNUC__)
|
||||
|
||||
#define SLJIT_CALL __attribute__ ((fastcall))
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#define SLJIT_CALL __msfastcall
|
||||
#else /* __BORLANDC__ */
|
||||
#define SLJIT_CALL __fastcall
|
||||
#endif /* __BORLANDC__ */
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#else /* defined(_WIN32) */
|
||||
#define SLJIT_CALL __stdcall
|
||||
#endif
|
||||
|
||||
#else /* Other architectures. */
|
||||
|
||||
#define SLJIT_CALL
|
||||
|
||||
#endif /* SLJIT_CONFIG_X86_32 */
|
||||
|
||||
#endif /* !SLJIT_CALL */
|
||||
|
||||
#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
|
||||
|
||||
/* These macros are useful for the application. */
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
|
||||
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
|
||||
#ifdef __MIPSEL__
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#endif /* !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) */
|
||||
|
||||
/* Sanity check. */
|
||||
#if (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
|
||||
#error "Exactly one endianness must be selected"
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && !(defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
|
||||
#error "Exactly one endianness must be selected"
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
/* It seems ppc64 compilers use an indirect addressing for functions.
|
||||
It makes things really complicated. */
|
||||
#define SLJIT_INDIRECT_CALL 1
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_SSE2
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
/* Turn on SSE2 support on x86 (operating on doubles).
|
||||
(Better performance than legacy fpu instructions). */
|
||||
#define SLJIT_SSE2 1
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
/* Auto detect SSE2 support using CPUID.
|
||||
On 64 bit x86 cpus, sse2 must be present. */
|
||||
#define SLJIT_SSE2_AUTO 1
|
||||
#endif
|
||||
|
||||
#endif /* (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) */
|
||||
|
||||
#endif /* !SLJIT_SSE2 */
|
||||
|
||||
#ifndef SLJIT_UNALIGNED
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
|| (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|
||||
|| (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|
||||
|| (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define SLJIT_UNALIGNED 1
|
||||
#endif
|
||||
|
||||
#endif /* !SLJIT_UNALIGNED */
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
|
||||
#define SLJIT_MALLOC_EXEC(size) sljit_malloc_exec(size)
|
||||
#define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr)
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG) || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
|
||||
/* Feel free to redefine these two macros. */
|
||||
#ifndef SLJIT_ASSERT
|
||||
|
||||
#define SLJIT_HALT_PROCESS() \
|
||||
*((int*)0) = 0
|
||||
|
||||
#define SLJIT_ASSERT(x) \
|
||||
do { \
|
||||
if (SLJIT_UNLIKELY(!(x))) { \
|
||||
printf("Assertion failed at " __FILE__ ":%d\n", __LINE__); \
|
||||
SLJIT_HALT_PROCESS(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* !SLJIT_ASSERT */
|
||||
|
||||
#ifndef SLJIT_ASSERT_STOP
|
||||
|
||||
#define SLJIT_ASSERT_STOP() \
|
||||
do { \
|
||||
printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \
|
||||
SLJIT_HALT_PROCESS(); \
|
||||
} while (0)
|
||||
|
||||
#endif /* !SLJIT_ASSERT_STOP */
|
||||
|
||||
#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
|
||||
|
||||
#undef SLJIT_ASSERT
|
||||
#undef SLJIT_ASSERT_STOP
|
||||
|
||||
#define SLJIT_ASSERT(x) \
|
||||
do { } while (0)
|
||||
#define SLJIT_ASSERT_STOP() \
|
||||
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)
|
||||
|
||||
#endif /* !SLJIT_COMPILE_ASSERT */
|
||||
|
||||
#endif
|
||||
274
harbour/src/3rd/pcre/sjexeca.c
Normal file
274
harbour/src/3rd/pcre/sjexeca.c
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 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:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
This file contains a simple executable memory allocator
|
||||
|
||||
It is assumed, that executable code blocks are usually medium (or sometimes
|
||||
large) memory blocks, and the allocator is not too frequently called (less
|
||||
optimized than other allocators). Thus, using it as a generic allocator is
|
||||
not suggested.
|
||||
|
||||
How does it work:
|
||||
Memory is allocated in continuous memory areas called chunks by alloc_chunk()
|
||||
Chunk format:
|
||||
[ block ][ block ] ... [ block ][ block terminator ]
|
||||
|
||||
All blocks and the block terminator is started with block_header. The block
|
||||
header contains the size of the previous and the next block. These sizes
|
||||
can also contain special values.
|
||||
Block size:
|
||||
0 - The block is a free_block, with a different size member.
|
||||
1 - The block is a block terminator.
|
||||
n - The block is used at the moment, and the value contains its size.
|
||||
Previous block size:
|
||||
0 - This is the first block of the memory chunk.
|
||||
n - The size of the previous block.
|
||||
|
||||
Using these size values we can go forward or backward on the block chain.
|
||||
The unused blocks are stored in a chain list pointed by free_blocks. This
|
||||
list is useful if we need to find a suitable memory area when the allocator
|
||||
is called.
|
||||
|
||||
When a block is freed, the new free block is connected to its adjacent free
|
||||
blocks if possible.
|
||||
|
||||
[ free block ][ used block ][ free block ]
|
||||
and "used block" is freed, the three blocks are connected together:
|
||||
[ one big free block ]
|
||||
*/
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* System (OS) functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* 64 KByte. */
|
||||
#define CHUNK_SIZE 0x10000
|
||||
|
||||
/*
|
||||
alloc_chunk / free_chunk :
|
||||
* allocate executable system memory chunks
|
||||
* the size is always divisible by CHUNK_SIZE
|
||||
allocator_grab_lock / allocator_release_lock :
|
||||
* make the allocator thread safe
|
||||
* can be empty if the OS (or the application) does not support threading
|
||||
* only the allocator requires this lock, sljit is fully thread safe
|
||||
as it only uses local variables
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(size);
|
||||
VirtualFree(chunk, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
void* retval = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
return (retval != MAP_FAILED) ? retval : NULL;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
|
||||
{
|
||||
munmap(chunk, size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Common functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#define CHUNK_MASK (~(CHUNK_SIZE - 1))
|
||||
|
||||
struct block_header {
|
||||
sljit_uw size;
|
||||
sljit_uw prev_size;
|
||||
};
|
||||
|
||||
struct free_block {
|
||||
struct block_header header;
|
||||
struct free_block *next;
|
||||
struct free_block *prev;
|
||||
sljit_uw size;
|
||||
};
|
||||
|
||||
#define AS_BLOCK_HEADER(base, offset) \
|
||||
((struct block_header*)(((sljit_ub*)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)))
|
||||
#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7) & ~7)
|
||||
|
||||
static struct free_block* free_blocks;
|
||||
static sljit_uw allocated_size;
|
||||
static sljit_uw total_size;
|
||||
|
||||
static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)
|
||||
{
|
||||
free_block->header.size = 0;
|
||||
free_block->size = size;
|
||||
|
||||
free_block->next = free_blocks;
|
||||
free_block->prev = 0;
|
||||
if (free_blocks)
|
||||
free_blocks->prev = free_block;
|
||||
free_blocks = free_block;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)
|
||||
{
|
||||
if (free_block->next)
|
||||
free_block->next->prev = free_block->prev;
|
||||
|
||||
if (free_block->prev)
|
||||
free_block->prev->next = free_block->next;
|
||||
else {
|
||||
SLJIT_ASSERT(free_blocks == free_block);
|
||||
free_blocks = free_block->next;
|
||||
}
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
|
||||
{
|
||||
struct block_header *header;
|
||||
struct block_header *next_header;
|
||||
struct free_block *free_block;
|
||||
sljit_uw chunk_size;
|
||||
|
||||
allocator_grab_lock();
|
||||
if (size < sizeof(struct free_block))
|
||||
size = sizeof(struct free_block);
|
||||
size = ALIGN_SIZE(size);
|
||||
|
||||
free_block = free_blocks;
|
||||
while (free_block) {
|
||||
if (free_block->size >= size) {
|
||||
chunk_size = free_block->size;
|
||||
if (chunk_size > size + 64) {
|
||||
/* We just cut a block from the end of the free block. */
|
||||
chunk_size -= size;
|
||||
free_block->size = chunk_size;
|
||||
header = AS_BLOCK_HEADER(free_block, chunk_size);
|
||||
header->prev_size = chunk_size;
|
||||
AS_BLOCK_HEADER(header, size)->prev_size = size;
|
||||
}
|
||||
else {
|
||||
sljit_remove_free_block(free_block);
|
||||
header = (struct block_header*)free_block;
|
||||
size = chunk_size;
|
||||
}
|
||||
allocated_size += size;
|
||||
header->size = size;
|
||||
allocator_release_lock();
|
||||
return MEM_START(header);
|
||||
}
|
||||
free_block = free_block->next;
|
||||
}
|
||||
|
||||
chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK;
|
||||
header = (struct block_header*)alloc_chunk(chunk_size);
|
||||
PTR_FAIL_IF(!header);
|
||||
|
||||
chunk_size -= sizeof(struct block_header);
|
||||
total_size += chunk_size;
|
||||
|
||||
header->prev_size = 0;
|
||||
if (chunk_size > size + 64) {
|
||||
/* Cut the allocated space into a free and a used block. */
|
||||
allocated_size += size;
|
||||
header->size = size;
|
||||
chunk_size -= size;
|
||||
|
||||
free_block = AS_FREE_BLOCK(header, size);
|
||||
free_block->header.prev_size = size;
|
||||
sljit_insert_free_block(free_block, chunk_size);
|
||||
next_header = AS_BLOCK_HEADER(free_block, chunk_size);
|
||||
}
|
||||
else {
|
||||
/* All space belongs to this allocation. */
|
||||
allocated_size += chunk_size;
|
||||
header->size = chunk_size;
|
||||
next_header = AS_BLOCK_HEADER(header, chunk_size);
|
||||
}
|
||||
next_header->size = 1;
|
||||
next_header->prev_size = chunk_size;
|
||||
allocator_release_lock();
|
||||
return MEM_START(header);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
|
||||
{
|
||||
struct block_header *header;
|
||||
struct free_block* free_block;
|
||||
|
||||
allocator_grab_lock();
|
||||
header = AS_BLOCK_HEADER(ptr, -(sljit_w)sizeof(struct block_header));
|
||||
allocated_size -= header->size;
|
||||
|
||||
/* Connecting free blocks together if possible. */
|
||||
|
||||
/* If header->prev_size == 0, free_block will equal to header.
|
||||
In this case, free_block->header.size will be > 0. */
|
||||
free_block = AS_FREE_BLOCK(header, -(sljit_w)header->prev_size);
|
||||
if (SLJIT_UNLIKELY(!free_block->header.size)) {
|
||||
free_block->size += header->size;
|
||||
header = AS_BLOCK_HEADER(free_block, free_block->size);
|
||||
header->prev_size = free_block->size;
|
||||
}
|
||||
else {
|
||||
free_block = (struct free_block*)header;
|
||||
sljit_insert_free_block(free_block, header->size);
|
||||
}
|
||||
|
||||
header = AS_BLOCK_HEADER(free_block, free_block->size);
|
||||
if (SLJIT_UNLIKELY(!header->size)) {
|
||||
free_block->size += ((struct free_block*)header)->size;
|
||||
sljit_remove_free_block((struct free_block*)header);
|
||||
header = AS_BLOCK_HEADER(free_block, free_block->size);
|
||||
header->prev_size = free_block->size;
|
||||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {
|
||||
if (total_size - free_block->size > (allocated_size * 3 / 2)) {
|
||||
sljit_remove_free_block(free_block);
|
||||
free_chunk(free_block, free_block->size + sizeof(struct block_header));
|
||||
}
|
||||
}
|
||||
|
||||
allocator_release_lock();
|
||||
}
|
||||
1424
harbour/src/3rd/pcre/sjlir.c
Normal file
1424
harbour/src/3rd/pcre/sjlir.c
Normal file
File diff suppressed because it is too large
Load Diff
756
harbour/src/3rd/pcre/sjlir.h
Normal file
756
harbour/src/3rd/pcre/sjlir.h
Normal file
@@ -0,0 +1,756 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 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:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SLJIT_LIR_H_
|
||||
#define _SLJIT_LIR_H_
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------
|
||||
Stack-Less JIT compiler for multiple architectures (x86, ARM, PowerPC)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Short description
|
||||
Advantages:
|
||||
- The execution can be continued from any LIR instruction
|
||||
In other words, jump into and out of the code is safe
|
||||
- Both target of (conditional) jump and call instructions
|
||||
and constants can be dynamically modified during runtime
|
||||
- although it is not suggested to do it frequently
|
||||
- very effective to cache an important value once
|
||||
- A fixed stack space can be allocated for local variables
|
||||
- The compiler is thread-safe
|
||||
Disadvantages:
|
||||
- Limited number of registers (only 6+4 integer registers, max 3+2
|
||||
temporary and max 3+2 general, and 4 floating point registers)
|
||||
In practice:
|
||||
- This approach is very effective for interpreters
|
||||
- One of the general registers typically points to a stack interface
|
||||
- It can jump to any exception handler anytime (even for another
|
||||
function. It is safe for SLJIT.)
|
||||
- Fast paths can be modified during runtime reflecting the changes
|
||||
of the fastest execution path of the dynamic language
|
||||
- SLJIT supports complex memory addressing modes
|
||||
- mainly position independent code
|
||||
- Optimizations (perhaps later)
|
||||
- Only for basic blocks (when no labels inserted between LIR instructions)
|
||||
|
||||
For valgrind users:
|
||||
- pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code"
|
||||
*/
|
||||
|
||||
#if !(defined SLJIT_NO_DEFAULT_CONFIG && SLJIT_NO_DEFAULT_CONFIG)
|
||||
#include "sjconf.h"
|
||||
#endif
|
||||
#include "sjconfi.h"
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Error codes */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Indicates no error. */
|
||||
#define SLJIT_SUCCESS 0
|
||||
/* After the call of sljit_generate_code(), the error code of the compiler
|
||||
is set to this value to avoid future sljit calls (in debug mode at least).
|
||||
The complier should be freed after sljit_generate_code(). */
|
||||
#define SLJIT_ERR_COMPILED 1
|
||||
/* Cannot allocate non executable memory. */
|
||||
#define SLJIT_ERR_ALLOC_FAILED 2
|
||||
/* Cannot allocate executable memory.
|
||||
Only for sljit_generate_code() */
|
||||
#define SLJIT_ERR_EX_ALLOC_FAILED 3
|
||||
/* return value for SLJIT_CONFIG_UNSUPPORTED empty architecture. */
|
||||
#define SLJIT_ERR_UNSUPPORTED 4
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Registers */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#define SLJIT_UNUSED 0
|
||||
|
||||
/* Temporary (scratch) registers may not preserve their values across function calls. */
|
||||
#define SLJIT_TEMPORARY_REG1 1
|
||||
#define SLJIT_TEMPORARY_REG2 2
|
||||
#define SLJIT_TEMPORARY_REG3 3
|
||||
/* Note: Extra Registers cannot be used for memory addressing. */
|
||||
/* Note: on x86-32, these registers are emulated (using stack loads & stores). */
|
||||
#define SLJIT_TEMPORARY_EREG1 4
|
||||
#define SLJIT_TEMPORARY_EREG2 5
|
||||
|
||||
/* General (saved) registers preserve their values across function calls. */
|
||||
#define SLJIT_GENERAL_REG1 6
|
||||
#define SLJIT_GENERAL_REG2 7
|
||||
#define SLJIT_GENERAL_REG3 8
|
||||
/* Note: Extra Registers cannot be used for memory addressing. */
|
||||
/* Note: on x86-32, these registers are emulated (using stack loads & stores). */
|
||||
#define SLJIT_GENERAL_EREG1 9
|
||||
#define SLJIT_GENERAL_EREG2 10
|
||||
|
||||
/* Read-only register (cannot be the destination of an operation). */
|
||||
/* Note: SLJIT_MEM2( ... , SLJIT_LOCALS_REG) is not supported (x86 limitation). */
|
||||
/* Note: SLJIT_LOCALS_REG is not necessary the real stack pointer. See sljit_emit_enter. */
|
||||
#define SLJIT_LOCALS_REG 11
|
||||
|
||||
/* Number of registers. */
|
||||
#define SLJIT_NO_TMP_REGISTERS 5
|
||||
#define SLJIT_NO_GEN_REGISTERS 5
|
||||
#define SLJIT_NO_REGISTERS 11
|
||||
|
||||
/* Return with machine word. */
|
||||
|
||||
#define SLJIT_RETURN_REG SLJIT_TEMPORARY_REG1
|
||||
|
||||
/* x86 prefers temporary registers for special purposes. If other
|
||||
registers are used such purpose, it costs a little performance
|
||||
drawback. It doesn't matter for other archs. */
|
||||
|
||||
#define SLJIT_PREF_SHIFT_REG SLJIT_TEMPORARY_REG3
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Floating point registers */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Note: SLJIT_UNUSED as destination is not valid for floating point
|
||||
operations, since they cannot be used for setting flags. */
|
||||
|
||||
/* Floating point operations are performed on double precision values. */
|
||||
|
||||
#define SLJIT_FLOAT_REG1 1
|
||||
#define SLJIT_FLOAT_REG2 2
|
||||
#define SLJIT_FLOAT_REG3 3
|
||||
#define SLJIT_FLOAT_REG4 4
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Main structures and functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
struct sljit_memory_fragment {
|
||||
struct sljit_memory_fragment *next;
|
||||
sljit_uw used_size;
|
||||
sljit_ub memory[1];
|
||||
};
|
||||
|
||||
struct sljit_label {
|
||||
struct sljit_label *next;
|
||||
sljit_uw addr;
|
||||
/* The maximum size difference. */
|
||||
sljit_uw size;
|
||||
};
|
||||
|
||||
struct sljit_jump {
|
||||
struct sljit_jump *next;
|
||||
sljit_uw addr;
|
||||
sljit_w flags;
|
||||
union {
|
||||
sljit_uw target;
|
||||
struct sljit_label* label;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct sljit_const {
|
||||
struct sljit_const *next;
|
||||
sljit_uw addr;
|
||||
};
|
||||
|
||||
struct sljit_compiler {
|
||||
int error;
|
||||
|
||||
struct sljit_label *labels;
|
||||
struct sljit_jump *jumps;
|
||||
struct sljit_const *consts;
|
||||
struct sljit_label *last_label;
|
||||
struct sljit_jump *last_jump;
|
||||
struct sljit_const *last_const;
|
||||
|
||||
struct sljit_memory_fragment *buf;
|
||||
struct sljit_memory_fragment *abuf;
|
||||
|
||||
/* Used local registers. */
|
||||
int temporaries;
|
||||
/* Used general registers. */
|
||||
int generals;
|
||||
/* Local stack size. */
|
||||
int local_size;
|
||||
/* Code size. */
|
||||
sljit_uw size;
|
||||
/* For statistical purposes. */
|
||||
sljit_uw executable_size;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
int args;
|
||||
int temporaries_start;
|
||||
int generals_start;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
int mode32;
|
||||
#ifdef _WIN64
|
||||
int has_locals;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
int flags_saved;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
/* Constant pool handling. */
|
||||
sljit_uw *cpool;
|
||||
sljit_ub *cpool_unique;
|
||||
sljit_uw cpool_diff;
|
||||
sljit_uw cpool_fill;
|
||||
/* General fields. */
|
||||
/* Contains pointer, "ldr pc, [...]" pairs. */
|
||||
sljit_uw patches;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||
/* Temporary fields. */
|
||||
sljit_uw shift_imm;
|
||||
int cache_arg;
|
||||
sljit_w cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
||||
int cache_arg;
|
||||
sljit_w cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
int has_locals;
|
||||
sljit_w imm;
|
||||
int cache_arg;
|
||||
sljit_w cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
int has_locals;
|
||||
int delay_slot;
|
||||
int cache_arg;
|
||||
sljit_w cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
FILE* verbose;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
int skip_checks;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Main functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Creates an sljit compiler.
|
||||
Returns NULL if failed. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void);
|
||||
/* Free everything except the codes. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler);
|
||||
|
||||
static SLJIT_INLINE int sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; }
|
||||
|
||||
/*
|
||||
Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit,
|
||||
and <= 128 bytes on 64 bit architectures. The memory area is owned by the compiler,
|
||||
and freed by sljit_free_compiler. The returned pointer is sizeof(sljit_w) aligned.
|
||||
Excellent for allocating small blocks during the compiling, and no need to worry
|
||||
about freeing them. The size is enough to contain at most 16 pointers.
|
||||
If the size is outside of the range, the function will return with NULL,
|
||||
but this return value does not indicate that there is no more memory (does
|
||||
not set the compiler to out-of-memory status).
|
||||
*/
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
/* Passing NULL disables verbose. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose);
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code);
|
||||
|
||||
/*
|
||||
After the code generation we can retrieve the allocated executable memory size,
|
||||
although this area may not be fully filled with instructions depending on some
|
||||
optimizations. This function is useful only for statistical purposes.
|
||||
|
||||
Before a successful code generation, this function returns with 0.
|
||||
*/
|
||||
static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; }
|
||||
|
||||
/* Instruction generation. Returns with error code. */
|
||||
|
||||
/*
|
||||
Entry instruction. The instruction has "args" number of arguments
|
||||
and will use the first "general" number of general registers.
|
||||
The arguments are passed into the general registers (arg1 to general_reg1, and so on).
|
||||
Thus, "args" must be less or equal than "general". A local_size extra
|
||||
stack space is allocated for the jit code (must be less or equal than
|
||||
SLJIT_MAX_LOCAL_SIZE), which can accessed through SLJIT_LOCALS_REG (see
|
||||
the notes there). SLJIT_LOCALS_REG is not necessary the real stack pointer!
|
||||
It just points somewhere in the stack if local_size > 0 (!). Thus, the only
|
||||
thing which is known that the memory area between SLJIT_LOCALS_REG and
|
||||
SLJIT_LOCALS_REG + local_size is a valid stack area if local_size > 0
|
||||
*/
|
||||
|
||||
/* Note: multiple calls of this function overwrites the previous call. */
|
||||
|
||||
#define SLJIT_MAX_LOCAL_SIZE 65536
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size);
|
||||
|
||||
/* Since sljit_emit_return (and many asserts) uses variables which are initialized
|
||||
by sljit_emit_enter, a simple return is not possible if these variables are not
|
||||
initialized. sljit_fake_enter does not emit any instruction, just initialize
|
||||
those variables. */
|
||||
|
||||
/* Note: multiple calls of this function overwrites the previous call. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size);
|
||||
|
||||
/* Return from jit. See below the possible values for src and srcw. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw);
|
||||
|
||||
/* Really fast calling method for utility functions inside sljit (see SLJIT_FAST_CALL).
|
||||
All registers and even the stack frame is passed to the callee. The return address is
|
||||
preserved in dst/dstw by sljit_emit_fast_enter, and sljit_emit_fast_return can
|
||||
use this as a return value later. */
|
||||
|
||||
/* Note: only for sljit specific, non ABI compilant calls. Fast, since only a few machine instructions
|
||||
are needed. Excellent for small uility functions, where saving general registers and setting up
|
||||
a new stack frame would cost too much performance. However, it is still possible to return
|
||||
to the address of the caller (or anywhere else). */
|
||||
|
||||
/* Note: flags are not changed (unlike sljit_emit_enter / sljit_emit_return). */
|
||||
|
||||
/* Note: although sljit_emit_fast_return could be replaced by an ijump, it is not suggested,
|
||||
since many architectures do clever branch prediction on call / return instruction pairs. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int generals, int local_size);
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw);
|
||||
|
||||
/*
|
||||
Source and destination values for arithmetical instructions
|
||||
imm - a simple immediate value (cannot be used as a destination)
|
||||
reg - any of the registers (immediate argument must be 0)
|
||||
[imm] - absolute immediate memory address
|
||||
[reg+imm] - indirect memory address
|
||||
[reg+(reg<<imm)] - indirect indexed memory address (shift must be between 0 and 3)
|
||||
useful for (byte, half, int, sljit_w) array access
|
||||
(fully supported by both x86 and ARM architectures, and cheap operation on others)
|
||||
*/
|
||||
|
||||
/*
|
||||
IMPORATNT NOTE: memory access MUST be naturally aligned.
|
||||
length | alignment
|
||||
---------+-----------
|
||||
byte | 1 byte (not aligned)
|
||||
half | 2 byte (real_address & 0x1 == 0)
|
||||
int | 4 byte (real_address & 0x3 == 0)
|
||||
sljit_w | 4 byte if SLJIT_32BIT_ARCHITECTURE defined
|
||||
| 8 byte if SLJIT_64BIT_ARCHITECTURE defined
|
||||
(This is a strict requirement for embedded systems.)
|
||||
|
||||
Note: different architectures have different addressing limitations
|
||||
Thus sljit may generate several instructions for other addressing modes
|
||||
x86: all addressing modes supported, but write-back is not supported
|
||||
(requires an extra instruction). On x86-64 only 32 bit signed
|
||||
integers are supported by the architecture.
|
||||
arm: [reg+imm] supported for small immediates (-4095 <= imm <= 4095
|
||||
or -255 <= imm <= 255 for loading signed bytes, any halfs or doubles)
|
||||
[reg+(reg<<imm)] are supported or requires only two instructions
|
||||
Write back is limited to small immediates on thumb2
|
||||
ppc: [reg+imm], -65535 <= imm <= 65535. 64 bit moves requires immediates
|
||||
divisible by 4. [reg+reg] supported, write-back supported
|
||||
[reg+(reg<<imm)] (imm != 0) is cheap (requires two instructions)
|
||||
*/
|
||||
|
||||
/* Register output: simply the name of the register.
|
||||
For destination, you can use SLJIT_UNUSED as well. */
|
||||
#define SLJIT_MEM 0x100
|
||||
#define SLJIT_MEM0() (SLJIT_MEM)
|
||||
#define SLJIT_MEM1(r1) (SLJIT_MEM | (r1))
|
||||
#define SLJIT_MEM2(r1, r2) (SLJIT_MEM | (r1) | ((r2) << 4))
|
||||
#define SLJIT_IMM 0x200
|
||||
|
||||
/* Set 32 bit operation mode (I) on 64 bit CPUs. The flag is totally ignored on
|
||||
32 bit CPUs. The arithmetic instruction uses only the lower 32 bit of the
|
||||
input register(s), and set the flags according to the 32 bit result. If the
|
||||
destination is a register, the higher 32 bit of the result is undefined.
|
||||
The addressing modes (SLJIT_MEM1/SLJIT_MEM2 macros) are unaffected by this flag. */
|
||||
#define SLJIT_INT_OP 0x100
|
||||
|
||||
/* Common CPU status flags for all architectures (x86, ARM, PPC)
|
||||
- carry flag
|
||||
- overflow flag
|
||||
- zero flag
|
||||
- negative/positive flag (depends on arc)
|
||||
On mips, these flags are emulated by software. */
|
||||
|
||||
/* By default, the instructions may, or may not set the CPU status flags.
|
||||
Forcing to set or keep status flags can be done with the following flags: */
|
||||
|
||||
/* Note: sljit tries to emit the minimum number of instructions. Using these
|
||||
flags can increase them, so use them wisely to avoid unnecessary code generation. */
|
||||
|
||||
/* Set Equal (Zero) status flag (E). */
|
||||
#define SLJIT_SET_E 0x0200
|
||||
/* Set signed status flag (S). */
|
||||
#define SLJIT_SET_S 0x0400
|
||||
/* Set unsgined status flag (U). */
|
||||
#define SLJIT_SET_U 0x0800
|
||||
/* Set signed overflow flag (O). */
|
||||
#define SLJIT_SET_O 0x1000
|
||||
/* Set carry flag (C).
|
||||
Note: Kinda unsigned overflow, but behaves differently on various cpus. */
|
||||
#define SLJIT_SET_C 0x2000
|
||||
/* Do not modify the flags (K).
|
||||
Note: This flag cannot be combined with any other SLJIT_SET_* flag. */
|
||||
#define SLJIT_KEEP_FLAGS 0x4000
|
||||
|
||||
/* Notes:
|
||||
- you cannot postpone conditional jump instructions except if noted that
|
||||
the instruction does not set flags (See: SLJIT_KEEP_FLAGS).
|
||||
- flag combinations: '|' means 'logical or'. */
|
||||
|
||||
/* Flags: - (never set any flags)
|
||||
Note: breakpoint instruction is not supported by all architectures (namely ppc)
|
||||
It falls back to SLJIT_NOP in those cases. */
|
||||
#define SLJIT_BREAKPOINT 0
|
||||
/* Flags: - (never set any flags)
|
||||
Note: may or may not cause an extra cycle wait
|
||||
it can even decrease the runtime in a few cases. */
|
||||
#define SLJIT_NOP 1
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op);
|
||||
|
||||
/* Notes for MOV instructions:
|
||||
U = Mov with update (post form). If source or destination defined as SLJIT_MEM1(r1)
|
||||
or SLJIT_MEM2(r1, r2), r1 is increased by the sum of r2 and the constant argument
|
||||
UB = unsigned byte (8 bit)
|
||||
SB = signed byte (8 bit)
|
||||
UH = unsgined half (16 bit)
|
||||
SH = unsgined half (16 bit) */
|
||||
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV 2
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_UB 3
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_SB 4
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_UH 5
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_SH 6
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_UI 7
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOV_SI 8
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU 9
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_UB 10
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_SB 11
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_UH 12
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_SH 13
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_UI 14
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_MOVU_SI 15
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_NOT 16
|
||||
/* Flags: I | E | O | K */
|
||||
#define SLJIT_NEG 17
|
||||
/* Count leading zeroes
|
||||
Flags: I | E | K */
|
||||
#define SLJIT_CLZ 18
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src, sljit_w srcw);
|
||||
|
||||
/* Flags: I | E | O | C | K */
|
||||
#define SLJIT_ADD 19
|
||||
/* Flags: I | C | K */
|
||||
#define SLJIT_ADDC 20
|
||||
/* Flags: I | E | S | U | O | C | K */
|
||||
#define SLJIT_SUB 21
|
||||
/* Flags: I | C | K */
|
||||
#define SLJIT_SUBC 22
|
||||
/* Note: integer mul */
|
||||
/* Flags: I | O (see SLJIT_C_MUL_*) | K */
|
||||
#define SLJIT_MUL 23
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_AND 24
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_OR 25
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_XOR 26
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_SHL 27
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_LSHR 28
|
||||
/* Flags: I | E | K */
|
||||
#define SLJIT_ASHR 29
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w);
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void);
|
||||
|
||||
/* Note: dst is the left and src is the right operand for SLJIT_FCMP.
|
||||
Note: NaN check is always performed. If SLJIT_C_FLOAT_NAN is set,
|
||||
the comparison result is unpredictable.
|
||||
Flags: E | S (see SLJIT_C_FLOAT_*) */
|
||||
#define SLJIT_FCMP 30
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FMOV 31
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FNEG 32
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FABS 33
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src, sljit_w srcw);
|
||||
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FADD 34
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FSUB 35
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FMUL 36
|
||||
/* Flags: - (never set any flags) */
|
||||
#define SLJIT_FDIV 37
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
|
||||
int dst, sljit_w dstw,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w);
|
||||
|
||||
/* Label and jump instructions. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler);
|
||||
|
||||
/* Invert conditional instruction: xor (^) with 0x1 */
|
||||
#define SLJIT_C_EQUAL 0
|
||||
#define SLJIT_C_ZERO 0
|
||||
#define SLJIT_C_NOT_EQUAL 1
|
||||
#define SLJIT_C_NOT_ZERO 1
|
||||
|
||||
#define SLJIT_C_LESS 2
|
||||
#define SLJIT_C_GREATER_EQUAL 3
|
||||
#define SLJIT_C_GREATER 4
|
||||
#define SLJIT_C_LESS_EQUAL 5
|
||||
#define SLJIT_C_SIG_LESS 6
|
||||
#define SLJIT_C_SIG_GREATER_EQUAL 7
|
||||
#define SLJIT_C_SIG_GREATER 8
|
||||
#define SLJIT_C_SIG_LESS_EQUAL 9
|
||||
|
||||
#define SLJIT_C_OVERFLOW 10
|
||||
#define SLJIT_C_NOT_OVERFLOW 11
|
||||
|
||||
#define SLJIT_C_MUL_OVERFLOW 12
|
||||
#define SLJIT_C_MUL_NOT_OVERFLOW 13
|
||||
|
||||
#define SLJIT_C_FLOAT_EQUAL 14
|
||||
#define SLJIT_C_FLOAT_NOT_EQUAL 15
|
||||
#define SLJIT_C_FLOAT_LESS 16
|
||||
#define SLJIT_C_FLOAT_GREATER_EQUAL 17
|
||||
#define SLJIT_C_FLOAT_GREATER 18
|
||||
#define SLJIT_C_FLOAT_LESS_EQUAL 19
|
||||
#define SLJIT_C_FLOAT_NAN 20
|
||||
#define SLJIT_C_FLOAT_NOT_NAN 21
|
||||
|
||||
#define SLJIT_JUMP 22
|
||||
#define SLJIT_FAST_CALL 23
|
||||
#define SLJIT_CALL0 24
|
||||
#define SLJIT_CALL1 25
|
||||
#define SLJIT_CALL2 26
|
||||
#define SLJIT_CALL3 27
|
||||
|
||||
/* Fast calling method. See sljit_emit_fast_enter / sljit_emit_fast_return. */
|
||||
|
||||
/* The target can be changed during runtime (see: sljit_set_jump_addr). */
|
||||
#define SLJIT_REWRITABLE_JUMP 0x1000
|
||||
|
||||
/* Emit a jump instruction. The destination is not set, only the type of the jump.
|
||||
type must be between SLJIT_C_EQUAL and SLJIT_CALL3
|
||||
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
|
||||
Flags: - (never set any flags) for both conditional and unconditional jumps.
|
||||
Flags: destroy all flags for calls. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type);
|
||||
|
||||
/* Basic arithmetic comparison. In most architectures it is equal to
|
||||
an SLJIT_SUB operation (with SLJIT_UNUSED destination) followed by a
|
||||
sljit_emit_jump. However some architectures (i.e: MIPS) may employ
|
||||
special optimizations here. It is suggested to use this comparison
|
||||
form when flags are unimportant.
|
||||
type must be between SLJIT_C_EQUAL and SLJIT_C_SIG_LESS_EQUAL
|
||||
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP or SLJIT_INT_OP
|
||||
Flags: destroy flags. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type,
|
||||
int src1, sljit_w src1w,
|
||||
int src2, sljit_w src2w);
|
||||
|
||||
/* Set the destination of the jump to this label. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label);
|
||||
/* Only for jumps defined with SLJIT_REWRITABLE_JUMP flag.
|
||||
Note: use sljit_emit_ijump for fixed jumps. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target);
|
||||
|
||||
/* Call function or jump anywhere. Both direct and indirect form
|
||||
type must be between SLJIT_JUMP and SLJIT_CALL3
|
||||
Direct form: set src to SLJIT_IMM() and srcw to the address
|
||||
Indirect form: any other valid addressing mode
|
||||
Flags: - (never set any flags) for unconditional jumps.
|
||||
Flags: destroy all flags for calls. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw);
|
||||
|
||||
/* If op == SLJIT_MOV:
|
||||
Set dst to 1 if condition is fulfilled, 0 otherwise
|
||||
type must be between SLJIT_C_EQUAL and SLJIT_C_FLOAT_NOT_NAN
|
||||
Flags: - (never set any flags)
|
||||
If op == SLJIT_OR
|
||||
Dst is used as src as well, and set its lowest bit to 1 if
|
||||
the condition is fulfilled. Otherwise it does nothing.
|
||||
Flags: E | K
|
||||
Note: sljit_emit_cond_value does nothing, if dst is SLJIT_UNUSED (regardless of op). */
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type);
|
||||
|
||||
/* The constant can be changed runtime (see: sljit_set_const)
|
||||
Flags: - (never set any flags) */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value);
|
||||
|
||||
/* After the code generation the address for label, jump and const instructions
|
||||
are computed. Since these structures are freed sljit_free_compiler, the
|
||||
addresses must be preserved by the user program elsewere. */
|
||||
static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->addr; }
|
||||
static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; }
|
||||
static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { return const_->addr; }
|
||||
|
||||
/* Only the address is required to rewrite the code. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant);
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Miscellaneous utility functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#define SLJIT_MAJOR_VERSION 0
|
||||
#define SLJIT_MINOR_VERSION 82
|
||||
|
||||
/* Get the human readable name of the platfrom.
|
||||
Can be useful for debugging on platforms like ARM, where ARM and
|
||||
Thumb2 functions can be mixed. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void);
|
||||
|
||||
/* Portble helper function to get an offset of a member. */
|
||||
#define SLJIT_OFFSETOF(base, member) ((sljit_w)(&((base*)0x10)->member) - 0x10)
|
||||
|
||||
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
/* This global lock is useful to compile common functions. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void);
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
|
||||
|
||||
/* The sljit_stack is a utiliy feature of sljit, which allocates a
|
||||
writable memory region between base (inclusive) and limit (exclusive).
|
||||
Both base and limit is a pointer, and base is always <= than limit.
|
||||
This feature uses the "address space reserve" feature
|
||||
of modern operating systems. Basically we don't need to allocate a
|
||||
huge memory block in one step for the worst case, we can start with
|
||||
a smaller chunk and extend it later. Since the address space is
|
||||
reserved, the data never copied to other regions, thus it is safe
|
||||
to store pointers here. */
|
||||
|
||||
/* Note: The base field is aligned to PAGE_SIZE bytes (usually 4k or more).
|
||||
Note: stack growing should not happen in small steps: 4k, 16k or even
|
||||
bigger growth is better.
|
||||
Note: this structure may not be supported by all operating systems.
|
||||
Some kind of fallback mechanism is suggested when SLJIT_UTIL_STACK
|
||||
is not defined. */
|
||||
|
||||
struct sljit_stack {
|
||||
/* User data, anything can be stored here.
|
||||
Starting with the same value as base. */
|
||||
sljit_uw top;
|
||||
/* These members are read only. */
|
||||
sljit_uw base;
|
||||
sljit_uw limit;
|
||||
sljit_uw max_limit;
|
||||
};
|
||||
|
||||
/* Returns NULL if unsuccessful.
|
||||
Note: limit and max_limit contains the size for stack allocation
|
||||
Note: the top field is initialized to base. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* stack);
|
||||
|
||||
/* Can be used to increase (allocate) or decrease (free) the memory area.
|
||||
Returns with a non-zero value if unsuccessful. If new_limit is greater than
|
||||
max_limit, it will fail. It is very easy to implement a stack data structure,
|
||||
since the growth ratio can be added to the current limit, and sljit_stack_resize
|
||||
will do all the necessary checks. The fields of the stack are not changed if
|
||||
sljit_stack_resize fails. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit);
|
||||
|
||||
#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */
|
||||
|
||||
#if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
|
||||
|
||||
/* Get the entry address of a given function. */
|
||||
#define SLJIT_FUNC_OFFSET(func_name) ((sljit_w)func_name)
|
||||
|
||||
#else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
|
||||
|
||||
/* All JIT related code should be placed in the same context (library, binary, etc.). */
|
||||
|
||||
#define SLJIT_FUNC_OFFSET(func_name) ((sljit_w)*(void**)func_name)
|
||||
|
||||
/* For powerpc64, the function pointers point to a context descriptor. */
|
||||
struct sljit_function_context {
|
||||
sljit_w addr;
|
||||
sljit_w r2;
|
||||
sljit_w r11;
|
||||
};
|
||||
|
||||
/* Fill the context arguments using the addr and the function.
|
||||
If func_ptr is NULL, it will not be set to the address of context
|
||||
If addr is NULL, the function address also comes from the func pointer. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_w addr, void* func);
|
||||
|
||||
#endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
|
||||
|
||||
#endif /* _SLJIT_LIR_H_ */
|
||||
405
harbour/src/3rd/pcre/sjmips32.c
Normal file
405
harbour/src/3rd/pcre/sjmips32.c
Normal file
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 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:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* mips 32-bit arch dependent functions. */
|
||||
|
||||
static int load_immediate(struct sljit_compiler *compiler, int dst_ar, sljit_w imm)
|
||||
{
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
||||
if (imm < 0 && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#define EMIT_LOGICAL(op_imm, op_norm) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
|
||||
} \
|
||||
else { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
#define EMIT_SHIFT(op_imm, op_norm) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
|
||||
} \
|
||||
else { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
|
||||
int dst, int src1, sljit_w src2)
|
||||
{
|
||||
int overflow_ra = 0;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_ADD:
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
FAIL_IF(push_inst(compiler, SRL | T(src1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
|
||||
if (src2 < 0)
|
||||
FAIL_IF(push_inst(compiler, XORI | SA(TMP_EREG1) | TA(TMP_EREG1) | IMM(1), TMP_EREG1));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
if (op & SLJIT_SET_C) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_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));
|
||||
}
|
||||
}
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
if (op & SLJIT_SET_O) {
|
||||
FAIL_IF(push_inst(compiler, SRL | T(dst) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
if (src2 < 0)
|
||||
FAIL_IF(push_inst(compiler, XORI | SA(OVERFLOW_FLAG) | TA(OVERFLOW_FLAG) | IMM(1), OVERFLOW_FLAG));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O) {
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(TMP_EREG1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
|
||||
if (src1 != dst)
|
||||
overflow_ra = DR(src1);
|
||||
else if (src2 != dst)
|
||||
overflow_ra = DR(src2);
|
||||
else {
|
||||
/* Rare ocasion. */
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
|
||||
overflow_ra = TMP_EREG2;
|
||||
}
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
if (op & SLJIT_SET_O) {
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(overflow_ra) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
}
|
||||
}
|
||||
|
||||
/* a + b >= a | b (otherwise, the carry should be set to 1). */
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (op & SLJIT_SET_O)
|
||||
return push_inst(compiler, MOVN | SA(0) | TA(TMP_EREG1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
|
||||
else {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
}
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
} else {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
if (!(op & SLJIT_SET_C))
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
/* Set TMP_EREG2 (dst == 0) && (ULESS_FLAG == 1). */
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(TMP_EREG2) | IMM(1), TMP_EREG2));
|
||||
FAIL_IF(push_inst(compiler, AND | SA(TMP_EREG2) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2));
|
||||
/* Set carry flag. */
|
||||
return push_inst(compiler, OR | SA(TMP_EREG2) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG);
|
||||
|
||||
case SLJIT_SUB:
|
||||
if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_S | SLJIT_SET_U)) || 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;
|
||||
}
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
FAIL_IF(push_inst(compiler, SRL | T(src1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
|
||||
if (src2 < 0)
|
||||
FAIL_IF(push_inst(compiler, XORI | SA(TMP_EREG1) | TA(TMP_EREG1) | IMM(1), TMP_EREG1));
|
||||
if (src1 != dst)
|
||||
overflow_ra = DR(src1);
|
||||
else {
|
||||
/* Rare ocasion. */
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
|
||||
overflow_ra = TMP_EREG2;
|
||||
}
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
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(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(TMP_EREG1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
|
||||
if (src1 != dst)
|
||||
overflow_ra = DR(src1);
|
||||
else {
|
||||
/* Rare ocasion. */
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
|
||||
overflow_ra = TMP_EREG2;
|
||||
}
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_U | SLJIT_SET_C))
|
||||
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));
|
||||
}
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
if (op & SLJIT_SET_O) {
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(overflow_ra) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, MOVZ | SA(0) | TA(TMP_EREG1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_SUBC:
|
||||
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;
|
||||
}
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(-src2), TMP_EREG1));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
/* 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, MOVZ | SA(ULESS_FLAG) | T(dst) | DA(TMP_EREG1), TMP_EREG1));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, ADDU | SA(TMP_EREG1) | TA(0) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MUL:
|
||||
SLJIT_ASSERT(!(flags & SRC2_IMM));
|
||||
if (!(op & SLJIT_SET_O)) {
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
|
||||
return push_inst(compiler, MFLO | D(dst), DR(dst));
|
||||
#endif
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, MFHI | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(TMP_EREG2) | SH_IMM(31), TMP_EREG2));
|
||||
return push_inst(compiler, SUBU | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_AND:
|
||||
EMIT_LOGICAL(ANDI, AND);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_OR:
|
||||
EMIT_LOGICAL(ORI, OR);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_XOR:
|
||||
EMIT_LOGICAL(XORI, XOR);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_SHL:
|
||||
EMIT_SHIFT(SLL, SLLV);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_LSHR:
|
||||
EMIT_SHIFT(SRL, SRLV);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_ASHR:
|
||||
EMIT_SHIFT(SRA, SRAV);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
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:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB) {
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
|
||||
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
|
||||
#endif
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH) {
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
|
||||
#endif
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
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_32_64 && SLJIT_MIPS_32_64)
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
|
||||
#else
|
||||
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
|
||||
FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
|
||||
return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
|
||||
}
|
||||
/* Nearly all instructions are unmovable in the following sequence. */
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
/* Check zero. */
|
||||
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(6), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
|
||||
/* Check sign bit. */
|
||||
FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG1) | IMM(4), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(0), UNMOVABLE_INS));
|
||||
/* Loop for searching the highest bit. */
|
||||
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(dst) | T(dst) | IMM(1), UNMOVABLE_INS));
|
||||
if (op & SLJIT_SET_E)
|
||||
return push_inst(compiler, ADDU_W | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, LUI | T(reg) | IMM(init_value >> 16), DR(reg)));
|
||||
return push_inst(compiler, ORI | S(reg) | T(reg) | IMM(init_value), DR(reg));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
1726
harbour/src/3rd/pcre/sjmipsc.c
Normal file
1726
harbour/src/3rd/pcre/sjmipsc.c
Normal file
File diff suppressed because it is too large
Load Diff
246
harbour/src/3rd/pcre/sjppc32.c
Normal file
246
harbour/src/3rd/pcre/sjppc32.c
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 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:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* ppc 32-bit arch dependent functions. */
|
||||
|
||||
static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
|
||||
{
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#define INS_CLEAR_LEFT(dst, src, from) \
|
||||
(RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1))
|
||||
|
||||
static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
|
||||
int dst, int src1, int src2)
|
||||
{
|
||||
switch (op) {
|
||||
case SLJIT_ADD:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
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));
|
||||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | S(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) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM4)
|
||||
return push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2));
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
if (flags & ALT_FORM5)
|
||||
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));
|
||||
|
||||
case SLJIT_SUBC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | S(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:
|
||||
if (flags & ALT_FORM1) {
|
||||
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));
|
||||
|
||||
case SLJIT_AND:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_OR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm)));
|
||||
return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
|
||||
}
|
||||
return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_XOR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm)));
|
||||
return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
|
||||
}
|
||||
return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_SHL:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
compiler->imm &= 0x1f;
|
||||
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));
|
||||
}
|
||||
return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_LSHR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
compiler->imm &= 0x1f;
|
||||
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));
|
||||
}
|
||||
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_ASHR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
compiler->imm &= 0x1f;
|
||||
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
|
||||
}
|
||||
return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
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:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB)
|
||||
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)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH)
|
||||
return push_inst(compiler, EXTSH | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_NEG:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w 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_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
415
harbour/src/3rd/pcre/sjppc64.c
Normal file
415
harbour/src/3rd/pcre/sjppc64.c
Normal file
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 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:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* ppc 64-bit arch dependent functions. */
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define ASM_SLJIT_CLZ(src, dst) \
|
||||
asm volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
|
||||
#else
|
||||
#error "Must implement count leading zeroes"
|
||||
#endif
|
||||
|
||||
#define RLDI(dst, src, sh, mb, type) \
|
||||
(HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20))
|
||||
|
||||
#define PUSH_RLDICR(reg, shift) \
|
||||
push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))
|
||||
|
||||
static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
|
||||
{
|
||||
sljit_uw tmp;
|
||||
sljit_uw shift;
|
||||
sljit_uw tmp2;
|
||||
sljit_uw shift2;
|
||||
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
|
||||
|
||||
if (imm <= SLJIT_W(0x7fffffff) && imm >= SLJIT_W(-0x80000000)) {
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Count leading zeroes. */
|
||||
tmp = (imm >= 0) ? imm : ~imm;
|
||||
ASM_SLJIT_CLZ(tmp, shift);
|
||||
SLJIT_ASSERT(shift > 0);
|
||||
shift--;
|
||||
tmp = (imm << shift);
|
||||
|
||||
if ((tmp & ~0xffff000000000000ul) == 0) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
|
||||
shift += 15;
|
||||
return PUSH_RLDICR(reg, shift);
|
||||
}
|
||||
|
||||
if ((tmp & ~0xffffffff00000000ul) == 0) {
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(tmp >> 48)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32)));
|
||||
shift += 31;
|
||||
return PUSH_RLDICR(reg, shift);
|
||||
}
|
||||
|
||||
/* Cut out the 16 bit from immediate. */
|
||||
shift += 15;
|
||||
tmp2 = imm & ((1ul << (63 - shift)) - 1);
|
||||
|
||||
if (tmp2 <= 0xffff) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
|
||||
FAIL_IF(PUSH_RLDICR(reg, shift));
|
||||
return push_inst(compiler, ORI | S(reg) | A(reg) | tmp2);
|
||||
}
|
||||
|
||||
if (tmp2 <= 0xffffffff) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
|
||||
FAIL_IF(PUSH_RLDICR(reg, shift));
|
||||
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (tmp2 >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
ASM_SLJIT_CLZ(tmp2, shift2);
|
||||
tmp2 <<= shift2;
|
||||
|
||||
if ((tmp2 & ~0xffff000000000000ul) == 0) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
|
||||
shift2 += 15;
|
||||
shift += (63 - shift2);
|
||||
FAIL_IF(PUSH_RLDICR(reg, shift));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (tmp2 >> 48)));
|
||||
return PUSH_RLDICR(reg, shift2);
|
||||
}
|
||||
|
||||
/* The general version. */
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 48)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32)));
|
||||
FAIL_IF(PUSH_RLDICR(reg, 31));
|
||||
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16)));
|
||||
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm));
|
||||
}
|
||||
|
||||
/* Simplified mnemonics: clrldi. */
|
||||
#define INS_CLEAR_LEFT(dst, src, from) \
|
||||
(RLDICL | S(src) | A(dst) | ((from) << 6) | (1 << 5))
|
||||
|
||||
/* Sign extension for integer operations. */
|
||||
#define UN_EXTS() \
|
||||
if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
|
||||
src2 = TMP_REG2; \
|
||||
}
|
||||
|
||||
#define BIN_EXTS() \
|
||||
if (flags & ALT_SIGN_EXT) { \
|
||||
if (flags & REG1_SOURCE) { \
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
|
||||
src1 = TMP_REG1; \
|
||||
} \
|
||||
if (flags & REG2_SOURCE) { \
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
|
||||
src2 = TMP_REG2; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define BIN_IMM_EXTS() \
|
||||
if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
|
||||
src1 = TMP_REG1; \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
|
||||
int dst, int src1, int src2)
|
||||
{
|
||||
switch (op) {
|
||||
case SLJIT_ADD:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags 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_FORM2) {
|
||||
/* Flags not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
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_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));
|
||||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | S(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) {
|
||||
/* Flags 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) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, CMPLI | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM4)
|
||||
return push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
BIN_EXTS();
|
||||
if (flags & ALT_FORM5)
|
||||
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));
|
||||
|
||||
case SLJIT_SUBC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | S(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));
|
||||
|
||||
case SLJIT_MUL:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
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));
|
||||
|
||||
case SLJIT_AND:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_OR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm)));
|
||||
return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
|
||||
}
|
||||
return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_XOR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm)));
|
||||
return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
|
||||
}
|
||||
return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_SHL:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
if (flags & ALT_FORM2) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
if (flags & ALT_FORM2)
|
||||
return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
return push_inst(compiler, SLD | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_LSHR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
if (flags & ALT_FORM2) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
if (flags & ALT_FORM2)
|
||||
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
return push_inst(compiler, SRD | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_ASHR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
if (flags & ALT_FORM2) {
|
||||
compiler->imm &= 0x1f;
|
||||
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
|
||||
}
|
||||
else {
|
||||
compiler->imm &= 0x3f;
|
||||
return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4));
|
||||
}
|
||||
}
|
||||
if (flags & ALT_FORM2)
|
||||
return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
return push_inst(compiler, SRAD | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_MOV:
|
||||
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_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SI)
|
||||
return push_inst(compiler, EXTSW | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB)
|
||||
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)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH)
|
||||
return push_inst(compiler, EXTSH | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
UN_EXTS();
|
||||
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_NEG:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
UN_EXTS();
|
||||
return push_inst(compiler, NEG | OERC(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));
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w 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)));
|
||||
FAIL_IF(PUSH_RLDICR(reg, 31));
|
||||
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | 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_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);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 5);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
|
||||
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);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 5);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_w addr, void* func)
|
||||
{
|
||||
sljit_w* ptrs;
|
||||
if (func_ptr)
|
||||
*func_ptr = (void*)context;
|
||||
ptrs = (sljit_w*)func;
|
||||
context->addr = addr ? addr : ptrs[0];
|
||||
context->r2 = ptrs[1];
|
||||
context->r11 = ptrs[2];
|
||||
}
|
||||
1797
harbour/src/3rd/pcre/sjppcc.c
Normal file
1797
harbour/src/3rd/pcre/sjppcc.c
Normal file
File diff suppressed because it is too large
Load Diff
244
harbour/src/3rd/pcre/sjutils.c
Normal file
244
harbour/src/3rd/pcre/sjutils.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 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:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Locks */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) || (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
|
||||
static HANDLE allocator_mutex = 0;
|
||||
|
||||
static SLJIT_INLINE void allocator_grab_lock(void)
|
||||
{
|
||||
/* No idea what to do if an error occures. Static mutexes should never fail... */
|
||||
if (!allocator_mutex)
|
||||
allocator_mutex = CreateMutex(NULL, TRUE, NULL);
|
||||
else
|
||||
WaitForSingleObject(allocator_mutex, INFINITE);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void allocator_release_lock(void)
|
||||
{
|
||||
ReleaseMutex(allocator_mutex);
|
||||
}
|
||||
|
||||
#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
|
||||
static HANDLE global_mutex = 0;
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
|
||||
{
|
||||
/* No idea what to do if an error occures. Static mutexes should never fail... */
|
||||
if (!global_mutex)
|
||||
global_mutex = CreateMutex(NULL, TRUE, NULL);
|
||||
else
|
||||
WaitForSingleObject(global_mutex, INFINITE);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
|
||||
{
|
||||
ReleaseMutex(global_mutex);
|
||||
}
|
||||
|
||||
#endif /* SLJIT_UTIL_GLOBAL_LOCK */
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
#include "pthread.h"
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
|
||||
static pthread_mutex_t allocator_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static SLJIT_INLINE void allocator_grab_lock(void)
|
||||
{
|
||||
pthread_mutex_lock(&allocator_mutex);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void allocator_release_lock(void)
|
||||
{
|
||||
pthread_mutex_unlock(&allocator_mutex);
|
||||
}
|
||||
|
||||
#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
|
||||
static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
|
||||
{
|
||||
pthread_mutex_lock(&global_mutex);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
|
||||
{
|
||||
pthread_mutex_unlock(&global_mutex);
|
||||
}
|
||||
|
||||
#endif /* SLJIT_UTIL_GLOBAL_LOCK */
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Stack */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "windows.h"
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* Planning to make it even more clever in the future. */
|
||||
static sljit_w sljit_page_align = 0;
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit)
|
||||
{
|
||||
struct sljit_stack *stack;
|
||||
union {
|
||||
void *ptr;
|
||||
sljit_uw uw;
|
||||
} base;
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO si;
|
||||
#endif
|
||||
|
||||
if (limit > max_limit || limit < 1)
|
||||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!sljit_page_align) {
|
||||
GetSystemInfo(&si);
|
||||
sljit_page_align = si.dwPageSize - 1;
|
||||
}
|
||||
#else
|
||||
if (!sljit_page_align) {
|
||||
sljit_page_align = sysconf(_SC_PAGESIZE);
|
||||
/* Should never happen. */
|
||||
if (sljit_page_align < 0)
|
||||
sljit_page_align = 4096;
|
||||
sljit_page_align--;
|
||||
}
|
||||
#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));
|
||||
if (!stack)
|
||||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
base.ptr = VirtualAlloc(0, max_limit, MEM_RESERVE, PAGE_READWRITE);
|
||||
if (!base.ptr) {
|
||||
SLJIT_FREE(stack);
|
||||
return NULL;
|
||||
}
|
||||
stack->base = base.uw;
|
||||
stack->limit = stack->base;
|
||||
stack->max_limit = stack->base + max_limit;
|
||||
if (sljit_stack_resize(stack, stack->base + limit)) {
|
||||
sljit_free_stack(stack);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
base.ptr = mmap(0, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (base.ptr == MAP_FAILED) {
|
||||
SLJIT_FREE(stack);
|
||||
return NULL;
|
||||
}
|
||||
stack->base = base.uw;
|
||||
stack->limit = stack->base + limit;
|
||||
stack->max_limit = stack->base + max_limit;
|
||||
#endif
|
||||
stack->top = stack->base;
|
||||
return stack;
|
||||
}
|
||||
|
||||
#undef PAGE_ALIGN
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* stack)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
VirtualFree((void*)stack->base, 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap((void*)stack->base, stack->max_limit - stack->base);
|
||||
#endif
|
||||
SLJIT_FREE(stack);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
|
||||
{
|
||||
sljit_uw aligned_old_limit;
|
||||
sljit_uw aligned_new_limit;
|
||||
|
||||
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;
|
||||
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))
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
if (!VirtualFree((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_DECOMMIT))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
stack->limit = new_limit;
|
||||
return 0;
|
||||
#else
|
||||
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;
|
||||
if (aligned_new_limit < aligned_old_limit)
|
||||
madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED);
|
||||
stack->limit = new_limit;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* SLJIT_UTIL_STACK */
|
||||
|
||||
#endif
|
||||
521
harbour/src/3rd/pcre/sjx8632.c
Normal file
521
harbour/src/3rd/pcre/sjx8632.c
Normal file
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 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:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* x86 32-bit arch dependent functions. */
|
||||
|
||||
static int emit_do_imm(struct sljit_compiler *compiler, sljit_ub opcode, sljit_w imm)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_w));
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(1 + sizeof(sljit_w));
|
||||
*buf++ = opcode;
|
||||
*(sljit_w*)buf = imm;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type)
|
||||
{
|
||||
if (type == SLJIT_JUMP) {
|
||||
*code_ptr++ = 0xe9;
|
||||
jump->addr++;
|
||||
}
|
||||
else if (type >= SLJIT_FAST_CALL) {
|
||||
*code_ptr++ = 0xe8;
|
||||
jump->addr++;
|
||||
}
|
||||
else {
|
||||
*code_ptr++ = 0x0f;
|
||||
*code_ptr++ = get_jump_code(type);
|
||||
jump->addr += 2;
|
||||
}
|
||||
|
||||
if (jump->flags & JUMP_LABEL)
|
||||
jump->flags |= PATCH_MW;
|
||||
else
|
||||
*(sljit_w*)code_ptr = jump->u.target - (jump->addr + 4);
|
||||
code_ptr += 4;
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
{
|
||||
int size;
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, temporaries, generals, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->args = args;
|
||||
compiler->flags_saved = 0;
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
size = 1 + (generals <= 3 ? generals : 3) + (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
|
||||
#else
|
||||
size = 1 + (generals <= 3 ? generals : 3) + (args > 0 ? (2 + args * 3) : 0);
|
||||
#endif
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(size);
|
||||
PUSH_REG(reg_map[TMP_REGISTER]);
|
||||
#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (args > 0) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc4 | (reg_map[TMP_REGISTER] << 3);
|
||||
}
|
||||
#endif
|
||||
if (generals > 2)
|
||||
PUSH_REG(reg_map[SLJIT_GENERAL_REG3]);
|
||||
if (generals > 1)
|
||||
PUSH_REG(reg_map[SLJIT_GENERAL_REG2]);
|
||||
if (generals > 0)
|
||||
PUSH_REG(reg_map[SLJIT_GENERAL_REG1]);
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (args > 0) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG1] << 3) | reg_map[SLJIT_TEMPORARY_REG3];
|
||||
}
|
||||
if (args > 1) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG2] << 3) | reg_map[SLJIT_TEMPORARY_REG2];
|
||||
}
|
||||
if (args > 2) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0x44 | (reg_map[SLJIT_GENERAL_REG3] << 3);
|
||||
*buf++ = 0x24;
|
||||
*buf++ = sizeof(sljit_w) * (3 + 2); /* generals >= 3 as well. */
|
||||
}
|
||||
#else
|
||||
if (args > 0) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0x40 | (reg_map[SLJIT_GENERAL_REG1] << 3) | reg_map[TMP_REGISTER];
|
||||
*buf++ = sizeof(sljit_w) * 2;
|
||||
}
|
||||
if (args > 1) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0x40 | (reg_map[SLJIT_GENERAL_REG2] << 3) | reg_map[TMP_REGISTER];
|
||||
*buf++ = sizeof(sljit_w) * 3;
|
||||
}
|
||||
if (args > 2) {
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0x40 | (reg_map[SLJIT_GENERAL_REG3] << 3) | reg_map[TMP_REGISTER];
|
||||
*buf++ = sizeof(sljit_w) * 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
|
||||
compiler->temporaries_start = local_size;
|
||||
if (temporaries > 3)
|
||||
local_size += (temporaries - 3) * sizeof(sljit_uw);
|
||||
compiler->generals_start = local_size;
|
||||
if (generals > 3)
|
||||
local_size += (generals - 3) * sizeof(sljit_uw);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (local_size > 1024) {
|
||||
FAIL_IF(emit_do_imm(compiler, 0xb8 + reg_map[SLJIT_TEMPORARY_REG1], local_size));
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_touch_stack)));
|
||||
}
|
||||
#endif
|
||||
|
||||
compiler->local_size = local_size;
|
||||
if (local_size > 0)
|
||||
return emit_non_cum_binary(compiler, 0x2b, 0x29, 0x5 << 3, 0x2d,
|
||||
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size);
|
||||
|
||||
/* Mov arguments to general registers. */
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
{
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_fake_enter(compiler, args, temporaries, generals, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->args = args;
|
||||
compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
|
||||
compiler->temporaries_start = compiler->local_size;
|
||||
if (temporaries > 3)
|
||||
compiler->local_size += (temporaries - 3) * sizeof(sljit_uw);
|
||||
compiler->generals_start = compiler->local_size;
|
||||
if (generals > 3)
|
||||
compiler->local_size += (generals - 3) * sizeof(sljit_uw);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
{
|
||||
int size;
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, src, srcw);
|
||||
SLJIT_ASSERT(compiler->args >= 0);
|
||||
|
||||
compiler->flags_saved = 0;
|
||||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||
|
||||
if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG)
|
||||
FAIL_IF(emit_mov(compiler, SLJIT_RETURN_REG, 0, src, srcw));
|
||||
|
||||
if (compiler->local_size > 0)
|
||||
FAIL_IF(emit_cum_binary(compiler, 0x03, 0x01, 0x0 << 3, 0x05,
|
||||
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size));
|
||||
|
||||
size = 2 + (compiler->generals <= 3 ? compiler->generals : 3);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (compiler->args > 2)
|
||||
size += 2;
|
||||
#else
|
||||
if (compiler->args > 0)
|
||||
size += 2;
|
||||
#endif
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(size);
|
||||
|
||||
if (compiler->generals > 0)
|
||||
POP_REG(reg_map[SLJIT_GENERAL_REG1]);
|
||||
if (compiler->generals > 1)
|
||||
POP_REG(reg_map[SLJIT_GENERAL_REG2]);
|
||||
if (compiler->generals > 2)
|
||||
POP_REG(reg_map[SLJIT_GENERAL_REG3]);
|
||||
POP_REG(reg_map[TMP_REGISTER]);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (compiler->args > 2)
|
||||
RETN(sizeof(sljit_w));
|
||||
else
|
||||
RET();
|
||||
#else
|
||||
if (compiler->args > 0)
|
||||
RETN(compiler->args * sizeof(sljit_w));
|
||||
else
|
||||
RET();
|
||||
#endif
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Size contains the flags as well. */
|
||||
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
||||
/* The register or immediate operand. */
|
||||
int a, sljit_w imma,
|
||||
/* The general operand (not immediate). */
|
||||
int b, sljit_w immb)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *buf_ptr;
|
||||
int flags = size & ~0xf;
|
||||
int inst_size;
|
||||
|
||||
/* Both cannot be switched on. */
|
||||
SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
|
||||
/* Size flags not allowed for typed instructions. */
|
||||
SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
|
||||
/* Both size flags cannot be switched on. */
|
||||
SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
/* SSE2 and immediate is not possible. */
|
||||
SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
|
||||
#endif
|
||||
|
||||
size &= 0xf;
|
||||
inst_size = size;
|
||||
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (flags & EX86_PREF_F2)
|
||||
inst_size++;
|
||||
#endif
|
||||
if (flags & EX86_PREF_66)
|
||||
inst_size++;
|
||||
|
||||
/* Calculate size of b. */
|
||||
inst_size += 1; /* mod r/m byte. */
|
||||
if (b & SLJIT_MEM) {
|
||||
if ((b & 0x0f) == SLJIT_UNUSED)
|
||||
inst_size += sizeof(sljit_w);
|
||||
else if (immb != 0 && !(b & 0xf0)) {
|
||||
/* Immediate operand. */
|
||||
if (immb <= 127 && immb >= -128)
|
||||
inst_size += sizeof(sljit_b);
|
||||
else
|
||||
inst_size += sizeof(sljit_w);
|
||||
}
|
||||
|
||||
if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
|
||||
b |= SLJIT_LOCALS_REG << 4;
|
||||
|
||||
if ((b & 0xf0) != SLJIT_UNUSED)
|
||||
inst_size += 1; /* SIB byte. */
|
||||
}
|
||||
|
||||
/* Calculate size of a. */
|
||||
if (a & SLJIT_IMM) {
|
||||
if (flags & EX86_BIN_INS) {
|
||||
if (imma <= 127 && imma >= -128) {
|
||||
inst_size += 1;
|
||||
flags |= EX86_BYTE_ARG;
|
||||
} else
|
||||
inst_size += 4;
|
||||
}
|
||||
else if (flags & EX86_SHIFT_INS) {
|
||||
imma &= 0x1f;
|
||||
if (imma != 1) {
|
||||
inst_size ++;
|
||||
flags |= EX86_BYTE_ARG;
|
||||
}
|
||||
} else if (flags & EX86_BYTE_ARG)
|
||||
inst_size++;
|
||||
else if (flags & EX86_HALF_ARG)
|
||||
inst_size += sizeof(short);
|
||||
else
|
||||
inst_size += sizeof(sljit_w);
|
||||
}
|
||||
else
|
||||
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
|
||||
PTR_FAIL_IF(!buf);
|
||||
|
||||
/* Encoding the byte. */
|
||||
INC_SIZE(inst_size);
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (flags & EX86_PREF_F2)
|
||||
*buf++ = 0xf2;
|
||||
#endif
|
||||
if (flags & EX86_PREF_66)
|
||||
*buf++ = 0x66;
|
||||
|
||||
buf_ptr = buf + size;
|
||||
|
||||
/* Encode mod/rm byte. */
|
||||
if (!(flags & EX86_SHIFT_INS)) {
|
||||
if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
|
||||
*buf = (flags & EX86_BYTE_ARG) ? 0x83 : 0x81;
|
||||
|
||||
if ((a & SLJIT_IMM) || (a == 0))
|
||||
*buf_ptr = 0;
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
else if (!(flags & EX86_SSE2))
|
||||
*buf_ptr = reg_map[a] << 3;
|
||||
else
|
||||
*buf_ptr = a << 3;
|
||||
#else
|
||||
else
|
||||
*buf_ptr = reg_map[a] << 3;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if (a & SLJIT_IMM) {
|
||||
if (imma == 1)
|
||||
*buf = 0xd1;
|
||||
else
|
||||
*buf = 0xc1;
|
||||
} else
|
||||
*buf = 0xd3;
|
||||
*buf_ptr = 0;
|
||||
}
|
||||
|
||||
if (!(b & SLJIT_MEM))
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
*buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_map[b] : b);
|
||||
#else
|
||||
*buf_ptr++ |= 0xc0 + reg_map[b];
|
||||
#endif
|
||||
else if ((b & 0x0f) != SLJIT_UNUSED) {
|
||||
if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
|
||||
if (immb != 0) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr |= 0x40;
|
||||
else
|
||||
*buf_ptr |= 0x80;
|
||||
}
|
||||
|
||||
if ((b & 0xf0) == SLJIT_UNUSED)
|
||||
*buf_ptr++ |= reg_map[b & 0x0f];
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_map[b & 0x0f] | (reg_map[(b >> 4) & 0x0f] << 3);
|
||||
}
|
||||
|
||||
if (immb != 0) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr++ = immb; /* 8 bit displacement. */
|
||||
else {
|
||||
*(sljit_w*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_w);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_map[b & 0x0f] | (reg_map[(b >> 4) & 0x0f] << 3) | (immb << 6);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*buf_ptr++ |= 0x05;
|
||||
*(sljit_w*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_w);
|
||||
}
|
||||
|
||||
if (a & SLJIT_IMM) {
|
||||
if (flags & EX86_BYTE_ARG)
|
||||
*buf_ptr = imma;
|
||||
else if (flags & EX86_HALF_ARG)
|
||||
*(short*)buf_ptr = imma;
|
||||
else if (!(flags & EX86_SHIFT_INS))
|
||||
*(sljit_w*)buf_ptr = imma;
|
||||
}
|
||||
|
||||
return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Call / return instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
buf = (sljit_ub*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(type >= SLJIT_CALL3 ? 2 + 1 : 2);
|
||||
|
||||
if (type >= SLJIT_CALL3)
|
||||
PUSH_REG(reg_map[SLJIT_TEMPORARY_REG3]);
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_TEMPORARY_REG3] << 3) | reg_map[SLJIT_TEMPORARY_REG1];
|
||||
#else
|
||||
buf = (sljit_ub*)ensure_buf(compiler, type - SLJIT_CALL0 + 1);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(type - SLJIT_CALL0);
|
||||
if (type >= SLJIT_CALL3)
|
||||
PUSH_REG(reg_map[SLJIT_TEMPORARY_REG3]);
|
||||
if (type >= SLJIT_CALL2)
|
||||
PUSH_REG(reg_map[SLJIT_TEMPORARY_REG2]);
|
||||
PUSH_REG(reg_map[SLJIT_TEMPORARY_REG1]);
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int generals, int local_size)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->args = args;
|
||||
compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
|
||||
compiler->temporaries_start = compiler->local_size;
|
||||
if (temporaries > 3)
|
||||
compiler->local_size += (temporaries - 3) * sizeof(sljit_uw);
|
||||
compiler->generals_start = compiler->local_size;
|
||||
if (generals > 3)
|
||||
compiler->local_size += (generals - 3) * sizeof(sljit_uw);
|
||||
|
||||
CHECK_EXTRA_REGS(dst, dstw, (void)0);
|
||||
|
||||
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(1);
|
||||
POP_REG(reg_map[dst]);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
else if (dst & SLJIT_MEM) {
|
||||
buf = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
|
||||
FAIL_IF(!buf);
|
||||
*buf++ = 0x8f;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* For UNUSED dst. Uncommon, but possible. */
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(1);
|
||||
POP_REG(reg_map[TMP_REGISTER]);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_return(compiler, src, srcw);
|
||||
|
||||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||
|
||||
if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(1 + 1);
|
||||
PUSH_REG(reg_map[src]);
|
||||
}
|
||||
else if (src & SLJIT_MEM) {
|
||||
buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
|
||||
FAIL_IF(!buf);
|
||||
*buf++ = 0xff;
|
||||
*buf |= 6 << 3;
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(1);
|
||||
}
|
||||
else {
|
||||
/* SLJIT_IMM. */
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(5 + 1);
|
||||
*buf++ = 0x68;
|
||||
*(sljit_w*)buf = srcw;
|
||||
buf += sizeof(sljit_w);
|
||||
}
|
||||
|
||||
RET();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
863
harbour/src/3rd/pcre/sjx8664.c
Normal file
863
harbour/src/3rd/pcre/sjx8664.c
Normal file
@@ -0,0 +1,863 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2010 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:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* x86 64-bit arch dependent functions. */
|
||||
|
||||
static int emit_load_imm64(struct sljit_compiler *compiler, int reg, sljit_w imm)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_w));
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(2 + sizeof(sljit_w));
|
||||
*buf++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
|
||||
*buf++ = 0xb8 + (reg_map[reg] & 0x7);
|
||||
*(sljit_w*)buf = imm;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type)
|
||||
{
|
||||
if (type < SLJIT_JUMP) {
|
||||
*code_ptr++ = get_jump_code(type ^ 0x1) - 0x10;
|
||||
*code_ptr++ = 10 + 3;
|
||||
}
|
||||
|
||||
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first);
|
||||
*code_ptr++ = REX_W | REX_B;
|
||||
*code_ptr++ = 0xb8 + 1;
|
||||
jump->addr = (sljit_uw)code_ptr;
|
||||
|
||||
if (jump->flags & JUMP_LABEL)
|
||||
jump->flags |= PATCH_MD;
|
||||
else
|
||||
*(sljit_w*)code_ptr = jump->u.target;
|
||||
|
||||
code_ptr += sizeof(sljit_w);
|
||||
*code_ptr++ = REX_B;
|
||||
*code_ptr++ = 0xff;
|
||||
*code_ptr++ = (type >= SLJIT_FAST_CALL) ? 0xd1 /* call */ : 0xe1 /* jmp */;
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_w addr, int type)
|
||||
{
|
||||
sljit_w delta = addr - ((sljit_w)code_ptr + 1 + sizeof(sljit_hw));
|
||||
|
||||
if (delta <= SLJIT_W(0x7fffffff) && delta >= SLJIT_W(-0x80000000)) {
|
||||
*code_ptr++ = (type == 2) ? 0xe8 /* call */ : 0xe9 /* jmp */;
|
||||
*(sljit_w*)code_ptr = delta;
|
||||
}
|
||||
else {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second);
|
||||
*code_ptr++ = REX_W | REX_B;
|
||||
*code_ptr++ = 0xb8 + 1;
|
||||
*(sljit_w*)code_ptr = addr;
|
||||
code_ptr += sizeof(sljit_w);
|
||||
*code_ptr++ = REX_B;
|
||||
*code_ptr++ = 0xff;
|
||||
*code_ptr++ = (type == 2) ? 0xd1 /* call */ : 0xe1 /* jmp */;
|
||||
}
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
{
|
||||
int size, pushed_size;
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_enter(compiler, args, temporaries, generals, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->flags_saved = 0;
|
||||
|
||||
size = generals;
|
||||
/* Including the return address saved by the call instruction. */
|
||||
pushed_size = (generals + 1) * sizeof(sljit_w);
|
||||
#ifndef _WIN64
|
||||
if (generals >= 2)
|
||||
size += generals - 1;
|
||||
#else
|
||||
/* Saving the virtual stack pointer. */
|
||||
compiler->has_locals = local_size > 0;
|
||||
if (local_size > 0) {
|
||||
size += 2;
|
||||
pushed_size += sizeof(sljit_w);
|
||||
}
|
||||
if (generals >= 4)
|
||||
size += generals - 3;
|
||||
if (temporaries >= 5) {
|
||||
size += (5 - 4) * 2;
|
||||
pushed_size += sizeof(sljit_w);
|
||||
}
|
||||
#endif
|
||||
size += args * 3;
|
||||
if (size > 0) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(size);
|
||||
if (generals >= 5) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_EREG2] >= 8, general_ereg2_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_GENERAL_EREG2]);
|
||||
}
|
||||
if (generals >= 4) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_EREG1] >= 8, general_ereg1_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_GENERAL_EREG1]);
|
||||
}
|
||||
if (generals >= 3) {
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG3] >= 8, general_reg3_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG3] < 8, general_reg3_is_loreg);
|
||||
#endif
|
||||
PUSH_REG(reg_lmap[SLJIT_GENERAL_REG3]);
|
||||
}
|
||||
if (generals >= 2) {
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG2] >= 8, general_reg2_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG2] < 8, general_reg2_is_loreg);
|
||||
#endif
|
||||
PUSH_REG(reg_lmap[SLJIT_GENERAL_REG2]);
|
||||
}
|
||||
if (generals >= 1) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG1] < 8, general_reg1_is_loreg);
|
||||
PUSH_REG(reg_lmap[SLJIT_GENERAL_REG1]);
|
||||
}
|
||||
#ifdef _WIN64
|
||||
if (temporaries >= 5) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_EREG2] >= 8, temporary_ereg2_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
|
||||
}
|
||||
if (local_size > 0) {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_LOCALS_REG] >= 8, locals_reg_is_hireg);
|
||||
*buf++ = REX_B;
|
||||
PUSH_REG(reg_lmap[SLJIT_LOCALS_REG]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN64
|
||||
if (args > 0) {
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG1] << 3) | 0x7;
|
||||
}
|
||||
if (args > 1) {
|
||||
*buf++ = REX_W | REX_R;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_lmap[SLJIT_GENERAL_REG2] << 3) | 0x6;
|
||||
}
|
||||
if (args > 2) {
|
||||
*buf++ = REX_W | REX_R;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_lmap[SLJIT_GENERAL_REG3] << 3) | 0x2;
|
||||
}
|
||||
#else
|
||||
if (args > 0) {
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG1] << 3) | 0x1;
|
||||
}
|
||||
if (args > 1) {
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG2] << 3) | 0x2;
|
||||
}
|
||||
if (args > 2) {
|
||||
*buf++ = REX_W | REX_B;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG3] << 3) | 0x0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
|
||||
#ifdef _WIN64
|
||||
local_size += 4 * sizeof(sljit_w);
|
||||
compiler->local_size = local_size;
|
||||
if (local_size > 1024) {
|
||||
/* Allocate the stack for the function itself. */
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(4);
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x83;
|
||||
*buf++ = 0xc0 | (5 << 3) | 4;
|
||||
/* Pushed size must be divisible by 8. */
|
||||
SLJIT_ASSERT(!(pushed_size & 0x7));
|
||||
if (pushed_size & 0x8) {
|
||||
*buf++ = 5 * sizeof(sljit_w);
|
||||
local_size -= 5 * sizeof(sljit_w);
|
||||
} else {
|
||||
*buf++ = 4 * sizeof(sljit_w);
|
||||
local_size -= 4 * sizeof(sljit_w);
|
||||
}
|
||||
FAIL_IF(emit_load_imm64(compiler, SLJIT_TEMPORARY_REG1, local_size));
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_touch_stack)));
|
||||
}
|
||||
#else
|
||||
compiler->local_size = local_size;
|
||||
if (local_size > 0) {
|
||||
#endif
|
||||
/* In case of Win64, local_size is always > 4 * sizeof(sljit_w) */
|
||||
if (local_size <= 127) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(4);
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x83;
|
||||
*buf++ = 0xc0 | (5 << 3) | 4;
|
||||
*buf++ = local_size;
|
||||
}
|
||||
else {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(7);
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x81;
|
||||
*buf++ = 0xc0 | (5 << 3) | 4;
|
||||
*(sljit_hw*)buf = local_size;
|
||||
buf += sizeof(sljit_hw);
|
||||
}
|
||||
#ifndef _WIN64
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
if (compiler->has_locals) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(5);
|
||||
*buf++ = REX_W | REX_R;
|
||||
*buf++ = 0x8d;
|
||||
*buf++ = 0x40 | (reg_lmap[SLJIT_LOCALS_REG] << 3) | 0x4;
|
||||
*buf++ = 0x24;
|
||||
*buf = 4 * sizeof(sljit_w);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Mov arguments to general registers. */
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
|
||||
{
|
||||
int pushed_size;
|
||||
|
||||
CHECK_ERROR_VOID();
|
||||
check_sljit_fake_enter(compiler, args, temporaries, generals, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
/* Including the return address saved by the call instruction. */
|
||||
pushed_size = (generals + 1) * sizeof(sljit_w);
|
||||
#ifdef _WIN64
|
||||
compiler->has_locals = local_size > 0;
|
||||
if (local_size > 0)
|
||||
pushed_size += sizeof(sljit_w);
|
||||
if (temporaries >= 5)
|
||||
pushed_size += sizeof(sljit_w);
|
||||
#endif
|
||||
compiler->local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
|
||||
#ifdef _WIN64
|
||||
compiler->local_size += 4 * sizeof(sljit_w);
|
||||
#endif
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
{
|
||||
int size;
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, src, srcw);
|
||||
|
||||
compiler->flags_saved = 0;
|
||||
|
||||
if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG) {
|
||||
compiler->mode32 = 0;
|
||||
FAIL_IF(emit_mov(compiler, SLJIT_RETURN_REG, 0, src, srcw));
|
||||
}
|
||||
|
||||
if (compiler->local_size > 0) {
|
||||
if (compiler->local_size <= 127) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(4);
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x83;
|
||||
*buf++ = 0xc0 | (0 << 3) | 4;
|
||||
*buf = compiler->local_size;
|
||||
}
|
||||
else {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(7);
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x81;
|
||||
*buf++ = 0xc0 | (0 << 3) | 4;
|
||||
*(sljit_hw*)buf = compiler->local_size;
|
||||
}
|
||||
}
|
||||
|
||||
size = 1 + compiler->generals;
|
||||
#ifndef _WIN64
|
||||
if (compiler->generals >= 2)
|
||||
size += compiler->generals - 1;
|
||||
#else
|
||||
if (compiler->has_locals)
|
||||
size += 2;
|
||||
if (compiler->generals >= 4)
|
||||
size += compiler->generals - 3;
|
||||
if (compiler->temporaries >= 5)
|
||||
size += (5 - 4) * 2;
|
||||
#endif
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(size);
|
||||
|
||||
#ifdef _WIN64
|
||||
if (compiler->has_locals) {
|
||||
*buf++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_LOCALS_REG]);
|
||||
}
|
||||
if (compiler->temporaries >= 5) {
|
||||
*buf++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
|
||||
}
|
||||
#endif
|
||||
if (compiler->generals >= 1)
|
||||
POP_REG(reg_map[SLJIT_GENERAL_REG1]);
|
||||
if (compiler->generals >= 2) {
|
||||
#ifndef _WIN64
|
||||
*buf++ = REX_B;
|
||||
#endif
|
||||
POP_REG(reg_lmap[SLJIT_GENERAL_REG2]);
|
||||
}
|
||||
if (compiler->generals >= 3) {
|
||||
#ifndef _WIN64
|
||||
*buf++ = REX_B;
|
||||
#endif
|
||||
POP_REG(reg_lmap[SLJIT_GENERAL_REG3]);
|
||||
}
|
||||
if (compiler->generals >= 4) {
|
||||
*buf++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_GENERAL_EREG1]);
|
||||
}
|
||||
if (compiler->generals >= 5) {
|
||||
*buf++ = REX_B;
|
||||
POP_REG(reg_lmap[SLJIT_GENERAL_EREG2]);
|
||||
}
|
||||
|
||||
RET();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static int emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_w imm)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
|
||||
if (rex != 0) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_hw));
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(2 + sizeof(sljit_hw));
|
||||
*buf++ = rex;
|
||||
*buf++ = opcode;
|
||||
*(sljit_hw*)buf = imm;
|
||||
}
|
||||
else {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_hw));
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(1 + sizeof(sljit_hw));
|
||||
*buf++ = opcode;
|
||||
*(sljit_hw*)buf = imm;
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
|
||||
/* The register or immediate operand. */
|
||||
int a, sljit_w imma,
|
||||
/* The general operand (not immediate). */
|
||||
int b, sljit_w immb)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
sljit_ub *buf_ptr;
|
||||
sljit_ub rex = 0;
|
||||
int flags = size & ~0xf;
|
||||
int inst_size;
|
||||
|
||||
/* The immediate operand must be 32 bit. */
|
||||
SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
|
||||
/* Both cannot be switched on. */
|
||||
SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
|
||||
/* Size flags not allowed for typed instructions. */
|
||||
SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
|
||||
/* Both size flags cannot be switched on. */
|
||||
SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
/* SSE2 and immediate is not possible. */
|
||||
SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
|
||||
#endif
|
||||
|
||||
size &= 0xf;
|
||||
inst_size = size;
|
||||
|
||||
if ((b & SLJIT_MEM) && !(b & 0xf0) && NOT_HALFWORD(immb)) {
|
||||
if (emit_load_imm64(compiler, TMP_REG3, immb))
|
||||
return NULL;
|
||||
immb = 0;
|
||||
if (b & 0xf)
|
||||
b |= TMP_REG3 << 4;
|
||||
else
|
||||
b |= TMP_REG3;
|
||||
}
|
||||
|
||||
if (!compiler->mode32 && !(flags & EX86_NO_REXW))
|
||||
rex |= REX_W;
|
||||
else if (flags & EX86_REX)
|
||||
rex |= REX;
|
||||
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (flags & EX86_PREF_F2)
|
||||
inst_size++;
|
||||
#endif
|
||||
if (flags & EX86_PREF_66)
|
||||
inst_size++;
|
||||
|
||||
/* Calculate size of b. */
|
||||
inst_size += 1; /* mod r/m byte. */
|
||||
if (b & SLJIT_MEM) {
|
||||
if ((b & 0x0f) == SLJIT_UNUSED)
|
||||
inst_size += 1 + sizeof(sljit_hw); /* SIB byte required to avoid RIP based addressing. */
|
||||
else {
|
||||
if (reg_map[b & 0x0f] >= 8)
|
||||
rex |= REX_B;
|
||||
if (immb != 0 && !(b & 0xf0)) {
|
||||
/* Immediate operand. */
|
||||
if (immb <= 127 && immb >= -128)
|
||||
inst_size += sizeof(sljit_b);
|
||||
else
|
||||
inst_size += sizeof(sljit_hw);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _WIN64
|
||||
if ((b & 0xf) == SLJIT_LOCALS_REG && (b & 0xf0) == 0)
|
||||
b |= SLJIT_LOCALS_REG << 4;
|
||||
#endif
|
||||
|
||||
if ((b & 0xf0) != SLJIT_UNUSED) {
|
||||
inst_size += 1; /* SIB byte. */
|
||||
if (reg_map[(b >> 4) & 0x0f] >= 8)
|
||||
rex |= REX_X;
|
||||
}
|
||||
}
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
else if (!(flags & EX86_SSE2) && reg_map[b] >= 8)
|
||||
rex |= REX_B;
|
||||
#else
|
||||
else if (reg_map[b] >= 8)
|
||||
rex |= REX_B;
|
||||
#endif
|
||||
|
||||
if (a & SLJIT_IMM) {
|
||||
if (flags & EX86_BIN_INS) {
|
||||
if (imma <= 127 && imma >= -128) {
|
||||
inst_size += 1;
|
||||
flags |= EX86_BYTE_ARG;
|
||||
} else
|
||||
inst_size += 4;
|
||||
}
|
||||
else if (flags & EX86_SHIFT_INS) {
|
||||
imma &= 0x3f;
|
||||
if (imma != 1) {
|
||||
inst_size ++;
|
||||
flags |= EX86_BYTE_ARG;
|
||||
}
|
||||
} else if (flags & EX86_BYTE_ARG)
|
||||
inst_size++;
|
||||
else if (flags & EX86_HALF_ARG)
|
||||
inst_size += sizeof(short);
|
||||
else
|
||||
inst_size += sizeof(sljit_hw);
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
|
||||
/* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (!(flags & EX86_SSE2) && reg_map[a] >= 8)
|
||||
rex |= REX_R;
|
||||
#else
|
||||
if (reg_map[a] >= 8)
|
||||
rex |= REX_R;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rex)
|
||||
inst_size++;
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
|
||||
PTR_FAIL_IF(!buf);
|
||||
|
||||
/* Encoding the byte. */
|
||||
INC_SIZE(inst_size);
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
if (flags & EX86_PREF_F2)
|
||||
*buf++ = 0xf2;
|
||||
#endif
|
||||
if (flags & EX86_PREF_66)
|
||||
*buf++ = 0x66;
|
||||
if (rex)
|
||||
*buf++ = rex;
|
||||
buf_ptr = buf + size;
|
||||
|
||||
/* Encode mod/rm byte. */
|
||||
if (!(flags & EX86_SHIFT_INS)) {
|
||||
if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
|
||||
*buf = (flags & EX86_BYTE_ARG) ? 0x83 : 0x81;
|
||||
|
||||
if ((a & SLJIT_IMM) || (a == 0))
|
||||
*buf_ptr = 0;
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
else if (!(flags & EX86_SSE2))
|
||||
*buf_ptr = reg_lmap[a] << 3;
|
||||
else
|
||||
*buf_ptr = a << 3;
|
||||
#else
|
||||
else
|
||||
*buf_ptr = reg_lmap[a] << 3;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if (a & SLJIT_IMM) {
|
||||
if (imma == 1)
|
||||
*buf = 0xd1;
|
||||
else
|
||||
*buf = 0xc1;
|
||||
} else
|
||||
*buf = 0xd3;
|
||||
*buf_ptr = 0;
|
||||
}
|
||||
|
||||
if (!(b & SLJIT_MEM))
|
||||
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
|
||||
*buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_lmap[b] : b);
|
||||
#else
|
||||
*buf_ptr++ |= 0xc0 + reg_lmap[b];
|
||||
#endif
|
||||
else if ((b & 0x0f) != SLJIT_UNUSED) {
|
||||
#ifdef _WIN64
|
||||
SLJIT_ASSERT((b & 0xf0) != (SLJIT_LOCALS_REG << 4));
|
||||
#endif
|
||||
if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
|
||||
if (immb != 0) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr |= 0x40;
|
||||
else
|
||||
*buf_ptr |= 0x80;
|
||||
}
|
||||
|
||||
if ((b & 0xf0) == SLJIT_UNUSED)
|
||||
*buf_ptr++ |= reg_lmap[b & 0x0f];
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3);
|
||||
}
|
||||
|
||||
if (immb != 0) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr++ = immb; /* 8 bit displacement. */
|
||||
else {
|
||||
*(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_hw);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3) | (immb << 6);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = 0x25;
|
||||
*(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_hw);
|
||||
}
|
||||
|
||||
if (a & SLJIT_IMM) {
|
||||
if (flags & EX86_BYTE_ARG)
|
||||
*buf_ptr = imma;
|
||||
else if (flags & EX86_HALF_ARG)
|
||||
*(short*)buf_ptr = imma;
|
||||
else if (!(flags & EX86_SHIFT_INS))
|
||||
*(sljit_hw*)buf_ptr = imma;
|
||||
}
|
||||
|
||||
return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Call / return instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 6 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers);
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
|
||||
if (type >= SLJIT_CALL3) {
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (0x2 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3];
|
||||
}
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (0x7 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 2 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers);
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
|
||||
if (type >= SLJIT_CALL3) {
|
||||
*buf++ = REX_W | REX_R;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (0x0 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3];
|
||||
}
|
||||
*buf++ = REX_W;
|
||||
*buf++ = 0x8b;
|
||||
*buf++ = 0xc0 | (0x1 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int generals, int local_size)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size);
|
||||
|
||||
compiler->temporaries = temporaries;
|
||||
compiler->generals = generals;
|
||||
compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
|
||||
#ifdef _WIN64
|
||||
compiler->local_size += 4 * sizeof(sljit_w);
|
||||
#endif
|
||||
|
||||
/* For UNUSED dst. Uncommon, but possible. */
|
||||
if (dst == SLJIT_UNUSED)
|
||||
dst = TMP_REGISTER;
|
||||
|
||||
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
|
||||
if (reg_map[dst] < 8) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(1);
|
||||
POP_REG(reg_lmap[dst]);
|
||||
}
|
||||
else {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(2);
|
||||
*buf++ = REX_B;
|
||||
POP_REG(reg_lmap[dst]);
|
||||
}
|
||||
}
|
||||
else if (dst & SLJIT_MEM) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
/* REX_W is not necessary (src is not immediate). */
|
||||
compiler->mode32 = 1;
|
||||
#endif
|
||||
buf = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
|
||||
FAIL_IF(!buf);
|
||||
*buf++ = 0x8f;
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
|
||||
{
|
||||
sljit_ub *buf;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_fast_return(compiler, src, srcw);
|
||||
|
||||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||
|
||||
if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) {
|
||||
FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, srcw));
|
||||
src = TMP_REGISTER;
|
||||
}
|
||||
|
||||
if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REGISTER) {
|
||||
if (reg_map[src] < 8) {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(1 + 1);
|
||||
PUSH_REG(reg_lmap[src]);
|
||||
}
|
||||
else {
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(2 + 1);
|
||||
*buf++ = REX_B;
|
||||
PUSH_REG(reg_lmap[src]);
|
||||
}
|
||||
}
|
||||
else if (src & SLJIT_MEM) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
/* REX_W is not necessary (src is not immediate). */
|
||||
compiler->mode32 = 1;
|
||||
#endif
|
||||
buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
|
||||
FAIL_IF(!buf);
|
||||
*buf++ = 0xff;
|
||||
*buf |= 6 << 3;
|
||||
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!buf);
|
||||
INC_SIZE(1);
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(IS_HALFWORD(srcw));
|
||||
/* SLJIT_IMM. */
|
||||
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!buf);
|
||||
|
||||
INC_SIZE(5 + 1);
|
||||
*buf++ = 0x68;
|
||||
*(sljit_hw*)buf = srcw;
|
||||
buf += sizeof(sljit_hw);
|
||||
}
|
||||
|
||||
RET();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Extend input */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static int emit_mov_int(struct sljit_compiler *compiler, int sign,
|
||||
int dst, sljit_w dstw,
|
||||
int src, sljit_w srcw)
|
||||
{
|
||||
sljit_ub* code;
|
||||
int dst_r;
|
||||
|
||||
compiler->mode32 = 0;
|
||||
|
||||
if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS; /* Empty instruction. */
|
||||
|
||||
if (src & SLJIT_IMM) {
|
||||
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
|
||||
return emit_load_imm64(compiler, dst, srcw);
|
||||
compiler->mode32 = 1;
|
||||
code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(int)srcw, dst, dstw);
|
||||
FAIL_IF(!code);
|
||||
*code = 0xc7;
|
||||
compiler->mode32 = 0;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_GENERAL_REG3) ? dst : TMP_REGISTER;
|
||||
|
||||
if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_GENERAL_REG3))
|
||||
dst_r = src;
|
||||
else {
|
||||
if (sign) {
|
||||
code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
|
||||
FAIL_IF(!code);
|
||||
*code++ = 0x63;
|
||||
}
|
||||
else {
|
||||
if (dst_r == src) {
|
||||
compiler->mode32 = 1;
|
||||
code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, 0);
|
||||
FAIL_IF(!code);
|
||||
*code++ = 0x8b;
|
||||
compiler->mode32 = 0;
|
||||
}
|
||||
/* xor reg, reg. */
|
||||
code = emit_x86_instruction(compiler, 1, dst_r, 0, dst_r, 0);
|
||||
FAIL_IF(!code);
|
||||
*code++ = 0x33;
|
||||
if (dst_r != src) {
|
||||
compiler->mode32 = 1;
|
||||
code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
|
||||
FAIL_IF(!code);
|
||||
*code++ = 0x8b;
|
||||
compiler->mode32 = 0;
|
||||
}
|
||||
else {
|
||||
compiler->mode32 = 1;
|
||||
code = emit_x86_instruction(compiler, 1, src, 0, TMP_REGISTER, 0);
|
||||
FAIL_IF(!code);
|
||||
*code++ = 0x8b;
|
||||
compiler->mode32 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dst & SLJIT_MEM) {
|
||||
compiler->mode32 = 1;
|
||||
code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
|
||||
FAIL_IF(!code);
|
||||
*code = 0x89;
|
||||
compiler->mode32 = 0;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
2691
harbour/src/3rd/pcre/sjx86c.c
Normal file
2691
harbour/src/3rd/pcre/sjx86c.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user