#include "sljitLir.h"
#ifdef _WIN32
#include <windows.h>
#endif
#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)
#include <stdlib.h>
#include <string.h>
#endif
#define CHECK_ERROR() …
#define CHECK_ERROR_PTR() …
#define FAIL_IF(expr) …
#define PTR_FAIL_IF(expr) …
#define FAIL_IF_NULL(ptr) …
#define PTR_FAIL_IF_NULL(ptr) …
#define PTR_FAIL_WITH_EXEC_IF(ptr) …
#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
#define SSIZE_OF(type) …
#define VARIABLE_FLAG_SHIFT …
#define VARIABLE_FLAG_MASK …
#define GET_FLAG_TYPE(op) …
#define GET_OPCODE(op) …
#define HAS_FLAGS(op) …
#define GET_ALL_FLAGS(op) …
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
#define TYPE_CAST_NEEDED(op) …
#else
#define TYPE_CAST_NEEDED …
#endif
#define BUF_SIZE …
#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
#define ABUF_SIZE …
#else
#define ABUF_SIZE …
#endif
#define REG_MASK …
#define OFFS_REG(reg) …
#define OFFS_REG_MASK …
#define TO_OFFS_REG(reg) …
#define FAST_IS_REG(reg) …
#define SLJIT_ARG_MASK …
#define SLJIT_ARG_FULL_MASK …
#define REG_PAIR_MASK …
#define REG_PAIR_FIRST(reg) …
#define REG_PAIR_SECOND(reg) …
#define SLJIT_KEPT_SAVEDS_COUNT(options) …
#define SLJIT_SIMD_GET_OPCODE(type) …
#define SLJIT_SIMD_GET_REG_SIZE(type) …
#define SLJIT_SIMD_GET_ELEM_SIZE(type) …
#define SLJIT_SIMD_GET_ELEM2_SIZE(type) …
#define SLJIT_SIMD_CHECK_REG(type) …
#define SLJIT_SIMD_TYPE_MASK(m) …
#define SLJIT_SIMD_TYPE_MASK2(m) …
#define JUMP_LABEL …
#define JUMP_ADDR …
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
#define PATCH_MB …
#define PATCH_MW …
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
#define PATCH_MD …
#endif
#define TYPE_SHIFT …
#endif
#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
#define IS_BL …
#define PATCH_B …
#endif
#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
#define CPOOL_SIZE …
#endif
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
#define IS_COND …
#define IS_BL …
#define PATCH_TYPE1 …
#define PATCH_TYPE2 …
#define PATCH_TYPE3 …
#define PATCH_TYPE4 …
#define PATCH_TYPE5 …
#define PATCH_BL …
#endif
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
#define IS_COND …
#define IS_CBZ …
#define IS_BL …
#define PATCH_B …
#define PATCH_COND …
#define PATCH_ABS48 …
#define PATCH_ABS64 …
#endif
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
#define IS_COND …
#define IS_CALL …
#define PATCH_B …
#define PATCH_ABS_B …
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
#define PATCH_ABS32 …
#define PATCH_ABS48 …
#endif
#define REMOVE_COND …
#endif
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
#define IS_MOVABLE …
#define IS_JAL …
#define IS_CALL …
#define IS_BIT26_COND …
#define IS_BIT16_COND …
#define IS_BIT23_COND …
#define IS_COND …
#define PATCH_B …
#define PATCH_J …
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
#define PATCH_ABS32 …
#define PATCH_ABS48 …
#endif
#define MOVABLE_INS …
#define UNMOVABLE_INS …
#define FCSR_FCC …
#endif
#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
#define IS_COND …
#define IS_CALL …
#define PATCH_B …
#define PATCH_J …
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
#define PATCH_REL32 …
#define PATCH_ABS32 …
#define PATCH_ABS44 …
#define PATCH_ABS52 …
#else
#define PATCH_REL32 …
#endif
#endif
#if (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
#define IS_COND …
#define IS_CALL …
#define PATCH_B …
#define PATCH_J …
#define PATCH_REL32 …
#define PATCH_ABS32 …
#define PATCH_ABS52 …
#endif
#define GET_SAVED_REGISTERS_SIZE(scratches, saveds, extra) …
#define GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, type) …
#define ADJUST_LOCAL_OFFSET(p, i) …
#endif
#include "sljitUtils.c"
#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
#if defined(__NetBSD__)
#include "allocator_src/sljitProtExecAllocatorNetBSD.c"
#else
#include "allocator_src/sljitProtExecAllocatorPosix.c"
#endif
#elif (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)
#if defined(_WIN32)
#include "allocator_src/sljitWXExecAllocatorWindows.c"
#else
#include "allocator_src/sljitWXExecAllocatorPosix.c"
#endif
#else
#if defined(_WIN32)
#include "allocator_src/sljitExecAllocatorWindows.c"
#elif defined(__APPLE__)
#include "allocator_src/sljitExecAllocatorApple.c"
#elif defined(__FreeBSD__)
#include "allocator_src/sljitExecAllocatorFreeBSD.c"
#else
#include "allocator_src/sljitExecAllocatorPosix.c"
#endif
#endif
#else
#ifndef SLJIT_UPDATE_WX_FLAGS
#define SLJIT_UPDATE_WX_FLAGS …
#endif
#endif
#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
#define SLJIT_ADD_EXEC_OFFSET …
#else
#define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) …
#endif
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
#define CHECK_ARGUMENT …
#define CHECK_RETURN_TYPE …
#define CHECK_RETURN_OK …
#define CHECK …
#define CHECK_PTR …
#define CHECK_REG_INDEX …
#elif (defined SLJIT_DEBUG && SLJIT_DEBUG)
#undef SLJIT_ARGUMENT_CHECKS
#define SLJIT_ARGUMENT_CHECKS …
#define CHECK_ARGUMENT …
#define CHECK_RETURN_TYPE …
#define CHECK_RETURN_OK …
#define CHECK …
#define CHECK_PTR …
#define CHECK_REG_INDEX …
#elif (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
#define CHECK_RETURN_TYPE …
#define CHECK_RETURN_OK …
#define CHECK …
#define CHECK_PTR …
#define CHECK_REG_INDEX …
#else
#define CHECK(x) …
#define CHECK_PTR(x) …
#define CHECK_REG_INDEX(x) …
#endif
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
#define SLJIT_NEEDS_COMPILER_INIT …
static sljit_s32 compiler_initialized = …;
static void init_compiler(void);
#endif
SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data, void *exec_allocator_data)
{ … }
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler)
{ … }
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler)
{ … }
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)
{
SLJIT_UNUSED_ARG(exec_allocator_data);
SLJIT_FREE_EXEC((void*)((sljit_uw)code & ~(sljit_uw)0x1), exec_allocator_data);
}
#elif (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)
{
SLJIT_UNUSED_ARG(exec_allocator_data);
code = (void*)(*(sljit_uw*)code);
SLJIT_FREE_EXEC(code, exec_allocator_data);
}
#else
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)
{ … }
#endif
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)
{ … }
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)
{ … }
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label)
{ … }
#define SLJIT_CURRENT_FLAGS_ALL …
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)
{ … }
static void* ensure_buf(struct sljit_compiler *compiler, sljit_uw size)
{ … }
static void* ensure_abuf(struct sljit_compiler *compiler, sljit_uw size)
{ … }
SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size)
{ … }
static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler)
{ … }
#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
&& !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
static SLJIT_INLINE sljit_uw compute_next_addr(struct sljit_label *label, struct sljit_jump *jump,
struct sljit_const *const_, struct sljit_put_label *put_label)
{
sljit_uw result = ~(sljit_uw)0;
if (label)
result = label->size;
if (jump && jump->addr < result)
result = jump->addr;
if (const_ && const_->addr < result)
result = const_->addr;
if (put_label && put_label->addr < result)
result = put_label->addr;
return result;
}
#endif
static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{ … }
static SLJIT_INLINE void set_set_context(struct sljit_compiler *compiler,
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{ … }
static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compiler *compiler)
{ … }
static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_u32 flags)
{ … }
static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_compiler *compiler)
{ … }
static SLJIT_INLINE void set_put_label(struct sljit_put_label *put_label, struct sljit_compiler *compiler, sljit_uw offset)
{ … }
#define ADDRESSING_DEPENDS_ON(exp, reg) …
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
static sljit_s32 function_check_arguments(sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches)
{
sljit_s32 word_arg_count, scratch_arg_end, saved_arg_count, float_arg_count, curr_type;
curr_type = (arg_types & SLJIT_ARG_FULL_MASK);
if (curr_type >= SLJIT_ARG_TYPE_F64) {
if (curr_type > SLJIT_ARG_TYPE_F32 || fscratches == 0)
return 0;
} else if (curr_type >= SLJIT_ARG_TYPE_W) {
if (scratches == 0)
return 0;
}
arg_types >>= SLJIT_ARG_SHIFT;
word_arg_count = 0;
scratch_arg_end = 0;
saved_arg_count = 0;
float_arg_count = 0;
while (arg_types != 0) {
if (word_arg_count + float_arg_count >= 4)
return 0;
curr_type = (arg_types & SLJIT_ARG_MASK);
if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {
if (saveds == -1 || curr_type < SLJIT_ARG_TYPE_W || curr_type > SLJIT_ARG_TYPE_P)
return 0;
word_arg_count++;
scratch_arg_end = word_arg_count;
} else {
if (curr_type < SLJIT_ARG_TYPE_W || curr_type > SLJIT_ARG_TYPE_F32)
return 0;
if (curr_type < SLJIT_ARG_TYPE_F64) {
word_arg_count++;
saved_arg_count++;
} else
float_arg_count++;
}
arg_types >>= SLJIT_ARG_SHIFT;
}
if (saveds == -1)
return (word_arg_count <= scratches && float_arg_count <= fscratches);
return (saved_arg_count <= saveds && scratch_arg_end <= scratches && float_arg_count <= fscratches);
}
#define FUNCTION_CHECK_IS_REG …
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#define CHECK_IF_VIRTUAL_REGISTER …
#else
#define CHECK_IF_VIRTUAL_REGISTER …
#endif
static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
{
if (compiler->scratches == -1)
return 0;
if (!(p & SLJIT_MEM))
return 0;
if (p == SLJIT_MEM1(SLJIT_SP))
return (i >= 0 && i < compiler->logical_local_size);
if (!(!(p & REG_MASK) || FUNCTION_CHECK_IS_REG(p & REG_MASK)))
return 0;
if (CHECK_IF_VIRTUAL_REGISTER(p & REG_MASK))
return 0;
if (p & OFFS_REG_MASK) {
if (!(p & REG_MASK))
return 0;
if (!(FUNCTION_CHECK_IS_REG(OFFS_REG(p))))
return 0;
if (CHECK_IF_VIRTUAL_REGISTER(OFFS_REG(p)))
return 0;
if ((i & ~0x3) != 0)
return 0;
}
return (p & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK)) == 0;
}
#define FUNCTION_CHECK_SRC_MEM …
static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
{
if (compiler->scratches == -1)
return 0;
if (FUNCTION_CHECK_IS_REG(p))
return (i == 0);
if (p == SLJIT_IMM)
return 1;
return function_check_src_mem(compiler, p, i);
}
#define FUNCTION_CHECK_SRC …
static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
{
if (compiler->scratches == -1)
return 0;
if (FUNCTION_CHECK_IS_REG(p))
return (i == 0);
return function_check_src_mem(compiler, p, i);
}
#define FUNCTION_CHECK_DST …
#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
#define FUNCTION_CHECK_IS_FREG …
static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32);
#define FUNCTION_FCHECK …
static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 is_32)
{
if (compiler->scratches == -1)
return 0;
if (FUNCTION_CHECK_IS_FREG(p, is_32))
return (i == 0);
return function_check_src_mem(compiler, p, i);
}
#else
#define FUNCTION_CHECK_IS_FREG …
static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr)
{
if (compiler->scratches == -1)
return 0;
return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches))
|| (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0)
|| (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));
}
#define FUNCTION_FCHECK …
static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
{
if (compiler->scratches == -1)
return 0;
if ((p >= SLJIT_FR0 && p < (SLJIT_FR0 + compiler->fscratches))
|| (p > (SLJIT_FS0 - compiler->fsaveds) && p <= SLJIT_FS0)
|| (p >= SLJIT_TMP_FREGISTER_BASE && p < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)))
return (i == 0);
return function_check_src_mem(compiler, p, i);
}
#endif
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose)
{
compiler->verbose = verbose;
}
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
#ifdef _WIN64
#ifdef __GNUC__
#define SLJIT_PRINT_D …
#else
#define SLJIT_PRINT_D …
#endif
#else
#define SLJIT_PRINT_D …
#endif
#else
#define SLJIT_PRINT_D …
#endif
static void sljit_verbose_reg(struct sljit_compiler *compiler, sljit_s32 r)
{
if (r < (SLJIT_R0 + compiler->scratches))
fprintf(compiler->verbose, "r%d", r - SLJIT_R0);
else if (r < SLJIT_SP)
fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - r);
else if (r == SLJIT_SP)
fprintf(compiler->verbose, "sp");
else
fprintf(compiler->verbose, "t%d", r - SLJIT_TMP_REGISTER_BASE);
}
static void sljit_verbose_freg(struct sljit_compiler *compiler, sljit_s32 r)
{
#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
if (r >= SLJIT_F64_SECOND(SLJIT_FR0)) {
fprintf(compiler->verbose, "^");
r -= SLJIT_F64_SECOND(0);
}
#endif
if (r < (SLJIT_FR0 + compiler->fscratches))
fprintf(compiler->verbose, "fr%d", r - SLJIT_FR0);
else if (r < SLJIT_TMP_FREGISTER_BASE)
fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - r);
else
fprintf(compiler->verbose, "ft%d", r - SLJIT_TMP_FREGISTER_BASE);
}
static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
{
if ((p) == SLJIT_IMM)
fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i));
else if ((p) & SLJIT_MEM) {
if ((p) & REG_MASK) {
fputc('[', compiler->verbose);
sljit_verbose_reg(compiler, (p) & REG_MASK);
if ((p) & OFFS_REG_MASK) {
fprintf(compiler->verbose, " + ");
sljit_verbose_reg(compiler, OFFS_REG(p));
if (i)
fprintf(compiler->verbose, " * %d", 1 << (i));
}
else if (i)
fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));
fputc(']', compiler->verbose);
}
else
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));
} else
sljit_verbose_reg(compiler, p);
}
static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
{
if ((p) & SLJIT_MEM) {
if ((p) & REG_MASK) {
fputc('[', compiler->verbose);
sljit_verbose_reg(compiler, (p) & REG_MASK);
if ((p) & OFFS_REG_MASK) {
fprintf(compiler->verbose, " + ");
sljit_verbose_reg(compiler, OFFS_REG(p));
if (i)
fprintf(compiler->verbose, "%d", 1 << (i));
}
else if (i)
fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));
fputc(']', compiler->verbose);
}
else
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));
}
else
sljit_verbose_freg(compiler, p);
}
static const char* op0_names[] = {
"breakpoint", "nop", "lmul.uw", "lmul.sw",
"divmod.u", "divmod.s", "div.u", "div.s",
"endbr", "skip_frames_before_return"
};
static const char* op1_names[] = {
"mov", "mov", "mov", "mov",
"mov", "mov", "mov", "mov",
"mov", "clz", "ctz", "rev",
"rev", "rev", "rev", "rev"
};
static const char* op1_types[] = {
"", ".u8", ".s8", ".u16",
".s16", ".u32", ".s32", "32",
".p", "", "", "",
".u16", ".s16", ".u32", ".s32"
};
static const char* op2_names[] = {
"add", "addc", "sub", "subc",
"mul", "and", "or", "xor",
"shl", "mshl", "lshr", "mlshr",
"ashr", "mashr", "rotl", "rotr"
};
static const char* op_src_dst_names[] = {
"fast_return", "skip_frames_before_fast_return",
"prefetch_l1", "prefetch_l2",
"prefetch_l3", "prefetch_once",
"fast_enter", "get_return_address"
};
static const char* fop1_names[] = {
"mov", "conv", "conv", "conv",
"conv", "conv", "conv", "conv",
"cmp", "neg", "abs",
};
static const char* fop1_conv_types[] = {
"sw", "s32", "sw", "s32",
"uw", "u32"
};
static const char* fop2_names[] = {
"add", "sub", "mul", "div"
};
static const char* fop2r_names[] = {
"copysign"
};
static const char* simd_op2_names[] = {
"and", "or", "xor"
};
static const char* jump_names[] = {
"equal", "not_equal",
"less", "greater_equal",
"greater", "less_equal",
"sig_less", "sig_greater_equal",
"sig_greater", "sig_less_equal",
"overflow", "not_overflow",
"carry", "not_carry",
"atomic_stored", "atomic_not_stored",
"f_equal", "f_not_equal",
"f_less", "f_greater_equal",
"f_greater", "f_less_equal",
"unordered", "ordered",
"ordered_equal", "unordered_or_not_equal",
"ordered_less", "unordered_or_greater_equal",
"ordered_greater", "unordered_or_less_equal",
"unordered_or_equal", "ordered_not_equal",
"unordered_or_less", "ordered_greater_equal",
"unordered_or_greater", "ordered_less_equal",
"jump", "fast_call",
"call", "call_reg_arg"
};
static const char* call_arg_names[] = {
"void", "w", "32", "p", "f64", "f32"
};
#endif
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
#define SLJIT_SKIP_CHECKS …
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
struct sljit_jump *jump;
#endif
SLJIT_UNUSED_ARG(compiler);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(compiler->size > 0);
jump = compiler->jumps;
while (jump) {
CHECK_ARGUMENT(jump->flags & (JUMP_LABEL | JUMP_ADDR));
jump = jump->next;
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compiler *compiler,
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
SLJIT_UNUSED_ARG(compiler);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
if (options & SLJIT_ENTER_REG_ARG) {
CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG)));
} else {
CHECK_ARGUMENT(options == 0);
}
CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);
CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);
CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) <= SLJIT_ARG_TYPE_F32);
CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches));
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " enter ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);
arg_types >>= SLJIT_ARG_SHIFT;
if (arg_types) {
fprintf(compiler->verbose, "], args[");
do {
fprintf(compiler->verbose, "%s%s", call_arg_names[arg_types & SLJIT_ARG_MASK],
(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? "_r" : "");
arg_types >>= SLJIT_ARG_SHIFT;
if (arg_types)
fprintf(compiler->verbose, ",");
} while (arg_types);
}
fprintf(compiler->verbose, "],");
if (options & SLJIT_ENTER_REG_ARG) {
fprintf(compiler->verbose, " enter:reg_arg,");
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options));
}
fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",
scratches, saveds, fscratches, fsaveds, local_size);
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compiler *compiler,
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
SLJIT_UNUSED_ARG(compiler);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
if (options & SLJIT_ENTER_REG_ARG) {
CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG)));
} else {
CHECK_ARGUMENT(options == 0);
}
CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);
CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);
CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64);
CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches));
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " set_context ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);
arg_types >>= SLJIT_ARG_SHIFT;
if (arg_types) {
fprintf(compiler->verbose, "], args[");
do {
fprintf(compiler->verbose, "%s%s", call_arg_names[arg_types & SLJIT_ARG_MASK],
(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? "_r" : "");
arg_types >>= SLJIT_ARG_SHIFT;
if (arg_types)
fprintf(compiler->verbose, ",");
} while (arg_types);
}
fprintf(compiler->verbose, "],");
if (options & SLJIT_ENTER_REG_ARG) {
fprintf(compiler->verbose, " enter:reg_arg,");
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options));
}
fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",
scratches, saveds, fscratches, fsaveds, local_size);
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_void(struct sljit_compiler *compiler)
{
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(compiler->last_return == SLJIT_ARG_TYPE_RET_VOID);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " return_void\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(compiler->scratches >= 0);
switch (compiler->last_return) {
case SLJIT_ARG_TYPE_W:
CHECK_ARGUMENT(op >= SLJIT_MOV && op <= SLJIT_MOV_S32);
break;
case SLJIT_ARG_TYPE_32:
CHECK_ARGUMENT(op == SLJIT_MOV32 || (op >= SLJIT_MOV32_U8 && op <= SLJIT_MOV32_S16));
break;
case SLJIT_ARG_TYPE_P:
CHECK_ARGUMENT(op == SLJIT_MOV_P);
break;
case SLJIT_ARG_TYPE_F64:
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(op == SLJIT_MOV_F64);
break;
case SLJIT_ARG_TYPE_F32:
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(op == SLJIT_MOV_F32);
break;
default:
CHECK_ARGUMENT(0);
break;
}
if (GET_OPCODE(op) < SLJIT_MOV_F64) {
FUNCTION_CHECK_SRC(src, srcw);
} else {
FUNCTION_FCHECK(src, srcw, op & SLJIT_32);
}
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (GET_OPCODE(op) < SLJIT_MOV_F64) {
fprintf(compiler->verbose, " return%s%s ", !(op & SLJIT_32) ? "" : "32",
op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);
sljit_verbose_param(compiler, src, srcw);
} else {
fprintf(compiler->verbose, " return%s ", !(op & SLJIT_32) ? ".f64" : ".f32");
sljit_verbose_fparam(compiler, src, srcw);
}
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_to(struct sljit_compiler *compiler,
sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
FUNCTION_CHECK_SRC(src, srcw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " return_to ");
sljit_verbose_param(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW)
|| ((op & ~SLJIT_32) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_32) <= SLJIT_DIV_SW)
|| (op >= SLJIT_ENDBR && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN));
CHECK_ARGUMENT(GET_OPCODE(op) < SLJIT_LMUL_UW || GET_OPCODE(op) >= SLJIT_ENDBR || compiler->scratches >= 2);
if ((GET_OPCODE(op) >= SLJIT_LMUL_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN)
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose))
{
fprintf(compiler->verbose, " %s", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]);
if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) {
fprintf(compiler->verbose, (op & SLJIT_32) ? "32" : "w");
}
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_REV_S32);
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
case SLJIT_MOV32:
case SLJIT_MOV_P:
case SLJIT_REV_U32:
case SLJIT_REV_S32:
CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
break;
default:
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
break;
}
FUNCTION_CHECK_DST(dst, dstw);
FUNCTION_CHECK_SRC(src, srcw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE],
!(op & SLJIT_32) ? "" : "32", op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst_reg,
sljit_s32 mem_reg)
{
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC));
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOV_P);
CHECK_ARGUMENT(GET_OPCODE(op) != SLJIT_MOV_S8 && GET_OPCODE(op) != SLJIT_MOV_S16 && GET_OPCODE(op) != SLJIT_MOV_S32);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(mem_reg) && !CHECK_IF_VIRTUAL_REGISTER(mem_reg));
if (op == SLJIT_MOV32_U8 || op == SLJIT_MOV32_U16) {
CHECK_ARGUMENT(!(op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z)));
} else {
CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
}
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " atomic_load%s%s ", !(op & SLJIT_32) ? "" : "32",
op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);
sljit_verbose_reg(compiler, dst_reg);
fprintf(compiler->verbose, ", [");
sljit_verbose_reg(compiler, mem_reg);
fprintf(compiler->verbose, "]\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src_reg,
sljit_s32 mem_reg,
sljit_s32 temp_reg)
{
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC));
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOV_P);
CHECK_ARGUMENT(GET_OPCODE(op) != SLJIT_MOV_S8 && GET_OPCODE(op) != SLJIT_MOV_S16 && GET_OPCODE(op) != SLJIT_MOV_S32);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src_reg));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(mem_reg) && !CHECK_IF_VIRTUAL_REGISTER(mem_reg));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(temp_reg) && src_reg != temp_reg);
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == SLJIT_ATOMIC_STORED);
if (GET_OPCODE(op) == SLJIT_MOV_U8 || GET_OPCODE(op) == SLJIT_MOV_U16) {
CHECK_ARGUMENT(!(op & SLJIT_SET_Z));
} else {
CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z)));
}
compiler->last_flags = GET_FLAG_TYPE(op) | (op & SLJIT_32);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " atomic_store%s%s%s ", !(op & SLJIT_32) ? "" : "32",
op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & VARIABLE_FLAG_MASK) ? "" : ".stored");
sljit_verbose_reg(compiler, src_reg);
fprintf(compiler->verbose, ", [");
sljit_verbose_reg(compiler, mem_reg);
fprintf(compiler->verbose, "], ");
sljit_verbose_reg(compiler, temp_reg);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 unset,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ROTR);
switch (GET_OPCODE(op)) {
case SLJIT_AND:
case SLJIT_OR:
case SLJIT_XOR:
case SLJIT_SHL:
case SLJIT_MSHL:
case SLJIT_LSHR:
case SLJIT_MLSHR:
case SLJIT_ASHR:
case SLJIT_MASHR:
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
break;
case SLJIT_MUL:
CHECK_ARGUMENT(!(op & SLJIT_SET_Z));
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
|| GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);
break;
case SLJIT_ADD:
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
|| GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)
|| GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);
break;
case SLJIT_SUB:
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
|| (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_OVERFLOW)
|| GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
break;
case SLJIT_ADDC:
case SLJIT_SUBC:
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
|| GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
CHECK_ARGUMENT((compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
CHECK_ARGUMENT((op & SLJIT_32) == (compiler->last_flags & SLJIT_32));
break;
case SLJIT_ROTL:
case SLJIT_ROTR:
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
break;
default:
SLJIT_UNREACHABLE();
break;
}
if (unset) {
CHECK_ARGUMENT(HAS_FLAGS(op));
} else {
FUNCTION_CHECK_DST(dst, dstw);
}
FUNCTION_CHECK_SRC(src1, src1w);
FUNCTION_CHECK_SRC(src2, src2w);
compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",
!(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",
!(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);
if (unset)
fprintf(compiler->verbose, "unset");
else
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, src2, src2w);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst_reg,
sljit_s32 src1_reg,
sljit_s32 src2_reg,
sljit_s32 src3, sljit_sw src3w)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_LSHR
|| GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR);
CHECK_ARGUMENT((op & ~(0xff | SLJIT_32 | SLJIT_SHIFT_INTO_NON_ZERO)) == 0);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src1_reg));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src2_reg));
FUNCTION_CHECK_SRC(src3, src3w);
CHECK_ARGUMENT(dst_reg != src2_reg);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s.into%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",
(op & SLJIT_SHIFT_INTO_NON_ZERO) ? ".nz" : "");
sljit_verbose_reg(compiler, dst_reg);
fprintf(compiler->verbose, ", ");
sljit_verbose_reg(compiler, src1_reg);
fprintf(compiler->verbose, ", ");
sljit_verbose_reg(compiler, src2_reg);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, src3, src3w);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(op >= SLJIT_FAST_RETURN && op <= SLJIT_PREFETCH_ONCE);
FUNCTION_CHECK_SRC(src, srcw);
if (op == SLJIT_FAST_RETURN || op == SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN) {
CHECK_ARGUMENT(src != SLJIT_IMM);
compiler->last_flags = 0;
} else if (op >= SLJIT_PREFETCH_L1 && op <= SLJIT_PREFETCH_ONCE) {
CHECK_ARGUMENT(src & SLJIT_MEM);
}
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s ", op_src_dst_names[op - SLJIT_OP_SRC_DST_BASE]);
sljit_verbose_param(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(op >= SLJIT_FAST_ENTER && op <= SLJIT_GET_RETURN_ADDRESS);
FUNCTION_CHECK_DST(dst, dstw);
if (op == SLJIT_FAST_ENTER)
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s ", op_src_dst_names[op - SLJIT_OP_SRC_DST_BASE]);
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
{
SLJIT_UNUSED_ARG(type);
SLJIT_UNUSED_ARG(reg);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
if (type == SLJIT_GP_REGISTER) {
CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_REGISTERS)
|| (reg >= SLJIT_TMP_REGISTER_BASE && reg <= (SLJIT_TMP_REGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_REGISTERS)));
} else {
CHECK_ARGUMENT(type == SLJIT_FLOAT_REGISTER || ((type >> 12) == 0 || ((type >> 12) >= 3 && (type >> 12) <= 6)));
CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_FLOAT_REGISTERS)
|| (reg >= SLJIT_TMP_FREGISTER_BASE && reg <= (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)));
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_compiler *compiler,
void *instruction, sljit_u32 size)
{
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
sljit_u32 i;
#endif
SLJIT_UNUSED_ARG(compiler);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(instruction);
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
CHECK_ARGUMENT(size > 0 && size < 16);
#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
CHECK_ARGUMENT((size == 2 && (((sljit_sw)instruction) & 0x1) == 0)
|| (size == 4 && (((sljit_sw)instruction) & 0x3) == 0));
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
CHECK_ARGUMENT(size == 2 || size == 4 || size == 6);
#else
CHECK_ARGUMENT(size == 4 && (((sljit_sw)instruction) & 0x3) == 0);
#endif
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " op_custom");
for (i = 0; i < size; i++)
fprintf(compiler->verbose, " 0x%x", ((sljit_u8*)instruction)[i]);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV_F64 && GET_OPCODE(op) <= SLJIT_ABS_F64);
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
FUNCTION_FCHECK(src, srcw, op & SLJIT_32);
FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
fprintf(compiler->verbose, " %s%s ", fop1_names[SLJIT_CONV_F64_FROM_F32 - SLJIT_FOP1_BASE],
(op & SLJIT_32) ? ".f32.from.f64" : ".f64.from.f32");
else
fprintf(compiler->verbose, " %s%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
(op & SLJIT_32) ? ".f32" : ".f64");
sljit_verbose_fparam(compiler, dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->last_flags = GET_FLAG_TYPE(op) | (op & SLJIT_32);
#endif
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_CMP_F64);
CHECK_ARGUMENT(!(op & SLJIT_SET_Z));
CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK)
|| (GET_FLAG_TYPE(op) >= SLJIT_F_EQUAL && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_LESS_EQUAL));
FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);
FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_32) ? ".f32" : ".f64");
if (op & VARIABLE_FLAG_MASK) {
fprintf(compiler->verbose, ".%s", jump_names[GET_FLAG_TYPE(op)]);
}
fprintf(compiler->verbose, " ");
sljit_verbose_fparam(compiler, src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src2, src2w);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
FUNCTION_FCHECK(src, srcw, op & SLJIT_32);
FUNCTION_CHECK_DST(dst, dstw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
fop1_conv_types[GET_OPCODE(op) - SLJIT_CONV_SW_FROM_F64],
(op & SLJIT_32) ? ".f32" : ".f64");
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
FUNCTION_CHECK_SRC(src, srcw);
FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s.from.%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
(op & SLJIT_32) ? ".f32" : ".f64",
fop1_conv_types[GET_OPCODE(op) - SLJIT_CONV_SW_FROM_F64]);
sljit_verbose_fparam(compiler, dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD_F64 && GET_OPCODE(op) <= SLJIT_DIV_F64);
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);
FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);
FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s ", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE], (op & SLJIT_32) ? ".f32" : ".f64");
sljit_verbose_fparam(compiler, dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src2, src2w);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst_freg,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_COPYSIGN_F64);
FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);
FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, op & SLJIT_32));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s ", fop2r_names[GET_OPCODE(op) - SLJIT_FOP2R_BASE], (op & SLJIT_32) ? ".f32" : ".f64");
sljit_verbose_freg(compiler, dst_freg);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src2, src2w);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fset32(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f32 value)
{
SLJIT_UNUSED_ARG(value);
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 1));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " fset32 ");
sljit_verbose_freg(compiler, freg);
fprintf(compiler->verbose, ", %f\n", value);
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fset64(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f64 value)
{
SLJIT_UNUSED_ARG(value);
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " fset64 ");
sljit_verbose_freg(compiler, freg);
fprintf(compiler->verbose, ", %f\n", value);
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 freg, sljit_s32 reg)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_COPY_TO_F64 && GET_OPCODE(op) <= SLJIT_COPY_FROM_F64);
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, op & SLJIT_32));
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
#else
switch (op) {
case SLJIT_COPY32_TO_F32:
case SLJIT_COPY32_FROM_F32:
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
break;
case SLJIT_COPY_TO_F64:
case SLJIT_COPY_FROM_F64:
if (reg & REG_PAIR_MASK) {
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_FIRST(reg)));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_SECOND(reg)));
if (op == SLJIT_COPY_TO_F64)
break;
CHECK_ARGUMENT(REG_PAIR_FIRST(reg) != REG_PAIR_SECOND(reg));
break;
}
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
break;
}
#endif
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " copy%s_%s_f%s ", (op & SLJIT_32) ? "32" : "",
GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? "to" : "from", (op & SLJIT_32) ? "32" : "64");
sljit_verbose_freg(compiler, freg);
if (reg & REG_PAIR_MASK) {
fprintf(compiler->verbose, ", {");
sljit_verbose_reg(compiler, REG_PAIR_FIRST(reg));
fprintf(compiler->verbose, ", ");
sljit_verbose_reg(compiler, REG_PAIR_SECOND(reg));
fprintf(compiler->verbose, "}\n");
} else {
fprintf(compiler->verbose, ", ");
sljit_verbose_reg(compiler, reg);
fprintf(compiler->verbose, "\n");
}
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compiler *compiler)
{
SLJIT_UNUSED_ARG(compiler);
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose))
fprintf(compiler->verbose, "label:\n");
#endif
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|| (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)
#define CHECK_UNORDERED …
#else
#define CHECK_UNORDERED …
#endif
#endif
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
{
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_FAST_CALL);
if ((type & 0xff) < SLJIT_JUMP) {
if ((type & 0xff) <= SLJIT_NOT_ZERO)
CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {
CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);
compiler->last_flags = 0;
} else
CHECK_ARGUMENT((type & 0xfe) == (compiler->last_flags & 0xff)
|| CHECK_UNORDERED(type, compiler->last_flags));
}
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose))
fprintf(compiler->verbose, " jump%s %s\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
jump_names[type & 0xff]);
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 arg_types)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_CALL_RETURN)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG);
CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));
if (type & SLJIT_CALL_RETURN) {
CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);
if (compiler->options & SLJIT_ENTER_REG_ARG) {
CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG);
} else {
CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG);
}
}
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s%s ret[%s", jump_names[type & 0xff],
!(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
!(type & SLJIT_CALL_RETURN) ? "" : ".ret",
call_arg_names[arg_types & SLJIT_ARG_MASK]);
arg_types >>= SLJIT_ARG_SHIFT;
if (arg_types) {
fprintf(compiler->verbose, "], args[");
do {
fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);
arg_types >>= SLJIT_ARG_SHIFT;
if (arg_types)
fprintf(compiler->verbose, ",");
} while (arg_types);
}
fprintf(compiler->verbose, "]\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_SIG_LESS_EQUAL);
FUNCTION_CHECK_SRC(src1, src1w);
FUNCTION_CHECK_SRC(src2, src2w);
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " cmp%s%s %s, ", (type & SLJIT_32) ? "32" : "",
!(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);
sljit_verbose_param(compiler, src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, src2, src2w);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_F_EQUAL && (type & 0xff) <= SLJIT_ORDERED_LESS_EQUAL);
FUNCTION_FCHECK(src1, src1w, type & SLJIT_32);
FUNCTION_FCHECK(src2, src2w, type & SLJIT_32);
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " fcmp%s%s %s, ", (type & SLJIT_32) ? ".f32" : ".f64",
!(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);
sljit_verbose_fparam(compiler, src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src2, src2w);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 src, sljit_sw srcw)
{
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(type >= SLJIT_JUMP && type <= SLJIT_FAST_CALL);
FUNCTION_CHECK_SRC(src, srcw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " ijump.%s ", jump_names[type]);
sljit_verbose_param(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 arg_types,
sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_CALL_RETURN)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG);
CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));
FUNCTION_CHECK_SRC(src, srcw);
if (type & SLJIT_CALL_RETURN) {
CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);
if (compiler->options & SLJIT_ENTER_REG_ARG) {
CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG);
} else {
CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG);
}
}
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " i%s%s ret[%s", jump_names[type & 0xff],
!(type & SLJIT_CALL_RETURN) ? "" : ".ret",
call_arg_names[arg_types & SLJIT_ARG_MASK]);
arg_types >>= SLJIT_ARG_SHIFT;
if (arg_types) {
fprintf(compiler->verbose, "], args[");
do {
fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);
arg_types >>= SLJIT_ARG_SHIFT;
if (arg_types)
fprintf(compiler->verbose, ",");
} while (arg_types);
}
fprintf(compiler->verbose, "], ");
sljit_verbose_param(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 type)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(type >= SLJIT_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL);
CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV32
|| (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR));
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
if (type <= SLJIT_NOT_ZERO)
CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
else
CHECK_ARGUMENT((type & 0xfe) == (compiler->last_flags & 0xff)
|| CHECK_UNORDERED(type, compiler->last_flags));
FUNCTION_CHECK_DST(dst, dstw);
if (GET_OPCODE(op) >= SLJIT_ADD)
compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " flags.%s%s%s ",
GET_OPCODE(op) < SLJIT_OP2_BASE ? "mov" : op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],
GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_32) ? "32" : ""),
!(op & SLJIT_SET_Z) ? "" : ".z");
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, ", %s\n", jump_names[type]);
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 dst_reg,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2_reg)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
sljit_s32 cond = type & ~SLJIT_32;
CHECK_ARGUMENT(cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL);
CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));
FUNCTION_CHECK_SRC(src1, src1w);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src2_reg));
if (cond <= SLJIT_NOT_ZERO)
CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {
CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);
compiler->last_flags = 0;
} else
CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff)
|| CHECK_UNORDERED(cond, compiler->last_flags));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " select%s %s, ",
!(type & SLJIT_32) ? "" : "32",
jump_names[type & ~SLJIT_32]);
sljit_verbose_reg(compiler, dst_reg);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_reg(compiler, src2_reg);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 dst_freg,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2_freg)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
sljit_s32 cond = type & ~SLJIT_32;
CHECK_ARGUMENT(cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL);
CHECK_ARGUMENT(compiler->fscratches != -1 && compiler->fsaveds != -1);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, type & SLJIT_32));
FUNCTION_FCHECK(src1, src1w, type & SLJIT_32);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src2_freg, type & SLJIT_32));
if (cond <= SLJIT_NOT_ZERO)
CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {
CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);
compiler->last_flags = 0;
} else
CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff)
|| CHECK_UNORDERED(cond, compiler->last_flags));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " fselect%s %s, ",
!(type & SLJIT_32) ? "" : "32",
jump_names[type & ~SLJIT_32]);
sljit_verbose_freg(compiler, dst_freg);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_freg(compiler, src2_freg);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 reg,
sljit_s32 mem, sljit_sw memw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
sljit_s32 allowed_flags;
#endif
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
if (type & SLJIT_MEM_UNALIGNED) {
CHECK_ARGUMENT(!(type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)));
} else if (type & SLJIT_MEM_ALIGNED_16) {
CHECK_ARGUMENT(!(type & SLJIT_MEM_ALIGNED_32));
} else {
CHECK_ARGUMENT((reg & REG_PAIR_MASK) || (type & SLJIT_MEM_ALIGNED_32));
}
allowed_flags = SLJIT_MEM_UNALIGNED;
switch (type & 0xff) {
case SLJIT_MOV_P:
case SLJIT_MOV:
allowed_flags |= SLJIT_MEM_ALIGNED_32;
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
case SLJIT_MOV32:
allowed_flags |= SLJIT_MEM_ALIGNED_16;
break;
}
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | allowed_flags)) == 0);
if (reg & REG_PAIR_MASK) {
CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_FIRST(reg)));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_SECOND(reg)));
CHECK_ARGUMENT(REG_PAIR_FIRST(reg) != REG_PAIR_SECOND(reg));
} else {
CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);
CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) >= SLJIT_MOV_U8 && (type & 0xff) <= SLJIT_MOV_S16));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
}
FUNCTION_CHECK_SRC_MEM(mem, memw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if ((type & 0xff) == SLJIT_MOV32)
fprintf(compiler->verbose, " %s32",
(type & SLJIT_MEM_STORE) ? "store" : "load");
else
fprintf(compiler->verbose, " %s%s%s",
(type & SLJIT_MEM_STORE) ? "store" : "load",
!(type & SLJIT_32) ? "" : "32", op1_types[(type & 0xff) - SLJIT_OP1_BASE]);
if (type & SLJIT_MEM_UNALIGNED)
printf(".unal");
else if (type & SLJIT_MEM_ALIGNED_16)
printf(".al16");
else if (type & SLJIT_MEM_ALIGNED_32)
printf(".al32");
if (reg & REG_PAIR_MASK) {
fprintf(compiler->verbose, " {");
sljit_verbose_reg(compiler, REG_PAIR_FIRST(reg));
fprintf(compiler->verbose, ", ");
sljit_verbose_reg(compiler, REG_PAIR_SECOND(reg));
fprintf(compiler->verbose, "}, ");
} else {
fprintf(compiler->verbose, " ");
sljit_verbose_reg(compiler, reg);
fprintf(compiler->verbose, ", ");
}
sljit_verbose_param(compiler, mem, memw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 reg,
sljit_s32 mem, sljit_sw memw)
{
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0);
CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg);
FUNCTION_CHECK_SRC_MEM(mem, memw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (type & SLJIT_MEM_SUPP)
CHECK_RETURN_OK;
if (sljit_emit_mem_update(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED) {
fprintf(compiler->verbose, " # mem: unsupported form, no instructions are emitted\n");
CHECK_RETURN_OK;
}
if ((type & 0xff) == SLJIT_MOV32)
fprintf(compiler->verbose, " %s32.%s ",
(type & SLJIT_MEM_STORE) ? "store" : "load",
(type & SLJIT_MEM_POST) ? "post" : "pre");
else
fprintf(compiler->verbose, " %s%s%s.%s ",
(type & SLJIT_MEM_STORE) ? "store" : "load",
!(type & SLJIT_32) ? "" : "32",
op1_types[(type & 0xff) - SLJIT_OP1_BASE],
(type & SLJIT_MEM_POST) ? "post" : "pre");
sljit_verbose_reg(compiler, reg);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, mem, memw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 mem, sljit_sw memw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);
if (type & SLJIT_MEM_UNALIGNED) {
CHECK_ARGUMENT(!(type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)));
} else if (type & SLJIT_MEM_ALIGNED_16) {
CHECK_ARGUMENT(!(type & SLJIT_MEM_ALIGNED_32));
} else {
CHECK_ARGUMENT(type & SLJIT_MEM_ALIGNED_32);
CHECK_ARGUMENT(!(type & SLJIT_32));
}
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, type & SLJIT_32));
FUNCTION_CHECK_SRC_MEM(mem, memw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s.%s",
(type & SLJIT_MEM_STORE) ? "store" : "load",
!(type & SLJIT_32) ? "f64" : "f32");
if (type & SLJIT_MEM_UNALIGNED)
printf(".unal");
else if (type & SLJIT_MEM_ALIGNED_16)
printf(".al16");
else if (type & SLJIT_MEM_ALIGNED_32)
printf(".al32");
fprintf(compiler->verbose, " ");
sljit_verbose_freg(compiler, freg);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, mem, memw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 mem, sljit_sw memw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0);
FUNCTION_CHECK_SRC_MEM(mem, memw);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, type & SLJIT_32));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (type & SLJIT_MEM_SUPP)
CHECK_RETURN_OK;
if (sljit_emit_fmem_update(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED) {
fprintf(compiler->verbose, " # fmem: unsupported form, no instructions are emitted\n");
CHECK_RETURN_OK;
}
fprintf(compiler->verbose, " %s.%s.%s ",
(type & SLJIT_MEM_STORE) ? "store" : "load",
!(type & SLJIT_32) ? "f64" : "f32",
(type & SLJIT_MEM_POST) ? "post" : "pre");
sljit_verbose_freg(compiler, freg);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, mem, memw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 srcdst, sljit_sw srcdstw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(SLJIT_SIMD_STORE)) == 0);
CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) <= SLJIT_SIMD_GET_REG_SIZE(type));
CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) <= (srcdst & SLJIT_MEM) ? SLJIT_SIMD_GET_REG_SIZE(type) : 0);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));
FUNCTION_FCHECK(srcdst, srcdstw, 0);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (type & SLJIT_SIMD_TEST)
CHECK_RETURN_OK;
if (sljit_emit_simd_mov(compiler, type | SLJIT_SIMD_TEST, freg, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) {
fprintf(compiler->verbose, " # simd_mem: unsupported form, no instructions are emitted\n");
CHECK_RETURN_OK;
}
fprintf(compiler->verbose, " simd_%s.%d.%s%d",
(type & SLJIT_SIMD_STORE) ? "store" : "load",
(8 << SLJIT_SIMD_GET_REG_SIZE(type)),
(type & SLJIT_SIMD_FLOAT) ? "f" : "",
(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
if ((type & 0x3f000000) == SLJIT_SIMD_MEM_UNALIGNED)
fprintf(compiler->verbose, ".unal ");
else
fprintf(compiler->verbose, ".al%d ", (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type)));
sljit_verbose_freg(compiler, freg);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, srcdst, srcdstw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) == 0);
CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));
if (type & SLJIT_SIMD_FLOAT) {
if (src == SLJIT_IMM) {
CHECK_ARGUMENT(srcw == 0);
} else {
FUNCTION_FCHECK(src, srcw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2);
}
} else if (src != SLJIT_IMM) {
FUNCTION_CHECK_DST(src, srcw);
}
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (type & SLJIT_SIMD_TEST)
CHECK_RETURN_OK;
if (sljit_emit_simd_replicate(compiler, type | SLJIT_SIMD_TEST, freg, src, srcw) == SLJIT_ERR_UNSUPPORTED) {
fprintf(compiler->verbose, " # simd_dup: unsupported form, no instructions are emitted\n");
CHECK_RETURN_OK;
}
fprintf(compiler->verbose, " simd_replicate.%d.%s%d ",
(8 << SLJIT_SIMD_GET_REG_SIZE(type)),
(type & SLJIT_SIMD_FLOAT) ? "f" : "",
(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
sljit_verbose_freg(compiler, freg);
fprintf(compiler->verbose, ", ");
if (type & SLJIT_SIMD_FLOAT)
sljit_verbose_fparam(compiler, src, srcw);
else
sljit_verbose_param(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg, sljit_s32 lane_index,
sljit_s32 srcdst, sljit_sw srcdstw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO | SLJIT_SIMD_LANE_SIGNED | SLJIT_32)) == 0);
CHECK_ARGUMENT((type & (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO)) != (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO));
CHECK_ARGUMENT((type & (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_SIGNED)) != SLJIT_SIMD_LANE_SIGNED);
CHECK_ARGUMENT(!(type & SLJIT_SIMD_FLOAT) || !(type & (SLJIT_SIMD_LANE_SIGNED | SLJIT_32)));
CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));
CHECK_ARGUMENT(!(type & SLJIT_32) || SLJIT_SIMD_GET_ELEM_SIZE(type) <= 2);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));
CHECK_ARGUMENT(lane_index >= 0 && lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type))));
if (type & SLJIT_SIMD_FLOAT) {
FUNCTION_FCHECK(srcdst, srcdstw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2);
} else if ((type & SLJIT_SIMD_STORE) || srcdst != SLJIT_IMM) {
FUNCTION_CHECK_DST(srcdst, srcdstw);
}
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (type & SLJIT_SIMD_TEST)
CHECK_RETURN_OK;
if (sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_TEST, freg, lane_index, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) {
fprintf(compiler->verbose, " # simd_move_lane: unsupported form, no instructions are emitted\n");
CHECK_RETURN_OK;
}
fprintf(compiler->verbose, " simd_%s_lane%s%s%s.%d.%s%d ",
(type & SLJIT_SIMD_STORE) ? "store" : "load",
(type & SLJIT_32) ? "32" : "",
(type & SLJIT_SIMD_LANE_ZERO) ? "_z" : "",
(type & SLJIT_SIMD_LANE_SIGNED) ? "_s" : "",
(8 << SLJIT_SIMD_GET_REG_SIZE(type)),
(type & SLJIT_SIMD_FLOAT) ? "f" : "",
(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
sljit_verbose_freg(compiler, freg);
fprintf(compiler->verbose, "[%d], ", lane_index);
if (type & SLJIT_SIMD_FLOAT)
sljit_verbose_fparam(compiler, srcdst, srcdstw);
else
sljit_verbose_param(compiler, srcdst, srcdstw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 src, sljit_s32 src_lane_index)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) == 0);
CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src, 0));
CHECK_ARGUMENT(src_lane_index >= 0 && src_lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type))));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (type & SLJIT_SIMD_TEST)
CHECK_RETURN_OK;
if (sljit_emit_simd_lane_replicate(compiler, type | SLJIT_SIMD_TEST, freg, src, src_lane_index) == SLJIT_ERR_UNSUPPORTED) {
fprintf(compiler->verbose, " # simd_lane_replicate: unsupported form, no instructions are emitted\n");
CHECK_RETURN_OK;
}
fprintf(compiler->verbose, " simd_lane_replicate.%d.%s%d ",
(8 << SLJIT_SIMD_GET_REG_SIZE(type)),
(type & SLJIT_SIMD_FLOAT) ? "f" : "",
(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
sljit_verbose_freg(compiler, freg);
fprintf(compiler->verbose, ", ");
sljit_verbose_freg(compiler, src);
fprintf(compiler->verbose, "[%d]\n", src_lane_index);
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(SLJIT_SIMD_EXTEND_SIGNED)) == 0);
CHECK_ARGUMENT((type & (SLJIT_SIMD_EXTEND_SIGNED | SLJIT_SIMD_FLOAT)) != (SLJIT_SIMD_EXTEND_SIGNED | SLJIT_SIMD_FLOAT));
CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));
CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_ELEM2_SIZE(type));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));
FUNCTION_FCHECK(src, srcw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (type & SLJIT_SIMD_TEST)
CHECK_RETURN_OK;
if (sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_TEST, freg, src, srcw) == SLJIT_ERR_UNSUPPORTED) {
fprintf(compiler->verbose, " # simd_extend: unsupported form, no instructions are emitted\n");
CHECK_RETURN_OK;
}
fprintf(compiler->verbose, " simd_load_extend%s.%d.%s%d.%s%d ",
(type & SLJIT_SIMD_EXTEND_SIGNED) ? "_s" : "",
(8 << SLJIT_SIMD_GET_REG_SIZE(type)),
(type & SLJIT_SIMD_FLOAT) ? "f" : "",
(8 << SLJIT_SIMD_GET_ELEM2_SIZE(type)),
(type & SLJIT_SIMD_FLOAT) ? "f" : "",
(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
sljit_verbose_freg(compiler, freg);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 dst, sljit_sw dstw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(SLJIT_32)) == SLJIT_SIMD_STORE);
CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));
FUNCTION_CHECK_DST(dst, dstw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (type & SLJIT_SIMD_TEST)
CHECK_RETURN_OK;
if (sljit_emit_simd_sign(compiler, type | SLJIT_SIMD_TEST, freg, dst, dstw) == SLJIT_ERR_UNSUPPORTED) {
fprintf(compiler->verbose, " # simd_sign: unsupported form, no instructions are emitted\n");
CHECK_RETURN_OK;
}
fprintf(compiler->verbose, " simd_store_sign%s.%d.%s%d ",
(type & SLJIT_32) ? "32" : "",
(8 << SLJIT_SIMD_GET_REG_SIZE(type)),
(type & SLJIT_SIMD_FLOAT) ? "f" : "",
(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
sljit_verbose_freg(compiler, freg);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) >= SLJIT_SIMD_OP2_AND && (type & SLJIT_SIMD_TYPE_MASK(0)) <= SLJIT_SIMD_OP2_XOR);
CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) <= SLJIT_SIMD_GET_REG_SIZE(type));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, 0));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src1_freg, 0));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src2_freg, 0));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (type & SLJIT_SIMD_TEST)
CHECK_RETURN_OK;
if (sljit_emit_simd_op2(compiler, type | SLJIT_SIMD_TEST, dst_freg, src1_freg, src2_freg) == SLJIT_ERR_UNSUPPORTED) {
fprintf(compiler->verbose, " # simd_op2: unsupported form, no instructions are emitted\n");
CHECK_RETURN_OK;
}
fprintf(compiler->verbose, " simd_%s.%d.%s%d ",
simd_op2_names[SLJIT_SIMD_GET_OPCODE(type) - 1],
(8 << SLJIT_SIMD_GET_REG_SIZE(type)),
(type & SLJIT_SIMD_FLOAT) ? "f" : "",
(8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
sljit_verbose_freg(compiler, dst_freg);
fprintf(compiler->verbose, ", ");
sljit_verbose_freg(compiler, src1_freg);
fprintf(compiler->verbose, ", ");
sljit_verbose_freg(compiler, src2_freg);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
{
SLJIT_UNUSED_ARG(offset);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
FUNCTION_CHECK_DST(dst, dstw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " local_base ");
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", offset);
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
SLJIT_UNUSED_ARG(init_value);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
FUNCTION_CHECK_DST(dst, dstw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " const ");
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", init_value);
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
FUNCTION_CHECK_DST(dst, dstw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " put_label ");
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
#else
#define SLJIT_SKIP_CHECKS(compiler) …
#endif
#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) …
#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6))
static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 reg,
sljit_s32 mem, sljit_sw memw)
{ … }
#endif
#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) \
&& !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)
static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 mem, sljit_sw memw)
{ … }
#endif
#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
#define SLJIT_CPUINFO_PART1 …
#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
#define SLJIT_CPUINFO_PART1 …
#else
#error "Internal error: CPU type info missing"
#endif
#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
#define SLJIT_CPUINFO_PART2 …
#elif (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)
#define SLJIT_CPUINFO_PART2 …
#else
#error "Internal error: CPU type info missing"
#endif
#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED)
#define SLJIT_CPUINFO_PART3 …
#else
#define SLJIT_CPUINFO_PART3 …
#endif
#define SLJIT_CPUINFO …
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
# include "sljitNativeX86_common.c"
#elif (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
# include "sljitNativeARM_32.c"
#elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
# include "sljitNativeARM_32.c"
#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
# include "sljitNativeARM_T2_32.c"
#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
# include "sljitNativeARM_64.c"
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
# include "sljitNativePPC_common.c"
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
# include "sljitNativeMIPS_common.c"
#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
# include "sljitNativeRISCV_common.c"
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
# include "sljitNativeS390X.c"
#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
# include "sljitNativeLOONGARCH_64.c"
#endif
static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
{ … }
#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
&& !((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && defined __SOFTFP__)
static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
{ … }
#endif
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
{ … }
#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
&& !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
&& !(defined(SLJIT_CONFIG_LOONGARCH_64) && SLJIT_CONFIG_LOONGARCH_64)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst_freg,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
CHECK_ERROR();
CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_fop2(compiler, op, dst_freg, 0, src1, src1w, src2, src2w);
}
#endif
#if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
&& !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
&& !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{ … }
#endif
#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
{
switch (type) {
case SLJIT_UNORDERED_OR_EQUAL:
case SLJIT_ORDERED_NOT_EQUAL:
return 1;
}
return 0;
}
#endif
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{ … }
#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 reg,
sljit_s32 mem, sljit_sw memw)
{ … }
#endif
#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
&& !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 mem, sljit_sw memw)
{ … }
#endif
#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 mem, sljit_sw memw)
{ … }
#endif
#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
&& !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
&& !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 srcdst, sljit_sw srcdstw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw));
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
SLJIT_UNUSED_ARG(freg);
SLJIT_UNUSED_ARG(srcdst);
SLJIT_UNUSED_ARG(srcdstw);
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw));
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
SLJIT_UNUSED_ARG(freg);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg, sljit_s32 lane_index,
sljit_s32 srcdst, sljit_sw srcdstw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw));
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
SLJIT_UNUSED_ARG(freg);
SLJIT_UNUSED_ARG(lane_index);
SLJIT_UNUSED_ARG(srcdst);
SLJIT_UNUSED_ARG(srcdstw);
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 src, sljit_s32 src_lane_index)
{
CHECK_ERROR();
CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index));
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
SLJIT_UNUSED_ARG(freg);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(src_lane_index);
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw));
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
SLJIT_UNUSED_ARG(freg);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 dst, sljit_sw dstw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw));
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
SLJIT_UNUSED_ARG(freg);
SLJIT_UNUSED_ARG(dst);
SLJIT_UNUSED_ARG(dstw);
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg)
{
CHECK_ERROR();
CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg));
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
SLJIT_UNUSED_ARG(dst_freg);
SLJIT_UNUSED_ARG(src1_freg);
SLJIT_UNUSED_ARG(src2_freg);
return SLJIT_ERR_UNSUPPORTED;
}
#endif
#if !(defined(SLJIT_CONFIG_X86) && SLJIT_CONFIG_X86) \
&& !(defined(SLJIT_CONFIG_ARM) && SLJIT_CONFIG_ARM) \
&& !(defined(SLJIT_CONFIG_S390X) && SLJIT_CONFIG_S390X) \
&& !(defined(SLJIT_CONFIG_LOONGARCH) && SLJIT_CONFIG_LOONGARCH)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler,
sljit_s32 op,
sljit_s32 dst_reg,
sljit_s32 mem_reg)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
SLJIT_UNUSED_ARG(dst_reg);
SLJIT_UNUSED_ARG(mem_reg);
CHECK_ERROR();
CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler,
sljit_s32 op,
sljit_s32 src_reg,
sljit_s32 mem_reg,
sljit_s32 temp_reg)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
SLJIT_UNUSED_ARG(src_reg);
SLJIT_UNUSED_ARG(mem_reg);
SLJIT_UNUSED_ARG(temp_reg);
CHECK_ERROR();
CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
return SLJIT_ERR_UNSUPPORTED;
}
#endif
#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
{
CHECK_ERROR();
CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
SLJIT_SKIP_CHECKS(compiler);
if (offset != 0)
return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0);
}
#endif
#endif