static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 size, /* The register or immediate operand. */ sljit_s32 a, sljit_sw imma, /* The general operand (not immediate). */ sljit_s32 b, sljit_sw immb) { sljit_u8 *inst; sljit_u8 *buf_ptr; sljit_u8 rex = 0; sljit_s32 flags = size & ~0xf; sljit_s32 inst_size; /* The immediate operand must be 32 bit. */ SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma)); /* Both cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS)); /* Size flags not allowed for typed instructions. */ SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0); /* Both size flags cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG)); /* SSE2 and immediate is not possible. */ SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2)); SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3) && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66) && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66)); size &= 0xf; inst_size = size; if (!compiler->mode32 && !(flags & EX86_NO_REXW)) rex |= REX_W; else if (flags & EX86_REX) rex |= REX; if (flags & (EX86_PREF_F2 | EX86_PREF_F3)) inst_size++; if (flags & EX86_PREF_66) inst_size++; /* Calculate size of b. */ inst_size += 1; /* mod r/m byte. */ if (b & SLJIT_MEM) { if (!(b & OFFS_REG_MASK)) { if (NOT_HALFWORD(immb)) { PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG3, immb)); immb = 0; if (b & REG_MASK) b |= TO_OFFS_REG(TMP_REG3); else b |= TMP_REG3; } else if (reg_lmap[b & REG_MASK] == 4) b |= TO_OFFS_REG(SLJIT_SP); } if ((b & REG_MASK) == SLJIT_UNUSED) inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */ else { if (reg_map[b & REG_MASK] >= 8) rex |= REX_B; if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) { /* Immediate operand. */ if (immb <= 127 && immb >= -128) inst_size += sizeof(sljit_s8); else inst_size += sizeof(sljit_s32); } else if (reg_lmap[b & REG_MASK] == 5) inst_size += sizeof(sljit_s8); if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) { inst_size += 1; /* SIB byte. */ if (reg_map[OFFS_REG(b)] >= 8) rex |= REX_X; } } } else if (!(flags & EX86_SSE2_OP2) && reg_map[b] >= 8) rex |= REX_B; if (a & SLJIT_IMM) { if (flags & EX86_BIN_INS) { if (imma <= 127 && imma >= -128) { inst_size += 1; flags |= EX86_BYTE_ARG; } else inst_size += 4; } else if (flags & EX86_SHIFT_INS) { imma &= compiler->mode32 ? 0x1f : 0x3f; if (imma != 1) { inst_size ++; flags |= EX86_BYTE_ARG; } } else if (flags & EX86_BYTE_ARG) inst_size++; else if (flags & EX86_HALF_ARG) inst_size += sizeof(short); else inst_size += sizeof(sljit_s32); } else { SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG); /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */ if (!(flags & EX86_SSE2_OP1) && reg_map[a] >= 8) rex |= REX_R; } if (rex) inst_size++; inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size); PTR_FAIL_IF(!inst); /* Encoding the byte. */ INC_SIZE(inst_size); if (flags & EX86_PREF_F2) *inst++ = 0xf2; if (flags & EX86_PREF_F3) *inst++ = 0xf3; if (flags & EX86_PREF_66) *inst++ = 0x66; if (rex) *inst++ = rex; buf_ptr = inst + size; /* Encode mod/rm byte. */ if (!(flags & EX86_SHIFT_INS)) { if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM)) *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81; if ((a & SLJIT_IMM) || (a == 0)) *buf_ptr = 0; else if (!(flags & EX86_SSE2_OP1)) *buf_ptr = reg_lmap[a] << 3; else *buf_ptr = a << 3; } else { if (a & SLJIT_IMM) { if (imma == 1) *inst = GROUP_SHIFT_1; else *inst = GROUP_SHIFT_N; } else *inst = GROUP_SHIFT_CL; *buf_ptr = 0; } if (!(b & SLJIT_MEM)) *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_lmap[b] : b); else if ((b & REG_MASK) != SLJIT_UNUSED) { if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) { if (immb != 0 || reg_lmap[b & REG_MASK] == 5) { if (immb <= 127 && immb >= -128) *buf_ptr |= 0x40; else *buf_ptr |= 0x80; } if ((b & OFFS_REG_MASK) == SLJIT_UNUSED) *buf_ptr++ |= reg_lmap[b & REG_MASK]; else { *buf_ptr++ |= 0x04; *buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3); } if (immb != 0 || reg_lmap[b & REG_MASK] == 5) { if (immb <= 127 && immb >= -128) *buf_ptr++ = immb; /* 8 bit displacement. */ else { sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */ buf_ptr += sizeof(sljit_s32); } } } else { if (reg_lmap[b & REG_MASK] == 5) *buf_ptr |= 0x40; *buf_ptr++ |= 0x04; *buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6); if (reg_lmap[b & REG_MASK] == 5) *buf_ptr++ = 0; } } else { *buf_ptr++ |= 0x04; *buf_ptr++ = 0x25; sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */ buf_ptr += sizeof(sljit_s32); } if (a & SLJIT_IMM) { if (flags & EX86_BYTE_ARG) *buf_ptr = imma; else if (flags & EX86_HALF_ARG) sljit_unaligned_store_s16(buf_ptr, imma); else if (!(flags & EX86_SHIFT_INS)) sljit_unaligned_store_s32(buf_ptr, imma); } return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1); }
/* Size contains the flags as well. */ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size, /* The register or immediate operand. */ sljit_si a, sljit_sw imma, /* The general operand (not immediate). */ sljit_si b, sljit_sw immb) { sljit_ub *inst; sljit_ub *buf_ptr; sljit_si flags = size & ~0xf; sljit_si inst_size; /* Both cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS)); /* Size flags not allowed for typed instructions. */ SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0); /* Both size flags cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG)); #if (defined SLJIT_SSE2 && SLJIT_SSE2) /* SSE2 and immediate is not possible. */ SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2)); SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3) && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66) && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66)); #endif size &= 0xf; inst_size = size; #if (defined SLJIT_SSE2 && SLJIT_SSE2) if (flags & (EX86_PREF_F2 | EX86_PREF_F3)) inst_size++; #endif if (flags & EX86_PREF_66) inst_size++; /* Calculate size of b. */ inst_size += 1; /* mod r/m byte. */ if (b & SLJIT_MEM) { if ((b & 0x0f) == SLJIT_UNUSED) inst_size += sizeof(sljit_sw); else if (immb != 0 && !(b & 0xf0)) { /* Immediate operand. */ if (immb <= 127 && immb >= -128) inst_size += sizeof(sljit_sb); else inst_size += sizeof(sljit_sw); } if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0)) b |= SLJIT_LOCALS_REG << 4; if ((b & 0xf0) != SLJIT_UNUSED) inst_size += 1; /* SIB byte. */ } /* Calculate size of a. */ if (a & SLJIT_IMM) { if (flags & EX86_BIN_INS) { if (imma <= 127 && imma >= -128) { inst_size += 1; flags |= EX86_BYTE_ARG; } else inst_size += 4; } else if (flags & EX86_SHIFT_INS) { imma &= 0x1f; if (imma != 1) { inst_size ++; flags |= EX86_BYTE_ARG; } } else if (flags & EX86_BYTE_ARG) inst_size++; else if (flags & EX86_HALF_ARG) inst_size += sizeof(short); else inst_size += sizeof(sljit_sw); } else SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG); inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size); PTR_FAIL_IF(!inst); /* Encoding the byte. */ INC_SIZE(inst_size); #if (defined SLJIT_SSE2 && SLJIT_SSE2) if (flags & EX86_PREF_F2) *inst++ = 0xf2; if (flags & EX86_PREF_F3) *inst++ = 0xf3; #endif if (flags & EX86_PREF_66) *inst++ = 0x66; buf_ptr = inst + size; /* Encode mod/rm byte. */ if (!(flags & EX86_SHIFT_INS)) { if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM)) *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81; if ((a & SLJIT_IMM) || (a == 0)) *buf_ptr = 0; #if (defined SLJIT_SSE2 && SLJIT_SSE2) else if (!(flags & EX86_SSE2)) *buf_ptr = reg_map[a] << 3; else *buf_ptr = a << 3; #else else *buf_ptr = reg_map[a] << 3; #endif }
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type, int src1, sljit_w src1w, int src2, sljit_w src2w) { /* Default compare for most architectures. */ int flags, tmp_src, condition; sljit_w tmp_srcw; CHECK_ERROR_PTR(); check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w); condition = type & 0xff; if (SLJIT_UNLIKELY((src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM))) { /* Immediate is prefered as second argument by most architectures. */ switch (condition) { case SLJIT_C_LESS: condition = SLJIT_C_GREATER; break; case SLJIT_C_GREATER_EQUAL: condition = SLJIT_C_LESS_EQUAL; break; case SLJIT_C_GREATER: condition = SLJIT_C_LESS; break; case SLJIT_C_LESS_EQUAL: condition = SLJIT_C_GREATER_EQUAL; break; case SLJIT_C_SIG_LESS: condition = SLJIT_C_SIG_GREATER; break; case SLJIT_C_SIG_GREATER_EQUAL: condition = SLJIT_C_SIG_LESS_EQUAL; break; case SLJIT_C_SIG_GREATER: condition = SLJIT_C_SIG_LESS; break; case SLJIT_C_SIG_LESS_EQUAL: condition = SLJIT_C_SIG_GREATER_EQUAL; break; } type = condition | (type & (SLJIT_INT_OP | SLJIT_REWRITABLE_JUMP)); tmp_src = src1; src1 = src2; src2 = tmp_src; tmp_srcw = src1w; src1w = src2w; src2w = tmp_srcw; } if (condition <= SLJIT_C_NOT_ZERO) flags = SLJIT_SET_E; else if (condition <= SLJIT_C_LESS_EQUAL) flags = SLJIT_SET_U; else flags = SLJIT_SET_S; #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) compiler->skip_checks = 1; #endif PTR_FAIL_IF(sljit_emit_op2(compiler, SLJIT_SUB | flags | (type & SLJIT_INT_OP), SLJIT_UNUSED, 0, src1, src1w, src2, src2w)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) compiler->skip_checks = 1; #endif return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP)); }
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) { struct block_header *header; struct block_header *next_header; struct free_block *free_block; sljit_uw chunk_size; allocator_grab_lock(); if (size < sizeof(struct free_block)) size = sizeof(struct free_block); size = ALIGN_SIZE(size); free_block = free_blocks; while (free_block) { if (free_block->size >= size) { chunk_size = free_block->size; if (chunk_size > size + 64) { /* We just cut a block from the end of the free block. */ chunk_size -= size; free_block->size = chunk_size; header = AS_BLOCK_HEADER(free_block, chunk_size); header->prev_size = chunk_size; AS_BLOCK_HEADER(header, size)->prev_size = size; } else { sljit_remove_free_block(free_block); header = (struct block_header*)free_block; size = chunk_size; } allocated_size += size; header->size = size; allocator_release_lock(); return MEM_START(header); } free_block = free_block->next; } chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK; header = (struct block_header*)alloc_chunk(chunk_size); PTR_FAIL_IF(!header); chunk_size -= sizeof(struct block_header); total_size += chunk_size; header->prev_size = 0; if (chunk_size > size + 64) { /* Cut the allocated space into a free and a used block. */ allocated_size += size; header->size = size; chunk_size -= size; free_block = AS_FREE_BLOCK(header, size); free_block->header.prev_size = size; sljit_insert_free_block(free_block, chunk_size); next_header = AS_BLOCK_HEADER(free_block, chunk_size); } else { /* All space belongs to this allocation. */ allocated_size += chunk_size; header->size = chunk_size; next_header = AS_BLOCK_HEADER(header, chunk_size); } next_header->size = 1; next_header->prev_size = chunk_size; allocator_release_lock(); return MEM_START(header); }
/* Size contains the flags as well. */ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size, /* The register or immediate operand. */ sljit_si a, sljit_sw imma, /* The general operand (not immediate). */ sljit_si b, sljit_sw immb) { sljit_ub *inst; sljit_ub *buf_ptr; sljit_si flags = size & ~0xf; sljit_si inst_size; /* Both cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS)); /* Size flags not allowed for typed instructions. */ SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0); /* Both size flags cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG)); /* SSE2 and immediate is not possible. */ SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2)); SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3) && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66) && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66)); size &= 0xf; inst_size = size; if (flags & (EX86_PREF_F2 | EX86_PREF_F3)) inst_size++; if (flags & EX86_PREF_66) inst_size++; /* Calculate size of b. */ inst_size += 1; /* mod r/m byte. */ if (b & SLJIT_MEM) { if ((b & REG_MASK) == SLJIT_UNUSED) inst_size += sizeof(sljit_sw); else if (immb != 0 && !(b & OFFS_REG_MASK)) { /* Immediate operand. */ if (immb <= 127 && immb >= -128) inst_size += sizeof(sljit_sb); else inst_size += sizeof(sljit_sw); } if ((b & REG_MASK) == SLJIT_SP && !(b & OFFS_REG_MASK)) b |= TO_OFFS_REG(SLJIT_SP); if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) inst_size += 1; /* SIB byte. */ } /* Calculate size of a. */ if (a & SLJIT_IMM) { if (flags & EX86_BIN_INS) { if (imma <= 127 && imma >= -128) { inst_size += 1; flags |= EX86_BYTE_ARG; } else inst_size += 4; } else if (flags & EX86_SHIFT_INS) { imma &= 0x1f; if (imma != 1) { inst_size ++; flags |= EX86_BYTE_ARG; } } else if (flags & EX86_BYTE_ARG) inst_size++; else if (flags & EX86_HALF_ARG) inst_size += sizeof(short); else inst_size += sizeof(sljit_sw); } else SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG); inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size); PTR_FAIL_IF(!inst); /* Encoding the byte. */ INC_SIZE(inst_size); if (flags & EX86_PREF_F2) *inst++ = 0xf2; if (flags & EX86_PREF_F3) *inst++ = 0xf3; if (flags & EX86_PREF_66) *inst++ = 0x66; buf_ptr = inst + size; /* Encode mod/rm byte. */ if (!(flags & EX86_SHIFT_INS)) { if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM)) *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81; if ((a & SLJIT_IMM) || (a == 0)) *buf_ptr = 0; else if (!(flags & EX86_SSE2_OP1)) *buf_ptr = reg_map[a] << 3; else *buf_ptr = a << 3; } else { if (a & SLJIT_IMM) { if (imma == 1) *inst = GROUP_SHIFT_1; else *inst = GROUP_SHIFT_N; } else *inst = GROUP_SHIFT_CL; *buf_ptr = 0; } if (!(b & SLJIT_MEM)) *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_map[b] : b); else if ((b & REG_MASK) != SLJIT_UNUSED) { if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) { if (immb != 0) { if (immb <= 127 && immb >= -128) *buf_ptr |= 0x40; else *buf_ptr |= 0x80; } if ((b & OFFS_REG_MASK) == SLJIT_UNUSED) *buf_ptr++ |= reg_map[b & REG_MASK]; else { *buf_ptr++ |= 0x04; *buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3); } if (immb != 0) { if (immb <= 127 && immb >= -128) *buf_ptr++ = immb; /* 8 bit displacement. */ else { *(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */ buf_ptr += sizeof(sljit_sw); } } } else { *buf_ptr++ |= 0x04; *buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3) | (immb << 6); } } else { *buf_ptr++ |= 0x05; *(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */ buf_ptr += sizeof(sljit_sw); } if (a & SLJIT_IMM) { if (flags & EX86_BYTE_ARG) *buf_ptr = imma; else if (flags & EX86_HALF_ARG) *(short*)buf_ptr = imma; else if (!(flags & EX86_SHIFT_INS)) *(sljit_sw*)buf_ptr = imma; } return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1); }