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);
}
Exemple #2
0
/* 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
	}
Exemple #3
0
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));
}
Exemple #4
0
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);
}
Exemple #5
0
/* 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);
}