X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=sljit%2FsljitLir.h;h=2e2e9ac09cd660883f7c362b2260c7730a6060ca;hb=86ef59c527b0015060b75bf41698f0310bb1ef72;hp=e2cd21846df431450d992600016070faeb54247c;hpb=dd986e8b547c0dde924c4b566ad0894ad4f1beb9;p=pcre3.git diff --git a/sljit/sljitLir.h b/sljit/sljitLir.h index e2cd218..2e2e9ac 100644 --- a/sljit/sljitLir.h +++ b/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 @@ -97,83 +95,178 @@ of sljitConfigInternal.h */ /* Cannot allocate executable memory. Only for sljit_generate_code() */ #define SLJIT_ERR_EX_ALLOC_FAILED 3 -/* return value for SLJIT_CONFIG_UNSUPPORTED empty architecture. */ +/* Return value for SLJIT_CONFIG_UNSUPPORTED placeholder architecture. */ #define SLJIT_ERR_UNSUPPORTED 4 +/* An ivalid argument is passed to any SLJIT function. */ +#define SLJIT_ERR_BAD_ARGUMENT 5 /* --------------------------------------------------------------------- */ /* 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. */ - -/* 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 +/* 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. */ -#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 +298,7 @@ struct sljit_const { struct sljit_compiler { sljit_si error; + sljit_si options; struct sljit_label *labels; struct sljit_jump *jumps; @@ -213,13 +307,18 @@ struct sljit_compiler { struct sljit_jump *last_jump; struct sljit_const *last_const; + void *allocator_data; 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 +328,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 @@ -266,18 +362,17 @@ struct sljit_compiler { #endif #if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) - sljit_si locals_offset; sljit_si cache_arg; 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; @@ -298,12 +393,15 @@ struct sljit_compiler { FILE* verbose; #endif -#if (defined SLJIT_DEBUG && SLJIT_DEBUG) +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ + || (defined SLJIT_DEBUG && SLJIT_DEBUG) /* Local size passed to the functions. */ sljit_si logical_local_size; #endif -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ + || (defined SLJIT_DEBUG && SLJIT_DEBUG) \ + || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) sljit_si skip_checks; #endif }; @@ -312,11 +410,16 @@ struct sljit_compiler { /* Main functions */ /* --------------------------------------------------------------------- */ -/* Creates an sljit compiler. +/* Creates an sljit compiler. The allocator_data is required by some + custom memory managers. This pointer is passed to SLJIT_MALLOC + and SLJIT_FREE macros. Most allocators (including the default + one) ignores this value, and it is recommended to pass NULL + as a dummy value for allocator_data. + 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 *allocator_data); -/* Free everything except the compiled machine code. */ +/* Frees everything except the compiled machine code. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler); /* Returns the current error code. If an error is occurred, future sljit @@ -326,6 +429,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compile 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; } +/* Sets the compiler error code to SLJIT_ERR_ALLOC_FAILED except + if an error was detected before. After the error code is set + the compiler behaves as if the allocation failure happened + during an sljit function call. This can greatly simplify error + checking, since only the compiler status needs to be checked + after the compilation. */ +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler); + /* 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 @@ -361,46 +472,69 @@ 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. The + available options are listed before sljit_emit_enter. + + 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. +*/ + +/* The absolute address returned by sljit_get_local_base with +offset 0 is aligned to sljit_d. Otherwise it is aligned to sljit_uw. */ +#define SLJIT_DOUBLE_ALIGNMENT 0x00000001 +/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */ #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_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler, + 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 +683,61 @@ 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) + Note: breakpoint instruction is not supported by all architectures (e.g. 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 is placed into SLJIT_R1:SLJIT_R0 (high:low) word */ +#define SLJIT_LUMUL (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 is placed into SLJIT_R1:SLJIT_R0 (high:low) word */ +#define SLJIT_LSMUL (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 -#define SLJIT_IUDIV (SLJIT_UDIV | SLJIT_INT_OP) + Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1. + The result is placed into SLJIT_R0 and the remainder into SLJIT_R1. + Note: if SLJIT_R1 is 0, the behaviour is undefined. */ +#define SLJIT_UDIVMOD (SLJIT_OP0_BASE + 4) +#define SLJIT_IUDIVMOD (SLJIT_UDIVMOD | 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 -#define SLJIT_ISDIV (SLJIT_SDIV | SLJIT_INT_OP) + Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1. + The result is placed into SLJIT_R0 and the remainder into SLJIT_R1. + Note: if SLJIT_R1 is 0, the behaviour is undefined. + Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00), + the behaviour is undefined. */ +#define SLJIT_SDIVMOD (SLJIT_OP0_BASE + 5) +#define SLJIT_ISDIVMOD (SLJIT_SDIVMOD | SLJIT_INT_OP) +/* Flags: I - (may destroy flags) + Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1. + The result is placed into SLJIT_R0. SLJIT_R1 preserves its value. + Note: if SLJIT_R1 is 0, the behaviour is undefined. + Note: SLJIT_SDIV is single precision divide. */ +#define SLJIT_UDIVI (SLJIT_OP0_BASE + 6) +#define SLJIT_IUDIVI (SLJIT_UDIVI | SLJIT_INT_OP) +/* Flags: I - (may destroy flags) + Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1. + The result is placed into SLJIT_R0. SLJIT_R1 preserves its value. + Note: if SLJIT_R1 is 0, the behaviour is undefined. + Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00), + the behaviour is undefined. + Note: SLJIT_SDIV is single precision divide. */ +#define SLJIT_SDIVI (SLJIT_OP0_BASE + 7) +#define SLJIT_ISDIVI (SLJIT_SDIVI | 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 +750,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, @@ -708,68 +869,66 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler sljit_si src1, sljit_sw src1w, 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). */ - -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 - sljit_emit_op_custom. It has a similar purpose as inline assembly. - The size parameter must match to the instruction size of the target - architecture: - - x86: 0 < size <= 15. The instruction argument can be byte aligned. - Thumb2: if size == 2, the instruction argument must be 2 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. */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler, - void *instruction, sljit_si size); - /* Returns with non-zero if fpu is available. */ 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_DMOV (SLJIT_FOP1_BASE + 0) +#define SLJIT_SMOV (SLJIT_DMOV | 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_MOVD 37 -#define SLJIT_MOVS (SLJIT_MOVD | SLJIT_SINGLE_OP) +#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_NEGD 38 -#define SLJIT_NEGS (SLJIT_NEGD | SLJIT_SINGLE_OP) +#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_ABSD 39 -#define SLJIT_ABSS (SLJIT_ABSD | SLJIT_SINGLE_OP) +#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_DCMP (SLJIT_FOP1_BASE + 6) +#define SLJIT_SCMP (SLJIT_DCMP | SLJIT_SINGLE_OP) +/* Flags: SP - (never set any flags) */ +#define SLJIT_DNEG (SLJIT_FOP1_BASE + 7) +#define SLJIT_SNEG (SLJIT_DNEG | SLJIT_SINGLE_OP) +/* Flags: SP - (never set any flags) */ +#define SLJIT_DABS (SLJIT_FOP1_BASE + 8) +#define SLJIT_SABS (SLJIT_DABS | 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_ADDS (SLJIT_ADDD | SLJIT_SINGLE_OP) +#define SLJIT_DADD (SLJIT_FOP2_BASE + 0) +#define SLJIT_SADD (SLJIT_DADD | SLJIT_SINGLE_OP) /* Flags: SP - (never set any flags) */ -#define SLJIT_SUBD 41 -#define SLJIT_SUBS (SLJIT_SUBD | SLJIT_SINGLE_OP) +#define SLJIT_DSUB (SLJIT_FOP2_BASE + 1) +#define SLJIT_SSUB (SLJIT_DSUB | SLJIT_SINGLE_OP) /* Flags: SP - (never set any flags) */ -#define SLJIT_MULD 42 -#define SLJIT_MULS (SLJIT_MULD | SLJIT_SINGLE_OP) +#define SLJIT_DMUL (SLJIT_FOP2_BASE + 2) +#define SLJIT_SMUL (SLJIT_DMUL | SLJIT_SINGLE_OP) /* Flags: SP - (never set any flags) */ -#define SLJIT_DIVD 43 -#define SLJIT_DIVS (SLJIT_DIVD | SLJIT_SINGLE_OP) +#define SLJIT_DDIV (SLJIT_FOP2_BASE + 3) +#define SLJIT_SDIV (SLJIT_DDIV | SLJIT_SINGLE_OP) SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, @@ -780,36 +939,64 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler); -/* Invert conditional instruction: xor (^) with 0x1 */ -#define SLJIT_C_EQUAL 0 -#define SLJIT_C_ZERO 0 -#define SLJIT_C_NOT_EQUAL 1 -#define SLJIT_C_NOT_ZERO 1 - -#define SLJIT_C_LESS 2 -#define SLJIT_C_GREATER_EQUAL 3 -#define SLJIT_C_GREATER 4 -#define SLJIT_C_LESS_EQUAL 5 -#define SLJIT_C_SIG_LESS 6 -#define SLJIT_C_SIG_GREATER_EQUAL 7 -#define SLJIT_C_SIG_GREATER 8 -#define SLJIT_C_SIG_LESS_EQUAL 9 - -#define SLJIT_C_OVERFLOW 10 -#define SLJIT_C_NOT_OVERFLOW 11 - -#define SLJIT_C_MUL_OVERFLOW 12 -#define SLJIT_C_MUL_NOT_OVERFLOW 13 - -#define SLJIT_C_FLOAT_EQUAL 14 -#define SLJIT_C_FLOAT_NOT_EQUAL 15 -#define SLJIT_C_FLOAT_LESS 16 -#define SLJIT_C_FLOAT_GREATER_EQUAL 17 -#define SLJIT_C_FLOAT_GREATER 18 -#define SLJIT_C_FLOAT_LESS_EQUAL 19 -#define SLJIT_C_FLOAT_UNORDERED 20 -#define SLJIT_C_FLOAT_ORDERED 21 - +/* Invert (negate) conditional type: xor (^) with 0x1 */ + +/* Integer comparison types. */ +#define SLJIT_EQUAL 0 +#define SLJIT_I_EQUAL (SLJIT_EQUAL | SLJIT_INT_OP) +#define SLJIT_ZERO 0 +#define SLJIT_I_ZERO (SLJIT_ZERO | SLJIT_INT_OP) +#define SLJIT_NOT_EQUAL 1 +#define SLJIT_I_NOT_EQUAL (SLJIT_NOT_EQUAL | SLJIT_INT_OP) +#define SLJIT_NOT_ZERO 1 +#define SLJIT_I_NOT_ZERO (SLJIT_NOT_ZERO | SLJIT_INT_OP) + +#define SLJIT_LESS 2 +#define SLJIT_I_LESS (SLJIT_LESS | SLJIT_INT_OP) +#define SLJIT_GREATER_EQUAL 3 +#define SLJIT_I_GREATER_EQUAL (SLJIT_GREATER_EQUAL | SLJIT_INT_OP) +#define SLJIT_GREATER 4 +#define SLJIT_I_GREATER (SLJIT_GREATER | SLJIT_INT_OP) +#define SLJIT_LESS_EQUAL 5 +#define SLJIT_I_LESS_EQUAL (SLJIT_LESS_EQUAL | SLJIT_INT_OP) +#define SLJIT_SIG_LESS 6 +#define SLJIT_I_SIG_LESS (SLJIT_SIG_LESS | SLJIT_INT_OP) +#define SLJIT_SIG_GREATER_EQUAL 7 +#define SLJIT_I_SIG_GREATER_EQUAL (SLJIT_SIG_GREATER_EQUAL | SLJIT_INT_OP) +#define SLJIT_SIG_GREATER 8 +#define SLJIT_I_SIG_GREATER (SLJIT_SIG_GREATER | SLJIT_INT_OP) +#define SLJIT_SIG_LESS_EQUAL 9 +#define SLJIT_I_SIG_LESS_EQUAL (SLJIT_SIG_LESS_EQUAL | SLJIT_INT_OP) + +#define SLJIT_OVERFLOW 10 +#define SLJIT_I_OVERFLOW (SLJIT_OVERFLOW | SLJIT_INT_OP) +#define SLJIT_NOT_OVERFLOW 11 +#define SLJIT_I_NOT_OVERFLOW (SLJIT_NOT_OVERFLOW | SLJIT_INT_OP) + +#define SLJIT_MUL_OVERFLOW 12 +#define SLJIT_I_MUL_OVERFLOW (SLJIT_MUL_OVERFLOW | SLJIT_INT_OP) +#define SLJIT_MUL_NOT_OVERFLOW 13 +#define SLJIT_I_MUL_NOT_OVERFLOW (SLJIT_MUL_NOT_OVERFLOW | SLJIT_INT_OP) + +/* Floating point comparison types. */ +#define SLJIT_D_EQUAL 14 +#define SLJIT_S_EQUAL (SLJIT_D_EQUAL | SLJIT_SINGLE_OP) +#define SLJIT_D_NOT_EQUAL 15 +#define SLJIT_S_NOT_EQUAL (SLJIT_D_NOT_EQUAL | SLJIT_SINGLE_OP) +#define SLJIT_D_LESS 16 +#define SLJIT_S_LESS (SLJIT_D_LESS | SLJIT_SINGLE_OP) +#define SLJIT_D_GREATER_EQUAL 17 +#define SLJIT_S_GREATER_EQUAL (SLJIT_D_GREATER_EQUAL | SLJIT_SINGLE_OP) +#define SLJIT_D_GREATER 18 +#define SLJIT_S_GREATER (SLJIT_D_GREATER | SLJIT_SINGLE_OP) +#define SLJIT_D_LESS_EQUAL 19 +#define SLJIT_S_LESS_EQUAL (SLJIT_D_LESS_EQUAL | SLJIT_SINGLE_OP) +#define SLJIT_D_UNORDERED 20 +#define SLJIT_S_UNORDERED (SLJIT_D_UNORDERED | SLJIT_SINGLE_OP) +#define SLJIT_D_ORDERED 21 +#define SLJIT_S_ORDERED (SLJIT_D_ORDERED | SLJIT_SINGLE_OP) + +/* Unconditional jump types. */ #define SLJIT_JUMP 22 #define SLJIT_FAST_CALL 23 #define SLJIT_CALL0 24 @@ -823,7 +1010,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi #define SLJIT_REWRITABLE_JUMP 0x1000 /* Emit a jump instruction. The destination is not set, only the type of the jump. - type must be between SLJIT_C_EQUAL and SLJIT_CALL3 + type must be between SLJIT_EQUAL and SLJIT_CALL3 type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP Flags: - (never set any flags) for both conditional and unconditional jumps. Flags: destroy all flags for calls. */ @@ -832,10 +1019,10 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile /* Basic arithmetic comparison. In most architectures it is implemented as an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting appropriate flags) followed by a sljit_emit_jump. However some - architectures (i.e: MIPS) may employ special optimizations here. It is - suggested to use this comparison form when appropriate. - 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 + architectures (i.e: ARM64 or MIPS) may employ special optimizations here. + It is suggested to use this comparison form when appropriate. + type must be between SLJIT_EQUAL and SLJIT_I_SIG_LESS_EQUAL + type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP Flags: destroy flags. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type, sljit_si src1, sljit_sw src1w, @@ -846,11 +1033,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler sljit_emit_jump. However some architectures (i.e: MIPS) may employ special optimizations here. It is suggested to use this comparison form when appropriate. - type must be between SLJIT_C_FLOAT_EQUAL and SLJIT_C_FLOAT_ORDERED - type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and SLJIT_SINGLE_OP + type must be between SLJIT_D_EQUAL and SLJIT_S_ORDERED + type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP Flags: destroy flags. Note: if either operand is NaN, the behaviour is undefined for - type <= SLJIT_C_FLOAT_LESS_EQUAL. */ + types up to SLJIT_S_LESS_EQUAL. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w); @@ -869,8 +1056,8 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw); /* Perform the operation using the conditional flags as the second argument. - Type must always be between SLJIT_C_EQUAL and SLJIT_C_FLOAT_ORDERED. The - value represented by the type is 1, if the condition represented by the type + Type must always be between SLJIT_EQUAL and SLJIT_S_ORDERED. The 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: @@ -888,7 +1075,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 +1099,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 93 /* Get the human readable name of the platform. Can be useful on platforms like ARM, where ARM and Thumb2 functions can be mixed, and @@ -958,10 +1145,11 @@ struct sljit_stack { }; /* Returns NULL if unsuccessful. - Note: limit and max_limit contains the size for stack allocation - Note: the top field is initialized to base. */ -SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit); -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* stack); + Note: limit and max_limit contains the size for stack allocation. + Note: the top field is initialized to base. + Note: see sljit_create_compiler for the explanation of allocator_data. */ +SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data); +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack *stack, void *allocator_data); /* Can be used to increase (allocate) or decrease (free) the memory area. Returns with a non-zero value if unsuccessful. If new_limit is greater than @@ -969,7 +1157,7 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* st 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 sljit_stack_resize fails. */ -SLJIT_API_FUNC_ATTRIBUTE sljit_sw 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) */ @@ -998,4 +1186,64 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct #endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */ +/* --------------------------------------------------------------------- */ +/* CPU specific functions */ +/* --------------------------------------------------------------------- */ + +/* The following function is a helper function for sljit_emit_op_custom. + 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 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); + +/* Any instruction can be inserted into the instruction stream by + sljit_emit_op_custom. It has a similar purpose as inline assembly. + The size parameter must match to the instruction size of the target + architecture: + + x86: 0 < size <= 15. The instruction argument can be byte aligned. + Thumb2: if size == 2, the instruction argument must be 2 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. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, sljit_si size); + +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) + +/* Returns with non-zero if sse2 is available. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_is_sse2_available(void); + +/* Returns with non-zero if cmov instruction is available. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_is_cmov_available(void); + +/* Emit a conditional mov instruction on x86 CPUs. This instruction + moves src to destination, if the condition is satisfied. Unlike + other arithmetic instructions, destination must be a register. + Before such instructions are emitted, cmov support should be + checked by sljit_x86_is_cmov_available function. + type must be between SLJIT_EQUAL and SLJIT_S_ORDERED + dst_reg must be a valid register and it can be combined + with SLJIT_INT_OP to perform 32 bit arithmetic + Flags: I - (never set any flags) + */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_emit_cmov(struct sljit_compiler *compiler, + sljit_si type, + sljit_si dst_reg, + sljit_si src, sljit_sw srcw); + +#endif + #endif /* _SLJIT_LIR_H_ */