summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/pcre/sljit
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/pcre/sljit')
-rw-r--r--src/3rdparty/pcre/sljit/sljitConfig.h16
-rw-r--r--src/3rdparty/pcre/sljit/sljitConfigInternal.h140
-rw-r--r--src/3rdparty/pcre/sljit/sljitExecAllocator.c28
-rw-r--r--src/3rdparty/pcre/sljit/sljitLir.c624
-rw-r--r--src/3rdparty/pcre/sljit/sljitLir.h606
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c529
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeARM_v5.c913
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c177
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c836
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativePPC_32.c117
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativePPC_64.c175
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativePPC_common.c1094
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeSPARC_32.c164
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c1348
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeX86_32.c354
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeX86_64.c602
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeX86_common.c2468
-rw-r--r--src/3rdparty/pcre/sljit/sljitUtils.c104
18 files changed, 6318 insertions, 3977 deletions
diff --git a/src/3rdparty/pcre/sljit/sljitConfig.h b/src/3rdparty/pcre/sljit/sljitConfig.h
index c832dfe60d..68bc59d089 100644
--- a/src/3rdparty/pcre/sljit/sljitConfig.h
+++ b/src/3rdparty/pcre/sljit/sljitConfig.h
@@ -28,10 +28,17 @@
#define _SLJIT_CONFIG_H_
/* --------------------------------------------------------------------- */
+/* Custom defines */
+/* --------------------------------------------------------------------- */
+
+/* Put your custom defines here. This empty section will never change
+ which helps maintaining patches (with diff / patch utilities). */
+
+/* --------------------------------------------------------------------- */
/* Architecture */
/* --------------------------------------------------------------------- */
-/* Architecture selection */
+/* Architecture selection. */
/* #define SLJIT_CONFIG_X86_32 1 */
/* #define SLJIT_CONFIG_X86_64 1 */
/* #define SLJIT_CONFIG_ARM_V5 1 */
@@ -40,6 +47,7 @@
/* #define SLJIT_CONFIG_PPC_32 1 */
/* #define SLJIT_CONFIG_PPC_64 1 */
/* #define SLJIT_CONFIG_MIPS_32 1 */
+/* #define SLJIT_CONFIG_SPARC_32 1 */
/* #define SLJIT_CONFIG_AUTO 1 */
/* #define SLJIT_CONFIG_UNSUPPORTED 1 */
@@ -60,6 +68,12 @@
#define SLJIT_UTIL_STACK 1
#endif
+/* Single threaded application. Does not require any locks. */
+#ifndef SLJIT_SINGLE_THREADED
+/* Disabled by default. */
+#define SLJIT_SINGLE_THREADED 0
+#endif
+
/* --------------------------------------------------------------------- */
/* Configuration */
/* --------------------------------------------------------------------- */
diff --git a/src/3rdparty/pcre/sljit/sljitConfigInternal.h b/src/3rdparty/pcre/sljit/sljitConfigInternal.h
index de6e9f07e2..2b6616ef66 100644
--- a/src/3rdparty/pcre/sljit/sljitConfigInternal.h
+++ b/src/3rdparty/pcre/sljit/sljitConfigInternal.h
@@ -33,18 +33,23 @@
Feature detection (boolean) macros:
SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
- SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_w/sljit_uw array by index
- SLJIT_FLOAT_SHIFT : the shift required to apply when accessing a double array by index
+ SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index
+ SLJIT_DOUBLE_SHIFT : the shift required to apply when accessing a double array by index
SLJIT_LITTLE_ENDIAN : little endian architecture
SLJIT_BIG_ENDIAN : big endian architecture
SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!)
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET() for more information
+ SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
Types and useful macros:
- 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_sb, sljit_ub : signed and unsigned 8 bit byte
+ sljit_sh, sljit_uh : signed and unsigned 16 bit half-word (short) type
+ sljit_si, sljit_ui : signed and unsigned 32 bit integer type
+ sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer
+ sljit_p : unsgined pointer value (usually the same as sljit_uw, but
+ some 64 bit ABIs may use 32 bit pointers)
+ sljit_s : single precision floating point value
+ sljit_d : double precision floating point value
SLJIT_CALL : C calling convention define for both calling JIT form C and C callbacks for JIT
SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (compiler independent helper)
*/
@@ -57,6 +62,7 @@
|| (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_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|| (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|| (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED))
#error "An architecture must be selected"
@@ -71,6 +77,7 @@
+ (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_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
+ (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
#error "Multiple architectures are selected"
@@ -93,12 +100,14 @@
#else
#define SLJIT_CONFIG_ARM_V5 1
#endif
-#elif defined(__ppc64__) || defined(__powerpc64__)
+#elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_PPC64) || (defined(_POWER) && defined(__64BIT__))
#define SLJIT_CONFIG_PPC_64 1
-#elif defined(__ppc__) || defined(__powerpc__)
+#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER)
#define SLJIT_CONFIG_PPC_32 1
#elif defined(__mips__)
#define SLJIT_CONFIG_MIPS_32 1
+#elif defined(__sparc__) || defined(__sparc)
+#define SLJIT_CONFIG_SPARC_32 1
#else
/* Unsupported architecture */
#define SLJIT_CONFIG_UNSUPPORTED 1
@@ -194,16 +203,31 @@
#ifndef SLJIT_CACHE_FLUSH
-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#if (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)
+
+#elif defined __APPLE__
+
+/* Supported by all macs since Mac OS 10.5.
+ However, it does not work on non-jailbroken iOS devices,
+ although the compilation is successful. */
+
+#define SLJIT_CACHE_FLUSH(from, to) \
+ sys_icache_invalidate((char*)(from), (char*)(to) - (char*)(from))
+
+#elif (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)
+#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
-/* Not required to implement on archs with unified caches. */
-#define SLJIT_CACHE_FLUSH(from, to)
+/* The __clear_cache() implementation of GCC is a dummy function on Sparc. */
+#define SLJIT_CACHE_FLUSH(from, to) \
+ sparc_cache_flush((from), (to))
#else
@@ -217,15 +241,15 @@
/* 8 bit byte type. */
typedef unsigned char sljit_ub;
-typedef signed char sljit_b;
+typedef signed char sljit_sb;
/* 16 bit half-word type. */
typedef unsigned short int sljit_uh;
-typedef signed short int sljit_h;
+typedef signed short int sljit_sh;
/* 32 bit integer type. */
typedef unsigned int sljit_ui;
-typedef signed int sljit_i;
+typedef signed int sljit_si;
/* Machine word type. Can encapsulate a pointer.
32 bit for 32 bit machines.
@@ -234,26 +258,35 @@ typedef signed int sljit_i;
/* Just to have something. */
#define SLJIT_WORD_SHIFT 0
typedef unsigned long int sljit_uw;
-typedef long int sljit_w;
+typedef long int sljit_sw;
#elif !(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;
+typedef int sljit_sw;
#else
#define SLJIT_64BIT_ARCHITECTURE 1
#define SLJIT_WORD_SHIFT 3
#ifdef _WIN32
typedef unsigned __int64 sljit_uw;
-typedef __int64 sljit_w;
+typedef __int64 sljit_sw;
#else
typedef unsigned long int sljit_uw;
-typedef long int sljit_w;
+typedef long int sljit_sw;
#endif
#endif
-/* Double precision. */
-#define SLJIT_FLOAT_SHIFT 3
+typedef sljit_uw sljit_p;
+
+/* Floating point types. */
+typedef float sljit_s;
+typedef double sljit_d;
+
+/* Shift for pointer sized data. */
+#define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT
+
+/* Shift for double precision sized data. */
+#define SLJIT_DOUBLE_SHIFT 3
#ifndef SLJIT_W
@@ -276,20 +309,24 @@ typedef long int sljit_w;
#define SLJIT_CALL __attribute__ ((fastcall))
#define SLJIT_X86_32_FASTCALL 1
-#elif defined(_WIN32)
+#elif defined(_MSC_VER)
-#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
+#elif defined(__BORLANDC__)
+
+#define SLJIT_CALL __msfastcall
+#define SLJIT_X86_32_FASTCALL 1
+
+#else /* Unknown compiler. */
+
+/* The cdecl attribute is the default. */
+#define SLJIT_CALL
+
#endif
-#else /* Other architectures. */
+#else /* Non x86-32 architectures. */
#define SLJIT_CALL
@@ -300,7 +337,9 @@ typedef long int sljit_w;
#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)
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
+ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
+ || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
#define SLJIT_BIG_ENDIAN 1
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
@@ -326,23 +365,32 @@ typedef long int sljit_w;
#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. */
+#ifndef SLJIT_INDIRECT_CALL
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32 && defined _AIX)
+/* It seems certain ppc compilers use an indirect addressing for functions
+ which makes things complicated. */
#define SLJIT_INDIRECT_CALL 1
#endif
+#endif /* SLJIT_INDIRECT_CALL */
+
+#ifndef SLJIT_RETURN_ADDRESS_OFFSET
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+#define SLJIT_RETURN_ADDRESS_OFFSET 8
+#else
+#define SLJIT_RETURN_ADDRESS_OFFSET 0
+#endif
+#endif /* SLJIT_RETURN_ADDRESS_OFFSET */
#ifndef SLJIT_SSE2
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-/* Turn on SSE2 support on x86 (operating on doubles).
- (Better performance than legacy fpu instructions). */
+/* Turn on SSE2 support on x86. */
#define SLJIT_SSE2 1
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
/* Auto detect SSE2 support using CPUID.
On 64 bit x86 cpus, sse2 must be present. */
-#define SLJIT_SSE2_AUTO 1
+#define SLJIT_DETECT_SSE2 1
#endif
#endif /* (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) */
@@ -369,17 +417,28 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
#define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr)
#endif
-#if (defined SLJIT_DEBUG && SLJIT_DEBUG) || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+#if (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
+#if !defined(SLJIT_ASSERT) || !defined(SLJIT_ASSERT_STOP)
+
+/* SLJIT_HALT_PROCESS must halt the process. */
+#ifndef SLJIT_HALT_PROCESS
+#include <stdlib.h>
#define SLJIT_HALT_PROCESS() \
- *((int*)0) = 0
+ abort();
+#endif /* !SLJIT_HALT_PROCESS */
+
+#include <stdio.h>
+
+#endif /* !SLJIT_ASSERT || !SLJIT_ASSERT_STOP */
+
+/* Feel free to redefine these two macros. */
+#ifndef SLJIT_ASSERT
#define SLJIT_ASSERT(x) \
do { \
@@ -403,6 +462,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
+/* Forcing empty, but valid statements. */
#undef SLJIT_ASSERT
#undef SLJIT_ASSERT_STOP
diff --git a/src/3rdparty/pcre/sljit/sljitExecAllocator.c b/src/3rdparty/pcre/sljit/sljitExecAllocator.c
index f66744df82..75a38991d5 100644
--- a/src/3rdparty/pcre/sljit/sljitExecAllocator.c
+++ b/src/3rdparty/pcre/sljit/sljitExecAllocator.c
@@ -52,7 +52,7 @@
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.
@@ -83,7 +83,7 @@
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
{
- return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
}
static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
@@ -94,11 +94,20 @@ static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
#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);
+ void* retval;
+
+#ifdef MAP_ANON
+ retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
+#else
+ if (dev_zero < 0) {
+ if (open_dev_zero())
+ return NULL;
+ }
+ retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, dev_zero, 0);
+#endif
+
return (retval != MAP_FAILED) ? retval : NULL;
}
@@ -202,7 +211,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK;
header = (struct block_header*)alloc_chunk(chunk_size);
- PTR_FAIL_IF(!header);
+ if (!header) {
+ allocator_release_lock();
+ return NULL;
+ }
chunk_size -= sizeof(struct block_header);
total_size += chunk_size;
@@ -237,14 +249,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
struct free_block* free_block;
allocator_grab_lock();
- header = AS_BLOCK_HEADER(ptr, -(sljit_w)sizeof(struct block_header));
+ header = AS_BLOCK_HEADER(ptr, -(sljit_sw)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);
+ free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);
if (SLJIT_UNLIKELY(!free_block->header.size)) {
free_block->size += header->size;
header = AS_BLOCK_HEADER(free_block, free_block->size);
diff --git a/src/3rdparty/pcre/sljit/sljitLir.c b/src/3rdparty/pcre/sljit/sljitLir.c
index c1fa5e4af9..6979841070 100644
--- a/src/3rdparty/pcre/sljit/sljitLir.c
+++ b/src/3rdparty/pcre/sljit/sljitLir.c
@@ -89,7 +89,10 @@
((op) & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C))
#define GET_ALL_FLAGS(op) \
- ((op) & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
+ ((op) & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
+
+#define TYPE_CAST_NEEDED(op) \
+ (((op) >= SLJIT_MOV_UB && (op) <= SLJIT_MOV_SH) || ((op) >= SLJIT_MOVU_UB && (op) <= SLJIT_MOVU_SH))
#define BUF_SIZE 4096
@@ -105,65 +108,145 @@
/* SLJIT_REWRITABLE_JUMP is 0x1000. */
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- #define PATCH_MB 0x4
- #define PATCH_MW 0x8
+# define PATCH_MB 0x4
+# define PATCH_MW 0x8
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- #define PATCH_MD 0x10
+# define PATCH_MD 0x10
#endif
#endif
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
- #define IS_BL 0x4
- #define PATCH_B 0x8
+# define IS_BL 0x4
+# define PATCH_B 0x8
#endif
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- #define CPOOL_SIZE 512
+# define CPOOL_SIZE 512
#endif
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
- #define IS_CONDITIONAL 0x04
- #define IS_BL 0x08
+# define IS_COND 0x04
+# define IS_BL 0x08
/* cannot be encoded as branch */
- #define B_TYPE0 0x00
+# define B_TYPE0 0x00
/* conditional + imm8 */
- #define B_TYPE1 0x10
+# define B_TYPE1 0x10
/* conditional + imm20 */
- #define B_TYPE2 0x20
+# define B_TYPE2 0x20
/* IT + imm24 */
- #define B_TYPE3 0x30
+# define B_TYPE3 0x30
/* imm11 */
- #define B_TYPE4 0x40
+# define B_TYPE4 0x40
/* imm24 */
- #define B_TYPE5 0x50
+# define B_TYPE5 0x50
/* BL + imm24 */
- #define BL_TYPE6 0x60
+# define BL_TYPE6 0x60
/* 0xf00 cc code for branches */
#endif
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- #define UNCOND_B 0x04
- #define PATCH_B 0x08
- #define ABSOLUTE_B 0x10
+# define UNCOND_B 0x04
+# define PATCH_B 0x08
+# define ABSOLUTE_B 0x10
#endif
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- #define IS_MOVABLE 0x04
- #define IS_JAL 0x08
- #define IS_BIT26_COND 0x10
- #define IS_BIT16_COND 0x20
+# define IS_MOVABLE 0x04
+# define IS_JAL 0x08
+# define IS_BIT26_COND 0x10
+# define IS_BIT16_COND 0x20
- #define IS_COND (IS_BIT26_COND | IS_BIT16_COND)
+# define IS_COND (IS_BIT26_COND | IS_BIT16_COND)
- #define PATCH_B 0x40
- #define PATCH_J 0x80
+# define PATCH_B 0x40
+# define PATCH_J 0x80
/* instruction types */
- #define UNMOVABLE_INS 0
+# define MOVABLE_INS 0
/* 1 - 31 last destination register */
- #define FCSR_FCC 32
/* no destination (i.e: store) */
- #define MOVABLE_INS 33
+# define UNMOVABLE_INS 32
+ /* FPU status register */
+# define FCSR_FCC 33
+#endif
+
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+# define IS_MOVABLE 0x04
+# define IS_COND 0x08
+# define IS_CALL 0x10
+
+# define PATCH_B 0x20
+# define PATCH_CALL 0x40
+
+ /* instruction types */
+# define MOVABLE_INS 0
+ /* 1 - 31 last destination register */
+ /* no destination (i.e: store) */
+# define UNMOVABLE_INS 32
+
+# define DST_INS_MASK 0xff
+
+ /* ICC_SET is the same as SET_FLAGS. */
+# define ICC_IS_SET (1 << 23)
+# define FCC_IS_SET (1 << 24)
+#endif
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+#define SLJIT_HAS_VARIABLE_LOCALS_OFFSET 1
+#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+#define FIXED_LOCALS_OFFSET (3 * sizeof(sljit_sw))
+#endif
+#endif
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
+#ifdef _WIN64
+#define FIXED_LOCALS_OFFSET ((4 + 2) * sizeof(sljit_sw))
+#else
+#define FIXED_LOCALS_OFFSET (sizeof(sljit_sw))
+#endif
+#endif
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+#define FIXED_LOCALS_OFFSET ((6 + 8) * sizeof(sljit_sw))
+#else
+#define FIXED_LOCALS_OFFSET (2 * sizeof(sljit_sw))
+#endif
+#endif
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
+#define FIXED_LOCALS_OFFSET ((6 + 8) * sizeof(sljit_sw))
+#endif
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
+#define FIXED_LOCALS_OFFSET (4 * sizeof(sljit_sw))
+#endif
+
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
+#define FIXED_LOCALS_OFFSET (23 * sizeof(sljit_sw))
+#endif
+
+#if (defined SLJIT_HAS_VARIABLE_LOCALS_OFFSET && SLJIT_HAS_VARIABLE_LOCALS_OFFSET)
+
+#define ADJUST_LOCAL_OFFSET(p, i) \
+ if ((p) == (SLJIT_MEM1(SLJIT_LOCALS_REG))) \
+ (i) += compiler->locals_offset;
+
+#elif (defined SLJIT_HAS_FIXED_LOCALS_OFFSET && SLJIT_HAS_FIXED_LOCALS_OFFSET)
+
+#define ADJUST_LOCAL_OFFSET(p, i) \
+ if ((p) == (SLJIT_MEM1(SLJIT_LOCALS_REG))) \
+ (i) += FIXED_LOCALS_OFFSET;
+
+#else
+
+#define ADJUST_LOCAL_OFFSET(p, i)
+
#endif
#endif /* !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) */
@@ -187,12 +270,11 @@
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || ((defined SLJIT_SSE2 && SLJIT_SSE2) && ((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)))
#define SLJIT_NEEDS_COMPILER_INIT 1
-static int compiler_initialized = 0;
+static sljit_si compiler_initialized = 0;
/* A thread safe initialization. */
static void init_compiler(void);
#endif
-
SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
{
struct sljit_compiler *compiler = (struct sljit_compiler*)SLJIT_MALLOC(sizeof(struct sljit_compiler));
@@ -201,11 +283,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
SLJIT_ZEROMEM(compiler, sizeof(struct sljit_compiler));
SLJIT_COMPILE_ASSERT(
- sizeof(sljit_b) == 1 && sizeof(sljit_ub) == 1
- && sizeof(sljit_h) == 2 && sizeof(sljit_uh) == 2
- && sizeof(sljit_i) == 4 && sizeof(sljit_ui) == 4
- && ((sizeof(sljit_w) == 4 && sizeof(sljit_uw) == 4) || (sizeof(sljit_w) == 8 && sizeof(sljit_uw) == 8)),
+ sizeof(sljit_sb) == 1 && sizeof(sljit_ub) == 1
+ && sizeof(sljit_sh) == 2 && sizeof(sljit_uh) == 2
+ && sizeof(sljit_si) == 4 && sizeof(sljit_ui) == 4
+ && (sizeof(sljit_p) == 4 || sizeof(sljit_p) == 8)
+ && sizeof(sljit_p) <= sizeof(sljit_sw)
+ && (sizeof(sljit_sw) == 4 || sizeof(sljit_sw) == 8)
+ && (sizeof(sljit_uw) == 4 || sizeof(sljit_uw) == 8),
invalid_integer_types);
+ SLJIT_COMPILE_ASSERT(SLJIT_INT_OP == SLJIT_SINGLE_OP,
+ int_op_and_single_op_must_be_the_same);
+ SLJIT_COMPILE_ASSERT(SLJIT_REWRITABLE_JUMP != SLJIT_SINGLE_OP,
+ rewritable_jump_and_single_op_must_not_be_the_same);
/* Only the non-zero members must be set. */
compiler->error = SLJIT_SUCCESS;
@@ -227,7 +316,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
compiler->abuf->next = NULL;
compiler->abuf->used_size = 0;
- compiler->temporaries = -1;
+ compiler->scratches = -1;
compiler->saveds = -1;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
@@ -250,6 +339,10 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
compiler->delay_slot = UNMOVABLE_INS;
#endif
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ compiler->delay_slot = UNMOVABLE_INS;
+#endif
+
#if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT)
if (!compiler_initialized) {
init_compiler();
@@ -291,7 +384,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
/* Remove thumb mode flag. */
SLJIT_FREE_EXEC((void*)((sljit_uw)code & ~0x1));
}
-#elif (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#elif (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
{
/* Resolve indirection. */
@@ -329,12 +422,13 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
/* Private functions */
/* --------------------------------------------------------------------- */
-static void* ensure_buf(struct sljit_compiler *compiler, int size)
+static void* ensure_buf(struct sljit_compiler *compiler, sljit_uw size)
{
sljit_ub *ret;
struct sljit_memory_fragment *new_frag;
- if (compiler->buf->used_size + size <= (int)(BUF_SIZE - sizeof(sljit_uw) - sizeof(void*))) {
+ SLJIT_ASSERT(size <= 256);
+ if (compiler->buf->used_size + size <= (BUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) {
ret = compiler->buf->memory + compiler->buf->used_size;
compiler->buf->used_size += size;
return ret;
@@ -347,12 +441,13 @@ static void* ensure_buf(struct sljit_compiler *compiler, int size)
return new_frag->memory;
}
-static void* ensure_abuf(struct sljit_compiler *compiler, int size)
+static void* ensure_abuf(struct sljit_compiler *compiler, sljit_uw size)
{
sljit_ub *ret;
struct sljit_memory_fragment *new_frag;
- if (compiler->abuf->used_size + size <= (int)(ABUF_SIZE - sizeof(sljit_uw) - sizeof(void*))) {
+ SLJIT_ASSERT(size <= 256);
+ if (compiler->abuf->used_size + size <= (ABUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) {
ret = compiler->abuf->memory + compiler->abuf->used_size;
compiler->abuf->used_size += size;
return ret;
@@ -365,7 +460,7 @@ static void* ensure_abuf(struct sljit_compiler *compiler, int size)
return new_frag->memory;
}
-SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size)
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_si size)
{
CHECK_ERROR_PTR();
@@ -408,7 +503,7 @@ static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compi
compiler->last_label = label;
}
-static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, int flags)
+static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_si flags)
{
jump->next = NULL;
jump->flags = flags;
@@ -453,8 +548,8 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
case SLJIT_MUL: \
SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))); \
break; \
- case SLJIT_FCMP: \
- SLJIT_ASSERT(!(op & (SLJIT_INT_OP | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
+ case SLJIT_CMPD: \
+ SLJIT_ASSERT(!(op & (SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
SLJIT_ASSERT((op & (SLJIT_SET_E | SLJIT_SET_S))); \
break; \
case SLJIT_ADD: \
@@ -466,57 +561,66 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
case SLJIT_SUBC: \
SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O))); \
break; \
- default: \
+ case SLJIT_BREAKPOINT: \
+ case SLJIT_NOP: \
+ case SLJIT_UMUL: \
+ case SLJIT_SMUL: \
+ case SLJIT_MOV: \
+ case SLJIT_MOV_P: \
+ case SLJIT_MOVU: \
+ case SLJIT_MOVU_P: \
/* Nothing allowed */ \
SLJIT_ASSERT(!(op & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
break; \
+ default: \
+ /* Only SLJIT_INT_OP or SLJIT_SINGLE_OP is allowed. */ \
+ SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
+ break; \
}
#define FUNCTION_CHECK_IS_REG(r) \
- ((r) == SLJIT_UNUSED || (r) == SLJIT_LOCALS_REG || \
- ((r) >= SLJIT_TEMPORARY_REG1 && (r) <= SLJIT_TEMPORARY_REG3 && (r) <= SLJIT_TEMPORARY_REG1 - 1 + compiler->temporaries) || \
- ((r) >= SLJIT_SAVED_REG1 && (r) <= SLJIT_SAVED_REG3 && (r) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds)) \
+ ((r) == SLJIT_UNUSED || \
+ ((r) >= SLJIT_SCRATCH_REG1 && (r) <= SLJIT_SCRATCH_REG1 - 1 + compiler->scratches) || \
+ ((r) >= SLJIT_SAVED_REG1 && (r) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds))
#define FUNCTION_CHECK_SRC(p, i) \
- SLJIT_ASSERT(compiler->temporaries != -1 && compiler->saveds != -1); \
- if (((p) >= SLJIT_TEMPORARY_REG1 && (p) <= SLJIT_TEMPORARY_REG1 - 1 + compiler->temporaries) || \
- ((p) >= SLJIT_SAVED_REG1 && (p) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds) || \
- (p) == SLJIT_LOCALS_REG) \
- SLJIT_ASSERT(i == 0); \
+ SLJIT_ASSERT(compiler->scratches != -1 && compiler->saveds != -1); \
+ if (FUNCTION_CHECK_IS_REG(p)) \
+ SLJIT_ASSERT((i) == 0 && (p) != SLJIT_UNUSED); \
else if ((p) == SLJIT_IMM) \
; \
+ else if ((p) == (SLJIT_MEM1(SLJIT_LOCALS_REG))) \
+ SLJIT_ASSERT((i) >= 0 && (i) < compiler->logical_local_size); \
else if ((p) & SLJIT_MEM) { \
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \
if ((p) & 0xf0) { \
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \
- SLJIT_ASSERT(((p) & 0xf0) != (SLJIT_LOCALS_REG << 4) && !(i & ~0x3)); \
- } else \
- SLJIT_ASSERT((((p) >> 4) & 0xf) == 0); \
+ SLJIT_ASSERT(!((i) & ~0x3)); \
+ } \
SLJIT_ASSERT(((p) >> 9) == 0); \
} \
else \
SLJIT_ASSERT_STOP();
#define FUNCTION_CHECK_DST(p, i) \
- SLJIT_ASSERT(compiler->temporaries != -1 && compiler->saveds != -1); \
- if (((p) >= SLJIT_TEMPORARY_REG1 && (p) <= SLJIT_TEMPORARY_REG1 - 1 + compiler->temporaries) || \
- ((p) >= SLJIT_SAVED_REG1 && (p) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds) || \
- (p) == SLJIT_UNUSED) \
- SLJIT_ASSERT(i == 0); \
+ SLJIT_ASSERT(compiler->scratches != -1 && compiler->saveds != -1); \
+ if (FUNCTION_CHECK_IS_REG(p)) \
+ SLJIT_ASSERT((i) == 0); \
+ else if ((p) == (SLJIT_MEM1(SLJIT_LOCALS_REG))) \
+ SLJIT_ASSERT((i) >= 0 && (i) < compiler->logical_local_size); \
else if ((p) & SLJIT_MEM) { \
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \
if ((p) & 0xf0) { \
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \
- SLJIT_ASSERT(((p) & 0xf0) != (SLJIT_LOCALS_REG << 4) && !(i & ~0x3)); \
- } else \
- SLJIT_ASSERT((((p) >> 4) & 0xf) == 0); \
+ SLJIT_ASSERT(!((i) & ~0x3)); \
+ } \
SLJIT_ASSERT(((p) >> 9) == 0); \
} \
else \
SLJIT_ASSERT_STOP();
#define FUNCTION_FCHECK(p, i) \
- if ((p) >= SLJIT_FLOAT_REG1 && (p) <= SLJIT_FLOAT_REG4) \
+ if ((p) >= SLJIT_FLOAT_REG1 && (p) <= SLJIT_FLOAT_REG6) \
SLJIT_ASSERT(i == 0); \
else if ((p) & SLJIT_MEM) { \
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \
@@ -531,10 +635,7 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
SLJIT_ASSERT_STOP();
#define FUNCTION_CHECK_OP1() \
- if (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI) { \
- SLJIT_ASSERT(!GET_ALL_FLAGS(op)); \
- } \
- if (GET_OPCODE(op) >= SLJIT_MOVU && GET_OPCODE(op) <= SLJIT_MOVU_SI) { \
+ if (GET_OPCODE(op) >= SLJIT_MOVU && GET_OPCODE(op) <= SLJIT_MOVU_P) { \
SLJIT_ASSERT(!(src & SLJIT_MEM) || (src & 0xf) != SLJIT_LOCALS_REG); \
SLJIT_ASSERT(!(dst & SLJIT_MEM) || (dst & 0xf) != SLJIT_LOCALS_REG); \
if ((src & SLJIT_MEM) && (src & 0xf)) \
@@ -557,29 +658,30 @@ static char* reg_names[] = {
};
static char* freg_names[] = {
- (char*)"<noreg>", (char*)"float_r1", (char*)"float_r2", (char*)"float_r3", (char*)"float_r4"
+ (char*)"<noreg>", (char*)"float_r1", (char*)"float_r2", (char*)"float_r3",
+ (char*)"float_r4", (char*)"float_r5", (char*)"float_r6"
};
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
#ifdef _WIN64
- #define SLJIT_PRINT_D "I64"
+# define SLJIT_PRINT_D "I64"
#else
- #define SLJIT_PRINT_D "l"
+# define SLJIT_PRINT_D "l"
#endif
#else
- #define SLJIT_PRINT_D ""
+# define SLJIT_PRINT_D ""
#endif
#define sljit_verbose_param(p, i) \
if ((p) & SLJIT_IMM) \
- fprintf(compiler->verbose, "#%"SLJIT_PRINT_D"d", (i)); \
+ fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i)); \
else if ((p) & SLJIT_MEM) { \
if ((p) & 0xf) { \
if (i) { \
if (((p) >> 4) & 0xf) \
fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF], 1 << (i)); \
else \
- fprintf(compiler->verbose, "[%s + #%"SLJIT_PRINT_D"d]", reg_names[(p) & 0xF], (i)); \
+ fprintf(compiler->verbose, "[%s + #%" SLJIT_PRINT_D "d]", reg_names[(p) & 0xF], (i)); \
} \
else { \
if (((p) >> 4) & 0xf) \
@@ -589,7 +691,7 @@ static char* freg_names[] = {
} \
} \
else \
- fprintf(compiler->verbose, "[#%"SLJIT_PRINT_D"d]", (i)); \
+ fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); \
} else \
fprintf(compiler->verbose, "%s", reg_names[p]);
#define sljit_verbose_fparam(p, i) \
@@ -599,7 +701,7 @@ static char* freg_names[] = {
if (((p) >> 4) & 0xf) \
fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF], 1 << (i)); \
else \
- fprintf(compiler->verbose, "[%s + #%"SLJIT_PRINT_D"d]", reg_names[(p) & 0xF], (i)); \
+ fprintf(compiler->verbose, "[%s + #%" SLJIT_PRINT_D "d]", reg_names[(p) & 0xF], (i)); \
} \
else { \
if (((p) >> 4) & 0xF) \
@@ -609,7 +711,7 @@ static char* freg_names[] = {
} \
} \
else \
- fprintf(compiler->verbose, "[#%"SLJIT_PRINT_D"d]", (i)); \
+ fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); \
} else \
fprintf(compiler->verbose, "%s", freg_names[p]);
@@ -619,18 +721,18 @@ static SLJIT_CONST char* op_names[] = {
(char*)"umul", (char*)"smul", (char*)"udiv", (char*)"sdiv",
/* op1 */
(char*)"mov", (char*)"mov.ub", (char*)"mov.sb", (char*)"mov.uh",
- (char*)"mov.sh", (char*)"mov.ui", (char*)"mov.si", (char*)"movu",
- (char*)"movu.ub", (char*)"movu.sb", (char*)"movu.uh", (char*)"movu.sh",
- (char*)"movu.ui", (char*)"movu.si", (char*)"not", (char*)"neg",
- (char*)"clz",
+ (char*)"mov.sh", (char*)"mov.ui", (char*)"mov.si", (char*)"mov.p",
+ (char*)"movu", (char*)"movu.ub", (char*)"movu.sb", (char*)"movu.uh",
+ (char*)"movu.sh", (char*)"movu.ui", (char*)"movu.si", (char*)"movu.p",
+ (char*)"not", (char*)"neg", (char*)"clz",
/* op2 */
(char*)"add", (char*)"addc", (char*)"sub", (char*)"subc",
(char*)"mul", (char*)"and", (char*)"or", (char*)"xor",
(char*)"shl", (char*)"lshr", (char*)"ashr",
/* fop1 */
- (char*)"fcmp", (char*)"fmov", (char*)"fneg", (char*)"fabs",
+ (char*)"cmp", (char*)"mov", (char*)"neg", (char*)"abs",
/* fop2 */
- (char*)"fadd", (char*)"fsub", (char*)"fmul", (char*)"fdiv"
+ (char*)"add", (char*)"sub", (char*)"mul", (char*)"div"
};
static char* jump_names[] = {
@@ -644,7 +746,7 @@ static char* jump_names[] = {
(char*)"c_float_equal", (char*)"c_float_not_equal",
(char*)"c_float_less", (char*)"c_float_greater_equal",
(char*)"c_float_greater", (char*)"c_float_less_equal",
- (char*)"c_float_nan", (char*)"c_float_not_nan",
+ (char*)"c_float_unordered", (char*)"c_float_ordered",
(char*)"jump", (char*)"fast_call",
(char*)"call0", (char*)"call1", (char*)"call2", (char*)"call3"
};
@@ -674,47 +776,54 @@ static SLJIT_INLINE void check_sljit_generate_code(struct sljit_compiler *compil
#endif
}
-static SLJIT_INLINE void check_sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+static SLJIT_INLINE void check_sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(args);
- SLJIT_UNUSED_ARG(temporaries);
+ SLJIT_UNUSED_ARG(scratches);
SLJIT_UNUSED_ARG(saveds);
SLJIT_UNUSED_ARG(local_size);
SLJIT_ASSERT(args >= 0 && args <= 3);
- SLJIT_ASSERT(temporaries >= 0 && temporaries <= SLJIT_NO_TMP_REGISTERS);
+ SLJIT_ASSERT(scratches >= 0 && scratches <= SLJIT_NO_TMP_REGISTERS);
SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS);
SLJIT_ASSERT(args <= saveds);
SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose))
- fprintf(compiler->verbose, " enter args=%d temporaries=%d saveds=%d local_size=%d\n", args, temporaries, saveds, local_size);
+ fprintf(compiler->verbose, " enter args=%d scratches=%d saveds=%d local_size=%d\n", args, scratches, saveds, local_size);
#endif
}
-static SLJIT_INLINE void check_sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+static SLJIT_INLINE void check_sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(args);
- SLJIT_UNUSED_ARG(temporaries);
+ SLJIT_UNUSED_ARG(scratches);
SLJIT_UNUSED_ARG(saveds);
SLJIT_UNUSED_ARG(local_size);
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ return;
+ }
+#endif
+
SLJIT_ASSERT(args >= 0 && args <= 3);
- SLJIT_ASSERT(temporaries >= 0 && temporaries <= SLJIT_NO_TMP_REGISTERS);
+ SLJIT_ASSERT(scratches >= 0 && scratches <= SLJIT_NO_TMP_REGISTERS);
SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS);
SLJIT_ASSERT(args <= saveds);
SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose))
- fprintf(compiler->verbose, " fake_enter args=%d temporaries=%d saveds=%d local_size=%d\n", args, temporaries, saveds, local_size);
+ fprintf(compiler->verbose, " set_context args=%d scratches=%d saveds=%d local_size=%d\n", args, scratches, saveds, local_size);
#endif
}
-static SLJIT_INLINE void check_sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+static SLJIT_INLINE void check_sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
@@ -724,7 +833,7 @@ static SLJIT_INLINE void check_sljit_emit_return(struct sljit_compiler *compiler
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
if (op != SLJIT_UNUSED) {
- SLJIT_ASSERT(op >= SLJIT_MOV && op <= SLJIT_MOV_SI);
+ SLJIT_ASSERT(op >= SLJIT_MOV && op <= SLJIT_MOV_P);
FUNCTION_CHECK_SRC(src, srcw);
}
else
@@ -743,39 +852,26 @@ static SLJIT_INLINE void check_sljit_emit_return(struct sljit_compiler *compiler
#endif
}
-static SLJIT_INLINE void check_sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+static SLJIT_INLINE void check_sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(dst);
SLJIT_UNUSED_ARG(dstw);
- SLJIT_UNUSED_ARG(args);
- SLJIT_UNUSED_ARG(temporaries);
- SLJIT_UNUSED_ARG(saveds);
- SLJIT_UNUSED_ARG(local_size);
- SLJIT_ASSERT(args >= 0 && args <= 3);
- SLJIT_ASSERT(temporaries >= 0 && temporaries <= SLJIT_NO_TMP_REGISTERS);
- SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS);
- SLJIT_ASSERT(args <= saveds);
- SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
- compiler->temporaries = temporaries;
- compiler->saveds = saveds;
FUNCTION_CHECK_DST(dst, dstw);
- compiler->temporaries = -1;
- compiler->saveds = -1;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " fast_enter ");
sljit_verbose_param(dst, dstw);
- fprintf(compiler->verbose, " args=%d temporaries=%d saveds=%d local_size=%d\n", args, temporaries, saveds, local_size);
+ fprintf(compiler->verbose, "\n");
}
#endif
}
-static SLJIT_INLINE void check_sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+static SLJIT_INLINE void check_sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
@@ -794,7 +890,7 @@ static SLJIT_INLINE void check_sljit_emit_fast_return(struct sljit_compiler *com
#endif
}
-static SLJIT_INLINE void check_sljit_emit_op0(struct sljit_compiler *compiler, int op)
+static SLJIT_INLINE void check_sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
@@ -808,9 +904,9 @@ static SLJIT_INLINE void check_sljit_emit_op0(struct sljit_compiler *compiler, i
#endif
}
-static SLJIT_INLINE void check_sljit_emit_op1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+static SLJIT_INLINE void check_sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
@@ -837,7 +933,8 @@ static SLJIT_INLINE void check_sljit_emit_op1(struct sljit_compiler *compiler, i
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)],
- !(op & SLJIT_SET_E) ? "" : "E", !(op & SLJIT_SET_S) ? "" : "S", !(op & SLJIT_SET_U) ? "" : "U", !(op & SLJIT_SET_O) ? "" : "O", !(op & SLJIT_SET_C) ? "" : "C", !(op & SLJIT_KEEP_FLAGS) ? "" : "K");
+ !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_S) ? "" : ".s", !(op & SLJIT_SET_U) ? "" : ".u",
+ !(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
sljit_verbose_param(dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(src, srcw);
@@ -846,10 +943,10 @@ static SLJIT_INLINE void check_sljit_emit_op1(struct sljit_compiler *compiler, i
#endif
}
-static SLJIT_INLINE void check_sljit_emit_op2(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+static SLJIT_INLINE void check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
@@ -878,7 +975,8 @@ static SLJIT_INLINE void check_sljit_emit_op2(struct sljit_compiler *compiler, i
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)],
- !(op & SLJIT_SET_E) ? "" : "E", !(op & SLJIT_SET_S) ? "" : "S", !(op & SLJIT_SET_U) ? "" : "U", !(op & SLJIT_SET_O) ? "" : "O", !(op & SLJIT_SET_C) ? "" : "C", !(op & SLJIT_KEEP_FLAGS) ? "" : "K");
+ !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_S) ? "" : ".s", !(op & SLJIT_SET_U) ? "" : ".u",
+ !(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
sljit_verbose_param(dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(src1, src1w);
@@ -889,14 +987,14 @@ static SLJIT_INLINE void check_sljit_emit_op2(struct sljit_compiler *compiler, i
#endif
}
-static SLJIT_INLINE void check_sljit_get_register_index(int reg)
+static SLJIT_INLINE void check_sljit_get_register_index(sljit_si reg)
{
SLJIT_UNUSED_ARG(reg);
SLJIT_ASSERT(reg > 0 && reg <= SLJIT_NO_REGISTERS);
}
static SLJIT_INLINE void check_sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, int size)
+ void *instruction, sljit_si size)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(instruction);
@@ -904,9 +1002,9 @@ static SLJIT_INLINE void check_sljit_emit_op_custom(struct sljit_compiler *compi
SLJIT_ASSERT(instruction);
}
-static SLJIT_INLINE void check_sljit_emit_fop1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+static SLJIT_INLINE void check_sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
@@ -924,7 +1022,7 @@ static SLJIT_INLINE void check_sljit_emit_fop1(struct sljit_compiler *compiler,
#endif
SLJIT_ASSERT(sljit_is_fpu_available());
- SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_FCMP && GET_OPCODE(op) <= SLJIT_FABS);
+ SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_CMPD && GET_OPCODE(op) <= SLJIT_ABSD);
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
FUNCTION_CHECK_OP();
FUNCTION_FCHECK(src, srcw);
@@ -932,8 +1030,8 @@ static SLJIT_INLINE void check_sljit_emit_fop1(struct sljit_compiler *compiler,
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " %s%s%s ", op_names[GET_OPCODE(op)],
- !(op & SLJIT_SET_E) ? "" : "E", !(op & SLJIT_SET_S) ? "" : "S");
+ fprintf(compiler->verbose, " %s%s%s%s ", op_names[GET_OPCODE(op)], (op & SLJIT_SINGLE_OP) ? "s" : "d",
+ !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_S) ? "" : ".s");
sljit_verbose_fparam(dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(src, srcw);
@@ -942,10 +1040,10 @@ static SLJIT_INLINE void check_sljit_emit_fop1(struct sljit_compiler *compiler,
#endif
}
-static SLJIT_INLINE void check_sljit_emit_fop2(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+static SLJIT_INLINE void check_sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
@@ -958,7 +1056,7 @@ static SLJIT_INLINE void check_sljit_emit_fop2(struct sljit_compiler *compiler,
SLJIT_UNUSED_ARG(src2w);
SLJIT_ASSERT(sljit_is_fpu_available());
- SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_FADD && GET_OPCODE(op) <= SLJIT_FDIV);
+ SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_ADDD && GET_OPCODE(op) <= SLJIT_DIVD);
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
FUNCTION_CHECK_OP();
FUNCTION_FCHECK(src1, src1w);
@@ -967,7 +1065,7 @@ static SLJIT_INLINE void check_sljit_emit_fop2(struct sljit_compiler *compiler,
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " %s ", op_names[GET_OPCODE(op)]);
+ fprintf(compiler->verbose, " %s%s ", op_names[GET_OPCODE(op)], (op & SLJIT_SINGLE_OP) ? "s" : "d");
sljit_verbose_fparam(dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(src1, src1w);
@@ -989,7 +1087,7 @@ static SLJIT_INLINE void check_sljit_emit_label(struct sljit_compiler *compiler)
#endif
}
-static SLJIT_INLINE void check_sljit_emit_jump(struct sljit_compiler *compiler, int type)
+static SLJIT_INLINE void check_sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
@@ -1006,13 +1104,13 @@ static SLJIT_INLINE void check_sljit_emit_jump(struct sljit_compiler *compiler,
SLJIT_ASSERT((type & 0xff) >= SLJIT_C_EQUAL && (type & 0xff) <= SLJIT_CALL3);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose))
- fprintf(compiler->verbose, " jump%s <%s>\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : "R", jump_names[type & 0xff]);
+ fprintf(compiler->verbose, " jump%s<%s>\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);
#endif
}
-static SLJIT_INLINE void check_sljit_emit_cmp(struct sljit_compiler *compiler, int type,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+static SLJIT_INLINE void check_sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
@@ -1021,7 +1119,7 @@ static SLJIT_INLINE void check_sljit_emit_cmp(struct sljit_compiler *compiler, i
SLJIT_UNUSED_ARG(src2);
SLJIT_UNUSED_ARG(src2w);
- SLJIT_ASSERT(!(type & ~(0xff | SLJIT_INT_OP | SLJIT_REWRITABLE_JUMP)));
+ SLJIT_ASSERT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_INT_OP)));
SLJIT_ASSERT((type & 0xff) >= SLJIT_C_EQUAL && (type & 0xff) <= SLJIT_C_SIG_LESS_EQUAL);
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
FUNCTION_CHECK_SRC(src1, src1w);
@@ -1029,7 +1127,7 @@ static SLJIT_INLINE void check_sljit_emit_cmp(struct sljit_compiler *compiler, i
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " %scmp%s <%s> ", !(type & SLJIT_INT_OP) ? "" : "i", !(type & SLJIT_REWRITABLE_JUMP) ? "" : "R", jump_names[type & 0xff]);
+ fprintf(compiler->verbose, " %scmp%s<%s> ", !(type & SLJIT_INT_OP) ? "" : "i", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);
sljit_verbose_param(src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(src2, src2w);
@@ -1038,9 +1136,9 @@ static SLJIT_INLINE void check_sljit_emit_cmp(struct sljit_compiler *compiler, i
#endif
}
-static SLJIT_INLINE void check_sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+static SLJIT_INLINE void check_sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
@@ -1050,15 +1148,16 @@ static SLJIT_INLINE void check_sljit_emit_fcmp(struct sljit_compiler *compiler,
SLJIT_UNUSED_ARG(src2w);
SLJIT_ASSERT(sljit_is_fpu_available());
- SLJIT_ASSERT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP)));
- SLJIT_ASSERT((type & 0xff) >= SLJIT_C_FLOAT_EQUAL && (type & 0xff) <= SLJIT_C_FLOAT_NOT_NAN);
+ SLJIT_ASSERT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_SINGLE_OP)));
+ SLJIT_ASSERT((type & 0xff) >= SLJIT_C_FLOAT_EQUAL && (type & 0xff) <= SLJIT_C_FLOAT_ORDERED);
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
FUNCTION_FCHECK(src1, src1w);
FUNCTION_FCHECK(src2, src2w);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " fcmp%s <%s> ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : "R", jump_names[type & 0xff]);
+ fprintf(compiler->verbose, " %scmp%s<%s> ", (type & SLJIT_SINGLE_OP) ? "s" : "d",
+ !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);
sljit_verbose_fparam(src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(src2, src2w);
@@ -1067,7 +1166,7 @@ static SLJIT_INLINE void check_sljit_emit_fcmp(struct sljit_compiler *compiler,
#endif
}
-static SLJIT_INLINE void check_sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+static SLJIT_INLINE void check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
@@ -1075,45 +1174,87 @@ static SLJIT_INLINE void check_sljit_emit_ijump(struct sljit_compiler *compiler,
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ return;
+ }
+#endif
+
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL3);
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
FUNCTION_CHECK_SRC(src, srcw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " ijump <%s> ", jump_names[type]);
+ fprintf(compiler->verbose, " ijump<%s> ", jump_names[type]);
sljit_verbose_param(src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
}
-static SLJIT_INLINE void check_sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+static SLJIT_INLINE void check_sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw,
+ sljit_si type)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
SLJIT_UNUSED_ARG(dst);
SLJIT_UNUSED_ARG(dstw);
+ SLJIT_UNUSED_ARG(src);
+ SLJIT_UNUSED_ARG(srcw);
SLJIT_UNUSED_ARG(type);
SLJIT_ASSERT(type >= SLJIT_C_EQUAL && type < SLJIT_JUMP);
- SLJIT_ASSERT(op == SLJIT_MOV || GET_OPCODE(op) == SLJIT_OR);
- SLJIT_ASSERT(GET_ALL_FLAGS(op) == 0 || GET_ALL_FLAGS(op) == SLJIT_SET_E || GET_ALL_FLAGS(op) == SLJIT_KEEP_FLAGS);
+ SLJIT_ASSERT(op == SLJIT_MOV || GET_OPCODE(op) == SLJIT_MOV_UI || GET_OPCODE(op) == SLJIT_MOV_SI
+ || (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR));
+ SLJIT_ASSERT((op & (SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C)) == 0);
+ SLJIT_ASSERT((op & (SLJIT_SET_E | SLJIT_KEEP_FLAGS)) != (SLJIT_SET_E | SLJIT_KEEP_FLAGS));
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ if (GET_OPCODE(op) < SLJIT_ADD) {
+ SLJIT_ASSERT(src == SLJIT_UNUSED && srcw == 0);
+ } else {
+ SLJIT_ASSERT(src == dst && srcw == dstw);
+ }
FUNCTION_CHECK_DST(dst, dstw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " cond_set%s%s <%s> ", !(op & SLJIT_SET_E) ? "" : "E",
- !(op & SLJIT_KEEP_FLAGS) ? "" : "K", op_names[GET_OPCODE(op)]);
+ fprintf(compiler->verbose, " op_flags<%s%s%s%s> ", !(op & SLJIT_INT_OP) ? "" : "i",
+ op_names[GET_OPCODE(op)], !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
sljit_verbose_param(dst, dstw);
+ if (src != SLJIT_UNUSED) {
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(src, srcw);
+ }
fprintf(compiler->verbose, ", <%s>\n", jump_names[type]);
}
#endif
}
-static SLJIT_INLINE void check_sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
+static SLJIT_INLINE void check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(dst);
+ SLJIT_UNUSED_ARG(dstw);
+ SLJIT_UNUSED_ARG(offset);
+
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ FUNCTION_CHECK_DST(dst, dstw);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " local_base ");
+ sljit_verbose_param(dst, dstw);
+ fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", offset);
+ }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
{
/* If debug and verbose are disabled, all arguments are unused. */
SLJIT_UNUSED_ARG(compiler);
@@ -1128,22 +1269,23 @@ static SLJIT_INLINE void check_sljit_emit_const(struct sljit_compiler *compiler,
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " const ");
sljit_verbose_param(dst, dstw);
- fprintf(compiler->verbose, ", #%"SLJIT_PRINT_D"d\n", init_value);
+ fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", init_value);
}
#endif
}
-static SLJIT_INLINE int emit_mov_before_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+static SLJIT_INLINE sljit_si emit_mov_before_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
/* Return if don't need to do anything. */
if (op == SLJIT_UNUSED)
return SLJIT_SUCCESS;
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
- if (src == SLJIT_RETURN_REG && op == SLJIT_MOV)
+ /* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */
+ if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_P))
return SLJIT_SUCCESS;
#else
- if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI))
+ if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI || op == SLJIT_MOV_P))
return SLJIT_SUCCESS;
#endif
@@ -1180,32 +1322,34 @@ static SLJIT_INLINE int emit_mov_before_return(struct sljit_compiler *compiler,
#define SLJIT_CPUINFO SLJIT_CPUINFO_PART1 SLJIT_CPUINFO_PART2 SLJIT_CPUINFO_PART3
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- #include "sljitNativeX86_common.c"
+# include "sljitNativeX86_common.c"
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- #include "sljitNativeX86_common.c"
+# include "sljitNativeX86_common.c"
#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- #include "sljitNativeARM_v5.c"
+# include "sljitNativeARM_v5.c"
#elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
- #include "sljitNativeARM_v5.c"
+# include "sljitNativeARM_v5.c"
#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
- #include "sljitNativeARM_Thumb2.c"
+# include "sljitNativeARM_Thumb2.c"
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- #include "sljitNativePPC_common.c"
+# include "sljitNativePPC_common.c"
#elif (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- #include "sljitNativePPC_common.c"
+# include "sljitNativePPC_common.c"
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- #include "sljitNativeMIPS_common.c"
+# include "sljitNativeMIPS_common.c"
+#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+# include "sljitNativeSPARC_common.c"
#endif
#if !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-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)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
/* Default compare for most architectures. */
- int flags, tmp_src, condition;
- sljit_w tmp_srcw;
+ sljit_si flags, tmp_src, condition;
+ sljit_sw tmp_srcw;
CHECK_ERROR_PTR();
check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w);
@@ -1266,24 +1410,23 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP));
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- int flags, condition;
+ sljit_si flags, condition;
check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w);
condition = type & 0xff;
- if (condition <= SLJIT_C_FLOAT_NOT_EQUAL)
- flags = SLJIT_SET_E;
- else
- flags = SLJIT_SET_S;
+ flags = (condition <= SLJIT_C_FLOAT_NOT_EQUAL) ? SLJIT_SET_E : SLJIT_SET_S;
+ if (type & SLJIT_SINGLE_OP)
+ flags |= SLJIT_SINGLE_OP;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
compiler->skip_checks = 1;
#endif
- sljit_emit_fop1(compiler, SLJIT_FCMP | flags, src1, src1w, src2, src2w);
+ sljit_emit_fop1(compiler, SLJIT_CMPD | flags, src1, src1w, src2, src2w);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
compiler->skip_checks = 1;
@@ -1293,11 +1436,29 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
#endif
+#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) && !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
+{
+ CHECK_ERROR();
+ check_sljit_get_local_base(compiler, dst, dstw, offset);
+
+ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_LOCALS_REG), offset);
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->skip_checks = 1;
+#endif
+ if (offset != 0)
+ return sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, SLJIT_IMM, offset);
+ return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_LOCALS_REG, 0);
+}
+
+#endif
+
#else /* SLJIT_CONFIG_UNSUPPORTED */
/* Empty function bodies for those machines, which are not (yet) supported. */
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
{
return "unsupported";
}
@@ -1314,7 +1475,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compile
SLJIT_ASSERT_STOP();
}
-SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size)
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_si size)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(size);
@@ -1344,28 +1505,28 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
SLJIT_ASSERT_STOP();
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(args);
- SLJIT_UNUSED_ARG(temporaries);
+ SLJIT_UNUSED_ARG(scratches);
SLJIT_UNUSED_ARG(saveds);
SLJIT_UNUSED_ARG(local_size);
SLJIT_ASSERT_STOP();
return SLJIT_ERR_UNSUPPORTED;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(args);
- SLJIT_UNUSED_ARG(temporaries);
+ SLJIT_UNUSED_ARG(scratches);
SLJIT_UNUSED_ARG(saveds);
SLJIT_UNUSED_ARG(local_size);
SLJIT_ASSERT_STOP();
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
@@ -1375,20 +1536,16 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
return SLJIT_ERR_UNSUPPORTED;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(dst);
SLJIT_UNUSED_ARG(dstw);
- SLJIT_UNUSED_ARG(args);
- SLJIT_UNUSED_ARG(temporaries);
- SLJIT_UNUSED_ARG(saveds);
- SLJIT_UNUSED_ARG(local_size);
SLJIT_ASSERT_STOP();
return SLJIT_ERR_UNSUPPORTED;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(src);
@@ -1397,7 +1554,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
return SLJIT_ERR_UNSUPPORTED;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
@@ -1405,9 +1562,9 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
return SLJIT_ERR_UNSUPPORTED;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
@@ -1419,10 +1576,10 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
return SLJIT_ERR_UNSUPPORTED;
}
-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 sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
@@ -1436,14 +1593,14 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
return SLJIT_ERR_UNSUPPORTED;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
{
SLJIT_ASSERT_STOP();
return reg;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, int size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_si size)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(instruction);
@@ -1452,15 +1609,15 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compile
return SLJIT_ERR_UNSUPPORTED;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
SLJIT_ASSERT_STOP();
return 0;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
@@ -1472,10 +1629,10 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, in
return SLJIT_ERR_UNSUPPORTED;
}
-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)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
@@ -1496,7 +1653,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return NULL;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
@@ -1504,9 +1661,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
return NULL;
}
-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)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
@@ -1518,9 +1675,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
return NULL;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
@@ -1546,7 +1703,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
SLJIT_ASSERT_STOP();
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
@@ -1556,18 +1713,33 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, i
return SLJIT_ERR_UNSUPPORTED;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw,
+ sljit_si type)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
SLJIT_UNUSED_ARG(dst);
SLJIT_UNUSED_ARG(dstw);
+ SLJIT_UNUSED_ARG(src);
+ SLJIT_UNUSED_ARG(srcw);
SLJIT_UNUSED_ARG(type);
SLJIT_ASSERT_STOP();
return SLJIT_ERR_UNSUPPORTED;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w initval)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(dst);
+ SLJIT_UNUSED_ARG(dstw);
+ SLJIT_UNUSED_ARG(offset);
+ SLJIT_ASSERT_STOP();
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw initval)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(dst);
@@ -1584,7 +1756,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ad
SLJIT_ASSERT_STOP();
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
{
SLJIT_UNUSED_ARG(addr);
SLJIT_UNUSED_ARG(new_constant);
diff --git a/src/3rdparty/pcre/sljit/sljitLir.h b/src/3rdparty/pcre/sljit/sljitLir.h
index 0cb1c1e589..3171d1557c 100644
--- a/src/3rdparty/pcre/sljit/sljitLir.h
+++ b/src/3rdparty/pcre/sljit/sljitLir.h
@@ -34,28 +34,39 @@
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
+ - The execution can be continued from any LIR instruction. In other
+ words, it is possible to jump to any label from anywhere, even from
+ a code fragment, which is compiled later, if both compiled code
+ shares the same context. See sljit_emit_enter for more details
+ - Supports self modifying code: target of (conditional) jump and call
+ instructions and some constant values can be dynamically modified
+ during runtime
- although it is not suggested to do it frequently
- - very effective to cache an important value once
+ - can be used for inline caching: save an important value once
+ in the instruction stream
+ - since this feature limits the optimization possibilities, a
+ special flag must be passed at compile time when these
+ instructions are emitted
- A fixed stack space can be allocated for local variables
- The compiler is thread-safe
+ - The compiler is highly configurable through preprocessor macros.
+ You can disable unneeded features (multithreading in single
+ threaded applications), and you can use your own system functions
+ (including memory allocators). See sljitConfig.h
Disadvantages:
+ - No automatic register allocation, and temporary results are
+ not stored on the stack. (hence the name comes)
- Limited number of registers (only 6+4 integer registers, max 3+2
- temporary, max 3+2 saved and 4 floating point registers)
+ scratch, max 3+2 saved and 6 floating point registers)
In practice:
- This approach is very effective for interpreters
- One of the saved registers typically points to a stack interface
- - 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
+ - It can jump to any exception handler anytime (even if it belongs
+ to another function)
+ - Hot 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)
+ - mainly position and context independent code (except some cases)
For valgrind users:
- pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code"
@@ -95,12 +106,14 @@ of sljitConfigInternal.h */
#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). */
+/* Scratch (temporary) registers whose may not preserve their values
+ across function calls. */
+#define SLJIT_SCRATCH_REG1 1
+#define SLJIT_SCRATCH_REG2 2
+#define SLJIT_SCRATCH_REG3 3
+/* Note: extra registers cannot be used for memory addressing. */
+/* Note: on x86-32, these registers are emulated (using stack
+ loads & stores). */
#define SLJIT_TEMPORARY_EREG1 4
#define SLJIT_TEMPORARY_EREG2 5
@@ -108,14 +121,17 @@ of sljitConfigInternal.h */
#define SLJIT_SAVED_REG1 6
#define SLJIT_SAVED_REG2 7
#define SLJIT_SAVED_REG3 8
-/* Note: Extra Registers cannot be used for memory addressing. */
-/* Note: on x86-32, these registers are emulated (using stack loads & stores). */
+/* Note: extra registers cannot be used for memory addressing. */
+/* Note: on x86-32, these registers are emulated (using stack
+ loads & stores). */
#define SLJIT_SAVED_EREG1 9
#define SLJIT_SAVED_EREG2 10
-/* 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. */
+/* Read-only register (cannot be the destination of an operation).
+ Only SLJIT_MEM1(SLJIT_LOCALS_REG) addressing mode is allowed since
+ several ABIs has certain limitations about the stack layout. However
+ sljit_get_local_base() can be used to obtain the offset of a value
+ on the stack. */
#define SLJIT_LOCALS_REG 11
/* Number of registers. */
@@ -125,15 +141,15 @@ of sljitConfigInternal.h */
/* Return with machine word. */
-#define SLJIT_RETURN_REG SLJIT_TEMPORARY_REG1
+#define SLJIT_RETURN_REG SLJIT_SCRATCH_REG1
/* x86 prefers specific registers for special purposes. In case of shift
- by register it supports only SLJIT_TEMPORARY_REG3 for shift argument
+ by register it supports only SLJIT_SCRATCH_REG3 for shift argument
(which is the src2 argument of sljit_emit_op2). If another register is
used, sljit must exchange data between registers which cause a minor
slowdown. Other architectures has no such limitation. */
-#define SLJIT_PREF_SHIFT_REG SLJIT_TEMPORARY_REG3
+#define SLJIT_PREF_SHIFT_REG SLJIT_SCRATCH_REG3
/* --------------------------------------------------------------------- */
/* Floating point registers */
@@ -142,12 +158,15 @@ of sljitConfigInternal.h */
/* 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. */
+/* Floating point operations are performed on double or
+ single precision values. */
#define SLJIT_FLOAT_REG1 1
#define SLJIT_FLOAT_REG2 2
#define SLJIT_FLOAT_REG3 3
#define SLJIT_FLOAT_REG4 4
+#define SLJIT_FLOAT_REG5 5
+#define SLJIT_FLOAT_REG6 6
/* --------------------------------------------------------------------- */
/* Main structures and functions */
@@ -156,6 +175,7 @@ of sljitConfigInternal.h */
struct sljit_memory_fragment {
struct sljit_memory_fragment *next;
sljit_uw used_size;
+ /* Must be aligned to sljit_sw. */
sljit_ub memory[1];
};
@@ -169,7 +189,7 @@ struct sljit_label {
struct sljit_jump {
struct sljit_jump *next;
sljit_uw addr;
- sljit_w flags;
+ sljit_sw flags;
union {
sljit_uw target;
struct sljit_label* label;
@@ -182,7 +202,7 @@ struct sljit_const {
};
struct sljit_compiler {
- int error;
+ sljit_si error;
struct sljit_label *labels;
struct sljit_jump *jumps;
@@ -195,31 +215,29 @@ struct sljit_compiler {
struct sljit_memory_fragment *abuf;
/* Used local registers. */
- int temporaries;
+ sljit_si scratches;
/* Used saved registers. */
- int saveds;
+ sljit_si saveds;
/* Local stack size. */
- int local_size;
+ sljit_si 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 saveds_start;
+ sljit_si args;
+ sljit_si locals_offset;
+ sljit_si scratches_start;
+ sljit_si saveds_start;
#endif
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- int mode32;
-#ifdef _WIN64
- int has_locals;
-#endif
+ sljit_si mode32;
#endif
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- int flags_saved;
+ sljit_si flags_saved;
#endif
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
@@ -236,35 +254,44 @@ struct sljit_compiler {
#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;
+ sljit_si cache_arg;
+ sljit_sw cache_argw;
#endif
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
- int cache_arg;
- sljit_w cache_argw;
+ sljit_si cache_arg;
+ sljit_sw 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;
+ sljit_sw imm;
+ sljit_si cache_arg;
+ sljit_sw 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;
+ sljit_si delay_slot;
+ sljit_si cache_arg;
+ sljit_sw cache_argw;
+#endif
+
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ sljit_si delay_slot;
+ sljit_si cache_arg;
+ sljit_sw cache_argw;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
FILE* verbose;
#endif
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ /* Local size passed to the functions. */
+ sljit_si logical_local_size;
+#endif
+
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
- int skip_checks;
+ sljit_si skip_checks;
#endif
};
@@ -275,22 +302,29 @@ struct sljit_compiler {
/* Creates an sljit compiler.
Returns NULL if failed. */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void);
-/* Free everything except the codes. */
+
+/* Free everything except the compiled machine code. */
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; }
+/* Returns the current error code. If an error is occured, future sljit
+ calls which uses the same compiler argument returns early with the same
+ error code. Thus there is no need for checking the error after every
+ call, it is enough to do it before the code is compiled. Removing
+ these checks increases the performance of the compiling process. */
+static SLJIT_INLINE sljit_si 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).
+ 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_sw) 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. However, this return value does not
+ indicate that there is no more memory (does not set the current error code
+ of the compiler to out-of-memory status).
*/
-SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size);
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_si size);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
/* Passing NULL disables verbose. */
@@ -301,15 +335,17 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
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.
+ After the machine code generation is finished 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. */
+/* Instruction generation. Returns with any error code. If there is no
+ error, they return with SLJIT_SUCCESS. */
/*
The executable code is basically a function call from the viewpoint of
@@ -320,8 +356,8 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
for the executable code and moves function arguments to the saved
registers. The number of arguments are specified in the "args"
parameter and the first argument goes to SLJIT_SAVED_REG1, the second
- goes to SLJIT_SAVED_REG2 and so on. The number of temporary and
- saved registers are passed in "temporaries" and "saveds" arguments
+ goes to SLJIT_SAVED_REG2 and so on. The number of scratch and
+ saved registers are passed in "scratches" and "saveds" arguments
respectively. Since the saved registers contains the arguments,
"args" must be less or equal than "saveds". The sljit_emit_enter
is also capable of allocating a stack space for local variables. The
@@ -332,54 +368,53 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
SLJIT_LOCALS_REG + local_size (exclusive) can be modified freely
until the function returns. The stack space is uninitialized.
- Note: every call of sljit_emit_enter and sljit_set_context overwrites
- the previous context. */
+ Note: every call of sljit_emit_enter and sljit_set_context
+ overwrites the previous context. */
#define SLJIT_MAX_LOCAL_SIZE 65536
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler,
- int args, int temporaries, int saveds, int local_size);
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size);
/* The machine code has a context (which contains the local stack space size,
number of used registers, etc.) which initialized by sljit_emit_enter. Several
functions (like sljit_emit_return) requres this context to be able to generate
the appropriate code. However, some code fragments (like inline cache) may have
no normal entry point so their context is unknown for the compiler. Using the
- function below we can specify thir context.
+ function below we can specify their context.
Note: every call of sljit_emit_enter and sljit_set_context overwrites
the previous context. */
-/* Note: multiple calls of this function overwrites the previous call. */
-
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
- int args, int temporaries, int saveds, int local_size);
+ sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size);
/* Return from machine code. The op argument can be SLJIT_UNUSED which means the
function does not return with anything or any opcode between SLJIT_MOV and
- SLJIT_MOV_SI (see sljit_emit_op1). As for src and srcw they must be 0 if op
+ SLJIT_MOV_P (see sljit_emit_op1). As for src and srcw they must be 0 if op
is SLJIT_UNUSED, otherwise see below the description about source and
destination arguments. */
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op,
- 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. */
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si src, sljit_sw srcw);
-/* 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 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). */
+/* Fast calling mechanism for utility functions (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 (the type of the value stored by this function
+ is sljit_p), 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 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 saveds, int local_size);
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw);
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw);
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw);
/*
Source and destination values for arithmetical instructions
@@ -388,7 +423,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
[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
+ useful for (byte, half, int, sljit_sw) array access
(fully supported by both x86 and ARM architectures, and cheap operation on others)
*/
@@ -398,24 +433,40 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
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 is defined and its value is 1
+ byte | 1 byte (any physical_address is accepted)
+ half | 2 byte (physical_address & 0x1 == 0)
+ int | 4 byte (physical_address & 0x3 == 0)
+ word | 4 byte if SLJIT_32BIT_ARCHITECTURE is defined and its value is 1
| 8 byte if SLJIT_64BIT_ARCHITECTURE is defined and its value is 1
-
- 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)
+ pointer | size of sljit_p type (4 byte on 32 bit machines, 4 or 8 byte
+ | on 64 bit machines)
+
+ Note: Different architectures have different addressing limitations.
+ A single instruction is enough for the following addressing
+ modes. Other adrressing modes are emulated by instruction
+ sequences. This information could help to improve those code
+ generators which focuses only a few architectures.
+
+ x86: [reg+imm], -2^32+1 <= imm <= 2^32-1 (full adress space on x86-32)
+ [reg+(reg<<imm)] is supported
+ [imm], -2^32+1 <= imm <= 2^32-1 is supported
+ Write-back is not supported
+ arm: [reg+imm], -4095 <= imm <= 4095 or -255 <= imm <= 255 for signed
+ bytes, any halfs or floating point values)
+ [reg+(reg<<imm)] is supported
+ Write-back is supported
+ arm-t2: [reg+imm], -255 <= imm <= 4095
+ [reg+(reg<<imm)] is supported
+ Write back is supported only for [reg+imm], where -255 <= imm <= 255
+ ppc: [reg+imm], -65536 <= imm <= 65535. 64 bit loads/stores and 32 bit
+ signed load on 64 bit requires immediates divisible by 4.
+ [reg+imm] is not supported for signed 8 bit values.
+ [reg+reg] is supported
+ Write-back is supported except for one instruction: 32 bit signed
+ load with [reg+imm] addressing mode on 64 bit.
+ mips: [reg+imm], -65536 <= imm <= 65535
+ sparc: [reg+imm], -4096 <= imm <= 4095
+ [reg+reg] is supported
*/
/* Register output: simply the name of the register.
@@ -427,12 +478,31 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
#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. */
+ 32 bit CPUs. If this flag is set for an arithmetic operation, it uses only the
+ lower 32 bit of the input register(s), and set the CPU status flags according
+ to the 32 bit result. The higher 32 bits are undefined for both the input and
+ output. However, the CPU might not ignore those higher 32 bits, like MIPS, which
+ expects it to be the sign extension of the lower 32 bit. All 32 bit operations
+ are undefined, if this condition is not fulfilled. Therefore, when SLJIT_INT_OP
+ is specified, all register arguments must be the result of other operations with
+ the same SLJIT_INT_OP flag. In other words, although a register can hold either
+ a 64 or 32 bit value, these values cannot be mixed. The only exceptions are
+ SLJIT_IMOV and SLJIT_IMOVU (SLJIT_MOV_SI/SLJIT_MOV_UI/SLJIT_MOVU_SI/SLJIT_MOV_UI
+ with SLJIT_INT_OP flag) which can convert any source argument to SLJIT_INT_OP
+ compatible result. This conversion might be unnecessary on some CPUs like x86-64,
+ since the upper 32 bit is always ignored. In this case SLJIT is clever enough
+ to not generate any instructions if the source and destination operands are the
+ same registers. Affects sljit_emit_op0, sljit_emit_op1 and sljit_emit_op2. */
#define SLJIT_INT_OP 0x100
+/* Single precision mode (SP). This flag is similar to SLJIT_INT_OP, just
+ it applies to floating point registers (it is even the same bit). When
+ this flag is passed, the CPU performs single precision floating point
+ operations. Similar to SLJIT_INT_OP, all register arguments must be the
+ result of other floating point operations with this flag. Affects
+ sljit_emit_fop1, sljit_emit_fop2 and sljit_emit_fcmp. */
+#define SLJIT_SINGLE_OP 0x100
+
/* Common CPU status flags for all architectures (x86, ARM, PPC)
- carry flag
- overflow flag
@@ -474,124 +544,165 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
Note: may or may not cause an extra cycle wait
it can even decrease the runtime in a few cases. */
#define SLJIT_NOP 1
-/* Flags: may destroy flags
- Unsigned multiplication of SLJIT_TEMPORARY_REG1 and SLJIT_TEMPORARY_REG2.
- Result goes to SLJIT_TEMPORARY_REG2:SLJIT_TEMPORARY_REG1 (high:low) word */
+/* Flags: - (may destroy flags)
+ Unsigned multiplication of SLJIT_SCRATCH_REG1 and SLJIT_SCRATCH_REG2.
+ Result goes to SLJIT_SCRATCH_REG2:SLJIT_SCRATCH_REG1 (high:low) word */
#define SLJIT_UMUL 2
-/* Flags: may destroy flags
- Signed multiplication of SLJIT_TEMPORARY_REG1 and SLJIT_TEMPORARY_REG2.
- Result goes to SLJIT_TEMPORARY_REG2:SLJIT_TEMPORARY_REG1 (high:low) word */
+/* Flags: - (may destroy flags)
+ Signed multiplication of SLJIT_SCRATCH_REG1 and SLJIT_SCRATCH_REG2.
+ Result goes to SLJIT_SCRATCH_REG2:SLJIT_SCRATCH_REG1 (high:low) word */
#define SLJIT_SMUL 3
-/* Flags: I | may destroy flags
- Unsigned divide of the value in SLJIT_TEMPORARY_REG1 by the value in SLJIT_TEMPORARY_REG2.
- The result is placed in SLJIT_TEMPORARY_REG1 and the remainder goes to SLJIT_TEMPORARY_REG2.
- Note: if SLJIT_TEMPORARY_REG2 contains 0, the behaviour is undefined. */
+/* Flags: I - (may destroy flags)
+ Unsigned divide of the value in SLJIT_SCRATCH_REG1 by the value in SLJIT_SCRATCH_REG2.
+ The result is placed in SLJIT_SCRATCH_REG1 and the remainder goes to SLJIT_SCRATCH_REG2.
+ Note: if SLJIT_SCRATCH_REG2 contains 0, the behaviour is undefined. */
#define SLJIT_UDIV 4
-/* Flags: I | may destroy flags
- Signed divide of the value in SLJIT_TEMPORARY_REG1 by the value in SLJIT_TEMPORARY_REG2.
- The result is placed in SLJIT_TEMPORARY_REG1 and the remainder goes to SLJIT_TEMPORARY_REG2.
- Note: if SLJIT_TEMPORARY_REG2 contains 0, the behaviour is undefined. */
+#define SLJIT_IUDIV (SLJIT_UDIV | SLJIT_INT_OP)
+/* Flags: I - (may destroy flags)
+ Signed divide of the value in SLJIT_SCRATCH_REG1 by the value in SLJIT_SCRATCH_REG2.
+ The result is placed in SLJIT_SCRATCH_REG1 and the remainder goes to SLJIT_SCRATCH_REG2.
+ Note: if SLJIT_SCRATCH_REG2 contains 0, the behaviour is undefined. */
#define SLJIT_SDIV 5
+#define SLJIT_ISDIV (SLJIT_SDIV | SLJIT_INT_OP)
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op);
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si 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) */
+ UH = unsigned half (16 bit)
+ SH = signed half (16 bit)
+ UI = unsigned int (32 bit)
+ SI = signed int (32 bit)
+ P = pointer (sljit_p) size */
/* Flags: - (never set any flags) */
#define SLJIT_MOV 6
-/* Flags: - (never set any flags) */
+/* Flags: I - (never set any flags) */
#define SLJIT_MOV_UB 7
-/* Flags: - (never set any flags) */
+#define SLJIT_IMOV_UB (SLJIT_MOV_UB | SLJIT_INT_OP)
+/* Flags: I - (never set any flags) */
#define SLJIT_MOV_SB 8
-/* Flags: - (never set any flags) */
+#define SLJIT_IMOV_SB (SLJIT_MOV_SB | SLJIT_INT_OP)
+/* Flags: I - (never set any flags) */
#define SLJIT_MOV_UH 9
-/* Flags: - (never set any flags) */
+#define SLJIT_IMOV_UH (SLJIT_MOV_UH | SLJIT_INT_OP)
+/* Flags: I - (never set any flags) */
#define SLJIT_MOV_SH 10
-/* Flags: - (never set any flags) */
+#define SLJIT_IMOV_SH (SLJIT_MOV_SH | SLJIT_INT_OP)
+/* Flags: I - (never set any flags)
+ Note: see SLJIT_INT_OP for further details. */
#define SLJIT_MOV_UI 11
-/* Flags: - (never set any flags) */
+/* No SLJIT_INT_OP form, since it the same as SLJIT_IMOVU. */
+/* Flags: I - (never set any flags)
+ Note: see SLJIT_INT_OP for further details. */
#define SLJIT_MOV_SI 12
+#define SLJIT_IMOV (SLJIT_MOV_SI | SLJIT_INT_OP)
/* Flags: - (never set any flags) */
-#define SLJIT_MOVU 13
+#define SLJIT_MOV_P 13
/* Flags: - (never set any flags) */
-#define SLJIT_MOVU_UB 14
+#define SLJIT_MOVU 14
+/* Flags: I - (never set any flags) */
+#define SLJIT_MOVU_UB 15
+#define SLJIT_IMOVU_UB (SLJIT_MOVU_UB | SLJIT_INT_OP)
+/* Flags: I - (never set any flags) */
+#define SLJIT_MOVU_SB 16
+#define SLJIT_IMOVU_SB (SLJIT_MOVU_SB | SLJIT_INT_OP)
+/* Flags: I - (never set any flags) */
+#define SLJIT_MOVU_UH 17
+#define SLJIT_IMOVU_UH (SLJIT_MOVU_UH | SLJIT_INT_OP)
+/* Flags: I - (never set any flags) */
+#define SLJIT_MOVU_SH 18
+#define SLJIT_IMOVU_SH (SLJIT_MOVU_SH | SLJIT_INT_OP)
+/* Flags: I - (never set any flags)
+ Note: see SLJIT_INT_OP for further details. */
+#define SLJIT_MOVU_UI 19
+/* No SLJIT_INT_OP form, since it the same as SLJIT_IMOVU. */
+/* Flags: I - (never set any flags)
+ Note: see SLJIT_INT_OP for further details. */
+#define SLJIT_MOVU_SI 20
+#define SLJIT_IMOVU (SLJIT_MOVU_SI | SLJIT_INT_OP)
/* Flags: - (never set any flags) */
-#define SLJIT_MOVU_SB 15
-/* Flags: - (never set any flags) */
-#define SLJIT_MOVU_UH 16
-/* Flags: - (never set any flags) */
-#define SLJIT_MOVU_SH 17
-/* Flags: - (never set any flags) */
-#define SLJIT_MOVU_UI 18
-/* Flags: - (never set any flags) */
-#define SLJIT_MOVU_SI 19
+#define SLJIT_MOVU_P 21
/* Flags: I | E | K */
-#define SLJIT_NOT 20
+#define SLJIT_NOT 22
+#define SLJIT_INOT (SLJIT_NOT | SLJIT_INT_OP)
/* Flags: I | E | O | K */
-#define SLJIT_NEG 21
+#define SLJIT_NEG 23
+#define SLJIT_INEG (SLJIT_NEG | SLJIT_INT_OP)
/* Count leading zeroes
- Flags: I | E | K */
-#define SLJIT_CLZ 22
+ Flags: I | E | K
+ Important note! Sparc 32 does not support K flag, since
+ the required popc instruction is introduced only in sparc 64. */
+#define SLJIT_CLZ 24
+#define SLJIT_ICLZ (SLJIT_CLZ | SLJIT_INT_OP)
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw);
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw);
/* Flags: I | E | O | C | K */
-#define SLJIT_ADD 23
+#define SLJIT_ADD 25
+#define SLJIT_IADD (SLJIT_ADD | SLJIT_INT_OP)
/* Flags: I | C | K */
-#define SLJIT_ADDC 24
+#define SLJIT_ADDC 26
+#define SLJIT_IADDC (SLJIT_ADDC | SLJIT_INT_OP)
/* Flags: I | E | S | U | O | C | K */
-#define SLJIT_SUB 25
+#define SLJIT_SUB 27
+#define SLJIT_ISUB (SLJIT_SUB | SLJIT_INT_OP)
/* Flags: I | C | K */
-#define SLJIT_SUBC 26
+#define SLJIT_SUBC 28
+#define SLJIT_ISUBC (SLJIT_SUBC | SLJIT_INT_OP)
/* Note: integer mul
Flags: I | O (see SLJIT_C_MUL_*) | K */
-#define SLJIT_MUL 27
+#define SLJIT_MUL 29
+#define SLJIT_IMUL (SLJIT_MUL | SLJIT_INT_OP)
/* Flags: I | E | K */
-#define SLJIT_AND 28
+#define SLJIT_AND 30
+#define SLJIT_IAND (SLJIT_AND | SLJIT_INT_OP)
/* Flags: I | E | K */
-#define SLJIT_OR 29
+#define SLJIT_OR 31
+#define SLJIT_IOR (SLJIT_OR | SLJIT_INT_OP)
/* Flags: I | E | K */
-#define SLJIT_XOR 30
+#define SLJIT_XOR 32
+#define SLJIT_IXOR (SLJIT_XOR | SLJIT_INT_OP)
/* Flags: I | E | K
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
to bit_length - 1, the operation is undefined. */
-#define SLJIT_SHL 31
+#define SLJIT_SHL 33
+#define SLJIT_ISHL (SLJIT_SHL | SLJIT_INT_OP)
/* Flags: I | E | K
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
to bit_length - 1, the operation is undefined. */
-#define SLJIT_LSHR 32
+#define SLJIT_LSHR 34
+#define SLJIT_ILSHR (SLJIT_LSHR | SLJIT_INT_OP)
/* Flags: I | E | K
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
to bit_length - 1, the operation is undefined. */
-#define SLJIT_ASHR 33
+#define SLJIT_ASHR 35
+#define SLJIT_IASHR (SLJIT_ASHR | SLJIT_INT_OP)
-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 sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w);
/* The following function is a helper function for sljit_emit_op_custom.
- It returns with the real machine register index of any SLJIT_TEMPORARY
+ It returns with the real machine register index of any SLJIT_SCRATCH
SLJIT_SAVED or SLJIT_LOCALS register.
Note: it returns with -1 for virtual registers (all EREGs on x86-32).
Note: register returned by SLJIT_LOCALS_REG is not necessary the real
stack pointer register of the target architecture. */
-SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg);
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg);
/* Any instruction can be inserted into the instruction stream by
sljit_emit_op_custom. It has a similar purpose as inline assembly.
@@ -603,42 +714,50 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg);
if size == 4, the instruction argument must be 4 byte aligned.
Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, int size);
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_si size);
/* Returns with non-zero if fpu is available. */
-SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void);
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void);
/* Note: dst is the left and src is the right operand for SLJIT_FCMP.
- Note: NaN check is always performed. If SLJIT_C_FLOAT_NAN is set,
+ Note: NaN check is always performed. If SLJIT_C_FLOAT_UNORDERED is set,
the comparison result is unpredictable.
- Flags: E | S (see SLJIT_C_FLOAT_*) */
-#define SLJIT_FCMP 34
-/* Flags: - (never set any flags) */
-#define SLJIT_FMOV 35
-/* Flags: - (never set any flags) */
-#define SLJIT_FNEG 36
-/* Flags: - (never set any flags) */
-#define SLJIT_FABS 37
-
-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 38
-/* Flags: - (never set any flags) */
-#define SLJIT_FSUB 39
-/* Flags: - (never set any flags) */
-#define SLJIT_FMUL 40
-/* Flags: - (never set any flags) */
-#define SLJIT_FDIV 41
-
-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);
+ Flags: SP | E | S (see SLJIT_C_FLOAT_*) */
+#define SLJIT_CMPD 36
+#define SLJIT_CMPS (SLJIT_CMPD | SLJIT_SINGLE_OP)
+/* Flags: SP - (never set any flags) */
+#define SLJIT_MOVD 37
+#define SLJIT_MOVS (SLJIT_MOVD | SLJIT_SINGLE_OP)
+/* Flags: SP - (never set any flags) */
+#define SLJIT_NEGD 38
+#define SLJIT_NEGS (SLJIT_NEGD | SLJIT_SINGLE_OP)
+/* Flags: SP - (never set any flags) */
+#define SLJIT_ABSD 39
+#define SLJIT_ABSS (SLJIT_ABSD | SLJIT_SINGLE_OP)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw);
+
+/* Flags: SP - (never set any flags) */
+#define SLJIT_ADDD 40
+#define SLJIT_ADDS (SLJIT_ADDD | SLJIT_SINGLE_OP)
+/* Flags: SP - (never set any flags) */
+#define SLJIT_SUBD 41
+#define SLJIT_SUBS (SLJIT_SUBD | SLJIT_SINGLE_OP)
+/* Flags: SP - (never set any flags) */
+#define SLJIT_MULD 42
+#define SLJIT_MULS (SLJIT_MULD | SLJIT_SINGLE_OP)
+/* Flags: SP - (never set any flags) */
+#define SLJIT_DIVD 43
+#define SLJIT_DIVS (SLJIT_DIVD | SLJIT_SINGLE_OP)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w);
/* Label and jump instructions. */
@@ -671,8 +790,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
#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_C_FLOAT_UNORDERED 20
+#define SLJIT_C_FLOAT_ORDERED 21
#define SLJIT_JUMP 22
#define SLJIT_FAST_CALL 23
@@ -691,7 +810,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
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);
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type);
/* Basic arithmetic comparison. In most architectures it is implemented as
an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting
@@ -701,23 +820,23 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
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);
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w);
/* Basic floating point comparison. In most architectures it is implemented as
an SLJIT_FCMP operation (setting appropriate flags) 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 appropriate.
- type must be between SLJIT_C_FLOAT_EQUAL and SLJIT_C_FLOAT_NOT_NAN
- type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
+ type must be between SLJIT_C_FLOAT_EQUAL and SLJIT_C_FLOAT_ORDERED
+ type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and SLJIT_SINGLE_OP
Flags: destroy flags.
Note: if either operand is NaN, the behaviour is undefined for
type <= SLJIT_C_FLOAT_LESS_EQUAL. */
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w);
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw 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);
@@ -731,25 +850,38 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
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);
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw 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
+/* Perform the operation using the conditional flags as the second argument.
+ Type must always be between SLJIT_C_EQUAL and SLJIT_C_FLOAT_ORDERED. The
+ value represented by the type is 1, if the condition represented by the type
+ is fulfilled, and 0 otherwise.
+
+ If op == SLJIT_MOV, SLJIT_MOV_SI, SLJIT_MOV_UI:
+ Set dst to the value represented by the type (0 or 1).
+ Src must be SLJIT_UNUSED, and srcw must be 0
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);
+ If op == SLJIT_OR, op == SLJIT_AND, op == SLJIT_XOR
+ Performs the binary operation using src as the first, and the value
+ represented by type as the second argument.
+ Important note: only dst=src and dstw=srcw is supported at the moment!
+ Flags: I | E | K
+ Note: sljit_emit_op_flags does nothing, if dst is SLJIT_UNUSED (regardless of op). */
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw,
+ sljit_si type);
+
+/* Copies the base address of SLJIT_LOCALS_REG+offset to dst.
+ Flags: - (never set any flags) */
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset);
/* 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);
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw 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
+ are computed. Since these structures are freed by 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; }
@@ -757,22 +889,22 @@ static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) {
/* 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);
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant);
/* --------------------------------------------------------------------- */
/* Miscellaneous utility functions */
/* --------------------------------------------------------------------- */
#define SLJIT_MAJOR_VERSION 0
-#define SLJIT_MINOR_VERSION 87
+#define SLJIT_MINOR_VERSION 90
-/* 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. */
+/* Get the human readable name of the platform. Can be useful on platforms
+ like ARM, where ARM and Thumb2 functions can be mixed, and
+ it is useful to know the type of the code generator. */
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)
+/* Portable helper function to get an offset of a member. */
+#define SLJIT_OFFSETOF(base, member) ((sljit_sw)(&((base*)0x10)->member) - 0x10)
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
/* This global lock is useful to compile common functions. */
@@ -821,32 +953,32 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* st
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);
+SLJIT_API_FUNC_ATTRIBUTE sljit_sw 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)
+#define SLJIT_FUNC_OFFSET(func_name) ((sljit_sw)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)
+#define SLJIT_FUNC_OFFSET(func_name) (*(sljit_sw*)(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;
+ sljit_sw addr;
+ sljit_sw r2;
+ sljit_sw 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);
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func);
#endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c b/src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c
index a51536b4a7..0a60dc2a67 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c
@@ -24,23 +24,26 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
{
return "ARM-Thumb2" SLJIT_CPUINFO;
}
+/* Length of an instruction word. */
+typedef sljit_ui sljit_ins;
+
/* Last register + 1. */
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
#define TMP_PC (SLJIT_NO_REGISTERS + 4)
-#define TMP_FREG1 (SLJIT_FLOAT_REG4 + 1)
-#define TMP_FREG2 (SLJIT_FLOAT_REG4 + 2)
+#define TMP_FREG1 (0)
+#define TMP_FREG2 (SLJIT_FLOAT_REG6 + 1)
/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
- 0, 0, 1, 2, 12, 5, 6, 7, 8, 10, 11, 13, 3, 4, 14, 15
+ 0, 0, 1, 2, 12, 5, 6, 7, 8, 10, 11, 13, 3, 4, 14, 15
};
#define COPY_BITS(src, from, to, bits) \
@@ -75,8 +78,6 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
#define IMM12(imm) \
(COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))
-typedef sljit_ui sljit_ins;
-
/* --------------------------------------------------------------------- */
/* Instrucion forms */
/* --------------------------------------------------------------------- */
@@ -165,18 +166,18 @@ typedef sljit_ui sljit_ins;
#define UXTB_W 0xfa5ff080
#define UXTH 0xb280
#define UXTH_W 0xfa1ff080
-#define VABS_F64 0xeeb00bc0
-#define VADD_F64 0xee300b00
-#define VCMP_F64 0xeeb40b40
-#define VDIV_F64 0xee800b00
-#define VMOV_F64 0xeeb00b40
+#define VABS_F32 0xeeb00ac0
+#define VADD_F32 0xee300a00
+#define VCMP_F32 0xeeb40a40
+#define VDIV_F32 0xee800a00
+#define VMOV_F32 0xeeb00a40
#define VMRS 0xeef1fa10
-#define VMUL_F64 0xee200b00
-#define VNEG_F64 0xeeb10b40
-#define VSTR 0xed000b00
-#define VSUB_F64 0xee300b40
+#define VMUL_F32 0xee200a00
+#define VNEG_F32 0xeeb10a40
+#define VSTR_F32 0xed000a00
+#define VSUB_F32 0xee300a40
-static int push_inst16(struct sljit_compiler *compiler, sljit_ins inst)
+static sljit_si push_inst16(struct sljit_compiler *compiler, sljit_ins inst)
{
sljit_uh *ptr;
SLJIT_ASSERT(!(inst & 0xffff0000));
@@ -188,7 +189,7 @@ static int push_inst16(struct sljit_compiler *compiler, sljit_ins inst)
return SLJIT_SUCCESS;
}
-static int push_inst32(struct sljit_compiler *compiler, sljit_ins inst)
+static sljit_si push_inst32(struct sljit_compiler *compiler, sljit_ins inst)
{
sljit_uh *ptr = (sljit_uh*)ensure_buf(compiler, sizeof(sljit_ins));
FAIL_IF(!ptr);
@@ -198,7 +199,7 @@ static int push_inst32(struct sljit_compiler *compiler, sljit_ins inst)
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE int emit_imm32_const(struct sljit_compiler *compiler, int dst, sljit_uw imm)
+static SLJIT_INLINE sljit_si emit_imm32_const(struct sljit_compiler *compiler, sljit_si dst, sljit_uw imm)
{
FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) |
COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)));
@@ -208,7 +209,7 @@ static SLJIT_INLINE int emit_imm32_const(struct sljit_compiler *compiler, int ds
static SLJIT_INLINE void modify_imm32_const(sljit_uh* inst, sljit_uw new_imm)
{
- int dst = inst[1] & 0x0f00;
+ sljit_si dst = inst[1] & 0x0f00;
SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00));
inst[0] = (MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1);
inst[1] = dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff);
@@ -216,9 +217,9 @@ static SLJIT_INLINE void modify_imm32_const(sljit_uh* inst, sljit_uw new_imm)
inst[3] = dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16);
}
-static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uh *code_ptr, sljit_uh *code)
+static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uh *code_ptr, sljit_uh *code)
{
- sljit_w diff;
+ sljit_sw diff;
if (jump->flags & SLJIT_REWRITABLE_JUMP)
return 0;
@@ -227,14 +228,14 @@ static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uh *code
/* Branch to ARM code is not optimized yet. */
if (!(jump->u.target & 0x1))
return 0;
- diff = ((sljit_w)jump->u.target - (sljit_w)(code_ptr + 2)) >> 1;
+ diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2)) >> 1;
}
else {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
- diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)(code_ptr + 2)) >> 1;
+ diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2)) >> 1;
}
- if (jump->flags & IS_CONDITIONAL) {
+ if (jump->flags & IS_COND) {
SLJIT_ASSERT(!(jump->flags & IS_BL));
if (diff <= 127 && diff >= -128) {
jump->flags |= B_TYPE1;
@@ -271,7 +272,7 @@ static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uh *code
return 0;
}
-static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, int flush)
+static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, sljit_si flush)
{
sljit_uh* inst = (sljit_uh*)addr;
modify_imm32_const(inst, new_addr);
@@ -282,10 +283,10 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr,
static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump)
{
- int type = (jump->flags >> 4) & 0xf;
- sljit_w diff;
+ sljit_si type = (jump->flags >> 4) & 0xf;
+ sljit_sw diff;
sljit_uh *jump_inst;
- int s, j1, j2;
+ sljit_si s, j1, j2;
if (SLJIT_UNLIKELY(type == 0)) {
inline_set_jump_addr(jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
@@ -294,33 +295,33 @@ static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump)
if (jump->flags & JUMP_ADDR) {
SLJIT_ASSERT(jump->u.target & 0x1);
- diff = ((sljit_w)jump->u.target - (sljit_w)(jump->addr + 4)) >> 1;
+ diff = ((sljit_sw)jump->u.target - (sljit_sw)(jump->addr + 4)) >> 1;
}
else
- diff = ((sljit_w)(jump->u.label->addr) - (sljit_w)(jump->addr + 4)) >> 1;
+ diff = ((sljit_sw)(jump->u.label->addr) - (sljit_sw)(jump->addr + 4)) >> 1;
jump_inst = (sljit_uh*)jump->addr;
switch (type) {
case 1:
/* Encoding T1 of 'B' instruction */
- SLJIT_ASSERT(diff <= 127 && diff >= -128 && (jump->flags & IS_CONDITIONAL));
+ SLJIT_ASSERT(diff <= 127 && diff >= -128 && (jump->flags & IS_COND));
jump_inst[0] = 0xd000 | (jump->flags & 0xf00) | (diff & 0xff);
return;
case 2:
/* Encoding T3 of 'B' instruction */
- SLJIT_ASSERT(diff <= 524287 && diff >= -524288 && (jump->flags & IS_CONDITIONAL));
+ SLJIT_ASSERT(diff <= 524287 && diff >= -524288 && (jump->flags & IS_COND));
jump_inst[0] = 0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1);
jump_inst[1] = 0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | (diff & 0x7ff);
return;
case 3:
- SLJIT_ASSERT(jump->flags & IS_CONDITIONAL);
+ SLJIT_ASSERT(jump->flags & IS_COND);
*jump_inst++ = IT | ((jump->flags >> 4) & 0xf0) | 0x8;
diff--;
type = 5;
break;
case 4:
/* Encoding T2 of 'B' instruction */
- SLJIT_ASSERT(diff <= 1023 && diff >= -1024 && !(jump->flags & IS_CONDITIONAL));
+ SLJIT_ASSERT(diff <= 1023 && diff >= -1024 && !(jump->flags & IS_COND));
jump_inst[0] = 0xe000 | (diff & 0x7ff);
return;
}
@@ -385,7 +386,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
label = label->next;
}
if (jump && jump->addr == half_count) {
- jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_CONDITIONAL) ? 10 : 8);
+ jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8);
code_ptr -= detect_jump_type(jump, code_ptr, code);
jump = jump->next;
}
@@ -409,7 +410,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
- SLJIT_ASSERT(code_ptr - code <= (int)compiler->size);
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
jump = compiler->jumps;
while (jump) {
@@ -428,7 +429,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
static sljit_uw get_imm(sljit_uw imm)
{
/* Thumb immediate form. */
- int counter;
+ sljit_si counter;
if (imm <= 0xff)
return imm;
@@ -474,7 +475,7 @@ static sljit_uw get_imm(sljit_uw imm)
return ((imm >> 24) & 0x7f) | COPY_BITS(counter, 4, 26, 1) | COPY_BITS(counter, 1, 12, 3) | COPY_BITS(counter, 0, 7, 1);
}
-static int load_immediate(struct sljit_compiler *compiler, int dst, sljit_uw imm)
+static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sljit_uw imm)
{
sljit_uw tmp;
@@ -509,13 +510,13 @@ static int load_immediate(struct sljit_compiler *compiler, int dst, sljit_uw imm
#define SLOW_SRC1 0x0800000
#define SLOW_SRC2 0x1000000
-static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, sljit_uw arg1, sljit_uw arg2)
+static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, sljit_si dst, sljit_uw arg1, sljit_uw arg2)
{
/* dst must be register, TMP_REG1
arg1 must be register, TMP_REG1, imm
arg2 must be register, TMP_REG2, imm */
- int reg;
- sljit_uw imm;
+ sljit_si reg;
+ sljit_uw imm, negated_imm;
if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {
/* Both are immediates. */
@@ -542,14 +543,25 @@ static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, slji
/* No form with immediate operand. */
break;
case SLJIT_ADD:
+ negated_imm = (sljit_uw)-(sljit_sw)imm;
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
if (imm <= 0x7)
return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
- if (reg == dst && imm <= 0xff)
- return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst));
+ if (negated_imm <= 0x7)
+ return push_inst16(compiler, SUBSI3 | IMM3(negated_imm) | RD3(dst) | RN3(reg));
+ if (reg == dst) {
+ if (imm <= 0xff)
+ return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst));
+ if (negated_imm <= 0xff)
+ return push_inst16(compiler, SUBSI8 | IMM8(negated_imm) | RDN3(dst));
+ }
+ }
+ if (!(flags & SET_FLAGS)) {
+ if (imm <= 0xfff)
+ return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm));
+ if (negated_imm <= 0xfff)
+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(negated_imm));
}
- if (imm <= 0xfff && !(flags & SET_FLAGS))
- return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm));
imm = get_imm(imm);
if (imm != INVALID_IMM)
return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
@@ -561,18 +573,27 @@ static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, slji
break;
case SLJIT_SUB:
if (flags & ARG2_IMM) {
+ negated_imm = (sljit_uw)-(sljit_sw)imm;
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
if (imm <= 0x7)
return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
- if (imm <= 0xff) {
- if (reg == dst)
+ if (negated_imm <= 0x7)
+ return push_inst16(compiler, ADDSI3 | IMM3(negated_imm) | RD3(dst) | RN3(reg));
+ if (reg == dst) {
+ if (imm <= 0xff)
return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst));
- if (flags & UNUSED_RETURN)
- return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
+ if (negated_imm <= 0xff)
+ return push_inst16(compiler, ADDSI8 | IMM8(negated_imm) | RDN3(dst));
}
+ if (imm <= 0xff && (flags & UNUSED_RETURN))
+ return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
+ }
+ if (!(flags & SET_FLAGS)) {
+ if (imm <= 0xfff)
+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm));
+ if (negated_imm <= 0xfff)
+ return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(negated_imm));
}
- if (imm <= 0xfff && !(flags & SET_FLAGS))
- return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm));
imm = get_imm(imm);
if (imm != INVALID_IMM)
return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
@@ -681,9 +702,11 @@ static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, slji
case SLJIT_MOV:
case SLJIT_MOV_UI:
case SLJIT_MOV_SI:
+ case SLJIT_MOV_P:
case SLJIT_MOVU:
case SLJIT_MOVU_UI:
case SLJIT_MOVU_SI:
+ case SLJIT_MOVU_P:
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));
case SLJIT_MOV_UB:
@@ -865,7 +888,7 @@ static SLJIT_CONST sljit_uw sljit_mem32[12] = {
};
/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
-static int emit_set_delta(struct sljit_compiler *compiler, int dst, int reg, sljit_w value)
+static sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sljit_si reg, sljit_sw value)
{
if (value >= 0) {
if (value <= 0xfff)
@@ -886,9 +909,9 @@ static int emit_set_delta(struct sljit_compiler *compiler, int dst, int reg, slj
}
/* Can perform an operation using at most 1 instruction. */
-static int getput_arg_fast(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw)
+static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
{
- int tmp;
+ sljit_si tmp;
SLJIT_ASSERT(arg & SLJIT_MEM);
@@ -971,7 +994,7 @@ static int getput_arg_fast(struct sljit_compiler *compiler, int flags, int reg,
/* see getput_arg below.
Note: can_cache is called only for binary operators. Those
operators always uses word arguments without write back. */
-static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
{
/* Simple operation except for updates. */
if ((arg & 0xf0) || !(next_arg & SLJIT_MEM))
@@ -993,10 +1016,10 @@ static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
}
/* Emit the necessary instructions. See can_cache above. */
-static int getput_arg(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
{
- int tmp_r;
- sljit_w tmp;
+ sljit_si tmp_r;
+ sljit_sw tmp;
SLJIT_ASSERT(arg & SLJIT_MEM);
if (!(next_arg & SLJIT_MEM)) {
@@ -1092,7 +1115,7 @@ static int getput_arg(struct sljit_compiler *compiler, int flags, int reg, int a
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0);
}
-static SLJIT_INLINE int emit_op_mem(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw)
+static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
{
if (getput_arg_fast(compiler, flags, reg, arg, argw))
return compiler->error;
@@ -1101,16 +1124,30 @@ static SLJIT_INLINE int emit_op_mem(struct sljit_compiler *compiler, int flags,
return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
{
- int size;
+ if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
+ return compiler->error;
+ return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+}
+
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
+{
+ sljit_si size;
sljit_ins push;
CHECK_ERROR();
- check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
+ check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
- compiler->temporaries = temporaries;
+ compiler->scratches = scratches;
compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
push = (1 << 4);
if (saveds >= 5)
@@ -1123,7 +1160,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
push |= 1 << 7;
if (saveds >= 1)
push |= 1 << 6;
- if (temporaries >= 5)
+ if (scratches >= 5)
push |= 1 << 5;
FAIL_IF(saveds >= 3
? push_inst32(compiler, PUSH_W | (1 << 14) | push)
@@ -1143,24 +1180,27 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
}
if (args >= 1)
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG1, SLJIT_TEMPORARY_REG1)));
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG1, SLJIT_SCRATCH_REG1)));
if (args >= 2)
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG2, SLJIT_TEMPORARY_REG2)));
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG2, SLJIT_SCRATCH_REG2)));
if (args >= 3)
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG3, SLJIT_TEMPORARY_REG3)));
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG3, SLJIT_SCRATCH_REG3)));
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
- int size;
+ sljit_si size;
CHECK_ERROR_VOID();
- check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
+ check_sljit_set_context(compiler, args, scratches, saveds, local_size);
- compiler->temporaries = temporaries;
+ compiler->scratches = scratches;
compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
size = (3 + saveds) * sizeof(sljit_uw);
local_size += size;
@@ -1169,7 +1209,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
compiler->local_size = local_size;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
sljit_ins pop;
@@ -1196,7 +1236,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
pop |= 1 << 7;
if (compiler->saveds >= 1)
pop |= 1 << 6;
- if (compiler->temporaries >= 5)
+ if (compiler->scratches >= 5)
pop |= 1 << 5;
return compiler->saveds >= 3
? push_inst32(compiler, POP_W | (1 << 15) | pop)
@@ -1212,8 +1252,8 @@ extern "C" {
#endif
#if defined(__GNUC__)
-extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator);
-extern unsigned int __aeabi_idivmod(unsigned numerator, unsigned denominator);
+extern unsigned int __aeabi_uidivmod(unsigned int numerator, int unsigned denominator);
+extern int __aeabi_idivmod(int numerator, int denominator);
#else
#error "Software divmod functions are needed"
#endif
@@ -1222,7 +1262,7 @@ extern unsigned int __aeabi_idivmod(unsigned numerator, unsigned denominator);
}
#endif
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
{
CHECK_ERROR();
check_sljit_emit_op0(compiler, op);
@@ -1238,16 +1278,16 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
case SLJIT_UMUL:
case SLJIT_SMUL:
return push_inst32(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
- | (reg_map[SLJIT_TEMPORARY_REG2] << 8)
- | (reg_map[SLJIT_TEMPORARY_REG1] << 12)
- | (reg_map[SLJIT_TEMPORARY_REG1] << 16)
- | reg_map[SLJIT_TEMPORARY_REG2]);
+ | (reg_map[SLJIT_SCRATCH_REG2] << 8)
+ | (reg_map[SLJIT_SCRATCH_REG1] << 12)
+ | (reg_map[SLJIT_SCRATCH_REG1] << 16)
+ | reg_map[SLJIT_SCRATCH_REG2]);
case SLJIT_UDIV:
case SLJIT_SDIV:
- if (compiler->temporaries >= 4) {
+ if (compiler->scratches >= 4) {
FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */));
FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */));
- } else if (compiler->temporaries >= 3)
+ } else if (compiler->scratches >= 3)
FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */));
#if defined(__GNUC__)
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
@@ -1255,10 +1295,10 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
#else
#error "Software divmod functions are needed"
#endif
- if (compiler->temporaries >= 4) {
+ if (compiler->scratches >= 4) {
FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */));
return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */);
- } else if (compiler->temporaries >= 3)
+ } else if (compiler->scratches >= 3)
return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */);
return SLJIT_SUCCESS;
}
@@ -1266,72 +1306,77 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- int op_type, dst_r, flags;
+ sljit_si dst_r, flags;
+ sljit_si op_flags = GET_ALL_FLAGS(op);
CHECK_ERROR();
check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- op_type = GET_OPCODE(op);
- dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG1;
+ dst_r = (dst >= SLJIT_SCRATCH_REG1 && dst <= TMP_REG3) ? dst : TMP_REG1;
- if (op_type >= SLJIT_MOV && op_type <= SLJIT_MOVU_SI) {
- switch (op_type) {
+ op = GET_OPCODE(op);
+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
+ switch (op) {
case SLJIT_MOV:
case SLJIT_MOV_UI:
case SLJIT_MOV_SI:
+ case SLJIT_MOV_P:
flags = WORD_SIZE;
break;
case SLJIT_MOV_UB:
flags = BYTE_SIZE;
if (src & SLJIT_IMM)
- srcw = (unsigned char)srcw;
+ srcw = (sljit_ub)srcw;
break;
case SLJIT_MOV_SB:
flags = BYTE_SIZE | SIGNED;
if (src & SLJIT_IMM)
- srcw = (signed char)srcw;
+ srcw = (sljit_sb)srcw;
break;
case SLJIT_MOV_UH:
flags = HALF_SIZE;
if (src & SLJIT_IMM)
- srcw = (unsigned short)srcw;
+ srcw = (sljit_uh)srcw;
break;
case SLJIT_MOV_SH:
flags = HALF_SIZE | SIGNED;
if (src & SLJIT_IMM)
- srcw = (signed short)srcw;
+ srcw = (sljit_sh)srcw;
break;
case SLJIT_MOVU:
case SLJIT_MOVU_UI:
case SLJIT_MOVU_SI:
+ case SLJIT_MOVU_P:
flags = WORD_SIZE | UPDATE;
break;
case SLJIT_MOVU_UB:
flags = BYTE_SIZE | UPDATE;
if (src & SLJIT_IMM)
- srcw = (unsigned char)srcw;
+ srcw = (sljit_ub)srcw;
break;
case SLJIT_MOVU_SB:
flags = BYTE_SIZE | SIGNED | UPDATE;
if (src & SLJIT_IMM)
- srcw = (signed char)srcw;
+ srcw = (sljit_sb)srcw;
break;
case SLJIT_MOVU_UH:
flags = HALF_SIZE | UPDATE;
if (src & SLJIT_IMM)
- srcw = (unsigned short)srcw;
+ srcw = (sljit_uh)srcw;
break;
case SLJIT_MOVU_SH:
flags = HALF_SIZE | SIGNED | UPDATE;
if (src & SLJIT_IMM)
- srcw = (signed short)srcw;
+ srcw = (sljit_sh)srcw;
break;
default:
SLJIT_ASSERT_STOP();
@@ -1348,7 +1393,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
FAIL_IF(getput_arg(compiler, flags, dst_r, src, srcw, dst, dstw));
} else {
if (dst_r != TMP_REG1)
- return emit_op_imm(compiler, op_type, dst_r, TMP_REG1, src);
+ return emit_op_imm(compiler, op, dst_r, TMP_REG1, src);
dst_r = src;
}
@@ -1361,14 +1406,14 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
return SLJIT_SUCCESS;
}
- if (op_type == SLJIT_NEG) {
+ if (op == SLJIT_NEG) {
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
compiler->skip_checks = 1;
#endif
- return sljit_emit_op2(compiler, GET_FLAGS(op) | SLJIT_SUB, dst, dstw, SLJIT_IMM, 0, src, srcw);
+ return sljit_emit_op2(compiler, SLJIT_SUB | op_flags, dst, dstw, SLJIT_IMM, 0, src, srcw);
}
- flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0);
+ flags = (GET_FLAGS(op_flags) ? SET_FLAGS : 0) | ((op_flags & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0);
if (src & SLJIT_MEM) {
if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src, srcw))
FAIL_IF(compiler->error);
@@ -1382,7 +1427,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
else
srcw = src;
- emit_op_imm(compiler, flags | op_type, dst_r, TMP_REG1, srcw);
+ emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, srcw);
if (dst & SLJIT_MEM) {
if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw))
@@ -1393,20 +1438,23 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
return SLJIT_SUCCESS;
}
-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 sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- int dst_r, flags;
+ sljit_si dst_r, flags;
CHECK_ERROR();
check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG1;
+ dst_r = (dst >= SLJIT_SCRATCH_REG1 && dst <= TMP_REG3) ? dst : TMP_REG1;
flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0);
if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, WORD_SIZE | STORE | ARG_TEST, TMP_REG1, dst, dstw))
@@ -1472,14 +1520,14 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
{
check_sljit_get_register_index(reg);
return reg_map[reg];
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, int size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_si size)
{
CHECK_ERROR();
check_sljit_emit_op_custom(compiler, instruction, size);
@@ -1494,15 +1542,18 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compile
/* Floating point operators */
/* --------------------------------------------------------------------- */
-SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
return 1;
}
-static int emit_fop_mem(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw)
+#define FPU_LOAD (1 << 20)
+
+static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
{
- sljit_w tmp;
- sljit_w inst = VSTR | ((flags & STORE) ? 0 : 0x00100000);
+ sljit_sw tmp;
+ sljit_uw imm;
+ sljit_sw inst = VSTR_F32 | (flags & (SLJIT_SINGLE_OP | FPU_LOAD));
SLJIT_ASSERT(arg & SLJIT_MEM);
@@ -1513,7 +1564,7 @@ static int emit_fop_mem(struct sljit_compiler *compiler, int flags, int reg, int
argw = 0;
}
- if (arg & 0xf) {
+ if ((arg & 0xf) && (argw & 0x3) == 0) {
if (!(argw & ~0x3fc))
return push_inst32(compiler, inst | 0x800000 | RN4(arg & 0xf) | DD4(reg) | (argw >> 2));
if (!(-argw & ~0x3fc))
@@ -1534,13 +1585,29 @@ static int emit_fop_mem(struct sljit_compiler *compiler, int flags, int reg, int
}
}
+ if (arg & 0xf) {
+ if (emit_set_delta(compiler, TMP_REG1, arg & 0xf, argw) != SLJIT_ERR_UNSUPPORTED) {
+ FAIL_IF(compiler->error);
+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg));
+ }
+ imm = get_imm(argw & ~0x3fc);
+ if (imm != INVALID_IMM) {
+ FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & 0xf) | imm));
+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2));
+ }
+ imm = get_imm(-argw & ~0x3fc);
+ if (imm != INVALID_IMM) {
+ argw = -argw;
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & 0xf) | imm));
+ return push_inst32(compiler, inst | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2));
+ }
+ }
+
compiler->cache_arg = arg;
compiler->cache_argw = argw;
if (SLJIT_UNLIKELY(!(arg & 0xf)))
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
- else if (emit_set_delta(compiler, TMP_REG3, arg & 0xf, argw) != SLJIT_ERR_UNSUPPORTED)
- FAIL_IF(compiler->error);
else {
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
if (arg & 0xf)
@@ -1549,138 +1616,137 @@ static int emit_fop_mem(struct sljit_compiler *compiler, int flags, int reg, int
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg));
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- int dst_r;
+ sljit_si dst_r;
CHECK_ERROR();
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
+ SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100), float_transfer_bit_error);
compiler->cache_arg = 0;
compiler->cache_argw = 0;
+ op ^= SLJIT_SINGLE_OP;
- if (GET_OPCODE(op) == SLJIT_FCMP) {
+ if (GET_OPCODE(op) == SLJIT_CMPD) {
if (dst & SLJIT_MEM) {
- emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);
+ emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, dst, dstw);
dst = TMP_FREG1;
}
if (src & SLJIT_MEM) {
- emit_fop_mem(compiler, 0, TMP_FREG2, src, srcw);
+ emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src, srcw);
src = TMP_FREG2;
}
- FAIL_IF(push_inst32(compiler, VCMP_F64 | DD4(dst) | DM4(src)));
+ FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst) | DM4(src)));
return push_inst32(compiler, VMRS);
}
- dst_r = (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) ? dst : TMP_FREG1;
+ dst_r = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
if (src & SLJIT_MEM) {
- emit_fop_mem(compiler, 0, dst_r, src, srcw);
+ emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_r, src, srcw);
src = dst_r;
}
switch (GET_OPCODE(op)) {
- case SLJIT_FMOV:
+ case SLJIT_MOVD:
if (src != dst_r)
- FAIL_IF(push_inst32(compiler, VMOV_F64 | DD4(dst_r) | DM4(src)));
+ FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
break;
- case SLJIT_FNEG:
- FAIL_IF(push_inst32(compiler, VNEG_F64 | DD4(dst_r) | DM4(src)));
+ case SLJIT_NEGD:
+ FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
break;
- case SLJIT_FABS:
- FAIL_IF(push_inst32(compiler, VABS_F64 | DD4(dst_r) | DM4(src)));
+ case SLJIT_ABSD:
+ FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
break;
}
if (dst & SLJIT_MEM)
- return emit_fop_mem(compiler, STORE, TMP_FREG1, dst, dstw);
+ return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
return SLJIT_SUCCESS;
}
-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)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- int dst_r;
+ sljit_si dst_r;
CHECK_ERROR();
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
compiler->cache_arg = 0;
compiler->cache_argw = 0;
+ op ^= SLJIT_SINGLE_OP;
- dst_r = (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) ? dst : TMP_FREG1;
+ dst_r = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
if (src1 & SLJIT_MEM) {
- emit_fop_mem(compiler, 0, TMP_FREG1, src1, src1w);
+ emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
src1 = TMP_FREG1;
}
if (src2 & SLJIT_MEM) {
- emit_fop_mem(compiler, 0, TMP_FREG2, src2, src2w);
+ emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w);
src2 = TMP_FREG2;
}
switch (GET_OPCODE(op)) {
- case SLJIT_FADD:
- FAIL_IF(push_inst32(compiler, VADD_F64 | DD4(dst_r) | DN4(src1) | DM4(src2)));
+ case SLJIT_ADDD:
+ FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
break;
- case SLJIT_FSUB:
- FAIL_IF(push_inst32(compiler, VSUB_F64 | DD4(dst_r) | DN4(src1) | DM4(src2)));
+ case SLJIT_SUBD:
+ FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
break;
- case SLJIT_FMUL:
- FAIL_IF(push_inst32(compiler, VMUL_F64 | DD4(dst_r) | DN4(src1) | DM4(src2)));
+ case SLJIT_MULD:
+ FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
break;
- case SLJIT_FDIV:
- FAIL_IF(push_inst32(compiler, VDIV_F64 | DD4(dst_r) | DN4(src1) | DM4(src2)));
+ case SLJIT_DIVD:
+ FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
break;
}
if (dst & SLJIT_MEM)
- return emit_fop_mem(compiler, STORE, TMP_FREG1, dst, dstw);
+ return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
return SLJIT_SUCCESS;
}
+#undef FPU_LOAD
+
/* --------------------------------------------------------------------- */
/* Other instructions */
/* --------------------------------------------------------------------- */
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
- int size;
-
CHECK_ERROR();
- check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
+ check_sljit_emit_fast_enter(compiler, dst, dstw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
- compiler->temporaries = temporaries;
- compiler->saveds = saveds;
-
- size = (3 + saveds) * sizeof(sljit_uw);
- local_size += size;
- local_size = (local_size + 7) & ~7;
- local_size -= size;
- compiler->local_size = local_size;
+ /* For UNUSED dst. Uncommon, but possible. */
+ if (dst == SLJIT_UNUSED)
+ return SLJIT_SUCCESS;
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
+ if (dst <= TMP_REG3)
return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3));
- else if (dst & SLJIT_MEM) {
- if (getput_arg_fast(compiler, WORD_SIZE | STORE, TMP_REG3, dst, dstw))
- return compiler->error;
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, TMP_REG3)));
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0);
- }
- return SLJIT_SUCCESS;
+ /* Memory. */
+ if (getput_arg_fast(compiler, WORD_SIZE | STORE, TMP_REG3, dst, dstw))
+ return compiler->error;
+ /* TMP_REG3 is used for caching. */
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, TMP_REG3)));
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0);
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
CHECK_ERROR();
check_sljit_emit_fast_return(compiler, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
- if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+ if (src <= TMP_REG3)
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src)));
else if (src & SLJIT_MEM) {
if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG3, src, srcw))
@@ -1701,7 +1767,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
/* Conditional instructions */
/* --------------------------------------------------------------------- */
-static sljit_uw get_cc(int type)
+static sljit_uw get_cc(sljit_si type)
{
switch (type) {
case SLJIT_C_EQUAL:
@@ -1743,11 +1809,11 @@ static sljit_uw get_cc(int type)
return 0xd;
case SLJIT_C_OVERFLOW:
- case SLJIT_C_FLOAT_NAN:
+ case SLJIT_C_FLOAT_UNORDERED:
return 0x6;
case SLJIT_C_NOT_OVERFLOW:
- case SLJIT_C_FLOAT_NOT_NAN:
+ case SLJIT_C_FLOAT_ORDERED:
return 0x7;
default: /* SLJIT_JUMP */
@@ -1771,10 +1837,10 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
{
struct sljit_jump *jump;
- int cc;
+ sljit_si cc;
CHECK_ERROR_PTR();
check_sljit_emit_jump(compiler, type);
@@ -1787,7 +1853,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
/* In ARM, we don't need to touch the arguments. */
PTR_FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));
if (type < SLJIT_JUMP) {
- jump->flags |= IS_CONDITIONAL;
+ jump->flags |= IS_COND;
cc = get_cc(type);
jump->flags |= cc << 8;
PTR_FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
@@ -1804,12 +1870,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
return jump;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
{
struct sljit_jump *jump;
CHECK_ERROR();
check_sljit_emit_ijump(compiler, type, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
/* In ARM, we don't need to touch the arguments. */
if (src & SLJIT_IMM) {
@@ -1823,7 +1890,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, i
FAIL_IF(push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1)));
}
else {
- if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+ if (src <= TMP_REG3)
return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src));
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw));
@@ -1833,66 +1900,94 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, i
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw,
+ sljit_si type)
{
- int dst_r;
+ sljit_si dst_r, flags = GET_ALL_FLAGS(op);
+ sljit_ins ins;
sljit_uw cc;
CHECK_ERROR();
- check_sljit_emit_cond_value(compiler, op, dst, dstw, type);
+ check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
+ op = GET_OPCODE(op);
cc = get_cc(type);
- if (GET_OPCODE(op) == SLJIT_OR && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+ dst_r = (dst <= TMP_REG3) ? dst : TMP_REG2;
+
+ if (op < SLJIT_ADD) {
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
+ if (reg_map[dst_r] > 7) {
+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 1));
+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 0));
+ } else {
+ FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 1));
+ FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0));
+ }
+ return dst_r == TMP_REG2 ? emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw) : SLJIT_SUCCESS;
+ }
+
+ ins = (op == SLJIT_AND ? ANDI : (op == SLJIT_OR ? ORRI : EORI));
+ if ((op == SLJIT_OR || op == SLJIT_XOR) && dst <= TMP_REG3 && dst == src) {
+ /* Does not change the other bits. */
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
- FAIL_IF(push_inst32(compiler, ORRI | RN4(dst) | RD4(dst) | 0x1));
- if (op & SLJIT_SET_E) {
+ FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst) | 1));
+ if (flags & SLJIT_SET_E) {
+ /* The condition must always be set, even if the ORRI/EORI is not executed above. */
if (reg_map[dst] <= 7)
- return push_inst16(compiler, ORRS | RD3(dst) | RN3(dst));
- return push_inst32(compiler, ORR_W | SET_FLAGS | RD4(TMP_REG1) | RN4(dst) | RM4(dst));
+ return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst));
+ return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst));
}
return SLJIT_SUCCESS;
}
- dst_r = TMP_REG2;
- if (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS && reg_map[dst] <= 7)
- dst_r = dst;
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_SIZE, TMP_REG1, src, srcw, dst, dstw));
+ src = TMP_REG1;
+ srcw = 0;
+ } else if (src & SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ src = TMP_REG1;
+ srcw = 0;
+ }
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
- FAIL_IF(push_inst16(compiler, MOVSI | 0x1 | RDN3(dst_r)));
- FAIL_IF(push_inst16(compiler, MOVSI | 0x0 | RDN3(dst_r)));
-
- if (dst_r == TMP_REG2) {
- if (GET_OPCODE(op) == SLJIT_OR) {
-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
- compiler->skip_checks = 1;
-#endif
- return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REG2, 0);
- }
- if (dst & SLJIT_MEM)
- return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw);
- else
- return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2));
+ FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1));
+ FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 0));
+ if (dst_r == TMP_REG2)
+ FAIL_IF(emit_op_mem2(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0));
+
+ if (flags & SLJIT_SET_E) {
+ /* The condition must always be set, even if the ORR/EORI is not executed above. */
+ if (reg_map[dst_r] <= 7)
+ return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst_r));
+ return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r));
}
-
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;
- int dst_r;
+ sljit_si dst_r;
CHECK_ERROR_PTR();
check_sljit_emit_const(compiler, dst, dstw, init_value);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG1;
+ dst_r = (dst <= TMP_REG3) ? dst : TMP_REG1;
PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value));
if (dst & SLJIT_MEM)
@@ -1905,7 +2000,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ad
inline_set_jump_addr(addr, new_addr, 1);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
{
sljit_uh* inst = (sljit_uh*)addr;
modify_imm32_const(inst, new_constant);
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_v5.c b/src/3rdparty/pcre/sljit/sljitNativeARM_v5.c
index e3a5873247..23a45a4c6a 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeARM_v5.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeARM_v5.c
@@ -24,7 +24,7 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
{
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
return "ARMv7" SLJIT_CPUINFO;
@@ -41,8 +41,8 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
#define TMP_PC (SLJIT_NO_REGISTERS + 4)
-#define TMP_FREG1 (SLJIT_FLOAT_REG4 + 1)
-#define TMP_FREG2 (SLJIT_FLOAT_REG4 + 2)
+#define TMP_FREG1 (0)
+#define TMP_FREG2 (SLJIT_FLOAT_REG6 + 1)
/* In ARM instruction words.
Cache lines are usually 32 byte aligned. */
@@ -52,11 +52,11 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
#define ALIGN_INSTRUCTION(ptr) \
(sljit_uw*)(((sljit_uw)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1))
#define MAX_DIFFERENCE(max_diff) \
- (((max_diff) / (int)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1))
+ (((max_diff) / (sljit_si)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1))
/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
- 0, 0, 1, 2, 10, 11, 4, 5, 6, 7, 8, 13, 3, 12, 14, 15
+ 0, 0, 1, 2, 10, 11, 4, 5, 6, 7, 8, 13, 3, 12, 14, 15
};
#define RM(rm) (reg_map[rm])
@@ -99,16 +99,16 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
#define SMULL 0xe0c00090
#define SUB_DP 0x2
#define UMULL 0xe0800090
-#define VABS_F64 0xeeb00bc0
-#define VADD_F64 0xee300b00
-#define VCMP_F64 0xeeb40b40
-#define VDIV_F64 0xee800b00
-#define VMOV_F64 0xeeb00b40
+#define VABS_F32 0xeeb00ac0
+#define VADD_F32 0xee300a00
+#define VCMP_F32 0xeeb40a40
+#define VDIV_F32 0xee800a00
+#define VMOV_F32 0xeeb00a40
#define VMRS 0xeef1fa10
-#define VMUL_F64 0xee200b00
-#define VNEG_F64 0xeeb10b40
-#define VSTR 0xed000b00
-#define VSUB_F64 0xee300b40
+#define VMUL_F32 0xee200a00
+#define VNEG_F32 0xeeb10a40
+#define VSTR_F32 0xed000a00
+#define VSUB_F32 0xee300a40
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
/* Arm v7 specific instructions. */
@@ -122,13 +122,13 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
-static int push_cpool(struct sljit_compiler *compiler)
+static sljit_si push_cpool(struct sljit_compiler *compiler)
{
/* Pushing the constant pool into the instruction stream. */
sljit_uw* inst;
sljit_uw* cpool_ptr;
sljit_uw* cpool_end;
- int i;
+ sljit_si i;
/* The label could point the address after the constant pool. */
if (compiler->last_label && compiler->last_label->size == compiler->size)
@@ -160,7 +160,7 @@ static int push_cpool(struct sljit_compiler *compiler)
return SLJIT_SUCCESS;
}
-static int push_inst(struct sljit_compiler *compiler, sljit_uw inst)
+static sljit_si push_inst(struct sljit_compiler *compiler, sljit_uw inst)
{
sljit_uw* ptr;
@@ -174,7 +174,7 @@ static int push_inst(struct sljit_compiler *compiler, sljit_uw inst)
return SLJIT_SUCCESS;
}
-static int push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
+static sljit_si push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
{
sljit_uw* ptr;
sljit_uw cpool_index = CPOOL_SIZE;
@@ -224,7 +224,7 @@ static int push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst
return SLJIT_SUCCESS;
}
-static int push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
+static sljit_si push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
{
sljit_uw* ptr;
if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE))
@@ -244,7 +244,7 @@ static int push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE int prepare_blx(struct sljit_compiler *compiler)
+static SLJIT_INLINE sljit_si prepare_blx(struct sljit_compiler *compiler)
{
/* Place for at least two instruction (doesn't matter whether the first has a literal). */
if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4088)))
@@ -252,7 +252,7 @@ static SLJIT_INLINE int prepare_blx(struct sljit_compiler *compiler)
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE int emit_blx(struct sljit_compiler *compiler)
+static SLJIT_INLINE sljit_si emit_blx(struct sljit_compiler *compiler)
{
/* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */
SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092));
@@ -282,7 +282,7 @@ static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_
/* Must be a load instruction with immediate offset. */
SLJIT_ASSERT(ind < cpool_size && !(*last_pc_patch & (1 << 25)) && (*last_pc_patch & (1 << 20)));
- if ((int)const_pool[ind] < 0) {
+ if ((sljit_si)const_pool[ind] < 0) {
const_pool[ind] = counter;
ind = counter;
counter++;
@@ -307,24 +307,24 @@ static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_
/* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */
struct future_patch {
struct future_patch* next;
- int index;
- int value;
+ sljit_si index;
+ sljit_si value;
};
-static SLJIT_INLINE int resolve_const_pool_index(struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr)
+static SLJIT_INLINE sljit_si resolve_const_pool_index(struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr)
{
- int value;
+ sljit_si value;
struct future_patch *curr_patch, *prev_patch;
/* Using the values generated by patch_pc_relative_loads. */
if (!*first_patch)
- value = (int)cpool_start_address[cpool_current_index];
+ value = (sljit_si)cpool_start_address[cpool_current_index];
else {
curr_patch = *first_patch;
prev_patch = 0;
while (1) {
if (!curr_patch) {
- value = (int)cpool_start_address[cpool_current_index];
+ value = (sljit_si)cpool_start_address[cpool_current_index];
break;
}
if ((sljit_uw)curr_patch->index == cpool_current_index) {
@@ -364,7 +364,7 @@ static SLJIT_INLINE int resolve_const_pool_index(struct future_patch **first_pat
#else
-static int push_inst(struct sljit_compiler *compiler, sljit_uw inst)
+static sljit_si push_inst(struct sljit_compiler *compiler, sljit_uw inst)
{
sljit_uw* ptr;
@@ -375,7 +375,7 @@ static int push_inst(struct sljit_compiler *compiler, sljit_uw inst)
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE int emit_imm(struct sljit_compiler *compiler, int reg, sljit_w imm)
+static SLJIT_INLINE sljit_si emit_imm(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
{
FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));
return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));
@@ -383,9 +383,9 @@ static SLJIT_INLINE int emit_imm(struct sljit_compiler *compiler, int reg, sljit
#endif
-static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code)
+static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code)
{
- sljit_w diff;
+ sljit_sw diff;
if (jump->flags & SLJIT_REWRITABLE_JUMP)
return 0;
@@ -395,10 +395,10 @@ static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uw *code
code_ptr--;
if (jump->flags & JUMP_ADDR)
- diff = ((sljit_w)jump->u.target - (sljit_w)(code_ptr + 2));
+ diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2));
else {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
- diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)(code_ptr + 2));
+ diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2));
}
/* Branch to Thumb code has not been optimized yet. */
@@ -421,10 +421,10 @@ static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uw *code
}
#else
if (jump->flags & JUMP_ADDR)
- diff = ((sljit_w)jump->u.target - (sljit_w)code_ptr);
+ diff = ((sljit_sw)jump->u.target - (sljit_sw)code_ptr);
else {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
- diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)code_ptr);
+ diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)code_ptr);
}
/* Branch to Thumb code has not been optimized yet. */
@@ -442,14 +442,14 @@ static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uw *code
return 0;
}
-static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, int flush)
+static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, sljit_si flush)
{
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
sljit_uw *ptr = (sljit_uw*)addr;
sljit_uw *inst = (sljit_uw*)ptr[0];
sljit_uw mov_pc = ptr[1];
- int bl = (mov_pc & 0x0000f000) != RD(TMP_PC);
- sljit_w diff = (sljit_w)(((sljit_w)new_addr - (sljit_w)(inst + 2)) >> 2);
+ sljit_si bl = (mov_pc & 0x0000f000) != RD(TMP_PC);
+ sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2)) >> 2);
if (diff <= 0x7fffff && diff >= -0x800000) {
/* Turn to branch. */
@@ -498,9 +498,9 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr,
#endif
}
-static sljit_uw get_immediate(sljit_uw imm);
+static sljit_uw get_imm(sljit_uw imm);
-static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_w new_constant, int flush)
+static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw new_constant, sljit_si flush)
{
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
sljit_uw *ptr = (sljit_uw*)addr;
@@ -508,7 +508,7 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_w new_constant, i
sljit_uw ldr_literal = ptr[1];
sljit_uw src2;
- src2 = get_immediate(new_constant);
+ src2 = get_imm(new_constant);
if (src2) {
*inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2;
if (flush) {
@@ -517,7 +517,7 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_w new_constant, i
return;
}
- src2 = get_immediate(~new_constant);
+ src2 = get_imm(~new_constant);
if (src2) {
*inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2;
if (flush) {
@@ -730,12 +730,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (jump->flags & PATCH_B) {
if (!(jump->flags & JUMP_ADDR)) {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
- SLJIT_ASSERT(((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) >= -0x02000000);
- *buf_ptr |= (((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) >> 2) & 0x00ffffff;
+ SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - (sljit_sw)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - (sljit_sw)(buf_ptr + 2)) >= -0x02000000);
+ *buf_ptr |= (((sljit_sw)jump->u.label->addr - (sljit_sw)(buf_ptr + 2)) >> 2) & 0x00ffffff;
}
else {
- SLJIT_ASSERT(((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) >= -0x02000000);
- *buf_ptr |= (((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) >> 2) & 0x00ffffff;
+ SLJIT_ASSERT(((sljit_sw)jump->u.target - (sljit_sw)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_sw)jump->u.target - (sljit_sw)(buf_ptr + 2)) >= -0x02000000);
+ *buf_ptr |= (((sljit_sw)jump->u.target - (sljit_sw)(buf_ptr + 2)) >> 2) & 0x00ffffff;
}
}
else if (jump->flags & SLJIT_REWRITABLE_JUMP) {
@@ -785,7 +785,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
}
#endif
- SLJIT_ASSERT(code_ptr - code <= (int)size);
+ SLJIT_ASSERT(code_ptr - code <= (sljit_si)size);
SLJIT_CACHE_FLUSH(code, code_ptr);
compiler->error = SLJIT_ERR_COMPILED;
@@ -793,6 +793,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
return code;
}
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
/* emit_op inp_flags.
WRITE_BACK must be the first, since it is a flag. */
#define WRITE_BACK 0x01
@@ -815,28 +819,31 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#define EMIT_DATA_PROCESS_INS(opcode, set_flags, dst, src1, src2) \
(0xe0000000 | ((opcode) << 21) | (set_flags) | RD(dst) | RN(src1) | (src2))
-static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w);
+static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si inp_flags,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w);
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
- int size;
+ sljit_si size;
sljit_uw push;
CHECK_ERROR();
- check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
+ check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
- compiler->temporaries = temporaries;
+ compiler->scratches = scratches;
compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
/* Push saved registers, temporary registers
stmdb sp!, {..., lr} */
push = PUSH | (1 << 14);
- if (temporaries >= 5)
+ if (scratches >= 5)
push |= 1 << 11;
- if (temporaries >= 4)
+ if (scratches >= 4)
push |= 1 << 10;
if (saveds >= 5)
push |= 1 << 8;
@@ -852,8 +859,8 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
/* Stack must be aligned to 8 bytes: */
size = (1 + saveds) * sizeof(sljit_uw);
- if (temporaries >= 4)
- size += (temporaries - 3) * sizeof(sljit_uw);
+ if (scratches >= 4)
+ size += (scratches - 3) * sizeof(sljit_uw);
local_size += size;
local_size = (local_size + 7) & ~7;
local_size -= size;
@@ -862,35 +869,38 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size));
if (args >= 1)
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG1, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG1)));
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG1, SLJIT_UNUSED, RM(SLJIT_SCRATCH_REG1)));
if (args >= 2)
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG2, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG2)));
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG2, SLJIT_UNUSED, RM(SLJIT_SCRATCH_REG2)));
if (args >= 3)
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG3, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG3)));
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG3, SLJIT_UNUSED, RM(SLJIT_SCRATCH_REG3)));
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
- int size;
+ sljit_si size;
CHECK_ERROR_VOID();
- check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
+ check_sljit_set_context(compiler, args, scratches, saveds, local_size);
- compiler->temporaries = temporaries;
+ compiler->scratches = scratches;
compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
size = (1 + saveds) * sizeof(sljit_uw);
- if (temporaries >= 4)
- size += (temporaries - 3) * sizeof(sljit_uw);
+ if (scratches >= 4)
+ size += (scratches - 3) * sizeof(sljit_uw);
local_size += size;
local_size = (local_size + 7) & ~7;
local_size -= size;
compiler->local_size = local_size;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
sljit_uw pop;
@@ -905,9 +915,9 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
pop = POP | (1 << 15);
/* Push saved registers, temporary registers
ldmia sp!, {..., pc} */
- if (compiler->temporaries >= 5)
+ if (compiler->scratches >= 5)
pop |= 1 << 11;
- if (compiler->temporaries >= 4)
+ if (compiler->scratches >= 4)
pop |= 1 << 10;
if (compiler->saveds >= 5)
pop |= 1 << 8;
@@ -932,7 +942,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
w/b/h/N - word/byte/half/NOT allowed (2 bit)
It contans 16 items, but not all are different. */
-static sljit_w data_transfer_insts[16] = {
+static sljit_sw data_transfer_insts[16] = {
/* s u w */ 0xe5000000 /* str */,
/* s u b */ 0xe5400000 /* strb */,
/* s u h */ 0xe10000b0 /* strh */,
@@ -998,12 +1008,80 @@ static sljit_w data_transfer_insts[16] = {
} \
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | ((flags & ARGS_SWAPPED) ? reg_map[src2] : reg_map[src1])));
-static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
- int dst, int src1, int src2)
+static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
+ sljit_si dst, sljit_si src1, sljit_si src2)
{
- sljit_w mul_inst;
+ sljit_sw mul_inst;
switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
+ if (dst != src2) {
+ if (src2 & SRC2_IMM) {
+ if (flags & INV_IMM)
+ EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
+ EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+ }
+ EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, reg_map[src2]);
+ }
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_UB:
+ case SLJIT_MOV_SB:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
+ if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+ if (op == SLJIT_MOV_UB)
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(AND_DP, 0, dst, src2, SRC2_IMM | 0xff));
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2]));
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_UB ? 0x20 : 0x40) | reg_map[dst]));
+#else
+ return push_inst(compiler, (op == SLJIT_MOV_UB ? UXTB : SXTB) | RD(dst) | RM(src2));
+#endif
+ }
+ else if (dst != src2) {
+ SLJIT_ASSERT(src2 & SRC2_IMM);
+ if (flags & INV_IMM)
+ EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
+ EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+ }
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_UH:
+ case SLJIT_MOV_SH:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
+ if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2]));
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_UH ? 0x20 : 0x40) | reg_map[dst]));
+#else
+ return push_inst(compiler, (op == SLJIT_MOV_UH ? UXTH : SXTH) | RD(dst) | RM(src2));
+#endif
+ }
+ else if (dst != src2) {
+ SLJIT_ASSERT(src2 & SRC2_IMM);
+ if (flags & INV_IMM)
+ EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
+ EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+ }
+ return SLJIT_SUCCESS;
+
+ case SLJIT_NOT:
+ if (src2 & SRC2_IMM) {
+ if (flags & INV_IMM)
+ EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+ EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
+ }
+ EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, RM(src2));
+
+ case SLJIT_CLZ:
+ SLJIT_ASSERT(!(flags & INV_IMM));
+ SLJIT_ASSERT(!(src2 & SRC2_IMM));
+ FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));
+ if (flags & SET_FLAGS)
+ EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(CMP_DP, SLJIT_UNUSED, dst, SRC2_IMM);
+ return SLJIT_SUCCESS;
+
case SLJIT_ADD:
SLJIT_ASSERT(!(flags & INV_IMM));
EMIT_DATA_PROCESS_INS_AND_RETURN(ADD_DP);
@@ -1073,74 +1151,6 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
case SLJIT_ASHR:
EMIT_SHIFT_INS_AND_RETURN(2);
-
- case SLJIT_MOV:
- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
- if (dst != src2) {
- if (src2 & SRC2_IMM) {
- if (flags & INV_IMM)
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
- }
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, reg_map[src2]);
- }
- return SLJIT_SUCCESS;
-
- case SLJIT_MOV_UB:
- case SLJIT_MOV_SB:
- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
- if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- if (op == SLJIT_MOV_UB)
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(AND_DP, 0, dst, src2, SRC2_IMM | 0xff));
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2]));
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_UB ? 0x20 : 0x40) | reg_map[dst]));
-#else
- return push_inst(compiler, (op == SLJIT_MOV_UB ? UXTB : SXTB) | RD(dst) | RM(src2));
-#endif
- }
- else if (dst != src2) {
- SLJIT_ASSERT(src2 & SRC2_IMM);
- if (flags & INV_IMM)
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
- }
- return SLJIT_SUCCESS;
-
- case SLJIT_MOV_UH:
- case SLJIT_MOV_SH:
- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
- if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2]));
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_UH ? 0x20 : 0x40) | reg_map[dst]));
-#else
- return push_inst(compiler, (op == SLJIT_MOV_UH ? UXTH : SXTH) | RD(dst) | RM(src2));
-#endif
- }
- else if (dst != src2) {
- SLJIT_ASSERT(src2 & SRC2_IMM);
- if (flags & INV_IMM)
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
- }
- return SLJIT_SUCCESS;
-
- case SLJIT_NOT:
- if (src2 & SRC2_IMM) {
- if (flags & INV_IMM)
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
- }
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, RM(src2));
-
- case SLJIT_CLZ:
- SLJIT_ASSERT(!(flags & INV_IMM));
- SLJIT_ASSERT(!(src2 & SRC2_IMM));
- FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));
- if (flags & SET_FLAGS)
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(CMP_DP, SLJIT_UNUSED, dst, SRC2_IMM);
- return SLJIT_SUCCESS;
}
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
@@ -1152,9 +1162,9 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
/* Tests whether the immediate can be stored in the 12 bit imm field.
Returns with 0 if not possible. */
-static sljit_uw get_immediate(sljit_uw imm)
+static sljit_uw get_imm(sljit_uw imm)
{
- int rol;
+ sljit_si rol;
if (imm <= 0xff)
return SRC2_IMM | imm;
@@ -1190,12 +1200,12 @@ static sljit_uw get_immediate(sljit_uw imm)
}
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
-static int generate_int(struct sljit_compiler *compiler, int reg, sljit_uw imm, int positive)
+static sljit_si generate_int(struct sljit_compiler *compiler, sljit_si reg, sljit_uw imm, sljit_si positive)
{
sljit_uw mask;
sljit_uw imm1;
sljit_uw imm2;
- int rol;
+ sljit_si rol;
/* Step1: Search a zero byte (8 continous zero bit). */
mask = 0xff000000;
@@ -1301,7 +1311,7 @@ static int generate_int(struct sljit_compiler *compiler, int reg, sljit_uw imm,
}
#endif
-static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_uw imm)
+static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_uw imm)
{
sljit_uw tmp;
@@ -1311,13 +1321,13 @@ static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_uw imm
#endif
/* Create imm by 1 inst. */
- tmp = get_immediate(imm);
+ tmp = get_imm(imm);
if (tmp) {
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, tmp));
return SLJIT_SUCCESS;
}
- tmp = get_immediate(~imm);
+ tmp = get_imm(~imm);
if (tmp) {
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, tmp));
return SLJIT_SUCCESS;
@@ -1335,20 +1345,36 @@ static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_uw imm
#endif
}
+/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
+static sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sljit_si reg, sljit_sw value)
+{
+ if (value >= 0) {
+ value = get_imm(value);
+ if (value)
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, dst, reg, value));
+ }
+ else {
+ value = get_imm(-value);
+ if (value)
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, dst, reg, value));
+ }
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
/* Can perform an operation using at most 1 instruction. */
-static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw)
+static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_flags, sljit_si reg, sljit_si arg, sljit_sw argw)
{
sljit_uw imm;
if (arg & SLJIT_IMM) {
- imm = get_immediate(argw);
+ imm = get_imm(argw);
if (imm) {
if (inp_flags & ARG_TEST)
return 1;
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, imm));
return -1;
}
- imm = get_immediate(~argw);
+ imm = get_imm(~argw);
if (imm) {
if (inp_flags & ARG_TEST)
return 1;
@@ -1408,7 +1434,7 @@ static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int r
/* See getput_arg below.
Note: can_cache is called only for binary operators. Those
operators always uses word arguments without write back. */
-static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
{
/* Immediate caching is not supported as it would be an operation on constant arguments. */
if (arg & SLJIT_IMM)
@@ -1456,11 +1482,12 @@ static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
}
/* Emit the necessary instructions. See can_cache above. */
-static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags, sljit_si reg, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
{
- int tmp_r;
- sljit_w max_delta;
- sljit_w sign;
+ sljit_si tmp_r;
+ sljit_sw max_delta;
+ sljit_sw sign;
+ sljit_uw imm;
if (arg & SLJIT_IMM) {
SLJIT_ASSERT(inp_flags & LOAD_DATA);
@@ -1474,8 +1501,9 @@ static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, i
if ((arg & 0xf) == SLJIT_UNUSED) {
/* Write back is not used. */
- if ((compiler->cache_arg & SLJIT_IMM) && (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta || ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= (sljit_uw)max_delta)) {
- if (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta) {
+ imm = (sljit_uw)(argw - compiler->cache_argw);
+ if ((compiler->cache_arg & SLJIT_IMM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
+ if (imm <= (sljit_uw)max_delta) {
sign = 1;
argw = argw - compiler->cache_argw;
}
@@ -1484,18 +1512,14 @@ static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, i
argw = compiler->cache_argw - argw;
}
- if (max_delta & 0xf00) {
- EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, sign, 0, reg, TMP_REG3, argw));
- }
- else {
- EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, sign, 0, reg, TMP_REG3, TYPE2_TRANSFER_IMM(argw)));
- }
+ GETPUT_ARG_DATA_TRANSFER(sign, 0, reg, TMP_REG3, argw);
return SLJIT_SUCCESS;
}
/* With write back, we can create some sophisticated loads, but
it is hard to decide whether we should convert downward (0s) or upward (1s). */
- if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= (sljit_uw)max_delta || (sljit_uw)next_argw - (sljit_uw)argw <= (sljit_uw)max_delta)) {
+ imm = (sljit_uw)(argw - next_argw);
+ if ((next_arg & SLJIT_MEM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
SLJIT_ASSERT(inp_flags & LOAD_DATA);
compiler->cache_arg = SLJIT_IMM;
@@ -1508,29 +1532,6 @@ static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, i
return SLJIT_SUCCESS;
}
- /* Extended imm addressing for [reg+imm] format. */
- sign = (max_delta << 8) | 0xff;
- if (!(arg & 0xf0) && argw <= sign && argw >= -sign) {
- TEST_WRITE_BACK();
- if (argw >= 0) {
- sign = 1;
- }
- else {
- sign = 0;
- argw = -argw;
- }
-
- /* Optimization: add is 0x4, sub is 0x2. Sign is 1 for add and 0 for sub. */
- if (max_delta & 0xf00)
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP << sign, 0, tmp_r, arg & 0xf, SRC2_IMM | (argw >> 12) | 0xa00));
- else
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP << sign, 0, tmp_r, arg & 0xf, SRC2_IMM | (argw >> 8) | 0xc00));
-
- argw &= max_delta;
- GETPUT_ARG_DATA_TRANSFER(sign, inp_flags & WRITE_BACK, reg, tmp_r, argw);
- return SLJIT_SUCCESS;
- }
-
if (arg & 0xf0) {
SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00));
if (inp_flags & WRITE_BACK)
@@ -1540,17 +1541,33 @@ static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, i
return SLJIT_SUCCESS;
}
- if (compiler->cache_arg == arg && ((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta) {
+ imm = (sljit_uw)(argw - compiler->cache_argw);
+ if (compiler->cache_arg == arg && imm <= (sljit_uw)max_delta) {
SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
- argw = argw - compiler->cache_argw;
- GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, argw);
+ GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, imm);
return SLJIT_SUCCESS;
}
-
- if (compiler->cache_arg == arg && ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= (sljit_uw)max_delta) {
+ if (compiler->cache_arg == arg && imm >= (sljit_uw)-max_delta) {
SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
- argw = compiler->cache_argw - argw;
- GETPUT_ARG_DATA_TRANSFER(0, 0, reg, TMP_REG3, argw);
+ imm = (sljit_uw)-(sljit_sw)imm;
+ GETPUT_ARG_DATA_TRANSFER(0, 0, reg, TMP_REG3, imm);
+ return SLJIT_SUCCESS;
+ }
+
+ imm = get_imm(argw & ~max_delta);
+ if (imm) {
+ TEST_WRITE_BACK();
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & 0xf, imm));
+ GETPUT_ARG_DATA_TRANSFER(1, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
+ return SLJIT_SUCCESS;
+ }
+
+ imm = get_imm(-argw & ~max_delta);
+ if (imm) {
+ argw = -argw;
+ TEST_WRITE_BACK();
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, tmp_r, arg & 0xf, imm));
+ GETPUT_ARG_DATA_TRANSFER(0, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
return SLJIT_SUCCESS;
}
@@ -1572,7 +1589,8 @@ static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, i
return SLJIT_SUCCESS;
}
- if (arg == next_arg && !(inp_flags & WRITE_BACK) && ((sljit_uw)argw - (sljit_uw)next_argw <= (sljit_uw)max_delta || (sljit_uw)next_argw - (sljit_uw)argw <= (sljit_uw)max_delta)) {
+ imm = (sljit_uw)(argw - next_argw);
+ if (arg == next_arg && !(inp_flags & WRITE_BACK) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
SLJIT_ASSERT(inp_flags & LOAD_DATA);
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & 0xf]));
@@ -1595,10 +1613,26 @@ static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, i
return SLJIT_SUCCESS;
}
-static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+{
+ if (getput_arg_fast(compiler, flags, reg, arg, argw))
+ return compiler->error;
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
+}
+
+static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
+{
+ if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
+ return compiler->error;
+ return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+}
+
+static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si inp_flags,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
/* arg1 goes to TMP_REG1 or src reg
arg2 goes to TMP_REG2, imm or src reg
@@ -1606,27 +1640,27 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
/* We prefers register and simple consts. */
- int dst_r;
- int src1_r;
- int src2_r = 0;
- int sugg_src2_r = TMP_REG2;
- int flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+ sljit_si dst_r;
+ sljit_si src1_r;
+ sljit_si src2_r = 0;
+ sljit_si sugg_src2_r = TMP_REG2;
+ sljit_si flags = GET_FLAGS(op) ? SET_FLAGS : 0;
compiler->cache_arg = 0;
compiler->cache_argw = 0;
/* Destination check. */
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REG3) {
+ if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ dst_r = TMP_REG2;
+ }
+ else if (dst <= TMP_REG3) {
dst_r = dst;
flags |= REG_DEST;
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
sugg_src2_r = dst_r;
}
- else if (dst == SLJIT_UNUSED) {
- if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
- return SLJIT_SUCCESS;
- dst_r = TMP_REG2;
- }
else {
SLJIT_ASSERT(dst & SLJIT_MEM);
if (getput_arg_fast(compiler, inp_flags | ARG_TEST, TMP_REG2, dst, dstw)) {
@@ -1640,43 +1674,55 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
}
/* Source 1. */
- if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= TMP_REG3)
+ if (src1 <= TMP_REG3)
src1_r = src1;
- else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) {
+ else if (src2 <= TMP_REG3) {
flags |= ARGS_SWAPPED;
src1_r = src2;
src2 = src1;
src2w = src1w;
}
- else {
+ else do { /* do { } while(0) is used because of breaks. */
+ src1_r = 0;
if ((inp_flags & ALLOW_ANY_IMM) && (src1 & SLJIT_IMM)) {
/* The second check will generate a hit. */
- src2_r = get_immediate(src1w);
+ src2_r = get_imm(src1w);
if (src2_r) {
flags |= ARGS_SWAPPED;
src1 = src2;
src1w = src2w;
+ break;
}
if (inp_flags & ALLOW_INV_IMM) {
- src2_r = get_immediate(~src1w);
+ src2_r = get_imm(~src1w);
if (src2_r) {
flags |= ARGS_SWAPPED | INV_IMM;
src1 = src2;
src1w = src2w;
+ break;
+ }
+ }
+ if (GET_OPCODE(op) == SLJIT_ADD) {
+ src2_r = get_imm(-src1w);
+ if (src2_r) {
+ /* Note: ARGS_SWAPPED is intentionally not applied! */
+ src1 = src2;
+ src1w = src2w;
+ op = SLJIT_SUB | GET_ALL_FLAGS(op);
+ break;
}
}
}
- src1_r = 0;
if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w)) {
FAIL_IF(compiler->error);
src1_r = TMP_REG1;
}
- }
+ } while (0);
/* Source 2. */
if (src2_r == 0) {
- if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) {
+ if (src2 <= TMP_REG3) {
src2_r = src2;
flags |= REG_SOURCE;
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
@@ -1684,16 +1730,32 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
}
else do { /* do { } while(0) is used because of breaks. */
if ((inp_flags & ALLOW_ANY_IMM) && (src2 & SLJIT_IMM)) {
- src2_r = get_immediate(src2w);
+ src2_r = get_imm(src2w);
if (src2_r)
break;
if (inp_flags & ALLOW_INV_IMM) {
- src2_r = get_immediate(~src2w);
+ src2_r = get_imm(~src2w);
if (src2_r) {
flags |= INV_IMM;
break;
}
}
+ if (GET_OPCODE(op) == SLJIT_ADD) {
+ src2_r = get_imm(-src2w);
+ if (src2_r) {
+ op = SLJIT_SUB | GET_ALL_FLAGS(op);
+ flags &= ~ARGS_SWAPPED;
+ break;
+ }
+ }
+ if (GET_OPCODE(op) == SLJIT_SUB && !(flags & ARGS_SWAPPED)) {
+ src2_r = get_imm(-src2w);
+ if (src2_r) {
+ op = SLJIT_ADD | GET_ALL_FLAGS(op);
+ flags &= ~ARGS_SWAPPED;
+ break;
+ }
+ }
}
/* src2_r is 0. */
@@ -1762,8 +1824,8 @@ extern "C" {
#endif
#if defined(__GNUC__)
-extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator);
-extern unsigned int __aeabi_idivmod(unsigned numerator, unsigned denominator);
+extern unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator);
+extern int __aeabi_idivmod(int numerator, int denominator);
#else
#error "Software divmod functions are needed"
#endif
@@ -1772,7 +1834,7 @@ extern unsigned int __aeabi_idivmod(unsigned numerator, unsigned denominator);
}
#endif
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
{
CHECK_ERROR();
check_sljit_emit_op0(compiler, op);
@@ -1789,21 +1851,21 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
case SLJIT_SMUL:
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
- | (reg_map[SLJIT_TEMPORARY_REG2] << 16)
- | (reg_map[SLJIT_TEMPORARY_REG1] << 12)
- | (reg_map[SLJIT_TEMPORARY_REG1] << 8)
- | reg_map[SLJIT_TEMPORARY_REG2]);
+ | (reg_map[SLJIT_SCRATCH_REG2] << 16)
+ | (reg_map[SLJIT_SCRATCH_REG1] << 12)
+ | (reg_map[SLJIT_SCRATCH_REG1] << 8)
+ | reg_map[SLJIT_SCRATCH_REG2]);
#else
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG2)));
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, RM(SLJIT_SCRATCH_REG2)));
return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
- | (reg_map[SLJIT_TEMPORARY_REG2] << 16)
- | (reg_map[SLJIT_TEMPORARY_REG1] << 12)
- | (reg_map[SLJIT_TEMPORARY_REG1] << 8)
+ | (reg_map[SLJIT_SCRATCH_REG2] << 16)
+ | (reg_map[SLJIT_SCRATCH_REG1] << 12)
+ | (reg_map[SLJIT_SCRATCH_REG1] << 8)
| reg_map[TMP_REG1]);
#endif
case SLJIT_UDIV:
case SLJIT_SDIV:
- if (compiler->temporaries >= 3)
+ if (compiler->scratches >= 3)
EMIT_INSTRUCTION(0xe52d2008 /* str r2, [sp, #-8]! */);
#if defined(__GNUC__)
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
@@ -1811,7 +1873,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
#else
#error "Software divmod functions are needed"
#endif
- if (compiler->temporaries >= 3)
+ if (compiler->scratches >= 3)
return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */);
return SLJIT_SUCCESS;
}
@@ -1819,47 +1881,51 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
CHECK_ERROR();
check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
case SLJIT_MOV_UI:
case SLJIT_MOV_SI:
+ case SLJIT_MOV_P:
return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_MOV_UB:
- return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
case SLJIT_MOV_SB:
- return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
case SLJIT_MOV_UH:
- return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
case SLJIT_MOV_SH:
- return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
case SLJIT_MOVU:
case SLJIT_MOVU_UI:
case SLJIT_MOVU_SI:
+ case SLJIT_MOVU_P:
return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_MOVU_UB:
- return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
case SLJIT_MOVU_SB:
- return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
case SLJIT_MOVU_UH:
- return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
case SLJIT_MOVU_SH:
- return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
case SLJIT_NOT:
return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
@@ -1868,7 +1934,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
compiler->skip_checks = 1;
#endif
- return sljit_emit_op2(compiler, SLJIT_SUB | GET_FLAGS(op), dst, dstw, SLJIT_IMM, 0, src, srcw);
+ return sljit_emit_op2(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), dst, dstw, SLJIT_IMM, 0, src, srcw);
case SLJIT_CLZ:
return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
@@ -1877,13 +1943,16 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
return SLJIT_SUCCESS;
}
-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 sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
CHECK_ERROR();
check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
switch (GET_OPCODE(op)) {
case SLJIT_ADD:
@@ -1916,14 +1985,14 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
{
check_sljit_get_register_index(reg);
return reg_map[reg];
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, int size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_si size)
{
CHECK_ERROR();
check_sljit_emit_op_custom(compiler, instruction, size);
@@ -1940,9 +2009,9 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compile
/* 0 - no fpu
1 - vfp */
-static int arm_fpu_type = -1;
+static sljit_si arm_fpu_type = -1;
-static void init_compiler()
+static void init_compiler(void)
{
if (arm_fpu_type != -1)
return;
@@ -1951,7 +2020,7 @@ static void init_compiler()
arm_fpu_type = 1;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
if (arm_fpu_type == -1)
init_compiler();
@@ -1962,7 +2031,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
#define arm_fpu_type 1
-SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
/* Always available. */
return 1;
@@ -1970,56 +2039,61 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
#endif
-#define EMIT_FPU_DATA_TRANSFER(add, load, base, freg, offs) \
- (VSTR | ((add) << 23) | ((load) << 20) | (reg_map[base] << 16) | (freg << 12) | (offs))
-#define EMIT_FPU_OPERATION(opcode, dst, src1, src2) \
- ((opcode) | ((dst) << 12) | (src1) | ((src2) << 16))
+#define FPU_LOAD (1 << 20)
+#define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \
+ ((inst) | ((add) << 23) | (reg_map[base] << 16) | (freg << 12) | (offs))
+#define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \
+ ((opcode) | (mode) | ((dst) << 12) | (src1) | ((src2) << 16))
-static int emit_fpu_data_transfer(struct sljit_compiler *compiler, int fpu_reg, int load, int arg, sljit_w argw)
+static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
{
+ sljit_sw tmp;
+ sljit_uw imm;
+ sljit_sw inst = VSTR_F32 | (flags & (SLJIT_SINGLE_OP | FPU_LOAD));
SLJIT_ASSERT(arg & SLJIT_MEM);
- /* Fast loads and stores. */
- if ((arg & 0xf) && !(arg & 0xf0) && (argw & 0x3) == 0) {
- if (argw >= 0 && argw <= 0x3ff) {
- EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, arg & 0xf, fpu_reg, argw >> 2));
- return SLJIT_SUCCESS;
- }
- if (argw < 0 && argw >= -0x3ff) {
- EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, arg & 0xf, fpu_reg, (-argw) >> 2));
- return SLJIT_SUCCESS;
- }
- if (argw >= 0 && argw <= 0x3ffff) {
- SLJIT_ASSERT(get_immediate(argw & 0x3fc00));
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, get_immediate(argw & 0x3fc00)));
- argw &= 0x3ff;
- EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG1, fpu_reg, argw >> 2));
- return SLJIT_SUCCESS;
- }
- if (argw < 0 && argw >= -0x3ffff) {
- argw = -argw;
- SLJIT_ASSERT(get_immediate(argw & 0x3fc00));
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & 0xf, get_immediate(argw & 0x3fc00)));
- argw &= 0x3ff;
- EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, TMP_REG1, fpu_reg, argw >> 2));
- return SLJIT_SUCCESS;
- }
+ if (SLJIT_UNLIKELY(arg & 0xf0)) {
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7)));
+ arg = SLJIT_MEM | TMP_REG1;
+ argw = 0;
}
- if (arg & 0xf0) {
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7)));
- EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG1, fpu_reg, 0));
- return SLJIT_SUCCESS;
+ /* Fast loads and stores. */
+ if ((arg & 0xf)) {
+ if (!(argw & ~0x3fc))
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & 0xf, reg, argw >> 2));
+ if (!(-argw & ~0x3fc))
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & 0xf, reg, (-argw) >> 2));
+ }
+
+ if (compiler->cache_arg == arg) {
+ tmp = argw - compiler->cache_argw;
+ if (!(tmp & ~0x3fc))
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, tmp >> 2));
+ if (!(-tmp & ~0x3fc))
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG3, reg, -tmp >> 2));
+ if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, tmp) != SLJIT_ERR_UNSUPPORTED) {
+ FAIL_IF(compiler->error);
+ compiler->cache_argw = argw;
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, 0));
+ }
}
- if (compiler->cache_arg == arg && ((argw - compiler->cache_argw) & 0x3) == 0) {
- if (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= 0x3ff) {
- EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG3, fpu_reg, (argw - compiler->cache_argw) >> 2));
- return SLJIT_SUCCESS;
+ if (arg & 0xf) {
+ if (emit_set_delta(compiler, TMP_REG1, arg & 0xf, argw) != SLJIT_ERR_UNSUPPORTED) {
+ FAIL_IF(compiler->error);
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, 0));
}
- if (((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= 0x3ff) {
- EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, TMP_REG3, fpu_reg, (compiler->cache_argw - argw) >> 2));
- return SLJIT_SUCCESS;
+ imm = get_imm(argw & ~0x3fc);
+ if (imm) {
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, imm));
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, (argw & 0x3fc) >> 2));
+ }
+ imm = get_imm(-argw & ~0x3fc);
+ if (imm) {
+ argw = -argw;
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & 0xf, imm));
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG1, reg, (argw & 0x3fc) >> 2));
}
}
@@ -2032,153 +2106,154 @@ static int emit_fpu_data_transfer(struct sljit_compiler *compiler, int fpu_reg,
else
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
- EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG3, fpu_reg, 0));
- return SLJIT_SUCCESS;
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, 0));
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- int dst_freg;
+ sljit_si dst_fr;
CHECK_ERROR();
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
+ SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100), float_transfer_bit_error);
compiler->cache_arg = 0;
compiler->cache_argw = 0;
+ op ^= SLJIT_SINGLE_OP;
- if (GET_OPCODE(op) == SLJIT_FCMP) {
- if (dst > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, dst, dstw));
+ if (GET_OPCODE(op) == SLJIT_CMPD) {
+ if (dst > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, dst, dstw));
dst = TMP_FREG1;
}
- if (src > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src, srcw));
+ if (src > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src, srcw));
src = TMP_FREG2;
}
- EMIT_INSTRUCTION(VCMP_F64 | (dst << 12) | src);
+ EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_SINGLE_OP, dst, src, 0));
EMIT_INSTRUCTION(VMRS);
return SLJIT_SUCCESS;
}
- dst_freg = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
+ dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
- if (src > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, dst_freg, 1, src, srcw));
- src = dst_freg;
+ if (src > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_fr, src, srcw));
+ src = dst_fr;
}
- switch (op) {
- case SLJIT_FMOV:
- if (src != dst_freg && dst_freg != TMP_FREG1)
- EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMOV_F64, dst_freg, src, 0));
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOVD:
+ if (src != dst_fr && dst_fr != TMP_FREG1)
+ EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_SINGLE_OP, dst_fr, src, 0));
break;
- case SLJIT_FNEG:
- EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VNEG_F64, dst_freg, src, 0));
+ case SLJIT_NEGD:
+ EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_SINGLE_OP, dst_fr, src, 0));
break;
- case SLJIT_FABS:
- EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VABS_F64, dst_freg, src, 0));
+ case SLJIT_ABSD:
+ EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_SINGLE_OP, dst_fr, src, 0));
break;
}
- if (dst_freg == TMP_FREG1)
- FAIL_IF(emit_fpu_data_transfer(compiler, src, 0, dst, dstw));
+ if (dst_fr == TMP_FREG1) {
+ if (GET_OPCODE(op) == SLJIT_MOVD)
+ dst_fr = src;
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), dst_fr, dst, dstw));
+ }
return SLJIT_SUCCESS;
}
-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)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- int dst_freg;
+ sljit_si dst_fr;
CHECK_ERROR();
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
compiler->cache_arg = 0;
compiler->cache_argw = 0;
+ op ^= SLJIT_SINGLE_OP;
- dst_freg = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
+ dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
- if (src2 > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w));
+ if (src2 > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));
src2 = TMP_FREG2;
}
- if (src1 > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w));
+ if (src1 > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));
src1 = TMP_FREG1;
}
- switch (op) {
- case SLJIT_FADD:
- EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VADD_F64, dst_freg, src2, src1));
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADDD:
+ EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_SINGLE_OP, dst_fr, src2, src1));
break;
- case SLJIT_FSUB:
- EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VSUB_F64, dst_freg, src2, src1));
+ case SLJIT_SUBD:
+ EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_SINGLE_OP, dst_fr, src2, src1));
break;
- case SLJIT_FMUL:
- EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMUL_F64, dst_freg, src2, src1));
+ case SLJIT_MULD:
+ EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_SINGLE_OP, dst_fr, src2, src1));
break;
- case SLJIT_FDIV:
- EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VDIV_F64, dst_freg, src2, src1));
+ case SLJIT_DIVD:
+ EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_SINGLE_OP, dst_fr, src2, src1));
break;
}
- if (dst_freg == TMP_FREG1)
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 0, dst, dstw));
+ if (dst_fr == TMP_FREG1)
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw));
return SLJIT_SUCCESS;
}
+#undef FPU_LOAD
+#undef EMIT_FPU_DATA_TRANSFER
+#undef EMIT_FPU_OPERATION
+
/* --------------------------------------------------------------------- */
/* Other instructions */
/* --------------------------------------------------------------------- */
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
- int size;
-
CHECK_ERROR();
- check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
-
- compiler->temporaries = temporaries;
- compiler->saveds = saveds;
+ check_sljit_emit_fast_enter(compiler, dst, dstw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
- size = (1 + saveds) * sizeof(sljit_uw);
- if (temporaries >= 4)
- size += (temporaries - 3) * sizeof(sljit_uw);
- local_size += size;
- local_size = (local_size + 7) & ~7;
- local_size -= size;
- compiler->local_size = local_size;
+ /* For UNUSED dst. Uncommon, but possible. */
+ if (dst == SLJIT_UNUSED)
+ return SLJIT_SUCCESS;
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
+ if (dst <= TMP_REG3)
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG3)));
- else if (dst & SLJIT_MEM) {
- if (getput_arg_fast(compiler, WORD_DATA, TMP_REG3, dst, dstw))
- return compiler->error;
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG2, SLJIT_UNUSED, RM(TMP_REG3)));
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- return getput_arg(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0);
- }
- return SLJIT_SUCCESS;
+ /* Memory. */
+ if (getput_arg_fast(compiler, WORD_DATA, TMP_REG3, dst, dstw))
+ return compiler->error;
+ /* TMP_REG3 is used for caching. */
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG2, SLJIT_UNUSED, RM(TMP_REG3)));
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ return getput_arg(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0);
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
CHECK_ERROR();
check_sljit_emit_fast_return(compiler, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
- if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+ if (src <= TMP_REG3)
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src)));
else if (src & SLJIT_MEM) {
if (getput_arg_fast(compiler, WORD_DATA | LOAD_DATA, TMP_REG3, src, srcw))
@@ -2199,7 +2274,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
/* Conditional instructions */
/* --------------------------------------------------------------------- */
-static sljit_uw get_cc(int type)
+static sljit_uw get_cc(sljit_si type)
{
switch (type) {
case SLJIT_C_EQUAL:
@@ -2241,11 +2316,11 @@ static sljit_uw get_cc(int type)
return 0xd0000000;
case SLJIT_C_OVERFLOW:
- case SLJIT_C_FLOAT_NAN:
+ case SLJIT_C_FLOAT_UNORDERED:
return 0x60000000;
case SLJIT_C_NOT_OVERFLOW:
- case SLJIT_C_FLOAT_NOT_NAN:
+ case SLJIT_C_FLOAT_ORDERED:
return 0x70000000;
default: /* SLJIT_JUMP */
@@ -2269,7 +2344,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
{
struct sljit_jump *jump;
@@ -2310,12 +2385,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
return jump;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
{
struct sljit_jump *jump;
CHECK_ERROR();
check_sljit_emit_ijump(compiler, type, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
/* In ARM, we don't need to touch the arguments. */
if (src & SLJIT_IMM) {
@@ -2337,67 +2413,83 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, i
jump->addr = compiler->size;
}
else {
- if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+ if (src <= TMP_REG3)
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));
SLJIT_ASSERT(src & SLJIT_MEM);
- FAIL_IF(emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw));
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2));
}
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw,
+ sljit_si type)
{
- int reg;
- sljit_uw cc;
+ sljit_si dst_r, flags = GET_ALL_FLAGS(op);
+ sljit_uw cc, ins;
CHECK_ERROR();
- check_sljit_emit_cond_value(compiler, op, dst, dstw, type);
+ check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
+ op = GET_OPCODE(op);
cc = get_cc(type);
- if (GET_OPCODE(op) == SLJIT_OR) {
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
- EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ORR_DP, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc);
- if (op & SLJIT_SET_E)
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst)));
- return SLJIT_SUCCESS;
- }
+ dst_r = (dst <= TMP_REG3) ? dst : TMP_REG2;
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 0));
- EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc);
-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
- compiler->skip_checks = 1;
-#endif
- return emit_op(compiler, op, ALLOW_IMM, dst, dstw, TMP_REG1, 0, dst, dstw);
+ if (op < SLJIT_ADD) {
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 0));
+ EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc);
+ return (dst_r == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS;
}
- reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2;
-
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 0));
- EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc);
+ ins = (op == SLJIT_AND ? AND_DP : (op == SLJIT_OR ? ORR_DP : EOR_DP));
+ if ((op == SLJIT_OR || op == SLJIT_XOR) && dst <= TMP_REG3 && dst == src) {
+ EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ins, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc);
+ /* The condition must always be set, even if the ORR/EOR is not executed above. */
+ return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst))) : SLJIT_SUCCESS;
+ }
- if (reg == TMP_REG2)
- return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
- return SLJIT_SUCCESS;
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
+ src = TMP_REG1;
+ srcw = 0;
+ } else if (src & SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 1) & ~COND_MASK) | cc);
+ EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000));
+ if (dst_r == TMP_REG2)
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0));
+
+ return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst_r))) : SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;
- int reg;
+ sljit_si reg;
CHECK_ERROR_PTR();
check_sljit_emit_const(compiler, dst, dstw, init_value);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
PTR_FAIL_IF(!const_);
- reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2;
+ reg = (dst <= TMP_REG3) ? dst : TMP_REG2;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), init_value));
@@ -2408,8 +2500,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
set_const(const_, compiler);
if (reg == TMP_REG2 && dst != SLJIT_UNUSED)
- if (emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, TMP_REG2, 0))
- return NULL;
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
return const_;
}
@@ -2418,7 +2509,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ad
inline_set_jump_addr(addr, new_addr, 1);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
{
inline_set_const(addr, new_constant, 1);
}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c b/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c
index c0cc8b58bb..f8c214863d 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c
@@ -26,7 +26,7 @@
/* mips 32-bit arch dependent functions. */
-static int load_immediate(struct sljit_compiler *compiler, int dst_ar, sljit_w imm)
+static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
{
if (!(imm & ~0xffff))
return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
@@ -66,12 +66,92 @@ static int load_immediate(struct sljit_compiler *compiler, int dst_ar, sljit_w i
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)
+static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
+ sljit_si dst, sljit_si src1, sljit_sw src2)
{
- int overflow_ra = 0;
+ sljit_si overflow_ra = 0;
switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_UI:
+ case SLJIT_MOV_SI:
+ case SLJIT_MOV_P:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if (dst != src2)
+ return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_UB:
+ case SLJIT_MOV_SB:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_SB) {
+#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
+ 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 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_SH) {
+#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
+ 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(5), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, ADDIU_W | SA(0) | T(dst) | IMM(-1), DR(dst)));
+ /* Loop for searching the highest bit. */
+ FAIL_IF(push_inst(compiler, ADDIU_W | S(dst) | T(dst) | IMM(1), DR(dst)));
+ FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
+ if (op & SLJIT_SET_E)
+ return push_inst(compiler, ADDU_W | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
+#endif
+ return SLJIT_SUCCESS;
+
case SLJIT_ADD:
if (flags & SRC2_IMM) {
if (op & SLJIT_SET_O) {
@@ -293,97 +373,16 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
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)
+static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw 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));
+ FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));
+ return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
@@ -395,7 +394,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ad
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
{
sljit_ins *inst = (sljit_ins*)addr;
diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c
index 3c6ee663e1..9559ec32de 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c
@@ -24,14 +24,18 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
+/* Latest MIPS architecture. */
+/* Automatically detect SLJIT_MIPS_32_64 */
+
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
{
+#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
return "MIPS" SLJIT_CPUINFO;
+#else
+ return "MIPS III" SLJIT_CPUINFO;
+#endif
}
-/* Latest MIPS architecture. */
-/* Detect SLJIT_MIPS_32_64 */
-
/* Length of an instruction word
Both for mips-32 and mips-64 */
typedef sljit_ui sljit_ins;
@@ -39,18 +43,17 @@ typedef sljit_ui sljit_ins;
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
-#define REAL_STACK_PTR (SLJIT_NO_REGISTERS + 4)
/* For position independent code, t9 must contain the function address. */
-#define PIC_ADDR_REG TMP_REG2
+#define PIC_ADDR_REG TMP_REG2
/* TMP_EREG1 is used mainly for literal encoding on 64 bit. */
-#define TMP_EREG1 15
-#define TMP_EREG2 24
+#define TMP_EREG1 15
+#define TMP_EREG2 24
/* Floating point status register. */
-#define FCSR_REG 31
+#define FCSR_REG 31
/* Return address register. */
-#define RETURN_ADDR_REG 31
+#define RETURN_ADDR_REG 31
/* Flags are keept in volatile registers. */
#define EQUAL_FLAG 7
@@ -61,8 +64,12 @@ typedef sljit_ui sljit_ins;
#define GREATER_FLAG 13
#define OVERFLOW_FLAG 14
-#define TMP_FREG1 (SLJIT_FLOAT_REG4 + 1)
-#define TMP_FREG2 (SLJIT_FLOAT_REG4 + 2)
+#define TMP_FREG1 (0)
+#define TMP_FREG2 ((SLJIT_FLOAT_REG6 + 1) << 1)
+
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
+ 0, 2, 5, 6, 3, 8, 16, 17, 18, 19, 20, 29, 4, 25, 9
+};
/* --------------------------------------------------------------------- */
/* Instrucion forms */
@@ -75,19 +82,20 @@ typedef sljit_ui sljit_ins;
#define SA(s) ((s) << 21)
#define TA(t) ((t) << 16)
#define DA(d) ((d) << 11)
-#define FT(t) ((t) << (16 + 1))
-#define FS(s) ((s) << (11 + 1))
-#define FD(d) ((d) << (6 + 1))
+#define FT(t) ((t) << 16)
+#define FS(s) ((s) << 11)
+#define FD(d) ((d) << 6)
#define IMM(imm) ((imm) & 0xffff)
#define SH_IMM(imm) ((imm & 0x1f) << 6)
#define DR(dr) (reg_map[dr])
#define HI(opcode) ((opcode) << 26)
#define LO(opcode) (opcode)
-#define FMT_D (17 << 21)
+/* S = (16 << 21) D = (17 << 21) */
+#define FMT_SD (16 << 21)
-#define ABS_D (HI(17) | FMT_D | LO(5))
-#define ADD_D (HI(17) | FMT_D | LO(0))
+#define ABS_fmt (HI(17) | FMT_SD | LO(5))
+#define ADD_fmt (HI(17) | FMT_SD | LO(0))
#define ADDU (HI(0) | LO(33))
#define ADDIU (HI(9))
#define AND (HI(0) | LO(36))
@@ -103,37 +111,35 @@ typedef sljit_ui sljit_ins;
#define BLTZ (HI(1) | (0 << 16))
#define BNE (HI(5))
#define BREAK (HI(0) | LO(13))
-#define C_UN_D (HI(17) | FMT_D | LO(49))
-#define C_UEQ_D (HI(17) | FMT_D | LO(51))
-#define C_ULE_D (HI(17) | FMT_D | LO(55))
-#define C_ULT_D (HI(17) | FMT_D | LO(53))
+#define CFC1 (HI(17) | (2 << 21))
+#define C_UN_fmt (HI(17) | FMT_SD | LO(49))
+#define C_UEQ_fmt (HI(17) | FMT_SD | LO(51))
+#define C_ULE_fmt (HI(17) | FMT_SD | LO(55))
+#define C_ULT_fmt (HI(17) | FMT_SD | LO(53))
#define DIV (HI(0) | LO(26))
#define DIVU (HI(0) | LO(27))
-#define DIV_D (HI(17) | FMT_D | LO(3))
+#define DIV_fmt (HI(17) | FMT_SD | LO(3))
#define J (HI(2))
#define JAL (HI(3))
#define JALR (HI(0) | LO(9))
#define JR (HI(0) | LO(8))
#define LD (HI(55))
-#define LDC1 (HI(53))
#define LUI (HI(15))
#define LW (HI(35))
-#define NEG_D (HI(17) | FMT_D | LO(7))
#define MFHI (HI(0) | LO(16))
#define MFLO (HI(0) | LO(18))
-#define MOV_D (HI(17) | FMT_D | LO(6))
-#define CFC1 (HI(17) | (2 << 21))
+#define MOV_fmt (HI(17) | FMT_SD | LO(6))
#define MOVN (HI(0) | LO(11))
#define MOVZ (HI(0) | LO(10))
-#define MUL_D (HI(17) | FMT_D | LO(2))
+#define MUL_fmt (HI(17) | FMT_SD | LO(2))
#define MULT (HI(0) | LO(24))
#define MULTU (HI(0) | LO(25))
+#define NEG_fmt (HI(17) | FMT_SD | LO(7))
#define NOP (HI(0) | LO(0))
#define NOR (HI(0) | LO(39))
#define OR (HI(0) | LO(37))
#define ORI (HI(13))
#define SD (HI(63))
-#define SDC1 (HI(61))
#define SLT (HI(0) | LO(42))
#define SLTI (HI(10))
#define SLTIU (HI(11))
@@ -144,7 +150,7 @@ typedef sljit_ui sljit_ins;
#define SRLV (HI(0) | LO(6))
#define SRA (HI(0) | LO(3))
#define SRAV (HI(0) | LO(7))
-#define SUB_D (HI(17) | FMT_D | LO(1))
+#define SUB_fmt (HI(17) | FMT_SD | LO(1))
#define SUBU (HI(0) | LO(35))
#define SW (HI(43))
#define XOR (HI(0) | LO(38))
@@ -173,14 +179,12 @@ typedef sljit_ui sljit_ins;
#define SIMM_MIN (-0x8000)
#define UIMM_MAX (0xffff)
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 6] = {
- 0, 2, 5, 6, 3, 8, 17, 18, 19, 20, 21, 16, 4, 25, 9, 29
-};
-
/* dest_reg is the absolute name of the register
Useful for reordering instructions in the delay slot. */
-static int push_inst(struct sljit_compiler *compiler, sljit_ins ins, int delay_slot)
+static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_si delay_slot)
{
+ SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS
+ || delay_slot == ((ins >> 11) & 0x1f) || delay_slot == ((ins >> 16) & 0x1f));
sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
FAIL_IF(!ptr);
*ptr = ins;
@@ -189,14 +193,14 @@ static int push_inst(struct sljit_compiler *compiler, sljit_ins ins, int delay_s
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE sljit_ins invert_branch(int flags)
+static SLJIT_INLINE sljit_ins invert_branch(sljit_si flags)
{
return (flags & IS_BIT26_COND) ? (1 << 26) : (1 << 16);
}
static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
{
- sljit_w diff;
+ sljit_sw diff;
sljit_uw target_addr;
sljit_ins *inst;
sljit_ins saved_inst;
@@ -216,7 +220,7 @@ static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins
/* B instructions. */
if (jump->flags & IS_MOVABLE) {
- diff = ((sljit_w)target_addr - (sljit_w)(inst)) >> 2;
+ diff = ((sljit_sw)target_addr - (sljit_sw)(inst)) >> 2;
if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
jump->flags |= PATCH_B;
@@ -234,7 +238,7 @@ static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins
}
}
- diff = ((sljit_w)target_addr - (sljit_w)(inst + 1)) >> 2;
+ diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1)) >> 2;
if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
jump->flags |= PATCH_B;
@@ -336,7 +340,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
jump->addr = (sljit_uw)(code_ptr - 3);
#else
- jump->addr = (sljit_uw)(code_ptr - 6);
+#error "Implementation required"
#endif
code_ptr = optimize_jump(jump, code_ptr, code);
jump = jump->next;
@@ -362,7 +366,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
- SLJIT_ASSERT(code_ptr - code <= (int)compiler->size);
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
jump = compiler->jumps;
while (jump) {
@@ -371,8 +375,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
buf_ptr = (sljit_ins*)jump->addr;
if (jump->flags & PATCH_B) {
- addr = (sljit_w)(addr - (jump->addr + sizeof(sljit_ins))) >> 2;
- SLJIT_ASSERT((sljit_w)addr <= SIMM_MAX && (sljit_w)addr >= SIMM_MIN);
+ addr = (sljit_sw)(addr - (jump->addr + sizeof(sljit_ins))) >> 2;
+ SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);
buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | (addr & 0xffff);
break;
}
@@ -387,10 +391,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
#else
- buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
- buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
- buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
- buf_ptr[4] = (buf_ptr[4] & 0xffff0000) | (addr & 0xffff);
+#error "Implementation required"
#endif
} while (0);
jump = jump->next;
@@ -407,42 +408,44 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
return code;
}
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
/* Creates an index in data_transfer_insts array. */
+#define LOAD_DATA 0x01
#define WORD_DATA 0x00
-#define BYTE_DATA 0x01
-#define HALF_DATA 0x02
-#define INT_DATA 0x03
-#define SIGNED_DATA 0x04
-#define LOAD_DATA 0x08
-
-#define MEM_MASK 0x0f
-
-#define WRITE_BACK 0x00010
-#define ARG_TEST 0x00020
-#define CUMULATIVE_OP 0x00040
-#define LOGICAL_OP 0x00080
-#define IMM_OP 0x00100
-#define SRC2_IMM 0x00200
-
-#define UNUSED_DEST 0x00400
-#define REG_DEST 0x00800
-#define REG1_SOURCE 0x01000
-#define REG2_SOURCE 0x02000
-#define SLOW_SRC1 0x04000
-#define SLOW_SRC2 0x08000
-#define SLOW_DEST 0x10000
+#define BYTE_DATA 0x02
+#define HALF_DATA 0x04
+#define INT_DATA 0x06
+#define SIGNED_DATA 0x08
+/* Separates integer and floating point registers */
+#define GPR_REG 0x0f
+#define DOUBLE_DATA 0x10
+
+#define MEM_MASK 0x1f
+
+#define WRITE_BACK 0x00020
+#define ARG_TEST 0x00040
+#define ALT_KEEP_CACHE 0x00080
+#define CUMULATIVE_OP 0x00100
+#define LOGICAL_OP 0x00200
+#define IMM_OP 0x00400
+#define SRC2_IMM 0x00800
+
+#define UNUSED_DEST 0x01000
+#define REG_DEST 0x02000
+#define REG1_SOURCE 0x04000
+#define REG2_SOURCE 0x08000
+#define SLOW_SRC1 0x10000
+#define SLOW_SRC2 0x20000
+#define SLOW_DEST 0x40000
/* Only these flags are set. UNUSED_DEST is not set when no flags should be set. */
#define CHECK_FLAGS(list) \
(!(flags & UNUSED_DEST) || (op & GET_FLAGS(~(list))))
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-#include "sljitNativeMIPS_32.c"
-#else
-#include "sljitNativeMIPS_64.c"
-#endif
-
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
#define STACK_STORE SW
#define STACK_LOAD LW
#else
@@ -450,55 +453,53 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#define STACK_LOAD LD
#endif
-static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#include "sljitNativeMIPS_32.c"
+#else
+#include "sljitNativeMIPS_64.c"
+#endif
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
sljit_ins base;
CHECK_ERROR();
- check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
+ check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
- compiler->temporaries = temporaries;
+ compiler->scratches = scratches;
compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
- compiler->has_locals = local_size > 0;
- local_size += (saveds + 2 + 4) * sizeof(sljit_w);
+ local_size += (saveds + 1 + 4) * sizeof(sljit_sw);
local_size = (local_size + 15) & ~0xf;
compiler->local_size = local_size;
if (local_size <= SIMM_MAX) {
/* Frequent case. */
- FAIL_IF(push_inst(compiler, ADDIU_W | S(REAL_STACK_PTR) | T(REAL_STACK_PTR) | IMM(-local_size), DR(REAL_STACK_PTR)));
- base = S(REAL_STACK_PTR);
+ FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_LOCALS_REG) | T(SLJIT_LOCALS_REG) | IMM(-local_size), DR(SLJIT_LOCALS_REG)));
+ base = S(SLJIT_LOCALS_REG);
}
else {
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size));
- FAIL_IF(push_inst(compiler, ADDU_W | S(REAL_STACK_PTR) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
- FAIL_IF(push_inst(compiler, SUBU_W | S(REAL_STACK_PTR) | T(TMP_REG1) | D(REAL_STACK_PTR), DR(REAL_STACK_PTR)));
+ FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_LOCALS_REG) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_LOCALS_REG) | T(TMP_REG1) | D(SLJIT_LOCALS_REG), DR(SLJIT_LOCALS_REG)));
base = S(TMP_REG2);
local_size = 0;
}
- FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(local_size - 1 * (int)sizeof(sljit_w)), MOVABLE_INS));
- if (compiler->has_locals)
- FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_LOCALS_REG) | IMM(local_size - 2 * (int)sizeof(sljit_w)), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(local_size - 1 * (sljit_si)sizeof(sljit_sw)), MOVABLE_INS));
if (saveds >= 1)
- FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG1) | IMM(local_size - 3 * (int)sizeof(sljit_w)), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG1) | IMM(local_size - 2 * (sljit_si)sizeof(sljit_sw)), MOVABLE_INS));
if (saveds >= 2)
- FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG2) | IMM(local_size - 4 * (int)sizeof(sljit_w)), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG2) | IMM(local_size - 3 * (sljit_si)sizeof(sljit_sw)), MOVABLE_INS));
if (saveds >= 3)
- FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG3) | IMM(local_size - 5 * (int)sizeof(sljit_w)), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG3) | IMM(local_size - 4 * (sljit_si)sizeof(sljit_sw)), MOVABLE_INS));
if (saveds >= 4)
- FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_EREG1) | IMM(local_size - 6 * (int)sizeof(sljit_w)), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_EREG1) | IMM(local_size - 5 * (sljit_si)sizeof(sljit_sw)), MOVABLE_INS));
if (saveds >= 5)
- FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_EREG2) | IMM(local_size - 7 * (int)sizeof(sljit_w)), MOVABLE_INS));
-
- if (compiler->has_locals)
- FAIL_IF(push_inst(compiler, ADDIU_W | S(REAL_STACK_PTR) | T(SLJIT_LOCALS_REG) | IMM(4 * sizeof(sljit_w)), DR(SLJIT_LOCALS_REG)));
+ FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_EREG2) | IMM(local_size - 6 * (sljit_si)sizeof(sljit_sw)), MOVABLE_INS));
if (args >= 1)
FAIL_IF(push_inst(compiler, ADDU_W | SA(4) | TA(0) | D(SLJIT_SAVED_REG1), DR(SLJIT_SAVED_REG1)));
@@ -510,22 +511,24 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
CHECK_ERROR_VOID();
- check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
+ check_sljit_set_context(compiler, args, scratches, saveds, local_size);
- compiler->temporaries = temporaries;
+ compiler->scratches = scratches;
compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
- compiler->has_locals = local_size > 0;
- local_size += (saveds + 2 + 4) * sizeof(sljit_w);
+ local_size += (saveds + 1 + 4) * sizeof(sljit_sw);
compiler->local_size = (local_size + 15) & ~0xf;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
- int local_size;
+ sljit_si local_size;
sljit_ins base;
CHECK_ERROR();
@@ -535,33 +538,31 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
local_size = compiler->local_size;
if (local_size <= SIMM_MAX)
- base = S(REAL_STACK_PTR);
+ base = S(SLJIT_LOCALS_REG);
else {
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size));
- FAIL_IF(push_inst(compiler, ADDU_W | S(REAL_STACK_PTR) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_LOCALS_REG) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1)));
base = S(TMP_REG1);
local_size = 0;
}
- FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - 1 * (int)sizeof(sljit_w)), RETURN_ADDR_REG));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - 1 * (sljit_si)sizeof(sljit_sw)), RETURN_ADDR_REG));
if (compiler->saveds >= 5)
- FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_EREG2) | IMM(local_size - 7 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_EREG2)));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_EREG2) | IMM(local_size - 6 * (sljit_si)sizeof(sljit_sw)), DR(SLJIT_SAVED_EREG2)));
if (compiler->saveds >= 4)
- FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_EREG1) | IMM(local_size - 6 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_EREG1)));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_EREG1) | IMM(local_size - 5 * (sljit_si)sizeof(sljit_sw)), DR(SLJIT_SAVED_EREG1)));
if (compiler->saveds >= 3)
- FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG3) | IMM(local_size - 5 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_REG3)));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG3) | IMM(local_size - 4 * (sljit_si)sizeof(sljit_sw)), DR(SLJIT_SAVED_REG3)));
if (compiler->saveds >= 2)
- FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG2) | IMM(local_size - 4 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_REG2)));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG2) | IMM(local_size - 3 * (sljit_si)sizeof(sljit_sw)), DR(SLJIT_SAVED_REG2)));
if (compiler->saveds >= 1)
- FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG1) | IMM(local_size - 3 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_REG1)));
- if (compiler->has_locals)
- FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_LOCALS_REG) | IMM(local_size - 2 * (int)sizeof(sljit_w)), DR(SLJIT_LOCALS_REG)));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG1) | IMM(local_size - 2 * (sljit_si)sizeof(sljit_sw)), DR(SLJIT_SAVED_REG1)));
FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
if (compiler->local_size <= SIMM_MAX)
- return push_inst(compiler, ADDIU_W | S(REAL_STACK_PTR) | T(REAL_STACK_PTR) | IMM(compiler->local_size), UNMOVABLE_INS);
+ return push_inst(compiler, ADDIU_W | S(SLJIT_LOCALS_REG) | T(SLJIT_LOCALS_REG) | IMM(compiler->local_size), UNMOVABLE_INS);
else
- return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(REAL_STACK_PTR), UNMOVABLE_INS);
+ return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_LOCALS_REG), UNMOVABLE_INS);
}
#undef STACK_STORE
@@ -572,57 +573,62 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
/* --------------------------------------------------------------------- */
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-#define ARCH_DEPEND(a, b) a
+#define ARCH_32_64(a, b) a
#else
-#define ARCH_DEPEND(a, b) b
+#define ARCH_32_64(a, b) b
#endif
-static SLJIT_CONST sljit_ins data_transfer_insts[16] = {
-/* s u w */ ARCH_DEPEND(HI(43) /* sw */, HI(63) /* sd */),
-/* s u b */ HI(40) /* sb */,
-/* s u h */ HI(41) /* sh*/,
-/* s u i */ HI(43) /* sw */,
-
-/* s s w */ ARCH_DEPEND(HI(43) /* sw */, HI(63) /* sd */),
-/* s s b */ HI(40) /* sb */,
-/* s s h */ HI(41) /* sh*/,
-/* s s i */ HI(43) /* sw */,
-
-/* l u w */ ARCH_DEPEND(HI(35) /* lw */, HI(55) /* ld */),
-/* l u b */ HI(36) /* lbu */,
-/* l u h */ HI(37) /* lhu */,
-/* l u i */ ARCH_DEPEND(HI(35) /* lw */, HI(39) /* lwu */),
-
-/* l s w */ ARCH_DEPEND(HI(35) /* lw */, HI(55) /* ld */),
-/* l s b */ HI(32) /* lb */,
-/* l s h */ HI(33) /* lh */,
-/* l s i */ HI(35) /* lw */,
+static SLJIT_CONST sljit_ins data_transfer_insts[16 + 4] = {
+/* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
+/* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
+/* u b s */ HI(40) /* sb */,
+/* u b l */ HI(36) /* lbu */,
+/* u h s */ HI(41) /* sh */,
+/* u h l */ HI(37) /* lhu */,
+/* u i s */ HI(43) /* sw */,
+/* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),
+
+/* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
+/* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
+/* s b s */ HI(40) /* sb */,
+/* s b l */ HI(32) /* lb */,
+/* s h s */ HI(41) /* sh */,
+/* s h l */ HI(33) /* lh */,
+/* s i s */ HI(43) /* sw */,
+/* s i l */ HI(35) /* lw */,
+
+/* d s */ HI(61) /* sdc1 */,
+/* d l */ HI(53) /* ldc1 */,
+/* s s */ HI(57) /* swc1 */,
+/* s l */ HI(49) /* lwc1 */,
};
+#undef ARCH_32_64
+
/* reg_ar is an absoulute register! */
/* Can perform an operation using at most 1 instruction. */
-static int getput_arg_fast(struct sljit_compiler *compiler, int flags, int reg_ar, int arg, sljit_w argw)
+static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw)
{
SLJIT_ASSERT(arg & SLJIT_MEM);
- if (!(flags & WRITE_BACK) && !(arg & 0xf0) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
+ if ((!(flags & WRITE_BACK) || !(arg & 0xf)) && !(arg & 0xf0) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
/* Works for both absoulte and relative addresses. */
if (SLJIT_UNLIKELY(flags & ARG_TEST))
return 1;
- FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & 0xf) | TA(reg_ar) | IMM(argw), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & 0xf)
+ | TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));
return -1;
}
- return (flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+ return 0;
}
/* See getput_arg below.
Note: can_cache is called only for binary operators. Those
operators always uses word arguments without write back. */
-static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
{
- if (!(next_arg & SLJIT_MEM))
- return 0;
+ SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
/* Simple operation except for updates. */
if (arg & 0xf0) {
@@ -634,7 +640,7 @@ static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
}
if (arg == next_arg) {
- if (((sljit_uw)(next_argw - argw) <= SIMM_MAX && (sljit_uw)(next_argw - argw) >= SIMM_MIN))
+ if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN))
return 1;
return 0;
}
@@ -643,10 +649,9 @@ static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
}
/* Emit the necessary instructions. See can_cache above. */
-static int getput_arg(struct sljit_compiler *compiler, int flags, int reg_ar, int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
{
- int tmp_ar;
- int base;
+ sljit_si tmp_ar, base, delay_slot;
SLJIT_ASSERT(arg & SLJIT_MEM);
if (!(next_arg & SLJIT_MEM)) {
@@ -654,7 +659,13 @@ static int getput_arg(struct sljit_compiler *compiler, int flags, int reg_ar, in
next_argw = 0;
}
- tmp_ar = (flags & LOAD_DATA) ? reg_ar : DR(TMP_REG3);
+ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
+ tmp_ar = reg_ar;
+ delay_slot = reg_ar;
+ } else {
+ tmp_ar = DR(TMP_REG1);
+ delay_slot = MOVABLE_INS;
+ }
base = arg & 0xf;
if (SLJIT_UNLIKELY(arg & 0xf0)) {
@@ -669,22 +680,22 @@ static int getput_arg(struct sljit_compiler *compiler, int flags, int reg_ar, in
if (argw == compiler->cache_argw) {
if (!(flags & WRITE_BACK)) {
if (arg == compiler->cache_arg)
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
if ((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) {
if (arg == next_arg && argw == (next_argw & 0x3)) {
compiler->cache_arg = arg;
compiler->cache_argw = argw;
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
}
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
}
}
else {
if ((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) {
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
}
}
}
@@ -704,10 +715,10 @@ static int getput_arg(struct sljit_compiler *compiler, int flags, int reg_ar, in
}
else
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | DA(tmp_ar), tmp_ar));
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
}
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | D(base), DR(base)));
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
}
if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) {
@@ -743,7 +754,7 @@ static int getput_arg(struct sljit_compiler *compiler, int flags, int reg_ar, in
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
}
}
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
}
if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
@@ -751,7 +762,7 @@ static int getput_arg(struct sljit_compiler *compiler, int flags, int reg_ar, in
FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
compiler->cache_argw = argw;
}
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
}
if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
@@ -765,19 +776,19 @@ static int getput_arg(struct sljit_compiler *compiler, int flags, int reg_ar, in
compiler->cache_argw = argw;
if (!base)
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {
compiler->cache_arg = arg;
FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
}
FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
}
-static SLJIT_INLINE int emit_op_mem(struct sljit_compiler *compiler, int flags, int reg_ar, int arg, sljit_w argw)
+static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw)
{
if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
return compiler->error;
@@ -786,35 +797,44 @@ static SLJIT_INLINE int emit_op_mem(struct sljit_compiler *compiler, int flags,
return getput_arg(compiler, flags, reg_ar, arg, argw, 0, 0);
}
-static int emit_op(struct sljit_compiler *compiler, int op, int flags,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
+{
+ if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
+ return compiler->error;
+ return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+}
+
+static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
/* arg1 goes to TMP_REG1 or src reg
arg2 goes to TMP_REG2, imm or src reg
TMP_REG3 can be used for caching
result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
- int dst_r = TMP_REG2;
- int src1_r;
- sljit_w src2_r = 0;
- int sugg_src2_r = TMP_REG2;
-
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
-
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REG3) {
- dst_r = dst;
- flags |= REG_DEST;
- if (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI)
- sugg_src2_r = dst_r;
+ sljit_si dst_r = TMP_REG2;
+ sljit_si src1_r;
+ sljit_sw src2_r = 0;
+ sljit_si sugg_src2_r = TMP_REG2;
+
+ if (!(flags & ALT_KEEP_CACHE)) {
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
}
- else if (dst == SLJIT_UNUSED) {
+
+ if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
return SLJIT_SUCCESS;
if (GET_FLAGS(op))
flags |= UNUSED_DEST;
}
+ else if (dst <= TMP_REG3) {
+ dst_r = dst;
+ flags |= REG_DEST;
+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+ sugg_src2_r = dst_r;
+ }
else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
flags |= SLOW_DEST;
@@ -826,7 +846,7 @@ static int emit_op(struct sljit_compiler *compiler, int op, int flags,
src2_r = src2w;
}
}
- if ((src1 & SLJIT_IMM) && src1w && (flags & CUMULATIVE_OP) && !(flags & SRC2_IMM)) {
+ if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) {
if ((!(flags & LOGICAL_OP) && (src1w <= SIMM_MAX && src1w >= SIMM_MIN))
|| ((flags & LOGICAL_OP) && !(src1w & ~UIMM_MAX))) {
flags |= SRC2_IMM;
@@ -842,7 +862,7 @@ static int emit_op(struct sljit_compiler *compiler, int op, int flags,
}
/* Source 1. */
- if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= TMP_REG3) {
+ if (src1 <= TMP_REG3) {
src1_r = src1;
flags |= REG1_SOURCE;
}
@@ -863,20 +883,23 @@ static int emit_op(struct sljit_compiler *compiler, int op, int flags,
}
/* Source 2. */
- if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) {
+ if (src2 <= TMP_REG3) {
src2_r = src2;
flags |= REG2_SOURCE;
- if (!(flags & REG_DEST) && GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI)
+ if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
dst_r = src2_r;
}
else if (src2 & SLJIT_IMM) {
if (!(flags & SRC2_IMM)) {
- if (src2w || (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI)) {
+ if (src2w) {
FAIL_IF(load_immediate(compiler, DR(sugg_src2_r), src2w));
src2_r = sugg_src2_r;
}
- else
+ else {
src2_r = 0;
+ if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) && (dst & SLJIT_MEM))
+ dst_r = 0;
+ }
}
}
else {
@@ -916,7 +939,7 @@ static int emit_op(struct sljit_compiler *compiler, int op, int flags,
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
{
CHECK_ERROR();
check_sljit_emit_op0(compiler, op);
@@ -929,123 +952,128 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
return push_inst(compiler, NOP, UNMOVABLE_INS);
case SLJIT_UMUL:
case SLJIT_SMUL:
- FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? MULTU : MULT) | S(SLJIT_TEMPORARY_REG1) | T(SLJIT_TEMPORARY_REG2), MOVABLE_INS));
- FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_TEMPORARY_REG1), DR(SLJIT_TEMPORARY_REG1)));
- return push_inst(compiler, MFHI | D(SLJIT_TEMPORARY_REG2), DR(SLJIT_TEMPORARY_REG2));
+ FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? MULTU : MULT) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_SCRATCH_REG1), DR(SLJIT_SCRATCH_REG1)));
+ return push_inst(compiler, MFHI | D(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2));
case SLJIT_UDIV:
case SLJIT_SDIV:
#if !(defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif
- FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_TEMPORARY_REG1) | T(SLJIT_TEMPORARY_REG2), MOVABLE_INS));
- FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_TEMPORARY_REG1), DR(SLJIT_TEMPORARY_REG1)));
- return push_inst(compiler, MFHI | D(SLJIT_TEMPORARY_REG2), DR(SLJIT_TEMPORARY_REG2));
+ FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_SCRATCH_REG1), DR(SLJIT_SCRATCH_REG1)));
+ return push_inst(compiler, MFHI | D(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2));
}
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- #define inp_flags 0
+# define flags 0
#endif
CHECK_ERROR();
check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
-
- SLJIT_COMPILE_ASSERT(SLJIT_MOV + 7 == SLJIT_MOVU, movu_offset);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
- return emit_op(compiler, SLJIT_MOV, inp_flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+ case SLJIT_MOV_P:
+ return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_MOV_UI:
- return emit_op(compiler, SLJIT_MOV_UI, inp_flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_MOV_SI:
- return emit_op(compiler, SLJIT_MOV_SI, inp_flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_MOV_UB:
- return emit_op(compiler, SLJIT_MOV_UB, inp_flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
case SLJIT_MOV_SB:
- return emit_op(compiler, SLJIT_MOV_SB, inp_flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
case SLJIT_MOV_UH:
- return emit_op(compiler, SLJIT_MOV_UH, inp_flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
case SLJIT_MOV_SH:
- return emit_op(compiler, SLJIT_MOV_SH, inp_flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
case SLJIT_MOVU:
- return emit_op(compiler, SLJIT_MOV, inp_flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+ case SLJIT_MOVU_P:
+ return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_MOVU_UI:
- return emit_op(compiler, SLJIT_MOV_UI, inp_flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_MOVU_SI:
- return emit_op(compiler, SLJIT_MOV_SI, inp_flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_MOVU_UB:
- return emit_op(compiler, SLJIT_MOV_UB, inp_flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
case SLJIT_MOVU_SB:
- return emit_op(compiler, SLJIT_MOV_SB, inp_flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
case SLJIT_MOVU_UH:
- return emit_op(compiler, SLJIT_MOV_UH, inp_flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
case SLJIT_MOVU_SH:
- return emit_op(compiler, SLJIT_MOV_SH, inp_flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
case SLJIT_NOT:
- return emit_op(compiler, op, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_NEG:
- return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), inp_flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
+ return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
case SLJIT_CLZ:
- return emit_op(compiler, op, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
}
return SLJIT_SUCCESS;
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- #undef inp_flags
+# undef flags
#endif
}
-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 sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- #define inp_flags 0
+# define flags 0
#endif
CHECK_ERROR();
check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
switch (GET_OPCODE(op)) {
case SLJIT_ADD:
case SLJIT_ADDC:
- return emit_op(compiler, op, inp_flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUB:
case SLJIT_SUBC:
- return emit_op(compiler, op, inp_flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_MUL:
- return emit_op(compiler, op, inp_flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_AND:
case SLJIT_OR:
case SLJIT_XOR:
- return emit_op(compiler, op, inp_flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SHL:
case SLJIT_LSHR:
@@ -1054,26 +1082,25 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
if (src2 & SLJIT_IMM)
src2w &= 0x1f;
#else
- if (src2 & SLJIT_IMM)
- src2w &= 0x3f;
+ SLJIT_ASSERT_STOP();
#endif
- return emit_op(compiler, op, inp_flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
}
return SLJIT_SUCCESS;
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- #undef inp_flags
+# undef flags
#endif
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
{
check_sljit_get_register_index(reg);
return reg_map[reg];
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, int size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_si size)
{
CHECK_ERROR();
check_sljit_emit_op_custom(compiler, instruction, size);
@@ -1086,13 +1113,13 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compile
/* Floating point operators */
/* --------------------------------------------------------------------- */
-SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
#if (defined SLJIT_QEMU && SLJIT_QEMU)
/* Qemu says fir is 0 by default. */
return 1;
#elif defined(__GNUC__)
- sljit_w fir;
+ sljit_sw fir;
asm ("cfc1 %0, $0" : "=r"(fir));
return (fir >> 22) & 0x1;
#else
@@ -1100,119 +1127,95 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
#endif
}
-static int emit_fpu_data_transfer(struct sljit_compiler *compiler, int fpu_reg, int load, int arg, sljit_w argw)
-{
- int hi_reg;
+#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 7))
+#define FMT(op) (((op & SLJIT_SINGLE_OP) ^ SLJIT_SINGLE_OP) << (21 - 8))
- SLJIT_ASSERT(arg & SLJIT_MEM);
-
- /* Fast loads and stores. */
- if (!(arg & 0xf0)) {
- /* Both for (arg & 0xf) == SLJIT_UNUSED and (arg & 0xf) != SLJIT_UNUSED. */
- if (argw <= SIMM_MAX && argw >= SIMM_MIN)
- return push_inst(compiler, (load ? LDC1 : SDC1) | S(arg & 0xf) | FT(fpu_reg) | IMM(argw), MOVABLE_INS);
- }
-
- if (arg & 0xf0) {
- argw &= 0x3;
- hi_reg = (arg >> 4) & 0xf;
- if (argw) {
- FAIL_IF(push_inst(compiler, SLL_W | T(hi_reg) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1)));
- hi_reg = TMP_REG1;
- }
- FAIL_IF(push_inst(compiler, ADDU_W | S(hi_reg) | T(arg & 0xf) | D(TMP_REG1), DR(TMP_REG1)));
- return push_inst(compiler, (load ? LDC1 : SDC1) | S(TMP_REG1) | FT(fpu_reg) | IMM(0), MOVABLE_INS);
- }
-
- /* Use cache. */
- if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)
- return push_inst(compiler, (load ? LDC1 : SDC1) | S(TMP_REG3) | FT(fpu_reg) | IMM(argw - compiler->cache_argw), MOVABLE_INS);
-
- /* Put value to cache. */
- compiler->cache_arg = arg;
- compiler->cache_argw = argw;
-
- FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
- if (arg & 0xf)
- FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(arg & 0xf) | D(TMP_REG3), DR(TMP_REG3)));
- return push_inst(compiler, (load ? LDC1 : SDC1) | S(TMP_REG3) | FT(fpu_reg) | IMM(0), MOVABLE_INS);
-}
-
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- int dst_fr;
+ sljit_si dst_fr;
CHECK_ERROR();
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
+ SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- if (GET_OPCODE(op) == SLJIT_FCMP) {
- if (dst > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, dst, dstw));
+ if (GET_OPCODE(op) == SLJIT_CMPD) {
+ if (dst > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, dst, dstw, src, srcw));
dst = TMP_FREG1;
}
- if (src > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src, srcw));
+ else
+ dst <<= 1;
+
+ if (src > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src, srcw, 0, 0));
src = TMP_FREG2;
}
+ else
+ src <<= 1;
/* src and dst are swapped. */
if (op & SLJIT_SET_E) {
- FAIL_IF(push_inst(compiler, C_UEQ_D | FT(src) | FS(dst), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, C_UEQ_fmt | FMT(op) | FT(src) | FS(dst), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, CFC1 | TA(EQUAL_FLAG) | DA(FCSR_REG), EQUAL_FLAG));
FAIL_IF(push_inst(compiler, SRL | TA(EQUAL_FLAG) | DA(EQUAL_FLAG) | SH_IMM(23), EQUAL_FLAG));
FAIL_IF(push_inst(compiler, ANDI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG));
}
if (op & SLJIT_SET_S) {
/* Mixing the instructions for the two checks. */
- FAIL_IF(push_inst(compiler, C_ULT_D | FT(src) | FS(dst), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, C_ULT_fmt | FMT(op) | FT(src) | FS(dst), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, CFC1 | TA(ULESS_FLAG) | DA(FCSR_REG), ULESS_FLAG));
- FAIL_IF(push_inst(compiler, C_ULT_D | FT(dst) | FS(src), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, C_ULT_fmt | FMT(op) | FT(dst) | FS(src), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, SRL | TA(ULESS_FLAG) | DA(ULESS_FLAG) | SH_IMM(23), ULESS_FLAG));
FAIL_IF(push_inst(compiler, ANDI | SA(ULESS_FLAG) | TA(ULESS_FLAG) | IMM(1), ULESS_FLAG));
FAIL_IF(push_inst(compiler, CFC1 | TA(UGREATER_FLAG) | DA(FCSR_REG), UGREATER_FLAG));
FAIL_IF(push_inst(compiler, SRL | TA(UGREATER_FLAG) | DA(UGREATER_FLAG) | SH_IMM(23), UGREATER_FLAG));
FAIL_IF(push_inst(compiler, ANDI | SA(UGREATER_FLAG) | TA(UGREATER_FLAG) | IMM(1), UGREATER_FLAG));
}
- return push_inst(compiler, C_UN_D | FT(src) | FS(dst), FCSR_FCC);
+ return push_inst(compiler, C_UN_fmt | FMT(op) | FT(src) | FS(dst), FCSR_FCC);
}
- dst_fr = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
+ dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : (dst << 1);
- if (src > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, dst_fr, 1, src, srcw));
+ if (src > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_fr, src, srcw, dst, dstw));
src = dst_fr;
}
+ else
+ src <<= 1;
- switch (op) {
- case SLJIT_FMOV:
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOVD:
if (src != dst_fr && dst_fr != TMP_FREG1)
- FAIL_IF(push_inst(compiler, MOV_D | FS(src) | FD(dst_fr), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, MOV_fmt | FMT(op) | FS(src) | FD(dst_fr), MOVABLE_INS));
break;
- case SLJIT_FNEG:
- FAIL_IF(push_inst(compiler, NEG_D | FS(src) | FD(dst_fr), MOVABLE_INS));
+ case SLJIT_NEGD:
+ FAIL_IF(push_inst(compiler, NEG_fmt | FMT(op) | FS(src) | FD(dst_fr), MOVABLE_INS));
break;
- case SLJIT_FABS:
- FAIL_IF(push_inst(compiler, ABS_D | FS(src) | FD(dst_fr), MOVABLE_INS));
+ case SLJIT_ABSD:
+ FAIL_IF(push_inst(compiler, ABS_fmt | FMT(op) | FS(src) | FD(dst_fr), MOVABLE_INS));
break;
}
- if (dst_fr == TMP_FREG1)
- FAIL_IF(emit_fpu_data_transfer(compiler, src, 0, dst, dstw));
+ if (dst_fr == TMP_FREG1) {
+ if (GET_OPCODE(op) == SLJIT_MOVD)
+ dst_fr = src;
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_fr, dst, dstw, 0, 0));
+ }
return SLJIT_SUCCESS;
}
-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)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- int dst_fr;
+ sljit_si dst_fr, flags = 0;
CHECK_ERROR();
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
@@ -1220,38 +1223,68 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, in
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- dst_fr = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
+ dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG2 : (dst << 1);
- if (src2 > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w));
- src2 = TMP_FREG2;
+ if (src1 > SLJIT_FLOAT_REG6) {
+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
+ FAIL_IF(compiler->error);
+ src1 = TMP_FREG1;
+ } else
+ flags |= SLOW_SRC1;
}
+ else
+ src1 <<= 1;
- if (src1 > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w));
- src1 = TMP_FREG1;
+ if (src2 > SLJIT_FLOAT_REG6) {
+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
+ FAIL_IF(compiler->error);
+ src2 = TMP_FREG2;
+ } else
+ flags |= SLOW_SRC2;
}
+ else
+ src2 <<= 1;
- switch (op) {
- case SLJIT_FADD:
- FAIL_IF(push_inst(compiler, ADD_D | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
+ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+ if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
+ }
+ else {
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
+ }
+ }
+ else if (flags & SLOW_SRC1)
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
+ else if (flags & SLOW_SRC2)
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
+
+ if (flags & SLOW_SRC1)
+ src1 = TMP_FREG1;
+ if (flags & SLOW_SRC2)
+ src2 = TMP_FREG2;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADDD:
+ FAIL_IF(push_inst(compiler, ADD_fmt | FMT(op) | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
break;
- case SLJIT_FSUB:
- FAIL_IF(push_inst(compiler, SUB_D | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
+ case SLJIT_SUBD:
+ FAIL_IF(push_inst(compiler, SUB_fmt | FMT(op) | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
break;
- case SLJIT_FMUL:
- FAIL_IF(push_inst(compiler, MUL_D | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
+ case SLJIT_MULD:
+ FAIL_IF(push_inst(compiler, MUL_fmt | FMT(op) | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
break;
- case SLJIT_FDIV:
- FAIL_IF(push_inst(compiler, DIV_D | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
+ case SLJIT_DIVD:
+ FAIL_IF(push_inst(compiler, DIV_fmt | FMT(op) | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
break;
}
- if (dst_fr == TMP_FREG1)
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 0, dst, dstw));
+ if (dst_fr == TMP_FREG2)
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
return SLJIT_SUCCESS;
}
@@ -1260,31 +1293,30 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, in
/* Other instructions */
/* --------------------------------------------------------------------- */
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
CHECK_ERROR();
- check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
-
- compiler->temporaries = temporaries;
- compiler->saveds = saveds;
+ check_sljit_emit_fast_enter(compiler, dst, dstw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
- compiler->has_locals = local_size > 0;
- local_size += (saveds + 2 + 4) * sizeof(sljit_w);
- compiler->local_size = (local_size + 15) & ~0xf;
+ /* For UNUSED dst. Uncommon, but possible. */
+ if (dst == SLJIT_UNUSED)
+ return SLJIT_SUCCESS;
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
+ if (dst <= TMP_REG3)
return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), DR(dst));
- else if (dst & SLJIT_MEM)
- return emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw);
- return SLJIT_SUCCESS;
+
+ /* Memory. */
+ return emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw);
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
CHECK_ERROR();
check_sljit_emit_fast_return(compiler, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
- if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+ if (src <= TMP_REG3)
FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
else if (src & SLJIT_MEM)
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
@@ -1319,7 +1351,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
#define JUMP_LENGTH 4
#else
-#define JUMP_LENGTH 7
+#error "Implementation required"
#endif
#define BR_Z(src) \
@@ -1342,12 +1374,12 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
flags = IS_BIT16_COND; \
delay_check = FCSR_FCC;
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
{
struct sljit_jump *jump;
sljit_ins inst;
- int flags = 0;
- int delay_check = UNMOVABLE_INS;
+ sljit_si flags = 0;
+ sljit_si delay_check = UNMOVABLE_INS;
CHECK_ERROR_PTR();
check_sljit_emit_jump(compiler, type);
@@ -1402,10 +1434,10 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
case SLJIT_C_MUL_NOT_OVERFLOW:
BR_NZ(OVERFLOW_FLAG);
break;
- case SLJIT_C_FLOAT_NAN:
+ case SLJIT_C_FLOAT_UNORDERED:
BR_F();
break;
- case SLJIT_C_FLOAT_NOT_NAN:
+ case SLJIT_C_FLOAT_ORDERED:
BR_T();
break;
default:
@@ -1433,7 +1465,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
jump->addr = compiler->size;
/* A NOP if type < CALL1. */
- PTR_FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_TEMPORARY_REG1) | TA(0) | DA(4), UNMOVABLE_INS));
+ PTR_FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SCRATCH_REG1) | TA(0) | DA(4), UNMOVABLE_INS));
}
return jump;
}
@@ -1458,32 +1490,28 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
src2 = 0; \
}
-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)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
struct sljit_jump *jump;
- int flags;
+ sljit_si flags;
sljit_ins inst;
CHECK_ERROR_PTR();
check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
compiler->cache_arg = 0;
compiler->cache_argw = 0;
flags = ((type & SLJIT_INT_OP) ? INT_DATA : WORD_DATA) | LOAD_DATA;
if (src1 & SLJIT_MEM) {
- if (getput_arg_fast(compiler, flags, DR(TMP_REG1), src1, src1w))
- PTR_FAIL_IF(compiler->error);
- else
- PTR_FAIL_IF(getput_arg(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));
+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));
src1 = TMP_REG1;
}
if (src2 & SLJIT_MEM) {
- if (getput_arg_fast(compiler, flags, DR(TMP_REG2), src2, src2w))
- PTR_FAIL_IF(compiler->error);
- else
- PTR_FAIL_IF(getput_arg(compiler, flags, DR(TMP_REG2), src2, src2w, 0, 0));
+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG2), src2, src2w, 0, 0));
src2 = TMP_REG2;
}
@@ -1583,13 +1611,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
#undef RESOLVE_IMM1
#undef RESOLVE_IMM2
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
struct sljit_jump *jump;
sljit_ins inst;
- int if_true;
+ sljit_si if_true;
CHECK_ERROR_PTR();
check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w);
@@ -1597,58 +1625,62 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- if (src1 > SLJIT_FLOAT_REG4) {
- PTR_FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w));
+ if (src1 > SLJIT_FLOAT_REG6) {
+ PTR_FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
src1 = TMP_FREG1;
}
- if (src2 > SLJIT_FLOAT_REG4) {
- PTR_FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w));
+ else
+ src1 <<= 1;
+
+ if (src2 > SLJIT_FLOAT_REG6) {
+ PTR_FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
src2 = TMP_FREG2;
}
+ else
+ src2 <<= 1;
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
jump->flags |= IS_BIT16_COND;
- type &= 0xff;
- switch (type) {
+ switch (type & 0xff) {
case SLJIT_C_FLOAT_EQUAL:
- inst = C_UEQ_D;
+ inst = C_UEQ_fmt;
if_true = 1;
break;
case SLJIT_C_FLOAT_NOT_EQUAL:
- inst = C_UEQ_D;
+ inst = C_UEQ_fmt;
if_true = 0;
break;
case SLJIT_C_FLOAT_LESS:
- inst = C_ULT_D;
+ inst = C_ULT_fmt;
if_true = 1;
break;
case SLJIT_C_FLOAT_GREATER_EQUAL:
- inst = C_ULT_D;
+ inst = C_ULT_fmt;
if_true = 0;
break;
case SLJIT_C_FLOAT_GREATER:
- inst = C_ULE_D;
+ inst = C_ULE_fmt;
if_true = 0;
break;
case SLJIT_C_FLOAT_LESS_EQUAL:
- inst = C_ULE_D;
+ inst = C_ULE_fmt;
if_true = 1;
break;
- case SLJIT_C_FLOAT_NAN:
- inst = C_UN_D;
+ case SLJIT_C_FLOAT_UNORDERED:
+ inst = C_UN_fmt;
if_true = 1;
break;
- case SLJIT_C_FLOAT_NOT_NAN:
+ case SLJIT_C_FLOAT_ORDERED:
default: /* Make compilers happy. */
- inst = C_UN_D;
+ inst = C_UN_fmt;
if_true = 0;
break;
}
- PTR_FAIL_IF(push_inst(compiler, inst | FT(src2) | FS(src1), UNMOVABLE_INS));
+ PTR_FAIL_IF(push_inst(compiler, inst | FMT(type) | FT(src2) | FS(src1), UNMOVABLE_INS));
/* Intentionally the other opcode. */
PTR_FAIL_IF(push_inst(compiler, (if_true ? BC1F : BC1T) | JUMP_LENGTH, UNMOVABLE_INS));
PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
@@ -1664,15 +1696,19 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
#undef BR_T
#undef BR_F
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+#undef FLOAT_DATA
+#undef FMT
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
{
- int src_r = TMP_REG2;
+ sljit_si src_r = TMP_REG2;
struct sljit_jump *jump = NULL;
CHECK_ERROR();
check_sljit_emit_ijump(compiler, type, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
- if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) {
+ if (src <= TMP_REG3) {
if (DR(src) != 4)
src_r = src;
else
@@ -1690,12 +1726,12 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, i
}
FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
/* We need an extra instruction in any case. */
- return push_inst(compiler, ADDU_W | S(SLJIT_TEMPORARY_REG1) | TA(0) | DA(4), UNMOVABLE_INS);
+ return push_inst(compiler, ADDU_W | S(SLJIT_SCRATCH_REG1) | TA(0) | DA(4), UNMOVABLE_INS);
}
/* Register input. */
if (type >= SLJIT_CALL1)
- FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_TEMPORARY_REG1) | TA(0) | DA(4), 4));
+ FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SCRATCH_REG1) | TA(0) | DA(4), 4));
FAIL_IF(push_inst(compiler, JALR | S(src_r) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
return push_inst(compiler, ADDU_W | S(src_r) | TA(0) | D(PIC_ADDR_REG), UNMOVABLE_INS);
}
@@ -1721,17 +1757,32 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, i
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw,
+ sljit_si type)
{
- int sugg_dst_ar, dst_ar;
+ sljit_si sugg_dst_ar, dst_ar;
+ sljit_si flags = GET_ALL_FLAGS(op);
CHECK_ERROR();
- check_sljit_emit_cond_value(compiler, op, dst, dstw, type);
+ check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
- sugg_dst_ar = DR((op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2);
+ op = GET_OPCODE(op);
+ sugg_dst_ar = DR((op < SLJIT_ADD && dst <= TMP_REG3) ? dst : TMP_REG2);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw));
+ src = TMP_REG1;
+ srcw = 0;
+ }
switch (type) {
case SLJIT_C_EQUAL:
@@ -1774,8 +1825,8 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compil
dst_ar = EQUAL_FLAG;
break;
- case SLJIT_C_FLOAT_NAN:
- case SLJIT_C_FLOAT_NOT_NAN:
+ case SLJIT_C_FLOAT_UNORDERED:
+ case SLJIT_C_FLOAT_ORDERED:
FAIL_IF(push_inst(compiler, CFC1 | TA(sugg_dst_ar) | DA(FCSR_REG), sugg_dst_ar));
FAIL_IF(push_inst(compiler, SRL | TA(sugg_dst_ar) | DA(sugg_dst_ar) | SH_IMM(23), sugg_dst_ar));
FAIL_IF(push_inst(compiler, ANDI | SA(sugg_dst_ar) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
@@ -1793,10 +1844,10 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compil
dst_ar = sugg_dst_ar;
}
- if (GET_OPCODE(op) == SLJIT_OR) {
+ if (op >= SLJIT_ADD) {
if (DR(TMP_REG2) != dst_ar)
FAIL_IF(push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
- return emit_op(compiler, op, CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, dst, dstw, TMP_REG2, 0);
+ return emit_op(compiler, op | flags, CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
}
if (dst & SLJIT_MEM)
@@ -1807,19 +1858,20 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compil
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;
- int reg;
+ sljit_si reg;
CHECK_ERROR_PTR();
check_sljit_emit_const(compiler, dst, dstw, init_value);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2;
+ reg = (dst <= TMP_REG3) ? dst : TMP_REG2;
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_32.c b/src/3rdparty/pcre/sljit/sljitNativePPC_32.c
index 82d0508ac1..0bd35a6e0e 100644
--- a/src/3rdparty/pcre/sljit/sljitNativePPC_32.c
+++ b/src/3rdparty/pcre/sljit/sljitNativePPC_32.c
@@ -26,7 +26,7 @@
/* ppc 32-bit arch dependent functions. */
-static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
+static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
{
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
@@ -41,10 +41,59 @@ static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
#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)
+static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
+ sljit_si dst, sljit_si src1, sljit_si src2)
{
switch (op) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_UI:
+ case SLJIT_MOV_SI:
+ case SLJIT_MOV_P:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ if (dst != src2)
+ return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_UB:
+ case SLJIT_MOV_SB:
+ 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 {
+ SLJIT_ASSERT(dst == src2);
+ }
+ 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 {
+ SLJIT_ASSERT(dst == src2);
+ }
+ 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));
+
case SLJIT_ADD:
if (flags & ALT_FORM1) {
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
@@ -71,7 +120,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
case SLJIT_ADDC:
if (flags & ALT_FORM1) {
- FAIL_IF(push_inst(compiler, MFXER | S(0)));
+ FAIL_IF(push_inst(compiler, MFXER | D(0)));
FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
return push_inst(compiler, MTXER | S(0));
}
@@ -106,7 +155,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
case SLJIT_SUBC:
if (flags & ALT_FORM1) {
- FAIL_IF(push_inst(compiler, MFXER | S(0)));
+ FAIL_IF(push_inst(compiler, MFXER | D(0)));
FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
return push_inst(compiler, MTXER | S(0));
}
@@ -179,65 +228,23 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_ASHR:
+ if (flags & ALT_FORM3)
+ FAIL_IF(push_inst(compiler, MFXER | D(0)));
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
compiler->imm &= 0x1f;
- 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));
+ FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
}
- 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));
+ else
+ FAIL_IF(push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)));
+ return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
}
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
+static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
{
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
@@ -252,7 +259,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ad
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
{
sljit_ins *inst = (sljit_ins*)addr;
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_64.c b/src/3rdparty/pcre/sljit/sljitNativePPC_64.c
index cc2ae37eb9..8eaeb41f4e 100644
--- a/src/3rdparty/pcre/sljit/sljitNativePPC_64.c
+++ b/src/3rdparty/pcre/sljit/sljitNativePPC_64.c
@@ -26,9 +26,11 @@
/* ppc 64-bit arch dependent functions. */
-#ifdef __GNUC__
+#if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
#define ASM_SLJIT_CLZ(src, dst) \
- asm volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
+ __asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
+#elif defined(__xlc__)
+#error "Please enable GCC syntax for inline assembly statements"
#else
#error "Must implement count leading zeroes"
#endif
@@ -39,7 +41,7 @@
#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)
+static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
{
sljit_uw tmp;
sljit_uw shift;
@@ -143,10 +145,74 @@ static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
src1 = TMP_REG1; \
}
-static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
- int dst, int src1, int src2)
+static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
+ sljit_si dst, sljit_si src1, sljit_si src2)
{
switch (op) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ if (dst != src2)
+ return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_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 {
+ SLJIT_ASSERT(dst == 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 {
+ SLJIT_ASSERT(dst == src2);
+ }
+ 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 {
+ SLJIT_ASSERT(dst == src2);
+ }
+ 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));
+
case SLJIT_ADD:
if (flags & ALT_FORM1) {
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
@@ -175,7 +241,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
case SLJIT_ADDC:
if (flags & ALT_FORM1) {
- FAIL_IF(push_inst(compiler, MFXER | S(0)));
+ FAIL_IF(push_inst(compiler, MFXER | D(0)));
FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
return push_inst(compiler, MTXER | S(0));
}
@@ -212,7 +278,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
case SLJIT_SUBC:
if (flags & ALT_FORM1) {
- FAIL_IF(push_inst(compiler, MFXER | S(0)));
+ FAIL_IF(push_inst(compiler, MFXER | D(0)));
FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
return push_inst(compiler, MTXER | S(0));
}
@@ -284,9 +350,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
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));
+ return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_LSHR:
if (flags & ALT_FORM1) {
@@ -300,92 +364,32 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
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));
+ return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_ASHR:
+ if (flags & ALT_FORM3)
+ FAIL_IF(push_inst(compiler, MFXER | D(0)));
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
if (flags & ALT_FORM2) {
compiler->imm &= 0x1f;
- return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
+ FAIL_IF(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));
+ FAIL_IF(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));
+ else
+ FAIL_IF(push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2)));
+ return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
}
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
+static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
{
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));
@@ -405,7 +409,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ad
SLJIT_CACHE_FLUSH(inst, inst + 5);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
{
sljit_ins *inst = (sljit_ins*)addr;
@@ -415,14 +419,3 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constan
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];
-}
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c
index f0f191de1f..f7c75a7906 100644
--- a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c
+++ b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c
@@ -24,7 +24,7 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
{
return "PowerPC" SLJIT_CPUINFO;
}
@@ -33,26 +33,62 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
Both for ppc-32 and ppc-64. */
typedef sljit_ui sljit_ins;
+#ifdef _AIX
+#include <sys/cache.h>
+#endif
+
static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
{
+#ifdef _AIX
+ _sync_cache_range((caddr_t)from, (int)((size_t)to - (size_t)from));
+#elif defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
+# if defined(_ARCH_PWR) || defined(_ARCH_PWR2)
+ /* Cache flush for POWER architecture. */
while (from < to) {
-#ifdef __GNUC__
- asm volatile ( "icbi 0, %0" : : "r"(from) );
-#else
-#error "Must implement icbi"
-#endif
+ __asm__ volatile (
+ "clf 0, %0\n"
+ "dcs\n"
+ : : "r"(from)
+ );
from++;
}
+ __asm__ volatile ( "ics" );
+# elif defined(_ARCH_COM) && !defined(_ARCH_PPC)
+# error "Cache flush is not implemented for PowerPC/POWER common mode."
+# else
+ /* Cache flush for PowerPC architecture. */
+ while (from < to) {
+ __asm__ volatile (
+ "dcbf 0, %0\n"
+ "sync\n"
+ "icbi 0, %0\n"
+ : : "r"(from)
+ );
+ from++;
+ }
+ __asm__ volatile ( "isync" );
+# endif
+# ifdef __xlc__
+# warning "This file may fail to compile if -qfuncsect is used"
+# endif
+#elif defined(__xlc__)
+#error "Please enable GCC syntax for inline assembly statements with -qasm=gcc"
+#else
+#error "This platform requires a cache flush implementation."
+#endif /* _AIX */
}
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
#define ZERO_REG (SLJIT_NO_REGISTERS + 4)
-#define REAL_STACK_PTR (SLJIT_NO_REGISTERS + 5)
-#define TMP_FREG1 (SLJIT_FLOAT_REG4 + 1)
-#define TMP_FREG2 (SLJIT_FLOAT_REG4 + 2)
+#define TMP_FREG1 (0)
+#define TMP_FREG2 (SLJIT_FLOAT_REG6 + 1)
+
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
+ 0, 3, 4, 5, 6, 7, 30, 29, 28, 27, 26, 1, 8, 9, 10, 31
+};
/* --------------------------------------------------------------------- */
/* Instrucion forms */
@@ -107,16 +143,17 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
#define EXTSW (HI(31) | LO(986))
#define FABS (HI(63) | LO(264))
#define FADD (HI(63) | LO(21))
+#define FADDS (HI(59) | LO(21))
#define FCMPU (HI(63) | LO(0))
#define FDIV (HI(63) | LO(18))
+#define FDIVS (HI(59) | LO(18))
#define FMR (HI(63) | LO(72))
#define FMUL (HI(63) | LO(25))
+#define FMULS (HI(59) | LO(25))
#define FNEG (HI(63) | LO(40))
#define FSUB (HI(63) | LO(20))
+#define FSUBS (HI(59) | LO(20))
#define LD (HI(58) | 0)
-#define LFD (HI(50))
-#define LFDUX (HI(31) | LO(631))
-#define LFDX (HI(31) | LO(599))
#define LWZ (HI(32))
#define MFCR (HI(31) | LO(19))
#define MFLR (HI(31) | LO(339) | 0x80000)
@@ -150,9 +187,6 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
#define STD (HI(62) | 0)
#define STDU (HI(62) | 1)
#define STDUX (HI(31) | LO(181))
-#define STFD (HI(54))
-#define STFDUX (HI(31) | LO(759))
-#define STFDX (HI(31) | LO(727))
#define STW (HI(36))
#define STWU (HI(37))
#define STWUX (HI(31) | LO(183))
@@ -168,13 +202,20 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
#define SIMM_MIN (-0x8000)
#define UIMM_MAX (0xffff)
-/* SLJIT_LOCALS_REG is not the real stack register, since it must
- point to the head of the stack chain. */
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 6] = {
- 0, 3, 4, 5, 6, 7, 29, 28, 27, 26, 25, 31, 8, 9, 10, 30, 1
-};
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func)
+{
+ sljit_sw* ptrs;
+ if (func_ptr)
+ *func_ptr = (void*)context;
+ ptrs = (sljit_sw*)func;
+ context->addr = addr ? addr : ptrs[0];
+ context->r2 = ptrs[1];
+ context->r11 = ptrs[2];
+}
+#endif
-static int push_inst(struct sljit_compiler *compiler, sljit_ins ins)
+static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins)
{
sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
FAIL_IF(!ptr);
@@ -183,9 +224,9 @@ static int push_inst(struct sljit_compiler *compiler, sljit_ins ins)
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE int optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+static SLJIT_INLINE sljit_si optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
{
- sljit_w diff;
+ sljit_sw diff;
sljit_uw target_addr;
if (jump->flags & SLJIT_REWRITABLE_JUMP)
@@ -197,7 +238,7 @@ static SLJIT_INLINE int optimize_jump(struct sljit_jump *jump, sljit_ins *code_p
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
target_addr = (sljit_uw)(code + jump->u.label->size);
}
- diff = ((sljit_w)target_addr - (sljit_w)(code_ptr)) & ~0x3l;
+ diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr)) & ~0x3l;
if (jump->flags & UNCOND_B) {
if (diff <= 0x01ffffff && diff >= -0x02000000) {
@@ -240,8 +281,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
check_sljit_generate_code(compiler);
reverse_buf(compiler);
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
+#else
+ compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
+#endif
#endif
code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins));
PTR_FAIL_WITH_EXEC_IF(code);
@@ -305,10 +350,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- SLJIT_ASSERT(code_ptr - code <= (int)compiler->size - ((compiler->size & 0x1) ? 3 : 2));
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins)));
#else
- SLJIT_ASSERT(code_ptr - code <= (int)compiler->size);
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
#endif
jump = compiler->jumps;
@@ -320,7 +365,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (jump->flags & UNCOND_B) {
if (!(jump->flags & ABSOLUTE_B)) {
addr = addr - jump->addr;
- SLJIT_ASSERT((sljit_w)addr <= 0x01ffffff && (sljit_w)addr >= -0x02000000);
+ SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
*buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
}
else {
@@ -331,7 +376,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
else {
if (!(jump->flags & ABSOLUTE_B)) {
addr = addr - jump->addr;
- SLJIT_ASSERT((sljit_w)addr <= 0x7fff && (sljit_w)addr >= -0x8000);
+ SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
*buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
}
else {
@@ -361,29 +406,41 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_size = compiler->size * sizeof(sljit_ins);
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if (((sljit_w)code_ptr) & 0x4)
+ if (((sljit_sw)code_ptr) & 0x4)
code_ptr++;
- sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_w)code, sljit_generate_code);
+ sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);
return code_ptr;
#else
+ sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);
+ return code_ptr;
+#endif
+#else
return code;
#endif
}
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
/* inp_flags: */
/* Creates an index in data_transfer_insts array. */
+#define LOAD_DATA 0x01
+#define INDEXED 0x02
+#define WRITE_BACK 0x04
#define WORD_DATA 0x00
-#define BYTE_DATA 0x01
-#define HALF_DATA 0x02
-#define INT_DATA 0x03
-#define SIGNED_DATA 0x04
-#define LOAD_DATA 0x08
-#define WRITE_BACK 0x10
-#define INDEXED 0x20
+#define BYTE_DATA 0x08
+#define HALF_DATA 0x10
+#define INT_DATA 0x18
+#define SIGNED_DATA 0x20
+/* Separates integer and floating point registers */
+#define GPR_REG 0x3f
+#define DOUBLE_DATA 0x40
-#define MEM_MASK 0x3f
+#define MEM_MASK 0x7f
/* Other inp_flags. */
@@ -392,6 +449,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#define ALT_SIGN_EXT 0x000200
/* This flag affects the RC() and OERC() macros. */
#define ALT_SET_FLAGS 0x000400
+#define ALT_KEEP_CACHE 0x000800
#define ALT_FORM1 0x010000
#define ALT_FORM2 0x020000
#define ALT_FORM3 0x040000
@@ -428,92 +486,85 @@ ALT_FORM6 0x200000 */
#define STACK_LOAD LD
#endif
-static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w);
-
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
CHECK_ERROR();
- check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
+ check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
- compiler->temporaries = temporaries;
+ compiler->scratches = scratches;
compiler->saveds = saveds;
- compiler->has_locals = local_size > 0;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
FAIL_IF(push_inst(compiler, MFLR | D(0)));
- if (compiler->has_locals)
- FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM(-(int)(sizeof(sljit_w))) ));
- FAIL_IF(push_inst(compiler, STACK_STORE | S(ZERO_REG) | A(REAL_STACK_PTR) | IMM(-2 * (int)(sizeof(sljit_w))) ));
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(ZERO_REG) | A(SLJIT_LOCALS_REG) | IMM(-(sljit_si)(sizeof(sljit_sw))) ));
if (saveds >= 1)
- FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG1) | A(REAL_STACK_PTR) | IMM(-3 * (int)(sizeof(sljit_w))) ));
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG1) | A(SLJIT_LOCALS_REG) | IMM(-2 * (sljit_si)(sizeof(sljit_sw))) ));
if (saveds >= 2)
- FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG2) | A(REAL_STACK_PTR) | IMM(-4 * (int)(sizeof(sljit_w))) ));
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG2) | A(SLJIT_LOCALS_REG) | IMM(-3 * (sljit_si)(sizeof(sljit_sw))) ));
if (saveds >= 3)
- FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG3) | A(REAL_STACK_PTR) | IMM(-5 * (int)(sizeof(sljit_w))) ));
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG3) | A(SLJIT_LOCALS_REG) | IMM(-4 * (sljit_si)(sizeof(sljit_sw))) ));
if (saveds >= 4)
- FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG1) | A(REAL_STACK_PTR) | IMM(-6 * (int)(sizeof(sljit_w))) ));
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG1) | A(SLJIT_LOCALS_REG) | IMM(-5 * (sljit_si)(sizeof(sljit_sw))) ));
if (saveds >= 5)
- FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG2) | A(REAL_STACK_PTR) | IMM(-7 * (int)(sizeof(sljit_w))) ));
- FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(REAL_STACK_PTR) | IMM(sizeof(sljit_w)) ));
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG2) | A(SLJIT_LOCALS_REG) | IMM(-6 * (sljit_si)(sizeof(sljit_sw))) ));
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_LOCALS_REG) | IMM(sizeof(sljit_sw)) ));
FAIL_IF(push_inst(compiler, ADDI | D(ZERO_REG) | A(0) | 0));
if (args >= 1)
- FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(SLJIT_SAVED_REG1) | B(SLJIT_TEMPORARY_REG1)));
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG1) | A(SLJIT_SAVED_REG1) | B(SLJIT_SCRATCH_REG1)));
if (args >= 2)
- FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG2) | A(SLJIT_SAVED_REG2) | B(SLJIT_TEMPORARY_REG2)));
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG2) | A(SLJIT_SAVED_REG2) | B(SLJIT_SCRATCH_REG2)));
if (args >= 3)
- FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG3) | A(SLJIT_SAVED_REG3) | B(SLJIT_TEMPORARY_REG3)));
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG3) | A(SLJIT_SAVED_REG3) | B(SLJIT_SCRATCH_REG3)));
-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- compiler->local_size = (2 + saveds + 2) * sizeof(sljit_w) + local_size;
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+ compiler->local_size = (1 + saveds + 6 + 8) * sizeof(sljit_sw) + local_size;
#else
- compiler->local_size = (2 + saveds + 7 + 8) * sizeof(sljit_w) + local_size;
+ compiler->local_size = (1 + saveds + 2) * sizeof(sljit_sw) + local_size;
#endif
compiler->local_size = (compiler->local_size + 15) & ~0xf;
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
if (compiler->local_size <= SIMM_MAX)
- FAIL_IF(push_inst(compiler, STWU | S(REAL_STACK_PTR) | A(REAL_STACK_PTR) | IMM(-compiler->local_size)));
+ FAIL_IF(push_inst(compiler, STWU | S(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | IMM(-compiler->local_size)));
else {
FAIL_IF(load_immediate(compiler, 0, -compiler->local_size));
- FAIL_IF(push_inst(compiler, STWUX | S(REAL_STACK_PTR) | A(REAL_STACK_PTR) | B(0)));
+ FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | B(0)));
}
- if (compiler->has_locals)
- FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM(2 * sizeof(sljit_w))));
#else
if (compiler->local_size <= SIMM_MAX)
- FAIL_IF(push_inst(compiler, STDU | S(REAL_STACK_PTR) | A(REAL_STACK_PTR) | IMM(-compiler->local_size)));
+ FAIL_IF(push_inst(compiler, STDU | S(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | IMM(-compiler->local_size)));
else {
FAIL_IF(load_immediate(compiler, 0, -compiler->local_size));
- FAIL_IF(push_inst(compiler, STDUX | S(REAL_STACK_PTR) | A(REAL_STACK_PTR) | B(0)));
+ FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | B(0)));
}
- if (compiler->has_locals)
- FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM((7 + 8) * sizeof(sljit_w))));
#endif
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
CHECK_ERROR_VOID();
- check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
+ check_sljit_set_context(compiler, args, scratches, saveds, local_size);
- compiler->temporaries = temporaries;
+ compiler->scratches = scratches;
compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
- compiler->has_locals = local_size > 0;
-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- compiler->local_size = (2 + saveds + 2) * sizeof(sljit_w) + local_size;
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+ compiler->local_size = (1 + saveds + 6 + 8) * sizeof(sljit_sw) + local_size;
#else
- compiler->local_size = (2 + saveds + 7 + 8) * sizeof(sljit_w) + local_size;
+ compiler->local_size = (1 + saveds + 2) * sizeof(sljit_sw) + local_size;
#endif
compiler->local_size = (compiler->local_size + 15) & ~0xf;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
CHECK_ERROR();
check_sljit_emit_return(compiler, op, src, srcw);
@@ -521,26 +572,24 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
if (compiler->local_size <= SIMM_MAX)
- FAIL_IF(push_inst(compiler, ADDI | D(REAL_STACK_PTR) | A(REAL_STACK_PTR) | IMM(compiler->local_size)));
+ FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | IMM(compiler->local_size)));
else {
FAIL_IF(load_immediate(compiler, 0, compiler->local_size));
- FAIL_IF(push_inst(compiler, ADD | D(REAL_STACK_PTR) | A(REAL_STACK_PTR) | B(0)));
+ FAIL_IF(push_inst(compiler, ADD | D(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | B(0)));
}
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(REAL_STACK_PTR) | IMM(sizeof(sljit_w))));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_LOCALS_REG) | IMM(sizeof(sljit_sw))));
if (compiler->saveds >= 5)
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG2) | A(REAL_STACK_PTR) | IMM(-7 * (int)(sizeof(sljit_w))) ));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG2) | A(SLJIT_LOCALS_REG) | IMM(-6 * (sljit_si)(sizeof(sljit_sw))) ));
if (compiler->saveds >= 4)
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG1) | A(REAL_STACK_PTR) | IMM(-6 * (int)(sizeof(sljit_w))) ));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG1) | A(SLJIT_LOCALS_REG) | IMM(-5 * (sljit_si)(sizeof(sljit_sw))) ));
if (compiler->saveds >= 3)
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG3) | A(REAL_STACK_PTR) | IMM(-5 * (int)(sizeof(sljit_w))) ));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG3) | A(SLJIT_LOCALS_REG) | IMM(-4 * (sljit_si)(sizeof(sljit_sw))) ));
if (compiler->saveds >= 2)
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG2) | A(REAL_STACK_PTR) | IMM(-4 * (int)(sizeof(sljit_w))) ));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG2) | A(SLJIT_LOCALS_REG) | IMM(-3 * (sljit_si)(sizeof(sljit_sw))) ));
if (compiler->saveds >= 1)
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG1) | A(REAL_STACK_PTR) | IMM(-3 * (int)(sizeof(sljit_w))) ));
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(ZERO_REG) | A(REAL_STACK_PTR) | IMM(-2 * (int)(sizeof(sljit_w))) ));
- if (compiler->has_locals)
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM(-(int)(sizeof(sljit_w))) ));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG1) | A(SLJIT_LOCALS_REG) | IMM(-2 * (sljit_si)(sizeof(sljit_sw))) ));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(ZERO_REG) | A(SLJIT_LOCALS_REG) | IMM(-(sljit_si)(sizeof(sljit_sw))) ));
FAIL_IF(push_inst(compiler, MTLR | S(0)));
FAIL_IF(push_inst(compiler, BLR));
@@ -568,117 +617,139 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
#define UPDATE_REQ 0x20000
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
-#define ARCH_DEPEND(a, b) a
-#define GET_INST_CODE(inst) (inst)
+#define ARCH_32_64(a, b) a
+#define INST_CODE_AND_DST(inst, flags, reg) \
+ ((inst) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
#else
-#define ARCH_DEPEND(a, b) b
-#define GET_INST_CODE(index) ((inst) & ~(ADDR_MODE2 | UPDATE_REQ))
+#define ARCH_32_64(a, b) b
+#define INST_CODE_AND_DST(inst, flags, reg) \
+ (((inst) & ~(ADDR_MODE2 | UPDATE_REQ)) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
#endif
-static SLJIT_CONST sljit_ins data_transfer_insts[64] = {
+static SLJIT_CONST sljit_ins data_transfer_insts[64 + 8] = {
+
+/* -------- Unsigned -------- */
+
+/* Word. */
+
+/* u w n i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | ADDR_MODE2 | 0x0 /* std */),
+/* u w n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x0 /* ld */),
+/* u w n x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
+/* u w n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
+
+/* u w w i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | ADDR_MODE2 | 0x1 /* stdu */),
+/* u w w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | 0x1 /* ldu */),
+/* u w w x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
+/* u w w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
+
+/* Byte. */
-/* No write-back. */
+/* u b n i s */ HI(38) /* stb */,
+/* u b n i l */ HI(34) /* lbz */,
+/* u b n x s */ HI(31) | LO(215) /* stbx */,
+/* u b n x l */ HI(31) | LO(87) /* lbzx */,
-/* i n s u w */ ARCH_DEPEND(HI(36) /* stw */, HI(62) | ADDR_MODE2 | 0x0 /* std */),
-/* i n s u b */ HI(38) /* stb */,
-/* i n s u h */ HI(44) /* sth*/,
-/* i n s u i */ HI(36) /* stw */,
+/* u b w i s */ HI(39) /* stbu */,
+/* u b w i l */ HI(35) /* lbzu */,
+/* u b w x s */ HI(31) | LO(247) /* stbux */,
+/* u b w x l */ HI(31) | LO(119) /* lbzux */,
-/* i n s s w */ ARCH_DEPEND(HI(36) /* stw */, HI(62) | ADDR_MODE2 | 0x0 /* std */),
-/* i n s s b */ HI(38) /* stb */,
-/* i n s s h */ HI(44) /* sth*/,
-/* i n s s i */ HI(36) /* stw */,
+/* Half. */
-/* i n l u w */ ARCH_DEPEND(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x0 /* ld */),
-/* i n l u b */ HI(34) /* lbz */,
-/* i n l u h */ HI(40) /* lhz */,
-/* i n l u i */ HI(32) /* lwz */,
+/* u h n i s */ HI(44) /* sth */,
+/* u h n i l */ HI(40) /* lhz */,
+/* u h n x s */ HI(31) | LO(407) /* sthx */,
+/* u h n x l */ HI(31) | LO(279) /* lhzx */,
-/* i n l s w */ ARCH_DEPEND(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x0 /* ld */),
-/* i n l s b */ HI(34) /* lbz */ /* EXTS_REQ */,
-/* i n l s h */ HI(42) /* lha */,
-/* i n l s i */ ARCH_DEPEND(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x2 /* lwa */),
+/* u h w i s */ HI(45) /* sthu */,
+/* u h w i l */ HI(41) /* lhzu */,
+/* u h w x s */ HI(31) | LO(439) /* sthux */,
+/* u h w x l */ HI(31) | LO(311) /* lhzux */,
-/* Write-back. */
+/* Int. */
-/* i w s u w */ ARCH_DEPEND(HI(37) /* stwu */, HI(62) | ADDR_MODE2 | 0x1 /* stdu */),
-/* i w s u b */ HI(39) /* stbu */,
-/* i w s u h */ HI(45) /* sthu */,
-/* i w s u i */ HI(37) /* stwu */,
+/* u i n i s */ HI(36) /* stw */,
+/* u i n i l */ HI(32) /* lwz */,
+/* u i n x s */ HI(31) | LO(151) /* stwx */,
+/* u i n x l */ HI(31) | LO(23) /* lwzx */,
-/* i w s s w */ ARCH_DEPEND(HI(37) /* stwu */, HI(62) | ADDR_MODE2 | 0x1 /* stdu */),
-/* i w s s b */ HI(39) /* stbu */,
-/* i w s s h */ HI(45) /* sthu */,
-/* i w s s i */ HI(37) /* stwu */,
+/* u i w i s */ HI(37) /* stwu */,
+/* u i w i l */ HI(33) /* lwzu */,
+/* u i w x s */ HI(31) | LO(183) /* stwux */,
+/* u i w x l */ HI(31) | LO(55) /* lwzux */,
-/* i w l u w */ ARCH_DEPEND(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | 0x1 /* ldu */),
-/* i w l u b */ HI(35) /* lbzu */,
-/* i w l u h */ HI(41) /* lhzu */,
-/* i w l u i */ HI(33) /* lwzu */,
+/* -------- Signed -------- */
-/* i w l s w */ ARCH_DEPEND(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | 0x1 /* ldu */),
-/* i w l s b */ HI(35) /* lbzu */ /* EXTS_REQ */,
-/* i w l s h */ HI(43) /* lhau */,
-/* i w l s i */ ARCH_DEPEND(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | UPDATE_REQ | 0x2 /* lwa */),
+/* Word. */
-/* ---------- */
-/* Indexed */
-/* ---------- */
+/* s w n i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | ADDR_MODE2 | 0x0 /* std */),
+/* s w n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x0 /* ld */),
+/* s w n x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
+/* s w n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
-/* No write-back. */
+/* s w w i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | ADDR_MODE2 | 0x1 /* stdu */),
+/* s w w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | 0x1 /* ldu */),
+/* s w w x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
+/* s w w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
-/* x n s u w */ ARCH_DEPEND(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
-/* x n s u b */ HI(31) | LO(215) /* stbx */,
-/* x n s u h */ HI(31) | LO(407) /* sthx */,
-/* x n s u i */ HI(31) | LO(151) /* stwx */,
+/* Byte. */
-/* x n s s w */ ARCH_DEPEND(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
-/* x n s s b */ HI(31) | LO(215) /* stbx */,
-/* x n s s h */ HI(31) | LO(407) /* sthx */,
-/* x n s s i */ HI(31) | LO(151) /* stwx */,
+/* s b n i s */ HI(38) /* stb */,
+/* s b n i l */ HI(34) /* lbz */ /* EXTS_REQ */,
+/* s b n x s */ HI(31) | LO(215) /* stbx */,
+/* s b n x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,
-/* x n l u w */ ARCH_DEPEND(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
-/* x n l u b */ HI(31) | LO(87) /* lbzx */,
-/* x n l u h */ HI(31) | LO(279) /* lhzx */,
-/* x n l u i */ HI(31) | LO(23) /* lwzx */,
+/* s b w i s */ HI(39) /* stbu */,
+/* s b w i l */ HI(35) /* lbzu */ /* EXTS_REQ */,
+/* s b w x s */ HI(31) | LO(247) /* stbux */,
+/* s b w x l */ HI(31) | LO(119) /* lbzux */ /* EXTS_REQ */,
-/* x n l s w */ ARCH_DEPEND(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
-/* x n l s b */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,
-/* x n l s h */ HI(31) | LO(343) /* lhax */,
-/* x n l s i */ ARCH_DEPEND(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
+/* Half. */
-/* Write-back. */
+/* s h n i s */ HI(44) /* sth */,
+/* s h n i l */ HI(42) /* lha */,
+/* s h n x s */ HI(31) | LO(407) /* sthx */,
+/* s h n x l */ HI(31) | LO(343) /* lhax */,
-/* x w s u w */ ARCH_DEPEND(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
-/* x w s u b */ HI(31) | LO(247) /* stbux */,
-/* x w s u h */ HI(31) | LO(439) /* sthux */,
-/* x w s u i */ HI(31) | LO(183) /* stwux */,
+/* s h w i s */ HI(45) /* sthu */,
+/* s h w i l */ HI(43) /* lhau */,
+/* s h w x s */ HI(31) | LO(439) /* sthux */,
+/* s h w x l */ HI(31) | LO(375) /* lhaux */,
-/* x w s s w */ ARCH_DEPEND(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
-/* x w s s b */ HI(31) | LO(247) /* stbux */,
-/* x w s s h */ HI(31) | LO(439) /* sthux */,
-/* x w s s i */ HI(31) | LO(183) /* stwux */,
+/* Int. */
-/* x w l u w */ ARCH_DEPEND(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
-/* x w l u b */ HI(31) | LO(119) /* lbzux */,
-/* x w l u h */ HI(31) | LO(311) /* lhzux */,
-/* x w l u i */ HI(31) | LO(55) /* lwzux */,
+/* s i n i s */ HI(36) /* stw */,
+/* s i n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x2 /* lwa */),
+/* s i n x s */ HI(31) | LO(151) /* stwx */,
+/* s i n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
-/* x w l s w */ ARCH_DEPEND(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
-/* x w l s b */ HI(31) | LO(119) /* lbzux */ /* EXTS_REQ */,
-/* x w l s h */ HI(31) | LO(375) /* lhaux */,
-/* x w l s i */ ARCH_DEPEND(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */)
+/* s i w i s */ HI(37) /* stwu */,
+/* s i w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | UPDATE_REQ | 0x2 /* lwa */),
+/* s i w x s */ HI(31) | LO(183) /* stwux */,
+/* s i w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),
+
+/* -------- Double -------- */
+
+/* d n i s */ HI(54) /* stfd */,
+/* d n i l */ HI(50) /* lfd */,
+/* d n x s */ HI(31) | LO(727) /* stfdx */,
+/* d n x l */ HI(31) | LO(599) /* lfdx */,
+
+/* s n i s */ HI(52) /* stfs */,
+/* s n i l */ HI(48) /* lfs */,
+/* s n x s */ HI(31) | LO(663) /* stfsx */,
+/* s n x l */ HI(31) | LO(535) /* lfsx */,
};
-#undef ARCH_DEPEND
+#undef ARCH_32_64
/* Simple cases, (no caching is required). */
-static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw)
+static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_flags, sljit_si reg, sljit_si arg, sljit_sw argw)
{
sljit_ins inst;
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- int tmp_reg;
+ sljit_si tmp_reg;
#endif
SLJIT_ASSERT(arg & SLJIT_MEM);
@@ -690,7 +761,7 @@ static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int r
inst = data_transfer_insts[(inp_flags & ~WRITE_BACK) & MEM_MASK];
SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- push_inst(compiler, GET_INST_CODE(inst) | D(reg) | IMM(argw));
+ push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | IMM(argw));
return -1;
}
#else
@@ -700,11 +771,11 @@ static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int r
if (inp_flags & ARG_TEST)
return 1;
- push_inst(compiler, GET_INST_CODE(inst) | D(reg) | IMM(argw));
+ push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | IMM(argw));
return -1;
}
#endif
- return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+ return 0;
}
if (!(arg & 0xf0)) {
@@ -715,7 +786,7 @@ static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int r
inst = data_transfer_insts[inp_flags & MEM_MASK];
SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | IMM(argw));
+ push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | IMM(argw));
return -1;
}
#else
@@ -731,7 +802,7 @@ static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int r
arg = tmp_reg | SLJIT_MEM;
argw = 0;
}
- push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | IMM(argw));
+ push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | IMM(argw));
return -1;
}
#endif
@@ -741,28 +812,24 @@ static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int r
return 1;
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B((arg >> 4) & 0xf));
+ push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | B((arg >> 4) & 0xf));
return -1;
}
- return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+ return 0;
}
/* See getput_arg below.
Note: can_cache is called only for binary operators. Those operator always
uses word arguments without write back. */
-static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
{
- SLJIT_ASSERT(arg & SLJIT_MEM);
- SLJIT_ASSERT(next_arg & SLJIT_MEM);
+ SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
- if (!(arg & 0xf)) {
- if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= SIMM_MAX || (sljit_uw)next_argw - (sljit_uw)argw <= SIMM_MAX))
- return 1;
- return 0;
- }
+ if (!(arg & 0xf))
+ return (next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= SIMM_MAX || (sljit_uw)next_argw - (sljit_uw)argw <= SIMM_MAX);
if (arg & 0xf0)
- return 0;
+ return ((arg & 0xf0) == (next_arg & 0xf0) && (argw & 0x3) == (next_argw & 0x3));
if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
if (arg == next_arg && (next_argw >= SIMM_MAX && next_argw <= SIMM_MIN))
@@ -788,21 +855,17 @@ static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
#endif
/* Emit the necessary instructions. See can_cache above. */
-static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags, sljit_si reg, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
{
- int tmp_r;
+ sljit_si tmp_r;
sljit_ins inst;
SLJIT_ASSERT(arg & SLJIT_MEM);
- tmp_r = (inp_flags & LOAD_DATA) ? reg : TMP_REG3;
- if ((arg & 0xf) == tmp_r) {
- /* Special case for "mov reg, [reg, ... ]".
- Caching would not happen anyway. */
- tmp_r = TMP_REG3;
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- }
+ tmp_r = ((inp_flags & LOAD_DATA) && ((inp_flags) & MEM_MASK) <= GPR_REG) ? reg : TMP_REG1;
+ /* Special case for "mov reg, [reg, ... ]". */
+ if ((arg & 0xf) == tmp_r)
+ tmp_r = TMP_REG1;
if (!(arg & 0xf)) {
inst = data_transfer_insts[(inp_flags & ~WRITE_BACK) & MEM_MASK];
@@ -810,7 +873,7 @@ static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, i
argw = argw - compiler->cache_argw;
ADJUST_CACHED_IMM(argw);
SLJIT_ASSERT(!(inst & UPDATE_REQ));
- return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(TMP_REG3) | IMM(argw));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3) | IMM(argw));
}
if ((next_arg & SLJIT_MEM) && (argw - next_argw <= SIMM_MAX || next_argw - argw <= SIMM_MAX)) {
@@ -822,21 +885,31 @@ static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, i
}
FAIL_IF(load_immediate(compiler, tmp_r, argw));
- return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(tmp_r));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_r));
}
if (SLJIT_UNLIKELY(arg & 0xf0)) {
argw &= 0x3;
/* Otherwise getput_arg_fast would capture it. */
SLJIT_ASSERT(argw);
+
+ if ((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg && argw == compiler->cache_argw)
+ tmp_r = TMP_REG3;
+ else {
+ if ((arg & 0xf0) == (next_arg & 0xf0) && argw == (next_argw & 0x3)) {
+ compiler->cache_arg = SLJIT_MEM | (arg & 0xf0);
+ compiler->cache_argw = argw;
+ tmp_r = TMP_REG3;
+ }
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- FAIL_IF(push_inst(compiler, RLWINM | S((arg >> 4) & 0xf) | A(tmp_r) | (argw << 11) | ((31 - argw) << 1)));
+ FAIL_IF(push_inst(compiler, RLWINM | S((arg >> 4) & 0xf) | A(tmp_r) | (argw << 11) | ((31 - argw) << 1)));
#else
- FAIL_IF(push_inst(compiler, RLDI(tmp_r, (arg >> 4) & 0xf, argw, 63 - argw, 1)));
+ FAIL_IF(push_inst(compiler, RLDI(tmp_r, (arg >> 4) & 0xf, argw, 63 - argw, 1)));
#endif
+ }
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B(tmp_r));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | B(tmp_r));
}
inst = data_transfer_insts[inp_flags & MEM_MASK];
@@ -845,13 +918,13 @@ static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, i
SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
argw = argw - compiler->cache_argw;
ADJUST_CACHED_IMM(argw);
- return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(TMP_REG3) | IMM(argw));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3) | IMM(argw));
}
if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) {
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B(TMP_REG3));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | B(TMP_REG3));
}
if (argw == next_argw && (next_arg & SLJIT_MEM)) {
@@ -863,7 +936,7 @@ static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, i
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B(TMP_REG3));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | B(TMP_REG3));
}
if (arg == next_arg && !(inp_flags & WRITE_BACK) && ((sljit_uw)argw - (sljit_uw)next_argw <= SIMM_MAX || (sljit_uw)next_argw - (sljit_uw)argw <= SIMM_MAX)) {
@@ -874,49 +947,58 @@ static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, i
compiler->cache_arg = arg;
compiler->cache_argw = argw;
- return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(TMP_REG3));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3));
}
/* Get the indexed version instead of the normal one. */
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
FAIL_IF(load_immediate(compiler, tmp_r, argw));
- return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B(tmp_r));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | B(tmp_r));
}
-static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
+{
+ if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
+ return compiler->error;
+ return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+}
+
+static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si input_flags,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
/* arg1 goes to TMP_REG1 or src reg
arg2 goes to TMP_REG2, imm or src reg
TMP_REG3 can be used for caching
result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
- int dst_r;
- int src1_r;
- int src2_r;
- int sugg_src2_r = TMP_REG2;
- int flags = inp_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_FORM6 | ALT_SIGN_EXT | ALT_SET_FLAGS);
+ sljit_si dst_r;
+ sljit_si src1_r;
+ sljit_si src2_r;
+ sljit_si sugg_src2_r = TMP_REG2;
+ sljit_si flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_FORM6 | ALT_SIGN_EXT | ALT_SET_FLAGS);
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
+ if (!(input_flags & ALT_KEEP_CACHE)) {
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ }
/* Destination check. */
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= ZERO_REG) {
+ if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ dst_r = TMP_REG2;
+ }
+ else if (dst <= ZERO_REG) {
dst_r = dst;
flags |= REG_DEST;
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
sugg_src2_r = dst_r;
}
- else if (dst == SLJIT_UNUSED) {
- if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
- return SLJIT_SUCCESS;
- dst_r = TMP_REG2;
- }
else {
SLJIT_ASSERT(dst & SLJIT_MEM);
- if (getput_arg_fast(compiler, inp_flags | ARG_TEST, TMP_REG2, dst, dstw)) {
+ if (getput_arg_fast(compiler, input_flags | ARG_TEST, TMP_REG2, dst, dstw)) {
flags |= FAST_DEST;
dst_r = TMP_REG2;
}
@@ -927,23 +1009,15 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
}
/* Source 1. */
- if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= ZERO_REG) {
+ if (src1 <= ZERO_REG) {
src1_r = src1;
flags |= REG1_SOURCE;
}
else if (src1 & SLJIT_IMM) {
-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if ((inp_flags & 0x3) == INT_DATA) {
- if (inp_flags & SIGNED_DATA)
- src1w = (signed int)src1w;
- else
- src1w = (unsigned int)src1w;
- }
-#endif
FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
src1_r = TMP_REG1;
}
- else if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w)) {
+ else if (getput_arg_fast(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w)) {
FAIL_IF(compiler->error);
src1_r = TMP_REG1;
}
@@ -951,25 +1025,17 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
src1_r = 0;
/* Source 2. */
- if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= ZERO_REG) {
+ if (src2 <= ZERO_REG) {
src2_r = src2;
flags |= REG2_SOURCE;
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
dst_r = src2_r;
}
else if (src2 & SLJIT_IMM) {
-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if ((inp_flags & 0x3) == INT_DATA) {
- if (inp_flags & SIGNED_DATA)
- src2w = (signed int)src2w;
- else
- src2w = (unsigned int)src2w;
- }
-#endif
FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
src2_r = sugg_src2_r;
}
- else if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) {
+ else if (getput_arg_fast(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) {
FAIL_IF(compiler->error);
src2_r = sugg_src2_r;
}
@@ -980,26 +1046,26 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
All arguments are complex addressing modes, and it is a binary operator. */
if (src1_r == 0 && src2_r == 0 && dst_r == 0) {
if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+ FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
}
else {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));
+ FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));
}
src1_r = TMP_REG1;
src2_r = TMP_REG2;
}
else if (src1_r == 0 && src2_r == 0) {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
src1_r = TMP_REG1;
}
else if (src1_r == 0 && dst_r == 0) {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+ FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
src1_r = TMP_REG1;
}
else if (src2_r == 0 && dst_r == 0) {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));
+ FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));
src2_r = sugg_src2_r;
}
@@ -1007,12 +1073,12 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
dst_r = TMP_REG2;
if (src1_r == 0) {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0));
+ FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0));
src1_r = TMP_REG1;
}
if (src2_r == 0) {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0));
+ FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0));
src2_r = sugg_src2_r;
}
@@ -1020,14 +1086,14 @@ static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
if (flags & (FAST_DEST | SLOW_DEST)) {
if (flags & FAST_DEST)
- FAIL_IF(getput_arg_fast(compiler, inp_flags, dst_r, dst, dstw));
+ FAIL_IF(getput_arg_fast(compiler, input_flags, dst_r, dst, dstw));
else
- FAIL_IF(getput_arg(compiler, inp_flags, dst_r, dst, dstw, 0, 0));
+ FAIL_IF(getput_arg(compiler, input_flags, dst_r, dst, dstw, 0, 0));
}
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
{
CHECK_ERROR();
check_sljit_emit_op0(compiler, op);
@@ -1039,118 +1105,161 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
break;
case SLJIT_UMUL:
case SLJIT_SMUL:
- FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG1)));
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG1)));
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
- return push_inst(compiler, (GET_OPCODE(op) == SLJIT_UMUL ? MULHDU : MULHD) | D(SLJIT_TEMPORARY_REG2) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2));
+ FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_UMUL ? MULHDU : MULHD) | D(SLJIT_SCRATCH_REG2) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2));
#else
- FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
- return push_inst(compiler, (GET_OPCODE(op) == SLJIT_UMUL ? MULHWU : MULHW) | D(SLJIT_TEMPORARY_REG2) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2));
+ FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_UMUL ? MULHWU : MULHW) | D(SLJIT_SCRATCH_REG2) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2));
#endif
case SLJIT_UDIV:
case SLJIT_SDIV:
- FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG1)));
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG1)));
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
if (op & SLJIT_INT_OP) {
- FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
- FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG1) | B(SLJIT_TEMPORARY_REG2)));
- return push_inst(compiler, SUBF | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG2) | B(TMP_REG1));
+ FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
+ FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG1) | B(SLJIT_SCRATCH_REG2)));
+ return push_inst(compiler, SUBF | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG2) | B(TMP_REG1));
}
- FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVDU : DIVD) | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
- FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG1) | B(SLJIT_TEMPORARY_REG2)));
- return push_inst(compiler, SUBF | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG2) | B(TMP_REG1));
+ FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVDU : DIVD) | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
+ FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG1) | B(SLJIT_SCRATCH_REG2)));
+ return push_inst(compiler, SUBF | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG2) | B(TMP_REG1));
#else
- FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
- FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG1) | B(SLJIT_TEMPORARY_REG2)));
- return push_inst(compiler, SUBF | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG2) | B(TMP_REG1));
+ FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
+ FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG1) | B(SLJIT_SCRATCH_REG2)));
+ return push_inst(compiler, SUBF | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG2) | B(TMP_REG1));
#endif
}
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+#define EMIT_MOV(type, type_flags, type_cast) \
+ emit_op(compiler, (src & SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? type_cast srcw : srcw)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- int inp_flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0;
+ sljit_si flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0;
+ sljit_si op_flags = GET_ALL_FLAGS(op);
CHECK_ERROR();
check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ op = GET_OPCODE(op);
if ((src & SLJIT_IMM) && srcw == 0)
src = ZERO_REG;
+ if (op_flags & SLJIT_SET_O)
+ FAIL_IF(push_inst(compiler, MTXER | S(ZERO_REG)));
+
+ if (op_flags & SLJIT_INT_OP) {
+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
+ if (src <= ZERO_REG && src == dst) {
+ if (!TYPE_CAST_NEEDED(op))
+ return SLJIT_SUCCESS;
+ }
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if (op & SLJIT_INT_OP) {
- inp_flags |= INT_DATA | SIGNED_DATA;
- if (src & SLJIT_IMM)
- srcw = (int)srcw;
- }
+ if (op == SLJIT_MOV_SI && (src & SLJIT_MEM))
+ op = SLJIT_MOV_UI;
+ if (op == SLJIT_MOVU_SI && (src & SLJIT_MEM))
+ op = SLJIT_MOVU_UI;
+ if (op == SLJIT_MOV_UI && (src & SLJIT_IMM))
+ op = SLJIT_MOV_SI;
+ if (op == SLJIT_MOVU_UI && (src & SLJIT_IMM))
+ op = SLJIT_MOVU_SI;
#endif
- if (op & SLJIT_SET_O)
- FAIL_IF(push_inst(compiler, MTXER | S(ZERO_REG)));
+ }
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ else {
+ /* Most operations expect sign extended arguments. */
+ flags |= INT_DATA | SIGNED_DATA;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_si)srcw;
+ }
+#endif
+ }
- switch (GET_OPCODE(op)) {
+ switch (op) {
case SLJIT_MOV:
- return emit_op(compiler, SLJIT_MOV, inp_flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+ case SLJIT_MOV_P:
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ case SLJIT_MOV_UI:
+ case SLJIT_MOV_SI:
+#endif
+ return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
case SLJIT_MOV_UI:
- return emit_op(compiler, SLJIT_MOV_UI, inp_flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+ return EMIT_MOV(SLJIT_MOV_UI, INT_DATA, (sljit_ui));
case SLJIT_MOV_SI:
- return emit_op(compiler, SLJIT_MOV_SI, inp_flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+ return EMIT_MOV(SLJIT_MOV_SI, INT_DATA | SIGNED_DATA, (sljit_si));
+#endif
case SLJIT_MOV_UB:
- return emit_op(compiler, SLJIT_MOV_UB, inp_flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
+ return EMIT_MOV(SLJIT_MOV_UB, BYTE_DATA, (sljit_ub));
case SLJIT_MOV_SB:
- return emit_op(compiler, SLJIT_MOV_SB, inp_flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
+ return EMIT_MOV(SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA, (sljit_sb));
case SLJIT_MOV_UH:
- return emit_op(compiler, SLJIT_MOV_UH, inp_flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
+ return EMIT_MOV(SLJIT_MOV_UH, HALF_DATA, (sljit_uh));
case SLJIT_MOV_SH:
- return emit_op(compiler, SLJIT_MOV_SH, inp_flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
+ return EMIT_MOV(SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA, (sljit_sh));
case SLJIT_MOVU:
- return emit_op(compiler, SLJIT_MOV, inp_flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+ case SLJIT_MOVU_P:
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ case SLJIT_MOVU_UI:
+ case SLJIT_MOVU_SI:
+#endif
+ return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
case SLJIT_MOVU_UI:
- return emit_op(compiler, SLJIT_MOV_UI, inp_flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+ return EMIT_MOV(SLJIT_MOV_UI, INT_DATA | WRITE_BACK, (sljit_ui));
case SLJIT_MOVU_SI:
- return emit_op(compiler, SLJIT_MOV_SI, inp_flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+ return EMIT_MOV(SLJIT_MOV_SI, INT_DATA | SIGNED_DATA | WRITE_BACK, (sljit_si));
+#endif
case SLJIT_MOVU_UB:
- return emit_op(compiler, SLJIT_MOV_UB, inp_flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
+ return EMIT_MOV(SLJIT_MOV_UB, BYTE_DATA | WRITE_BACK, (sljit_ub));
case SLJIT_MOVU_SB:
- return emit_op(compiler, SLJIT_MOV_SB, inp_flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
+ return EMIT_MOV(SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA | WRITE_BACK, (sljit_sb));
case SLJIT_MOVU_UH:
- return emit_op(compiler, SLJIT_MOV_UH, inp_flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
+ return EMIT_MOV(SLJIT_MOV_UH, HALF_DATA | WRITE_BACK, (sljit_uh));
case SLJIT_MOVU_SH:
- return emit_op(compiler, SLJIT_MOV_SH, inp_flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
+ return EMIT_MOV(SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA | WRITE_BACK, (sljit_sh));
case SLJIT_NOT:
- return emit_op(compiler, SLJIT_NOT, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_NEG:
- return emit_op(compiler, SLJIT_NEG, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_NEG, flags, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_CLZ:
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- return emit_op(compiler, SLJIT_CLZ, inp_flags | (!(op & SLJIT_INT_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_INT_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
#else
- return emit_op(compiler, SLJIT_CLZ, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw);
#endif
}
return SLJIT_SUCCESS;
}
+#undef EMIT_MOV
+
#define TEST_SL_IMM(src, srcw) \
(((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)
@@ -1184,15 +1293,18 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
((src) & SLJIT_IMM)
#endif
-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 sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- int inp_flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0;
+ sljit_si flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0;
CHECK_ERROR();
check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
if ((src1 & SLJIT_IMM) && src1w == 0)
src1 = ZERO_REG;
@@ -1201,80 +1313,83 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
if (op & SLJIT_INT_OP) {
- inp_flags |= INT_DATA | SIGNED_DATA;
+ /* Most operations expect sign extended arguments. */
+ flags |= INT_DATA | SIGNED_DATA;
if (src1 & SLJIT_IMM)
- src1w = (src1w << 32) >> 32;
+ src1w = (sljit_si)(src1w);
if (src2 & SLJIT_IMM)
- src2w = (src2w << 32) >> 32;
+ src2w = (sljit_si)(src2w);
if (GET_FLAGS(op))
- inp_flags |= ALT_SIGN_EXT;
+ flags |= ALT_SIGN_EXT;
}
#endif
if (op & SLJIT_SET_O)
FAIL_IF(push_inst(compiler, MTXER | S(ZERO_REG)));
+ if (src2 == TMP_REG2)
+ flags |= ALT_KEEP_CACHE;
switch (GET_OPCODE(op)) {
case SLJIT_ADD:
if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
if (TEST_SL_IMM(src2, src2w)) {
compiler->imm = src2w & 0xffff;
- return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SL_IMM(src1, src1w)) {
compiler->imm = src1w & 0xffff;
- return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
}
if (TEST_SH_IMM(src2, src2w)) {
compiler->imm = (src2w >> 16) & 0xffff;
- return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SH_IMM(src1, src1w)) {
compiler->imm = (src1w >> 16) & 0xffff;
- return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
}
/* Range between -1 and -32768 is covered above. */
if (TEST_ADD_IMM(src2, src2w)) {
compiler->imm = src2w & 0xffffffff;
- return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_ADD_IMM(src1, src1w)) {
compiler->imm = src1w & 0xffffffff;
- return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
if (!(GET_FLAGS(op) & (SLJIT_SET_E | SLJIT_SET_O))) {
if (TEST_SL_IMM(src2, src2w)) {
compiler->imm = src2w & 0xffff;
- return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SL_IMM(src1, src1w)) {
compiler->imm = src1w & 0xffff;
- return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
- return emit_op(compiler, SLJIT_ADD, inp_flags, dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, SLJIT_ADD, flags, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_ADDC:
- return emit_op(compiler, SLJIT_ADDC, inp_flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, SLJIT_ADDC, flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUB:
if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
if (TEST_SL_IMM(src2, -src2w)) {
compiler->imm = (-src2w) & 0xffff;
- return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SL_IMM(src1, src1w)) {
compiler->imm = src1w & 0xffff;
- return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
}
if (TEST_SH_IMM(src2, -src2w)) {
compiler->imm = ((-src2w) >> 16) & 0xffff;
- return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
}
/* Range between -1 and -32768 is covered above. */
if (TEST_ADD_IMM(src2, -src2w)) {
compiler->imm = -src2w & 0xffffffff;
- return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
}
}
if (dst == SLJIT_UNUSED && (op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U)) && !(op & (SLJIT_SET_O | SLJIT_SET_C))) {
@@ -1282,55 +1397,55 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
/* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
if (TEST_SL_IMM(src2, src2w)) {
compiler->imm = src2w & 0xffff;
- return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (GET_FLAGS(op) == SLJIT_SET_E && TEST_SL_IMM(src1, src1w)) {
compiler->imm = src1w & 0xffff;
- return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
if (!(op & (SLJIT_SET_E | SLJIT_SET_S))) {
/* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
if (TEST_UL_IMM(src2, src2w)) {
compiler->imm = src2w & 0xffff;
- return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
- return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
}
if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= 0x7fff) {
compiler->imm = src2w;
- return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
- return emit_op(compiler, SLJIT_SUB, inp_flags | ((op & SLJIT_SET_U) ? ALT_FORM4 : 0) | ((op & (SLJIT_SET_E | SLJIT_SET_S)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, SLJIT_SUB, flags | ((op & SLJIT_SET_U) ? ALT_FORM4 : 0) | ((op & (SLJIT_SET_E | SLJIT_SET_S)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
}
if (!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O))) {
if (TEST_SL_IMM(src2, -src2w)) {
compiler->imm = (-src2w) & 0xffff;
- return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
}
/* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
- return emit_op(compiler, SLJIT_SUB, inp_flags | (!(op & SLJIT_SET_U) ? 0 : ALT_FORM6), dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, SLJIT_SUB, flags | (!(op & SLJIT_SET_U) ? 0 : ALT_FORM6), dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUBC:
- return emit_op(compiler, SLJIT_SUBC, inp_flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, SLJIT_SUBC, flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
case SLJIT_MUL:
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
if (op & SLJIT_INT_OP)
- inp_flags |= ALT_FORM2;
+ flags |= ALT_FORM2;
#endif
if (!GET_FLAGS(op)) {
if (TEST_SL_IMM(src2, src2w)) {
compiler->imm = src2w & 0xffff;
- return emit_op(compiler, SLJIT_MUL, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SL_IMM(src1, src1w)) {
compiler->imm = src1w & 0xffff;
- return emit_op(compiler, SLJIT_MUL, inp_flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
- return emit_op(compiler, SLJIT_MUL, inp_flags, dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_AND:
case SLJIT_OR:
@@ -1339,58 +1454,61 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
if (!GET_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
if (TEST_UL_IMM(src2, src2w)) {
compiler->imm = src2w;
- return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_UL_IMM(src1, src1w)) {
compiler->imm = src1w;
- return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
}
if (TEST_UH_IMM(src2, src2w)) {
compiler->imm = (src2w >> 16) & 0xffff;
- return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_UH_IMM(src1, src1w)) {
compiler->imm = (src1w >> 16) & 0xffff;
- return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
if (!GET_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {
if (TEST_UI_IMM(src2, src2w)) {
compiler->imm = src2w;
- return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_UI_IMM(src1, src1w)) {
compiler->imm = src1w;
- return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
- return emit_op(compiler, GET_OPCODE(op), inp_flags, dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_ASHR:
+ if (op & SLJIT_KEEP_FLAGS)
+ flags |= ALT_FORM3;
+ /* Fall through. */
case SLJIT_SHL:
case SLJIT_LSHR:
- case SLJIT_ASHR:
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
if (op & SLJIT_INT_OP)
- inp_flags |= ALT_FORM2;
+ flags |= ALT_FORM2;
#endif
if (src2 & SLJIT_IMM) {
compiler->imm = src2w;
- return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
}
- return emit_op(compiler, GET_OPCODE(op), inp_flags, dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
}
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
{
check_sljit_get_register_index(reg);
return reg_map[reg];
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, int size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_si size)
{
CHECK_ERROR();
check_sljit_emit_op_custom(compiler, instruction, size);
@@ -1403,106 +1521,77 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compile
/* Floating point operators */
/* --------------------------------------------------------------------- */
-SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
/* Always available. */
return 1;
}
-static int emit_fpu_data_transfer(struct sljit_compiler *compiler, int fpu_reg, int load, int arg, sljit_w argw)
-{
- SLJIT_ASSERT(arg & SLJIT_MEM);
-
- /* Fast loads and stores. */
- if (!(arg & 0xf0)) {
- /* Both for (arg & 0xf) == SLJIT_UNUSED and (arg & 0xf) != SLJIT_UNUSED. */
- if (argw <= SIMM_MAX && argw >= SIMM_MIN)
- return push_inst(compiler, (load ? LFD : STFD) | FD(fpu_reg) | A(arg & 0xf) | IMM(argw));
- }
+#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 6))
+#define SELECT_FOP(op, single, double) ((op & SLJIT_SINGLE_OP) ? single : double)
- if (arg & 0xf0) {
- argw &= 0x3;
- if (argw) {
-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- FAIL_IF(push_inst(compiler, RLWINM | S((arg >> 4) & 0xf) | A(TMP_REG2) | (argw << 11) | ((31 - argw) << 1)));
-#else
- FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, (arg >> 4) & 0xf, argw, 63 - argw, 1)));
-#endif
- return push_inst(compiler, (load ? LFDX : STFDX) | FD(fpu_reg) | A(arg & 0xf) | B(TMP_REG2));
- }
- return push_inst(compiler, (load ? LFDX : STFDX) | FD(fpu_reg) | A(arg & 0xf) | B((arg >> 4) & 0xf));
- }
-
- /* Use cache. */
- if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)
- return push_inst(compiler, (load ? LFD : STFD) | FD(fpu_reg) | A(TMP_REG3) | IMM(argw - compiler->cache_argw));
-
- /* Put value to cache. */
- compiler->cache_arg = arg;
- compiler->cache_argw = argw;
-
- FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
- if (!(arg & 0xf))
- return push_inst(compiler, (load ? LFDX : STFDX) | FD(fpu_reg) | A(0) | B(TMP_REG3));
- return push_inst(compiler, (load ? LFDUX : STFDUX) | FD(fpu_reg) | A(TMP_REG3) | B(arg & 0xf));
-}
-
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- int dst_fr;
+ sljit_si dst_fr;
CHECK_ERROR();
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
+ SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- if (GET_OPCODE(op) == SLJIT_FCMP) {
- if (dst > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, dst, dstw));
+ if (GET_OPCODE(op) == SLJIT_CMPD) {
+ if (dst > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, dst, dstw, src, srcw));
dst = TMP_FREG1;
}
- if (src > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src, srcw));
+
+ if (src > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src, srcw, 0, 0));
src = TMP_FREG2;
}
+
return push_inst(compiler, FCMPU | CRD(4) | FA(dst) | FB(src));
}
- dst_fr = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
+ dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
- if (src > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, dst_fr, 1, src, srcw));
+ if (src > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_fr, src, srcw, dst, dstw));
src = dst_fr;
}
- switch (op) {
- case SLJIT_FMOV:
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOVD:
if (src != dst_fr && dst_fr != TMP_FREG1)
FAIL_IF(push_inst(compiler, FMR | FD(dst_fr) | FB(src)));
break;
- case SLJIT_FNEG:
+ case SLJIT_NEGD:
FAIL_IF(push_inst(compiler, FNEG | FD(dst_fr) | FB(src)));
break;
- case SLJIT_FABS:
+ case SLJIT_ABSD:
FAIL_IF(push_inst(compiler, FABS | FD(dst_fr) | FB(src)));
break;
}
- if (dst_fr == TMP_FREG1)
- FAIL_IF(emit_fpu_data_transfer(compiler, src, 0, dst, dstw));
+ if (dst_fr == TMP_FREG1) {
+ if (GET_OPCODE(op) == SLJIT_MOVD)
+ dst_fr = src;
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_fr, dst, dstw, 0, 0));
+ }
return SLJIT_SUCCESS;
}
-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)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- int dst_fr;
+ sljit_si dst_fr, flags = 0;
CHECK_ERROR();
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
@@ -1510,78 +1599,100 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, in
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- dst_fr = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
+ dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG2 : dst;
- if (src2 > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w));
- src2 = TMP_FREG2;
+ if (src1 > SLJIT_FLOAT_REG6) {
+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
+ FAIL_IF(compiler->error);
+ src1 = TMP_FREG1;
+ } else
+ flags |= ALT_FORM1;
}
- if (src1 > SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w));
- src1 = TMP_FREG1;
+ if (src2 > SLJIT_FLOAT_REG6) {
+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
+ FAIL_IF(compiler->error);
+ src2 = TMP_FREG2;
+ } else
+ flags |= ALT_FORM2;
}
- switch (op) {
- case SLJIT_FADD:
- FAIL_IF(push_inst(compiler, FADD | FD(dst_fr) | FA(src1) | FB(src2)));
+ if ((flags & (ALT_FORM1 | ALT_FORM2)) == (ALT_FORM1 | ALT_FORM2)) {
+ if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
+ }
+ else {
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
+ }
+ }
+ else if (flags & ALT_FORM1)
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
+ else if (flags & ALT_FORM2)
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
+
+ if (flags & ALT_FORM1)
+ src1 = TMP_FREG1;
+ if (flags & ALT_FORM2)
+ src2 = TMP_FREG2;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADDD:
+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_fr) | FA(src1) | FB(src2)));
break;
- case SLJIT_FSUB:
- FAIL_IF(push_inst(compiler, FSUB | FD(dst_fr) | FA(src1) | FB(src2)));
+ case SLJIT_SUBD:
+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_fr) | FA(src1) | FB(src2)));
break;
- case SLJIT_FMUL:
- FAIL_IF(push_inst(compiler, FMUL | FD(dst_fr) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
+ case SLJIT_MULD:
+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_fr) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
break;
- case SLJIT_FDIV:
- FAIL_IF(push_inst(compiler, FDIV | FD(dst_fr) | FA(src1) | FB(src2)));
+ case SLJIT_DIVD:
+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_fr) | FA(src1) | FB(src2)));
break;
}
- if (dst_fr == TMP_FREG1)
- FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 0, dst, dstw));
+ if (dst_fr == TMP_FREG2)
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
return SLJIT_SUCCESS;
}
+#undef FLOAT_DATA
+#undef SELECT_FOP
+
/* --------------------------------------------------------------------- */
/* Other instructions */
/* --------------------------------------------------------------------- */
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
CHECK_ERROR();
- check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
-
- compiler->temporaries = temporaries;
- compiler->saveds = saveds;
+ check_sljit_emit_fast_enter(compiler, dst, dstw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
- compiler->has_locals = local_size > 0;
-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- compiler->local_size = (2 + saveds + 2) * sizeof(sljit_w) + local_size;
-#else
- compiler->local_size = (2 + saveds + 7 + 8) * sizeof(sljit_w) + local_size;
-#endif
- compiler->local_size = (compiler->local_size + 15) & ~0xf;
+ /* For UNUSED dst. Uncommon, but possible. */
+ if (dst == SLJIT_UNUSED)
+ return SLJIT_SUCCESS;
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
+ if (dst <= ZERO_REG)
return push_inst(compiler, MFLR | D(dst));
- else if (dst & SLJIT_MEM) {
- FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2)));
- return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
- }
- return SLJIT_SUCCESS;
+ /* Memory. */
+ FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2)));
+ return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
CHECK_ERROR();
check_sljit_emit_fast_return(compiler, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
- if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+ if (src <= ZERO_REG)
FAIL_IF(push_inst(compiler, MTLR | S(src)));
else {
if (src & SLJIT_MEM)
@@ -1613,7 +1724,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
-static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, int type)
+static sljit_ins get_bo_bi_flags(sljit_si type)
{
switch (type) {
case SLJIT_C_EQUAL:
@@ -1664,10 +1775,10 @@ static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, int type)
case SLJIT_C_FLOAT_NOT_EQUAL:
return (4 << 21) | ((4 + 2) << 16);
- case SLJIT_C_FLOAT_NAN:
+ case SLJIT_C_FLOAT_UNORDERED:
return (12 << 21) | ((4 + 3) << 16);
- case SLJIT_C_FLOAT_NOT_NAN:
+ case SLJIT_C_FLOAT_ORDERED:
return (4 << 21) | ((4 + 3) << 16);
default:
@@ -1676,7 +1787,7 @@ static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, int type)
}
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
{
struct sljit_jump *jump;
sljit_ins bo_bi_flags;
@@ -1684,7 +1795,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
CHECK_ERROR_PTR();
check_sljit_emit_jump(compiler, type);
- bo_bi_flags = get_bo_bi_flags(compiler, type & 0xff);
+ bo_bi_flags = get_bo_bi_flags(type & 0xff);
if (!bo_bi_flags)
return NULL;
@@ -1704,19 +1815,16 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
return jump;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
{
- sljit_ins bo_bi_flags;
struct sljit_jump *jump = NULL;
- int src_r;
+ sljit_si src_r;
CHECK_ERROR();
check_sljit_emit_ijump(compiler, type, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
- bo_bi_flags = get_bo_bi_flags(compiler, type);
- FAIL_IF(!bo_bi_flags);
-
- if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+ if (src <= ZERO_REG)
src_r = src;
else if (src & SLJIT_IMM) {
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -1735,7 +1843,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, i
FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));
if (jump)
jump->addr = compiler->size;
- return push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0));
+ return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));
}
/* Get a bit from CR, all other bits are zeroed. */
@@ -1746,17 +1854,37 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, i
#define INVERT_BIT(dst) \
FAIL_IF(push_inst(compiler, XORI | S(dst) | A(dst) | 0x1));
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw,
+ sljit_si type)
{
- int reg;
+ sljit_si reg, input_flags;
+ sljit_si flags = GET_ALL_FLAGS(op);
CHECK_ERROR();
- check_sljit_emit_cond_value(compiler, op, dst, dstw, type);
+ check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
- reg = (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2;
+ op = GET_OPCODE(op);
+ reg = (op < SLJIT_ADD && dst <= ZERO_REG) ? dst : TMP_REG2;
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ input_flags = (flags & SLJIT_INT_OP) ? INT_DATA : WORD_DATA;
+#else
+ input_flags = WORD_DATA;
+#endif
+ FAIL_IF(emit_op_mem2(compiler, input_flags | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
+ src = TMP_REG1;
+ srcw = 0;
+ }
switch (type) {
case SLJIT_C_EQUAL:
@@ -1828,11 +1956,11 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compil
INVERT_BIT(reg);
break;
- case SLJIT_C_FLOAT_NAN:
+ case SLJIT_C_FLOAT_UNORDERED:
GET_CR_BIT(4 + 3, reg);
break;
- case SLJIT_C_FLOAT_NOT_NAN:
+ case SLJIT_C_FLOAT_ORDERED:
GET_CR_BIT(4 + 3, reg);
INVERT_BIT(reg);
break;
@@ -1842,27 +1970,41 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compil
break;
}
- if (GET_OPCODE(op) == SLJIT_OR)
- return emit_op(compiler, GET_OPCODE(op), GET_FLAGS(op) ? ALT_SET_FLAGS : 0, dst, dstw, dst, dstw, TMP_REG2, 0);
+ if (op < SLJIT_ADD) {
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (op == SLJIT_MOV)
+ input_flags = WORD_DATA;
+ else {
+ op = SLJIT_MOV_UI;
+ input_flags = INT_DATA;
+ }
+#else
+ op = SLJIT_MOV;
+ input_flags = WORD_DATA;
+#endif
+ return (reg == TMP_REG2) ? emit_op(compiler, op, input_flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0) : SLJIT_SUCCESS;
+ }
- if (reg == TMP_REG2)
- return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
- return SLJIT_SUCCESS;
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->skip_checks = 1;
+#endif
+ return sljit_emit_op2(compiler, op | flags, dst, dstw, src, srcw, TMP_REG2, 0);
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;
- int reg;
+ sljit_si reg;
CHECK_ERROR_PTR();
check_sljit_emit_const(compiler, dst, dstw, init_value);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2;
+ reg = (dst <= ZERO_REG) ? dst : TMP_REG2;
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
diff --git a/src/3rdparty/pcre/sljit/sljitNativeSPARC_32.c b/src/3rdparty/pcre/sljit/sljitNativeSPARC_32.c
new file mode 100644
index 0000000000..80479bfe2b
--- /dev/null
+++ b/src/3rdparty/pcre/sljit/sljitNativeSPARC_32.c
@@ -0,0 +1,164 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright 2009-2012 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.
+ */
+
+static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sljit_sw imm)
+{
+ if (imm <= SIMM_MAX && imm >= SIMM_MIN)
+ return push_inst(compiler, OR | D(dst) | S1(0) | IMM(imm), DR(dst));
+
+ FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((imm >> 10) & 0x3fffff), DR(dst)));
+ return (imm & 0x3ff) ? push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (imm & 0x3ff), DR(dst)) : SLJIT_SUCCESS;
+}
+
+#define ARG2(flags, src2) ((flags & SRC2_IMM) ? IMM(src2) : S2(src2))
+
+static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
+ sljit_si dst, sljit_si src1, sljit_sw src2)
+{
+ SLJIT_COMPILE_ASSERT(ICC_IS_SET == SET_FLAGS, icc_is_set_and_set_flags_must_be_the_same);
+
+ switch (op) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_UI:
+ case SLJIT_MOV_SI:
+ case SLJIT_MOV_P:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if (dst != src2)
+ return push_inst(compiler, OR | D(dst) | S1(0) | S2(src2), DR(dst));
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_UB:
+ case SLJIT_MOV_SB:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_UB)
+ return push_inst(compiler, AND | D(dst) | S1(src2) | IMM(0xff), DR(dst));
+ FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(24), DR(dst)));
+ return push_inst(compiler, SRA | D(dst) | S1(dst) | IMM(24), DR(dst));
+ }
+ else if (dst != src2)
+ SLJIT_ASSERT_STOP();
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_UH:
+ case SLJIT_MOV_SH:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(16), DR(dst)));
+ return push_inst(compiler, (op == SLJIT_MOV_SH ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst));
+ }
+ else if (dst != src2)
+ SLJIT_ASSERT_STOP();
+ return SLJIT_SUCCESS;
+
+ case SLJIT_NOT:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ return push_inst(compiler, XNOR | (flags & SET_FLAGS) | D(dst) | S1(0) | S2(src2), DR(dst) | (flags & SET_FLAGS));
+
+ case SLJIT_CLZ:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ /* sparc 32 does not support SLJIT_KEEP_FLAGS. Not sure I can fix this. */
+ FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS));
+ FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS | (flags & SET_FLAGS)));
+ FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst)));
+
+ /* Loop. */
+ FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS));
+ FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS));
+ return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS | (flags & SET_FLAGS));
+
+ case SLJIT_ADD:
+ return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+
+ case SLJIT_ADDC:
+ return push_inst(compiler, ADDC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+
+ case SLJIT_SUB:
+ return push_inst(compiler, SUB | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+
+ case SLJIT_SUBC:
+ return push_inst(compiler, SUBC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+
+ case SLJIT_MUL:
+ FAIL_IF(push_inst(compiler, SMUL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
+ if (!(flags & SET_FLAGS))
+ return SLJIT_SUCCESS;
+ FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(dst) | IMM(31), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, RDY | D(TMP_REG4), DR(TMP_REG4)));
+ return push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(TMP_REG4), MOVABLE_INS | SET_FLAGS);
+
+ case SLJIT_AND:
+ return push_inst(compiler, AND | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+
+ case SLJIT_OR:
+ return push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+
+ case SLJIT_XOR:
+ return push_inst(compiler, XOR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+
+ case SLJIT_SHL:
+ FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
+ return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
+
+ case SLJIT_LSHR:
+ FAIL_IF(push_inst(compiler, SRL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
+ return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
+
+ case SLJIT_ASHR:
+ FAIL_IF(push_inst(compiler, SRA | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
+ return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
+ }
+
+ SLJIT_ASSERT_STOP();
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
+{
+ FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((init_value >> 10) & 0x3fffff), DR(dst)));
+ return push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (init_value & 0x3ff), DR(dst));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+{
+ sljit_ins *inst = (sljit_ins*)addr;
+
+ inst[0] = (inst[0] & 0xffc00000) | ((new_addr >> 10) & 0x3fffff);
+ inst[1] = (inst[1] & 0xfffffc00) | (new_addr & 0x3ff);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+{
+ sljit_ins *inst = (sljit_ins*)addr;
+
+ inst[0] = (inst[0] & 0xffc00000) | ((new_constant >> 10) & 0x3fffff);
+ inst[1] = (inst[1] & 0xfffffc00) | (new_constant & 0x3ff);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c b/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c
new file mode 100644
index 0000000000..c6522be2a7
--- /dev/null
+++ b/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c
@@ -0,0 +1,1348 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright 2009-2012 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.
+ */
+
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
+{
+ return "SPARC" SLJIT_CPUINFO;
+}
+
+/* Length of an instruction word
+ Both for sparc-32 and sparc-64 */
+typedef sljit_ui sljit_ins;
+
+static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
+{
+ if (SLJIT_UNLIKELY(from == to))
+ return;
+
+ do {
+ __asm__ volatile (
+ "flush %0\n"
+ : : "r"(from)
+ );
+ /* Operates at least on doubleword. */
+ from += 2;
+ } while (from < to);
+
+ if (from == to) {
+ /* Flush the last word. */
+ to --;
+ __asm__ volatile (
+ "flush %0\n"
+ : : "r"(to)
+ );
+ }
+}
+
+/* TMP_REG2 is not used by getput_arg */
+#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
+#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
+#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
+#define TMP_REG4 (SLJIT_NO_REGISTERS + 4)
+#define LINK_REG (SLJIT_NO_REGISTERS + 5)
+
+#define TMP_FREG1 (0)
+#define TMP_FREG2 ((SLJIT_FLOAT_REG6 + 1) << 1)
+
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 7] = {
+ 0, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 14, 1, 24, 25, 26, 15
+};
+
+/* --------------------------------------------------------------------- */
+/* Instrucion forms */
+/* --------------------------------------------------------------------- */
+
+#define D(d) (reg_map[d] << 25)
+#define DA(d) ((d) << 25)
+#define S1(s1) (reg_map[s1] << 14)
+#define S2(s2) (reg_map[s2])
+#define S1A(s1) ((s1) << 14)
+#define S2A(s2) (s2)
+#define IMM_ARG 0x2000
+#define DOP(op) ((op) << 5)
+#define IMM(imm) (((imm) & 0x1fff) | IMM_ARG)
+
+#define DR(dr) (reg_map[dr])
+#define OPC1(opcode) ((opcode) << 30)
+#define OPC2(opcode) ((opcode) << 22)
+#define OPC3(opcode) ((opcode) << 19)
+#define SET_FLAGS OPC3(0x10)
+
+#define ADD (OPC1(0x2) | OPC3(0x00))
+#define ADDC (OPC1(0x2) | OPC3(0x08))
+#define AND (OPC1(0x2) | OPC3(0x01))
+#define ANDN (OPC1(0x2) | OPC3(0x05))
+#define CALL (OPC1(0x1))
+#define FABSS (OPC1(0x2) | OPC3(0x34) | DOP(0x09))
+#define FADDD (OPC1(0x2) | OPC3(0x34) | DOP(0x42))
+#define FADDS (OPC1(0x2) | OPC3(0x34) | DOP(0x41))
+#define FCMPD (OPC1(0x2) | OPC3(0x35) | DOP(0x52))
+#define FCMPS (OPC1(0x2) | OPC3(0x35) | DOP(0x51))
+#define FDIVD (OPC1(0x2) | OPC3(0x34) | DOP(0x4e))
+#define FDIVS (OPC1(0x2) | OPC3(0x34) | DOP(0x4d))
+#define FMOVS (OPC1(0x2) | OPC3(0x34) | DOP(0x01))
+#define FMULD (OPC1(0x2) | OPC3(0x34) | DOP(0x4a))
+#define FMULS (OPC1(0x2) | OPC3(0x34) | DOP(0x49))
+#define FNEGS (OPC1(0x2) | OPC3(0x34) | DOP(0x05))
+#define FSUBD (OPC1(0x2) | OPC3(0x34) | DOP(0x46))
+#define FSUBS (OPC1(0x2) | OPC3(0x34) | DOP(0x45))
+#define JMPL (OPC1(0x2) | OPC3(0x38))
+#define NOP (OPC1(0x0) | OPC2(0x04))
+#define OR (OPC1(0x2) | OPC3(0x02))
+#define ORN (OPC1(0x2) | OPC3(0x06))
+#define RDY (OPC1(0x2) | OPC3(0x28) | S1A(0))
+#define RESTORE (OPC1(0x2) | OPC3(0x3d))
+#define SAVE (OPC1(0x2) | OPC3(0x3c))
+#define SETHI (OPC1(0x0) | OPC2(0x04))
+#define SLL (OPC1(0x2) | OPC3(0x25))
+#define SLLX (OPC1(0x2) | OPC3(0x25) | (1 << 12))
+#define SRA (OPC1(0x2) | OPC3(0x27))
+#define SRAX (OPC1(0x2) | OPC3(0x27) | (1 << 12))
+#define SRL (OPC1(0x2) | OPC3(0x26))
+#define SRLX (OPC1(0x2) | OPC3(0x26) | (1 << 12))
+#define SUB (OPC1(0x2) | OPC3(0x04))
+#define SUBC (OPC1(0x2) | OPC3(0x0c))
+#define TA (OPC1(0x2) | OPC3(0x3a) | (8 << 25))
+#define WRY (OPC1(0x2) | OPC3(0x30) | DA(0))
+#define XOR (OPC1(0x2) | OPC3(0x03))
+#define XNOR (OPC1(0x2) | OPC3(0x07))
+
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+#define MAX_DISP (0x1fffff)
+#define MIN_DISP (-0x200000)
+#define DISP_MASK (0x3fffff)
+
+#define BICC (OPC1(0x0) | OPC2(0x2))
+#define FBFCC (OPC1(0x0) | OPC2(0x6))
+#define SLL_W SLL
+#define SDIV (OPC1(0x2) | OPC3(0x0f))
+#define SMUL (OPC1(0x2) | OPC3(0x0b))
+#define UDIV (OPC1(0x2) | OPC3(0x0e))
+#define UMUL (OPC1(0x2) | OPC3(0x0a))
+#else
+#define SLL_W SLLX
+#endif
+
+#define SIMM_MAX (0x0fff)
+#define SIMM_MIN (-0x1000)
+
+/* dest_reg is the absolute name of the register
+ Useful for reordering instructions in the delay slot. */
+static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_si delay_slot)
+{
+ sljit_ins *ptr;
+ SLJIT_ASSERT((delay_slot & DST_INS_MASK) == UNMOVABLE_INS
+ || (delay_slot & DST_INS_MASK) == MOVABLE_INS
+ || (delay_slot & DST_INS_MASK) == ((ins >> 25) & 0x1f));
+ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ *ptr = ins;
+ compiler->size++;
+ compiler->delay_slot = delay_slot;
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+{
+ sljit_sw diff;
+ sljit_uw target_addr;
+ sljit_ins *inst;
+ sljit_ins saved_inst;
+
+ if (jump->flags & SLJIT_REWRITABLE_JUMP)
+ return code_ptr;
+
+ if (jump->flags & JUMP_ADDR)
+ target_addr = jump->u.target;
+ else {
+ SLJIT_ASSERT(jump->flags & JUMP_LABEL);
+ target_addr = (sljit_uw)(code + jump->u.label->size);
+ }
+ inst = (sljit_ins*)jump->addr;
+
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ if (jump->flags & IS_CALL) {
+ /* Call is always patchable on sparc 32. */
+ jump->flags |= PATCH_CALL;
+ if (jump->flags & IS_MOVABLE) {
+ inst[0] = inst[-1];
+ inst[-1] = CALL;
+ jump->addr -= sizeof(sljit_ins);
+ return inst;
+ }
+ inst[0] = CALL;
+ inst[1] = NOP;
+ return inst + 1;
+ }
+#else
+ /* Both calls and BPr instructions shall not pass this point. */
+#error "Implementation required"
+#endif
+
+ if (jump->flags & IS_COND)
+ inst--;
+
+ if (jump->flags & IS_MOVABLE) {
+ diff = ((sljit_sw)target_addr - (sljit_sw)(inst - 1)) >> 2;
+ if (diff <= MAX_DISP && diff >= MIN_DISP) {
+ jump->flags |= PATCH_B;
+ inst--;
+ if (jump->flags & IS_COND) {
+ saved_inst = inst[0];
+ inst[0] = inst[1] ^ (1 << 28);
+ inst[1] = saved_inst;
+ } else {
+ inst[1] = inst[0];
+ inst[0] = BICC | DA(0x8);
+ }
+ jump->addr = (sljit_uw)inst;
+ return inst + 1;
+ }
+ }
+
+ diff = ((sljit_sw)target_addr - (sljit_sw)(inst)) >> 2;
+ if (diff <= MAX_DISP && diff >= MIN_DISP) {
+ jump->flags |= PATCH_B;
+ if (jump->flags & IS_COND)
+ inst[0] ^= (1 << 28);
+ else
+ inst[0] = BICC | DA(0x8);
+ inst[1] = NOP;
+ jump->addr = (sljit_uw)inst;
+ return inst + 1;
+ }
+
+ return code_ptr;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
+{
+ struct sljit_memory_fragment *buf;
+ sljit_ins *code;
+ sljit_ins *code_ptr;
+ sljit_ins *buf_ptr;
+ sljit_ins *buf_end;
+ sljit_uw word_count;
+ sljit_uw addr;
+
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+
+ CHECK_ERROR_PTR();
+ check_sljit_generate_code(compiler);
+ reverse_buf(compiler);
+
+ code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins));
+ PTR_FAIL_WITH_EXEC_IF(code);
+ buf = compiler->buf;
+
+ code_ptr = code;
+ word_count = 0;
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ do {
+ buf_ptr = (sljit_ins*)buf->memory;
+ buf_end = buf_ptr + (buf->used_size >> 2);
+ do {
+ *code_ptr = *buf_ptr++;
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ /* These structures are ordered by their address. */
+ if (label && label->size == word_count) {
+ /* Just recording the address. */
+ label->addr = (sljit_uw)code_ptr;
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+ if (jump && jump->addr == word_count) {
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ jump->addr = (sljit_uw)(code_ptr - 3);
+#else
+ jump->addr = (sljit_uw)(code_ptr - 6);
+#endif
+ code_ptr = optimize_jump(jump, code_ptr, code);
+ jump = jump->next;
+ }
+ if (const_ && const_->addr == word_count) {
+ /* Just recording the address. */
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ }
+ code_ptr ++;
+ word_count ++;
+ } while (buf_ptr < buf_end);
+
+ buf = buf->next;
+ } while (buf);
+
+ if (label && label->size == word_count) {
+ label->addr = (sljit_uw)code_ptr;
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+
+ SLJIT_ASSERT(!label);
+ SLJIT_ASSERT(!jump);
+ SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(code_ptr - code <= (sljit_si)compiler->size);
+
+ jump = compiler->jumps;
+ while (jump) {
+ do {
+ addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
+ buf_ptr = (sljit_ins*)jump->addr;
+
+ if (jump->flags & PATCH_CALL) {
+ addr = (sljit_sw)(addr - jump->addr) >> 2;
+ SLJIT_ASSERT((sljit_sw)addr <= 0x1fffffff && (sljit_sw)addr >= -0x20000000);
+ buf_ptr[0] = CALL | (addr & 0x3fffffff);
+ break;
+ }
+ if (jump->flags & PATCH_B) {
+ addr = (sljit_sw)(addr - jump->addr) >> 2;
+ SLJIT_ASSERT((sljit_sw)addr <= MAX_DISP && (sljit_sw)addr >= MIN_DISP);
+ buf_ptr[0] = (buf_ptr[0] & ~DISP_MASK) | (addr & DISP_MASK);
+ break;
+ }
+
+ /* Set the fields of immediate loads. */
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ buf_ptr[0] = (buf_ptr[0] & 0xffc00000) | ((addr >> 10) & 0x3fffff);
+ buf_ptr[1] = (buf_ptr[1] & 0xfffffc00) | (addr & 0x3ff);
+#else
+#error "Implementation required"
+#endif
+ } while (0);
+ jump = jump->next;
+ }
+
+
+ compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_size = compiler->size * sizeof(sljit_ins);
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+ return code;
+}
+
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
+/* Creates an index in data_transfer_insts array. */
+#define LOAD_DATA 0x01
+#define WORD_DATA 0x00
+#define BYTE_DATA 0x02
+#define HALF_DATA 0x04
+#define INT_DATA 0x06
+#define SIGNED_DATA 0x08
+/* Separates integer and floating point registers */
+#define GPR_REG 0x0f
+#define DOUBLE_DATA 0x10
+
+#define MEM_MASK 0x1f
+
+#define WRITE_BACK 0x00020
+#define ARG_TEST 0x00040
+#define ALT_KEEP_CACHE 0x00080
+#define CUMULATIVE_OP 0x00100
+#define IMM_OP 0x00200
+#define SRC2_IMM 0x00400
+
+#define REG_DEST 0x00800
+#define REG2_SOURCE 0x01000
+#define SLOW_SRC1 0x02000
+#define SLOW_SRC2 0x04000
+#define SLOW_DEST 0x08000
+
+/* SET_FLAGS (0x10 << 19) also belong here! */
+
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+#include "sljitNativeSPARC_32.c"
+#else
+#include "sljitNativeSPARC_64.c"
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
+{
+ CHECK_ERROR();
+ check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
+
+ compiler->scratches = scratches;
+ compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
+
+ local_size += 23 * sizeof(sljit_sw);
+ local_size = (local_size + 7) & ~0x7;
+ compiler->local_size = local_size;
+
+ if (local_size <= SIMM_MAX) {
+ FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_LOCALS_REG) | S1(SLJIT_LOCALS_REG) | IMM(-local_size), UNMOVABLE_INS));
+ }
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, -local_size));
+ FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_LOCALS_REG) | S1(SLJIT_LOCALS_REG) | S2(TMP_REG1), UNMOVABLE_INS));
+ }
+
+ if (args >= 1)
+ FAIL_IF(push_inst(compiler, OR | D(SLJIT_SAVED_REG1) | S1(0) | S2A(24), DR(SLJIT_SAVED_REG1)));
+ if (args >= 2)
+ FAIL_IF(push_inst(compiler, OR | D(SLJIT_SAVED_REG2) | S1(0) | S2A(25), DR(SLJIT_SAVED_REG2)));
+ if (args >= 3)
+ FAIL_IF(push_inst(compiler, OR | D(SLJIT_SAVED_REG3) | S1(0) | S2A(26), DR(SLJIT_SAVED_REG3)));
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
+{
+ CHECK_ERROR_VOID();
+ check_sljit_set_context(compiler, args, scratches, saveds, local_size);
+
+ compiler->scratches = scratches;
+ compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
+
+ local_size += 23 * sizeof(sljit_sw);
+ compiler->local_size = (local_size + 7) & ~0x7;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ check_sljit_emit_return(compiler, op, src, srcw);
+
+ if (op != SLJIT_MOV || !(src <= TMP_REG3)) {
+ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+ src = SLJIT_SCRATCH_REG1;
+ }
+
+ FAIL_IF(push_inst(compiler, JMPL | D(0) | S1A(31) | IMM(8), UNMOVABLE_INS));
+ return push_inst(compiler, RESTORE | D(SLJIT_SCRATCH_REG1) | S1(src) | S2(0), UNMOVABLE_INS);
+}
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+#define ARCH_32_64(a, b) a
+#else
+#define ARCH_32_64(a, b) b
+#endif
+
+static SLJIT_CONST sljit_ins data_transfer_insts[16 + 4] = {
+/* u w s */ ARCH_32_64(OPC1(3) | OPC3(0x04) /* stw */, OPC1(3) | OPC3(0x0e) /* stx */),
+/* u w l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x0b) /* ldx */),
+/* u b s */ OPC1(3) | OPC3(0x05) /* stb */,
+/* u b l */ OPC1(3) | OPC3(0x01) /* ldub */,
+/* u h s */ OPC1(3) | OPC3(0x06) /* sth */,
+/* u h l */ OPC1(3) | OPC3(0x02) /* lduh */,
+/* u i s */ OPC1(3) | OPC3(0x04) /* stw */,
+/* u i l */ OPC1(3) | OPC3(0x00) /* lduw */,
+
+/* s w s */ ARCH_32_64(OPC1(3) | OPC3(0x04) /* stw */, OPC1(3) | OPC3(0x0e) /* stx */),
+/* s w l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x0b) /* ldx */),
+/* s b s */ OPC1(3) | OPC3(0x05) /* stb */,
+/* s b l */ OPC1(3) | OPC3(0x09) /* ldsb */,
+/* s h s */ OPC1(3) | OPC3(0x06) /* sth */,
+/* s h l */ OPC1(3) | OPC3(0x0a) /* ldsh */,
+/* s i s */ OPC1(3) | OPC3(0x04) /* stw */,
+/* s i l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x08) /* ldsw */),
+
+/* d s */ OPC1(3) | OPC3(0x27),
+/* d l */ OPC1(3) | OPC3(0x23),
+/* s s */ OPC1(3) | OPC3(0x24),
+/* s l */ OPC1(3) | OPC3(0x20),
+};
+
+#undef ARCH_32_64
+
+/* Can perform an operation using at most 1 instruction. */
+static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+{
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+
+ if (!(flags & WRITE_BACK) || !(arg & 0xf)) {
+ if ((!(arg & 0xf0) && argw <= SIMM_MAX && argw >= SIMM_MIN)
+ || ((arg & 0xf0) && (argw & 0x3) == 0)) {
+ /* Works for both absoulte and relative addresses (immediate case). */
+ if (SLJIT_UNLIKELY(flags & ARG_TEST))
+ return 1;
+ FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK]
+ | ((flags & MEM_MASK) <= GPR_REG ? D(reg) : DA(reg))
+ | S1(arg & 0xf) | ((arg & 0xf0) ? S2((arg >> 4) & 0xf) : IMM(argw)),
+ ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* See getput_arg below.
+ Note: can_cache is called only for binary operators. Those
+ operators always uses word arguments without write back. */
+static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+{
+ SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
+
+ /* Simple operation except for updates. */
+ if (arg & 0xf0) {
+ argw &= 0x3;
+ SLJIT_ASSERT(argw);
+ next_argw &= 0x3;
+ if ((arg & 0xf0) == (next_arg & 0xf0) && argw == next_argw)
+ return 1;
+ return 0;
+ }
+
+ if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN))
+ return 1;
+ return 0;
+}
+
+/* Emit the necessary instructions. See can_cache above. */
+static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+{
+ sljit_si base, arg2, delay_slot;
+ sljit_ins dest;
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+ if (!(next_arg & SLJIT_MEM)) {
+ next_arg = 0;
+ next_argw = 0;
+ }
+
+ base = arg & 0xf;
+ if (SLJIT_UNLIKELY(arg & 0xf0)) {
+ argw &= 0x3;
+ SLJIT_ASSERT(argw != 0);
+
+ /* Using the cache. */
+ if (((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) && (argw == compiler->cache_argw))
+ arg2 = TMP_REG3;
+ else {
+ if ((arg & 0xf0) == (next_arg & 0xf0) && argw == (next_argw & 0x3)) {
+ compiler->cache_arg = SLJIT_MEM | (arg & 0xf0);
+ compiler->cache_argw = argw;
+ arg2 = TMP_REG3;
+ }
+ else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base && (reg << 4) != (arg & 0xf0))
+ arg2 = reg;
+ else /* It must be a mov operation, so tmp1 must be free to use. */
+ arg2 = TMP_REG1;
+ FAIL_IF(push_inst(compiler, SLL_W | D(arg2) | S1((arg >> 4) & 0xf) | IMM_ARG | argw, DR(arg2)));
+ }
+ }
+ else {
+ /* Using the cache. */
+ if ((compiler->cache_arg == SLJIT_MEM) && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) {
+ if (argw != compiler->cache_argw) {
+ FAIL_IF(push_inst(compiler, ADD | D(TMP_REG3) | S1(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
+ compiler->cache_argw = argw;
+ }
+ arg2 = TMP_REG3;
+ } else {
+ if ((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN) {
+ compiler->cache_arg = SLJIT_MEM;
+ compiler->cache_argw = argw;
+ arg2 = TMP_REG3;
+ }
+ else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base)
+ arg2 = reg;
+ else /* It must be a mov operation, so tmp1 must be free to use. */
+ arg2 = TMP_REG1;
+ FAIL_IF(load_immediate(compiler, arg2, argw));
+ }
+ }
+
+ dest = ((flags & MEM_MASK) <= GPR_REG ? D(reg) : DA(reg));
+ delay_slot = ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS;
+ if (!base)
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(arg2) | IMM(0), delay_slot);
+ if (!(flags & WRITE_BACK))
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot);
+ FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot));
+ return push_inst(compiler, ADD | D(base) | S1(base) | S2(arg2), DR(base));
+}
+
+static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+{
+ if (getput_arg_fast(compiler, flags, reg, arg, argw))
+ return compiler->error;
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
+}
+
+static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
+{
+ if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
+ return compiler->error;
+ return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+}
+
+static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
+{
+ /* arg1 goes to TMP_REG1 or src reg
+ arg2 goes to TMP_REG2, imm or src reg
+ TMP_REG3 can be used for caching
+ result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
+ sljit_si dst_r = TMP_REG2;
+ sljit_si src1_r;
+ sljit_sw src2_r = 0;
+ sljit_si sugg_src2_r = TMP_REG2;
+
+ if (!(flags & ALT_KEEP_CACHE)) {
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ }
+
+ if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ }
+ else if (dst <= TMP_REG3) {
+ dst_r = dst;
+ flags |= REG_DEST;
+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+ sugg_src2_r = dst_r;
+ }
+ else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
+ flags |= SLOW_DEST;
+
+ if (flags & IMM_OP) {
+ if ((src2 & SLJIT_IMM) && src2w) {
+ if (src2w <= SIMM_MAX && src2w >= SIMM_MIN) {
+ flags |= SRC2_IMM;
+ src2_r = src2w;
+ }
+ }
+ if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) {
+ if (src1w <= SIMM_MAX && src1w >= SIMM_MIN) {
+ flags |= SRC2_IMM;
+ src2_r = src1w;
+
+ /* And swap arguments. */
+ src1 = src2;
+ src1w = src2w;
+ src2 = SLJIT_IMM;
+ /* src2w = src2_r unneeded. */
+ }
+ }
+ }
+
+ /* Source 1. */
+ if (src1 <= TMP_REG3)
+ src1_r = src1;
+ else if (src1 & SLJIT_IMM) {
+ if (src1w) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ src1_r = TMP_REG1;
+ }
+ else
+ src1_r = 0;
+ }
+ else {
+ if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w))
+ FAIL_IF(compiler->error);
+ else
+ flags |= SLOW_SRC1;
+ src1_r = TMP_REG1;
+ }
+
+ /* Source 2. */
+ if (src2 <= TMP_REG3) {
+ src2_r = src2;
+ flags |= REG2_SOURCE;
+ if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+ dst_r = src2_r;
+ }
+ else if (src2 & SLJIT_IMM) {
+ if (!(flags & SRC2_IMM)) {
+ if (src2w) {
+ FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
+ src2_r = sugg_src2_r;
+ }
+ else {
+ src2_r = 0;
+ if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) && (dst & SLJIT_MEM))
+ dst_r = 0;
+ }
+ }
+ }
+ else {
+ if (getput_arg_fast(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w))
+ FAIL_IF(compiler->error);
+ else
+ flags |= SLOW_SRC2;
+ src2_r = sugg_src2_r;
+ }
+
+ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+ SLJIT_ASSERT(src2_r == TMP_REG2);
+ if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+ }
+ else {
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));
+ }
+ }
+ else if (flags & SLOW_SRC1)
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+ else if (flags & SLOW_SRC2)
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));
+
+ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
+
+ if (dst & SLJIT_MEM) {
+ if (!(flags & SLOW_DEST)) {
+ getput_arg_fast(compiler, flags, dst_r, dst, dstw);
+ return compiler->error;
+ }
+ return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
+{
+ CHECK_ERROR();
+ check_sljit_emit_op0(compiler, op);
+
+ op = GET_OPCODE(op);
+ switch (op) {
+ case SLJIT_BREAKPOINT:
+ return push_inst(compiler, TA, UNMOVABLE_INS);
+ case SLJIT_NOP:
+ return push_inst(compiler, NOP, UNMOVABLE_INS);
+ case SLJIT_UMUL:
+ case SLJIT_SMUL:
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? UMUL : SMUL) | D(SLJIT_SCRATCH_REG1) | S1(SLJIT_SCRATCH_REG1) | S2(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG1)));
+ return push_inst(compiler, RDY | D(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2));
+#else
+#error "Implementation required"
+#endif
+ case SLJIT_UDIV:
+ case SLJIT_SDIV:
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ if (op == SLJIT_UDIV)
+ FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS));
+ else {
+ FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_SCRATCH_REG1) | IMM(31), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, WRY | S1(TMP_REG1), MOVABLE_INS));
+ }
+ FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_SCRATCH_REG1), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? UDIV : SDIV) | D(SLJIT_SCRATCH_REG1) | S1(SLJIT_SCRATCH_REG1) | S2(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG1)));
+ FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_SCRATCH_REG2) | S1(SLJIT_SCRATCH_REG1) | S2(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2)));
+ FAIL_IF(push_inst(compiler, SUB | D(SLJIT_SCRATCH_REG2) | S1(TMP_REG2) | S2(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2)));
+ return SLJIT_SUCCESS;
+#else
+#error "Implementation required"
+#endif
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
+{
+ sljit_si flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+
+ CHECK_ERROR();
+ check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ op = GET_OPCODE(op);
+ switch (op) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOV_UI:
+ return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOV_SI:
+ return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOV_UB:
+ return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
+
+ case SLJIT_MOV_SB:
+ return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
+
+ case SLJIT_MOV_UH:
+ return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
+
+ case SLJIT_MOV_SH:
+ return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
+
+ case SLJIT_MOVU:
+ case SLJIT_MOVU_P:
+ return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOVU_UI:
+ return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOVU_SI:
+ return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOVU_UB:
+ return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
+
+ case SLJIT_MOVU_SB:
+ return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
+
+ case SLJIT_MOVU_UH:
+ return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
+
+ case SLJIT_MOVU_SH:
+ return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
+
+ case SLJIT_NOT:
+ case SLJIT_CLZ:
+ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_NEG:
+ return emit_op(compiler, SLJIT_SUB, flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
+{
+ sljit_si flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+
+ CHECK_ERROR();
+ check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ op = GET_OPCODE(op);
+ switch (op) {
+ case SLJIT_ADD:
+ case SLJIT_ADDC:
+ case SLJIT_MUL:
+ case SLJIT_AND:
+ case SLJIT_OR:
+ case SLJIT_XOR:
+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SUB:
+ case SLJIT_SUBC:
+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SHL:
+ case SLJIT_LSHR:
+ case SLJIT_ASHR:
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ if (src2 & SLJIT_IMM)
+ src2w &= 0x1f;
+#else
+ SLJIT_ASSERT_STOP();
+#endif
+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
+{
+ check_sljit_get_register_index(reg);
+ return reg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_si size)
+{
+ CHECK_ERROR();
+ check_sljit_emit_op_custom(compiler, instruction, size);
+ SLJIT_ASSERT(size == 4);
+
+ return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);
+}
+
+/* --------------------------------------------------------------------- */
+/* Floating point operators */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
+{
+ return 1;
+}
+
+#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 7))
+#define SELECT_FOP(op, single, double) ((op & SLJIT_SINGLE_OP) ? single : double)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
+{
+ sljit_si dst_fr;
+
+ CHECK_ERROR();
+ check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
+ SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ if (GET_OPCODE(op) == SLJIT_CMPD) {
+ if (dst > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, dst, dstw, src, srcw));
+ dst = TMP_FREG1;
+ }
+ else
+ dst <<= 1;
+
+ if (src > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src, srcw, 0, 0));
+ src = TMP_FREG2;
+ }
+ else
+ src <<= 1;
+
+ return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | S1A(dst) | S2A(src), FCC_IS_SET | MOVABLE_INS);
+ }
+
+ dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : (dst << 1);
+
+ if (src > SLJIT_FLOAT_REG6) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_fr, src, srcw, dst, dstw));
+ src = dst_fr;
+ }
+ else
+ src <<= 1;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOVD:
+ if (src != dst_fr && dst_fr != TMP_FREG1) {
+ FAIL_IF(push_inst(compiler, FMOVS | DA(dst_fr) | S2A(src), MOVABLE_INS));
+ if (!(op & SLJIT_SINGLE_OP))
+ FAIL_IF(push_inst(compiler, FMOVS | DA(dst_fr | 1) | S2A(src | 1), MOVABLE_INS));
+ }
+ break;
+ case SLJIT_NEGD:
+ FAIL_IF(push_inst(compiler, FNEGS | DA(dst_fr) | S2A(src), MOVABLE_INS));
+ if (dst_fr != src && !(op & SLJIT_SINGLE_OP))
+ FAIL_IF(push_inst(compiler, FMOVS | DA(dst_fr | 1) | S2A(src | 1), MOVABLE_INS));
+ break;
+ case SLJIT_ABSD:
+ FAIL_IF(push_inst(compiler, FABSS | DA(dst_fr) | S2A(src), MOVABLE_INS));
+ if (dst_fr != src && !(op & SLJIT_SINGLE_OP))
+ FAIL_IF(push_inst(compiler, FMOVS | DA(dst_fr | 1) | S2A(src | 1), MOVABLE_INS));
+ break;
+ }
+
+ if (dst_fr == TMP_FREG1) {
+ if (GET_OPCODE(op) == SLJIT_MOVD)
+ dst_fr = src;
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_fr, dst, dstw, 0, 0));
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
+{
+ sljit_si dst_fr, flags = 0;
+
+ CHECK_ERROR();
+ check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG2 : (dst << 1);
+
+ if (src1 > SLJIT_FLOAT_REG6) {
+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
+ FAIL_IF(compiler->error);
+ src1 = TMP_FREG1;
+ } else
+ flags |= SLOW_SRC1;
+ }
+ else
+ src1 <<= 1;
+
+ if (src2 > SLJIT_FLOAT_REG6) {
+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
+ FAIL_IF(compiler->error);
+ src2 = TMP_FREG2;
+ } else
+ flags |= SLOW_SRC2;
+ }
+ else
+ src2 <<= 1;
+
+ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+ if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
+ }
+ else {
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
+ }
+ }
+ else if (flags & SLOW_SRC1)
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
+ else if (flags & SLOW_SRC2)
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
+
+ if (flags & SLOW_SRC1)
+ src1 = TMP_FREG1;
+ if (flags & SLOW_SRC2)
+ src2 = TMP_FREG2;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADDD:
+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | DA(dst_fr) | S1A(src1) | S2A(src2), MOVABLE_INS));
+ break;
+
+ case SLJIT_SUBD:
+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | DA(dst_fr) | S1A(src1) | S2A(src2), MOVABLE_INS));
+ break;
+
+ case SLJIT_MULD:
+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | DA(dst_fr) | S1A(src1) | S2A(src2), MOVABLE_INS));
+ break;
+
+ case SLJIT_DIVD:
+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | DA(dst_fr) | S1A(src1) | S2A(src2), MOVABLE_INS));
+ break;
+ }
+
+ if (dst_fr == TMP_FREG2)
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
+
+ return SLJIT_SUCCESS;
+}
+
+#undef FLOAT_DATA
+#undef SELECT_FOP
+
+/* --------------------------------------------------------------------- */
+/* Other instructions */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+{
+ CHECK_ERROR();
+ check_sljit_emit_fast_enter(compiler, dst, dstw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ /* For UNUSED dst. Uncommon, but possible. */
+ if (dst == SLJIT_UNUSED)
+ return SLJIT_SUCCESS;
+
+ if (dst <= TMP_REG3)
+ return push_inst(compiler, OR | D(dst) | S1(0) | S2(LINK_REG), DR(dst));
+
+ /* Memory. */
+ return emit_op_mem(compiler, WORD_DATA, LINK_REG, dst, dstw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ check_sljit_emit_fast_return(compiler, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (src <= TMP_REG3)
+ FAIL_IF(push_inst(compiler, OR | D(LINK_REG) | S1(0) | S2(src), DR(LINK_REG)));
+ else if (src & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, LINK_REG, src, srcw));
+ else if (src & SLJIT_IMM)
+ FAIL_IF(load_immediate(compiler, LINK_REG, srcw));
+
+ FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(LINK_REG) | IMM(8), UNMOVABLE_INS));
+ return push_inst(compiler, NOP, UNMOVABLE_INS);
+}
+
+/* --------------------------------------------------------------------- */
+/* Conditional instructions */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+
+ CHECK_ERROR_PTR();
+ check_sljit_emit_label(compiler);
+
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ return compiler->last_label;
+
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ PTR_FAIL_IF(!label);
+ set_label(label, compiler);
+ compiler->delay_slot = UNMOVABLE_INS;
+ return label;
+}
+
+static sljit_ins get_cc(sljit_si type)
+{
+ switch (type) {
+ case SLJIT_C_EQUAL:
+ case SLJIT_C_MUL_NOT_OVERFLOW:
+ return DA(0x1);
+
+ case SLJIT_C_NOT_EQUAL:
+ case SLJIT_C_MUL_OVERFLOW:
+ return DA(0x9);
+
+ case SLJIT_C_LESS:
+ return DA(0x5);
+
+ case SLJIT_C_GREATER_EQUAL:
+ return DA(0xd);
+
+ case SLJIT_C_GREATER:
+ return DA(0xc);
+
+ case SLJIT_C_LESS_EQUAL:
+ return DA(0x4);
+
+ case SLJIT_C_SIG_LESS:
+ return DA(0x3);
+
+ case SLJIT_C_SIG_GREATER_EQUAL:
+ return DA(0xb);
+
+ case SLJIT_C_SIG_GREATER:
+ return DA(0xa);
+
+ case SLJIT_C_SIG_LESS_EQUAL:
+ return DA(0x2);
+
+ case SLJIT_C_OVERFLOW:
+ return DA(0x7);
+
+ case SLJIT_C_NOT_OVERFLOW:
+ return DA(0xf);
+
+ case SLJIT_C_FLOAT_EQUAL:
+ return DA(0x9);
+
+ case SLJIT_C_FLOAT_NOT_EQUAL: /* Unordered. */
+ return DA(0x1);
+
+ case SLJIT_C_FLOAT_LESS:
+ return DA(0x4);
+
+ case SLJIT_C_FLOAT_GREATER_EQUAL: /* Unordered. */
+ return DA(0xc);
+
+ case SLJIT_C_FLOAT_LESS_EQUAL:
+ return DA(0xd);
+
+ case SLJIT_C_FLOAT_GREATER: /* Unordered. */
+ return DA(0x5);
+
+ case SLJIT_C_FLOAT_UNORDERED:
+ return DA(0x7);
+
+ case SLJIT_C_FLOAT_ORDERED:
+ return DA(0xf);
+
+ default:
+ SLJIT_ASSERT_STOP();
+ return DA(0x8);
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+{
+ struct sljit_jump *jump;
+
+ CHECK_ERROR_PTR();
+ check_sljit_emit_jump(compiler, type);
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ type &= 0xff;
+
+ if (type < SLJIT_C_FLOAT_EQUAL) {
+ jump->flags |= IS_COND;
+ if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & ICC_IS_SET))
+ jump->flags |= IS_MOVABLE;
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ PTR_FAIL_IF(push_inst(compiler, BICC | get_cc(type ^ 1) | 5, UNMOVABLE_INS));
+#else
+#error "Implementation required"
+#endif
+ }
+ else if (type < SLJIT_JUMP) {
+ jump->flags |= IS_COND;
+ if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & FCC_IS_SET))
+ jump->flags |= IS_MOVABLE;
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ PTR_FAIL_IF(push_inst(compiler, FBFCC | get_cc(type ^ 1) | 5, UNMOVABLE_INS));
+#else
+#error "Implementation required"
+#endif
+ } else {
+ if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS)
+ jump->flags |= IS_MOVABLE;
+ if (type >= SLJIT_FAST_CALL)
+ jump->flags |= IS_CALL;
+ }
+
+ PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
+ PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? LINK_REG : 0) | S1(TMP_REG2) | IMM(0), UNMOVABLE_INS));
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+{
+ struct sljit_jump *jump = NULL;
+ sljit_si src_r;
+
+ CHECK_ERROR();
+ check_sljit_emit_ijump(compiler, type, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (src <= TMP_REG3)
+ src_r = src;
+ else if (src & SLJIT_IMM) {
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR);
+ jump->u.target = srcw;
+ if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS)
+ jump->flags |= IS_MOVABLE;
+ if (type >= SLJIT_FAST_CALL)
+ jump->flags |= IS_CALL;
+
+ FAIL_IF(emit_const(compiler, TMP_REG2, 0));
+ src_r = TMP_REG2;
+ }
+ else {
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw));
+ src_r = TMP_REG2;
+ }
+
+ FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? LINK_REG : 0) | S1(src_r) | IMM(0), UNMOVABLE_INS));
+ if (jump)
+ jump->addr = compiler->size;
+ return push_inst(compiler, NOP, UNMOVABLE_INS);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw,
+ sljit_si type)
+{
+ sljit_si reg, flags = (GET_FLAGS(op) ? SET_FLAGS : 0);
+
+ CHECK_ERROR();
+ check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ if (dst == SLJIT_UNUSED)
+ return SLJIT_SUCCESS;
+
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ op = GET_OPCODE(op);
+ reg = (op < SLJIT_ADD && dst <= TMP_REG3) ? dst : TMP_REG2;
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ if (type < SLJIT_C_FLOAT_EQUAL)
+ FAIL_IF(push_inst(compiler, BICC | get_cc(type) | 3, UNMOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, FBFCC | get_cc(type) | 3, UNMOVABLE_INS));
+
+ FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(1), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(0), UNMOVABLE_INS));
+
+ if (op >= SLJIT_ADD)
+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
+
+ return (reg == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS;
+#else
+#error "Implementation required"
+#endif
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
+{
+ sljit_si reg;
+ struct sljit_const *const_;
+
+ CHECK_ERROR_PTR();
+ check_sljit_emit_const(compiler, dst, dstw, init_value);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+ PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
+
+ reg = (dst <= TMP_REG3) ? dst : TMP_REG2;
+
+ PTR_FAIL_IF(emit_const(compiler, reg, init_value));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
+
+ return const_;
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_32.c b/src/3rdparty/pcre/sljit/sljitNativeX86_32.c
index 68bca8441a..03a595bd85 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeX86_32.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeX86_32.c
@@ -26,30 +26,30 @@
/* x86 32-bit arch dependent functions. */
-static int emit_do_imm(struct sljit_compiler *compiler, sljit_ub opcode, sljit_w imm)
+static sljit_si emit_do_imm(struct sljit_compiler *compiler, sljit_ub opcode, sljit_sw imm)
{
- sljit_ub *buf;
+ sljit_ub *inst;
- 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;
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw));
+ FAIL_IF(!inst);
+ INC_SIZE(1 + sizeof(sljit_sw));
+ *inst++ = opcode;
+ *(sljit_sw*)inst = imm;
return SLJIT_SUCCESS;
}
-static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type)
+static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type)
{
if (type == SLJIT_JUMP) {
- *code_ptr++ = 0xe9;
+ *code_ptr++ = JMP_i32;
jump->addr++;
}
else if (type >= SLJIT_FAST_CALL) {
- *code_ptr++ = 0xe8;
+ *code_ptr++ = CALL_i32;
jump->addr++;
}
else {
- *code_ptr++ = 0x0f;
+ *code_ptr++ = GROUP_0F;
*code_ptr++ = get_jump_code(type);
jump->addr += 2;
}
@@ -57,39 +57,43 @@ static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_
if (jump->flags & JUMP_LABEL)
jump->flags |= PATCH_MW;
else
- *(sljit_w*)code_ptr = jump->u.target - (jump->addr + 4);
+ *(sljit_sw*)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 saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
- int size;
- sljit_ub *buf;
+ sljit_si size;
+ sljit_si locals_offset;
+ sljit_ub *inst;
CHECK_ERROR();
- check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
+ check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
- compiler->temporaries = temporaries;
+ compiler->scratches = scratches;
compiler->saveds = saveds;
compiler->args = args;
compiler->flags_saved = 0;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
#else
size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (2 + args * 3) : 0);
#endif
- buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
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);
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (reg_map[TMP_REGISTER] << 3) | 0x4 /* esp */;
}
#endif
if (saveds > 2)
@@ -101,81 +105,105 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
if (args > 0) {
- *buf++ = 0x8b;
- *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[SLJIT_TEMPORARY_REG3];
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[SLJIT_SCRATCH_REG3];
}
if (args > 1) {
- *buf++ = 0x8b;
- *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[SLJIT_TEMPORARY_REG2];
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[SLJIT_SCRATCH_REG2];
}
if (args > 2) {
- *buf++ = 0x8b;
- *buf++ = 0x44 | (reg_map[SLJIT_SAVED_REG3] << 3);
- *buf++ = 0x24;
- *buf++ = sizeof(sljit_w) * (3 + 2); /* saveds >= 3 as well. */
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x4 /* esp */;
+ *inst++ = 0x24;
+ *inst++ = sizeof(sljit_sw) * (3 + 2); /* saveds >= 3 as well. */
}
#else
if (args > 0) {
- *buf++ = 0x8b;
- *buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REGISTER];
- *buf++ = sizeof(sljit_w) * 2;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REGISTER];
+ *inst++ = sizeof(sljit_sw) * 2;
}
if (args > 1) {
- *buf++ = 0x8b;
- *buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REGISTER];
- *buf++ = sizeof(sljit_w) * 3;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REGISTER];
+ *inst++ = sizeof(sljit_sw) * 3;
}
if (args > 2) {
- *buf++ = 0x8b;
- *buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REGISTER];
- *buf++ = sizeof(sljit_w) * 4;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REGISTER];
+ *inst++ = sizeof(sljit_sw) * 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->saveds_start = local_size;
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ locals_offset = 2 * sizeof(sljit_uw);
+#else
+ SLJIT_COMPILE_ASSERT(FIXED_LOCALS_OFFSET >= 2 * sizeof(sljit_uw), require_at_least_two_words);
+ locals_offset = FIXED_LOCALS_OFFSET;
+#endif
+ compiler->scratches_start = locals_offset;
+ if (scratches > 3)
+ locals_offset += (scratches - 3) * sizeof(sljit_uw);
+ compiler->saveds_start = locals_offset;
if (saveds > 3)
- local_size += (saveds - 3) * sizeof(sljit_uw);
+ locals_offset += (saveds - 3) * sizeof(sljit_uw);
+ compiler->locals_offset = locals_offset;
+ local_size = locals_offset + ((local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1));
+ compiler->local_size = local_size;
#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)));
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_SCRATCH_REG1], local_size));
+#else
+ local_size -= FIXED_LOCALS_OFFSET;
+ FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_SCRATCH_REG1], local_size));
+ FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
+ SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, FIXED_LOCALS_OFFSET));
+#endif
+ FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_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);
-
- return SLJIT_SUCCESS;
+ SLJIT_ASSERT(local_size > 0);
+ return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
+ SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
+ sljit_si locals_offset;
+
CHECK_ERROR_VOID();
- check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
+ check_sljit_set_context(compiler, args, scratches, saveds, local_size);
- compiler->temporaries = temporaries;
+ compiler->scratches = scratches;
compiler->saveds = saveds;
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->saveds_start = compiler->local_size;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ locals_offset = 2 * sizeof(sljit_uw);
+#else
+ locals_offset = FIXED_LOCALS_OFFSET;
+#endif
+ compiler->scratches_start = locals_offset;
+ if (scratches > 3)
+ locals_offset += (scratches - 3) * sizeof(sljit_uw);
+ compiler->saveds_start = locals_offset;
if (saveds > 3)
- compiler->local_size += (saveds - 3) * sizeof(sljit_uw);
+ locals_offset += (saveds - 3) * sizeof(sljit_uw);
+ compiler->locals_offset = locals_offset;
+ compiler->local_size = locals_offset + ((local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1));
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
- int size;
- sljit_ub *buf;
+ sljit_si size;
+ sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_return(compiler, op, src, srcw);
@@ -184,9 +212,9 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
compiler->flags_saved = 0;
FAIL_IF(emit_mov_before_return(compiler, op, 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));
+ SLJIT_ASSERT(compiler->local_size > 0);
+ FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+ SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size));
size = 2 + (compiler->saveds <= 3 ? compiler->saveds : 3);
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
@@ -196,8 +224,8 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
if (compiler->args > 0)
size += 2;
#endif
- buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
INC_SIZE(size);
@@ -210,14 +238,11 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
POP_REG(reg_map[TMP_REGISTER]);
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
if (compiler->args > 2)
- RETN(sizeof(sljit_w));
+ RET_I16(sizeof(sljit_sw));
else
RET();
#else
- if (compiler->args > 0)
- RETN(compiler->args * sizeof(sljit_w));
- else
- RET();
+ RET();
#endif
return SLJIT_SUCCESS;
@@ -228,16 +253,16 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
/* --------------------------------------------------------------------- */
/* Size contains the flags as well. */
-static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
+static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size,
/* The register or immediate operand. */
- int a, sljit_w imma,
+ sljit_si a, sljit_sw imma,
/* The general operand (not immediate). */
- int b, sljit_w immb)
+ sljit_si b, sljit_sw immb)
{
- sljit_ub *buf;
+ sljit_ub *inst;
sljit_ub *buf_ptr;
- int flags = size & ~0xf;
- int inst_size;
+ sljit_si flags = size & ~0xf;
+ sljit_si inst_size;
/* Both cannot be switched on. */
SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
@@ -248,13 +273,16 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
/* SSE2 and immediate is not possible. */
SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
+ SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
+ && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
+ && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
#endif
size &= 0xf;
inst_size = size;
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
- if (flags & EX86_PREF_F2)
+ if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
inst_size++;
#endif
if (flags & EX86_PREF_66)
@@ -264,13 +292,13 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
inst_size += 1; /* mod r/m byte. */
if (b & SLJIT_MEM) {
if ((b & 0x0f) == SLJIT_UNUSED)
- inst_size += sizeof(sljit_w);
+ inst_size += sizeof(sljit_sw);
else if (immb != 0 && !(b & 0xf0)) {
/* Immediate operand. */
if (immb <= 127 && immb >= -128)
- inst_size += sizeof(sljit_b);
+ inst_size += sizeof(sljit_sb);
else
- inst_size += sizeof(sljit_w);
+ inst_size += sizeof(sljit_sw);
}
if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
@@ -300,29 +328,31 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else if (flags & EX86_HALF_ARG)
inst_size += sizeof(short);
else
- inst_size += sizeof(sljit_w);
+ inst_size += sizeof(sljit_sw);
}
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);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
+ PTR_FAIL_IF(!inst);
/* Encoding the byte. */
INC_SIZE(inst_size);
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
if (flags & EX86_PREF_F2)
- *buf++ = 0xf2;
+ *inst++ = 0xf2;
+ if (flags & EX86_PREF_F3)
+ *inst++ = 0xf3;
#endif
if (flags & EX86_PREF_66)
- *buf++ = 0x66;
+ *inst++ = 0x66;
- buf_ptr = buf + size;
+ buf_ptr = inst + 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;
+ *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
if ((a & SLJIT_IMM) || (a == 0))
*buf_ptr = 0;
@@ -339,19 +369,19 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else {
if (a & SLJIT_IMM) {
if (imma == 1)
- *buf = 0xd1;
+ *inst = GROUP_SHIFT_1;
else
- *buf = 0xc1;
+ *inst = GROUP_SHIFT_N;
} else
- *buf = 0xd3;
+ *inst = GROUP_SHIFT_CL;
*buf_ptr = 0;
}
if (!(b & SLJIT_MEM))
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
- *buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_map[b] : b);
+ *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2)) ? reg_map[b] : b);
#else
- *buf_ptr++ |= 0xc0 + reg_map[b];
+ *buf_ptr++ |= MOD_REG + reg_map[b];
#endif
else if ((b & 0x0f) != SLJIT_UNUSED) {
if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
@@ -373,8 +403,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
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);
+ *(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
+ buf_ptr += sizeof(sljit_sw);
}
}
}
@@ -385,8 +415,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
}
else {
*buf_ptr++ |= 0x05;
- *(sljit_w*)buf_ptr = immb; /* 32 bit displacement. */
- buf_ptr += sizeof(sljit_w);
+ *(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
+ buf_ptr += sizeof(sljit_sw);
}
if (a & SLJIT_IMM) {
@@ -395,121 +425,121 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else if (flags & EX86_HALF_ARG)
*(short*)buf_ptr = imma;
else if (!(flags & EX86_SHIFT_INS))
- *(sljit_w*)buf_ptr = imma;
+ *(sljit_sw*)buf_ptr = imma;
}
- return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1);
+ return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
}
/* --------------------------------------------------------------------- */
/* Call / return instructions */
/* --------------------------------------------------------------------- */
-static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type)
+static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type)
{
- sljit_ub *buf;
+ sljit_ub *inst;
#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);
+ inst = (sljit_ub*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
+ FAIL_IF(!inst);
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];
+ PUSH_REG(reg_map[SLJIT_SCRATCH_REG3]);
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (reg_map[SLJIT_SCRATCH_REG3] << 3) | reg_map[SLJIT_SCRATCH_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]);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 * (type - SLJIT_CALL0));
+ FAIL_IF(!inst);
+ INC_SIZE(4 * (type - SLJIT_CALL0));
+
+ *inst++ = MOV_rm_r;
+ *inst++ = MOD_DISP8 | (reg_map[SLJIT_SCRATCH_REG1] << 3) | 0x4 /* SIB */;
+ *inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_LOCALS_REG];
+ *inst++ = 0;
+ if (type >= SLJIT_CALL2) {
+ *inst++ = MOV_rm_r;
+ *inst++ = MOD_DISP8 | (reg_map[SLJIT_SCRATCH_REG2] << 3) | 0x4 /* SIB */;
+ *inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_LOCALS_REG];
+ *inst++ = sizeof(sljit_sw);
+ }
+ if (type >= SLJIT_CALL3) {
+ *inst++ = MOV_rm_r;
+ *inst++ = MOD_DISP8 | (reg_map[SLJIT_SCRATCH_REG3] << 3) | 0x4 /* SIB */;
+ *inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_LOCALS_REG];
+ *inst++ = 2 * sizeof(sljit_sw);
+ }
#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 saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
- sljit_ub *buf;
+ sljit_ub *inst;
CHECK_ERROR();
- check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
-
- compiler->temporaries = temporaries;
- compiler->saveds = saveds;
- 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->saveds_start = compiler->local_size;
- if (saveds > 3)
- compiler->local_size += (saveds - 3) * sizeof(sljit_uw);
+ check_sljit_emit_fast_enter(compiler, dst, dstw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
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);
+ /* For UNUSED dst. Uncommon, but possible. */
+ if (dst == SLJIT_UNUSED)
+ dst = TMP_REGISTER;
+
+ if (dst <= TMP_REGISTER) {
+ /* Unused dest is possible here. */
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
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]);
+ /* Memory. */
+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst++ = POP_rm;
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
- sljit_ub *buf;
+ sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_fast_return(compiler, src, srcw);
+ ADJUST_LOCAL_OFFSET(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);
+ if (src <= TMP_REGISTER) {
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
+ FAIL_IF(!inst);
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;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_FF;
+ *inst |= PUSH_rm;
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
INC_SIZE(1);
}
else {
/* SLJIT_IMM. */
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
+ FAIL_IF(!inst);
INC_SIZE(5 + 1);
- *buf++ = 0x68;
- *(sljit_w*)buf = srcw;
- buf += sizeof(sljit_w);
+ *inst++ = PUSH_i32;
+ *(sljit_sw*)inst = srcw;
+ inst += sizeof(sljit_sw);
}
RET();
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_64.c b/src/3rdparty/pcre/sljit/sljitNativeX86_64.c
index 40d875b841..28f04fddd8 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeX86_64.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeX86_64.c
@@ -26,118 +26,116 @@
/* x86 64-bit arch dependent functions. */
-static int emit_load_imm64(struct sljit_compiler *compiler, int reg, sljit_w imm)
+static sljit_si emit_load_imm64(struct sljit_compiler *compiler, sljit_si reg, sljit_sw 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;
+ sljit_ub *inst;
+
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw));
+ FAIL_IF(!inst);
+ INC_SIZE(2 + sizeof(sljit_sw));
+ *inst++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
+ *inst++ = MOV_r_i32 + (reg_map[reg] & 0x7);
+ *(sljit_sw*)inst = imm;
return SLJIT_SUCCESS;
}
-static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type)
+static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type)
{
if (type < SLJIT_JUMP) {
+ /* Invert type. */
*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;
+ *code_ptr++ = MOV_r_i32 + 1;
jump->addr = (sljit_uw)code_ptr;
if (jump->flags & JUMP_LABEL)
jump->flags |= PATCH_MD;
else
- *(sljit_w*)code_ptr = jump->u.target;
+ *(sljit_sw*)code_ptr = jump->u.target;
- code_ptr += sizeof(sljit_w);
+ code_ptr += sizeof(sljit_sw);
*code_ptr++ = REX_B;
- *code_ptr++ = 0xff;
- *code_ptr++ = (type >= SLJIT_FAST_CALL) ? 0xd1 /* call */ : 0xe1 /* jmp */;
+ *code_ptr++ = GROUP_FF;
+ *code_ptr++ = (type >= SLJIT_FAST_CALL) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
return code_ptr;
}
-static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_w addr, int type)
+static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si type)
{
- sljit_w delta = addr - ((sljit_w)code_ptr + 1 + sizeof(sljit_hw));
+ sljit_sw delta = addr - ((sljit_sw)code_ptr + 1 + sizeof(sljit_si));
if (delta <= SLJIT_W(0x7fffffff) && delta >= SLJIT_W(-0x80000000)) {
- *code_ptr++ = (type == 2) ? 0xe8 /* call */ : 0xe9 /* jmp */;
- *(sljit_w*)code_ptr = delta;
+ *code_ptr++ = (type == 2) ? CALL_i32 : JMP_i32;
+ *(sljit_sw*)code_ptr = delta;
}
else {
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second);
*code_ptr++ = REX_W | REX_B;
- *code_ptr++ = 0xb8 + 1;
- *(sljit_w*)code_ptr = addr;
- code_ptr += sizeof(sljit_w);
+ *code_ptr++ = MOV_r_i32 + 1;
+ *(sljit_sw*)code_ptr = addr;
+ code_ptr += sizeof(sljit_sw);
*code_ptr++ = REX_B;
- *code_ptr++ = 0xff;
- *code_ptr++ = (type == 2) ? 0xd1 /* call */ : 0xe1 /* jmp */;
+ *code_ptr++ = GROUP_FF;
+ *code_ptr++ = (type == 2) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
}
return code_ptr;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
- int size, pushed_size;
- sljit_ub *buf;
+ sljit_si size, pushed_size;
+ sljit_ub *inst;
CHECK_ERROR();
- check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
+ check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
- compiler->temporaries = temporaries;
+ compiler->scratches = scratches;
compiler->saveds = saveds;
compiler->flags_saved = 0;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
size = saveds;
/* Including the return address saved by the call instruction. */
- pushed_size = (saveds + 1) * sizeof(sljit_w);
+ pushed_size = (saveds + 1) * sizeof(sljit_sw);
#ifndef _WIN64
if (saveds >= 2)
size += saveds - 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 (saveds >= 4)
size += saveds - 3;
- if (temporaries >= 5) {
+ if (scratches >= 5) {
size += (5 - 4) * 2;
- pushed_size += sizeof(sljit_w);
+ pushed_size += sizeof(sljit_sw);
}
#endif
size += args * 3;
if (size > 0) {
- buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
INC_SIZE(size);
if (saveds >= 5) {
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG2] >= 8, saved_ereg2_is_hireg);
- *buf++ = REX_B;
+ *inst++ = REX_B;
PUSH_REG(reg_lmap[SLJIT_SAVED_EREG2]);
}
if (saveds >= 4) {
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG1] >= 8, saved_ereg1_is_hireg);
- *buf++ = REX_B;
+ *inst++ = REX_B;
PUSH_REG(reg_lmap[SLJIT_SAVED_EREG1]);
}
if (saveds >= 3) {
#ifndef _WIN64
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] >= 8, saved_reg3_is_hireg);
- *buf++ = REX_B;
+ *inst++ = REX_B;
#else
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] < 8, saved_reg3_is_loreg);
#endif
@@ -146,7 +144,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
if (saveds >= 2) {
#ifndef _WIN64
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] >= 8, saved_reg2_is_hireg);
- *buf++ = REX_B;
+ *inst++ = REX_B;
#else
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] < 8, saved_reg2_is_loreg);
#endif
@@ -157,149 +155,138 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
PUSH_REG(reg_lmap[SLJIT_SAVED_REG1]);
}
#ifdef _WIN64
- if (temporaries >= 5) {
+ if (scratches >= 5) {
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_EREG2] >= 8, temporary_ereg2_is_hireg);
- *buf++ = REX_B;
+ *inst++ = 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_SAVED_REG1] << 3) | 0x7;
+ *inst++ = REX_W;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x7 /* rdi */;
}
if (args > 1) {
- *buf++ = REX_W | REX_R;
- *buf++ = 0x8b;
- *buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG2] << 3) | 0x6;
+ *inst++ = REX_W | REX_R;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (reg_lmap[SLJIT_SAVED_REG2] << 3) | 0x6 /* rsi */;
}
if (args > 2) {
- *buf++ = REX_W | REX_R;
- *buf++ = 0x8b;
- *buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG3] << 3) | 0x2;
+ *inst++ = REX_W | REX_R;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (reg_lmap[SLJIT_SAVED_REG3] << 3) | 0x2 /* rdx */;
}
#else
if (args > 0) {
- *buf++ = REX_W;
- *buf++ = 0x8b;
- *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x1;
+ *inst++ = REX_W;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x1 /* rcx */;
}
if (args > 1) {
- *buf++ = REX_W;
- *buf++ = 0x8b;
- *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | 0x2;
+ *inst++ = REX_W;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG2] << 3) | 0x2 /* rdx */;
}
if (args > 2) {
- *buf++ = REX_W | REX_B;
- *buf++ = 0x8b;
- *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x0;
+ *inst++ = REX_W | REX_B;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x0 /* r8 */;
}
#endif
}
- local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
-#ifdef _WIN64
- local_size += 4 * sizeof(sljit_w);
+ local_size = ((local_size + FIXED_LOCALS_OFFSET + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
compiler->local_size = local_size;
+#ifdef _WIN64
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;
+ /* Allocate stack for the callback, which grows the stack. */
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + (3 + sizeof(sljit_si)));
+ FAIL_IF(!inst);
+ INC_SIZE(4 + (3 + sizeof(sljit_si)));
+ *inst++ = REX_W;
+ *inst++ = GROUP_BINARY_83;
+ *inst++ = MOD_REG | SUB | 4;
/* Pushed size must be divisible by 8. */
SLJIT_ASSERT(!(pushed_size & 0x7));
if (pushed_size & 0x8) {
- *buf++ = 5 * sizeof(sljit_w);
- local_size -= 5 * sizeof(sljit_w);
+ *inst++ = 5 * sizeof(sljit_sw);
+ local_size -= 5 * sizeof(sljit_sw);
} else {
- *buf++ = 4 * sizeof(sljit_w);
- local_size -= 4 * sizeof(sljit_w);
+ *inst++ = 4 * sizeof(sljit_sw);
+ local_size -= 4 * sizeof(sljit_sw);
}
- 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) {
+ /* Second instruction */
+ SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG1] < 8, temporary_reg1_is_loreg);
+ *inst++ = REX_W;
+ *inst++ = MOV_rm_i32;
+ *inst++ = MOD_REG | reg_lmap[SLJIT_SCRATCH_REG1];
+ *(sljit_si*)inst = local_size;
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->skip_checks = 1;
#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
+ FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
}
#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);
+ SLJIT_ASSERT(local_size > 0);
+ if (local_size <= 127) {
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ *inst++ = REX_W;
+ *inst++ = GROUP_BINARY_83;
+ *inst++ = MOD_REG | SUB | 4;
+ *inst++ = local_size;
+ }
+ else {
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 7);
+ FAIL_IF(!inst);
+ INC_SIZE(7);
+ *inst++ = REX_W;
+ *inst++ = GROUP_BINARY_81;
+ *inst++ = MOD_REG | SUB | 4;
+ *(sljit_si*)inst = local_size;
+ inst += sizeof(sljit_si);
}
+#ifdef _WIN64
+ /* Save xmm6 with MOVAPS instruction. */
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
+ FAIL_IF(!inst);
+ INC_SIZE(5);
+ *inst++ = GROUP_0F;
+ *(sljit_si*)inst = 0x20247429;
#endif
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
- int pushed_size;
+ sljit_si pushed_size;
CHECK_ERROR_VOID();
- check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
+ check_sljit_set_context(compiler, args, scratches, saveds, local_size);
- compiler->temporaries = temporaries;
+ compiler->scratches = scratches;
compiler->saveds = saveds;
- /* Including the return address saved by the call instruction. */
- pushed_size = (saveds + 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);
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
#endif
- compiler->local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
+
+ /* Including the return address saved by the call instruction. */
+ pushed_size = (saveds + 1) * sizeof(sljit_sw);
#ifdef _WIN64
- compiler->local_size += 4 * sizeof(sljit_w);
+ if (scratches >= 5)
+ pushed_size += sizeof(sljit_sw);
#endif
+ compiler->local_size = ((local_size + FIXED_LOCALS_OFFSET + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
- int size;
- sljit_ub *buf;
+ sljit_si size;
+ sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_return(compiler, op, src, srcw);
@@ -307,25 +294,32 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
compiler->flags_saved = 0;
FAIL_IF(emit_mov_before_return(compiler, op, 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;
- }
+#ifdef _WIN64
+ /* Restore xmm6 with MOVAPS instruction. */
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
+ FAIL_IF(!inst);
+ INC_SIZE(5);
+ *inst++ = GROUP_0F;
+ *(sljit_si*)inst = 0x20247428;
+#endif
+ SLJIT_ASSERT(compiler->local_size > 0);
+ if (compiler->local_size <= 127) {
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ *inst++ = REX_W;
+ *inst++ = GROUP_BINARY_83;
+ *inst++ = MOD_REG | ADD | 4;
+ *inst = compiler->local_size;
+ }
+ else {
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 7);
+ FAIL_IF(!inst);
+ INC_SIZE(7);
+ *inst++ = REX_W;
+ *inst++ = GROUP_BINARY_81;
+ *inst++ = MOD_REG | ADD | 4;
+ *(sljit_si*)inst = compiler->local_size;
}
size = 1 + compiler->saveds;
@@ -333,25 +327,19 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
if (compiler->saveds >= 2)
size += compiler->saveds - 1;
#else
- if (compiler->has_locals)
- size += 2;
if (compiler->saveds >= 4)
size += compiler->saveds - 3;
- if (compiler->temporaries >= 5)
+ if (compiler->scratches >= 5)
size += (5 - 4) * 2;
#endif
- buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
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;
+ if (compiler->scratches >= 5) {
+ *inst++ = REX_B;
POP_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
}
#endif
@@ -359,22 +347,22 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
POP_REG(reg_map[SLJIT_SAVED_REG1]);
if (compiler->saveds >= 2) {
#ifndef _WIN64
- *buf++ = REX_B;
+ *inst++ = REX_B;
#endif
POP_REG(reg_lmap[SLJIT_SAVED_REG2]);
}
if (compiler->saveds >= 3) {
#ifndef _WIN64
- *buf++ = REX_B;
+ *inst++ = REX_B;
#endif
POP_REG(reg_lmap[SLJIT_SAVED_REG3]);
}
if (compiler->saveds >= 4) {
- *buf++ = REX_B;
+ *inst++ = REX_B;
POP_REG(reg_lmap[SLJIT_SAVED_EREG1]);
}
if (compiler->saveds >= 5) {
- *buf++ = REX_B;
+ *inst++ = REX_B;
POP_REG(reg_lmap[SLJIT_SAVED_EREG2]);
}
@@ -386,39 +374,32 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
/* Operators */
/* --------------------------------------------------------------------- */
-static int emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_w imm)
+static sljit_si emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_sw imm)
{
- sljit_ub *buf;
+ sljit_ub *inst;
+ sljit_si length = 1 + (rex ? 1 : 0) + sizeof(sljit_si);
- 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;
- }
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + length);
+ FAIL_IF(!inst);
+ INC_SIZE(length);
+ if (rex)
+ *inst++ = rex;
+ *inst++ = opcode;
+ *(sljit_si*)inst = imm;
return SLJIT_SUCCESS;
}
-static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
+static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size,
/* The register or immediate operand. */
- int a, sljit_w imma,
+ sljit_si a, sljit_sw imma,
/* The general operand (not immediate). */
- int b, sljit_w immb)
+ sljit_si b, sljit_sw immb)
{
- sljit_ub *buf;
+ sljit_ub *inst;
sljit_ub *buf_ptr;
sljit_ub rex = 0;
- int flags = size & ~0xf;
- int inst_size;
+ sljit_si flags = size & ~0xf;
+ sljit_si inst_size;
/* The immediate operand must be 32 bit. */
SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
@@ -431,6 +412,9 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
/* SSE2 and immediate is not possible. */
SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
+ SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
+ && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
+ && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
#endif
size &= 0xf;
@@ -452,7 +436,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
rex |= REX;
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
- if (flags & EX86_PREF_F2)
+ if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
inst_size++;
#endif
if (flags & EX86_PREF_66)
@@ -462,23 +446,21 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
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. */
+ inst_size += 1 + sizeof(sljit_si); /* 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);
+ inst_size += sizeof(sljit_sb);
else
- inst_size += sizeof(sljit_hw);
+ inst_size += sizeof(sljit_si);
}
}
-#ifndef _WIN64
- if ((b & 0xf) == SLJIT_LOCALS_REG && (b & 0xf0) == 0)
+ if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
b |= SLJIT_LOCALS_REG << 4;
-#endif
if ((b & 0xf0) != SLJIT_UNUSED) {
inst_size += 1; /* SIB byte. */
@@ -513,7 +495,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else if (flags & EX86_HALF_ARG)
inst_size += sizeof(short);
else
- inst_size += sizeof(sljit_hw);
+ inst_size += sizeof(sljit_si);
}
else {
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
@@ -530,25 +512,27 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
if (rex)
inst_size++;
- buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
- PTR_FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
+ PTR_FAIL_IF(!inst);
/* Encoding the byte. */
INC_SIZE(inst_size);
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
if (flags & EX86_PREF_F2)
- *buf++ = 0xf2;
+ *inst++ = 0xf2;
+ if (flags & EX86_PREF_F3)
+ *inst++ = 0xf3;
#endif
if (flags & EX86_PREF_66)
- *buf++ = 0x66;
+ *inst++ = 0x66;
if (rex)
- *buf++ = rex;
- buf_ptr = buf + size;
+ *inst++ = rex;
+ buf_ptr = inst + 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;
+ *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
if ((a & SLJIT_IMM) || (a == 0))
*buf_ptr = 0;
@@ -565,24 +549,21 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else {
if (a & SLJIT_IMM) {
if (imma == 1)
- *buf = 0xd1;
+ *inst = GROUP_SHIFT_1;
else
- *buf = 0xc1;
+ *inst = GROUP_SHIFT_N;
} else
- *buf = 0xd3;
+ *inst = GROUP_SHIFT_CL;
*buf_ptr = 0;
}
if (!(b & SLJIT_MEM))
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
- *buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_lmap[b] : b);
+ *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2)) ? reg_lmap[b] : b);
#else
- *buf_ptr++ |= 0xc0 + reg_lmap[b];
+ *buf_ptr++ |= MOD_REG + 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)
@@ -602,8 +583,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
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);
+ *(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */
+ buf_ptr += sizeof(sljit_si);
}
}
}
@@ -615,8 +596,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else {
*buf_ptr++ |= 0x04;
*buf_ptr++ = 0x25;
- *(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
- buf_ptr += sizeof(sljit_hw);
+ *(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */
+ buf_ptr += sizeof(sljit_si);
}
if (a & SLJIT_IMM) {
@@ -625,154 +606,141 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else if (flags & EX86_HALF_ARG)
*(short*)buf_ptr = imma;
else if (!(flags & EX86_SHIFT_INS))
- *(sljit_hw*)buf_ptr = imma;
+ *(sljit_si*)buf_ptr = imma;
}
- return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1);
+ return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
}
/* --------------------------------------------------------------------- */
/* Call / return instructions */
/* --------------------------------------------------------------------- */
-static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type)
+static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type)
{
- sljit_ub *buf;
+ sljit_ub *inst;
#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);
+ SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG2] == 6 && reg_map[SLJIT_SCRATCH_REG1] < 8 && reg_map[SLJIT_SCRATCH_REG3] < 8, args_registers);
- buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
+ FAIL_IF(!inst);
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];
+ *inst++ = REX_W;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (0x2 /* rdx */ << 3) | reg_lmap[SLJIT_SCRATCH_REG3];
}
- *buf++ = REX_W;
- *buf++ = 0x8b;
- *buf++ = 0xc0 | (0x7 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
+ *inst++ = REX_W;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (0x7 /* rdi */ << 3) | reg_lmap[SLJIT_SCRATCH_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);
+ SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG2] == 2 && reg_map[SLJIT_SCRATCH_REG1] < 8 && reg_map[SLJIT_SCRATCH_REG3] < 8, args_registers);
- buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
+ FAIL_IF(!inst);
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];
+ *inst++ = REX_W | REX_R;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (0x0 /* r8 */ << 3) | reg_lmap[SLJIT_SCRATCH_REG3];
}
- *buf++ = REX_W;
- *buf++ = 0x8b;
- *buf++ = 0xc0 | (0x1 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
+ *inst++ = REX_W;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (0x1 /* rcx */ << 3) | reg_lmap[SLJIT_SCRATCH_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 saveds, int local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
- sljit_ub *buf;
+ sljit_ub *inst;
CHECK_ERROR();
- check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
-
- compiler->temporaries = temporaries;
- compiler->saveds = saveds;
- compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
-#ifdef _WIN64
- compiler->local_size += 4 * sizeof(sljit_w);
-#endif
+ check_sljit_emit_fast_enter(compiler, dst, dstw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
/* For UNUSED dst. Uncommon, but possible. */
if (dst == SLJIT_UNUSED)
dst = TMP_REGISTER;
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
+ if (dst <= TMP_REGISTER) {
if (reg_map[dst] < 8) {
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
- FAIL_IF(!buf);
-
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
INC_SIZE(1);
POP_REG(reg_lmap[dst]);
+ return SLJIT_SUCCESS;
}
- 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;
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ *inst++ = REX_B;
+ POP_REG(reg_lmap[dst]);
+ return SLJIT_SUCCESS;
}
+
+ /* REX_W is not necessary (src is not immediate). */
+ compiler->mode32 = 1;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst++ = POP_rm;
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
- sljit_ub *buf;
+ sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_fast_return(compiler, src, srcw);
-
- CHECK_EXTRA_REGS(src, srcw, (void)0);
+ ADJUST_LOCAL_OFFSET(src, srcw);
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 (src <= TMP_REGISTER) {
if (reg_map[src] < 8) {
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
+ FAIL_IF(!inst);
INC_SIZE(1 + 1);
PUSH_REG(reg_lmap[src]);
}
else {
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
+ FAIL_IF(!inst);
INC_SIZE(2 + 1);
- *buf++ = REX_B;
+ *inst++ = 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;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_FF;
+ *inst |= PUSH_rm;
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
INC_SIZE(1);
}
else {
SLJIT_ASSERT(IS_HALFWORD(srcw));
/* SLJIT_IMM. */
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
+ FAIL_IF(!inst);
INC_SIZE(5 + 1);
- *buf++ = 0x68;
- *(sljit_hw*)buf = srcw;
- buf += sizeof(sljit_hw);
+ *inst++ = PUSH_i32;
+ *(sljit_si*)inst = srcw;
+ inst += sizeof(sljit_si);
}
RET();
@@ -784,12 +752,12 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
/* Extend input */
/* --------------------------------------------------------------------- */
-static int emit_mov_int(struct sljit_compiler *compiler, int sign,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- sljit_ub* code;
- int dst_r;
+ sljit_ub* inst;
+ sljit_si dst_r;
compiler->mode32 = 0;
@@ -797,32 +765,32 @@ static int emit_mov_int(struct sljit_compiler *compiler, int sign,
return SLJIT_SUCCESS; /* Empty instruction. */
if (src & SLJIT_IMM) {
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+ if (dst <= TMP_REGISTER) {
if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
- code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
- FAIL_IF(!code);
- *code = 0xc7;
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_i32;
return SLJIT_SUCCESS;
}
return emit_load_imm64(compiler, dst, srcw);
}
compiler->mode32 = 1;
- code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
- FAIL_IF(!code);
- *code = 0xc7;
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_i32;
compiler->mode32 = 0;
return SLJIT_SUCCESS;
}
- dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_SAVED_REG3) ? dst : TMP_REGISTER;
+ dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
- if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_SAVED_REG3))
+ if ((dst & SLJIT_MEM) && (src <= TMP_REGISTER))
dst_r = src;
else {
if (sign) {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
- FAIL_IF(!code);
- *code++ = 0x63;
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst++ = MOVSXD_r_rm;
} else {
compiler->mode32 = 1;
FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw));
@@ -832,9 +800,9 @@ static int emit_mov_int(struct sljit_compiler *compiler, int sign,
if (dst & SLJIT_MEM) {
compiler->mode32 = 1;
- code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
- FAIL_IF(!code);
- *code = 0x89;
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_r;
compiler->mode32 = 0;
}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
index 0a44163802..ab98a03d2c 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
@@ -24,7 +24,7 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
{
return "x86" SLJIT_CPUINFO;
}
@@ -67,17 +67,17 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
#define TMP_REGISTER (SLJIT_NO_REGISTERS + 1)
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 2] = {
- 0, 0, 2, 1, 0, 0, 3, 6, 7, 0, 0, 4, 5
+ 0, 0, 2, 1, 0, 0, 3, 6, 7, 0, 0, 4, 5
};
#define CHECK_EXTRA_REGS(p, w, do) \
if (p >= SLJIT_TEMPORARY_EREG1 && p <= SLJIT_TEMPORARY_EREG2) { \
- w = compiler->temporaries_start + (p - SLJIT_TEMPORARY_EREG1) * sizeof(sljit_w); \
+ w = compiler->scratches_start + (p - SLJIT_TEMPORARY_EREG1) * sizeof(sljit_sw); \
p = SLJIT_MEM1(SLJIT_LOCALS_REG); \
do; \
} \
else if (p >= SLJIT_SAVED_EREG1 && p <= SLJIT_SAVED_EREG2) { \
- w = compiler->saveds_start + (p - SLJIT_SAVED_EREG1) * sizeof(sljit_w); \
+ w = compiler->saveds_start + (p - SLJIT_SAVED_EREG1) * sizeof(sljit_sw); \
p = SLJIT_MEM1(SLJIT_LOCALS_REG); \
do; \
}
@@ -95,20 +95,20 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 2] = {
#ifndef _WIN64
/* 1st passed in rdi, 2nd argument passed in rsi, 3rd in rdx. */
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
- 0, 0, 6, 1, 8, 11, 3, 15, 14, 13, 12, 4, 2, 7, 9
+ 0, 0, 6, 1, 8, 11, 3, 15, 14, 13, 12, 4, 2, 7, 9
};
/* low-map. reg_map & 0x7. */
static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
- 0, 0, 6, 1, 0, 3, 3, 7, 6, 5, 4, 4, 2, 7, 1
+ 0, 0, 6, 1, 0, 3, 3, 7, 6, 5, 4, 4, 2, 7, 1
};
#else
/* 1st passed in rcx, 2nd argument passed in rdx, 3rd in r8. */
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
- 0, 0, 2, 1, 11, 13, 3, 6, 7, 14, 12, 15, 10, 8, 9
+ 0, 0, 2, 1, 11, 13, 3, 6, 7, 14, 15, 4, 10, 8, 9
};
/* low-map. reg_map & 0x7. */
static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
- 0, 0, 2, 1, 3, 5, 3, 6, 7, 6, 4, 7, 2, 0, 1
+ 0, 0, 2, 1, 3, 5, 3, 6, 7, 6, 7, 4, 2, 0, 1
};
#endif
@@ -118,9 +118,6 @@ static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
#define REX_B 0x41
#define REX 0x40
-typedef unsigned int sljit_uhw;
-typedef int sljit_hw;
-
#define IS_HALFWORD(x) ((x) <= 0x7fffffffll && (x) >= -0x80000000ll)
#define NOT_HALFWORD(x) ((x) > 0x7fffffffll || (x) < -0x80000000ll)
@@ -129,7 +126,7 @@ typedef int sljit_hw;
#endif /* SLJIT_CONFIG_X86_32 */
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
-#define TMP_FREG (SLJIT_FLOAT_REG4 + 1)
+#define TMP_FREG (0)
#endif
/* Size flags for emit_x86_instruction: */
@@ -142,108 +139,298 @@ typedef int sljit_hw;
#define EX86_PREF_66 0x0400
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
-#define EX86_PREF_F2 0x0800
-#define EX86_SSE2 0x1000
+#define EX86_SSE2 0x0800
+#define EX86_PREF_F2 0x1000
+#define EX86_PREF_F3 0x2000
#endif
-#define INC_SIZE(s) (*buf++ = (s), compiler->size += (s))
-#define INC_CSIZE(s) (*code++ = (s), compiler->size += (s))
+/* --------------------------------------------------------------------- */
+/* Instrucion forms */
+/* --------------------------------------------------------------------- */
-#define PUSH_REG(r) (*buf++ = (0x50 + (r)))
-#define POP_REG(r) (*buf++ = (0x58 + (r)))
-#define RET() (*buf++ = (0xc3))
-#define RETN(n) (*buf++ = (0xc2), *buf++ = n, *buf++ = 0)
+#define ADD (/* BINARY */ 0 << 3)
+#define ADD_EAX_i32 0x05
+#define ADD_r_rm 0x03
+#define ADD_rm_r 0x01
+#define ADDSD_x_xm 0x58
+#define ADC (/* BINARY */ 2 << 3)
+#define ADC_EAX_i32 0x15
+#define ADC_r_rm 0x13
+#define ADC_rm_r 0x11
+#define AND (/* BINARY */ 4 << 3)
+#define AND_EAX_i32 0x25
+#define AND_r_rm 0x23
+#define AND_rm_r 0x21
+#define ANDPD_x_xm 0x54
+#define BSR_r_rm (/* GROUP_0F */ 0xbd)
+#define CALL_i32 0xe8
+#define CALL_rm (/* GROUP_FF */ 2 << 3)
+#define CDQ 0x99
+#define CMOVNE_r_rm (/* GROUP_0F */ 0x45)
+#define CMP (/* BINARY */ 7 << 3)
+#define CMP_EAX_i32 0x3d
+#define CMP_r_rm 0x3b
+#define CMP_rm_r 0x39
+#define DIV (/* GROUP_F7 */ 6 << 3)
+#define DIVSD_x_xm 0x5e
+#define INT3 0xcc
+#define IDIV (/* GROUP_F7 */ 7 << 3)
+#define IMUL (/* GROUP_F7 */ 5 << 3)
+#define IMUL_r_rm (/* GROUP_0F */ 0xaf)
+#define IMUL_r_rm_i8 0x6b
+#define IMUL_r_rm_i32 0x69
+#define JE_i8 0x74
+#define JMP_i8 0xeb
+#define JMP_i32 0xe9
+#define JMP_rm (/* GROUP_FF */ 4 << 3)
+#define LEA_r_m 0x8d
+#define MOV_r_rm 0x8b
+#define MOV_r_i32 0xb8
+#define MOV_rm_r 0x89
+#define MOV_rm_i32 0xc7
+#define MOV_rm8_i8 0xc6
+#define MOV_rm8_r8 0x88
+#define MOVSD_x_xm 0x10
+#define MOVSD_xm_x 0x11
+#define MOVSXD_r_rm 0x63
+#define MOVSX_r_rm8 (/* GROUP_0F */ 0xbe)
+#define MOVSX_r_rm16 (/* GROUP_0F */ 0xbf)
+#define MOVZX_r_rm8 (/* GROUP_0F */ 0xb6)
+#define MOVZX_r_rm16 (/* GROUP_0F */ 0xb7)
+#define MUL (/* GROUP_F7 */ 4 << 3)
+#define MULSD_x_xm 0x59
+#define NEG_rm (/* GROUP_F7 */ 3 << 3)
+#define NOP 0x90
+#define NOT_rm (/* GROUP_F7 */ 2 << 3)
+#define OR (/* BINARY */ 1 << 3)
+#define OR_r_rm 0x0b
+#define OR_EAX_i32 0x0d
+#define OR_rm_r 0x09
+#define POP_r 0x58
+#define POP_rm 0x8f
+#define POPF 0x9d
+#define PUSH_i32 0x68
+#define PUSH_r 0x50
+#define PUSH_rm (/* GROUP_FF */ 6 << 3)
+#define PUSHF 0x9c
+#define RET_near 0xc3
+#define RET_i16 0xc2
+#define SBB (/* BINARY */ 3 << 3)
+#define SBB_EAX_i32 0x1d
+#define SBB_r_rm 0x1b
+#define SBB_rm_r 0x19
+#define SAR (/* SHIFT */ 7 << 3)
+#define SHL (/* SHIFT */ 4 << 3)
+#define SHR (/* SHIFT */ 5 << 3)
+#define SUB (/* BINARY */ 5 << 3)
+#define SUB_EAX_i32 0x2d
+#define SUB_r_rm 0x2b
+#define SUB_rm_r 0x29
+#define SUBSD_x_xm 0x5c
+#define TEST_EAX_i32 0xa9
+#define TEST_rm_r 0x85
+#define UCOMISD_x_xm 0x2e
+#define XCHG_EAX_r 0x90
+#define XCHG_r_rm 0x87
+#define XOR (/* BINARY */ 6 << 3)
+#define XOR_EAX_i32 0x35
+#define XOR_r_rm 0x33
+#define XOR_rm_r 0x31
+#define XORPD_x_xm 0x57
+
+#define GROUP_0F 0x0f
+#define GROUP_F7 0xf7
+#define GROUP_FF 0xff
+#define GROUP_BINARY_81 0x81
+#define GROUP_BINARY_83 0x83
+#define GROUP_SHIFT_1 0xd1
+#define GROUP_SHIFT_N 0xc1
+#define GROUP_SHIFT_CL 0xd3
+
+#define MOD_REG 0xc0
+#define MOD_DISP8 0x40
+
+#define INC_SIZE(s) (*inst++ = (s), compiler->size += (s))
+
+#define PUSH_REG(r) (*inst++ = (PUSH_r + (r)))
+#define POP_REG(r) (*inst++ = (POP_r + (r)))
+#define RET() (*inst++ = (RET_near))
+#define RET_I16(n) (*inst++ = (RET_i16), *inst++ = n, *inst++ = 0)
/* r32, r/m32 */
-#define MOV_RM(mod, reg, rm) (*buf++ = (0x8b), *buf++ = (mod) << 6 | (reg) << 3 | (rm))
+#define MOV_RM(mod, reg, rm) (*inst++ = (MOV_r_rm), *inst++ = (mod) << 6 | (reg) << 3 | (rm))
+
+/* Multithreading does not affect these static variables, since they store
+ built-in CPU features. Therefore they can be overwritten by different threads
+ if they detect the CPU features in the same time. */
+#if (defined SLJIT_SSE2 && SLJIT_SSE2) && (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
+static sljit_si cpu_has_sse2 = -1;
+#endif
+static sljit_si cpu_has_cmov = -1;
+
+#if defined(_MSC_VER) && (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+#if _MSC_VER >= 1400
+#include <intrin.h>
+#else
+#error "MSVC does not support inline assembly in 64 bit mode"
+#endif
+#endif /* _MSC_VER && SLJIT_CONFIG_X86_64 */
+
+static void get_cpu_features(void)
+{
+ sljit_ui features;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C)
+ /* AT&T syntax. */
+ __asm__ (
+ "pushl %%ebx\n"
+ "movl $0x1, %%eax\n"
+ "cpuid\n"
+ "popl %%ebx\n"
+ "movl %%edx, %0\n"
+ : "=g" (features)
+ :
+ : "%eax", "%ecx", "%edx"
+ );
+#elif defined(_MSC_VER) || defined(__BORLANDC__)
+ /* Intel syntax. */
+ __asm {
+ mov eax, 1
+ push ebx
+ cpuid
+ pop ebx
+ mov features, edx
+ }
+#else
+# error "SLJIT_DETECT_SSE2 is not implemented for this C compiler"
+#endif
+
+#else /* SLJIT_CONFIG_X86_32 */
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C)
+ /* AT&T syntax. */
+ __asm__ (
+ "pushq %%rbx\n"
+ "movl $0x1, %%eax\n"
+ "cpuid\n"
+ "popq %%rbx\n"
+ "movl %%edx, %0\n"
+ : "=g" (features)
+ :
+ : "%rax", "%rcx", "%rdx"
+ );
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+ int CPUInfo[4];
+
+ __cpuid(CPUInfo, 1);
+ features = (sljit_ui)CPUInfo[3];
+#else
+ __asm {
+ mov eax, 1
+ push rbx
+ cpuid
+ pop rbx
+ mov features, edx
+ }
+#endif
-static sljit_ub get_jump_code(int type)
+#endif /* SLJIT_CONFIG_X86_32 */
+
+#if (defined SLJIT_SSE2 && SLJIT_SSE2) && (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
+ cpu_has_sse2 = (features >> 26) & 0x1;
+#endif
+ cpu_has_cmov = (features >> 15) & 0x1;
+}
+
+static sljit_ub get_jump_code(sljit_si type)
{
switch (type) {
case SLJIT_C_EQUAL:
case SLJIT_C_FLOAT_EQUAL:
- return 0x84;
+ return 0x84 /* je */;
case SLJIT_C_NOT_EQUAL:
case SLJIT_C_FLOAT_NOT_EQUAL:
- return 0x85;
+ return 0x85 /* jne */;
case SLJIT_C_LESS:
case SLJIT_C_FLOAT_LESS:
- return 0x82;
+ return 0x82 /* jc */;
case SLJIT_C_GREATER_EQUAL:
case SLJIT_C_FLOAT_GREATER_EQUAL:
- return 0x83;
+ return 0x83 /* jae */;
case SLJIT_C_GREATER:
case SLJIT_C_FLOAT_GREATER:
- return 0x87;
+ return 0x87 /* jnbe */;
case SLJIT_C_LESS_EQUAL:
case SLJIT_C_FLOAT_LESS_EQUAL:
- return 0x86;
+ return 0x86 /* jbe */;
case SLJIT_C_SIG_LESS:
- return 0x8c;
+ return 0x8c /* jl */;
case SLJIT_C_SIG_GREATER_EQUAL:
- return 0x8d;
+ return 0x8d /* jnl */;
case SLJIT_C_SIG_GREATER:
- return 0x8f;
+ return 0x8f /* jnle */;
case SLJIT_C_SIG_LESS_EQUAL:
- return 0x8e;
+ return 0x8e /* jle */;
case SLJIT_C_OVERFLOW:
case SLJIT_C_MUL_OVERFLOW:
- return 0x80;
+ return 0x80 /* jo */;
case SLJIT_C_NOT_OVERFLOW:
case SLJIT_C_MUL_NOT_OVERFLOW:
- return 0x81;
+ return 0x81 /* jno */;
- case SLJIT_C_FLOAT_NAN:
- return 0x8a;
+ case SLJIT_C_FLOAT_UNORDERED:
+ return 0x8a /* jp */;
- case SLJIT_C_FLOAT_NOT_NAN:
- return 0x8b;
+ case SLJIT_C_FLOAT_ORDERED:
+ return 0x8b /* jpo */;
}
return 0;
}
-static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type);
+static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type);
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_w addr, int type);
+static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si type);
#endif
-static sljit_ub* generate_near_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_ub *code, int type)
+static sljit_ub* generate_near_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_ub *code, sljit_si type)
{
- int short_jump;
+ sljit_si short_jump;
sljit_uw label_addr;
if (jump->flags & JUMP_LABEL)
label_addr = (sljit_uw)(code + jump->u.label->size);
else
label_addr = jump->u.target;
- short_jump = (sljit_w)(label_addr - (jump->addr + 2)) >= -128 && (sljit_w)(label_addr - (jump->addr + 2)) <= 127;
+ short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if ((sljit_w)(label_addr - (jump->addr + 1)) > 0x7fffffffll || (sljit_w)(label_addr - (jump->addr + 1)) < -0x80000000ll)
+ if ((sljit_sw)(label_addr - (jump->addr + 1)) > 0x7fffffffll || (sljit_sw)(label_addr - (jump->addr + 1)) < -0x80000000ll)
return generate_far_jump_code(jump, code_ptr, type);
#endif
if (type == SLJIT_JUMP) {
if (short_jump)
- *code_ptr++ = 0xeb;
+ *code_ptr++ = JMP_i8;
else
- *code_ptr++ = 0xe9;
+ *code_ptr++ = JMP_i32;
jump->addr++;
}
else if (type >= SLJIT_FAST_CALL) {
short_jump = 0;
- *code_ptr++ = 0xe8;
+ *code_ptr++ = CALL_i32;
jump->addr++;
}
else if (short_jump) {
@@ -251,20 +438,20 @@ static sljit_ub* generate_near_jump_code(struct sljit_jump *jump, sljit_ub *code
jump->addr++;
}
else {
- *code_ptr++ = 0x0f;
+ *code_ptr++ = GROUP_0F;
*code_ptr++ = get_jump_code(type);
jump->addr += 2;
}
if (short_jump) {
jump->flags |= PATCH_MB;
- code_ptr += sizeof(sljit_b);
+ code_ptr += sizeof(sljit_sb);
} else {
jump->flags |= PATCH_MW;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- code_ptr += sizeof(sljit_w);
+ code_ptr += sizeof(sljit_sw);
#else
- code_ptr += sizeof(sljit_hw);
+ code_ptr += sizeof(sljit_si);
#endif
}
@@ -323,19 +510,19 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
label = label->next;
}
else if (*buf_ptr == 1) {
- const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_w);
+ const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw);
const_ = const_->next;
}
else {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- *code_ptr++ = (*buf_ptr == 2) ? 0xe8 /* call */ : 0xe9 /* jmp */;
+ *code_ptr++ = (*buf_ptr == 2) ? CALL_i32 : JMP_i32;
buf_ptr++;
- *(sljit_w*)code_ptr = *(sljit_w*)buf_ptr - ((sljit_w)code_ptr + sizeof(sljit_w));
- code_ptr += sizeof(sljit_w);
- buf_ptr += sizeof(sljit_w) - 1;
+ *(sljit_sw*)code_ptr = *(sljit_sw*)buf_ptr - ((sljit_sw)code_ptr + sizeof(sljit_sw));
+ code_ptr += sizeof(sljit_sw);
+ buf_ptr += sizeof(sljit_sw) - 1;
#else
- code_ptr = generate_fixed_jump(code_ptr, *(sljit_w*)(buf_ptr + 1), *buf_ptr);
- buf_ptr += sizeof(sljit_w);
+ code_ptr = generate_fixed_jump(code_ptr, *(sljit_sw*)(buf_ptr + 1), *buf_ptr);
+ buf_ptr += sizeof(sljit_sw);
#endif
}
buf_ptr++;
@@ -352,29 +539,29 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = compiler->jumps;
while (jump) {
if (jump->flags & PATCH_MB) {
- SLJIT_ASSERT((sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_b))) >= -128 && (sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_b))) <= 127);
- *(sljit_ub*)jump->addr = (sljit_ub)(jump->u.label->addr - (jump->addr + sizeof(sljit_b)));
+ SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sb))) >= -128 && (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sb))) <= 127);
+ *(sljit_ub*)jump->addr = (sljit_ub)(jump->u.label->addr - (jump->addr + sizeof(sljit_sb)));
} else if (jump->flags & PATCH_MW) {
if (jump->flags & JUMP_LABEL) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- *(sljit_w*)jump->addr = (sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_w)));
+ *(sljit_sw*)jump->addr = (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sw)));
#else
- SLJIT_ASSERT((sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_hw))) >= -0x80000000ll && (sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_hw))) <= 0x7fffffffll);
- *(sljit_hw*)jump->addr = (sljit_hw)(jump->u.label->addr - (jump->addr + sizeof(sljit_hw)));
+ SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_si))) >= -0x80000000ll && (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_si))) <= 0x7fffffffll);
+ *(sljit_si*)jump->addr = (sljit_si)(jump->u.label->addr - (jump->addr + sizeof(sljit_si)));
#endif
}
else {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- *(sljit_w*)jump->addr = (sljit_w)(jump->u.target - (jump->addr + sizeof(sljit_w)));
+ *(sljit_sw*)jump->addr = (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_sw)));
#else
- SLJIT_ASSERT((sljit_w)(jump->u.target - (jump->addr + sizeof(sljit_hw))) >= -0x80000000ll && (sljit_w)(jump->u.target - (jump->addr + sizeof(sljit_hw))) <= 0x7fffffffll);
- *(sljit_hw*)jump->addr = (sljit_hw)(jump->u.target - (jump->addr + sizeof(sljit_hw)));
+ SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_si))) >= -0x80000000ll && (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_si))) <= 0x7fffffffll);
+ *(sljit_si*)jump->addr = (sljit_si)(jump->u.target - (jump->addr + sizeof(sljit_si)));
#endif
}
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
else if (jump->flags & PATCH_MD)
- *(sljit_w*)jump->addr = jump->u.label->addr;
+ *(sljit_sw*)jump->addr = jump->u.label->addr;
#endif
jump = jump->next;
@@ -391,65 +578,65 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* Operators */
/* --------------------------------------------------------------------- */
-static int emit_cum_binary(struct sljit_compiler *compiler,
+static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w);
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w);
-static int emit_non_cum_binary(struct sljit_compiler *compiler,
+static sljit_si emit_non_cum_binary(struct sljit_compiler *compiler,
sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w);
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w);
-static int emit_mov(struct sljit_compiler *compiler,
- int dst, sljit_w dstw,
- int src, sljit_w srcw);
+static sljit_si emit_mov(struct sljit_compiler *compiler,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw);
-static SLJIT_INLINE int emit_save_flags(struct sljit_compiler *compiler)
+static SLJIT_INLINE sljit_si emit_save_flags(struct sljit_compiler *compiler)
{
- sljit_ub *buf;
+ sljit_ub *inst;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 5);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
+ FAIL_IF(!inst);
INC_SIZE(5);
- *buf++ = 0x9c; /* pushfd */
#else
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 6);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 6);
+ FAIL_IF(!inst);
INC_SIZE(6);
- *buf++ = 0x9c; /* pushfq */
- *buf++ = 0x48;
+ *inst++ = REX_W;
#endif
- *buf++ = 0x8d; /* lea esp/rsp, [esp/rsp + sizeof(sljit_w)] */
- *buf++ = 0x64;
- *buf++ = 0x24;
- *buf++ = sizeof(sljit_w);
+ *inst++ = LEA_r_m; /* lea esp/rsp, [esp/rsp + sizeof(sljit_sw)] */
+ *inst++ = 0x64;
+ *inst++ = 0x24;
+ *inst++ = (sljit_ub)sizeof(sljit_sw);
+ *inst++ = PUSHF;
compiler->flags_saved = 1;
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE int emit_restore_flags(struct sljit_compiler *compiler, int keep_flags)
+static SLJIT_INLINE sljit_si emit_restore_flags(struct sljit_compiler *compiler, sljit_si keep_flags)
{
- sljit_ub *buf;
+ sljit_ub *inst;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 5);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
+ FAIL_IF(!inst);
INC_SIZE(5);
+ *inst++ = POPF;
#else
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 6);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 6);
+ FAIL_IF(!inst);
INC_SIZE(6);
- *buf++ = 0x48;
+ *inst++ = POPF;
+ *inst++ = REX_W;
#endif
- *buf++ = 0x8d; /* lea esp/rsp, [esp/rsp - sizeof(sljit_w)] */
- *buf++ = 0x64;
- *buf++ = 0x24;
- *buf++ = (sljit_ub)-(int)sizeof(sljit_w);
- *buf++ = 0x9d; /* popfd / popfq */
+ *inst++ = LEA_r_m; /* lea esp/rsp, [esp/rsp - sizeof(sljit_sw)] */
+ *inst++ = 0x64;
+ *inst++ = 0x24;
+ *inst++ = (sljit_ub)-(sljit_sb)sizeof(sljit_sw);
compiler->flags_saved = keep_flags;
return SLJIT_SUCCESS;
}
@@ -457,11 +644,17 @@ static SLJIT_INLINE int emit_restore_flags(struct sljit_compiler *compiler, int
#ifdef _WIN32
#include <malloc.h>
-static void SLJIT_CALL sljit_touch_stack(sljit_w local_size)
+static void SLJIT_CALL sljit_grow_stack(sljit_sw local_size)
{
- /* Workaround for calling _chkstk. */
+ /* Workaround for calling the internal _chkstk() function on Windows.
+ This function touches all 4k pages belongs to the requested stack space,
+ which size is passed in local_size. This is necessary on Windows where
+ the stack can only grow in 4k steps. However, this function just burn
+ CPU cycles if the stack is large enough, but you don't know it in advance.
+ I think this is a bad design even if it has some reasons. */
alloca(local_size);
}
+
#endif
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
@@ -470,79 +663,79 @@ static void SLJIT_CALL sljit_touch_stack(sljit_w local_size)
#include "sljitNativeX86_64.c"
#endif
-static int emit_mov(struct sljit_compiler *compiler,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+static sljit_si emit_mov(struct sljit_compiler *compiler,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- sljit_ub* code;
+ sljit_ub* inst;
if (dst == SLJIT_UNUSED) {
/* No destination, doesn't need to setup flags. */
if (src & SLJIT_MEM) {
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, srcw);
- FAIL_IF(!code);
- *code = 0x8b;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst = MOV_r_rm;
}
return SLJIT_SUCCESS;
}
- if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REGISTER) {
- code = emit_x86_instruction(compiler, 1, src, 0, dst, dstw);
- FAIL_IF(!code);
- *code = 0x89;
+ if (src <= TMP_REGISTER) {
+ inst = emit_x86_instruction(compiler, 1, src, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_r;
return SLJIT_SUCCESS;
}
if (src & SLJIT_IMM) {
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
+ if (dst <= TMP_REGISTER) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- return emit_do_imm(compiler, 0xb8 + reg_map[dst], srcw);
+ return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);
#else
if (!compiler->mode32) {
if (NOT_HALFWORD(srcw))
return emit_load_imm64(compiler, dst, srcw);
}
else
- return emit_do_imm32(compiler, (reg_map[dst] >= 8) ? REX_B : 0, 0xb8 + reg_lmap[dst], srcw);
+ return emit_do_imm32(compiler, (reg_map[dst] >= 8) ? REX_B : 0, MOV_r_i32 + reg_lmap[dst], srcw);
#endif
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (!compiler->mode32 && NOT_HALFWORD(srcw)) {
FAIL_IF(emit_load_imm64(compiler, TMP_REG2, srcw));
- code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, dst, dstw);
- FAIL_IF(!code);
- *code = 0x89;
+ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_r;
return SLJIT_SUCCESS;
}
#endif
- code = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, dstw);
- FAIL_IF(!code);
- *code = 0xc7;
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_i32;
return SLJIT_SUCCESS;
}
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
- code = emit_x86_instruction(compiler, 1, dst, 0, src, srcw);
- FAIL_IF(!code);
- *code = 0x8b;
+ if (dst <= TMP_REGISTER) {
+ inst = emit_x86_instruction(compiler, 1, dst, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst = MOV_r_rm;
return SLJIT_SUCCESS;
}
/* Memory to memory move. Requires two instruction. */
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, srcw);
- FAIL_IF(!code);
- *code = 0x8b;
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
- FAIL_IF(!code);
- *code = 0x89;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst = MOV_r_rm;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_r;
return SLJIT_SUCCESS;
}
#define EMIT_MOV(compiler, dst, dstw, src, srcw) \
FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
{
- sljit_ub *buf;
+ sljit_ub *inst;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- int size;
+ sljit_si size;
#endif
CHECK_ERROR();
@@ -550,16 +743,16 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
switch (GET_OPCODE(op)) {
case SLJIT_BREAKPOINT:
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
INC_SIZE(1);
- *buf = 0xcc;
+ *inst = INT3;
break;
case SLJIT_NOP:
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
INC_SIZE(1);
- *buf = 0x90;
+ *inst = NOP;
break;
case SLJIT_UMUL:
case SLJIT_SMUL:
@@ -569,14 +762,14 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
#ifdef _WIN64
SLJIT_COMPILE_ASSERT(
- reg_map[SLJIT_TEMPORARY_REG1] == 0
- && reg_map[SLJIT_TEMPORARY_REG2] == 2
+ reg_map[SLJIT_SCRATCH_REG1] == 0
+ && reg_map[SLJIT_SCRATCH_REG2] == 2
&& reg_map[TMP_REGISTER] > 7,
invalid_register_assignment_for_div_mul);
#else
SLJIT_COMPILE_ASSERT(
- reg_map[SLJIT_TEMPORARY_REG1] == 0
- && reg_map[SLJIT_TEMPORARY_REG2] < 7
+ reg_map[SLJIT_SCRATCH_REG1] == 0
+ && reg_map[SLJIT_SCRATCH_REG2] < 7
&& reg_map[TMP_REGISTER] == 2,
invalid_register_assignment_for_div_mul);
#endif
@@ -586,87 +779,86 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
op = GET_OPCODE(op);
if (op == SLJIT_UDIV) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
- EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG2, 0);
- buf = emit_x86_instruction(compiler, 1, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0);
+ EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_SCRATCH_REG2, 0);
+ inst = emit_x86_instruction(compiler, 1, SLJIT_SCRATCH_REG2, 0, SLJIT_SCRATCH_REG2, 0);
#else
- buf = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
#endif
- FAIL_IF(!buf);
- *buf = 0x33;
+ FAIL_IF(!inst);
+ *inst = XOR_r_rm;
}
if (op == SLJIT_SDIV) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
- EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG2, 0);
+ EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_SCRATCH_REG2, 0);
#endif
- /* CDQ instruction */
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
INC_SIZE(1);
- *buf = 0x99;
+ *inst = CDQ;
#else
if (compiler->mode32) {
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
INC_SIZE(1);
- *buf = 0x99;
+ *inst = CDQ;
} else {
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
INC_SIZE(2);
- *buf++ = REX_W;
- *buf = 0x99;
+ *inst++ = REX_W;
+ *inst = CDQ;
}
#endif
}
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
INC_SIZE(2);
- *buf++ = 0xf7;
- *buf = 0xc0 | ((op >= SLJIT_UDIV) ? reg_map[TMP_REGISTER] : reg_map[SLJIT_TEMPORARY_REG2]);
+ *inst++ = GROUP_F7;
+ *inst = MOD_REG | ((op >= SLJIT_UDIV) ? reg_map[TMP_REGISTER] : reg_map[SLJIT_SCRATCH_REG2]);
#else
#ifdef _WIN64
size = (!compiler->mode32 || op >= SLJIT_UDIV) ? 3 : 2;
#else
size = (!compiler->mode32) ? 3 : 2;
#endif
- buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
INC_SIZE(size);
#ifdef _WIN64
if (!compiler->mode32)
- *buf++ = REX_W | ((op >= SLJIT_UDIV) ? REX_B : 0);
+ *inst++ = REX_W | ((op >= SLJIT_UDIV) ? REX_B : 0);
else if (op >= SLJIT_UDIV)
- *buf++ = REX_B;
- *buf++ = 0xf7;
- *buf = 0xc0 | ((op >= SLJIT_UDIV) ? reg_lmap[TMP_REGISTER] : reg_lmap[SLJIT_TEMPORARY_REG2]);
+ *inst++ = REX_B;
+ *inst++ = GROUP_F7;
+ *inst = MOD_REG | ((op >= SLJIT_UDIV) ? reg_lmap[TMP_REGISTER] : reg_lmap[SLJIT_SCRATCH_REG2]);
#else
if (!compiler->mode32)
- *buf++ = REX_W;
- *buf++ = 0xf7;
- *buf = 0xc0 | reg_map[SLJIT_TEMPORARY_REG2];
+ *inst++ = REX_W;
+ *inst++ = GROUP_F7;
+ *inst = MOD_REG | reg_map[SLJIT_SCRATCH_REG2];
#endif
#endif
switch (op) {
case SLJIT_UMUL:
- *buf |= 4 << 3;
+ *inst |= MUL;
break;
case SLJIT_SMUL:
- *buf |= 5 << 3;
+ *inst |= IMUL;
break;
case SLJIT_UDIV:
- *buf |= 6 << 3;
+ *inst |= DIV;
break;
case SLJIT_SDIV:
- *buf |= 7 << 3;
+ *inst |= IDIV;
break;
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
- EMIT_MOV(compiler, SLJIT_TEMPORARY_REG2, 0, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, SLJIT_SCRATCH_REG2, 0, TMP_REGISTER, 0);
#endif
break;
}
@@ -676,20 +868,20 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int
#define ENCODE_PREFIX(prefix) \
do { \
- code = (sljit_ub*)ensure_buf(compiler, 1 + 1); \
- FAIL_IF(!code); \
- INC_CSIZE(1); \
- *code = (prefix); \
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1); \
+ FAIL_IF(!inst); \
+ INC_SIZE(1); \
+ *inst = (prefix); \
} while (0)
-static int emit_mov_byte(struct sljit_compiler *compiler, int sign,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+static sljit_si emit_mov_byte(struct sljit_compiler *compiler, sljit_si sign,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- sljit_ub* code;
- int dst_r;
+ sljit_ub* inst;
+ sljit_si dst_r;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- int work_r;
+ sljit_si work_r;
#endif
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
@@ -700,22 +892,25 @@ static int emit_mov_byte(struct sljit_compiler *compiler, int sign,
return SLJIT_SUCCESS; /* Empty instruction. */
if (src & SLJIT_IMM) {
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
+ if (dst <= TMP_REGISTER) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- return emit_do_imm(compiler, 0xb8 + reg_map[dst], srcw);
+ return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);
#else
- return emit_load_imm64(compiler, dst, srcw);
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_i32;
+ return SLJIT_SUCCESS;
#endif
}
- code = emit_x86_instruction(compiler, 1 | EX86_BYTE_ARG | EX86_NO_REXW, SLJIT_IMM, srcw, dst, dstw);
- FAIL_IF(!code);
- *code = 0xc6;
+ inst = emit_x86_instruction(compiler, 1 | EX86_BYTE_ARG | EX86_NO_REXW, SLJIT_IMM, srcw, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm8_i8;
return SLJIT_SUCCESS;
}
- dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
+ dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
- if ((dst & SLJIT_MEM) && src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) {
+ if ((dst & SLJIT_MEM) && src <= TMP_REGISTER) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
if (reg_map[src] >= 4) {
SLJIT_ASSERT(dst_r == TMP_REGISTER);
@@ -727,35 +922,34 @@ static int emit_mov_byte(struct sljit_compiler *compiler, int sign,
#endif
}
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- else if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS && reg_map[src] >= 4) {
+ else if (src <= TMP_REGISTER && reg_map[src] >= 4) {
/* src, dst are registers. */
- SLJIT_ASSERT(dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER);
+ SLJIT_ASSERT(dst >= SLJIT_SCRATCH_REG1 && dst <= TMP_REGISTER);
if (reg_map[dst] < 4) {
if (dst != src)
EMIT_MOV(compiler, dst, 0, src, 0);
- code = emit_x86_instruction(compiler, 2, dst, 0, dst, 0);
- FAIL_IF(!code);
- *code++ = 0x0f;
- *code = sign ? 0xbe : 0xb6;
+ inst = emit_x86_instruction(compiler, 2, dst, 0, dst, 0);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = sign ? MOVSX_r_rm8 : MOVZX_r_rm8;
}
else {
if (dst != src)
EMIT_MOV(compiler, dst, 0, src, 0);
if (sign) {
/* shl reg, 24 */
- code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0);
- FAIL_IF(!code);
- *code |= 0x4 << 3;
- code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0);
- FAIL_IF(!code);
- /* shr/sar reg, 24 */
- *code |= 0x7 << 3;
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0);
+ FAIL_IF(!inst);
+ *inst |= SHL;
+ /* sar reg, 24 */
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0);
+ FAIL_IF(!inst);
+ *inst |= SAR;
}
else {
- /* and dst, 0xff */
- code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 255, dst, 0);
- FAIL_IF(!code);
- *(code + 1) |= 0x4 << 3;
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 0xff, dst, 0);
+ FAIL_IF(!inst);
+ *(inst + 1) |= AND;
}
}
return SLJIT_SUCCESS;
@@ -763,74 +957,74 @@ static int emit_mov_byte(struct sljit_compiler *compiler, int sign,
#endif
else {
/* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */
- code = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);
- FAIL_IF(!code);
- *code++ = 0x0f;
- *code = sign ? 0xbe : 0xb6;
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = sign ? MOVSX_r_rm8 : MOVZX_r_rm8;
}
if (dst & SLJIT_MEM) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
if (dst_r == TMP_REGISTER) {
/* Find a non-used register, whose reg_map[src] < 4. */
- if ((dst & 0xf) == SLJIT_TEMPORARY_REG1) {
- if ((dst & 0xf0) == (SLJIT_TEMPORARY_REG2 << 4))
- work_r = SLJIT_TEMPORARY_REG3;
+ if ((dst & 0xf) == SLJIT_SCRATCH_REG1) {
+ if ((dst & 0xf0) == (SLJIT_SCRATCH_REG2 << 4))
+ work_r = SLJIT_SCRATCH_REG3;
else
- work_r = SLJIT_TEMPORARY_REG2;
+ work_r = SLJIT_SCRATCH_REG2;
}
else {
- if ((dst & 0xf0) != (SLJIT_TEMPORARY_REG1 << 4))
- work_r = SLJIT_TEMPORARY_REG1;
- else if ((dst & 0xf) == SLJIT_TEMPORARY_REG2)
- work_r = SLJIT_TEMPORARY_REG3;
+ if ((dst & 0xf0) != (SLJIT_SCRATCH_REG1 << 4))
+ work_r = SLJIT_SCRATCH_REG1;
+ else if ((dst & 0xf) == SLJIT_SCRATCH_REG2)
+ work_r = SLJIT_SCRATCH_REG3;
else
- work_r = SLJIT_TEMPORARY_REG2;
+ work_r = SLJIT_SCRATCH_REG2;
}
- if (work_r == SLJIT_TEMPORARY_REG1) {
- ENCODE_PREFIX(0x90 + reg_map[TMP_REGISTER]);
+ if (work_r == SLJIT_SCRATCH_REG1) {
+ ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REGISTER]);
}
else {
- code = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);
- FAIL_IF(!code);
- *code = 0x87;
+ inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);
+ FAIL_IF(!inst);
+ *inst = XCHG_r_rm;
}
- code = emit_x86_instruction(compiler, 1, work_r, 0, dst, dstw);
- FAIL_IF(!code);
- *code = 0x88;
+ inst = emit_x86_instruction(compiler, 1, work_r, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm8_r8;
- if (work_r == SLJIT_TEMPORARY_REG1) {
- ENCODE_PREFIX(0x90 + reg_map[TMP_REGISTER]);
+ if (work_r == SLJIT_SCRATCH_REG1) {
+ ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REGISTER]);
}
else {
- code = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);
- FAIL_IF(!code);
- *code = 0x87;
+ inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);
+ FAIL_IF(!inst);
+ *inst = XCHG_r_rm;
}
}
else {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
- FAIL_IF(!code);
- *code = 0x88;
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm8_r8;
}
#else
- code = emit_x86_instruction(compiler, 1 | EX86_REX | EX86_NO_REXW, dst_r, 0, dst, dstw);
- FAIL_IF(!code);
- *code = 0x88;
+ inst = emit_x86_instruction(compiler, 1 | EX86_REX | EX86_NO_REXW, dst_r, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm8_r8;
#endif
}
return SLJIT_SUCCESS;
}
-static int emit_mov_half(struct sljit_compiler *compiler, int sign,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+static sljit_si emit_mov_half(struct sljit_compiler *compiler, sljit_si sign,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- sljit_ub* code;
- int dst_r;
+ sljit_ub* inst;
+ sljit_si dst_r;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
compiler->mode32 = 0;
@@ -840,193 +1034,222 @@ static int emit_mov_half(struct sljit_compiler *compiler, int sign,
return SLJIT_SUCCESS; /* Empty instruction. */
if (src & SLJIT_IMM) {
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
+ if (dst <= TMP_REGISTER) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- return emit_do_imm(compiler, 0xb8 + reg_map[dst], srcw);
+ return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);
#else
- return emit_load_imm64(compiler, dst, srcw);
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_i32;
+ return SLJIT_SUCCESS;
#endif
}
- code = emit_x86_instruction(compiler, 1 | EX86_HALF_ARG | EX86_NO_REXW | EX86_PREF_66, SLJIT_IMM, srcw, dst, dstw);
- FAIL_IF(!code);
- *code = 0xc7;
+ inst = emit_x86_instruction(compiler, 1 | EX86_HALF_ARG | EX86_NO_REXW | EX86_PREF_66, SLJIT_IMM, srcw, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_i32;
return SLJIT_SUCCESS;
}
- dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
+ dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
- if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS))
+ if ((dst & SLJIT_MEM) && src <= TMP_REGISTER)
dst_r = src;
else {
- code = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);
- FAIL_IF(!code);
- *code++ = 0x0f;
- *code = sign ? 0xbf : 0xb7;
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = sign ? MOVSX_r_rm16 : MOVZX_r_rm16;
}
if (dst & SLJIT_MEM) {
- code = emit_x86_instruction(compiler, 1 | EX86_NO_REXW | EX86_PREF_66, dst_r, 0, dst, dstw);
- FAIL_IF(!code);
- *code = 0x89;
+ inst = emit_x86_instruction(compiler, 1 | EX86_NO_REXW | EX86_PREF_66, dst_r, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_r;
}
return SLJIT_SUCCESS;
}
-static int emit_unary(struct sljit_compiler *compiler, int un_index,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+static sljit_si emit_unary(struct sljit_compiler *compiler, sljit_ub opcode,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- sljit_ub* code;
+ sljit_ub* inst;
if (dst == SLJIT_UNUSED) {
EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
- code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code++ = 0xf7;
- *code |= (un_index) << 3;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_F7;
+ *inst |= opcode;
return SLJIT_SUCCESS;
}
if (dst == src && dstw == srcw) {
/* Same input and output */
- code = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
- FAIL_IF(!code);
- *code++ = 0xf7;
- *code |= (un_index) << 3;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_F7;
+ *inst |= opcode;
return SLJIT_SUCCESS;
}
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+ if (dst <= TMP_REGISTER) {
EMIT_MOV(compiler, dst, 0, src, srcw);
- code = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
- FAIL_IF(!code);
- *code++ = 0xf7;
- *code |= (un_index) << 3;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_F7;
+ *inst |= opcode;
return SLJIT_SUCCESS;
}
EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
- code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code++ = 0xf7;
- *code |= (un_index) << 3;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_F7;
+ *inst |= opcode;
EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
return SLJIT_SUCCESS;
}
-static int emit_not_with_flags(struct sljit_compiler *compiler,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+static sljit_si emit_not_with_flags(struct sljit_compiler *compiler,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- sljit_ub* code;
+ sljit_ub* inst;
if (dst == SLJIT_UNUSED) {
EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
- code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code++ = 0xf7;
- *code |= 0x2 << 3;
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code = 0x0b;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_F7;
+ *inst |= NOT_rm;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst = OR_r_rm;
return SLJIT_SUCCESS;
}
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+ if (dst <= TMP_REGISTER) {
EMIT_MOV(compiler, dst, 0, src, srcw);
- code = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
- FAIL_IF(!code);
- *code++ = 0xf7;
- *code |= 0x2 << 3;
- code = emit_x86_instruction(compiler, 1, dst, 0, dst, 0);
- FAIL_IF(!code);
- *code = 0x0b;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_F7;
+ *inst |= NOT_rm;
+ inst = emit_x86_instruction(compiler, 1, dst, 0, dst, 0);
+ FAIL_IF(!inst);
+ *inst = OR_r_rm;
return SLJIT_SUCCESS;
}
EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
- code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code++ = 0xf7;
- *code |= 0x2 << 3;
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code = 0x0b;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_F7;
+ *inst |= NOT_rm;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst = OR_r_rm;
EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
return SLJIT_SUCCESS;
}
-static int emit_clz(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+static sljit_si emit_clz(struct sljit_compiler *compiler, sljit_si op_flags,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- sljit_ub* code;
- int dst_r;
+ sljit_ub* inst;
+ sljit_si dst_r;
- SLJIT_UNUSED_ARG(op);
+ SLJIT_UNUSED_ARG(op_flags);
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
/* Just set the zero flag. */
EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
- code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code++ = 0xf7;
- *code |= 0x2 << 3;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_F7;
+ *inst |= NOT_rm;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 31, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 31, TMP_REGISTER, 0);
#else
- code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, !(op & SLJIT_INT_OP) ? 63 : 31, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, !(op_flags & SLJIT_INT_OP) ? 63 : 31, TMP_REGISTER, 0);
#endif
- FAIL_IF(!code);
- *code |= 0x5 << 3;
+ FAIL_IF(!inst);
+ *inst |= SHR;
return SLJIT_SUCCESS;
}
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
+ EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_IMM, srcw);
src = TMP_REGISTER;
srcw = 0;
}
- code = emit_x86_instruction(compiler, 2, TMP_REGISTER, 0, src, srcw);
- FAIL_IF(!code);
- *code++ = 0x0f;
- *code = 0xbd;
+ inst = emit_x86_instruction(compiler, 2, TMP_REGISTER, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = BSR_r_rm;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER)
+ if (dst <= TMP_REGISTER)
dst_r = dst;
else {
/* Find an unused temporary register. */
- if ((dst & 0xf) != SLJIT_TEMPORARY_REG1 && (dst & 0xf0) != (SLJIT_TEMPORARY_REG1 << 4))
- dst_r = SLJIT_TEMPORARY_REG1;
- else if ((dst & 0xf) != SLJIT_TEMPORARY_REG2 && (dst & 0xf0) != (SLJIT_TEMPORARY_REG2 << 4))
- dst_r = SLJIT_TEMPORARY_REG2;
+ if ((dst & 0xf) != SLJIT_SCRATCH_REG1 && (dst & 0xf0) != (SLJIT_SCRATCH_REG1 << 4))
+ dst_r = SLJIT_SCRATCH_REG1;
+ else if ((dst & 0xf) != SLJIT_SCRATCH_REG2 && (dst & 0xf0) != (SLJIT_SCRATCH_REG2 << 4))
+ dst_r = SLJIT_SCRATCH_REG2;
else
- dst_r = SLJIT_TEMPORARY_REG3;
+ dst_r = SLJIT_SCRATCH_REG3;
EMIT_MOV(compiler, dst, dstw, dst_r, 0);
}
EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, 32 + 31);
#else
- dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) ? dst : TMP_REG2;
+ dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REG2;
compiler->mode32 = 0;
- EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, !(op & SLJIT_INT_OP) ? 64 + 63 : 32 + 31);
- compiler->mode32 = op & SLJIT_INT_OP;
+ EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, !(op_flags & SLJIT_INT_OP) ? 64 + 63 : 32 + 31);
+ compiler->mode32 = op_flags & SLJIT_INT_OP;
#endif
- code = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code++ = 0x0f;
- *code = 0x45;
+ if (cpu_has_cmov == -1)
+ get_cpu_features();
+
+ if (cpu_has_cmov) {
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = CMOVNE_r_rm;
+ } else {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+
+ *inst++ = JE_i8;
+ *inst++ = 2;
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (reg_map[dst_r] << 3) | reg_map[TMP_REGISTER];
+#else
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
+ FAIL_IF(!inst);
+ INC_SIZE(5);
+
+ *inst++ = JE_i8;
+ *inst++ = 3;
+ *inst++ = REX_W | (reg_map[dst_r] >= 8 ? REX_R : 0) | (reg_map[TMP_REGISTER] >= 8 ? REX_B : 0);
+ *inst++ = MOV_r_rm;
+ *inst++ = MOD_REG | (reg_lmap[dst_r] << 3) | reg_lmap[TMP_REGISTER];
+#endif
+ }
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0);
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0);
#else
- code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op & SLJIT_INT_OP) ? 63 : 31, dst_r, 0);
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_INT_OP) ? 63 : 31, dst_r, 0);
#endif
- FAIL_IF(!code);
- *(code + 1) |= 0x6 << 3;
+ FAIL_IF(!inst);
+ *(inst + 1) |= XOR;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
if (dst & SLJIT_MEM) {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
- FAIL_IF(!code);
- *code = 0x87;
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = XCHG_r_rm;
}
#else
if (dst & SLJIT_MEM)
@@ -1035,60 +1258,80 @@ static int emit_clz(struct sljit_compiler *compiler, int op,
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- sljit_ub* code;
- int update = 0;
+ sljit_ub* inst;
+ sljit_si update = 0;
+ sljit_si op_flags = GET_ALL_FLAGS(op);
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- int dst_is_ereg = 0;
- int src_is_ereg = 0;
+ sljit_si dst_is_ereg = 0;
+ sljit_si src_is_ereg = 0;
#else
- #define src_is_ereg 0
+# define src_is_ereg 0
#endif
CHECK_ERROR();
check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- compiler->mode32 = op & SLJIT_INT_OP;
-#endif
CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);
CHECK_EXTRA_REGS(src, srcw, src_is_ereg = 1);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = op_flags & SLJIT_INT_OP;
+#endif
- if (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI) {
- op = GET_OPCODE(op);
+ op = GET_OPCODE(op);
+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
compiler->mode32 = 0;
#endif
- SLJIT_COMPILE_ASSERT(SLJIT_MOV + 7 == SLJIT_MOVU, movu_offset);
+ if (op_flags & SLJIT_INT_OP) {
+ if (src <= TMP_REGISTER && src == dst) {
+ if (!TYPE_CAST_NEEDED(op))
+ return SLJIT_SUCCESS;
+ }
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (op == SLJIT_MOV_SI && (src & SLJIT_MEM))
+ op = SLJIT_MOV_UI;
+ if (op == SLJIT_MOVU_SI && (src & SLJIT_MEM))
+ op = SLJIT_MOVU_UI;
+ if (op == SLJIT_MOV_UI && (src & SLJIT_IMM))
+ op = SLJIT_MOV_SI;
+ if (op == SLJIT_MOVU_UI && (src & SLJIT_IMM))
+ op = SLJIT_MOVU_SI;
+#endif
+ }
+
+ SLJIT_COMPILE_ASSERT(SLJIT_MOV + 8 == SLJIT_MOVU, movu_offset);
if (op >= SLJIT_MOVU) {
update = 1;
- op -= 7;
+ op -= 8;
}
if (src & SLJIT_IMM) {
switch (op) {
case SLJIT_MOV_UB:
- srcw = (unsigned char)srcw;
+ srcw = (sljit_ub)srcw;
break;
case SLJIT_MOV_SB:
- srcw = (signed char)srcw;
+ srcw = (sljit_sb)srcw;
break;
case SLJIT_MOV_UH:
- srcw = (unsigned short)srcw;
+ srcw = (sljit_uh)srcw;
break;
case SLJIT_MOV_SH:
- srcw = (signed short)srcw;
+ srcw = (sljit_sh)srcw;
break;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
case SLJIT_MOV_UI:
- srcw = (unsigned int)srcw;
+ srcw = (sljit_ui)srcw;
break;
case SLJIT_MOV_SI:
- srcw = (signed int)srcw;
+ srcw = (sljit_si)srcw;
break;
#endif
}
@@ -1099,15 +1342,15 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
}
if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & 0xf) && (srcw != 0 || (src & 0xf0) != 0)) {
- code = emit_x86_instruction(compiler, 1, src & 0xf, 0, src, srcw);
- FAIL_IF(!code);
- *code = 0x8d;
+ inst = emit_x86_instruction(compiler, 1, src & 0xf, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst = LEA_r_m;
src &= SLJIT_MEM | 0xf;
srcw = 0;
}
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI) || (src & SLJIT_MEM))) {
+ if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI || op == SLJIT_MOV_P) || (src & SLJIT_MEM))) {
SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_LOCALS_REG));
dst = TMP_REGISTER;
}
@@ -1115,6 +1358,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
switch (op) {
case SLJIT_MOV:
+ case SLJIT_MOV_P:
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
case SLJIT_MOV_UI:
case SLJIT_MOV_SI:
@@ -1122,23 +1366,23 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
break;
case SLJIT_MOV_UB:
- FAIL_IF(emit_mov_byte(compiler, 0, dst, dstw, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw));
+ FAIL_IF(emit_mov_byte(compiler, 0, dst, dstw, src, srcw));
break;
case SLJIT_MOV_SB:
- FAIL_IF(emit_mov_byte(compiler, 1, dst, dstw, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw));
+ FAIL_IF(emit_mov_byte(compiler, 1, dst, dstw, src, srcw));
break;
case SLJIT_MOV_UH:
- FAIL_IF(emit_mov_half(compiler, 0, dst, dstw, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw));
+ FAIL_IF(emit_mov_half(compiler, 0, dst, dstw, src, srcw));
break;
case SLJIT_MOV_SH:
- FAIL_IF(emit_mov_half(compiler, 1, dst, dstw, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw));
+ FAIL_IF(emit_mov_half(compiler, 1, dst, dstw, src, srcw));
break;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
case SLJIT_MOV_UI:
- FAIL_IF(emit_mov_int(compiler, 0, dst, dstw, src, (src & SLJIT_IMM) ? (unsigned int)srcw : srcw));
+ FAIL_IF(emit_mov_int(compiler, 0, dst, dstw, src, srcw));
break;
case SLJIT_MOV_SI:
- FAIL_IF(emit_mov_int(compiler, 1, dst, dstw, src, (src & SLJIT_IMM) ? (signed int)srcw : srcw));
+ FAIL_IF(emit_mov_int(compiler, 1, dst, dstw, src, srcw));
break;
#endif
}
@@ -1149,77 +1393,77 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int
#endif
if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & 0xf) && (dstw != 0 || (dst & 0xf0) != 0)) {
- code = emit_x86_instruction(compiler, 1, dst & 0xf, 0, dst, dstw);
- FAIL_IF(!code);
- *code = 0x8d;
+ inst = emit_x86_instruction(compiler, 1, dst & 0xf, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = LEA_r_m;
}
return SLJIT_SUCCESS;
}
- if (SLJIT_UNLIKELY(GET_FLAGS(op)))
+ if (SLJIT_UNLIKELY(GET_FLAGS(op_flags)))
compiler->flags_saved = 0;
- switch (GET_OPCODE(op)) {
+ switch (op) {
case SLJIT_NOT:
- if (SLJIT_UNLIKELY(op & SLJIT_SET_E))
+ if (SLJIT_UNLIKELY(op_flags & SLJIT_SET_E))
return emit_not_with_flags(compiler, dst, dstw, src, srcw);
- return emit_unary(compiler, 0x2, dst, dstw, src, srcw);
+ return emit_unary(compiler, NOT_rm, dst, dstw, src, srcw);
case SLJIT_NEG:
- if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
+ if (SLJIT_UNLIKELY(op_flags & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
FAIL_IF(emit_save_flags(compiler));
- return emit_unary(compiler, 0x3, dst, dstw, src, srcw);
+ return emit_unary(compiler, NEG_rm, dst, dstw, src, srcw);
case SLJIT_CLZ:
- if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
+ if (SLJIT_UNLIKELY(op_flags & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
FAIL_IF(emit_save_flags(compiler));
- return emit_clz(compiler, op, dst, dstw, src, srcw);
+ return emit_clz(compiler, op_flags, dst, dstw, src, srcw);
}
return SLJIT_SUCCESS;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- #undef src_is_ereg
+# undef src_is_ereg
#endif
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-#define BINARY_IMM(_op_imm_, _op_mr_, immw, arg, argw) \
+#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \
if (IS_HALFWORD(immw) || compiler->mode32) { \
- code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
- FAIL_IF(!code); \
- *(code + 1) |= (_op_imm_); \
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
+ FAIL_IF(!inst); \
+ *(inst + 1) |= (op_imm); \
} \
else { \
FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immw)); \
- code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, arg, argw); \
- FAIL_IF(!code); \
- *code = (_op_mr_); \
+ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, arg, argw); \
+ FAIL_IF(!inst); \
+ *inst = (op_mr); \
}
-#define BINARY_EAX_IMM(_op_eax_imm_, immw) \
- FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (_op_eax_imm_), immw))
+#define BINARY_EAX_IMM(op_eax_imm, immw) \
+ FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (op_eax_imm), immw))
#else
-#define BINARY_IMM(_op_imm_, _op_mr_, immw, arg, argw) \
- code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
- FAIL_IF(!code); \
- *(code + 1) |= (_op_imm_);
+#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
+ FAIL_IF(!inst); \
+ *(inst + 1) |= (op_imm);
-#define BINARY_EAX_IMM(_op_eax_imm_, immw) \
- FAIL_IF(emit_do_imm(compiler, (_op_eax_imm_), immw))
+#define BINARY_EAX_IMM(op_eax_imm, immw) \
+ FAIL_IF(emit_do_imm(compiler, (op_eax_imm), immw))
#endif
-static int emit_cum_binary(struct sljit_compiler *compiler,
+static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- sljit_ub* code;
+ sljit_ub* inst;
if (dst == SLJIT_UNUSED) {
EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
@@ -1227,9 +1471,9 @@ static int emit_cum_binary(struct sljit_compiler *compiler,
BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
}
else {
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
- FAIL_IF(!code);
- *code = op_rm;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
}
return SLJIT_SUCCESS;
}
@@ -1237,9 +1481,9 @@ static int emit_cum_binary(struct sljit_compiler *compiler,
if (dst == src1 && dstw == src1w) {
if (src2 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if ((dst == SLJIT_TEMPORARY_REG1) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+ if ((dst == SLJIT_SCRATCH_REG1) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
#else
- if ((dst == SLJIT_TEMPORARY_REG1) && (src2w > 127 || src2w < -128)) {
+ if ((dst == SLJIT_SCRATCH_REG1) && (src2w > 127 || src2w < -128)) {
#endif
BINARY_EAX_IMM(op_eax_imm, src2w);
}
@@ -1247,22 +1491,22 @@ static int emit_cum_binary(struct sljit_compiler *compiler,
BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);
}
}
- else if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
- code = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);
- FAIL_IF(!code);
- *code = op_rm;
+ else if (dst <= TMP_REGISTER) {
+ inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
}
- else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REGISTER) {
- /* Special exception for sljit_emit_cond_value. */
- code = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);
- FAIL_IF(!code);
- *code = op_mr;
+ else if (src2 <= TMP_REGISTER) {
+ /* Special exception for sljit_emit_op_flags. */
+ inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = op_mr;
}
else {
EMIT_MOV(compiler, TMP_REGISTER, 0, src2, src2w);
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
- FAIL_IF(!code);
- *code = op_mr;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = op_mr;
}
return SLJIT_SUCCESS;
}
@@ -1271,9 +1515,9 @@ static int emit_cum_binary(struct sljit_compiler *compiler,
if (dst == src2 && dstw == src2w) {
if (src1 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if ((dst == SLJIT_TEMPORARY_REG1) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
+ if ((dst == SLJIT_SCRATCH_REG1) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
#else
- if ((dst == SLJIT_TEMPORARY_REG1) && (src1w > 127 || src1w < -128)) {
+ if ((dst == SLJIT_SCRATCH_REG1) && (src1w > 127 || src1w < -128)) {
#endif
BINARY_EAX_IMM(op_eax_imm, src1w);
}
@@ -1281,35 +1525,35 @@ static int emit_cum_binary(struct sljit_compiler *compiler,
BINARY_IMM(op_imm, op_mr, src1w, dst, dstw);
}
}
- else if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
- code = emit_x86_instruction(compiler, 1, dst, dstw, src1, src1w);
- FAIL_IF(!code);
- *code = op_rm;
+ else if (dst <= TMP_REGISTER) {
+ inst = emit_x86_instruction(compiler, 1, dst, dstw, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
}
- else if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) {
- code = emit_x86_instruction(compiler, 1, src1, src1w, dst, dstw);
- FAIL_IF(!code);
- *code = op_mr;
+ else if (src1 <= TMP_REGISTER) {
+ inst = emit_x86_instruction(compiler, 1, src1, src1w, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = op_mr;
}
else {
EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
- FAIL_IF(!code);
- *code = op_mr;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = op_mr;
}
return SLJIT_SUCCESS;
}
/* General version. */
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+ if (dst <= TMP_REGISTER) {
EMIT_MOV(compiler, dst, 0, src1, src1w);
if (src2 & SLJIT_IMM) {
BINARY_IMM(op_imm, op_mr, src2w, dst, 0);
}
else {
- code = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);
- FAIL_IF(!code);
- *code = op_rm;
+ inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
}
}
else {
@@ -1319,9 +1563,9 @@ static int emit_cum_binary(struct sljit_compiler *compiler,
BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
}
else {
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
- FAIL_IF(!code);
- *code = op_rm;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
}
EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
}
@@ -1329,13 +1573,13 @@ static int emit_cum_binary(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
-static int emit_non_cum_binary(struct sljit_compiler *compiler,
+static sljit_si emit_non_cum_binary(struct sljit_compiler *compiler,
sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- sljit_ub* code;
+ sljit_ub* inst;
if (dst == SLJIT_UNUSED) {
EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
@@ -1343,9 +1587,9 @@ static int emit_non_cum_binary(struct sljit_compiler *compiler,
BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
}
else {
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
- FAIL_IF(!code);
- *code = op_rm;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
}
return SLJIT_SUCCESS;
}
@@ -1353,9 +1597,9 @@ static int emit_non_cum_binary(struct sljit_compiler *compiler,
if (dst == src1 && dstw == src1w) {
if (src2 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if ((dst == SLJIT_TEMPORARY_REG1) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+ if ((dst == SLJIT_SCRATCH_REG1) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
#else
- if ((dst == SLJIT_TEMPORARY_REG1) && (src2w > 127 || src2w < -128)) {
+ if ((dst == SLJIT_SCRATCH_REG1) && (src2w > 127 || src2w < -128)) {
#endif
BINARY_EAX_IMM(op_eax_imm, src2w);
}
@@ -1363,35 +1607,35 @@ static int emit_non_cum_binary(struct sljit_compiler *compiler,
BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);
}
}
- else if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
- code = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);
- FAIL_IF(!code);
- *code = op_rm;
+ else if (dst <= TMP_REGISTER) {
+ inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
}
- else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) {
- code = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);
- FAIL_IF(!code);
- *code = op_mr;
+ else if (src2 <= TMP_REGISTER) {
+ inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = op_mr;
}
else {
EMIT_MOV(compiler, TMP_REGISTER, 0, src2, src2w);
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
- FAIL_IF(!code);
- *code = op_mr;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = op_mr;
}
return SLJIT_SUCCESS;
}
/* General version. */
- if ((dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) && dst != src2) {
+ if (dst <= TMP_REGISTER && dst != src2) {
EMIT_MOV(compiler, dst, 0, src1, src1w);
if (src2 & SLJIT_IMM) {
BINARY_IMM(op_imm, op_mr, src2w, dst, 0);
}
else {
- code = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);
- FAIL_IF(!code);
- *code = op_rm;
+ inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
}
}
else {
@@ -1401,9 +1645,9 @@ static int emit_non_cum_binary(struct sljit_compiler *compiler,
BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
}
else {
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
- FAIL_IF(!code);
- *code = op_rm;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
}
EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
}
@@ -1411,28 +1655,28 @@ static int emit_non_cum_binary(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
-static int emit_mul(struct sljit_compiler *compiler,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+static sljit_si emit_mul(struct sljit_compiler *compiler,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- sljit_ub* code;
- int dst_r;
+ sljit_ub* inst;
+ sljit_si dst_r;
- dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER;
+ dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
/* Register destination. */
if (dst_r == src1 && !(src2 & SLJIT_IMM)) {
- code = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);
- FAIL_IF(!code);
- *code++ = 0x0f;
- *code = 0xaf;
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = IMUL_r_rm;
}
else if (dst_r == src2 && !(src1 & SLJIT_IMM)) {
- code = emit_x86_instruction(compiler, 2, dst_r, 0, src1, src1w);
- FAIL_IF(!code);
- *code++ = 0x0f;
- *code = 0xaf;
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = IMUL_r_rm;
}
else if (src1 & SLJIT_IMM) {
if (src2 & SLJIT_IMM) {
@@ -1442,42 +1686,42 @@ static int emit_mul(struct sljit_compiler *compiler,
}
if (src1w <= 127 && src1w >= -128) {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
- FAIL_IF(!code);
- *code = 0x6b;
- code = (sljit_ub*)ensure_buf(compiler, 1 + 1);
- FAIL_IF(!code);
- INC_CSIZE(1);
- *code = (sljit_b)src1w;
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = IMUL_r_rm_i8;
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
+ INC_SIZE(1);
+ *inst = (sljit_sb)src1w;
}
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
else {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
- FAIL_IF(!code);
- *code = 0x69;
- code = (sljit_ub*)ensure_buf(compiler, 1 + 4);
- FAIL_IF(!code);
- INC_CSIZE(4);
- *(sljit_w*)code = src1w;
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = IMUL_r_rm_i32;
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ *(sljit_sw*)inst = src1w;
}
#else
else if (IS_HALFWORD(src1w)) {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
- FAIL_IF(!code);
- *code = 0x69;
- code = (sljit_ub*)ensure_buf(compiler, 1 + 4);
- FAIL_IF(!code);
- INC_CSIZE(4);
- *(sljit_hw*)code = (sljit_hw)src1w;
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = IMUL_r_rm_i32;
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ *(sljit_si*)inst = (sljit_si)src1w;
}
else {
EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src1w);
if (dst_r != src2)
EMIT_MOV(compiler, dst_r, 0, src2, src2w);
- code = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
- FAIL_IF(!code);
- *code++ = 0x0f;
- *code = 0xaf;
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = IMUL_r_rm;
}
#endif
}
@@ -1485,42 +1729,42 @@ static int emit_mul(struct sljit_compiler *compiler,
/* Note: src1 is NOT immediate. */
if (src2w <= 127 && src2w >= -128) {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
- FAIL_IF(!code);
- *code = 0x6b;
- code = (sljit_ub*)ensure_buf(compiler, 1 + 1);
- FAIL_IF(!code);
- INC_CSIZE(1);
- *code = (sljit_b)src2w;
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = IMUL_r_rm_i8;
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
+ INC_SIZE(1);
+ *inst = (sljit_sb)src2w;
}
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
else {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
- FAIL_IF(!code);
- *code = 0x69;
- code = (sljit_ub*)ensure_buf(compiler, 1 + 4);
- FAIL_IF(!code);
- INC_CSIZE(4);
- *(sljit_w*)code = src2w;
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = IMUL_r_rm_i32;
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ *(sljit_sw*)inst = src2w;
}
#else
else if (IS_HALFWORD(src2w)) {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
- FAIL_IF(!code);
- *code = 0x69;
- code = (sljit_ub*)ensure_buf(compiler, 1 + 4);
- FAIL_IF(!code);
- INC_CSIZE(4);
- *(sljit_hw*)code = (sljit_hw)src2w;
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = IMUL_r_rm_i32;
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ *(sljit_si*)inst = (sljit_si)src2w;
}
else {
EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src1w);
if (dst_r != src1)
EMIT_MOV(compiler, dst_r, 0, src1, src1w);
- code = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
- FAIL_IF(!code);
- *code++ = 0x0f;
- *code = 0xaf;
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = IMUL_r_rm;
}
#endif
}
@@ -1529,10 +1773,10 @@ static int emit_mul(struct sljit_compiler *compiler,
if (ADDRESSING_DEPENDS_ON(src2, dst_r))
dst_r = TMP_REGISTER;
EMIT_MOV(compiler, dst_r, 0, src1, src1w);
- code = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);
- FAIL_IF(!code);
- *code++ = 0x0f;
- *code = 0xaf;
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = IMUL_r_rm;
}
if (dst_r == TMP_REGISTER)
@@ -1541,13 +1785,13 @@ static int emit_mul(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
-static int emit_lea_binary(struct sljit_compiler *compiler,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+static sljit_si emit_lea_binary(struct sljit_compiler *compiler,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- sljit_ub* code;
- int dst_r, done = 0;
+ sljit_ub* inst;
+ sljit_si dst_r, done = 0;
/* These cases better be left to handled by normal way. */
if (dst == src1 && dstw == src1w)
@@ -1555,40 +1799,37 @@ static int emit_lea_binary(struct sljit_compiler *compiler,
if (dst == src2 && dstw == src2w)
return SLJIT_ERR_UNSUPPORTED;
- dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER;
+ dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
- if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) {
- if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) {
- /* It is not possible to be both SLJIT_LOCALS_REG. */
- if (src1 != SLJIT_LOCALS_REG || src2 != SLJIT_LOCALS_REG) {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0);
- FAIL_IF(!code);
- *code = 0x8d;
- done = 1;
- }
+ if (src1 <= TMP_REGISTER) {
+ if (src2 <= TMP_REGISTER || src2 == TMP_REGISTER) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0);
+ FAIL_IF(!inst);
+ *inst = LEA_r_m;
+ done = 1;
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if ((src2 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src2w))) {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), (int)src2w);
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), (sljit_si)src2w);
#else
if (src2 & SLJIT_IMM) {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), src2w);
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), src2w);
#endif
- FAIL_IF(!code);
- *code = 0x8d;
+ FAIL_IF(!inst);
+ *inst = LEA_r_m;
done = 1;
}
}
- else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) {
+ else if (src2 <= TMP_REGISTER) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if ((src1 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src1w))) {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), (int)src1w);
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), (sljit_si)src1w);
#else
if (src1 & SLJIT_IMM) {
- code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), src1w);
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), src1w);
#endif
- FAIL_IF(!code);
- *code = 0x8d;
+ FAIL_IF(!inst);
+ *inst = LEA_r_m;
done = 1;
}
}
@@ -1601,37 +1842,37 @@ static int emit_lea_binary(struct sljit_compiler *compiler,
return SLJIT_ERR_UNSUPPORTED;
}
-static int emit_cmp_binary(struct sljit_compiler *compiler,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+static sljit_si emit_cmp_binary(struct sljit_compiler *compiler,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- sljit_ub* code;
+ sljit_ub* inst;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if (src1 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+ if (src1 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
#else
- if (src1 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {
+ if (src1 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {
#endif
- BINARY_EAX_IMM(0x3d, src2w);
+ BINARY_EAX_IMM(CMP_EAX_i32, src2w);
return SLJIT_SUCCESS;
}
- if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) {
+ if (src1 <= TMP_REGISTER) {
if (src2 & SLJIT_IMM) {
- BINARY_IMM(0x7 << 3, 0x39, src2w, src1, 0);
+ BINARY_IMM(CMP, CMP_rm_r, src2w, src1, 0);
}
else {
- code = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
- FAIL_IF(!code);
- *code = 0x3b;
+ inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = CMP_r_rm;
}
return SLJIT_SUCCESS;
}
- if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS && !(src1 & SLJIT_IMM)) {
- code = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
- FAIL_IF(!code);
- *code = 0x39;
+ if (src2 <= TMP_REGISTER && !(src1 & SLJIT_IMM)) {
+ inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = CMP_rm_r;
return SLJIT_SUCCESS;
}
@@ -1641,93 +1882,93 @@ static int emit_cmp_binary(struct sljit_compiler *compiler,
src1 = TMP_REGISTER;
src1w = 0;
}
- BINARY_IMM(0x7 << 3, 0x39, src2w, src1, src1w);
+ BINARY_IMM(CMP, CMP_rm_r, src2w, src1, src1w);
}
else {
EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
- FAIL_IF(!code);
- *code = 0x3b;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = CMP_r_rm;
}
return SLJIT_SUCCESS;
}
-static int emit_test_binary(struct sljit_compiler *compiler,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+static sljit_si emit_test_binary(struct sljit_compiler *compiler,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- sljit_ub* code;
+ sljit_ub* inst;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if (src1 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+ if (src1 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
#else
- if (src1 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {
+ if (src1 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {
#endif
- BINARY_EAX_IMM(0xa9, src2w);
+ BINARY_EAX_IMM(TEST_EAX_i32, src2w);
return SLJIT_SUCCESS;
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if (src2 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
+ if (src2 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
#else
- if (src2 == SLJIT_TEMPORARY_REG1 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) {
+ if (src2 == SLJIT_SCRATCH_REG1 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) {
#endif
- BINARY_EAX_IMM(0xa9, src1w);
+ BINARY_EAX_IMM(TEST_EAX_i32, src1w);
return SLJIT_SUCCESS;
}
- if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) {
+ if (src1 <= TMP_REGISTER) {
if (src2 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (IS_HALFWORD(src2w) || compiler->mode32) {
- code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
- FAIL_IF(!code);
- *code = 0xf7;
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
+ FAIL_IF(!inst);
+ *inst = GROUP_F7;
}
else {
FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
- code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, 0);
- FAIL_IF(!code);
- *code = 0x85;
+ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, 0);
+ FAIL_IF(!inst);
+ *inst = TEST_rm_r;
}
#else
- code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
- FAIL_IF(!code);
- *code = 0xf7;
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
+ FAIL_IF(!inst);
+ *inst = GROUP_F7;
#endif
}
else {
- code = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
- FAIL_IF(!code);
- *code = 0x85;
+ inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = TEST_rm_r;
}
return SLJIT_SUCCESS;
}
- if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) {
+ if (src2 <= TMP_REGISTER) {
if (src1 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (IS_HALFWORD(src1w) || compiler->mode32) {
- code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, 0);
- FAIL_IF(!code);
- *code = 0xf7;
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, 0);
+ FAIL_IF(!inst);
+ *inst = GROUP_F7;
}
else {
FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));
- code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, 0);
- FAIL_IF(!code);
- *code = 0x85;
+ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, 0);
+ FAIL_IF(!inst);
+ *inst = TEST_rm_r;
}
#else
- code = emit_x86_instruction(compiler, 1, src1, src1w, src2, 0);
- FAIL_IF(!code);
- *code = 0xf7;
+ inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, 0);
+ FAIL_IF(!inst);
+ *inst = GROUP_F7;
#endif
}
else {
- code = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
- FAIL_IF(!code);
- *code = 0x85;
+ inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = TEST_rm_r;
}
return SLJIT_SUCCESS;
}
@@ -1736,72 +1977,72 @@ static int emit_test_binary(struct sljit_compiler *compiler,
if (src2 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (IS_HALFWORD(src2w) || compiler->mode32) {
- code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code = 0xf7;
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst = GROUP_F7;
}
else {
FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
- code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code = 0x85;
+ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst = TEST_rm_r;
}
#else
- code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code = 0xf7;
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst = GROUP_F7;
#endif
}
else {
- code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
- FAIL_IF(!code);
- *code = 0x85;
+ inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = TEST_rm_r;
}
return SLJIT_SUCCESS;
}
-static int emit_shift(struct sljit_compiler *compiler,
+static sljit_si emit_shift(struct sljit_compiler *compiler,
sljit_ub mode,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- sljit_ub* code;
+ sljit_ub* inst;
if ((src2 & SLJIT_IMM) || (src2 == SLJIT_PREF_SHIFT_REG)) {
if (dst == src1 && dstw == src1w) {
- code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, dstw);
- FAIL_IF(!code);
- *code |= mode;
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, dstw);
+ FAIL_IF(!inst);
+ *inst |= mode;
return SLJIT_SUCCESS;
}
if (dst == SLJIT_UNUSED) {
EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
- code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code |= mode;
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst |= mode;
return SLJIT_SUCCESS;
}
if (dst == SLJIT_PREF_SHIFT_REG && src2 == SLJIT_PREF_SHIFT_REG) {
EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
- code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code |= mode;
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst |= mode;
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
return SLJIT_SUCCESS;
}
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+ if (dst <= TMP_REGISTER) {
EMIT_MOV(compiler, dst, 0, src1, src1w);
- code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, 0);
- FAIL_IF(!code);
- *code |= mode;
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, 0);
+ FAIL_IF(!inst);
+ *inst |= mode;
return SLJIT_SUCCESS;
}
EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
- code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code |= mode;
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst |= mode;
EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
return SLJIT_SUCCESS;
}
@@ -1809,19 +2050,19 @@ static int emit_shift(struct sljit_compiler *compiler,
if (dst == SLJIT_PREF_SHIFT_REG) {
EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
- code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code |= mode;
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst |= mode;
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
}
- else if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) {
+ else if (dst <= TMP_REGISTER && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) {
if (src1 != dst)
EMIT_MOV(compiler, dst, 0, src1, src1w);
EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_PREF_SHIFT_REG, 0);
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
- code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0);
- FAIL_IF(!code);
- *code |= mode;
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0);
+ FAIL_IF(!inst);
+ *inst |= mode;
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
}
else {
@@ -1831,18 +2072,17 @@ static int emit_shift(struct sljit_compiler *compiler,
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
#else
- /* [esp - 4] is reserved for eflags. */
- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), -(int)(2 * sizeof(sljit_w)), SLJIT_PREF_SHIFT_REG, 0);
+ /* [esp+0] contains the flags. */
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), sizeof(sljit_sw), SLJIT_PREF_SHIFT_REG, 0);
#endif
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
- code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
- FAIL_IF(!code);
- *code |= mode;
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+ FAIL_IF(!inst);
+ *inst |= mode;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);
#else
- /* [esp - 4] is reserved for eflags. */
- EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), -(int)(2 * sizeof(sljit_w)));
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), sizeof(sljit_sw));
#endif
EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
}
@@ -1850,11 +2090,11 @@ static int emit_shift(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
-static int emit_shift_with_flags(struct sljit_compiler *compiler,
- sljit_ub mode, int set_flags,
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+static sljit_si emit_shift_with_flags(struct sljit_compiler *compiler,
+ sljit_ub mode, sljit_si set_flags,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
/* The CPU does not set flags if the shift count is 0. */
if (src2 & SLJIT_IMM) {
@@ -1868,37 +2108,40 @@ static int emit_shift_with_flags(struct sljit_compiler *compiler,
if (!set_flags)
return emit_mov(compiler, dst, dstw, src1, src1w);
/* OR dst, src, 0 */
- return emit_cum_binary(compiler, 0x0b, 0x09, 0x1 << 3, 0x0d,
+ return emit_cum_binary(compiler, OR_r_rm, OR_rm_r, OR, OR_EAX_i32,
dst, dstw, src1, src1w, SLJIT_IMM, 0);
}
if (!set_flags)
return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
- if (!(dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS))
+ if (!(dst <= TMP_REGISTER))
FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0));
FAIL_IF(emit_shift(compiler,mode, dst, dstw, src1, src1w, src2, src2w));
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
+ if (dst <= TMP_REGISTER)
return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0);
return SLJIT_SUCCESS;
}
-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 sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
CHECK_ERROR();
check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- compiler->mode32 = op & SLJIT_INT_OP;
-#endif
CHECK_EXTRA_REGS(dst, dstw, (void)0);
CHECK_EXTRA_REGS(src1, src1w, (void)0);
CHECK_EXTRA_REGS(src2, src2w, (void)0);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = op & SLJIT_INT_OP;
+#endif
if (GET_OPCODE(op) >= SLJIT_MUL) {
if (SLJIT_UNLIKELY(GET_FLAGS(op)))
@@ -1912,12 +2155,12 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
if (!GET_FLAGS(op)) {
if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED)
return compiler->error;
- }
+ }
else
compiler->flags_saved = 0;
if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
FAIL_IF(emit_save_flags(compiler));
- return emit_cum_binary(compiler, 0x03, 0x01, 0x0 << 3, 0x05,
+ return emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_ADDC:
if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */
@@ -1926,7 +2169,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
FAIL_IF(emit_save_flags(compiler));
if (SLJIT_UNLIKELY(GET_FLAGS(op)))
compiler->flags_saved = 0;
- return emit_cum_binary(compiler, 0x13, 0x11, 0x2 << 3, 0x15,
+ return emit_cum_binary(compiler, ADC_r_rm, ADC_rm_r, ADC, ADC_EAX_i32,
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUB:
if (!GET_FLAGS(op)) {
@@ -1939,7 +2182,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
FAIL_IF(emit_save_flags(compiler));
if (dst == SLJIT_UNUSED)
return emit_cmp_binary(compiler, src1, src1w, src2, src2w);
- return emit_non_cum_binary(compiler, 0x2b, 0x29, 0x5 << 3, 0x2d,
+ return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUBC:
if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */
@@ -1948,36 +2191,36 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int
FAIL_IF(emit_save_flags(compiler));
if (SLJIT_UNLIKELY(GET_FLAGS(op)))
compiler->flags_saved = 0;
- return emit_non_cum_binary(compiler, 0x1b, 0x19, 0x3 << 3, 0x1d,
+ return emit_non_cum_binary(compiler, SBB_r_rm, SBB_rm_r, SBB, SBB_EAX_i32,
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_MUL:
return emit_mul(compiler, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_AND:
if (dst == SLJIT_UNUSED)
return emit_test_binary(compiler, src1, src1w, src2, src2w);
- return emit_cum_binary(compiler, 0x23, 0x21, 0x4 << 3, 0x25,
+ return emit_cum_binary(compiler, AND_r_rm, AND_rm_r, AND, AND_EAX_i32,
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_OR:
- return emit_cum_binary(compiler, 0x0b, 0x09, 0x1 << 3, 0x0d,
+ return emit_cum_binary(compiler, OR_r_rm, OR_rm_r, OR, OR_EAX_i32,
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_XOR:
- return emit_cum_binary(compiler, 0x33, 0x31, 0x6 << 3, 0x35,
+ return emit_cum_binary(compiler, XOR_r_rm, XOR_rm_r, XOR, XOR_EAX_i32,
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SHL:
- return emit_shift_with_flags(compiler, 0x4 << 3, GET_FLAGS(op),
+ return emit_shift_with_flags(compiler, SHL, GET_FLAGS(op),
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_LSHR:
- return emit_shift_with_flags(compiler, 0x5 << 3, GET_FLAGS(op),
+ return emit_shift_with_flags(compiler, SHR, GET_FLAGS(op),
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_ASHR:
- return emit_shift_with_flags(compiler, 0x7 << 3, GET_FLAGS(op),
+ return emit_shift_with_flags(compiler, SAR, GET_FLAGS(op),
dst, dstw, src1, src1w, src2, src2w);
}
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
{
check_sljit_get_register_index(reg);
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
@@ -1988,19 +2231,19 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
return reg_map[reg];
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, int size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_si size)
{
- sljit_ub *buf;
+ sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_op_custom(compiler, instruction, size);
SLJIT_ASSERT(size > 0 && size < 16);
- buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
- FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
INC_SIZE(size);
- SLJIT_MEMMOVE(buf, instruction, size);
+ SLJIT_MEMMOVE(inst, instruction, size);
return SLJIT_SUCCESS;
}
@@ -2008,112 +2251,85 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compile
/* Floating point operators */
/* --------------------------------------------------------------------- */
-#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
-static int sse2_available = 0;
-#endif
-
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
/* Alignment + 2 * 16 bytes. */
-static sljit_i sse2_data[3 + 4 + 4];
-static sljit_i *sse2_buffer;
+static sljit_si sse2_data[3 + (4 + 4) * 2];
+static sljit_si *sse2_buffer;
-static void init_compiler()
+static void init_compiler(void)
{
-#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
- int features = 0;
-#endif
-
- sse2_buffer = (sljit_i*)(((sljit_uw)sse2_data + 15) & ~0xf);
- sse2_buffer[0] = 0;
- sse2_buffer[1] = 0x80000000;
- sse2_buffer[4] = 0xffffffff;
- sse2_buffer[5] = 0x7fffffff;
-
-#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
-#ifdef __GNUC__
- /* AT&T syntax. */
- asm (
- "pushl %%ebx\n"
- "movl $0x1, %%eax\n"
- "cpuid\n"
- "popl %%ebx\n"
- "movl %%edx, %0\n"
- : "=g" (features)
- :
- : "%eax", "%ecx", "%edx"
- );
-#elif defined(_MSC_VER) || defined(__BORLANDC__)
- /* Intel syntax. */
- __asm {
- mov eax, 1
- push ebx
- cpuid
- pop ebx
- mov features, edx
- }
-#else
- #error "SLJIT_SSE2_AUTO is not implemented for this C compiler"
-#endif
- sse2_available = (features >> 26) & 0x1;
-#endif
+ sse2_buffer = (sljit_si*)(((sljit_uw)sse2_data + 15) & ~0xf);
+ /* Single precision constants. */
+ sse2_buffer[0] = 0x80000000;
+ sse2_buffer[4] = 0x7fffffff;
+ /* Double precision constants. */
+ sse2_buffer[8] = 0;
+ sse2_buffer[9] = 0x80000000;
+ sse2_buffer[12] = 0xffffffff;
+ sse2_buffer[13] = 0x7fffffff;
}
#endif
-SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
- /* Always available. */
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
+ if (cpu_has_sse2 == -1)
+ get_cpu_features();
+ return cpu_has_sse2;
+#else /* SLJIT_DETECT_SSE2 */
return 1;
+#endif /* SLJIT_DETECT_SSE2 */
+#else /* SLJIT_SSE2 */
+ return 0;
+#endif
}
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
-static int emit_sse2(struct sljit_compiler *compiler, sljit_ub opcode,
- int xmm1, int xmm2, sljit_w xmm2w)
+static sljit_si emit_sse2(struct sljit_compiler *compiler, sljit_ub opcode,
+ sljit_si single, sljit_si xmm1, sljit_si xmm2, sljit_sw xmm2w)
{
- sljit_ub *buf;
+ sljit_ub *inst;
- buf = emit_x86_instruction(compiler, 2 | EX86_PREF_F2 | EX86_SSE2, xmm1, 0, xmm2, xmm2w);
- FAIL_IF(!buf);
- *buf++ = 0x0f;
- *buf = opcode;
+ inst = emit_x86_instruction(compiler, 2 | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, xmm1, 0, xmm2, xmm2w);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = opcode;
return SLJIT_SUCCESS;
}
-static int emit_sse2_logic(struct sljit_compiler *compiler, sljit_ub opcode,
- int xmm1, int xmm2, sljit_w xmm2w)
+static sljit_si emit_sse2_logic(struct sljit_compiler *compiler, sljit_ub opcode,
+ sljit_si pref66, sljit_si xmm1, sljit_si xmm2, sljit_sw xmm2w)
{
- sljit_ub *buf;
+ sljit_ub *inst;
- buf = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2, xmm1, 0, xmm2, xmm2w);
- FAIL_IF(!buf);
- *buf++ = 0x0f;
- *buf = opcode;
+ inst = emit_x86_instruction(compiler, 2 | (pref66 ? EX86_PREF_66 : 0) | EX86_SSE2, xmm1, 0, xmm2, xmm2w);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = opcode;
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE int emit_sse2_load(struct sljit_compiler *compiler,
- int dst, int src, sljit_w srcw)
+static SLJIT_INLINE sljit_si emit_sse2_load(struct sljit_compiler *compiler,
+ sljit_si single, sljit_si dst, sljit_si src, sljit_sw srcw)
{
- return emit_sse2(compiler, 0x10, dst, src, srcw);
+ return emit_sse2(compiler, MOVSD_x_xm, single, dst, src, srcw);
}
-static SLJIT_INLINE int emit_sse2_store(struct sljit_compiler *compiler,
- int dst, sljit_w dstw, int src)
+static SLJIT_INLINE sljit_si emit_sse2_store(struct sljit_compiler *compiler,
+ sljit_si single, sljit_si dst, sljit_sw dstw, sljit_si src)
{
- return emit_sse2(compiler, 0x11, src, dst, dstw);
+ return emit_sse2(compiler, MOVSD_xm_x, single, src, dst, dstw);
}
-#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
-#else
-static int sljit_emit_sse2_fop1(struct sljit_compiler *compiler, int op,
-#endif
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
{
- int dst_r;
+ sljit_si dst_r;
CHECK_ERROR();
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
@@ -2122,61 +2338,57 @@ static int sljit_emit_sse2_fop1(struct sljit_compiler *compiler, int op,
compiler->mode32 = 1;
#endif
- if (GET_OPCODE(op) == SLJIT_FCMP) {
+ if (GET_OPCODE(op) == SLJIT_CMPD) {
compiler->flags_saved = 0;
- if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4)
+ if (dst <= SLJIT_FLOAT_REG6)
dst_r = dst;
else {
dst_r = TMP_FREG;
- FAIL_IF(emit_sse2_load(compiler, dst_r, dst, dstw));
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, dst, dstw));
}
- return emit_sse2_logic(compiler, 0x2e, dst_r, src, srcw);
+ return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_SINGLE_OP), dst_r, src, srcw);
}
- if (op == SLJIT_FMOV) {
- if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4)
- return emit_sse2_load(compiler, dst, src, srcw);
- if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4)
- return emit_sse2_store(compiler, dst, dstw, src);
- FAIL_IF(emit_sse2_load(compiler, TMP_FREG, src, srcw));
- return emit_sse2_store(compiler, dst, dstw, TMP_FREG);
+ if (op == SLJIT_MOVD) {
+ if (dst <= SLJIT_FLOAT_REG6)
+ return emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst, src, srcw);
+ if (src <= SLJIT_FLOAT_REG6)
+ return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, src);
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, TMP_FREG, src, srcw));
+ return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
}
- if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) {
+ if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG6) {
dst_r = dst;
if (dst != src)
- FAIL_IF(emit_sse2_load(compiler, dst_r, src, srcw));
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, src, srcw));
}
else {
dst_r = TMP_FREG;
- FAIL_IF(emit_sse2_load(compiler, dst_r, src, srcw));
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, src, srcw));
}
- switch (op) {
- case SLJIT_FNEG:
- FAIL_IF(emit_sse2_logic(compiler, 0x57, dst_r, SLJIT_MEM0(), (sljit_w)sse2_buffer));
+ switch (GET_OPCODE(op)) {
+ case SLJIT_NEGD:
+ FAIL_IF(emit_sse2_logic(compiler, XORPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_SINGLE_OP ? sse2_buffer : sse2_buffer + 8)));
break;
- case SLJIT_FABS:
- FAIL_IF(emit_sse2_logic(compiler, 0x54, dst_r, SLJIT_MEM0(), (sljit_w)(sse2_buffer + 4)));
+ case SLJIT_ABSD:
+ FAIL_IF(emit_sse2_logic(compiler, ANDPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_SINGLE_OP ? sse2_buffer + 4 : sse2_buffer + 12)));
break;
}
if (dst_r == TMP_FREG)
- return emit_sse2_store(compiler, dst, dstw, TMP_FREG);
+ return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
return SLJIT_SUCCESS;
}
-#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
-#else
-static int sljit_emit_sse2_fop2(struct sljit_compiler *compiler, int op,
-#endif
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
- int dst_r;
+ sljit_si dst_r;
CHECK_ERROR();
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
@@ -2185,274 +2397,73 @@ static int sljit_emit_sse2_fop2(struct sljit_compiler *compiler, int op,
compiler->mode32 = 1;
#endif
- if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) {
+ if (dst <= SLJIT_FLOAT_REG6) {
dst_r = dst;
if (dst == src1)
; /* Do nothing here. */
- else if (dst == src2 && (op == SLJIT_FADD || op == SLJIT_FMUL)) {
+ else if (dst == src2 && (op == SLJIT_ADDD || op == SLJIT_MULD)) {
/* Swap arguments. */
src2 = src1;
src2w = src1w;
}
else if (dst != src2)
- FAIL_IF(emit_sse2_load(compiler, dst_r, src1, src1w));
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, src1, src1w));
else {
dst_r = TMP_FREG;
- FAIL_IF(emit_sse2_load(compiler, TMP_FREG, src1, src1w));
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, TMP_FREG, src1, src1w));
}
}
else {
dst_r = TMP_FREG;
- FAIL_IF(emit_sse2_load(compiler, TMP_FREG, src1, src1w));
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, TMP_FREG, src1, src1w));
}
- switch (op) {
- case SLJIT_FADD:
- FAIL_IF(emit_sse2(compiler, 0x58, dst_r, src2, src2w));
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADDD:
+ FAIL_IF(emit_sse2(compiler, ADDSD_x_xm, op & SLJIT_SINGLE_OP, dst_r, src2, src2w));
break;
- case SLJIT_FSUB:
- FAIL_IF(emit_sse2(compiler, 0x5c, dst_r, src2, src2w));
+ case SLJIT_SUBD:
+ FAIL_IF(emit_sse2(compiler, SUBSD_x_xm, op & SLJIT_SINGLE_OP, dst_r, src2, src2w));
break;
- case SLJIT_FMUL:
- FAIL_IF(emit_sse2(compiler, 0x59, dst_r, src2, src2w));
+ case SLJIT_MULD:
+ FAIL_IF(emit_sse2(compiler, MULSD_x_xm, op & SLJIT_SINGLE_OP, dst_r, src2, src2w));
break;
- case SLJIT_FDIV:
- FAIL_IF(emit_sse2(compiler, 0x5e, dst_r, src2, src2w));
+ case SLJIT_DIVD:
+ FAIL_IF(emit_sse2(compiler, DIVSD_x_xm, op & SLJIT_SINGLE_OP, dst_r, src2, src2w));
break;
}
if (dst_r == TMP_FREG)
- return emit_sse2_store(compiler, dst, dstw, TMP_FREG);
+ return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
return SLJIT_SUCCESS;
}
-#endif
-
-#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) || !(defined SLJIT_SSE2 && SLJIT_SSE2)
-
-static int emit_fld(struct sljit_compiler *compiler,
- int src, sljit_w srcw)
-{
- sljit_ub *buf;
-
- if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) {
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
- FAIL_IF(!buf);
- INC_SIZE(2);
- *buf++ = 0xd9;
- *buf = 0xc0 + src - 1;
- return SLJIT_SUCCESS;
- }
-
- buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
- FAIL_IF(!buf);
- *buf = 0xdd;
- return SLJIT_SUCCESS;
-}
-
-static int emit_fop(struct sljit_compiler *compiler,
- sljit_ub st_arg, sljit_ub st_arg2,
- sljit_ub m64fp_arg, sljit_ub m64fp_arg2,
- int src, sljit_w srcw)
-{
- sljit_ub *buf;
-
- if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) {
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
- FAIL_IF(!buf);
- INC_SIZE(2);
- *buf++ = st_arg;
- *buf = st_arg2 + src;
- return SLJIT_SUCCESS;
- }
-
- buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
- FAIL_IF(!buf);
- *buf++ = m64fp_arg;
- *buf |= m64fp_arg2;
- return SLJIT_SUCCESS;
-}
-
-static int emit_fop_regs(struct sljit_compiler *compiler,
- sljit_ub st_arg, sljit_ub st_arg2,
- int src)
-{
- sljit_ub *buf;
-
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
- FAIL_IF(!buf);
- INC_SIZE(2);
- *buf++ = st_arg;
- *buf = st_arg2 + src;
- return SLJIT_SUCCESS;
-}
-
-#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
#else
-static int sljit_emit_fpu_fop1(struct sljit_compiler *compiler, int op,
-#endif
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
-{
-#if !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- sljit_ub *buf;
-#endif
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
+{
CHECK_ERROR();
+ /* Should cause an assertion fail. */
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
-
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- compiler->mode32 = 1;
-#endif
-
- if (GET_OPCODE(op) == SLJIT_FCMP) {
- compiler->flags_saved = 0;
-#if !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- FAIL_IF(emit_fld(compiler, dst, dstw));
- FAIL_IF(emit_fop(compiler, 0xd8, 0xd8, 0xdc, 0x3 << 3, src, srcw));
-
- /* Copy flags. */
- EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0);
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 3);
- FAIL_IF(!buf);
- INC_SIZE(3);
- *buf++ = 0xdf;
- *buf++ = 0xe0;
- /* Note: lahf is not supported on all x86-64 architectures. */
- *buf++ = 0x9e;
- EMIT_MOV(compiler, SLJIT_TEMPORARY_REG1, 0, TMP_REGISTER, 0);
-#else
- if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) {
- FAIL_IF(emit_fld(compiler, dst, dstw));
- FAIL_IF(emit_fop_regs(compiler, 0xdf, 0xe8, src));
- } else {
- FAIL_IF(emit_fld(compiler, src, srcw));
- FAIL_IF(emit_fld(compiler, dst + ((dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) ? 1 : 0), dstw));
- FAIL_IF(emit_fop_regs(compiler, 0xdf, 0xe8, src));
- FAIL_IF(emit_fop_regs(compiler, 0xdd, 0xd8, 0));
- }
-#endif
- return SLJIT_SUCCESS;
- }
-
- FAIL_IF(emit_fld(compiler, src, srcw));
-
- switch (op) {
- case SLJIT_FNEG:
- FAIL_IF(emit_fop_regs(compiler, 0xd9, 0xe0, 0));
- break;
- case SLJIT_FABS:
- FAIL_IF(emit_fop_regs(compiler, 0xd9, 0xe1, 0));
- break;
- }
-
- FAIL_IF(emit_fop(compiler, 0xdd, 0xd8, 0xdd, 0x3 << 3, dst, dstw));
-
- return SLJIT_SUCCESS;
+ compiler->error = SLJIT_ERR_UNSUPPORTED;
+ return SLJIT_ERR_UNSUPPORTED;
}
-#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
-#else
-static int sljit_emit_fpu_fop2(struct sljit_compiler *compiler, int op,
-#endif
- int dst, sljit_w dstw,
- int src1, sljit_w src1w,
- int src2, sljit_w src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
{
CHECK_ERROR();
+ /* Should cause an assertion fail. */
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
-
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- compiler->mode32 = 1;
-#endif
-
- if (src1 >= SLJIT_FLOAT_REG1 && src1 <= SLJIT_FLOAT_REG4 && dst == src1) {
- FAIL_IF(emit_fld(compiler, src2, src2w));
-
- switch (op) {
- case SLJIT_FADD:
- FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc0, src1));
- break;
- case SLJIT_FSUB:
- FAIL_IF(emit_fop_regs(compiler, 0xde, 0xe8, src1));
- break;
- case SLJIT_FMUL:
- FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc8, src1));
- break;
- case SLJIT_FDIV:
- FAIL_IF(emit_fop_regs(compiler, 0xde, 0xf8, src1));
- break;
- }
- return SLJIT_SUCCESS;
- }
-
- FAIL_IF(emit_fld(compiler, src1, src1w));
-
- if (src2 >= SLJIT_FLOAT_REG1 && src2 <= SLJIT_FLOAT_REG4 && dst == src2) {
- switch (op) {
- case SLJIT_FADD:
- FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc0, src2));
- break;
- case SLJIT_FSUB:
- FAIL_IF(emit_fop_regs(compiler, 0xde, 0xe0, src2));
- break;
- case SLJIT_FMUL:
- FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc8, src2));
- break;
- case SLJIT_FDIV:
- FAIL_IF(emit_fop_regs(compiler, 0xde, 0xf0, src2));
- break;
- }
- return SLJIT_SUCCESS;
- }
-
- switch (op) {
- case SLJIT_FADD:
- FAIL_IF(emit_fop(compiler, 0xd8, 0xc0, 0xdc, 0x0 << 3, src2, src2w));
- break;
- case SLJIT_FSUB:
- FAIL_IF(emit_fop(compiler, 0xd8, 0xe0, 0xdc, 0x4 << 3, src2, src2w));
- break;
- case SLJIT_FMUL:
- FAIL_IF(emit_fop(compiler, 0xd8, 0xc8, 0xdc, 0x1 << 3, src2, src2w));
- break;
- case SLJIT_FDIV:
- FAIL_IF(emit_fop(compiler, 0xd8, 0xf0, 0xdc, 0x6 << 3, src2, src2w));
- break;
- }
-
- FAIL_IF(emit_fop(compiler, 0xdd, 0xd8, 0xdd, 0x3 << 3, dst, dstw));
-
- return SLJIT_SUCCESS;
-}
-#endif
-
-#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
-
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
- int dst, sljit_w dstw,
- int src, sljit_w srcw)
-{
- if (sse2_available)
- return sljit_emit_sse2_fop1(compiler, op, dst, dstw, src, srcw);
- else
- return sljit_emit_fpu_fop1(compiler, op, dst, dstw, src, srcw);
-}
-
-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)
-{
- if (sse2_available)
- return sljit_emit_sse2_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
- else
- return sljit_emit_fpu_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ compiler->error = SLJIT_ERR_UNSUPPORTED;
+ return SLJIT_ERR_UNSUPPORTED;
}
#endif
@@ -2463,7 +2474,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, in
SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
{
- sljit_ub *buf;
+ sljit_ub *inst;
struct sljit_label *label;
CHECK_ERROR_PTR();
@@ -2481,18 +2492,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
PTR_FAIL_IF(!label);
set_label(label, compiler);
- buf = (sljit_ub*)ensure_buf(compiler, 2);
- PTR_FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 2);
+ PTR_FAIL_IF(!inst);
- *buf++ = 0;
- *buf++ = 0;
+ *inst++ = 0;
+ *inst++ = 0;
return label;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
{
- sljit_ub *buf;
+ sljit_ub *inst;
struct sljit_jump *jump;
CHECK_ERROR_PTR();
@@ -2519,23 +2530,25 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
compiler->size += (type >= SLJIT_JUMP) ? (10 + 3) : (2 + 10 + 3);
#endif
- buf = (sljit_ub*)ensure_buf(compiler, 2);
- PTR_FAIL_IF_NULL(buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 2);
+ PTR_FAIL_IF_NULL(inst);
- *buf++ = 0;
- *buf++ = type + 4;
+ *inst++ = 0;
+ *inst++ = type + 4;
return jump;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
{
- sljit_ub *code;
+ sljit_ub *inst;
struct sljit_jump *jump;
CHECK_ERROR();
check_sljit_emit_ijump(compiler, type, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
CHECK_EXTRA_REGS(src, srcw, (void)0);
+
if (SLJIT_UNLIKELY(compiler->flags_saved)) {
if (type <= SLJIT_JUMP)
FAIL_IF(emit_restore_flags(compiler, 0));
@@ -2545,31 +2558,16 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, i
if (type >= SLJIT_CALL1) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
- if (src == SLJIT_TEMPORARY_REG3) {
+ if (src == SLJIT_SCRATCH_REG3) {
EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0);
src = TMP_REGISTER;
}
- if ((src & SLJIT_MEM) && (src & 0xf) == SLJIT_LOCALS_REG && type >= SLJIT_CALL3) {
- if (src & 0xf0) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
- src = TMP_REGISTER;
- }
- else
- srcw += sizeof(sljit_w);
- }
-#else
- if ((src & SLJIT_MEM) && (src & 0xf) == SLJIT_LOCALS_REG) {
- if (src & 0xf0) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
- src = TMP_REGISTER;
- }
- else
- srcw += sizeof(sljit_w) * (type - SLJIT_CALL0);
- }
+ if (src == SLJIT_MEM1(SLJIT_LOCALS_REG) && type >= SLJIT_CALL3)
+ srcw += sizeof(sljit_sw);
#endif
#endif
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && defined(_WIN64)
- if (src == SLJIT_TEMPORARY_REG3) {
+ if (src == SLJIT_SCRATCH_REG3) {
EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0);
src = TMP_REGISTER;
}
@@ -2590,223 +2588,203 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, i
compiler->size += 10 + 3;
#endif
- code = (sljit_ub*)ensure_buf(compiler, 2);
- FAIL_IF_NULL(code);
+ inst = (sljit_ub*)ensure_buf(compiler, 2);
+ FAIL_IF_NULL(inst);
- *code++ = 0;
- *code++ = type + 4;
+ *inst++ = 0;
+ *inst++ = type + 4;
}
else {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
/* REX_W is not necessary (src is not immediate). */
compiler->mode32 = 1;
#endif
- code = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
- FAIL_IF(!code);
- *code++ = 0xff;
- *code |= (type >= SLJIT_FAST_CALL) ? (2 << 3) : (4 << 3);
+ inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_FF;
+ *inst |= (type >= SLJIT_FAST_CALL) ? CALL_rm : JMP_rm;
}
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw,
+ sljit_si type)
{
- sljit_ub *buf;
+ sljit_ub *inst;
sljit_ub cond_set = 0;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- int reg;
+ sljit_si reg;
+#else
+ /* CHECK_EXTRA_REGS migh overwrite these values. */
+ sljit_si dst_save = dst;
+ sljit_sw dstw_save = dstw;
#endif
CHECK_ERROR();
- check_sljit_emit_cond_value(compiler, op, dst, dstw, type);
+ check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
+ ADJUST_LOCAL_OFFSET(dst, dstw);
CHECK_EXTRA_REGS(dst, dstw, (void)0);
if (SLJIT_UNLIKELY(compiler->flags_saved))
- FAIL_IF(emit_restore_flags(compiler, 0));
+ FAIL_IF(emit_restore_flags(compiler, op & SLJIT_KEEP_FLAGS));
- switch (type) {
- case SLJIT_C_EQUAL:
- case SLJIT_C_FLOAT_EQUAL:
- cond_set = 0x94;
- break;
+ /* setcc = jcc + 0x10. */
+ cond_set = get_jump_code(type) + 0x10;
- case SLJIT_C_NOT_EQUAL:
- case SLJIT_C_FLOAT_NOT_EQUAL:
- cond_set = 0x95;
- break;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ reg = (op == SLJIT_MOV && dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
- case SLJIT_C_LESS:
- case SLJIT_C_FLOAT_LESS:
- cond_set = 0x92;
- break;
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4 + 4);
+ /* Set low register to conditional flag. */
+ *inst++ = (reg_map[reg] <= 7) ? REX : REX_B;
+ *inst++ = GROUP_0F;
+ *inst++ = cond_set;
+ *inst++ = MOD_REG | reg_lmap[reg];
+ *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R));
+ *inst++ = GROUP_0F;
+ *inst++ = MOVZX_r_rm8;
+ *inst = MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg];
+
+ if (reg != TMP_REGISTER)
+ return SLJIT_SUCCESS;
- case SLJIT_C_GREATER_EQUAL:
- case SLJIT_C_FLOAT_GREATER_EQUAL:
- cond_set = 0x93;
- break;
+ if (GET_OPCODE(op) < SLJIT_ADD) {
+ compiler->mode32 = GET_OPCODE(op) != SLJIT_MOV;
+ return emit_mov(compiler, dst, dstw, TMP_REGISTER, 0);
+ }
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->skip_checks = 1;
+#endif
+ return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REGISTER, 0);
+#else /* SLJIT_CONFIG_X86_64 */
+ if (GET_OPCODE(op) < SLJIT_ADD && dst <= TMP_REGISTER) {
+ if (reg_map[dst] <= 4) {
+ /* Low byte is accessible. */
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3);
+ FAIL_IF(!inst);
+ INC_SIZE(3 + 3);
+ /* Set low byte to conditional flag. */
+ *inst++ = GROUP_0F;
+ *inst++ = cond_set;
+ *inst++ = MOD_REG | reg_map[dst];
- case SLJIT_C_GREATER:
- case SLJIT_C_FLOAT_GREATER:
- cond_set = 0x97;
- break;
+ *inst++ = GROUP_0F;
+ *inst++ = MOVZX_r_rm8;
+ *inst = MOD_REG | (reg_map[dst] << 3) | reg_map[dst];
+ return SLJIT_SUCCESS;
+ }
- case SLJIT_C_LESS_EQUAL:
- case SLJIT_C_FLOAT_LESS_EQUAL:
- cond_set = 0x96;
- break;
+ /* Low byte is not accessible. */
+ if (cpu_has_cmov == -1)
+ get_cpu_features();
- case SLJIT_C_SIG_LESS:
- cond_set = 0x9c;
- break;
+ if (cpu_has_cmov) {
+ EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_IMM, 1);
+ /* a xor reg, reg operation would overwrite the flags. */
+ EMIT_MOV(compiler, dst, 0, SLJIT_IMM, 0);
- case SLJIT_C_SIG_GREATER_EQUAL:
- cond_set = 0x9d;
- break;
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 3);
+ FAIL_IF(!inst);
+ INC_SIZE(3);
- case SLJIT_C_SIG_GREATER:
- cond_set = 0x9f;
- break;
+ *inst++ = GROUP_0F;
+ /* cmovcc = setcc - 0x50. */
+ *inst++ = cond_set - 0x50;
+ *inst++ = MOD_REG | (reg_map[dst] << 3) | reg_map[TMP_REGISTER];
+ return SLJIT_SUCCESS;
+ }
- case SLJIT_C_SIG_LESS_EQUAL:
- cond_set = 0x9e;
- break;
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);
+ FAIL_IF(!inst);
+ INC_SIZE(1 + 3 + 3 + 1);
+ *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
+ /* Set al to conditional flag. */
+ *inst++ = GROUP_0F;
+ *inst++ = cond_set;
+ *inst++ = MOD_REG | 0 /* eax */;
- case SLJIT_C_OVERFLOW:
- case SLJIT_C_MUL_OVERFLOW:
- cond_set = 0x90;
- break;
+ *inst++ = GROUP_0F;
+ *inst++ = MOVZX_r_rm8;
+ *inst++ = MOD_REG | (reg_map[dst] << 3) | 0 /* eax */;
+ *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
+ return SLJIT_SUCCESS;
+ }
- case SLJIT_C_NOT_OVERFLOW:
- case SLJIT_C_MUL_NOT_OVERFLOW:
- cond_set = 0x91;
- break;
+ /* Set TMP_REGISTER to the bit. */
+ inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);
+ FAIL_IF(!inst);
+ INC_SIZE(1 + 3 + 3 + 1);
+ *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
+ /* Set al to conditional flag. */
+ *inst++ = GROUP_0F;
+ *inst++ = cond_set;
+ *inst++ = MOD_REG | 0 /* eax */;
- case SLJIT_C_FLOAT_NAN:
- cond_set = 0x9a;
- break;
+ *inst++ = GROUP_0F;
+ *inst++ = MOVZX_r_rm8;
+ *inst++ = MOD_REG | (0 << 3) /* eax */ | 0 /* eax */;
- case SLJIT_C_FLOAT_NOT_NAN:
- cond_set = 0x9b;
- break;
- }
+ *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- reg = (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER;
+ if (GET_OPCODE(op) < SLJIT_ADD)
+ return emit_mov(compiler, dst, dstw, TMP_REGISTER, 0);
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 4 + 4);
- FAIL_IF(!buf);
- INC_SIZE(4 + 4);
- /* Set low register to conditional flag. */
- *buf++ = (reg_map[reg] <= 7) ? 0x40 : REX_B;
- *buf++ = 0x0f;
- *buf++ = cond_set;
- *buf++ = 0xC0 | reg_lmap[reg];
- *buf++ = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R));
- *buf++ = 0x0f;
- *buf++ = 0xb6;
- *buf = 0xC0 | (reg_lmap[reg] << 3) | reg_lmap[reg];
-
- if (reg == TMP_REGISTER) {
- if (op == SLJIT_MOV) {
- compiler->mode32 = 0;
- EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
- }
- else {
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
- compiler->skip_checks = 1;
+ compiler->skip_checks = 1;
#endif
- return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REGISTER, 0);
- }
- }
-#else
- if (op == SLJIT_MOV) {
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_TEMPORARY_REG3) {
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3);
- FAIL_IF(!buf);
- INC_SIZE(3 + 3);
- /* Set low byte to conditional flag. */
- *buf++ = 0x0f;
- *buf++ = cond_set;
- *buf++ = 0xC0 | reg_map[dst];
-
- *buf++ = 0x0f;
- *buf++ = 0xb6;
- *buf = 0xC0 | (reg_map[dst] << 3) | reg_map[dst];
- }
- else {
- EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0);
-
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3);
- FAIL_IF(!buf);
- INC_SIZE(3 + 3);
- /* Set al to conditional flag. */
- *buf++ = 0x0f;
- *buf++ = cond_set;
- *buf++ = 0xC0;
-
- *buf++ = 0x0f;
- *buf++ = 0xb6;
- if (dst >= SLJIT_SAVED_REG1 && dst <= SLJIT_NO_REGISTERS)
- *buf = 0xC0 | (reg_map[dst] << 3);
- else {
- *buf = 0xC0;
- EMIT_MOV(compiler, dst, dstw, SLJIT_TEMPORARY_REG1, 0);
- }
+ return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REGISTER, 0);
+#endif /* SLJIT_CONFIG_X86_64 */
+}
- EMIT_MOV(compiler, SLJIT_TEMPORARY_REG1, 0, TMP_REGISTER, 0);
- }
- }
- else {
- if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_TEMPORARY_REG3) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, dst, 0);
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 3);
- FAIL_IF(!buf);
- INC_SIZE(3);
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
+{
+ CHECK_ERROR();
+ check_sljit_get_local_base(compiler, dst, dstw, offset);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
- *buf++ = 0x0f;
- *buf++ = cond_set;
- *buf++ = 0xC0 | reg_map[dst];
- }
- else {
- EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0);
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
- buf = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3 + 1);
- FAIL_IF(!buf);
- INC_SIZE(3 + 3 + 1);
- /* Set al to conditional flag. */
- *buf++ = 0x0f;
- *buf++ = cond_set;
- *buf++ = 0xC0;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+#endif
- *buf++ = 0x0f;
- *buf++ = 0xb6;
- *buf++ = 0xC0;
+ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_LOCALS_REG), offset);
- *buf++ = 0x90 + reg_map[TMP_REGISTER];
- }
-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
- compiler->skip_checks = 1;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (NOT_HALFWORD(offset)) {
+ FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, offset));
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ SLJIT_ASSERT(emit_lea_binary(compiler, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REGISTER, 0) != SLJIT_ERR_UNSUPPORTED);
+ return compiler->error;
+#else
+ return emit_lea_binary(compiler, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REGISTER, 0);
#endif
- return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REGISTER, 0);
}
#endif
- return SLJIT_SUCCESS;
+ if (offset != 0)
+ return emit_lea_binary(compiler, dst, dstw, SLJIT_LOCALS_REG, 0, SLJIT_IMM, offset);
+ return emit_mov(compiler, dst, dstw, SLJIT_LOCALS_REG, 0);
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
{
- sljit_ub *buf;
+ sljit_ub *inst;
struct sljit_const *const_;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- int reg;
+ sljit_si reg;
#endif
CHECK_ERROR_PTR();
check_sljit_emit_const(compiler, dst, dstw, init_value);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
CHECK_EXTRA_REGS(dst, dstw, (void)0);
@@ -2816,7 +2794,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
compiler->mode32 = 0;
- reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER;
+ reg = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
if (emit_load_imm64(compiler, reg, init_value))
return NULL;
@@ -2828,11 +2806,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
return NULL;
#endif
- buf = (sljit_ub*)ensure_buf(compiler, 2);
- PTR_FAIL_IF(!buf);
+ inst = (sljit_ub*)ensure_buf(compiler, 2);
+ PTR_FAIL_IF(!inst);
- *buf++ = 0;
- *buf++ = 1;
+ *inst++ = 0;
+ *inst++ = 1;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (reg == TMP_REGISTER && dst != SLJIT_UNUSED)
@@ -2846,13 +2824,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
{
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- *(sljit_w*)addr = new_addr - (addr + 4);
+ *(sljit_sw*)addr = new_addr - (addr + 4);
#else
*(sljit_uw*)addr = new_addr;
#endif
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
{
- *(sljit_w*)addr = new_constant;
+ *(sljit_sw*)addr = new_constant;
}
diff --git a/src/3rdparty/pcre/sljit/sljitUtils.c b/src/3rdparty/pcre/sljit/sljitUtils.c
index f3b52fece7..1f023fa644 100644
--- a/src/3rdparty/pcre/sljit/sljitUtils.c
+++ b/src/3rdparty/pcre/sljit/sljitUtils.c
@@ -30,7 +30,37 @@
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) || (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
-#ifdef _WIN32
+#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
+
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+
+static SLJIT_INLINE void allocator_grab_lock(void)
+{
+ /* Always successful. */
+}
+
+static SLJIT_INLINE void allocator_release_lock(void)
+{
+ /* Always successful. */
+}
+
+#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
+
+#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
+
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
+{
+ /* Always successful. */
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
+{
+ /* Always successful. */
+}
+
+#endif /* SLJIT_UTIL_GLOBAL_LOCK */
+
+#elif defined(_WIN32) /* SLJIT_SINGLE_THREADED */
#include "windows.h"
@@ -76,10 +106,10 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
#else /* _WIN32 */
-#include "pthread.h"
-
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+#include <pthread.h>
+
static pthread_mutex_t allocator_mutex = PTHREAD_MUTEX_INITIALIZER;
static SLJIT_INLINE void allocator_grab_lock(void)
@@ -96,6 +126,8 @@ static SLJIT_INLINE void allocator_release_lock(void)
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
+#include <pthread.h>
+
static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
@@ -116,17 +148,57 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
/* Stack */
/* ------------------------------------------------------------------------ */
-#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
+#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
#ifdef _WIN32
#include "windows.h"
#else
+/* Provides mmap function. */
#include <sys/mman.h>
+/* For detecting the page size. */
#include <unistd.h>
+
+#ifndef MAP_ANON
+
+#include <fcntl.h>
+
+/* Some old systems does not have MAP_ANON. */
+static sljit_si dev_zero = -1;
+
+#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
+
+static SLJIT_INLINE sljit_si open_dev_zero(void)
+{
+ dev_zero = open("/dev/zero", O_RDWR);
+ return dev_zero < 0;
+}
+
+#else /* SLJIT_SINGLE_THREADED */
+
+#include <pthread.h>
+
+static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static SLJIT_INLINE sljit_si open_dev_zero(void)
+{
+ pthread_mutex_lock(&dev_zero_mutex);
+ dev_zero = open("/dev/zero", O_RDWR);
+ pthread_mutex_unlock(&dev_zero_mutex);
+ return dev_zero < 0;
+}
+
+#endif /* SLJIT_SINGLE_THREADED */
+
#endif
+#endif
+
+#endif /* SLJIT_UTIL_STACK || SLJIT_EXECUTABLE_ALLOCATOR */
+
+#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
+
/* Planning to make it even more clever in the future. */
-static sljit_w sljit_page_align = 0;
+static sljit_sw sljit_page_align = 0;
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit)
{
@@ -165,7 +237,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
return NULL;
#ifdef _WIN32
- base.ptr = VirtualAlloc(0, max_limit, MEM_RESERVE, PAGE_READWRITE);
+ base.ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
if (!base.ptr) {
SLJIT_FREE(stack);
return NULL;
@@ -178,7 +250,17 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
return NULL;
}
#else
- base.ptr = mmap(0, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+#ifdef MAP_ANON
+ base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+#else
+ if (dev_zero < 0) {
+ if (open_dev_zero()) {
+ SLJIT_FREE(stack);
+ return NULL;
+ }
+ }
+ base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
+#endif
if (base.ptr == MAP_FAILED) {
SLJIT_FREE(stack);
return NULL;
@@ -203,7 +285,7 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* st
SLJIT_FREE(stack);
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
+SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
{
sljit_uw aligned_old_limit;
sljit_uw aligned_new_limit;
@@ -232,10 +314,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stac
}
aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
+ /* If madvise is available, we release the unnecessary space. */
+#if defined(POSIX_MADV_DONTNEED)
if (aligned_new_limit < aligned_old_limit)
-#if defined(__QNXNTO__) || defined(__LSB_VERSION__)
posix_madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, POSIX_MADV_DONTNEED);
-#else
+#elif defined(MADV_DONTNEED)
+ if (aligned_new_limit < aligned_old_limit)
madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED);
#endif
stack->limit = new_limit;