1/*
2 *    Stack-less Just-In-Time compiler
3 *
4 *    Copyright 2009-2012 Zoltan Herczeg (hzmester@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 64-bit arch dependent functions. */
28
29static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
30{
31	sljit_s32 shift = 32;
32	sljit_s32 shift2;
33	sljit_s32 inv = 0;
34	sljit_ins ins;
35	sljit_uw uimm;
36
37	if (!(imm & ~0xffff))
38		return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
39
40	if (imm < 0 && imm >= SIMM_MIN)
41		return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
42
43	if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
44		FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
45		return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
46	}
47
48	/* Zero extended number. */
49	uimm = imm;
50	if (imm < 0) {
51		uimm = ~imm;
52		inv = 1;
53	}
54
55	while (!(uimm & 0xff00000000000000l)) {
56		shift -= 8;
57		uimm <<= 8;
58	}
59
60	if (!(uimm & 0xf000000000000000l)) {
61		shift -= 4;
62		uimm <<= 4;
63	}
64
65	if (!(uimm & 0xc000000000000000l)) {
66		shift -= 2;
67		uimm <<= 2;
68	}
69
70	if ((sljit_sw)uimm < 0) {
71		uimm >>= 1;
72		shift += 1;
73	}
74	SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));
75
76	if (inv)
77		uimm = ~uimm;
78
79	FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
80	if (uimm & 0x0000ffff00000000l)
81		FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));
82
83	imm &= (1l << shift) - 1;
84	if (!(imm & ~0xffff)) {
85		ins = (shift == 32) ? DSLL32 : DSLL;
86		if (shift < 32)
87			ins |= SH_IMM(shift);
88		FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));
89		return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
90	}
91
92	/* Double shifts needs to be performed. */
93	uimm <<= 32;
94	shift2 = shift - 16;
95
96	while (!(uimm & 0xf000000000000000l)) {
97		shift2 -= 4;
98		uimm <<= 4;
99	}
100
101	if (!(uimm & 0xc000000000000000l)) {
102		shift2 -= 2;
103		uimm <<= 2;
104	}
105
106	if (!(uimm & 0x8000000000000000l)) {
107		shift2--;
108		uimm <<= 1;
109	}
110
111	SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));
112
113	FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));
114	FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
115	FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));
116
117	imm &= (1l << shift2) - 1;
118	return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
119}
120
121#define SELECT_OP(a, b) \
122	(!(op & SLJIT_I32_OP) ? a : b)
123
124#define EMIT_LOGICAL(op_imm, op_norm) \
125	if (flags & SRC2_IMM) { \
126		if (op & SLJIT_SET_E) \
127			FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
128		if (CHECK_FLAGS(SLJIT_SET_E)) \
129			FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
130	} \
131	else { \
132		if (op & SLJIT_SET_E) \
133			FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
134		if (CHECK_FLAGS(SLJIT_SET_E)) \
135			FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
136	}
137
138#define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \
139	if (flags & SRC2_IMM) { \
140		if (src2 >= 32) { \
141			SLJIT_ASSERT(!(op & SLJIT_I32_OP)); \
142			ins = op_dimm32; \
143			src2 -= 32; \
144		} \
145		else \
146			ins = (op & SLJIT_I32_OP) ? op_imm : op_dimm; \
147		if (op & SLJIT_SET_E) \
148			FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
149		if (CHECK_FLAGS(SLJIT_SET_E)) \
150			FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
151	} \
152	else { \
153		ins = (op & SLJIT_I32_OP) ? op_v : op_dv; \
154		if (op & SLJIT_SET_E) \
155			FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
156		if (CHECK_FLAGS(SLJIT_SET_E)) \
157			FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \
158	}
159
160static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
161	sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
162{
163	sljit_ins ins;
164
165	switch (GET_OPCODE(op)) {
166	case SLJIT_MOV:
167	case SLJIT_MOV_P:
168		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
169		if (dst != src2)
170			return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
171		return SLJIT_SUCCESS;
172
173	case SLJIT_MOV_U8:
174	case SLJIT_MOV_S8:
175		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
176		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
177			if (op == SLJIT_MOV_S8) {
178				FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
179				return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
180			}
181			return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
182		}
183		else if (dst != src2)
184			SLJIT_ASSERT_STOP();
185		return SLJIT_SUCCESS;
186
187	case SLJIT_MOV_U16:
188	case SLJIT_MOV_S16:
189		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
190		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
191			if (op == SLJIT_MOV_S16) {
192				FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
193				return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
194			}
195			return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
196		}
197		else if (dst != src2)
198			SLJIT_ASSERT_STOP();
199		return SLJIT_SUCCESS;
200
201	case SLJIT_MOV_U32:
202		SLJIT_ASSERT(!(op & SLJIT_I32_OP));
203		FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
204		return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
205
206	case SLJIT_MOV_S32:
207		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
208		return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
209
210	case SLJIT_NOT:
211		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
212		if (op & SLJIT_SET_E)
213			FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
214		if (CHECK_FLAGS(SLJIT_SET_E))
215			FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
216		return SLJIT_SUCCESS;
217
218	case SLJIT_CLZ:
219		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
220#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
221		if (op & SLJIT_SET_E)
222			FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
223		if (CHECK_FLAGS(SLJIT_SET_E))
224			FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));
225#else
226		if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
227			FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
228			return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
229		}
230		/* Nearly all instructions are unmovable in the following sequence. */
231		FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
232		/* Check zero. */
233		FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
234		FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_I32_OP) ? 32 : 64), UNMOVABLE_INS));
235		FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst)));
236		/* Loop for searching the highest bit. */
237		FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
238		FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
239		FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
240		if (op & SLJIT_SET_E)
241			return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
242#endif
243		return SLJIT_SUCCESS;
244
245	case SLJIT_ADD:
246		if (flags & SRC2_IMM) {
247			if (op & SLJIT_SET_O) {
248				if (src2 >= 0)
249					FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
250				else
251					FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
252			}
253			if (op & SLJIT_SET_E)
254				FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
255			if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
256				if (src2 >= 0)
257					FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
258				else {
259					FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
260					FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
261				}
262			}
263			/* dst may be the same as src1 or src2. */
264			if (CHECK_FLAGS(SLJIT_SET_E))
265				FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
266		}
267		else {
268			if (op & SLJIT_SET_O)
269				FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
270			if (op & SLJIT_SET_E)
271				FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
272			if (op & (SLJIT_SET_C | SLJIT_SET_O))
273				FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
274			/* dst may be the same as src1 or src2. */
275			if (CHECK_FLAGS(SLJIT_SET_E))
276				FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
277		}
278
279		/* a + b >= a | b (otherwise, the carry should be set to 1). */
280		if (op & (SLJIT_SET_C | SLJIT_SET_O))
281			FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
282		if (!(op & SLJIT_SET_O))
283			return SLJIT_SUCCESS;
284		FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
285		FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
286		FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
287		return push_inst(compiler, SELECT_OP(DSRL32, SLL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
288
289	case SLJIT_ADDC:
290		if (flags & SRC2_IMM) {
291			if (op & SLJIT_SET_C) {
292				if (src2 >= 0)
293					FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
294				else {
295					FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
296					FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
297				}
298			}
299			FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
300		} else {
301			if (op & SLJIT_SET_C)
302				FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
303			/* dst may be the same as src1 or src2. */
304			FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
305		}
306		if (op & SLJIT_SET_C)
307			FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
308
309		FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
310		if (!(op & SLJIT_SET_C))
311			return SLJIT_SUCCESS;
312
313		/* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
314		FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
315		/* Set carry flag. */
316		return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG);
317
318	case SLJIT_SUB:
319		if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
320			FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
321			src2 = TMP_REG2;
322			flags &= ~SRC2_IMM;
323		}
324
325		if (flags & SRC2_IMM) {
326			if (op & SLJIT_SET_O) {
327				if (src2 >= 0)
328					FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
329				else
330					FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
331			}
332			if (op & SLJIT_SET_E)
333				FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
334			if (op & (SLJIT_SET_C | SLJIT_SET_O))
335				FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
336			/* dst may be the same as src1 or src2. */
337			if (CHECK_FLAGS(SLJIT_SET_E))
338				FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
339		}
340		else {
341			if (op & SLJIT_SET_O)
342				FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
343			if (op & SLJIT_SET_E)
344				FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
345			if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
346				FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
347			if (op & SLJIT_SET_U)
348				FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
349			if (op & SLJIT_SET_S) {
350				FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
351				FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
352			}
353			/* dst may be the same as src1 or src2. */
354			if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
355				FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
356		}
357
358		if (!(op & SLJIT_SET_O))
359			return SLJIT_SUCCESS;
360		FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
361		FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
362		FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
363		return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
364
365	case SLJIT_SUBC:
366		if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
367			FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
368			src2 = TMP_REG2;
369			flags &= ~SRC2_IMM;
370		}
371
372		if (flags & SRC2_IMM) {
373			if (op & SLJIT_SET_C)
374				FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
375			/* dst may be the same as src1 or src2. */
376			FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
377		}
378		else {
379			if (op & SLJIT_SET_C)
380				FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
381			/* dst may be the same as src1 or src2. */
382			FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
383		}
384
385		if (op & SLJIT_SET_C)
386			FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(LESS_FLAG), LESS_FLAG));
387
388		FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
389		return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
390
391	case SLJIT_MUL:
392		SLJIT_ASSERT(!(flags & SRC2_IMM));
393		if (!(op & SLJIT_SET_O)) {
394#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
395			if (op & SLJIT_I32_OP)
396				return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
397			FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
398			return push_inst(compiler, MFLO | D(dst), DR(dst));
399#else
400			FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
401			return push_inst(compiler, MFLO | D(dst), DR(dst));
402#endif
403		}
404		FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
405		FAIL_IF(push_inst(compiler, MFHI | DA(ULESS_FLAG), ULESS_FLAG));
406		FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
407		FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(UGREATER_FLAG) | SH_IMM(31), UGREATER_FLAG));
408		return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(ULESS_FLAG) | TA(UGREATER_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
409
410	case SLJIT_AND:
411		EMIT_LOGICAL(ANDI, AND);
412		return SLJIT_SUCCESS;
413
414	case SLJIT_OR:
415		EMIT_LOGICAL(ORI, OR);
416		return SLJIT_SUCCESS;
417
418	case SLJIT_XOR:
419		EMIT_LOGICAL(XORI, XOR);
420		return SLJIT_SUCCESS;
421
422	case SLJIT_SHL:
423		EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);
424		return SLJIT_SUCCESS;
425
426	case SLJIT_LSHR:
427		EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);
428		return SLJIT_SUCCESS;
429
430	case SLJIT_ASHR:
431		EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);
432		return SLJIT_SUCCESS;
433	}
434
435	SLJIT_ASSERT_STOP();
436	return SLJIT_SUCCESS;
437}
438
439static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
440{
441	FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));
442	FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));
443	FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
444	FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));
445	FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
446	return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
447}
448
449SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
450{
451	sljit_ins *inst = (sljit_ins*)addr;
452
453	inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff);
454	inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff);
455	inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
456	inst[5] = (inst[5] & 0xffff0000) | (new_addr & 0xffff);
457	SLJIT_CACHE_FLUSH(inst, inst + 6);
458}
459
460SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
461{
462	sljit_ins *inst = (sljit_ins*)addr;
463
464	inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
465	inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
466	inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
467	inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff);
468	SLJIT_CACHE_FLUSH(inst, inst + 6);
469}
470