Home | History | Annotate | Download | only in sljit
      1 /*
      2  *    Stack-less Just-In-Time compiler
      3  *
      4  *    Copyright 2009-2012 Zoltan Herczeg (hzmester (at) freemail.hu). All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without modification, are
      7  * permitted provided that the following conditions are met:
      8  *
      9  *   1. Redistributions of source code must retain the above copyright notice, this list of
     10  *      conditions and the following disclaimer.
     11  *
     12  *   2. Redistributions in binary form must reproduce the above copyright notice, this list
     13  *      of conditions and the following disclaimer in the documentation and/or other materials
     14  *      provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
     17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
     19  * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
     21  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     22  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 /* mips 32-bit arch dependent functions. */
     28 
     29 static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
     30 {
     31 	if (!(imm & ~0xffff))
     32 		return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
     33 
     34 	if (imm < 0 && imm >= SIMM_MIN)
     35 		return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
     36 
     37 	FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
     38 	return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
     39 }
     40 
     41 #define EMIT_LOGICAL(op_imm, op_norm) \
     42 	if (flags & SRC2_IMM) { \
     43 		if (op & SLJIT_SET_E) \
     44 			FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
     45 		if (CHECK_FLAGS(SLJIT_SET_E)) \
     46 			FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
     47 	} \
     48 	else { \
     49 		if (op & SLJIT_SET_E) \
     50 			FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
     51 		if (CHECK_FLAGS(SLJIT_SET_E)) \
     52 			FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
     53 	}
     54 
     55 #define EMIT_SHIFT(op_imm, op_v) \
     56 	if (flags & SRC2_IMM) { \
     57 		if (op & SLJIT_SET_E) \
     58 			FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
     59 		if (CHECK_FLAGS(SLJIT_SET_E)) \
     60 			FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
     61 	} \
     62 	else { \
     63 		if (op & SLJIT_SET_E) \
     64 			FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
     65 		if (CHECK_FLAGS(SLJIT_SET_E)) \
     66 			FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \
     67 	}
     68 
     69 static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
     70 	sljit_si dst, sljit_si src1, sljit_sw src2)
     71 {
     72 	switch (GET_OPCODE(op)) {
     73 	case SLJIT_MOV:
     74 	case SLJIT_MOV_UI:
     75 	case SLJIT_MOV_SI:
     76 	case SLJIT_MOV_P:
     77 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
     78 		if (dst != src2)
     79 			return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
     80 		return SLJIT_SUCCESS;
     81 
     82 	case SLJIT_MOV_UB:
     83 	case SLJIT_MOV_SB:
     84 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
     85 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
     86 			if (op == SLJIT_MOV_SB) {
     87 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
     88 				return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
     89 #else
     90 				FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
     91 				return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
     92 #endif
     93 			}
     94 			return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
     95 		}
     96 		else if (dst != src2)
     97 			SLJIT_ASSERT_STOP();
     98 		return SLJIT_SUCCESS;
     99 
    100 	case SLJIT_MOV_UH:
    101 	case SLJIT_MOV_SH:
    102 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
    103 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
    104 			if (op == SLJIT_MOV_SH) {
    105 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
    106 				return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
    107 #else
    108 				FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
    109 				return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
    110 #endif
    111 			}
    112 			return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
    113 		}
    114 		else if (dst != src2)
    115 			SLJIT_ASSERT_STOP();
    116 		return SLJIT_SUCCESS;
    117 
    118 	case SLJIT_NOT:
    119 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
    120 		if (op & SLJIT_SET_E)
    121 			FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
    122 		if (CHECK_FLAGS(SLJIT_SET_E))
    123 			FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
    124 		return SLJIT_SUCCESS;
    125 
    126 	case SLJIT_CLZ:
    127 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
    128 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
    129 		if (op & SLJIT_SET_E)
    130 			FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
    131 		if (CHECK_FLAGS(SLJIT_SET_E))
    132 			FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
    133 #else
    134 		if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
    135 			FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
    136 			return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
    137 		}
    138 		/* Nearly all instructions are unmovable in the following sequence. */
    139 		FAIL_IF(push_inst(compiler, ADDU | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
    140 		/* Check zero. */
    141 		FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
    142 		FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
    143 		FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst) | IMM(-1), DR(dst)));
    144 		/* Loop for searching the highest bit. */
    145 		FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst)));
    146 		FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
    147 		FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
    148 		if (op & SLJIT_SET_E)
    149 			return push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
    150 #endif
    151 		return SLJIT_SUCCESS;
    152 
    153 	case SLJIT_ADD:
    154 		if (flags & SRC2_IMM) {
    155 			if (op & SLJIT_SET_O) {
    156 				if (src2 >= 0)
    157 					FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    158 				else
    159 					FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    160 			}
    161 			if (op & SLJIT_SET_E)
    162 				FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
    163 			if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
    164 				if (src2 >= 0)
    165 					FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
    166 				else {
    167 					FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
    168 					FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
    169 				}
    170 			}
    171 			/* dst may be the same as src1 or src2. */
    172 			if (CHECK_FLAGS(SLJIT_SET_E))
    173 				FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
    174 		}
    175 		else {
    176 			if (op & SLJIT_SET_O)
    177 				FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    178 			if (op & SLJIT_SET_E)
    179 				FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
    180 			if (op & (SLJIT_SET_C | SLJIT_SET_O))
    181 				FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
    182 			/* dst may be the same as src1 or src2. */
    183 			if (CHECK_FLAGS(SLJIT_SET_E))
    184 				FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
    185 		}
    186 
    187 		/* a + b >= a | b (otherwise, the carry should be set to 1). */
    188 		if (op & (SLJIT_SET_C | SLJIT_SET_O))
    189 			FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
    190 		if (!(op & SLJIT_SET_O))
    191 			return SLJIT_SUCCESS;
    192 		FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
    193 		FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    194 		FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    195 		return push_inst(compiler, SLL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
    196 
    197 	case SLJIT_ADDC:
    198 		if (flags & SRC2_IMM) {
    199 			if (op & SLJIT_SET_C) {
    200 				if (src2 >= 0)
    201 					FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
    202 				else {
    203 					FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
    204 					FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    205 				}
    206 			}
    207 			FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
    208 		} else {
    209 			if (op & SLJIT_SET_C)
    210 				FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    211 			/* dst may be the same as src1 or src2. */
    212 			FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
    213 		}
    214 		if (op & SLJIT_SET_C)
    215 			FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    216 
    217 		FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
    218 		if (!(op & SLJIT_SET_C))
    219 			return SLJIT_SUCCESS;
    220 
    221 		/* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
    222 		FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
    223 		/* Set carry flag. */
    224 		return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG);
    225 
    226 	case SLJIT_SUB:
    227 		if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
    228 			FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
    229 			src2 = TMP_REG2;
    230 			flags &= ~SRC2_IMM;
    231 		}
    232 
    233 		if (flags & SRC2_IMM) {
    234 			if (op & SLJIT_SET_O) {
    235 				if (src2 >= 0)
    236 					FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    237 				else
    238 					FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    239 			}
    240 			if (op & SLJIT_SET_E)
    241 				FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
    242 			if (op & (SLJIT_SET_C | SLJIT_SET_O))
    243 				FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
    244 			/* dst may be the same as src1 or src2. */
    245 			if (CHECK_FLAGS(SLJIT_SET_E))
    246 				FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
    247 		}
    248 		else {
    249 			if (op & SLJIT_SET_O)
    250 				FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    251 			if (op & SLJIT_SET_E)
    252 				FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
    253 			if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
    254 				FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
    255 			if (op & SLJIT_SET_U)
    256 				FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
    257 			if (op & SLJIT_SET_S) {
    258 				FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
    259 				FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
    260 			}
    261 			/* dst may be the same as src1 or src2. */
    262 			if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
    263 				FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
    264 		}
    265 
    266 		if (!(op & SLJIT_SET_O))
    267 			return SLJIT_SUCCESS;
    268 		FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
    269 		FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    270 		FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    271 		return push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
    272 
    273 	case SLJIT_SUBC:
    274 		if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
    275 			FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
    276 			src2 = TMP_REG2;
    277 			flags &= ~SRC2_IMM;
    278 		}
    279 
    280 		if (flags & SRC2_IMM) {
    281 			if (op & SLJIT_SET_C)
    282 				FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
    283 			/* dst may be the same as src1 or src2. */
    284 			FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
    285 		}
    286 		else {
    287 			if (op & SLJIT_SET_C)
    288 				FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
    289 			/* dst may be the same as src1 or src2. */
    290 			FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
    291 		}
    292 
    293 		if (op & SLJIT_SET_C)
    294 			FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(LESS_FLAG), LESS_FLAG));
    295 
    296 		FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
    297 		return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
    298 
    299 	case SLJIT_MUL:
    300 		SLJIT_ASSERT(!(flags & SRC2_IMM));
    301 		if (!(op & SLJIT_SET_O)) {
    302 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
    303 			return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
    304 #else
    305 			FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
    306 			return push_inst(compiler, MFLO | D(dst), DR(dst));
    307 #endif
    308 		}
    309 		FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
    310 		FAIL_IF(push_inst(compiler, MFHI | DA(ULESS_FLAG), ULESS_FLAG));
    311 		FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
    312 		FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(UGREATER_FLAG) | SH_IMM(31), UGREATER_FLAG));
    313 		return push_inst(compiler, SUBU | SA(ULESS_FLAG) | TA(UGREATER_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
    314 
    315 	case SLJIT_AND:
    316 		EMIT_LOGICAL(ANDI, AND);
    317 		return SLJIT_SUCCESS;
    318 
    319 	case SLJIT_OR:
    320 		EMIT_LOGICAL(ORI, OR);
    321 		return SLJIT_SUCCESS;
    322 
    323 	case SLJIT_XOR:
    324 		EMIT_LOGICAL(XORI, XOR);
    325 		return SLJIT_SUCCESS;
    326 
    327 	case SLJIT_SHL:
    328 		EMIT_SHIFT(SLL, SLLV);
    329 		return SLJIT_SUCCESS;
    330 
    331 	case SLJIT_LSHR:
    332 		EMIT_SHIFT(SRL, SRLV);
    333 		return SLJIT_SUCCESS;
    334 
    335 	case SLJIT_ASHR:
    336 		EMIT_SHIFT(SRA, SRAV);
    337 		return SLJIT_SUCCESS;
    338 	}
    339 
    340 	SLJIT_ASSERT_STOP();
    341 	return SLJIT_SUCCESS;
    342 }
    343 
    344 static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
    345 {
    346 	FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));
    347 	return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
    348 }
    349 
    350 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
    351 {
    352 	sljit_ins *inst = (sljit_ins*)addr;
    353 
    354 	inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
    355 	inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
    356 	SLJIT_CACHE_FLUSH(inst, inst + 2);
    357 }
    358 
    359 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
    360 {
    361 	sljit_ins *inst = (sljit_ins*)addr;
    362 
    363 	inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
    364 	inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
    365 	SLJIT_CACHE_FLUSH(inst, inst + 2);
    366 }
    367