version 1.1.1.3, 2012/10/09 09:19:18
|
version 1.1.1.4, 2013/07/22 08:25:57
|
Line 34
|
Line 34
|
|
|
Short description |
Short description |
Advantages: |
Advantages: |
- The execution can be continued from any LIR instruction | - The execution can be continued from any LIR instruction. In other |
In other words, jump into and out of the code is safe | words, it is possible to jump to any label from anywhere, even from |
- Both target of (conditional) jump and call instructions | a code fragment, which is compiled later, if both compiled code |
and constants can be dynamically modified during runtime | shares the same context. See sljit_emit_enter for more details |
| - Supports self modifying code: target of (conditional) jump and call |
| instructions and some constant values can be dynamically modified |
| during runtime |
- although it is not suggested to do it frequently |
- although it is not suggested to do it frequently |
- very effective to cache an important value once | - can be used for inline caching: save an important value once |
| in the instruction stream |
| - since this feature limits the optimization possibilities, a |
| special flag must be passed at compile time when these |
| instructions are emitted |
- A fixed stack space can be allocated for local variables |
- A fixed stack space can be allocated for local variables |
- The compiler is thread-safe |
- The compiler is thread-safe |
- The compiler is highly configurable through preprocessor macros. |
- The compiler is highly configurable through preprocessor macros. |
Line 47
|
Line 54
|
threaded applications), and you can use your own system functions |
threaded applications), and you can use your own system functions |
(including memory allocators). See sljitConfig.h |
(including memory allocators). See sljitConfig.h |
Disadvantages: |
Disadvantages: |
|
- No automatic register allocation, and temporary results are |
|
not stored on the stack. (hence the name comes) |
- Limited number of registers (only 6+4 integer registers, max 3+2 |
- Limited number of registers (only 6+4 integer registers, max 3+2 |
temporary, max 3+2 saved and 4 floating point registers) | scratch, max 3+2 saved and 6 floating point registers) |
In practice: |
In practice: |
- This approach is very effective for interpreters |
- This approach is very effective for interpreters |
- One of the saved registers typically points to a stack interface |
- One of the saved registers typically points to a stack interface |
- It can jump to any exception handler anytime (even for another | - It can jump to any exception handler anytime (even if it belongs |
function. It is safe for SLJIT.) | to another function) |
- Fast paths can be modified during runtime reflecting the changes | - Hot paths can be modified during runtime reflecting the changes |
of the fastest execution path of the dynamic language |
of the fastest execution path of the dynamic language |
- SLJIT supports complex memory addressing modes |
- SLJIT supports complex memory addressing modes |
- mainly position independent code | - mainly position and context independent code (except some cases) |
- Optimizations (perhaps later) | |
- Only for basic blocks (when no labels inserted between LIR instructions) | |
|
|
For valgrind users: |
For valgrind users: |
- pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code" |
- pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code" |
Line 70
|
Line 77
|
#endif |
#endif |
|
|
/* The following header file defines useful macros for fine tuning |
/* The following header file defines useful macros for fine tuning |
sljit based code generators. They are listed in the begining | sljit based code generators. They are listed in the beginning |
of sljitConfigInternal.h */ |
of sljitConfigInternal.h */ |
|
|
#include "sljitConfigInternal.h" |
#include "sljitConfigInternal.h" |
Line 99 of sljitConfigInternal.h */
|
Line 106 of sljitConfigInternal.h */
|
|
|
#define SLJIT_UNUSED 0 |
#define SLJIT_UNUSED 0 |
|
|
/* Temporary (scratch) registers may not preserve their values across function calls. */ | /* Scratch (temporary) registers whose may not preserve their values |
#define SLJIT_TEMPORARY_REG1 1 | across function calls. */ |
#define SLJIT_TEMPORARY_REG2 2 | #define SLJIT_SCRATCH_REG1 1 |
#define SLJIT_TEMPORARY_REG3 3 | #define SLJIT_SCRATCH_REG2 2 |
/* Note: Extra Registers cannot be used for memory addressing. */ | #define SLJIT_SCRATCH_REG3 3 |
/* Note: on x86-32, these registers are emulated (using stack loads & stores). */ | /* Note: extra registers cannot be used for memory addressing. */ |
| /* Note: on x86-32, these registers are emulated (using stack |
| loads & stores). */ |
#define SLJIT_TEMPORARY_EREG1 4 |
#define SLJIT_TEMPORARY_EREG1 4 |
#define SLJIT_TEMPORARY_EREG2 5 |
#define SLJIT_TEMPORARY_EREG2 5 |
|
|
Line 112 of sljitConfigInternal.h */
|
Line 121 of sljitConfigInternal.h */
|
#define SLJIT_SAVED_REG1 6 |
#define SLJIT_SAVED_REG1 6 |
#define SLJIT_SAVED_REG2 7 |
#define SLJIT_SAVED_REG2 7 |
#define SLJIT_SAVED_REG3 8 |
#define SLJIT_SAVED_REG3 8 |
/* Note: Extra Registers cannot be used for memory addressing. */ | /* Note: extra registers cannot be used for memory addressing. */ |
/* Note: on x86-32, these registers are emulated (using stack loads & stores). */ | /* Note: on x86-32, these registers are emulated (using stack |
| loads & stores). */ |
#define SLJIT_SAVED_EREG1 9 |
#define SLJIT_SAVED_EREG1 9 |
#define SLJIT_SAVED_EREG2 10 |
#define SLJIT_SAVED_EREG2 10 |
|
|
/* Read-only register (cannot be the destination of an operation). |
/* Read-only register (cannot be the destination of an operation). |
Only SLJIT_MEM1(SLJIT_LOCALS_REG) addressing mode is allowed since |
Only SLJIT_MEM1(SLJIT_LOCALS_REG) addressing mode is allowed since |
several ABIs has certain limitations about the stack layout. However |
several ABIs has certain limitations about the stack layout. However |
sljit_get_local_base() can be used to obtain the offset of a value. */ | sljit_get_local_base() can be used to obtain the offset of a value |
| on the stack. */ |
#define SLJIT_LOCALS_REG 11 |
#define SLJIT_LOCALS_REG 11 |
|
|
/* Number of registers. */ |
/* Number of registers. */ |
Line 130 of sljitConfigInternal.h */
|
Line 141 of sljitConfigInternal.h */
|
|
|
/* Return with machine word. */ |
/* Return with machine word. */ |
|
|
#define SLJIT_RETURN_REG SLJIT_TEMPORARY_REG1 | #define SLJIT_RETURN_REG SLJIT_SCRATCH_REG1 |
|
|
/* x86 prefers specific registers for special purposes. In case of shift |
/* x86 prefers specific registers for special purposes. In case of shift |
by register it supports only SLJIT_TEMPORARY_REG3 for shift argument | by register it supports only SLJIT_SCRATCH_REG3 for shift argument |
(which is the src2 argument of sljit_emit_op2). If another register is |
(which is the src2 argument of sljit_emit_op2). If another register is |
used, sljit must exchange data between registers which cause a minor |
used, sljit must exchange data between registers which cause a minor |
slowdown. Other architectures has no such limitation. */ |
slowdown. Other architectures has no such limitation. */ |
|
|
#define SLJIT_PREF_SHIFT_REG SLJIT_TEMPORARY_REG3 | #define SLJIT_PREF_SHIFT_REG SLJIT_SCRATCH_REG3 |
|
|
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
/* Floating point registers */ |
/* Floating point registers */ |
Line 147 of sljitConfigInternal.h */
|
Line 158 of sljitConfigInternal.h */
|
/* Note: SLJIT_UNUSED as destination is not valid for floating point |
/* Note: SLJIT_UNUSED as destination is not valid for floating point |
operations, since they cannot be used for setting flags. */ |
operations, since they cannot be used for setting flags. */ |
|
|
/* Floating point operations are performed on double precision values. */ | /* Floating point operations are performed on double or |
| single precision values. */ |
|
|
#define SLJIT_FLOAT_REG1 1 | #define SLJIT_FLOAT_REG1 1 |
#define SLJIT_FLOAT_REG2 2 | #define SLJIT_FLOAT_REG2 2 |
#define SLJIT_FLOAT_REG3 3 | #define SLJIT_FLOAT_REG3 3 |
#define SLJIT_FLOAT_REG4 4 | #define SLJIT_FLOAT_REG4 4 |
| #define SLJIT_FLOAT_REG5 5 |
| #define SLJIT_FLOAT_REG6 6 |
|
|
|
#define SLJIT_NO_FLOAT_REGISTERS 6 |
|
|
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
/* Main structures and functions */ |
/* Main structures and functions */ |
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
Line 161 of sljitConfigInternal.h */
|
Line 177 of sljitConfigInternal.h */
|
struct sljit_memory_fragment { |
struct sljit_memory_fragment { |
struct sljit_memory_fragment *next; |
struct sljit_memory_fragment *next; |
sljit_uw used_size; |
sljit_uw used_size; |
|
/* Must be aligned to sljit_sw. */ |
sljit_ub memory[1]; |
sljit_ub memory[1]; |
}; |
}; |
|
|
Line 174 struct sljit_label {
|
Line 191 struct sljit_label {
|
struct sljit_jump { |
struct sljit_jump { |
struct sljit_jump *next; |
struct sljit_jump *next; |
sljit_uw addr; |
sljit_uw addr; |
sljit_w flags; | sljit_sw flags; |
union { |
union { |
sljit_uw target; |
sljit_uw target; |
struct sljit_label* label; |
struct sljit_label* label; |
Line 187 struct sljit_const {
|
Line 204 struct sljit_const {
|
}; |
}; |
|
|
struct sljit_compiler { |
struct sljit_compiler { |
int error; | sljit_si error; |
|
|
struct sljit_label *labels; |
struct sljit_label *labels; |
struct sljit_jump *jumps; |
struct sljit_jump *jumps; |
Line 200 struct sljit_compiler {
|
Line 217 struct sljit_compiler {
|
struct sljit_memory_fragment *abuf; |
struct sljit_memory_fragment *abuf; |
|
|
/* Used local registers. */ |
/* Used local registers. */ |
int temporaries; | sljit_si scratches; |
/* Used saved registers. */ |
/* Used saved registers. */ |
int saveds; | sljit_si saveds; |
/* Local stack size. */ |
/* Local stack size. */ |
int local_size; | sljit_si local_size; |
/* Code size. */ |
/* Code size. */ |
sljit_uw size; |
sljit_uw size; |
/* For statistical purposes. */ |
/* For statistical purposes. */ |
sljit_uw executable_size; |
sljit_uw executable_size; |
|
|
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) |
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) |
int args; | sljit_si args; |
int locals_offset; | sljit_si locals_offset; |
int temporaries_start; | sljit_si scratches_start; |
int saveds_start; | sljit_si saveds_start; |
#endif |
#endif |
|
|
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
int mode32; | sljit_si mode32; |
#endif |
#endif |
|
|
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
int flags_saved; | sljit_si flags_saved; |
#endif |
#endif |
|
|
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
Line 239 struct sljit_compiler {
|
Line 256 struct sljit_compiler {
|
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) |
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) |
/* Temporary fields. */ |
/* Temporary fields. */ |
sljit_uw shift_imm; |
sljit_uw shift_imm; |
int cache_arg; | sljit_si cache_arg; |
sljit_w cache_argw; | sljit_sw cache_argw; |
#endif |
#endif |
|
|
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) |
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) |
int cache_arg; | sljit_si cache_arg; |
sljit_w cache_argw; | sljit_sw cache_argw; |
#endif |
#endif |
|
|
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) |
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) |
sljit_w imm; | sljit_sw imm; |
int cache_arg; | sljit_si cache_arg; |
sljit_w cache_argw; | sljit_sw cache_argw; |
#endif |
#endif |
|
|
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) |
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) |
int delay_slot; | sljit_si delay_slot; |
int cache_arg; | sljit_si cache_arg; |
sljit_w cache_argw; | sljit_sw cache_argw; |
#endif |
#endif |
|
|
|
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) |
|
sljit_si delay_slot; |
|
sljit_si cache_arg; |
|
sljit_sw cache_argw; |
|
#endif |
|
|
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) |
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) |
FILE* verbose; |
FILE* verbose; |
#endif |
#endif |
|
|
#if (defined SLJIT_DEBUG && SLJIT_DEBUG) |
#if (defined SLJIT_DEBUG && SLJIT_DEBUG) |
/* Local size passed to the functions. */ |
/* Local size passed to the functions. */ |
int logical_local_size; | sljit_si logical_local_size; |
#endif |
#endif |
|
|
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) |
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) |
int skip_checks; | sljit_si skip_checks; |
#endif |
#endif |
}; |
}; |
|
|
Line 281 struct sljit_compiler {
|
Line 304 struct sljit_compiler {
|
/* Creates an sljit compiler. |
/* Creates an sljit compiler. |
Returns NULL if failed. */ |
Returns NULL if failed. */ |
SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void); |
SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void); |
/* Free everything except the codes. */ | |
| /* Free everything except the compiled machine code. */ |
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler); |
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler); |
|
|
static SLJIT_INLINE int sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; } | /* Returns the current error code. If an error is occurred, future sljit |
| calls which uses the same compiler argument returns early with the same |
| error code. Thus there is no need for checking the error after every |
| call, it is enough to do it before the code is compiled. Removing |
| these checks increases the performance of the compiling process. */ |
| static SLJIT_INLINE sljit_si sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; } |
|
|
/* |
/* |
Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit, |
Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit, |
and <= 128 bytes on 64 bit architectures. The memory area is owned by the compiler, | and <= 128 bytes on 64 bit architectures. The memory area is owned by the |
and freed by sljit_free_compiler. The returned pointer is sizeof(sljit_w) aligned. | compiler, and freed by sljit_free_compiler. The returned pointer is |
Excellent for allocating small blocks during the compiling, and no need to worry | sizeof(sljit_sw) aligned. Excellent for allocating small blocks during |
about freeing them. The size is enough to contain at most 16 pointers. | the compiling, and no need to worry about freeing them. The size is |
If the size is outside of the range, the function will return with NULL, | enough to contain at most 16 pointers. If the size is outside of the range, |
but this return value does not indicate that there is no more memory (does | the function will return with NULL. However, this return value does not |
not set the compiler to out-of-memory status). | indicate that there is no more memory (does not set the current error code |
| of the compiler to out-of-memory status). |
*/ |
*/ |
SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size); | SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_si size); |
|
|
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) |
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) |
/* Passing NULL disables verbose. */ |
/* Passing NULL disables verbose. */ |
Line 307 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
Line 337 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code); |
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code); |
|
|
/* |
/* |
After the code generation we can retrieve the allocated executable memory size, | After the machine code generation is finished we can retrieve the allocated |
although this area may not be fully filled with instructions depending on some | executable memory size, although this area may not be fully filled with |
optimizations. This function is useful only for statistical purposes. | instructions depending on some optimizations. This function is useful only |
| for statistical purposes. |
|
|
Before a successful code generation, this function returns with 0. |
Before a successful code generation, this function returns with 0. |
*/ |
*/ |
static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; } |
static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; } |
|
|
/* Instruction generation. Returns with error code. */ | /* Instruction generation. Returns with any error code. If there is no |
| error, they return with SLJIT_SUCCESS. */ |
|
|
/* |
/* |
The executable code is basically a function call from the viewpoint of |
The executable code is basically a function call from the viewpoint of |
Line 326 static SLJIT_INLINE sljit_uw sljit_get_generated_code_
|
Line 358 static SLJIT_INLINE sljit_uw sljit_get_generated_code_
|
for the executable code and moves function arguments to the saved |
for the executable code and moves function arguments to the saved |
registers. The number of arguments are specified in the "args" |
registers. The number of arguments are specified in the "args" |
parameter and the first argument goes to SLJIT_SAVED_REG1, the second |
parameter and the first argument goes to SLJIT_SAVED_REG1, the second |
goes to SLJIT_SAVED_REG2 and so on. The number of temporary and | goes to SLJIT_SAVED_REG2 and so on. The number of scratch and |
saved registers are passed in "temporaries" and "saveds" arguments | saved registers are passed in "scratches" and "saveds" arguments |
respectively. Since the saved registers contains the arguments, |
respectively. Since the saved registers contains the arguments, |
"args" must be less or equal than "saveds". The sljit_emit_enter |
"args" must be less or equal than "saveds". The sljit_emit_enter |
is also capable of allocating a stack space for local variables. The |
is also capable of allocating a stack space for local variables. The |
Line 338 static SLJIT_INLINE sljit_uw sljit_get_generated_code_
|
Line 370 static SLJIT_INLINE sljit_uw sljit_get_generated_code_
|
SLJIT_LOCALS_REG + local_size (exclusive) can be modified freely |
SLJIT_LOCALS_REG + local_size (exclusive) can be modified freely |
until the function returns. The stack space is uninitialized. |
until the function returns. The stack space is uninitialized. |
|
|
Note: every call of sljit_emit_enter and sljit_set_context overwrites | Note: every call of sljit_emit_enter and sljit_set_context |
the previous context. */ | overwrites the previous context. */ |
|
|
#define SLJIT_MAX_LOCAL_SIZE 65536 |
#define SLJIT_MAX_LOCAL_SIZE 65536 |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, |
int args, int temporaries, int saveds, int local_size); | sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size); |
|
|
/* The machine code has a context (which contains the local stack space size, |
/* The machine code has a context (which contains the local stack space size, |
number of used registers, etc.) which initialized by sljit_emit_enter. Several |
number of used registers, etc.) which initialized by sljit_emit_enter. Several |
functions (like sljit_emit_return) requres this context to be able to generate |
functions (like sljit_emit_return) requres this context to be able to generate |
the appropriate code. However, some code fragments (like inline cache) may have |
the appropriate code. However, some code fragments (like inline cache) may have |
no normal entry point so their context is unknown for the compiler. Using the |
no normal entry point so their context is unknown for the compiler. Using the |
function below we can specify thir context. | function below we can specify their context. |
|
|
Note: every call of sljit_emit_enter and sljit_set_context overwrites |
Note: every call of sljit_emit_enter and sljit_set_context overwrites |
the previous context. */ |
the previous context. */ |
|
|
/* Note: multiple calls of this function overwrites the previous call. */ |
|
|
|
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, |
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, |
int args, int temporaries, int saveds, int local_size); | sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size); |
|
|
/* Return from machine code. The op argument can be SLJIT_UNUSED which means the |
/* Return from machine code. The op argument can be SLJIT_UNUSED which means the |
function does not return with anything or any opcode between SLJIT_MOV and |
function does not return with anything or any opcode between SLJIT_MOV and |
SLJIT_MOV_SI (see sljit_emit_op1). As for src and srcw they must be 0 if op | SLJIT_MOV_P (see sljit_emit_op1). As for src and srcw they must be 0 if op |
is SLJIT_UNUSED, otherwise see below the description about source and |
is SLJIT_UNUSED, otherwise see below the description about source and |
destination arguments. */ |
destination arguments. */ |
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, |
|
int src, sljit_w srcw); |
|
|
|
/* Really fast calling method for utility functions inside sljit (see SLJIT_FAST_CALL). | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, |
All registers and even the stack frame is passed to the callee. The return address is | sljit_si src, sljit_sw srcw); |
preserved in dst/dstw by sljit_emit_fast_enter, and sljit_emit_fast_return can | |
use this as a return value later. */ | |
|
|
/* Note: only for sljit specific, non ABI compilant calls. Fast, since only a few machine instructions | /* Fast calling mechanism for utility functions (see SLJIT_FAST_CALL). All registers and |
are needed. Excellent for small uility functions, where saving registers and setting up | even the stack frame is passed to the callee. The return address is preserved in |
a new stack frame would cost too much performance. However, it is still possible to return | dst/dstw by sljit_emit_fast_enter (the type of the value stored by this function |
to the address of the caller (or anywhere else). */ | is sljit_p), and sljit_emit_fast_return can use this as a return value later. */ |
|
|
|
/* Note: only for sljit specific, non ABI compilant calls. Fast, since only a few machine |
|
instructions are needed. Excellent for small uility functions, where saving registers |
|
and setting up a new stack frame would cost too much performance. However, it is still |
|
possible to return to the address of the caller (or anywhere else). */ |
|
|
/* Note: flags are not changed (unlike sljit_emit_enter / sljit_emit_return). */ |
/* Note: flags are not changed (unlike sljit_emit_enter / sljit_emit_return). */ |
|
|
/* Note: although sljit_emit_fast_return could be replaced by an ijump, it is not suggested, |
/* Note: although sljit_emit_fast_return could be replaced by an ijump, it is not suggested, |
since many architectures do clever branch prediction on call / return instruction pairs. */ |
since many architectures do clever branch prediction on call / return instruction pairs. */ |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw); | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw); |
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw); | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw); |
|
|
/* |
/* |
Source and destination values for arithmetical instructions |
Source and destination values for arithmetical instructions |
Line 394 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st
|
Line 425 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st
|
[imm] - absolute immediate memory address |
[imm] - absolute immediate memory address |
[reg+imm] - indirect memory address |
[reg+imm] - indirect memory address |
[reg+(reg<<imm)] - indirect indexed memory address (shift must be between 0 and 3) |
[reg+(reg<<imm)] - indirect indexed memory address (shift must be between 0 and 3) |
useful for (byte, half, int, sljit_w) array access | useful for (byte, half, int, sljit_sw) array access |
(fully supported by both x86 and ARM architectures, and cheap operation on others) |
(fully supported by both x86 and ARM architectures, and cheap operation on others) |
*/ |
*/ |
|
|
Line 404 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st
|
Line 435 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st
|
|
|
length | alignment |
length | alignment |
---------+----------- |
---------+----------- |
byte | 1 byte (not aligned) | byte | 1 byte (any physical_address is accepted) |
half | 2 byte (real_address & 0x1 == 0) | half | 2 byte (physical_address & 0x1 == 0) |
int | 4 byte (real_address & 0x3 == 0) | int | 4 byte (physical_address & 0x3 == 0) |
sljit_w | 4 byte if SLJIT_32BIT_ARCHITECTURE is defined and its value is 1 | word | 4 byte if SLJIT_32BIT_ARCHITECTURE is defined and its value is 1 |
| 8 byte if SLJIT_64BIT_ARCHITECTURE is defined and its value is 1 |
| 8 byte if SLJIT_64BIT_ARCHITECTURE is defined and its value is 1 |
|
pointer | size of sljit_p type (4 byte on 32 bit machines, 4 or 8 byte |
|
| on 64 bit machines) |
|
|
Note: different architectures have different addressing limitations | Note: Different architectures have different addressing limitations. |
Thus sljit may generate several instructions for other addressing modes | A single instruction is enough for the following addressing |
x86: all addressing modes supported, but write-back is not supported | modes. Other adrressing modes are emulated by instruction |
(requires an extra instruction). On x86-64 only 32 bit signed | sequences. This information could help to improve those code |
integers are supported by the architecture. | generators which focuses only a few architectures. |
arm: [reg+imm] supported for small immediates (-4095 <= imm <= 4095 | |
or -255 <= imm <= 255 for loading signed bytes, any halfs or doubles) | x86: [reg+imm], -2^32+1 <= imm <= 2^32-1 (full address space on x86-32) |
[reg+(reg<<imm)] are supported or requires only two instructions | [reg+(reg<<imm)] is supported |
Write back is limited to small immediates on thumb2 | [imm], -2^32+1 <= imm <= 2^32-1 is supported |
ppc: [reg+imm], -65535 <= imm <= 65535. 64 bit moves requires immediates | Write-back is not supported |
divisible by 4. [reg+reg] supported, write-back supported | arm: [reg+imm], -4095 <= imm <= 4095 or -255 <= imm <= 255 for signed |
[reg+(reg<<imm)] (imm != 0) is cheap (requires two instructions) | bytes, any halfs or floating point values) |
| [reg+(reg<<imm)] is supported |
| Write-back is supported |
| arm-t2: [reg+imm], -255 <= imm <= 4095 |
| [reg+(reg<<imm)] is supported |
| Write back is supported only for [reg+imm], where -255 <= imm <= 255 |
| ppc: [reg+imm], -65536 <= imm <= 65535. 64 bit loads/stores and 32 bit |
| signed load on 64 bit requires immediates divisible by 4. |
| [reg+imm] is not supported for signed 8 bit values. |
| [reg+reg] is supported |
| Write-back is supported except for one instruction: 32 bit signed |
| load with [reg+imm] addressing mode on 64 bit. |
| mips: [reg+imm], -65536 <= imm <= 65535 |
| sparc: [reg+imm], -4096 <= imm <= 4095 |
| [reg+reg] is supported |
*/ |
*/ |
|
|
/* Register output: simply the name of the register. |
/* Register output: simply the name of the register. |
Line 433 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st
|
Line 480 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st
|
#define SLJIT_IMM 0x200 |
#define SLJIT_IMM 0x200 |
|
|
/* Set 32 bit operation mode (I) on 64 bit CPUs. The flag is totally ignored on |
/* Set 32 bit operation mode (I) on 64 bit CPUs. The flag is totally ignored on |
32 bit CPUs. The arithmetic instruction uses only the lower 32 bit of the | 32 bit CPUs. If this flag is set for an arithmetic operation, it uses only the |
input register(s), and set the flags according to the 32 bit result. If the | lower 32 bit of the input register(s), and set the CPU status flags according |
destination is a register, the higher 32 bit of the result is undefined. | to the 32 bit result. The higher 32 bits are undefined for both the input and |
The addressing modes (SLJIT_MEM1/SLJIT_MEM2 macros) are unaffected by this flag. */ | output. However, the CPU might not ignore those higher 32 bits, like MIPS, which |
| expects it to be the sign extension of the lower 32 bit. All 32 bit operations |
| are undefined, if this condition is not fulfilled. Therefore, when SLJIT_INT_OP |
| is specified, all register arguments must be the result of other operations with |
| the same SLJIT_INT_OP flag. In other words, although a register can hold either |
| a 64 or 32 bit value, these values cannot be mixed. The only exceptions are |
| SLJIT_IMOV and SLJIT_IMOVU (SLJIT_MOV_SI/SLJIT_MOV_UI/SLJIT_MOVU_SI/SLJIT_MOV_UI |
| with SLJIT_INT_OP flag) which can convert any source argument to SLJIT_INT_OP |
| compatible result. This conversion might be unnecessary on some CPUs like x86-64, |
| since the upper 32 bit is always ignored. In this case SLJIT is clever enough |
| to not generate any instructions if the source and destination operands are the |
| same registers. Affects sljit_emit_op0, sljit_emit_op1 and sljit_emit_op2. */ |
#define SLJIT_INT_OP 0x100 |
#define SLJIT_INT_OP 0x100 |
|
|
|
/* Single precision mode (SP). This flag is similar to SLJIT_INT_OP, just |
|
it applies to floating point registers (it is even the same bit). When |
|
this flag is passed, the CPU performs single precision floating point |
|
operations. Similar to SLJIT_INT_OP, all register arguments must be the |
|
result of other floating point operations with this flag. Affects |
|
sljit_emit_fop1, sljit_emit_fop2 and sljit_emit_fcmp. */ |
|
#define SLJIT_SINGLE_OP 0x100 |
|
|
/* Common CPU status flags for all architectures (x86, ARM, PPC) |
/* Common CPU status flags for all architectures (x86, ARM, PPC) |
- carry flag |
- carry flag |
- overflow flag |
- overflow flag |
Line 480 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st
|
Line 546 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st
|
Note: may or may not cause an extra cycle wait |
Note: may or may not cause an extra cycle wait |
it can even decrease the runtime in a few cases. */ |
it can even decrease the runtime in a few cases. */ |
#define SLJIT_NOP 1 |
#define SLJIT_NOP 1 |
/* Flags: may destroy flags | /* Flags: - (may destroy flags) |
Unsigned multiplication of SLJIT_TEMPORARY_REG1 and SLJIT_TEMPORARY_REG2. | Unsigned multiplication of SLJIT_SCRATCH_REG1 and SLJIT_SCRATCH_REG2. |
Result goes to SLJIT_TEMPORARY_REG2:SLJIT_TEMPORARY_REG1 (high:low) word */ | Result goes to SLJIT_SCRATCH_REG2:SLJIT_SCRATCH_REG1 (high:low) word */ |
#define SLJIT_UMUL 2 |
#define SLJIT_UMUL 2 |
/* Flags: may destroy flags | /* Flags: - (may destroy flags) |
Signed multiplication of SLJIT_TEMPORARY_REG1 and SLJIT_TEMPORARY_REG2. | Signed multiplication of SLJIT_SCRATCH_REG1 and SLJIT_SCRATCH_REG2. |
Result goes to SLJIT_TEMPORARY_REG2:SLJIT_TEMPORARY_REG1 (high:low) word */ | Result goes to SLJIT_SCRATCH_REG2:SLJIT_SCRATCH_REG1 (high:low) word */ |
#define SLJIT_SMUL 3 |
#define SLJIT_SMUL 3 |
/* Flags: I | may destroy flags | /* Flags: I - (may destroy flags) |
Unsigned divide of the value in SLJIT_TEMPORARY_REG1 by the value in SLJIT_TEMPORARY_REG2. | Unsigned divide of the value in SLJIT_SCRATCH_REG1 by the value in SLJIT_SCRATCH_REG2. |
The result is placed in SLJIT_TEMPORARY_REG1 and the remainder goes to SLJIT_TEMPORARY_REG2. | The result is placed in SLJIT_SCRATCH_REG1 and the remainder goes to SLJIT_SCRATCH_REG2. |
Note: if SLJIT_TEMPORARY_REG2 contains 0, the behaviour is undefined. */ | Note: if SLJIT_SCRATCH_REG2 contains 0, the behaviour is undefined. */ |
#define SLJIT_UDIV 4 |
#define SLJIT_UDIV 4 |
/* Flags: I | may destroy flags | #define SLJIT_IUDIV (SLJIT_UDIV | SLJIT_INT_OP) |
Signed divide of the value in SLJIT_TEMPORARY_REG1 by the value in SLJIT_TEMPORARY_REG2. | /* Flags: I - (may destroy flags) |
The result is placed in SLJIT_TEMPORARY_REG1 and the remainder goes to SLJIT_TEMPORARY_REG2. | Signed divide of the value in SLJIT_SCRATCH_REG1 by the value in SLJIT_SCRATCH_REG2. |
Note: if SLJIT_TEMPORARY_REG2 contains 0, the behaviour is undefined. */ | The result is placed in SLJIT_SCRATCH_REG1 and the remainder goes to SLJIT_SCRATCH_REG2. |
| Note: if SLJIT_SCRATCH_REG2 contains 0, the behaviour is undefined. */ |
#define SLJIT_SDIV 5 |
#define SLJIT_SDIV 5 |
|
#define SLJIT_ISDIV (SLJIT_SDIV | SLJIT_INT_OP) |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op); | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op); |
|
|
/* Notes for MOV instructions: |
/* Notes for MOV instructions: |
U = Mov with update (post form). If source or destination defined as SLJIT_MEM1(r1) |
U = Mov with update (post form). If source or destination defined as SLJIT_MEM1(r1) |
or SLJIT_MEM2(r1, r2), r1 is increased by the sum of r2 and the constant argument |
or SLJIT_MEM2(r1, r2), r1 is increased by the sum of r2 and the constant argument |
UB = unsigned byte (8 bit) |
UB = unsigned byte (8 bit) |
SB = signed byte (8 bit) |
SB = signed byte (8 bit) |
UH = unsgined half (16 bit) | UH = unsigned half (16 bit) |
SH = unsgined half (16 bit) */ | SH = signed half (16 bit) |
| UI = unsigned int (32 bit) |
| SI = signed int (32 bit) |
| P = pointer (sljit_p) size */ |
|
|
/* Flags: - (never set any flags) */ |
/* Flags: - (never set any flags) */ |
#define SLJIT_MOV 6 |
#define SLJIT_MOV 6 |
/* Flags: - (never set any flags) */ | /* Flags: I - (never set any flags) */ |
#define SLJIT_MOV_UB 7 |
#define SLJIT_MOV_UB 7 |
/* Flags: - (never set any flags) */ | #define SLJIT_IMOV_UB (SLJIT_MOV_UB | SLJIT_INT_OP) |
| /* Flags: I - (never set any flags) */ |
#define SLJIT_MOV_SB 8 |
#define SLJIT_MOV_SB 8 |
/* Flags: - (never set any flags) */ | #define SLJIT_IMOV_SB (SLJIT_MOV_SB | SLJIT_INT_OP) |
| /* Flags: I - (never set any flags) */ |
#define SLJIT_MOV_UH 9 |
#define SLJIT_MOV_UH 9 |
/* Flags: - (never set any flags) */ | #define SLJIT_IMOV_UH (SLJIT_MOV_UH | SLJIT_INT_OP) |
| /* Flags: I - (never set any flags) */ |
#define SLJIT_MOV_SH 10 |
#define SLJIT_MOV_SH 10 |
/* Flags: - (never set any flags) */ | #define SLJIT_IMOV_SH (SLJIT_MOV_SH | SLJIT_INT_OP) |
| /* Flags: I - (never set any flags) |
| Note: see SLJIT_INT_OP for further details. */ |
#define SLJIT_MOV_UI 11 |
#define SLJIT_MOV_UI 11 |
/* Flags: - (never set any flags) */ | /* No SLJIT_INT_OP form, since it the same as SLJIT_IMOVU. */ |
| /* Flags: I - (never set any flags) |
| Note: see SLJIT_INT_OP for further details. */ |
#define SLJIT_MOV_SI 12 |
#define SLJIT_MOV_SI 12 |
|
#define SLJIT_IMOV (SLJIT_MOV_SI | SLJIT_INT_OP) |
/* Flags: - (never set any flags) */ |
/* Flags: - (never set any flags) */ |
#define SLJIT_MOVU 13 | #define SLJIT_MOV_P 13 |
/* Flags: - (never set any flags) */ |
/* Flags: - (never set any flags) */ |
#define SLJIT_MOVU_UB 14 | #define SLJIT_MOVU 14 |
| /* Flags: I - (never set any flags) */ |
| #define SLJIT_MOVU_UB 15 |
| #define SLJIT_IMOVU_UB (SLJIT_MOVU_UB | SLJIT_INT_OP) |
| /* Flags: I - (never set any flags) */ |
| #define SLJIT_MOVU_SB 16 |
| #define SLJIT_IMOVU_SB (SLJIT_MOVU_SB | SLJIT_INT_OP) |
| /* Flags: I - (never set any flags) */ |
| #define SLJIT_MOVU_UH 17 |
| #define SLJIT_IMOVU_UH (SLJIT_MOVU_UH | SLJIT_INT_OP) |
| /* Flags: I - (never set any flags) */ |
| #define SLJIT_MOVU_SH 18 |
| #define SLJIT_IMOVU_SH (SLJIT_MOVU_SH | SLJIT_INT_OP) |
| /* Flags: I - (never set any flags) |
| Note: see SLJIT_INT_OP for further details. */ |
| #define SLJIT_MOVU_UI 19 |
| /* No SLJIT_INT_OP form, since it the same as SLJIT_IMOVU. */ |
| /* Flags: I - (never set any flags) |
| Note: see SLJIT_INT_OP for further details. */ |
| #define SLJIT_MOVU_SI 20 |
| #define SLJIT_IMOVU (SLJIT_MOVU_SI | SLJIT_INT_OP) |
/* Flags: - (never set any flags) */ |
/* Flags: - (never set any flags) */ |
#define SLJIT_MOVU_SB 15 | #define SLJIT_MOVU_P 21 |
/* Flags: - (never set any flags) */ | |
#define SLJIT_MOVU_UH 16 | |
/* Flags: - (never set any flags) */ | |
#define SLJIT_MOVU_SH 17 | |
/* Flags: - (never set any flags) */ | |
#define SLJIT_MOVU_UI 18 | |
/* Flags: - (never set any flags) */ | |
#define SLJIT_MOVU_SI 19 | |
/* Flags: I | E | K */ |
/* Flags: I | E | K */ |
#define SLJIT_NOT 20 | #define SLJIT_NOT 22 |
| #define SLJIT_INOT (SLJIT_NOT | SLJIT_INT_OP) |
/* Flags: I | E | O | K */ |
/* Flags: I | E | O | K */ |
#define SLJIT_NEG 21 | #define SLJIT_NEG 23 |
| #define SLJIT_INEG (SLJIT_NEG | SLJIT_INT_OP) |
/* Count leading zeroes |
/* Count leading zeroes |
Flags: I | E | K */ | Flags: I | E | K |
#define SLJIT_CLZ 22 | Important note! Sparc 32 does not support K flag, since |
| the required popc instruction is introduced only in sparc 64. */ |
| #define SLJIT_CLZ 24 |
| #define SLJIT_ICLZ (SLJIT_CLZ | SLJIT_INT_OP) |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op, | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op, |
int dst, sljit_w dstw, | sljit_si dst, sljit_sw dstw, |
int src, sljit_w srcw); | sljit_si src, sljit_sw srcw); |
|
|
/* Flags: I | E | O | C | K */ |
/* Flags: I | E | O | C | K */ |
#define SLJIT_ADD 23 | #define SLJIT_ADD 25 |
| #define SLJIT_IADD (SLJIT_ADD | SLJIT_INT_OP) |
/* Flags: I | C | K */ |
/* Flags: I | C | K */ |
#define SLJIT_ADDC 24 | #define SLJIT_ADDC 26 |
| #define SLJIT_IADDC (SLJIT_ADDC | SLJIT_INT_OP) |
/* Flags: I | E | S | U | O | C | K */ |
/* Flags: I | E | S | U | O | C | K */ |
#define SLJIT_SUB 25 | #define SLJIT_SUB 27 |
| #define SLJIT_ISUB (SLJIT_SUB | SLJIT_INT_OP) |
/* Flags: I | C | K */ |
/* Flags: I | C | K */ |
#define SLJIT_SUBC 26 | #define SLJIT_SUBC 28 |
| #define SLJIT_ISUBC (SLJIT_SUBC | SLJIT_INT_OP) |
/* Note: integer mul |
/* Note: integer mul |
Flags: I | O (see SLJIT_C_MUL_*) | K */ |
Flags: I | O (see SLJIT_C_MUL_*) | K */ |
#define SLJIT_MUL 27 | #define SLJIT_MUL 29 |
| #define SLJIT_IMUL (SLJIT_MUL | SLJIT_INT_OP) |
/* Flags: I | E | K */ |
/* Flags: I | E | K */ |
#define SLJIT_AND 28 | #define SLJIT_AND 30 |
| #define SLJIT_IAND (SLJIT_AND | SLJIT_INT_OP) |
/* Flags: I | E | K */ |
/* Flags: I | E | K */ |
#define SLJIT_OR 29 | #define SLJIT_OR 31 |
| #define SLJIT_IOR (SLJIT_OR | SLJIT_INT_OP) |
/* Flags: I | E | K */ |
/* Flags: I | E | K */ |
#define SLJIT_XOR 30 | #define SLJIT_XOR 32 |
| #define SLJIT_IXOR (SLJIT_XOR | SLJIT_INT_OP) |
/* Flags: I | E | K |
/* Flags: I | E | K |
Let bit_length be the length of the shift operation: 32 or 64. |
Let bit_length be the length of the shift operation: 32 or 64. |
If src2 is immediate, src2w is masked by (bit_length - 1). |
If src2 is immediate, src2w is masked by (bit_length - 1). |
Otherwise, if the content of src2 is outside the range from 0 |
Otherwise, if the content of src2 is outside the range from 0 |
to bit_length - 1, the operation is undefined. */ |
to bit_length - 1, the operation is undefined. */ |
#define SLJIT_SHL 31 | #define SLJIT_SHL 33 |
| #define SLJIT_ISHL (SLJIT_SHL | SLJIT_INT_OP) |
/* Flags: I | E | K |
/* Flags: I | E | K |
Let bit_length be the length of the shift operation: 32 or 64. |
Let bit_length be the length of the shift operation: 32 or 64. |
If src2 is immediate, src2w is masked by (bit_length - 1). |
If src2 is immediate, src2w is masked by (bit_length - 1). |
Otherwise, if the content of src2 is outside the range from 0 |
Otherwise, if the content of src2 is outside the range from 0 |
to bit_length - 1, the operation is undefined. */ |
to bit_length - 1, the operation is undefined. */ |
#define SLJIT_LSHR 32 | #define SLJIT_LSHR 34 |
| #define SLJIT_ILSHR (SLJIT_LSHR | SLJIT_INT_OP) |
/* Flags: I | E | K |
/* Flags: I | E | K |
Let bit_length be the length of the shift operation: 32 or 64. |
Let bit_length be the length of the shift operation: 32 or 64. |
If src2 is immediate, src2w is masked by (bit_length - 1). |
If src2 is immediate, src2w is masked by (bit_length - 1). |
Otherwise, if the content of src2 is outside the range from 0 |
Otherwise, if the content of src2 is outside the range from 0 |
to bit_length - 1, the operation is undefined. */ |
to bit_length - 1, the operation is undefined. */ |
#define SLJIT_ASHR 33 | #define SLJIT_ASHR 35 |
| #define SLJIT_IASHR (SLJIT_ASHR | SLJIT_INT_OP) |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op, | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op, |
int dst, sljit_w dstw, | sljit_si dst, sljit_sw dstw, |
int src1, sljit_w src1w, | sljit_si src1, sljit_sw src1w, |
int src2, sljit_w src2w); | sljit_si src2, sljit_sw src2w); |
|
|
/* The following function is a helper function for sljit_emit_op_custom. |
/* The following function is a helper function for sljit_emit_op_custom. |
It returns with the real machine register index of any SLJIT_TEMPORARY | It returns with the real machine register index of any SLJIT_SCRATCH |
SLJIT_SAVED or SLJIT_LOCALS register. |
SLJIT_SAVED or SLJIT_LOCALS register. |
Note: it returns with -1 for virtual registers (all EREGs on x86-32). | Note: it returns with -1 for virtual registers (all EREGs on x86-32). */ |
Note: register returned by SLJIT_LOCALS_REG is not necessary the real | |
stack pointer register of the target architecture. */ | |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg); | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg); |
|
|
|
/* The following function is a helper function for sljit_emit_op_custom. |
|
It returns with the real machine register index of any SLJIT_FLOAT register. |
|
Note: the index is divided by 2 on ARM 32 bit architectures. */ |
|
|
|
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg); |
|
|
/* Any instruction can be inserted into the instruction stream by |
/* Any instruction can be inserted into the instruction stream by |
sljit_emit_op_custom. It has a similar purpose as inline assembly. |
sljit_emit_op_custom. It has a similar purpose as inline assembly. |
The size parameter must match to the instruction size of the target |
The size parameter must match to the instruction size of the target |
Line 609 SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(
|
Line 720 SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(
|
if size == 4, the instruction argument must be 4 byte aligned. |
if size == 4, the instruction argument must be 4 byte aligned. |
Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */ |
Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */ |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler, | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler, |
void *instruction, int size); | void *instruction, sljit_si size); |
|
|
/* Returns with non-zero if fpu is available. */ |
/* Returns with non-zero if fpu is available. */ |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void); | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void); |
|
|
/* Note: dst is the left and src is the right operand for SLJIT_FCMP. |
/* Note: dst is the left and src is the right operand for SLJIT_FCMP. |
Note: NaN check is always performed. If SLJIT_C_FLOAT_NAN is set, | Note: NaN check is always performed. If SLJIT_C_FLOAT_UNORDERED is set, |
the comparison result is unpredictable. |
the comparison result is unpredictable. |
Flags: E | S (see SLJIT_C_FLOAT_*) */ | Flags: SP | E | S (see SLJIT_C_FLOAT_*) */ |
#define SLJIT_FCMP 34 | #define SLJIT_CMPD 36 |
/* Flags: - (never set any flags) */ | #define SLJIT_CMPS (SLJIT_CMPD | SLJIT_SINGLE_OP) |
#define SLJIT_FMOV 35 | /* Flags: SP - (never set any flags) */ |
/* Flags: - (never set any flags) */ | #define SLJIT_MOVD 37 |
#define SLJIT_FNEG 36 | #define SLJIT_MOVS (SLJIT_MOVD | SLJIT_SINGLE_OP) |
/* Flags: - (never set any flags) */ | /* Flags: SP - (never set any flags) */ |
#define SLJIT_FABS 37 | #define SLJIT_NEGD 38 |
| #define SLJIT_NEGS (SLJIT_NEGD | SLJIT_SINGLE_OP) |
| /* Flags: SP - (never set any flags) */ |
| #define SLJIT_ABSD 39 |
| #define SLJIT_ABSS (SLJIT_ABSD | SLJIT_SINGLE_OP) |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op, |
int dst, sljit_w dstw, | sljit_si dst, sljit_sw dstw, |
int src, sljit_w srcw); | sljit_si src, sljit_sw srcw); |
|
|
/* Flags: - (never set any flags) */ | /* Flags: SP - (never set any flags) */ |
#define SLJIT_FADD 38 | #define SLJIT_ADDD 40 |
/* Flags: - (never set any flags) */ | #define SLJIT_ADDS (SLJIT_ADDD | SLJIT_SINGLE_OP) |
#define SLJIT_FSUB 39 | /* Flags: SP - (never set any flags) */ |
/* Flags: - (never set any flags) */ | #define SLJIT_SUBD 41 |
#define SLJIT_FMUL 40 | #define SLJIT_SUBS (SLJIT_SUBD | SLJIT_SINGLE_OP) |
/* Flags: - (never set any flags) */ | /* Flags: SP - (never set any flags) */ |
#define SLJIT_FDIV 41 | #define SLJIT_MULD 42 |
| #define SLJIT_MULS (SLJIT_MULD | SLJIT_SINGLE_OP) |
| /* Flags: SP - (never set any flags) */ |
| #define SLJIT_DIVD 43 |
| #define SLJIT_DIVS (SLJIT_DIVD | SLJIT_SINGLE_OP) |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op, |
int dst, sljit_w dstw, | sljit_si dst, sljit_sw dstw, |
int src1, sljit_w src1w, | sljit_si src1, sljit_sw src1w, |
int src2, sljit_w src2w); | sljit_si src2, sljit_sw src2w); |
|
|
/* Label and jump instructions. */ |
/* Label and jump instructions. */ |
|
|
Line 677 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emi
|
Line 796 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emi
|
#define SLJIT_C_FLOAT_GREATER_EQUAL 17 |
#define SLJIT_C_FLOAT_GREATER_EQUAL 17 |
#define SLJIT_C_FLOAT_GREATER 18 |
#define SLJIT_C_FLOAT_GREATER 18 |
#define SLJIT_C_FLOAT_LESS_EQUAL 19 |
#define SLJIT_C_FLOAT_LESS_EQUAL 19 |
#define SLJIT_C_FLOAT_NAN 20 | #define SLJIT_C_FLOAT_UNORDERED 20 |
#define SLJIT_C_FLOAT_NOT_NAN 21 | #define SLJIT_C_FLOAT_ORDERED 21 |
|
|
#define SLJIT_JUMP 22 |
#define SLJIT_JUMP 22 |
#define SLJIT_FAST_CALL 23 |
#define SLJIT_FAST_CALL 23 |
Line 697 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emi
|
Line 816 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emi
|
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP |
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP |
Flags: - (never set any flags) for both conditional and unconditional jumps. |
Flags: - (never set any flags) for both conditional and unconditional jumps. |
Flags: destroy all flags for calls. */ |
Flags: destroy all flags for calls. */ |
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type); | SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type); |
|
|
/* Basic arithmetic comparison. In most architectures it is implemented as |
/* Basic arithmetic comparison. In most architectures it is implemented as |
an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting |
an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting |
Line 707 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit
|
Line 826 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit
|
type must be between SLJIT_C_EQUAL and SLJIT_C_SIG_LESS_EQUAL |
type must be between SLJIT_C_EQUAL and SLJIT_C_SIG_LESS_EQUAL |
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP or SLJIT_INT_OP |
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP or SLJIT_INT_OP |
Flags: destroy flags. */ |
Flags: destroy flags. */ |
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type, | SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type, |
int src1, sljit_w src1w, | sljit_si src1, sljit_sw src1w, |
int src2, sljit_w src2w); | sljit_si src2, sljit_sw src2w); |
|
|
/* Basic floating point comparison. In most architectures it is implemented as |
/* Basic floating point comparison. In most architectures it is implemented as |
an SLJIT_FCMP operation (setting appropriate flags) followed by a |
an SLJIT_FCMP operation (setting appropriate flags) followed by a |
sljit_emit_jump. However some architectures (i.e: MIPS) may employ |
sljit_emit_jump. However some architectures (i.e: MIPS) may employ |
special optimizations here. It is suggested to use this comparison form |
special optimizations here. It is suggested to use this comparison form |
when appropriate. |
when appropriate. |
type must be between SLJIT_C_FLOAT_EQUAL and SLJIT_C_FLOAT_NOT_NAN | type must be between SLJIT_C_FLOAT_EQUAL and SLJIT_C_FLOAT_ORDERED |
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP | type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and SLJIT_SINGLE_OP |
Flags: destroy flags. |
Flags: destroy flags. |
Note: if either operand is NaN, the behaviour is undefined for |
Note: if either operand is NaN, the behaviour is undefined for |
type <= SLJIT_C_FLOAT_LESS_EQUAL. */ |
type <= SLJIT_C_FLOAT_LESS_EQUAL. */ |
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type, | SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type, |
int src1, sljit_w src1w, | sljit_si src1, sljit_sw src1w, |
int src2, sljit_w src2w); | sljit_si src2, sljit_sw src2w); |
|
|
/* Set the destination of the jump to this label. */ |
/* Set the destination of the jump to this label. */ |
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label); |
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label); |
Line 737 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct
|
Line 856 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct
|
Indirect form: any other valid addressing mode |
Indirect form: any other valid addressing mode |
Flags: - (never set any flags) for unconditional jumps. |
Flags: - (never set any flags) for unconditional jumps. |
Flags: destroy all flags for calls. */ |
Flags: destroy all flags for calls. */ |
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw); | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw); |
|
|
/* If op == SLJIT_MOV: | /* Perform the operation using the conditional flags as the second argument. |
Set dst to 1 if condition is fulfilled, 0 otherwise | Type must always be between SLJIT_C_EQUAL and SLJIT_C_FLOAT_ORDERED. The |
type must be between SLJIT_C_EQUAL and SLJIT_C_FLOAT_NOT_NAN | value represented by the type is 1, if the condition represented by the type |
| is fulfilled, and 0 otherwise. |
| |
| If op == SLJIT_MOV, SLJIT_MOV_SI, SLJIT_MOV_UI: |
| Set dst to the value represented by the type (0 or 1). |
| Src must be SLJIT_UNUSED, and srcw must be 0 |
Flags: - (never set any flags) |
Flags: - (never set any flags) |
If op == SLJIT_OR | If op == SLJIT_OR, op == SLJIT_AND, op == SLJIT_XOR |
Dst is used as src as well, and set its lowest bit to 1 if | Performs the binary operation using src as the first, and the value |
the condition is fulfilled. Otherwise it does nothing. | represented by type as the second argument. |
Flags: E | K | Important note: only dst=src and dstw=srcw is supported at the moment! |
Note: sljit_emit_cond_value does nothing, if dst is SLJIT_UNUSED (regardless of op). */ | Flags: I | E | K |
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type); | Note: sljit_emit_op_flags does nothing, if dst is SLJIT_UNUSED (regardless of op). */ |
| SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op, |
| sljit_si dst, sljit_sw dstw, |
| sljit_si src, sljit_sw srcw, |
| sljit_si type); |
|
|
/* Copies the base address of SLJIT_MEM1(SLJIT_LOCALS_REG)+offset to dst. | /* Copies the base address of SLJIT_LOCALS_REG+offset to dst. |
Flags: - (never set any flags) */ |
Flags: - (never set any flags) */ |
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_local_base(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w offset); | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset); |
|
|
/* The constant can be changed runtime (see: sljit_set_const) |
/* The constant can be changed runtime (see: sljit_set_const) |
Flags: - (never set any flags) */ |
Flags: - (never set any flags) */ |
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value); | SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value); |
|
|
/* After the code generation the address for label, jump and const instructions |
/* After the code generation the address for label, jump and const instructions |
are computed. Since these structures are freed sljit_free_compiler, the | are computed. Since these structures are freed by sljit_free_compiler, the |
addresses must be preserved by the user program elsewere. */ |
addresses must be preserved by the user program elsewere. */ |
static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->addr; } |
static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->addr; } |
static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; } |
static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; } |
Line 767 static SLJIT_INLINE sljit_uw sljit_get_const_addr(stru
|
Line 895 static SLJIT_INLINE sljit_uw sljit_get_const_addr(stru
|
|
|
/* Only the address is required to rewrite the code. */ |
/* Only the address is required to rewrite the code. */ |
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr); |
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr); |
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant); | SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant); |
|
|
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
/* Miscellaneous utility functions */ |
/* Miscellaneous utility functions */ |
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
|
|
#define SLJIT_MAJOR_VERSION 0 |
#define SLJIT_MAJOR_VERSION 0 |
#define SLJIT_MINOR_VERSION 88 | #define SLJIT_MINOR_VERSION 91 |
|
|
/* Get the human readable name of the platfrom. | /* Get the human readable name of the platform. Can be useful on platforms |
Can be useful for debugging on platforms like ARM, where ARM and | like ARM, where ARM and Thumb2 functions can be mixed, and |
Thumb2 functions can be mixed. */ | it is useful to know the type of the code generator. */ |
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void); |
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void); |
|
|
/* Portble helper function to get an offset of a member. */ | /* Portable helper function to get an offset of a member. */ |
#define SLJIT_OFFSETOF(base, member) ((sljit_w)(&((base*)0x10)->member) - 0x10) | #define SLJIT_OFFSETOF(base, member) ((sljit_sw)(&((base*)0x10)->member) - 0x10) |
|
|
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) |
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) |
/* This global lock is useful to compile common functions. */ |
/* This global lock is useful to compile common functions. */ |
Line 831 SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_st
|
Line 959 SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_st
|
since the growth ratio can be added to the current limit, and sljit_stack_resize |
since the growth ratio can be added to the current limit, and sljit_stack_resize |
will do all the necessary checks. The fields of the stack are not changed if |
will do all the necessary checks. The fields of the stack are not changed if |
sljit_stack_resize fails. */ |
sljit_stack_resize fails. */ |
SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit); | SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit); |
|
|
#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */ |
#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */ |
|
|
#if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) |
#if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) |
|
|
/* Get the entry address of a given function. */ |
/* Get the entry address of a given function. */ |
#define SLJIT_FUNC_OFFSET(func_name) ((sljit_w)func_name) | #define SLJIT_FUNC_OFFSET(func_name) ((sljit_sw)func_name) |
|
|
#else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */ |
#else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */ |
|
|
/* All JIT related code should be placed in the same context (library, binary, etc.). */ |
/* All JIT related code should be placed in the same context (library, binary, etc.). */ |
|
|
#define SLJIT_FUNC_OFFSET(func_name) ((sljit_w)*(void**)func_name) | #define SLJIT_FUNC_OFFSET(func_name) (*(sljit_sw*)(void*)func_name) |
|
|
/* For powerpc64, the function pointers point to a context descriptor. */ |
/* For powerpc64, the function pointers point to a context descriptor. */ |
struct sljit_function_context { |
struct sljit_function_context { |
sljit_w addr; | sljit_sw addr; |
sljit_w r2; | sljit_sw r2; |
sljit_w r11; | sljit_sw r11; |
}; |
}; |
|
|
/* Fill the context arguments using the addr and the function. |
/* Fill the context arguments using the addr and the function. |
If func_ptr is NULL, it will not be set to the address of context |
If func_ptr is NULL, it will not be set to the address of context |
If addr is NULL, the function address also comes from the func pointer. */ |
If addr is NULL, the function address also comes from the func pointer. */ |
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_w addr, void* func); | SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func); |
|
|
#endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */ |
#endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */ |
|
|