Skip to content

Commit

Permalink
Support target address for mov_addr operations
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoltan Herczeg committed Feb 22, 2024
1 parent a5503d6 commit ebe11ba
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 149 deletions.
1 change: 1 addition & 0 deletions sljit_src/sljitLir.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
# define PATCH_MW 0x08
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
# define PATCH_MD 0x10
# define MOV_ADDR_HI 0x20
# define JUMP_MAX_SIZE ((sljit_uw)(10 + 3))
# define CJUMP_MAX_SIZE ((sljit_uw)(2 + 10 + 3))
#else /* !SLJIT_CONFIG_X86_64 */
Expand Down
28 changes: 20 additions & 8 deletions sljit_src/sljitNativeARM_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -710,11 +710,21 @@ static void set_const_value(sljit_uw addr, sljit_sw executable_offset, sljit_uw
#endif /* SLJIT_CONFIG_ARM_V6 */
}

static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump)
static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
{
sljit_sw diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
sljit_uw addr;
sljit_sw diff;
SLJIT_UNUSED_ARG(executable_offset);

if (jump->flags & JUMP_ADDR)
addr = jump->u.target;
else
addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);

if (diff <= 0xff + 2 && diff >= -0xff + 2) {
/* The pc+8 offset is represented by the 2 * SSIZE_OF(ins) below. */
diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);

if ((diff & 0x3) == 0 && diff <= (0x3fc + 2 * SSIZE_OF(ins)) && diff >= (-0x3fc + 2 * SSIZE_OF(ins))) {
jump->flags |= PATCH_B;
return 0;
}
Expand Down Expand Up @@ -782,10 +792,12 @@ static void reduce_code_size(struct sljit_compiler *compiler)
} else {
/* Real size minus 1. Unit size: instruction. */
total_size = 1;
diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;

if (diff <= 0xff + 2 && diff >= -0xff + 2)
total_size = 0;
if (!(jump->flags & JUMP_ADDR)) {
diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
if (diff <= 0xff + 2 && diff >= -0xff + 2)
total_size = 0;
}

size_reduce += 1 - total_size;
}
Expand Down Expand Up @@ -917,12 +929,11 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT((sljit_uw)code_ptr - jump->addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins));
#endif /* SLJIT_CONFIG_ARM_V6 */
} else {
SLJIT_ASSERT(jump->u.label);
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
word_count += jump->flags >> JUMP_SIZE_SHIFT;
#endif /* SLJIT_CONFIG_ARM_V7 */
addr = (sljit_uw)code_ptr;
code_ptr += mov_addr_get_length(jump);
code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);
jump->addr = addr;
}
jump = jump->next;
Expand Down Expand Up @@ -1005,6 +1016,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#endif /* SLJIT_CONFIG_ARM_V6 */

if (jump->flags & PATCH_B) {
SLJIT_ASSERT((((sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset)) & 0x3) == 0);
diff = ((sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset)) >> 2;

SLJIT_ASSERT(diff <= 0xff && diff >= -0xff);
Expand Down
71 changes: 47 additions & 24 deletions sljit_src/sljitNativeARM_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,32 +268,44 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
return code_ptr + 4;
}

static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *mov_addr, sljit_uw addr)
static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
{
sljit_sw diff = (sljit_sw)mov_addr->u.label->size - (sljit_sw)mov_addr->addr;
sljit_uw addr;
sljit_sw diff;
SLJIT_UNUSED_ARG(executable_offset);

SLJIT_ASSERT(jump->flags < ((sljit_uw)4 << JUMP_SIZE_SHIFT));
if (jump->flags & JUMP_ADDR)
addr = jump->u.target;
else
addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);

if (diff <= (0xfffff / SSIZE_OF(ins)) && diff >= (-0x100000 / SSIZE_OF(ins))) {
mov_addr->flags |= PATCH_B;
diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);

if (diff <= 0xfffff && diff >= -0x100000) {
jump->flags |= PATCH_B;
return 0;
}

