1f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* 2f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * Stack-less Just-In-Time compiler 3f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * 4f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. 5f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * 6f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * Redistribution and use in source and binary forms, with or without modification, are 7f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * permitted provided that the following conditions are met: 8f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * 9f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * 1. Redistributions of source code must retain the above copyright notice, this list of 10f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * conditions and the following disclaimer. 11f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * 12f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * 2. Redistributions in binary form must reproduce the above copyright notice, this list 13f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * of conditions and the following disclaimer in the documentation and/or other materials 14f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * provided with the distribution. 15f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * 16f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY 17f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 19f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 22f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich */ 26f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 27f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void) 28f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 29f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return "ARM-64" SLJIT_CPUINFO; 30f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 31f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 32f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* Length of an instruction word */ 33f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichtypedef sljit_ui sljit_ins; 34f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 35f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define TMP_ZERO 0 36f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 37f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) 38f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) 39f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) 40f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define TMP_REG4 (SLJIT_NUMBER_OF_REGISTERS + 5) 41f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define TMP_LR (SLJIT_NUMBER_OF_REGISTERS + 6) 42f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define TMP_SP (SLJIT_NUMBER_OF_REGISTERS + 7) 43f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 44f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define TMP_FREG1 (0) 45f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) 46f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 47f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = { 48f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 31, 0, 1, 2, 3, 4, 5, 6, 7, 13, 14, 15, 16, 17, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 29, 9, 10, 11, 12, 30, 31 49f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich}; 50f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 51f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define W_OP (1 << 31) 52f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define RD(rd) (reg_map[rd]) 53f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define RT(rt) (reg_map[rt]) 54f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define RN(rn) (reg_map[rn] << 5) 55f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define RT2(rt2) (reg_map[rt2] << 10) 56f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define RM(rm) (reg_map[rm] << 16) 57f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define VD(vd) (vd) 58f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define VT(vt) (vt) 59f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define VN(vn) ((vn) << 5) 60f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define VM(vm) ((vm) << 16) 61f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 62f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 63f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* Instrucion forms */ 64f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 65f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 66f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define ADC 0x9a000000 67f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define ADD 0x8b000000 68f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define ADDI 0x91000000 69f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define AND 0x8a000000 70f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define ANDI 0x92000000 71f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define ASRV 0x9ac02800 72f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define B 0x14000000 73f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define B_CC 0x54000000 74f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define BL 0x94000000 75f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define BLR 0xd63f0000 76f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define BR 0xd61f0000 77f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define BRK 0xd4200000 78f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define CBZ 0xb4000000 79f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define CLZ 0xdac01000 80f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define CSINC 0x9a800400 81f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define EOR 0xca000000 82f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define EORI 0xd2000000 83f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define FABS 0x1e60c000 84f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define FADD 0x1e602800 85f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define FCMP 0x1e602000 86f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define FCVT 0x1e224000 87f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define FCVTZS 0x9e780000 88f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define FDIV 0x1e601800 89f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define FMOV 0x1e604000 90f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define FMUL 0x1e600800 91f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define FNEG 0x1e614000 92f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define FSUB 0x1e603800 93f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define LDRI 0xf9400000 94f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define LDP 0xa9400000 95f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define LDP_PST 0xa8c00000 96f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define LSLV 0x9ac02000 97f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define LSRV 0x9ac02400 98f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define MADD 0x9b000000 99f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define MOVK 0xf2800000 100f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define MOVN 0x92800000 101f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define MOVZ 0xd2800000 102f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define NOP 0xd503201f 103f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define ORN 0xaa200000 104f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define ORR 0xaa000000 105f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define ORRI 0xb2000000 106f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define RET 0xd65f0000 107f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SBC 0xda000000 108f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SBFM 0x93000000 109f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SCVTF 0x9e620000 110f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SDIV 0x9ac00c00 111f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SMADDL 0x9b200000 112f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SMULH 0x9b403c00 113f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define STP 0xa9000000 114f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define STP_PRE 0xa9800000 115f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define STRI 0xf9000000 116f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define STR_FI 0x3d000000 117f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define STR_FR 0x3c206800 118f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define STUR_FI 0x3c000000 119f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SUB 0xcb000000 120f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SUBI 0xd1000000 121f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SUBS 0xeb000000 122f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define UBFM 0xd3000000 123f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define UDIV 0x9ac00800 124f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define UMULH 0x9bc03c00 125f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 126f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* dest_reg is the absolute name of the register 127f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich Useful for reordering instructions in the delay slot. */ 128f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins) 129f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 130f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); 131f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(!ptr); 132f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich *ptr = ins; 133f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->size++; 134f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 135f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 136f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 137f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_INLINE sljit_si emit_imm64_const(struct sljit_compiler *compiler, sljit_si dst, sljit_uw imm) 138f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 139f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((imm & 0xffff) << 5))); 140f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((imm >> 16) & 0xffff) << 5) | (1 << 21))); 141f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((imm >> 32) & 0xffff) << 5) | (2 << 21))); 142f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, MOVK | RD(dst) | ((imm >> 48) << 5) | (3 << 21)); 143f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 144f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 145f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_INLINE void modify_imm64_const(sljit_ins* inst, sljit_uw new_imm) 146f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 147f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst = inst[0] & 0x1f; 148f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ && (inst[1] & 0xffe00000) == (MOVK | (1 << 21))); 149f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inst[0] = MOVZ | dst | ((new_imm & 0xffff) << 5); 150f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inst[1] = MOVK | dst | (((new_imm >> 16) & 0xffff) << 5) | (1 << 21); 151f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inst[2] = MOVK | dst | (((new_imm >> 32) & 0xffff) << 5) | (2 << 21); 152f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inst[3] = MOVK | dst | ((new_imm >> 48) << 5) | (3 << 21); 153f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 154f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 155f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code) 156f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 157f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_sw diff; 158f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_uw target_addr; 159f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 160f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (jump->flags & SLJIT_REWRITABLE_JUMP) { 161f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->flags |= PATCH_ABS64; 162f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0; 163f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 164f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 165f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (jump->flags & JUMP_ADDR) 166f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich target_addr = jump->u.target; 167f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 168f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(jump->flags & JUMP_LABEL); 169f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich target_addr = (sljit_uw)(code + jump->u.label->size); 170f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 171f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich diff = (sljit_sw)target_addr - (sljit_sw)(code_ptr + 4); 172f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 173f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (jump->flags & IS_COND) { 174f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich diff += sizeof(sljit_ins); 175f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (diff <= 0xfffff && diff >= -0x100000) { 176f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich code_ptr[-5] ^= (jump->flags & IS_CBZ) ? (0x1 << 24) : 0x1; 177f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->addr -= sizeof(sljit_ins); 178f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->flags |= PATCH_COND; 179f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 5; 180f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 181f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich diff -= sizeof(sljit_ins); 182f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 183f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 184f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (diff <= 0x7ffffff && diff >= -0x8000000) { 185f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->flags |= PATCH_B; 186f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 4; 187f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 188f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 189f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (target_addr <= 0xffffffffl) { 190f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (jump->flags & IS_COND) 191f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich code_ptr[-5] -= (2 << 5); 192f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich code_ptr[-2] = code_ptr[0]; 193f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 2; 194f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 195f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (target_addr <= 0xffffffffffffl) { 196f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (jump->flags & IS_COND) 197f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich code_ptr[-5] -= (1 << 5); 198f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->flags |= PATCH_ABS48; 199f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich code_ptr[-1] = code_ptr[0]; 200f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 1; 201f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 202f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 203f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->flags |= PATCH_ABS64; 204f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0; 205f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 206f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 207f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) 208f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 209f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich struct sljit_memory_fragment *buf; 210f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins *code; 211f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins *code_ptr; 212f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins *buf_ptr; 213f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins *buf_end; 214f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_uw word_count; 215f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_uw addr; 216f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst; 217f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 218f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich struct sljit_label *label; 219f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich struct sljit_jump *jump; 220f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich struct sljit_const *const_; 221f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 222f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR_PTR(); 223f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_generate_code(compiler); 224f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich reverse_buf(compiler); 225f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 226f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); 227f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_WITH_EXEC_IF(code); 228f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich buf = compiler->buf; 229f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 230f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich code_ptr = code; 231f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich word_count = 0; 232f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich label = compiler->labels; 233f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump = compiler->jumps; 234f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich const_ = compiler->consts; 235f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 236f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich do { 237f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich buf_ptr = (sljit_ins*)buf->memory; 238f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich buf_end = buf_ptr + (buf->used_size >> 2); 239f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich do { 240f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich *code_ptr = *buf_ptr++; 241f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* These structures are ordered by their address. */ 242f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!label || label->size >= word_count); 243f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!jump || jump->addr >= word_count); 244f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!const_ || const_->addr >= word_count); 245f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (label && label->size == word_count) { 246f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich label->addr = (sljit_uw)code_ptr; 247f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich label->size = code_ptr - code; 248f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich label = label->next; 249f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 250f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (jump && jump->addr == word_count) { 251f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->addr = (sljit_uw)(code_ptr - 4); 252f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich code_ptr -= detect_jump_type(jump, code_ptr, code); 253f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump = jump->next; 254f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 255f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (const_ && const_->addr == word_count) { 256f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich const_->addr = (sljit_uw)code_ptr; 257f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich const_ = const_->next; 258f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 259f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich code_ptr ++; 260f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich word_count ++; 261f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } while (buf_ptr < buf_end); 262f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 263f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich buf = buf->next; 264f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } while (buf); 265f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 266f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (label && label->size == word_count) { 267f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich label->addr = (sljit_uw)code_ptr; 268f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich label->size = code_ptr - code; 269f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich label = label->next; 270f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 271f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 272f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!label); 273f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!jump); 274f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!const_); 275f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); 276f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 277f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump = compiler->jumps; 278f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich while (jump) { 279f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich do { 280f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; 281f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich buf_ptr = (sljit_ins*)jump->addr; 282f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (jump->flags & PATCH_B) { 283f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich addr = (sljit_sw)(addr - jump->addr) >> 2; 284f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT((sljit_sw)addr <= 0x1ffffff && (sljit_sw)addr >= -0x2000000); 285f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (addr & 0x3ffffff); 286f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (jump->flags & IS_COND) 287f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich buf_ptr[-1] -= (4 << 5); 288f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 289f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 290f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (jump->flags & PATCH_COND) { 291f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich addr = (sljit_sw)(addr - jump->addr) >> 2; 292f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT((sljit_sw)addr <= 0x3ffff && (sljit_sw)addr >= -0x40000); 293f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich buf_ptr[0] = (buf_ptr[0] & ~0xffffe0) | ((addr & 0x7ffff) << 5); 294f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 295f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 296f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 297f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT((jump->flags & (PATCH_ABS48 | PATCH_ABS64)) || addr <= 0xffffffffl); 298f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT((jump->flags & PATCH_ABS64) || addr <= 0xffffffffffffl); 299f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 300f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich dst = buf_ptr[0] & 0x1f; 301f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich buf_ptr[0] = MOVZ | dst | ((addr & 0xffff) << 5); 302f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich buf_ptr[1] = MOVK | dst | (((addr >> 16) & 0xffff) << 5) | (1 << 21); 303f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (jump->flags & (PATCH_ABS48 | PATCH_ABS64)) 304f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich buf_ptr[2] = MOVK | dst | (((addr >> 32) & 0xffff) << 5) | (2 << 21); 305f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (jump->flags & PATCH_ABS64) 306f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich buf_ptr[3] = MOVK | dst | (((addr >> 48) & 0xffff) << 5) | (3 << 21); 307f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } while (0); 308f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump = jump->next; 309f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 310f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 311f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->error = SLJIT_ERR_COMPILED; 312f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins); 313f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_CACHE_FLUSH(code, code_ptr); 314f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return code; 315f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 316f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 317f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 318f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* Core code generator functions. */ 319f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 320f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 321f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define COUNT_TRAILING_ZERO(value, result) \ 322f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich result = 0; \ 323f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(value & 0xffffffff)) { \ 324f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich result += 32; \ 325f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich value >>= 32; \ 326f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } \ 327f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(value & 0xffff)) { \ 328f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich result += 16; \ 329f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich value >>= 16; \ 330f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } \ 331f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(value & 0xff)) { \ 332f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich result += 8; \ 333f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich value >>= 8; \ 334f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } \ 335f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(value & 0xf)) { \ 336f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich result += 4; \ 337f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich value >>= 4; \ 338f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } \ 339f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(value & 0x3)) { \ 340f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich result += 2; \ 341f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich value >>= 2; \ 342f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } \ 343f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(value & 0x1)) { \ 344f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich result += 1; \ 345f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich value >>= 1; \ 346f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 347f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 348f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define LOGICAL_IMM_CHECK 0x100 349f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 350f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic sljit_ins logical_imm(sljit_sw imm, sljit_si len) 351f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 352f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si negated, ones, right; 353f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_uw mask, uimm; 354f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins ins; 355f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 356f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (len & LOGICAL_IMM_CHECK) { 357f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich len &= ~LOGICAL_IMM_CHECK; 358f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (len == 32 && (imm == 0 || imm == -1)) 359f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0; 360f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (len == 16 && ((sljit_si)imm == 0 || (sljit_si)imm == -1)) 361f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0; 362f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 363f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 364f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT((len == 32 && imm != 0 && imm != -1) 365f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich || (len == 16 && (sljit_si)imm != 0 && (sljit_si)imm != -1)); 366f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich uimm = (sljit_uw)imm; 367f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich while (1) { 368f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (len <= 0) { 369f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT_STOP(); 370f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0; 371f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 372f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich mask = ((sljit_uw)1 << len) - 1; 373f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((uimm & mask) != ((uimm >> len) & mask)) 374f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 375f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich len >>= 1; 376f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 377f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 378f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich len <<= 1; 379f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 380f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich negated = 0; 381f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (uimm & 0x1) { 382f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich negated = 1; 383f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich uimm = ~uimm; 384f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 385f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 386f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (len < 64) 387f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich uimm &= ((sljit_uw)1 << len) - 1; 388f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 389f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* Unsigned right shift. */ 390f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich COUNT_TRAILING_ZERO(uimm, right); 391f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 392f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* Signed shift. We also know that the highest bit is set. */ 393f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich imm = (sljit_sw)~uimm; 394f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(imm < 0); 395f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 396f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich COUNT_TRAILING_ZERO(imm, ones); 397f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 398f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (~imm) 399f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0; 400f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 401f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (len == 64) 402f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ins = 1 << 22; 403f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 404f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ins = (0x3f - ((len << 1) - 1)) << 10; 405f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 406f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (negated) 407f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return ins | ((len - ones - 1) << 10) | ((len - ones - right) << 16); 408f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 409f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return ins | ((ones - 1) << 10) | ((len - right) << 16); 410f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 411f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 412f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#undef COUNT_TRAILING_ZERO 413f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 414f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sljit_sw simm) 415f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 416f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_uw imm = (sljit_uw)simm; 417f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si i, zeros, ones, first; 418f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins bitmask; 419f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 420f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (imm <= 0xffff) 421f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, MOVZ | RD(dst) | (imm << 5)); 422f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 423f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (simm >= -0x10000 && simm < 0) 424f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff) << 5)); 425f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 426f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (imm <= 0xffffffffl) { 427f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((imm & 0xffff0000l) == 0xffff0000) 428f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | ((~imm & 0xffff) << 5)); 429f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((imm & 0xffff) == 0xffff) 430f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | ((~imm & 0xffff0000l) >> (16 - 5)) | (1 << 21)); 431f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich bitmask = logical_imm(simm, 16); 432f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (bitmask != 0) 433f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (ORRI ^ W_OP) | RD(dst) | RN(TMP_ZERO) | bitmask); 434f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 435f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 436f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich bitmask = logical_imm(simm, 32); 437f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (bitmask != 0) 438f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, ORRI | RD(dst) | RN(TMP_ZERO) | bitmask); 439f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 440f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 441f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (imm <= 0xffffffffl) { 442f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((imm & 0xffff) << 5))); 443f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, MOVK | RD(dst) | ((imm & 0xffff0000l) >> (16 - 5)) | (1 << 21)); 444f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 445f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 446f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (simm >= -0x100000000l && simm < 0) { 447f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff) << 5))); 448f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, MOVK | RD(dst) | ((imm & 0xffff0000l) >> (16 - 5)) | (1 << 21)); 449f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 450f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 451f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* A large amount of number can be constructed from ORR and MOVx, 452f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich but computing them is costly. We don't */ 453f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 454f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich zeros = 0; 455f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ones = 0; 456f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich for (i = 4; i > 0; i--) { 457f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((simm & 0xffff) == 0) 458f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich zeros++; 459f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((simm & 0xffff) == 0xffff) 460f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ones++; 461f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich simm >>= 16; 462f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 463f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 464f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich simm = (sljit_sw)imm; 465f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich first = 1; 466f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (ones > zeros) { 467f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich simm = ~simm; 468f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich for (i = 0; i < 4; i++) { 469f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(simm & 0xffff)) { 470f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich simm >>= 16; 471f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich continue; 472f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 473f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (first) { 474f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich first = 0; 475f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, MOVN | RD(dst) | ((simm & 0xffff) << 5) | (i << 21))); 476f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 477f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 478f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, MOVK | RD(dst) | ((~simm & 0xffff) << 5) | (i << 21))); 479f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich simm >>= 16; 480f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 481f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 482f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 483f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 484f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich for (i = 0; i < 4; i++) { 485f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(simm & 0xffff)) { 486f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich simm >>= 16; 487f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich continue; 488f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 489f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (first) { 490f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich first = 0; 491f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((simm & 0xffff) << 5) | (i << 21))); 492f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 493f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 494f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, MOVK | RD(dst) | ((simm & 0xffff) << 5) | (i << 21))); 495f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich simm >>= 16; 496f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 497f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 498f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 499f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 500f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define ARG1_IMM 0x0010000 501f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define ARG2_IMM 0x0020000 502f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define INT_OP 0x0040000 503f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SET_FLAGS 0x0080000 504f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define UNUSED_RETURN 0x0100000 505f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SLOW_DEST 0x0200000 506f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SLOW_SRC1 0x0400000 507f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SLOW_SRC2 0x0800000 508f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 509f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define CHECK_FLAGS(flag_bits) \ 510f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (flags & SET_FLAGS) { \ 511f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inv_bits |= flag_bits; \ 512f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (flags & UNUSED_RETURN) \ 513f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich dst = TMP_ZERO; \ 514f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 515f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 516f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, sljit_si dst, sljit_sw arg1, sljit_sw arg2) 517f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 518f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* dst must be register, TMP_REG1 519f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg1 must be register, TMP_REG1, imm 520f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg2 must be register, TMP_REG2, imm */ 521f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins inv_bits = (flags & INT_OP) ? (1 << 31) : 0; 522f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins inst_bits; 523f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si op = (flags & 0xffff); 524f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si reg; 525f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_sw imm, nimm; 526f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 527f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) { 528f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* Both are immediates. */ 529f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags &= ~ARG1_IMM; 530f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (arg1 == 0 && op != SLJIT_ADD && op != SLJIT_SUB) 531f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg1 = TMP_ZERO; 532f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 533f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(load_immediate(compiler, TMP_REG1, arg1)); 534f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg1 = TMP_REG1; 535f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 536f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 537f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 538f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (flags & (ARG1_IMM | ARG2_IMM)) { 539f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich reg = (flags & ARG2_IMM) ? arg1 : arg2; 540f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich imm = (flags & ARG2_IMM) ? arg2 : arg1; 541f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 542f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich switch (op) { 543f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MUL: 544f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_NEG: 545f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_CLZ: 546f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_ADDC: 547f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_SUBC: 548f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* No form with immediate operand (except imm 0, which 549f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich is represented by a ZERO register). */ 550f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 551f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV: 552f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1); 553f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return load_immediate(compiler, dst, imm); 554f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_NOT: 555f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(flags & ARG2_IMM); 556f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(load_immediate(compiler, dst, (flags & INT_OP) ? (~imm & 0xffffffff) : ~imm)); 557f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich goto set_flags; 558f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_SUB: 559f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (flags & ARG1_IMM) 560f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 561f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich imm = -imm; 562f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* Fall through. */ 563f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_ADD: 564f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (imm == 0) { 565f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_FLAGS(1 << 29); 566f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, ((op == SLJIT_ADD ? ADDI : SUBI) ^ inv_bits) | RD(dst) | RN(reg)); 567f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 568f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (imm > 0 && imm <= 0xfff) { 569f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_FLAGS(1 << 29); 570f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (imm << 10)); 571f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 572f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich nimm = -imm; 573f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (nimm > 0 && nimm <= 0xfff) { 574f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_FLAGS(1 << 29); 575f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (nimm << 10)); 576f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 577f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (imm > 0 && imm <= 0xffffff && !(imm & 0xfff)) { 578f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_FLAGS(1 << 29); 579f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((imm >> 12) << 10) | (1 << 22)); 580f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 581f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (nimm > 0 && nimm <= 0xffffff && !(nimm & 0xfff)) { 582f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_FLAGS(1 << 29); 583f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((nimm >> 12) << 10) | (1 << 22)); 584f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 585f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (imm > 0 && imm <= 0xffffff && !(flags & SET_FLAGS)) { 586f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((imm >> 12) << 10) | (1 << 22))); 587f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(dst) | ((imm & 0xfff) << 10)); 588f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 589f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (nimm > 0 && nimm <= 0xffffff && !(flags & SET_FLAGS)) { 590f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((nimm >> 12) << 10) | (1 << 22))); 591f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(dst) | ((nimm & 0xfff) << 10)); 592f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 593f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 594f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_AND: 595f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32)); 596f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!inst_bits) 597f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 598f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_FLAGS(3 << 29); 599f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (ANDI ^ inv_bits) | RD(dst) | RN(reg) | inst_bits); 600f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_OR: 601f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_XOR: 602f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32)); 603f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!inst_bits) 604f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 605f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (op == SLJIT_OR) 606f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inst_bits |= ORRI; 607f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 608f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inst_bits |= EORI; 609f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (inst_bits ^ inv_bits) | RD(dst) | RN(reg))); 610f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich goto set_flags; 611f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_SHL: 612f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (flags & ARG1_IMM) 613f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 614f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (flags & INT_OP) { 615f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich imm &= 0x1f; 616f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | ((-imm & 0x1f) << 16) | ((31 - imm) << 10))); 617f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 618f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 619f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich imm &= 0x3f; 620f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22) | ((-imm & 0x3f) << 16) | ((63 - imm) << 10))); 621f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 622f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich goto set_flags; 623f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_LSHR: 624f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_ASHR: 625f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (flags & ARG1_IMM) 626f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 627f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (op == SLJIT_ASHR) 628f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inv_bits |= 1 << 30; 629f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (flags & INT_OP) { 630f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich imm &= 0x1f; 631f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (imm << 16) | (31 << 10))); 632f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 633f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 634f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich imm &= 0x3f; 635f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22) | (imm << 16) | (63 << 10))); 636f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 637f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich goto set_flags; 638f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich default: 639f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT_STOP(); 640f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 641f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 642f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 643f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (flags & ARG2_IMM) { 644f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (arg2 == 0) 645f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg2 = TMP_ZERO; 646f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 647f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(load_immediate(compiler, TMP_REG2, arg2)); 648f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg2 = TMP_REG2; 649f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 650f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 651f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 652f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (arg1 == 0) 653f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg1 = TMP_ZERO; 654f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 655f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(load_immediate(compiler, TMP_REG1, arg1)); 656f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg1 = TMP_REG1; 657f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 658f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 659f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 660f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 661f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* Both arguments are registers. */ 662f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich switch (op) { 663f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV: 664f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_P: 665f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU: 666f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_P: 667f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); 668f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst == arg2) 669f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 670f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(arg2)); 671f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_UB: 672f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_UB: 673f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); 674f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (UBFM ^ (1 << 31)) | RD(dst) | RN(arg2) | (7 << 10)); 675f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_SB: 676f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_SB: 677f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); 678f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(flags & INT_OP)) 679f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inv_bits |= 1 << 22; 680f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10)); 681f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_UH: 682f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_UH: 683f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); 684f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (UBFM ^ (1 << 31)) | RD(dst) | RN(arg2) | (15 << 10)); 685f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_SH: 686f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_SH: 687f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); 688f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(flags & INT_OP)) 689f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inv_bits |= 1 << 22; 690f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10)); 691f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_UI: 692f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_UI: 693f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); 694f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((flags & INT_OP) && dst == arg2) 695f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 696f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (ORR ^ (1 << 31)) | RD(dst) | RN(TMP_ZERO) | RM(arg2)); 697f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_SI: 698f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_SI: 699f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); 700f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((flags & INT_OP) && dst == arg2) 701f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 702f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(arg2) | (31 << 10)); 703f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_NOT: 704f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(arg1 == TMP_REG1); 705f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2))); 706f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich goto set_flags; 707f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_NEG: 708f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(arg1 == TMP_REG1); 709f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (flags & SET_FLAGS) 710f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inv_bits |= 1 << 29; 711f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2)); 712f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_CLZ: 713f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(arg1 == TMP_REG1); 714f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2))); 715f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich goto set_flags; 716f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_ADD: 717f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_FLAGS(1 << 29); 718f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); 719f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_ADDC: 720f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_FLAGS(1 << 29); 721f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (ADC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); 722f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_SUB: 723f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_FLAGS(1 << 29); 724f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); 725f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_SUBC: 726f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_FLAGS(1 << 29); 727f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (SBC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); 728f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MUL: 729f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(flags & SET_FLAGS)) 730f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (MADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO)); 731f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (flags & INT_OP) { 732f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, SMADDL | RD(dst) | RN(arg1) | RM(arg2) | (31 << 10))); 733f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG4) | RN(TMP_ZERO) | RM(dst) | (2 << 22) | (31 << 10))); 734f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_REG4) | RM(dst) | (2 << 22) | (63 << 10)); 735f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 736f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, SMULH | RD(TMP_REG4) | RN(arg1) | RM(arg2))); 737f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, MADD | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO))); 738f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_REG4) | RM(dst) | (2 << 22) | (63 << 10)); 739f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_AND: 740f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_FLAGS(3 << 29); 741f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (AND ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); 742f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_OR: 743f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); 744f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich goto set_flags; 745f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_XOR: 746f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); 747f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich goto set_flags; 748f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_SHL: 749f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); 750f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich goto set_flags; 751f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_LSHR: 752f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); 753f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich goto set_flags; 754f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_ASHR: 755f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); 756f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich goto set_flags; 757f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 758f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 759f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT_STOP(); 760f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 761f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 762f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichset_flags: 763f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (flags & SET_FLAGS) 764f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (SUBS ^ inv_bits) | RD(TMP_ZERO) | RN(dst) | RM(TMP_ZERO)); 765f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 766f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 767f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 768f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define STORE 0x01 769f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define SIGNED 0x02 770f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 771f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define UPDATE 0x04 772f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define ARG_TEST 0x08 773f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 774f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define BYTE_SIZE 0x000 775f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define HALF_SIZE 0x100 776f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define INT_SIZE 0x200 777f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define WORD_SIZE 0x300 778f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 779f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#define MEM_SIZE_SHIFT(flags) ((flags) >> 8) 780f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 781f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_CONST sljit_ins sljit_mem_imm[4] = { 782f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* u l */ 0x39400000 /* ldrb [reg,imm] */, 783f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* u s */ 0x39000000 /* strb [reg,imm] */, 784f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* s l */ 0x39800000 /* ldrsb [reg,imm] */, 785f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* s s */ 0x39000000 /* strb [reg,imm] */, 786f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich}; 787f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 788f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_CONST sljit_ins sljit_mem_simm[4] = { 789f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* u l */ 0x38400000 /* ldurb [reg,imm] */, 790f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* u s */ 0x38000000 /* sturb [reg,imm] */, 791f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* s l */ 0x38800000 /* ldursb [reg,imm] */, 792f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* s s */ 0x38000000 /* sturb [reg,imm] */, 793f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich}; 794f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 795f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_CONST sljit_ins sljit_mem_pre_simm[4] = { 796f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* u l */ 0x38400c00 /* ldrb [reg,imm]! */, 797f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* u s */ 0x38000c00 /* strb [reg,imm]! */, 798f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* s l */ 0x38800c00 /* ldrsb [reg,imm]! */, 799f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* s s */ 0x38000c00 /* strb [reg,imm]! */, 800f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich}; 801f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 802f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_CONST sljit_ins sljit_mem_reg[4] = { 803f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* u l */ 0x38606800 /* ldrb [reg,reg] */, 804f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* u s */ 0x38206800 /* strb [reg,reg] */, 805f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* s l */ 0x38a06800 /* ldrsb [reg,reg] */, 806f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* s s */ 0x38206800 /* strb [reg,reg] */, 807f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich}; 808f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 809f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */ 810f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sljit_si reg, sljit_sw value) 811f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 812f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (value >= 0) { 813f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (value <= 0xfff) 814f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, ADDI | RD(dst) | RN(reg) | (value << 10)); 815f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (value <= 0xffffff && !(value & 0xfff)) 816f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, ADDI | (1 << 22) | RD(dst) | RN(reg) | (value >> 2)); 817f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 818f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 819f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich value = -value; 820f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (value <= 0xfff) 821f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, SUBI | RD(dst) | RN(reg) | (value << 10)); 822f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (value <= 0xffffff && !(value & 0xfff)) 823f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, SUBI | (1 << 22) | RD(dst) | RN(reg) | (value >> 2)); 824f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 825f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_ERR_UNSUPPORTED; 826f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 827f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 828f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* Can perform an operation using at most 1 instruction. */ 829f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw) 830f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 831f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ui shift = MEM_SIZE_SHIFT(flags); 832f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 833f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(arg & SLJIT_MEM); 834f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 835f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (SLJIT_UNLIKELY(flags & UPDATE)) { 836f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((arg & REG_MASK) && !(arg & OFFS_REG_MASK) && argw <= 255 && argw >= -256) { 837f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (SLJIT_UNLIKELY(flags & ARG_TEST)) 838f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 1; 839f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 840f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg &= REG_MASK; 841f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich argw &= 0x1ff; 842f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, sljit_mem_pre_simm[flags & 0x3] 843f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich | (shift << 30) | RT(reg) | RN(arg) | (argw << 12))); 844f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return -1; 845f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 846f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0; 847f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 848f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 849f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { 850f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich argw &= 0x3; 851f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (argw && argw != shift) 852f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0; 853f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 854f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (SLJIT_UNLIKELY(flags & ARG_TEST)) 855f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 1; 856f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 857f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) 858f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0))); 859f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return -1; 860f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 861f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 862f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg &= REG_MASK; 863f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (argw >= 0 && (argw >> shift) <= 0xfff && (argw & ((1 << shift) - 1)) == 0) { 864f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (SLJIT_UNLIKELY(flags & ARG_TEST)) 865f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 1; 866f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 867f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) 868f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich | RT(reg) | RN(arg) | (argw << (10 - shift)))); 869f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return -1; 870f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 871f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 872f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (argw > 255 || argw < -256) 873f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0; 874f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 875f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (SLJIT_UNLIKELY(flags & ARG_TEST)) 876f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 1; 877f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 878f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, sljit_mem_simm[flags & 0x3] | (shift << 30) 879f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich | RT(reg) | RN(arg) | ((argw & 0x1ff) << 12))); 880f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return -1; 881f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 882f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 883f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* see getput_arg below. 884f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich Note: can_cache is called only for binary operators. Those 885f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich operators always uses word arguments without write back. */ 886f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw) 887f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 888f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_sw diff; 889f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((arg & OFFS_REG_MASK) || !(next_arg & SLJIT_MEM)) 890f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0; 891f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 892f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(arg & REG_MASK)) { 893f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich diff = argw - next_argw; 894f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (diff <= 0xfff && diff >= -0xfff) 895f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 1; 896f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0; 897f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 898f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 899f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (argw == next_argw) 900f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 1; 901f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 902f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich diff = argw - next_argw; 903f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (arg == next_arg && diff <= 0xfff && diff >= -0xfff) 904f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 1; 905f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 906f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0; 907f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 908f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 909f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* Emit the necessary instructions. See can_cache above. */ 910f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, 911f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw) 912f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 913f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ui shift = MEM_SIZE_SHIFT(flags); 914f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si tmp_r, other_r; 915f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_sw diff; 916f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 917f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(arg & SLJIT_MEM); 918f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(next_arg & SLJIT_MEM)) { 919f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich next_arg = 0; 920f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich next_argw = 0; 921f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 922f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 923f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich tmp_r = (flags & STORE) ? TMP_REG3 : reg; 924f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 925f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (SLJIT_UNLIKELY((flags & UPDATE) && (arg & REG_MASK))) { 926f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* Update only applies if a base register exists. */ 927f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich other_r = OFFS_REG(arg); 928f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!other_r) { 929f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich other_r = arg & REG_MASK; 930f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (other_r != reg && argw >= 0 && argw <= 0xffffff) { 931f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((argw & 0xfff) != 0) 932f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ADDI | RD(other_r) | RN(other_r) | ((argw & 0xfff) << 10))); 933f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (argw >> 12) 934f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(other_r) | RN(other_r) | ((argw >> 12) << 10))); 935f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(other_r)); 936f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 937f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else if (other_r != reg && argw < 0 && argw >= -0xffffff) { 938f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich argw = -argw; 939f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((argw & 0xfff) != 0) 940f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, SUBI | RD(other_r) | RN(other_r) | ((argw & 0xfff) << 10))); 941f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (argw >> 12) 942f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(other_r) | RN(other_r) | ((argw >> 12) << 10))); 943f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(other_r)); 944f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 945f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 946f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (compiler->cache_arg == SLJIT_MEM) { 947f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (argw == compiler->cache_argw) { 948f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich other_r = TMP_REG3; 949f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich argw = 0; 950f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 951f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) { 952f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(compiler->error); 953f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_argw = argw; 954f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich other_r = TMP_REG3; 955f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich argw = 0; 956f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 957f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 958f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 959f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (argw) { 960f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); 961f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_arg = SLJIT_MEM; 962f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_argw = argw; 963f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich other_r = TMP_REG3; 964f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich argw = 0; 965f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 966f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 967f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 968f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* No caching here. */ 969f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg &= REG_MASK; 970f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich argw &= 0x3; 971f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!argw || argw == shift) { 972f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(other_r) | (argw ? (1 << 12) : 0))); 973f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r) | (argw << 10)); 974f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 975f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (arg != reg) { 976f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r) | (argw << 10))); 977f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg)); 978f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 979f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG4) | RN(arg) | RM(other_r) | (argw << 10))); 980f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(TMP_REG4))); 981f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, ORR | RD(arg) | RN(TMP_ZERO) | RM(TMP_REG4)); 982f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 983f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 984f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (arg & OFFS_REG_MASK) { 985f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich other_r = OFFS_REG(arg); 986f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg &= REG_MASK; 987f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RN(arg) | RM(other_r) | ((argw & 0x3) << 10))); 988f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(tmp_r)); 989f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 990f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 991f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (compiler->cache_arg == arg) { 992f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich diff = argw - compiler->cache_argw; 993f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (diff <= 255 && diff >= -256) 994f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, sljit_mem_simm[flags & 0x3] | (shift << 30) 995f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich | RT(reg) | RN(TMP_REG3) | ((diff & 0x1ff) << 12)); 996f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, diff) != SLJIT_ERR_UNSUPPORTED) { 997f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(compiler->error); 998f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg)); 999f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1000f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1001f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1002f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (argw >= 0 && argw <= 0xffffff && (argw & ((1 << shift) - 1)) == 0) { 1003f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_r) | RN(arg & REG_MASK) | ((argw >> 12) << 10))); 1004f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) 1005f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich | RT(reg) | RN(tmp_r) | ((argw & 0xfff) << (10 - shift))); 1006f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1007f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1008f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich diff = argw - next_argw; 1009f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich next_arg = (arg & REG_MASK) && (arg == next_arg) && diff <= 0xfff && diff >= -0xfff && diff != 0; 1010f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg &= REG_MASK; 1011f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1012f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (arg && compiler->cache_arg == SLJIT_MEM) { 1013f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (compiler->cache_argw == argw) 1014f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3)); 1015f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) { 1016f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(compiler->error); 1017f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_argw = argw; 1018f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3)); 1019f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1020f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1021f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1022f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_argw = argw; 1023f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (next_arg && emit_set_delta(compiler, TMP_REG3, arg, argw) != SLJIT_ERR_UNSUPPORTED) { 1024f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(compiler->error); 1025f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_arg = SLJIT_MEM | arg; 1026f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg = 0; 1027f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1028f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 1029f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); 1030f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_arg = SLJIT_MEM; 1031f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1032f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (next_arg) { 1033f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RN(TMP_REG3) | RM(arg))); 1034f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_arg = SLJIT_MEM | arg; 1035f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg = 0; 1036f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1037f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1038f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1039f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (arg) 1040f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3)); 1041f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(TMP_REG3)); 1042f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1043f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1044f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw) 1045f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1046f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (getput_arg_fast(compiler, flags, reg, arg, argw)) 1047f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return compiler->error; 1048f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_arg = 0; 1049f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_argw = 0; 1050f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return getput_arg(compiler, flags, reg, arg, argw, 0, 0); 1051f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1052f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1053f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w) 1054f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1055f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) 1056f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return compiler->error; 1057f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); 1058f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1059f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1060f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 1061f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* Entry, exit */ 1062f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 1063f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1064f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, 1065f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds, 1066f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si fscratches, sljit_si fsaveds, sljit_si local_size) 1067f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1068f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si i, tmp, offs, prev; 1069f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1070f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR(); 1071f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); 1072f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1073f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->options = options; 1074f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->scratches = scratches; 1075f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->saveds = saveds; 1076f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->fscratches = fscratches; 1077f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->fsaveds = fsaveds; 1078f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#if (defined SLJIT_DEBUG && SLJIT_DEBUG) 1079f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->logical_local_size = local_size; 1080f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#endif 1081f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->locals_offset = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2); 1082f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich local_size = (compiler->locals_offset + local_size + 15) & ~15; 1083f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->local_size = local_size; 1084f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1085f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (local_size <= (64 << 3)) 1086f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, STP_PRE | 29 | RT2(TMP_LR) 1087f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich | RN(TMP_SP) | ((-(local_size >> 3) & 0x7f) << 15))); 1088f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 1089f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich local_size -= (64 << 3); 1090f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (local_size > 0xfff) { 1091f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | ((local_size >> 12) << 10) | (1 << 22))); 1092f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich local_size &= 0xfff; 1093f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1094f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (local_size) 1095f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (local_size << 10))); 1096f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, STP_PRE | 29 | RT2(TMP_LR) | RN(TMP_SP) | (0x40 << 15))); 1097f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1098f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1099f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_SP))); 1100f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1101f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; 1102f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich offs = 2 << 15; 1103f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich prev = -1; 1104f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich for (i = SLJIT_S0; i >= tmp; i--) { 1105f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (prev == -1) { 1106f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich prev = i; 1107f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich continue; 1108f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1109f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); 1110f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich offs += 2 << 15; 1111f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich prev = -1; 1112f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1113f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1114f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { 1115f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (prev == -1) { 1116f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich prev = i; 1117f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich continue; 1118f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1119f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); 1120f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich offs += 2 << 15; 1121f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich prev = -1; 1122f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1123f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1124f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (prev != -1) 1125f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(TMP_SP) | (offs >> 5))); 1126f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1127f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (args >= 1) 1128f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0) | RN(TMP_ZERO) | RM(SLJIT_R0))); 1129f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (args >= 2) 1130f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S1) | RN(TMP_ZERO) | RM(SLJIT_R1))); 1131f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (args >= 3) 1132f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S2) | RN(TMP_ZERO) | RM(SLJIT_R2))); 1133f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1134f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1135f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1136f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1137f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, 1138f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds, 1139f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si fscratches, sljit_si fsaveds, sljit_si local_size) 1140f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1141f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR_VOID(); 1142f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); 1143f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1144f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->options = options; 1145f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->scratches = scratches; 1146f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->saveds = saveds; 1147f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->fscratches = fscratches; 1148f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->fsaveds = fsaveds; 1149f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#if (defined SLJIT_DEBUG && SLJIT_DEBUG) 1150f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->logical_local_size = local_size; 1151f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#endif 1152f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->locals_offset = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2); 1153f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->local_size = (compiler->locals_offset + local_size + 15) & ~15; 1154f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1155f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1156f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw) 1157f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1158f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si local_size; 1159f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si i, tmp, offs, prev; 1160f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1161f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR(); 1162f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_return(compiler, op, src, srcw); 1163f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1164f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); 1165f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1166f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG; 1167f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich offs = 2 << 15; 1168f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich prev = -1; 1169f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich for (i = SLJIT_S0; i >= tmp; i--) { 1170f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (prev == -1) { 1171f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich prev = i; 1172f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich continue; 1173f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1174f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); 1175f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich offs += 2 << 15; 1176f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich prev = -1; 1177f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1178f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1179f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { 1180f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (prev == -1) { 1181f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich prev = i; 1182f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich continue; 1183f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1184f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); 1185f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich offs += 2 << 15; 1186f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich prev = -1; 1187f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1188f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1189f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (prev != -1) 1190f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(TMP_SP) | (offs >> 5))); 1191f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1192f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich local_size = compiler->local_size; 1193f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1194f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (local_size <= (62 << 3)) 1195f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR) 1196f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich | RN(TMP_SP) | (((local_size >> 3) & 0x7f) << 15))); 1197f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 1198f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR) | RN(TMP_SP) | (0x3e << 15))); 1199f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich local_size -= (62 << 3); 1200f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (local_size > 0xfff) { 1201f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | ((local_size >> 12) << 10) | (1 << 22))); 1202f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich local_size &= 0xfff; 1203f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1204f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (local_size) 1205f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (local_size << 10))); 1206f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1207f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1208f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, RET | RN(TMP_LR))); 1209f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1210f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1211f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1212f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 1213f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* Operators */ 1214f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 1215f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1216f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) 1217f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1218f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins inv_bits = (op & SLJIT_INT_OP) ? (1 << 31) : 0; 1219f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1220f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR(); 1221f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_op0(compiler, op); 1222f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1223f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich op = GET_OPCODE(op); 1224f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich switch (op) { 1225f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_BREAKPOINT: 1226f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, BRK); 1227f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_NOP: 1228f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, NOP); 1229f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_UMUL: 1230f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_SMUL: 1231f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); 1232f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); 1233f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (op == SLJIT_SMUL ? SMULH : UMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); 1234f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_UDIV: 1235f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_SDIV: 1236f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); 1237f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ((op == SLJIT_SDIV ? SDIV : UDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1))); 1238f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); 1239f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); 1240f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1241f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1242f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1243f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1244f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1245f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op, 1246f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst, sljit_sw dstw, 1247f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si src, sljit_sw srcw) 1248f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1249f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst_r, flags, mem_flags; 1250f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si op_flags = GET_ALL_FLAGS(op); 1251f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1252f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR(); 1253f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); 1254f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(dst, dstw); 1255f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(src, srcw); 1256f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1257f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_arg = 0; 1258f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_argw = 0; 1259f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1260f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; 1261f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1262f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich op = GET_OPCODE(op); 1263f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) { 1264f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich switch (op) { 1265f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV: 1266f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_P: 1267f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = WORD_SIZE; 1268f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1269f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_UB: 1270f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = BYTE_SIZE; 1271f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1272f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_ub)srcw; 1273f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1274f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_SB: 1275f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = BYTE_SIZE | SIGNED; 1276f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1277f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_sb)srcw; 1278f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1279f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_UH: 1280f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = HALF_SIZE; 1281f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1282f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_uh)srcw; 1283f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1284f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_SH: 1285f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = HALF_SIZE | SIGNED; 1286f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1287f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_sh)srcw; 1288f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1289f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_UI: 1290f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = INT_SIZE; 1291f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1292f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_ui)srcw; 1293f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1294f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOV_SI: 1295f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = INT_SIZE | SIGNED; 1296f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1297f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_si)srcw; 1298f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1299f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU: 1300f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_P: 1301f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = WORD_SIZE | UPDATE; 1302f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1303f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_UB: 1304f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = BYTE_SIZE | UPDATE; 1305f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1306f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_ub)srcw; 1307f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1308f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_SB: 1309f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = BYTE_SIZE | SIGNED | UPDATE; 1310f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1311f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_sb)srcw; 1312f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1313f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_UH: 1314f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = HALF_SIZE | UPDATE; 1315f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1316f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_uh)srcw; 1317f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1318f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_SH: 1319f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = HALF_SIZE | SIGNED | UPDATE; 1320f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1321f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_sh)srcw; 1322f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1323f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_UI: 1324f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = INT_SIZE | UPDATE; 1325f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1326f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_ui)srcw; 1327f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1328f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVU_SI: 1329f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = INT_SIZE | SIGNED | UPDATE; 1330f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1331f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_si)srcw; 1332f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1333f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich default: 1334f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT_STOP(); 1335f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = 0; 1336f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1337f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1338f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1339f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) 1340f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw)); 1341f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else if (src & SLJIT_MEM) { 1342f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (getput_arg_fast(compiler, flags, dst_r, src, srcw)) 1343f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(compiler->error); 1344f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 1345f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(getput_arg(compiler, flags, dst_r, src, srcw, dst, dstw)); 1346f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } else { 1347f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst_r != TMP_REG1) 1348f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return emit_op_imm(compiler, op | ((op_flags & SLJIT_INT_OP) ? INT_OP : 0), dst_r, TMP_REG1, src); 1349f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich dst_r = src; 1350f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1351f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1352f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst & SLJIT_MEM) { 1353f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw)) 1354f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return compiler->error; 1355f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 1356f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0); 1357f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1358f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1359f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1360f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1361f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = GET_FLAGS(op_flags) ? SET_FLAGS : 0; 1362f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich mem_flags = WORD_SIZE; 1363f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (op_flags & SLJIT_INT_OP) { 1364f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags |= INT_OP; 1365f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich mem_flags = INT_SIZE; 1366f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1367f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1368f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst == SLJIT_UNUSED) 1369f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags |= UNUSED_RETURN; 1370f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1371f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_MEM) { 1372f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (getput_arg_fast(compiler, mem_flags, TMP_REG2, src, srcw)) 1373f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(compiler->error); 1374f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 1375f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG2, src, srcw, dst, dstw)); 1376f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src = TMP_REG2; 1377f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1378f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1379f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_IMM) { 1380f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags |= ARG2_IMM; 1381f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (op_flags & SLJIT_INT_OP) 1382f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_si)srcw; 1383f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } else 1384f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = src; 1385f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1386f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, srcw); 1387f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1388f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst & SLJIT_MEM) { 1389f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (getput_arg_fast(compiler, mem_flags | STORE, dst_r, dst, dstw)) 1390f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return compiler->error; 1391f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 1392f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return getput_arg(compiler, mem_flags | STORE, dst_r, dst, dstw, 0, 0); 1393f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1394f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1395f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1396f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1397f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op, 1398f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst, sljit_sw dstw, 1399f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si src1, sljit_sw src1w, 1400f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si src2, sljit_sw src2w) 1401f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1402f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst_r, flags, mem_flags; 1403f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1404f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR(); 1405f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); 1406f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(dst, dstw); 1407f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(src1, src1w); 1408f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(src2, src2w); 1409f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1410f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_arg = 0; 1411f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_argw = 0; 1412f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1413f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; 1414f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = GET_FLAGS(op) ? SET_FLAGS : 0; 1415f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich mem_flags = WORD_SIZE; 1416f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (op & SLJIT_INT_OP) { 1417f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags |= INT_OP; 1418f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich mem_flags = INT_SIZE; 1419f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1420f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1421f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst == SLJIT_UNUSED) 1422f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags |= UNUSED_RETURN; 1423f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1424f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, mem_flags | STORE | ARG_TEST, TMP_REG1, dst, dstw)) 1425f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags |= SLOW_DEST; 1426f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1427f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src1 & SLJIT_MEM) { 1428f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (getput_arg_fast(compiler, mem_flags, TMP_REG1, src1, src1w)) 1429f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(compiler->error); 1430f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 1431f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags |= SLOW_SRC1; 1432f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1433f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src2 & SLJIT_MEM) { 1434f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (getput_arg_fast(compiler, mem_flags, TMP_REG2, src2, src2w)) 1435f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(compiler->error); 1436f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 1437f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags |= SLOW_SRC2; 1438f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1439f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1440f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { 1441f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { 1442f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG2, src2, src2w, src1, src1w)); 1443f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG1, src1, src1w, dst, dstw)); 1444f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1445f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else { 1446f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG1, src1, src1w, src2, src2w)); 1447f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG2, src2, src2w, dst, dstw)); 1448f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1449f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1450f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else if (flags & SLOW_SRC1) 1451f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG1, src1, src1w, dst, dstw)); 1452f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else if (flags & SLOW_SRC2) 1453f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG2, src2, src2w, dst, dstw)); 1454f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1455f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src1 & SLJIT_MEM) 1456f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src1 = TMP_REG1; 1457f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src2 & SLJIT_MEM) 1458f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src2 = TMP_REG2; 1459f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1460f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src1 & SLJIT_IMM) 1461f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags |= ARG1_IMM; 1462f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 1463f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src1w = src1; 1464f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src2 & SLJIT_IMM) 1465f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags |= ARG2_IMM; 1466f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 1467f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src2w = src2; 1468f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1469f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w); 1470f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1471f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst & SLJIT_MEM) { 1472f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(flags & SLOW_DEST)) { 1473f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich getput_arg_fast(compiler, mem_flags | STORE, dst_r, dst, dstw); 1474f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return compiler->error; 1475f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1476f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return getput_arg(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, 0, 0); 1477f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1478f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1479f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1480f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1481f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1482f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg) 1483f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1484f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_get_register_index(reg); 1485f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return reg_map[reg]; 1486f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1487f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1488f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg) 1489f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1490f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_get_float_register_index(reg); 1491f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return reg; 1492f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1493f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1494f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler, 1495f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich void *instruction, sljit_si size) 1496f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1497f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR(); 1498f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_op_custom(compiler, instruction, size); 1499f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(size == 4); 1500f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1501f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, *(sljit_ins*)instruction); 1502f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1503f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1504f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 1505f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* Floating point operators */ 1506f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 1507f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1508f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void) 1509f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1510f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#ifdef SLJIT_IS_FPU_AVAILABLE 1511f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_IS_FPU_AVAILABLE; 1512f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#else 1513f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* Available by default. */ 1514f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 1; 1515f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#endif 1516f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1517f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1518f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw) 1519f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1520f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ui shift = MEM_SIZE_SHIFT(flags); 1521f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins ins_bits = (shift << 30); 1522f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si other_r; 1523f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_sw diff; 1524f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1525f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(arg & SLJIT_MEM); 1526f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1527f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(flags & STORE)) 1528f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ins_bits |= 1 << 22; 1529f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1530f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (arg & OFFS_REG_MASK) { 1531f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich argw &= 3; 1532f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!argw || argw == shift) 1533f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, STR_FR | ins_bits | VT(reg) 1534f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0)); 1535f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich other_r = OFFS_REG(arg); 1536f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg &= REG_MASK; 1537f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg) | RM(other_r) | (argw << 10))); 1538f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg = TMP_REG1; 1539f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich argw = 0; 1540f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1541f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1542f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich arg &= REG_MASK; 1543f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (arg && argw >= 0 && ((argw >> shift) <= 0xfff) && (argw & ((1 << shift) - 1)) == 0) 1544f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, STR_FI | ins_bits | VT(reg) | RN(arg) | (argw << (10 - shift))); 1545f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1546f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (arg && argw <= 255 && argw >= -256) 1547f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, STUR_FI | ins_bits | VT(reg) | RN(arg) | ((argw & 0x1ff) << 12)); 1548f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1549f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* Slow cases */ 1550f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (compiler->cache_arg == SLJIT_MEM && argw != compiler->cache_argw) { 1551f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich diff = argw - compiler->cache_argw; 1552f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!arg && diff <= 255 && diff >= -256) 1553f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, STUR_FI | ins_bits | VT(reg) | RN(TMP_REG3) | ((diff & 0x1ff) << 12)); 1554f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) { 1555f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(compiler->error); 1556f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_argw = argw; 1557f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1558f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1559f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1560f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (compiler->cache_arg != SLJIT_MEM || argw != compiler->cache_argw) { 1561f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_arg = SLJIT_MEM; 1562f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_argw = argw; 1563f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); 1564f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1565f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1566f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (arg & REG_MASK) 1567f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, STR_FR | ins_bits | VT(reg) | RN(arg) | RM(TMP_REG3)); 1568f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, STR_FI | ins_bits | VT(reg) | RN(TMP_REG3)); 1569f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1570f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1571f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op, 1572f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst, sljit_sw dstw, 1573f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si src, sljit_sw srcw) 1574f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1575f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; 1576f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0; 1577f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1578f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (GET_OPCODE(op) == SLJIT_CONVI_FROMD) 1579f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inv_bits |= (1 << 31); 1580f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1581f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_MEM) { 1582f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src, srcw); 1583f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src = TMP_FREG1; 1584f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1585f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1586f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (FCVTZS ^ inv_bits) | RD(dst_r) | VN(src))); 1587f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1588f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst_r == TMP_REG1 && dst != SLJIT_UNUSED) 1589f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONVI_FROMD) ? INT_SIZE : WORD_SIZE) | STORE, TMP_REG1, dst, dstw); 1590f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1591f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1592f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1593f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op, 1594f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst, sljit_sw dstw, 1595f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si src, sljit_sw srcw) 1596f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1597f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; 1598f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0; 1599f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1600f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (GET_OPCODE(op) == SLJIT_CONVD_FROMI) 1601f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inv_bits |= (1 << 31); 1602f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1603f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_MEM) { 1604f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONVD_FROMI) ? INT_SIZE : WORD_SIZE), TMP_REG1, src, srcw); 1605f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src = TMP_REG1; 1606f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } else if (src & SLJIT_IMM) { 1607f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) 1608f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (GET_OPCODE(op) == SLJIT_CONVD_FROMI) 1609f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = (sljit_si)srcw; 1610f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich#endif 1611f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); 1612f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src = TMP_REG1; 1613f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1614f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1615f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (SCVTF ^ inv_bits) | VD(dst_r) | RN(src))); 1616f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1617f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst & SLJIT_MEM) 1618f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return emit_fop_mem(compiler, ((op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE) | STORE, TMP_FREG1, dst, dstw); 1619f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1620f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1621f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1622f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op, 1623f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si src1, sljit_sw src1w, 1624f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si src2, sljit_sw src2w) 1625f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1626f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si mem_flags = (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE; 1627f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0; 1628f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1629f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src1 & SLJIT_MEM) { 1630f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w); 1631f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src1 = TMP_FREG1; 1632f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1633f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1634f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src2 & SLJIT_MEM) { 1635f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w); 1636f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src2 = TMP_FREG2; 1637f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1638f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1639f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, (FCMP ^ inv_bits) | VN(src1) | VM(src2)); 1640f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1641f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1642f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op, 1643f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst, sljit_sw dstw, 1644f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si src, sljit_sw srcw) 1645f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1646f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst_r, mem_flags = (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE; 1647f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins inv_bits; 1648f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1649f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR(); 1650f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_arg = 0; 1651f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_argw = 0; 1652f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1653f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_COMPILE_ASSERT((INT_SIZE ^ 0x100) == WORD_SIZE, must_be_one_bit_difference); 1654f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); 1655f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1656f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0; 1657f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; 1658f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1659f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_MEM) { 1660f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONVD_FROMS) ? (mem_flags ^ 0x100) : mem_flags, dst_r, src, srcw); 1661f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src = dst_r; 1662f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1663f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1664f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich switch (GET_OPCODE(op)) { 1665f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MOVD: 1666f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src != dst_r) { 1667f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst_r != TMP_FREG1) 1668f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (FMOV ^ inv_bits) | VD(dst_r) | VN(src))); 1669f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else 1670f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich dst_r = src; 1671f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1672f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1673f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_NEGD: 1674f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (FNEG ^ inv_bits) | VD(dst_r) | VN(src))); 1675f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1676f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_ABSD: 1677f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src))); 1678f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1679f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_CONVD_FROMS: 1680f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, FCVT | ((op & SLJIT_SINGLE_OP) ? (1 << 22) : (1 << 15)) | VD(dst_r) | VN(src))); 1681f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1682f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1683f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1684f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst & SLJIT_MEM) 1685f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return emit_fop_mem(compiler, mem_flags | STORE, dst_r, dst, dstw); 1686f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1687f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1688f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1689f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op, 1690f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst, sljit_sw dstw, 1691f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si src1, sljit_sw src1w, 1692f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si src2, sljit_sw src2w) 1693f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1694f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst_r, mem_flags = (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE; 1695f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0; 1696f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1697f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR(); 1698f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); 1699f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(dst, dstw); 1700f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(src1, src1w); 1701f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(src2, src2w); 1702f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1703f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_arg = 0; 1704f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_argw = 0; 1705f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1706f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; 1707f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src1 & SLJIT_MEM) { 1708f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w); 1709f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src1 = TMP_FREG1; 1710f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1711f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src2 & SLJIT_MEM) { 1712f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w); 1713f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src2 = TMP_FREG2; 1714f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1715f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1716f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich switch (GET_OPCODE(op)) { 1717f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_ADDD: 1718f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (FADD ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2))); 1719f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1720f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_SUBD: 1721f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (FSUB ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2))); 1722f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1723f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_MULD: 1724f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (FMUL ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2))); 1725f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1726f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_DIVD: 1727f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, (FDIV ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2))); 1728f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich break; 1729f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1730f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1731f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(dst & SLJIT_MEM)) 1732f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1733f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return emit_fop_mem(compiler, mem_flags | STORE, TMP_FREG1, dst, dstw); 1734f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1735f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1736f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 1737f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* Other instructions */ 1738f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 1739f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1740f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw) 1741f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1742f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR(); 1743f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_fast_enter(compiler, dst, dstw); 1744f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(dst, dstw); 1745f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1746f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* For UNUSED dst. Uncommon, but possible. */ 1747f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst == SLJIT_UNUSED) 1748f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1749f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1750f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (FAST_IS_REG(dst)) 1751f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(TMP_LR)); 1752f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1753f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* Memory. */ 1754f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_LR, dst, dstw); 1755f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1756f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1757f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw) 1758f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1759f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR(); 1760f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_fast_return(compiler, src, srcw); 1761f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(src, srcw); 1762f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1763f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (FAST_IS_REG(src)) 1764f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src))); 1765f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else if (src & SLJIT_MEM) 1766f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw)); 1767f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else if (src & SLJIT_IMM) 1768f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(load_immediate(compiler, TMP_LR, srcw)); 1769f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1770f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, RET | RN(TMP_LR)); 1771f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1772f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1773f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 1774f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* Conditional instructions */ 1775f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich/* --------------------------------------------------------------------- */ 1776f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1777f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic sljit_uw get_cc(sljit_si type) 1778f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1779f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich switch (type) { 1780f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_EQUAL: 1781f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_MUL_NOT_OVERFLOW: 1782f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_FLOAT_EQUAL: 1783f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0x1; 1784f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1785f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_NOT_EQUAL: 1786f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_MUL_OVERFLOW: 1787f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_FLOAT_NOT_EQUAL: 1788f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0x0; 1789f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1790f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_LESS: 1791f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_FLOAT_LESS: 1792f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0x2; 1793f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1794f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_GREATER_EQUAL: 1795f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_FLOAT_GREATER_EQUAL: 1796f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0x3; 1797f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1798f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_GREATER: 1799f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_FLOAT_GREATER: 1800f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0x9; 1801f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1802f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_LESS_EQUAL: 1803f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_FLOAT_LESS_EQUAL: 1804f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0x8; 1805f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1806f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_SIG_LESS: 1807f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0xa; 1808f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1809f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_SIG_GREATER_EQUAL: 1810f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0xb; 1811f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1812f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_SIG_GREATER: 1813f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0xd; 1814f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1815f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_SIG_LESS_EQUAL: 1816f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0xc; 1817f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1818f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_OVERFLOW: 1819f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_FLOAT_UNORDERED: 1820f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0x7; 1821f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1822f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_NOT_OVERFLOW: 1823f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich case SLJIT_C_FLOAT_ORDERED: 1824f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0x6; 1825f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1826f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich default: 1827f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT_STOP(); 1828f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return 0xe; 1829f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1830f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1831f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1832f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) 1833f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1834f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich struct sljit_label *label; 1835f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1836f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR_PTR(); 1837f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_label(compiler); 1838f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1839f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (compiler->last_label && compiler->last_label->size == compiler->size) 1840f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return compiler->last_label; 1841f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1842f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); 1843f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(!label); 1844f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich set_label(label, compiler); 1845f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return label; 1846f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1847f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1848f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type) 1849f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1850f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich struct sljit_jump *jump; 1851f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1852f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR_PTR(); 1853f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_jump(compiler, type); 1854f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1855f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); 1856f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(!jump); 1857f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); 1858f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich type &= 0xff; 1859f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1860f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (type < SLJIT_JUMP) { 1861f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->flags |= IS_COND; 1862f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(push_inst(compiler, B_CC | (6 << 5) | get_cc(type))); 1863f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1864f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else if (type >= SLJIT_FAST_CALL) 1865f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->flags |= IS_BL; 1866f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1867f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0)); 1868f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->addr = compiler->size; 1869f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1))); 1870f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1871f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return jump; 1872f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1873f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1874f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevichstatic SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compiler, sljit_si type, 1875f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si src, sljit_sw srcw) 1876f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1877f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich struct sljit_jump *jump; 1878f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins inv_bits = (type & SLJIT_INT_OP) ? (1 << 31) : 0; 1879f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1880f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT((type & 0xff) == SLJIT_C_EQUAL || (type & 0xff) == SLJIT_C_NOT_EQUAL); 1881f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(src, srcw); 1882f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1883f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); 1884f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(!jump); 1885f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); 1886f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->flags |= IS_CBZ | IS_COND; 1887f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1888f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_MEM) { 1889f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG1, src, srcw)); 1890f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src = TMP_REG1; 1891f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1892f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich else if (src & SLJIT_IMM) { 1893f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); 1894f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src = TMP_REG1; 1895f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1896f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_ASSERT(FAST_IS_REG(src)); 1897f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1898f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if ((type & 0xff) == SLJIT_C_EQUAL) 1899f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich inv_bits |= 1 << 24; 1900f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1901f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(push_inst(compiler, (CBZ ^ inv_bits) | (6 << 5) | RT(src))); 1902f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0)); 1903f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->addr = compiler->size; 1904f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(push_inst(compiler, BR | RN(TMP_REG1))); 1905f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return jump; 1906f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1907f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1908f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw) 1909f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1910f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich struct sljit_jump *jump; 1911f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1912f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR(); 1913f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_ijump(compiler, type, src, srcw); 1914f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(src, srcw); 1915f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1916f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich /* In ARM, we don't need to touch the arguments. */ 1917f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (!(src & SLJIT_IMM)) { 1918f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_MEM) { 1919f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw)); 1920f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src = TMP_REG1; 1921f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1922f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(src)); 1923f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1924f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1925f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); 1926f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(!jump); 1927f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0)); 1928f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->u.target = srcw; 1929f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1930f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0)); 1931f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich jump->addr = compiler->size; 1932f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1)); 1933f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1934f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1935f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op, 1936f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst, sljit_sw dstw, 1937f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si src, sljit_sw srcw, 1938f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si type) 1939f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1940f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst_r, flags, mem_flags; 1941f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins cc; 1942f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1943f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR(); 1944f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type); 1945f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(dst, dstw); 1946f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(src, srcw); 1947f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1948f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst == SLJIT_UNUSED) 1949f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1950f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1951f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich cc = get_cc(type); 1952f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; 1953f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1954f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (GET_OPCODE(op) < SLJIT_ADD) { 1955f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(dst_r) | RN(TMP_ZERO) | RM(TMP_ZERO))); 1956f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst_r != TMP_REG1) 1957f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1958f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return emit_op_mem(compiler, (GET_OPCODE(op) == SLJIT_MOV ? WORD_SIZE : INT_SIZE) | STORE, TMP_REG1, dst, dstw); 1959f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1960f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1961f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_arg = 0; 1962f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich compiler->cache_argw = 0; 1963f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags = GET_FLAGS(op) ? SET_FLAGS : 0; 1964f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich mem_flags = WORD_SIZE; 1965f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (op & SLJIT_INT_OP) { 1966f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags |= INT_OP; 1967f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich mem_flags = INT_SIZE; 1968f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } 1969f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1970f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (src & SLJIT_MEM) { 1971f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(emit_op_mem2(compiler, mem_flags, TMP_REG1, src, srcw, dst, dstw)); 1972f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich src = TMP_REG1; 1973f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich srcw = 0; 1974f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich } else if (src & SLJIT_IMM) 1975f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich flags |= ARG1_IMM; 1976f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1977f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(TMP_ZERO))); 1978f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src, TMP_REG2); 1979f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1980f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst_r != TMP_REG1) 1981f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return SLJIT_SUCCESS; 1982f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return emit_op_mem2(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, 0, 0); 1983f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 1984f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1985f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value) 1986f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 1987f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich struct sljit_const *const_; 1988f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_si dst_r; 1989f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1990f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich CHECK_ERROR_PTR(); 1991f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich check_sljit_emit_const(compiler, dst, dstw, init_value); 1992f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich ADJUST_LOCAL_OFFSET(dst, dstw); 1993f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1994f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); 1995f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(!const_); 1996f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich set_const(const_, compiler); 1997f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 1998f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; 1999f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, init_value)); 2000f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 2001f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich if (dst & SLJIT_MEM) 2002f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw)); 2003f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich return const_; 2004f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 2005f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 2006f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr) 2007f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 2008f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins* inst = (sljit_ins*)addr; 2009f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich modify_imm64_const(inst, new_addr); 2010f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_CACHE_FLUSH(inst, inst + 4); 2011f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 2012f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich 2013f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick KralevichSLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant) 2014f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich{ 2015f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich sljit_ins* inst = (sljit_ins*)addr; 2016f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich modify_imm64_const(inst, new_constant); 2017f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich SLJIT_CACHE_FLUSH(inst, inst + 4); 2018f73ff17bddb7dc18ff9044773dd65d040e8f4fcfNick Kralevich} 2019