version 1.1.1.3, 2012/10/09 09:19:18
|
version 1.1.1.4, 2013/07/22 08:25:57
|
Line 24
|
Line 24
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
*/ |
|
|
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name() | SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void) |
{ |
{ |
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) |
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) |
return "ARMv7" SLJIT_CPUINFO; |
return "ARMv7" SLJIT_CPUINFO; |
Line 41 SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_p
|
Line 41 SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_p
|
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3) |
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3) |
#define TMP_PC (SLJIT_NO_REGISTERS + 4) |
#define TMP_PC (SLJIT_NO_REGISTERS + 4) |
|
|
#define TMP_FREG1 (SLJIT_FLOAT_REG4 + 1) | #define TMP_FREG1 (0) |
#define TMP_FREG2 (SLJIT_FLOAT_REG4 + 2) | #define TMP_FREG2 (SLJIT_FLOAT_REG6 + 1) |
|
|
/* In ARM instruction words. |
/* In ARM instruction words. |
Cache lines are usually 32 byte aligned. */ |
Cache lines are usually 32 byte aligned. */ |
Line 52 SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_p
|
Line 52 SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_p
|
#define ALIGN_INSTRUCTION(ptr) \ |
#define ALIGN_INSTRUCTION(ptr) \ |
(sljit_uw*)(((sljit_uw)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1)) |
(sljit_uw*)(((sljit_uw)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1)) |
#define MAX_DIFFERENCE(max_diff) \ |
#define MAX_DIFFERENCE(max_diff) \ |
(((max_diff) / (int)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1)) | (((max_diff) / (sljit_si)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1)) |
|
|
/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */ |
/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */ |
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = { |
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = { |
0, 0, 1, 2, 10, 11, 4, 5, 6, 7, 8, 13, 3, 12, 14, 15 | 0, 0, 1, 2, 10, 11, 4, 5, 6, 7, 8, 13, 3, 12, 14, 15 |
}; |
}; |
|
|
#define RM(rm) (reg_map[rm]) |
#define RM(rm) (reg_map[rm]) |
Line 99 static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS
|
Line 99 static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS
|
#define SMULL 0xe0c00090 |
#define SMULL 0xe0c00090 |
#define SUB_DP 0x2 |
#define SUB_DP 0x2 |
#define UMULL 0xe0800090 |
#define UMULL 0xe0800090 |
#define VABS_F64 0xeeb00bc0 | #define VABS_F32 0xeeb00ac0 |
#define VADD_F64 0xee300b00 | #define VADD_F32 0xee300a00 |
#define VCMP_F64 0xeeb40b40 | #define VCMP_F32 0xeeb40a40 |
#define VDIV_F64 0xee800b00 | #define VDIV_F32 0xee800a00 |
#define VMOV_F64 0xeeb00b40 | #define VMOV_F32 0xeeb00a40 |
#define VMRS 0xeef1fa10 |
#define VMRS 0xeef1fa10 |
#define VMUL_F64 0xee200b00 | #define VMUL_F32 0xee200a00 |
#define VNEG_F64 0xeeb10b40 | #define VNEG_F32 0xeeb10a40 |
#define VSTR 0xed000b00 | #define VSTR_F32 0xed000a00 |
#define VSUB_F64 0xee300b40 | #define VSUB_F32 0xee300a40 |
|
|
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) |
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) |
/* Arm v7 specific instructions. */ |
/* Arm v7 specific instructions. */ |
Line 122 static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS
|
Line 122 static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS
|
|
|
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
|
|
static int push_cpool(struct sljit_compiler *compiler) | static sljit_si push_cpool(struct sljit_compiler *compiler) |
{ |
{ |
/* Pushing the constant pool into the instruction stream. */ |
/* Pushing the constant pool into the instruction stream. */ |
sljit_uw* inst; |
sljit_uw* inst; |
sljit_uw* cpool_ptr; |
sljit_uw* cpool_ptr; |
sljit_uw* cpool_end; |
sljit_uw* cpool_end; |
int i; | sljit_si i; |
|
|
/* The label could point the address after the constant pool. */ |
/* The label could point the address after the constant pool. */ |
if (compiler->last_label && compiler->last_label->size == compiler->size) |
if (compiler->last_label && compiler->last_label->size == compiler->size) |
Line 160 static int push_cpool(struct sljit_compiler *compiler)
|
Line 160 static int push_cpool(struct sljit_compiler *compiler)
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
static int push_inst(struct sljit_compiler *compiler, sljit_uw inst) | static sljit_si push_inst(struct sljit_compiler *compiler, sljit_uw inst) |
{ |
{ |
sljit_uw* ptr; |
sljit_uw* ptr; |
|
|
Line 174 static int push_inst(struct sljit_compiler *compiler,
|
Line 174 static int push_inst(struct sljit_compiler *compiler,
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
static int push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal) | static sljit_si push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal) |
{ |
{ |
sljit_uw* ptr; |
sljit_uw* ptr; |
sljit_uw cpool_index = CPOOL_SIZE; |
sljit_uw cpool_index = CPOOL_SIZE; |
Line 224 static int push_inst_with_literal(struct sljit_compile
|
Line 224 static int push_inst_with_literal(struct sljit_compile
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
static int push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal) | static sljit_si push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal) |
{ |
{ |
sljit_uw* ptr; |
sljit_uw* ptr; |
if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE)) |
if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE)) |
Line 244 static int push_inst_with_unique_literal(struct sljit_
|
Line 244 static int push_inst_with_unique_literal(struct sljit_
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
static SLJIT_INLINE int prepare_blx(struct sljit_compiler *compiler) | static SLJIT_INLINE sljit_si prepare_blx(struct sljit_compiler *compiler) |
{ |
{ |
/* Place for at least two instruction (doesn't matter whether the first has a literal). */ |
/* Place for at least two instruction (doesn't matter whether the first has a literal). */ |
if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4088))) |
if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4088))) |
Line 252 static SLJIT_INLINE int prepare_blx(struct sljit_compi
|
Line 252 static SLJIT_INLINE int prepare_blx(struct sljit_compi
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
static SLJIT_INLINE int emit_blx(struct sljit_compiler *compiler) | static SLJIT_INLINE sljit_si emit_blx(struct sljit_compiler *compiler) |
{ |
{ |
/* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */ |
/* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */ |
SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092)); |
SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092)); |
Line 282 static sljit_uw patch_pc_relative_loads(sljit_uw *last
|
Line 282 static sljit_uw patch_pc_relative_loads(sljit_uw *last
|
|
|
/* Must be a load instruction with immediate offset. */ |
/* Must be a load instruction with immediate offset. */ |
SLJIT_ASSERT(ind < cpool_size && !(*last_pc_patch & (1 << 25)) && (*last_pc_patch & (1 << 20))); |
SLJIT_ASSERT(ind < cpool_size && !(*last_pc_patch & (1 << 25)) && (*last_pc_patch & (1 << 20))); |
if ((int)const_pool[ind] < 0) { | if ((sljit_si)const_pool[ind] < 0) { |
const_pool[ind] = counter; |
const_pool[ind] = counter; |
ind = counter; |
ind = counter; |
counter++; |
counter++; |
Line 307 static sljit_uw patch_pc_relative_loads(sljit_uw *last
|
Line 307 static sljit_uw patch_pc_relative_loads(sljit_uw *last
|
/* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */ |
/* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */ |
struct future_patch { |
struct future_patch { |
struct future_patch* next; |
struct future_patch* next; |
int index; | sljit_si index; |
int value; | sljit_si value; |
}; |
}; |
|
|
static SLJIT_INLINE int resolve_const_pool_index(struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr) | static SLJIT_INLINE sljit_si resolve_const_pool_index(struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr) |
{ |
{ |
int value; | sljit_si value; |
struct future_patch *curr_patch, *prev_patch; |
struct future_patch *curr_patch, *prev_patch; |
|
|
/* Using the values generated by patch_pc_relative_loads. */ |
/* Using the values generated by patch_pc_relative_loads. */ |
if (!*first_patch) |
if (!*first_patch) |
value = (int)cpool_start_address[cpool_current_index]; | value = (sljit_si)cpool_start_address[cpool_current_index]; |
else { |
else { |
curr_patch = *first_patch; |
curr_patch = *first_patch; |
prev_patch = 0; |
prev_patch = 0; |
while (1) { |
while (1) { |
if (!curr_patch) { |
if (!curr_patch) { |
value = (int)cpool_start_address[cpool_current_index]; | value = (sljit_si)cpool_start_address[cpool_current_index]; |
break; |
break; |
} |
} |
if ((sljit_uw)curr_patch->index == cpool_current_index) { |
if ((sljit_uw)curr_patch->index == cpool_current_index) { |
Line 364 static SLJIT_INLINE int resolve_const_pool_index(struc
|
Line 364 static SLJIT_INLINE int resolve_const_pool_index(struc
|
|
|
#else |
#else |
|
|
static int push_inst(struct sljit_compiler *compiler, sljit_uw inst) | static sljit_si push_inst(struct sljit_compiler *compiler, sljit_uw inst) |
{ |
{ |
sljit_uw* ptr; |
sljit_uw* ptr; |
|
|
Line 375 static int push_inst(struct sljit_compiler *compiler,
|
Line 375 static int push_inst(struct sljit_compiler *compiler,
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
static SLJIT_INLINE int emit_imm(struct sljit_compiler *compiler, int reg, sljit_w imm) | static SLJIT_INLINE sljit_si emit_imm(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm) |
{ |
{ |
FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff))); |
FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff))); |
return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff)); |
return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff)); |
Line 383 static SLJIT_INLINE int emit_imm(struct sljit_compiler
|
Line 383 static SLJIT_INLINE int emit_imm(struct sljit_compiler
|
|
|
#endif |
#endif |
|
|
static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code) | static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code) |
{ |
{ |
sljit_w diff; | sljit_sw diff; |
|
|
if (jump->flags & SLJIT_REWRITABLE_JUMP) |
if (jump->flags & SLJIT_REWRITABLE_JUMP) |
return 0; |
return 0; |
Line 395 static SLJIT_INLINE int detect_jump_type(struct sljit_
|
Line 395 static SLJIT_INLINE int detect_jump_type(struct sljit_
|
code_ptr--; |
code_ptr--; |
|
|
if (jump->flags & JUMP_ADDR) |
if (jump->flags & JUMP_ADDR) |
diff = ((sljit_w)jump->u.target - (sljit_w)(code_ptr + 2)); | diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2)); |
else { |
else { |
SLJIT_ASSERT(jump->flags & JUMP_LABEL); |
SLJIT_ASSERT(jump->flags & JUMP_LABEL); |
diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)(code_ptr + 2)); | diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2)); |
} |
} |
|
|
/* Branch to Thumb code has not been optimized yet. */ |
/* Branch to Thumb code has not been optimized yet. */ |
if (diff & 0x3) |
if (diff & 0x3) |
return 0; |
return 0; |
|
|
diff >>= 2; |
|
if (jump->flags & IS_BL) { |
if (jump->flags & IS_BL) { |
if (diff <= 0x01ffffff && diff >= -0x02000000) { |
if (diff <= 0x01ffffff && diff >= -0x02000000) { |
*code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK); |
*code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK); |
Line 421 static SLJIT_INLINE int detect_jump_type(struct sljit_
|
Line 420 static SLJIT_INLINE int detect_jump_type(struct sljit_
|
} |
} |
#else |
#else |
if (jump->flags & JUMP_ADDR) |
if (jump->flags & JUMP_ADDR) |
diff = ((sljit_w)jump->u.target - (sljit_w)code_ptr); | diff = ((sljit_sw)jump->u.target - (sljit_sw)code_ptr); |
else { |
else { |
SLJIT_ASSERT(jump->flags & JUMP_LABEL); |
SLJIT_ASSERT(jump->flags & JUMP_LABEL); |
diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)code_ptr); | diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)code_ptr); |
} |
} |
|
|
/* Branch to Thumb code has not been optimized yet. */ |
/* Branch to Thumb code has not been optimized yet. */ |
if (diff & 0x3) |
if (diff & 0x3) |
return 0; |
return 0; |
|
|
diff >>= 2; |
|
if (diff <= 0x01ffffff && diff >= -0x02000000) { |
if (diff <= 0x01ffffff && diff >= -0x02000000) { |
code_ptr -= 2; |
code_ptr -= 2; |
*code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (code_ptr[2] & COND_MASK); |
*code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (code_ptr[2] & COND_MASK); |
Line 442 static SLJIT_INLINE int detect_jump_type(struct sljit_
|
Line 440 static SLJIT_INLINE int detect_jump_type(struct sljit_
|
return 0; |
return 0; |
} |
} |
|
|
static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, int flush) | static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, sljit_si flush) |
{ |
{ |
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
sljit_uw *ptr = (sljit_uw*)addr; |
sljit_uw *ptr = (sljit_uw*)addr; |
sljit_uw *inst = (sljit_uw*)ptr[0]; |
sljit_uw *inst = (sljit_uw*)ptr[0]; |
sljit_uw mov_pc = ptr[1]; |
sljit_uw mov_pc = ptr[1]; |
int bl = (mov_pc & 0x0000f000) != RD(TMP_PC); | sljit_si bl = (mov_pc & 0x0000f000) != RD(TMP_PC); |
sljit_w diff = (sljit_w)(((sljit_w)new_addr - (sljit_w)(inst + 2)) >> 2); | sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2)) >> 2); |
|
|
if (diff <= 0x7fffff && diff >= -0x800000) { |
if (diff <= 0x7fffff && diff >= -0x800000) { |
/* Turn to branch. */ |
/* Turn to branch. */ |
Line 498 static SLJIT_INLINE void inline_set_jump_addr(sljit_uw
|
Line 496 static SLJIT_INLINE void inline_set_jump_addr(sljit_uw
|
#endif |
#endif |
} |
} |
|
|
static sljit_uw get_immediate(sljit_uw imm); | static sljit_uw get_imm(sljit_uw imm); |
|
|
static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_w new_constant, int flush) | static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw new_constant, sljit_si flush) |
{ |
{ |
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
sljit_uw *ptr = (sljit_uw*)addr; |
sljit_uw *ptr = (sljit_uw*)addr; |
Line 508 static SLJIT_INLINE void inline_set_const(sljit_uw add
|
Line 506 static SLJIT_INLINE void inline_set_const(sljit_uw add
|
sljit_uw ldr_literal = ptr[1]; |
sljit_uw ldr_literal = ptr[1]; |
sljit_uw src2; |
sljit_uw src2; |
|
|
src2 = get_immediate(new_constant); | src2 = get_imm(new_constant); |
if (src2) { |
if (src2) { |
*inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2; |
*inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2; |
if (flush) { |
if (flush) { |
Line 517 static SLJIT_INLINE void inline_set_const(sljit_uw add
|
Line 515 static SLJIT_INLINE void inline_set_const(sljit_uw add
|
return; |
return; |
} |
} |
|
|
src2 = get_immediate(~new_constant); | src2 = get_imm(~new_constant); |
if (src2) { |
if (src2) { |
*inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2; |
*inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2; |
if (flush) { |
if (flush) { |
Line 730 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
Line 728 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
if (jump->flags & PATCH_B) { |
if (jump->flags & PATCH_B) { |
if (!(jump->flags & JUMP_ADDR)) { |
if (!(jump->flags & JUMP_ADDR)) { |
SLJIT_ASSERT(jump->flags & JUMP_LABEL); |
SLJIT_ASSERT(jump->flags & JUMP_LABEL); |
SLJIT_ASSERT(((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) >= -0x02000000); | SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - (sljit_sw)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - (sljit_sw)(buf_ptr + 2)) >= -0x02000000); |
*buf_ptr |= (((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) >> 2) & 0x00ffffff; | *buf_ptr |= (((sljit_sw)jump->u.label->addr - (sljit_sw)(buf_ptr + 2)) >> 2) & 0x00ffffff; |
} |
} |
else { |
else { |
SLJIT_ASSERT(((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) >= -0x02000000); | SLJIT_ASSERT(((sljit_sw)jump->u.target - (sljit_sw)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_sw)jump->u.target - (sljit_sw)(buf_ptr + 2)) >= -0x02000000); |
*buf_ptr |= (((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) >> 2) & 0x00ffffff; | *buf_ptr |= (((sljit_sw)jump->u.target - (sljit_sw)(buf_ptr + 2)) >> 2) & 0x00ffffff; |
} |
} |
} |
} |
else if (jump->flags & SLJIT_REWRITABLE_JUMP) { |
else if (jump->flags & SLJIT_REWRITABLE_JUMP) { |
Line 785 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
Line 783 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
} |
} |
#endif |
#endif |
|
|
SLJIT_ASSERT(code_ptr - code <= (int)size); | SLJIT_ASSERT(code_ptr - code <= (sljit_si)size); |
|
|
SLJIT_CACHE_FLUSH(code, code_ptr); |
|
compiler->error = SLJIT_ERR_COMPILED; |
compiler->error = SLJIT_ERR_COMPILED; |
compiler->executable_size = size * sizeof(sljit_uw); | compiler->executable_size = (code_ptr - code) * sizeof(sljit_uw); |
| SLJIT_CACHE_FLUSH(code, code_ptr); |
return code; |
return code; |
} |
} |
|
|
|
/* --------------------------------------------------------------------- */ |
|
/* Entry, exit */ |
|
/* --------------------------------------------------------------------- */ |
|
|
/* emit_op inp_flags. |
/* emit_op inp_flags. |
WRITE_BACK must be the first, since it is a flag. */ |
WRITE_BACK must be the first, since it is a flag. */ |
#define WRITE_BACK 0x01 |
#define WRITE_BACK 0x01 |
Line 815 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
Line 817 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
#define EMIT_DATA_PROCESS_INS(opcode, set_flags, dst, src1, src2) \ |
#define EMIT_DATA_PROCESS_INS(opcode, set_flags, dst, src1, src2) \ |
(0xe0000000 | ((opcode) << 21) | (set_flags) | RD(dst) | RN(src1) | (src2)) |
(0xe0000000 | ((opcode) << 21) | (set_flags) | RD(dst) | RN(src1) | (src2)) |
|
|
static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags, | static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si inp_flags, |
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); |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) | 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) |
{ |
{ |
int size; | sljit_si size; |
sljit_uw push; |
sljit_uw push; |
|
|
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size); | check_sljit_emit_enter(compiler, args, scratches, saveds, local_size); |
|
|
compiler->temporaries = temporaries; | compiler->scratches = scratches; |
compiler->saveds = saveds; |
compiler->saveds = saveds; |
#if (defined SLJIT_DEBUG && SLJIT_DEBUG) |
#if (defined SLJIT_DEBUG && SLJIT_DEBUG) |
compiler->logical_local_size = local_size; |
compiler->logical_local_size = local_size; |
Line 837 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s
|
Line 839 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s
|
/* Push saved registers, temporary registers |
/* Push saved registers, temporary registers |
stmdb sp!, {..., lr} */ |
stmdb sp!, {..., lr} */ |
push = PUSH | (1 << 14); |
push = PUSH | (1 << 14); |
if (temporaries >= 5) | if (scratches >= 5) |
push |= 1 << 11; |
push |= 1 << 11; |
if (temporaries >= 4) | if (scratches >= 4) |
push |= 1 << 10; |
push |= 1 << 10; |
if (saveds >= 5) |
if (saveds >= 5) |
push |= 1 << 8; |
push |= 1 << 8; |
Line 855 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s
|
Line 857 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s
|
|
|
/* Stack must be aligned to 8 bytes: */ |
/* Stack must be aligned to 8 bytes: */ |
size = (1 + saveds) * sizeof(sljit_uw); |
size = (1 + saveds) * sizeof(sljit_uw); |
if (temporaries >= 4) | if (scratches >= 4) |
size += (temporaries - 3) * sizeof(sljit_uw); | size += (scratches - 3) * sizeof(sljit_uw); |
local_size += size; |
local_size += size; |
local_size = (local_size + 7) & ~7; |
local_size = (local_size + 7) & ~7; |
local_size -= size; |
local_size -= size; |
Line 865 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s
|
Line 867 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s
|
FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size)); |
FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size)); |
|
|
if (args >= 1) |
if (args >= 1) |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG1, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG1))); | EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG1, SLJIT_UNUSED, RM(SLJIT_SCRATCH_REG1))); |
if (args >= 2) |
if (args >= 2) |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG2, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG2))); | EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG2, SLJIT_UNUSED, RM(SLJIT_SCRATCH_REG2))); |
if (args >= 3) |
if (args >= 3) |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG3, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG3))); | EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG3, SLJIT_UNUSED, RM(SLJIT_SCRATCH_REG3))); |
|
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) | 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) |
{ |
{ |
int size; | sljit_si size; |
|
|
CHECK_ERROR_VOID(); |
CHECK_ERROR_VOID(); |
check_sljit_set_context(compiler, args, temporaries, saveds, local_size); | check_sljit_set_context(compiler, args, scratches, saveds, local_size); |
|
|
compiler->temporaries = temporaries; | compiler->scratches = scratches; |
compiler->saveds = saveds; |
compiler->saveds = saveds; |
#if (defined SLJIT_DEBUG && SLJIT_DEBUG) |
#if (defined SLJIT_DEBUG && SLJIT_DEBUG) |
compiler->logical_local_size = local_size; |
compiler->logical_local_size = local_size; |
#endif |
#endif |
|
|
size = (1 + saveds) * sizeof(sljit_uw); |
size = (1 + saveds) * sizeof(sljit_uw); |
if (temporaries >= 4) | if (scratches >= 4) |
size += (temporaries - 3) * sizeof(sljit_uw); | size += (scratches - 3) * sizeof(sljit_uw); |
local_size += size; |
local_size += size; |
local_size = (local_size + 7) & ~7; |
local_size = (local_size + 7) & ~7; |
local_size -= size; |
local_size -= size; |
compiler->local_size = local_size; |
compiler->local_size = local_size; |
} |
} |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw) | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw) |
{ |
{ |
sljit_uw pop; |
sljit_uw pop; |
|
|
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_return(compiler, op, src, srcw); |
check_sljit_emit_return(compiler, op, src, srcw); |
ADJUST_LOCAL_OFFSET(src, srcw); |
|
|
|
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); |
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); |
|
|
Line 912 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct
|
Line 913 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct
|
pop = POP | (1 << 15); |
pop = POP | (1 << 15); |
/* Push saved registers, temporary registers |
/* Push saved registers, temporary registers |
ldmia sp!, {..., pc} */ |
ldmia sp!, {..., pc} */ |
if (compiler->temporaries >= 5) | if (compiler->scratches >= 5) |
pop |= 1 << 11; |
pop |= 1 << 11; |
if (compiler->temporaries >= 4) | if (compiler->scratches >= 4) |
pop |= 1 << 10; |
pop |= 1 << 10; |
if (compiler->saveds >= 5) |
if (compiler->saveds >= 5) |
pop |= 1 << 8; |
pop |= 1 << 8; |
Line 939 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct
|
Line 940 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct
|
w/b/h/N - word/byte/half/NOT allowed (2 bit) |
w/b/h/N - word/byte/half/NOT allowed (2 bit) |
It contans 16 items, but not all are different. */ |
It contans 16 items, but not all are different. */ |
|
|
static sljit_w data_transfer_insts[16] = { | static sljit_sw data_transfer_insts[16] = { |
/* s u w */ 0xe5000000 /* str */, |
/* s u w */ 0xe5000000 /* str */, |
/* s u b */ 0xe5400000 /* strb */, |
/* s u b */ 0xe5400000 /* strb */, |
/* s u h */ 0xe10000b0 /* strh */, |
/* s u h */ 0xe10000b0 /* strh */, |
Line 1005 static sljit_w data_transfer_insts[16] = {
|
Line 1006 static sljit_w data_transfer_insts[16] = {
|
} \ |
} \ |
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | ((flags & ARGS_SWAPPED) ? reg_map[src2] : reg_map[src1]))); |
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | ((flags & ARGS_SWAPPED) ? reg_map[src2] : reg_map[src1]))); |
|
|
static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags, | static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags, |
int dst, int src1, int src2) | sljit_si dst, sljit_si src1, sljit_si src2) |
{ |
{ |
sljit_w mul_inst; | sljit_sw mul_inst; |
|
|
switch (GET_OPCODE(op)) { |
switch (GET_OPCODE(op)) { |
|
case SLJIT_MOV: |
|
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); |
|
if (dst != src2) { |
|
if (src2 & SRC2_IMM) { |
|
if (flags & INV_IMM) |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); |
|
} |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, reg_map[src2]); |
|
} |
|
return SLJIT_SUCCESS; |
|
|
|
case SLJIT_MOV_UB: |
|
case SLJIT_MOV_SB: |
|
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); |
|
if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) { |
|
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
|
if (op == SLJIT_MOV_UB) |
|
return push_inst(compiler, EMIT_DATA_PROCESS_INS(AND_DP, 0, dst, src2, SRC2_IMM | 0xff)); |
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2])); |
|
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_UB ? 0x20 : 0x40) | reg_map[dst])); |
|
#else |
|
return push_inst(compiler, (op == SLJIT_MOV_UB ? UXTB : SXTB) | RD(dst) | RM(src2)); |
|
#endif |
|
} |
|
else if (dst != src2) { |
|
SLJIT_ASSERT(src2 & SRC2_IMM); |
|
if (flags & INV_IMM) |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); |
|
} |
|
return SLJIT_SUCCESS; |
|
|
|
case SLJIT_MOV_UH: |
|
case SLJIT_MOV_SH: |
|
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); |
|
if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) { |
|
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2])); |
|
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_UH ? 0x20 : 0x40) | reg_map[dst])); |
|
#else |
|
return push_inst(compiler, (op == SLJIT_MOV_UH ? UXTH : SXTH) | RD(dst) | RM(src2)); |
|
#endif |
|
} |
|
else if (dst != src2) { |
|
SLJIT_ASSERT(src2 & SRC2_IMM); |
|
if (flags & INV_IMM) |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); |
|
} |
|
return SLJIT_SUCCESS; |
|
|
|
case SLJIT_NOT: |
|
if (src2 & SRC2_IMM) { |
|
if (flags & INV_IMM) |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); |
|
} |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, RM(src2)); |
|
|
|
case SLJIT_CLZ: |
|
SLJIT_ASSERT(!(flags & INV_IMM)); |
|
SLJIT_ASSERT(!(src2 & SRC2_IMM)); |
|
FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2))); |
|
if (flags & SET_FLAGS) |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(CMP_DP, SLJIT_UNUSED, dst, SRC2_IMM); |
|
return SLJIT_SUCCESS; |
|
|
case SLJIT_ADD: |
case SLJIT_ADD: |
SLJIT_ASSERT(!(flags & INV_IMM)); |
SLJIT_ASSERT(!(flags & INV_IMM)); |
EMIT_DATA_PROCESS_INS_AND_RETURN(ADD_DP); |
EMIT_DATA_PROCESS_INS_AND_RETURN(ADD_DP); |
Line 1080 static SLJIT_INLINE int emit_single_op(struct sljit_co
|
Line 1149 static SLJIT_INLINE int emit_single_op(struct sljit_co
|
|
|
case SLJIT_ASHR: |
case SLJIT_ASHR: |
EMIT_SHIFT_INS_AND_RETURN(2); |
EMIT_SHIFT_INS_AND_RETURN(2); |
|
|
case SLJIT_MOV: |
|
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); |
|
if (dst != src2) { |
|
if (src2 & SRC2_IMM) { |
|
if (flags & INV_IMM) |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); |
|
} |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, reg_map[src2]); |
|
} |
|
return SLJIT_SUCCESS; |
|
|
|
case SLJIT_MOV_UB: |
|
case SLJIT_MOV_SB: |
|
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); |
|
if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) { |
|
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
|
if (op == SLJIT_MOV_UB) |
|
return push_inst(compiler, EMIT_DATA_PROCESS_INS(AND_DP, 0, dst, src2, SRC2_IMM | 0xff)); |
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2])); |
|
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_UB ? 0x20 : 0x40) | reg_map[dst])); |
|
#else |
|
return push_inst(compiler, (op == SLJIT_MOV_UB ? UXTB : SXTB) | RD(dst) | RM(src2)); |
|
#endif |
|
} |
|
else if (dst != src2) { |
|
SLJIT_ASSERT(src2 & SRC2_IMM); |
|
if (flags & INV_IMM) |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); |
|
} |
|
return SLJIT_SUCCESS; |
|
|
|
case SLJIT_MOV_UH: |
|
case SLJIT_MOV_SH: |
|
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); |
|
if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) { |
|
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2])); |
|
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_UH ? 0x20 : 0x40) | reg_map[dst])); |
|
#else |
|
return push_inst(compiler, (op == SLJIT_MOV_UH ? UXTH : SXTH) | RD(dst) | RM(src2)); |
|
#endif |
|
} |
|
else if (dst != src2) { |
|
SLJIT_ASSERT(src2 & SRC2_IMM); |
|
if (flags & INV_IMM) |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); |
|
} |
|
return SLJIT_SUCCESS; |
|
|
|
case SLJIT_NOT: |
|
if (src2 & SRC2_IMM) { |
|
if (flags & INV_IMM) |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); |
|
} |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, RM(src2)); |
|
|
|
case SLJIT_CLZ: |
|
SLJIT_ASSERT(!(flags & INV_IMM)); |
|
SLJIT_ASSERT(!(src2 & SRC2_IMM)); |
|
FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2))); |
|
if (flags & SET_FLAGS) |
|
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(CMP_DP, SLJIT_UNUSED, dst, SRC2_IMM); |
|
return SLJIT_SUCCESS; |
|
} |
} |
SLJIT_ASSERT_STOP(); |
SLJIT_ASSERT_STOP(); |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
Line 1159 static SLJIT_INLINE int emit_single_op(struct sljit_co
|
Line 1160 static SLJIT_INLINE int emit_single_op(struct sljit_co
|
|
|
/* Tests whether the immediate can be stored in the 12 bit imm field. |
/* Tests whether the immediate can be stored in the 12 bit imm field. |
Returns with 0 if not possible. */ |
Returns with 0 if not possible. */ |
static sljit_uw get_immediate(sljit_uw imm) | static sljit_uw get_imm(sljit_uw imm) |
{ |
{ |
int rol; | sljit_si rol; |
|
|
if (imm <= 0xff) |
if (imm <= 0xff) |
return SRC2_IMM | imm; |
return SRC2_IMM | imm; |
Line 1197 static sljit_uw get_immediate(sljit_uw imm)
|
Line 1198 static sljit_uw get_immediate(sljit_uw imm)
|
} |
} |
|
|
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
static int generate_int(struct sljit_compiler *compiler, int reg, sljit_uw imm, int positive) | static sljit_si generate_int(struct sljit_compiler *compiler, sljit_si reg, sljit_uw imm, sljit_si positive) |
{ |
{ |
sljit_uw mask; |
sljit_uw mask; |
sljit_uw imm1; |
sljit_uw imm1; |
sljit_uw imm2; |
sljit_uw imm2; |
int rol; | sljit_si rol; |
|
|
/* Step1: Search a zero byte (8 continous zero bit). */ |
/* Step1: Search a zero byte (8 continous zero bit). */ |
mask = 0xff000000; |
mask = 0xff000000; |
Line 1308 static int generate_int(struct sljit_compiler *compile
|
Line 1309 static int generate_int(struct sljit_compiler *compile
|
} |
} |
#endif |
#endif |
|
|
static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_uw imm) | static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_uw imm) |
{ |
{ |
sljit_uw tmp; |
sljit_uw tmp; |
|
|
Line 1318 static int load_immediate(struct sljit_compiler *compi
|
Line 1319 static int load_immediate(struct sljit_compiler *compi
|
#endif |
#endif |
|
|
/* Create imm by 1 inst. */ |
/* Create imm by 1 inst. */ |
tmp = get_immediate(imm); | tmp = get_imm(imm); |
if (tmp) { |
if (tmp) { |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, tmp)); |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, tmp)); |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
tmp = get_immediate(~imm); | tmp = get_imm(~imm); |
if (tmp) { |
if (tmp) { |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, tmp)); |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, tmp)); |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
Line 1342 static int load_immediate(struct sljit_compiler *compi
|
Line 1343 static int load_immediate(struct sljit_compiler *compi
|
#endif |
#endif |
} |
} |
|
|
|
/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */ |
|
static sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sljit_si reg, sljit_sw value) |
|
{ |
|
if (value >= 0) { |
|
value = get_imm(value); |
|
if (value) |
|
return push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, dst, reg, value)); |
|
} |
|
else { |
|
value = get_imm(-value); |
|
if (value) |
|
return push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, dst, reg, value)); |
|
} |
|
return SLJIT_ERR_UNSUPPORTED; |
|
} |
|
|
/* Can perform an operation using at most 1 instruction. */ |
/* Can perform an operation using at most 1 instruction. */ |
static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw) | static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_flags, sljit_si reg, sljit_si arg, sljit_sw argw) |
{ |
{ |
sljit_uw imm; |
sljit_uw imm; |
|
|
if (arg & SLJIT_IMM) { |
if (arg & SLJIT_IMM) { |
imm = get_immediate(argw); | imm = get_imm(argw); |
if (imm) { |
if (imm) { |
if (inp_flags & ARG_TEST) |
if (inp_flags & ARG_TEST) |
return 1; |
return 1; |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, imm)); |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, imm)); |
return -1; |
return -1; |
} |
} |
imm = get_immediate(~argw); | imm = get_imm(~argw); |
if (imm) { |
if (imm) { |
if (inp_flags & ARG_TEST) |
if (inp_flags & ARG_TEST) |
return 1; |
return 1; |
Line 1415 static int getput_arg_fast(struct sljit_compiler *comp
|
Line 1432 static int getput_arg_fast(struct sljit_compiler *comp
|
/* See getput_arg below. |
/* See getput_arg below. |
Note: can_cache is called only for binary operators. Those |
Note: can_cache is called only for binary operators. Those |
operators always uses word arguments without write back. */ |
operators always uses word arguments without write back. */ |
static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw) | static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw) |
{ |
{ |
/* Immediate caching is not supported as it would be an operation on constant arguments. */ |
/* Immediate caching is not supported as it would be an operation on constant arguments. */ |
if (arg & SLJIT_IMM) |
if (arg & SLJIT_IMM) |
Line 1463 static int can_cache(int arg, sljit_w argw, int next_a
|
Line 1480 static int can_cache(int arg, sljit_w argw, int next_a
|
} |
} |
|
|
/* Emit the necessary instructions. See can_cache above. */ |
/* Emit the necessary instructions. See can_cache above. */ |
static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw, int next_arg, sljit_w next_argw) | static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags, sljit_si reg, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw) |
{ |
{ |
int tmp_r; | sljit_si tmp_r; |
sljit_w max_delta; | sljit_sw max_delta; |
sljit_w sign; | sljit_sw sign; |
| sljit_uw imm; |
|
|
if (arg & SLJIT_IMM) { |
if (arg & SLJIT_IMM) { |
SLJIT_ASSERT(inp_flags & LOAD_DATA); |
SLJIT_ASSERT(inp_flags & LOAD_DATA); |
Line 1481 static int getput_arg(struct sljit_compiler *compiler,
|
Line 1499 static int getput_arg(struct sljit_compiler *compiler,
|
|
|
if ((arg & 0xf) == SLJIT_UNUSED) { |
if ((arg & 0xf) == SLJIT_UNUSED) { |
/* Write back is not used. */ |
/* Write back is not used. */ |
if ((compiler->cache_arg & SLJIT_IMM) && (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta || ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= (sljit_uw)max_delta)) { | imm = (sljit_uw)(argw - compiler->cache_argw); |
if (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta) { | if ((compiler->cache_arg & SLJIT_IMM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) { |
| if (imm <= (sljit_uw)max_delta) { |
sign = 1; |
sign = 1; |
argw = argw - compiler->cache_argw; |
argw = argw - compiler->cache_argw; |
} |
} |
Line 1491 static int getput_arg(struct sljit_compiler *compiler,
|
Line 1510 static int getput_arg(struct sljit_compiler *compiler,
|
argw = compiler->cache_argw - argw; |
argw = compiler->cache_argw - argw; |
} |
} |
|
|
if (max_delta & 0xf00) { | GETPUT_ARG_DATA_TRANSFER(sign, 0, reg, TMP_REG3, argw); |
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, sign, 0, reg, TMP_REG3, argw)); | |
} | |
else { | |
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, sign, 0, reg, TMP_REG3, TYPE2_TRANSFER_IMM(argw))); | |
} | |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
/* With write back, we can create some sophisticated loads, but |
/* With write back, we can create some sophisticated loads, but |
it is hard to decide whether we should convert downward (0s) or upward (1s). */ |
it is hard to decide whether we should convert downward (0s) or upward (1s). */ |
if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= (sljit_uw)max_delta || (sljit_uw)next_argw - (sljit_uw)argw <= (sljit_uw)max_delta)) { | imm = (sljit_uw)(argw - next_argw); |
| if ((next_arg & SLJIT_MEM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) { |
SLJIT_ASSERT(inp_flags & LOAD_DATA); |
SLJIT_ASSERT(inp_flags & LOAD_DATA); |
|
|
compiler->cache_arg = SLJIT_IMM; |
compiler->cache_arg = SLJIT_IMM; |
Line 1515 static int getput_arg(struct sljit_compiler *compiler,
|
Line 1530 static int getput_arg(struct sljit_compiler *compiler,
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
/* Extended imm addressing for [reg+imm] format. */ |
|
sign = (max_delta << 8) | 0xff; |
|
if (!(arg & 0xf0) && argw <= sign && argw >= -sign) { |
|
TEST_WRITE_BACK(); |
|
if (argw >= 0) { |
|
sign = 1; |
|
} |
|
else { |
|
sign = 0; |
|
argw = -argw; |
|
} |
|
|
|
/* Optimization: add is 0x4, sub is 0x2. Sign is 1 for add and 0 for sub. */ |
|
if (max_delta & 0xf00) |
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP << sign, 0, tmp_r, arg & 0xf, SRC2_IMM | (argw >> 12) | 0xa00)); |
|
else |
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP << sign, 0, tmp_r, arg & 0xf, SRC2_IMM | (argw >> 8) | 0xc00)); |
|
|
|
argw &= max_delta; |
|
GETPUT_ARG_DATA_TRANSFER(sign, inp_flags & WRITE_BACK, reg, tmp_r, argw); |
|
return SLJIT_SUCCESS; |
|
} |
|
|
|
if (arg & 0xf0) { |
if (arg & 0xf0) { |
SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00)); |
SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00)); |
if (inp_flags & WRITE_BACK) |
if (inp_flags & WRITE_BACK) |
Line 1547 static int getput_arg(struct sljit_compiler *compiler,
|
Line 1539 static int getput_arg(struct sljit_compiler *compiler,
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
if (compiler->cache_arg == arg && ((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta) { | imm = (sljit_uw)(argw - compiler->cache_argw); |
| if (compiler->cache_arg == arg && imm <= (sljit_uw)max_delta) { |
SLJIT_ASSERT(!(inp_flags & WRITE_BACK)); |
SLJIT_ASSERT(!(inp_flags & WRITE_BACK)); |
argw = argw - compiler->cache_argw; | GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, imm); |
GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, argw); | |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
| if (compiler->cache_arg == arg && imm >= (sljit_uw)-max_delta) { |
if (compiler->cache_arg == arg && ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= (sljit_uw)max_delta) { | |
SLJIT_ASSERT(!(inp_flags & WRITE_BACK)); |
SLJIT_ASSERT(!(inp_flags & WRITE_BACK)); |
argw = compiler->cache_argw - argw; | imm = (sljit_uw)-(sljit_sw)imm; |
GETPUT_ARG_DATA_TRANSFER(0, 0, reg, TMP_REG3, argw); | GETPUT_ARG_DATA_TRANSFER(0, 0, reg, TMP_REG3, imm); |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
|
imm = get_imm(argw & ~max_delta); |
|
if (imm) { |
|
TEST_WRITE_BACK(); |
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & 0xf, imm)); |
|
GETPUT_ARG_DATA_TRANSFER(1, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta); |
|
return SLJIT_SUCCESS; |
|
} |
|
|
|
imm = get_imm(-argw & ~max_delta); |
|
if (imm) { |
|
argw = -argw; |
|
TEST_WRITE_BACK(); |
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, tmp_r, arg & 0xf, imm)); |
|
GETPUT_ARG_DATA_TRANSFER(0, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta); |
|
return SLJIT_SUCCESS; |
|
} |
|
|
if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) { |
if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) { |
TEST_WRITE_BACK(); |
TEST_WRITE_BACK(); |
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0))); |
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0))); |
Line 1579 static int getput_arg(struct sljit_compiler *compiler,
|
Line 1587 static int getput_arg(struct sljit_compiler *compiler,
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
if (arg == next_arg && !(inp_flags & WRITE_BACK) && ((sljit_uw)argw - (sljit_uw)next_argw <= (sljit_uw)max_delta || (sljit_uw)next_argw - (sljit_uw)argw <= (sljit_uw)max_delta)) { | imm = (sljit_uw)(argw - next_argw); |
| if (arg == next_arg && !(inp_flags & WRITE_BACK) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) { |
SLJIT_ASSERT(inp_flags & LOAD_DATA); |
SLJIT_ASSERT(inp_flags & LOAD_DATA); |
FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); |
FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & 0xf])); |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & 0xf])); |
Line 1602 static int getput_arg(struct sljit_compiler *compiler,
|
Line 1611 static int getput_arg(struct sljit_compiler *compiler,
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags, | static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw) |
int dst, sljit_w dstw, | |
int src1, sljit_w src1w, | |
int src2, sljit_w src2w) | |
{ |
{ |
|
if (getput_arg_fast(compiler, flags, reg, arg, argw)) |
|
return compiler->error; |
|
compiler->cache_arg = 0; |
|
compiler->cache_argw = 0; |
|
return getput_arg(compiler, flags, reg, arg, argw, 0, 0); |
|
} |
|
|
|
static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w) |
|
{ |
|
if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) |
|
return compiler->error; |
|
return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); |
|
} |
|
|
|
static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si inp_flags, |
|
sljit_si dst, sljit_sw dstw, |
|
sljit_si src1, sljit_sw src1w, |
|
sljit_si src2, sljit_sw src2w) |
|
{ |
/* arg1 goes to TMP_REG1 or src reg |
/* arg1 goes to TMP_REG1 or src reg |
arg2 goes to TMP_REG2, imm or src reg |
arg2 goes to TMP_REG2, imm or src reg |
TMP_REG3 can be used for caching |
TMP_REG3 can be used for caching |
result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ |
result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ |
|
|
/* We prefers register and simple consts. */ |
/* We prefers register and simple consts. */ |
int dst_r; | sljit_si dst_r; |
int src1_r; | sljit_si src1_r; |
int src2_r = 0; | sljit_si src2_r = 0; |
int sugg_src2_r = TMP_REG2; | sljit_si sugg_src2_r = TMP_REG2; |
int flags = GET_FLAGS(op) ? SET_FLAGS : 0; | sljit_si flags = GET_FLAGS(op) ? SET_FLAGS : 0; |
|
|
compiler->cache_arg = 0; |
compiler->cache_arg = 0; |
compiler->cache_argw = 0; |
compiler->cache_argw = 0; |
|
|
/* Destination check. */ |
/* Destination check. */ |
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REG3) { | if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) { |
| if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM)) |
| return SLJIT_SUCCESS; |
| dst_r = TMP_REG2; |
| } |
| else if (dst <= TMP_REG3) { |
dst_r = dst; |
dst_r = dst; |
flags |= REG_DEST; |
flags |= REG_DEST; |
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) |
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) |
sugg_src2_r = dst_r; |
sugg_src2_r = dst_r; |
} |
} |
else if (dst == SLJIT_UNUSED) { |
|
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM)) |
|
return SLJIT_SUCCESS; |
|
dst_r = TMP_REG2; |
|
} |
|
else { |
else { |
SLJIT_ASSERT(dst & SLJIT_MEM); |
SLJIT_ASSERT(dst & SLJIT_MEM); |
if (getput_arg_fast(compiler, inp_flags | ARG_TEST, TMP_REG2, dst, dstw)) { |
if (getput_arg_fast(compiler, inp_flags | ARG_TEST, TMP_REG2, dst, dstw)) { |
Line 1647 static int emit_op(struct sljit_compiler *compiler, in
|
Line 1672 static int emit_op(struct sljit_compiler *compiler, in
|
} |
} |
|
|
/* Source 1. */ |
/* Source 1. */ |
if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= TMP_REG3) | if (src1 <= TMP_REG3) |
src1_r = src1; |
src1_r = src1; |
else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) { | else if (src2 <= TMP_REG3) { |
flags |= ARGS_SWAPPED; |
flags |= ARGS_SWAPPED; |
src1_r = src2; |
src1_r = src2; |
src2 = src1; |
src2 = src1; |
Line 1659 static int emit_op(struct sljit_compiler *compiler, in
|
Line 1684 static int emit_op(struct sljit_compiler *compiler, in
|
src1_r = 0; |
src1_r = 0; |
if ((inp_flags & ALLOW_ANY_IMM) && (src1 & SLJIT_IMM)) { |
if ((inp_flags & ALLOW_ANY_IMM) && (src1 & SLJIT_IMM)) { |
/* The second check will generate a hit. */ |
/* The second check will generate a hit. */ |
src2_r = get_immediate(src1w); | src2_r = get_imm(src1w); |
if (src2_r) { |
if (src2_r) { |
flags |= ARGS_SWAPPED; |
flags |= ARGS_SWAPPED; |
src1 = src2; |
src1 = src2; |
Line 1667 static int emit_op(struct sljit_compiler *compiler, in
|
Line 1692 static int emit_op(struct sljit_compiler *compiler, in
|
break; |
break; |
} |
} |
if (inp_flags & ALLOW_INV_IMM) { |
if (inp_flags & ALLOW_INV_IMM) { |
src2_r = get_immediate(~src1w); | src2_r = get_imm(~src1w); |
if (src2_r) { |
if (src2_r) { |
flags |= ARGS_SWAPPED | INV_IMM; |
flags |= ARGS_SWAPPED | INV_IMM; |
src1 = src2; |
src1 = src2; |
Line 1676 static int emit_op(struct sljit_compiler *compiler, in
|
Line 1701 static int emit_op(struct sljit_compiler *compiler, in
|
} |
} |
} |
} |
if (GET_OPCODE(op) == SLJIT_ADD) { |
if (GET_OPCODE(op) == SLJIT_ADD) { |
src2_r = get_immediate(-src1w); | src2_r = get_imm(-src1w); |
if (src2_r) { |
if (src2_r) { |
/* Note: ARGS_SWAPPED is intentionally not applied! */ |
/* Note: ARGS_SWAPPED is intentionally not applied! */ |
src1 = src2; |
src1 = src2; |
Line 1695 static int emit_op(struct sljit_compiler *compiler, in
|
Line 1720 static int emit_op(struct sljit_compiler *compiler, in
|
|
|
/* Source 2. */ |
/* Source 2. */ |
if (src2_r == 0) { |
if (src2_r == 0) { |
if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) { | if (src2 <= TMP_REG3) { |
src2_r = src2; |
src2_r = src2; |
flags |= REG_SOURCE; |
flags |= REG_SOURCE; |
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) |
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) |
Line 1703 static int emit_op(struct sljit_compiler *compiler, in
|
Line 1728 static int emit_op(struct sljit_compiler *compiler, in
|
} |
} |
else do { /* do { } while(0) is used because of breaks. */ |
else do { /* do { } while(0) is used because of breaks. */ |
if ((inp_flags & ALLOW_ANY_IMM) && (src2 & SLJIT_IMM)) { |
if ((inp_flags & ALLOW_ANY_IMM) && (src2 & SLJIT_IMM)) { |
src2_r = get_immediate(src2w); | src2_r = get_imm(src2w); |
if (src2_r) |
if (src2_r) |
break; |
break; |
if (inp_flags & ALLOW_INV_IMM) { |
if (inp_flags & ALLOW_INV_IMM) { |
src2_r = get_immediate(~src2w); | src2_r = get_imm(~src2w); |
if (src2_r) { |
if (src2_r) { |
flags |= INV_IMM; |
flags |= INV_IMM; |
break; |
break; |
} |
} |
} |
} |
if (GET_OPCODE(op) == SLJIT_ADD) { |
if (GET_OPCODE(op) == SLJIT_ADD) { |
src2_r = get_immediate(-src2w); | src2_r = get_imm(-src2w); |
if (src2_r) { |
if (src2_r) { |
op = SLJIT_SUB | GET_ALL_FLAGS(op); |
op = SLJIT_SUB | GET_ALL_FLAGS(op); |
flags &= ~ARGS_SWAPPED; |
flags &= ~ARGS_SWAPPED; |
Line 1722 static int emit_op(struct sljit_compiler *compiler, in
|
Line 1747 static int emit_op(struct sljit_compiler *compiler, in
|
} |
} |
} |
} |
if (GET_OPCODE(op) == SLJIT_SUB && !(flags & ARGS_SWAPPED)) { |
if (GET_OPCODE(op) == SLJIT_SUB && !(flags & ARGS_SWAPPED)) { |
src2_r = get_immediate(-src2w); | src2_r = get_imm(-src2w); |
if (src2_r) { |
if (src2_r) { |
op = SLJIT_ADD | GET_ALL_FLAGS(op); |
op = SLJIT_ADD | GET_ALL_FLAGS(op); |
flags &= ~ARGS_SWAPPED; |
flags &= ~ARGS_SWAPPED; |
Line 1797 extern "C" {
|
Line 1822 extern "C" {
|
#endif |
#endif |
|
|
#if defined(__GNUC__) |
#if defined(__GNUC__) |
extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator); | extern unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator); |
extern unsigned int __aeabi_idivmod(unsigned numerator, unsigned denominator); | extern int __aeabi_idivmod(int numerator, int denominator); |
#else |
#else |
#error "Software divmod functions are needed" |
#error "Software divmod functions are needed" |
#endif |
#endif |
Line 1807 extern unsigned int __aeabi_idivmod(unsigned numerator
|
Line 1832 extern unsigned int __aeabi_idivmod(unsigned numerator
|
} |
} |
#endif |
#endif |
|
|
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) |
{ |
{ |
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_op0(compiler, op); |
check_sljit_emit_op0(compiler, op); |
Line 1824 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj
|
Line 1849 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj
|
case SLJIT_SMUL: |
case SLJIT_SMUL: |
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) |
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) |
return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL) |
return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL) |
| (reg_map[SLJIT_TEMPORARY_REG2] << 16) | | (reg_map[SLJIT_SCRATCH_REG2] << 16) |
| (reg_map[SLJIT_TEMPORARY_REG1] << 12) | | (reg_map[SLJIT_SCRATCH_REG1] << 12) |
| (reg_map[SLJIT_TEMPORARY_REG1] << 8) | | (reg_map[SLJIT_SCRATCH_REG1] << 8) |
| reg_map[SLJIT_TEMPORARY_REG2]); | | reg_map[SLJIT_SCRATCH_REG2]); |
#else |
#else |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG2))); | EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, RM(SLJIT_SCRATCH_REG2))); |
return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL) |
return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL) |
| (reg_map[SLJIT_TEMPORARY_REG2] << 16) | | (reg_map[SLJIT_SCRATCH_REG2] << 16) |
| (reg_map[SLJIT_TEMPORARY_REG1] << 12) | | (reg_map[SLJIT_SCRATCH_REG1] << 12) |
| (reg_map[SLJIT_TEMPORARY_REG1] << 8) | | (reg_map[SLJIT_SCRATCH_REG1] << 8) |
| reg_map[TMP_REG1]); |
| reg_map[TMP_REG1]); |
#endif |
#endif |
case SLJIT_UDIV: |
case SLJIT_UDIV: |
case SLJIT_SDIV: |
case SLJIT_SDIV: |
if (compiler->temporaries >= 3) | if (compiler->scratches >= 3) |
EMIT_INSTRUCTION(0xe52d2008 /* str r2, [sp, #-8]! */); |
EMIT_INSTRUCTION(0xe52d2008 /* str r2, [sp, #-8]! */); |
#if defined(__GNUC__) |
#if defined(__GNUC__) |
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, |
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, |
Line 1846 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj
|
Line 1871 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj
|
#else |
#else |
#error "Software divmod functions are needed" |
#error "Software divmod functions are needed" |
#endif |
#endif |
if (compiler->temporaries >= 3) | if (compiler->scratches >= 3) |
return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */); |
return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */); |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
Line 1854 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj
|
Line 1879 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
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) |
{ |
{ |
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); |
check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); |
Line 1867 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
Line 1892 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
case SLJIT_MOV: |
case SLJIT_MOV: |
case SLJIT_MOV_UI: |
case SLJIT_MOV_UI: |
case SLJIT_MOV_SI: |
case SLJIT_MOV_SI: |
|
case SLJIT_MOV_P: |
return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); |
return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); |
|
|
case SLJIT_MOV_UB: |
case SLJIT_MOV_UB: |
return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw); | return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw); |
|
|
case SLJIT_MOV_SB: |
case SLJIT_MOV_SB: |
return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw); | return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw); |
|
|
case SLJIT_MOV_UH: |
case SLJIT_MOV_UH: |
return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw); | return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw); |
|
|
case SLJIT_MOV_SH: |
case SLJIT_MOV_SH: |
return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw); | return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw); |
|
|
case SLJIT_MOVU: |
case SLJIT_MOVU: |
case SLJIT_MOVU_UI: |
case SLJIT_MOVU_UI: |
case SLJIT_MOVU_SI: |
case SLJIT_MOVU_SI: |
|
case SLJIT_MOVU_P: |
return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); |
return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); |
|
|
case SLJIT_MOVU_UB: |
case SLJIT_MOVU_UB: |
return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw); | return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw); |
|
|
case SLJIT_MOVU_SB: |
case SLJIT_MOVU_SB: |
return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw); | return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw); |
|
|
case SLJIT_MOVU_UH: |
case SLJIT_MOVU_UH: |
return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw); | return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw); |
|
|
case SLJIT_MOVU_SH: |
case SLJIT_MOVU_SH: |
return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw); | return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw); |
|
|
case SLJIT_NOT: |
case SLJIT_NOT: |
return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); |
return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); |
Line 1914 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
Line 1941 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
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) |
{ |
{ |
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); |
check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); |
Line 1956 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj
|
Line 1983 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg) | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg) |
{ |
{ |
check_sljit_get_register_index(reg); |
check_sljit_get_register_index(reg); |
return reg_map[reg]; |
return reg_map[reg]; |
} |
} |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler, | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg) |
void *instruction, int size) | |
{ |
{ |
|
check_sljit_get_float_register_index(reg); |
|
return reg; |
|
} |
|
|
|
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler, |
|
void *instruction, sljit_si size) |
|
{ |
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_op_custom(compiler, instruction, size); |
check_sljit_emit_op_custom(compiler, instruction, size); |
SLJIT_ASSERT(size == 4); |
SLJIT_ASSERT(size == 4); |
Line 1980 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(stru
|
Line 2013 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(stru
|
|
|
/* 0 - no fpu |
/* 0 - no fpu |
1 - vfp */ |
1 - vfp */ |
static int arm_fpu_type = -1; | static sljit_si arm_fpu_type = -1; |
|
|
static void init_compiler() | static void init_compiler(void) |
{ |
{ |
if (arm_fpu_type != -1) |
if (arm_fpu_type != -1) |
return; |
return; |
Line 1991 static void init_compiler()
|
Line 2024 static void init_compiler()
|
arm_fpu_type = 1; |
arm_fpu_type = 1; |
} |
} |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void) | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void) |
{ |
{ |
if (arm_fpu_type == -1) |
if (arm_fpu_type == -1) |
init_compiler(); |
init_compiler(); |
Line 2002 SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(vo
|
Line 2035 SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(vo
|
|
|
#define arm_fpu_type 1 |
#define arm_fpu_type 1 |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void) | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void) |
{ |
{ |
/* Always available. */ |
/* Always available. */ |
return 1; |
return 1; |
Line 2010 SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(vo
|
Line 2043 SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(vo
|
|
|
#endif |
#endif |
|
|
#define EMIT_FPU_DATA_TRANSFER(add, load, base, freg, offs) \ | #define FPU_LOAD (1 << 20) |
(VSTR | ((add) << 23) | ((load) << 20) | (reg_map[base] << 16) | (freg << 12) | (offs)) | #define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \ |
#define EMIT_FPU_OPERATION(opcode, dst, src1, src2) \ | ((inst) | ((add) << 23) | (reg_map[base] << 16) | (freg << 12) | (offs)) |
((opcode) | ((dst) << 12) | (src1) | ((src2) << 16)) | #define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \ |
| ((opcode) | (mode) | ((dst) << 12) | (src1) | ((src2) << 16)) |
|
|
static int emit_fpu_data_transfer(struct sljit_compiler *compiler, int fpu_reg, int load, int arg, sljit_w argw) | static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw) |
{ |
{ |
|
sljit_sw tmp; |
|
sljit_uw imm; |
|
sljit_sw inst = VSTR_F32 | (flags & (SLJIT_SINGLE_OP | FPU_LOAD)); |
SLJIT_ASSERT(arg & SLJIT_MEM); |
SLJIT_ASSERT(arg & SLJIT_MEM); |
|
|
|
if (SLJIT_UNLIKELY(arg & 0xf0)) { |
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7))); |
|
arg = SLJIT_MEM | TMP_REG1; |
|
argw = 0; |
|
} |
|
|
/* Fast loads and stores. */ |
/* Fast loads and stores. */ |
if ((arg & 0xf) && !(arg & 0xf0) && (argw & 0x3) == 0) { | if ((arg & 0xf)) { |
if (argw >= 0 && argw <= 0x3ff) { | if (!(argw & ~0x3fc)) |
EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, arg & 0xf, fpu_reg, argw >> 2)); | return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & 0xf, reg, argw >> 2)); |
return SLJIT_SUCCESS; | if (!(-argw & ~0x3fc)) |
} | return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & 0xf, reg, (-argw) >> 2)); |
if (argw < 0 && argw >= -0x3ff) { | |
EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, arg & 0xf, fpu_reg, (-argw) >> 2)); | |
return SLJIT_SUCCESS; | |
} | |
if (argw >= 0 && argw <= 0x3ffff) { | |
SLJIT_ASSERT(get_immediate(argw & 0x3fc00)); | |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, get_immediate(argw & 0x3fc00))); | |
argw &= 0x3ff; | |
EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG1, fpu_reg, argw >> 2)); | |
return SLJIT_SUCCESS; | |
} | |
if (argw < 0 && argw >= -0x3ffff) { | |
argw = -argw; | |
SLJIT_ASSERT(get_immediate(argw & 0x3fc00)); | |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & 0xf, get_immediate(argw & 0x3fc00))); | |
argw &= 0x3ff; | |
EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, TMP_REG1, fpu_reg, argw >> 2)); | |
return SLJIT_SUCCESS; | |
} | |
} |
} |
|
|
if (arg & 0xf0) { | if (compiler->cache_arg == arg) { |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7))); | tmp = argw - compiler->cache_argw; |
EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG1, fpu_reg, 0)); | if (!(tmp & ~0x3fc)) |
return SLJIT_SUCCESS; | return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, tmp >> 2)); |
| if (!(-tmp & ~0x3fc)) |
| return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG3, reg, -tmp >> 2)); |
| if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, tmp) != SLJIT_ERR_UNSUPPORTED) { |
| FAIL_IF(compiler->error); |
| compiler->cache_argw = argw; |
| return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, 0)); |
| } |
} |
} |
|
|
if (compiler->cache_arg == arg && ((argw - compiler->cache_argw) & 0x3) == 0) { | if (arg & 0xf) { |
if (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= 0x3ff) { | if (emit_set_delta(compiler, TMP_REG1, arg & 0xf, argw) != SLJIT_ERR_UNSUPPORTED) { |
EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG3, fpu_reg, (argw - compiler->cache_argw) >> 2)); | FAIL_IF(compiler->error); |
return SLJIT_SUCCESS; | return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, 0)); |
} |
} |
if (((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= 0x3ff) { | imm = get_imm(argw & ~0x3fc); |
EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, TMP_REG3, fpu_reg, (compiler->cache_argw - argw) >> 2)); | if (imm) { |
return SLJIT_SUCCESS; | EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, imm)); |
| return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, (argw & 0x3fc) >> 2)); |
} |
} |
|
imm = get_imm(-argw & ~0x3fc); |
|
if (imm) { |
|
argw = -argw; |
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & 0xf, imm)); |
|
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG1, reg, (argw & 0x3fc) >> 2)); |
|
} |
} |
} |
|
|
compiler->cache_arg = arg; |
compiler->cache_arg = arg; |
Line 2072 static int emit_fpu_data_transfer(struct sljit_compile
|
Line 2110 static int emit_fpu_data_transfer(struct sljit_compile
|
else |
else |
FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); |
FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); |
|
|
EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG3, fpu_reg, 0)); | return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, 0)); |
return SLJIT_SUCCESS; | |
} |
} |
|
|
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) |
{ |
{ |
int dst_freg; | sljit_si dst_fr; |
|
|
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw); |
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw); |
|
SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100), float_transfer_bit_error); |
|
|
compiler->cache_arg = 0; |
compiler->cache_arg = 0; |
compiler->cache_argw = 0; |
compiler->cache_argw = 0; |
|
op ^= SLJIT_SINGLE_OP; |
|
|
if (GET_OPCODE(op) == SLJIT_FCMP) { | if (GET_OPCODE(op) == SLJIT_CMPD) { |
if (dst > SLJIT_FLOAT_REG4) { | if (dst > SLJIT_FLOAT_REG6) { |
FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, dst, dstw)); | FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, dst, dstw)); |
dst = TMP_FREG1; |
dst = TMP_FREG1; |
} |
} |
if (src > SLJIT_FLOAT_REG4) { | if (src > SLJIT_FLOAT_REG6) { |
FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src, srcw)); | FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src, srcw)); |
src = TMP_FREG2; |
src = TMP_FREG2; |
} |
} |
EMIT_INSTRUCTION(VCMP_F64 | (dst << 12) | src); | EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_SINGLE_OP, dst, src, 0)); |
EMIT_INSTRUCTION(VMRS); |
EMIT_INSTRUCTION(VMRS); |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
dst_freg = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst; | dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst; |
|
|
if (src > SLJIT_FLOAT_REG4) { | if (src > SLJIT_FLOAT_REG6) { |
FAIL_IF(emit_fpu_data_transfer(compiler, dst_freg, 1, src, srcw)); | FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_fr, src, srcw)); |
src = dst_freg; | src = dst_fr; |
} |
} |
|
|
switch (op) { | switch (GET_OPCODE(op)) { |
case SLJIT_FMOV: | case SLJIT_MOVD: |
if (src != dst_freg && dst_freg != TMP_FREG1) | if (src != dst_fr && dst_fr != TMP_FREG1) |
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMOV_F64, dst_freg, src, 0)); | EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_SINGLE_OP, dst_fr, src, 0)); |
break; |
break; |
case SLJIT_FNEG: | case SLJIT_NEGD: |
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VNEG_F64, dst_freg, src, 0)); | EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_SINGLE_OP, dst_fr, src, 0)); |
break; |
break; |
case SLJIT_FABS: | case SLJIT_ABSD: |
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VABS_F64, dst_freg, src, 0)); | EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_SINGLE_OP, dst_fr, src, 0)); |
break; |
break; |
} |
} |
|
|
if (dst_freg == TMP_FREG1) | if (dst_fr == TMP_FREG1) { |
FAIL_IF(emit_fpu_data_transfer(compiler, src, 0, dst, dstw)); | if (GET_OPCODE(op) == SLJIT_MOVD) |
| dst_fr = src; |
| FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), dst_fr, dst, dstw)); |
| } |
|
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
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) |
{ |
{ |
int dst_freg; | sljit_si dst_fr; |
|
|
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); |
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); |
|
|
compiler->cache_arg = 0; |
compiler->cache_arg = 0; |
compiler->cache_argw = 0; |
compiler->cache_argw = 0; |
|
op ^= SLJIT_SINGLE_OP; |
|
|
dst_freg = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst; | dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst; |
|
|
if (src2 > SLJIT_FLOAT_REG4) { | if (src2 > SLJIT_FLOAT_REG6) { |
FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w)); | FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w)); |
src2 = TMP_FREG2; |
src2 = TMP_FREG2; |
} |
} |
|
|
if (src1 > SLJIT_FLOAT_REG4) { | if (src1 > SLJIT_FLOAT_REG6) { |
FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w)); | FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w)); |
src1 = TMP_FREG1; |
src1 = TMP_FREG1; |
} |
} |
|
|
switch (op) { | switch (GET_OPCODE(op)) { |
case SLJIT_FADD: | case SLJIT_ADDD: |
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VADD_F64, dst_freg, src2, src1)); | EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_SINGLE_OP, dst_fr, src2, src1)); |
break; |
break; |
|
|
case SLJIT_FSUB: | case SLJIT_SUBD: |
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VSUB_F64, dst_freg, src2, src1)); | EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_SINGLE_OP, dst_fr, src2, src1)); |
break; |
break; |
|
|
case SLJIT_FMUL: | case SLJIT_MULD: |
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMUL_F64, dst_freg, src2, src1)); | EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_SINGLE_OP, dst_fr, src2, src1)); |
break; |
break; |
|
|
case SLJIT_FDIV: | case SLJIT_DIVD: |
EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VDIV_F64, dst_freg, src2, src1)); | EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_SINGLE_OP, dst_fr, src2, src1)); |
break; |
break; |
} |
} |
|
|
if (dst_freg == TMP_FREG1) | if (dst_fr == TMP_FREG1) |
FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 0, dst, dstw)); | FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw)); |
|
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
|
#undef FPU_LOAD |
|
#undef EMIT_FPU_DATA_TRANSFER |
|
#undef EMIT_FPU_OPERATION |
|
|
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
/* Other instructions */ |
/* Other instructions */ |
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
|
|
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) |
{ |
{ |
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_fast_enter(compiler, dst, dstw); |
check_sljit_emit_fast_enter(compiler, dst, dstw); |
ADJUST_LOCAL_OFFSET(dst, dstw); |
ADJUST_LOCAL_OFFSET(dst, dstw); |
|
|
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) | /* For UNUSED dst. Uncommon, but possible. */ |
| if (dst == SLJIT_UNUSED) |
| return SLJIT_SUCCESS; |
| |
| if (dst <= TMP_REG3) |
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG3))); |
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG3))); |
else if (dst & SLJIT_MEM) { |
|
if (getput_arg_fast(compiler, WORD_DATA, TMP_REG3, dst, dstw)) |
|
return compiler->error; |
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG2, SLJIT_UNUSED, RM(TMP_REG3))); |
|
compiler->cache_arg = 0; |
|
compiler->cache_argw = 0; |
|
return getput_arg(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0); |
|
} |
|
|
|
return SLJIT_SUCCESS; | /* Memory. */ |
| if (getput_arg_fast(compiler, WORD_DATA, TMP_REG3, dst, dstw)) |
| return compiler->error; |
| /* TMP_REG3 is used for caching. */ |
| EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG2, SLJIT_UNUSED, RM(TMP_REG3))); |
| compiler->cache_arg = 0; |
| compiler->cache_argw = 0; |
| return getput_arg(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0); |
} |
} |
|
|
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) |
{ |
{ |
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_fast_return(compiler, src, srcw); |
check_sljit_emit_fast_return(compiler, src, srcw); |
ADJUST_LOCAL_OFFSET(src, srcw); |
ADJUST_LOCAL_OFFSET(src, srcw); |
|
|
if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) | if (src <= TMP_REG3) |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src))); |
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src))); |
else if (src & SLJIT_MEM) { |
else if (src & SLJIT_MEM) { |
if (getput_arg_fast(compiler, WORD_DATA | LOAD_DATA, TMP_REG3, src, srcw)) |
if (getput_arg_fast(compiler, WORD_DATA | LOAD_DATA, TMP_REG3, src, srcw)) |
Line 2228 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st
|
Line 2278 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st
|
/* Conditional instructions */ |
/* Conditional instructions */ |
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
|
|
static sljit_uw get_cc(int type) | static sljit_uw get_cc(sljit_si type) |
{ |
{ |
switch (type) { |
switch (type) { |
case SLJIT_C_EQUAL: |
case SLJIT_C_EQUAL: |
Line 2270 static sljit_uw get_cc(int type)
|
Line 2320 static sljit_uw get_cc(int type)
|
return 0xd0000000; |
return 0xd0000000; |
|
|
case SLJIT_C_OVERFLOW: |
case SLJIT_C_OVERFLOW: |
case SLJIT_C_FLOAT_NAN: | case SLJIT_C_FLOAT_UNORDERED: |
return 0x60000000; |
return 0x60000000; |
|
|
case SLJIT_C_NOT_OVERFLOW: |
case SLJIT_C_NOT_OVERFLOW: |
case SLJIT_C_FLOAT_NOT_NAN: | case SLJIT_C_FLOAT_ORDERED: |
return 0x70000000; |
return 0x70000000; |
|
|
default: /* SLJIT_JUMP */ |
default: /* SLJIT_JUMP */ |
Line 2298 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emi
|
Line 2348 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emi
|
return label; |
return label; |
} |
} |
|
|
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) |
{ |
{ |
struct sljit_jump *jump; |
struct sljit_jump *jump; |
|
|
Line 2339 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit
|
Line 2389 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit
|
return jump; |
return jump; |
} |
} |
|
|
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) |
{ |
{ |
struct sljit_jump *jump; |
struct sljit_jump *jump; |
|
|
Line 2367 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct s
|
Line 2417 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct s
|
jump->addr = compiler->size; |
jump->addr = compiler->size; |
} |
} |
else { |
else { |
if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) | if (src <= TMP_REG3) |
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src)); |
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src)); |
|
|
SLJIT_ASSERT(src & SLJIT_MEM); |
SLJIT_ASSERT(src & SLJIT_MEM); |
FAIL_IF(emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); | FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw)); |
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2)); |
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2)); |
} |
} |
|
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type) | 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) |
{ |
{ |
int reg; | sljit_si dst_r, flags = GET_ALL_FLAGS(op); |
sljit_uw cc; | sljit_uw cc, ins; |
|
|
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_cond_value(compiler, op, dst, dstw, type); | check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type); |
ADJUST_LOCAL_OFFSET(dst, dstw); |
ADJUST_LOCAL_OFFSET(dst, dstw); |
|
ADJUST_LOCAL_OFFSET(src, srcw); |
|
|
if (dst == SLJIT_UNUSED) |
if (dst == SLJIT_UNUSED) |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
|
|
|
op = GET_OPCODE(op); |
cc = get_cc(type); |
cc = get_cc(type); |
if (GET_OPCODE(op) == SLJIT_OR) { | dst_r = (dst <= TMP_REG3) ? dst : TMP_REG2; |
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { | |
EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ORR_DP, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc); | |
if (op & SLJIT_SET_E) | |
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst))); | |
return SLJIT_SUCCESS; | |
} | |
|
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 0)); | if (op < SLJIT_ADD) { |
EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc); | EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 0)); |
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) | EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc); |
compiler->skip_checks = 1; | return (dst_r == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS; |
#endif | |
return emit_op(compiler, op, ALLOW_IMM, dst, dstw, TMP_REG1, 0, dst, dstw); | |
} |
} |
|
|
reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; | ins = (op == SLJIT_AND ? AND_DP : (op == SLJIT_OR ? ORR_DP : EOR_DP)); |
| if ((op == SLJIT_OR || op == SLJIT_XOR) && dst <= TMP_REG3 && dst == src) { |
| EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ins, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc); |
| /* The condition must always be set, even if the ORR/EOR is not executed above. */ |
| return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst))) : SLJIT_SUCCESS; |
| } |
|
|
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 0)); | compiler->cache_arg = 0; |
EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc); | compiler->cache_argw = 0; |
| if (src & SLJIT_MEM) { |
| FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw)); |
| src = TMP_REG1; |
| srcw = 0; |
| } else if (src & SLJIT_IMM) { |
| FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); |
| src = TMP_REG1; |
| srcw = 0; |
| } |
|
|
if (reg == TMP_REG2) | EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 1) & ~COND_MASK) | cc); |
return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); | EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)); |
return SLJIT_SUCCESS; | if (dst_r == TMP_REG2) |
| FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0)); |
| |
| return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst_r))) : SLJIT_SUCCESS; |
} |
} |
|
|
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) |
{ |
{ |
struct sljit_const *const_; |
struct sljit_const *const_; |
int reg; | sljit_si reg; |
|
|
CHECK_ERROR_PTR(); |
CHECK_ERROR_PTR(); |
check_sljit_emit_const(compiler, dst, dstw, init_value); |
check_sljit_emit_const(compiler, dst, dstw, init_value); |
Line 2429 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emi
|
Line 2493 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emi
|
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); |
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); |
PTR_FAIL_IF(!const_); |
PTR_FAIL_IF(!const_); |
|
|
reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; | reg = (dst <= TMP_REG3) ? dst : TMP_REG2; |
|
|
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) |
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), init_value)); |
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), init_value)); |
Line 2440 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emi
|
Line 2504 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emi
|
set_const(const_, compiler); |
set_const(const_, compiler); |
|
|
if (reg == TMP_REG2 && dst != SLJIT_UNUSED) |
if (reg == TMP_REG2 && dst != SLJIT_UNUSED) |
if (emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, TMP_REG2, 0)) | PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw)); |
return NULL; | |
return const_; |
return const_; |
} |
} |
|
|
Line 2450 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(slji
|
Line 2513 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(slji
|
inline_set_jump_addr(addr, new_addr, 1); |
inline_set_jump_addr(addr, new_addr, 1); |
} |
} |
|
|
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) |
{ |
{ |
inline_set_const(addr, new_constant, 1); |
inline_set_const(addr, new_constant, 1); |
} |
} |