if (diff <= (0xfffff000l / SSIZE_OF(ins)) && diff >= (-0x100000000l / SSIZE_OF(ins))) {
mov_addr->flags |= PATCH_B32;
if (diff <= 0xfffff000l && diff >= -0x100000000l) {
SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
jump->flags |= PATCH_B32;
return 1;
}

addr += mov_addr->u.label->size;

if (addr < (0x100000000l / sizeof(sljit_ins))) {
if (addr < 0x100000000l) {
SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
return 1;
}

if (addr < (0x1000000000000l / sizeof(sljit_ins))) {
mov_addr->flags |= PATCH_ABS48;
if (addr < 0x1000000000000l) {
SLJIT_ASSERT(jump->flags >= ((sljit_uw)2 << JUMP_SIZE_SHIFT));
jump->flags |= PATCH_ABS48;
return 2;
}

mov_addr->flags |= PATCH_ABS64;
SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
jump->flags |= PATCH_ABS64;
return 3;
}

Expand Down Expand Up @@ -356,7 +368,7 @@ static SLJIT_INLINE void generate_jump_or_mov_addr(struct sljit_jump *jump, slji
buf_ptr[2] = MOVK | (((sljit_ins)(addr >> 32) & 0xffff) << 5) | (2 << 21) | dst;

if (jump->flags & PATCH_ABS64)
buf_ptr[3] = MOVK | ((sljit_ins)(addr >> 48) << 5) | (3 << 21) | dst;
buf_ptr[3] = MOVK | ((sljit_ins)((sljit_uw)addr >> 48) << 5) | (3 << 21) | dst;
}

static void reduce_code_size(struct sljit_compiler *compiler)
Expand Down Expand Up @@ -424,12 +436,18 @@ static void reduce_code_size(struct sljit_compiler *compiler)
} else {
/* Real size minus 1. Unit size: instruction. */
total_size = 3;
diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;

if (diff <= (0xfffff / SSIZE_OF(ins)) && diff >= (-0x100000 / SSIZE_OF(ins)))
total_size = 0;
else if (diff <= (0xfffff000l / SSIZE_OF(ins)) && diff >= (-0x100000000l / SSIZE_OF(ins)))
if (!(jump->flags & JUMP_ADDR)) {
diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;

if (diff <= (0xfffff / SSIZE_OF(ins)) && diff >= (-0x100000 / SSIZE_OF(ins)))
total_size = 0;
else if (diff <= (0xfffff000l / SSIZE_OF(ins)) && diff >= (-0x100000000l / SSIZE_OF(ins)))
total_size = 1;
} else if (jump->u.target < 0x100000000l)
total_size = 1;
else if (jump->u.target < 0x1000000000000l)
total_size = 2;

size_reduce += 3 - total_size;
}
Expand Down Expand Up @@ -504,10 +522,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
SLJIT_ASSERT((jump->flags & PATCH_COND) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));
} else {
SLJIT_ASSERT(jump->u.label);
word_count += jump->flags >> JUMP_SIZE_SHIFT;
addr = (sljit_sw)code_ptr;
code_ptr += mov_addr_get_length(jump, (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset));
code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);
jump->addr = (sljit_uw)addr;
}

Expand Down Expand Up @@ -1163,14 +1180,20 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s
if (argw <= 0xff && argw >= -0x100)
return push_inst(compiler, STURBI | type | RT(reg) | RN(arg) | (((sljit_ins)argw & 0x1ff) << 12));

if (argw >= 0) {
if (argw <= 0xfff0ff && ((argw + 0x100) & 0xfff) <= 0x1ff) {
if (((argw + 0x100) & 0xfff) <= 0x1ff && argw <= 0xfff0ff && argw >= -0xfff100) {
if (argw >= 0) {
if (argw & 0x100)
argw += 0x1000;

FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)argw >> 12) << 10)));
return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12));
} else {
if (!(argw & 0x100))
argw -= 0x1000;

FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)-argw >> 12) << 10)));
return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12));
}
} else if (argw >= -0xfff100 && ((-argw + 0xff) & 0xfff) <= 0x1ff) {
FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)-argw >> 12) << 10)));
return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12));
}

FAIL_IF(load_immediate(compiler, tmp_reg, argw));
Expand Down
30 changes: 21 additions & 9 deletions sljit_src/sljitNativeARM_T2_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,13 +376,23 @@ static SLJIT_INLINE sljit_u16* detect_jump_type(struct sljit_jump *jump, sljit_u
return code_ptr + 4;
}

static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump)
static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)
{
sljit_sw diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
sljit_uw addr;
sljit_sw diff;
SLJIT_UNUSED_ARG(executable_offset);

if (jump->flags & JUMP_ADDR)
addr = jump->u.target;
else
addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);

/* The pc+4 offset is represented by the 2 * SSIZE_OF(sljit_u16) below. */
diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);

/* Note: ADR with imm8 does not set the last bit (Thumb2 flag). */

