165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich/* 265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * Stack-less Just-In-Time compiler 365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * 465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. 565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * 665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * Redistribution and use in source and binary forms, with or without modification, are 765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * permitted provided that the following conditions are met: 865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * 965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * 1. Redistributions of source code must retain the above copyright notice, this list of 1065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * conditions and the following disclaimer. 1165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * 1265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * 2. Redistributions in binary form must reproduce the above copyright notice, this list 1365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * of conditions and the following disclaimer in the documentation and/or other materials 1465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * provided with the distribution. 1565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * 1665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY 1765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 1965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 2265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 2465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich */ 2665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 2765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich/* x86 64-bit arch dependent functions. */ 2865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 2965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevichstatic sljit_si emit_load_imm64(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm) 3065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich{ 3165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_ub *inst; 3265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 3365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw)); 3465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 3565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(2 + sizeof(sljit_sw)); 3665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B); 3765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOV_r_i32 + (reg_map[reg] & 0x7); 3865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_sw*)inst = imm; 3965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; 4065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich} 4165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 4265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevichstatic sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type) 4365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich{ 4465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (type < SLJIT_JUMP) { 4565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Invert type. */ 4665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = get_jump_code(type ^ 0x1) - 0x10; 4765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = 10 + 3; 4865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 4965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 5065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first); 5165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = REX_W | REX_B; 5265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = MOV_r_i32 + 1; 5365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich jump->addr = (sljit_uw)code_ptr; 5465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 5565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (jump->flags & JUMP_LABEL) 5665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich jump->flags |= PATCH_MD; 5765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else 5865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_sw*)code_ptr = jump->u.target; 5965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 6065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich code_ptr += sizeof(sljit_sw); 6165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = REX_B; 6265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = GROUP_FF; 6365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = (type >= SLJIT_FAST_CALL) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1); 6465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 6565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return code_ptr; 6665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich} 6765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 6865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevichstatic sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si type) 6965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich{ 7065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_sw delta = addr - ((sljit_sw)code_ptr + 1 + sizeof(sljit_si)); 7165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 7265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (delta <= HALFWORD_MAX && delta >= HALFWORD_MIN) { 7365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = (type == 2) ? CALL_i32 : JMP_i32; 7465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_sw*)code_ptr = delta; 7565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 7665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 7765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second); 7865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = REX_W | REX_B; 7965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = MOV_r_i32 + 1; 8065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_sw*)code_ptr = addr; 8165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich code_ptr += sizeof(sljit_sw); 8265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = REX_B; 8365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = GROUP_FF; 8465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *code_ptr++ = (type == 2) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1); 8565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 8665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 8765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return code_ptr; 8865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich} 8965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 9065de34233da93a3d65c00b8aad3ff9aad44c57deNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, 9165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds, 9265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si fscratches, sljit_si fsaveds, sljit_si local_size) 9365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich{ 9465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si i, tmp, size, saved_register_size; 9565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_ub *inst; 9665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 9765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich CHECK_ERROR(); 9865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); 9965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 10065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->options = options; 10165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->scratches = scratches; 10265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->saveds = saveds; 10365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->fscratches = fscratches; 10465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->fsaveds = fsaveds; 10565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->flags_saved = 0; 10665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#if (defined SLJIT_DEBUG && SLJIT_DEBUG) 10765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->logical_local_size = local_size; 10865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#endif 10965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 11065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Including the return address saved by the call instruction. */ 11165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); 11265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 11365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; 11465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich for (i = SLJIT_S0; i >= tmp; i--) { 11565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich size = reg_map[i] >= 8 ? 2 : 1; 11665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + size); 11765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 11865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(size); 11965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (reg_map[i] >= 8) 12065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_B; 12165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich PUSH_REG(reg_lmap[i]); 12265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 12365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 12465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { 12565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich size = reg_map[i] >= 8 ? 2 : 1; 12665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + size); 12765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 12865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(size); 12965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (reg_map[i] >= 8) 13065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_B; 13165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich PUSH_REG(reg_lmap[i]); 13265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 13365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 13465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (args > 0) { 13565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich size = args * 3; 13665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + size); 13765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 13865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 13965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(size); 14065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 14165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#ifndef _WIN64 14265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (args > 0) { 14365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W; 14465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOV_r_rm; 14565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x7 /* rdi */; 14665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 14765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (args > 1) { 14865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W | REX_R; 14965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOV_r_rm; 15065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | (reg_lmap[SLJIT_S1] << 3) | 0x6 /* rsi */; 15165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 15265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (args > 2) { 15365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W | REX_R; 15465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOV_r_rm; 15565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | (reg_lmap[SLJIT_S2] << 3) | 0x2 /* rdx */; 15665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 15765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#else 15865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (args > 0) { 15965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W; 16065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOV_r_rm; 16165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x1 /* rcx */; 16265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 16365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (args > 1) { 16465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W; 16565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOV_r_rm; 16665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | (reg_map[SLJIT_S1] << 3) | 0x2 /* rdx */; 16765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 16865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (args > 2) { 16965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W | REX_B; 17065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOV_r_rm; 17165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | (reg_map[SLJIT_S2] << 3) | 0x0 /* r8 */; 17265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 17365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#endif 17465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 17565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 17665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich local_size = ((local_size + FIXED_LOCALS_OFFSET + saved_register_size + 16 - 1) & ~(16 - 1)) - saved_register_size; 17765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->local_size = local_size; 17865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 17965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#ifdef _WIN64 18065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (local_size > 1024) { 18165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Allocate stack for the callback, which grows the stack. */ 18265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + (3 + sizeof(sljit_si))); 18365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 18465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(4 + (3 + sizeof(sljit_si))); 18565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W; 18665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = GROUP_BINARY_83; 18765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | SUB | 4; 18865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Allocated size for registers must be divisible by 8. */ 18965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_ASSERT(!(saved_register_size & 0x7)); 19065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Aligned to 16 byte. */ 19165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (saved_register_size & 0x8) { 19265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = 5 * sizeof(sljit_sw); 19365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich local_size -= 5 * sizeof(sljit_sw); 19465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } else { 19565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = 4 * sizeof(sljit_sw); 19665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich local_size -= 4 * sizeof(sljit_sw); 19765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 19865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Second instruction */ 19965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R0] < 8, temporary_reg1_is_loreg); 20065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W; 20165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOV_rm_i32; 20265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | reg_lmap[SLJIT_R0]; 20365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_si*)inst = local_size; 20465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) 20565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->skip_checks = 1; 20665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#endif 20765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack))); 20865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 20965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#endif 21065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 21165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_ASSERT(local_size > 0); 21265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (local_size <= 127) { 21365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 4); 21465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 21565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(4); 21665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W; 21765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = GROUP_BINARY_83; 21865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | SUB | 4; 21965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = local_size; 22065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 22165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 22265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 7); 22365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 22465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(7); 22565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W; 22665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = GROUP_BINARY_81; 22765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | SUB | 4; 22865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_si*)inst = local_size; 22965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst += sizeof(sljit_si); 23065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 23165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 23265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#ifdef _WIN64 23365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Save xmm6 register: movaps [rsp + 0x20], xmm6 */ 23465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (fscratches >= 6 || fsaveds >= 1) { 23565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 5); 23665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 23765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(5); 23865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = GROUP_0F; 23965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_si*)inst = 0x20247429; 24065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 24165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#endif 24265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 24365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; 24465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich} 24565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 24665de34233da93a3d65c00b8aad3ff9aad44c57deNick KralevichSLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, 24765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds, 24865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si fscratches, sljit_si fsaveds, sljit_si local_size) 24965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich{ 25065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si saved_register_size; 25165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 25265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich CHECK_ERROR_VOID(); 25365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); 25465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 25565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->options = options; 25665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->scratches = scratches; 25765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->saveds = saveds; 25865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->fscratches = fscratches; 25965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->fsaveds = fsaveds; 26065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#if (defined SLJIT_DEBUG && SLJIT_DEBUG) 26165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->logical_local_size = local_size; 26265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#endif 26365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 26465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Including the return address saved by the call instruction. */ 26565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); 26665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->local_size = ((local_size + FIXED_LOCALS_OFFSET + saved_register_size + 16 - 1) & ~(16 - 1)) - saved_register_size; 26765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich} 26865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 26965de34233da93a3d65c00b8aad3ff9aad44c57deNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw) 27065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich{ 27165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si i, tmp, size; 27265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_ub *inst; 27365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 27465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich CHECK_ERROR(); 27565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich check_sljit_emit_return(compiler, op, src, srcw); 27665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 27765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->flags_saved = 0; 27865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); 27965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 28065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#ifdef _WIN64 28165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Restore xmm6 register: movaps xmm6, [rsp + 0x20] */ 28265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (compiler->fscratches >= 6 || compiler->fsaveds >= 1) { 28365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 5); 28465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 28565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(5); 28665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = GROUP_0F; 28765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_si*)inst = 0x20247428; 28865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 28965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#endif 29065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 29165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_ASSERT(compiler->local_size > 0); 29265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (compiler->local_size <= 127) { 29365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 4); 29465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 29565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(4); 29665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W; 29765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = GROUP_BINARY_83; 29865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | ADD | 4; 29965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst = compiler->local_size; 30065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 30165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 30265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 7); 30365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 30465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(7); 30565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W; 30665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = GROUP_BINARY_81; 30765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | ADD | 4; 30865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_si*)inst = compiler->local_size; 30965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 31065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 31165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich tmp = compiler->scratches; 31265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) { 31365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich size = reg_map[i] >= 8 ? 2 : 1; 31465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + size); 31565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 31665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(size); 31765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (reg_map[i] >= 8) 31865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_B; 31965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich POP_REG(reg_lmap[i]); 32065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 32165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 32265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG; 32365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich for (i = tmp; i <= SLJIT_S0; i++) { 32465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich size = reg_map[i] >= 8 ? 2 : 1; 32565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + size); 32665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 32765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(size); 32865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (reg_map[i] >= 8) 32965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_B; 33065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich POP_REG(reg_lmap[i]); 33165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 33265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 33365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 1); 33465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 33565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(1); 33665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich RET(); 33765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; 33865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich} 33965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 34065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich/* --------------------------------------------------------------------- */ 34165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich/* Operators */ 34265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich/* --------------------------------------------------------------------- */ 34365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 34465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevichstatic sljit_si emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_sw imm) 34565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich{ 34665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_ub *inst; 34765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si length = 1 + (rex ? 1 : 0) + sizeof(sljit_si); 34865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 34965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + length); 35065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 35165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(length); 35265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (rex) 35365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = rex; 35465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = opcode; 35565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_si*)inst = imm; 35665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; 35765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich} 35865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 35965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevichstatic sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size, 36065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* The register or immediate operand. */ 36165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si a, sljit_sw imma, 36265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* The general operand (not immediate). */ 36365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si b, sljit_sw immb) 36465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich{ 36565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_ub *inst; 36665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_ub *buf_ptr; 36765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_ub rex = 0; 36865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si flags = size & ~0xf; 36965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si inst_size; 37065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 37165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* The immediate operand must be 32 bit. */ 37265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma)); 37365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Both cannot be switched on. */ 37465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS)); 37565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Size flags not allowed for typed instructions. */ 37665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0); 37765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Both size flags cannot be switched on. */ 37865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG)); 37965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* SSE2 and immediate is not possible. */ 38065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2)); 38165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3) 38265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66) 38365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66)); 38465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 38565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich size &= 0xf; 38665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size = size; 38765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 38865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (!compiler->mode32 && !(flags & EX86_NO_REXW)) 38965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich rex |= REX_W; 39065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else if (flags & EX86_REX) 39165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich rex |= REX; 39265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 39365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (flags & (EX86_PREF_F2 | EX86_PREF_F3)) 39465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size++; 39565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (flags & EX86_PREF_66) 39665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size++; 39765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 39865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Calculate size of b. */ 39965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size += 1; /* mod r/m byte. */ 40065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (b & SLJIT_MEM) { 40165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (!(b & OFFS_REG_MASK)) { 40265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (NOT_HALFWORD(immb)) { 40365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (emit_load_imm64(compiler, TMP_REG3, immb)) 40465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return NULL; 40565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich immb = 0; 40665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (b & REG_MASK) 40765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich b |= TO_OFFS_REG(TMP_REG3); 40865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else 40965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich b |= TMP_REG3; 41065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 41165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else if (reg_lmap[b & REG_MASK] == 4) 41265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich b |= TO_OFFS_REG(SLJIT_SP); 41365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 41465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 41565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if ((b & REG_MASK) == SLJIT_UNUSED) 41665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size += 1 + sizeof(sljit_si); /* SIB byte required to avoid RIP based addressing. */ 41765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 41865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (reg_map[b & REG_MASK] >= 8) 41965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich rex |= REX_B; 42065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 42165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) { 42265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Immediate operand. */ 42365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (immb <= 127 && immb >= -128) 42465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size += sizeof(sljit_sb); 42565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else 42665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size += sizeof(sljit_si); 42765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 42865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else if (reg_lmap[b & REG_MASK] == 5) 42965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size += sizeof(sljit_sb); 43065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 43165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) { 43265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size += 1; /* SIB byte. */ 43365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (reg_map[OFFS_REG(b)] >= 8) 43465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich rex |= REX_X; 43565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 43665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 43765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 43865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else if (!(flags & EX86_SSE2_OP2) && reg_map[b] >= 8) 43965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich rex |= REX_B; 44065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 44165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (a & SLJIT_IMM) { 44265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (flags & EX86_BIN_INS) { 44365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (imma <= 127 && imma >= -128) { 44465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size += 1; 44565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich flags |= EX86_BYTE_ARG; 44665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } else 44765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size += 4; 44865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 44965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else if (flags & EX86_SHIFT_INS) { 45065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich imma &= compiler->mode32 ? 0x1f : 0x3f; 45165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (imma != 1) { 45265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size ++; 45365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich flags |= EX86_BYTE_ARG; 45465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 45565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } else if (flags & EX86_BYTE_ARG) 45665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size++; 45765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else if (flags & EX86_HALF_ARG) 45865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size += sizeof(short); 45965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else 46065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size += sizeof(sljit_si); 46165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 46265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 46365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG); 46465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */ 46565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (!(flags & EX86_SSE2_OP1) && reg_map[a] >= 8) 46665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich rex |= REX_R; 46765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 46865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 46965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (rex) 47065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst_size++; 47165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 47265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size); 47365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich PTR_FAIL_IF(!inst); 47465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 47565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Encoding the byte. */ 47665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(inst_size); 47765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (flags & EX86_PREF_F2) 47865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = 0xf2; 47965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (flags & EX86_PREF_F3) 48065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = 0xf3; 48165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (flags & EX86_PREF_66) 48265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = 0x66; 48365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (rex) 48465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = rex; 48565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich buf_ptr = inst + size; 48665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 48765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* Encode mod/rm byte. */ 48865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (!(flags & EX86_SHIFT_INS)) { 48965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM)) 49065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81; 49165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 49265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if ((a & SLJIT_IMM) || (a == 0)) 49365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr = 0; 49465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else if (!(flags & EX86_SSE2_OP1)) 49565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr = reg_lmap[a] << 3; 49665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else 49765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr = a << 3; 49865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 49965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 50065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (a & SLJIT_IMM) { 50165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (imma == 1) 50265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst = GROUP_SHIFT_1; 50365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else 50465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst = GROUP_SHIFT_N; 50565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } else 50665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst = GROUP_SHIFT_CL; 50765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr = 0; 50865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 50965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 51065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (!(b & SLJIT_MEM)) 51165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_lmap[b] : b); 51265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else if ((b & REG_MASK) != SLJIT_UNUSED) { 51365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) { 51465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (immb != 0 || reg_lmap[b & REG_MASK] == 5) { 51565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (immb <= 127 && immb >= -128) 51665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr |= 0x40; 51765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else 51865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr |= 0x80; 51965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 52065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 52165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if ((b & OFFS_REG_MASK) == SLJIT_UNUSED) 52265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr++ |= reg_lmap[b & REG_MASK]; 52365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 52465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr++ |= 0x04; 52565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3); 52665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 52765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 52865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (immb != 0 || reg_lmap[b & REG_MASK] == 5) { 52965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (immb <= 127 && immb >= -128) 53065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr++ = immb; /* 8 bit displacement. */ 53165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 53265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */ 53365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich buf_ptr += sizeof(sljit_si); 53465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 53565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 53665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 53765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 53865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (reg_lmap[b & REG_MASK] == 5) 53965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr |= 0x40; 54065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr++ |= 0x04; 54165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6); 54265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (reg_lmap[b & REG_MASK] == 5) 54365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr++ = 0; 54465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 54565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 54665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 54765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr++ |= 0x04; 54865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr++ = 0x25; 54965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */ 55065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich buf_ptr += sizeof(sljit_si); 55165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 55265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 55365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (a & SLJIT_IMM) { 55465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (flags & EX86_BYTE_ARG) 55565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *buf_ptr = imma; 55665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else if (flags & EX86_HALF_ARG) 55765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(short*)buf_ptr = imma; 55865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else if (!(flags & EX86_SHIFT_INS)) 55965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_si*)buf_ptr = imma; 56065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 56165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 56265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1); 56365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich} 56465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 56565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich/* --------------------------------------------------------------------- */ 56665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich/* Call / return instructions */ 56765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich/* --------------------------------------------------------------------- */ 56865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 56965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevichstatic SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type) 57065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich{ 57165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_ub *inst; 57265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 57365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#ifndef _WIN64 57465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers); 57565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 57665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6)); 57765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 57865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE((type < SLJIT_CALL3) ? 3 : 6); 57965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (type >= SLJIT_CALL3) { 58065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W; 58165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOV_r_rm; 58265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | (0x2 /* rdx */ << 3) | reg_lmap[SLJIT_R2]; 58365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 58465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W; 58565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOV_r_rm; 58665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | (0x7 /* rdi */ << 3) | reg_lmap[SLJIT_R0]; 58765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#else 58865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers); 58965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 59065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6)); 59165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 59265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE((type < SLJIT_CALL3) ? 3 : 6); 59365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (type >= SLJIT_CALL3) { 59465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W | REX_R; 59565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOV_r_rm; 59665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | (0x0 /* r8 */ << 3) | reg_lmap[SLJIT_R2]; 59765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 59865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_W; 59965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOV_r_rm; 60065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOD_REG | (0x1 /* rcx */ << 3) | reg_lmap[SLJIT_R0]; 60165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich#endif 60265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; 60365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich} 60465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 60565de34233da93a3d65c00b8aad3ff9aad44c57deNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw) 60665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich{ 60765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_ub *inst; 60865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 60965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich CHECK_ERROR(); 61065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich check_sljit_emit_fast_enter(compiler, dst, dstw); 61165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich ADJUST_LOCAL_OFFSET(dst, dstw); 61265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 61365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* For UNUSED dst. Uncommon, but possible. */ 61465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (dst == SLJIT_UNUSED) 61565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich dst = TMP_REG1; 61665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 61765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (FAST_IS_REG(dst)) { 61865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (reg_map[dst] < 8) { 61965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 1); 62065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 62165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(1); 62265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich POP_REG(reg_lmap[dst]); 62365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; 62465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 62565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 62665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 2); 62765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 62865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(2); 62965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_B; 63065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich POP_REG(reg_lmap[dst]); 63165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; 63265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 63365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 63465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* REX_W is not necessary (src is not immediate). */ 63565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->mode32 = 1; 63665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); 63765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 63865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = POP_rm; 63965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; 64065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich} 64165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 64265de34233da93a3d65c00b8aad3ff9aad44c57deNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw) 64365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich{ 64465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_ub *inst; 64565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 64665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich CHECK_ERROR(); 64765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich check_sljit_emit_fast_return(compiler, src, srcw); 64865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich ADJUST_LOCAL_OFFSET(src, srcw); 64965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 65065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) { 65165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw)); 65265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich src = TMP_REG1; 65365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 65465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 65565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (FAST_IS_REG(src)) { 65665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (reg_map[src] < 8) { 65765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1); 65865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 65965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 66065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(1 + 1); 66165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich PUSH_REG(reg_lmap[src]); 66265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 66365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 66465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1); 66565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 66665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 66765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(2 + 1); 66865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = REX_B; 66965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich PUSH_REG(reg_lmap[src]); 67065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 67165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 67265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else if (src & SLJIT_MEM) { 67365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* REX_W is not necessary (src is not immediate). */ 67465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->mode32 = 1; 67565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); 67665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 67765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = GROUP_FF; 67865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst |= PUSH_rm; 67965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 68065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 1); 68165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 68265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(1); 68365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 68465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 68565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich SLJIT_ASSERT(IS_HALFWORD(srcw)); 68665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich /* SLJIT_IMM. */ 68765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1); 68865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 68965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 69065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich INC_SIZE(5 + 1); 69165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = PUSH_i32; 69265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *(sljit_si*)inst = srcw; 69365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst += sizeof(sljit_si); 69465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 69565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 69665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich RET(); 69765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; 69865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich} 69965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 70065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 70165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich/* --------------------------------------------------------------------- */ 70265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich/* Extend input */ 70365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich/* --------------------------------------------------------------------- */ 70465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 70565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevichstatic sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign, 70665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si dst, sljit_sw dstw, 70765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si src, sljit_sw srcw) 70865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich{ 70965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_ub* inst; 71065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich sljit_si dst_r; 71165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 71265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->mode32 = 0; 71365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 71465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM)) 71565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; /* Empty instruction. */ 71665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 71765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (src & SLJIT_IMM) { 71865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (FAST_IS_REG(dst)) { 71965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (sign || ((sljit_uw)srcw <= 0x7fffffff)) { 72065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw); 72165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 72265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst = MOV_rm_i32; 72365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; 72465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 72565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return emit_load_imm64(compiler, dst, srcw); 72665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 72765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->mode32 = 1; 72865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw); 72965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 73065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst = MOV_rm_i32; 73165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->mode32 = 0; 73265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; 73365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 73465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 73565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; 73665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 73765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if ((dst & SLJIT_MEM) && FAST_IS_REG(src)) 73865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich dst_r = src; 73965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich else { 74065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (sign) { 74165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw); 74265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 74365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst++ = MOVSXD_r_rm; 74465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } else { 74565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->mode32 = 1; 74665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw)); 74765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->mode32 = 0; 74865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 74965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 75065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 75165de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich if (dst & SLJIT_MEM) { 75265de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->mode32 = 1; 75365de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw); 75465de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich FAIL_IF(!inst); 75565de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich *inst = MOV_rm_r; 75665de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich compiler->mode32 = 0; 75765de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich } 75865de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich 75965de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich return SLJIT_SUCCESS; 76065de34233da93a3d65c00b8aad3ff9aad44c57deNick Kralevich} 761