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) |
{ |
{ |
return "ARM-Thumb2" SLJIT_CPUINFO; |
return "ARM-Thumb2" SLJIT_CPUINFO; |
} |
} |
|
|
|
/* Length of an instruction word. */ |
|
typedef sljit_ui sljit_ins; |
|
|
/* Last register + 1. */ |
/* Last register + 1. */ |
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1) |
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1) |
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2) |
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2) |
#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) |
|
|
/* 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, 12, 5, 6, 7, 8, 10, 11, 13, 3, 4, 14, 15 | 0, 0, 1, 2, 12, 5, 6, 7, 8, 10, 11, 13, 3, 4, 14, 15 |
}; |
}; |
|
|
#define COPY_BITS(src, from, to, bits) \ |
#define COPY_BITS(src, from, to, bits) \ |
Line 75 static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS
|
Line 78 static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS
|
#define IMM12(imm) \ |
#define IMM12(imm) \ |
(COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)) |
(COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)) |
|
|
typedef sljit_ui sljit_ins; |
|
|
|
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
/* Instrucion forms */ |
/* Instrucion forms */ |
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
Line 165 typedef sljit_ui sljit_ins;
|
Line 166 typedef sljit_ui sljit_ins;
|
#define UXTB_W 0xfa5ff080 |
#define UXTB_W 0xfa5ff080 |
#define UXTH 0xb280 |
#define UXTH 0xb280 |
#define UXTH_W 0xfa1ff080 |
#define UXTH_W 0xfa1ff080 |
#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 |
|
|
static int push_inst16(struct sljit_compiler *compiler, sljit_ins inst) | static sljit_si push_inst16(struct sljit_compiler *compiler, sljit_ins inst) |
{ |
{ |
sljit_uh *ptr; |
sljit_uh *ptr; |
SLJIT_ASSERT(!(inst & 0xffff0000)); |
SLJIT_ASSERT(!(inst & 0xffff0000)); |
Line 188 static int push_inst16(struct sljit_compiler *compiler
|
Line 189 static int push_inst16(struct sljit_compiler *compiler
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
static int push_inst32(struct sljit_compiler *compiler, sljit_ins inst) | static sljit_si push_inst32(struct sljit_compiler *compiler, sljit_ins inst) |
{ |
{ |
sljit_uh *ptr = (sljit_uh*)ensure_buf(compiler, sizeof(sljit_ins)); |
sljit_uh *ptr = (sljit_uh*)ensure_buf(compiler, sizeof(sljit_ins)); |
FAIL_IF(!ptr); |
FAIL_IF(!ptr); |
Line 198 static int push_inst32(struct sljit_compiler *compiler
|
Line 199 static int push_inst32(struct sljit_compiler *compiler
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
static SLJIT_INLINE int emit_imm32_const(struct sljit_compiler *compiler, int dst, sljit_uw imm) | static SLJIT_INLINE sljit_si emit_imm32_const(struct sljit_compiler *compiler, sljit_si dst, sljit_uw imm) |
{ |
{ |
FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) | |
FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) | |
COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))); |
COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))); |
Line 208 static SLJIT_INLINE int emit_imm32_const(struct sljit_
|
Line 209 static SLJIT_INLINE int emit_imm32_const(struct sljit_
|
|
|
static SLJIT_INLINE void modify_imm32_const(sljit_uh* inst, sljit_uw new_imm) |
static SLJIT_INLINE void modify_imm32_const(sljit_uh* inst, sljit_uw new_imm) |
{ |
{ |
int dst = inst[1] & 0x0f00; | sljit_si dst = inst[1] & 0x0f00; |
SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00)); |
SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00)); |
inst[0] = (MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1); |
inst[0] = (MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1); |
inst[1] = dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff); |
inst[1] = dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff); |
Line 216 static SLJIT_INLINE void modify_imm32_const(sljit_uh*
|
Line 217 static SLJIT_INLINE void modify_imm32_const(sljit_uh*
|
inst[3] = dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16); |
inst[3] = dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16); |
} |
} |
|
|
static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uh *code_ptr, sljit_uh *code) | static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uh *code_ptr, sljit_uh *code) |
{ |
{ |
sljit_w diff; | sljit_sw diff; |
|
|
if (jump->flags & SLJIT_REWRITABLE_JUMP) |
if (jump->flags & SLJIT_REWRITABLE_JUMP) |
return 0; |
return 0; |
Line 227 static SLJIT_INLINE int detect_jump_type(struct sljit_
|
Line 228 static SLJIT_INLINE int detect_jump_type(struct sljit_
|
/* Branch to ARM code is not optimized yet. */ |
/* Branch to ARM code is not optimized yet. */ |
if (!(jump->u.target & 0x1)) |
if (!(jump->u.target & 0x1)) |
return 0; |
return 0; |
diff = ((sljit_w)jump->u.target - (sljit_w)(code_ptr + 2)) >> 1; | diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2)) >> 1; |
} |
} |
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)) >> 1; | diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2)) >> 1; |
} |
} |
|
|
if (jump->flags & IS_CONDITIONAL) { | if (jump->flags & IS_COND) { |
SLJIT_ASSERT(!(jump->flags & IS_BL)); |
SLJIT_ASSERT(!(jump->flags & IS_BL)); |
if (diff <= 127 && diff >= -128) { |
if (diff <= 127 && diff >= -128) { |
jump->flags |= B_TYPE1; |
jump->flags |= B_TYPE1; |
Line 271 static SLJIT_INLINE int detect_jump_type(struct sljit_
|
Line 272 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) |
{ |
{ |
sljit_uh* inst = (sljit_uh*)addr; |
sljit_uh* inst = (sljit_uh*)addr; |
modify_imm32_const(inst, new_addr); |
modify_imm32_const(inst, new_addr); |
Line 282 static SLJIT_INLINE void inline_set_jump_addr(sljit_uw
|
Line 283 static SLJIT_INLINE void inline_set_jump_addr(sljit_uw
|
|
|
static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump) |
static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump) |
{ |
{ |
int type = (jump->flags >> 4) & 0xf; | sljit_si type = (jump->flags >> 4) & 0xf; |
sljit_w diff; | sljit_sw diff; |
sljit_uh *jump_inst; |
sljit_uh *jump_inst; |
int s, j1, j2; | sljit_si s, j1, j2; |
|
|
if (SLJIT_UNLIKELY(type == 0)) { |
if (SLJIT_UNLIKELY(type == 0)) { |
inline_set_jump_addr(jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0); |
inline_set_jump_addr(jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0); |
Line 294 static SLJIT_INLINE void set_jump_instruction(struct s
|
Line 295 static SLJIT_INLINE void set_jump_instruction(struct s
|
|
|
if (jump->flags & JUMP_ADDR) { |
if (jump->flags & JUMP_ADDR) { |
SLJIT_ASSERT(jump->u.target & 0x1); |
SLJIT_ASSERT(jump->u.target & 0x1); |
diff = ((sljit_w)jump->u.target - (sljit_w)(jump->addr + 4)) >> 1; | diff = ((sljit_sw)jump->u.target - (sljit_sw)(jump->addr + 4)) >> 1; |
} |
} |
else |
else |
diff = ((sljit_w)(jump->u.label->addr) - (sljit_w)(jump->addr + 4)) >> 1; | diff = ((sljit_sw)(jump->u.label->addr) - (sljit_sw)(jump->addr + 4)) >> 1; |
jump_inst = (sljit_uh*)jump->addr; |
jump_inst = (sljit_uh*)jump->addr; |
|
|
switch (type) { |
switch (type) { |
case 1: |
case 1: |
/* Encoding T1 of 'B' instruction */ |
/* Encoding T1 of 'B' instruction */ |
SLJIT_ASSERT(diff <= 127 && diff >= -128 && (jump->flags & IS_CONDITIONAL)); | SLJIT_ASSERT(diff <= 127 && diff >= -128 && (jump->flags & IS_COND)); |
jump_inst[0] = 0xd000 | (jump->flags & 0xf00) | (diff & 0xff); |
jump_inst[0] = 0xd000 | (jump->flags & 0xf00) | (diff & 0xff); |
return; |
return; |
case 2: |
case 2: |
/* Encoding T3 of 'B' instruction */ |
/* Encoding T3 of 'B' instruction */ |
SLJIT_ASSERT(diff <= 524287 && diff >= -524288 && (jump->flags & IS_CONDITIONAL)); | SLJIT_ASSERT(diff <= 524287 && diff >= -524288 && (jump->flags & IS_COND)); |
jump_inst[0] = 0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1); |
jump_inst[0] = 0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1); |
jump_inst[1] = 0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | (diff & 0x7ff); |
jump_inst[1] = 0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | (diff & 0x7ff); |
return; |
return; |
case 3: |
case 3: |
SLJIT_ASSERT(jump->flags & IS_CONDITIONAL); | SLJIT_ASSERT(jump->flags & IS_COND); |
*jump_inst++ = IT | ((jump->flags >> 4) & 0xf0) | 0x8; |
*jump_inst++ = IT | ((jump->flags >> 4) & 0xf0) | 0x8; |
diff--; |
diff--; |
type = 5; |
type = 5; |
break; |
break; |
case 4: |
case 4: |
/* Encoding T2 of 'B' instruction */ |
/* Encoding T2 of 'B' instruction */ |
SLJIT_ASSERT(diff <= 1023 && diff >= -1024 && !(jump->flags & IS_CONDITIONAL)); | SLJIT_ASSERT(diff <= 1023 && diff >= -1024 && !(jump->flags & IS_COND)); |
jump_inst[0] = 0xe000 | (diff & 0x7ff); |
jump_inst[0] = 0xe000 | (diff & 0x7ff); |
return; |
return; |
} |
} |
Line 385 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
Line 386 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
label = label->next; |
label = label->next; |
} |
} |
if (jump && jump->addr == half_count) { |
if (jump && jump->addr == half_count) { |
jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_CONDITIONAL) ? 10 : 8); | jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8); |
code_ptr -= detect_jump_type(jump, code_ptr, code); |
code_ptr -= detect_jump_type(jump, code_ptr, code); |
jump = jump->next; |
jump = jump->next; |
} |
} |
Line 409 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
Line 410 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
SLJIT_ASSERT(!label); |
SLJIT_ASSERT(!label); |
SLJIT_ASSERT(!jump); |
SLJIT_ASSERT(!jump); |
SLJIT_ASSERT(!const_); |
SLJIT_ASSERT(!const_); |
SLJIT_ASSERT(code_ptr - code <= (int)compiler->size); | SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); |
|
|
jump = compiler->jumps; |
jump = compiler->jumps; |
while (jump) { |
while (jump) { |
Line 417 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
Line 418 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
jump = jump->next; |
jump = jump->next; |
} |
} |
|
|
SLJIT_CACHE_FLUSH(code, code_ptr); |
|
compiler->error = SLJIT_ERR_COMPILED; |
compiler->error = SLJIT_ERR_COMPILED; |
compiler->executable_size = compiler->size * sizeof(sljit_uh); | compiler->executable_size = (code_ptr - code) * sizeof(sljit_uh); |
| SLJIT_CACHE_FLUSH(code, code_ptr); |
/* Set thumb mode flag. */ |
/* Set thumb mode flag. */ |
return (void*)((sljit_uw)code | 0x1); |
return (void*)((sljit_uw)code | 0x1); |
} |
} |
Line 428 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
Line 429 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(str
|
static sljit_uw get_imm(sljit_uw imm) |
static sljit_uw get_imm(sljit_uw imm) |
{ |
{ |
/* Thumb immediate form. */ |
/* Thumb immediate form. */ |
int counter; | sljit_si counter; |
|
|
if (imm <= 0xff) |
if (imm <= 0xff) |
return imm; |
return imm; |
Line 474 static sljit_uw get_imm(sljit_uw imm)
|
Line 475 static sljit_uw get_imm(sljit_uw imm)
|
return ((imm >> 24) & 0x7f) | COPY_BITS(counter, 4, 26, 1) | COPY_BITS(counter, 1, 12, 3) | COPY_BITS(counter, 0, 7, 1); |
return ((imm >> 24) & 0x7f) | COPY_BITS(counter, 4, 26, 1) | COPY_BITS(counter, 1, 12, 3) | COPY_BITS(counter, 0, 7, 1); |
} |
} |
|
|
static int load_immediate(struct sljit_compiler *compiler, int dst, sljit_uw imm) | static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sljit_uw imm) |
{ |
{ |
sljit_uw tmp; |
sljit_uw tmp; |
|
|
Line 509 static int load_immediate(struct sljit_compiler *compi
|
Line 510 static int load_immediate(struct sljit_compiler *compi
|
#define SLOW_SRC1 0x0800000 |
#define SLOW_SRC1 0x0800000 |
#define SLOW_SRC2 0x1000000 |
#define SLOW_SRC2 0x1000000 |
|
|
static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, sljit_uw arg1, sljit_uw arg2) | static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, sljit_si dst, sljit_uw arg1, sljit_uw arg2) |
{ |
{ |
/* dst must be register, TMP_REG1 |
/* dst must be register, TMP_REG1 |
arg1 must be register, TMP_REG1, imm |
arg1 must be register, TMP_REG1, imm |
arg2 must be register, TMP_REG2, imm */ |
arg2 must be register, TMP_REG2, imm */ |
int reg; | sljit_si reg; |
sljit_uw imm, negated_imm; |
sljit_uw imm, negated_imm; |
|
|
if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) { |
if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) { |
Line 542 static int emit_op_imm(struct sljit_compiler *compiler
|
Line 543 static int emit_op_imm(struct sljit_compiler *compiler
|
/* No form with immediate operand. */ |
/* No form with immediate operand. */ |
break; |
break; |
case SLJIT_ADD: |
case SLJIT_ADD: |
negated_imm = (sljit_uw)-(sljit_w)imm; | negated_imm = (sljit_uw)-(sljit_sw)imm; |
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) { |
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) { |
if (imm <= 0x7) |
if (imm <= 0x7) |
return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); |
return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); |
Line 572 static int emit_op_imm(struct sljit_compiler *compiler
|
Line 573 static int emit_op_imm(struct sljit_compiler *compiler
|
break; |
break; |
case SLJIT_SUB: |
case SLJIT_SUB: |
if (flags & ARG2_IMM) { |
if (flags & ARG2_IMM) { |
negated_imm = (sljit_uw)-(sljit_w)imm; | negated_imm = (sljit_uw)-(sljit_sw)imm; |
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) { |
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) { |
if (imm <= 0x7) |
if (imm <= 0x7) |
return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); |
return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); |
Line 701 static int emit_op_imm(struct sljit_compiler *compiler
|
Line 702 static int emit_op_imm(struct sljit_compiler *compiler
|
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: |
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: |
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); |
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); |
return push_inst16(compiler, MOV | SET_REGS44(dst, arg2)); |
return push_inst16(compiler, MOV | SET_REGS44(dst, arg2)); |
case SLJIT_MOV_UB: |
case SLJIT_MOV_UB: |
Line 885 static SLJIT_CONST sljit_uw sljit_mem32[12] = {
|
Line 888 static SLJIT_CONST sljit_uw sljit_mem32[12] = {
|
}; |
}; |
|
|
/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */ |
/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */ |
static int emit_set_delta(struct sljit_compiler *compiler, int dst, int reg, sljit_w value) | static sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sljit_si reg, sljit_sw value) |
{ |
{ |
if (value >= 0) { |
if (value >= 0) { |
if (value <= 0xfff) |
if (value <= 0xfff) |
Line 906 static int emit_set_delta(struct sljit_compiler *compi
|
Line 909 static int emit_set_delta(struct sljit_compiler *compi
|
} |
} |
|
|
/* 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 flags, int reg, int arg, sljit_w argw) | static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw) |
{ |
{ |
int tmp; | sljit_si tmp; |
|
|
SLJIT_ASSERT(arg & SLJIT_MEM); |
SLJIT_ASSERT(arg & SLJIT_MEM); |
|
|
Line 991 static int getput_arg_fast(struct sljit_compiler *comp
|
Line 994 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) |
{ |
{ |
/* Simple operation except for updates. */ |
/* Simple operation except for updates. */ |
if ((arg & 0xf0) || !(next_arg & SLJIT_MEM)) |
if ((arg & 0xf0) || !(next_arg & SLJIT_MEM)) |
Line 1013 static int can_cache(int arg, sljit_w argw, int next_a
|
Line 1016 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 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 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 tmp; | sljit_sw tmp; |
|
|
SLJIT_ASSERT(arg & SLJIT_MEM); |
SLJIT_ASSERT(arg & SLJIT_MEM); |
if (!(next_arg & SLJIT_MEM)) { |
if (!(next_arg & SLJIT_MEM)) { |
Line 1112 static int getput_arg(struct sljit_compiler *compiler,
|
Line 1115 static int getput_arg(struct sljit_compiler *compiler,
|
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0); |
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0); |
} |
} |
|
|
static SLJIT_INLINE int emit_op_mem(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw) | static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw) |
{ |
{ |
if (getput_arg_fast(compiler, flags, reg, arg, argw)) |
if (getput_arg_fast(compiler, flags, reg, arg, argw)) |
return compiler->error; |
return compiler->error; |
Line 1121 static SLJIT_INLINE int emit_op_mem(struct sljit_compi
|
Line 1124 static SLJIT_INLINE int emit_op_mem(struct sljit_compi
|
return getput_arg(compiler, flags, reg, arg, argw, 0, 0); |
return getput_arg(compiler, flags, reg, arg, argw, 0, 0); |
} |
} |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) | 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) |
{ |
{ |
int size; | if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) |
| return compiler->error; |
| return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); |
| } |
| |
| /* --------------------------------------------------------------------- */ |
| /* Entry, exit */ |
| /* --------------------------------------------------------------------- */ |
| |
| 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 size; |
sljit_ins push; |
sljit_ins 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 1146 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s
|
Line 1160 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s
|
push |= 1 << 7; |
push |= 1 << 7; |
if (saveds >= 1) |
if (saveds >= 1) |
push |= 1 << 6; |
push |= 1 << 6; |
if (temporaries >= 5) | if (scratches >= 5) |
push |= 1 << 5; |
push |= 1 << 5; |
FAIL_IF(saveds >= 3 |
FAIL_IF(saveds >= 3 |
? push_inst32(compiler, PUSH_W | (1 << 14) | push) |
? push_inst32(compiler, PUSH_W | (1 << 14) | push) |
Line 1166 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s
|
Line 1180 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s
|
} |
} |
|
|
if (args >= 1) |
if (args >= 1) |
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG1, SLJIT_TEMPORARY_REG1))); | FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG1, SLJIT_SCRATCH_REG1))); |
if (args >= 2) |
if (args >= 2) |
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG2, SLJIT_TEMPORARY_REG2))); | FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG2, SLJIT_SCRATCH_REG2))); |
if (args >= 3) |
if (args >= 3) |
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG3, SLJIT_TEMPORARY_REG3))); | FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG3, 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; |
Line 1195 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct
|
Line 1209 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct
|
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_ins pop; |
sljit_ins 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 1223 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct
|
Line 1236 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct
|
pop |= 1 << 7; |
pop |= 1 << 7; |
if (compiler->saveds >= 1) |
if (compiler->saveds >= 1) |
pop |= 1 << 6; |
pop |= 1 << 6; |
if (compiler->temporaries >= 5) | if (compiler->scratches >= 5) |
pop |= 1 << 5; |
pop |= 1 << 5; |
return compiler->saveds >= 3 |
return compiler->saveds >= 3 |
? push_inst32(compiler, POP_W | (1 << 15) | pop) |
? push_inst32(compiler, POP_W | (1 << 15) | pop) |
Line 1239 extern "C" {
|
Line 1252 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, int unsigned 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 1249 extern unsigned int __aeabi_idivmod(unsigned numerator
|
Line 1262 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 1265 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj
|
Line 1278 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj
|
case SLJIT_UMUL: |
case SLJIT_UMUL: |
case SLJIT_SMUL: |
case SLJIT_SMUL: |
return push_inst32(compiler, (op == SLJIT_UMUL ? UMULL : SMULL) |
return push_inst32(compiler, (op == SLJIT_UMUL ? UMULL : SMULL) |
| (reg_map[SLJIT_TEMPORARY_REG2] << 8) | | (reg_map[SLJIT_SCRATCH_REG2] << 8) |
| (reg_map[SLJIT_TEMPORARY_REG1] << 12) | | (reg_map[SLJIT_SCRATCH_REG1] << 12) |
| (reg_map[SLJIT_TEMPORARY_REG1] << 16) | | (reg_map[SLJIT_SCRATCH_REG1] << 16) |
| reg_map[SLJIT_TEMPORARY_REG2]); | | reg_map[SLJIT_SCRATCH_REG2]); |
case SLJIT_UDIV: |
case SLJIT_UDIV: |
case SLJIT_SDIV: |
case SLJIT_SDIV: |
if (compiler->temporaries >= 4) { | if (compiler->scratches >= 4) { |
FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */)); |
FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */)); |
FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */)); |
FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */)); |
} else if (compiler->temporaries >= 3) | } else if (compiler->scratches >= 3) |
FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */)); |
FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* 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 1282 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj
|
Line 1295 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 >= 4) { | if (compiler->scratches >= 4) { |
FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */)); |
FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */)); |
return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */); |
return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */); |
} else if (compiler->temporaries >= 3) | } else if (compiler->scratches >= 3) |
return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */); |
return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */); |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
Line 1293 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj
|
Line 1306 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) |
{ |
{ |
int op_type, dst_r, flags; | sljit_si dst_r, flags; |
| sljit_si op_flags = GET_ALL_FLAGS(op); |
|
|
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 1307 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
Line 1321 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
compiler->cache_arg = 0; |
compiler->cache_arg = 0; |
compiler->cache_argw = 0; |
compiler->cache_argw = 0; |
|
|
op_type = GET_OPCODE(op); | dst_r = (dst >= SLJIT_SCRATCH_REG1 && dst <= TMP_REG3) ? dst : TMP_REG1; |
dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG1; | |
|
|
if (op_type >= SLJIT_MOV && op_type <= SLJIT_MOVU_SI) { | op = GET_OPCODE(op); |
switch (op_type) { | if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) { |
| switch (op) { |
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: |
flags = WORD_SIZE; |
flags = WORD_SIZE; |
break; |
break; |
case SLJIT_MOV_UB: |
case SLJIT_MOV_UB: |
flags = BYTE_SIZE; |
flags = BYTE_SIZE; |
if (src & SLJIT_IMM) |
if (src & SLJIT_IMM) |
srcw = (unsigned char)srcw; | srcw = (sljit_ub)srcw; |
break; |
break; |
case SLJIT_MOV_SB: |
case SLJIT_MOV_SB: |
flags = BYTE_SIZE | SIGNED; |
flags = BYTE_SIZE | SIGNED; |
if (src & SLJIT_IMM) |
if (src & SLJIT_IMM) |
srcw = (signed char)srcw; | srcw = (sljit_sb)srcw; |
break; |
break; |
case SLJIT_MOV_UH: |
case SLJIT_MOV_UH: |
flags = HALF_SIZE; |
flags = HALF_SIZE; |
if (src & SLJIT_IMM) |
if (src & SLJIT_IMM) |
srcw = (unsigned short)srcw; | srcw = (sljit_uh)srcw; |
break; |
break; |
case SLJIT_MOV_SH: |
case SLJIT_MOV_SH: |
flags = HALF_SIZE | SIGNED; |
flags = HALF_SIZE | SIGNED; |
if (src & SLJIT_IMM) |
if (src & SLJIT_IMM) |
srcw = (signed short)srcw; | srcw = (sljit_sh)srcw; |
break; |
break; |
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: |
flags = WORD_SIZE | UPDATE; |
flags = WORD_SIZE | UPDATE; |
break; |
break; |
case SLJIT_MOVU_UB: |
case SLJIT_MOVU_UB: |
flags = BYTE_SIZE | UPDATE; |
flags = BYTE_SIZE | UPDATE; |
if (src & SLJIT_IMM) |
if (src & SLJIT_IMM) |
srcw = (unsigned char)srcw; | srcw = (sljit_ub)srcw; |
break; |
break; |
case SLJIT_MOVU_SB: |
case SLJIT_MOVU_SB: |
flags = BYTE_SIZE | SIGNED | UPDATE; |
flags = BYTE_SIZE | SIGNED | UPDATE; |
if (src & SLJIT_IMM) |
if (src & SLJIT_IMM) |
srcw = (signed char)srcw; | srcw = (sljit_sb)srcw; |
break; |
break; |
case SLJIT_MOVU_UH: |
case SLJIT_MOVU_UH: |
flags = HALF_SIZE | UPDATE; |
flags = HALF_SIZE | UPDATE; |
if (src & SLJIT_IMM) |
if (src & SLJIT_IMM) |
srcw = (unsigned short)srcw; | srcw = (sljit_uh)srcw; |
break; |
break; |
case SLJIT_MOVU_SH: |
case SLJIT_MOVU_SH: |
flags = HALF_SIZE | SIGNED | UPDATE; |
flags = HALF_SIZE | SIGNED | UPDATE; |
if (src & SLJIT_IMM) |
if (src & SLJIT_IMM) |
srcw = (signed short)srcw; | srcw = (sljit_sh)srcw; |
break; |
break; |
default: |
default: |
SLJIT_ASSERT_STOP(); |
SLJIT_ASSERT_STOP(); |
Line 1377 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
Line 1393 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
FAIL_IF(getput_arg(compiler, flags, dst_r, src, srcw, dst, dstw)); |
FAIL_IF(getput_arg(compiler, flags, dst_r, src, srcw, dst, dstw)); |
} else { |
} else { |
if (dst_r != TMP_REG1) |
if (dst_r != TMP_REG1) |
return emit_op_imm(compiler, op_type, dst_r, TMP_REG1, src); | return emit_op_imm(compiler, op, dst_r, TMP_REG1, src); |
dst_r = src; |
dst_r = src; |
} |
} |
|
|
Line 1390 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
Line 1406 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
if (op_type == SLJIT_NEG) { | if (op == SLJIT_NEG) { |
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) |
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) |
compiler->skip_checks = 1; |
compiler->skip_checks = 1; |
#endif |
#endif |
return sljit_emit_op2(compiler, GET_FLAGS(op) | SLJIT_SUB, dst, dstw, SLJIT_IMM, 0, src, srcw); | return sljit_emit_op2(compiler, SLJIT_SUB | op_flags, dst, dstw, SLJIT_IMM, 0, src, srcw); |
} |
} |
|
|
flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0); | flags = (GET_FLAGS(op_flags) ? SET_FLAGS : 0) | ((op_flags & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0); |
if (src & SLJIT_MEM) { |
if (src & SLJIT_MEM) { |
if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src, srcw)) |
if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src, srcw)) |
FAIL_IF(compiler->error); |
FAIL_IF(compiler->error); |
Line 1411 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
Line 1427 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
else |
else |
srcw = src; |
srcw = src; |
|
|
emit_op_imm(compiler, flags | op_type, dst_r, TMP_REG1, srcw); | emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, srcw); |
|
|
if (dst & SLJIT_MEM) { |
if (dst & SLJIT_MEM) { |
if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw)) |
if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw)) |
Line 1422 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
Line 1438 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) |
{ |
{ |
int dst_r, flags; | sljit_si dst_r, flags; |
|
|
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 1438 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj
|
Line 1454 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj
|
compiler->cache_arg = 0; |
compiler->cache_arg = 0; |
compiler->cache_argw = 0; |
compiler->cache_argw = 0; |
|
|
dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG1; | dst_r = (dst >= SLJIT_SCRATCH_REG1 && dst <= TMP_REG3) ? dst : TMP_REG1; |
flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0); |
flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0); |
|
|
if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, WORD_SIZE | STORE | ARG_TEST, TMP_REG1, dst, dstw)) |
if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, WORD_SIZE | STORE | ARG_TEST, TMP_REG1, dst, dstw)) |
Line 1504 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj
|
Line 1520 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 == 2 || size == 4); |
SLJIT_ASSERT(size == 2 || size == 4); |
Line 1526 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(stru
|
Line 1548 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(stru
|
/* Floating point operators */ |
/* Floating point operators */ |
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void) | SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void) |
{ |
{ |
return 1; |
return 1; |
} |
} |
|
|
static int emit_fop_mem(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw) | #define FPU_LOAD (1 << 20) |
| |
| static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw) |
{ |
{ |
sljit_w tmp; | sljit_sw tmp; |
sljit_w inst = VSTR | ((flags & STORE) ? 0 : 0x00100000); | sljit_uw imm; |
| sljit_sw inst = VSTR_F32 | (flags & (SLJIT_SINGLE_OP | FPU_LOAD)); |
|
|
SLJIT_ASSERT(arg & SLJIT_MEM); |
SLJIT_ASSERT(arg & SLJIT_MEM); |
|
|
Line 1545 static int emit_fop_mem(struct sljit_compiler *compile
|
Line 1570 static int emit_fop_mem(struct sljit_compiler *compile
|
argw = 0; |
argw = 0; |
} |
} |
|
|
if (arg & 0xf) { | if ((arg & 0xf) && (argw & 0x3) == 0) { |
if (!(argw & ~0x3fc)) |
if (!(argw & ~0x3fc)) |
return push_inst32(compiler, inst | 0x800000 | RN4(arg & 0xf) | DD4(reg) | (argw >> 2)); |
return push_inst32(compiler, inst | 0x800000 | RN4(arg & 0xf) | DD4(reg) | (argw >> 2)); |
if (!(-argw & ~0x3fc)) |
if (!(-argw & ~0x3fc)) |
Line 1566 static int emit_fop_mem(struct sljit_compiler *compile
|
Line 1591 static int emit_fop_mem(struct sljit_compiler *compile
|
} |
} |
} |
} |
|
|
|
if (arg & 0xf) { |
|
if (emit_set_delta(compiler, TMP_REG1, arg & 0xf, argw) != SLJIT_ERR_UNSUPPORTED) { |
|
FAIL_IF(compiler->error); |
|
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg)); |
|
} |
|
imm = get_imm(argw & ~0x3fc); |
|
if (imm != INVALID_IMM) { |
|
FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & 0xf) | imm)); |
|
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2)); |
|
} |
|
imm = get_imm(-argw & ~0x3fc); |
|
if (imm != INVALID_IMM) { |
|
argw = -argw; |
|
FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & 0xf) | imm)); |
|
return push_inst32(compiler, inst | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2)); |
|
} |
|
} |
|
|
compiler->cache_arg = arg; |
compiler->cache_arg = arg; |
compiler->cache_argw = argw; |
compiler->cache_argw = argw; |
|
|
if (SLJIT_UNLIKELY(!(arg & 0xf))) |
if (SLJIT_UNLIKELY(!(arg & 0xf))) |
FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); |
FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); |
else if (emit_set_delta(compiler, TMP_REG3, arg & 0xf, argw) != SLJIT_ERR_UNSUPPORTED) |
|
FAIL_IF(compiler->error); |
|
else { |
else { |
FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); |
FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); |
if (arg & 0xf) |
if (arg & 0xf) |
Line 1581 static int emit_fop_mem(struct sljit_compiler *compile
|
Line 1622 static int emit_fop_mem(struct sljit_compiler *compile
|
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg)); |
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg)); |
} |
} |
|
|
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_r; | sljit_si dst_r; |
|
|
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_MEM) { |
if (dst & SLJIT_MEM) { |
emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw); | emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, dst, dstw); |
dst = TMP_FREG1; |
dst = TMP_FREG1; |
} |
} |
if (src & SLJIT_MEM) { |
if (src & SLJIT_MEM) { |
emit_fop_mem(compiler, 0, TMP_FREG2, src, srcw); | emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src, srcw); |
src = TMP_FREG2; |
src = TMP_FREG2; |
} |
} |
FAIL_IF(push_inst32(compiler, VCMP_F64 | DD4(dst) | DM4(src))); | FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst) | DM4(src))); |
return push_inst32(compiler, VMRS); |
return push_inst32(compiler, VMRS); |
} |
} |
|
|
dst_r = (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) ? dst : TMP_FREG1; | dst_r = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst; |
if (src & SLJIT_MEM) { |
if (src & SLJIT_MEM) { |
emit_fop_mem(compiler, 0, dst_r, src, srcw); | emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_r, src, srcw); |
src = dst_r; |
src = dst_r; |
} |
} |
|
|
switch (GET_OPCODE(op)) { |
switch (GET_OPCODE(op)) { |
case SLJIT_FMOV: | case SLJIT_MOVD: |
if (src != dst_r) |
if (src != dst_r) |
FAIL_IF(push_inst32(compiler, VMOV_F64 | DD4(dst_r) | DM4(src))); | FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src))); |
break; |
break; |
case SLJIT_FNEG: | case SLJIT_NEGD: |
FAIL_IF(push_inst32(compiler, VNEG_F64 | DD4(dst_r) | DM4(src))); | FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src))); |
break; |
break; |
case SLJIT_FABS: | case SLJIT_ABSD: |
FAIL_IF(push_inst32(compiler, VABS_F64 | DD4(dst_r) | DM4(src))); | FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src))); |
break; |
break; |
} |
} |
|
|
if (dst & SLJIT_MEM) |
if (dst & SLJIT_MEM) |
return emit_fop_mem(compiler, STORE, TMP_FREG1, dst, dstw); | return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, 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_r; | sljit_si dst_r; |
|
|
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_r = (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) ? dst : TMP_FREG1; | dst_r = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst; |
if (src1 & SLJIT_MEM) { |
if (src1 & SLJIT_MEM) { |
emit_fop_mem(compiler, 0, TMP_FREG1, src1, src1w); | emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w); |
src1 = TMP_FREG1; |
src1 = TMP_FREG1; |
} |
} |
if (src2 & SLJIT_MEM) { |
if (src2 & SLJIT_MEM) { |
emit_fop_mem(compiler, 0, TMP_FREG2, src2, src2w); | emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w); |
src2 = TMP_FREG2; |
src2 = TMP_FREG2; |
} |
} |
|
|
switch (GET_OPCODE(op)) { |
switch (GET_OPCODE(op)) { |
case SLJIT_FADD: | case SLJIT_ADDD: |
FAIL_IF(push_inst32(compiler, VADD_F64 | DD4(dst_r) | DN4(src1) | DM4(src2))); | FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2))); |
break; |
break; |
case SLJIT_FSUB: | case SLJIT_SUBD: |
FAIL_IF(push_inst32(compiler, VSUB_F64 | DD4(dst_r) | DN4(src1) | DM4(src2))); | FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2))); |
break; |
break; |
case SLJIT_FMUL: | case SLJIT_MULD: |
FAIL_IF(push_inst32(compiler, VMUL_F64 | DD4(dst_r) | DN4(src1) | DM4(src2))); | FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2))); |
break; |
break; |
case SLJIT_FDIV: | case SLJIT_DIVD: |
FAIL_IF(push_inst32(compiler, VDIV_F64 | DD4(dst_r) | DN4(src1) | DM4(src2))); | FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2))); |
break; |
break; |
} |
} |
|
|
if (dst & SLJIT_MEM) |
if (dst & SLJIT_MEM) |
return emit_fop_mem(compiler, STORE, TMP_FREG1, dst, dstw); | return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw); |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
|
#undef FPU_LOAD |
|
|
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
/* 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_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3)); |
return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3)); |
else if (dst & SLJIT_MEM) { |
|
if (getput_arg_fast(compiler, WORD_SIZE | STORE, TMP_REG3, dst, dstw)) |
|
return compiler->error; |
|
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, TMP_REG3))); |
|
compiler->cache_arg = 0; |
|
compiler->cache_argw = 0; |
|
return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0); |
|
} |
|
|
|
return SLJIT_SUCCESS; | /* Memory. */ |
| if (getput_arg_fast(compiler, WORD_SIZE | STORE, TMP_REG3, dst, dstw)) |
| return compiler->error; |
| /* TMP_REG3 is used for caching. */ |
| FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, TMP_REG3))); |
| compiler->cache_arg = 0; |
| compiler->cache_argw = 0; |
| return getput_arg(compiler, WORD_SIZE | STORE, 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) |
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src))); |
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src))); |
else if (src & SLJIT_MEM) { |
else if (src & SLJIT_MEM) { |
if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG3, src, srcw)) |
if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG3, src, srcw)) |
Line 1724 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st
|
Line 1773 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 1766 static sljit_uw get_cc(int type)
|
Line 1815 static sljit_uw get_cc(int type)
|
return 0xd; |
return 0xd; |
|
|
case SLJIT_C_OVERFLOW: |
case SLJIT_C_OVERFLOW: |
case SLJIT_C_FLOAT_NAN: | case SLJIT_C_FLOAT_UNORDERED: |
return 0x6; |
return 0x6; |
|
|
case SLJIT_C_NOT_OVERFLOW: |
case SLJIT_C_NOT_OVERFLOW: |
case SLJIT_C_FLOAT_NOT_NAN: | case SLJIT_C_FLOAT_ORDERED: |
return 0x7; |
return 0x7; |
|
|
default: /* SLJIT_JUMP */ |
default: /* SLJIT_JUMP */ |
Line 1794 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emi
|
Line 1843 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; |
int cc; | sljit_si cc; |
|
|
CHECK_ERROR_PTR(); |
CHECK_ERROR_PTR(); |
check_sljit_emit_jump(compiler, type); |
check_sljit_emit_jump(compiler, type); |
Line 1810 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit
|
Line 1859 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit
|
/* In ARM, we don't need to touch the arguments. */ |
/* In ARM, we don't need to touch the arguments. */ |
PTR_FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0)); |
PTR_FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0)); |
if (type < SLJIT_JUMP) { |
if (type < SLJIT_JUMP) { |
jump->flags |= IS_CONDITIONAL; | jump->flags |= IS_COND; |
cc = get_cc(type); |
cc = get_cc(type); |
jump->flags |= cc << 8; |
jump->flags |= cc << 8; |
PTR_FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); |
PTR_FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); |
Line 1827 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit
|
Line 1876 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 1847 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct s
|
Line 1896 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct s
|
FAIL_IF(push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1))); |
FAIL_IF(push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1))); |
} |
} |
else { |
else { |
if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) | if (src <= TMP_REG3) |
return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src)); |
return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src)); |
|
|
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw)); |
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw)); |
Line 1857 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct s
|
Line 1906 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct s
|
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 dst_r; | sljit_si dst_r, flags = GET_ALL_FLAGS(op); |
| sljit_ins ins; |
sljit_uw cc; |
sljit_uw cc; |
|
|
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 >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { | dst_r = (dst <= TMP_REG3) ? dst : TMP_REG2; |
| |
| if (op < SLJIT_ADD) { |
| FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4)); |
| if (reg_map[dst_r] > 7) { |
| FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 1)); |
| FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 0)); |
| } else { |
| FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 1)); |
| FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0)); |
| } |
| return dst_r == TMP_REG2 ? emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw) : SLJIT_SUCCESS; |
| } |
| |
| ins = (op == SLJIT_AND ? ANDI : (op == SLJIT_OR ? ORRI : EORI)); |
| if ((op == SLJIT_OR || op == SLJIT_XOR) && dst <= TMP_REG3 && dst == src) { |
| /* Does not change the other bits. */ |
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); |
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); |
FAIL_IF(push_inst32(compiler, ORRI | RN4(dst) | RD4(dst) | 0x1)); | FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst) | 1)); |
if (op & SLJIT_SET_E) { | if (flags & SLJIT_SET_E) { |
| /* The condition must always be set, even if the ORRI/EORI is not executed above. */ |
if (reg_map[dst] <= 7) |
if (reg_map[dst] <= 7) |
return push_inst16(compiler, ORRS | RD3(dst) | RN3(dst)); | return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst)); |
return push_inst32(compiler, ORR_W | SET_FLAGS | RD4(TMP_REG1) | RN4(dst) | RM4(dst)); | return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst)); |
} |
} |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
dst_r = TMP_REG2; | compiler->cache_arg = 0; |
if (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS && reg_map[dst] <= 7) | compiler->cache_argw = 0; |
dst_r = dst; | if (src & SLJIT_MEM) { |
| FAIL_IF(emit_op_mem2(compiler, WORD_SIZE, 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; |
| } |
|
|
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4)); |
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4)); |
FAIL_IF(push_inst16(compiler, MOVSI | 0x1 | RDN3(dst_r))); | FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1)); |
FAIL_IF(push_inst16(compiler, MOVSI | 0x0 | RDN3(dst_r))); | FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 0)); |
| if (dst_r == TMP_REG2) |
| FAIL_IF(emit_op_mem2(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0)); |
|
|
if (dst_r == TMP_REG2) { | if (flags & SLJIT_SET_E) { |
if (GET_OPCODE(op) == SLJIT_OR) { | /* The condition must always be set, even if the ORR/EORI is not executed above. */ |
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) | if (reg_map[dst_r] <= 7) |
compiler->skip_checks = 1; | return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst_r)); |
#endif | return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r)); |
return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REG2, 0); | |
} | |
if (dst & SLJIT_MEM) | |
return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw); | |
else | |
return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2)); | |
} |
} |
|
|
return SLJIT_SUCCESS; |
return 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 dst_r; | sljit_si dst_r; |
|
|
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 1918 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emi
|
Line 1993 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emi
|
PTR_FAIL_IF(!const_); |
PTR_FAIL_IF(!const_); |
set_const(const_, compiler); |
set_const(const_, compiler); |
|
|
dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG1; | dst_r = (dst <= TMP_REG3) ? dst : TMP_REG1; |
PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value)); |
PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value)); |
|
|
if (dst & SLJIT_MEM) |
if (dst & SLJIT_MEM) |
Line 1931 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(slji
|
Line 2006 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) |
{ |
{ |
sljit_uh* inst = (sljit_uh*)addr; |
sljit_uh* inst = (sljit_uh*)addr; |
modify_imm32_const(inst, new_constant); |
modify_imm32_const(inst, new_constant); |