initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
137
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c
vendored
Normal file
137
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
/*
|
||||
On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a
|
||||
version where it's OK to have more than one JIT block or where MAP_JIT is
|
||||
required.
|
||||
On non-macOS systems, returns MAP_JIT if it is defined.
|
||||
*/
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if (defined(TARGET_OS_OSX) && TARGET_OS_OSX) || (TARGET_OS_MAC && !TARGET_OS_IPHONE)
|
||||
|
||||
#if defined(SLJIT_CONFIG_X86) && SLJIT_CONFIG_X86
|
||||
|
||||
#include <sys/utsname.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
|
||||
|
||||
#ifdef MAP_JIT
|
||||
#define SLJIT_MAP_JIT (get_map_jit_flag())
|
||||
static SLJIT_INLINE int get_map_jit_flag(void)
|
||||
{
|
||||
size_t page_size;
|
||||
void *ptr;
|
||||
struct utsname name;
|
||||
static int map_jit_flag = -1;
|
||||
|
||||
if (map_jit_flag < 0) {
|
||||
map_jit_flag = 0;
|
||||
uname(&name);
|
||||
|
||||
/* Kernel version for 10.14.0 (Mojave) or later */
|
||||
if (atoi(name.release) >= 18) {
|
||||
page_size = get_page_alignment() + 1;
|
||||
/* Only use MAP_JIT if a hardened runtime is used */
|
||||
ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
|
||||
if (ptr != MAP_FAILED)
|
||||
munmap(ptr, page_size);
|
||||
else
|
||||
map_jit_flag = MAP_JIT;
|
||||
}
|
||||
}
|
||||
return map_jit_flag;
|
||||
}
|
||||
#else /* !defined(MAP_JIT) */
|
||||
#define SLJIT_MAP_JIT (0)
|
||||
#endif
|
||||
|
||||
#elif defined(SLJIT_CONFIG_ARM) && SLJIT_CONFIG_ARM
|
||||
|
||||
#include <AvailabilityMacros.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define SLJIT_MAP_JIT (MAP_JIT)
|
||||
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \
|
||||
apple_update_wx_flags(enable_exec)
|
||||
|
||||
static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 110000
|
||||
if (__builtin_available(macos 11, *))
|
||||
#endif /* BigSur */
|
||||
pthread_jit_write_protect_np(enable_exec);
|
||||
}
|
||||
|
||||
#elif defined(SLJIT_CONFIG_PPC) && SLJIT_CONFIG_PPC
|
||||
|
||||
#define SLJIT_MAP_JIT (0)
|
||||
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
|
||||
|
||||
#else
|
||||
#error "Unsupported architecture"
|
||||
#endif /* SLJIT_CONFIG */
|
||||
|
||||
#else /* !TARGET_OS_OSX */
|
||||
|
||||
#ifdef MAP_JIT
|
||||
#define SLJIT_MAP_JIT (MAP_JIT)
|
||||
#else
|
||||
#define SLJIT_MAP_JIT (0)
|
||||
#endif
|
||||
|
||||
#endif /* TARGET_OS_OSX */
|
||||
|
||||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
void *retval;
|
||||
int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
|
||||
int flags = MAP_PRIVATE;
|
||||
int fd = -1;
|
||||
|
||||
flags |= MAP_ANON | SLJIT_MAP_JIT;
|
||||
|
||||
retval = mmap(NULL, size, prot, flags, fd, 0);
|
||||
if (retval == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(retval, (uint8_t *)retval + size, 0);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
|
||||
{
|
||||
munmap(chunk, size);
|
||||
}
|
||||
|
||||
#include "sljitExecAllocatorCore.c"
|
327
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c
vendored
Normal file
327
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
This file contains a simple executable memory allocator
|
||||
|
||||
It is assumed, that executable code blocks are usually medium (or sometimes
|
||||
large) memory blocks, and the allocator is not too frequently called (less
|
||||
optimized than other allocators). Thus, using it as a generic allocator is
|
||||
not suggested.
|
||||
|
||||
How does it work:
|
||||
Memory is allocated in continuous memory areas called chunks by alloc_chunk()
|
||||
Chunk format:
|
||||
[ block ][ block ] ... [ block ][ block terminator ]
|
||||
|
||||
All blocks and the block terminator is started with block_header. The block
|
||||
header contains the size of the previous and the next block. These sizes
|
||||
can also contain special values.
|
||||
Block size:
|
||||
0 - The block is a free_block, with a different size member.
|
||||
1 - The block is a block terminator.
|
||||
n - The block is used at the moment, and the value contains its size.
|
||||
Previous block size:
|
||||
0 - This is the first block of the memory chunk.
|
||||
n - The size of the previous block.
|
||||
|
||||
Using these size values we can go forward or backward on the block chain.
|
||||
The unused blocks are stored in a chain list pointed by free_blocks. This
|
||||
list is useful if we need to find a suitable memory area when the allocator
|
||||
is called.
|
||||
|
||||
When a block is freed, the new free block is connected to its adjacent free
|
||||
blocks if possible.
|
||||
|
||||
[ free block ][ used block ][ free block ]
|
||||
and "used block" is freed, the three blocks are connected together:
|
||||
[ one big free block ]
|
||||
*/
|
||||
|
||||
/* Expected functions:
|
||||
alloc_chunk / free_chunk :
|
||||
* allocate executable system memory chunks
|
||||
* the size is always divisible by CHUNK_SIZE
|
||||
SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK :
|
||||
* provided as part of sljitUtils
|
||||
* only the allocator requires this lock, sljit is fully thread safe
|
||||
as it only uses local variables
|
||||
|
||||
Supported defines:
|
||||
SLJIT_HAS_CHUNK_HEADER - (optional) sljit_chunk_header is defined
|
||||
SLJIT_HAS_EXECUTABLE_OFFSET - (optional) has executable offset data
|
||||
SLJIT_UPDATE_WX_FLAGS - (optional) update WX flags
|
||||
*/
|
||||
|
||||
#ifdef SLJIT_HAS_CHUNK_HEADER
|
||||
#define CHUNK_HEADER_SIZE (sizeof(struct sljit_chunk_header))
|
||||
#else /* !SLJIT_HAS_CHUNK_HEADER */
|
||||
#define CHUNK_HEADER_SIZE 0
|
||||
#endif /* SLJIT_HAS_CHUNK_HEADER */
|
||||
|
||||
#ifndef SLJIT_UPDATE_WX_FLAGS
|
||||
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
|
||||
#endif /* SLJIT_UPDATE_WX_FLAGS */
|
||||
|
||||
#ifndef CHUNK_SIZE
|
||||
/* 64 KByte if not specified. */
|
||||
#define CHUNK_SIZE (sljit_uw)0x10000
|
||||
#endif /* CHUNK_SIZE */
|
||||
|
||||
struct block_header {
|
||||
sljit_uw size;
|
||||
sljit_uw prev_size;
|
||||
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
|
||||
sljit_sw executable_offset;
|
||||
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
|
||||
};
|
||||
|
||||
struct free_block {
|
||||
struct block_header header;
|
||||
struct free_block *next;
|
||||
struct free_block *prev;
|
||||
sljit_uw size;
|
||||
};
|
||||
|
||||
#define AS_BLOCK_HEADER(base, offset) \
|
||||
((struct block_header*)(((sljit_u8*)base) + offset))
|
||||
#define AS_FREE_BLOCK(base, offset) \
|
||||
((struct free_block*)(((sljit_u8*)base) + offset))
|
||||
#define MEM_START(base) ((void*)((base) + 1))
|
||||
#define CHUNK_MASK (~(CHUNK_SIZE - 1))
|
||||
#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7u) & ~(sljit_uw)7)
|
||||
#define CHUNK_EXTRA_SIZE (sizeof(struct block_header) + CHUNK_HEADER_SIZE)
|
||||
|
||||
static struct free_block* free_blocks;
|
||||
static sljit_uw allocated_size;
|
||||
static sljit_uw total_size;
|
||||
|
||||
static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)
|
||||
{
|
||||
free_block->header.size = 0;
|
||||
free_block->size = size;
|
||||
|
||||
free_block->next = free_blocks;
|
||||
free_block->prev = NULL;
|
||||
if (free_blocks)
|
||||
free_blocks->prev = free_block;
|
||||
free_blocks = free_block;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)
|
||||
{
|
||||
if (free_block->next)
|
||||
free_block->next->prev = free_block->prev;
|
||||
|
||||
if (free_block->prev)
|
||||
free_block->prev->next = free_block->next;
|
||||
else {
|
||||
SLJIT_ASSERT(free_blocks == free_block);
|
||||
free_blocks = free_block->next;
|
||||
}
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
|
||||
{
|
||||
struct block_header *header;
|
||||
struct block_header *next_header;
|
||||
struct free_block *free_block;
|
||||
sljit_uw chunk_size;
|
||||
|
||||
#ifdef SLJIT_HAS_CHUNK_HEADER
|
||||
struct sljit_chunk_header *chunk_header;
|
||||
#else /* !SLJIT_HAS_CHUNK_HEADER */
|
||||
void *chunk_header;
|
||||
#endif /* SLJIT_HAS_CHUNK_HEADER */
|
||||
|
||||
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
|
||||
sljit_sw executable_offset;
|
||||
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
|
||||
|
||||
if (size < (64 - sizeof(struct block_header)))
|
||||
size = (64 - sizeof(struct block_header));
|
||||
size = ALIGN_SIZE(size);
|
||||
|
||||
SLJIT_ALLOCATOR_LOCK();
|
||||
free_block = free_blocks;
|
||||
while (free_block) {
|
||||
if (free_block->size >= size) {
|
||||
chunk_size = free_block->size;
|
||||
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
|
||||
if (chunk_size > size + 64) {
|
||||
/* We just cut a block from the end of the free block. */
|
||||
chunk_size -= size;
|
||||
free_block->size = chunk_size;
|
||||
header = AS_BLOCK_HEADER(free_block, chunk_size);
|
||||
header->prev_size = chunk_size;
|
||||
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
|
||||
header->executable_offset = free_block->header.executable_offset;
|
||||
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
|
||||
AS_BLOCK_HEADER(header, size)->prev_size = size;
|
||||
} else {
|
||||
sljit_remove_free_block(free_block);
|
||||
header = (struct block_header*)free_block;
|
||||
size = chunk_size;
|
||||
}
|
||||
allocated_size += size;
|
||||
header->size = size;
|
||||
SLJIT_ALLOCATOR_UNLOCK();
|
||||
return MEM_START(header);
|
||||
}
|
||||
free_block = free_block->next;
|
||||
}
|
||||
|
||||
chunk_size = (size + CHUNK_EXTRA_SIZE + CHUNK_SIZE - 1) & CHUNK_MASK;
|
||||
|
||||
chunk_header = alloc_chunk(chunk_size);
|
||||
if (!chunk_header) {
|
||||
SLJIT_ALLOCATOR_UNLOCK();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
|
||||
executable_offset = (sljit_sw)((sljit_u8*)chunk_header->executable - (sljit_u8*)chunk_header);
|
||||
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
|
||||
|
||||
chunk_size -= CHUNK_EXTRA_SIZE;
|
||||
total_size += chunk_size;
|
||||
|
||||
header = (struct block_header*)(((sljit_u8*)chunk_header) + CHUNK_HEADER_SIZE);
|
||||
|
||||
header->prev_size = 0;
|
||||
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
|
||||
header->executable_offset = executable_offset;
|
||||
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
|
||||
|
||||
if (chunk_size > size + 64) {
|
||||
/* Cut the allocated space into a free and a used block. */
|
||||
allocated_size += size;
|
||||
header->size = size;
|
||||
chunk_size -= size;
|
||||
|
||||
free_block = AS_FREE_BLOCK(header, size);
|
||||
free_block->header.prev_size = size;
|
||||
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
|
||||
free_block->header.executable_offset = executable_offset;
|
||||
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
|
||||
sljit_insert_free_block(free_block, chunk_size);
|
||||
next_header = AS_BLOCK_HEADER(free_block, chunk_size);
|
||||
} else {
|
||||
/* All space belongs to this allocation. */
|
||||
allocated_size += chunk_size;
|
||||
header->size = chunk_size;
|
||||
next_header = AS_BLOCK_HEADER(header, chunk_size);
|
||||
}
|
||||
next_header->size = 1;
|
||||
next_header->prev_size = chunk_size;
|
||||
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
|
||||
next_header->executable_offset = executable_offset;
|
||||
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
|
||||
SLJIT_ALLOCATOR_UNLOCK();
|
||||
return MEM_START(header);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void *ptr)
|
||||
{
|
||||
struct block_header *header;
|
||||
struct free_block *free_block;
|
||||
|
||||
SLJIT_ALLOCATOR_LOCK();
|
||||
header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));
|
||||
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
|
||||
header = AS_BLOCK_HEADER(header, -header->executable_offset);
|
||||
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
|
||||
allocated_size -= header->size;
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
|
||||
|
||||
/* 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_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);
|
||||
header->prev_size = free_block->size;
|
||||
} else {
|
||||
free_block = (struct free_block*)header;
|
||||
sljit_insert_free_block(free_block, header->size);
|
||||
}
|
||||
|
||||
header = AS_BLOCK_HEADER(free_block, free_block->size);
|
||||
if (SLJIT_UNLIKELY(!header->size)) {
|
||||
free_block->size += ((struct free_block*)header)->size;
|
||||
sljit_remove_free_block((struct free_block*)header);
|
||||
header = AS_BLOCK_HEADER(free_block, free_block->size);
|
||||
header->prev_size = free_block->size;
|
||||
}
|
||||
|
||||
/* The whole chunk is free. */
|
||||
if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {
|
||||
/* If this block is freed, we still have (allocated_size / 2) free space. */
|
||||
if (total_size - free_block->size > (allocated_size * 3 / 2)) {
|
||||
total_size -= free_block->size;
|
||||
sljit_remove_free_block(free_block);
|
||||
free_chunk(free_block, free_block->size + CHUNK_EXTRA_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);
|
||||
SLJIT_ALLOCATOR_UNLOCK();
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
|
||||
{
|
||||
struct free_block* free_block;
|
||||
struct free_block* next_free_block;
|
||||
|
||||
SLJIT_ALLOCATOR_LOCK();
|
||||
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
|
||||
|
||||
free_block = free_blocks;
|
||||
while (free_block) {
|
||||
next_free_block = free_block->next;
|
||||
if (!free_block->header.prev_size &&
|
||||
AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) {
|
||||
total_size -= free_block->size;
|
||||
sljit_remove_free_block(free_block);
|
||||
free_chunk(free_block, free_block->size + CHUNK_EXTRA_SIZE);
|
||||
}
|
||||
free_block = next_free_block;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(total_size || (!total_size && !free_blocks));
|
||||
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);
|
||||
SLJIT_ALLOCATOR_UNLOCK();
|
||||
}
|
||||
|
||||
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code)
|
||||
{
|
||||
return ((struct block_header*)SLJIT_CODE_TO_PTR(code))[-1].executable_offset;
|
||||
}
|
||||
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
|
89
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c
vendored
Normal file
89
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/procctl.h>
|
||||
|
||||
#ifdef PROC_WXMAP_CTL
|
||||
static SLJIT_INLINE int sljit_is_wx_block(void)
|
||||
{
|
||||
static int wx_block = -1;
|
||||
if (wx_block < 0) {
|
||||
int sljit_wx_enable = PROC_WX_MAPPINGS_PERMIT;
|
||||
wx_block = !!procctl(P_PID, 0, PROC_WXMAP_CTL, &sljit_wx_enable);
|
||||
}
|
||||
return wx_block;
|
||||
}
|
||||
|
||||
#define SLJIT_IS_WX_BLOCK sljit_is_wx_block()
|
||||
#else /* !PROC_WXMAP_CTL */
|
||||
#define SLJIT_IS_WX_BLOCK (1)
|
||||
#endif /* PROC_WXMAP_CTL */
|
||||
|
||||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
void *retval;
|
||||
int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
|
||||
int flags = MAP_PRIVATE;
|
||||
int fd = -1;
|
||||
|
||||
#ifdef PROT_MAX
|
||||
prot |= PROT_MAX(prot);
|
||||
#endif
|
||||
|
||||
#ifdef MAP_ANON
|
||||
flags |= MAP_ANON;
|
||||
#else /* !MAP_ANON */
|
||||
if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero()))
|
||||
return NULL;
|
||||
|
||||
fd = dev_zero;
|
||||
#endif /* MAP_ANON */
|
||||
|
||||
retry:
|
||||
retval = mmap(NULL, size, prot, flags, fd, 0);
|
||||
if (retval == MAP_FAILED) {
|
||||
if (!SLJIT_IS_WX_BLOCK)
|
||||
goto retry;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* HardenedBSD's mmap lies, so check permissions again. */
|
||||
if (mprotect(retval, size, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) {
|
||||
munmap(retval, size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
|
||||
{
|
||||
munmap(chunk, size);
|
||||
}
|
||||
|
||||
#include "sljitExecAllocatorCore.c"
|
62
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c
vendored
Normal file
62
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
void *retval;
|
||||
int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
|
||||
int flags = MAP_PRIVATE;
|
||||
int fd = -1;
|
||||
|
||||
#ifdef PROT_MAX
|
||||
prot |= PROT_MAX(prot);
|
||||
#endif
|
||||
|
||||
#ifdef MAP_ANON
|
||||
flags |= MAP_ANON;
|
||||
#else /* !MAP_ANON */
|
||||
if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero()))
|
||||
return NULL;
|
||||
|
||||
fd = dev_zero;
|
||||
#endif /* MAP_ANON */
|
||||
|
||||
retval = mmap(NULL, size, prot, flags, fd, 0);
|
||||
if (retval == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
|
||||
{
|
||||
munmap(chunk, size);
|
||||
}
|
||||
|
||||
#include "sljitExecAllocatorCore.c"
|
40
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c
vendored
Normal file
40
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
|
||||
|
||||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(size);
|
||||
VirtualFree(chunk, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
#include "sljitExecAllocatorCore.c"
|
72
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c
vendored
Normal file
72
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define SLJIT_HAS_CHUNK_HEADER
|
||||
#define SLJIT_HAS_EXECUTABLE_OFFSET
|
||||
|
||||
struct sljit_chunk_header {
|
||||
void *executable;
|
||||
};
|
||||
|
||||
/*
|
||||
* MAP_REMAPDUP is a NetBSD extension available sinde 8.0, make sure to
|
||||
* adjust your feature macros (ex: -D_NETBSD_SOURCE) as needed
|
||||
*/
|
||||
static SLJIT_INLINE struct sljit_chunk_header* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
struct sljit_chunk_header *retval;
|
||||
|
||||
retval = (struct sljit_chunk_header *)mmap(NULL, size,
|
||||
PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC),
|
||||
MAP_ANON | MAP_SHARED, -1, 0);
|
||||
|
||||
if (retval == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
retval->executable = mremap(retval, size, NULL, size, MAP_REMAPDUP);
|
||||
if (retval->executable == MAP_FAILED) {
|
||||
munmap((void *)retval, size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mprotect(retval->executable, size, PROT_READ | PROT_EXEC) == -1) {
|
||||
munmap(retval->executable, size);
|
||||
munmap((void *)retval, size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
|
||||
{
|
||||
struct sljit_chunk_header *header = ((struct sljit_chunk_header *)chunk) - 1;
|
||||
|
||||
munmap(header->executable, size);
|
||||
munmap((void *)header, size);
|
||||
}
|
||||
|
||||
#include "sljitExecAllocatorCore.c"
|
172
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c
vendored
Normal file
172
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define SLJIT_HAS_CHUNK_HEADER
|
||||
#define SLJIT_HAS_EXECUTABLE_OFFSET
|
||||
|
||||
struct sljit_chunk_header {
|
||||
void *executable;
|
||||
};
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef O_NOATIME
|
||||
#define O_NOATIME 0
|
||||
#endif
|
||||
|
||||
/* this is a linux extension available since kernel 3.11 */
|
||||
#ifndef O_TMPFILE
|
||||
#define O_TMPFILE 0x404000
|
||||
#endif
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
char *secure_getenv(const char *name);
|
||||
int mkostemp(char *template, int flags);
|
||||
#endif
|
||||
|
||||
static SLJIT_INLINE int create_tempfile(void)
|
||||
{
|
||||
int fd;
|
||||
char tmp_name[256];
|
||||
size_t tmp_name_len = 0;
|
||||
char *dir;
|
||||
struct stat st;
|
||||
#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
|
||||
mode_t mode;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MEMFD_CREATE
|
||||
/* this is a GNU extension, make sure to use -D_GNU_SOURCE */
|
||||
fd = memfd_create("sljit", MFD_CLOEXEC);
|
||||
if (fd != -1) {
|
||||
fchmod(fd, 0);
|
||||
return fd;
|
||||
}
|
||||
#endif
|
||||
|
||||
dir = secure_getenv("TMPDIR");
|
||||
|
||||
if (dir) {
|
||||
size_t len = strlen(dir);
|
||||
if (len > 0 && len < sizeof(tmp_name)) {
|
||||
if ((stat(dir, &st) == 0) && S_ISDIR(st.st_mode)) {
|
||||
memcpy(tmp_name, dir, len + 1);
|
||||
tmp_name_len = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef P_tmpdir
|
||||
if (!tmp_name_len) {
|
||||
tmp_name_len = strlen(P_tmpdir);
|
||||
if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name))
|
||||
strcpy(tmp_name, P_tmpdir);
|
||||
}
|
||||
#endif
|
||||
if (!tmp_name_len) {
|
||||
strcpy(tmp_name, "/tmp");
|
||||
tmp_name_len = 4;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name));
|
||||
|
||||
if (tmp_name_len > 1 && tmp_name[tmp_name_len - 1] == '/')
|
||||
tmp_name[--tmp_name_len] = '\0';
|
||||
|
||||
fd = open(tmp_name, O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, 0);
|
||||
if (fd != -1)
|
||||
return fd;
|
||||
|
||||
if (tmp_name_len >= sizeof(tmp_name) - 7)
|
||||
return -1;
|
||||
|
||||
strcpy(tmp_name + tmp_name_len, "/XXXXXX");
|
||||
#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
|
||||
mode = umask(0777);
|
||||
#endif
|
||||
fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME);
|
||||
#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
|
||||
umask(mode);
|
||||
#else
|
||||
fchmod(fd, 0);
|
||||
#endif
|
||||
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
if (unlink(tmp_name)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE struct sljit_chunk_header* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
struct sljit_chunk_header *retval;
|
||||
int fd;
|
||||
|
||||
fd = create_tempfile();
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
|
||||
if (ftruncate(fd, (off_t)size)) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retval = (struct sljit_chunk_header *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
|
||||
if (retval == MAP_FAILED) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);
|
||||
|
||||
if (retval->executable == MAP_FAILED) {
|
||||
munmap((void *)retval, size);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
|
||||
{
|
||||
struct sljit_chunk_header *header = ((struct sljit_chunk_header *)chunk) - 1;
|
||||
|
||||
munmap(header->executable, size);
|
||||
munmap((void *)header, size);
|
||||
}
|
||||
|
||||
#include "sljitExecAllocatorCore.c"
|
141
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c
vendored
Normal file
141
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
This file contains a simple W^X executable memory allocator
|
||||
|
||||
In *NIX, MAP_ANON is required (that is considered a feature) so make
|
||||
sure to set the right availability macros for your system or the code
|
||||
will fail to build.
|
||||
|
||||
If your system doesn't support mapping of anonymous pages (ex: IRIX) it
|
||||
is also likely that it doesn't need this allocator and should be using
|
||||
the standard one instead.
|
||||
|
||||
It allocates a separate map for each code block and may waste a lot of
|
||||
memory, because whatever was requested, will be rounded up to the page
|
||||
size (minimum 4KB, but could be even bigger).
|
||||
|
||||
It changes the page permissions (RW <-> RX) as needed and therefore, if you
|
||||
will be updating the code after it has been generated, need to make sure to
|
||||
block any concurrent execution, or could result in a SIGBUS, that could
|
||||
even manifest itself at a different address than the one that was being
|
||||
modified.
|
||||
|
||||
Only use if you are unable to use the regular allocator because of security
|
||||
restrictions and adding exceptions to your application or the system are
|
||||
not possible.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \
|
||||
sljit_update_wx_flags((from), (to), (enable_exec))
|
||||
|
||||
#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
|
||||
#include <pthread.h>
|
||||
#define SLJIT_SE_LOCK() pthread_mutex_lock(&se_lock)
|
||||
#define SLJIT_SE_UNLOCK() pthread_mutex_unlock(&se_lock)
|
||||
#else
|
||||
#define SLJIT_SE_LOCK()
|
||||
#define SLJIT_SE_UNLOCK()
|
||||
#endif /* !SLJIT_SINGLE_THREADED */
|
||||
|
||||
#define SLJIT_WX_IS_BLOCK(ptr, size) generic_check_is_wx_block(ptr, size)
|
||||
|
||||
static SLJIT_INLINE int generic_check_is_wx_block(void *ptr, sljit_uw size)
|
||||
{
|
||||
if (SLJIT_LIKELY(!mprotect(ptr, size, PROT_EXEC)))
|
||||
return !!mprotect(ptr, size, PROT_READ | PROT_WRITE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
|
||||
{
|
||||
#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
|
||||
static pthread_mutex_t se_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
static int wx_block = -1;
|
||||
int prot = PROT_READ | PROT_WRITE;
|
||||
sljit_uw* ptr;
|
||||
|
||||
if (SLJIT_UNLIKELY(wx_block > 0))
|
||||
return NULL;
|
||||
|
||||
#ifdef PROT_MAX
|
||||
prot |= PROT_MAX(PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
#endif
|
||||
|
||||
size += sizeof(sljit_uw);
|
||||
ptr = (sljit_uw*)mmap(NULL, size, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
|
||||
if (ptr == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
if (SLJIT_UNLIKELY(wx_block < 0)) {
|
||||
SLJIT_SE_LOCK();
|
||||
wx_block = SLJIT_WX_IS_BLOCK(ptr, size);
|
||||
SLJIT_SE_UNLOCK();
|
||||
if (SLJIT_UNLIKELY(wx_block)) {
|
||||
munmap((void *)ptr, size);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
*ptr++ = size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#undef SLJIT_SE_UNLOCK
|
||||
#undef SLJIT_SE_LOCK
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
|
||||
{
|
||||
sljit_uw *start_ptr = ((sljit_uw*)ptr) - 1;
|
||||
munmap((void*)start_ptr, *start_ptr);
|
||||
}
|
||||
|
||||
static void sljit_update_wx_flags(void *from, void *to, int enable_exec)
|
||||
{
|
||||
sljit_uw page_mask = (sljit_uw)get_page_alignment();
|
||||
sljit_uw start = (sljit_uw)from;
|
||||
sljit_uw end = (sljit_uw)to;
|
||||
int prot = PROT_READ | (enable_exec ? PROT_EXEC : PROT_WRITE);
|
||||
|
||||
SLJIT_ASSERT(start < end);
|
||||
|
||||
start &= ~page_mask;
|
||||
end = (end + page_mask) & ~page_mask;
|
||||
|
||||
mprotect((void*)start, end - start, prot);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
|
||||
{
|
||||
/* This allocator does not keep unused memory for future allocations. */
|
||||
}
|
102
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c
vendored
Normal file
102
thirdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
This file contains a simple W^X executable memory allocator
|
||||
|
||||
In *NIX, MAP_ANON is required (that is considered a feature) so make
|
||||
sure to set the right availability macros for your system or the code
|
||||
will fail to build.
|
||||
|
||||
If your system doesn't support mapping of anonymous pages (ex: IRIX) it
|
||||
is also likely that it doesn't need this allocator and should be using
|
||||
the standard one instead.
|
||||
|
||||
It allocates a separate map for each code block and may waste a lot of
|
||||
memory, because whatever was requested, will be rounded up to the page
|
||||
size (minimum 4KB, but could be even bigger).
|
||||
|
||||
It changes the page permissions (RW <-> RX) as needed and therefore, if you
|
||||
will be updating the code after it has been generated, need to make sure to
|
||||
block any concurrent execution, or could result in a SIGBUS, that could
|
||||
even manifest itself at a different address than the one that was being
|
||||
modified.
|
||||
|
||||
Only use if you are unable to use the regular allocator because of security
|
||||
restrictions and adding exceptions to your application or the system are
|
||||
not possible.
|
||||
*/
|
||||
|
||||
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \
|
||||
sljit_update_wx_flags((from), (to), (enable_exec))
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
|
||||
{
|
||||
sljit_uw *ptr;
|
||||
|
||||
size += sizeof(sljit_uw);
|
||||
ptr = (sljit_uw*)VirtualAlloc(NULL, size,
|
||||
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
|
||||
*ptr++ = size;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
|
||||
{
|
||||
sljit_uw start = (sljit_uw)ptr - sizeof(sljit_uw);
|
||||
#if defined(SLJIT_DEBUG) && SLJIT_DEBUG
|
||||
sljit_uw page_mask = (sljit_uw)get_page_alignment();
|
||||
|
||||
SLJIT_ASSERT(!(start & page_mask));
|
||||
#endif
|
||||
VirtualFree((void*)start, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec)
|
||||
{
|
||||
DWORD oldprot;
|
||||
sljit_uw page_mask = (sljit_uw)get_page_alignment();
|
||||
sljit_uw start = (sljit_uw)from;
|
||||
sljit_uw end = (sljit_uw)to;
|
||||
DWORD prot = enable_exec ? PAGE_EXECUTE : PAGE_READWRITE;
|
||||
|
||||
SLJIT_ASSERT(start < end);
|
||||
|
||||
start &= ~page_mask;
|
||||
end = (end + page_mask) & ~page_mask;
|
||||
|
||||
VirtualProtect((void*)start, end - start, prot, &oldprot);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
|
||||
{
|
||||
/* This allocator does not keep unused memory for future allocations. */
|
||||
}
|
142
thirdparty/pcre2/deps/sljit/sljit_src/sljitConfig.h
vendored
Normal file
142
thirdparty/pcre2/deps/sljit/sljit_src/sljitConfig.h
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SLJIT_CONFIG_H_
|
||||
#define SLJIT_CONFIG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*
|
||||
This file contains the basic configuration options for the SLJIT compiler
|
||||
and their default values. These options can be overridden in the
|
||||
sljitConfigPre.h header file when SLJIT_HAVE_CONFIG_PRE is set to a
|
||||
non-zero value.
|
||||
*/
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Utilities */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Implements a stack like data structure (by using mmap / VirtualAlloc */
|
||||
/* or a custom allocator). */
|
||||
#ifndef SLJIT_UTIL_STACK
|
||||
/* Enabled by default */
|
||||
#define SLJIT_UTIL_STACK 1
|
||||
#endif /* SLJIT_UTIL_STACK */
|
||||
|
||||
/* Uses user provided allocator to allocate the stack (see SLJIT_UTIL_STACK) */
|
||||
#ifndef SLJIT_UTIL_SIMPLE_STACK_ALLOCATION
|
||||
/* Disabled by default */
|
||||
#define SLJIT_UTIL_SIMPLE_STACK_ALLOCATION 0
|
||||
#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */
|
||||
|
||||
/* Single threaded application. Does not require any locks. */
|
||||
#ifndef SLJIT_SINGLE_THREADED
|
||||
/* Disabled by default. */
|
||||
#define SLJIT_SINGLE_THREADED 0
|
||||
#endif /* SLJIT_SINGLE_THREADED */
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Configuration */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* If SLJIT_STD_MACROS_DEFINED is not defined, the application should
|
||||
define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMCPY, and NULL. */
|
||||
#ifndef SLJIT_STD_MACROS_DEFINED
|
||||
/* Disabled by default. */
|
||||
#define SLJIT_STD_MACROS_DEFINED 0
|
||||
#endif /* SLJIT_STD_MACROS_DEFINED */
|
||||
|
||||
/* Executable code allocation:
|
||||
If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should
|
||||
define SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC.
|
||||
Optionally, depending on the implementation used for the allocator,
|
||||
SLJIT_EXEC_OFFSET and SLJIT_UPDATE_WX_FLAGS might also be needed. */
|
||||
#ifndef SLJIT_EXECUTABLE_ALLOCATOR
|
||||
/* Enabled by default. */
|
||||
#define SLJIT_EXECUTABLE_ALLOCATOR 1
|
||||
|
||||
/* When SLJIT_PROT_EXECUTABLE_ALLOCATOR is enabled SLJIT uses
|
||||
an allocator which does not set writable and executable
|
||||
permission flags at the same time.
|
||||
Instead, it creates a shared memory segment (usually backed by a file)
|
||||
and maps it twice, with different permissions, depending on the use
|
||||
case.
|
||||
The trade-off is increased use of virtual memory, incompatibility with
|
||||
fork(), and some possible additional security risks by the use of
|
||||
publicly accessible files for the generated code. */
|
||||
#ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR
|
||||
/* Disabled by default. */
|
||||
#define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0
|
||||
#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
/* When SLJIT_WX_EXECUTABLE_ALLOCATOR is enabled SLJIT uses an
|
||||
allocator which does not set writable and executable permission
|
||||
flags at the same time.
|
||||
Instead, it creates a new independent map on each invocation and
|
||||
switches permissions at the underlying pages as needed.
|
||||
The trade-off is increased memory use and degraded performance. */
|
||||
#ifndef SLJIT_WX_EXECUTABLE_ALLOCATOR
|
||||
/* Disabled by default. */
|
||||
#define SLJIT_WX_EXECUTABLE_ALLOCATOR 0
|
||||
#endif /* SLJIT_WX_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
#endif /* !SLJIT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
/* Return with error when an invalid argument is passed. */
|
||||
#ifndef SLJIT_ARGUMENT_CHECKS
|
||||
/* Disabled by default */
|
||||
#define SLJIT_ARGUMENT_CHECKS 0
|
||||
#endif /* SLJIT_ARGUMENT_CHECKS */
|
||||
|
||||
/* Debug checks (assertions, etc.). */
|
||||
#ifndef SLJIT_DEBUG
|
||||
/* Enabled by default */
|
||||
#define SLJIT_DEBUG 1
|
||||
#endif /* SLJIT_DEBUG */
|
||||
|
||||
/* Verbose operations. */
|
||||
#ifndef SLJIT_VERBOSE
|
||||
/* Enabled by default */
|
||||
#define SLJIT_VERBOSE 1
|
||||
#endif /* SLJIT_VERBOSE */
|
||||
|
||||
/*
|
||||
SLJIT_IS_FPU_AVAILABLE
|
||||
The availability of the FPU can be controlled by SLJIT_IS_FPU_AVAILABLE.
|
||||
zero value - FPU is NOT present.
|
||||
nonzero value - FPU is present.
|
||||
*/
|
||||
|
||||
/* For further configurations, see the beginning of sljitConfigInternal.h */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SLJIT_CONFIG_H_ */
|
188
thirdparty/pcre2/deps/sljit/sljit_src/sljitConfigCPU.h
vendored
Normal file
188
thirdparty/pcre2/deps/sljit/sljit_src/sljitConfigCPU.h
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SLJIT_CONFIG_CPU_H_
|
||||
#define SLJIT_CONFIG_CPU_H_
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Architecture */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Architecture selection. */
|
||||
/* #define SLJIT_CONFIG_X86_32 1 */
|
||||
/* #define SLJIT_CONFIG_X86_64 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_V6 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_V7 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_THUMB2 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_64 1 */
|
||||
/* #define SLJIT_CONFIG_PPC_32 1 */
|
||||
/* #define SLJIT_CONFIG_PPC_64 1 */
|
||||
/* #define SLJIT_CONFIG_MIPS_32 1 */
|
||||
/* #define SLJIT_CONFIG_MIPS_64 1 */
|
||||
/* #define SLJIT_CONFIG_RISCV_32 1 */
|
||||
/* #define SLJIT_CONFIG_RISCV_64 1 */
|
||||
/* #define SLJIT_CONFIG_S390X 1 */
|
||||
/* #define SLJIT_CONFIG_LOONGARCH_64 */
|
||||
|
||||
/* #define SLJIT_CONFIG_AUTO 1 */
|
||||
/* #define SLJIT_CONFIG_UNSUPPORTED 1 */
|
||||
|
||||
/*****************/
|
||||
/* Sanity check. */
|
||||
/*****************/
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
+ (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|
||||
+ (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) \
|
||||
+ (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
+ (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|
||||
+ (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
+ (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_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||
+ (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
|
||||
+ (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
|
||||
+ (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
|
||||
+ (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) \
|
||||
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|
||||
+ (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
|
||||
#error "Multiple architectures are selected"
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
&& !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|
||||
&& !(defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) \
|
||||
&& !(defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
&& !(defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|
||||
&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
&& !(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_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||
&& !(defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
|
||||
&& !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
|
||||
&& !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
|
||||
&& !(defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) \
|
||||
&& !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \
|
||||
&& !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
|
||||
#if defined SLJIT_CONFIG_AUTO && !SLJIT_CONFIG_AUTO
|
||||
#error "An architecture must be selected"
|
||||
#else /* SLJIT_CONFIG_AUTO */
|
||||
#define SLJIT_CONFIG_AUTO 1
|
||||
#endif /* !SLJIT_CONFIG_AUTO */
|
||||
#endif /* !SLJIT_CONFIG */
|
||||
|
||||
/********************************************************/
|
||||
/* Automatic CPU detection (requires compiler support). */
|
||||
/********************************************************/
|
||||
|
||||
#if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
|
||||
#ifndef _WIN32
|
||||
|
||||
#if defined(__i386__) || defined(__i386)
|
||||
#define SLJIT_CONFIG_X86_32 1
|
||||
#elif defined(__x86_64__)
|
||||
#define SLJIT_CONFIG_X86_64 1
|
||||
#elif defined(__aarch64__)
|
||||
#define SLJIT_CONFIG_ARM_64 1
|
||||
#elif defined(__thumb2__)
|
||||
#define SLJIT_CONFIG_ARM_THUMB2 1
|
||||
#elif (defined(__ARM_ARCH) && __ARM_ARCH >= 7) || \
|
||||
((defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7S__)) \
|
||||
|| (defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_8R__)) \
|
||||
|| (defined(__ARM_ARCH_9A__)))
|
||||
#define SLJIT_CONFIG_ARM_V7 1
|
||||
#elif defined(__arm__) || defined (__ARM__)
|
||||
#define SLJIT_CONFIG_ARM_V6 1
|
||||
#elif defined(__ppc64__) || defined(__powerpc64__) || (defined(_ARCH_PPC64) && defined(__64BIT__)) || (defined(_POWER) && defined(__64BIT__))
|
||||
#define SLJIT_CONFIG_PPC_64 1
|
||||
#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__) && !defined(_LP64)
|
||||
#define SLJIT_CONFIG_MIPS_32 1
|
||||
#elif defined(__mips64)
|
||||
#define SLJIT_CONFIG_MIPS_64 1
|
||||
#elif defined (__riscv_xlen) && (__riscv_xlen == 32)
|
||||
#define SLJIT_CONFIG_RISCV_32 1
|
||||
#elif defined (__riscv_xlen) && (__riscv_xlen == 64)
|
||||
#define SLJIT_CONFIG_RISCV_64 1
|
||||
#elif defined (__loongarch_lp64)
|
||||
#define SLJIT_CONFIG_LOONGARCH_64 1
|
||||
#elif defined(__s390x__)
|
||||
#define SLJIT_CONFIG_S390X 1
|
||||
#else
|
||||
/* Unsupported architecture */
|
||||
#define SLJIT_CONFIG_UNSUPPORTED 1
|
||||
#endif
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define SLJIT_CONFIG_X86_64 1
|
||||
#elif (defined(_M_ARM) && _M_ARM >= 7 && defined(_M_ARMT)) || defined(__thumb2__)
|
||||
#define SLJIT_CONFIG_ARM_THUMB2 1
|
||||
#elif (defined(_M_ARM) && _M_ARM >= 7)
|
||||
#define SLJIT_CONFIG_ARM_V7 1
|
||||
#elif defined(_ARM_)
|
||||
#define SLJIT_CONFIG_ARM_V6 1
|
||||
#elif defined(_M_ARM64) || defined(__aarch64__)
|
||||
#define SLJIT_CONFIG_ARM_64 1
|
||||
#else
|
||||
#define SLJIT_CONFIG_X86_32 1
|
||||
#endif
|
||||
|
||||
#endif /* !_WIN32 */
|
||||
#endif /* SLJIT_CONFIG_AUTO */
|
||||
|
||||
#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
|
||||
#undef SLJIT_EXECUTABLE_ALLOCATOR
|
||||
#endif /* SLJIT_CONFIG_UNSUPPORTED */
|
||||
|
||||
/******************************/
|
||||
/* CPU family type detection. */
|
||||
/******************************/
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
||||
#define SLJIT_CONFIG_ARM_32 1
|
||||
#endif /* SLJIT_CONFIG_ARM_V6 || SLJIT_CONFIG_ARM_V7 || SLJIT_CONFIG_ARM_THUMB2 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#define SLJIT_CONFIG_X86 1
|
||||
#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
#define SLJIT_CONFIG_ARM 1
|
||||
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define SLJIT_CONFIG_PPC 1
|
||||
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
#define SLJIT_CONFIG_MIPS 1
|
||||
#elif (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
||||
#define SLJIT_CONFIG_RISCV 1
|
||||
#elif (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64)
|
||||
#define SLJIT_CONFIG_LOONGARCH 1
|
||||
#endif
|
||||
|
||||
#endif /* SLJIT_CONFIG_CPU_H_ */
|
972
thirdparty/pcre2/deps/sljit/sljit_src/sljitConfigInternal.h
vendored
Normal file
972
thirdparty/pcre2/deps/sljit/sljit_src/sljitConfigInternal.h
vendored
Normal file
@@ -0,0 +1,972 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SLJIT_CONFIG_INTERNAL_H_
|
||||
#define SLJIT_CONFIG_INTERNAL_H_
|
||||
|
||||
/*
|
||||
SLJIT defines the following architecture dependent types and macros:
|
||||
|
||||
Types:
|
||||
sljit_s8, sljit_u8 : signed and unsigned 8 bit integer type
|
||||
sljit_s16, sljit_u16 : signed and unsigned 16 bit integer type
|
||||
sljit_s32, sljit_u32 : signed and unsigned 32 bit integer type
|
||||
sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer
|
||||
sljit_sp, sljit_up : signed and unsigned pointer value (usually the same as
|
||||
sljit_uw, but some 64 bit ABIs may use 32 bit pointers)
|
||||
sljit_f32 : 32 bit single precision floating point value
|
||||
sljit_f64 : 64 bit double precision floating point value
|
||||
|
||||
Macros for feature detection (boolean):
|
||||
SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
|
||||
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
|
||||
SLJIT_LITTLE_ENDIAN : little endian architecture
|
||||
SLJIT_BIG_ENDIAN : big endian architecture
|
||||
SLJIT_UNALIGNED : unaligned memory accesses for non-fpu operations are supported
|
||||
SLJIT_FPU_UNALIGNED : unaligned memory accesses for fpu operations are supported
|
||||
SLJIT_MASKED_SHIFT : all word shifts are always masked
|
||||
SLJIT_MASKED_SHIFT32 : all 32 bit shifts are always masked
|
||||
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_ADDR() for more information
|
||||
SLJIT_UPPER_BITS_IGNORED : 32 bit operations ignores the upper bits of source registers
|
||||
SLJIT_UPPER_BITS_ZERO_EXTENDED : 32 bit operations clears the upper bits of destination registers
|
||||
SLJIT_UPPER_BITS_SIGN_EXTENDED : 32 bit operations replicates the sign bit in the upper bits of destination registers
|
||||
SLJIT_UPPER_BITS_PRESERVED : 32 bit operations preserves the upper bits of destination registers
|
||||
|
||||
Constants:
|
||||
SLJIT_NUMBER_OF_REGISTERS : number of available registers
|
||||
SLJIT_NUMBER_OF_SCRATCH_REGISTERS : number of available scratch registers
|
||||
SLJIT_NUMBER_OF_SAVED_REGISTERS : number of available saved registers
|
||||
SLJIT_NUMBER_OF_FLOAT_REGISTERS : number of available floating point registers
|
||||
SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS : number of available scratch floating point registers
|
||||
SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS : number of available saved floating point registers
|
||||
SLJIT_NUMBER_OF_VECTOR_REGISTERS : number of available vector registers
|
||||
SLJIT_NUMBER_OF_SCRATCH_VECTOR_REGISTERS : number of available scratch vector registers
|
||||
SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS : number of available saved vector registers
|
||||
SLJIT_NUMBER_OF_TEMPORARY_REGISTERS : number of available temporary registers
|
||||
SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS : number of available temporary floating point registers
|
||||
SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS : number of available temporary vector registers
|
||||
SLJIT_SEPARATE_VECTOR_REGISTERS : if this macro is defined, the vector registers do not
|
||||
overlap with floating point registers
|
||||
SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index
|
||||
SLJIT_F32_SHIFT : the shift required to apply when accessing
|
||||
a single precision floating point array by index
|
||||
SLJIT_F64_SHIFT : the shift required to apply when accessing
|
||||
a double precision floating point array by index
|
||||
SLJIT_PREF_SHIFT_REG : x86 systems prefers ecx for shifting by register
|
||||
the scratch register index of ecx is stored in this variable
|
||||
SLJIT_LOCALS_OFFSET : local space starting offset (SLJIT_SP + SLJIT_LOCALS_OFFSET)
|
||||
SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
|
||||
SLJIT_CONV_MAX_FLOAT : result when a floating point value is converted to integer
|
||||
and the floating point value is higher than the maximum integer value
|
||||
(possible values: SLJIT_CONV_RESULT_MAX_INT or SLJIT_CONV_RESULT_MIN_INT)
|
||||
SLJIT_CONV_MIN_FLOAT : result when a floating point value is converted to integer
|
||||
and the floating point value is lower than the minimum integer value
|
||||
(possible values: SLJIT_CONV_RESULT_MAX_INT or SLJIT_CONV_RESULT_MIN_INT)
|
||||
SLJIT_CONV_NAN_FLOAT : result when a NaN floating point value is converted to integer
|
||||
(possible values: SLJIT_CONV_RESULT_MAX_INT, SLJIT_CONV_RESULT_MIN_INT,
|
||||
or SLJIT_CONV_RESULT_ZERO)
|
||||
|
||||
Other macros:
|
||||
SLJIT_TMP_R0 .. R9 : accessing temporary registers
|
||||
SLJIT_TMP_R(i) : accessing temporary registers
|
||||
SLJIT_TMP_FR0 .. FR9 : accessing temporary floating point registers
|
||||
SLJIT_TMP_FR(i) : accessing temporary floating point registers
|
||||
SLJIT_TMP_VR0 .. VR9 : accessing temporary vector registers
|
||||
SLJIT_TMP_VR(i) : accessing temporary vector registers
|
||||
SLJIT_TMP_DEST_REG : a temporary register for results
|
||||
SLJIT_TMP_MEM_REG : a temporary base register for accessing memory
|
||||
(can be the same as SLJIT_TMP_DEST_REG)
|
||||
SLJIT_TMP_DEST_FREG : a temporary register for float results
|
||||
SLJIT_TMP_DEST_VREG : a temporary register for vector results
|
||||
SLJIT_FUNC : calling convention attribute for both calling JIT from C and C calling back from JIT
|
||||
SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (platform independent helper)
|
||||
SLJIT_F64_SECOND(reg) : provides the register index of the second 32 bit part of a 64 bit
|
||||
floating point register when SLJIT_HAS_F64_AS_F32_PAIR returns non-zero
|
||||
*/
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_DEBUG && SLJIT_DEBUG && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)))
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG \
|
||||
&& (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) || !defined(SLJIT_HALT_PROCESS)))
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***********************************************************/
|
||||
/* Intel Control-flow Enforcement Technology (CET) spport. */
|
||||
/***********************************************************/
|
||||
|
||||
#ifdef SLJIT_CONFIG_X86
|
||||
|
||||
#if defined(__CET__) && !(defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)
|
||||
#define SLJIT_CONFIG_X86_CET 1
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined(__GNUC__)
|
||||
#include <x86intrin.h>
|
||||
#endif
|
||||
|
||||
#endif /* SLJIT_CONFIG_X86 */
|
||||
|
||||
/**********************************/
|
||||
/* External function definitions. */
|
||||
/**********************************/
|
||||
|
||||
/* General macros:
|
||||
Note: SLJIT is designed to be independent from them as possible.
|
||||
|
||||
In release mode (SLJIT_DEBUG is not defined) only the following
|
||||
external functions are needed:
|
||||
*/
|
||||
|
||||
#ifndef SLJIT_MALLOC
|
||||
#define SLJIT_MALLOC(size, allocator_data) (malloc(size))
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_FREE
|
||||
#define SLJIT_FREE(ptr, allocator_data) (free(ptr))
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_MEMCPY
|
||||
#define SLJIT_MEMCPY(dest, src, len) (memcpy(dest, src, len))
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_MEMMOVE
|
||||
#define SLJIT_MEMMOVE(dest, src, len) (memmove(dest, src, len))
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_ZEROMEM
|
||||
#define SLJIT_ZEROMEM(dest, len) (memset(dest, 0, len))
|
||||
#endif
|
||||
|
||||
/***************************/
|
||||
/* Compiler helper macros. */
|
||||
/***************************/
|
||||
|
||||
#if !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY)
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
#define SLJIT_LIKELY(x) __builtin_expect((x), 1)
|
||||
#define SLJIT_UNLIKELY(x) __builtin_expect((x), 0)
|
||||
#else
|
||||
#define SLJIT_LIKELY(x) (x)
|
||||
#define SLJIT_UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
#endif /* !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) */
|
||||
|
||||
#ifndef SLJIT_INLINE
|
||||
/* Inline functions. Some old compilers do not support them. */
|
||||
#ifdef __SUNPRO_C
|
||||
#if __SUNPRO_C < 0x560
|
||||
#define SLJIT_INLINE
|
||||
#else
|
||||
#define SLJIT_INLINE inline
|
||||
#endif /* __SUNPRO_C */
|
||||
#else
|
||||
#define SLJIT_INLINE __inline
|
||||
#endif
|
||||
#endif /* !SLJIT_INLINE */
|
||||
|
||||
#ifndef SLJIT_NOINLINE
|
||||
/* Not inline functions. */
|
||||
#if defined(__GNUC__)
|
||||
#define SLJIT_NOINLINE __attribute__ ((noinline))
|
||||
#else
|
||||
#define SLJIT_NOINLINE
|
||||
#endif
|
||||
#endif /* !SLJIT_INLINE */
|
||||
|
||||
#ifndef SLJIT_UNUSED_ARG
|
||||
/* Unused arguments. */
|
||||
#define SLJIT_UNUSED_ARG(arg) (void)arg
|
||||
#endif
|
||||
|
||||
/*********************************/
|
||||
/* Type of public API functions. */
|
||||
/*********************************/
|
||||
|
||||
#ifndef SLJIT_API_FUNC_ATTRIBUTE
|
||||
#if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC)
|
||||
/* Static ABI functions. For all-in-one programs. */
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/* Disable unused warnings in gcc. */
|
||||
#define SLJIT_API_FUNC_ATTRIBUTE static __attribute__((unused))
|
||||
#else
|
||||
#define SLJIT_API_FUNC_ATTRIBUTE static
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define SLJIT_API_FUNC_ATTRIBUTE
|
||||
#endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */
|
||||
#endif /* defined SLJIT_API_FUNC_ATTRIBUTE */
|
||||
|
||||
/****************************/
|
||||
/* Instruction cache flush. */
|
||||
/****************************/
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <AvailabilityMacros.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
*
|
||||
* clang >= 15 could be safe to enable below
|
||||
* older versions are known to abort in some targets
|
||||
* https://github.com/PhilipHazel/pcre2/issues/92
|
||||
*
|
||||
* beware some vendors (ex: Microsoft, Apple) are known to have
|
||||
* removed the code to support this builtin even if the call for
|
||||
* __has_builtin reports it is available.
|
||||
*
|
||||
* make sure linking doesn't fail because __clear_cache() is
|
||||
* missing before changing it or add an exception so that the
|
||||
* system provided method that should be defined below is used
|
||||
* instead.
|
||||
*/
|
||||
#if (!defined SLJIT_CACHE_FLUSH && defined __has_builtin)
|
||||
#if __has_builtin(__builtin___clear_cache) && !defined(__clang__)
|
||||
|
||||
/*
|
||||
* https://gcc.gnu.org/bugzilla//show_bug.cgi?id=91248
|
||||
* https://gcc.gnu.org/bugzilla//show_bug.cgi?id=93811
|
||||
* gcc's clear_cache builtin for power is broken
|
||||
*/
|
||||
#if !defined(SLJIT_CONFIG_PPC)
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
__builtin___clear_cache((char*)(from), (char*)(to))
|
||||
#endif
|
||||
|
||||
#endif /* gcc >= 10 */
|
||||
#endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */
|
||||
|
||||
#ifndef SLJIT_CACHE_FLUSH
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|
||||
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
|
||||
/* Not required to implement on archs with unified caches. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to)
|
||||
|
||||
#elif defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
|
||||
|
||||
/* Supported by all macs since Mac OS 10.5.
|
||||
However, it does not work on non-jailbroken iOS devices,
|
||||
although the compilation is successful. */
|
||||
#include <libkern/OSCacheControl.h>
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
sys_icache_invalidate((void*)(from), (size_t)((char*)(to) - (char*)(from)))
|
||||
|
||||
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
ppc_cache_flush((from), (to))
|
||||
#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
FlushInstructionCache(GetCurrentProcess(), (void*)(from), (size_t)((char*)(to) - (char*)(from)))
|
||||
|
||||
#elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || defined(__clang__)
|
||||
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
__builtin___clear_cache((char*)(from), (char*)(to))
|
||||
|
||||
#elif defined __ANDROID__
|
||||
|
||||
/* Android ARMv7 with gcc lacks __clear_cache; use cacheflush instead. */
|
||||
#include <sys/cachectl.h>
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
cacheflush((long)(from), (long)(to), 0)
|
||||
|
||||
#else
|
||||
|
||||
/* Call __ARM_NR_cacheflush on ARM-Linux or the corresponding MIPS syscall. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
__clear_cache((char*)(from), (char*)(to))
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !SLJIT_CACHE_FLUSH */
|
||||
|
||||
/******************************************************/
|
||||
/* Integer and floating point type definitions. */
|
||||
/******************************************************/
|
||||
|
||||
/* 8 bit byte type. */
|
||||
typedef unsigned char sljit_u8;
|
||||
typedef signed char sljit_s8;
|
||||
|
||||
/* 16 bit half-word type. */
|
||||
typedef unsigned short int sljit_u16;
|
||||
typedef signed short int sljit_s16;
|
||||
|
||||
/* 32 bit integer type. */
|
||||
typedef unsigned int sljit_u32;
|
||||
typedef signed int sljit_s32;
|
||||
|
||||
/* Machine word type. Enough for storing a pointer.
|
||||
32 bit for 32 bit machines.
|
||||
64 bit for 64 bit machines. */
|
||||
#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
|
||||
/* Just to have something. */
|
||||
#define SLJIT_WORD_SHIFT 0
|
||||
typedef unsigned int sljit_uw;
|
||||
typedef int sljit_sw;
|
||||
#elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|
||||
&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
&& !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
&& !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||
&& !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
|
||||
&& !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
|
||||
&& !(defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64)
|
||||
#define SLJIT_32BIT_ARCHITECTURE 1
|
||||
#define SLJIT_WORD_SHIFT 2
|
||||
typedef unsigned int sljit_uw;
|
||||
typedef int sljit_sw;
|
||||
#else
|
||||
#define SLJIT_64BIT_ARCHITECTURE 1
|
||||
#define SLJIT_WORD_SHIFT 3
|
||||
#ifdef _WIN32
|
||||
#ifdef __GNUC__
|
||||
/* These types do not require windows.h */
|
||||
typedef unsigned long long sljit_uw;
|
||||
typedef long long sljit_sw;
|
||||
#else
|
||||
typedef unsigned __int64 sljit_uw;
|
||||
typedef __int64 sljit_sw;
|
||||
#endif
|
||||
#else /* !_WIN32 */
|
||||
typedef unsigned long int sljit_uw;
|
||||
typedef long int sljit_sw;
|
||||
#endif /* _WIN32 */
|
||||
#endif
|
||||
|
||||
typedef sljit_sw sljit_sp;
|
||||
typedef sljit_uw sljit_up;
|
||||
|
||||
/* Floating point types. */
|
||||
typedef float sljit_f32;
|
||||
typedef double sljit_f64;
|
||||
|
||||
/* Shift for pointer sized data. */
|
||||
#define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT
|
||||
|
||||
/* Shift for double precision sized data. */
|
||||
#define SLJIT_F32_SHIFT 2
|
||||
#define SLJIT_F64_SHIFT 3
|
||||
|
||||
#define SLJIT_CONV_RESULT_MAX_INT 0
|
||||
#define SLJIT_CONV_RESULT_MIN_INT 1
|
||||
#define SLJIT_CONV_RESULT_ZERO 2
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MIN_INT
|
||||
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
|
||||
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT
|
||||
#elif (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)
|
||||
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
|
||||
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
|
||||
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_ZERO
|
||||
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
|
||||
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MAX_INT
|
||||
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MAX_INT
|
||||
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
|
||||
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
|
||||
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT
|
||||
#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
|
||||
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
|
||||
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
|
||||
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MAX_INT
|
||||
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
|
||||
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
|
||||
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT
|
||||
#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
|
||||
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
|
||||
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
|
||||
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_ZERO
|
||||
#else
|
||||
#error "Result for float to integer conversion is not defined"
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_W
|
||||
|
||||
/* Defining long constants. */
|
||||
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
||||
#ifdef _WIN64
|
||||
#define SLJIT_W(w) (w##ll)
|
||||
#else /* !windows */
|
||||
#define SLJIT_W(w) (w##l)
|
||||
#endif /* windows */
|
||||
#else /* 32 bit */
|
||||
#define SLJIT_W(w) (w)
|
||||
#endif /* unknown */
|
||||
|
||||
#endif /* !SLJIT_W */
|
||||
|
||||
/*************************/
|
||||
/* Endianness detection. */
|
||||
/*************************/
|
||||
|
||||
#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
|
||||
|
||||
/* These macros are mostly useful for the applications. */
|
||||
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
|
||||
#ifdef __MIPSEL__
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_MIPS_REV
|
||||
|
||||
/* Auto detecting mips revision. */
|
||||
#if (defined __mips_isa_rev) && (__mips_isa_rev >= 6)
|
||||
#define SLJIT_MIPS_REV 6
|
||||
#elif defined(__mips_isa_rev) && __mips_isa_rev >= 1
|
||||
#define SLJIT_MIPS_REV __mips_isa_rev
|
||||
#elif defined(__clang__) \
|
||||
&& (defined(_MIPS_ARCH_OCTEON) || defined(_MIPS_ARCH_P5600))
|
||||
/* clang either forgets to define (clang-7) __mips_isa_rev at all
|
||||
* or sets it to zero (clang-8,-9) for -march=octeon (MIPS64 R2+)
|
||||
* and -march=p5600 (MIPS32 R5).
|
||||
* It also sets the __mips macro to 64 or 32 for -mipsN when N <= 5
|
||||
* (should be set to N exactly) so we cannot rely on this too.
|
||||
*/
|
||||
#define SLJIT_MIPS_REV 1
|
||||
#endif
|
||||
|
||||
#endif /* !SLJIT_MIPS_REV */
|
||||
|
||||
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
|
||||
#else
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#endif /* !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) */
|
||||
|
||||
/* Sanity check. */
|
||||
#if (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
|
||||
#error "Exactly one endianness must be selected"
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && !(defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
|
||||
#error "Exactly one endianness must be selected"
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_UNALIGNED
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|
||||
|| (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|
||||
|| (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|
||||
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
|
||||
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
|
||||
|| (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
|
||||
#define SLJIT_UNALIGNED 1
|
||||
#endif
|
||||
|
||||
#endif /* !SLJIT_UNALIGNED */
|
||||
|
||||
#ifndef SLJIT_FPU_UNALIGNED
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|
||||
|| (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|
||||
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
|
||||
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
|
||||
|| (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
|
||||
#define SLJIT_FPU_UNALIGNED 1
|
||||
#endif
|
||||
|
||||
#endif /* !SLJIT_FPU_UNALIGNED */
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
/* Auto detect SSE2 support using CPUID.
|
||||
On 64 bit x86 cpus, sse2 must be present. */
|
||||
#define SLJIT_DETECT_SSE2 1
|
||||
#endif
|
||||
|
||||
/*****************************************************************************************/
|
||||
/* Calling convention of functions generated by SLJIT or called from the generated code. */
|
||||
/*****************************************************************************************/
|
||||
|
||||
#ifndef SLJIT_FUNC
|
||||
#define SLJIT_FUNC
|
||||
#endif /* !SLJIT_FUNC */
|
||||
|
||||
#ifndef SLJIT_INDIRECT_CALL
|
||||
#if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (!defined _CALL_ELF || _CALL_ELF == 1)) \
|
||||
|| ((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 */
|
||||
|
||||
/* The offset which needs to be subtracted from the return address to
|
||||
determine the next executed instruction after return. */
|
||||
#ifndef SLJIT_RETURN_ADDRESS_OFFSET
|
||||
#define SLJIT_RETURN_ADDRESS_OFFSET 0
|
||||
#endif /* SLJIT_RETURN_ADDRESS_OFFSET */
|
||||
|
||||
/***************************************************/
|
||||
/* Functions of the built-in executable allocator. */
|
||||
/***************************************************/
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
|
||||
/* Note: sljitLir.h also defines sljit_free_unused_memory_exec() function. */
|
||||
#define SLJIT_BUILTIN_MALLOC_EXEC(size, exec_allocator_data) sljit_malloc_exec(size)
|
||||
#define SLJIT_BUILTIN_FREE_EXEC(ptr, exec_allocator_data) sljit_free_exec(ptr)
|
||||
|
||||
#ifndef SLJIT_MALLOC_EXEC
|
||||
#define SLJIT_MALLOC_EXEC(size, exec_allocator_data) SLJIT_BUILTIN_MALLOC_EXEC((size), (exec_allocator_data))
|
||||
#endif /* SLJIT_MALLOC_EXEC */
|
||||
|
||||
#ifndef SLJIT_FREE_EXEC
|
||||
#define SLJIT_FREE_EXEC(ptr, exec_allocator_data) SLJIT_BUILTIN_FREE_EXEC((ptr), (exec_allocator_data))
|
||||
#endif /* SLJIT_FREE_EXEC */
|
||||
|
||||
#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
|
||||
#define SLJIT_EXEC_OFFSET(code) sljit_exec_offset(code)
|
||||
#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
#ifndef SLJIT_EXEC_OFFSET
|
||||
#define SLJIT_EXEC_OFFSET(ptr) 0
|
||||
#endif
|
||||
|
||||
/**********************************************/
|
||||
/* Registers and locals offset determination. */
|
||||
/**********************************************/
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 1
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 7
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1
|
||||
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0
|
||||
#define SLJIT_TMP_MEM_REG SLJIT_TMP_R0
|
||||
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (8 * (sljit_s32)sizeof(sljit_sw))
|
||||
#define SLJIT_PREF_SHIFT_REG SLJIT_R2
|
||||
#define SLJIT_MASKED_SHIFT 1
|
||||
#define SLJIT_MASKED_SHIFT32 1
|
||||
#define SLJIT_UPPER_BITS_IGNORED 1
|
||||
#define SLJIT_UPPER_BITS_ZERO_EXTENDED 1
|
||||
|
||||
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 13
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 2
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1
|
||||
#ifndef _WIN64
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 6
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
#else /* _WIN64 */
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 10
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))
|
||||
#endif /* !_WIN64 */
|
||||
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0
|
||||
#define SLJIT_TMP_MEM_REG SLJIT_TMP_R0
|
||||
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
|
||||
#define SLJIT_PREF_SHIFT_REG SLJIT_R3
|
||||
#define SLJIT_MASKED_SHIFT 1
|
||||
#define SLJIT_MASKED_SHIFT32 1
|
||||
#define SLJIT_UPPER_BITS_IGNORED 1
|
||||
#define SLJIT_UPPER_BITS_ZERO_EXTENDED 1
|
||||
|
||||
#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 2
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
|
||||
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
|
||||
#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1
|
||||
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
|
||||
#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 26
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
|
||||
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0
|
||||
#define SLJIT_TMP_MEM_REG SLJIT_TMP_R0
|
||||
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (2 * (sljit_s32)sizeof(sljit_sw))
|
||||
#define SLJIT_MASKED_SHIFT 1
|
||||
#define SLJIT_MASKED_SHIFT32 1
|
||||
#define SLJIT_UPPER_BITS_IGNORED 1
|
||||
#define SLJIT_UPPER_BITS_ZERO_EXTENDED 1
|
||||
|
||||
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 23
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 17
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 18
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
|
||||
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
|
||||
#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1
|
||||
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX)
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * (sljit_s32)sizeof(sljit_sw))
|
||||
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
/* Add +1 for double alignment. */
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1) * (sljit_s32)sizeof(sljit_sw))
|
||||
#else
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (3 * (sljit_s32)sizeof(sljit_sw))
|
||||
#endif /* SLJIT_CONFIG_PPC_64 || _AIX */
|
||||
#define SLJIT_UPPER_BITS_IGNORED 1
|
||||
|
||||
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 21
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 13
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 6
|
||||
#else
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 29
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
|
||||
#endif
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 3
|
||||
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
|
||||
#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1
|
||||
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
|
||||
#define SLJIT_MASKED_SHIFT 1
|
||||
#define SLJIT_MASKED_SHIFT32 1
|
||||
#define SLJIT_UPPER_BITS_SIGN_EXTENDED 1
|
||||
|
||||
#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 23
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
|
||||
#define SLJIT_SEPARATE_VECTOR_REGISTERS 1
|
||||
#define SLJIT_NUMBER_OF_VECTOR_REGISTERS 30
|
||||
#define SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS 0
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS 2
|
||||
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
|
||||
#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1
|
||||
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
|
||||
#define SLJIT_TMP_DEST_VREG SLJIT_TMP_VR0
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
#define SLJIT_MASKED_SHIFT 1
|
||||
#define SLJIT_MASKED_SHIFT32 1
|
||||
#define SLJIT_UPPER_BITS_IGNORED 1
|
||||
#define SLJIT_UPPER_BITS_SIGN_EXTENDED 1
|
||||
|
||||
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
|
||||
/*
|
||||
* https://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html#STACKFRAME
|
||||
*
|
||||
* 160
|
||||
* .. FR6
|
||||
* .. FR4
|
||||
* .. FR2
|
||||
* 128 FR0
|
||||
* 120 R15 (used for SP)
|
||||
* 112 R14
|
||||
* 104 R13
|
||||
* 96 R12
|
||||
* ..
|
||||
* 48 R6
|
||||
* ..
|
||||
* 16 R2
|
||||
* 8 RESERVED
|
||||
* 0 SP
|
||||
*/
|
||||
#define SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE 160
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1
|
||||
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0
|
||||
#define SLJIT_TMP_MEM_REG SLJIT_TMP_R2
|
||||
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
|
||||
#define SLJIT_LOCALS_OFFSET_BASE SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE
|
||||
#define SLJIT_MASKED_SHIFT 1
|
||||
#define SLJIT_UPPER_BITS_IGNORED 1
|
||||
#define SLJIT_UPPER_BITS_PRESERVED 1
|
||||
|
||||
#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 23
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
|
||||
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
|
||||
#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1
|
||||
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
#define SLJIT_MASKED_SHIFT 1
|
||||
#define SLJIT_MASKED_SHIFT32 1
|
||||
#define SLJIT_UPPER_BITS_SIGN_EXTENDED 1
|
||||
|
||||
#elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
|
||||
|
||||
/* Just to have something. */
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 0
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 0
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 0
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 0
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 0
|
||||
#define SLJIT_TMP_DEST_REG 0
|
||||
#define SLJIT_TMP_MEM_REG 0
|
||||
#define SLJIT_TMP_DEST_FREG 0
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)
|
||||
#define SLJIT_NUMBER_OF_VECTOR_REGISTERS (SLJIT_NUMBER_OF_FLOAT_REGISTERS)
|
||||
#define SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS (SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS)
|
||||
#define SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS (SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)
|
||||
#define SLJIT_TMP_DEST_VREG (SLJIT_TMP_DEST_FREG)
|
||||
#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */
|
||||
|
||||
#define SLJIT_LOCALS_OFFSET (SLJIT_LOCALS_OFFSET_BASE)
|
||||
|
||||
#define SLJIT_NUMBER_OF_SCRATCH_REGISTERS \
|
||||
(SLJIT_NUMBER_OF_REGISTERS - SLJIT_NUMBER_OF_SAVED_REGISTERS)
|
||||
|
||||
#define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \
|
||||
(SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS)
|
||||
|
||||
#define SLJIT_NUMBER_OF_SCRATCH_VECTOR_REGISTERS \
|
||||
(SLJIT_NUMBER_OF_VECTOR_REGISTERS - SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS)
|
||||
|
||||
#if (defined SLJIT_UPPER_BITS_ZERO_EXTENDED && SLJIT_UPPER_BITS_ZERO_EXTENDED) \
|
||||
+ (defined SLJIT_UPPER_BITS_SIGN_EXTENDED && SLJIT_UPPER_BITS_SIGN_EXTENDED) \
|
||||
+ (defined SLJIT_UPPER_BITS_PRESERVED && SLJIT_UPPER_BITS_PRESERVED) > 1
|
||||
#error "Invalid upper bits defintion"
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_UPPER_BITS_PRESERVED && SLJIT_UPPER_BITS_PRESERVED) \
|
||||
&& !(defined SLJIT_UPPER_BITS_IGNORED && SLJIT_UPPER_BITS_IGNORED)
|
||||
#error "Upper bits preserved requires bits ignored"
|
||||
#endif
|
||||
|
||||
/**********************************/
|
||||
/* Temporary register management. */
|
||||
/**********************************/
|
||||
|
||||
#define SLJIT_TMP_REGISTER_BASE (SLJIT_NUMBER_OF_REGISTERS + 2)
|
||||
#define SLJIT_TMP_FREGISTER_BASE (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
|
||||
#define SLJIT_TMP_VREGISTER_BASE (SLJIT_NUMBER_OF_VECTOR_REGISTERS + 1)
|
||||
|
||||
/* WARNING: Accessing temporary registers is not recommended, because they
|
||||
are also used by the JIT compiler for various computations. Using them
|
||||
might have any side effects including incorrect operations and crashes,
|
||||
so use them at your own risk. The machine registers themselves might have
|
||||
limitations, e.g. the r0 register on s390x / ppc cannot be used as
|
||||
base address for memory operations. */
|
||||
|
||||
/* Temporary registers */
|
||||
#define SLJIT_TMP_R0 (SLJIT_TMP_REGISTER_BASE + 0)
|
||||
#define SLJIT_TMP_R1 (SLJIT_TMP_REGISTER_BASE + 1)
|
||||
#define SLJIT_TMP_R2 (SLJIT_TMP_REGISTER_BASE + 2)
|
||||
#define SLJIT_TMP_R3 (SLJIT_TMP_REGISTER_BASE + 3)
|
||||
#define SLJIT_TMP_R4 (SLJIT_TMP_REGISTER_BASE + 4)
|
||||
#define SLJIT_TMP_R5 (SLJIT_TMP_REGISTER_BASE + 5)
|
||||
#define SLJIT_TMP_R6 (SLJIT_TMP_REGISTER_BASE + 6)
|
||||
#define SLJIT_TMP_R7 (SLJIT_TMP_REGISTER_BASE + 7)
|
||||
#define SLJIT_TMP_R8 (SLJIT_TMP_REGISTER_BASE + 8)
|
||||
#define SLJIT_TMP_R9 (SLJIT_TMP_REGISTER_BASE + 9)
|
||||
#define SLJIT_TMP_R(i) (SLJIT_TMP_REGISTER_BASE + (i))
|
||||
|
||||
#define SLJIT_TMP_FR0 (SLJIT_TMP_FREGISTER_BASE + 0)
|
||||
#define SLJIT_TMP_FR1 (SLJIT_TMP_FREGISTER_BASE + 1)
|
||||
#define SLJIT_TMP_FR2 (SLJIT_TMP_FREGISTER_BASE + 2)
|
||||
#define SLJIT_TMP_FR3 (SLJIT_TMP_FREGISTER_BASE + 3)
|
||||
#define SLJIT_TMP_FR4 (SLJIT_TMP_FREGISTER_BASE + 4)
|
||||
#define SLJIT_TMP_FR5 (SLJIT_TMP_FREGISTER_BASE + 5)
|
||||
#define SLJIT_TMP_FR6 (SLJIT_TMP_FREGISTER_BASE + 6)
|
||||
#define SLJIT_TMP_FR7 (SLJIT_TMP_FREGISTER_BASE + 7)
|
||||
#define SLJIT_TMP_FR8 (SLJIT_TMP_FREGISTER_BASE + 8)
|
||||
#define SLJIT_TMP_FR9 (SLJIT_TMP_FREGISTER_BASE + 9)
|
||||
#define SLJIT_TMP_FR(i) (SLJIT_TMP_FREGISTER_BASE + (i))
|
||||
|
||||
#define SLJIT_TMP_VR0 (SLJIT_TMP_VREGISTER_BASE + 0)
|
||||
#define SLJIT_TMP_VR1 (SLJIT_TMP_VREGISTER_BASE + 1)
|
||||
#define SLJIT_TMP_VR2 (SLJIT_TMP_VREGISTER_BASE + 2)
|
||||
#define SLJIT_TMP_VR3 (SLJIT_TMP_VREGISTER_BASE + 3)
|
||||
#define SLJIT_TMP_VR4 (SLJIT_TMP_VREGISTER_BASE + 4)
|
||||
#define SLJIT_TMP_VR5 (SLJIT_TMP_VREGISTER_BASE + 5)
|
||||
#define SLJIT_TMP_VR6 (SLJIT_TMP_VREGISTER_BASE + 6)
|
||||
#define SLJIT_TMP_VR7 (SLJIT_TMP_VREGISTER_BASE + 7)
|
||||
#define SLJIT_TMP_VR8 (SLJIT_TMP_VREGISTER_BASE + 8)
|
||||
#define SLJIT_TMP_VR9 (SLJIT_TMP_VREGISTER_BASE + 9)
|
||||
#define SLJIT_TMP_VR(i) (SLJIT_TMP_VREGISTER_BASE + (i))
|
||||
|
||||
/********************************/
|
||||
/* CPU status flags management. */
|
||||
/********************************/
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
|
||||
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|
||||
|| (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
|
||||
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
|
||||
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
|
||||
|| (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
|
||||
#define SLJIT_HAS_STATUS_FLAGS_STATE 1
|
||||
#endif
|
||||
|
||||
/***************************************/
|
||||
/* Floating point register management. */
|
||||
/***************************************/
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#define SLJIT_F64_SECOND(reg) \
|
||||
((reg) + SLJIT_FS0 + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)
|
||||
#else /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS_32 */
|
||||
#define SLJIT_F64_SECOND(reg) \
|
||||
(reg)
|
||||
#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */
|
||||
|
||||
/*************************************/
|
||||
/* Debug and verbose related macros. */
|
||||
/*************************************/
|
||||
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
|
||||
#if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)
|
||||
|
||||
/* SLJIT_HALT_PROCESS must halt the process. */
|
||||
#ifndef SLJIT_HALT_PROCESS
|
||||
#define SLJIT_HALT_PROCESS() \
|
||||
abort();
|
||||
#endif /* !SLJIT_HALT_PROCESS */
|
||||
|
||||
#endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */
|
||||
|
||||
/* Feel free to redefine these two macros. */
|
||||
#ifndef SLJIT_ASSERT
|
||||
|
||||
#define SLJIT_ASSERT(x) \
|
||||
do { \
|
||||
if (SLJIT_UNLIKELY(!(x))) { \
|
||||
printf("Assertion failed at " __FILE__ ":%d\n", __LINE__); \
|
||||
SLJIT_HALT_PROCESS(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* !SLJIT_ASSERT */
|
||||
|
||||
#ifndef SLJIT_UNREACHABLE
|
||||
|
||||
#define SLJIT_UNREACHABLE() \
|
||||
do { \
|
||||
printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \
|
||||
SLJIT_HALT_PROCESS(); \
|
||||
} while (0)
|
||||
|
||||
#endif /* !SLJIT_UNREACHABLE */
|
||||
|
||||
#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
|
||||
|
||||
/* Forcing empty, but valid statements. */
|
||||
#undef SLJIT_ASSERT
|
||||
#undef SLJIT_UNREACHABLE
|
||||
|
||||
#define SLJIT_ASSERT(x) \
|
||||
do { } while (0)
|
||||
#define SLJIT_UNREACHABLE() \
|
||||
do { } while (0)
|
||||
|
||||
#endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
|
||||
|
||||
#ifndef SLJIT_COMPILE_ASSERT
|
||||
|
||||
#define SLJIT_COMPILE_ASSERT(x, description) \
|
||||
switch(0) { case 0: case ((x) ? 1 : 0): break; }
|
||||
|
||||
#endif /* !SLJIT_COMPILE_ASSERT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* SLJIT_CONFIG_INTERNAL_H_ */
|
3690
thirdparty/pcre2/deps/sljit/sljit_src/sljitLir.c
vendored
Normal file
3690
thirdparty/pcre2/deps/sljit/sljit_src/sljitLir.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2586
thirdparty/pcre2/deps/sljit/sljit_src/sljitLir.h
vendored
Normal file
2586
thirdparty/pcre2/deps/sljit/sljit_src/sljitLir.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4758
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_32.c
vendored
Normal file
4758
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_32.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3571
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_64.c
vendored
Normal file
3571
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_64.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4418
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_T2_32.c
vendored
Normal file
4418
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_T2_32.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3882
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c
vendored
Normal file
3882
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
472
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_32.c
vendored
Normal file
472
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_32.c
vendored
Normal file
@@ -0,0 +1,472 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* mips 32-bit arch dependent functions. */
|
||||
|
||||
static sljit_s32 emit_copysign(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_sw src1, sljit_sw src2, sljit_sw dst)
|
||||
{
|
||||
int is_32 = (op & SLJIT_32);
|
||||
sljit_ins mfhc = MFC1, mthc = MTC1;
|
||||
sljit_ins src1_r = FS(src1), src2_r = FS(src2), dst_r = FS(dst);
|
||||
|
||||
if (!is_32) {
|
||||
switch (cpu_feature_list & CPU_FEATURE_FR) {
|
||||
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
|
||||
case CPU_FEATURE_FR:
|
||||
mfhc = MFHC1;
|
||||
mthc = MTHC1;
|
||||
break;
|
||||
#endif /* SLJIT_MIPS_REV >= 2 */
|
||||
default:
|
||||
src1_r |= (1 << 11);
|
||||
src2_r |= (1 << 11);
|
||||
dst_r |= (1 << 11);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, mfhc | T(TMP_REG1) | src1_r, DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, mfhc | T(TMP_REG2) | src2_r, DR(TMP_REG2)));
|
||||
if (!is_32 && src1 != dst)
|
||||
FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(src1) | FD(dst), MOVABLE_INS));
|
||||
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif /* MIPS III */
|
||||
FAIL_IF(push_inst(compiler, XOR | T(TMP_REG1) | D(TMP_REG2) | S(TMP_REG2), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, SRL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, XOR | T(TMP_REG2) | D(TMP_REG1) | S(TMP_REG1), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, mthc | T(TMP_REG1) | dst_r, MOVABLE_INS));
|
||||
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
|
||||
if (mthc == MTC1)
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
#endif /* MIPS III */
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
|
||||
{
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
||||
if (imm < 0 && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));
|
||||
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
|
||||
sljit_s32 freg, sljit_f64 value)
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN
|
||||
sljit_s32 lo;
|
||||
sljit_s32 hi;
|
||||
#else /* !SLJIT_LITTLE_ENDIAN */
|
||||
sljit_s32 hi;
|
||||
sljit_s32 lo;
|
||||
#endif /* SLJIT_LITTLE_ENDIAN */
|
||||
} bin;
|
||||
sljit_f64 value;
|
||||
} u;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fset64(compiler, freg, value));
|
||||
|
||||
u.value = value;
|
||||
|
||||
if (u.bin.lo != 0)
|
||||
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.bin.lo));
|
||||
if (u.bin.hi != 0)
|
||||
FAIL_IF(load_immediate(compiler, DR(TMP_REG2), u.bin.hi));
|
||||
|
||||
FAIL_IF(push_inst(compiler, MTC1 | (u.bin.lo != 0 ? T(TMP_REG1) : TA(0)) | FS(freg), MOVABLE_INS));
|
||||
switch (cpu_feature_list & CPU_FEATURE_FR) {
|
||||
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
|
||||
case CPU_FEATURE_FR:
|
||||
return push_inst(compiler, MTHC1 | (u.bin.hi != 0 ? T(TMP_REG2) : TA(0)) | FS(freg), MOVABLE_INS);
|
||||
#endif /* SLJIT_MIPS_REV >= 2 */
|
||||
default:
|
||||
FAIL_IF(push_inst(compiler, MTC1 | (u.bin.hi != 0 ? T(TMP_REG2) : TA(0)) | FS(freg) | (1 << 11), MOVABLE_INS));
|
||||
break;
|
||||
}
|
||||
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif /* MIPS III */
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 freg, sljit_s32 reg)
|
||||
{
|
||||
sljit_s32 reg2 = 0;
|
||||
sljit_ins inst = FS(freg);
|
||||
sljit_ins mthc = MTC1, mfhc = MFC1;
|
||||
int is_32 = (op & SLJIT_32);
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
if (reg & REG_PAIR_MASK) {
|
||||
reg2 = REG_PAIR_SECOND(reg);
|
||||
reg = REG_PAIR_FIRST(reg);
|
||||
|
||||
inst |= T(reg2);
|
||||
|
||||
if (op == SLJIT_COPY_TO_F64)
|
||||
FAIL_IF(push_inst(compiler, MTC1 | inst, MOVABLE_INS));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, MFC1 | inst, DR(reg2)));
|
||||
|
||||
inst = FS(freg) | (1 << 11);
|
||||
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
|
||||
if (cpu_feature_list & CPU_FEATURE_FR) {
|
||||
mthc = MTHC1;
|
||||
mfhc = MFHC1;
|
||||
inst = FS(freg);
|
||||
}
|
||||
#endif /* SLJIT_MIPS_REV >= 2 */
|
||||
}
|
||||
|
||||
inst |= T(reg);
|
||||
if (!is_32 && !reg2) {
|
||||
switch (cpu_feature_list & CPU_FEATURE_FR) {
|
||||
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
|
||||
case CPU_FEATURE_FR:
|
||||
mthc = MTHC1;
|
||||
mfhc = MFHC1;
|
||||
break;
|
||||
#endif /* SLJIT_MIPS_REV >= 2 */
|
||||
default:
|
||||
inst |= (1 << 11);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (op == SLJIT_COPY_TO_F64)
|
||||
FAIL_IF(push_inst(compiler, mthc | inst, MOVABLE_INS));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, mfhc | inst, DR(reg)));
|
||||
|
||||
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
|
||||
if (mthc == MTC1 || mfhc == MFC1)
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
#endif /* MIPS III */
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
SLJIT_UNUSED_ARG(executable_offset);
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
|
||||
SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
|
||||
}
|
||||
|
||||
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr, sljit_u32 *extra_space)
|
||||
{
|
||||
sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;
|
||||
sljit_u32 offset = 0;
|
||||
sljit_s32 float_arg_count = 0;
|
||||
sljit_s32 word_arg_count = 0;
|
||||
sljit_s32 types = 0;
|
||||
sljit_ins prev_ins = NOP;
|
||||
sljit_ins ins = NOP;
|
||||
sljit_u8 offsets[4];
|
||||
sljit_u8 *offsets_ptr = offsets;
|
||||
#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN
|
||||
sljit_ins f64_hi = TA(7), f64_lo = TA(6);
|
||||
#else
|
||||
sljit_ins f64_hi = TA(6), f64_lo = TA(7);
|
||||
#endif /* SLJIT_LITTLE_ENDIAN */
|
||||
|
||||
SLJIT_ASSERT(reg_map[TMP_REG2] == 4 && freg_map[TMP_FREG1] == 12);
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
|
||||
/* See ABI description in sljit_emit_enter. */
|
||||
|
||||
while (arg_types) {
|
||||
types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
|
||||
*offsets_ptr = (sljit_u8)offset;
|
||||
|
||||
switch (arg_types & SLJIT_ARG_MASK) {
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
if (offset & 0x7) {
|
||||
offset += sizeof(sljit_sw);
|
||||
*offsets_ptr = (sljit_u8)offset;
|
||||
}
|
||||
|
||||
if (word_arg_count == 0 && float_arg_count <= 1)
|
||||
*offsets_ptr = (sljit_u8)(254 + float_arg_count);
|
||||
|
||||
offset += sizeof(sljit_f64);
|
||||
float_arg_count++;
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
if (word_arg_count == 0 && float_arg_count <= 1)
|
||||
*offsets_ptr = (sljit_u8)(254 + float_arg_count);
|
||||
|
||||
offset += sizeof(sljit_f32);
|
||||
float_arg_count++;
|
||||
break;
|
||||
default:
|
||||
offset += sizeof(sljit_sw);
|
||||
word_arg_count++;
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
offsets_ptr++;
|
||||
}
|
||||
|
||||
/* Stack is aligned to 16 bytes. */
|
||||
SLJIT_ASSERT(offset <= 8 * sizeof(sljit_sw));
|
||||
|
||||
if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {
|
||||
if (is_tail_call) {
|
||||
offset = (offset + sizeof(sljit_sw) + 15) & ~(sljit_uw)0xf;
|
||||
FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset, &prev_ins));
|
||||
*extra_space = offset;
|
||||
} else {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP)));
|
||||
*extra_space = 16;
|
||||
}
|
||||
} else {
|
||||
if (is_tail_call)
|
||||
FAIL_IF(emit_stack_frame_release(compiler, 0, &prev_ins));
|
||||
*extra_space = 0;
|
||||
}
|
||||
|
||||
while (types) {
|
||||
--offsets_ptr;
|
||||
|
||||
switch (types & SLJIT_ARG_MASK) {
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
if (*offsets_ptr < 4 * sizeof(sljit_sw)) {
|
||||
if (prev_ins != NOP)
|
||||
FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
|
||||
|
||||
/* Must be preceded by at least one other argument,
|
||||
* and its starting offset must be 8 because of alignment. */
|
||||
SLJIT_ASSERT((*offsets_ptr >> 2) == 2);
|
||||
switch (cpu_feature_list & CPU_FEATURE_FR) {
|
||||
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
|
||||
case CPU_FEATURE_FR:
|
||||
prev_ins = MFHC1 | f64_hi | FS(float_arg_count);
|
||||
break;
|
||||
#endif /* SLJIT_MIPS_REV >= 2 */
|
||||
default:
|
||||
prev_ins = MFC1 | f64_hi | FS(float_arg_count) | (1 << 11);
|
||||
break;
|
||||
}
|
||||
ins = MFC1 | f64_lo | FS(float_arg_count);
|
||||
} else if (*offsets_ptr < 254)
|
||||
ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr);
|
||||
else if (*offsets_ptr == 254)
|
||||
ins = MOV_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1);
|
||||
|
||||
float_arg_count--;
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
if (*offsets_ptr < 4 * sizeof (sljit_sw))
|
||||
ins = MFC1 | TA(4 + (*offsets_ptr >> 2)) | FS(float_arg_count);
|
||||
else if (*offsets_ptr < 254)
|
||||
ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr);
|
||||
else if (*offsets_ptr == 254)
|
||||
ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1);
|
||||
|
||||
float_arg_count--;
|
||||
break;
|
||||
default:
|
||||
if (*offsets_ptr >= 4 * sizeof (sljit_sw))
|
||||
ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(*offsets_ptr);
|
||||
else if ((*offsets_ptr >> 2) != word_arg_count - 1)
|
||||
ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (*offsets_ptr >> 2));
|
||||
else if (*offsets_ptr == 0)
|
||||
ins = ADDU | S(SLJIT_R0) | TA(0) | DA(4);
|
||||
|
||||
word_arg_count--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ins != NOP) {
|
||||
if (prev_ins != NOP)
|
||||
FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
|
||||
prev_ins = ins;
|
||||
ins = NOP;
|
||||
}
|
||||
|
||||
types >>= SLJIT_ARG_SHIFT;
|
||||
}
|
||||
|
||||
*ins_ptr = prev_ins;
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types)
|
||||
{
|
||||
struct sljit_jump *jump;
|
||||
sljit_u32 extra_space = 0;
|
||||
sljit_ins ins = NOP;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
PTR_FAIL_IF(!jump);
|
||||
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
||||
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
|
||||
extra_space = (sljit_u32)type;
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
|
||||
} else if (type & SLJIT_CALL_RETURN)
|
||||
PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
||||
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25);
|
||||
|
||||
if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)
|
||||
jump->flags |= IS_MOVABLE;
|
||||
|
||||
if (!(type & SLJIT_CALL_RETURN) || extra_space > 0) {
|
||||
jump->flags |= IS_JAL;
|
||||
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
jump->flags |= IS_CALL;
|
||||
|
||||
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
} else
|
||||
PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
|
||||
|
||||
jump->addr = compiler->size;
|
||||
PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
|
||||
|
||||
/* Maximum number of instructions required for generating a constant. */
|
||||
compiler->size += 2;
|
||||
|
||||
if (extra_space == 0)
|
||||
return jump;
|
||||
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG,
|
||||
SLJIT_MEM1(SLJIT_SP), (sljit_sw)(extra_space - sizeof(sljit_sw))));
|
||||
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
PTR_FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
|
||||
PTR_FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(extra_space),
|
||||
(type & SLJIT_CALL_RETURN) ? UNMOVABLE_INS : DR(SLJIT_SP)));
|
||||
return jump;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_u32 extra_space = (sljit_u32)type;
|
||||
sljit_ins ins;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
|
||||
src = PIC_ADDR_REG;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
|
||||
src = PIC_ADDR_REG;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
||||
|
||||
if (ins != NOP)
|
||||
FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
|
||||
}
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25);
|
||||
|
||||
if (src == SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
|
||||
else if (src != PIC_ADDR_REG)
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
|
||||
|
||||
FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
|
||||
|
||||
/* Register input. */
|
||||
if (!(type & SLJIT_CALL_RETURN) || extra_space > 0)
|
||||
FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
|
||||
|
||||
if (extra_space == 0)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG,
|
||||
SLJIT_MEM1(SLJIT_SP), (sljit_sw)(extra_space - sizeof(sljit_sw))));
|
||||
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
|
||||
return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(extra_space),
|
||||
(type & SLJIT_CALL_RETURN) ? UNMOVABLE_INS : DR(SLJIT_SP));
|
||||
}
|
387
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_64.c
vendored
Normal file
387
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_64.c
vendored
Normal file
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* mips 64-bit arch dependent functions. */
|
||||
|
||||
static sljit_s32 emit_copysign(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 src1, sljit_s32 src2, sljit_s32 dst)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | T(TMP_REG1) | FS(src1), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | T(TMP_REG2) | FS(src2), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG2) | T(TMP_REG1) | D(TMP_REG2), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | T(TMP_REG2) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DMTC1, MTC1) | T(TMP_REG1) | FS(dst), MOVABLE_INS));
|
||||
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
|
||||
if (!(op & SLJIT_32))
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
#endif /* MIPS III */
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
|
||||
{
|
||||
sljit_s32 shift = 32;
|
||||
sljit_s32 shift2;
|
||||
sljit_s32 inv = 0;
|
||||
sljit_ins ins;
|
||||
sljit_uw uimm;
|
||||
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
||||
if (imm < 0 && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
||||
if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
|
||||
FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Zero extended number. */
|
||||
uimm = (sljit_uw)imm;
|
||||
if (imm < 0) {
|
||||
uimm = ~(sljit_uw)imm;
|
||||
inv = 1;
|
||||
}
|
||||
|
||||
while (!(uimm & 0xff00000000000000l)) {
|
||||
shift -= 8;
|
||||
uimm <<= 8;
|
||||
}
|
||||
|
||||
if (!(uimm & 0xf000000000000000l)) {
|
||||
shift -= 4;
|
||||
uimm <<= 4;
|
||||
}
|
||||
|
||||
if (!(uimm & 0xc000000000000000l)) {
|
||||
shift -= 2;
|
||||
uimm <<= 2;
|
||||
}
|
||||
|
||||
if ((sljit_sw)uimm < 0) {
|
||||
uimm >>= 1;
|
||||
shift += 1;
|
||||
}
|
||||
SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));
|
||||
|
||||
if (inv)
|
||||
uimm = ~uimm;
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
|
||||
if (uimm & 0x0000ffff00000000l)
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));
|
||||
|
||||
imm &= (1l << shift) - 1;
|
||||
if (!(imm & ~0xffff)) {
|
||||
ins = (shift == 32) ? DSLL32 : DSLL;
|
||||
if (shift < 32)
|
||||
ins |= SH_IMM(shift);
|
||||
FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));
|
||||
return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
}
|
||||
|
||||
/* Double shifts needs to be performed. */
|
||||
uimm <<= 32;
|
||||
shift2 = shift - 16;
|
||||
|
||||
while (!(uimm & 0xf000000000000000l)) {
|
||||
shift2 -= 4;
|
||||
uimm <<= 4;
|
||||
}
|
||||
|
||||
if (!(uimm & 0xc000000000000000l)) {
|
||||
shift2 -= 2;
|
||||
uimm <<= 2;
|
||||
}
|
||||
|
||||
if (!(uimm & 0x8000000000000000l)) {
|
||||
shift2--;
|
||||
uimm <<= 1;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));
|
||||
|
||||
FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
|
||||
FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));
|
||||
|
||||
imm &= (1l << shift2) - 1;
|
||||
return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
|
||||
sljit_s32 freg, sljit_f64 value)
|
||||
{
|
||||
union {
|
||||
sljit_sw imm;
|
||||
sljit_f64 value;
|
||||
} u;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fset64(compiler, freg, value));
|
||||
|
||||
u.value = value;
|
||||
|
||||
if (u.imm == 0) {
|
||||
FAIL_IF(push_inst(compiler, DMTC1 | TA(0) | FS(freg), MOVABLE_INS));
|
||||
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif /* MIPS III */
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.imm));
|
||||
FAIL_IF(push_inst(compiler, DMTC1 | T(TMP_REG1) | FS(freg), MOVABLE_INS));
|
||||
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif /* MIPS III */
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 freg, sljit_s32 reg)
|
||||
{
|
||||
sljit_ins inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
|
||||
|
||||
inst = T(reg) | FS(freg);
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_COPY_TO_F64)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DMTC1, MTC1) | inst, MOVABLE_INS));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | inst, DR(reg)));
|
||||
|
||||
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
|
||||
if (!(op & SLJIT_32))
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
#endif /* MIPS III */
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
SLJIT_UNUSED_ARG(executable_offset);
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 0);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((sljit_ins)(new_target >> 48) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | ((sljit_ins)(new_target >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((sljit_ins)(new_target >> 16) & 0xffff);
|
||||
inst[5] = (inst[5] & 0xffff0000) | ((sljit_ins)new_target & 0xffff);
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 1);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 6);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
|
||||
}
|
||||
|
||||
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
|
||||
{
|
||||
sljit_s32 arg_count = 0;
|
||||
sljit_s32 word_arg_count = 0;
|
||||
sljit_s32 float_arg_count = 0;
|
||||
sljit_s32 types = 0;
|
||||
sljit_ins prev_ins = *ins_ptr;
|
||||
sljit_ins ins = NOP;
|
||||
|
||||
SLJIT_ASSERT(reg_map[TMP_REG2] == 4 && freg_map[TMP_FREG1] == 12);
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
|
||||
|
||||
switch (arg_types & SLJIT_ARG_MASK) {
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
arg_count++;
|
||||
float_arg_count++;
|
||||
break;
|
||||
default:
|
||||
arg_count++;
|
||||
word_arg_count++;
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
}
|
||||
|
||||
while (types) {
|
||||
switch (types & SLJIT_ARG_MASK) {
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
if (arg_count != float_arg_count)
|
||||
ins = MOV_fmt(FMT_D) | FS(float_arg_count) | FD(arg_count);
|
||||
else if (arg_count == 1)
|
||||
ins = MOV_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1);
|
||||
arg_count--;
|
||||
float_arg_count--;
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
if (arg_count != float_arg_count)
|
||||
ins = MOV_fmt(FMT_S) | FS(float_arg_count) | FD(arg_count);
|
||||
else if (arg_count == 1)
|
||||
ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1);
|
||||
arg_count--;
|
||||
float_arg_count--;
|
||||
break;
|
||||
default:
|
||||
if (arg_count != word_arg_count)
|
||||
ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count);
|
||||
else if (arg_count == 1)
|
||||
ins = DADDU | S(SLJIT_R0) | TA(0) | DA(4);
|
||||
arg_count--;
|
||||
word_arg_count--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ins != NOP) {
|
||||
if (prev_ins != NOP)
|
||||
FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
|
||||
prev_ins = ins;
|
||||
ins = NOP;
|
||||
}
|
||||
|
||||
types >>= SLJIT_ARG_SHIFT;
|
||||
}
|
||||
|
||||
*ins_ptr = prev_ins;
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types)
|
||||
{
|
||||
struct sljit_jump *jump;
|
||||
sljit_ins ins = NOP;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
PTR_FAIL_IF(!jump);
|
||||
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
||||
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
||||
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
|
||||
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25);
|
||||
|
||||
if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)
|
||||
jump->flags |= IS_MOVABLE;
|
||||
|
||||
if (!(type & SLJIT_CALL_RETURN)) {
|
||||
jump->flags |= IS_JAL;
|
||||
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
jump->flags |= IS_CALL;
|
||||
|
||||
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
} else
|
||||
PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
|
||||
|
||||
jump->addr = compiler->size;
|
||||
PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
|
||||
|
||||
/* Maximum number of instructions required for generating a constant. */
|
||||
compiler->size += 6;
|
||||
return jump;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_ins ins = NOP;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
|
||||
src = PIC_ADDR_REG;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
|
||||
FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
|
||||
src = PIC_ADDR_REG;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
||||
|
||||
if (ins != NOP)
|
||||
FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
|
||||
}
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG1);
|
||||
|
||||
if (src == SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
|
||||
else if (src != PIC_ADDR_REG)
|
||||
FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
|
||||
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
||||
|
||||
FAIL_IF(call_with_args(compiler, arg_types, &ins));
|
||||
|
||||
/* Register input. */
|
||||
if (!(type & SLJIT_CALL_RETURN))
|
||||
FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
|
||||
return push_inst(compiler, ins, UNMOVABLE_INS);
|
||||
}
|
4369
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_common.c
vendored
Normal file
4369
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_common.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
485
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_32.c
vendored
Normal file
485
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_32.c
vendored
Normal file
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* ppc 32-bit arch dependent functions. */
|
||||
|
||||
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
|
||||
{
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
|
||||
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Simplified mnemonics: clrlwi. */
|
||||
#define INS_CLEAR_LEFT(dst, src, from) \
|
||||
(RLWINM | S(src) | A(dst) | RLWI_MBE(from, 31))
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
|
||||
sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
|
||||
{
|
||||
sljit_u32 imm;
|
||||
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOV_S8:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_S8)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
|
||||
}
|
||||
else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOV_S16:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_S16)
|
||||
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_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, CNTLZW | S(src2) | A(dst));
|
||||
|
||||
case SLJIT_CTZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2)));
|
||||
FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, CNTLZW | S(dst) | A(dst)));
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM(-32)));
|
||||
/* The highest bits are set, if dst < 32, zero otherwise. */
|
||||
FAIL_IF(push_inst(compiler, SRWI(27) | S(TMP_REG1) | A(TMP_REG1)));
|
||||
return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1));
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||
return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
|
||||
if (flags & ALT_FORM3)
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
||||
|
||||
imm = compiler->imm;
|
||||
|
||||
if (flags & ALT_FORM4) {
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));
|
||||
src1 = dst;
|
||||
}
|
||||
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
SLJIT_ASSERT(!(flags & ALT_FORM4));
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
||||
if (flags & ALT_FORM5)
|
||||
return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
|
||||
|
||||
case SLJIT_ADDC:
|
||||
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
|
||||
|
||||
case SLJIT_SUB:
|
||||
if (flags & ALT_FORM1) {
|
||||
if (flags & ALT_FORM2) {
|
||||
FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));
|
||||
if (!(flags & ALT_FORM3))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));
|
||||
if (!(flags & ALT_FORM3))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
if (flags & ALT_FORM3) {
|
||||
FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
|
||||
if (!(flags & ALT_FORM4))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
|
||||
if (!(flags & ALT_FORM4))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM3) {
|
||||
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||
if (src1 != TMP_ZERO)
|
||||
return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
return push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM4) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
|
||||
if (!(flags & ALT_SET_FLAGS)) {
|
||||
SLJIT_ASSERT(src1 != TMP_ZERO);
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM5)
|
||||
return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
if (src1 != TMP_ZERO)
|
||||
return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
|
||||
|
||||
case SLJIT_SUBC:
|
||||
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_MUL:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_AND:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_OR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
imm = compiler->imm;
|
||||
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm)));
|
||||
return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16));
|
||||
}
|
||||
return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_XOR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
imm = compiler->imm;
|
||||
|
||||
FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm)));
|
||||
return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16));
|
||||
}
|
||||
if (flags & ALT_FORM4) {
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
|
||||
}
|
||||
return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_SHL:
|
||||
case SLJIT_MSHL:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
imm = compiler->imm & 0x1f;
|
||||
return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst));
|
||||
}
|
||||
|
||||
if (op == SLJIT_MSHL) {
|
||||
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
|
||||
src2 = TMP_REG2;
|
||||
}
|
||||
|
||||
return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_LSHR:
|
||||
case SLJIT_MLSHR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
imm = compiler->imm & 0x1f;
|
||||
/* Since imm can be 0, SRWI() cannot be used. */
|
||||
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31));
|
||||
}
|
||||
|
||||
if (op == SLJIT_MLSHR) {
|
||||
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
|
||||
src2 = TMP_REG2;
|
||||
}
|
||||
|
||||
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_ASHR:
|
||||
case SLJIT_MASHR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
imm = compiler->imm & 0x1f;
|
||||
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11));
|
||||
}
|
||||
|
||||
if (op == SLJIT_MASHR) {
|
||||
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
|
||||
src2 = TMP_REG2;
|
||||
}
|
||||
|
||||
return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_ROTL:
|
||||
case SLJIT_ROTR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
imm = compiler->imm;
|
||||
|
||||
if (op == SLJIT_ROTR)
|
||||
imm = (sljit_u32)(-(sljit_s32)imm);
|
||||
|
||||
imm &= 0x1f;
|
||||
return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31));
|
||||
}
|
||||
|
||||
if (op == SLJIT_ROTR) {
|
||||
FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0));
|
||||
src2 = TMP_REG2;
|
||||
}
|
||||
|
||||
return push_inst(compiler, RLWNM | S(src1) | A(dst) | B(src2) | RLWI_MBE(0, 31));
|
||||
}
|
||||
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
|
||||
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
sljit_s32 invert_sign = 1;
|
||||
|
||||
if (src == SLJIT_IMM) {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ (sljit_sw)0x80000000));
|
||||
src = TMP_REG1;
|
||||
invert_sign = 0;
|
||||
} else if (!FAST_IS_REG(src)) {
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
/* First, a special double precision floating point value is constructed:
|
||||
(2^53 + (src xor (2^31)))
|
||||
The upper 32 bits of this number is a constant, and the lower 32 bits
|
||||
is simply the value of the source argument. The xor 2^31 operation adds
|
||||
0x80000000 to the source argument, which moves it into the 0 - 0xffffffff
|
||||
range. Finally we substract 2^53 + 2^31 to get the converted value. */
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
|
||||
if (invert_sign)
|
||||
FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));
|
||||
FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
|
||||
FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));
|
||||
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
|
||||
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
|
||||
FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
|
||||
|
||||
if (op & SLJIT_32)
|
||||
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (src == SLJIT_IMM) {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
||||
src = TMP_REG1;
|
||||
} else if (!FAST_IS_REG(src)) {
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
/* First, a special double precision floating point value is constructed:
|
||||
(2^53 + src)
|
||||
The upper 32 bits of this number is a constant, and the lower 32 bits
|
||||
is simply the value of the source argument. Finally we substract 2^53
|
||||
to get the converted value. */
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
|
||||
FAIL_IF(push_inst(compiler, STW | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
|
||||
FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
|
||||
|
||||
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
FAIL_IF(push_inst(compiler, STW | S(TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
|
||||
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
|
||||
FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
|
||||
|
||||
if (op & SLJIT_32)
|
||||
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
|
||||
sljit_s32 freg, sljit_f64 value)
|
||||
{
|
||||
union {
|
||||
sljit_s32 imm[2];
|
||||
sljit_f64 value;
|
||||
} u;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fset64(compiler, freg, value));
|
||||
|
||||
u.value = value;
|
||||
|
||||
if (u.imm[0] != 0)
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0]));
|
||||
if (u.imm[1] != 0)
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1]));
|
||||
|
||||
/* Saved in the same endianness. */
|
||||
FAIL_IF(push_inst(compiler, STW | S(u.imm[0] != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
FAIL_IF(push_inst(compiler, STW | S(u.imm[1] != 0 ? TMP_REG2 : TMP_ZERO) | A(SLJIT_SP) | (TMP_MEM_OFFSET + sizeof(sljit_s32))));
|
||||
return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 freg, sljit_s32 reg)
|
||||
{
|
||||
sljit_s32 reg2 = 0;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
|
||||
|
||||
if (op & SLJIT_32) {
|
||||
if (op == SLJIT_COPY32_TO_F32) {
|
||||
FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, STFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
|
||||
}
|
||||
|
||||
if (reg & REG_PAIR_MASK) {
|
||||
reg2 = REG_PAIR_SECOND(reg);
|
||||
reg = REG_PAIR_FIRST(reg);
|
||||
}
|
||||
|
||||
if (op == SLJIT_COPY_TO_F64) {
|
||||
FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
|
||||
|
||||
if (reg2 != 0)
|
||||
FAIL_IF(push_inst(compiler, STW | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
|
||||
|
||||
return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
|
||||
if (reg2 != 0)
|
||||
FAIL_IF(push_inst(compiler, LWZ | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
|
||||
|
||||
return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
SLJIT_UNUSED_ARG(executable_offset);
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
|
||||
SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
719
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_64.c
vendored
Normal file
719
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_64.c
vendored
Normal file
@@ -0,0 +1,719 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* ppc 64-bit arch dependent functions. */
|
||||
|
||||
#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) )
|
||||
#elif defined(__xlc__)
|
||||
#error "Please enable GCC syntax for inline assembly statements"
|
||||
#else
|
||||
#error "Must implement count leading zeroes"
|
||||
#endif
|
||||
|
||||
/* Computes SLDI(63 - shift). */
|
||||
#define PUSH_SLDI_NEG(reg, shift) \
|
||||
push_inst(compiler, RLDICR | S(reg) | A(reg) | RLDI_SH(63 - shift) | RLDI_ME(shift))
|
||||
|
||||
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
|
||||
{
|
||||
sljit_uw tmp;
|
||||
sljit_uw shift;
|
||||
sljit_uw tmp2;
|
||||
sljit_uw shift2;
|
||||
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
|
||||
|
||||
if (((sljit_uw)imm >> 16) == 0)
|
||||
return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
|
||||
|
||||
if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (((sljit_uw)imm >> 32) == 0) {
|
||||
FAIL_IF(push_inst(compiler, ORIS | S(TMP_ZERO) | A(reg) | IMM(imm >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Count leading zeroes. */
|
||||
tmp = (sljit_uw)((imm >= 0) ? imm : ~imm);
|
||||
ASM_SLJIT_CLZ(tmp, shift);
|
||||
SLJIT_ASSERT(shift > 0);
|
||||
shift--;
|
||||
tmp = ((sljit_uw)imm << shift);
|
||||
|
||||
if ((tmp & ~0xffff000000000000ul) == 0) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
|
||||
shift += 15;
|
||||
return PUSH_SLDI_NEG(reg, shift);
|
||||
}
|
||||
|
||||
if ((tmp & ~0xffffffff00000000ul) == 0) {
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32)));
|
||||
shift += 31;
|
||||
return PUSH_SLDI_NEG(reg, shift);
|
||||
}
|
||||
|
||||
/* Cut out the 16 bit from immediate. */
|
||||
shift += 15;
|
||||
tmp2 = (sljit_uw)imm & (((sljit_uw)1 << (63 - shift)) - 1);
|
||||
|
||||
if (tmp2 <= 0xffff) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
|
||||
FAIL_IF(PUSH_SLDI_NEG(reg, shift));
|
||||
return push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)tmp2);
|
||||
}
|
||||
|
||||
if (tmp2 <= 0xffffffff) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
|
||||
FAIL_IF(PUSH_SLDI_NEG(reg, shift));
|
||||
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
ASM_SLJIT_CLZ(tmp2, shift2);
|
||||
tmp2 <<= shift2;
|
||||
|
||||
if ((tmp2 & ~0xffff000000000000ul) == 0) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
|
||||
shift2 += 15;
|
||||
shift += (63 - shift2);
|
||||
FAIL_IF(PUSH_SLDI_NEG(reg, shift));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 48)));
|
||||
return PUSH_SLDI_NEG(reg, shift2);
|
||||
}
|
||||
|
||||
/* The general version. */
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)((sljit_uw)imm >> 48)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32)));
|
||||
FAIL_IF(PUSH_SLDI_NEG(reg, 31));
|
||||
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16)));
|
||||
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm));
|
||||
}
|
||||
|
||||
#undef PUSH_SLDI_NEG
|
||||
|
||||
#define CLRLDI(dst, src, n) \
|
||||
(RLDICL | S(src) | A(dst) | RLDI_SH(0) | RLDI_MB(n))
|
||||
|
||||
/* Sign extension for integer operations. */
|
||||
#define UN_EXTS() \
|
||||
if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
|
||||
src2 = TMP_REG2; \
|
||||
}
|
||||
|
||||
#define BIN_EXTS() \
|
||||
if (flags & ALT_SIGN_EXT) { \
|
||||
if (flags & REG1_SOURCE) { \
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
|
||||
src1 = TMP_REG1; \
|
||||
} \
|
||||
if (flags & REG2_SOURCE) { \
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
|
||||
src2 = TMP_REG2; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define BIN_IMM_EXTS() \
|
||||
if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
|
||||
src1 = TMP_REG1; \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
|
||||
sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
|
||||
{
|
||||
sljit_u32 imm;
|
||||
|
||||
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_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_S32)
|
||||
return push_inst(compiler, EXTSW | S(src2) | A(dst));
|
||||
return push_inst(compiler, CLRLDI(dst, src2, 32));
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOV_S8:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_S8)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
return push_inst(compiler, CLRLDI(dst, src2, 56));
|
||||
}
|
||||
else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOV_S16:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_S16)
|
||||
return push_inst(compiler, EXTSH | S(src2) | A(dst));
|
||||
return push_inst(compiler, CLRLDI(dst, src2, 48));
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(src2) | A(dst));
|
||||
|
||||
case SLJIT_CTZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2)));
|
||||
FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(dst) | A(dst)));
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM((flags & ALT_FORM1) ? -32 : -64)));
|
||||
/* The highest bits are set, if dst < bit width, zero otherwise. */
|
||||
FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? SRWI(27) : SRDI(58)) | S(TMP_REG1) | A(TMP_REG1)));
|
||||
return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1));
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & ALT_FORM1) {
|
||||
if (flags & ALT_SIGN_EXT) {
|
||||
FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1)));
|
||||
src1 = TMP_REG1;
|
||||
FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
}
|
||||
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||
FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)));
|
||||
if (flags & ALT_SIGN_EXT)
|
||||
return push_inst(compiler, SRDI(32) | S(dst) | A(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
|
||||
if (flags & ALT_FORM3)
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
||||
|
||||
imm = compiler->imm;
|
||||
|
||||
if (flags & ALT_FORM4) {
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));
|
||||
src1 = dst;
|
||||
}
|
||||
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
BIN_IMM_EXTS();
|
||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM4) {
|
||||
if (flags & ALT_FORM5)
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, CMPI | A(dst) | 0);
|
||||
}
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
||||
BIN_EXTS();
|
||||
if (flags & ALT_FORM5)
|
||||
return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
|
||||
|
||||
case SLJIT_ADDC:
|
||||
BIN_EXTS();
|
||||
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
|
||||
|
||||
case SLJIT_SUB:
|
||||
if (flags & ALT_FORM1) {
|
||||
if (flags & ALT_FORM2) {
|
||||
FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
|
||||
if (!(flags & ALT_FORM3))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
|
||||
if (!(flags & ALT_FORM3))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
if (flags & ALT_FORM3) {
|
||||
FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
|
||||
if (!(flags & ALT_FORM4))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
|
||||
if (!(flags & ALT_FORM4))
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM3) {
|
||||
if (flags & ALT_SIGN_EXT) {
|
||||
if (src1 != TMP_ZERO) {
|
||||
FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1)));
|
||||
src1 = TMP_REG1;
|
||||
}
|
||||
if (src2 != TMP_ZERO) {
|
||||
FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||
if (src1 != TMP_ZERO)
|
||||
FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2)));
|
||||
|
||||
if (flags & ALT_SIGN_EXT)
|
||||
return push_inst(compiler, SRDI(32) | S(dst) | A(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (flags & ALT_FORM4) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
|
||||
if (!(flags & ALT_SET_FLAGS)) {
|
||||
SLJIT_ASSERT(src1 != TMP_ZERO);
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
}
|
||||
|
||||
BIN_EXTS();
|
||||
if (flags & ALT_FORM5)
|
||||
return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
if (src1 != TMP_ZERO)
|
||||
return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
|
||||
|
||||
case SLJIT_SUBC:
|
||||
BIN_EXTS();
|
||||
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_MUL:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
BIN_EXTS();
|
||||
if (flags & ALT_FORM2)
|
||||
return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||
return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_AND:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_OR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
imm = compiler->imm;
|
||||
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm)));
|
||||
return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16));
|
||||
}
|
||||
return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_XOR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
imm = compiler->imm;
|
||||
|
||||
FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm)));
|
||||
return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16));
|
||||
}
|
||||
if (flags & ALT_FORM4) {
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
UN_EXTS();
|
||||
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
|
||||
}
|
||||
return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_SHL:
|
||||
case SLJIT_MSHL:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
imm = compiler->imm;
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
imm &= 0x1f;
|
||||
return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst));
|
||||
}
|
||||
|
||||
imm &= 0x3f;
|
||||
return push_inst(compiler, SLDI(imm) | RC(flags) | S(src1) | A(dst));
|
||||
}
|
||||
|
||||
if (op == SLJIT_MSHL) {
|
||||
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));
|
||||
src2 = TMP_REG2;
|
||||
}
|
||||
|
||||
return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_LSHR:
|
||||
case SLJIT_MLSHR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
imm = compiler->imm;
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
imm &= 0x1f;
|
||||
/* Since imm can be 0, SRWI() cannot be used. */
|
||||
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31));
|
||||
}
|
||||
|
||||
imm &= 0x3f;
|
||||
/* Since imm can be 0, SRDI() cannot be used. */
|
||||
return push_inst(compiler, RLDICL | RC(flags) | S(src1) | A(dst) | RLDI_SH((64 - imm) & 0x3f) | RLDI_MB(imm));
|
||||
}
|
||||
|
||||
if (op == SLJIT_MLSHR) {
|
||||
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));
|
||||
src2 = TMP_REG2;
|
||||
}
|
||||
|
||||
return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_ASHR:
|
||||
case SLJIT_MASHR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
imm = compiler->imm;
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
imm &= 0x1f;
|
||||
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11));
|
||||
}
|
||||
|
||||
imm &= 0x3f;
|
||||
return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | RLDI_SH(imm));
|
||||
}
|
||||
|
||||
if (op == SLJIT_MASHR) {
|
||||
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));
|
||||
src2 = TMP_REG2;
|
||||
}
|
||||
|
||||
return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_ROTL:
|
||||
case SLJIT_ROTR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
imm = compiler->imm;
|
||||
|
||||
if (op == SLJIT_ROTR)
|
||||
imm = (sljit_u32)(-(sljit_s32)imm);
|
||||
|
||||
if (flags & ALT_FORM2) {
|
||||
imm &= 0x1f;
|
||||
return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31));
|
||||
}
|
||||
|
||||
imm &= 0x3f;
|
||||
return push_inst(compiler, RLDICL | S(src1) | A(dst) | RLDI_SH(imm));
|
||||
}
|
||||
|
||||
if (op == SLJIT_ROTR) {
|
||||
FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0));
|
||||
src2 = TMP_REG2;
|
||||
}
|
||||
|
||||
return push_inst(compiler, ((flags & ALT_FORM2) ? (RLWNM | RLWI_MBE(0, 31)) : (RLDCL | RLDI_MB(0))) | S(src1) | A(dst) | B(src2));
|
||||
}
|
||||
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)
|
||||
{
|
||||
sljit_s32 arg_count = 0;
|
||||
sljit_s32 word_arg_count = 0;
|
||||
sljit_s32 types = 0;
|
||||
sljit_s32 reg = 0;
|
||||
|
||||
if (src)
|
||||
reg = *src & REG_MASK;
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
|
||||
|
||||
switch (arg_types & SLJIT_ARG_MASK) {
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
arg_count++;
|
||||
break;
|
||||
default:
|
||||
arg_count++;
|
||||
word_arg_count++;
|
||||
|
||||
if (arg_count != word_arg_count && arg_count == reg) {
|
||||
FAIL_IF(push_inst(compiler, OR | S(reg) | A(TMP_CALL_REG) | B(reg)));
|
||||
*src = TMP_CALL_REG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
}
|
||||
|
||||
while (types) {
|
||||
switch (types & SLJIT_ARG_MASK) {
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
arg_count--;
|
||||
break;
|
||||
default:
|
||||
if (arg_count != word_arg_count)
|
||||
FAIL_IF(push_inst(compiler, OR | S(word_arg_count) | A(arg_count) | B(word_arg_count)));
|
||||
|
||||
arg_count--;
|
||||
word_arg_count--;
|
||||
break;
|
||||
}
|
||||
|
||||
types >>= SLJIT_ARG_SHIFT;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));
|
||||
FAIL_IF(push_inst(compiler, SLDI(32) | S(reg) | A(reg)));
|
||||
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16)));
|
||||
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (src == SLJIT_IMM) {
|
||||
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
|
||||
srcw = (sljit_s32)srcw;
|
||||
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
||||
src = TMP_REG1;
|
||||
} else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));
|
||||
else
|
||||
FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
if (FAST_IS_REG(src)) {
|
||||
FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
} else
|
||||
FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
|
||||
|
||||
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
|
||||
|
||||
if (op & SLJIT_32)
|
||||
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {
|
||||
if (src == SLJIT_IMM) {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_u32)srcw));
|
||||
src = TMP_REG1;
|
||||
} else {
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, CLRLDI(TMP_REG1, src, 32)));
|
||||
else
|
||||
FAIL_IF(emit_op_mem(compiler, INT_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
|
||||
} else {
|
||||
if (src == SLJIT_IMM) {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
||||
src = TMP_REG1;
|
||||
} else if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, CMPI | CRD(0 | 1) | A(src) | 0));
|
||||
FAIL_IF(push_inst(compiler, BCx | (12 << 21) | (0 << 16) | 20));
|
||||
FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
|
||||
FAIL_IF(push_inst(compiler, Bx | ((op & SLJIT_32) ? 36 : 32)));
|
||||
|
||||
if (op & SLJIT_32)
|
||||
FAIL_IF(push_inst(compiler, RLWINM | S(src) | A(TMP_REG2) | RLWI_SH(10) | RLWI_MBE(10, 21)));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, ANDI | S(src) | A(TMP_REG2) | 0x1));
|
||||
|
||||
/* Shift right. */
|
||||
FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(63) | RLDI_MB(1)));
|
||||
|
||||
if (op & SLJIT_32)
|
||||
FAIL_IF(push_inst(compiler, RLDICR | S(TMP_REG1) | A(TMP_REG1) | RLDI_SH(0) | RLDI_ME(53)));
|
||||
|
||||
FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));
|
||||
|
||||
FAIL_IF(push_inst(compiler, STD | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
|
||||
FAIL_IF(push_inst(compiler, FADD | FD(dst_r) | FA(dst_r) | FB(dst_r)));
|
||||
}
|
||||
|
||||
if (op & SLJIT_32)
|
||||
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
|
||||
sljit_s32 freg, sljit_f64 value)
|
||||
{
|
||||
union {
|
||||
sljit_sw imm;
|
||||
sljit_f64 value;
|
||||
} u;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fset64(compiler, freg, value));
|
||||
|
||||
u.value = value;
|
||||
|
||||
if (u.imm != 0)
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));
|
||||
|
||||
FAIL_IF(push_inst(compiler, STD | S(u.imm != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 freg, sljit_s32 reg)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) {
|
||||
FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STW : STD) | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
return push_inst(compiler, ((op & SLJIT_32) ? LFS : LFD) | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STFS : STFD) | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
||||
return push_inst(compiler, ((op & SLJIT_32) ? LWZ : LD) | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
SLJIT_UNUSED_ARG(executable_offset);
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);
|
||||
inst[0] = (inst[0] & 0xffff0000u) | ((sljit_ins)(new_target >> 48) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000u) | ((sljit_ins)(new_target >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000u) | ((sljit_ins)(new_target >> 16) & 0xffff);
|
||||
inst[4] = (inst[4] & 0xffff0000u) | ((sljit_ins)new_target & 0xffff);
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 5);
|
||||
}
|
3271
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_common.c
vendored
Normal file
3271
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_common.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
142
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_32.c
vendored
Normal file
142
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_32.c
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 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_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(tmp_r);
|
||||
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));
|
||||
|
||||
if (imm & 0x800)
|
||||
imm += 0x1000;
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));
|
||||
|
||||
if ((imm & 0xfff) == 0)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
|
||||
sljit_s32 freg, sljit_f64 value)
|
||||
{
|
||||
union {
|
||||
sljit_s32 imm[2];
|
||||
sljit_f64 value;
|
||||
} u;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fset64(compiler, freg, value));
|
||||
|
||||
u.value = value;
|
||||
|
||||
if (u.imm[0] != 0)
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0], TMP_REG3));
|
||||
if (u.imm[1] != 0)
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1], TMP_REG3));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-16)));
|
||||
FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(u.imm[0] != 0 ? TMP_REG1 : TMP_ZERO) | (8 << 7)));
|
||||
FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(u.imm[1] != 0 ? TMP_REG2 : TMP_ZERO) | (12 << 7)));
|
||||
FAIL_IF(push_inst(compiler, FLD | FRD(freg) | RS1(SLJIT_SP) | IMM_I(8)));
|
||||
return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(16));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 freg, sljit_s32 reg)
|
||||
{
|
||||
sljit_ins inst;
|
||||
sljit_s32 reg2 = 0;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
|
||||
|
||||
if (op & SLJIT_32) {
|
||||
if (op == SLJIT_COPY32_TO_F32)
|
||||
inst = FMV_W_X | RS1(reg) | FRD(freg);
|
||||
else
|
||||
inst = FMV_X_W | FRS1(freg) | RD(reg);
|
||||
|
||||
return push_inst(compiler, inst);
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-16)));
|
||||
|
||||
if (reg & REG_PAIR_MASK) {
|
||||
reg2 = REG_PAIR_SECOND(reg);
|
||||
reg = REG_PAIR_FIRST(reg);
|
||||
}
|
||||
|
||||
if (op == SLJIT_COPY_TO_F64) {
|
||||
if (reg2 != 0)
|
||||
FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(reg2) | (8 << 7)));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, FSW | RS1(SLJIT_SP) | FRS2(freg) | (8 << 7)));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(reg) | (12 << 7)));
|
||||
FAIL_IF(push_inst(compiler, FLD | FRD(freg) | RS1(SLJIT_SP) | IMM_I(8)));
|
||||
} else {
|
||||
FAIL_IF(push_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(freg) | (8 << 7)));
|
||||
|
||||
if (reg2 != 0)
|
||||
FAIL_IF(push_inst(compiler, FMV_X_W | FRS1(freg) | RD(reg2)));
|
||||
|
||||
FAIL_IF(push_inst(compiler, LW | RD(reg) | RS1(SLJIT_SP) | IMM_I(12)));
|
||||
}
|
||||
|
||||
return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(16));
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins)
|
||||
{
|
||||
if ((init_value & 0x800) != 0)
|
||||
init_value += 0x1000;
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | RD(dst) | (sljit_ins)(init_value & ~0xfff)));
|
||||
return push_inst(compiler, last_ins | RS1(dst) | IMM_I(init_value));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
SLJIT_UNUSED_ARG(executable_offset);
|
||||
|
||||
if ((new_target & 0x800) != 0)
|
||||
new_target += 0x1000;
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);
|
||||
|
||||
SLJIT_ASSERT((inst[0] & 0x7f) == LUI);
|
||||
inst[0] = (inst[0] & 0xfff) | (sljit_ins)((sljit_sw)new_target & ~0xfff);
|
||||
SLJIT_ASSERT((inst[1] & 0x707f) == ADDI || (inst[1] & 0x707f) == JALR);
|
||||
inst[1] = (inst[1] & 0xfffff) | IMM_I(new_target);
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 5);
|
||||
}
|
222
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_64.c
vendored
Normal file
222
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_64.c
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 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_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r)
|
||||
{
|
||||
sljit_sw high;
|
||||
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));
|
||||
|
||||
if (imm <= 0x7fffffffl && imm >= S32_MIN) {
|
||||
if (imm > S32_MAX) {
|
||||
SLJIT_ASSERT((imm & 0x800) != 0);
|
||||
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));
|
||||
return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
|
||||
}
|
||||
|
||||
if ((imm & 0x800) != 0)
|
||||
imm += 0x1000;
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));
|
||||
|
||||
if ((imm & 0xfff) == 0)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
|
||||
}
|
||||
|
||||
/* Trailing zeroes could be used to produce shifted immediates. */
|
||||
|
||||
if (imm <= 0x7ffffffffffl && imm >= -0x80000000000l) {
|
||||
high = imm >> 12;
|
||||
|
||||
if (imm & 0x800)
|
||||
high = ~high;
|
||||
|
||||
if (high > S32_MAX) {
|
||||
SLJIT_ASSERT((high & 0x800) != 0);
|
||||
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));
|
||||
FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(high)));
|
||||
} else {
|
||||
if ((high & 0x800) != 0)
|
||||
high += 0x1000;
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(high & ~0xfff)));
|
||||
|
||||
if ((high & 0xfff) != 0)
|
||||
FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(high)));
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, SLLI | RD(dst_r) | RS1(dst_r) | IMM_I(12)));
|
||||
|
||||
if ((imm & 0xfff) != 0)
|
||||
return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(dst_r != tmp_r);
|
||||
|
||||
high = imm >> 32;
|
||||
imm = (sljit_s32)imm;
|
||||
|
||||
if ((imm & 0x80000000l) != 0)
|
||||
high = ~high;
|
||||
|
||||
if (high <= 0x7ffff && high >= -0x80000) {
|
||||
FAIL_IF(push_inst(compiler, LUI | RD(tmp_r) | (sljit_ins)(high << 12)));
|
||||
high = 0x1000;
|
||||
} else {
|
||||
if ((high & 0x800) != 0)
|
||||
high += 0x1000;
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | RD(tmp_r) | (sljit_ins)(high & ~0xfff)));
|
||||
high &= 0xfff;
|
||||
}
|
||||
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)));
|
||||
imm = 0;
|
||||
} else if (imm > S32_MAX) {
|
||||
SLJIT_ASSERT((imm & 0x800) != 0);
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));
|
||||
imm = 0x1000 | (imm & 0xfff);
|
||||
} else {
|
||||
if ((imm & 0x800) != 0)
|
||||
imm += 0x1000;
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));
|
||||
imm &= 0xfff;
|
||||
}
|
||||
|
||||
if ((high & 0xfff) != 0)
|
||||
FAIL_IF(push_inst(compiler, ADDI | RD(tmp_r) | RS1(tmp_r) | IMM_I(high)));
|
||||
|
||||
if (imm & 0x1000)
|
||||
FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)));
|
||||
else if (imm != 0)
|
||||
FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(tmp_r) | IMM_I((high & 0x1000) ? 20 : 32)));
|
||||
return push_inst(compiler, XOR | RD(dst_r) | RS1(dst_r) | RS2(tmp_r));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
|
||||
sljit_s32 freg, sljit_f64 value)
|
||||
{
|
||||
union {
|
||||
sljit_sw imm;
|
||||
sljit_f64 value;
|
||||
} u;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fset64(compiler, freg, value));
|
||||
|
||||
u.value = value;
|
||||
|
||||
if (u.imm == 0)
|
||||
return push_inst(compiler, FMV_W_X | (1 << 25) | RS1(TMP_ZERO) | FRD(freg));
|
||||
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm, TMP_REG3));
|
||||
return push_inst(compiler, FMV_W_X | (1 << 25) | RS1(TMP_REG1) | FRD(freg));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 freg, sljit_s32 reg)
|
||||
{
|
||||
sljit_ins inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_COPY_TO_F64)
|
||||
inst = FMV_W_X | RS1(reg) | FRD(freg);
|
||||
else
|
||||
inst = FMV_X_W | FRS1(freg) | RD(reg);
|
||||
|
||||
if (!(op & SLJIT_32))
|
||||
inst |= (sljit_ins)1 << 25;
|
||||
|
||||
return push_inst(compiler, inst);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins)
|
||||
{
|
||||
sljit_sw high;
|
||||
|
||||
if ((init_value & 0x800) != 0)
|
||||
init_value += 0x1000;
|
||||
|
||||
high = init_value >> 32;
|
||||
|
||||
if ((init_value & 0x80000000l) != 0)
|
||||
high = ~high;
|
||||
|
||||
if ((high & 0x800) != 0)
|
||||
high += 0x1000;
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff)));
|
||||
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high)));
|
||||
FAIL_IF(push_inst(compiler, LUI | RD(dst) | (sljit_ins)(init_value & ~0xfff)));
|
||||
FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(32)));
|
||||
FAIL_IF(push_inst(compiler, XOR | RD(dst) | RS1(dst) | RS2(TMP_REG3)));
|
||||
return push_inst(compiler, last_ins | RS1(dst) | IMM_I(init_value));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
sljit_sw high;
|
||||
SLJIT_UNUSED_ARG(executable_offset);
|
||||
|
||||
if ((new_target & 0x800) != 0)
|
||||
new_target += 0x1000;
|
||||
|
||||
high = (sljit_sw)new_target >> 32;
|
||||
|
||||
if ((new_target & 0x80000000l) != 0)
|
||||
high = ~high;
|
||||
|
||||
if ((high & 0x800) != 0)
|
||||
high += 0x1000;
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);
|
||||
|
||||
SLJIT_ASSERT((inst[0] & 0x7f) == LUI);
|
||||
inst[0] = (inst[0] & 0xfff) | (sljit_ins)(high & ~0xfff);
|
||||
SLJIT_ASSERT((inst[1] & 0x707f) == ADDI);
|
||||
inst[1] = (inst[1] & 0xfffff) | IMM_I(high);
|
||||
SLJIT_ASSERT((inst[2] & 0x7f) == LUI);
|
||||
inst[2] = (inst[2] & 0xfff) | (sljit_ins)((sljit_sw)new_target & ~0xfff);
|
||||
SLJIT_ASSERT((inst[5] & 0x707f) == ADDI || (inst[5] & 0x707f) == JALR);
|
||||
inst[5] = (inst[5] & 0xfffff) | IMM_I(new_target);
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);
|
||||
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 5);
|
||||
}
|
3877
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_common.c
vendored
Normal file
3877
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_common.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4554
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeS390X.c
vendored
Normal file
4554
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeS390X.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1689
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_32.c
vendored
Normal file
1689
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_32.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1415
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_64.c
vendored
Normal file
1415
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_64.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5138
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_common.c
vendored
Normal file
5138
thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_common.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
516
thirdparty/pcre2/deps/sljit/sljit_src/sljitSerialize.c
vendored
Normal file
516
thirdparty/pcre2/deps/sljit/sljit_src/sljitSerialize.c
vendored
Normal file
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 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_s32 sljit_jump_has_label(struct sljit_jump *jump)
|
||||
{
|
||||
return !(jump->flags & JUMP_ADDR) && (jump->u.label != NULL);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_target(struct sljit_jump *jump)
|
||||
{
|
||||
return (jump->flags & JUMP_ADDR) != 0;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_is_mov_addr(struct sljit_jump *jump)
|
||||
{
|
||||
return (jump->flags & JUMP_MOV_ADDR) != 0;
|
||||
}
|
||||
|
||||
#define SLJIT_SERIALIZE_DEBUG ((sljit_u16)0x1)
|
||||
|
||||
struct sljit_serialized_compiler {
|
||||
sljit_u32 signature;
|
||||
sljit_u16 version;
|
||||
sljit_u16 cpu_type;
|
||||
|
||||
sljit_uw buf_segment_count;
|
||||
sljit_uw label_count;
|
||||
sljit_uw jump_count;
|
||||
sljit_uw const_count;
|
||||
|
||||
sljit_s32 options;
|
||||
sljit_s32 scratches;
|
||||
sljit_s32 saveds;
|
||||
sljit_s32 fscratches;
|
||||
sljit_s32 fsaveds;
|
||||
sljit_s32 local_size;
|
||||
sljit_uw size;
|
||||
|
||||
#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
|
||||
sljit_s32 status_flags_state;
|
||||
#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
sljit_s32 args_size;
|
||||
#endif /* SLJIT_CONFIG_X86_32 */
|
||||
|
||||
#if ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
sljit_uw args_size;
|
||||
#endif /* (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
|
||||
sljit_uw cpool_diff;
|
||||
sljit_uw cpool_fill;
|
||||
sljit_uw patches;
|
||||
#endif /* SLJIT_CONFIG_ARM_V6 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
sljit_s32 delay_slot;
|
||||
#endif /* SLJIT_CONFIG_MIPS */
|
||||
|
||||
};
|
||||
|
||||
struct sljit_serialized_debug_info {
|
||||
sljit_sw last_flags;
|
||||
sljit_s32 last_return;
|
||||
sljit_s32 logical_local_size;
|
||||
};
|
||||
|
||||
struct sljit_serialized_label {
|
||||
sljit_uw size;
|
||||
};
|
||||
|
||||
struct sljit_serialized_jump {
|
||||
sljit_uw addr;
|
||||
sljit_uw flags;
|
||||
sljit_uw value;
|
||||
};
|
||||
|
||||
struct sljit_serialized_const {
|
||||
sljit_uw addr;
|
||||
};
|
||||
|
||||
#define SLJIT_SERIALIZE_ALIGN(v) (((v) + sizeof(sljit_uw) - 1) & ~(sljit_uw)(sizeof(sljit_uw) - 1))
|
||||
#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
|
||||
#define SLJIT_SERIALIZE_SIGNATURE 0x534c4a54
|
||||
#else /* !SLJIT_LITTLE_ENDIAN */
|
||||
#define SLJIT_SERIALIZE_SIGNATURE 0x544a4c53
|
||||
#endif /* SLJIT_LITTLE_ENDIAN */
|
||||
#define SLJIT_SERIALIZE_VERSION 1
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_uw *size)
|
||||
{
|
||||
sljit_uw serialized_size = sizeof(struct sljit_serialized_compiler);
|
||||
struct sljit_memory_fragment *buf;
|
||||
struct sljit_label *label;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_const *const_;
|
||||
struct sljit_serialized_compiler *serialized_compiler;
|
||||
struct sljit_serialized_label *serialized_label;
|
||||
struct sljit_serialized_jump *serialized_jump;
|
||||
struct sljit_serialized_const *serialized_const;
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
||||
|| (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
struct sljit_serialized_debug_info *serialized_debug_info;
|
||||
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
|
||||
sljit_uw counter, used_size;
|
||||
sljit_u8 *result;
|
||||
sljit_u8 *ptr;
|
||||
SLJIT_UNUSED_ARG(options);
|
||||
|
||||
if (size != NULL)
|
||||
*size = 0;
|
||||
|
||||
PTR_FAIL_IF(compiler->error);
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
||||
|| (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
if (!(options & SLJIT_SERIALIZE_IGNORE_DEBUG))
|
||||
serialized_size += sizeof(struct sljit_serialized_debug_info);
|
||||
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
|
||||
serialized_size += SLJIT_SERIALIZE_ALIGN(compiler->cpool_fill * (sizeof(sljit_uw) + 1));
|
||||
#endif /* SLJIT_CONFIG_ARM_V6 */
|
||||
|
||||
/* Compute the size of the data. */
|
||||
buf = compiler->buf;
|
||||
while (buf != NULL) {
|
||||
serialized_size += sizeof(sljit_uw) + SLJIT_SERIALIZE_ALIGN(buf->used_size);
|
||||
buf = buf->next;
|
||||
}
|
||||
|
||||
serialized_size += compiler->label_count * sizeof(struct sljit_serialized_label);
|
||||
|
||||
jump = compiler->jumps;
|
||||
while (jump != NULL) {
|
||||
serialized_size += sizeof(struct sljit_serialized_jump);
|
||||
jump = jump->next;
|
||||
}
|
||||
|
||||
const_ = compiler->consts;
|
||||
while (const_ != NULL) {
|
||||
serialized_size += sizeof(struct sljit_serialized_const);
|
||||
const_ = const_->next;
|
||||
}
|
||||
|
||||
result = (sljit_u8*)SLJIT_MALLOC(serialized_size, compiler->allocator_data);
|
||||
PTR_FAIL_IF_NULL(result);
|
||||
|
||||
if (size != NULL)
|
||||
*size = serialized_size;
|
||||
|
||||
ptr = result;
|
||||
serialized_compiler = (struct sljit_serialized_compiler*)ptr;
|
||||
ptr += sizeof(struct sljit_serialized_compiler);
|
||||
|
||||
serialized_compiler->signature = SLJIT_SERIALIZE_SIGNATURE;
|
||||
serialized_compiler->version = SLJIT_SERIALIZE_VERSION;
|
||||
serialized_compiler->cpu_type = 0;
|
||||
serialized_compiler->label_count = compiler->label_count;
|
||||
serialized_compiler->options = compiler->options;
|
||||
serialized_compiler->scratches = compiler->scratches;
|
||||
serialized_compiler->saveds = compiler->saveds;
|
||||
serialized_compiler->fscratches = compiler->fscratches;
|
||||
serialized_compiler->fsaveds = compiler->fsaveds;
|
||||
serialized_compiler->local_size = compiler->local_size;
|
||||
serialized_compiler->size = compiler->size;
|
||||
|
||||
#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
|
||||
serialized_compiler->status_flags_state = compiler->status_flags_state;
|
||||
#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
|| ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
serialized_compiler->args_size = compiler->args_size;
|
||||
#endif /* SLJIT_CONFIG_X86_32 || (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
|
||||
serialized_compiler->cpool_diff = compiler->cpool_diff;
|
||||
serialized_compiler->cpool_fill = compiler->cpool_fill;
|
||||
serialized_compiler->patches = compiler->patches;
|
||||
|
||||
SLJIT_MEMCPY(ptr, compiler->cpool, compiler->cpool_fill * sizeof(sljit_uw));
|
||||
SLJIT_MEMCPY(ptr + compiler->cpool_fill * sizeof(sljit_uw), compiler->cpool_unique, compiler->cpool_fill);
|
||||
ptr += SLJIT_SERIALIZE_ALIGN(compiler->cpool_fill * (sizeof(sljit_uw) + 1));
|
||||
#endif /* SLJIT_CONFIG_ARM_V6 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
serialized_compiler->delay_slot = compiler->delay_slot;
|
||||
#endif /* SLJIT_CONFIG_MIPS */
|
||||
|
||||
buf = compiler->buf;
|
||||
counter = 0;
|
||||
while (buf != NULL) {
|
||||
used_size = buf->used_size;
|
||||
*(sljit_uw*)ptr = used_size;
|
||||
ptr += sizeof(sljit_uw);
|
||||
SLJIT_MEMCPY(ptr, buf->memory, used_size);
|
||||
ptr += SLJIT_SERIALIZE_ALIGN(used_size);
|
||||
buf = buf->next;
|
||||
counter++;
|
||||
}
|
||||
serialized_compiler->buf_segment_count = counter;
|
||||
|
||||
label = compiler->labels;
|
||||
while (label != NULL) {
|
||||
serialized_label = (struct sljit_serialized_label*)ptr;
|
||||
serialized_label->size = label->size;
|
||||
ptr += sizeof(struct sljit_serialized_label);
|
||||
label = label->next;
|
||||
}
|
||||
|
||||
jump = compiler->jumps;
|
||||
counter = 0;
|
||||
while (jump != NULL) {
|
||||
serialized_jump = (struct sljit_serialized_jump*)ptr;
|
||||
serialized_jump->addr = jump->addr;
|
||||
serialized_jump->flags = jump->flags;
|
||||
|
||||
if (jump->flags & JUMP_ADDR)
|
||||
serialized_jump->value = jump->u.target;
|
||||
else if (jump->u.label != NULL)
|
||||
serialized_jump->value = jump->u.label->u.index;
|
||||
else
|
||||
serialized_jump->value = SLJIT_MAX_ADDRESS;
|
||||
|
||||
ptr += sizeof(struct sljit_serialized_jump);
|
||||
jump = jump->next;
|
||||
counter++;
|
||||
}
|
||||
serialized_compiler->jump_count = counter;
|
||||
|
||||
const_ = compiler->consts;
|
||||
counter = 0;
|
||||
while (const_ != NULL) {
|
||||
serialized_const = (struct sljit_serialized_const*)ptr;
|
||||
serialized_const->addr = const_->addr;
|
||||
ptr += sizeof(struct sljit_serialized_const);
|
||||
const_ = const_->next;
|
||||
counter++;
|
||||
}
|
||||
serialized_compiler->const_count = counter;
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
||||
|| (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
if (!(options & SLJIT_SERIALIZE_IGNORE_DEBUG)) {
|
||||
serialized_debug_info = (struct sljit_serialized_debug_info*)ptr;
|
||||
serialized_debug_info->last_flags = compiler->last_flags;
|
||||
serialized_debug_info->last_return = compiler->last_return;
|
||||
serialized_debug_info->logical_local_size = compiler->logical_local_size;
|
||||
serialized_compiler->cpu_type |= SLJIT_SERIALIZE_DEBUG;
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
ptr += sizeof(struct sljit_serialized_debug_info);
|
||||
#endif /* SLJIT_DEBUG */
|
||||
}
|
||||
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
|
||||
|
||||
SLJIT_ASSERT((sljit_uw)(ptr - result) == serialized_size);
|
||||
return (sljit_uw*)result;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit_uw* buffer, sljit_uw size,
|
||||
sljit_s32 options, void *allocator_data)
|
||||
{
|
||||
struct sljit_compiler *compiler;
|
||||
struct sljit_serialized_compiler *serialized_compiler;
|
||||
struct sljit_serialized_label *serialized_label;
|
||||
struct sljit_serialized_jump *serialized_jump;
|
||||
struct sljit_serialized_const *serialized_const;
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
||||
|| (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
struct sljit_serialized_debug_info *serialized_debug_info;
|
||||
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
|
||||
struct sljit_memory_fragment *buf;
|
||||
struct sljit_memory_fragment *last_buf;
|
||||
struct sljit_label *label;
|
||||
struct sljit_label *last_label;
|
||||
struct sljit_label **label_list = NULL;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_jump *last_jump;
|
||||
struct sljit_const *const_;
|
||||
struct sljit_const *last_const;
|
||||
sljit_u8 *ptr = (sljit_u8*)buffer;
|
||||
sljit_u8 *end = ptr + size;
|
||||
sljit_uw i, used_size, aligned_size, label_count;
|
||||
SLJIT_UNUSED_ARG(options);
|
||||
|
||||
if (size < sizeof(struct sljit_serialized_compiler) || (size & (sizeof(sljit_uw) - 1)) != 0)
|
||||
return NULL;
|
||||
|
||||
serialized_compiler = (struct sljit_serialized_compiler*)ptr;
|
||||
|
||||
if (serialized_compiler->signature != SLJIT_SERIALIZE_SIGNATURE || serialized_compiler->version != SLJIT_SERIALIZE_VERSION)
|
||||
return NULL;
|
||||
|
||||
compiler = sljit_create_compiler(allocator_data);
|
||||
PTR_FAIL_IF(compiler == NULL);
|
||||
|
||||
compiler->label_count = serialized_compiler->label_count;
|
||||
compiler->options = serialized_compiler->options;
|
||||
compiler->scratches = serialized_compiler->scratches;
|
||||
compiler->saveds = serialized_compiler->saveds;
|
||||
compiler->fscratches = serialized_compiler->fscratches;
|
||||
compiler->fsaveds = serialized_compiler->fsaveds;
|
||||
compiler->local_size = serialized_compiler->local_size;
|
||||
compiler->size = serialized_compiler->size;
|
||||
|
||||
#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
|
||||
compiler->status_flags_state = serialized_compiler->status_flags_state;
|
||||
#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
|| ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
compiler->args_size = serialized_compiler->args_size;
|
||||
#endif /* SLJIT_CONFIG_X86_32 || (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
|
||||
used_size = serialized_compiler->cpool_fill;
|
||||
aligned_size = SLJIT_SERIALIZE_ALIGN(used_size * (sizeof(sljit_uw) + 1));
|
||||
compiler->cpool_diff = serialized_compiler->cpool_diff;
|
||||
compiler->cpool_fill = used_size;
|
||||
compiler->patches = serialized_compiler->patches;
|
||||
|
||||
if ((sljit_uw)(end - ptr) < aligned_size)
|
||||
goto error;
|
||||
|
||||
SLJIT_MEMCPY(compiler->cpool, ptr, used_size * sizeof(sljit_uw));
|
||||
SLJIT_MEMCPY(compiler->cpool_unique, ptr + used_size * sizeof(sljit_uw), used_size);
|
||||
ptr += aligned_size;
|
||||
#endif /* SLJIT_CONFIG_ARM_V6 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
compiler->delay_slot = serialized_compiler->delay_slot;
|
||||
#endif /* SLJIT_CONFIG_MIPS */
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
||||
|| (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
if (!(serialized_compiler->cpu_type & SLJIT_SERIALIZE_DEBUG))
|
||||
goto error;
|
||||
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
|
||||
|
||||
ptr += sizeof(struct sljit_serialized_compiler);
|
||||
i = serialized_compiler->buf_segment_count;
|
||||
last_buf = NULL;
|
||||
while (i > 0) {
|
||||
if ((sljit_uw)(end - ptr) < sizeof(sljit_uw))
|
||||
goto error;
|
||||
|
||||
used_size = *(sljit_uw*)ptr;
|
||||
aligned_size = SLJIT_SERIALIZE_ALIGN(used_size);
|
||||
ptr += sizeof(sljit_uw);
|
||||
|
||||
if ((sljit_uw)(end - ptr) < aligned_size)
|
||||
goto error;
|
||||
|
||||
if (last_buf == NULL) {
|
||||
SLJIT_ASSERT(compiler->buf != NULL && compiler->buf->next == NULL);
|
||||
buf = compiler->buf;
|
||||
} else {
|
||||
buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data);
|
||||
if (!buf)
|
||||
goto error;
|
||||
buf->next = NULL;
|
||||
}
|
||||
|
||||
buf->used_size = used_size;
|
||||
SLJIT_MEMCPY(buf->memory, ptr, used_size);
|
||||
|
||||
if (last_buf != NULL)
|
||||
last_buf->next = buf;
|
||||
last_buf = buf;
|
||||
|
||||
ptr += aligned_size;
|
||||
i--;
|
||||
}
|
||||
|
||||
last_label = NULL;
|
||||
label_count = serialized_compiler->label_count;
|
||||
if ((sljit_uw)(end - ptr) < label_count * sizeof(struct sljit_serialized_label))
|
||||
goto error;
|
||||
|
||||
label_list = (struct sljit_label **)SLJIT_MALLOC(label_count * sizeof(struct sljit_label*), allocator_data);
|
||||
if (label_list == NULL)
|
||||
goto error;
|
||||
|
||||
for (i = 0; i < label_count; i++) {
|
||||
label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
|
||||
if (label == NULL)
|
||||
goto error;
|
||||
|
||||
serialized_label = (struct sljit_serialized_label*)ptr;
|
||||
label->next = NULL;
|
||||
label->u.index = i;
|
||||
label->size = serialized_label->size;
|
||||
|
||||
if (last_label != NULL)
|
||||
last_label->next = label;
|
||||
else
|
||||
compiler->labels = label;
|
||||
last_label = label;
|
||||
|
||||
label_list[i] = label;
|
||||
ptr += sizeof(struct sljit_serialized_label);
|
||||
}
|
||||
compiler->last_label = last_label;
|
||||
|
||||
last_jump = NULL;
|
||||
i = serialized_compiler->jump_count;
|
||||
if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_jump))
|
||||
goto error;
|
||||
|
||||
while (i > 0) {
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
if (jump == NULL)
|
||||
goto error;
|
||||
|
||||
serialized_jump = (struct sljit_serialized_jump*)ptr;
|
||||
jump->next = NULL;
|
||||
jump->addr = serialized_jump->addr;
|
||||
jump->flags = serialized_jump->flags;
|
||||
|
||||
if (!(serialized_jump->flags & JUMP_ADDR)) {
|
||||
if (serialized_jump->value != SLJIT_MAX_ADDRESS) {
|
||||
if (serialized_jump->value >= label_count)
|
||||
goto error;
|
||||
jump->u.label = label_list[serialized_jump->value];
|
||||
} else
|
||||
jump->u.label = NULL;
|
||||
} else
|
||||
jump->u.target = serialized_jump->value;
|
||||
|
||||
if (last_jump != NULL)
|
||||
last_jump->next = jump;
|
||||
else
|
||||
compiler->jumps = jump;
|
||||
last_jump = jump;
|
||||
|
||||
ptr += sizeof(struct sljit_serialized_jump);
|
||||
i--;
|
||||
}
|
||||
compiler->last_jump = last_jump;
|
||||
|
||||
SLJIT_FREE(label_list, allocator_data);
|
||||
label_list = NULL;
|
||||
|
||||
last_const = NULL;
|
||||
i = serialized_compiler->const_count;
|
||||
if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_const))
|
||||
goto error;
|
||||
|
||||
while (i > 0) {
|
||||
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
|
||||
if (const_ == NULL)
|
||||
goto error;
|
||||
|
||||
serialized_const = (struct sljit_serialized_const*)ptr;
|
||||
const_->next = NULL;
|
||||
const_->addr = serialized_const->addr;
|
||||
|
||||
if (last_const != NULL)
|
||||
last_const->next = const_;
|
||||
else
|
||||
compiler->consts = const_;
|
||||
last_const = const_;
|
||||
|
||||
ptr += sizeof(struct sljit_serialized_const);
|
||||
i--;
|
||||
}
|
||||
compiler->last_const = last_const;
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
||||
|| (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
if ((sljit_uw)(end - ptr) < sizeof(struct sljit_serialized_debug_info))
|
||||
goto error;
|
||||
|
||||
serialized_debug_info = (struct sljit_serialized_debug_info*)ptr;
|
||||
compiler->last_flags = (sljit_s32)serialized_debug_info->last_flags;
|
||||
compiler->last_return = serialized_debug_info->last_return;
|
||||
compiler->logical_local_size = serialized_debug_info->logical_local_size;
|
||||
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
|
||||
|
||||
return compiler;
|
||||
|
||||
error:
|
||||
sljit_free_compiler(compiler);
|
||||
if (label_list != NULL)
|
||||
SLJIT_FREE(label_list, allocator_data);
|
||||
return NULL;
|
||||
}
|
344
thirdparty/pcre2/deps/sljit/sljit_src/sljitUtils.c
vendored
Normal file
344
thirdparty/pcre2/deps/sljit/sljit_src/sljitUtils.c
vendored
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Locks */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Executable Allocator */
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \
|
||||
&& !(defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)
|
||||
#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
|
||||
#define SLJIT_ALLOCATOR_LOCK()
|
||||
#define SLJIT_ALLOCATOR_UNLOCK()
|
||||
#elif !(defined _WIN32)
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_mutex_t allocator_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
#define SLJIT_ALLOCATOR_LOCK() pthread_mutex_lock(&allocator_lock)
|
||||
#define SLJIT_ALLOCATOR_UNLOCK() pthread_mutex_unlock(&allocator_lock)
|
||||
#else /* windows */
|
||||
static HANDLE allocator_lock;
|
||||
|
||||
static SLJIT_INLINE void allocator_grab_lock(void)
|
||||
{
|
||||
HANDLE lock;
|
||||
if (SLJIT_UNLIKELY(!InterlockedCompareExchangePointer(&allocator_lock, NULL, NULL))) {
|
||||
lock = CreateMutex(NULL, FALSE, NULL);
|
||||
if (InterlockedCompareExchangePointer(&allocator_lock, lock, NULL))
|
||||
CloseHandle(lock);
|
||||
}
|
||||
WaitForSingleObject(allocator_lock, INFINITE);
|
||||
}
|
||||
|
||||
#define SLJIT_ALLOCATOR_LOCK() allocator_grab_lock()
|
||||
#define SLJIT_ALLOCATOR_UNLOCK() ReleaseMutex(allocator_lock)
|
||||
#endif /* thread implementation */
|
||||
#endif /* SLJIT_EXECUTABLE_ALLOCATOR && !SLJIT_WX_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Stack */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#if ((defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \
|
||||
&& !(defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)) \
|
||||
|| ((defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \
|
||||
&& !((defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) \
|
||||
|| (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)))
|
||||
|
||||
#ifndef _WIN32
|
||||
/* Provides mmap function. */
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifndef MAP_ANON
|
||||
#ifdef MAP_ANONYMOUS
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#endif /* MAP_ANONYMOUS */
|
||||
#endif /* !MAP_ANON */
|
||||
|
||||
#ifndef MAP_ANON
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef O_CLOEXEC
|
||||
#define SLJIT_CLOEXEC O_CLOEXEC
|
||||
#else /* !O_CLOEXEC */
|
||||
#define SLJIT_CLOEXEC 0
|
||||
#endif /* O_CLOEXEC */
|
||||
|
||||
/* Some old systems do not have MAP_ANON. */
|
||||
static int dev_zero = -1;
|
||||
|
||||
#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
|
||||
|
||||
static SLJIT_INLINE int open_dev_zero(void)
|
||||
{
|
||||
dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);
|
||||
|
||||
return dev_zero < 0;
|
||||
}
|
||||
|
||||
#else /* !SLJIT_SINGLE_THREADED */
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static SLJIT_INLINE int open_dev_zero(void)
|
||||
{
|
||||
pthread_mutex_lock(&dev_zero_mutex);
|
||||
if (SLJIT_UNLIKELY(dev_zero < 0))
|
||||
dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);
|
||||
|
||||
pthread_mutex_unlock(&dev_zero_mutex);
|
||||
return dev_zero < 0;
|
||||
}
|
||||
|
||||
#endif /* SLJIT_SINGLE_THREADED */
|
||||
#undef SLJIT_CLOEXEC
|
||||
#endif /* !MAP_ANON */
|
||||
#endif /* !_WIN32 */
|
||||
#endif /* open_dev_zero */
|
||||
|
||||
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \
|
||||
|| (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static SLJIT_INLINE sljit_uw get_page_alignment(void) {
|
||||
SYSTEM_INFO si;
|
||||
static sljit_uw sljit_page_align = 0;
|
||||
if (!sljit_page_align) {
|
||||
GetSystemInfo(&si);
|
||||
sljit_page_align = (sljit_uw)si.dwPageSize - 1;
|
||||
}
|
||||
return sljit_page_align;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
static SLJIT_INLINE sljit_uw get_page_alignment(void) {
|
||||
static sljit_uw sljit_page_align = 0;
|
||||
|
||||
sljit_sw align;
|
||||
|
||||
if (!sljit_page_align) {
|
||||
#ifdef _SC_PAGESIZE
|
||||
align = sysconf(_SC_PAGESIZE);
|
||||
#else
|
||||
align = getpagesize();
|
||||
#endif
|
||||
/* Should never happen. */
|
||||
if (align < 0)
|
||||
align = 4096;
|
||||
sljit_page_align = (sljit_uw)align - 1;
|
||||
}
|
||||
return sljit_page_align;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif /* get_page_alignment() */
|
||||
|
||||
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
|
||||
|
||||
#if (defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)
|
||||
{
|
||||
struct sljit_stack *stack;
|
||||
void *ptr;
|
||||
|
||||
SLJIT_UNUSED_ARG(allocator_data);
|
||||
|
||||
if (start_size > max_size || start_size < 1)
|
||||
return NULL;
|
||||
|
||||
stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);
|
||||
if (stack == NULL)
|
||||
return NULL;
|
||||
|
||||
ptr = SLJIT_MALLOC(max_size, allocator_data);
|
||||
if (ptr == NULL) {
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stack->min_start = (sljit_u8 *)ptr;
|
||||
stack->end = stack->min_start + max_size;
|
||||
stack->start = stack->end - start_size;
|
||||
stack->top = stack->end;
|
||||
return stack;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(allocator_data);
|
||||
SLJIT_FREE((void*)stack->min_start, allocator_data);
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)
|
||||
{
|
||||
if ((new_start < stack->min_start) || (new_start >= stack->end))
|
||||
return NULL;
|
||||
stack->start = new_start;
|
||||
return new_start;
|
||||
}
|
||||
|
||||
#else /* !SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(allocator_data);
|
||||
VirtualFree((void*)stack->min_start, 0, MEM_RELEASE);
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
}
|
||||
|
||||
#else /* !_WIN32 */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(allocator_data);
|
||||
munmap((void*)stack->min_start, (size_t)(stack->end - stack->min_start));
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)
|
||||
{
|
||||
struct sljit_stack *stack;
|
||||
void *ptr;
|
||||
sljit_uw page_align;
|
||||
|
||||
SLJIT_UNUSED_ARG(allocator_data);
|
||||
|
||||
if (start_size > max_size || start_size < 1)
|
||||
return NULL;
|
||||
|
||||
stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);
|
||||
if (stack == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Align max_size. */
|
||||
page_align = get_page_alignment();
|
||||
max_size = (max_size + page_align) & ~page_align;
|
||||
|
||||
#ifdef _WIN32
|
||||
ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE);
|
||||
if (!ptr) {
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stack->min_start = (sljit_u8 *)ptr;
|
||||
stack->end = stack->min_start + max_size;
|
||||
stack->start = stack->end;
|
||||
|
||||
if (sljit_stack_resize(stack, stack->end - start_size) == NULL) {
|
||||
sljit_free_stack(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
#else /* !_WIN32 */
|
||||
#ifdef MAP_ANON
|
||||
ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
#else /* !MAP_ANON */
|
||||
if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero())) {
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
|
||||
#endif /* MAP_ANON */
|
||||
if (ptr == MAP_FAILED) {
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
stack->min_start = (sljit_u8 *)ptr;
|
||||
stack->end = stack->min_start + max_size;
|
||||
stack->start = stack->end - start_size;
|
||||
#endif /* _WIN32 */
|
||||
|
||||
stack->top = stack->end;
|
||||
return stack;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)
|
||||
{
|
||||
#if defined _WIN32 || defined(POSIX_MADV_DONTNEED)
|
||||
sljit_uw aligned_old_start;
|
||||
sljit_uw aligned_new_start;
|
||||
sljit_uw page_align;
|
||||
#endif
|
||||
|
||||
if ((new_start < stack->min_start) || (new_start >= stack->end))
|
||||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
page_align = get_page_alignment();
|
||||
|
||||
aligned_new_start = (sljit_uw)new_start & ~page_align;
|
||||
aligned_old_start = ((sljit_uw)stack->start) & ~page_align;
|
||||
if (aligned_new_start != aligned_old_start) {
|
||||
if (aligned_new_start < aligned_old_start) {
|
||||
if (!VirtualAlloc((void*)aligned_new_start, aligned_old_start - aligned_new_start, MEM_COMMIT, PAGE_READWRITE))
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
if (!VirtualFree((void*)aligned_old_start, aligned_new_start - aligned_old_start, MEM_DECOMMIT))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#elif defined(POSIX_MADV_DONTNEED)
|
||||
if (stack->start < new_start) {
|
||||
page_align = get_page_alignment();
|
||||
|
||||
aligned_new_start = (sljit_uw)new_start & ~page_align;
|
||||
aligned_old_start = ((sljit_uw)stack->start) & ~page_align;
|
||||
|
||||
if (aligned_new_start > aligned_old_start) {
|
||||
posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED);
|
||||
#ifdef MADV_FREE
|
||||
madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_FREE);
|
||||
#endif /* MADV_FREE */
|
||||
}
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
stack->start = new_start;
|
||||
return new_start;
|
||||
}
|
||||
|
||||
#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */
|
||||
|
||||
#endif /* SLJIT_UTIL_STACK */
|
Reference in New Issue
Block a user