summaryrefslogtreecommitdiff
path: root/pcre/sljit/sljitLir.h
diff options
context:
space:
mode:
Diffstat (limited to 'pcre/sljit/sljitLir.h')
-rw-r--r--pcre/sljit/sljitLir.h444
1 files changed, 295 insertions, 149 deletions
diff --git a/pcre/sljit/sljitLir.h b/pcre/sljit/sljitLir.h
index e2cd21846df..97188719390 100644
--- a/pcre/sljit/sljitLir.h
+++ b/pcre/sljit/sljitLir.h
@@ -56,8 +56,6 @@
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
- scratch, max 3+2 saved and 6 floating point registers)
In practice:
- This approach is very effective for interpreters
- One of the saved registers typically points to a stack interface
@@ -104,76 +102,169 @@ of sljitConfigInternal.h */
/* Registers */
/* --------------------------------------------------------------------- */
+/*
+ Scratch (R) registers: registers whose may not preserve their values
+ across function calls.
+
+ Saved (S) registers: registers whose preserve their values across
+ function calls.
+
+ The scratch and saved register sets are overlap. The last scratch register
+ is the first saved register, the one before the last is the second saved
+ register, and so on.
+
+ If an architecture provides two scratch and three saved registers,
+ its scratch and saved register sets are the following:
+
+ R0 | [S4] | R0 and S4 represent the same physical register
+ R1 | [S3] | R1 and S3 represent the same physical register
+ [R2] | S2 | R2 and S2 represent the same physical register
+ [R3] | S1 | R3 and S1 represent the same physical register
+ [R4] | S0 | R4 and S0 represent the same physical register
+
+ Note: SLJIT_NUMBER_OF_SCRATCH_REGISTERS would be 2 and
+ SLJIT_NUMBER_OF_SAVED_REGISTERS would be 3 for this architecture.
+
+ Note: On all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 10
+ and SLJIT_NUMBER_OF_SAVED_REGISTERS >= 5. However, 4 registers
+ are virtual on x86-32. See below.
+
+ The purpose of this definition is convenience. Although a register
+ is either scratch register or saved register, SLJIT allows accessing
+ them from the other set. For example, four registers can be used as
+ scratch registers and the fifth one as saved register on the architecture
+ above. Of course the last two scratch registers (R2 and R3) from this
+ four will be saved on the stack, because they are defined as saved
+ registers in the application binary interface. Still R2 and R3 can be
+ used for referencing to these registers instead of S2 and S1, which
+ makes easier to write platform independent code. Scratch registers
+ can be saved registers in a similar way, but these extra saved
+ registers will not be preserved across function calls! Hence the
+ application must save them on those platforms, where the number of
+ saved registers is too low. This can be done by copy them onto
+ the stack and restore them after a function call.
+
+ Note: To emphasize that registers assigned to R2-R4 are saved
+ registers, they are enclosed by square brackets. S3-S4
+ are marked in a similar way.
+
+ Note: sljit_emit_enter and sljit_set_context defines whether a register
+ is S or R register. E.g: when 3 scratches and 1 saved is mapped
+ by sljit_emit_enter, the allowed register set will be: R0-R2 and
+ S0. Although S2 is mapped to the same position as R2, it does not
+ available in the current configuration. Furthermore the R3 (S1)
+ register does not available as well.
+*/
+
+/* When SLJIT_UNUSED is specified as destination, the result is discarded. */
#define SLJIT_UNUSED 0
-/* Scratch (temporary) registers whose may not preserve their values
- across function calls. */
-#define SLJIT_SCRATCH_REG1 1
-#define SLJIT_SCRATCH_REG2 2
-#define SLJIT_SCRATCH_REG3 3
-/* Note: extra registers cannot be used for memory addressing. */
-/* Note: on x86-32, these registers are emulated (using stack
- loads & stores). */
-#define SLJIT_TEMPORARY_EREG1 4
-#define SLJIT_TEMPORARY_EREG2 5
-
-/* Saved registers whose preserve their values across function calls. */
-#define SLJIT_SAVED_REG1 6
-#define SLJIT_SAVED_REG2 7
-#define SLJIT_SAVED_REG3 8
-/* Note: extra registers cannot be used for memory addressing. */
-/* Note: on x86-32, these registers are emulated (using stack
- loads & stores). */
-#define SLJIT_SAVED_EREG1 9
-#define SLJIT_SAVED_EREG2 10
-
-/* Read-only register (cannot be the destination of an operation).
- Only SLJIT_MEM1(SLJIT_LOCALS_REG) addressing mode is allowed since
- several ABIs has certain limitations about the stack layout. However
- sljit_get_local_base() can be used to obtain the offset of a value
- on the stack. */
-#define SLJIT_LOCALS_REG 11
-
-/* Number of registers. */
-#define SLJIT_NO_TMP_REGISTERS 5
-#define SLJIT_NO_GEN_REGISTERS 5
-#define SLJIT_NO_REGISTERS 11
+/* Scratch registers. */
+#define SLJIT_R0 1
+#define SLJIT_R1 2
+#define SLJIT_R2 3
+/* Note: on x86-32, R3 - R6 (same as S3 - S6) are emulated (they
+ are allocated on the stack). These registers are called virtual
+ and cannot be used for memory addressing (cannot be part of
+ any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such
+ limitation on other CPUs. See sljit_get_register_index(). */
+#define SLJIT_R3 4
+#define SLJIT_R4 5
+#define SLJIT_R5 6
+#define SLJIT_R6 7
+#define SLJIT_R7 8
+#define SLJIT_R8 9
+#define SLJIT_R9 10
+/* All R registers provided by the architecture can be accessed by SLJIT_R(i)
+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_REGISTERS. */
+#define SLJIT_R(i) (1 + (i))
+
+/* Saved registers. */
+#define SLJIT_S0 (SLJIT_NUMBER_OF_REGISTERS)
+#define SLJIT_S1 (SLJIT_NUMBER_OF_REGISTERS - 1)
+#define SLJIT_S2 (SLJIT_NUMBER_OF_REGISTERS - 2)
+/* Note: on x86-32, S3 - S6 (same as R3 - R6) are emulated (they
+ are allocated on the stack). These registers are called virtual
+ and cannot be used for memory addressing (cannot be part of
+ any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such
+ limitation on other CPUs. See sljit_get_register_index(). */
+#define SLJIT_S3 (SLJIT_NUMBER_OF_REGISTERS - 3)
+#define SLJIT_S4 (SLJIT_NUMBER_OF_REGISTERS - 4)
+#define SLJIT_S5 (SLJIT_NUMBER_OF_REGISTERS - 5)
+#define SLJIT_S6 (SLJIT_NUMBER_OF_REGISTERS - 6)
+#define SLJIT_S7 (SLJIT_NUMBER_OF_REGISTERS - 7)
+#define SLJIT_S8 (SLJIT_NUMBER_OF_REGISTERS - 8)
+#define SLJIT_S9 (SLJIT_NUMBER_OF_REGISTERS - 9)
+/* All S registers provided by the architecture can be accessed by SLJIT_S(i)
+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_REGISTERS. */
+#define SLJIT_S(i) (SLJIT_NUMBER_OF_REGISTERS - (i))
+
+/* Registers >= SLJIT_FIRST_SAVED_REG are saved registers. */
+#define SLJIT_FIRST_SAVED_REG (SLJIT_S0 - SLJIT_NUMBER_OF_SAVED_REGISTERS + 1)
+
+/* The SLJIT_SP provides direct access to the linear stack space allocated by
+ sljit_emit_enter. It can only be used in the following form: SLJIT_MEM1(SLJIT_SP).
+ The immediate offset is extended by the relative stack offset automatically.
+ The sljit_get_local_base can be used to obtain the absolute offset. */
+#define SLJIT_SP (SLJIT_NUMBER_OF_REGISTERS + 1)
/* Return with machine word. */
-#define SLJIT_RETURN_REG SLJIT_SCRATCH_REG1
+#define SLJIT_RETURN_REG SLJIT_R0
/* x86 prefers specific registers for special purposes. In case of shift
- by register it supports only SLJIT_SCRATCH_REG3 for shift argument
+ by register it supports only SLJIT_R2 for shift argument
(which is the src2 argument of sljit_emit_op2). If another register is
used, sljit must exchange data between registers which cause a minor
slowdown. Other architectures has no such limitation. */
-#define SLJIT_PREF_SHIFT_REG SLJIT_SCRATCH_REG3
+#define SLJIT_PREF_SHIFT_REG SLJIT_R2
/* --------------------------------------------------------------------- */
/* Floating point registers */
/* --------------------------------------------------------------------- */
-/* Note: SLJIT_UNUSED as destination is not valid for floating point
- operations, since they cannot be used for setting flags. */
+/* Each floating point register can store a double or single precision
+ value. The FR and FS register sets are overlap in the same way as R
+ and S register sets. See above. */
-/* Floating point operations are performed on double or
- single precision values. */
-
-#define SLJIT_FLOAT_REG1 1
-#define SLJIT_FLOAT_REG2 2
-#define SLJIT_FLOAT_REG3 3
-#define SLJIT_FLOAT_REG4 4
-#define SLJIT_FLOAT_REG5 5
-#define SLJIT_FLOAT_REG6 6
-
-#define SLJIT_NO_FLOAT_REGISTERS 6
+/* Note: SLJIT_UNUSED as destination is not valid for floating point
+ operations, since they cannot be used for setting flags. */
+
+/* Floating point scratch registers. */
+#define SLJIT_FR0 1
+#define SLJIT_FR1 2
+#define SLJIT_FR2 3
+#define SLJIT_FR3 4
+#define SLJIT_FR4 5
+#define SLJIT_FR5 6
+/* All FR registers provided by the architecture can be accessed by SLJIT_FR(i)
+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_FLOAT_REGISTERS. */
+#define SLJIT_FR(i) (1 + (i))
+
+/* Floating point saved registers. */
+#define SLJIT_FS0 (SLJIT_NUMBER_OF_FLOAT_REGISTERS)
+#define SLJIT_FS1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 1)
+#define SLJIT_FS2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2)
+#define SLJIT_FS3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 3)
+#define SLJIT_FS4 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 4)
+#define SLJIT_FS5 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 5)
+/* All S registers provided by the architecture can be accessed by SLJIT_FS(i)
+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS. */
+#define SLJIT_FS(i) (SLJIT_NUMBER_OF_FLOAT_REGISTERS - (i))
+
+/* Float registers >= SLJIT_FIRST_SAVED_FLOAT_REG are saved registers. */
+#define SLJIT_FIRST_SAVED_FLOAT_REG (SLJIT_FS0 - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS + 1)
/* --------------------------------------------------------------------- */
/* Main structures and functions */
/* --------------------------------------------------------------------- */
+/*
+ The following structures are private, and can be changed in the
+ future. Keeping them here allows code inlining.
+*/
+
struct sljit_memory_fragment {
struct sljit_memory_fragment *next;
sljit_uw used_size;
@@ -205,6 +296,7 @@ struct sljit_const {
struct sljit_compiler {
sljit_si error;
+ sljit_si options;
struct sljit_label *labels;
struct sljit_jump *jumps;
@@ -216,10 +308,14 @@ struct sljit_compiler {
struct sljit_memory_fragment *buf;
struct sljit_memory_fragment *abuf;
- /* Used local registers. */
+ /* Used scratch registers. */
sljit_si scratches;
/* Used saved registers. */
sljit_si saveds;
+ /* Used float scratch registers. */
+ sljit_si fscratches;
+ /* Used float saved registers. */
+ sljit_si fsaveds;
/* Local stack size. */
sljit_si local_size;
/* Code size. */
@@ -229,16 +325,13 @@ struct sljit_compiler {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
sljit_si args;
- sljit_si locals_offset;
- sljit_si scratches_start;
- sljit_si saveds_start;
#endif
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
sljit_si mode32;
#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 && SLJIT_CONFIG_X86)
sljit_si flags_saved;
#endif
@@ -271,13 +364,13 @@ struct sljit_compiler {
sljit_sw cache_argw;
#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 && SLJIT_CONFIG_PPC)
sljit_sw imm;
sljit_si cache_arg;
sljit_sw cache_argw;
#endif
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
sljit_si delay_slot;
sljit_si cache_arg;
sljit_sw cache_argw;
@@ -361,46 +454,64 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
error, they return with SLJIT_SUCCESS. */
/*
- The executable code is basically a function call from the viewpoint of
- the C language. The function calls must obey to the ABI (Application
- Binary Interface) of the platform, which specify the purpose of machine
- registers and stack handling among other things. The sljit_emit_enter
- function emits the necessary instructions for setting up a new context
- for the executable code and moves function arguments to the saved
- registers. The number of arguments are specified in the "args"
- parameter and the first argument goes to SLJIT_SAVED_REG1, the second
- goes to SLJIT_SAVED_REG2 and so on. The number of scratch and
- saved registers are passed in "scratches" and "saveds" arguments
- respectively. Since the saved registers contains the arguments,
- "args" must be less or equal than "saveds". The sljit_emit_enter
- is also capable of allocating a stack space for local variables. The
- "local_size" argument contains the size in bytes of this local area
- and its staring address is stored in SLJIT_LOCALS_REG. However
- the SLJIT_LOCALS_REG is not necessary the machine stack pointer.
- The memory bytes between SLJIT_LOCALS_REG (inclusive) and
- SLJIT_LOCALS_REG + local_size (exclusive) can be modified freely
- until the function returns. The stack space is uninitialized.
+ The executable code is a function call from the viewpoint of the C
+ language. The function calls must obey to the ABI (Application
+ Binary Interface) of the platform, which specify the purpose of
+ all machine registers and stack handling among other things. The
+ sljit_emit_enter function emits the necessary instructions for
+ setting up a new context for the executable code and moves function
+ arguments to the saved registers. Furthermore the options argument
+ can be used to pass configuration options to the compiler. Currently
+ there are no options, so it must be set to 0.
+
+ The number of sljit_sw arguments passed to the generated function
+ are specified in the "args" parameter. The number of arguments must
+ be less than or equal to 3. The first argument goes to SLJIT_S0,
+ the second goes to SLJIT_S1 and so on. The register set used by
+ the function must be declared as well. The number of scratch and
+ saved registers used by the function must be passed to sljit_emit_enter.
+ Only R registers between R0 and "scratches" argument can be used
+ later. E.g. if "scratches" is set to 2, the register set will be
+ limited to R0 and R1. The S registers and the floating point
+ registers ("fscratches" and "fsaveds") are specified in a similar
+ way. The sljit_emit_enter is also capable of allocating a stack
+ space for local variables. The "local_size" argument contains the
+ size in bytes of this local area and its staring address is stored
+ in SLJIT_SP. The memory area between SLJIT_SP (inclusive) and
+ SLJIT_SP + local_size (exclusive) can be modified freely until
+ the function returns. The stack space is not initialized.
+
+ Note: the following conditions must met:
+ 0 <= scratches <= SLJIT_NUMBER_OF_REGISTERS
+ 0 <= saveds <= SLJIT_NUMBER_OF_REGISTERS
+ scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS
+ 0 <= fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS
+ 0 <= fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS
+ fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS
Note: every call of sljit_emit_enter and sljit_set_context
- overwrites the previous context. */
+ overwrites the previous context.
+*/
#define SLJIT_MAX_LOCAL_SIZE 65536
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
- sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size);
+ sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
+ sljit_si fscratches, sljit_si fsaveds, sljit_si local_size);
/* The machine code has a context (which contains the local stack space size,
number of used registers, etc.) which initialized by sljit_emit_enter. Several
functions (like sljit_emit_return) requres this context to be able to generate
the appropriate code. However, some code fragments (like inline cache) may have
- no normal entry point so their context is unknown for the compiler. Using the
- function below we can specify their context.
+ no normal entry point so their context is unknown for the compiler. Their context
+ can be provided to the compiler by the sljit_set_context function.
Note: every call of sljit_emit_enter and sljit_set_context overwrites
the previous context. */
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
- sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size);
+ sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
+ sljit_si fscratches, sljit_si fsaveds, sljit_si local_size);
/* Return from machine code. The op argument can be SLJIT_UNUSED which means the
function does not return with anything or any opcode between SLJIT_MOV and
@@ -549,37 +660,43 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
the instruction does not set flags (See: SLJIT_KEEP_FLAGS).
- flag combinations: '|' means 'logical or'. */
+/* Starting index of opcodes for sljit_emit_op0. */
+#define SLJIT_OP0_BASE 0
+
/* Flags: - (never set any flags)
Note: breakpoint instruction is not supported by all architectures (namely ppc)
It falls back to SLJIT_NOP in those cases. */
-#define SLJIT_BREAKPOINT 0
+#define SLJIT_BREAKPOINT (SLJIT_OP0_BASE + 0)
/* Flags: - (never set any flags)
Note: may or may not cause an extra cycle wait
it can even decrease the runtime in a few cases. */
-#define SLJIT_NOP 1
+#define SLJIT_NOP (SLJIT_OP0_BASE + 1)
/* Flags: - (may destroy flags)
- Unsigned multiplication of SLJIT_SCRATCH_REG1 and SLJIT_SCRATCH_REG2.
- Result goes to SLJIT_SCRATCH_REG2:SLJIT_SCRATCH_REG1 (high:low) word */
-#define SLJIT_UMUL 2
+ Unsigned multiplication of SLJIT_R0 and SLJIT_R1.
+ Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */
+#define SLJIT_UMUL (SLJIT_OP0_BASE + 2)
/* Flags: - (may destroy flags)
- Signed multiplication of SLJIT_SCRATCH_REG1 and SLJIT_SCRATCH_REG2.
- Result goes to SLJIT_SCRATCH_REG2:SLJIT_SCRATCH_REG1 (high:low) word */
-#define SLJIT_SMUL 3
+ Signed multiplication of SLJIT_R0 and SLJIT_R1.
+ Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */
+#define SLJIT_SMUL (SLJIT_OP0_BASE + 3)
/* Flags: I - (may destroy flags)
- Unsigned divide of the value in SLJIT_SCRATCH_REG1 by the value in SLJIT_SCRATCH_REG2.
- The result is placed in SLJIT_SCRATCH_REG1 and the remainder goes to SLJIT_SCRATCH_REG2.
- Note: if SLJIT_SCRATCH_REG2 contains 0, the behaviour is undefined. */
-#define SLJIT_UDIV 4
+ Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
+ The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1.
+ Note: if SLJIT_R1 contains 0, the behaviour is undefined. */
+#define SLJIT_UDIV (SLJIT_OP0_BASE + 4)
#define SLJIT_IUDIV (SLJIT_UDIV | SLJIT_INT_OP)
/* Flags: I - (may destroy flags)
- Signed divide of the value in SLJIT_SCRATCH_REG1 by the value in SLJIT_SCRATCH_REG2.
- The result is placed in SLJIT_SCRATCH_REG1 and the remainder goes to SLJIT_SCRATCH_REG2.
- Note: if SLJIT_SCRATCH_REG2 contains 0, the behaviour is undefined. */
-#define SLJIT_SDIV 5
+ Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
+ The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1.
+ Note: if SLJIT_R1 contains 0, the behaviour is undefined. */
+#define SLJIT_SDIV (SLJIT_OP0_BASE + 5)
#define SLJIT_ISDIV (SLJIT_SDIV | SLJIT_INT_OP)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op);
+/* Starting index of opcodes for sljit_emit_op1. */
+#define SLJIT_OP1_BASE 32
+
/* Notes for MOV instructions:
U = Mov with update (pre 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
@@ -592,115 +709,118 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
P = pointer (sljit_p) size */
/* Flags: - (never set any flags) */
-#define SLJIT_MOV 6
+#define SLJIT_MOV (SLJIT_OP1_BASE + 0)
/* Flags: I - (never set any flags) */
-#define SLJIT_MOV_UB 7
+#define SLJIT_MOV_UB (SLJIT_OP1_BASE + 1)
#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 (SLJIT_OP1_BASE + 2)
#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 (SLJIT_OP1_BASE + 3)
#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 (SLJIT_OP1_BASE + 4)
#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 (SLJIT_OP1_BASE + 5)
/* No SLJIT_INT_OP form, since it is the same as SLJIT_IMOV. */
/* Flags: I - (never set any flags)
Note: see SLJIT_INT_OP for further details. */
-#define SLJIT_MOV_SI 12
+#define SLJIT_MOV_SI (SLJIT_OP1_BASE + 6)
#define SLJIT_IMOV (SLJIT_MOV_SI | SLJIT_INT_OP)
/* Flags: - (never set any flags) */
-#define SLJIT_MOV_P 13
+#define SLJIT_MOV_P (SLJIT_OP1_BASE + 7)
/* Flags: - (never set any flags) */
-#define SLJIT_MOVU 14
+#define SLJIT_MOVU (SLJIT_OP1_BASE + 8)
/* Flags: I - (never set any flags) */
-#define SLJIT_MOVU_UB 15
+#define SLJIT_MOVU_UB (SLJIT_OP1_BASE + 9)
#define SLJIT_IMOVU_UB (SLJIT_MOVU_UB | SLJIT_INT_OP)
/* Flags: I - (never set any flags) */
-#define SLJIT_MOVU_SB 16
+#define SLJIT_MOVU_SB (SLJIT_OP1_BASE + 10)
#define SLJIT_IMOVU_SB (SLJIT_MOVU_SB | SLJIT_INT_OP)
/* Flags: I - (never set any flags) */
-#define SLJIT_MOVU_UH 17
+#define SLJIT_MOVU_UH (SLJIT_OP1_BASE + 11)
#define SLJIT_IMOVU_UH (SLJIT_MOVU_UH | SLJIT_INT_OP)
/* Flags: I - (never set any flags) */
-#define SLJIT_MOVU_SH 18
+#define SLJIT_MOVU_SH (SLJIT_OP1_BASE + 12)
#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
+#define SLJIT_MOVU_UI (SLJIT_OP1_BASE + 13)
/* No SLJIT_INT_OP form, since it is 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_MOVU_SI (SLJIT_OP1_BASE + 14)
#define SLJIT_IMOVU (SLJIT_MOVU_SI | SLJIT_INT_OP)
/* Flags: - (never set any flags) */
-#define SLJIT_MOVU_P 21
+#define SLJIT_MOVU_P (SLJIT_OP1_BASE + 15)
/* Flags: I | E | K */
-#define SLJIT_NOT 22
+#define SLJIT_NOT (SLJIT_OP1_BASE + 16)
#define SLJIT_INOT (SLJIT_NOT | SLJIT_INT_OP)
/* Flags: I | E | O | K */
-#define SLJIT_NEG 23
+#define SLJIT_NEG (SLJIT_OP1_BASE + 17)
#define SLJIT_INEG (SLJIT_NEG | SLJIT_INT_OP)
/* Count leading zeroes
Flags: I | E | K
Important note! Sparc 32 does not support K flag, since
the required popc instruction is introduced only in sparc 64. */
-#define SLJIT_CLZ 24
+#define SLJIT_CLZ (SLJIT_OP1_BASE + 18)
#define SLJIT_ICLZ (SLJIT_CLZ | SLJIT_INT_OP)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
sljit_si dst, sljit_sw dstw,
sljit_si src, sljit_sw srcw);
+/* Starting index of opcodes for sljit_emit_op2. */
+#define SLJIT_OP2_BASE 96
+
/* Flags: I | E | O | C | K */
-#define SLJIT_ADD 25
+#define SLJIT_ADD (SLJIT_OP2_BASE + 0)
#define SLJIT_IADD (SLJIT_ADD | SLJIT_INT_OP)
/* Flags: I | C | K */
-#define SLJIT_ADDC 26
+#define SLJIT_ADDC (SLJIT_OP2_BASE + 1)
#define SLJIT_IADDC (SLJIT_ADDC | SLJIT_INT_OP)
/* Flags: I | E | U | S | O | C | K */
-#define SLJIT_SUB 27
+#define SLJIT_SUB (SLJIT_OP2_BASE + 2)
#define SLJIT_ISUB (SLJIT_SUB | SLJIT_INT_OP)
/* Flags: I | C | K */
-#define SLJIT_SUBC 28
+#define SLJIT_SUBC (SLJIT_OP2_BASE + 3)
#define SLJIT_ISUBC (SLJIT_SUBC | SLJIT_INT_OP)
/* Note: integer mul
Flags: I | O (see SLJIT_C_MUL_*) | K */
-#define SLJIT_MUL 29
+#define SLJIT_MUL (SLJIT_OP2_BASE + 4)
#define SLJIT_IMUL (SLJIT_MUL | SLJIT_INT_OP)
/* Flags: I | E | K */
-#define SLJIT_AND 30
+#define SLJIT_AND (SLJIT_OP2_BASE + 5)
#define SLJIT_IAND (SLJIT_AND | SLJIT_INT_OP)
/* Flags: I | E | K */
-#define SLJIT_OR 31
+#define SLJIT_OR (SLJIT_OP2_BASE + 6)
#define SLJIT_IOR (SLJIT_OR | SLJIT_INT_OP)
/* Flags: I | E | K */
-#define SLJIT_XOR 32
+#define SLJIT_XOR (SLJIT_OP2_BASE + 7)
#define SLJIT_IXOR (SLJIT_XOR | SLJIT_INT_OP)
/* Flags: I | E | K
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
- to bit_length - 1, the operation is undefined. */
-#define SLJIT_SHL 33
+ to bit_length - 1, the result is undefined. */
+#define SLJIT_SHL (SLJIT_OP2_BASE + 8)
#define SLJIT_ISHL (SLJIT_SHL | SLJIT_INT_OP)
/* Flags: I | E | K
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
- to bit_length - 1, the operation is undefined. */
-#define SLJIT_LSHR 34
+ to bit_length - 1, the result is undefined. */
+#define SLJIT_LSHR (SLJIT_OP2_BASE + 9)
#define SLJIT_ILSHR (SLJIT_LSHR | SLJIT_INT_OP)
/* Flags: I | E | K
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
- to bit_length - 1, the operation is undefined. */
-#define SLJIT_ASHR 35
+ to bit_length - 1, the result is undefined. */
+#define SLJIT_ASHR (SLJIT_OP2_BASE + 10)
#define SLJIT_IASHR (SLJIT_ASHR | SLJIT_INT_OP)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
@@ -709,15 +829,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
sljit_si src2, sljit_sw src2w);
/* The following function is a helper function for sljit_emit_op_custom.
- It returns with the real machine register index of any SLJIT_SCRATCH
- SLJIT_SAVED or SLJIT_LOCALS register.
- Note: it returns with -1 for virtual registers (all EREGs on x86-32). */
+ It returns with the real machine register index ( >=0 ) of any SLJIT_R,
+ SLJIT_S and SLJIT_SP registers.
+
+ Note: it returns with -1 for virtual registers (only on x86-32). */
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. */
+
+ Note: the index is always an even number on ARM (except ARM-64), MIPS, and SPARC. */
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg);
@@ -738,37 +860,61 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void);
-/* Note: dst is the left and src is the right operand for SLJIT_FCMP.
- Note: NaN check is always performed. If SLJIT_C_FLOAT_UNORDERED is set,
- the comparison result is unpredictable.
- Flags: SP | E | S (see SLJIT_C_FLOAT_*) */
-#define SLJIT_CMPD 36
-#define SLJIT_CMPS (SLJIT_CMPD | SLJIT_SINGLE_OP)
+/* Starting index of opcodes for sljit_emit_fop1. */
+#define SLJIT_FOP1_BASE 128
+
/* Flags: SP - (never set any flags) */
-#define SLJIT_MOVD 37
+#define SLJIT_MOVD (SLJIT_FOP1_BASE + 0)
#define SLJIT_MOVS (SLJIT_MOVD | SLJIT_SINGLE_OP)
+/* Convert opcodes: CONV[DST_TYPE].FROM[SRC_TYPE]
+ SRC/DST TYPE can be: D - double, S - single, W - signed word, I - signed int
+ Rounding mode when the destination is W or I: round towards zero. */
+/* Flags: SP - (never set any flags) */
+#define SLJIT_CONVD_FROMS (SLJIT_FOP1_BASE + 1)
+#define SLJIT_CONVS_FROMD (SLJIT_CONVD_FROMS | SLJIT_SINGLE_OP)
+/* Flags: SP - (never set any flags) */
+#define SLJIT_CONVW_FROMD (SLJIT_FOP1_BASE + 2)
+#define SLJIT_CONVW_FROMS (SLJIT_CONVW_FROMD | SLJIT_SINGLE_OP)
/* Flags: SP - (never set any flags) */
-#define SLJIT_NEGD 38
+#define SLJIT_CONVI_FROMD (SLJIT_FOP1_BASE + 3)
+#define SLJIT_CONVI_FROMS (SLJIT_CONVI_FROMD | SLJIT_SINGLE_OP)
+/* Flags: SP - (never set any flags) */
+#define SLJIT_CONVD_FROMW (SLJIT_FOP1_BASE + 4)
+#define SLJIT_CONVS_FROMW (SLJIT_CONVD_FROMW | SLJIT_SINGLE_OP)
+/* Flags: SP - (never set any flags) */
+#define SLJIT_CONVD_FROMI (SLJIT_FOP1_BASE + 5)
+#define SLJIT_CONVS_FROMI (SLJIT_CONVD_FROMI | SLJIT_SINGLE_OP)
+/* Note: dst is the left and src is the right operand for SLJIT_CMPD.
+ Note: NaN check is always performed. If SLJIT_C_FLOAT_UNORDERED flag
+ is set, the comparison result is unpredictable.
+ Flags: SP | E | S (see SLJIT_C_FLOAT_*) */
+#define SLJIT_CMPD (SLJIT_FOP1_BASE + 6)
+#define SLJIT_CMPS (SLJIT_CMPD | SLJIT_SINGLE_OP)
+/* Flags: SP - (never set any flags) */
+#define SLJIT_NEGD (SLJIT_FOP1_BASE + 7)
#define SLJIT_NEGS (SLJIT_NEGD | SLJIT_SINGLE_OP)
/* Flags: SP - (never set any flags) */
-#define SLJIT_ABSD 39
+#define SLJIT_ABSD (SLJIT_FOP1_BASE + 8)
#define SLJIT_ABSS (SLJIT_ABSD | SLJIT_SINGLE_OP)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
sljit_si dst, sljit_sw dstw,
sljit_si src, sljit_sw srcw);
+/* Starting index of opcodes for sljit_emit_fop2. */
+#define SLJIT_FOP2_BASE 160
+
/* Flags: SP - (never set any flags) */
-#define SLJIT_ADDD 40
+#define SLJIT_ADDD (SLJIT_FOP2_BASE + 0)
#define SLJIT_ADDS (SLJIT_ADDD | SLJIT_SINGLE_OP)
/* Flags: SP - (never set any flags) */
-#define SLJIT_SUBD 41
+#define SLJIT_SUBD (SLJIT_FOP2_BASE + 1)
#define SLJIT_SUBS (SLJIT_SUBD | SLJIT_SINGLE_OP)
/* Flags: SP - (never set any flags) */
-#define SLJIT_MULD 42
+#define SLJIT_MULD (SLJIT_FOP2_BASE + 2)
#define SLJIT_MULS (SLJIT_MULD | SLJIT_SINGLE_OP)
/* Flags: SP - (never set any flags) */
-#define SLJIT_DIVD 43
+#define SLJIT_DIVD (SLJIT_FOP2_BASE + 3)
#define SLJIT_DIVS (SLJIT_DIVD | SLJIT_SINGLE_OP)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
@@ -888,7 +1034,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
sljit_si src, sljit_sw srcw,
sljit_si type);
-/* Copies the base address of SLJIT_LOCALS_REG+offset to dst.
+/* Copies the base address of SLJIT_SP + offset to dst.
Flags: - (never set any flags) */
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset);
@@ -912,7 +1058,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
/* --------------------------------------------------------------------- */
#define SLJIT_MAJOR_VERSION 0
-#define SLJIT_MINOR_VERSION 91
+#define SLJIT_MINOR_VERSION 92
/* Get the human readable name of the platform. Can be useful on platforms
like ARM, where ARM and Thumb2 functions can be mixed, and