summaryrefslogtreecommitdiff
path: root/sljit/sljitNativeARM_T2_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'sljit/sljitNativeARM_T2_32.c')
-rw-r--r--sljit/sljitNativeARM_T2_32.c413
1 files changed, 248 insertions, 165 deletions
diff --git a/sljit/sljitNativeARM_T2_32.c b/sljit/sljitNativeARM_T2_32.c
index 682f964..f9803f5 100644
--- a/sljit/sljitNativeARM_T2_32.c
+++ b/sljit/sljitNativeARM_T2_32.c
@@ -33,17 +33,17 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
typedef sljit_ui sljit_ins;
/* Last register + 1. */
-#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
-#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
-#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
-#define TMP_PC (SLJIT_NO_REGISTERS + 4)
+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
+#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
+#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 5)
#define TMP_FREG1 (0)
-#define TMP_FREG2 (SLJIT_FLOAT_REG6 + 1)
+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
/* 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] = {
- 0, 0, 1, 2, 12, 5, 6, 7, 8, 10, 11, 13, 3, 4, 14, 15
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
+ 0, 0, 1, 2, 12, 11, 10, 9, 8, 7, 6, 5, 13, 3, 4, 14, 15
};
#define COPY_BITS(src, from, to, bits) \
@@ -138,9 +138,9 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
#define ORRI 0xf0400000
#define ORRS 0x4300
#define ORR_W 0xea400000
-#define POP 0xbd00
+#define POP 0xbc00
#define POP_W 0xe8bd0000
-#define PUSH 0xb500
+#define PUSH 0xb400
#define PUSH_W 0xe92d0000
#define RSB_WI 0xf1c00000
#define RSBSI 0x4240
@@ -169,8 +169,12 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
#define VABS_F32 0xeeb00ac0
#define VADD_F32 0xee300a00
#define VCMP_F32 0xeeb40a40
+#define VCVT_F32_S32 0xeeb80ac0
+#define VCVT_F64_F32 0xeeb70ac0
+#define VCVT_S32_F32 0xeebd0ac0
#define VDIV_F32 0xee800a00
#define VMOV_F32 0xeeb00a40
+#define VMOV 0xee000a10
#define VMRS 0xeef1fa10
#define VMUL_F32 0xee200a00
#define VNEG_F32 0xeeb10a40
@@ -349,7 +353,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_const *const_;
CHECK_ERROR_PTR();
- check_sljit_generate_code(compiler);
+ CHECK_PTR(check_sljit_generate_code(compiler));
reverse_buf(compiler);
code = (sljit_uh*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_uh));
@@ -956,7 +960,7 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
}
/* SP based immediate. */
- if (SLJIT_UNLIKELY(arg == SLJIT_LOCALS_REG) && OFFSET_CHECK(0xff, 2) && IS_WORD_SIZE(flags) && reg_map[reg] <= 7) {
+ if (SLJIT_UNLIKELY(arg == SLJIT_SP) && OFFSET_CHECK(0xff, 2) && IS_WORD_SIZE(flags) && reg_map[reg] <= 7) {
FAIL_IF(push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2)));
return -1;
}
@@ -1123,86 +1127,73 @@ static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit
/* 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_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
+ sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
{
- sljit_si size;
+ sljit_si size, i, tmp;
sljit_ins push;
CHECK_ERROR();
- check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
-
- compiler->scratches = scratches;
- compiler->saveds = saveds;
-#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
- compiler->logical_local_size = local_size;
-#endif
+ CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
+ set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
push = (1 << 4);
- if (saveds >= 5)
- push |= 1 << 11;
- if (saveds >= 4)
- push |= 1 << 10;
- if (saveds >= 3)
- push |= 1 << 8;
- if (saveds >= 2)
- push |= 1 << 7;
- if (saveds >= 1)
- push |= 1 << 6;
- if (scratches >= 5)
- push |= 1 << 5;
- FAIL_IF(saveds >= 3
+
+ tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
+ for (i = SLJIT_S0; i >= tmp; i--)
+ push |= 1 << reg_map[i];
+
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
+ push |= 1 << reg_map[i];
+
+ FAIL_IF((push & 0xff00)
? push_inst32(compiler, PUSH_W | (1 << 14) | push)
- : push_inst16(compiler, PUSH | push));
+ : push_inst16(compiler, PUSH | (1 << 8) | push));
- /* Stack must be aligned to 8 bytes: */
- size = (3 + saveds) * sizeof(sljit_uw);
- local_size += size;
- local_size = (local_size + 7) & ~7;
- local_size -= size;
+ /* Stack must be aligned to 8 bytes: (LR, R4) */
+ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
+ local_size = ((size + local_size + 7) & ~7) - size;
compiler->local_size = local_size;
if (local_size > 0) {
if (local_size <= (127 << 2))
FAIL_IF(push_inst16(compiler, SUB_SP | (local_size >> 2)));
else
- FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_LOCALS_REG, SLJIT_LOCALS_REG, local_size));
+ FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, local_size));
}
if (args >= 1)
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG1, SLJIT_SCRATCH_REG1)));
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S0, SLJIT_R0)));
if (args >= 2)
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG2, SLJIT_SCRATCH_REG2)));
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S1, SLJIT_R1)));
if (args >= 3)
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG3, SLJIT_SCRATCH_REG3)));
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S2, SLJIT_R2)));
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
+ sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
+ sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
{
sljit_si size;
- CHECK_ERROR_VOID();
- check_sljit_set_context(compiler, args, scratches, saveds, local_size);
-
- compiler->scratches = scratches;
- compiler->saveds = saveds;
-#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
- compiler->logical_local_size = local_size;
-#endif
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
+ set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
- size = (3 + saveds) * sizeof(sljit_uw);
- local_size += size;
- local_size = (local_size + 7) & ~7;
- local_size -= size;
- compiler->local_size = local_size;
+ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
+ compiler->local_size = ((size + local_size + 7) & ~7) - size;
+ return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
+ sljit_si i, tmp;
sljit_ins pop;
CHECK_ERROR();
- check_sljit_emit_return(compiler, op, src, srcw);
+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
@@ -1210,25 +1201,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
if (compiler->local_size <= (127 << 2))
FAIL_IF(push_inst16(compiler, ADD_SP | (compiler->local_size >> 2)));
else
- FAIL_IF(emit_op_imm(compiler, SLJIT_ADD | ARG2_IMM, SLJIT_LOCALS_REG, SLJIT_LOCALS_REG, compiler->local_size));
+ FAIL_IF(emit_op_imm(compiler, SLJIT_ADD | ARG2_IMM, SLJIT_SP, SLJIT_SP, compiler->local_size));
}
pop = (1 << 4);
- if (compiler->saveds >= 5)
- pop |= 1 << 11;
- if (compiler->saveds >= 4)
- pop |= 1 << 10;
- if (compiler->saveds >= 3)
- pop |= 1 << 8;
- if (compiler->saveds >= 2)
- pop |= 1 << 7;
- if (compiler->saveds >= 1)
- pop |= 1 << 6;
- if (compiler->scratches >= 5)
- pop |= 1 << 5;
- return compiler->saveds >= 3
+
+ tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
+ for (i = SLJIT_S0; i >= tmp; i--)
+ pop |= 1 << reg_map[i];
+
+ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
+ pop |= 1 << reg_map[i];
+
+ return (pop & 0xff00)
? push_inst32(compiler, POP_W | (1 << 15) | pop)
- : push_inst16(compiler, POP | pop);
+ : push_inst16(compiler, POP | (1 << 8) | pop);
}
/* --------------------------------------------------------------------- */
@@ -1252,8 +1239,11 @@ extern int __aeabi_idivmod(int numerator, int denominator);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
{
+ sljit_sw saved_reg_list[3];
+ sljit_sw saved_reg_count;
+
CHECK_ERROR();
- check_sljit_emit_op0(compiler, op);
+ CHECK(check_sljit_emit_op0(compiler, op));
op = GET_OPCODE(op);
switch (op) {
@@ -1261,31 +1251,60 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
return push_inst16(compiler, BKPT);
case SLJIT_NOP:
return push_inst16(compiler, NOP);
- case SLJIT_UMUL:
- case SLJIT_SMUL:
- return push_inst32(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
- | (reg_map[SLJIT_SCRATCH_REG2] << 8)
- | (reg_map[SLJIT_SCRATCH_REG1] << 12)
- | (reg_map[SLJIT_SCRATCH_REG1] << 16)
- | reg_map[SLJIT_SCRATCH_REG2]);
- case SLJIT_UDIV:
- case SLJIT_SDIV:
- if (compiler->scratches >= 4) {
- FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */));
- FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */));
- } else if (compiler->scratches >= 3)
- FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */));
+ case SLJIT_LUMUL:
+ case SLJIT_LSMUL:
+ return push_inst32(compiler, (op == SLJIT_LUMUL ? UMULL : SMULL)
+ | (reg_map[SLJIT_R1] << 8)
+ | (reg_map[SLJIT_R0] << 12)
+ | (reg_map[SLJIT_R0] << 16)
+ | reg_map[SLJIT_R1]);
+ case SLJIT_UDIVMOD:
+ case SLJIT_SDIVMOD:
+ case SLJIT_UDIVI:
+ case SLJIT_SDIVI:
+ SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
+ SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12, bad_register_mapping);
+
+ saved_reg_count = 0;
+ if (compiler->scratches >= 4)
+ saved_reg_list[saved_reg_count++] = 12;
+ if (compiler->scratches >= 3)
+ saved_reg_list[saved_reg_count++] = 2;
+ if (op >= SLJIT_UDIVI)
+ saved_reg_list[saved_reg_count++] = 1;
+
+ if (saved_reg_count > 0) {
+ FAIL_IF(push_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8)
+ | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));
+ if (saved_reg_count >= 2) {
+ SLJIT_ASSERT(saved_reg_list[1] < 8);
+ FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */));
+ }
+ if (saved_reg_count >= 3) {
+ SLJIT_ASSERT(saved_reg_list[2] < 8);
+ FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */));
+ }
+ }
+
#if defined(__GNUC__)
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
- (op == SLJIT_UDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
+ ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
#else
#error "Software divmod functions are needed"
#endif
- if (compiler->scratches >= 4) {
- FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */));
- return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */);
- } else if (compiler->scratches >= 3)
- return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */);
+
+ if (saved_reg_count > 0) {
+ if (saved_reg_count >= 3) {
+ SLJIT_ASSERT(saved_reg_list[2] < 8);
+ FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */));
+ }
+ if (saved_reg_count >= 2) {
+ SLJIT_ASSERT(saved_reg_list[1] < 8);
+ FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */));
+ }
+ return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8)
+ | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
+ }
return SLJIT_SUCCESS;
}
@@ -1300,7 +1319,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
sljit_si op_flags = GET_ALL_FLAGS(op);
CHECK_ERROR();
- check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
@@ -1393,7 +1412,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
}
if (op == SLJIT_NEG) {
-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
return sljit_emit_op2(compiler, SLJIT_SUB | op_flags, dst, dstw, SLJIT_IMM, 0, src, srcw);
@@ -1432,7 +1452,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
sljit_si dst_r, flags;
CHECK_ERROR();
- check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
@@ -1505,22 +1525,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
{
- check_sljit_get_register_index(reg);
+ CHECK_REG_INDEX(check_sljit_get_register_index(reg));
return reg_map[reg];
}
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
{
- check_sljit_get_float_register_index(reg);
- return reg;
+ CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
+ return reg << 1;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
void *instruction, sljit_si size)
{
CHECK_ERROR();
- check_sljit_emit_op_custom(compiler, instruction, size);
- SLJIT_ASSERT(size == 2 || size == 4);
+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
if (size == 2)
return push_inst16(compiler, *(sljit_uh*)instruction);
@@ -1607,6 +1626,69 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg));
}
+static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
+{
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src, srcw));
+ src = TMP_FREG1;
+ }
+
+ FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_SINGLE_OP) | DD4(TMP_FREG1) | DM4(src)));
+
+ if (dst == SLJIT_UNUSED)
+ return SLJIT_SUCCESS;
+
+ if (FAST_IS_REG(dst))
+ return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | DN4(TMP_FREG1));
+
+ /* Store the integer value from a VFP register. */
+ return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);
+}
+
+static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
+{
+ sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (FAST_IS_REG(src))
+ FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | DN4(TMP_FREG1)));
+ else if (src & SLJIT_MEM) {
+ /* Load the integer value into a VFP register. */
+ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));
+ }
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ FAIL_IF(push_inst32(compiler, VMOV | RT4(TMP_REG1) | DN4(TMP_FREG1)));
+ }
+
+ FAIL_IF(push_inst32(compiler, VCVT_F32_S32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(TMP_FREG1)));
+
+ if (dst & SLJIT_MEM)
+ return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
+{
+ if (src1 & SLJIT_MEM) {
+ emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
+ src1 = TMP_FREG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w);
+ src2 = TMP_FREG2;
+ }
+
+ FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_SINGLE_OP) | DD4(src1) | DM4(src2)));
+ return push_inst32(compiler, VMRS);
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
sljit_si dst, sljit_sw dstw,
sljit_si src, sljit_sw srcw)
@@ -1614,48 +1696,45 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
sljit_si dst_r;
CHECK_ERROR();
- 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_argw = 0;
- op ^= SLJIT_SINGLE_OP;
+ if (GET_OPCODE(op) != SLJIT_CONVD_FROMS)
+ op ^= SLJIT_SINGLE_OP;
- if (GET_OPCODE(op) == SLJIT_CMPD) {
- if (dst & SLJIT_MEM) {
- emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, dst, dstw);
- dst = TMP_FREG1;
- }
- if (src & SLJIT_MEM) {
- emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src, srcw);
- src = TMP_FREG2;
- }
- FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst) | DM4(src)));
- return push_inst32(compiler, VMRS);
- }
+ SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100), float_transfer_bit_error);
+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
- dst_r = (dst <= REG_MASK) ? dst : TMP_FREG1;
if (src & SLJIT_MEM) {
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_r, src, srcw);
src = dst_r;
}
switch (GET_OPCODE(op)) {
- case SLJIT_MOVD:
- if (src != dst_r)
- FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
+ case SLJIT_DMOV:
+ if (src != dst_r) {
+ if (dst_r != TMP_FREG1)
+ FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
+ else
+ dst_r = src;
+ }
break;
- case SLJIT_NEGD:
+ case SLJIT_DNEG:
FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
break;
- case SLJIT_ABSD:
+ case SLJIT_DABS:
FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
break;
+ case SLJIT_CONVD_FROMS:
+ FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
+ op ^= SLJIT_SINGLE_OP;
+ break;
}
- if (!(dst & SLJIT_MEM))
- return SLJIT_SUCCESS;
- return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
+ if (dst & SLJIT_MEM)
+ return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), dst_r, dst, dstw);
+ return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
@@ -1666,13 +1745,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
sljit_si dst_r;
CHECK_ERROR();
- check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
compiler->cache_arg = 0;
compiler->cache_argw = 0;
op ^= SLJIT_SINGLE_OP;
- dst_r = (dst <= REG_MASK) ? dst : TMP_FREG1;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
if (src1 & SLJIT_MEM) {
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
src1 = TMP_FREG1;
@@ -1683,16 +1765,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
}
switch (GET_OPCODE(op)) {
- case SLJIT_ADDD:
+ case SLJIT_DADD:
FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
break;
- case SLJIT_SUBD:
+ case SLJIT_DSUB:
FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
break;
- case SLJIT_MULD:
+ case SLJIT_DMUL:
FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
break;
- case SLJIT_DIVD:
+ case SLJIT_DDIV:
FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
break;
}
@@ -1711,14 +1793,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
CHECK_ERROR();
- check_sljit_emit_fast_enter(compiler, dst, dstw);
+ CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
/* For UNUSED dst. Uncommon, but possible. */
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
- if (dst <= REG_MASK)
+ if (FAST_IS_REG(dst))
return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3));
/* Memory. */
@@ -1734,10 +1816,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
CHECK_ERROR();
- check_sljit_emit_fast_return(compiler, src, srcw);
+ CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
- if (src <= REG_MASK)
+ if (FAST_IS_REG(src))
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src)));
else if (src & SLJIT_MEM) {
if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG3, src, srcw))
@@ -1761,53 +1843,54 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
static sljit_uw get_cc(sljit_si type)
{
switch (type) {
- case SLJIT_C_EQUAL:
- case SLJIT_C_MUL_NOT_OVERFLOW:
- case SLJIT_C_FLOAT_EQUAL:
+ case SLJIT_EQUAL:
+ case SLJIT_MUL_NOT_OVERFLOW:
+ case SLJIT_D_EQUAL:
return 0x0;
- case SLJIT_C_NOT_EQUAL:
- case SLJIT_C_MUL_OVERFLOW:
- case SLJIT_C_FLOAT_NOT_EQUAL:
+ case SLJIT_NOT_EQUAL:
+ case SLJIT_MUL_OVERFLOW:
+ case SLJIT_D_NOT_EQUAL:
return 0x1;
- case SLJIT_C_LESS:
- case SLJIT_C_FLOAT_LESS:
+ case SLJIT_LESS:
+ case SLJIT_D_LESS:
return 0x3;
- case SLJIT_C_GREATER_EQUAL:
- case SLJIT_C_FLOAT_GREATER_EQUAL:
+ case SLJIT_GREATER_EQUAL:
+ case SLJIT_D_GREATER_EQUAL:
return 0x2;
- case SLJIT_C_GREATER:
- case SLJIT_C_FLOAT_GREATER:
+ case SLJIT_GREATER:
+ case SLJIT_D_GREATER:
return 0x8;
- case SLJIT_C_LESS_EQUAL:
- case SLJIT_C_FLOAT_LESS_EQUAL:
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_D_LESS_EQUAL:
return 0x9;
- case SLJIT_C_SIG_LESS:
+ case SLJIT_SIG_LESS:
return 0xb;
- case SLJIT_C_SIG_GREATER_EQUAL:
+ case SLJIT_SIG_GREATER_EQUAL:
return 0xa;
- case SLJIT_C_SIG_GREATER:
+ case SLJIT_SIG_GREATER:
return 0xc;
- case SLJIT_C_SIG_LESS_EQUAL:
+ case SLJIT_SIG_LESS_EQUAL:
return 0xd;
- case SLJIT_C_OVERFLOW:
- case SLJIT_C_FLOAT_UNORDERED:
+ case SLJIT_OVERFLOW:
+ case SLJIT_D_UNORDERED:
return 0x6;
- case SLJIT_C_NOT_OVERFLOW:
- case SLJIT_C_FLOAT_ORDERED:
+ case SLJIT_NOT_OVERFLOW:
+ case SLJIT_D_ORDERED:
return 0x7;
default: /* SLJIT_JUMP */
+ SLJIT_ASSERT_STOP();
return 0xe;
}
}
@@ -1817,7 +1900,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
struct sljit_label *label;
CHECK_ERROR_PTR();
- check_sljit_emit_label(compiler);
+ CHECK_PTR(check_sljit_emit_label(compiler));
if (compiler->last_label && compiler->last_label->size == compiler->size)
return compiler->last_label;
@@ -1834,7 +1917,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
sljit_ins cc;
CHECK_ERROR_PTR();
- check_sljit_emit_jump(compiler, type);
+ CHECK_PTR(check_sljit_emit_jump(compiler, type));
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
@@ -1866,7 +1949,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
struct sljit_jump *jump;
CHECK_ERROR();
- check_sljit_emit_ijump(compiler, type, src, srcw);
+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
/* In ARM, we don't need to touch the arguments. */
@@ -1898,7 +1981,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
sljit_ins cc, ins;
CHECK_ERROR();
- check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
@@ -1906,7 +1989,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
return SLJIT_SUCCESS;
op = GET_OPCODE(op);
- cc = get_cc(type);
+ cc = get_cc(type & 0xff);
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
if (op < SLJIT_ADD) {
@@ -1977,7 +2060,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
sljit_si dst_r;
CHECK_ERROR_PTR();
- check_sljit_emit_const(compiler, dst, dstw, init_value);
+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));