Path: blob/master/thirdparty/pcre2/deps/sljit/sljit_src/sljitLir.c
22335 views
/*1* Stack-less Just-In-Time compiler2*3* Copyright Zoltan Herczeg ([email protected]). All rights reserved.4*5* Redistribution and use in source and binary forms, with or without modification, are6* permitted provided that the following conditions are met:7*8* 1. Redistributions of source code must retain the above copyright notice, this list of9* conditions and the following disclaimer.10*11* 2. Redistributions in binary form must reproduce the above copyright notice, this list12* of conditions and the following disclaimer in the documentation and/or other materials13* provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY16* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES17* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT18* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,19* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED20* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR21* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN22* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN23* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.24*/2526#include "sljitLir.h"2728#ifdef _WIN322930#include <windows.h>3132#endif /* _WIN32 */3334#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)3536/* These libraries are needed for the macros below. */37#include <stdlib.h>38#include <string.h>3940#endif /* SLJIT_STD_MACROS_DEFINED */4142#define CHECK_ERROR() \43do { \44if (SLJIT_UNLIKELY(compiler->error)) \45return compiler->error; \46} while (0)4748#define CHECK_ERROR_PTR() \49do { \50if (SLJIT_UNLIKELY(compiler->error)) \51return NULL; \52} while (0)5354#define FAIL_IF(expr) \55do { \56if (SLJIT_UNLIKELY(expr)) \57return compiler->error; \58} while (0)5960#define PTR_FAIL_IF(expr) \61do { \62if (SLJIT_UNLIKELY(expr)) \63return NULL; \64} while (0)6566#define FAIL_IF_NULL(ptr) \67do { \68if (SLJIT_UNLIKELY(!(ptr))) { \69compiler->error = SLJIT_ERR_ALLOC_FAILED; \70return SLJIT_ERR_ALLOC_FAILED; \71} \72} while (0)7374#define PTR_FAIL_IF_NULL(ptr) \75do { \76if (SLJIT_UNLIKELY(!(ptr))) { \77compiler->error = SLJIT_ERR_ALLOC_FAILED; \78return NULL; \79} \80} while (0)8182#define PTR_FAIL_WITH_EXEC_IF(ptr) \83do { \84if (SLJIT_UNLIKELY(!(ptr))) { \85compiler->error = SLJIT_ERR_EX_ALLOC_FAILED; \86return NULL; \87} \88} while (0)8990#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)9192#define SSIZE_OF(type) ((sljit_s32)sizeof(sljit_ ## type))9394#define VARIABLE_FLAG_SHIFT (10)95/* All variable flags are even. */96#define VARIABLE_FLAG_MASK (0x3e << VARIABLE_FLAG_SHIFT)97#define ALL_STATUS_FLAGS_MASK (VARIABLE_FLAG_MASK | SLJIT_SET_Z)98#define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT)99#define GET_FLAG_TYPE_MASK(op) (((op) >> VARIABLE_FLAG_SHIFT) & 0x3e)100#define GET_OPCODE(op) ((op) & 0xff)101#define HAS_FLAGS(op) ((op) & ALL_STATUS_FLAGS_MASK)102#define GET_ALL_FLAGS(op) ((op) & (SLJIT_32 | ALL_STATUS_FLAGS_MASK))103104#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)105#define TYPE_CAST_NEEDED(op) \106((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S32)107#else /* !SLJIT_64BIT_ARCHITECTURE */108#define TYPE_CAST_NEEDED(op) \109((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16)110#endif /* SLJIT_64BIT_ARCHITECTURE */111112#define BUF_SIZE 4096113114#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)115#define ABUF_SIZE 2048116#else /* !SLJIT_32BIT_ARCHITECTURE */117#define ABUF_SIZE 4096118#endif /* SLJIT_32BIT_ARCHITECTURE */119120/* Parameter parsing. */121#define REG_MASK 0x7f122#define OFFS_REG(reg) (((reg) >> 8) & REG_MASK)123#define OFFS_REG_MASK (REG_MASK << 8)124#define TO_OFFS_REG(reg) ((reg) << 8)125#define FAST_IS_REG(reg) ((reg) < REG_MASK)126127/* Mask for argument types. */128#define SLJIT_ARG_MASK 0x7129#define SLJIT_ARG_FULL_MASK (SLJIT_ARG_MASK | SLJIT_ARG_TYPE_SCRATCH_REG)130131/* Mask for register pairs. */132#define REG_PAIR_MASK 0x7f00133#define REG_PAIR_FIRST(reg) ((reg) & 0x7f)134#define REG_PAIR_SECOND(reg) ((reg) >> 8)135136/* Mask for sljit_emit_enter. */137#define ENTER_GET_REGS(regs) ((regs) & 0xff)138#define ENTER_GET_FLOAT_REGS(regs) (((regs) >> 8) & 0xff)139#define ENTER_GET_VECTOR_REGS(regs) (((regs) >> 16) & 0xff)140#define SLJIT_KEPT_SAVEDS_COUNT(options) ((options) & 0x3)141142/* Getters for simd operations, which returns with log2(size). */143#define SLJIT_SIMD_GET_OPCODE(type) ((type) & 0xff)144#define SLJIT_SIMD_GET_REG_SIZE(type) (((type) >> 12) & 0x3f)145#define SLJIT_SIMD_GET_ELEM_SIZE(type) (((type) >> 18) & 0x3f)146#define SLJIT_SIMD_GET_ELEM2_SIZE(type) (((type) >> 24) & 0x3f)147148#define SLJIT_SIMD_CHECK_REG(type) (((type) & 0x3f000) >= SLJIT_SIMD_REG_64 && ((type) & 0x3f000) <= SLJIT_SIMD_REG_512)149#define SLJIT_SIMD_TYPE_MASK(m) ((sljit_s32)0xff000fff & ~(SLJIT_SIMD_FLOAT | SLJIT_SIMD_TEST | (m)))150#define SLJIT_SIMD_TYPE_MASK2(m) ((sljit_s32)0xc0000fff & ~(SLJIT_SIMD_FLOAT | SLJIT_SIMD_TEST | (m)))151152/* Label definitions. */153154#define SLJIT_LABEL_ALIGNED ((~(sljit_uw)0) - 1)155156struct sljit_extended_label {157struct sljit_label label;158sljit_uw index;159sljit_uw data;160};161162/* Jump definitions. */163164/* Jump flag bits. */165#define JUMP_ADDR 0x1166#define JUMP_MOV_ADDR 0x2167/* SLJIT_REWRITABLE_JUMP is 0x10000. */168169#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)170# define PATCH_MB 0x04171# define PATCH_MW 0x08172#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)173# define PATCH_MD 0x10174# define MOV_ADDR_HI 0x20175# define JUMP_MAX_SIZE ((sljit_uw)(10 + 3))176# define CJUMP_MAX_SIZE ((sljit_uw)(2 + 10 + 3))177#else /* !SLJIT_CONFIG_X86_64 */178# define JUMP_MAX_SIZE ((sljit_uw)5)179# define CJUMP_MAX_SIZE ((sljit_uw)6)180#endif /* SLJIT_CONFIG_X86_64 */181# define TYPE_SHIFT 17182#if (defined SLJIT_DEBUG && SLJIT_DEBUG)183/* Bits 7..15 is for debug jump size, SLJIT_REWRITABLE_JUMP is 0x10000 */184# define JUMP_SIZE_SHIFT 8185#endif /* SLJIT_DEBUG */186#endif /* SLJIT_CONFIG_X86 */187188#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)189/* SLJIT_REWRITABLE_JUMP is 0x10000. */190# define IS_BL 0x04191# define PATCH_B 0x08192#endif /* SLJIT_CONFIG_ARM_V6 || SLJIT_CONFIG_ARM_V7 */193194#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)195# define CPOOL_SIZE 512196#endif /* SLJIT_CONFIG_ARM_V6 */197198#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)199# define JUMP_SIZE_SHIFT 26200# define JUMP_MAX_SIZE ((sljit_uw)3)201#endif /* SLJIT_CONFIG_ARM_V7 */202203#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)204/* SLJIT_REWRITABLE_JUMP is 0x10000. */205# define IS_COND 0x04206# define IS_BL 0x08207/* mov_addr does not use IS_BL */208# define IS_ABS IS_BL209/* conditional + imm8 */210# define PATCH_TYPE1 0x10211/* conditional + imm20 */212# define PATCH_TYPE2 0x20213/* imm11 */214# define PATCH_TYPE3 0x30215/* imm24 */216# define PATCH_TYPE4 0x40217/* BL + imm24 */218# define PATCH_TYPE5 0x50219/* addwi/subwi */220# define PATCH_TYPE6 0x60221/* 0xf00 cc code for branches */222# define JUMP_SIZE_SHIFT 26223# define JUMP_MAX_SIZE ((sljit_uw)5)224#endif /* SLJIT_CONFIG_ARM_THUMB2 */225226#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)227/* SLJIT_REWRITABLE_JUMP is 0x10000. */228# define IS_COND 0x004229# define IS_CBZ 0x008230# define IS_BL 0x010231# define PATCH_COND 0x020232# define PATCH_B 0x040233# define PATCH_B32 0x080234# define PATCH_ABS48 0x100235# define PATCH_ABS64 0x200236# define JUMP_SIZE_SHIFT 58237# define JUMP_MAX_SIZE ((sljit_uw)5)238#endif /* SLJIT_CONFIG_ARM_64 */239240#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)241/* SLJIT_REWRITABLE_JUMP is 0x10000. */242# define IS_COND 0x004243# define IS_CALL 0x008244# define PATCH_B 0x010245# define PATCH_ABS_B 0x020246#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)247# define PATCH_ABS32 0x040248# define PATCH_ABS48 0x080249# define JUMP_SIZE_SHIFT 58250# define JUMP_MAX_SIZE ((sljit_uw)7)251#else /* !SLJIT_CONFIG_PPC_64 */252# define JUMP_SIZE_SHIFT 26253# define JUMP_MAX_SIZE ((sljit_uw)4)254#endif /* SLJIT_CONFIG_PPC_64 */255#endif /* SLJIT_CONFIG_PPC */256257#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)258/* SLJIT_REWRITABLE_JUMP is 0x10000. */259# define IS_MOVABLE 0x004260# define IS_JAL 0x008261# define IS_CALL 0x010262# define IS_BIT26_COND 0x020263# define IS_BIT16_COND 0x040264# define IS_BIT23_COND 0x080265266# define IS_COND (IS_BIT26_COND | IS_BIT16_COND | IS_BIT23_COND)267268# define PATCH_B 0x100269# define PATCH_J 0x200270271#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)272# define PATCH_ABS32 0x400273# define PATCH_ABS48 0x800274#endif /* SLJIT_CONFIG_MIPS_64 */275276/* instruction types */277# define MOVABLE_INS 0278/* 1 - 31 last destination register */279/* no destination (i.e: store) */280# define UNMOVABLE_INS 32281/* FPU status register */282# define FCSR_FCC 33283#endif /* SLJIT_CONFIG_MIPS */284285#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)286/* SLJIT_REWRITABLE_JUMP is 0x10000. */287# define IS_COND 0x0004288# define IS_CALL 0x0008289290# define IS_COND16 0x0010291# define PATCH_B 0x0020292# define PATCH_J 0x0040293# define PATCH_16 0x0080294295#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)296# define PATCH_REL32 0x0100297# define PATCH_ABS32 0x0200298# define PATCH_ABS44 0x0400299# define PATCH_ABS52 0x0800300# define JUMP_SIZE_SHIFT 58301# define JUMP_MAX_SIZE ((sljit_uw)12)302#else /* !SLJIT_CONFIG_RISCV_64 */303# define JUMP_SIZE_SHIFT 26304# define JUMP_MAX_SIZE ((sljit_uw)4)305#endif /* SLJIT_CONFIG_RISCV_64 */306#endif /* SLJIT_CONFIG_RISCV */307308#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)309/* SLJIT_REWRITABLE_JUMP is 0x10000. */310# define PATCH_POOL 0x004311# define PATCH_IMM32 0x008312#endif /* SLJIT_CONFIG_S390X */313314#if (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)315/* SLJIT_REWRITABLE_JUMP is 0x10000. */316# define IS_COND 0x004317# define IS_CALL 0x008318319# define PATCH_B 0x010320# define PATCH_J 0x020321322# define PATCH_REL32 0x040323# define PATCH_ABS32 0x080324# define PATCH_ABS52 0x100325# define JUMP_SIZE_SHIFT 58326# define JUMP_MAX_SIZE ((sljit_uw)4)327328#endif /* SLJIT_CONFIG_LOONGARCH */329330/* Stack management. */331332#define GET_SAVED_REGISTERS_SIZE(scratches, saveds, extra) \333(((scratches < SLJIT_NUMBER_OF_SCRATCH_REGISTERS ? 0 : (scratches - SLJIT_NUMBER_OF_SCRATCH_REGISTERS)) + \334(saveds) + (sljit_s32)(extra)) * (sljit_s32)sizeof(sljit_sw))335336#define GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, type) \337(((fscratches < SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS ? 0 : (fscratches - SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)) + \338(fsaveds)) * SSIZE_OF(type))339340#define ADJUST_LOCAL_OFFSET(p, i) \341if ((p) == (SLJIT_MEM1(SLJIT_SP))) \342(i) += SLJIT_LOCALS_OFFSET;343344#endif /* !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) */345346/* Utils can still be used even if SLJIT_CONFIG_UNSUPPORTED is set. */347#include "sljitUtils.c"348349#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)350#define SLJIT_CODE_TO_PTR(code) ((void*)((sljit_up)(code) & ~(sljit_up)0x1))351#elif (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)352#define SLJIT_CODE_TO_PTR(code) ((void*)(*(sljit_up*)code))353#else /* !SLJIT_CONFIG_ARM_THUMB2 && !SLJIT_INDIRECT_CALL */354#define SLJIT_CODE_TO_PTR(code) ((void*)(code))355#endif /* SLJIT_CONFIG_ARM_THUMB2 || SLJIT_INDIRECT_CALL */356357#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)358359#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)360361#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)362363#if defined(__NetBSD__)364#include "allocator_src/sljitProtExecAllocatorNetBSD.c"365#else /* !__NetBSD__ */366#include "allocator_src/sljitProtExecAllocatorPosix.c"367#endif /* __NetBSD__ */368369#elif (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)370371#if defined(_WIN32)372#include "allocator_src/sljitWXExecAllocatorWindows.c"373#else /* !_WIN32 */374#include "allocator_src/sljitWXExecAllocatorPosix.c"375#endif /* _WIN32 */376377#else /* !SLJIT_PROT_EXECUTABLAE_ALLOCATOR && !SLJIT_WX_EXECUTABLE_ALLOCATOR */378379#if defined(_WIN32)380#include "allocator_src/sljitExecAllocatorWindows.c"381#elif defined(__APPLE__)382#include "allocator_src/sljitExecAllocatorApple.c"383#elif defined(__FreeBSD__)384#include "allocator_src/sljitExecAllocatorFreeBSD.c"385#else /* !_WIN32 && !__APPLE__ && !__FreeBSD__ */386#include "allocator_src/sljitExecAllocatorPosix.c"387#endif /* _WIN32 */388389#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */390391#else /* !SLJIT_EXECUTABLE_ALLOCATOR */392393#ifndef SLJIT_UPDATE_WX_FLAGS394#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)395#endif /* SLJIT_UPDATE_WX_FLAGS */396397#endif /* SLJIT_EXECUTABLE_ALLOCATOR */398399#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)400#define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr) + (exec_offset))401#else /* !SLJIT_PROT_EXECUTABLE_ALLOCATOR */402#define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr))403#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */404405/* Argument checking features. */406407#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)408409/* Returns with error when an invalid argument is passed. */410411#define CHECK_ARGUMENT(x) \412do { \413if (SLJIT_UNLIKELY(!(x))) \414return 1; \415} while (0)416417#define CHECK_RETURN_TYPE sljit_s32418#define CHECK_RETURN_OK return 0419420#define CHECK(x) \421do { \422if (SLJIT_UNLIKELY(x)) { \423compiler->error = SLJIT_ERR_BAD_ARGUMENT; \424return SLJIT_ERR_BAD_ARGUMENT; \425} \426} while (0)427428#define CHECK_PTR(x) \429do { \430if (SLJIT_UNLIKELY(x)) { \431compiler->error = SLJIT_ERR_BAD_ARGUMENT; \432return NULL; \433} \434} while (0)435436#define CHECK_REG_INDEX(x) \437do { \438if (SLJIT_UNLIKELY(x)) { \439return -2; \440} \441} while (0)442443#elif (defined SLJIT_DEBUG && SLJIT_DEBUG)444445/* Assertion failure occures if an invalid argument is passed. */446#undef SLJIT_ARGUMENT_CHECKS447#define SLJIT_ARGUMENT_CHECKS 1448449#define CHECK_ARGUMENT(x) SLJIT_ASSERT(x)450#define CHECK_RETURN_TYPE void451#define CHECK_RETURN_OK return452#define CHECK(x) x453#define CHECK_PTR(x) x454#define CHECK_REG_INDEX(x) x455456#elif (defined SLJIT_VERBOSE && SLJIT_VERBOSE)457458/* Arguments are not checked. */459#define CHECK_RETURN_TYPE void460#define CHECK_RETURN_OK return461#define CHECK(x) x462#define CHECK_PTR(x) x463#define CHECK_REG_INDEX(x) x464465#else /* !SLJIT_ARGUMENT_CHECKS && !SLJIT_DEBUG && !SLJIT_VERBOSE */466467/* Arguments are not checked. */468#define CHECK(x)469#define CHECK_PTR(x)470#define CHECK_REG_INDEX(x)471472#endif /* SLJIT_ARGUMENT_CHECKS */473474/* --------------------------------------------------------------------- */475/* Public functions */476/* --------------------------------------------------------------------- */477478#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)479#define SLJIT_NEEDS_COMPILER_INIT 1480static sljit_s32 compiler_initialized = 0;481/* A thread safe initialization. */482static void init_compiler(void);483#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_RISCV */484485SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data)486{487struct sljit_compiler *compiler = (struct sljit_compiler*)SLJIT_MALLOC(sizeof(struct sljit_compiler), allocator_data);488if (!compiler)489return NULL;490SLJIT_ZEROMEM(compiler, sizeof(struct sljit_compiler));491492SLJIT_COMPILE_ASSERT(493sizeof(sljit_s8) == 1 && sizeof(sljit_u8) == 1494&& sizeof(sljit_s16) == 2 && sizeof(sljit_u16) == 2495&& sizeof(sljit_s32) == 4 && sizeof(sljit_u32) == 4496&& (sizeof(sljit_up) == 4 || sizeof(sljit_up) == 8)497&& sizeof(sljit_up) <= sizeof(sljit_sw)498&& sizeof(sljit_up) == sizeof(sljit_sp)499&& (sizeof(sljit_sw) == 4 || sizeof(sljit_sw) == 8)500&& (sizeof(sljit_uw) == sizeof(sljit_sw)),501invalid_integer_types);502SLJIT_COMPILE_ASSERT((SLJIT_REWRITABLE_JUMP & SLJIT_32) == 0503&& (ALL_STATUS_FLAGS_MASK & SLJIT_32) == 0504&& (SLJIT_REWRITABLE_JUMP & ALL_STATUS_FLAGS_MASK) == 0,505rewritable_jump_and_status_flag_bits_and_sljit_32_must_not_have_common_bits);506SLJIT_COMPILE_ASSERT((VARIABLE_FLAG_MASK & SLJIT_SET_Z) == 0,507rewritable_jump_and_status_flag_bits_must_not_have_common_bits);508SLJIT_COMPILE_ASSERT(!(SLJIT_EQUAL & 0x1) && !(SLJIT_LESS & 0x1) && !(SLJIT_F_EQUAL & 0x1) && !(SLJIT_JUMP & 0x1),509conditional_flags_must_be_even_numbers);510511/* Only the non-zero members must be set. */512compiler->error = SLJIT_SUCCESS;513514compiler->allocator_data = allocator_data;515compiler->buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data);516compiler->abuf = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, allocator_data);517518if (!compiler->buf || !compiler->abuf) {519if (compiler->buf)520SLJIT_FREE(compiler->buf, allocator_data);521if (compiler->abuf)522SLJIT_FREE(compiler->abuf, allocator_data);523SLJIT_FREE(compiler, allocator_data);524return NULL;525}526527compiler->buf->next = NULL;528compiler->buf->used_size = 0;529compiler->abuf->next = NULL;530compiler->abuf->used_size = 0;531532compiler->scratches = -1;533compiler->saveds = -1;534compiler->fscratches = -1;535compiler->fsaveds = -1;536#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) \537|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \538|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)539compiler->vscratches = -1;540compiler->vsaveds = -1;541#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS || SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */542compiler->local_size = -1;543544#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)545compiler->args_size = -1;546#endif /* SLJIT_CONFIG_X86_32 */547548#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)549compiler->cpool = (sljit_uw*)SLJIT_MALLOC(CPOOL_SIZE * sizeof(sljit_uw)550+ CPOOL_SIZE * sizeof(sljit_u8), allocator_data);551if (!compiler->cpool) {552SLJIT_FREE(compiler->buf, allocator_data);553SLJIT_FREE(compiler->abuf, allocator_data);554SLJIT_FREE(compiler, allocator_data);555return NULL;556}557compiler->cpool_unique = (sljit_u8*)(compiler->cpool + CPOOL_SIZE);558compiler->cpool_diff = 0xffffffff;559#endif /* SLJIT_CONFIG_ARM_V6 */560561#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)562compiler->delay_slot = UNMOVABLE_INS;563#endif /* SLJIT_CONFIG_MIPS */564565#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \566|| (defined SLJIT_DEBUG && SLJIT_DEBUG)567SLJIT_ASSERT(compiler->last_flags == 0 && compiler->logical_local_size == 0);568compiler->last_return = -1;569#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */570571#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \572|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)573#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)574compiler->real_fscratches = -1;575compiler->real_fsaveds = -1;576#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */577SLJIT_ASSERT(compiler->skip_checks == 0);578#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */579580#if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT)581if (!compiler_initialized) {582init_compiler();583compiler_initialized = 1;584}585#endif /* SLJIT_NEEDS_COMPILER_INIT */586587return compiler;588}589590SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler)591{592struct sljit_memory_fragment *buf;593struct sljit_memory_fragment *curr;594void *allocator_data = compiler->allocator_data;595SLJIT_UNUSED_ARG(allocator_data);596597buf = compiler->buf;598while (buf) {599curr = buf;600buf = buf->next;601SLJIT_FREE(curr, allocator_data);602}603604buf = compiler->abuf;605while (buf) {606curr = buf;607buf = buf->next;608SLJIT_FREE(curr, allocator_data);609}610611#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)612SLJIT_FREE(compiler->cpool, allocator_data);613#endif /* SLJIT_CONFIG_ARM_V6 */614SLJIT_FREE(compiler, allocator_data);615}616617SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler)618{619if (compiler->error == SLJIT_SUCCESS)620compiler->error = SLJIT_ERR_ALLOC_FAILED;621}622623SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)624{625SLJIT_UNUSED_ARG(exec_allocator_data);626627SLJIT_FREE_EXEC(SLJIT_CODE_TO_PTR(code), exec_allocator_data);628}629630SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)631{632if (SLJIT_LIKELY(!!jump) && SLJIT_LIKELY(!!label)) {633jump->flags &= (sljit_uw)~JUMP_ADDR;634jump->u.label = label;635}636}637638SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)639{640if (SLJIT_LIKELY(!!jump)) {641jump->flags |= JUMP_ADDR;642jump->u.target = target;643}644}645646#define SLJIT_CURRENT_FLAGS_ALL (SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_ADD \647| SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE | SLJIT_CURRENT_FLAGS_OP2CMPZ)648649SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)650{651SLJIT_UNUSED_ARG(compiler);652SLJIT_UNUSED_ARG(current_flags);653654#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)655#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)656if (current_flags & SLJIT_CURRENT_FLAGS_OP2CMPZ) {657current_flags |= SLJIT_SET_Z;658}659#endif /* SLJIT_CONFIG_S390X */660661compiler->status_flags_state = current_flags;662#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */663664#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)665compiler->last_flags = 0;666if ((current_flags & ~(ALL_STATUS_FLAGS_MASK | SLJIT_CURRENT_FLAGS_ALL)) == 0) {667compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_32 | SLJIT_SET_Z));668}669#endif /* SLJIT_ARGUMENT_CHECKS */670}671672/* --------------------------------------------------------------------- */673/* Private functions */674/* --------------------------------------------------------------------- */675676static void* ensure_buf(struct sljit_compiler *compiler, sljit_uw size)677{678sljit_u8 *ret;679struct sljit_memory_fragment *new_frag;680681SLJIT_ASSERT(size <= 256);682if (compiler->buf->used_size + size <= (BUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) {683ret = compiler->buf->memory + compiler->buf->used_size;684compiler->buf->used_size += size;685return ret;686}687new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, compiler->allocator_data);688PTR_FAIL_IF_NULL(new_frag);689new_frag->next = compiler->buf;690compiler->buf = new_frag;691new_frag->used_size = size;692return new_frag->memory;693}694695static void* ensure_abuf(struct sljit_compiler *compiler, sljit_uw size)696{697sljit_u8 *ret;698struct sljit_memory_fragment *new_frag;699700SLJIT_ASSERT(size <= 256);701if (compiler->abuf->used_size + size <= (ABUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) {702ret = compiler->abuf->memory + compiler->abuf->used_size;703compiler->abuf->used_size += size;704return ret;705}706new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, compiler->allocator_data);707PTR_FAIL_IF_NULL(new_frag);708new_frag->next = compiler->abuf;709compiler->abuf = new_frag;710new_frag->used_size = size;711return new_frag->memory;712}713714SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size)715{716CHECK_ERROR_PTR();717718#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)719if (size <= 0 || size > 128)720return NULL;721size = (size + 7) & ~7;722#else /* !SLJIT_64BIT_ARCHITECTURE */723if (size <= 0 || size > 64)724return NULL;725size = (size + 3) & ~3;726#endif /* SLJIT_64BIT_ARCHITECTURE */727return ensure_abuf(compiler, (sljit_uw)size);728}729730static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler)731{732struct sljit_memory_fragment *buf = compiler->buf;733struct sljit_memory_fragment *prev = NULL;734struct sljit_memory_fragment *tmp;735736do {737tmp = buf->next;738buf->next = prev;739prev = buf;740buf = tmp;741} while (buf != NULL);742743compiler->buf = prev;744}745746static SLJIT_INLINE void* allocate_executable_memory(sljit_uw size, sljit_s32 options,747void *exec_allocator_data, sljit_sw *executable_offset)748{749void *code;750struct sljit_generate_code_buffer *buffer;751752if (SLJIT_LIKELY(!(options & SLJIT_GENERATE_CODE_BUFFER))) {753code = SLJIT_MALLOC_EXEC(size, exec_allocator_data);754*executable_offset = SLJIT_EXEC_OFFSET(code);755return code;756}757758buffer = (struct sljit_generate_code_buffer*)exec_allocator_data;759760if (size <= buffer->size) {761*executable_offset = buffer->executable_offset;762return buffer->buffer;763}764765return NULL;766}767768#define SLJIT_MAX_ADDRESS ~(sljit_uw)0769770#define SLJIT_GET_NEXT_SIZE(ptr) (ptr != NULL) ? ((ptr)->size) : SLJIT_MAX_ADDRESS771#define SLJIT_GET_NEXT_ADDRESS(ptr) (ptr != NULL) ? ((ptr)->addr) : SLJIT_MAX_ADDRESS772773#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)774775#define SLJIT_NEXT_DEFINE_TYPES \776sljit_uw next_label_size; \777sljit_uw next_jump_addr; \778sljit_uw next_const_addr; \779sljit_uw next_min_addr780781#define SLJIT_NEXT_INIT_TYPES() \782next_label_size = SLJIT_GET_NEXT_SIZE(label); \783next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); \784next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);785786#define SLJIT_GET_NEXT_MIN() \787next_min_addr = sljit_get_next_min(next_label_size, next_jump_addr, next_const_addr);788789static SLJIT_INLINE sljit_uw sljit_get_next_min(sljit_uw next_label_size,790sljit_uw next_jump_addr, sljit_uw next_const_addr)791{792sljit_uw result = next_jump_addr;793794SLJIT_ASSERT(result == SLJIT_MAX_ADDRESS || result != next_const_addr);795796if (next_const_addr < result)797result = next_const_addr;798799if (next_label_size < result)800result = next_label_size;801802return result;803}804805#endif /* !SLJIT_CONFIG_X86 */806807#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)808809static void update_float_register_count(struct sljit_compiler *compiler, sljit_s32 scratches, sljit_s32 saveds)810{811sljit_s32 vscratches = ENTER_GET_VECTOR_REGS(scratches);812sljit_s32 vsaveds = ENTER_GET_VECTOR_REGS(saveds);813814if (compiler->fscratches < vscratches)815compiler->fscratches = vscratches;816817if (compiler->fsaveds < vsaveds)818compiler->fsaveds = vsaveds;819820if (compiler->fsaveds + compiler->fscratches > SLJIT_NUMBER_OF_FLOAT_REGISTERS)821compiler->fscratches = SLJIT_NUMBER_OF_FLOAT_REGISTERS - compiler->fsaveds;822}823824#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */825826static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,827sljit_s32 options, sljit_s32 args,828sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)829{830SLJIT_UNUSED_ARG(args);831SLJIT_UNUSED_ARG(local_size);832833compiler->options = options;834compiler->scratches = ENTER_GET_REGS(scratches);835compiler->saveds = ENTER_GET_REGS(saveds);836/* These members may be copied to real_* members below. */837compiler->fscratches = ENTER_GET_FLOAT_REGS(scratches);838compiler->fsaveds = ENTER_GET_FLOAT_REGS(saveds);839#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)840compiler->vscratches = ENTER_GET_VECTOR_REGS(scratches);841compiler->vsaveds = ENTER_GET_VECTOR_REGS(saveds);842#else /* !SLJIT_SEPARATE_VECTOR_REGISTERS */843#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \844|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)845compiler->real_fscratches = compiler->fscratches;846compiler->real_fsaveds = compiler->fsaveds;847compiler->vscratches = ENTER_GET_VECTOR_REGS(scratches);848compiler->vsaveds = ENTER_GET_VECTOR_REGS(saveds);849#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */850update_float_register_count(compiler, scratches, saveds);851#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS */852#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)853compiler->last_return = args & SLJIT_ARG_MASK;854compiler->logical_local_size = local_size;855#endif /* SLJIT_ARGUMENT_CHECKS */856}857858static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compiler *compiler)859{860label->next = NULL;861label->u.index = compiler->label_count++;862label->size = compiler->size;863864if (compiler->last_label != NULL)865compiler->last_label->next = label;866else867compiler->labels = label;868869compiler->last_label = label;870}871872static SLJIT_INLINE void set_extended_label(struct sljit_extended_label *ext_label, struct sljit_compiler *compiler, sljit_uw type, sljit_uw data)873{874set_label(&ext_label->label, compiler);875ext_label->index = ext_label->label.u.index;876ext_label->label.u.index = type;877ext_label->data = data;878}879880static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_u32 flags)881{882jump->next = NULL;883jump->flags = flags;884jump->u.label = NULL;885886if (compiler->last_jump != NULL)887compiler->last_jump->next = jump;888else889compiler->jumps = jump;890891compiler->last_jump = jump;892}893894static SLJIT_INLINE void set_mov_addr(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_uw offset)895{896jump->next = NULL;897jump->addr = compiler->size - offset;898jump->flags = JUMP_MOV_ADDR;899jump->u.label = NULL;900if (compiler->last_jump != NULL)901compiler->last_jump->next = jump;902else903compiler->jumps = jump;904compiler->last_jump = jump;905}906907static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_compiler *compiler)908{909const_->next = NULL;910const_->addr = compiler->size;911if (compiler->last_const != NULL)912compiler->last_const->next = const_;913else914compiler->consts = const_;915compiler->last_const = const_;916}917918#define ADDRESSING_DEPENDS_ON(exp, reg) \919(((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg))920921#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)922923static sljit_s32 function_check_arguments(sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches)924{925sljit_s32 word_arg_count, scratch_arg_end, saved_arg_count, float_arg_count, curr_type;926927curr_type = (arg_types & SLJIT_ARG_FULL_MASK);928929if (curr_type >= SLJIT_ARG_TYPE_F64) {930if (curr_type > SLJIT_ARG_TYPE_F32 || fscratches == 0)931return 0;932} else if (curr_type >= SLJIT_ARG_TYPE_W) {933if (scratches == 0)934return 0;935}936937arg_types >>= SLJIT_ARG_SHIFT;938939word_arg_count = 0;940scratch_arg_end = 0;941saved_arg_count = 0;942float_arg_count = 0;943while (arg_types != 0) {944if (word_arg_count + float_arg_count >= 4)945return 0;946947curr_type = (arg_types & SLJIT_ARG_MASK);948949if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {950if (saveds == -1 || curr_type < SLJIT_ARG_TYPE_W || curr_type > SLJIT_ARG_TYPE_P)951return 0;952953word_arg_count++;954scratch_arg_end = word_arg_count;955} else {956if (curr_type < SLJIT_ARG_TYPE_W || curr_type > SLJIT_ARG_TYPE_F32)957return 0;958959if (curr_type < SLJIT_ARG_TYPE_F64) {960word_arg_count++;961saved_arg_count++;962} else963float_arg_count++;964}965966arg_types >>= SLJIT_ARG_SHIFT;967}968969if (saveds == -1)970return (word_arg_count <= scratches && float_arg_count <= fscratches);971972return (saved_arg_count <= saveds && scratch_arg_end <= scratches && float_arg_count <= fscratches);973}974975#define FUNCTION_CHECK_IS_REG(r) \976(((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) \977|| ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0) \978|| ((r) >= SLJIT_TMP_REGISTER_BASE && (r) < (SLJIT_TMP_REGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_REGISTERS)))979980#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)981#define CHECK_IF_VIRTUAL_REGISTER(p) ((p) <= SLJIT_S3 && (p) >= SLJIT_S8)982#else /* !SLJIT_CONFIG_X86_32 */983#define CHECK_IF_VIRTUAL_REGISTER(p) 0984#endif /* SLJIT_CONFIG_X86_32 */985986static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)987{988if (compiler->scratches == -1)989return 0;990991if (!(p & SLJIT_MEM))992return 0;993994if (p == SLJIT_MEM1(SLJIT_SP))995return (i >= 0 && i < compiler->logical_local_size);996997if (!(!(p & REG_MASK) || FUNCTION_CHECK_IS_REG(p & REG_MASK)))998return 0;9991000if (CHECK_IF_VIRTUAL_REGISTER(p & REG_MASK))1001return 0;10021003if (p & OFFS_REG_MASK) {1004if (!(p & REG_MASK))1005return 0;10061007if (!(FUNCTION_CHECK_IS_REG(OFFS_REG(p))))1008return 0;10091010if (CHECK_IF_VIRTUAL_REGISTER(OFFS_REG(p)))1011return 0;10121013if ((i & ~0x3) != 0)1014return 0;1015}10161017return (p & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK)) == 0;1018}10191020#define FUNCTION_CHECK_SRC_MEM(p, i) \1021CHECK_ARGUMENT(function_check_src_mem(compiler, p, i));10221023static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)1024{1025if (compiler->scratches == -1)1026return 0;10271028if (FUNCTION_CHECK_IS_REG(p))1029return (i == 0);10301031if (p == SLJIT_IMM)1032return 1;10331034return function_check_src_mem(compiler, p, i);1035}10361037#define FUNCTION_CHECK_SRC(p, i) \1038CHECK_ARGUMENT(function_check_src(compiler, p, i));10391040static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)1041{1042if (compiler->scratches == -1)1043return 0;10441045if (FUNCTION_CHECK_IS_REG(p))1046return (i == 0);10471048return function_check_src_mem(compiler, p, i);1049}10501051#define FUNCTION_CHECK_DST(p, i) \1052CHECK_ARGUMENT(function_check_dst(compiler, p, i));10531054#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \1055|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)10561057#define FUNCTION_CHECK_IS_FREG(fr, is_32) \1058function_check_is_freg(compiler, (fr), (is_32))10591060static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32);10611062#define FUNCTION_FCHECK(p, i, is_32) \1063CHECK_ARGUMENT(function_fcheck(compiler, (p), (i), (is_32)));10641065static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 is_32)1066{1067if (compiler->scratches == -1)1068return 0;10691070if (FUNCTION_CHECK_IS_FREG(p, is_32))1071return (i == 0);10721073return function_check_src_mem(compiler, p, i);1074}10751076static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type);10771078#define FUNCTION_CHECK_IS_VREG(vr, type) \1079function_check_is_vreg(compiler, (vr), (type))10801081#define FUNCTION_VCHECK(p, i, type) \1082CHECK_ARGUMENT(function_vcheck(compiler, (p), (i), (type)))10831084static sljit_s32 function_vcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 type)1085{1086if (compiler->scratches == -1)1087return 0;10881089if (FUNCTION_CHECK_IS_VREG(p, type))1090return (i == 0);10911092return function_check_src_mem(compiler, p, i);1093}10941095#else /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS_32 */10961097#define FUNCTION_CHECK_IS_FREG(fr, is_32) \1098function_check_is_freg(compiler, (fr))10991100static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr)1101{1102sljit_s32 fscratches, fsaveds;11031104if (compiler->scratches == -1)1105return 0;11061107#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)1108fscratches = compiler->fscratches;1109fsaveds = compiler->fsaveds;1110#else /* SLJIT_SEPARATE_VECTOR_REGISTERS */1111fscratches = compiler->real_fscratches;1112fsaveds = compiler->real_fsaveds;1113#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */11141115return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + fscratches))1116|| (fr > (SLJIT_FS0 - fsaveds) && fr <= SLJIT_FS0)1117|| (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));1118}11191120#define FUNCTION_FCHECK(p, i, is_32) \1121CHECK_ARGUMENT(function_fcheck(compiler, (p), (i)));11221123static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)1124{1125if (compiler->scratches == -1)1126return 0;11271128if (function_check_is_freg(compiler, p))1129return (i == 0);11301131return function_check_src_mem(compiler, p, i);1132}11331134#define FUNCTION_CHECK_IS_VREG(vr, type) \1135function_check_is_vreg(compiler, (vr))11361137static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr)1138{1139if (compiler->scratches == -1)1140return 0;11411142return (vr >= SLJIT_VR0 && vr < (SLJIT_VR0 + compiler->vscratches))1143|| (vr > (SLJIT_VS0 - compiler->vsaveds) && vr <= SLJIT_VS0)1144|| (vr >= SLJIT_TMP_VREGISTER_BASE && vr < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS));1145}11461147#define FUNCTION_VCHECK(p, i, type) \1148CHECK_ARGUMENT(function_vcheck(compiler, (p), (i)))11491150static sljit_s32 function_vcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)1151{1152if (compiler->scratches == -1)1153return 0;11541155if (function_check_is_vreg(compiler, p))1156return (i == 0);11571158return function_check_src_mem(compiler, p, i);1159}11601161#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */11621163#endif /* SLJIT_ARGUMENT_CHECKS */11641165#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)11661167SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose)1168{1169compiler->verbose = verbose;1170}11711172#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)1173#ifdef _WIN641174#ifdef __GNUC__1175# define SLJIT_PRINT_D "ll"1176#else /* !__GNUC__ */1177# define SLJIT_PRINT_D "I64"1178#endif /* __GNUC__ */1179#else /* !_WIN64 */1180# define SLJIT_PRINT_D "l"1181#endif /* _WIN64 */1182#else /* !SLJIT_64BIT_ARCHITECTURE */1183# define SLJIT_PRINT_D ""1184#endif /* SLJIT_64BIT_ARCHITECTURE */11851186static void sljit_verbose_reg(struct sljit_compiler *compiler, sljit_s32 r)1187{1188if (r < (SLJIT_R0 + compiler->scratches))1189fprintf(compiler->verbose, "r%d", r - SLJIT_R0);1190else if (r < SLJIT_SP)1191fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - r);1192else if (r == SLJIT_SP)1193fprintf(compiler->verbose, "sp");1194else1195fprintf(compiler->verbose, "t%d", r - SLJIT_TMP_REGISTER_BASE);1196}11971198static void sljit_verbose_freg(struct sljit_compiler *compiler, sljit_s32 r)1199{1200#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \1201|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1202if (r >= SLJIT_F64_SECOND(SLJIT_FR0)) {1203fprintf(compiler->verbose, "^");1204r -= SLJIT_F64_SECOND(0);1205}1206#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */12071208if (r < (SLJIT_FR0 + compiler->fscratches))1209fprintf(compiler->verbose, "fr%d", r - SLJIT_FR0);1210else if (r < SLJIT_TMP_FREGISTER_BASE)1211fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - r);1212else1213fprintf(compiler->verbose, "ft%d", r - SLJIT_TMP_FREGISTER_BASE);1214}12151216static void sljit_verbose_vreg(struct sljit_compiler *compiler, sljit_s32 r)1217{1218#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \1219|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1220if (r >= SLJIT_F64_SECOND(SLJIT_VR0)) {1221fprintf(compiler->verbose, "^");1222r -= SLJIT_F64_SECOND(0);1223}1224#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */12251226if (r < (SLJIT_VR0 + compiler->vscratches))1227fprintf(compiler->verbose, "vr%d", r - SLJIT_VR0);1228else if (r < SLJIT_TMP_VREGISTER_BASE)1229fprintf(compiler->verbose, "vs%d", SLJIT_NUMBER_OF_VECTOR_REGISTERS - r);1230else1231fprintf(compiler->verbose, "vt%d", r - SLJIT_TMP_VREGISTER_BASE);1232}12331234static void sljit_verbose_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)1235{1236if (!(p & REG_MASK)) {1237fprintf(compiler->verbose, "[%" SLJIT_PRINT_D "d]", i);1238return;1239}12401241fputc('[', compiler->verbose);1242sljit_verbose_reg(compiler, (p) & REG_MASK);1243if (p & OFFS_REG_MASK) {1244fprintf(compiler->verbose, " + ");1245sljit_verbose_reg(compiler, OFFS_REG(p));1246if (i)1247fprintf(compiler->verbose, " * %d", 1 << (i));1248} else if (i)1249fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));1250fputc(']', compiler->verbose);1251}12521253static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)1254{1255if (p == SLJIT_IMM)1256fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", i);1257else if (p & SLJIT_MEM)1258sljit_verbose_mem(compiler, p, i);1259else1260sljit_verbose_reg(compiler, p);1261}12621263static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)1264{1265if (p & SLJIT_MEM)1266sljit_verbose_mem(compiler, p, i);1267else1268sljit_verbose_freg(compiler, p);1269}12701271static void sljit_verbose_vparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)1272{1273if (p & SLJIT_MEM)1274sljit_verbose_mem(compiler, p, i);1275else1276sljit_verbose_vreg(compiler, p);1277}12781279static const char* op0_names[] = {1280"breakpoint", "nop", "lmul.uw", "lmul.sw",1281"divmod.u", "divmod.s", "div.u", "div.s",1282"memory_barrier", "endbr", "skip_frames_before_return"1283};12841285static const char* op1_names[] = {1286"mov", "mov", "mov", "mov",1287"mov", "mov", "mov", "mov",1288"mov", "clz", "ctz", "rev",1289"rev", "rev", "rev", "rev"1290};12911292static const char* op1_types[] = {1293"", ".u8", ".s8", ".u16",1294".s16", ".u32", ".s32", "32",1295".p", "", "", "",1296".u16", ".s16", ".u32", ".s32"1297};12981299static const char* op2_names[] = {1300"add", "addc", "sub", "subc",1301"mul", "and", "or", "xor",1302"shl", "mshl", "lshr", "mlshr",1303"ashr", "mashr", "rotl", "rotr"1304};13051306static const char* op2r_names[] = {1307"muladd"1308};13091310static const char* op_src_dst_names[] = {1311"fast_return", "skip_frames_before_fast_return",1312"prefetch_l1", "prefetch_l2",1313"prefetch_l3", "prefetch_once",1314"fast_enter", "get_return_address"1315};13161317static const char* fop1_names[] = {1318"mov", "conv", "conv", "conv",1319"conv", "conv", "conv", "conv",1320"cmp", "neg", "abs",1321};13221323static const char* fop1_conv_types[] = {1324"sw", "s32", "sw", "s32",1325"uw", "u32"1326};13271328static const char* fop2_names[] = {1329"add", "sub", "mul", "div"1330};13311332static const char* fop2r_names[] = {1333"copysign"1334};13351336static const char* simd_op2_names[] = {1337"and", "or", "xor", "shuffle"1338};13391340static const char* jump_names[] = {1341"equal", "not_equal",1342"less", "greater_equal",1343"greater", "less_equal",1344"sig_less", "sig_greater_equal",1345"sig_greater", "sig_less_equal",1346"overflow", "not_overflow",1347"carry", "not_carry",1348"atomic_stored", "atomic_not_stored",1349"f_equal", "f_not_equal",1350"f_less", "f_greater_equal",1351"f_greater", "f_less_equal",1352"unordered", "ordered",1353"ordered_equal", "unordered_or_not_equal",1354"ordered_less", "unordered_or_greater_equal",1355"ordered_greater", "unordered_or_less_equal",1356"unordered_or_equal", "ordered_not_equal",1357"unordered_or_less", "ordered_greater_equal",1358"unordered_or_greater", "ordered_less_equal",1359"jump", "fast_call",1360"call", "call_reg_arg"1361};13621363static const char* call_arg_names[] = {1364"void", "w", "32", "p", "f64", "f32"1365};13661367static const char* op_addr_types[] = {1368"mov_addr", "mov_abs_addr", "add_abs_addr"1369};13701371#endif /* SLJIT_VERBOSE */13721373/* --------------------------------------------------------------------- */1374/* Arch dependent */1375/* --------------------------------------------------------------------- */13761377#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \1378|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)13791380#define SLJIT_SKIP_CHECKS(compiler) (compiler)->skip_checks = 11381#define SLJIT_CHECK_OPCODE(op, flags) ((op) & ~(SLJIT_32 | ALL_STATUS_FLAGS_MASK | (flags)))13821383static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options)1384{1385#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1386struct sljit_jump *jump;1387#endif /* SLJIT_ARGUMENT_CHECKS */13881389SLJIT_UNUSED_ARG(compiler);1390SLJIT_UNUSED_ARG(options);13911392#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1393CHECK_ARGUMENT(compiler->size > 0);1394CHECK_ARGUMENT((options & ~(SLJIT_GENERATE_CODE_BUFFER | SLJIT_GENERATE_CODE_NO_CONTEXT)) == 0);13951396jump = compiler->jumps;1397while (jump) {1398/* All jumps have target. */1399CHECK_ARGUMENT((jump->flags & JUMP_ADDR) || jump->u.label != NULL);1400jump = jump->next;1401}1402#endif /* SLJIT_ARGUMENT_CHECKS */1403CHECK_RETURN_OK;1404}14051406#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)1407#define SLJIT_ENTER_CPU_SPECIFIC_OPTIONS (SLJIT_ENTER_USE_VEX)1408#else /* !SLJIT_CONFIG_X86 */1409#define SLJIT_ENTER_CPU_SPECIFIC_OPTIONS (0)1410#endif /* !SLJIT_CONFIG_X86 */14111412static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compiler *compiler,1413sljit_s32 options, sljit_s32 arg_types,1414sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)1415{1416#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1417sljit_s32 real_scratches = ENTER_GET_REGS(scratches);1418sljit_s32 real_saveds = ENTER_GET_REGS(saveds);1419sljit_s32 real_fscratches = ENTER_GET_FLOAT_REGS(scratches);1420sljit_s32 real_fsaveds = ENTER_GET_FLOAT_REGS(saveds);1421sljit_s32 real_vscratches = ENTER_GET_VECTOR_REGS(scratches);1422sljit_s32 real_vsaveds = ENTER_GET_VECTOR_REGS(saveds);1423#endif /* SLJIT_ARGUMENT_CHECKS */1424SLJIT_UNUSED_ARG(compiler);14251426#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1427if (options & SLJIT_ENTER_REG_ARG) {1428CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG | SLJIT_ENTER_CPU_SPECIFIC_OPTIONS)));1429} else {1430CHECK_ARGUMENT((options & ~SLJIT_ENTER_CPU_SPECIFIC_OPTIONS) == 0);1431}1432CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);1433CHECK_ARGUMENT((scratches & ~0xffffff) == 0 && (saveds & ~0xffffff) == 0);1434CHECK_ARGUMENT(real_scratches >= 0 && real_scratches <= SLJIT_NUMBER_OF_REGISTERS);1435CHECK_ARGUMENT(real_saveds >= 0 && real_saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);1436CHECK_ARGUMENT(real_scratches + real_saveds <= SLJIT_NUMBER_OF_REGISTERS);1437CHECK_ARGUMENT(real_fscratches >= 0 && real_fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);1438CHECK_ARGUMENT(real_fsaveds >= 0 && real_fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);1439CHECK_ARGUMENT(real_fscratches + real_fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);1440CHECK_ARGUMENT(real_vscratches >= 0 && real_vscratches <= SLJIT_NUMBER_OF_VECTOR_REGISTERS);1441CHECK_ARGUMENT(real_vsaveds >= 0 && real_vsaveds <= SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS);1442CHECK_ARGUMENT(real_vscratches + real_vsaveds <= SLJIT_NUMBER_OF_VECTOR_REGISTERS);1443CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);1444CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) <= SLJIT_ARG_TYPE_F32);1445CHECK_ARGUMENT(function_check_arguments(arg_types, real_scratches,1446(options & SLJIT_ENTER_REG_ARG) ? 0 : real_saveds, real_fscratches));14471448compiler->last_flags = 0;1449#endif /* SLJIT_ARGUMENT_CHECKS */1450#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1451if (SLJIT_UNLIKELY(!!compiler->verbose)) {1452fprintf(compiler->verbose, " enter ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);14531454arg_types >>= SLJIT_ARG_SHIFT;1455if (arg_types) {1456fprintf(compiler->verbose, "], args[");1457do {1458fprintf(compiler->verbose, "%s%s", call_arg_names[arg_types & SLJIT_ARG_MASK],1459(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? "_r" : "");1460arg_types >>= SLJIT_ARG_SHIFT;1461if (arg_types)1462fprintf(compiler->verbose, ",");1463} while (arg_types);1464}14651466fprintf(compiler->verbose, "],");14671468if (options & SLJIT_ENTER_REG_ARG) {1469if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)1470fprintf(compiler->verbose, " opt:reg_arg(%d),", SLJIT_KEPT_SAVEDS_COUNT(options));1471else1472fprintf(compiler->verbose, " opt:reg_arg,");1473}14741475#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)1476if (options & SLJIT_ENTER_USE_VEX) {1477fprintf(compiler->verbose, " opt:use_vex,");1478}1479#endif /* !SLJIT_CONFIG_X86 */14801481fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, vscratches:%d, vsaveds:%d, local_size:%d\n",1482ENTER_GET_REGS(scratches), ENTER_GET_REGS(saveds), ENTER_GET_FLOAT_REGS(scratches), ENTER_GET_FLOAT_REGS(saveds),1483ENTER_GET_VECTOR_REGS(scratches), ENTER_GET_VECTOR_REGS(saveds), local_size);1484}1485#endif /* SLJIT_VERBOSE */1486CHECK_RETURN_OK;1487}14881489static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compiler *compiler,1490sljit_s32 options, sljit_s32 arg_types,1491sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)1492{1493#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1494sljit_s32 real_scratches = ENTER_GET_REGS(scratches);1495sljit_s32 real_saveds = ENTER_GET_REGS(saveds);1496sljit_s32 real_fscratches = ENTER_GET_FLOAT_REGS(scratches);1497sljit_s32 real_fsaveds = ENTER_GET_FLOAT_REGS(saveds);1498sljit_s32 real_vscratches = ENTER_GET_VECTOR_REGS(scratches);1499sljit_s32 real_vsaveds = ENTER_GET_VECTOR_REGS(saveds);1500#endif /* SLJIT_ARGUMENT_CHECKS */1501SLJIT_UNUSED_ARG(compiler);15021503#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1504if (options & SLJIT_ENTER_REG_ARG) {1505CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG | SLJIT_ENTER_CPU_SPECIFIC_OPTIONS)));1506} else {1507CHECK_ARGUMENT((options & ~SLJIT_ENTER_CPU_SPECIFIC_OPTIONS) == 0);1508}1509CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);1510CHECK_ARGUMENT((scratches & ~0xffffff) == 0 && (saveds & ~0xffffff) == 0);1511CHECK_ARGUMENT(real_scratches >= 0 && real_scratches <= SLJIT_NUMBER_OF_REGISTERS);1512CHECK_ARGUMENT(real_saveds >= 0 && real_saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);1513CHECK_ARGUMENT(real_scratches + real_saveds <= SLJIT_NUMBER_OF_REGISTERS);1514CHECK_ARGUMENT(real_fscratches >= 0 && real_fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);1515CHECK_ARGUMENT(real_fsaveds >= 0 && real_fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);1516CHECK_ARGUMENT(real_fscratches + real_fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);1517CHECK_ARGUMENT(real_vscratches >= 0 && real_vscratches <= SLJIT_NUMBER_OF_VECTOR_REGISTERS);1518CHECK_ARGUMENT(real_vsaveds >= 0 && real_vsaveds <= SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS);1519CHECK_ARGUMENT(real_vscratches + real_vsaveds <= SLJIT_NUMBER_OF_VECTOR_REGISTERS);1520CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);1521CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64);1522CHECK_ARGUMENT(function_check_arguments(arg_types, real_scratches,1523(options & SLJIT_ENTER_REG_ARG) ? 0 : real_saveds, real_fscratches));15241525compiler->last_flags = 0;1526#endif /* SLJIT_ARGUMENT_CHECKS */1527#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1528if (SLJIT_UNLIKELY(!!compiler->verbose)) {1529fprintf(compiler->verbose, " set_context ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);15301531arg_types >>= SLJIT_ARG_SHIFT;1532if (arg_types) {1533fprintf(compiler->verbose, "], args[");1534do {1535fprintf(compiler->verbose, "%s%s", call_arg_names[arg_types & SLJIT_ARG_MASK],1536(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? "_r" : "");1537arg_types >>= SLJIT_ARG_SHIFT;1538if (arg_types)1539fprintf(compiler->verbose, ",");1540} while (arg_types);1541}15421543fprintf(compiler->verbose, "],");15441545if (options & SLJIT_ENTER_REG_ARG) {1546if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)1547fprintf(compiler->verbose, " opt:reg_arg(%d),", SLJIT_KEPT_SAVEDS_COUNT(options));1548else1549fprintf(compiler->verbose, " opt:reg_arg,");1550}15511552#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)1553if (options & SLJIT_ENTER_USE_VEX) {1554fprintf(compiler->verbose, " opt:use_vex,");1555}1556#endif /* !SLJIT_CONFIG_X86 */15571558fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, vscratches:%d, vsaveds:%d, local_size:%d\n",1559ENTER_GET_REGS(scratches), ENTER_GET_REGS(saveds), ENTER_GET_FLOAT_REGS(scratches), ENTER_GET_FLOAT_REGS(saveds),1560ENTER_GET_VECTOR_REGS(scratches), ENTER_GET_VECTOR_REGS(saveds), local_size);1561}1562#endif /* SLJIT_VERBOSE */1563CHECK_RETURN_OK;1564}15651566#undef SLJIT_ENTER_CPU_SPECIFIC_OPTIONS15671568static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_void(struct sljit_compiler *compiler)1569{1570if (SLJIT_UNLIKELY(compiler->skip_checks)) {1571compiler->skip_checks = 0;1572CHECK_RETURN_OK;1573}15741575#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1576CHECK_ARGUMENT(compiler->last_return == SLJIT_ARG_TYPE_RET_VOID);1577#endif /* SLJIT_ARGUMENT_CHECKS */15781579#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1580if (SLJIT_UNLIKELY(!!compiler->verbose)) {1581fprintf(compiler->verbose, " return_void\n");1582}1583#endif /* SLJIT_VERBOSE */1584CHECK_RETURN_OK;1585}15861587static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)1588{1589#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1590CHECK_ARGUMENT(compiler->scratches >= 0);15911592switch (compiler->last_return) {1593case SLJIT_ARG_TYPE_W:1594CHECK_ARGUMENT(op >= SLJIT_MOV && op <= SLJIT_MOV_S32);1595break;1596case SLJIT_ARG_TYPE_32:1597CHECK_ARGUMENT(op == SLJIT_MOV32 || (op >= SLJIT_MOV32_U8 && op <= SLJIT_MOV32_S16));1598break;1599case SLJIT_ARG_TYPE_P:1600CHECK_ARGUMENT(op == SLJIT_MOV_P);1601break;1602case SLJIT_ARG_TYPE_F64:1603CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));1604CHECK_ARGUMENT(op == SLJIT_MOV_F64);1605break;1606case SLJIT_ARG_TYPE_F32:1607CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));1608CHECK_ARGUMENT(op == SLJIT_MOV_F32);1609break;1610default:1611/* Context not initialized, void, etc. */1612CHECK_ARGUMENT(0);1613break;1614}16151616if (SLJIT_CHECK_OPCODE(op, 0) < SLJIT_MOV_F64) {1617FUNCTION_CHECK_SRC(src, srcw);1618} else {1619FUNCTION_FCHECK(src, srcw, op & SLJIT_32);1620}1621compiler->last_flags = 0;1622#endif /* SLJIT_ARGUMENT_CHECKS */1623#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1624if (SLJIT_UNLIKELY(!!compiler->verbose)) {1625if (GET_OPCODE(op) < SLJIT_MOV_F64) {1626fprintf(compiler->verbose, " return%s%s ", !(op & SLJIT_32) ? "" : "32",1627op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);1628sljit_verbose_param(compiler, src, srcw);1629} else {1630fprintf(compiler->verbose, " return%s ", !(op & SLJIT_32) ? ".f64" : ".f32");1631sljit_verbose_fparam(compiler, src, srcw);1632}1633fprintf(compiler->verbose, "\n");1634}1635#endif /* SLJIT_VERBOSE */1636CHECK_RETURN_OK;1637}16381639static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_to(struct sljit_compiler *compiler,1640sljit_s32 src, sljit_sw srcw)1641{1642#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1643FUNCTION_CHECK_SRC(src, srcw);1644#endif /* SLJIT_ARGUMENT_CHECKS */1645#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1646if (SLJIT_UNLIKELY(!!compiler->verbose)) {1647fprintf(compiler->verbose, " return_to ");1648sljit_verbose_param(compiler, src, srcw);1649fprintf(compiler->verbose, "\n");1650}1651#endif /* SLJIT_VERBOSE */1652CHECK_RETURN_OK;1653}16541655static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)1656{1657#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1658CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW)1659|| ((op & ~SLJIT_32) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_32) <= SLJIT_DIV_SW)1660|| (op >= SLJIT_MEMORY_BARRIER && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN));1661CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) < SLJIT_LMUL_UW || SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MEMORY_BARRIER || compiler->scratches >= 2);1662if ((SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_LMUL_UW && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN)1663compiler->last_flags = 0;1664#endif /* SLJIT_ARGUMENT_CHECKS */1665#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1666if (SLJIT_UNLIKELY(!!compiler->verbose))1667{1668fprintf(compiler->verbose, " %s", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]);1669if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) {1670fprintf(compiler->verbose, (op & SLJIT_32) ? "32" : "w");1671}1672fprintf(compiler->verbose, "\n");1673}1674#endif /* SLJIT_VERBOSE */1675CHECK_RETURN_OK;1676}16771678static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,1679sljit_s32 dst, sljit_sw dstw,1680sljit_s32 src, sljit_sw srcw)1681{1682if (SLJIT_UNLIKELY(compiler->skip_checks)) {1683compiler->skip_checks = 0;1684CHECK_RETURN_OK;1685}16861687#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1688CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MOV && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_REV_S32);16891690switch (GET_OPCODE(op)) {1691case SLJIT_MOV:1692case SLJIT_MOV_U32:1693case SLJIT_MOV_S32:1694case SLJIT_MOV32:1695case SLJIT_MOV_P:1696case SLJIT_REV_U32:1697case SLJIT_REV_S32:1698/* Nothing allowed */1699CHECK_ARGUMENT(!(op & (SLJIT_32 | ALL_STATUS_FLAGS_MASK)));1700break;1701default:1702/* Only SLJIT_32 is allowed. */1703CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));1704break;1705}17061707FUNCTION_CHECK_DST(dst, dstw);1708FUNCTION_CHECK_SRC(src, srcw);1709#endif /* SLJIT_ARGUMENT_CHECKS */1710#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1711if (SLJIT_UNLIKELY(!!compiler->verbose)) {1712fprintf(compiler->verbose, " %s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE],1713!(op & SLJIT_32) ? "" : "32", op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);17141715sljit_verbose_param(compiler, dst, dstw);1716fprintf(compiler->verbose, ", ");1717sljit_verbose_param(compiler, src, srcw);1718fprintf(compiler->verbose, "\n");1719}1720#endif /* SLJIT_VERBOSE */1721CHECK_RETURN_OK;1722}17231724static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,1725sljit_s32 dst_reg,1726sljit_s32 mem_reg)1727{1728if (SLJIT_UNLIKELY(compiler->skip_checks)) {1729compiler->skip_checks = 0;1730CHECK_RETURN_OK;1731}17321733#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1734CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC));1735CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | ALL_STATUS_FLAGS_MASK) >= SLJIT_MOV1736&& SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | ALL_STATUS_FLAGS_MASK) <= SLJIT_MOV_P);1737CHECK_ARGUMENT((op & (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS)) != (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS));17381739/* All arguments must be valid registers. */1740CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));1741CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(mem_reg) && !CHECK_IF_VIRTUAL_REGISTER(mem_reg));17421743if (GET_OPCODE(op) < SLJIT_MOV_U8 || GET_OPCODE(op) > SLJIT_MOV_S16) {1744/* Nothing allowed. */1745CHECK_ARGUMENT(!(op & SLJIT_32));1746}17471748compiler->last_flags = 0;1749#endif /* SLJIT_ARGUMENT_CHECKS */1750#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1751if (SLJIT_UNLIKELY(!!compiler->verbose)) {1752if (op & SLJIT_ATOMIC_TEST)1753CHECK_RETURN_OK;1754if (sljit_emit_atomic_load(compiler, op | SLJIT_ATOMIC_TEST, dst_reg, mem_reg)) {1755fprintf(compiler->verbose, " # atomic_load: unsupported form, no instructions are emitted\n");1756CHECK_RETURN_OK;1757}17581759fprintf(compiler->verbose, " atomic_load");1760if (op & SLJIT_ATOMIC_USE_CAS)1761fprintf(compiler->verbose, "_cas");1762if (op & SLJIT_ATOMIC_USE_LS)1763fprintf(compiler->verbose, "_ls");17641765fprintf(compiler->verbose, "%s%s ", !(op & SLJIT_32) ? "" : "32",1766op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);1767sljit_verbose_reg(compiler, dst_reg);1768fprintf(compiler->verbose, ", [");1769sljit_verbose_reg(compiler, mem_reg);1770fprintf(compiler->verbose, "]\n");1771}1772#endif /* SLJIT_VERBOSE */1773CHECK_RETURN_OK;1774}17751776static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,1777sljit_s32 src_reg,1778sljit_s32 mem_reg,1779sljit_s32 temp_reg)1780{1781if (SLJIT_UNLIKELY(compiler->skip_checks)) {1782compiler->skip_checks = 0;1783CHECK_RETURN_OK;1784}17851786#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1787CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC));1788CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | SLJIT_SET_Z) >= SLJIT_MOV1789&& SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | SLJIT_SET_Z) <= SLJIT_MOV_P);1790CHECK_ARGUMENT((op & (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS)) != (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS));17911792/* All arguments must be valid registers. */1793CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src_reg));1794CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(mem_reg) && !CHECK_IF_VIRTUAL_REGISTER(mem_reg));1795CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(temp_reg) && (src_reg != temp_reg || (op & SLJIT_ATOMIC_USE_LS)));17961797CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE_MASK(op) == SLJIT_ATOMIC_STORED);17981799if (GET_OPCODE(op) < SLJIT_MOV_U8 || GET_OPCODE(op) > SLJIT_MOV_S16) {1800/* Nothing allowed. */1801CHECK_ARGUMENT(!(op & SLJIT_32));1802}18031804compiler->last_flags = GET_FLAG_TYPE_MASK(op) | (op & SLJIT_32);1805#endif /* SLJIT_ARGUMENT_CHECKS */1806#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1807if (SLJIT_UNLIKELY(!!compiler->verbose)) {1808if (op & SLJIT_ATOMIC_TEST)1809CHECK_RETURN_OK;1810if (sljit_emit_atomic_store(compiler, op | SLJIT_ATOMIC_TEST, src_reg, mem_reg, temp_reg)) {1811fprintf(compiler->verbose, " # atomic_store: unsupported form, no instructions are emitted\n");1812CHECK_RETURN_OK;1813}18141815fprintf(compiler->verbose, " atomic_store");1816if (op & SLJIT_ATOMIC_USE_CAS)1817fprintf(compiler->verbose, "_cas");1818if (op & SLJIT_ATOMIC_USE_LS)1819fprintf(compiler->verbose, "_ls");18201821fprintf(compiler->verbose, "%s%s%s ", !(op & SLJIT_32) ? "" : "32",1822op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & VARIABLE_FLAG_MASK) ? "" : ".stored");1823sljit_verbose_reg(compiler, src_reg);1824fprintf(compiler->verbose, ", [");1825sljit_verbose_reg(compiler, mem_reg);1826fprintf(compiler->verbose, "], ");1827sljit_verbose_reg(compiler, temp_reg);1828fprintf(compiler->verbose, "\n");1829}1830#endif /* SLJIT_VERBOSE */1831CHECK_RETURN_OK;1832}18331834#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)18351836static sljit_s32 check_sljit_emit_op2_operation(struct sljit_compiler *compiler, sljit_s32 op)1837{1838switch (GET_OPCODE(op)) {1839case SLJIT_AND:1840case SLJIT_OR:1841case SLJIT_XOR:1842case SLJIT_SHL:1843case SLJIT_MSHL:1844case SLJIT_LSHR:1845case SLJIT_MLSHR:1846case SLJIT_ASHR:1847case SLJIT_MASHR:1848return !(op & VARIABLE_FLAG_MASK);1849case SLJIT_MUL:1850return !(op & SLJIT_SET_Z) && (!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);1851case SLJIT_ADD:1852return !(op & VARIABLE_FLAG_MASK)1853|| GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)1854|| GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;1855case SLJIT_SUB:1856return !(op & VARIABLE_FLAG_MASK)1857|| (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_OVERFLOW)1858|| GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);1859case SLJIT_ADDC:1860case SLJIT_SUBC:1861return (!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY))1862&& (compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY)1863&& (op & SLJIT_32) == (compiler->last_flags & SLJIT_32);1864break;1865case SLJIT_ROTL:1866case SLJIT_ROTR:1867return !(op & ALL_STATUS_FLAGS_MASK);1868}18691870/* Operation type should be checked earlier. */1871SLJIT_UNREACHABLE();1872return 1;1873}18741875#endif /* SLJIT_ARGUMENT_CHECKS */18761877static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 unset,1878sljit_s32 dst, sljit_sw dstw,1879sljit_s32 src1, sljit_sw src1w,1880sljit_s32 src2, sljit_sw src2w)1881{1882if (SLJIT_UNLIKELY(compiler->skip_checks)) {1883compiler->skip_checks = 0;1884CHECK_RETURN_OK;1885}18861887#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1888CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_ADD && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_ROTR);1889CHECK_ARGUMENT(check_sljit_emit_op2_operation(compiler, op));18901891if (unset) {1892CHECK_ARGUMENT(HAS_FLAGS(op));1893} else {1894FUNCTION_CHECK_DST(dst, dstw);1895}1896FUNCTION_CHECK_SRC(src1, src1w);1897FUNCTION_CHECK_SRC(src2, src2w);1898compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));1899#endif /* SLJIT_ARGUMENT_CHECKS */1900#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1901if (SLJIT_UNLIKELY(!!compiler->verbose)) {1902fprintf(compiler->verbose, " %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",1903!(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",1904!(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);1905if (unset)1906fprintf(compiler->verbose, "unset");1907else1908sljit_verbose_param(compiler, dst, dstw);1909fprintf(compiler->verbose, ", ");1910sljit_verbose_param(compiler, src1, src1w);1911fprintf(compiler->verbose, ", ");1912sljit_verbose_param(compiler, src2, src2w);1913fprintf(compiler->verbose, "\n");1914}1915#endif /* SLJIT_VERBOSE */1916CHECK_RETURN_OK;1917}19181919static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,1920sljit_s32 dst_reg,1921sljit_s32 src1, sljit_sw src1w,1922sljit_s32 src2, sljit_sw src2w)1923{1924#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1925CHECK_ARGUMENT((op | SLJIT_32) == SLJIT_MULADD32);1926CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));1927FUNCTION_CHECK_SRC(src1, src1w);1928FUNCTION_CHECK_SRC(src2, src2w);1929compiler->last_flags = 0;1930#endif /* SLJIT_ARGUMENT_CHECKS */1931#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1932if (SLJIT_UNLIKELY(!!compiler->verbose)) {1933fprintf(compiler->verbose, " %s%s ", op2r_names[GET_OPCODE(op) - SLJIT_OP2R_BASE], !(op & SLJIT_32) ? "" : "32");19341935sljit_verbose_reg(compiler, dst_reg);1936fprintf(compiler->verbose, ", ");1937sljit_verbose_param(compiler, src1, src1w);1938fprintf(compiler->verbose, ", ");1939sljit_verbose_param(compiler, src2, src2w);1940fprintf(compiler->verbose, "\n");1941}1942#endif /* SLJIT_VERBOSE */1943CHECK_RETURN_OK;1944}19451946static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,1947sljit_s32 dst_reg,1948sljit_s32 src1_reg,1949sljit_s32 src2_reg,1950sljit_s32 src3, sljit_sw src3w)1951{1952#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1953CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) == SLJIT_SHL || SLJIT_CHECK_OPCODE(op, 0) == SLJIT_LSHR1954|| SLJIT_CHECK_OPCODE(op, 0) == SLJIT_MSHL || SLJIT_CHECK_OPCODE(op, 0) == SLJIT_MLSHR);1955CHECK_ARGUMENT((op & ~(0xff | SLJIT_32 | SLJIT_SHIFT_INTO_NON_ZERO)) == 0);1956CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));1957CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src1_reg));1958CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src2_reg));1959FUNCTION_CHECK_SRC(src3, src3w);1960CHECK_ARGUMENT(dst_reg != src2_reg);1961#endif /* SLJIT_ARGUMENT_CHECKS */1962#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1963if (SLJIT_UNLIKELY(!!compiler->verbose)) {1964fprintf(compiler->verbose, " %s%s.into%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",1965(op & SLJIT_SHIFT_INTO_NON_ZERO) ? ".nz" : "");19661967sljit_verbose_reg(compiler, dst_reg);1968fprintf(compiler->verbose, ", ");1969sljit_verbose_reg(compiler, src1_reg);1970fprintf(compiler->verbose, ", ");1971sljit_verbose_reg(compiler, src2_reg);1972fprintf(compiler->verbose, ", ");1973sljit_verbose_param(compiler, src3, src3w);1974fprintf(compiler->verbose, "\n");1975}1976#endif /* SLJIT_VERBOSE */1977CHECK_RETURN_OK;1978}19791980static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,1981sljit_s32 dst, sljit_sw dstw,1982sljit_s32 src1, sljit_sw src1w,1983sljit_s32 src2, sljit_sw src2w,1984sljit_sw shift_arg)1985{1986SLJIT_UNUSED_ARG(shift_arg);1987#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)1988CHECK_ARGUMENT((op & ~SLJIT_SRC2_UNDEFINED) == (SLJIT_ADD | SLJIT_SHL_IMM));1989FUNCTION_CHECK_DST(dst, dstw);1990FUNCTION_CHECK_SRC(src1, src1w);1991FUNCTION_CHECK_SRC(src2, src2w);1992compiler->last_flags = 0;1993#endif /* SLJIT_ARGUMENT_CHECKS */1994#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)1995if (SLJIT_UNLIKELY(!!compiler->verbose)) {1996fprintf(compiler->verbose, " %s.shl_imm%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],1997(op & SLJIT_SRC2_UNDEFINED) ? ".src2und" : "");19981999sljit_verbose_param(compiler, dst, dstw);2000fprintf(compiler->verbose, ", ");2001sljit_verbose_param(compiler, src1, src1w);2002fprintf(compiler->verbose, ", ");2003sljit_verbose_param(compiler, src2, src2w);2004fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", shift_arg);2005}2006#endif /* SLJIT_VERBOSE */2007CHECK_RETURN_OK;2008}20092010static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,2011sljit_s32 src, sljit_sw srcw)2012{2013#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2014CHECK_ARGUMENT(op >= SLJIT_FAST_RETURN && op <= SLJIT_PREFETCH_ONCE);2015FUNCTION_CHECK_SRC(src, srcw);20162017if (op == SLJIT_FAST_RETURN || op == SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN) {2018CHECK_ARGUMENT(src != SLJIT_IMM);2019compiler->last_flags = 0;2020} else if (op >= SLJIT_PREFETCH_L1 && op <= SLJIT_PREFETCH_ONCE) {2021CHECK_ARGUMENT(src & SLJIT_MEM);2022}2023#endif /* SLJIT_ARGUMENT_CHECKS */2024#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2025if (SLJIT_UNLIKELY(!!compiler->verbose)) {2026fprintf(compiler->verbose, " %s ", op_src_dst_names[op - SLJIT_OP_SRC_DST_BASE]);2027sljit_verbose_param(compiler, src, srcw);2028fprintf(compiler->verbose, "\n");2029}2030#endif /* SLJIT_VERBOSE */2031CHECK_RETURN_OK;2032}20332034static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,2035sljit_s32 dst, sljit_sw dstw)2036{2037#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2038CHECK_ARGUMENT(op >= SLJIT_FAST_ENTER && op <= SLJIT_GET_RETURN_ADDRESS);2039FUNCTION_CHECK_DST(dst, dstw);20402041if (op == SLJIT_FAST_ENTER)2042compiler->last_flags = 0;2043#endif /* SLJIT_ARGUMENT_CHECKS */2044#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2045if (SLJIT_UNLIKELY(!!compiler->verbose)) {2046fprintf(compiler->verbose, " %s ", op_src_dst_names[op - SLJIT_OP_SRC_DST_BASE]);2047sljit_verbose_param(compiler, dst, dstw);2048fprintf(compiler->verbose, "\n");2049}2050#endif /* SLJIT_VERBOSE */2051CHECK_RETURN_OK;2052}20532054static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 type, sljit_s32 reg)2055{2056SLJIT_UNUSED_ARG(type);2057SLJIT_UNUSED_ARG(reg);2058#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2059if (type == SLJIT_GP_REGISTER) {2060CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_REGISTERS)2061|| (reg >= SLJIT_TMP_REGISTER_BASE && reg < (SLJIT_TMP_REGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_REGISTERS)));2062}2063#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)2064else if (((type >> 12) == 0 || ((type >> 12) >= 3 && (type >> 12) <= 6))) {2065CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_VECTOR_REGISTERS)2066|| (reg >= SLJIT_TMP_VREGISTER_BASE && reg < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS)));2067}2068#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS */2069else {2070CHECK_ARGUMENT(type == SLJIT_FLOAT_REGISTER || ((type >> 12) == 0 || ((type >> 12) >= 3 && (type >> 12) <= 6) || (type & (3 << 12)) || (type & (4 << 12)) || (type & (5 << 12)) || (type & (6 << 12))));2071CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_FLOAT_REGISTERS)2072|| (reg >= SLJIT_TMP_FREGISTER_BASE && reg < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)));2073}2074#endif /* SLJIT_ARGUMENT_CHECKS */2075CHECK_RETURN_OK;2076}20772078static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_compiler *compiler,2079void *instruction, sljit_u32 size)2080{2081#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2082sljit_u32 i;2083#endif /* SLJIT_VERBOSE */20842085SLJIT_UNUSED_ARG(compiler);20862087#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2088CHECK_ARGUMENT(instruction);20892090#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)2091CHECK_ARGUMENT(size > 0 && size < 16);2092#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)2093CHECK_ARGUMENT((size == 2 && (((sljit_sw)instruction) & 0x1) == 0)2094|| (size == 4 && (((sljit_sw)instruction) & 0x3) == 0));2095#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)2096CHECK_ARGUMENT(size == 2 || size == 4 || size == 6);2097#else /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM_THUMB2 && !SLJIT_CONFIG_RISCV && !SLJIT_CONFIG_S390X */2098CHECK_ARGUMENT(size == 4 && (((sljit_sw)instruction) & 0x3) == 0);2099#endif /* SLJIT_CONFIG_X86 */21002101compiler->last_flags = 0;2102#endif /* SLJIT_ARGUMENT_CHECKS */2103#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2104if (SLJIT_UNLIKELY(!!compiler->verbose)) {2105fprintf(compiler->verbose, " op_custom");2106for (i = 0; i < size; i++)2107fprintf(compiler->verbose, " 0x%x", ((sljit_u8*)instruction)[i]);2108fprintf(compiler->verbose, "\n");2109}2110#endif /* SLJIT_VERBOSE */2111CHECK_RETURN_OK;2112}21132114static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,2115sljit_s32 dst, sljit_sw dstw,2116sljit_s32 src, sljit_sw srcw)2117{2118if (SLJIT_UNLIKELY(compiler->skip_checks)) {2119compiler->skip_checks = 0;2120CHECK_RETURN_OK;2121}21222123#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2124CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));2125CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MOV_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_ABS_F64);2126CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));2127FUNCTION_FCHECK(src, srcw, op & SLJIT_32);2128FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);2129#endif /* SLJIT_ARGUMENT_CHECKS */2130#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2131if (SLJIT_UNLIKELY(!!compiler->verbose)) {2132if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)2133fprintf(compiler->verbose, " %s%s ", fop1_names[SLJIT_CONV_F64_FROM_F32 - SLJIT_FOP1_BASE],2134(op & SLJIT_32) ? ".f32.from.f64" : ".f64.from.f32");2135else2136fprintf(compiler->verbose, " %s%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],2137(op & SLJIT_32) ? ".f32" : ".f64");21382139sljit_verbose_fparam(compiler, dst, dstw);2140fprintf(compiler->verbose, ", ");2141sljit_verbose_fparam(compiler, src, srcw);2142fprintf(compiler->verbose, "\n");2143}2144#endif /* SLJIT_VERBOSE */2145CHECK_RETURN_OK;2146}21472148static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,2149sljit_s32 src1, sljit_sw src1w,2150sljit_s32 src2, sljit_sw src2w)2151{2152#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2153compiler->last_flags = GET_FLAG_TYPE(op) | (op & SLJIT_32);2154#endif /* SLJIT_ARGUMENT_CHECKS */21552156if (SLJIT_UNLIKELY(compiler->skip_checks)) {2157compiler->skip_checks = 0;2158CHECK_RETURN_OK;2159}21602161#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2162CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));2163CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) == SLJIT_CMP_F64);2164CHECK_ARGUMENT(!(op & SLJIT_SET_Z));2165CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK)2166|| (GET_FLAG_TYPE(op) >= SLJIT_F_EQUAL && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_LESS_EQUAL));2167FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);2168FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);2169#endif /* SLJIT_ARGUMENT_CHECKS */2170#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2171if (SLJIT_UNLIKELY(!!compiler->verbose)) {2172fprintf(compiler->verbose, " %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_32) ? ".f32" : ".f64");2173if (op & VARIABLE_FLAG_MASK) {2174fprintf(compiler->verbose, ".%s", jump_names[GET_FLAG_TYPE(op)]);2175}2176fprintf(compiler->verbose, " ");2177sljit_verbose_fparam(compiler, src1, src1w);2178fprintf(compiler->verbose, ", ");2179sljit_verbose_fparam(compiler, src2, src2w);2180fprintf(compiler->verbose, "\n");2181}2182#endif /* SLJIT_VERBOSE */2183CHECK_RETURN_OK;2184}21852186static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,2187sljit_s32 dst, sljit_sw dstw,2188sljit_s32 src, sljit_sw srcw)2189{2190if (SLJIT_UNLIKELY(compiler->skip_checks)) {2191compiler->skip_checks = 0;2192CHECK_RETURN_OK;2193}21942195#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2196CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));2197CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));2198FUNCTION_FCHECK(src, srcw, op & SLJIT_32);2199FUNCTION_CHECK_DST(dst, dstw);2200#endif /* SLJIT_ARGUMENT_CHECKS */2201#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2202if (SLJIT_UNLIKELY(!!compiler->verbose)) {2203fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],2204fop1_conv_types[GET_OPCODE(op) - SLJIT_CONV_SW_FROM_F64],2205(op & SLJIT_32) ? ".f32" : ".f64");2206sljit_verbose_param(compiler, dst, dstw);2207fprintf(compiler->verbose, ", ");2208sljit_verbose_fparam(compiler, src, srcw);2209fprintf(compiler->verbose, "\n");2210}2211#endif /* SLJIT_VERBOSE */2212CHECK_RETURN_OK;2213}22142215static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_s32 op,2216sljit_s32 dst, sljit_sw dstw,2217sljit_s32 src, sljit_sw srcw)2218{2219if (SLJIT_UNLIKELY(compiler->skip_checks)) {2220compiler->skip_checks = 0;2221CHECK_RETURN_OK;2222}22232224#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2225CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));2226CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));2227FUNCTION_CHECK_SRC(src, srcw);2228FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);2229#endif /* SLJIT_ARGUMENT_CHECKS */2230#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2231if (SLJIT_UNLIKELY(!!compiler->verbose)) {2232fprintf(compiler->verbose, " %s%s.from.%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],2233(op & SLJIT_32) ? ".f32" : ".f64",2234fop1_conv_types[GET_OPCODE(op) - SLJIT_CONV_SW_FROM_F64]);2235sljit_verbose_fparam(compiler, dst, dstw);2236fprintf(compiler->verbose, ", ");2237sljit_verbose_param(compiler, src, srcw);2238fprintf(compiler->verbose, "\n");2239}2240#endif /* SLJIT_VERBOSE */2241CHECK_RETURN_OK;2242}22432244static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,2245sljit_s32 dst, sljit_sw dstw,2246sljit_s32 src1, sljit_sw src1w,2247sljit_s32 src2, sljit_sw src2w)2248{2249if (SLJIT_UNLIKELY(compiler->skip_checks)) {2250compiler->skip_checks = 0;2251CHECK_RETURN_OK;2252}22532254#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2255CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));2256CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_ADD_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_DIV_F64);2257CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));2258FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);2259FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);2260FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);2261#endif /* SLJIT_ARGUMENT_CHECKS */2262#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2263if (SLJIT_UNLIKELY(!!compiler->verbose)) {2264fprintf(compiler->verbose, " %s%s ", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE], (op & SLJIT_32) ? ".f32" : ".f64");2265sljit_verbose_fparam(compiler, dst, dstw);2266fprintf(compiler->verbose, ", ");2267sljit_verbose_fparam(compiler, src1, src1w);2268fprintf(compiler->verbose, ", ");2269sljit_verbose_fparam(compiler, src2, src2w);2270fprintf(compiler->verbose, "\n");2271}2272#endif /* SLJIT_VERBOSE */2273CHECK_RETURN_OK;2274}22752276static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,2277sljit_s32 dst_freg,2278sljit_s32 src1, sljit_sw src1w,2279sljit_s32 src2, sljit_sw src2w)2280{2281#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2282CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));2283CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) == SLJIT_COPYSIGN_F64);2284FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);2285FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);2286CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, op & SLJIT_32));2287#endif /* SLJIT_ARGUMENT_CHECKS */2288#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2289if (SLJIT_UNLIKELY(!!compiler->verbose)) {2290fprintf(compiler->verbose, " %s%s ", fop2r_names[GET_OPCODE(op) - SLJIT_FOP2R_BASE], (op & SLJIT_32) ? ".f32" : ".f64");2291sljit_verbose_freg(compiler, dst_freg);2292fprintf(compiler->verbose, ", ");2293sljit_verbose_fparam(compiler, src1, src1w);2294fprintf(compiler->verbose, ", ");2295sljit_verbose_fparam(compiler, src2, src2w);2296fprintf(compiler->verbose, "\n");2297}2298#endif /* SLJIT_VERBOSE */2299CHECK_RETURN_OK;2300}23012302static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fset32(struct sljit_compiler *compiler,2303sljit_s32 freg, sljit_f32 value)2304{2305SLJIT_UNUSED_ARG(value);23062307if (SLJIT_UNLIKELY(compiler->skip_checks)) {2308compiler->skip_checks = 0;2309CHECK_RETURN_OK;2310}23112312#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2313CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));2314CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 1));2315#endif /* SLJIT_ARGUMENT_CHECKS */2316#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2317if (SLJIT_UNLIKELY(!!compiler->verbose)) {2318fprintf(compiler->verbose, " fset32 ");2319sljit_verbose_freg(compiler, freg);2320fprintf(compiler->verbose, ", %f\n", value);2321}2322#endif /* SLJIT_VERBOSE */2323CHECK_RETURN_OK;2324}23252326static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fset64(struct sljit_compiler *compiler,2327sljit_s32 freg, sljit_f64 value)2328{2329SLJIT_UNUSED_ARG(value);23302331if (SLJIT_UNLIKELY(compiler->skip_checks)) {2332compiler->skip_checks = 0;2333CHECK_RETURN_OK;2334}23352336#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2337CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));2338CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));2339#endif /* SLJIT_ARGUMENT_CHECKS */2340#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2341if (SLJIT_UNLIKELY(!!compiler->verbose)) {2342fprintf(compiler->verbose, " fset64 ");2343sljit_verbose_freg(compiler, freg);2344fprintf(compiler->verbose, ", %f\n", value);2345}2346#endif /* SLJIT_VERBOSE */2347CHECK_RETURN_OK;2348}23492350static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,2351sljit_s32 freg, sljit_s32 reg)2352{2353#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2354CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));2355CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_COPY_TO_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_COPY_FROM_F64);2356CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));2357CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, op & SLJIT_32));23582359#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)2360CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));2361#else /* !SLJIT_64BIT_ARCHITECTURE */2362switch (op) {2363case SLJIT_COPY32_TO_F32:2364case SLJIT_COPY32_FROM_F32:2365CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));2366break;2367case SLJIT_COPY_TO_F64:2368case SLJIT_COPY_FROM_F64:2369if (reg & REG_PAIR_MASK) {2370CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_FIRST(reg)));2371CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_SECOND(reg)));23722373if (op == SLJIT_COPY_TO_F64)2374break;23752376CHECK_ARGUMENT(REG_PAIR_FIRST(reg) != REG_PAIR_SECOND(reg));2377break;2378}23792380CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));2381break;2382}2383#endif /* SLJIT_64BIT_ARCHITECTURE */2384#endif /* SLJIT_ARGUMENT_CHECKS */2385#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2386if (SLJIT_UNLIKELY(!!compiler->verbose)) {2387fprintf(compiler->verbose, " copy%s_%s_f%s ", (op & SLJIT_32) ? "32" : "",2388GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? "to" : "from", (op & SLJIT_32) ? "32" : "64");23892390sljit_verbose_freg(compiler, freg);23912392if (reg & REG_PAIR_MASK) {2393fprintf(compiler->verbose, ", {");2394sljit_verbose_reg(compiler, REG_PAIR_FIRST(reg));2395fprintf(compiler->verbose, ", ");2396sljit_verbose_reg(compiler, REG_PAIR_SECOND(reg));2397fprintf(compiler->verbose, "}\n");2398} else {2399fprintf(compiler->verbose, ", ");2400sljit_verbose_reg(compiler, reg);2401fprintf(compiler->verbose, "\n");2402}2403}2404#endif /* SLJIT_VERBOSE */2405CHECK_RETURN_OK;2406}24072408static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compiler *compiler)2409{2410SLJIT_UNUSED_ARG(compiler);24112412if (SLJIT_UNLIKELY(compiler->skip_checks)) {2413compiler->skip_checks = 0;2414CHECK_RETURN_OK;2415}24162417#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2418compiler->last_flags = 0;2419#endif /* SLJIT_ARGUMENT_CHECKS */24202421#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2422if (SLJIT_UNLIKELY(!!compiler->verbose))2423fprintf(compiler->verbose, "label:\n");2424#endif /* SLJIT_VERBOSE */2425CHECK_RETURN_OK;2426}24272428static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_aligned_label(struct sljit_compiler *compiler,2429sljit_s32 alignment, struct sljit_read_only_buffer *buffers)2430{2431SLJIT_UNUSED_ARG(compiler);2432SLJIT_UNUSED_ARG(buffers);24332434#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2435CHECK_ARGUMENT(alignment >= SLJIT_LABEL_ALIGN_1 && alignment <= SLJIT_LABEL_ALIGN_16);2436compiler->last_flags = 0;2437#endif /* SLJIT_ARGUMENT_CHECKS */24382439#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2440if (SLJIT_UNLIKELY(!!compiler->verbose)) {2441fprintf(compiler->verbose, "label.al%d:%s", 1 << alignment, buffers == NULL ? "\n" : " [");24422443if (buffers != NULL) {2444fprintf(compiler->verbose, "%ld", (long int)buffers->size);2445buffers = buffers->next;24462447while (buffers != NULL) {2448fprintf(compiler->verbose, ", %ld", (long int)buffers->size);2449buffers = buffers->next;2450}24512452fprintf(compiler->verbose, "]\n");2453}2454}2455#endif /* SLJIT_VERBOSE */2456CHECK_RETURN_OK;2457}24582459#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2460#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \2461|| (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)2462#define CHECK_UNORDERED(type, last_flags) \2463((((type) & 0xfe) == SLJIT_ORDERED) && \2464((last_flags) & 0xff) >= SLJIT_UNORDERED && ((last_flags) & 0xff) <= SLJIT_ORDERED_LESS_EQUAL)2465#else /* !SLJIT_CONFIG_X86 || SLJIT_CONFIG_ARM */2466#define CHECK_UNORDERED(type, last_flags) 02467#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_ARM */2468#endif /* SLJIT_ARGUMENT_CHECKS */24692470static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)2471{2472if (SLJIT_UNLIKELY(compiler->skip_checks)) {2473compiler->skip_checks = 0;2474CHECK_RETURN_OK;2475}24762477#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2478CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP)));2479CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_FAST_CALL);24802481if ((type & 0xff) < SLJIT_JUMP) {2482if ((type & 0xff) <= SLJIT_NOT_ZERO)2483CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);2484else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {2485CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);2486compiler->last_flags = 0;2487} else2488CHECK_ARGUMENT((type & 0xfe) == (compiler->last_flags & 0xff)2489|| CHECK_UNORDERED(type, compiler->last_flags));2490}2491#endif /* SLJIT_ARGUMENT_CHECKS */2492#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2493if (SLJIT_UNLIKELY(!!compiler->verbose))2494fprintf(compiler->verbose, " jump%s %s\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",2495jump_names[type & 0xff]);2496#endif /* SLJIT_VERBOSE */2497CHECK_RETURN_OK;2498}24992500static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,2501sljit_s32 arg_types)2502{2503#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2504CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_CALL_RETURN)));2505CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG);2506CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));25072508if (type & SLJIT_CALL_RETURN) {2509CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);25102511if (compiler->options & SLJIT_ENTER_REG_ARG) {2512CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG);2513} else {2514CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG);2515}2516}2517#endif /* SLJIT_ARGUMENT_CHECKS */2518#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2519if (SLJIT_UNLIKELY(!!compiler->verbose)) {2520fprintf(compiler->verbose, " %s%s%s ret[%s", jump_names[type & 0xff],2521!(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",2522!(type & SLJIT_CALL_RETURN) ? "" : ".ret",2523call_arg_names[arg_types & SLJIT_ARG_MASK]);25242525arg_types >>= SLJIT_ARG_SHIFT;2526if (arg_types) {2527fprintf(compiler->verbose, "], args[");2528do {2529fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);2530arg_types >>= SLJIT_ARG_SHIFT;2531if (arg_types)2532fprintf(compiler->verbose, ",");2533} while (arg_types);2534}2535fprintf(compiler->verbose, "]\n");2536}2537#endif /* SLJIT_VERBOSE */2538CHECK_RETURN_OK;2539}25402541static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,2542sljit_s32 src1, sljit_sw src1w,2543sljit_s32 src2, sljit_sw src2w)2544{2545if (SLJIT_UNLIKELY(compiler->skip_checks)) {2546compiler->skip_checks = 0;2547CHECK_RETURN_OK;2548}25492550#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2551CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));2552CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_SIG_LESS_EQUAL);2553FUNCTION_CHECK_SRC(src1, src1w);2554FUNCTION_CHECK_SRC(src2, src2w);2555compiler->last_flags = 0;2556#endif /* SLJIT_ARGUMENT_CHECKS */2557#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2558if (SLJIT_UNLIKELY(!!compiler->verbose)) {2559fprintf(compiler->verbose, " cmp%s%s %s, ", (type & SLJIT_32) ? "32" : "",2560!(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);2561sljit_verbose_param(compiler, src1, src1w);2562fprintf(compiler->verbose, ", ");2563sljit_verbose_param(compiler, src2, src2w);2564fprintf(compiler->verbose, "\n");2565}2566#endif /* SLJIT_VERBOSE */2567CHECK_RETURN_OK;2568}25692570static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,2571sljit_s32 src1, sljit_sw src1w,2572sljit_s32 src2, sljit_sw src2w)2573{2574#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2575CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));2576CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));2577CHECK_ARGUMENT((type & 0xff) >= SLJIT_F_EQUAL && (type & 0xff) <= SLJIT_ORDERED_LESS_EQUAL);2578FUNCTION_FCHECK(src1, src1w, type & SLJIT_32);2579FUNCTION_FCHECK(src2, src2w, type & SLJIT_32);2580compiler->last_flags = 0;2581#endif /* SLJIT_ARGUMENT_CHECKS */2582#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2583if (SLJIT_UNLIKELY(!!compiler->verbose)) {2584fprintf(compiler->verbose, " fcmp%s%s %s, ", (type & SLJIT_32) ? ".f32" : ".f64",2585!(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);2586sljit_verbose_fparam(compiler, src1, src1w);2587fprintf(compiler->verbose, ", ");2588sljit_verbose_fparam(compiler, src2, src2w);2589fprintf(compiler->verbose, "\n");2590}2591#endif /* SLJIT_VERBOSE */2592CHECK_RETURN_OK;2593}25942595static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2cmpz(struct sljit_compiler *compiler, sljit_s32 op,2596sljit_s32 dst, sljit_sw dstw,2597sljit_s32 src1, sljit_sw src1w,2598sljit_s32 src2, sljit_sw src2w)2599{2600SLJIT_COMPILE_ASSERT((SLJIT_JUMP_IF_ZERO == SLJIT_SET_Z) && (SLJIT_JUMP_IF_NON_ZERO == 0),2601incorrect_values_for_sljit_jump_zero_or_non_zero);26022603#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2604CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, SLJIT_REWRITABLE_JUMP) >= SLJIT_ADD && SLJIT_CHECK_OPCODE(op, SLJIT_REWRITABLE_JUMP) <= SLJIT_ROTR);2605/* Not all opcodes allow setting zero flags. */2606CHECK_ARGUMENT(check_sljit_emit_op2_operation(compiler, ((op | SLJIT_SET_Z) & ~SLJIT_REWRITABLE_JUMP)));2607FUNCTION_CHECK_DST(dst, dstw);2608FUNCTION_CHECK_SRC(src1, src1w);2609FUNCTION_CHECK_SRC(src2, src2w);2610compiler->last_flags = GET_FLAG_TYPE(op) | (op & SLJIT_32);2611#endif /* SLJIT_ARGUMENT_CHECKS */2612#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2613if (SLJIT_UNLIKELY(!!compiler->verbose)) {2614fprintf(compiler->verbose, " cmp%sz.%s%s%s%s%s ", (op & SLJIT_JUMP_IF_ZERO) ? "" : "n",2615op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",2616!(op & VARIABLE_FLAG_MASK) ? "" : ".", !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op & ~SLJIT_REWRITABLE_JUMP)],2617!(op & SLJIT_REWRITABLE_JUMP) ? "" : ".r");2618sljit_verbose_param(compiler, dst, dstw);2619fprintf(compiler->verbose, ", ");2620sljit_verbose_param(compiler, src1, src1w);2621fprintf(compiler->verbose, ", ");2622sljit_verbose_param(compiler, src2, src2w);2623fprintf(compiler->verbose, "\n");2624}2625#endif /* SLJIT_VERBOSE */2626CHECK_RETURN_OK;2627}26282629static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type,2630sljit_s32 src, sljit_sw srcw)2631{2632if (SLJIT_UNLIKELY(compiler->skip_checks)) {2633compiler->skip_checks = 0;2634CHECK_RETURN_OK;2635}26362637#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2638CHECK_ARGUMENT(type >= SLJIT_JUMP && type <= SLJIT_FAST_CALL);2639FUNCTION_CHECK_SRC(src, srcw);2640#endif /* SLJIT_ARGUMENT_CHECKS */2641#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2642if (SLJIT_UNLIKELY(!!compiler->verbose)) {2643fprintf(compiler->verbose, " ijump.%s ", jump_names[type]);2644sljit_verbose_param(compiler, src, srcw);2645fprintf(compiler->verbose, "\n");2646}2647#endif /* SLJIT_VERBOSE */2648CHECK_RETURN_OK;2649}26502651static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,2652sljit_s32 arg_types,2653sljit_s32 src, sljit_sw srcw)2654{2655#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2656CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_CALL_RETURN)));2657CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG);2658CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));2659FUNCTION_CHECK_SRC(src, srcw);26602661if (type & SLJIT_CALL_RETURN) {2662CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);26632664if (compiler->options & SLJIT_ENTER_REG_ARG) {2665CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG);2666} else {2667CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG);2668}2669}2670#endif /* SLJIT_ARGUMENT_CHECKS */2671#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2672if (SLJIT_UNLIKELY(!!compiler->verbose)) {2673fprintf(compiler->verbose, " i%s%s ret[%s", jump_names[type & 0xff],2674!(type & SLJIT_CALL_RETURN) ? "" : ".ret",2675call_arg_names[arg_types & SLJIT_ARG_MASK]);26762677arg_types >>= SLJIT_ARG_SHIFT;2678if (arg_types) {2679fprintf(compiler->verbose, "], args[");2680do {2681fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);2682arg_types >>= SLJIT_ARG_SHIFT;2683if (arg_types)2684fprintf(compiler->verbose, ",");2685} while (arg_types);2686}2687fprintf(compiler->verbose, "], ");2688sljit_verbose_param(compiler, src, srcw);2689fprintf(compiler->verbose, "\n");2690}2691#endif /* SLJIT_VERBOSE */2692CHECK_RETURN_OK;2693}26942695static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,2696sljit_s32 dst, sljit_sw dstw,2697sljit_s32 type)2698{2699#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2700CHECK_ARGUMENT(type >= SLJIT_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL);2701CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV322702|| (SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_AND && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_XOR));2703CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));27042705if (type <= SLJIT_NOT_ZERO)2706CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);2707else2708CHECK_ARGUMENT((type & 0xfe) == (compiler->last_flags & 0xff)2709|| CHECK_UNORDERED(type, compiler->last_flags));27102711FUNCTION_CHECK_DST(dst, dstw);27122713if (GET_OPCODE(op) >= SLJIT_ADD)2714compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));2715#endif /* SLJIT_ARGUMENT_CHECKS */2716#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2717if (SLJIT_UNLIKELY(!!compiler->verbose)) {2718fprintf(compiler->verbose, " flags.%s%s%s ",2719GET_OPCODE(op) < SLJIT_OP2_BASE ? "mov" : op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],2720GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_32) ? "32" : ""),2721!(op & SLJIT_SET_Z) ? "" : ".z");2722sljit_verbose_param(compiler, dst, dstw);2723fprintf(compiler->verbose, ", %s\n", jump_names[type]);2724}2725#endif /* SLJIT_VERBOSE */2726CHECK_RETURN_OK;2727}27282729static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,2730sljit_s32 dst_reg,2731sljit_s32 src1, sljit_sw src1w,2732sljit_s32 src2_reg)2733{2734#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2735sljit_s32 cond = type & ~(SLJIT_32 | SLJIT_COMPARE_SELECT);2736CHECK_ARGUMENT((type & SLJIT_COMPARE_SELECT) ? (cond >= SLJIT_LESS && cond <= SLJIT_SET_SIG_LESS_EQUAL)2737: (cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL));2738CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1);2739CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));2740FUNCTION_CHECK_SRC(src1, src1w);2741CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src2_reg));27422743if (!(type & SLJIT_COMPARE_SELECT)) {2744if (cond <= SLJIT_NOT_ZERO)2745CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);2746else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {2747CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);2748compiler->last_flags = 0;2749} else2750CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff)2751|| CHECK_UNORDERED(cond, compiler->last_flags));2752} else2753compiler->last_flags = 0;2754#endif /* SLJIT_ARGUMENT_CHECKS */2755#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2756if (SLJIT_UNLIKELY(!!compiler->verbose)) {2757fprintf(compiler->verbose, " %sselect%s %s, ",2758!(type & SLJIT_COMPARE_SELECT) ? "" : "cmp_",2759!(type & SLJIT_32) ? "" : "32",2760jump_names[type & ~SLJIT_32]);2761sljit_verbose_reg(compiler, dst_reg);2762fprintf(compiler->verbose, ", ");2763sljit_verbose_param(compiler, src1, src1w);2764fprintf(compiler->verbose, ", ");2765sljit_verbose_reg(compiler, src2_reg);2766fprintf(compiler->verbose, "\n");2767}2768#endif /* SLJIT_VERBOSE */2769CHECK_RETURN_OK;2770}27712772static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,2773sljit_s32 dst_freg,2774sljit_s32 src1, sljit_sw src1w,2775sljit_s32 src2_freg)2776{2777#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2778sljit_s32 cond = type & ~SLJIT_32;27792780CHECK_ARGUMENT(cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL);27812782CHECK_ARGUMENT(compiler->fscratches != -1 && compiler->fsaveds != -1);2783CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, type & SLJIT_32));2784FUNCTION_FCHECK(src1, src1w, type & SLJIT_32);2785CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src2_freg, type & SLJIT_32));27862787if (cond <= SLJIT_NOT_ZERO)2788CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);2789else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {2790CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);2791compiler->last_flags = 0;2792} else2793CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff)2794|| CHECK_UNORDERED(cond, compiler->last_flags));2795#endif /* SLJIT_ARGUMENT_CHECKS */2796#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2797if (SLJIT_UNLIKELY(!!compiler->verbose)) {2798fprintf(compiler->verbose, " fselect%s %s, ",2799!(type & SLJIT_32) ? "" : "32",2800jump_names[type & ~SLJIT_32]);2801sljit_verbose_freg(compiler, dst_freg);2802fprintf(compiler->verbose, ", ");2803sljit_verbose_fparam(compiler, src1, src1w);2804fprintf(compiler->verbose, ", ");2805sljit_verbose_freg(compiler, src2_freg);2806fprintf(compiler->verbose, "\n");2807}2808#endif /* SLJIT_VERBOSE */2809CHECK_RETURN_OK;2810}28112812static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,2813sljit_s32 reg,2814sljit_s32 mem, sljit_sw memw)2815{2816#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2817sljit_s32 allowed_flags;2818#endif /* SLJIT_ARGUMENT_CHECKS */28192820if (SLJIT_UNLIKELY(compiler->skip_checks)) {2821compiler->skip_checks = 0;2822CHECK_RETURN_OK;2823}28242825#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2826if (type & SLJIT_MEM_UNALIGNED) {2827CHECK_ARGUMENT(!(type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)));2828} else if (type & SLJIT_MEM_ALIGNED_16) {2829CHECK_ARGUMENT(!(type & SLJIT_MEM_ALIGNED_32));2830} else {2831CHECK_ARGUMENT((reg & REG_PAIR_MASK) || (type & SLJIT_MEM_ALIGNED_32));2832}28332834allowed_flags = SLJIT_MEM_UNALIGNED;28352836switch (type & 0xff) {2837case SLJIT_MOV_P:2838case SLJIT_MOV:2839allowed_flags |= SLJIT_MEM_ALIGNED_32;2840SLJIT_FALLTHROUGH2841case SLJIT_MOV_U32:2842case SLJIT_MOV_S32:2843case SLJIT_MOV32:2844allowed_flags |= SLJIT_MEM_ALIGNED_16;2845break;2846}28472848CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | allowed_flags)) == 0);28492850if (reg & REG_PAIR_MASK) {2851CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV);2852CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_FIRST(reg)));2853CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_SECOND(reg)));2854CHECK_ARGUMENT(REG_PAIR_FIRST(reg) != REG_PAIR_SECOND(reg));2855} else {2856CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);2857CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) >= SLJIT_MOV_U8 && (type & 0xff) <= SLJIT_MOV_S16));2858CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));2859}28602861FUNCTION_CHECK_SRC_MEM(mem, memw);2862#endif /* SLJIT_ARGUMENT_CHECKS */2863#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2864if (SLJIT_UNLIKELY(!!compiler->verbose)) {2865if ((type & 0xff) == SLJIT_MOV32)2866fprintf(compiler->verbose, " %s32",2867(type & SLJIT_MEM_STORE) ? "store" : "load");2868else2869fprintf(compiler->verbose, " %s%s%s",2870(type & SLJIT_MEM_STORE) ? "store" : "load",2871!(type & SLJIT_32) ? "" : "32", op1_types[(type & 0xff) - SLJIT_OP1_BASE]);28722873if (type & SLJIT_MEM_UNALIGNED)2874fprintf(compiler->verbose, ".unal");2875else if (type & SLJIT_MEM_ALIGNED_16)2876fprintf(compiler->verbose, ".al16");2877else if (type & SLJIT_MEM_ALIGNED_32)2878fprintf(compiler->verbose, ".al32");28792880if (reg & REG_PAIR_MASK) {2881fprintf(compiler->verbose, " {");2882sljit_verbose_reg(compiler, REG_PAIR_FIRST(reg));2883fprintf(compiler->verbose, ", ");2884sljit_verbose_reg(compiler, REG_PAIR_SECOND(reg));2885fprintf(compiler->verbose, "}, ");2886} else {2887fprintf(compiler->verbose, " ");2888sljit_verbose_reg(compiler, reg);2889fprintf(compiler->verbose, ", ");2890}2891sljit_verbose_param(compiler, mem, memw);2892fprintf(compiler->verbose, "\n");2893}2894#endif /* SLJIT_VERBOSE */2895CHECK_RETURN_OK;2896}28972898static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,2899sljit_s32 reg,2900sljit_s32 mem, sljit_sw memw)2901{2902if (SLJIT_UNLIKELY(compiler->skip_checks)) {2903compiler->skip_checks = 0;2904CHECK_RETURN_OK;2905}29062907#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2908CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);2909CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0);2910CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg);29112912FUNCTION_CHECK_SRC_MEM(mem, memw);2913#endif /* SLJIT_ARGUMENT_CHECKS */2914#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2915if (SLJIT_UNLIKELY(!!compiler->verbose)) {2916if (type & SLJIT_MEM_SUPP)2917CHECK_RETURN_OK;2918if (sljit_emit_mem_update(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED) {2919fprintf(compiler->verbose, " # mem: unsupported form, no instructions are emitted\n");2920CHECK_RETURN_OK;2921}29222923if ((type & 0xff) == SLJIT_MOV32)2924fprintf(compiler->verbose, " %s32.%s ",2925(type & SLJIT_MEM_STORE) ? "store" : "load",2926(type & SLJIT_MEM_POST) ? "post" : "pre");2927else2928fprintf(compiler->verbose, " %s%s%s.%s ",2929(type & SLJIT_MEM_STORE) ? "store" : "load",2930!(type & SLJIT_32) ? "" : "32",2931op1_types[(type & 0xff) - SLJIT_OP1_BASE],2932(type & SLJIT_MEM_POST) ? "post" : "pre");29332934sljit_verbose_reg(compiler, reg);2935fprintf(compiler->verbose, ", ");2936sljit_verbose_param(compiler, mem, memw);2937fprintf(compiler->verbose, "\n");2938}2939#endif /* SLJIT_VERBOSE */2940CHECK_RETURN_OK;2941}29422943static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,2944sljit_s32 freg,2945sljit_s32 mem, sljit_sw memw)2946{2947#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2948CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));2949CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);29502951if (type & SLJIT_MEM_UNALIGNED) {2952CHECK_ARGUMENT(!(type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)));2953} else if (type & SLJIT_MEM_ALIGNED_16) {2954CHECK_ARGUMENT(!(type & SLJIT_MEM_ALIGNED_32));2955} else {2956CHECK_ARGUMENT(type & SLJIT_MEM_ALIGNED_32);2957CHECK_ARGUMENT(!(type & SLJIT_32));2958}29592960CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)));2961CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, type & SLJIT_32));2962FUNCTION_CHECK_SRC_MEM(mem, memw);2963#endif /* SLJIT_ARGUMENT_CHECKS */2964#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2965if (SLJIT_UNLIKELY(!!compiler->verbose)) {2966fprintf(compiler->verbose, " %s.%s",2967(type & SLJIT_MEM_STORE) ? "store" : "load",2968!(type & SLJIT_32) ? "f64" : "f32");29692970if (type & SLJIT_MEM_UNALIGNED)2971printf(".unal");2972else if (type & SLJIT_MEM_ALIGNED_16)2973printf(".al16");2974else if (type & SLJIT_MEM_ALIGNED_32)2975printf(".al32");29762977fprintf(compiler->verbose, " ");2978sljit_verbose_freg(compiler, freg);2979fprintf(compiler->verbose, ", ");2980sljit_verbose_param(compiler, mem, memw);2981fprintf(compiler->verbose, "\n");2982}2983#endif /* SLJIT_VERBOSE */2984CHECK_RETURN_OK;2985}29862987static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,2988sljit_s32 freg,2989sljit_s32 mem, sljit_sw memw)2990{2991#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)2992CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));2993CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);2994CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0);2995FUNCTION_CHECK_SRC_MEM(mem, memw);2996CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, type & SLJIT_32));2997#endif /* SLJIT_ARGUMENT_CHECKS */2998#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)2999if (SLJIT_UNLIKELY(!!compiler->verbose)) {3000if (type & SLJIT_MEM_SUPP)3001CHECK_RETURN_OK;3002if (sljit_emit_fmem_update(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED) {3003fprintf(compiler->verbose, " # fmem: unsupported form, no instructions are emitted\n");3004CHECK_RETURN_OK;3005}30063007fprintf(compiler->verbose, " %s.%s.%s ",3008(type & SLJIT_MEM_STORE) ? "store" : "load",3009!(type & SLJIT_32) ? "f64" : "f32",3010(type & SLJIT_MEM_POST) ? "post" : "pre");30113012sljit_verbose_freg(compiler, freg);3013fprintf(compiler->verbose, ", ");3014sljit_verbose_param(compiler, mem, memw);3015fprintf(compiler->verbose, "\n");3016}3017#endif /* SLJIT_VERBOSE */3018CHECK_RETURN_OK;3019}30203021static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,3022sljit_s32 vreg,3023sljit_s32 srcdst, sljit_sw srcdstw)3024{3025#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)3026CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));3027CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(SLJIT_SIMD_STORE)) == 0);3028CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));3029CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) <= SLJIT_SIMD_GET_REG_SIZE(type));3030CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) <= (srcdst & SLJIT_MEM) ? SLJIT_SIMD_GET_REG_SIZE(type) : 0);3031CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type));3032FUNCTION_VCHECK(srcdst, srcdstw, type);3033#endif /* SLJIT_ARGUMENT_CHECKS */3034#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)3035if (SLJIT_UNLIKELY(!!compiler->verbose)) {3036if (type & SLJIT_SIMD_TEST)3037CHECK_RETURN_OK;3038if (sljit_emit_simd_mov(compiler, type | SLJIT_SIMD_TEST, vreg, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) {3039fprintf(compiler->verbose, " # simd_mem: unsupported form, no instructions are emitted\n");3040CHECK_RETURN_OK;3041}30423043fprintf(compiler->verbose, " simd_%s.%d.%s%d",3044(type & SLJIT_SIMD_STORE) ? "store" : "load",3045(8 << SLJIT_SIMD_GET_REG_SIZE(type)),3046(type & SLJIT_SIMD_FLOAT) ? "f" : "",3047(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));30483049if ((type & 0x3f000000) == SLJIT_SIMD_MEM_UNALIGNED)3050fprintf(compiler->verbose, ".unal ");3051else3052fprintf(compiler->verbose, ".al%d ", (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type)));30533054sljit_verbose_vreg(compiler, vreg);3055fprintf(compiler->verbose, ", ");3056sljit_verbose_vparam(compiler, srcdst, srcdstw);3057fprintf(compiler->verbose, "\n");3058}3059#endif /* SLJIT_VERBOSE */3060CHECK_RETURN_OK;3061}30623063static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,3064sljit_s32 vreg,3065sljit_s32 src, sljit_sw srcw)3066{3067#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)3068CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));3069CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) == 0);3070CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));3071CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));3072CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type));30733074if (type & SLJIT_SIMD_FLOAT) {3075if (src == SLJIT_IMM) {3076CHECK_ARGUMENT(srcw == 0);3077} else {3078FUNCTION_FCHECK(src, srcw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2);3079}3080} else if (src != SLJIT_IMM) {3081FUNCTION_CHECK_DST(src, srcw);3082}3083#endif /* SLJIT_ARGUMENT_CHECKS */3084#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)3085if (SLJIT_UNLIKELY(!!compiler->verbose)) {3086if (type & SLJIT_SIMD_TEST)3087CHECK_RETURN_OK;3088if (sljit_emit_simd_replicate(compiler, type | SLJIT_SIMD_TEST, vreg, src, srcw) == SLJIT_ERR_UNSUPPORTED) {3089fprintf(compiler->verbose, " # simd_dup: unsupported form, no instructions are emitted\n");3090CHECK_RETURN_OK;3091}30923093fprintf(compiler->verbose, " simd_replicate.%d.%s%d ",3094(8 << SLJIT_SIMD_GET_REG_SIZE(type)),3095(type & SLJIT_SIMD_FLOAT) ? "f" : "",3096(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));30973098sljit_verbose_vreg(compiler, vreg);3099fprintf(compiler->verbose, ", ");3100if (type & SLJIT_SIMD_FLOAT)3101sljit_verbose_fparam(compiler, src, srcw);3102else3103sljit_verbose_param(compiler, src, srcw);3104fprintf(compiler->verbose, "\n");3105}3106#endif /* SLJIT_VERBOSE */3107CHECK_RETURN_OK;3108}31093110static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,3111sljit_s32 vreg, sljit_s32 lane_index,3112sljit_s32 srcdst, sljit_sw srcdstw)3113{3114#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)3115CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));3116CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO | SLJIT_SIMD_LANE_SIGNED | SLJIT_32)) == 0);3117CHECK_ARGUMENT((type & (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO)) != (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO));3118CHECK_ARGUMENT((type & (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_SIGNED)) != SLJIT_SIMD_LANE_SIGNED);3119CHECK_ARGUMENT(!(type & SLJIT_SIMD_FLOAT) || !(type & (SLJIT_SIMD_LANE_SIGNED | SLJIT_32)));3120CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));3121CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));3122CHECK_ARGUMENT(!(type & SLJIT_32) || SLJIT_SIMD_GET_ELEM_SIZE(type) <= 2);3123CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type));3124CHECK_ARGUMENT(lane_index >= 0 && lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type))));31253126if (type & SLJIT_SIMD_FLOAT) {3127FUNCTION_FCHECK(srcdst, srcdstw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2);3128} else if ((type & SLJIT_SIMD_STORE) || srcdst != SLJIT_IMM) {3129FUNCTION_CHECK_DST(srcdst, srcdstw);3130}3131#endif /* SLJIT_ARGUMENT_CHECKS */3132#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)3133if (SLJIT_UNLIKELY(!!compiler->verbose)) {3134if (type & SLJIT_SIMD_TEST)3135CHECK_RETURN_OK;3136if (sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_TEST, vreg, lane_index, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) {3137fprintf(compiler->verbose, " # simd_move_lane: unsupported form, no instructions are emitted\n");3138CHECK_RETURN_OK;3139}31403141fprintf(compiler->verbose, " simd_%s_lane%s%s%s.%d.%s%d ",3142(type & SLJIT_SIMD_STORE) ? "store" : "load",3143(type & SLJIT_32) ? "32" : "",3144(type & SLJIT_SIMD_LANE_ZERO) ? "_z" : "",3145(type & SLJIT_SIMD_LANE_SIGNED) ? "_s" : "",3146(8 << SLJIT_SIMD_GET_REG_SIZE(type)),3147(type & SLJIT_SIMD_FLOAT) ? "f" : "",3148(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));31493150sljit_verbose_vreg(compiler, vreg);3151fprintf(compiler->verbose, "[%d], ", lane_index);3152if (type & SLJIT_SIMD_FLOAT)3153sljit_verbose_fparam(compiler, srcdst, srcdstw);3154else3155sljit_verbose_param(compiler, srcdst, srcdstw);3156fprintf(compiler->verbose, "\n");3157}3158#endif /* SLJIT_VERBOSE */3159CHECK_RETURN_OK;3160}31613162static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,3163sljit_s32 vreg,3164sljit_s32 src, sljit_s32 src_lane_index)3165{3166#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)3167CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));3168CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) == 0);3169CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));3170CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));3171CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type));3172CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(src, type));3173CHECK_ARGUMENT(src_lane_index >= 0 && src_lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type))));3174#endif /* SLJIT_ARGUMENT_CHECKS */3175#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)3176if (SLJIT_UNLIKELY(!!compiler->verbose)) {3177if (type & SLJIT_SIMD_TEST)3178CHECK_RETURN_OK;3179if (sljit_emit_simd_lane_replicate(compiler, type | SLJIT_SIMD_TEST, vreg, src, src_lane_index) == SLJIT_ERR_UNSUPPORTED) {3180fprintf(compiler->verbose, " # simd_lane_replicate: unsupported form, no instructions are emitted\n");3181CHECK_RETURN_OK;3182}31833184fprintf(compiler->verbose, " simd_lane_replicate.%d.%s%d ",3185(8 << SLJIT_SIMD_GET_REG_SIZE(type)),3186(type & SLJIT_SIMD_FLOAT) ? "f" : "",3187(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));31883189sljit_verbose_vreg(compiler, vreg);3190fprintf(compiler->verbose, ", ");3191sljit_verbose_vreg(compiler, src);3192fprintf(compiler->verbose, "[%d]\n", src_lane_index);3193}3194#endif /* SLJIT_VERBOSE */3195CHECK_RETURN_OK;3196}31973198static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,3199sljit_s32 vreg,3200sljit_s32 src, sljit_sw srcw)3201{3202#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)3203CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));3204CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(SLJIT_SIMD_EXTEND_SIGNED)) == 0);3205CHECK_ARGUMENT((type & (SLJIT_SIMD_EXTEND_SIGNED | SLJIT_SIMD_FLOAT)) != (SLJIT_SIMD_EXTEND_SIGNED | SLJIT_SIMD_FLOAT));3206CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));3207CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));3208CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_ELEM2_SIZE(type));3209CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type));3210FUNCTION_VCHECK(src, srcw, type);3211#endif /* SLJIT_ARGUMENT_CHECKS */3212#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)3213if (SLJIT_UNLIKELY(!!compiler->verbose)) {3214if (type & SLJIT_SIMD_TEST)3215CHECK_RETURN_OK;3216if (sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_TEST, vreg, src, srcw) == SLJIT_ERR_UNSUPPORTED) {3217fprintf(compiler->verbose, " # simd_extend: unsupported form, no instructions are emitted\n");3218CHECK_RETURN_OK;3219}32203221fprintf(compiler->verbose, " simd_load_extend%s.%d.%s%d.%s%d ",3222(type & SLJIT_SIMD_EXTEND_SIGNED) ? "_s" : "",3223(8 << SLJIT_SIMD_GET_REG_SIZE(type)),3224(type & SLJIT_SIMD_FLOAT) ? "f" : "",3225(8 << SLJIT_SIMD_GET_ELEM2_SIZE(type)),3226(type & SLJIT_SIMD_FLOAT) ? "f" : "",3227(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));32283229sljit_verbose_vreg(compiler, vreg);3230fprintf(compiler->verbose, ", ");3231sljit_verbose_vparam(compiler, src, srcw);3232fprintf(compiler->verbose, "\n");3233}3234#endif /* SLJIT_VERBOSE */3235CHECK_RETURN_OK;3236}32373238static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,3239sljit_s32 vreg,3240sljit_s32 dst, sljit_sw dstw)3241{3242#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)3243CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));3244CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(SLJIT_32)) == SLJIT_SIMD_STORE);3245CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));3246CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));3247CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type));3248FUNCTION_CHECK_DST(dst, dstw);3249#endif /* SLJIT_ARGUMENT_CHECKS */3250#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)3251if (SLJIT_UNLIKELY(!!compiler->verbose)) {3252if (type & SLJIT_SIMD_TEST)3253CHECK_RETURN_OK;3254if (sljit_emit_simd_sign(compiler, type | SLJIT_SIMD_TEST, vreg, dst, dstw) == SLJIT_ERR_UNSUPPORTED) {3255fprintf(compiler->verbose, " # simd_sign: unsupported form, no instructions are emitted\n");3256CHECK_RETURN_OK;3257}32583259fprintf(compiler->verbose, " simd_store_sign%s.%d.%s%d ",3260(type & SLJIT_32) ? "32" : "",3261(8 << SLJIT_SIMD_GET_REG_SIZE(type)),3262(type & SLJIT_SIMD_FLOAT) ? "f" : "",3263(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));32643265sljit_verbose_vreg(compiler, vreg);3266fprintf(compiler->verbose, ", ");3267sljit_verbose_param(compiler, dst, dstw);3268fprintf(compiler->verbose, "\n");3269}3270#endif /* SLJIT_VERBOSE */3271CHECK_RETURN_OK;3272}32733274static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,3275sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)3276{3277#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)3278CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));3279CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(0)) >= SLJIT_SIMD_OP2_AND && (type & SLJIT_SIMD_TYPE_MASK2(0)) <= SLJIT_SIMD_OP2_SHUFFLE);3280CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));3281CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) <= SLJIT_SIMD_GET_REG_SIZE(type));3282CHECK_ARGUMENT(SLJIT_SIMD_GET_OPCODE(type) != SLJIT_SIMD_OP2_SHUFFLE || (SLJIT_SIMD_GET_ELEM_SIZE(type) == 0 && !(type & SLJIT_SIMD_FLOAT)));3283CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) <= (src2 & SLJIT_MEM) ? SLJIT_SIMD_GET_REG_SIZE(type) : 0);3284CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(dst_vreg, type));3285CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(src1_vreg, type));3286FUNCTION_VCHECK(src2, src2w, type);3287#endif /* SLJIT_ARGUMENT_CHECKS */3288#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)3289if (SLJIT_UNLIKELY(!!compiler->verbose)) {3290if (type & SLJIT_SIMD_TEST)3291CHECK_RETURN_OK;3292if (sljit_emit_simd_op2(compiler, type | SLJIT_SIMD_TEST, dst_vreg, src1_vreg, src2, src2w) == SLJIT_ERR_UNSUPPORTED) {3293fprintf(compiler->verbose, " # simd_op2: unsupported form, no instructions are emitted\n");3294CHECK_RETURN_OK;3295}32963297fprintf(compiler->verbose, " simd_%s.%d.%s%d",3298simd_op2_names[SLJIT_SIMD_GET_OPCODE(type) - 1],3299(8 << SLJIT_SIMD_GET_REG_SIZE(type)),3300(type & SLJIT_SIMD_FLOAT) ? "f" : "",3301(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));33023303if ((type & 0x3f000000) != SLJIT_SIMD_MEM_UNALIGNED)3304fprintf(compiler->verbose, ".al%d", (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type)));33053306fprintf(compiler->verbose, " ");3307sljit_verbose_vreg(compiler, dst_vreg);3308fprintf(compiler->verbose, ", ");3309sljit_verbose_vreg(compiler, src1_vreg);3310fprintf(compiler->verbose, ", ");3311sljit_verbose_vparam(compiler, src2, src2w);3312fprintf(compiler->verbose, "\n");3313}3314#endif /* SLJIT_VERBOSE */3315CHECK_RETURN_OK;3316}33173318static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)3319{3320/* Any offset is allowed. */3321SLJIT_UNUSED_ARG(offset);33223323#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)3324FUNCTION_CHECK_DST(dst, dstw);3325#endif /* SLJIT_ARGUMENT_CHECKS */3326#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)3327if (SLJIT_UNLIKELY(!!compiler->verbose)) {3328fprintf(compiler->verbose, " local_base ");3329sljit_verbose_param(compiler, dst, dstw);3330fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", offset);3331}3332#endif /* SLJIT_VERBOSE */3333CHECK_RETURN_OK;3334}33353336static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,3337sljit_s32 dst, sljit_sw dstw,3338sljit_sw init_value)3339{3340SLJIT_UNUSED_ARG(init_value);33413342#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)3343CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV_S323344|| op == SLJIT_MOV32 || (op | SLJIT_32) == SLJIT_MOV32_U8);3345FUNCTION_CHECK_DST(dst, dstw);3346#endif /* SLJIT_ARGUMENT_CHECKS */3347#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)3348if (SLJIT_UNLIKELY(!!compiler->verbose)) {3349fprintf(compiler->verbose, " const%s%s ",3350!(op & SLJIT_32) ? "" : "32", op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);3351sljit_verbose_param(compiler, dst, dstw);3352fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", init_value);3353}3354#endif /* SLJIT_VERBOSE */3355CHECK_RETURN_OK;3356}33573358static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,3359sljit_s32 dst, sljit_sw dstw)3360{3361#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)3362CHECK_ARGUMENT(op == SLJIT_MOV_ADDR || op == SLJIT_MOV_ABS_ADDR || op == SLJIT_ADD_ABS_ADDR);3363FUNCTION_CHECK_DST(dst, dstw);3364#endif /* SLJIT_ARGUMENT_CHECKS */3365#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)3366if (SLJIT_UNLIKELY(!!compiler->verbose)) {3367fprintf(compiler->verbose, " %s ", op_addr_types[op]);3368sljit_verbose_param(compiler, dst, dstw);3369fprintf(compiler->verbose, "\n");3370}3371#endif /* SLJIT_VERBOSE */3372CHECK_RETURN_OK;3373}33743375#else /* !SLJIT_ARGUMENT_CHECKS && !SLJIT_VERBOSE */33763377#define SLJIT_SKIP_CHECKS(compiler)33783379#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */33803381#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \3382SLJIT_COMPILE_ASSERT(!(SLJIT_CONV_SW_FROM_F64 & 0x1) && !(SLJIT_CONV_F64_FROM_SW & 0x1) && !(SLJIT_CONV_F64_FROM_UW & 0x1), \3383invalid_float_opcodes); \3384if (GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CMP_F64) { \3385if (GET_OPCODE(op) == SLJIT_CMP_F64) { \3386CHECK(check_sljit_emit_fop1_cmp(compiler, op, dst, dstw, src, srcw)); \3387ADJUST_LOCAL_OFFSET(dst, dstw); \3388ADJUST_LOCAL_OFFSET(src, srcw); \3389return sljit_emit_fop1_cmp(compiler, op, dst, dstw, src, srcw); \3390} \3391if ((GET_OPCODE(op) | 0x1) == SLJIT_CONV_S32_FROM_F64) { \3392CHECK(check_sljit_emit_fop1_conv_sw_from_f64(compiler, op, dst, dstw, src, srcw)); \3393ADJUST_LOCAL_OFFSET(dst, dstw); \3394ADJUST_LOCAL_OFFSET(src, srcw); \3395return sljit_emit_fop1_conv_sw_from_f64(compiler, op, dst, dstw, src, srcw); \3396} \3397if ((GET_OPCODE(op) | 0x1) == SLJIT_CONV_F64_FROM_S32) { \3398CHECK(check_sljit_emit_fop1_conv_f64_from_w(compiler, op, dst, dstw, src, srcw)); \3399ADJUST_LOCAL_OFFSET(dst, dstw); \3400ADJUST_LOCAL_OFFSET(src, srcw); \3401return sljit_emit_fop1_conv_f64_from_sw(compiler, op, dst, dstw, src, srcw); \3402} \3403CHECK(check_sljit_emit_fop1_conv_f64_from_w(compiler, op, dst, dstw, src, srcw)); \3404ADJUST_LOCAL_OFFSET(dst, dstw); \3405ADJUST_LOCAL_OFFSET(src, srcw); \3406return sljit_emit_fop1_conv_f64_from_uw(compiler, op, dst, dstw, src, srcw); \3407} \3408CHECK(check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw)); \3409ADJUST_LOCAL_OFFSET(dst, dstw); \3410ADJUST_LOCAL_OFFSET(src, srcw);34113412#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6))34133414static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,3415sljit_s32 reg,3416sljit_s32 mem, sljit_sw memw)3417{3418SLJIT_SKIP_CHECKS(compiler);34193420if (type & SLJIT_MEM_STORE)3421return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), mem, memw, reg, 0);3422return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), reg, 0, mem, memw);3423}34243425#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) */34263427#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) \3428&& !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)34293430static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,3431sljit_s32 freg,3432sljit_s32 mem, sljit_sw memw)3433{3434SLJIT_SKIP_CHECKS(compiler);34353436if (type & SLJIT_MEM_STORE)3437return sljit_emit_fop1(compiler, type & (0xff | SLJIT_32), mem, memw, freg, 0);3438return sljit_emit_fop1(compiler, type & (0xff | SLJIT_32), freg, 0, mem, memw);3439}34403441#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) && !SLJIT_CONFIG_ARM */34423443static void sljit_reset_read_only_buffers(struct sljit_read_only_buffer *buffers)3444{3445while (buffers != NULL) {3446buffers->u.label = NULL;3447buffers = buffers->next;3448}3449}34503451/* CPU description section */34523453#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)3454#define SLJIT_CPUINFO_PART1 " 32bit ("3455#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)3456#define SLJIT_CPUINFO_PART1 " 64bit ("3457#else /* !SLJIT_32BIT_ARCHITECTURE && !SLJIT_64BIT_ARCHITECTURE */3458#error "Internal error: CPU type info missing"3459#endif /* SLJIT_32BIT_ARCHITECTURE */34603461#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)3462#define SLJIT_CPUINFO_PART2 "little endian + "3463#elif (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)3464#define SLJIT_CPUINFO_PART2 "big endian + "3465#else /* !SLJIT_LITTLE_ENDIAN && !SLJIT_BIG_ENDIAN */3466#error "Internal error: CPU type info missing"3467#endif /* SLJIT_LITTLE_ENDIAN */34683469#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED)3470#define SLJIT_CPUINFO_PART3 "unaligned)"3471#else /* !SLJIT_UNALIGNED */3472#define SLJIT_CPUINFO_PART3 "aligned)"3473#endif /* SLJIT_UNALIGNED */34743475#define SLJIT_CPUINFO SLJIT_CPUINFO_PART1 SLJIT_CPUINFO_PART2 SLJIT_CPUINFO_PART334763477#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)3478# include "sljitNativeX86_common.c"3479#elif (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)3480# include "sljitNativeARM_32.c"3481#elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)3482# include "sljitNativeARM_32.c"3483#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)3484# include "sljitNativeARM_T2_32.c"3485#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)3486# include "sljitNativeARM_64.c"3487#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)3488# include "sljitNativePPC_common.c"3489#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)3490# include "sljitNativeMIPS_common.c"3491#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)3492# include "sljitNativeRISCV_common.c"3493#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)3494# include "sljitNativeS390X.c"3495#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)3496# include "sljitNativeLOONGARCH_64.c"3497#endif /* SLJIT_CONFIG_X86 */34983499#include "sljitSerialize.c"35003501static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)3502{3503#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)3504/* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */3505if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_P))3506return SLJIT_SUCCESS;3507#else /* !SLJIT_64BIT_ARCHITECTURE */3508if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P))3509return SLJIT_SUCCESS;3510#endif /* SLJIT_64BIT_ARCHITECTURE */35113512SLJIT_SKIP_CHECKS(compiler);3513return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);3514}35153516#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \3517&& !((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && defined __SOFTFP__)35183519static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)3520{3521if (src == SLJIT_FR0)3522return SLJIT_SUCCESS;35233524SLJIT_SKIP_CHECKS(compiler);3525return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw);3526}35273528#endif /* !SLJIT_CONFIG_X86_32 && !(SLJIT_CONFIG_ARM_32 && __SOFTFP__) */35293530SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)3531{3532CHECK_ERROR();3533CHECK(check_sljit_emit_return(compiler, op, src, srcw));35343535if (GET_OPCODE(op) < SLJIT_MOV_F64) {3536FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));3537} else {3538FAIL_IF(emit_fmov_before_return(compiler, op, src, srcw));3539}35403541SLJIT_SKIP_CHECKS(compiler);3542return sljit_emit_return_void(compiler);3543}35443545#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \3546&& !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \3547&& !(defined(SLJIT_CONFIG_LOONGARCH_64) && SLJIT_CONFIG_LOONGARCH_64)35483549SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,3550sljit_s32 dst_freg,3551sljit_s32 src1, sljit_sw src1w,3552sljit_s32 src2, sljit_sw src2w)3553{3554CHECK_ERROR();3555CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w));3556ADJUST_LOCAL_OFFSET(src1, src1w);3557ADJUST_LOCAL_OFFSET(src2, src2w);35583559SLJIT_SKIP_CHECKS(compiler);3560return sljit_emit_fop2(compiler, op, dst_freg, 0, src1, src1w, src2, src2w);3561}35623563#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_S390X && !SLJIT_CONFIG_LOONGARCH_64 */35643565#if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \3566&& !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \3567&& !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)35683569SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,3570sljit_s32 src1, sljit_sw src1w,3571sljit_s32 src2, sljit_sw src2w)3572{3573/* Default compare for most architectures. */3574sljit_s32 flags, tmp_src, condition;3575sljit_sw tmp_srcw;35763577CHECK_ERROR_PTR();3578CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));35793580condition = type & 0xff;3581#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)3582if ((condition == SLJIT_EQUAL || condition == SLJIT_NOT_EQUAL)) {3583if (src1 == SLJIT_IMM && !src1w) {3584src1 = src2;3585src1w = src2w;3586src2 = SLJIT_IMM;3587src2w = 0;3588}3589if (src2 == SLJIT_IMM && !src2w)3590return emit_cmp_to0(compiler, type, src1, src1w);3591}3592#endif /* SLJIT_CONFIG_ARM_64 */35933594if (SLJIT_UNLIKELY(src1 == SLJIT_IMM && src2 != SLJIT_IMM)) {3595/* Immediate is preferred as second argument by most architectures. */3596switch (condition) {3597case SLJIT_LESS:3598condition = SLJIT_GREATER;3599break;3600case SLJIT_GREATER_EQUAL:3601condition = SLJIT_LESS_EQUAL;3602break;3603case SLJIT_GREATER:3604condition = SLJIT_LESS;3605break;3606case SLJIT_LESS_EQUAL:3607condition = SLJIT_GREATER_EQUAL;3608break;3609case SLJIT_SIG_LESS:3610condition = SLJIT_SIG_GREATER;3611break;3612case SLJIT_SIG_GREATER_EQUAL:3613condition = SLJIT_SIG_LESS_EQUAL;3614break;3615case SLJIT_SIG_GREATER:3616condition = SLJIT_SIG_LESS;3617break;3618case SLJIT_SIG_LESS_EQUAL:3619condition = SLJIT_SIG_GREATER_EQUAL;3620break;3621}36223623type = condition | (type & (SLJIT_32 | SLJIT_REWRITABLE_JUMP));3624tmp_src = src1;3625src1 = src2;3626src2 = tmp_src;3627tmp_srcw = src1w;3628src1w = src2w;3629src2w = tmp_srcw;3630}36313632if (condition <= SLJIT_NOT_ZERO)3633flags = SLJIT_SET_Z;3634else3635flags = (condition & 0xfe) << VARIABLE_FLAG_SHIFT;36363637SLJIT_SKIP_CHECKS(compiler);3638PTR_FAIL_IF(sljit_emit_op2u(compiler,3639SLJIT_SUB | flags | (type & SLJIT_32), src1, src1w, src2, src2w));36403641SLJIT_SKIP_CHECKS(compiler);3642return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_32)));3643}36443645#endif /* !SLJIT_CONFIG_MIPS */36463647#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)36483649SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)3650{3651switch (type) {3652case SLJIT_UNORDERED_OR_EQUAL:3653case SLJIT_ORDERED_NOT_EQUAL:3654return 1;3655}36563657return 0;3658}36593660#endif /* SLJIT_CONFIG_ARM */36613662SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,3663sljit_s32 src1, sljit_sw src1w,3664sljit_s32 src2, sljit_sw src2w)3665{3666CHECK_ERROR_PTR();3667CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));36683669SLJIT_SKIP_CHECKS(compiler);3670sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xfe) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_32), src1, src1w, src2, src2w);36713672SLJIT_SKIP_CHECKS(compiler);3673return sljit_emit_jump(compiler, type);3674}36753676#if !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \3677&& !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \3678&& !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)36793680SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op2cmpz(struct sljit_compiler *compiler, sljit_s32 op,3681sljit_s32 dst, sljit_sw dstw,3682sljit_s32 src1, sljit_sw src1w,3683sljit_s32 src2, sljit_sw src2w)3684{3685CHECK_ERROR_PTR();3686CHECK_PTR(check_sljit_emit_op2cmpz(compiler, op, dst, dstw, src1, src1w, src2, src2w));36873688SLJIT_SKIP_CHECKS(compiler);3689PTR_FAIL_IF(sljit_emit_op2(compiler, ((op | SLJIT_SET_Z) & ~SLJIT_REWRITABLE_JUMP), dst, dstw, src1, src1w, src2, src2w));36903691SLJIT_SKIP_CHECKS(compiler);3692return sljit_emit_jump(compiler, ((op & SLJIT_JUMP_IF_ZERO) ? SLJIT_ZERO : SLJIT_NOT_ZERO) | (op & SLJIT_REWRITABLE_JUMP));3693}36943695#else /* SLJIT_CONFIG_RISCV || SLJIT_CONFIG_MIPS || SLJIT_CONFIG_LOONGARCH */36963697SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op2cmpz(struct sljit_compiler *compiler, sljit_s32 op,3698sljit_s32 dst, sljit_sw dstw,3699sljit_s32 src1, sljit_sw src1w,3700sljit_s32 src2, sljit_sw src2w)3701{3702sljit_s32 reg;37033704CHECK_ERROR_PTR();3705CHECK_PTR(check_sljit_emit_op2cmpz(compiler, op, dst, dstw, src1, src1w, src2, src2w));37063707SLJIT_SKIP_CHECKS(compiler);3708PTR_FAIL_IF(sljit_emit_op2(compiler, (op & ~(SLJIT_SET_Z | SLJIT_REWRITABLE_JUMP)), dst, dstw, src1, src1w, src2, src2w));37093710/* When dst is a memory operand, its value is stored in SLJIT_TMP_DEST_FREG. */3711reg = FAST_IS_REG(dst) ? dst : SLJIT_TMP_DEST_REG;37123713SLJIT_SKIP_CHECKS(compiler);3714return sljit_emit_cmp(compiler, ((op & SLJIT_JUMP_IF_ZERO) ? SLJIT_ZERO : SLJIT_NOT_ZERO) | (op & (SLJIT_32 | SLJIT_REWRITABLE_JUMP)), reg, 0, SLJIT_IMM, 0);3715}37163717#endif /* !SLJIT_CONFIG_RISCV && !SLJIT_CONFIG_MIPS && !SLJIT_CONFIG_LOONGARCH */37183719#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \3720&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)37213722SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,3723sljit_s32 reg,3724sljit_s32 mem, sljit_sw memw)3725{3726CHECK_ERROR();3727CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));3728SLJIT_UNUSED_ARG(type);3729SLJIT_UNUSED_ARG(reg);3730SLJIT_UNUSED_ARG(mem);3731SLJIT_UNUSED_ARG(memw);37323733return SLJIT_ERR_UNSUPPORTED;3734}37353736#endif /* !SLJIT_CONFIG_ARM && !SLJIT_CONFIG_PPC */37373738#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \3739&& !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)37403741SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,3742sljit_s32 freg,3743sljit_s32 mem, sljit_sw memw)3744{3745CHECK_ERROR();3746CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));37473748return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw);3749}37503751#endif /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS */37523753#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \3754&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)37553756SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,3757sljit_s32 freg,3758sljit_s32 mem, sljit_sw memw)3759{3760CHECK_ERROR();3761CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw));3762SLJIT_UNUSED_ARG(type);3763SLJIT_UNUSED_ARG(freg);3764SLJIT_UNUSED_ARG(mem);3765SLJIT_UNUSED_ARG(memw);37663767return SLJIT_ERR_UNSUPPORTED;3768}37693770#endif /* !SLJIT_CONFIG_ARM_64 && !SLJIT_CONFIG_PPC */37713772#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \3773&& !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \3774&& !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \3775&& !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \3776&& !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)37773778SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,3779sljit_s32 vreg,3780sljit_s32 srcdst, sljit_sw srcdstw)3781{3782CHECK_ERROR();3783CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw));3784SLJIT_UNUSED_ARG(compiler);3785SLJIT_UNUSED_ARG(type);3786SLJIT_UNUSED_ARG(vreg);3787SLJIT_UNUSED_ARG(srcdst);3788SLJIT_UNUSED_ARG(srcdstw);37893790return SLJIT_ERR_UNSUPPORTED;3791}37923793SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,3794sljit_s32 vreg,3795sljit_s32 src, sljit_sw srcw)3796{3797CHECK_ERROR();3798CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw));3799SLJIT_UNUSED_ARG(compiler);3800SLJIT_UNUSED_ARG(type);3801SLJIT_UNUSED_ARG(vreg);3802SLJIT_UNUSED_ARG(src);3803SLJIT_UNUSED_ARG(srcw);38043805return SLJIT_ERR_UNSUPPORTED;3806}38073808SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,3809sljit_s32 vreg, sljit_s32 lane_index,3810sljit_s32 srcdst, sljit_sw srcdstw)3811{3812CHECK_ERROR();3813CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw));3814SLJIT_UNUSED_ARG(compiler);3815SLJIT_UNUSED_ARG(type);3816SLJIT_UNUSED_ARG(vreg);3817SLJIT_UNUSED_ARG(lane_index);3818SLJIT_UNUSED_ARG(srcdst);3819SLJIT_UNUSED_ARG(srcdstw);38203821return SLJIT_ERR_UNSUPPORTED;3822}38233824SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,3825sljit_s32 vreg,3826sljit_s32 src, sljit_s32 src_lane_index)3827{3828CHECK_ERROR();3829CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index));3830SLJIT_UNUSED_ARG(compiler);3831SLJIT_UNUSED_ARG(type);3832SLJIT_UNUSED_ARG(vreg);3833SLJIT_UNUSED_ARG(src);3834SLJIT_UNUSED_ARG(src_lane_index);38353836return SLJIT_ERR_UNSUPPORTED;3837}38383839SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,3840sljit_s32 vreg,3841sljit_s32 src, sljit_sw srcw)3842{3843CHECK_ERROR();3844CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw));3845SLJIT_UNUSED_ARG(compiler);3846SLJIT_UNUSED_ARG(type);3847SLJIT_UNUSED_ARG(vreg);3848SLJIT_UNUSED_ARG(src);3849SLJIT_UNUSED_ARG(srcw);38503851return SLJIT_ERR_UNSUPPORTED;3852}38533854SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,3855sljit_s32 vreg,3856sljit_s32 dst, sljit_sw dstw)3857{3858CHECK_ERROR();3859CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw));3860SLJIT_UNUSED_ARG(compiler);3861SLJIT_UNUSED_ARG(type);3862SLJIT_UNUSED_ARG(vreg);3863SLJIT_UNUSED_ARG(dst);3864SLJIT_UNUSED_ARG(dstw);38653866return SLJIT_ERR_UNSUPPORTED;3867}38683869SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,3870sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)3871{3872CHECK_ERROR();3873CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));3874SLJIT_UNUSED_ARG(compiler);3875SLJIT_UNUSED_ARG(type);3876SLJIT_UNUSED_ARG(dst_vreg);3877SLJIT_UNUSED_ARG(src1_vreg);3878SLJIT_UNUSED_ARG(src2);3879SLJIT_UNUSED_ARG(src2w);38803881return SLJIT_ERR_UNSUPPORTED;3882}38833884#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM && !SLJIT_CONFIG_S390X && !SLJIT_CONFIG_LOONGARCH */38853886#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \3887&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)38883889SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)3890{3891CHECK_ERROR();3892CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));38933894ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);38953896SLJIT_SKIP_CHECKS(compiler);38973898if (offset != 0)3899return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);3900return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0);3901}39023903#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM_64 */39043905SLJIT_API_FUNC_ATTRIBUTE void* sljit_read_only_buffer_start_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset)3906{3907SLJIT_UNUSED_ARG(size);3908SLJIT_UNUSED_ARG(executable_offset);39093910SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + size), 0);3911return SLJIT_ADD_EXEC_OFFSET(addr, -executable_offset);3912}39133914SLJIT_API_FUNC_ATTRIBUTE void sljit_read_only_buffer_end_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset)3915{3916SLJIT_UNUSED_ARG(addr);3917SLJIT_UNUSED_ARG(size);3918SLJIT_UNUSED_ARG(executable_offset);39193920SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + size), 1);3921SLJIT_CACHE_FLUSH((void*)addr, (void*)(addr + size));3922}39233924#endif /* !SLJIT_CONFIG_UNSUPPORTED */392539263927