if (diff <= (0xffd / SSIZE_OF(u16)) && diff >= (-0xfff / SSIZE_OF(u16))) {
if (diff <= 0xffd + 2 * SSIZE_OF(u16) && diff >= -0xfff + 2 * SSIZE_OF(u16)) {
jump->flags |= PATCH_TYPE6;
return 1;
}
Expand All @@ -407,7 +417,7 @@ static SLJIT_INLINE void generate_jump_or_mov_addr(struct sljit_jump *jump, slji

if (SLJIT_UNLIKELY(type == 6)) {
SLJIT_ASSERT(jump->flags & JUMP_MOV_ADDR);
diff -= ((sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_inst, executable_offset) + (2 * SSIZE_OF(u16))) & ~(sljit_sw)0x3;
diff -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_inst + 2, executable_offset) & ~(sljit_sw)0x3;

SLJIT_ASSERT(diff <= 0xfff && diff >= -0xfff);

Expand Down Expand Up @@ -526,10 +536,13 @@ static void reduce_code_size(struct sljit_compiler *compiler)
} else {
/* Real size minus 1. Unit size: instruction. */
total_size = 3;
diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;

if (diff <= (0xffd / SSIZE_OF(u16)) && diff >= (-0xfff / SSIZE_OF(u16)))
total_size = 1;
if (!(jump->flags & JUMP_ADDR)) {
diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;

if (diff <= (0xffd / SSIZE_OF(u16)) && diff >= (-0xfff / SSIZE_OF(u16)))
total_size = 1;
}

size_reduce += 3 - total_size;
}
Expand Down Expand Up @@ -605,10 +618,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT((sljit_uw)code_ptr - jump->addr <
((jump->flags >> JUMP_SIZE_SHIFT) + ((jump->flags & 0xf0) <= PATCH_TYPE2)) * sizeof(sljit_u16));
} else {
SLJIT_ASSERT(jump->u.label);
half_count += jump->flags >> JUMP_SIZE_SHIFT;
addr = (sljit_sw)code_ptr;
code_ptr += mov_addr_get_length(jump);
code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);
jump->addr = (sljit_uw)addr;
}

Expand Down
17 changes: 12 additions & 5 deletions sljit_src/sljitNativeMIPS_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -635,14 +635,22 @@ static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_

#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)

static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_uw max_label)
static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
{
if (max_label < 0x80000000l) {
sljit_uw addr;
SLJIT_UNUSED_ARG(executable_offset);

if (jump->flags & JUMP_ADDR)
addr = jump->u.target;
else
addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);

if (addr < 0x80000000l) {
jump->flags |= PATCH_ABS32;
return 1;
}

if (max_label < 0x800000000000l) {
if (addr < 0x800000000000l) {
jump->flags |= PATCH_ABS48;
return 3;
}
Expand Down Expand Up @@ -747,13 +755,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump->addr = (sljit_uw)(code_ptr - 1);
code_ptr = detect_jump_type(jump, code, executable_offset);
} else {
SLJIT_ASSERT(jump->u.label);
jump->addr = (sljit_uw)code_ptr;
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
code_ptr += 1;
word_count += 1;
#else /* !SLJIT_CONFIG_MIPS_32 */
code_ptr += mov_addr_get_length(jump, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + jump->u.label->size));
code_ptr += mov_addr_get_length(jump, code, executable_offset);
word_count += 5;
#endif /* SLJIT_CONFIG_MIPS_32 */
}
Expand Down
40 changes: 33 additions & 7 deletions sljit_src/sljitNativePPC_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,18 +399,30 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i

#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)

static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_uw max_label)
static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
{
if (max_label < 0x80000000l) {
sljit_uw addr;
SLJIT_UNUSED_ARG(executable_offset);

SLJIT_ASSERT(jump->flags < ((sljit_uw)5 << JUMP_SIZE_SHIFT));
if (jump->flags & JUMP_ADDR)
addr = jump->u.target;
else
addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);

if (addr < 0x80000000l) {
SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
jump->flags |= PATCH_ABS32;
return 1;
}

if (max_label < 0x800000000000l) {
if (addr < 0x800000000000l) {
SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
jump->flags |= PATCH_ABS48;
return 3;
}

SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT));
return 4;
}

Expand Down Expand Up @@ -548,6 +560,21 @@ static void reduce_code_size(struct sljit_compiler *compiler)

size_reduce += (JUMP_MAX_SIZE - 1) - total_size;
jump->flags |= total_size << JUMP_SIZE_SHIFT;
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
} else {
total_size = (sljit_uw)4 << JUMP_SIZE_SHIFT;

if (jump->flags & JUMP_ADDR) {
if (jump->u.target < 0x80000000l) {
total_size = (sljit_uw)1 << JUMP_SIZE_SHIFT;
size_reduce += 3;
} else if (jump->u.target < 0x800000000000l) {
total_size = (sljit_uw)3 << JUMP_SIZE_SHIFT;
size_reduce += 1;
}
}
jump->flags |= total_size;
#endif /* SLJIT_CONFIG_PPC_64 */
}

jump = jump->next;
Expand Down Expand Up @@ -627,14 +654,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
SLJIT_ASSERT(((sljit_uw)code_ptr - jump->addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));
} else {
SLJIT_ASSERT(jump->u.label);
jump->addr = (sljit_uw)code_ptr;
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
code_ptr += mov_addr_get_length(jump, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + jump->u.label->size));
word_count += 4;
word_count += jump->flags >> JUMP_SIZE_SHIFT;
code_ptr += mov_addr_get_length(jump, code, executable_offset);
#else /* !SLJIT_CONFIG_PPC_64 */
code_ptr++;
word_count++;
code_ptr++;
#endif /* SLJIT_CONFIG_PPC_64 */
}
jump = jump->next;
Expand Down
Loading

0 comments on commit ebe11ba

Please sign in to comment.