xref: /aosp_15_r20/external/pcre/src/sljit/sljitNativeMIPS_common.c (revision 22dc650d8ae982c6770746019a6f94af92b0f024)
1*22dc650dSSadaf Ebrahimi /*
2*22dc650dSSadaf Ebrahimi  *    Stack-less Just-In-Time compiler
3*22dc650dSSadaf Ebrahimi  *
4*22dc650dSSadaf Ebrahimi  *    Copyright Zoltan Herczeg ([email protected]). All rights reserved.
5*22dc650dSSadaf Ebrahimi  *
6*22dc650dSSadaf Ebrahimi  * Redistribution and use in source and binary forms, with or without modification, are
7*22dc650dSSadaf Ebrahimi  * permitted provided that the following conditions are met:
8*22dc650dSSadaf Ebrahimi  *
9*22dc650dSSadaf Ebrahimi  *   1. Redistributions of source code must retain the above copyright notice, this list of
10*22dc650dSSadaf Ebrahimi  *      conditions and the following disclaimer.
11*22dc650dSSadaf Ebrahimi  *
12*22dc650dSSadaf Ebrahimi  *   2. Redistributions in binary form must reproduce the above copyright notice, this list
13*22dc650dSSadaf Ebrahimi  *      of conditions and the following disclaimer in the documentation and/or other materials
14*22dc650dSSadaf Ebrahimi  *      provided with the distribution.
15*22dc650dSSadaf Ebrahimi  *
16*22dc650dSSadaf Ebrahimi  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17*22dc650dSSadaf Ebrahimi  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*22dc650dSSadaf Ebrahimi  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19*22dc650dSSadaf Ebrahimi  * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*22dc650dSSadaf Ebrahimi  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21*22dc650dSSadaf Ebrahimi  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22*22dc650dSSadaf Ebrahimi  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*22dc650dSSadaf Ebrahimi  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24*22dc650dSSadaf Ebrahimi  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*22dc650dSSadaf Ebrahimi  */
26*22dc650dSSadaf Ebrahimi 
27*22dc650dSSadaf Ebrahimi /* Latest MIPS architecture. */
28*22dc650dSSadaf Ebrahimi 
29*22dc650dSSadaf Ebrahimi #ifdef HAVE_PRCTL
30*22dc650dSSadaf Ebrahimi #include <sys/prctl.h>
31*22dc650dSSadaf Ebrahimi #endif
32*22dc650dSSadaf Ebrahimi 
33*22dc650dSSadaf Ebrahimi #if !defined(__mips_hard_float) || defined(__mips_single_float)
34*22dc650dSSadaf Ebrahimi /* Disable automatic detection, covers both -msoft-float and -mno-float */
35*22dc650dSSadaf Ebrahimi #define SLJIT_IS_FPU_AVAILABLE 0
36*22dc650dSSadaf Ebrahimi #endif
37*22dc650dSSadaf Ebrahimi 
sljit_get_platform_name(void)38*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
39*22dc650dSSadaf Ebrahimi {
40*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
41*22dc650dSSadaf Ebrahimi 
42*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
43*22dc650dSSadaf Ebrahimi 	return "MIPS32-R6" SLJIT_CPUINFO;
44*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
45*22dc650dSSadaf Ebrahimi 	return "MIPS64-R6" SLJIT_CPUINFO;
46*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
47*22dc650dSSadaf Ebrahimi 
48*22dc650dSSadaf Ebrahimi #elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 5)
49*22dc650dSSadaf Ebrahimi 
50*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
51*22dc650dSSadaf Ebrahimi 	return "MIPS32-R5" SLJIT_CPUINFO;
52*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
53*22dc650dSSadaf Ebrahimi 	return "MIPS64-R5" SLJIT_CPUINFO;
54*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
55*22dc650dSSadaf Ebrahimi 
56*22dc650dSSadaf Ebrahimi #elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
57*22dc650dSSadaf Ebrahimi 
58*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
59*22dc650dSSadaf Ebrahimi 	return "MIPS32-R2" SLJIT_CPUINFO;
60*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
61*22dc650dSSadaf Ebrahimi 	return "MIPS64-R2" SLJIT_CPUINFO;
62*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
63*22dc650dSSadaf Ebrahimi 
64*22dc650dSSadaf Ebrahimi #elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
65*22dc650dSSadaf Ebrahimi 
66*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
67*22dc650dSSadaf Ebrahimi 	return "MIPS32-R1" SLJIT_CPUINFO;
68*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
69*22dc650dSSadaf Ebrahimi 	return "MIPS64-R1" SLJIT_CPUINFO;
70*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
71*22dc650dSSadaf Ebrahimi 
72*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 1 */
73*22dc650dSSadaf Ebrahimi 	return "MIPS III" SLJIT_CPUINFO;
74*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
75*22dc650dSSadaf Ebrahimi }
76*22dc650dSSadaf Ebrahimi 
77*22dc650dSSadaf Ebrahimi /* Length of an instruction word
78*22dc650dSSadaf Ebrahimi    Both for mips-32 and mips-64 */
79*22dc650dSSadaf Ebrahimi typedef sljit_u32 sljit_ins;
80*22dc650dSSadaf Ebrahimi 
81*22dc650dSSadaf Ebrahimi #define TMP_REG1	(SLJIT_NUMBER_OF_REGISTERS + 2)
82*22dc650dSSadaf Ebrahimi #define TMP_REG2	(SLJIT_NUMBER_OF_REGISTERS + 3)
83*22dc650dSSadaf Ebrahimi #define TMP_REG3	(SLJIT_NUMBER_OF_REGISTERS + 4)
84*22dc650dSSadaf Ebrahimi 
85*22dc650dSSadaf Ebrahimi /* For position independent code, t9 must contain the function address. */
86*22dc650dSSadaf Ebrahimi #define PIC_ADDR_REG	TMP_REG1
87*22dc650dSSadaf Ebrahimi 
88*22dc650dSSadaf Ebrahimi /* Floating point status register. */
89*22dc650dSSadaf Ebrahimi #define FCSR_REG	31
90*22dc650dSSadaf Ebrahimi /* Return address register. */
91*22dc650dSSadaf Ebrahimi #define RETURN_ADDR_REG	31
92*22dc650dSSadaf Ebrahimi 
93*22dc650dSSadaf Ebrahimi /* Flags are kept in volatile registers. */
94*22dc650dSSadaf Ebrahimi #define EQUAL_FLAG	3
95*22dc650dSSadaf Ebrahimi #define OTHER_FLAG	1
96*22dc650dSSadaf Ebrahimi 
97*22dc650dSSadaf Ebrahimi static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
98*22dc650dSSadaf Ebrahimi 	0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 25, 4, 31, 3, 1
99*22dc650dSSadaf Ebrahimi };
100*22dc650dSSadaf Ebrahimi 
101*22dc650dSSadaf Ebrahimi #define TMP_FREG1	(SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
102*22dc650dSSadaf Ebrahimi #define TMP_FREG2	(SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
103*22dc650dSSadaf Ebrahimi #define TMP_FREG3	(SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3)
104*22dc650dSSadaf Ebrahimi 
105*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
106*22dc650dSSadaf Ebrahimi 
107*22dc650dSSadaf Ebrahimi static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3) << 1) + 1] = {
108*22dc650dSSadaf Ebrahimi 	0,
109*22dc650dSSadaf Ebrahimi 	0, 14, 2, 4, 6, 8, 18, 30, 28, 26, 24, 22, 20,
110*22dc650dSSadaf Ebrahimi 	12, 10, 16,
111*22dc650dSSadaf Ebrahimi 	1, 15, 3, 5, 7, 9, 19, 31, 29, 27, 25, 23, 21,
112*22dc650dSSadaf Ebrahimi 	13, 11, 17
113*22dc650dSSadaf Ebrahimi };
114*22dc650dSSadaf Ebrahimi 
115*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
116*22dc650dSSadaf Ebrahimi 
117*22dc650dSSadaf Ebrahimi static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
118*22dc650dSSadaf Ebrahimi 	0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 1, 2, 3, 4, 5, 6, 7, 8, 9, 31, 30, 29, 28, 27, 26, 25, 24, 12, 11, 10
119*22dc650dSSadaf Ebrahimi };
120*22dc650dSSadaf Ebrahimi 
121*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
122*22dc650dSSadaf Ebrahimi 
123*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
124*22dc650dSSadaf Ebrahimi /*  Instrucion forms                                                     */
125*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
126*22dc650dSSadaf Ebrahimi 
127*22dc650dSSadaf Ebrahimi #define S(s)		((sljit_ins)reg_map[s] << 21)
128*22dc650dSSadaf Ebrahimi #define T(t)		((sljit_ins)reg_map[t] << 16)
129*22dc650dSSadaf Ebrahimi #define D(d)		((sljit_ins)reg_map[d] << 11)
130*22dc650dSSadaf Ebrahimi #define FT(t)		((sljit_ins)freg_map[t] << 16)
131*22dc650dSSadaf Ebrahimi #define FS(s)		((sljit_ins)freg_map[s] << 11)
132*22dc650dSSadaf Ebrahimi #define FD(d)		((sljit_ins)freg_map[d] << 6)
133*22dc650dSSadaf Ebrahimi /* Absolute registers. */
134*22dc650dSSadaf Ebrahimi #define SA(s)		((sljit_ins)(s) << 21)
135*22dc650dSSadaf Ebrahimi #define TA(t)		((sljit_ins)(t) << 16)
136*22dc650dSSadaf Ebrahimi #define DA(d)		((sljit_ins)(d) << 11)
137*22dc650dSSadaf Ebrahimi #define IMM(imm)	((sljit_ins)(imm) & 0xffff)
138*22dc650dSSadaf Ebrahimi #define SH_IMM(imm)	((sljit_ins)(imm) << 6)
139*22dc650dSSadaf Ebrahimi 
140*22dc650dSSadaf Ebrahimi #define DR(dr)		(reg_map[dr])
141*22dc650dSSadaf Ebrahimi #define FR(dr)		(freg_map[dr])
142*22dc650dSSadaf Ebrahimi #define HI(opcode)	((sljit_ins)(opcode) << 26)
143*22dc650dSSadaf Ebrahimi #define LO(opcode)	((sljit_ins)(opcode))
144*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
145*22dc650dSSadaf Ebrahimi /* CMP.cond.fmt */
146*22dc650dSSadaf Ebrahimi /* S = (20 << 21) D = (21 << 21) */
147*22dc650dSSadaf Ebrahimi #define CMP_FMT_S	(20 << 21)
148*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
149*22dc650dSSadaf Ebrahimi /* S = (16 << 21) D = (17 << 21) */
150*22dc650dSSadaf Ebrahimi #define FMT_S		(16 << 21)
151*22dc650dSSadaf Ebrahimi #define FMT_D		(17 << 21)
152*22dc650dSSadaf Ebrahimi 
153*22dc650dSSadaf Ebrahimi #define ABS_S		(HI(17) | FMT_S | LO(5))
154*22dc650dSSadaf Ebrahimi #define ADD_S		(HI(17) | FMT_S | LO(0))
155*22dc650dSSadaf Ebrahimi #define ADDIU		(HI(9))
156*22dc650dSSadaf Ebrahimi #define ADDU		(HI(0) | LO(33))
157*22dc650dSSadaf Ebrahimi #define AND		(HI(0) | LO(36))
158*22dc650dSSadaf Ebrahimi #define ANDI		(HI(12))
159*22dc650dSSadaf Ebrahimi #define B		(HI(4))
160*22dc650dSSadaf Ebrahimi #define BAL		(HI(1) | (17 << 16))
161*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
162*22dc650dSSadaf Ebrahimi #define BC1EQZ		(HI(17) | (9 << 21) | FT(TMP_FREG3))
163*22dc650dSSadaf Ebrahimi #define BC1NEZ		(HI(17) | (13 << 21) | FT(TMP_FREG3))
164*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
165*22dc650dSSadaf Ebrahimi #define BC1F		(HI(17) | (8 << 21))
166*22dc650dSSadaf Ebrahimi #define BC1T		(HI(17) | (8 << 21) | (1 << 16))
167*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
168*22dc650dSSadaf Ebrahimi #define BEQ		(HI(4))
169*22dc650dSSadaf Ebrahimi #define BGEZ		(HI(1) | (1 << 16))
170*22dc650dSSadaf Ebrahimi #define BGTZ		(HI(7))
171*22dc650dSSadaf Ebrahimi #define BLEZ		(HI(6))
172*22dc650dSSadaf Ebrahimi #define BLTZ		(HI(1) | (0 << 16))
173*22dc650dSSadaf Ebrahimi #define BNE		(HI(5))
174*22dc650dSSadaf Ebrahimi #define BREAK		(HI(0) | LO(13))
175*22dc650dSSadaf Ebrahimi #define CFC1		(HI(17) | (2 << 21))
176*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
177*22dc650dSSadaf Ebrahimi #define C_EQ_S		(HI(17) | CMP_FMT_S | LO(2))
178*22dc650dSSadaf Ebrahimi #define C_OLE_S		(HI(17) | CMP_FMT_S | LO(6))
179*22dc650dSSadaf Ebrahimi #define C_OLT_S		(HI(17) | CMP_FMT_S | LO(4))
180*22dc650dSSadaf Ebrahimi #define C_UEQ_S		(HI(17) | CMP_FMT_S | LO(3))
181*22dc650dSSadaf Ebrahimi #define C_ULE_S		(HI(17) | CMP_FMT_S | LO(7))
182*22dc650dSSadaf Ebrahimi #define C_ULT_S		(HI(17) | CMP_FMT_S | LO(5))
183*22dc650dSSadaf Ebrahimi #define C_UN_S		(HI(17) | CMP_FMT_S | LO(1))
184*22dc650dSSadaf Ebrahimi #define C_FD		(FD(TMP_FREG3))
185*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
186*22dc650dSSadaf Ebrahimi #define C_EQ_S		(HI(17) | FMT_S | LO(50))
187*22dc650dSSadaf Ebrahimi #define C_OLE_S		(HI(17) | FMT_S | LO(54))
188*22dc650dSSadaf Ebrahimi #define C_OLT_S		(HI(17) | FMT_S | LO(52))
189*22dc650dSSadaf Ebrahimi #define C_UEQ_S		(HI(17) | FMT_S | LO(51))
190*22dc650dSSadaf Ebrahimi #define C_ULE_S		(HI(17) | FMT_S | LO(55))
191*22dc650dSSadaf Ebrahimi #define C_ULT_S		(HI(17) | FMT_S | LO(53))
192*22dc650dSSadaf Ebrahimi #define C_UN_S		(HI(17) | FMT_S | LO(49))
193*22dc650dSSadaf Ebrahimi #define C_FD		(0)
194*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
195*22dc650dSSadaf Ebrahimi #define CVT_S_S		(HI(17) | FMT_S | LO(32))
196*22dc650dSSadaf Ebrahimi #define DADDIU		(HI(25))
197*22dc650dSSadaf Ebrahimi #define DADDU		(HI(0) | LO(45))
198*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
199*22dc650dSSadaf Ebrahimi #define DDIV		(HI(0) | (2 << 6) | LO(30))
200*22dc650dSSadaf Ebrahimi #define DDIVU		(HI(0) | (2 << 6) | LO(31))
201*22dc650dSSadaf Ebrahimi #define DMOD		(HI(0) | (3 << 6) | LO(30))
202*22dc650dSSadaf Ebrahimi #define DMODU		(HI(0) | (3 << 6) | LO(31))
203*22dc650dSSadaf Ebrahimi #define DIV		(HI(0) | (2 << 6) | LO(26))
204*22dc650dSSadaf Ebrahimi #define DIVU		(HI(0) | (2 << 6) | LO(27))
205*22dc650dSSadaf Ebrahimi #define DMUH		(HI(0) | (3 << 6) | LO(28))
206*22dc650dSSadaf Ebrahimi #define DMUHU		(HI(0) | (3 << 6) | LO(29))
207*22dc650dSSadaf Ebrahimi #define DMUL		(HI(0) | (2 << 6) | LO(28))
208*22dc650dSSadaf Ebrahimi #define DMULU		(HI(0) | (2 << 6) | LO(29))
209*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
210*22dc650dSSadaf Ebrahimi #define DDIV		(HI(0) | LO(30))
211*22dc650dSSadaf Ebrahimi #define DDIVU		(HI(0) | LO(31))
212*22dc650dSSadaf Ebrahimi #define DIV		(HI(0) | LO(26))
213*22dc650dSSadaf Ebrahimi #define DIVU		(HI(0) | LO(27))
214*22dc650dSSadaf Ebrahimi #define DMULT		(HI(0) | LO(28))
215*22dc650dSSadaf Ebrahimi #define DMULTU		(HI(0) | LO(29))
216*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
217*22dc650dSSadaf Ebrahimi #define DIV_S		(HI(17) | FMT_S | LO(3))
218*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
219*22dc650dSSadaf Ebrahimi #define DINSU		(HI(31) | LO(6))
220*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
221*22dc650dSSadaf Ebrahimi #define DMFC1		(HI(17) | (1 << 21))
222*22dc650dSSadaf Ebrahimi #define DMTC1		(HI(17) | (5 << 21))
223*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
224*22dc650dSSadaf Ebrahimi #define DROTR		(HI(0) | (1 << 21) | LO(58))
225*22dc650dSSadaf Ebrahimi #define DROTR32		(HI(0) | (1 << 21) | LO(62))
226*22dc650dSSadaf Ebrahimi #define DROTRV		(HI(0) | (1 << 6) | LO(22))
227*22dc650dSSadaf Ebrahimi #define DSBH		(HI(31) | (2 << 6) | LO(36))
228*22dc650dSSadaf Ebrahimi #define DSHD		(HI(31) | (5 << 6) | LO(36))
229*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
230*22dc650dSSadaf Ebrahimi #define DSLL		(HI(0) | LO(56))
231*22dc650dSSadaf Ebrahimi #define DSLL32		(HI(0) | LO(60))
232*22dc650dSSadaf Ebrahimi #define DSLLV		(HI(0) | LO(20))
233*22dc650dSSadaf Ebrahimi #define DSRA		(HI(0) | LO(59))
234*22dc650dSSadaf Ebrahimi #define DSRA32		(HI(0) | LO(63))
235*22dc650dSSadaf Ebrahimi #define DSRAV		(HI(0) | LO(23))
236*22dc650dSSadaf Ebrahimi #define DSRL		(HI(0) | LO(58))
237*22dc650dSSadaf Ebrahimi #define DSRL32		(HI(0) | LO(62))
238*22dc650dSSadaf Ebrahimi #define DSRLV		(HI(0) | LO(22))
239*22dc650dSSadaf Ebrahimi #define DSUBU		(HI(0) | LO(47))
240*22dc650dSSadaf Ebrahimi #define J		(HI(2))
241*22dc650dSSadaf Ebrahimi #define JAL		(HI(3))
242*22dc650dSSadaf Ebrahimi #define JALR		(HI(0) | LO(9))
243*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
244*22dc650dSSadaf Ebrahimi #define JR		(HI(0) | LO(9))
245*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
246*22dc650dSSadaf Ebrahimi #define JR		(HI(0) | LO(8))
247*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
248*22dc650dSSadaf Ebrahimi #define LD		(HI(55))
249*22dc650dSSadaf Ebrahimi #define LDL		(HI(26))
250*22dc650dSSadaf Ebrahimi #define LDR		(HI(27))
251*22dc650dSSadaf Ebrahimi #define LDC1		(HI(53))
252*22dc650dSSadaf Ebrahimi #define LUI		(HI(15))
253*22dc650dSSadaf Ebrahimi #define LW		(HI(35))
254*22dc650dSSadaf Ebrahimi #define LWL		(HI(34))
255*22dc650dSSadaf Ebrahimi #define LWR		(HI(38))
256*22dc650dSSadaf Ebrahimi #define LWC1		(HI(49))
257*22dc650dSSadaf Ebrahimi #define MFC1		(HI(17))
258*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
259*22dc650dSSadaf Ebrahimi #define MFHC1		(HI(17) | (3 << 21))
260*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
261*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
262*22dc650dSSadaf Ebrahimi #define MOD		(HI(0) | (3 << 6) | LO(26))
263*22dc650dSSadaf Ebrahimi #define MODU		(HI(0) | (3 << 6) | LO(27))
264*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
265*22dc650dSSadaf Ebrahimi #define MFHI		(HI(0) | LO(16))
266*22dc650dSSadaf Ebrahimi #define MFLO		(HI(0) | LO(18))
267*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
268*22dc650dSSadaf Ebrahimi #define MTC1		(HI(17) | (4 << 21))
269*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
270*22dc650dSSadaf Ebrahimi #define MTHC1		(HI(17) | (7 << 21))
271*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
272*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
273*22dc650dSSadaf Ebrahimi #define MUH		(HI(0) | (3 << 6) | LO(24))
274*22dc650dSSadaf Ebrahimi #define MUHU		(HI(0) | (3 << 6) | LO(25))
275*22dc650dSSadaf Ebrahimi #define MUL		(HI(0) | (2 << 6) | LO(24))
276*22dc650dSSadaf Ebrahimi #define MULU		(HI(0) | (2 << 6) | LO(25))
277*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
278*22dc650dSSadaf Ebrahimi #define MULT		(HI(0) | LO(24))
279*22dc650dSSadaf Ebrahimi #define MULTU		(HI(0) | LO(25))
280*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
281*22dc650dSSadaf Ebrahimi #define MUL_S		(HI(17) | FMT_S | LO(2))
282*22dc650dSSadaf Ebrahimi #define NEG_S		(HI(17) | FMT_S | LO(7))
283*22dc650dSSadaf Ebrahimi #define NOP		(HI(0) | LO(0))
284*22dc650dSSadaf Ebrahimi #define NOR		(HI(0) | LO(39))
285*22dc650dSSadaf Ebrahimi #define OR		(HI(0) | LO(37))
286*22dc650dSSadaf Ebrahimi #define ORI		(HI(13))
287*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
288*22dc650dSSadaf Ebrahimi #define ROTR		(HI(0) | (1 << 21) | LO(2))
289*22dc650dSSadaf Ebrahimi #define ROTRV		(HI(0) | (1 << 6) | LO(6))
290*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
291*22dc650dSSadaf Ebrahimi #define SD		(HI(63))
292*22dc650dSSadaf Ebrahimi #define SDL		(HI(44))
293*22dc650dSSadaf Ebrahimi #define SDR		(HI(45))
294*22dc650dSSadaf Ebrahimi #define SDC1		(HI(61))
295*22dc650dSSadaf Ebrahimi #define SLT		(HI(0) | LO(42))
296*22dc650dSSadaf Ebrahimi #define SLTI		(HI(10))
297*22dc650dSSadaf Ebrahimi #define SLTIU		(HI(11))
298*22dc650dSSadaf Ebrahimi #define SLTU		(HI(0) | LO(43))
299*22dc650dSSadaf Ebrahimi #define SLL		(HI(0) | LO(0))
300*22dc650dSSadaf Ebrahimi #define SLLV		(HI(0) | LO(4))
301*22dc650dSSadaf Ebrahimi #define SRL		(HI(0) | LO(2))
302*22dc650dSSadaf Ebrahimi #define SRLV		(HI(0) | LO(6))
303*22dc650dSSadaf Ebrahimi #define SRA		(HI(0) | LO(3))
304*22dc650dSSadaf Ebrahimi #define SRAV		(HI(0) | LO(7))
305*22dc650dSSadaf Ebrahimi #define SUB_S		(HI(17) | FMT_S | LO(1))
306*22dc650dSSadaf Ebrahimi #define SUBU		(HI(0) | LO(35))
307*22dc650dSSadaf Ebrahimi #define SW		(HI(43))
308*22dc650dSSadaf Ebrahimi #define SWL		(HI(42))
309*22dc650dSSadaf Ebrahimi #define SWR		(HI(46))
310*22dc650dSSadaf Ebrahimi #define SWC1		(HI(57))
311*22dc650dSSadaf Ebrahimi #define TRUNC_W_S	(HI(17) | FMT_S | LO(13))
312*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
313*22dc650dSSadaf Ebrahimi #define WSBH		(HI(31) | (2 << 6) | LO(32))
314*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
315*22dc650dSSadaf Ebrahimi #define XOR		(HI(0) | LO(38))
316*22dc650dSSadaf Ebrahimi #define XORI		(HI(14))
317*22dc650dSSadaf Ebrahimi 
318*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
319*22dc650dSSadaf Ebrahimi #define CLZ		(HI(28) | LO(32))
320*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
321*22dc650dSSadaf Ebrahimi #define DCLZ		(LO(18))
322*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
323*22dc650dSSadaf Ebrahimi #define DCLZ		(HI(28) | LO(36))
324*22dc650dSSadaf Ebrahimi #define MOVF		(HI(0) | (0 << 16) | LO(1))
325*22dc650dSSadaf Ebrahimi #define MOVF_S		(HI(17) | FMT_S | (0 << 16) | LO(17))
326*22dc650dSSadaf Ebrahimi #define MOVN		(HI(0) | LO(11))
327*22dc650dSSadaf Ebrahimi #define MOVN_S		(HI(17) | FMT_S | LO(19))
328*22dc650dSSadaf Ebrahimi #define MOVT		(HI(0) | (1 << 16) | LO(1))
329*22dc650dSSadaf Ebrahimi #define MOVT_S		(HI(17) | FMT_S | (1 << 16) | LO(17))
330*22dc650dSSadaf Ebrahimi #define MOVZ		(HI(0) | LO(10))
331*22dc650dSSadaf Ebrahimi #define MOVZ_S		(HI(17) | FMT_S | LO(18))
332*22dc650dSSadaf Ebrahimi #define MUL		(HI(28) | LO(2))
333*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
334*22dc650dSSadaf Ebrahimi #define PREF		(HI(51))
335*22dc650dSSadaf Ebrahimi #define PREFX		(HI(19) | LO(15))
336*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
337*22dc650dSSadaf Ebrahimi #define SEB		(HI(31) | (16 << 6) | LO(32))
338*22dc650dSSadaf Ebrahimi #define SEH		(HI(31) | (24 << 6) | LO(32))
339*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
340*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 1 */
341*22dc650dSSadaf Ebrahimi 
342*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
343*22dc650dSSadaf Ebrahimi #define ADDU_W		ADDU
344*22dc650dSSadaf Ebrahimi #define ADDIU_W		ADDIU
345*22dc650dSSadaf Ebrahimi #define SLL_W		SLL
346*22dc650dSSadaf Ebrahimi #define SRA_W		SRA
347*22dc650dSSadaf Ebrahimi #define SUBU_W		SUBU
348*22dc650dSSadaf Ebrahimi #define STORE_W		SW
349*22dc650dSSadaf Ebrahimi #define LOAD_W		LW
350*22dc650dSSadaf Ebrahimi #else
351*22dc650dSSadaf Ebrahimi #define ADDU_W		DADDU
352*22dc650dSSadaf Ebrahimi #define ADDIU_W		DADDIU
353*22dc650dSSadaf Ebrahimi #define SLL_W		DSLL
354*22dc650dSSadaf Ebrahimi #define SRA_W		DSRA
355*22dc650dSSadaf Ebrahimi #define SUBU_W		DSUBU
356*22dc650dSSadaf Ebrahimi #define STORE_W		SD
357*22dc650dSSadaf Ebrahimi #define LOAD_W		LD
358*22dc650dSSadaf Ebrahimi #endif
359*22dc650dSSadaf Ebrahimi 
360*22dc650dSSadaf Ebrahimi #define MOV_fmt(f)	(HI(17) | f | LO(6))
361*22dc650dSSadaf Ebrahimi 
362*22dc650dSSadaf Ebrahimi #define SIMM_MAX	(0x7fff)
363*22dc650dSSadaf Ebrahimi #define SIMM_MIN	(-0x8000)
364*22dc650dSSadaf Ebrahimi #define UIMM_MAX	(0xffff)
365*22dc650dSSadaf Ebrahimi 
366*22dc650dSSadaf Ebrahimi #define CPU_FEATURE_DETECTED	(1 << 0)
367*22dc650dSSadaf Ebrahimi #define CPU_FEATURE_FPU		(1 << 1)
368*22dc650dSSadaf Ebrahimi #define CPU_FEATURE_FP64	(1 << 2)
369*22dc650dSSadaf Ebrahimi #define CPU_FEATURE_FR		(1 << 3)
370*22dc650dSSadaf Ebrahimi 
371*22dc650dSSadaf Ebrahimi static sljit_u32 cpu_feature_list = 0;
372*22dc650dSSadaf Ebrahimi 
373*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
374*22dc650dSSadaf Ebrahimi 	&& (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
375*22dc650dSSadaf Ebrahimi 
function_check_is_freg(struct sljit_compiler * compiler,sljit_s32 fr,sljit_s32 is_32)376*22dc650dSSadaf Ebrahimi static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32)
377*22dc650dSSadaf Ebrahimi {
378*22dc650dSSadaf Ebrahimi 	if (compiler->scratches == -1)
379*22dc650dSSadaf Ebrahimi 		return 0;
380*22dc650dSSadaf Ebrahimi 
381*22dc650dSSadaf Ebrahimi 	if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0))
382*22dc650dSSadaf Ebrahimi 		fr -= SLJIT_F64_SECOND(0);
383*22dc650dSSadaf Ebrahimi 
384*22dc650dSSadaf Ebrahimi 	return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches))
385*22dc650dSSadaf Ebrahimi 		|| (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0)
386*22dc650dSSadaf Ebrahimi 		|| (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));
387*22dc650dSSadaf Ebrahimi }
388*22dc650dSSadaf Ebrahimi 
389*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_ARGUMENT_CHECKS */
390*22dc650dSSadaf Ebrahimi 
get_cpu_features(void)391*22dc650dSSadaf Ebrahimi static void get_cpu_features(void)
392*22dc650dSSadaf Ebrahimi {
393*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_IS_FPU_AVAILABLE) && defined(__GNUC__)
394*22dc650dSSadaf Ebrahimi 	sljit_u32 fir = 0;
395*22dc650dSSadaf Ebrahimi #endif /* !SLJIT_IS_FPU_AVAILABLE && __GNUC__ */
396*22dc650dSSadaf Ebrahimi 	sljit_u32 feature_list = CPU_FEATURE_DETECTED;
397*22dc650dSSadaf Ebrahimi 
398*22dc650dSSadaf Ebrahimi #if defined(SLJIT_IS_FPU_AVAILABLE)
399*22dc650dSSadaf Ebrahimi #if SLJIT_IS_FPU_AVAILABLE
400*22dc650dSSadaf Ebrahimi 	feature_list |= CPU_FEATURE_FPU;
401*22dc650dSSadaf Ebrahimi #if SLJIT_IS_FPU_AVAILABLE == 64
402*22dc650dSSadaf Ebrahimi 	feature_list |= CPU_FEATURE_FP64;
403*22dc650dSSadaf Ebrahimi #endif /* SLJIT_IS_FPU_AVAILABLE == 64 */
404*22dc650dSSadaf Ebrahimi #endif /* SLJIT_IS_FPU_AVAILABLE */
405*22dc650dSSadaf Ebrahimi #elif defined(__GNUC__)
406*22dc650dSSadaf Ebrahimi 	__asm__ ("cfc1 %0, $0" : "=r"(fir));
407*22dc650dSSadaf Ebrahimi 	if ((fir & (0x3 << 16)) == (0x3 << 16))
408*22dc650dSSadaf Ebrahimi 		feature_list |= CPU_FEATURE_FPU;
409*22dc650dSSadaf Ebrahimi 
410*22dc650dSSadaf Ebrahimi #if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64) \
411*22dc650dSSadaf Ebrahimi 	&& (!defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV < 2)
412*22dc650dSSadaf Ebrahimi 	if ((feature_list & CPU_FEATURE_FPU))
413*22dc650dSSadaf Ebrahimi 		feature_list |= CPU_FEATURE_FP64;
414*22dc650dSSadaf Ebrahimi #else /* SLJIT_CONFIG_MIPS32 || SLJIT_MIPS_REV >= 2 */
415*22dc650dSSadaf Ebrahimi 	if ((fir & (1 << 22)))
416*22dc650dSSadaf Ebrahimi 		feature_list |= CPU_FEATURE_FP64;
417*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 && SLJIT_MIPS_REV < 2 */
418*22dc650dSSadaf Ebrahimi #endif /* SLJIT_IS_FPU_AVAILABLE */
419*22dc650dSSadaf Ebrahimi 
420*22dc650dSSadaf Ebrahimi 	if ((feature_list & CPU_FEATURE_FPU) && (feature_list & CPU_FEATURE_FP64)) {
421*22dc650dSSadaf Ebrahimi #if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32
422*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 6
423*22dc650dSSadaf Ebrahimi 		feature_list |= CPU_FEATURE_FR;
424*22dc650dSSadaf Ebrahimi #elif defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 0
425*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 5
426*22dc650dSSadaf Ebrahimi 		feature_list |= CPU_FEATURE_FR;
427*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 5 */
428*22dc650dSSadaf Ebrahimi #else
429*22dc650dSSadaf Ebrahimi 		sljit_s32 flag = -1;
430*22dc650dSSadaf Ebrahimi #ifndef FR_GET_FP_MODE
431*22dc650dSSadaf Ebrahimi 		sljit_f64 zero = 0.0;
432*22dc650dSSadaf Ebrahimi #else /* PR_GET_FP_MODE */
433*22dc650dSSadaf Ebrahimi 		flag = prctl(PR_GET_FP_MODE);
434*22dc650dSSadaf Ebrahimi 
435*22dc650dSSadaf Ebrahimi 		if (flag > 0)
436*22dc650dSSadaf Ebrahimi 			feature_list |= CPU_FEATURE_FR;
437*22dc650dSSadaf Ebrahimi #endif /* FP_GET_PR_MODE */
438*22dc650dSSadaf Ebrahimi #if ((defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 2) \
439*22dc650dSSadaf Ebrahimi 	|| (!defined(PR_GET_FP_MODE) && (!defined(SLJIT_DETECT_FR) || SLJIT_DETECT_FR >= 1))) \
440*22dc650dSSadaf Ebrahimi 	&& (defined(__GNUC__) && (defined(__mips) && __mips >= 2))
441*22dc650dSSadaf Ebrahimi 		if (flag < 0) {
442*22dc650dSSadaf Ebrahimi 			__asm__ (".set oddspreg\n"
443*22dc650dSSadaf Ebrahimi 				"lwc1 $f17, %0\n"
444*22dc650dSSadaf Ebrahimi 				"ldc1 $f16, %1\n"
445*22dc650dSSadaf Ebrahimi 				"swc1 $f17, %0\n"
446*22dc650dSSadaf Ebrahimi 			: "+m" (flag) : "m" (zero) : "$f16", "$f17");
447*22dc650dSSadaf Ebrahimi 			if (flag)
448*22dc650dSSadaf Ebrahimi 				feature_list |= CPU_FEATURE_FR;
449*22dc650dSSadaf Ebrahimi 		}
450*22dc650dSSadaf Ebrahimi #endif /* (!PR_GET_FP_MODE || (PR_GET_FP_MODE && SLJIT_DETECT_FR == 2)) && __GNUC__ */
451*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
452*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
453*22dc650dSSadaf Ebrahimi 		/* StatusFR=1 is the only mode supported by the code in MIPS64 */
454*22dc650dSSadaf Ebrahimi 		feature_list |= CPU_FEATURE_FR;
455*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
456*22dc650dSSadaf Ebrahimi 	}
457*22dc650dSSadaf Ebrahimi 
458*22dc650dSSadaf Ebrahimi 	cpu_feature_list = feature_list;
459*22dc650dSSadaf Ebrahimi }
460*22dc650dSSadaf Ebrahimi 
461*22dc650dSSadaf Ebrahimi /* dest_reg is the absolute name of the register
462*22dc650dSSadaf Ebrahimi    Useful for reordering instructions in the delay slot. */
push_inst(struct sljit_compiler * compiler,sljit_ins ins,sljit_s32 delay_slot)463*22dc650dSSadaf Ebrahimi static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)
464*22dc650dSSadaf Ebrahimi {
465*22dc650dSSadaf Ebrahimi 	sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
466*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS
467*22dc650dSSadaf Ebrahimi 		|| (sljit_ins)delay_slot == ((ins >> 11) & 0x1f)
468*22dc650dSSadaf Ebrahimi 		|| (sljit_ins)delay_slot == ((ins >> 16) & 0x1f));
469*22dc650dSSadaf Ebrahimi 	FAIL_IF(!ptr);
470*22dc650dSSadaf Ebrahimi 	*ptr = ins;
471*22dc650dSSadaf Ebrahimi 	compiler->size++;
472*22dc650dSSadaf Ebrahimi 	compiler->delay_slot = delay_slot;
473*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
474*22dc650dSSadaf Ebrahimi }
475*22dc650dSSadaf Ebrahimi 
invert_branch(sljit_uw flags)476*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_ins invert_branch(sljit_uw flags)
477*22dc650dSSadaf Ebrahimi {
478*22dc650dSSadaf Ebrahimi 	if (flags & IS_BIT26_COND)
479*22dc650dSSadaf Ebrahimi 		return (1 << 26);
480*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
481*22dc650dSSadaf Ebrahimi 	if (flags & IS_BIT23_COND)
482*22dc650dSSadaf Ebrahimi 		return (1 << 23);
483*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
484*22dc650dSSadaf Ebrahimi 	return (1 << 16);
485*22dc650dSSadaf Ebrahimi }
486*22dc650dSSadaf Ebrahimi 
detect_jump_type(struct sljit_jump * jump,sljit_ins * code,sljit_sw executable_offset)487*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
488*22dc650dSSadaf Ebrahimi {
489*22dc650dSSadaf Ebrahimi 	sljit_sw diff;
490*22dc650dSSadaf Ebrahimi 	sljit_uw target_addr;
491*22dc650dSSadaf Ebrahimi 	sljit_ins *inst;
492*22dc650dSSadaf Ebrahimi 	sljit_ins saved_inst;
493*22dc650dSSadaf Ebrahimi 
494*22dc650dSSadaf Ebrahimi 	inst = (sljit_ins *)jump->addr;
495*22dc650dSSadaf Ebrahimi 
496*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
497*22dc650dSSadaf Ebrahimi 	if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
498*22dc650dSSadaf Ebrahimi 		goto exit;
499*22dc650dSSadaf Ebrahimi #else
500*22dc650dSSadaf Ebrahimi 	if (jump->flags & SLJIT_REWRITABLE_JUMP)
501*22dc650dSSadaf Ebrahimi 		goto exit;
502*22dc650dSSadaf Ebrahimi #endif
503*22dc650dSSadaf Ebrahimi 
504*22dc650dSSadaf Ebrahimi 	if (jump->flags & JUMP_ADDR)
505*22dc650dSSadaf Ebrahimi 		target_addr = jump->u.target;
506*22dc650dSSadaf Ebrahimi 	else {
507*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(jump->u.label != NULL);
508*22dc650dSSadaf Ebrahimi 		target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
509*22dc650dSSadaf Ebrahimi 	}
510*22dc650dSSadaf Ebrahimi 
511*22dc650dSSadaf Ebrahimi 	if (jump->flags & IS_COND)
512*22dc650dSSadaf Ebrahimi 		inst--;
513*22dc650dSSadaf Ebrahimi 
514*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
515*22dc650dSSadaf Ebrahimi 	if (jump->flags & IS_CALL)
516*22dc650dSSadaf Ebrahimi 		goto preserve_addr;
517*22dc650dSSadaf Ebrahimi #endif
518*22dc650dSSadaf Ebrahimi 
519*22dc650dSSadaf Ebrahimi 	/* B instructions. */
520*22dc650dSSadaf Ebrahimi 	if (jump->flags & IS_MOVABLE) {
521*22dc650dSSadaf Ebrahimi 		diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;
522*22dc650dSSadaf Ebrahimi 		if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
523*22dc650dSSadaf Ebrahimi 			jump->flags |= PATCH_B;
524*22dc650dSSadaf Ebrahimi 
525*22dc650dSSadaf Ebrahimi 			if (!(jump->flags & IS_COND)) {
526*22dc650dSSadaf Ebrahimi 				inst[0] = inst[-1];
527*22dc650dSSadaf Ebrahimi 				inst[-1] = (jump->flags & IS_JAL) ? BAL : B;
528*22dc650dSSadaf Ebrahimi 				jump->addr -= sizeof(sljit_ins);
529*22dc650dSSadaf Ebrahimi 				return inst;
530*22dc650dSSadaf Ebrahimi 			}
531*22dc650dSSadaf Ebrahimi 			saved_inst = inst[0];
532*22dc650dSSadaf Ebrahimi 			inst[0] = inst[-1];
533*22dc650dSSadaf Ebrahimi 			inst[-1] = saved_inst ^ invert_branch(jump->flags);
534*22dc650dSSadaf Ebrahimi 			jump->addr -= 2 * sizeof(sljit_ins);
535*22dc650dSSadaf Ebrahimi 			return inst;
536*22dc650dSSadaf Ebrahimi 		}
537*22dc650dSSadaf Ebrahimi 	} else {
538*22dc650dSSadaf Ebrahimi 		diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;
539*22dc650dSSadaf Ebrahimi 		if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
540*22dc650dSSadaf Ebrahimi 			jump->flags |= PATCH_B;
541*22dc650dSSadaf Ebrahimi 
542*22dc650dSSadaf Ebrahimi 			if (!(jump->flags & IS_COND)) {
543*22dc650dSSadaf Ebrahimi 				inst[0] = (jump->flags & IS_JAL) ? BAL : B;
544*22dc650dSSadaf Ebrahimi 				/* Keep inst[1] */
545*22dc650dSSadaf Ebrahimi 				return inst + 1;
546*22dc650dSSadaf Ebrahimi 			}
547*22dc650dSSadaf Ebrahimi 			inst[0] ^= invert_branch(jump->flags);
548*22dc650dSSadaf Ebrahimi 			inst[1] = NOP;
549*22dc650dSSadaf Ebrahimi 			jump->addr -= sizeof(sljit_ins);
550*22dc650dSSadaf Ebrahimi 			return inst + 1;
551*22dc650dSSadaf Ebrahimi 		}
552*22dc650dSSadaf Ebrahimi 	}
553*22dc650dSSadaf Ebrahimi 
554*22dc650dSSadaf Ebrahimi 	if (jump->flags & IS_COND) {
555*22dc650dSSadaf Ebrahimi 		if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
556*22dc650dSSadaf Ebrahimi 			jump->flags |= PATCH_J;
557*22dc650dSSadaf Ebrahimi 			saved_inst = inst[0];
558*22dc650dSSadaf Ebrahimi 			inst[0] = inst[-1];
559*22dc650dSSadaf Ebrahimi 			inst[-1] = (saved_inst & 0xffff0000) | 3;
560*22dc650dSSadaf Ebrahimi 			inst[1] = J;
561*22dc650dSSadaf Ebrahimi 			inst[2] = NOP;
562*22dc650dSSadaf Ebrahimi 			return inst + 2;
563*22dc650dSSadaf Ebrahimi 		}
564*22dc650dSSadaf Ebrahimi 		else if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
565*22dc650dSSadaf Ebrahimi 			jump->flags |= PATCH_J;
566*22dc650dSSadaf Ebrahimi 			inst[0] = (inst[0] & 0xffff0000) | 3;
567*22dc650dSSadaf Ebrahimi 			inst[1] = NOP;
568*22dc650dSSadaf Ebrahimi 			inst[2] = J;
569*22dc650dSSadaf Ebrahimi 			inst[3] = NOP;
570*22dc650dSSadaf Ebrahimi 			jump->addr += sizeof(sljit_ins);
571*22dc650dSSadaf Ebrahimi 			return inst + 3;
572*22dc650dSSadaf Ebrahimi 		}
573*22dc650dSSadaf Ebrahimi 	}
574*22dc650dSSadaf Ebrahimi 	else {
575*22dc650dSSadaf Ebrahimi 		/* J instuctions. */
576*22dc650dSSadaf Ebrahimi 		if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == (jump->addr & ~(sljit_uw)0xfffffff)) {
577*22dc650dSSadaf Ebrahimi 			jump->flags |= PATCH_J;
578*22dc650dSSadaf Ebrahimi 			inst[0] = inst[-1];
579*22dc650dSSadaf Ebrahimi 			inst[-1] = (jump->flags & IS_JAL) ? JAL : J;
580*22dc650dSSadaf Ebrahimi 			jump->addr -= sizeof(sljit_ins);
581*22dc650dSSadaf Ebrahimi 			return inst;
582*22dc650dSSadaf Ebrahimi 		}
583*22dc650dSSadaf Ebrahimi 
584*22dc650dSSadaf Ebrahimi 		if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
585*22dc650dSSadaf Ebrahimi 			jump->flags |= PATCH_J;
586*22dc650dSSadaf Ebrahimi 			inst[0] = (jump->flags & IS_JAL) ? JAL : J;
587*22dc650dSSadaf Ebrahimi 			/* Keep inst[1] */
588*22dc650dSSadaf Ebrahimi 			return inst + 1;
589*22dc650dSSadaf Ebrahimi 		}
590*22dc650dSSadaf Ebrahimi 	}
591*22dc650dSSadaf Ebrahimi 
592*22dc650dSSadaf Ebrahimi 	if (jump->flags & IS_COND)
593*22dc650dSSadaf Ebrahimi 		inst++;
594*22dc650dSSadaf Ebrahimi 
595*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
596*22dc650dSSadaf Ebrahimi preserve_addr:
597*22dc650dSSadaf Ebrahimi 	if (target_addr <= 0x7fffffff) {
598*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_ABS32;
599*22dc650dSSadaf Ebrahimi 		if (jump->flags & IS_COND)
600*22dc650dSSadaf Ebrahimi 			inst[-1] -= 4;
601*22dc650dSSadaf Ebrahimi 
602*22dc650dSSadaf Ebrahimi 		inst[2] = inst[0];
603*22dc650dSSadaf Ebrahimi 		inst[3] = inst[1];
604*22dc650dSSadaf Ebrahimi 		return inst + 3;
605*22dc650dSSadaf Ebrahimi 	}
606*22dc650dSSadaf Ebrahimi 	if (target_addr <= 0x7fffffffffffl) {
607*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_ABS48;
608*22dc650dSSadaf Ebrahimi 		if (jump->flags & IS_COND)
609*22dc650dSSadaf Ebrahimi 			inst[-1] -= 2;
610*22dc650dSSadaf Ebrahimi 
611*22dc650dSSadaf Ebrahimi 		inst[4] = inst[0];
612*22dc650dSSadaf Ebrahimi 		inst[5] = inst[1];
613*22dc650dSSadaf Ebrahimi 		return inst + 5;
614*22dc650dSSadaf Ebrahimi 	}
615*22dc650dSSadaf Ebrahimi #endif
616*22dc650dSSadaf Ebrahimi 
617*22dc650dSSadaf Ebrahimi exit:
618*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
619*22dc650dSSadaf Ebrahimi 	inst[2] = inst[0];
620*22dc650dSSadaf Ebrahimi 	inst[3] = inst[1];
621*22dc650dSSadaf Ebrahimi 	return inst + 3;
622*22dc650dSSadaf Ebrahimi #else
623*22dc650dSSadaf Ebrahimi 	inst[6] = inst[0];
624*22dc650dSSadaf Ebrahimi 	inst[7] = inst[1];
625*22dc650dSSadaf Ebrahimi 	return inst + 7;
626*22dc650dSSadaf Ebrahimi #endif
627*22dc650dSSadaf Ebrahimi }
628*22dc650dSSadaf Ebrahimi 
629*22dc650dSSadaf Ebrahimi #ifdef __GNUC__
sljit_cache_flush(void * code,void * code_ptr)630*22dc650dSSadaf Ebrahimi static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr)
631*22dc650dSSadaf Ebrahimi {
632*22dc650dSSadaf Ebrahimi 	SLJIT_CACHE_FLUSH(code, code_ptr);
633*22dc650dSSadaf Ebrahimi }
634*22dc650dSSadaf Ebrahimi #endif
635*22dc650dSSadaf Ebrahimi 
636*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
637*22dc650dSSadaf Ebrahimi 
mov_addr_get_length(struct sljit_jump * jump,sljit_ins * code,sljit_sw executable_offset)638*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
639*22dc650dSSadaf Ebrahimi {
640*22dc650dSSadaf Ebrahimi 	sljit_uw addr;
641*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(executable_offset);
642*22dc650dSSadaf Ebrahimi 
643*22dc650dSSadaf Ebrahimi 	if (jump->flags & JUMP_ADDR)
644*22dc650dSSadaf Ebrahimi 		addr = jump->u.target;
645*22dc650dSSadaf Ebrahimi 	else
646*22dc650dSSadaf Ebrahimi 		addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
647*22dc650dSSadaf Ebrahimi 
648*22dc650dSSadaf Ebrahimi 	if (addr < 0x80000000l) {
649*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_ABS32;
650*22dc650dSSadaf Ebrahimi 		return 1;
651*22dc650dSSadaf Ebrahimi 	}
652*22dc650dSSadaf Ebrahimi 
653*22dc650dSSadaf Ebrahimi 	if (addr < 0x800000000000l) {
654*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_ABS48;
655*22dc650dSSadaf Ebrahimi 		return 3;
656*22dc650dSSadaf Ebrahimi 	}
657*22dc650dSSadaf Ebrahimi 
658*22dc650dSSadaf Ebrahimi 	return 5;
659*22dc650dSSadaf Ebrahimi }
660*22dc650dSSadaf Ebrahimi 
661*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
662*22dc650dSSadaf Ebrahimi 
load_addr_to_reg(struct sljit_jump * jump)663*22dc650dSSadaf Ebrahimi static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump)
664*22dc650dSSadaf Ebrahimi {
665*22dc650dSSadaf Ebrahimi 	sljit_uw flags = jump->flags;
666*22dc650dSSadaf Ebrahimi 	sljit_ins *ins = (sljit_ins*)jump->addr;
667*22dc650dSSadaf Ebrahimi 	sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
668*22dc650dSSadaf Ebrahimi 	sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : PIC_ADDR_REG;
669*22dc650dSSadaf Ebrahimi 
670*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
671*22dc650dSSadaf Ebrahimi 	ins[0] = LUI | T(reg) | IMM(addr >> 16);
672*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
673*22dc650dSSadaf Ebrahimi 	if (flags & PATCH_ABS32) {
674*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(addr < 0x80000000l);
675*22dc650dSSadaf Ebrahimi 		ins[0] = LUI | T(reg) | IMM(addr >> 16);
676*22dc650dSSadaf Ebrahimi 	}
677*22dc650dSSadaf Ebrahimi 	else if (flags & PATCH_ABS48) {
678*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(addr < 0x800000000000l);
679*22dc650dSSadaf Ebrahimi 		ins[0] = LUI | T(reg) | IMM(addr >> 32);
680*22dc650dSSadaf Ebrahimi 		ins[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
681*22dc650dSSadaf Ebrahimi 		ins[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
682*22dc650dSSadaf Ebrahimi 		ins += 2;
683*22dc650dSSadaf Ebrahimi 	}
684*22dc650dSSadaf Ebrahimi 	else {
685*22dc650dSSadaf Ebrahimi 		ins[0] = LUI | T(reg) | IMM(addr >> 48);
686*22dc650dSSadaf Ebrahimi 		ins[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);
687*22dc650dSSadaf Ebrahimi 		ins[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
688*22dc650dSSadaf Ebrahimi 		ins[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
689*22dc650dSSadaf Ebrahimi 		ins[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);
690*22dc650dSSadaf Ebrahimi 		ins += 4;
691*22dc650dSSadaf Ebrahimi 	}
692*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
693*22dc650dSSadaf Ebrahimi 
694*22dc650dSSadaf Ebrahimi 	ins[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);
695*22dc650dSSadaf Ebrahimi }
696*22dc650dSSadaf Ebrahimi 
sljit_generate_code(struct sljit_compiler * compiler,sljit_s32 options,void * exec_allocator_data)697*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
698*22dc650dSSadaf Ebrahimi {
699*22dc650dSSadaf Ebrahimi 	struct sljit_memory_fragment *buf;
700*22dc650dSSadaf Ebrahimi 	sljit_ins *code;
701*22dc650dSSadaf Ebrahimi 	sljit_ins *code_ptr;
702*22dc650dSSadaf Ebrahimi 	sljit_ins *buf_ptr;
703*22dc650dSSadaf Ebrahimi 	sljit_ins *buf_end;
704*22dc650dSSadaf Ebrahimi 	sljit_uw word_count;
705*22dc650dSSadaf Ebrahimi 	SLJIT_NEXT_DEFINE_TYPES;
706*22dc650dSSadaf Ebrahimi 	sljit_sw executable_offset;
707*22dc650dSSadaf Ebrahimi 	sljit_uw addr;
708*22dc650dSSadaf Ebrahimi 	struct sljit_label *label;
709*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
710*22dc650dSSadaf Ebrahimi 	struct sljit_const *const_;
711*22dc650dSSadaf Ebrahimi 
712*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
713*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_generate_code(compiler));
714*22dc650dSSadaf Ebrahimi 	reverse_buf(compiler);
715*22dc650dSSadaf Ebrahimi 
716*22dc650dSSadaf Ebrahimi 	code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
717*22dc650dSSadaf Ebrahimi 	PTR_FAIL_WITH_EXEC_IF(code);
718*22dc650dSSadaf Ebrahimi 	buf = compiler->buf;
719*22dc650dSSadaf Ebrahimi 
720*22dc650dSSadaf Ebrahimi 	code_ptr = code;
721*22dc650dSSadaf Ebrahimi 	word_count = 0;
722*22dc650dSSadaf Ebrahimi 	label = compiler->labels;
723*22dc650dSSadaf Ebrahimi 	jump = compiler->jumps;
724*22dc650dSSadaf Ebrahimi 	const_ = compiler->consts;
725*22dc650dSSadaf Ebrahimi 	SLJIT_NEXT_INIT_TYPES();
726*22dc650dSSadaf Ebrahimi 	SLJIT_GET_NEXT_MIN();
727*22dc650dSSadaf Ebrahimi 
728*22dc650dSSadaf Ebrahimi 	do {
729*22dc650dSSadaf Ebrahimi 		buf_ptr = (sljit_ins*)buf->memory;
730*22dc650dSSadaf Ebrahimi 		buf_end = buf_ptr + (buf->used_size >> 2);
731*22dc650dSSadaf Ebrahimi 		do {
732*22dc650dSSadaf Ebrahimi 			*code_ptr = *buf_ptr++;
733*22dc650dSSadaf Ebrahimi 			if (next_min_addr == word_count) {
734*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(!label || label->size >= word_count);
735*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(!jump || jump->addr >= word_count);
736*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(!const_ || const_->addr >= word_count);
737*22dc650dSSadaf Ebrahimi 
738*22dc650dSSadaf Ebrahimi 				/* These structures are ordered by their address. */
739*22dc650dSSadaf Ebrahimi 				if (next_min_addr == next_label_size) {
740*22dc650dSSadaf Ebrahimi 					label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
741*22dc650dSSadaf Ebrahimi 					label->size = (sljit_uw)(code_ptr - code);
742*22dc650dSSadaf Ebrahimi 					label = label->next;
743*22dc650dSSadaf Ebrahimi 					next_label_size = SLJIT_GET_NEXT_SIZE(label);
744*22dc650dSSadaf Ebrahimi 				}
745*22dc650dSSadaf Ebrahimi 
746*22dc650dSSadaf Ebrahimi 				if (next_min_addr == next_jump_addr) {
747*22dc650dSSadaf Ebrahimi 					if (!(jump->flags & JUMP_MOV_ADDR)) {
748*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
749*22dc650dSSadaf Ebrahimi 						word_count += 2;
750*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
751*22dc650dSSadaf Ebrahimi 						word_count += 6;
752*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
753*22dc650dSSadaf Ebrahimi 						jump->addr = (sljit_uw)(code_ptr - 1);
754*22dc650dSSadaf Ebrahimi 						code_ptr = detect_jump_type(jump, code, executable_offset);
755*22dc650dSSadaf Ebrahimi 					} else {
756*22dc650dSSadaf Ebrahimi 						jump->addr = (sljit_uw)code_ptr;
757*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
758*22dc650dSSadaf Ebrahimi 						code_ptr += 1;
759*22dc650dSSadaf Ebrahimi 						word_count += 1;
760*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
761*22dc650dSSadaf Ebrahimi 						code_ptr += mov_addr_get_length(jump, code, executable_offset);
762*22dc650dSSadaf Ebrahimi 						word_count += 5;
763*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
764*22dc650dSSadaf Ebrahimi 					}
765*22dc650dSSadaf Ebrahimi 
766*22dc650dSSadaf Ebrahimi 					jump = jump->next;
767*22dc650dSSadaf Ebrahimi 					next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
768*22dc650dSSadaf Ebrahimi 				} else if (next_min_addr == next_const_addr) {
769*22dc650dSSadaf Ebrahimi 					const_->addr = (sljit_uw)code_ptr;
770*22dc650dSSadaf Ebrahimi 					const_ = const_->next;
771*22dc650dSSadaf Ebrahimi 					next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
772*22dc650dSSadaf Ebrahimi 				}
773*22dc650dSSadaf Ebrahimi 
774*22dc650dSSadaf Ebrahimi 				SLJIT_GET_NEXT_MIN();
775*22dc650dSSadaf Ebrahimi 			}
776*22dc650dSSadaf Ebrahimi 			code_ptr++;
777*22dc650dSSadaf Ebrahimi 			word_count++;
778*22dc650dSSadaf Ebrahimi 		} while (buf_ptr < buf_end);
779*22dc650dSSadaf Ebrahimi 
780*22dc650dSSadaf Ebrahimi 		buf = buf->next;
781*22dc650dSSadaf Ebrahimi 	} while (buf);
782*22dc650dSSadaf Ebrahimi 
783*22dc650dSSadaf Ebrahimi 	if (label && label->size == word_count) {
784*22dc650dSSadaf Ebrahimi 		label->u.addr = (sljit_uw)code_ptr;
785*22dc650dSSadaf Ebrahimi 		label->size = (sljit_uw)(code_ptr - code);
786*22dc650dSSadaf Ebrahimi 		label = label->next;
787*22dc650dSSadaf Ebrahimi 	}
788*22dc650dSSadaf Ebrahimi 
789*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(!label);
790*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(!jump);
791*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(!const_);
792*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
793*22dc650dSSadaf Ebrahimi 
794*22dc650dSSadaf Ebrahimi 	jump = compiler->jumps;
795*22dc650dSSadaf Ebrahimi 	while (jump) {
796*22dc650dSSadaf Ebrahimi 		do {
797*22dc650dSSadaf Ebrahimi 			addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
798*22dc650dSSadaf Ebrahimi 			buf_ptr = (sljit_ins *)jump->addr;
799*22dc650dSSadaf Ebrahimi 
800*22dc650dSSadaf Ebrahimi 			if (jump->flags & PATCH_B) {
801*22dc650dSSadaf Ebrahimi 				addr = (sljit_uw)((sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) - sizeof(sljit_ins)) >> 2);
802*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);
803*22dc650dSSadaf Ebrahimi 				buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((sljit_ins)addr & 0xffff);
804*22dc650dSSadaf Ebrahimi 				break;
805*22dc650dSSadaf Ebrahimi 			}
806*22dc650dSSadaf Ebrahimi 			if (jump->flags & PATCH_J) {
807*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT((addr & ~(sljit_uw)0xfffffff)
808*22dc650dSSadaf Ebrahimi 					== (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff));
809*22dc650dSSadaf Ebrahimi 				buf_ptr[0] |= (sljit_ins)(addr >> 2) & 0x03ffffff;
810*22dc650dSSadaf Ebrahimi 				break;
811*22dc650dSSadaf Ebrahimi 			}
812*22dc650dSSadaf Ebrahimi 
813*22dc650dSSadaf Ebrahimi 			load_addr_to_reg(jump);
814*22dc650dSSadaf Ebrahimi 		} while (0);
815*22dc650dSSadaf Ebrahimi 
816*22dc650dSSadaf Ebrahimi 		jump = jump->next;
817*22dc650dSSadaf Ebrahimi 	}
818*22dc650dSSadaf Ebrahimi 
819*22dc650dSSadaf Ebrahimi 	compiler->error = SLJIT_ERR_COMPILED;
820*22dc650dSSadaf Ebrahimi 	compiler->executable_offset = executable_offset;
821*22dc650dSSadaf Ebrahimi 	compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
822*22dc650dSSadaf Ebrahimi 
823*22dc650dSSadaf Ebrahimi 	code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
824*22dc650dSSadaf Ebrahimi 	code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
825*22dc650dSSadaf Ebrahimi 
826*22dc650dSSadaf Ebrahimi #ifndef __GNUC__
827*22dc650dSSadaf Ebrahimi 	SLJIT_CACHE_FLUSH(code, code_ptr);
828*22dc650dSSadaf Ebrahimi #else
829*22dc650dSSadaf Ebrahimi 	/* GCC workaround for invalid code generation with -O2. */
830*22dc650dSSadaf Ebrahimi 	sljit_cache_flush(code, code_ptr);
831*22dc650dSSadaf Ebrahimi #endif
832*22dc650dSSadaf Ebrahimi 	SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
833*22dc650dSSadaf Ebrahimi 	return code;
834*22dc650dSSadaf Ebrahimi }
835*22dc650dSSadaf Ebrahimi 
sljit_has_cpu_feature(sljit_s32 feature_type)836*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
837*22dc650dSSadaf Ebrahimi {
838*22dc650dSSadaf Ebrahimi 	switch (feature_type) {
839*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
840*22dc650dSSadaf Ebrahimi 		&& (!defined(SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE)
841*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_F64_AS_F32_PAIR:
842*22dc650dSSadaf Ebrahimi 		if (!cpu_feature_list)
843*22dc650dSSadaf Ebrahimi 			get_cpu_features();
844*22dc650dSSadaf Ebrahimi 
845*22dc650dSSadaf Ebrahimi 		return (cpu_feature_list & CPU_FEATURE_FR) != 0;
846*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_IS_FPU_AVAILABLE */
847*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_FPU:
848*22dc650dSSadaf Ebrahimi 		if (!cpu_feature_list)
849*22dc650dSSadaf Ebrahimi 			get_cpu_features();
850*22dc650dSSadaf Ebrahimi 
851*22dc650dSSadaf Ebrahimi 		return (cpu_feature_list & CPU_FEATURE_FPU) != 0;
852*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_ZERO_REGISTER:
853*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_COPY_F32:
854*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_COPY_F64:
855*22dc650dSSadaf Ebrahimi 		return 1;
856*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
857*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_CLZ:
858*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_CMOV:
859*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_PREFETCH:
860*22dc650dSSadaf Ebrahimi 		return 1;
861*22dc650dSSadaf Ebrahimi 
862*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_CTZ:
863*22dc650dSSadaf Ebrahimi 		return 2;
864*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 1 */
865*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
866*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_REV:
867*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_ROT:
868*22dc650dSSadaf Ebrahimi 		return 1;
869*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
870*22dc650dSSadaf Ebrahimi 	default:
871*22dc650dSSadaf Ebrahimi 		return 0;
872*22dc650dSSadaf Ebrahimi 	}
873*22dc650dSSadaf Ebrahimi }
874*22dc650dSSadaf Ebrahimi 
sljit_cmp_info(sljit_s32 type)875*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
876*22dc650dSSadaf Ebrahimi {
877*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(type);
878*22dc650dSSadaf Ebrahimi 	return 0;
879*22dc650dSSadaf Ebrahimi }
880*22dc650dSSadaf Ebrahimi 
881*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
882*22dc650dSSadaf Ebrahimi /*  Entry, exit                                                          */
883*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
884*22dc650dSSadaf Ebrahimi 
885*22dc650dSSadaf Ebrahimi /* Creates an index in data_transfer_insts array. */
886*22dc650dSSadaf Ebrahimi #define LOAD_DATA	0x01
887*22dc650dSSadaf Ebrahimi #define WORD_DATA	0x00
888*22dc650dSSadaf Ebrahimi #define BYTE_DATA	0x02
889*22dc650dSSadaf Ebrahimi #define HALF_DATA	0x04
890*22dc650dSSadaf Ebrahimi #define INT_DATA	0x06
891*22dc650dSSadaf Ebrahimi #define SIGNED_DATA	0x08
892*22dc650dSSadaf Ebrahimi /* Separates integer and floating point registers */
893*22dc650dSSadaf Ebrahimi #define GPR_REG		0x0f
894*22dc650dSSadaf Ebrahimi #define DOUBLE_DATA	0x10
895*22dc650dSSadaf Ebrahimi #define SINGLE_DATA	0x12
896*22dc650dSSadaf Ebrahimi 
897*22dc650dSSadaf Ebrahimi #define MEM_MASK	0x1f
898*22dc650dSSadaf Ebrahimi 
899*22dc650dSSadaf Ebrahimi #define ARG_TEST	0x00020
900*22dc650dSSadaf Ebrahimi #define ALT_KEEP_CACHE	0x00040
901*22dc650dSSadaf Ebrahimi #define CUMULATIVE_OP	0x00080
902*22dc650dSSadaf Ebrahimi #define LOGICAL_OP	0x00100
903*22dc650dSSadaf Ebrahimi #define IMM_OP		0x00200
904*22dc650dSSadaf Ebrahimi #define MOVE_OP		0x00400
905*22dc650dSSadaf Ebrahimi #define SRC2_IMM	0x00800
906*22dc650dSSadaf Ebrahimi 
907*22dc650dSSadaf Ebrahimi #define UNUSED_DEST	0x01000
908*22dc650dSSadaf Ebrahimi #define REG_DEST	0x02000
909*22dc650dSSadaf Ebrahimi #define REG1_SOURCE	0x04000
910*22dc650dSSadaf Ebrahimi #define REG2_SOURCE	0x08000
911*22dc650dSSadaf Ebrahimi #define SLOW_SRC1	0x10000
912*22dc650dSSadaf Ebrahimi #define SLOW_SRC2	0x20000
913*22dc650dSSadaf Ebrahimi #define SLOW_DEST	0x40000
914*22dc650dSSadaf Ebrahimi 
915*22dc650dSSadaf Ebrahimi static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);
916*22dc650dSSadaf Ebrahimi static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr);
917*22dc650dSSadaf Ebrahimi 
918*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
919*22dc650dSSadaf Ebrahimi #define SELECT_OP(d, w)	(w)
920*22dc650dSSadaf Ebrahimi #else
921*22dc650dSSadaf Ebrahimi #define SELECT_OP(d, w)	(!(op & SLJIT_32) ? (d) : (w))
922*22dc650dSSadaf Ebrahimi #endif
923*22dc650dSSadaf Ebrahimi 
924*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
925*22dc650dSSadaf Ebrahimi #include "sljitNativeMIPS_32.c"
926*22dc650dSSadaf Ebrahimi #else
927*22dc650dSSadaf Ebrahimi #include "sljitNativeMIPS_64.c"
928*22dc650dSSadaf Ebrahimi #endif
929*22dc650dSSadaf Ebrahimi 
sljit_emit_enter(struct sljit_compiler * compiler,sljit_s32 options,sljit_s32 arg_types,sljit_s32 scratches,sljit_s32 saveds,sljit_s32 fscratches,sljit_s32 fsaveds,sljit_s32 local_size)930*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
931*22dc650dSSadaf Ebrahimi 	sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
932*22dc650dSSadaf Ebrahimi 	sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
933*22dc650dSSadaf Ebrahimi {
934*22dc650dSSadaf Ebrahimi 	sljit_ins base;
935*22dc650dSSadaf Ebrahimi 	sljit_s32 i, tmp, offset;
936*22dc650dSSadaf Ebrahimi 	sljit_s32 arg_count, word_arg_count, float_arg_count;
937*22dc650dSSadaf Ebrahimi 	sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
938*22dc650dSSadaf Ebrahimi 
939*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
940*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
941*22dc650dSSadaf Ebrahimi 	set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
942*22dc650dSSadaf Ebrahimi 
943*22dc650dSSadaf Ebrahimi 	local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);
944*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
945*22dc650dSSadaf Ebrahimi 	if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
946*22dc650dSSadaf Ebrahimi 		if ((local_size & SSIZE_OF(sw)) != 0)
947*22dc650dSSadaf Ebrahimi 			local_size += SSIZE_OF(sw);
948*22dc650dSSadaf Ebrahimi 		local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
949*22dc650dSSadaf Ebrahimi 	}
950*22dc650dSSadaf Ebrahimi 
951*22dc650dSSadaf Ebrahimi 	local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
952*22dc650dSSadaf Ebrahimi #else
953*22dc650dSSadaf Ebrahimi 	local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
954*22dc650dSSadaf Ebrahimi 	local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;
955*22dc650dSSadaf Ebrahimi #endif
956*22dc650dSSadaf Ebrahimi 	compiler->local_size = local_size;
957*22dc650dSSadaf Ebrahimi 
958*22dc650dSSadaf Ebrahimi 	offset = 0;
959*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
960*22dc650dSSadaf Ebrahimi 	if (!(options & SLJIT_ENTER_REG_ARG)) {
961*22dc650dSSadaf Ebrahimi 		tmp = arg_types >> SLJIT_ARG_SHIFT;
962*22dc650dSSadaf Ebrahimi 		arg_count = 0;
963*22dc650dSSadaf Ebrahimi 
964*22dc650dSSadaf Ebrahimi 		while (tmp) {
965*22dc650dSSadaf Ebrahimi 			offset = arg_count;
966*22dc650dSSadaf Ebrahimi 			if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {
967*22dc650dSSadaf Ebrahimi 				if ((arg_count & 0x1) != 0)
968*22dc650dSSadaf Ebrahimi 					arg_count++;
969*22dc650dSSadaf Ebrahimi 				arg_count++;
970*22dc650dSSadaf Ebrahimi 			}
971*22dc650dSSadaf Ebrahimi 
972*22dc650dSSadaf Ebrahimi 			arg_count++;
973*22dc650dSSadaf Ebrahimi 			tmp >>= SLJIT_ARG_SHIFT;
974*22dc650dSSadaf Ebrahimi 		}
975*22dc650dSSadaf Ebrahimi 
976*22dc650dSSadaf Ebrahimi 		compiler->args_size = (sljit_uw)arg_count << 2;
977*22dc650dSSadaf Ebrahimi 		offset = (offset >= 4) ? (offset << 2) : 0;
978*22dc650dSSadaf Ebrahimi 	}
979*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
980*22dc650dSSadaf Ebrahimi 
981*22dc650dSSadaf Ebrahimi 	if (local_size + offset <= -SIMM_MIN) {
982*22dc650dSSadaf Ebrahimi 		/* Frequent case. */
983*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));
984*22dc650dSSadaf Ebrahimi 		base = S(SLJIT_SP);
985*22dc650dSSadaf Ebrahimi 		offset = local_size - SSIZE_OF(sw);
986*22dc650dSSadaf Ebrahimi 	} else {
987*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, OTHER_FLAG, local_size));
988*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
989*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | TA(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
990*22dc650dSSadaf Ebrahimi 		base = S(TMP_REG1);
991*22dc650dSSadaf Ebrahimi 		offset = -SSIZE_OF(sw);
992*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
993*22dc650dSSadaf Ebrahimi 		local_size = 0;
994*22dc650dSSadaf Ebrahimi #endif
995*22dc650dSSadaf Ebrahimi 	}
996*22dc650dSSadaf Ebrahimi 
997*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, STORE_W | base | TA(RETURN_ADDR_REG) | IMM(offset), UNMOVABLE_INS));
998*22dc650dSSadaf Ebrahimi 
999*22dc650dSSadaf Ebrahimi 	tmp = SLJIT_S0 - saveds;
1000*22dc650dSSadaf Ebrahimi 	for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
1001*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(sw);
1002*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS));
1003*22dc650dSSadaf Ebrahimi 	}
1004*22dc650dSSadaf Ebrahimi 
1005*22dc650dSSadaf Ebrahimi 	for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
1006*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(sw);
1007*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS));
1008*22dc650dSSadaf Ebrahimi 	}
1009*22dc650dSSadaf Ebrahimi 
1010*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1011*22dc650dSSadaf Ebrahimi 	/* This alignment is valid because offset is not used after storing FPU regs. */
1012*22dc650dSSadaf Ebrahimi 	if ((offset & SSIZE_OF(sw)) != 0)
1013*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(sw);
1014*22dc650dSSadaf Ebrahimi #endif
1015*22dc650dSSadaf Ebrahimi 
1016*22dc650dSSadaf Ebrahimi 	tmp = SLJIT_FS0 - fsaveds;
1017*22dc650dSSadaf Ebrahimi 	for (i = SLJIT_FS0; i > tmp; i--) {
1018*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(f64);
1019*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
1020*22dc650dSSadaf Ebrahimi 	}
1021*22dc650dSSadaf Ebrahimi 
1022*22dc650dSSadaf Ebrahimi 	for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
1023*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(f64);
1024*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
1025*22dc650dSSadaf Ebrahimi 	}
1026*22dc650dSSadaf Ebrahimi 
1027*22dc650dSSadaf Ebrahimi 	if (options & SLJIT_ENTER_REG_ARG)
1028*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1029*22dc650dSSadaf Ebrahimi 
1030*22dc650dSSadaf Ebrahimi 	arg_types >>= SLJIT_ARG_SHIFT;
1031*22dc650dSSadaf Ebrahimi 	arg_count = 0;
1032*22dc650dSSadaf Ebrahimi 	word_arg_count = 0;
1033*22dc650dSSadaf Ebrahimi 	float_arg_count = 0;
1034*22dc650dSSadaf Ebrahimi 
1035*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1036*22dc650dSSadaf Ebrahimi 	/* The first maximum two floating point arguments are passed in floating point
1037*22dc650dSSadaf Ebrahimi 	   registers if no integer argument precedes them. The first 16 byte data is
1038*22dc650dSSadaf Ebrahimi 	   passed in four integer registers, the rest is placed onto the stack.
1039*22dc650dSSadaf Ebrahimi 	   The floating point registers are also part of the first 16 byte data, so
1040*22dc650dSSadaf Ebrahimi 	   their corresponding integer registers are not used when they are present. */
1041*22dc650dSSadaf Ebrahimi 
1042*22dc650dSSadaf Ebrahimi 	while (arg_types) {
1043*22dc650dSSadaf Ebrahimi 		switch (arg_types & SLJIT_ARG_MASK) {
1044*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F64:
1045*22dc650dSSadaf Ebrahimi 			float_arg_count++;
1046*22dc650dSSadaf Ebrahimi 			if ((arg_count & 0x1) != 0)
1047*22dc650dSSadaf Ebrahimi 				arg_count++;
1048*22dc650dSSadaf Ebrahimi 
1049*22dc650dSSadaf Ebrahimi 			if (word_arg_count == 0 && float_arg_count <= 2) {
1050*22dc650dSSadaf Ebrahimi 				if (float_arg_count == 1)
1051*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
1052*22dc650dSSadaf Ebrahimi 			} else if (arg_count < 4) {
1053*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
1054*22dc650dSSadaf Ebrahimi 				switch (cpu_feature_list & CPU_FEATURE_FR) {
1055*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
1056*22dc650dSSadaf Ebrahimi 				case CPU_FEATURE_FR:
1057*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, MTHC1 | TA(5 + arg_count) | FS(float_arg_count), MOVABLE_INS));
1058*22dc650dSSadaf Ebrahimi 					break;
1059*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
1060*22dc650dSSadaf Ebrahimi 				default:
1061*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS));
1062*22dc650dSSadaf Ebrahimi 					break;
1063*22dc650dSSadaf Ebrahimi 				}
1064*22dc650dSSadaf Ebrahimi 			} else
1065*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
1066*22dc650dSSadaf Ebrahimi 			arg_count++;
1067*22dc650dSSadaf Ebrahimi 			break;
1068*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F32:
1069*22dc650dSSadaf Ebrahimi 			float_arg_count++;
1070*22dc650dSSadaf Ebrahimi 
1071*22dc650dSSadaf Ebrahimi 			if (word_arg_count == 0 && float_arg_count <= 2) {
1072*22dc650dSSadaf Ebrahimi 				if (float_arg_count == 1)
1073*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
1074*22dc650dSSadaf Ebrahimi 			} else if (arg_count < 4)
1075*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
1076*22dc650dSSadaf Ebrahimi 			else
1077*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, LWC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
1078*22dc650dSSadaf Ebrahimi 			break;
1079*22dc650dSSadaf Ebrahimi 		default:
1080*22dc650dSSadaf Ebrahimi 			word_arg_count++;
1081*22dc650dSSadaf Ebrahimi 
1082*22dc650dSSadaf Ebrahimi 			if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
1083*22dc650dSSadaf Ebrahimi 				tmp = SLJIT_S0 - saved_arg_count;
1084*22dc650dSSadaf Ebrahimi 				saved_arg_count++;
1085*22dc650dSSadaf Ebrahimi 			} else if (word_arg_count != arg_count + 1 || arg_count == 0)
1086*22dc650dSSadaf Ebrahimi 				tmp = word_arg_count;
1087*22dc650dSSadaf Ebrahimi 			else
1088*22dc650dSSadaf Ebrahimi 				break;
1089*22dc650dSSadaf Ebrahimi 
1090*22dc650dSSadaf Ebrahimi 			if (arg_count < 4)
1091*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADDU_W | SA(4 + arg_count) | TA(0) | D(tmp), DR(tmp)));
1092*22dc650dSSadaf Ebrahimi 			else
1093*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, LW | base | T(tmp) | IMM(local_size + (arg_count << 2)), DR(tmp)));
1094*22dc650dSSadaf Ebrahimi 			break;
1095*22dc650dSSadaf Ebrahimi 		}
1096*22dc650dSSadaf Ebrahimi 		arg_count++;
1097*22dc650dSSadaf Ebrahimi 		arg_types >>= SLJIT_ARG_SHIFT;
1098*22dc650dSSadaf Ebrahimi 	}
1099*22dc650dSSadaf Ebrahimi 
1100*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(compiler->args_size == (sljit_uw)arg_count << 2);
1101*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
1102*22dc650dSSadaf Ebrahimi 	while (arg_types) {
1103*22dc650dSSadaf Ebrahimi 		arg_count++;
1104*22dc650dSSadaf Ebrahimi 		switch (arg_types & SLJIT_ARG_MASK) {
1105*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F64:
1106*22dc650dSSadaf Ebrahimi 			float_arg_count++;
1107*22dc650dSSadaf Ebrahimi 			if (arg_count != float_arg_count)
1108*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
1109*22dc650dSSadaf Ebrahimi 			else if (arg_count == 1)
1110*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
1111*22dc650dSSadaf Ebrahimi 			break;
1112*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F32:
1113*22dc650dSSadaf Ebrahimi 			float_arg_count++;
1114*22dc650dSSadaf Ebrahimi 			if (arg_count != float_arg_count)
1115*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
1116*22dc650dSSadaf Ebrahimi 			else if (arg_count == 1)
1117*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
1118*22dc650dSSadaf Ebrahimi 			break;
1119*22dc650dSSadaf Ebrahimi 		default:
1120*22dc650dSSadaf Ebrahimi 			word_arg_count++;
1121*22dc650dSSadaf Ebrahimi 
1122*22dc650dSSadaf Ebrahimi 			if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
1123*22dc650dSSadaf Ebrahimi 				tmp = SLJIT_S0 - saved_arg_count;
1124*22dc650dSSadaf Ebrahimi 				saved_arg_count++;
1125*22dc650dSSadaf Ebrahimi 			} else if (word_arg_count != arg_count || word_arg_count <= 1)
1126*22dc650dSSadaf Ebrahimi 				tmp = word_arg_count;
1127*22dc650dSSadaf Ebrahimi 			else
1128*22dc650dSSadaf Ebrahimi 				break;
1129*22dc650dSSadaf Ebrahimi 
1130*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDU_W | SA(3 + arg_count) | TA(0) | D(tmp), DR(tmp)));
1131*22dc650dSSadaf Ebrahimi 			break;
1132*22dc650dSSadaf Ebrahimi 		}
1133*22dc650dSSadaf Ebrahimi 		arg_types >>= SLJIT_ARG_SHIFT;
1134*22dc650dSSadaf Ebrahimi 	}
1135*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
1136*22dc650dSSadaf Ebrahimi 
1137*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
1138*22dc650dSSadaf Ebrahimi }
1139*22dc650dSSadaf Ebrahimi 
sljit_set_context(struct sljit_compiler * compiler,sljit_s32 options,sljit_s32 arg_types,sljit_s32 scratches,sljit_s32 saveds,sljit_s32 fscratches,sljit_s32 fsaveds,sljit_s32 local_size)1140*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
1141*22dc650dSSadaf Ebrahimi 	sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
1142*22dc650dSSadaf Ebrahimi 	sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
1143*22dc650dSSadaf Ebrahimi {
1144*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
1145*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
1146*22dc650dSSadaf Ebrahimi 	set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
1147*22dc650dSSadaf Ebrahimi 
1148*22dc650dSSadaf Ebrahimi 	local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);
1149*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1150*22dc650dSSadaf Ebrahimi 	if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
1151*22dc650dSSadaf Ebrahimi 		if ((local_size & SSIZE_OF(sw)) != 0)
1152*22dc650dSSadaf Ebrahimi 			local_size += SSIZE_OF(sw);
1153*22dc650dSSadaf Ebrahimi 		local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
1154*22dc650dSSadaf Ebrahimi 	}
1155*22dc650dSSadaf Ebrahimi 
1156*22dc650dSSadaf Ebrahimi 	compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
1157*22dc650dSSadaf Ebrahimi #else
1158*22dc650dSSadaf Ebrahimi 	local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
1159*22dc650dSSadaf Ebrahimi 	compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;
1160*22dc650dSSadaf Ebrahimi #endif
1161*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
1162*22dc650dSSadaf Ebrahimi }
1163*22dc650dSSadaf Ebrahimi 
emit_stack_frame_release(struct sljit_compiler * compiler,sljit_s32 frame_size,sljit_ins * ins_ptr)1164*22dc650dSSadaf Ebrahimi static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr)
1165*22dc650dSSadaf Ebrahimi {
1166*22dc650dSSadaf Ebrahimi 	sljit_s32 local_size, i, tmp, offset;
1167*22dc650dSSadaf Ebrahimi 	sljit_s32 load_return_addr = (frame_size == 0);
1168*22dc650dSSadaf Ebrahimi 	sljit_s32 scratches = compiler->scratches;
1169*22dc650dSSadaf Ebrahimi 	sljit_s32 saveds = compiler->saveds;
1170*22dc650dSSadaf Ebrahimi 	sljit_s32 fsaveds = compiler->fsaveds;
1171*22dc650dSSadaf Ebrahimi 	sljit_s32 fscratches = compiler->fscratches;
1172*22dc650dSSadaf Ebrahimi 	sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);
1173*22dc650dSSadaf Ebrahimi 
1174*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(frame_size == 1 || (frame_size & 0xf) == 0);
1175*22dc650dSSadaf Ebrahimi 	frame_size &= ~0xf;
1176*22dc650dSSadaf Ebrahimi 
1177*22dc650dSSadaf Ebrahimi 	local_size = compiler->local_size;
1178*22dc650dSSadaf Ebrahimi 
1179*22dc650dSSadaf Ebrahimi 	tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds - kept_saveds_count, 1);
1180*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1181*22dc650dSSadaf Ebrahimi 	if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
1182*22dc650dSSadaf Ebrahimi 		if ((tmp & SSIZE_OF(sw)) != 0)
1183*22dc650dSSadaf Ebrahimi 			tmp += SSIZE_OF(sw);
1184*22dc650dSSadaf Ebrahimi 		tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
1185*22dc650dSSadaf Ebrahimi 	}
1186*22dc650dSSadaf Ebrahimi #else
1187*22dc650dSSadaf Ebrahimi 	tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
1188*22dc650dSSadaf Ebrahimi #endif
1189*22dc650dSSadaf Ebrahimi 
1190*22dc650dSSadaf Ebrahimi 	if (local_size <= SIMM_MAX) {
1191*22dc650dSSadaf Ebrahimi 		if (local_size < frame_size) {
1192*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size), DR(SLJIT_SP)));
1193*22dc650dSSadaf Ebrahimi 			local_size = frame_size;
1194*22dc650dSSadaf Ebrahimi 		}
1195*22dc650dSSadaf Ebrahimi 	} else {
1196*22dc650dSSadaf Ebrahimi 		if (tmp < frame_size)
1197*22dc650dSSadaf Ebrahimi 			tmp = frame_size;
1198*22dc650dSSadaf Ebrahimi 
1199*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, DR(TMP_REG2), local_size - tmp));
1200*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG2) | D(SLJIT_SP), DR(SLJIT_SP)));
1201*22dc650dSSadaf Ebrahimi 		local_size = tmp;
1202*22dc650dSSadaf Ebrahimi 	}
1203*22dc650dSSadaf Ebrahimi 
1204*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(local_size >= frame_size);
1205*22dc650dSSadaf Ebrahimi 
1206*22dc650dSSadaf Ebrahimi 	offset = local_size - SSIZE_OF(sw);
1207*22dc650dSSadaf Ebrahimi 	if (load_return_addr)
1208*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG));
1209*22dc650dSSadaf Ebrahimi 
1210*22dc650dSSadaf Ebrahimi 	tmp = SLJIT_S0 - saveds;
1211*22dc650dSSadaf Ebrahimi 	for (i = SLJIT_S0 - kept_saveds_count; i > tmp; i--) {
1212*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(sw);
1213*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));
1214*22dc650dSSadaf Ebrahimi 	}
1215*22dc650dSSadaf Ebrahimi 
1216*22dc650dSSadaf Ebrahimi 	for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
1217*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(sw);
1218*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));
1219*22dc650dSSadaf Ebrahimi 	}
1220*22dc650dSSadaf Ebrahimi 
1221*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1222*22dc650dSSadaf Ebrahimi 	/* This alignment is valid because offset is not used after storing FPU regs. */
1223*22dc650dSSadaf Ebrahimi 	if ((offset & SSIZE_OF(sw)) != 0)
1224*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(sw);
1225*22dc650dSSadaf Ebrahimi #endif
1226*22dc650dSSadaf Ebrahimi 
1227*22dc650dSSadaf Ebrahimi 	tmp = SLJIT_FS0 - fsaveds;
1228*22dc650dSSadaf Ebrahimi 	for (i = SLJIT_FS0; i > tmp; i--) {
1229*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(f64);
1230*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));
1231*22dc650dSSadaf Ebrahimi 	}
1232*22dc650dSSadaf Ebrahimi 
1233*22dc650dSSadaf Ebrahimi 	for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
1234*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(f64);
1235*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));
1236*22dc650dSSadaf Ebrahimi 	}
1237*22dc650dSSadaf Ebrahimi 
1238*22dc650dSSadaf Ebrahimi 	if (local_size > frame_size)
1239*22dc650dSSadaf Ebrahimi 		*ins_ptr = ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size);
1240*22dc650dSSadaf Ebrahimi 	else
1241*22dc650dSSadaf Ebrahimi 		*ins_ptr = NOP;
1242*22dc650dSSadaf Ebrahimi 
1243*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
1244*22dc650dSSadaf Ebrahimi }
1245*22dc650dSSadaf Ebrahimi 
sljit_emit_return_void(struct sljit_compiler * compiler)1246*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
1247*22dc650dSSadaf Ebrahimi {
1248*22dc650dSSadaf Ebrahimi 	sljit_ins ins;
1249*22dc650dSSadaf Ebrahimi 
1250*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
1251*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_return_void(compiler));
1252*22dc650dSSadaf Ebrahimi 
1253*22dc650dSSadaf Ebrahimi 	emit_stack_frame_release(compiler, 0, &ins);
1254*22dc650dSSadaf Ebrahimi 
1255*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
1256*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ins, UNMOVABLE_INS);
1257*22dc650dSSadaf Ebrahimi }
1258*22dc650dSSadaf Ebrahimi 
sljit_emit_return_to(struct sljit_compiler * compiler,sljit_s32 src,sljit_sw srcw)1259*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
1260*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
1261*22dc650dSSadaf Ebrahimi {
1262*22dc650dSSadaf Ebrahimi 	sljit_ins ins;
1263*22dc650dSSadaf Ebrahimi 
1264*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
1265*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_return_to(compiler, src, srcw));
1266*22dc650dSSadaf Ebrahimi 
1267*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
1268*22dc650dSSadaf Ebrahimi 		ADJUST_LOCAL_OFFSET(src, srcw);
1269*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
1270*22dc650dSSadaf Ebrahimi 		src = PIC_ADDR_REG;
1271*22dc650dSSadaf Ebrahimi 		srcw = 0;
1272*22dc650dSSadaf Ebrahimi 	} else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
1273*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
1274*22dc650dSSadaf Ebrahimi 		src = PIC_ADDR_REG;
1275*22dc650dSSadaf Ebrahimi 		srcw = 0;
1276*22dc650dSSadaf Ebrahimi 	}
1277*22dc650dSSadaf Ebrahimi 
1278*22dc650dSSadaf Ebrahimi 	FAIL_IF(emit_stack_frame_release(compiler, 1, &ins));
1279*22dc650dSSadaf Ebrahimi 
1280*22dc650dSSadaf Ebrahimi 	if (src != SLJIT_IMM) {
1281*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));
1282*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ins, UNMOVABLE_INS);
1283*22dc650dSSadaf Ebrahimi 	}
1284*22dc650dSSadaf Ebrahimi 
1285*22dc650dSSadaf Ebrahimi 	if (ins != NOP)
1286*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
1287*22dc650dSSadaf Ebrahimi 
1288*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
1289*22dc650dSSadaf Ebrahimi 	return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
1290*22dc650dSSadaf Ebrahimi }
1291*22dc650dSSadaf Ebrahimi 
1292*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
1293*22dc650dSSadaf Ebrahimi /*  Operators                                                            */
1294*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
1295*22dc650dSSadaf Ebrahimi 
1296*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1297*22dc650dSSadaf Ebrahimi #define ARCH_32_64(a, b)	a
1298*22dc650dSSadaf Ebrahimi #else
1299*22dc650dSSadaf Ebrahimi #define ARCH_32_64(a, b)	b
1300*22dc650dSSadaf Ebrahimi #endif
1301*22dc650dSSadaf Ebrahimi 
1302*22dc650dSSadaf Ebrahimi static const sljit_ins data_transfer_insts[16 + 4] = {
1303*22dc650dSSadaf Ebrahimi /* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
1304*22dc650dSSadaf Ebrahimi /* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
1305*22dc650dSSadaf Ebrahimi /* u b s */ HI(40) /* sb */,
1306*22dc650dSSadaf Ebrahimi /* u b l */ HI(36) /* lbu */,
1307*22dc650dSSadaf Ebrahimi /* u h s */ HI(41) /* sh */,
1308*22dc650dSSadaf Ebrahimi /* u h l */ HI(37) /* lhu */,
1309*22dc650dSSadaf Ebrahimi /* u i s */ HI(43) /* sw */,
1310*22dc650dSSadaf Ebrahimi /* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),
1311*22dc650dSSadaf Ebrahimi 
1312*22dc650dSSadaf Ebrahimi /* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
1313*22dc650dSSadaf Ebrahimi /* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
1314*22dc650dSSadaf Ebrahimi /* s b s */ HI(40) /* sb */,
1315*22dc650dSSadaf Ebrahimi /* s b l */ HI(32) /* lb */,
1316*22dc650dSSadaf Ebrahimi /* s h s */ HI(41) /* sh */,
1317*22dc650dSSadaf Ebrahimi /* s h l */ HI(33) /* lh */,
1318*22dc650dSSadaf Ebrahimi /* s i s */ HI(43) /* sw */,
1319*22dc650dSSadaf Ebrahimi /* s i l */ HI(35) /* lw */,
1320*22dc650dSSadaf Ebrahimi 
1321*22dc650dSSadaf Ebrahimi /* d   s */ HI(61) /* sdc1 */,
1322*22dc650dSSadaf Ebrahimi /* d   l */ HI(53) /* ldc1 */,
1323*22dc650dSSadaf Ebrahimi /* s   s */ HI(57) /* swc1 */,
1324*22dc650dSSadaf Ebrahimi /* s   l */ HI(49) /* lwc1 */,
1325*22dc650dSSadaf Ebrahimi };
1326*22dc650dSSadaf Ebrahimi 
1327*22dc650dSSadaf Ebrahimi #undef ARCH_32_64
1328*22dc650dSSadaf Ebrahimi 
1329*22dc650dSSadaf Ebrahimi /* reg_ar is an absoulute register! */
1330*22dc650dSSadaf Ebrahimi 
1331*22dc650dSSadaf Ebrahimi /* Can perform an operation using at most 1 instruction. */
getput_arg_fast(struct sljit_compiler * compiler,sljit_s32 flags,sljit_s32 reg_ar,sljit_s32 arg,sljit_sw argw)1332*22dc650dSSadaf Ebrahimi static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
1333*22dc650dSSadaf Ebrahimi {
1334*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(arg & SLJIT_MEM);
1335*22dc650dSSadaf Ebrahimi 
1336*22dc650dSSadaf Ebrahimi 	if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
1337*22dc650dSSadaf Ebrahimi 		/* Works for both absoulte and relative addresses. */
1338*22dc650dSSadaf Ebrahimi 		if (SLJIT_UNLIKELY(flags & ARG_TEST))
1339*22dc650dSSadaf Ebrahimi 			return 1;
1340*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)
1341*22dc650dSSadaf Ebrahimi 			| TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));
1342*22dc650dSSadaf Ebrahimi 		return -1;
1343*22dc650dSSadaf Ebrahimi 	}
1344*22dc650dSSadaf Ebrahimi 	return 0;
1345*22dc650dSSadaf Ebrahimi }
1346*22dc650dSSadaf Ebrahimi 
1347*22dc650dSSadaf Ebrahimi #define TO_ARGW_HI(argw) (((argw) & ~0xffff) + (((argw) & 0x8000) ? 0x10000 : 0))
1348*22dc650dSSadaf Ebrahimi 
1349*22dc650dSSadaf Ebrahimi /* See getput_arg below.
1350*22dc650dSSadaf Ebrahimi    Note: can_cache is called only for binary operators. */
can_cache(sljit_s32 arg,sljit_sw argw,sljit_s32 next_arg,sljit_sw next_argw)1351*22dc650dSSadaf Ebrahimi static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
1352*22dc650dSSadaf Ebrahimi {
1353*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
1354*22dc650dSSadaf Ebrahimi 
1355*22dc650dSSadaf Ebrahimi 	/* Simple operation except for updates. */
1356*22dc650dSSadaf Ebrahimi 	if (arg & OFFS_REG_MASK) {
1357*22dc650dSSadaf Ebrahimi 		argw &= 0x3;
1358*22dc650dSSadaf Ebrahimi 		next_argw &= 0x3;
1359*22dc650dSSadaf Ebrahimi 		if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
1360*22dc650dSSadaf Ebrahimi 			return 1;
1361*22dc650dSSadaf Ebrahimi 		return 0;
1362*22dc650dSSadaf Ebrahimi 	}
1363*22dc650dSSadaf Ebrahimi 
1364*22dc650dSSadaf Ebrahimi 	if (arg == next_arg) {
1365*22dc650dSSadaf Ebrahimi 		if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)
1366*22dc650dSSadaf Ebrahimi 				|| TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))
1367*22dc650dSSadaf Ebrahimi 			return 1;
1368*22dc650dSSadaf Ebrahimi 		return 0;
1369*22dc650dSSadaf Ebrahimi 	}
1370*22dc650dSSadaf Ebrahimi 
1371*22dc650dSSadaf Ebrahimi 	return 0;
1372*22dc650dSSadaf Ebrahimi }
1373*22dc650dSSadaf Ebrahimi 
1374*22dc650dSSadaf Ebrahimi /* Emit the necessary instructions. See can_cache above. */
getput_arg(struct sljit_compiler * compiler,sljit_s32 flags,sljit_s32 reg_ar,sljit_s32 arg,sljit_sw argw,sljit_s32 next_arg,sljit_sw next_argw)1375*22dc650dSSadaf Ebrahimi static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
1376*22dc650dSSadaf Ebrahimi {
1377*22dc650dSSadaf Ebrahimi 	sljit_s32 tmp_ar, base, delay_slot;
1378*22dc650dSSadaf Ebrahimi 	sljit_sw offset, argw_hi;
1379*22dc650dSSadaf Ebrahimi 
1380*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(arg & SLJIT_MEM);
1381*22dc650dSSadaf Ebrahimi 	if (!(next_arg & SLJIT_MEM)) {
1382*22dc650dSSadaf Ebrahimi 		next_arg = 0;
1383*22dc650dSSadaf Ebrahimi 		next_argw = 0;
1384*22dc650dSSadaf Ebrahimi 	}
1385*22dc650dSSadaf Ebrahimi 
1386*22dc650dSSadaf Ebrahimi 	/* Since tmp can be the same as base or offset registers,
1387*22dc650dSSadaf Ebrahimi 	 * these might be unavailable after modifying tmp. */
1388*22dc650dSSadaf Ebrahimi 	if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
1389*22dc650dSSadaf Ebrahimi 		tmp_ar = reg_ar;
1390*22dc650dSSadaf Ebrahimi 		delay_slot = reg_ar;
1391*22dc650dSSadaf Ebrahimi 	}
1392*22dc650dSSadaf Ebrahimi 	else {
1393*22dc650dSSadaf Ebrahimi 		tmp_ar = DR(TMP_REG1);
1394*22dc650dSSadaf Ebrahimi 		delay_slot = MOVABLE_INS;
1395*22dc650dSSadaf Ebrahimi 	}
1396*22dc650dSSadaf Ebrahimi 	base = arg & REG_MASK;
1397*22dc650dSSadaf Ebrahimi 
1398*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1399*22dc650dSSadaf Ebrahimi 		argw &= 0x3;
1400*22dc650dSSadaf Ebrahimi 
1401*22dc650dSSadaf Ebrahimi 		/* Using the cache. */
1402*22dc650dSSadaf Ebrahimi 		if (argw == compiler->cache_argw) {
1403*22dc650dSSadaf Ebrahimi 			if (arg == compiler->cache_arg)
1404*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1405*22dc650dSSadaf Ebrahimi 
1406*22dc650dSSadaf Ebrahimi 			if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
1407*22dc650dSSadaf Ebrahimi 				if (arg == next_arg && argw == (next_argw & 0x3)) {
1408*22dc650dSSadaf Ebrahimi 					compiler->cache_arg = arg;
1409*22dc650dSSadaf Ebrahimi 					compiler->cache_argw = argw;
1410*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
1411*22dc650dSSadaf Ebrahimi 					return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1412*22dc650dSSadaf Ebrahimi 				}
1413*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
1414*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1415*22dc650dSSadaf Ebrahimi 			}
1416*22dc650dSSadaf Ebrahimi 		}
1417*22dc650dSSadaf Ebrahimi 
1418*22dc650dSSadaf Ebrahimi 		if (SLJIT_UNLIKELY(argw)) {
1419*22dc650dSSadaf Ebrahimi 			compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
1420*22dc650dSSadaf Ebrahimi 			compiler->cache_argw = argw;
1421*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
1422*22dc650dSSadaf Ebrahimi 		}
1423*22dc650dSSadaf Ebrahimi 
1424*22dc650dSSadaf Ebrahimi 		if (arg == next_arg && argw == (next_argw & 0x3)) {
1425*22dc650dSSadaf Ebrahimi 			compiler->cache_arg = arg;
1426*22dc650dSSadaf Ebrahimi 			compiler->cache_argw = argw;
1427*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
1428*22dc650dSSadaf Ebrahimi 			tmp_ar = DR(TMP_REG3);
1429*22dc650dSSadaf Ebrahimi 		}
1430*22dc650dSSadaf Ebrahimi 		else
1431*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
1432*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1433*22dc650dSSadaf Ebrahimi 	}
1434*22dc650dSSadaf Ebrahimi 
1435*22dc650dSSadaf Ebrahimi 	if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)
1436*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(argw - compiler->cache_argw), delay_slot);
1437*22dc650dSSadaf Ebrahimi 
1438*22dc650dSSadaf Ebrahimi 	if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) {
1439*22dc650dSSadaf Ebrahimi 		offset = argw - compiler->cache_argw;
1440*22dc650dSSadaf Ebrahimi 	} else {
1441*22dc650dSSadaf Ebrahimi 		compiler->cache_arg = SLJIT_MEM;
1442*22dc650dSSadaf Ebrahimi 
1443*22dc650dSSadaf Ebrahimi 		argw_hi = TO_ARGW_HI(argw);
1444*22dc650dSSadaf Ebrahimi 
1445*22dc650dSSadaf Ebrahimi 		if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) {
1446*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
1447*22dc650dSSadaf Ebrahimi 			compiler->cache_argw = argw;
1448*22dc650dSSadaf Ebrahimi 			offset = 0;
1449*22dc650dSSadaf Ebrahimi 		} else {
1450*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw_hi));
1451*22dc650dSSadaf Ebrahimi 			compiler->cache_argw = argw_hi;
1452*22dc650dSSadaf Ebrahimi 			offset = argw & 0xffff;
1453*22dc650dSSadaf Ebrahimi 			argw = argw_hi;
1454*22dc650dSSadaf Ebrahimi 		}
1455*22dc650dSSadaf Ebrahimi 	}
1456*22dc650dSSadaf Ebrahimi 
1457*22dc650dSSadaf Ebrahimi 	if (!base)
1458*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);
1459*22dc650dSSadaf Ebrahimi 
1460*22dc650dSSadaf Ebrahimi 	if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {
1461*22dc650dSSadaf Ebrahimi 		compiler->cache_arg = arg;
1462*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));
1463*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);
1464*22dc650dSSadaf Ebrahimi 	}
1465*22dc650dSSadaf Ebrahimi 
1466*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));
1467*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(offset), delay_slot);
1468*22dc650dSSadaf Ebrahimi }
1469*22dc650dSSadaf Ebrahimi 
emit_op_mem(struct sljit_compiler * compiler,sljit_s32 flags,sljit_s32 reg_ar,sljit_s32 arg,sljit_sw argw)1470*22dc650dSSadaf Ebrahimi static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
1471*22dc650dSSadaf Ebrahimi {
1472*22dc650dSSadaf Ebrahimi 	sljit_s32 tmp_ar, base, delay_slot;
1473*22dc650dSSadaf Ebrahimi 
1474*22dc650dSSadaf Ebrahimi 	if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
1475*22dc650dSSadaf Ebrahimi 		return compiler->error;
1476*22dc650dSSadaf Ebrahimi 
1477*22dc650dSSadaf Ebrahimi 	if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
1478*22dc650dSSadaf Ebrahimi 		tmp_ar = reg_ar;
1479*22dc650dSSadaf Ebrahimi 		delay_slot = reg_ar;
1480*22dc650dSSadaf Ebrahimi 	}
1481*22dc650dSSadaf Ebrahimi 	else {
1482*22dc650dSSadaf Ebrahimi 		tmp_ar = DR(TMP_REG1);
1483*22dc650dSSadaf Ebrahimi 		delay_slot = MOVABLE_INS;
1484*22dc650dSSadaf Ebrahimi 	}
1485*22dc650dSSadaf Ebrahimi 	base = arg & REG_MASK;
1486*22dc650dSSadaf Ebrahimi 
1487*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1488*22dc650dSSadaf Ebrahimi 		argw &= 0x3;
1489*22dc650dSSadaf Ebrahimi 
1490*22dc650dSSadaf Ebrahimi 		if (SLJIT_UNLIKELY(argw)) {
1491*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));
1492*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar));
1493*22dc650dSSadaf Ebrahimi 		}
1494*22dc650dSSadaf Ebrahimi 		else
1495*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));
1496*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1497*22dc650dSSadaf Ebrahimi 	}
1498*22dc650dSSadaf Ebrahimi 
1499*22dc650dSSadaf Ebrahimi 	FAIL_IF(load_immediate(compiler, tmp_ar, TO_ARGW_HI(argw)));
1500*22dc650dSSadaf Ebrahimi 
1501*22dc650dSSadaf Ebrahimi 	if (base != 0)
1502*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar));
1503*22dc650dSSadaf Ebrahimi 
1504*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(argw), delay_slot);
1505*22dc650dSSadaf Ebrahimi }
1506*22dc650dSSadaf Ebrahimi 
emit_op_mem2(struct sljit_compiler * compiler,sljit_s32 flags,sljit_s32 reg,sljit_s32 arg1,sljit_sw arg1w,sljit_s32 arg2,sljit_sw arg2w)1507*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
1508*22dc650dSSadaf Ebrahimi {
1509*22dc650dSSadaf Ebrahimi 	if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
1510*22dc650dSSadaf Ebrahimi 		return compiler->error;
1511*22dc650dSSadaf Ebrahimi 	return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
1512*22dc650dSSadaf Ebrahimi }
1513*22dc650dSSadaf Ebrahimi 
1514*22dc650dSSadaf Ebrahimi #define EMIT_LOGICAL(op_imm, op_reg) \
1515*22dc650dSSadaf Ebrahimi 	if (flags & SRC2_IMM) { \
1516*22dc650dSSadaf Ebrahimi 		if (op & SLJIT_SET_Z) \
1517*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
1518*22dc650dSSadaf Ebrahimi 		if (!(flags & UNUSED_DEST)) \
1519*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
1520*22dc650dSSadaf Ebrahimi 	} \
1521*22dc650dSSadaf Ebrahimi 	else { \
1522*22dc650dSSadaf Ebrahimi 		if (op & SLJIT_SET_Z) \
1523*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
1524*22dc650dSSadaf Ebrahimi 		if (!(flags & UNUSED_DEST)) \
1525*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | D(dst), DR(dst))); \
1526*22dc650dSSadaf Ebrahimi 	}
1527*22dc650dSSadaf Ebrahimi 
1528*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1529*22dc650dSSadaf Ebrahimi 
1530*22dc650dSSadaf Ebrahimi #define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \
1531*22dc650dSSadaf Ebrahimi 	op_imm = (imm); \
1532*22dc650dSSadaf Ebrahimi 	op_v = (v);
1533*22dc650dSSadaf Ebrahimi 
1534*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
1535*22dc650dSSadaf Ebrahimi 
1536*22dc650dSSadaf Ebrahimi 
1537*22dc650dSSadaf Ebrahimi #define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \
1538*22dc650dSSadaf Ebrahimi 	op_dimm = (dimm); \
1539*22dc650dSSadaf Ebrahimi 	op_dimm32 = (dimm32); \
1540*22dc650dSSadaf Ebrahimi 	op_imm = (imm); \
1541*22dc650dSSadaf Ebrahimi 	op_dv = (dv); \
1542*22dc650dSSadaf Ebrahimi 	op_v = (v);
1543*22dc650dSSadaf Ebrahimi 
1544*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
1545*22dc650dSSadaf Ebrahimi 
1546*22dc650dSSadaf Ebrahimi #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV < 1)
1547*22dc650dSSadaf Ebrahimi 
emit_clz_ctz(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw src)1548*22dc650dSSadaf Ebrahimi static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
1549*22dc650dSSadaf Ebrahimi {
1550*22dc650dSSadaf Ebrahimi 	sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ);
1551*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1552*22dc650dSSadaf Ebrahimi 	sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;
1553*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_64 */
1554*22dc650dSSadaf Ebrahimi 	sljit_ins word_size = 32;
1555*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
1556*22dc650dSSadaf Ebrahimi 
1557*22dc650dSSadaf Ebrahimi 	/* The TMP_REG2 is the next value. */
1558*22dc650dSSadaf Ebrahimi 	if (src != TMP_REG2)
1559*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
1560*22dc650dSSadaf Ebrahimi 
1561*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(is_clz ? 13 : 14), UNMOVABLE_INS));
1562*22dc650dSSadaf Ebrahimi 	/* The OTHER_FLAG is the counter. Delay slot. */
1563*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(word_size), OTHER_FLAG));
1564*22dc650dSSadaf Ebrahimi 
1565*22dc650dSSadaf Ebrahimi 	if (!is_clz) {
1566*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG2) | T(TMP_REG1) | IMM(1), DR(TMP_REG1)));
1567*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, BNE | S(TMP_REG1) | TA(0) | IMM(11), UNMOVABLE_INS));
1568*22dc650dSSadaf Ebrahimi 	} else
1569*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG2) | TA(0) | IMM(11), UNMOVABLE_INS));
1570*22dc650dSSadaf Ebrahimi 
1571*22dc650dSSadaf Ebrahimi 	/* Delay slot. */
1572*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(0), OTHER_FLAG));
1573*22dc650dSSadaf Ebrahimi 
1574*22dc650dSSadaf Ebrahimi 	/* The TMP_REG1 is the next shift. */
1575*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(TMP_REG1) | IMM(word_size), DR(TMP_REG1)));
1576*22dc650dSSadaf Ebrahimi 
1577*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(TMP_REG2) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
1578*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
1579*22dc650dSSadaf Ebrahimi 
1580*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG1) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2)));
1581*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, BNE | S(TMP_REG2) | TA(0) | IMM(-4), UNMOVABLE_INS));
1582*22dc650dSSadaf Ebrahimi 	/* Delay slot. */
1583*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
1584*22dc650dSSadaf Ebrahimi 
1585*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(TMP_REG1) | T(TMP_REG2) | IMM(-1), DR(TMP_REG2)));
1586*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG2) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2)));
1587*22dc650dSSadaf Ebrahimi 
1588*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(-7), UNMOVABLE_INS));
1589*22dc650dSSadaf Ebrahimi 	/* Delay slot. */
1590*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, OR | SA(OTHER_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG));
1591*22dc650dSSadaf Ebrahimi 
1592*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, SELECT_OP(DADDU, ADDU) | SA(OTHER_FLAG) | TA(0) | D(dst), DR(dst));
1593*22dc650dSSadaf Ebrahimi }
1594*22dc650dSSadaf Ebrahimi 
1595*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV < 1 */
1596*22dc650dSSadaf Ebrahimi 
emit_rev(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw src)1597*22dc650dSSadaf Ebrahimi static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
1598*22dc650dSSadaf Ebrahimi {
1599*22dc650dSSadaf Ebrahimi #if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64
1600*22dc650dSSadaf Ebrahimi 	int is_32 = (op & SLJIT_32);
1601*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
1602*22dc650dSSadaf Ebrahimi 
1603*22dc650dSSadaf Ebrahimi 	op = GET_OPCODE(op);
1604*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
1605*22dc650dSSadaf Ebrahimi #if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64
1606*22dc650dSSadaf Ebrahimi 	if (!is_32 && (op == SLJIT_REV)) {
1607*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst)));
1608*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, DSHD | T(dst) | D(dst), DR(dst));
1609*22dc650dSSadaf Ebrahimi 	}
1610*22dc650dSSadaf Ebrahimi 	if (op != SLJIT_REV && src != TMP_REG2) {
1611*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG1), DR(TMP_REG1)));
1612*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
1613*22dc650dSSadaf Ebrahimi 	}
1614*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
1615*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst)));
1616*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ROTR | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
1617*22dc650dSSadaf Ebrahimi #if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64
1618*22dc650dSSadaf Ebrahimi 	if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3)
1619*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DINSU | T(dst) | SA(0) | (31 << 11), DR(dst)));
1620*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
1621*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 2 */
1622*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1623*22dc650dSSadaf Ebrahimi 	if (!is_32) {
1624*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DSRL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));
1625*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ORI | SA(0) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG));
1626*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(dst) | SH_IMM(0), DR(dst)));
1627*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DSLL32 | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(0), OTHER_FLAG));
1628*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));
1629*22dc650dSSadaf Ebrahimi 
1630*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1)));
1631*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG));
1632*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
1633*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
1634*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DSLL | TA(OTHER_FLAG) | DA(EQUAL_FLAG) | SH_IMM(8), EQUAL_FLAG));
1635*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
1636*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, XOR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
1637*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));
1638*22dc650dSSadaf Ebrahimi 
1639*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));
1640*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
1641*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
1642*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(8), DR(dst)));
1643*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));
1644*22dc650dSSadaf Ebrahimi 	}
1645*22dc650dSSadaf Ebrahimi 
1646*22dc650dSSadaf Ebrahimi 	if (op != SLJIT_REV && src != TMP_REG2) {
1647*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(0), DR(TMP_REG2)));
1648*22dc650dSSadaf Ebrahimi 		src = TMP_REG2;
1649*22dc650dSSadaf Ebrahimi 	}
1650*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
1651*22dc650dSSadaf Ebrahimi 
1652*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1)));
1653*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, LUI | TA(OTHER_FLAG) | 0xff, OTHER_FLAG));
1654*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SLL | T(src) | D(dst) | SH_IMM(16), DR(dst)));
1655*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xff, OTHER_FLAG));
1656*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));
1657*22dc650dSSadaf Ebrahimi 
1658*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));
1659*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
1660*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
1661*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SLL | T(dst) | D(dst) | SH_IMM(8), DR(dst)));
1662*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));
1663*22dc650dSSadaf Ebrahimi 
1664*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1665*22dc650dSSadaf Ebrahimi 	if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3) {
1666*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DSLL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)));
1667*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)));
1668*22dc650dSSadaf Ebrahimi 	}
1669*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
1670*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPR_REV >= 2 */
1671*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
1672*22dc650dSSadaf Ebrahimi }
1673*22dc650dSSadaf Ebrahimi 
emit_rev16(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw src)1674*22dc650dSSadaf Ebrahimi static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
1675*22dc650dSSadaf Ebrahimi {
1676*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
1677*22dc650dSSadaf Ebrahimi #if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32
1678*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst)));
1679*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
1680*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst)));
1681*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
1682*22dc650dSSadaf Ebrahimi 	if (GET_OPCODE(op) == SLJIT_REV_U16)
1683*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ANDI | S(dst) | T(dst) | 0xffff, DR(dst));
1684*22dc650dSSadaf Ebrahimi 	else
1685*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, SEH | T(dst) | D(dst), DR(dst));
1686*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 2 */
1687*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(src) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));
1688*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | T(src) | D(dst) | SH_IMM(24), DR(dst)));
1689*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG1) | T(TMP_REG1) | 0xff, DR(TMP_REG1)));
1690*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SELECT_OP(DSRL32, SRL) : SELECT_OP(DSRA32, SRA)) | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
1691*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));
1692*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
1693*22dc650dSSadaf Ebrahimi }
1694*22dc650dSSadaf Ebrahimi 
emit_single_op(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 flags,sljit_s32 dst,sljit_s32 src1,sljit_sw src2)1695*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
1696*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
1697*22dc650dSSadaf Ebrahimi {
1698*22dc650dSSadaf Ebrahimi 	sljit_s32 is_overflow, is_carry, carry_src_ar, is_handled, reg;
1699*22dc650dSSadaf Ebrahimi 	sljit_ins op_imm, op_v;
1700*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1701*22dc650dSSadaf Ebrahimi 	sljit_ins ins, op_dimm, op_dimm32, op_dv;
1702*22dc650dSSadaf Ebrahimi #endif
1703*22dc650dSSadaf Ebrahimi 
1704*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
1705*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV:
1706*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1707*22dc650dSSadaf Ebrahimi 		if (dst != src2)
1708*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
1709*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1710*22dc650dSSadaf Ebrahimi 
1711*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U8:
1712*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1713*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
1714*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
1715*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(dst == src2);
1716*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1717*22dc650dSSadaf Ebrahimi 
1718*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S8:
1719*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1720*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1721*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1722*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
1723*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
1724*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 2 */
1725*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
1726*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
1727*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
1728*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
1729*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
1730*22dc650dSSadaf Ebrahimi 			if (op & SLJIT_32)
1731*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
1732*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
1733*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
1734*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
1735*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
1736*22dc650dSSadaf Ebrahimi 		}
1737*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(dst == src2);
1738*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1739*22dc650dSSadaf Ebrahimi 
1740*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U16:
1741*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1742*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
1743*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
1744*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(dst == src2);
1745*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1746*22dc650dSSadaf Ebrahimi 
1747*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S16:
1748*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1749*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1750*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1751*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
1752*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
1753*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 2 */
1754*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
1755*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
1756*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
1757*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
1758*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
1759*22dc650dSSadaf Ebrahimi 			if (op & SLJIT_32)
1760*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
1761*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
1762*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
1763*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
1764*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
1765*22dc650dSSadaf Ebrahimi 		}
1766*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(dst == src2);
1767*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1768*22dc650dSSadaf Ebrahimi 
1769*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1770*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U32:
1771*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));
1772*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1773*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
1774*22dc650dSSadaf Ebrahimi 			if (dst == src2)
1775*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11), DR(dst));
1776*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
1777*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
1778*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
1779*22dc650dSSadaf Ebrahimi 		}
1780*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(dst == src2);
1781*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1782*22dc650dSSadaf Ebrahimi 
1783*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S32:
1784*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));
1785*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1786*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
1787*22dc650dSSadaf Ebrahimi 		}
1788*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(dst == src2);
1789*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1790*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
1791*22dc650dSSadaf Ebrahimi 
1792*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1793*22dc650dSSadaf Ebrahimi 	case SLJIT_CLZ:
1794*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1795*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1796*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | D(dst), DR(dst));
1797*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
1798*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst));
1799*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
1800*22dc650dSSadaf Ebrahimi 	case SLJIT_CTZ:
1801*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1802*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));
1803*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, AND | S(src2) | T(TMP_REG1) | D(dst), DR(dst)));
1804*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1805*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | D(dst), DR(dst)));
1806*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
1807*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | T(dst) | D(dst), DR(dst)));
1808*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
1809*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(TMP_REG1) | IMM(SELECT_OP(-64, -32)), DR(TMP_REG1)));
1810*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(SELECT_OP(26, 27)), DR(TMP_REG1)));
1811*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, XOR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));
1812*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 1 */
1813*22dc650dSSadaf Ebrahimi 	case SLJIT_CLZ:
1814*22dc650dSSadaf Ebrahimi 	case SLJIT_CTZ:
1815*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1816*22dc650dSSadaf Ebrahimi 		return emit_clz_ctz(compiler, op, dst, src2);
1817*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 1 */
1818*22dc650dSSadaf Ebrahimi 
1819*22dc650dSSadaf Ebrahimi 	case SLJIT_REV:
1820*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U32:
1821*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_S32:
1822*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && src2 != TMP_REG1 && dst != TMP_REG1);
1823*22dc650dSSadaf Ebrahimi 		return emit_rev(compiler, op, dst, src2);
1824*22dc650dSSadaf Ebrahimi 
1825*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U16:
1826*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_S16:
1827*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1828*22dc650dSSadaf Ebrahimi 		return emit_rev16(compiler, op, dst, src2);
1829*22dc650dSSadaf Ebrahimi 
1830*22dc650dSSadaf Ebrahimi 	case SLJIT_ADD:
1831*22dc650dSSadaf Ebrahimi 		/* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */
1832*22dc650dSSadaf Ebrahimi 		is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
1833*22dc650dSSadaf Ebrahimi 		carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY;
1834*22dc650dSSadaf Ebrahimi 
1835*22dc650dSSadaf Ebrahimi 		if (flags & SRC2_IMM) {
1836*22dc650dSSadaf Ebrahimi 			if (is_overflow) {
1837*22dc650dSSadaf Ebrahimi 				if (src2 >= 0)
1838*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
1839*22dc650dSSadaf Ebrahimi 				else
1840*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
1841*22dc650dSSadaf Ebrahimi 			}
1842*22dc650dSSadaf Ebrahimi 			else if (op & SLJIT_SET_Z)
1843*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
1844*22dc650dSSadaf Ebrahimi 
1845*22dc650dSSadaf Ebrahimi 			/* Only the zero flag is needed. */
1846*22dc650dSSadaf Ebrahimi 			if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
1847*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
1848*22dc650dSSadaf Ebrahimi 		}
1849*22dc650dSSadaf Ebrahimi 		else {
1850*22dc650dSSadaf Ebrahimi 			if (is_overflow)
1851*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1852*22dc650dSSadaf Ebrahimi 			else if (op & SLJIT_SET_Z)
1853*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1854*22dc650dSSadaf Ebrahimi 
1855*22dc650dSSadaf Ebrahimi 			if (is_overflow || carry_src_ar != 0) {
1856*22dc650dSSadaf Ebrahimi 				if (src1 != dst)
1857*22dc650dSSadaf Ebrahimi 					carry_src_ar = DR(src1);
1858*22dc650dSSadaf Ebrahimi 				else if (src2 != dst)
1859*22dc650dSSadaf Ebrahimi 					carry_src_ar = DR(src2);
1860*22dc650dSSadaf Ebrahimi 				else {
1861*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG));
1862*22dc650dSSadaf Ebrahimi 					carry_src_ar = OTHER_FLAG;
1863*22dc650dSSadaf Ebrahimi 				}
1864*22dc650dSSadaf Ebrahimi 			}
1865*22dc650dSSadaf Ebrahimi 
1866*22dc650dSSadaf Ebrahimi 			/* Only the zero flag is needed. */
1867*22dc650dSSadaf Ebrahimi 			if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
1868*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
1869*22dc650dSSadaf Ebrahimi 		}
1870*22dc650dSSadaf Ebrahimi 
1871*22dc650dSSadaf Ebrahimi 		/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
1872*22dc650dSSadaf Ebrahimi 		if (is_overflow || carry_src_ar != 0) {
1873*22dc650dSSadaf Ebrahimi 			if (flags & SRC2_IMM)
1874*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
1875*22dc650dSSadaf Ebrahimi 			else
1876*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(OTHER_FLAG), OTHER_FLAG));
1877*22dc650dSSadaf Ebrahimi 		}
1878*22dc650dSSadaf Ebrahimi 
1879*22dc650dSSadaf Ebrahimi 		if (!is_overflow)
1880*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1881*22dc650dSSadaf Ebrahimi 
1882*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
1883*22dc650dSSadaf Ebrahimi 		if (op & SLJIT_SET_Z)
1884*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
1885*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
1886*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
1887*22dc650dSSadaf Ebrahimi 
1888*22dc650dSSadaf Ebrahimi 	case SLJIT_ADDC:
1889*22dc650dSSadaf Ebrahimi 		carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY;
1890*22dc650dSSadaf Ebrahimi 
1891*22dc650dSSadaf Ebrahimi 		if (flags & SRC2_IMM) {
1892*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
1893*22dc650dSSadaf Ebrahimi 		} else {
1894*22dc650dSSadaf Ebrahimi 			if (carry_src_ar != 0) {
1895*22dc650dSSadaf Ebrahimi 				if (src1 != dst)
1896*22dc650dSSadaf Ebrahimi 					carry_src_ar = DR(src1);
1897*22dc650dSSadaf Ebrahimi 				else if (src2 != dst)
1898*22dc650dSSadaf Ebrahimi 					carry_src_ar = DR(src2);
1899*22dc650dSSadaf Ebrahimi 				else {
1900*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
1901*22dc650dSSadaf Ebrahimi 					carry_src_ar = EQUAL_FLAG;
1902*22dc650dSSadaf Ebrahimi 				}
1903*22dc650dSSadaf Ebrahimi 			}
1904*22dc650dSSadaf Ebrahimi 
1905*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
1906*22dc650dSSadaf Ebrahimi 		}
1907*22dc650dSSadaf Ebrahimi 
1908*22dc650dSSadaf Ebrahimi 		/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
1909*22dc650dSSadaf Ebrahimi 		if (carry_src_ar != 0) {
1910*22dc650dSSadaf Ebrahimi 			if (flags & SRC2_IMM)
1911*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
1912*22dc650dSSadaf Ebrahimi 			else
1913*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(EQUAL_FLAG), EQUAL_FLAG));
1914*22dc650dSSadaf Ebrahimi 		}
1915*22dc650dSSadaf Ebrahimi 
1916*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
1917*22dc650dSSadaf Ebrahimi 
1918*22dc650dSSadaf Ebrahimi 		if (carry_src_ar == 0)
1919*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1920*22dc650dSSadaf Ebrahimi 
1921*22dc650dSSadaf Ebrahimi 		/* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
1922*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
1923*22dc650dSSadaf Ebrahimi 		/* Set carry flag. */
1924*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
1925*22dc650dSSadaf Ebrahimi 
1926*22dc650dSSadaf Ebrahimi 	case SLJIT_SUB:
1927*22dc650dSSadaf Ebrahimi 		if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
1928*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
1929*22dc650dSSadaf Ebrahimi 			src2 = TMP_REG2;
1930*22dc650dSSadaf Ebrahimi 			flags &= ~SRC2_IMM;
1931*22dc650dSSadaf Ebrahimi 		}
1932*22dc650dSSadaf Ebrahimi 
1933*22dc650dSSadaf Ebrahimi 		is_handled = 0;
1934*22dc650dSSadaf Ebrahimi 
1935*22dc650dSSadaf Ebrahimi 		if (flags & SRC2_IMM) {
1936*22dc650dSSadaf Ebrahimi 			if (GET_FLAG_TYPE(op) == SLJIT_LESS) {
1937*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
1938*22dc650dSSadaf Ebrahimi 				is_handled = 1;
1939*22dc650dSSadaf Ebrahimi 			}
1940*22dc650dSSadaf Ebrahimi 			else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {
1941*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
1942*22dc650dSSadaf Ebrahimi 				is_handled = 1;
1943*22dc650dSSadaf Ebrahimi 			}
1944*22dc650dSSadaf Ebrahimi 		}
1945*22dc650dSSadaf Ebrahimi 
1946*22dc650dSSadaf Ebrahimi 		if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
1947*22dc650dSSadaf Ebrahimi 			is_handled = 1;
1948*22dc650dSSadaf Ebrahimi 
1949*22dc650dSSadaf Ebrahimi 			if (flags & SRC2_IMM) {
1950*22dc650dSSadaf Ebrahimi 				reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
1951*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(reg) | IMM(src2), DR(reg)));
1952*22dc650dSSadaf Ebrahimi 				src2 = reg;
1953*22dc650dSSadaf Ebrahimi 				flags &= ~SRC2_IMM;
1954*22dc650dSSadaf Ebrahimi 			}
1955*22dc650dSSadaf Ebrahimi 
1956*22dc650dSSadaf Ebrahimi 			switch (GET_FLAG_TYPE(op)) {
1957*22dc650dSSadaf Ebrahimi 			case SLJIT_LESS:
1958*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
1959*22dc650dSSadaf Ebrahimi 				break;
1960*22dc650dSSadaf Ebrahimi 			case SLJIT_GREATER:
1961*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
1962*22dc650dSSadaf Ebrahimi 				break;
1963*22dc650dSSadaf Ebrahimi 			case SLJIT_SIG_LESS:
1964*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
1965*22dc650dSSadaf Ebrahimi 				break;
1966*22dc650dSSadaf Ebrahimi 			case SLJIT_SIG_GREATER:
1967*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
1968*22dc650dSSadaf Ebrahimi 				break;
1969*22dc650dSSadaf Ebrahimi 			}
1970*22dc650dSSadaf Ebrahimi 		}
1971*22dc650dSSadaf Ebrahimi 
1972*22dc650dSSadaf Ebrahimi 		if (is_handled) {
1973*22dc650dSSadaf Ebrahimi 			if (flags & SRC2_IMM) {
1974*22dc650dSSadaf Ebrahimi 				if (op & SLJIT_SET_Z)
1975*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
1976*22dc650dSSadaf Ebrahimi 				if (!(flags & UNUSED_DEST))
1977*22dc650dSSadaf Ebrahimi 					return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));
1978*22dc650dSSadaf Ebrahimi 			}
1979*22dc650dSSadaf Ebrahimi 			else {
1980*22dc650dSSadaf Ebrahimi 				if (op & SLJIT_SET_Z)
1981*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1982*22dc650dSSadaf Ebrahimi 				if (!(flags & UNUSED_DEST))
1983*22dc650dSSadaf Ebrahimi 					return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));
1984*22dc650dSSadaf Ebrahimi 			}
1985*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1986*22dc650dSSadaf Ebrahimi 		}
1987*22dc650dSSadaf Ebrahimi 
1988*22dc650dSSadaf Ebrahimi 		is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
1989*22dc650dSSadaf Ebrahimi 		is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
1990*22dc650dSSadaf Ebrahimi 
1991*22dc650dSSadaf Ebrahimi 		if (flags & SRC2_IMM) {
1992*22dc650dSSadaf Ebrahimi 			if (is_overflow) {
1993*22dc650dSSadaf Ebrahimi 				if (src2 >= 0)
1994*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
1995*22dc650dSSadaf Ebrahimi 				else
1996*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
1997*22dc650dSSadaf Ebrahimi 			}
1998*22dc650dSSadaf Ebrahimi 			else if (op & SLJIT_SET_Z)
1999*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
2000*22dc650dSSadaf Ebrahimi 
2001*22dc650dSSadaf Ebrahimi 			if (is_overflow || is_carry)
2002*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
2003*22dc650dSSadaf Ebrahimi 
2004*22dc650dSSadaf Ebrahimi 			/* Only the zero flag is needed. */
2005*22dc650dSSadaf Ebrahimi 			if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
2006*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
2007*22dc650dSSadaf Ebrahimi 		}
2008*22dc650dSSadaf Ebrahimi 		else {
2009*22dc650dSSadaf Ebrahimi 			if (is_overflow)
2010*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
2011*22dc650dSSadaf Ebrahimi 			else if (op & SLJIT_SET_Z)
2012*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
2013*22dc650dSSadaf Ebrahimi 
2014*22dc650dSSadaf Ebrahimi 			if (is_overflow || is_carry)
2015*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
2016*22dc650dSSadaf Ebrahimi 
2017*22dc650dSSadaf Ebrahimi 			/* Only the zero flag is needed. */
2018*22dc650dSSadaf Ebrahimi 			if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
2019*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
2020*22dc650dSSadaf Ebrahimi 		}
2021*22dc650dSSadaf Ebrahimi 
2022*22dc650dSSadaf Ebrahimi 		if (!is_overflow)
2023*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
2024*22dc650dSSadaf Ebrahimi 
2025*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
2026*22dc650dSSadaf Ebrahimi 		if (op & SLJIT_SET_Z)
2027*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
2028*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
2029*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
2030*22dc650dSSadaf Ebrahimi 
2031*22dc650dSSadaf Ebrahimi 	case SLJIT_SUBC:
2032*22dc650dSSadaf Ebrahimi 		if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
2033*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
2034*22dc650dSSadaf Ebrahimi 			src2 = TMP_REG2;
2035*22dc650dSSadaf Ebrahimi 			flags &= ~SRC2_IMM;
2036*22dc650dSSadaf Ebrahimi 		}
2037*22dc650dSSadaf Ebrahimi 
2038*22dc650dSSadaf Ebrahimi 		is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
2039*22dc650dSSadaf Ebrahimi 
2040*22dc650dSSadaf Ebrahimi 		if (flags & SRC2_IMM) {
2041*22dc650dSSadaf Ebrahimi 			if (is_carry)
2042*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
2043*22dc650dSSadaf Ebrahimi 
2044*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
2045*22dc650dSSadaf Ebrahimi 		}
2046*22dc650dSSadaf Ebrahimi 		else {
2047*22dc650dSSadaf Ebrahimi 			if (is_carry)
2048*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
2049*22dc650dSSadaf Ebrahimi 
2050*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
2051*22dc650dSSadaf Ebrahimi 		}
2052*22dc650dSSadaf Ebrahimi 
2053*22dc650dSSadaf Ebrahimi 		if (is_carry)
2054*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
2055*22dc650dSSadaf Ebrahimi 
2056*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
2057*22dc650dSSadaf Ebrahimi 
2058*22dc650dSSadaf Ebrahimi 		if (!is_carry)
2059*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
2060*22dc650dSSadaf Ebrahimi 
2061*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG);
2062*22dc650dSSadaf Ebrahimi 
2063*22dc650dSSadaf Ebrahimi 	case SLJIT_MUL:
2064*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(flags & SRC2_IMM));
2065*22dc650dSSadaf Ebrahimi 
2066*22dc650dSSadaf Ebrahimi 		if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) {
2067*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2068*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));
2069*22dc650dSSadaf Ebrahimi #elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
2070*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2071*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
2072*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
2073*22dc650dSSadaf Ebrahimi 			if (op & SLJIT_32)
2074*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
2075*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
2076*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, MFLO | D(dst), DR(dst));
2077*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
2078*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 1 */
2079*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
2080*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, MFLO | D(dst), DR(dst));
2081*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
2082*22dc650dSSadaf Ebrahimi 		}
2083*22dc650dSSadaf Ebrahimi 
2084*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2085*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)));
2086*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
2087*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
2088*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
2089*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
2090*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
2091*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
2092*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
2093*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
2094*22dc650dSSadaf Ebrahimi 
2095*22dc650dSSadaf Ebrahimi 	case SLJIT_AND:
2096*22dc650dSSadaf Ebrahimi 		EMIT_LOGICAL(ANDI, AND);
2097*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2098*22dc650dSSadaf Ebrahimi 
2099*22dc650dSSadaf Ebrahimi 	case SLJIT_OR:
2100*22dc650dSSadaf Ebrahimi 		EMIT_LOGICAL(ORI, OR);
2101*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2102*22dc650dSSadaf Ebrahimi 
2103*22dc650dSSadaf Ebrahimi 	case SLJIT_XOR:
2104*22dc650dSSadaf Ebrahimi 		if (!(flags & LOGICAL_OP)) {
2105*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT((flags & SRC2_IMM) && src2 == -1);
2106*22dc650dSSadaf Ebrahimi 			if (op & SLJIT_SET_Z)
2107*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
2108*22dc650dSSadaf Ebrahimi 			if (!(flags & UNUSED_DEST))
2109*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | D(dst), DR(dst)));
2110*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
2111*22dc650dSSadaf Ebrahimi 		}
2112*22dc650dSSadaf Ebrahimi 		EMIT_LOGICAL(XORI, XOR);
2113*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2114*22dc650dSSadaf Ebrahimi 
2115*22dc650dSSadaf Ebrahimi 	case SLJIT_SHL:
2116*22dc650dSSadaf Ebrahimi 	case SLJIT_MSHL:
2117*22dc650dSSadaf Ebrahimi 		EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);
2118*22dc650dSSadaf Ebrahimi 		break;
2119*22dc650dSSadaf Ebrahimi 
2120*22dc650dSSadaf Ebrahimi 	case SLJIT_LSHR:
2121*22dc650dSSadaf Ebrahimi 	case SLJIT_MLSHR:
2122*22dc650dSSadaf Ebrahimi 		EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);
2123*22dc650dSSadaf Ebrahimi 		break;
2124*22dc650dSSadaf Ebrahimi 
2125*22dc650dSSadaf Ebrahimi 	case SLJIT_ASHR:
2126*22dc650dSSadaf Ebrahimi 	case SLJIT_MASHR:
2127*22dc650dSSadaf Ebrahimi 		EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);
2128*22dc650dSSadaf Ebrahimi 		break;
2129*22dc650dSSadaf Ebrahimi 
2130*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
2131*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTL:
2132*22dc650dSSadaf Ebrahimi 		if ((flags & SRC2_IMM) || src2 == 0) {
2133*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2134*22dc650dSSadaf Ebrahimi 			src2 = -src2 & 0x1f;
2135*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
2136*22dc650dSSadaf Ebrahimi 			src2 = -src2 & ((op & SLJIT_32) ? 0x1f : 0x3f);
2137*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
2138*22dc650dSSadaf Ebrahimi 		} else {
2139*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG2), DR(TMP_REG2)));
2140*22dc650dSSadaf Ebrahimi 			src2 = TMP_REG2;
2141*22dc650dSSadaf Ebrahimi 		}
2142*22dc650dSSadaf Ebrahimi 		/* fallthrough */
2143*22dc650dSSadaf Ebrahimi 
2144*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTR:
2145*22dc650dSSadaf Ebrahimi 		EMIT_SHIFT(DROTR, DROTR32, ROTR, DROTRV, ROTRV);
2146*22dc650dSSadaf Ebrahimi 		break;
2147*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 1 */
2148*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTL:
2149*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTR:
2150*22dc650dSSadaf Ebrahimi 		if (flags & SRC2_IMM) {
2151*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(src2 != 0);
2152*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2153*22dc650dSSadaf Ebrahimi 			if (!(op & SLJIT_32)) {
2154*22dc650dSSadaf Ebrahimi 				if (GET_OPCODE(op) == SLJIT_ROTL)
2155*22dc650dSSadaf Ebrahimi 					op_imm = ((src2 < 32) ? DSLL : DSLL32);
2156*22dc650dSSadaf Ebrahimi 				else
2157*22dc650dSSadaf Ebrahimi 					op_imm = ((src2 < 32) ? DSRL : DSRL32);
2158*22dc650dSSadaf Ebrahimi 
2159*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | (((sljit_ins)src2 & 0x1f) << 6), OTHER_FLAG));
2160*22dc650dSSadaf Ebrahimi 
2161*22dc650dSSadaf Ebrahimi 				src2 = 64 - src2;
2162*22dc650dSSadaf Ebrahimi 				if (GET_OPCODE(op) == SLJIT_ROTL)
2163*22dc650dSSadaf Ebrahimi 					op_imm = ((src2 < 32) ? DSRL : DSRL32);
2164*22dc650dSSadaf Ebrahimi 				else
2165*22dc650dSSadaf Ebrahimi 					op_imm = ((src2 < 32) ? DSLL : DSLL32);
2166*22dc650dSSadaf Ebrahimi 
2167*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst)));
2168*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));
2169*22dc650dSSadaf Ebrahimi 			}
2170*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
2171*22dc650dSSadaf Ebrahimi 
2172*22dc650dSSadaf Ebrahimi 			op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL;
2173*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | ((sljit_ins)src2 << 6), OTHER_FLAG));
2174*22dc650dSSadaf Ebrahimi 
2175*22dc650dSSadaf Ebrahimi 			src2 = 32 - src2;
2176*22dc650dSSadaf Ebrahimi 			op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL;
2177*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst)));
2178*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));
2179*22dc650dSSadaf Ebrahimi 		}
2180*22dc650dSSadaf Ebrahimi 
2181*22dc650dSSadaf Ebrahimi 		if (src2 == 0) {
2182*22dc650dSSadaf Ebrahimi 			if (dst != src1)
2183*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | D(dst), DR(dst));
2184*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
2185*22dc650dSSadaf Ebrahimi 		}
2186*22dc650dSSadaf Ebrahimi 
2187*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
2188*22dc650dSSadaf Ebrahimi 
2189*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2190*22dc650dSSadaf Ebrahimi 		if (!(op & SLJIT_32)) {
2191*22dc650dSSadaf Ebrahimi 			op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSLLV : DSRLV;
2192*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
2193*22dc650dSSadaf Ebrahimi 			op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSRLV : DSLLV;
2194*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst)));
2195*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));
2196*22dc650dSSadaf Ebrahimi 		}
2197*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
2198*22dc650dSSadaf Ebrahimi 
2199*22dc650dSSadaf Ebrahimi 		op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLV : SRLV;
2200*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
2201*22dc650dSSadaf Ebrahimi 		op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLV : SLLV;
2202*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst)));
2203*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));
2204*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
2205*22dc650dSSadaf Ebrahimi 
2206*22dc650dSSadaf Ebrahimi 	default:
2207*22dc650dSSadaf Ebrahimi 		SLJIT_UNREACHABLE();
2208*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2209*22dc650dSSadaf Ebrahimi 	}
2210*22dc650dSSadaf Ebrahimi 
2211*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2212*22dc650dSSadaf Ebrahimi 	if ((flags & SRC2_IMM) || src2 == 0) {
2213*22dc650dSSadaf Ebrahimi 		if (op & SLJIT_SET_Z)
2214*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG));
2215*22dc650dSSadaf Ebrahimi 
2216*22dc650dSSadaf Ebrahimi 		if (flags & UNUSED_DEST)
2217*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
2218*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst));
2219*22dc650dSSadaf Ebrahimi 	}
2220*22dc650dSSadaf Ebrahimi 
2221*22dc650dSSadaf Ebrahimi 	if (op & SLJIT_SET_Z)
2222*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
2223*22dc650dSSadaf Ebrahimi 
2224*22dc650dSSadaf Ebrahimi 	if (flags & UNUSED_DEST)
2225*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2226*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst));
2227*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
2228*22dc650dSSadaf Ebrahimi 	if ((flags & SRC2_IMM) || src2 == 0) {
2229*22dc650dSSadaf Ebrahimi 		if (src2 >= 32) {
2230*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(!(op & SLJIT_32));
2231*22dc650dSSadaf Ebrahimi 			ins = op_dimm32;
2232*22dc650dSSadaf Ebrahimi 			src2 -= 32;
2233*22dc650dSSadaf Ebrahimi 		}
2234*22dc650dSSadaf Ebrahimi 		else
2235*22dc650dSSadaf Ebrahimi 			ins = (op & SLJIT_32) ? op_imm : op_dimm;
2236*22dc650dSSadaf Ebrahimi 
2237*22dc650dSSadaf Ebrahimi 		if (op & SLJIT_SET_Z)
2238*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG));
2239*22dc650dSSadaf Ebrahimi 
2240*22dc650dSSadaf Ebrahimi 		if (flags & UNUSED_DEST)
2241*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
2242*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst));
2243*22dc650dSSadaf Ebrahimi 	}
2244*22dc650dSSadaf Ebrahimi 
2245*22dc650dSSadaf Ebrahimi 	ins = (op & SLJIT_32) ? op_v : op_dv;
2246*22dc650dSSadaf Ebrahimi 	if (op & SLJIT_SET_Z)
2247*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
2248*22dc650dSSadaf Ebrahimi 
2249*22dc650dSSadaf Ebrahimi 	if (flags & UNUSED_DEST)
2250*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2251*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst));
2252*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
2253*22dc650dSSadaf Ebrahimi }
2254*22dc650dSSadaf Ebrahimi 
2255*22dc650dSSadaf Ebrahimi #define CHECK_IMM(flags, srcw) \
2256*22dc650dSSadaf Ebrahimi 	((!((flags) & LOGICAL_OP) && ((srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)) \
2257*22dc650dSSadaf Ebrahimi 		|| (((flags) & LOGICAL_OP) && !((srcw) & ~UIMM_MAX)))
2258*22dc650dSSadaf Ebrahimi 
emit_op(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 flags,sljit_s32 dst,sljit_sw dstw,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2259*22dc650dSSadaf Ebrahimi static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
2260*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2261*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2262*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2263*22dc650dSSadaf Ebrahimi {
2264*22dc650dSSadaf Ebrahimi 	/* arg1 goes to TMP_REG1 or src reg
2265*22dc650dSSadaf Ebrahimi 	   arg2 goes to TMP_REG2, imm or src reg
2266*22dc650dSSadaf Ebrahimi 	   TMP_REG3 can be used for caching
2267*22dc650dSSadaf Ebrahimi 	   result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
2268*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r = TMP_REG2;
2269*22dc650dSSadaf Ebrahimi 	sljit_s32 src1_r;
2270*22dc650dSSadaf Ebrahimi 	sljit_sw src2_r = 0;
2271*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;
2272*22dc650dSSadaf Ebrahimi 
2273*22dc650dSSadaf Ebrahimi 	if (!(flags & ALT_KEEP_CACHE)) {
2274*22dc650dSSadaf Ebrahimi 		compiler->cache_arg = 0;
2275*22dc650dSSadaf Ebrahimi 		compiler->cache_argw = 0;
2276*22dc650dSSadaf Ebrahimi 	}
2277*22dc650dSSadaf Ebrahimi 
2278*22dc650dSSadaf Ebrahimi 	if (dst == 0) {
2279*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(HAS_FLAGS(op));
2280*22dc650dSSadaf Ebrahimi 		flags |= UNUSED_DEST;
2281*22dc650dSSadaf Ebrahimi 		dst = TMP_REG2;
2282*22dc650dSSadaf Ebrahimi 	}
2283*22dc650dSSadaf Ebrahimi 	else if (FAST_IS_REG(dst)) {
2284*22dc650dSSadaf Ebrahimi 		dst_r = dst;
2285*22dc650dSSadaf Ebrahimi 		flags |= REG_DEST;
2286*22dc650dSSadaf Ebrahimi 		if (flags & MOVE_OP)
2287*22dc650dSSadaf Ebrahimi 			src2_tmp_reg = dst_r;
2288*22dc650dSSadaf Ebrahimi 	}
2289*22dc650dSSadaf Ebrahimi 	else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
2290*22dc650dSSadaf Ebrahimi 		flags |= SLOW_DEST;
2291*22dc650dSSadaf Ebrahimi 
2292*22dc650dSSadaf Ebrahimi 	if (flags & IMM_OP) {
2293*22dc650dSSadaf Ebrahimi 		if (src2 == SLJIT_IMM && src2w != 0 && CHECK_IMM(flags, src2w)) {
2294*22dc650dSSadaf Ebrahimi 			flags |= SRC2_IMM;
2295*22dc650dSSadaf Ebrahimi 			src2_r = src2w;
2296*22dc650dSSadaf Ebrahimi 		} else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && CHECK_IMM(flags, src1w)) {
2297*22dc650dSSadaf Ebrahimi 			flags |= SRC2_IMM;
2298*22dc650dSSadaf Ebrahimi 			src2_r = src1w;
2299*22dc650dSSadaf Ebrahimi 
2300*22dc650dSSadaf Ebrahimi 			/* And swap arguments. */
2301*22dc650dSSadaf Ebrahimi 			src1 = src2;
2302*22dc650dSSadaf Ebrahimi 			src1w = src2w;
2303*22dc650dSSadaf Ebrahimi 			src2 = SLJIT_IMM;
2304*22dc650dSSadaf Ebrahimi 			/* src2w = src2_r unneeded. */
2305*22dc650dSSadaf Ebrahimi 		}
2306*22dc650dSSadaf Ebrahimi 	}
2307*22dc650dSSadaf Ebrahimi 
2308*22dc650dSSadaf Ebrahimi 	/* Source 1. */
2309*22dc650dSSadaf Ebrahimi 	if (FAST_IS_REG(src1)) {
2310*22dc650dSSadaf Ebrahimi 		src1_r = src1;
2311*22dc650dSSadaf Ebrahimi 		flags |= REG1_SOURCE;
2312*22dc650dSSadaf Ebrahimi 	}
2313*22dc650dSSadaf Ebrahimi 	else if (src1 == SLJIT_IMM) {
2314*22dc650dSSadaf Ebrahimi 		if (src1w) {
2315*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
2316*22dc650dSSadaf Ebrahimi 			src1_r = TMP_REG1;
2317*22dc650dSSadaf Ebrahimi 		}
2318*22dc650dSSadaf Ebrahimi 		else
2319*22dc650dSSadaf Ebrahimi 			src1_r = 0;
2320*22dc650dSSadaf Ebrahimi 	}
2321*22dc650dSSadaf Ebrahimi 	else {
2322*22dc650dSSadaf Ebrahimi 		if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))
2323*22dc650dSSadaf Ebrahimi 			FAIL_IF(compiler->error);
2324*22dc650dSSadaf Ebrahimi 		else
2325*22dc650dSSadaf Ebrahimi 			flags |= SLOW_SRC1;
2326*22dc650dSSadaf Ebrahimi 		src1_r = TMP_REG1;
2327*22dc650dSSadaf Ebrahimi 	}
2328*22dc650dSSadaf Ebrahimi 
2329*22dc650dSSadaf Ebrahimi 	/* Source 2. */
2330*22dc650dSSadaf Ebrahimi 	if (FAST_IS_REG(src2)) {
2331*22dc650dSSadaf Ebrahimi 		src2_r = src2;
2332*22dc650dSSadaf Ebrahimi 		flags |= REG2_SOURCE;
2333*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
2334*22dc650dSSadaf Ebrahimi 			dst_r = (sljit_s32)src2_r;
2335*22dc650dSSadaf Ebrahimi 	}
2336*22dc650dSSadaf Ebrahimi 	else if (src2 == SLJIT_IMM) {
2337*22dc650dSSadaf Ebrahimi 		if (!(flags & SRC2_IMM)) {
2338*22dc650dSSadaf Ebrahimi 			if (src2w) {
2339*22dc650dSSadaf Ebrahimi 				FAIL_IF(load_immediate(compiler, DR(src2_tmp_reg), src2w));
2340*22dc650dSSadaf Ebrahimi 				src2_r = src2_tmp_reg;
2341*22dc650dSSadaf Ebrahimi 			}
2342*22dc650dSSadaf Ebrahimi 			else {
2343*22dc650dSSadaf Ebrahimi 				src2_r = 0;
2344*22dc650dSSadaf Ebrahimi 				if (flags & MOVE_OP) {
2345*22dc650dSSadaf Ebrahimi 					if (dst & SLJIT_MEM)
2346*22dc650dSSadaf Ebrahimi 						dst_r = 0;
2347*22dc650dSSadaf Ebrahimi 					else
2348*22dc650dSSadaf Ebrahimi 						op = SLJIT_MOV;
2349*22dc650dSSadaf Ebrahimi 				}
2350*22dc650dSSadaf Ebrahimi 			}
2351*22dc650dSSadaf Ebrahimi 		}
2352*22dc650dSSadaf Ebrahimi 	}
2353*22dc650dSSadaf Ebrahimi 	else {
2354*22dc650dSSadaf Ebrahimi 		if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(src2_tmp_reg), src2, src2w))
2355*22dc650dSSadaf Ebrahimi 			FAIL_IF(compiler->error);
2356*22dc650dSSadaf Ebrahimi 		else
2357*22dc650dSSadaf Ebrahimi 			flags |= SLOW_SRC2;
2358*22dc650dSSadaf Ebrahimi 		src2_r = src2_tmp_reg;
2359*22dc650dSSadaf Ebrahimi 	}
2360*22dc650dSSadaf Ebrahimi 
2361*22dc650dSSadaf Ebrahimi 	if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
2362*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src2_r == TMP_REG2);
2363*22dc650dSSadaf Ebrahimi 		if ((flags & SLOW_DEST) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
2364*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));
2365*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
2366*22dc650dSSadaf Ebrahimi 		}
2367*22dc650dSSadaf Ebrahimi 		else {
2368*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));
2369*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));
2370*22dc650dSSadaf Ebrahimi 		}
2371*22dc650dSSadaf Ebrahimi 	}
2372*22dc650dSSadaf Ebrahimi 	else if (flags & SLOW_SRC1)
2373*22dc650dSSadaf Ebrahimi 		FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
2374*22dc650dSSadaf Ebrahimi 	else if (flags & SLOW_SRC2)
2375*22dc650dSSadaf Ebrahimi 		FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(src2_tmp_reg), src2, src2w, dst, dstw));
2376*22dc650dSSadaf Ebrahimi 
2377*22dc650dSSadaf Ebrahimi 	FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
2378*22dc650dSSadaf Ebrahimi 
2379*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM) {
2380*22dc650dSSadaf Ebrahimi 		if (!(flags & SLOW_DEST)) {
2381*22dc650dSSadaf Ebrahimi 			getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);
2382*22dc650dSSadaf Ebrahimi 			return compiler->error;
2383*22dc650dSSadaf Ebrahimi 		}
2384*22dc650dSSadaf Ebrahimi 		return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);
2385*22dc650dSSadaf Ebrahimi 	}
2386*22dc650dSSadaf Ebrahimi 
2387*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2388*22dc650dSSadaf Ebrahimi }
2389*22dc650dSSadaf Ebrahimi 
2390*22dc650dSSadaf Ebrahimi #undef CHECK_IMM
2391*22dc650dSSadaf Ebrahimi 
sljit_emit_op0(struct sljit_compiler * compiler,sljit_s32 op)2392*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
2393*22dc650dSSadaf Ebrahimi {
2394*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2395*22dc650dSSadaf Ebrahimi 	sljit_s32 int_op = op & SLJIT_32;
2396*22dc650dSSadaf Ebrahimi #endif
2397*22dc650dSSadaf Ebrahimi 
2398*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2399*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op0(compiler, op));
2400*22dc650dSSadaf Ebrahimi 
2401*22dc650dSSadaf Ebrahimi 	op = GET_OPCODE(op);
2402*22dc650dSSadaf Ebrahimi 	switch (op) {
2403*22dc650dSSadaf Ebrahimi 	case SLJIT_BREAKPOINT:
2404*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, BREAK, UNMOVABLE_INS);
2405*22dc650dSSadaf Ebrahimi 	case SLJIT_NOP:
2406*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, NOP, UNMOVABLE_INS);
2407*22dc650dSSadaf Ebrahimi 	case SLJIT_LMUL_UW:
2408*22dc650dSSadaf Ebrahimi 	case SLJIT_LMUL_SW:
2409*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2410*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2411*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
2412*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
2413*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_64 */
2414*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
2415*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
2416*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
2417*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
2418*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
2419*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
2420*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2421*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2422*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_64 */
2423*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2424*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
2425*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
2426*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
2427*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
2428*22dc650dSSadaf Ebrahimi 	case SLJIT_DIVMOD_UW:
2429*22dc650dSSadaf Ebrahimi 	case SLJIT_DIVMOD_SW:
2430*22dc650dSSadaf Ebrahimi 	case SLJIT_DIV_UW:
2431*22dc650dSSadaf Ebrahimi 	case SLJIT_DIV_SW:
2432*22dc650dSSadaf Ebrahimi 		SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
2433*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2434*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2435*22dc650dSSadaf Ebrahimi 		if (int_op) {
2436*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
2437*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
2438*22dc650dSSadaf Ebrahimi 		}
2439*22dc650dSSadaf Ebrahimi 		else {
2440*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
2441*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
2442*22dc650dSSadaf Ebrahimi 		}
2443*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_64 */
2444*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
2445*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
2446*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
2447*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
2448*22dc650dSSadaf Ebrahimi 		return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
2449*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
2450*22dc650dSSadaf Ebrahimi #if !(defined SLJIT_MIPS_REV)
2451*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2452*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2453*22dc650dSSadaf Ebrahimi #endif /* !SLJIT_MIPS_REV */
2454*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2455*22dc650dSSadaf Ebrahimi 		if (int_op)
2456*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2457*22dc650dSSadaf Ebrahimi 		else
2458*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2459*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_64 */
2460*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2461*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
2462*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
2463*22dc650dSSadaf Ebrahimi 		return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
2464*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
2465*22dc650dSSadaf Ebrahimi 	case SLJIT_ENDBR:
2466*22dc650dSSadaf Ebrahimi 	case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
2467*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2468*22dc650dSSadaf Ebrahimi 	}
2469*22dc650dSSadaf Ebrahimi 
2470*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2471*22dc650dSSadaf Ebrahimi }
2472*22dc650dSSadaf Ebrahimi 
2473*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
emit_prefetch(struct sljit_compiler * compiler,sljit_s32 src,sljit_sw srcw)2474*22dc650dSSadaf Ebrahimi static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
2475*22dc650dSSadaf Ebrahimi         sljit_s32 src, sljit_sw srcw)
2476*22dc650dSSadaf Ebrahimi {
2477*22dc650dSSadaf Ebrahimi 	if (!(src & OFFS_REG_MASK)) {
2478*22dc650dSSadaf Ebrahimi 		if (srcw <= SIMM_MAX && srcw >= SIMM_MIN)
2479*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS);
2480*22dc650dSSadaf Ebrahimi 
2481*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
2482*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
2483*22dc650dSSadaf Ebrahimi 	}
2484*22dc650dSSadaf Ebrahimi 
2485*22dc650dSSadaf Ebrahimi 	srcw &= 0x3;
2486*22dc650dSSadaf Ebrahimi 
2487*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(srcw != 0)) {
2488*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1)));
2489*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
2490*22dc650dSSadaf Ebrahimi 	}
2491*22dc650dSSadaf Ebrahimi 
2492*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);
2493*22dc650dSSadaf Ebrahimi }
2494*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 1 */
2495*22dc650dSSadaf Ebrahimi 
sljit_emit_op1(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2496*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
2497*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2498*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2499*22dc650dSSadaf Ebrahimi {
2500*22dc650dSSadaf Ebrahimi 	sljit_s32 flags = 0;
2501*22dc650dSSadaf Ebrahimi 
2502*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2503*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
2504*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
2505*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src, srcw);
2506*22dc650dSSadaf Ebrahimi 
2507*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2508*22dc650dSSadaf Ebrahimi 	if (op & SLJIT_32)
2509*22dc650dSSadaf Ebrahimi 		flags = INT_DATA | SIGNED_DATA;
2510*22dc650dSSadaf Ebrahimi #endif
2511*22dc650dSSadaf Ebrahimi 
2512*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
2513*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV:
2514*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2515*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U32:
2516*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S32:
2517*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV32:
2518*22dc650dSSadaf Ebrahimi #endif
2519*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_P:
2520*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);
2521*22dc650dSSadaf Ebrahimi 
2522*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2523*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U32:
2524*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);
2525*22dc650dSSadaf Ebrahimi 
2526*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S32:
2527*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV32:
2528*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw);
2529*22dc650dSSadaf Ebrahimi #endif
2530*22dc650dSSadaf Ebrahimi 
2531*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U8:
2532*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);
2533*22dc650dSSadaf Ebrahimi 
2534*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S8:
2535*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);
2536*22dc650dSSadaf Ebrahimi 
2537*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U16:
2538*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);
2539*22dc650dSSadaf Ebrahimi 
2540*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S16:
2541*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);
2542*22dc650dSSadaf Ebrahimi 
2543*22dc650dSSadaf Ebrahimi 	case SLJIT_CLZ:
2544*22dc650dSSadaf Ebrahimi 	case SLJIT_CTZ:
2545*22dc650dSSadaf Ebrahimi 	case SLJIT_REV:
2546*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
2547*22dc650dSSadaf Ebrahimi 
2548*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U16:
2549*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_S16:
2550*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
2551*22dc650dSSadaf Ebrahimi 
2552*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U32:
2553*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_S32:
2554*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
2555*22dc650dSSadaf Ebrahimi 	}
2556*22dc650dSSadaf Ebrahimi 
2557*22dc650dSSadaf Ebrahimi 	SLJIT_UNREACHABLE();
2558*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2559*22dc650dSSadaf Ebrahimi }
2560*22dc650dSSadaf Ebrahimi 
sljit_emit_op2(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2561*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
2562*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2563*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2564*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2565*22dc650dSSadaf Ebrahimi {
2566*22dc650dSSadaf Ebrahimi 	sljit_s32 flags = 0;
2567*22dc650dSSadaf Ebrahimi 
2568*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2569*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
2570*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
2571*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
2572*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src2, src2w);
2573*22dc650dSSadaf Ebrahimi 
2574*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2575*22dc650dSSadaf Ebrahimi 	if (op & SLJIT_32) {
2576*22dc650dSSadaf Ebrahimi 		flags |= INT_DATA | SIGNED_DATA;
2577*22dc650dSSadaf Ebrahimi 		if (src1 == SLJIT_IMM)
2578*22dc650dSSadaf Ebrahimi 			src1w = (sljit_s32)src1w;
2579*22dc650dSSadaf Ebrahimi 		if (src2 == SLJIT_IMM)
2580*22dc650dSSadaf Ebrahimi 			src2w = (sljit_s32)src2w;
2581*22dc650dSSadaf Ebrahimi 	}
2582*22dc650dSSadaf Ebrahimi #endif
2583*22dc650dSSadaf Ebrahimi 
2584*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
2585*22dc650dSSadaf Ebrahimi 	case SLJIT_ADD:
2586*22dc650dSSadaf Ebrahimi 	case SLJIT_ADDC:
2587*22dc650dSSadaf Ebrahimi 		compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
2588*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2589*22dc650dSSadaf Ebrahimi 
2590*22dc650dSSadaf Ebrahimi 	case SLJIT_SUB:
2591*22dc650dSSadaf Ebrahimi 	case SLJIT_SUBC:
2592*22dc650dSSadaf Ebrahimi 		compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
2593*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2594*22dc650dSSadaf Ebrahimi 
2595*22dc650dSSadaf Ebrahimi 	case SLJIT_MUL:
2596*22dc650dSSadaf Ebrahimi 		compiler->status_flags_state = 0;
2597*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
2598*22dc650dSSadaf Ebrahimi 
2599*22dc650dSSadaf Ebrahimi 	case SLJIT_XOR:
2600*22dc650dSSadaf Ebrahimi 		if ((src1 == SLJIT_IMM && src1w == -1) || (src2 == SLJIT_IMM && src2w == -1)) {
2601*22dc650dSSadaf Ebrahimi 			return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2602*22dc650dSSadaf Ebrahimi 		}
2603*22dc650dSSadaf Ebrahimi 		/* fallthrough */
2604*22dc650dSSadaf Ebrahimi 	case SLJIT_AND:
2605*22dc650dSSadaf Ebrahimi 	case SLJIT_OR:
2606*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2607*22dc650dSSadaf Ebrahimi 
2608*22dc650dSSadaf Ebrahimi 	case SLJIT_SHL:
2609*22dc650dSSadaf Ebrahimi 	case SLJIT_MSHL:
2610*22dc650dSSadaf Ebrahimi 	case SLJIT_LSHR:
2611*22dc650dSSadaf Ebrahimi 	case SLJIT_MLSHR:
2612*22dc650dSSadaf Ebrahimi 	case SLJIT_ASHR:
2613*22dc650dSSadaf Ebrahimi 	case SLJIT_MASHR:
2614*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTL:
2615*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTR:
2616*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2617*22dc650dSSadaf Ebrahimi 		if (src2 == SLJIT_IMM)
2618*22dc650dSSadaf Ebrahimi 			src2w &= 0x1f;
2619*22dc650dSSadaf Ebrahimi #else
2620*22dc650dSSadaf Ebrahimi 		if (src2 == SLJIT_IMM) {
2621*22dc650dSSadaf Ebrahimi 			if (op & SLJIT_32)
2622*22dc650dSSadaf Ebrahimi 				src2w &= 0x1f;
2623*22dc650dSSadaf Ebrahimi 			else
2624*22dc650dSSadaf Ebrahimi 				src2w &= 0x3f;
2625*22dc650dSSadaf Ebrahimi 		}
2626*22dc650dSSadaf Ebrahimi #endif
2627*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2628*22dc650dSSadaf Ebrahimi 	}
2629*22dc650dSSadaf Ebrahimi 
2630*22dc650dSSadaf Ebrahimi 	SLJIT_UNREACHABLE();
2631*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2632*22dc650dSSadaf Ebrahimi }
2633*22dc650dSSadaf Ebrahimi 
sljit_emit_op2u(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2634*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
2635*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2636*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2637*22dc650dSSadaf Ebrahimi {
2638*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2639*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
2640*22dc650dSSadaf Ebrahimi 
2641*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
2642*22dc650dSSadaf Ebrahimi 	return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);
2643*22dc650dSSadaf Ebrahimi }
2644*22dc650dSSadaf Ebrahimi 
2645*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2646*22dc650dSSadaf Ebrahimi #define SELECT_OP3(op, src2w, D, D32, W) (((op & SLJIT_32) ? (W) : ((src2w) < 32) ? (D) : (D32)) | (((sljit_ins)src2w & 0x1f) << 6))
2647*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_64 */
2648*22dc650dSSadaf Ebrahimi #define SELECT_OP3(op, src2w, D, D32, W) ((W) | ((sljit_ins)(src2w) << 6))
2649*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
2650*22dc650dSSadaf Ebrahimi 
sljit_emit_op2r(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst_reg,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2651*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
2652*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg,
2653*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2654*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2655*22dc650dSSadaf Ebrahimi {
2656*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2657*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
2658*22dc650dSSadaf Ebrahimi 
2659*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
2660*22dc650dSSadaf Ebrahimi 	case SLJIT_MULADD:
2661*22dc650dSSadaf Ebrahimi 		SLJIT_SKIP_CHECKS(compiler);
2662*22dc650dSSadaf Ebrahimi 		FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));
2663*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst_reg) | T(TMP_REG2) | D(dst_reg), DR(dst_reg));
2664*22dc650dSSadaf Ebrahimi 	}
2665*22dc650dSSadaf Ebrahimi 
2666*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2667*22dc650dSSadaf Ebrahimi }
2668*22dc650dSSadaf Ebrahimi 
sljit_emit_shift_into(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst_reg,sljit_s32 src1_reg,sljit_s32 src2_reg,sljit_s32 src3,sljit_sw src3w)2669*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
2670*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg,
2671*22dc650dSSadaf Ebrahimi 	sljit_s32 src1_reg,
2672*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_reg,
2673*22dc650dSSadaf Ebrahimi 	sljit_s32 src3, sljit_sw src3w)
2674*22dc650dSSadaf Ebrahimi {
2675*22dc650dSSadaf Ebrahimi 	sljit_s32 is_left;
2676*22dc650dSSadaf Ebrahimi 	sljit_ins ins1, ins2, ins3;
2677*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2678*22dc650dSSadaf Ebrahimi 	sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
2679*22dc650dSSadaf Ebrahimi 	sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;
2680*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_64 */
2681*22dc650dSSadaf Ebrahimi 	sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
2682*22dc650dSSadaf Ebrahimi 	sljit_sw bit_length = 32;
2683*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
2684*22dc650dSSadaf Ebrahimi 
2685*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2686*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
2687*22dc650dSSadaf Ebrahimi 
2688*22dc650dSSadaf Ebrahimi 	is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);
2689*22dc650dSSadaf Ebrahimi 
2690*22dc650dSSadaf Ebrahimi 	if (src1_reg == src2_reg) {
2691*22dc650dSSadaf Ebrahimi 		SLJIT_SKIP_CHECKS(compiler);
2692*22dc650dSSadaf Ebrahimi 		return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);
2693*22dc650dSSadaf Ebrahimi 	}
2694*22dc650dSSadaf Ebrahimi 
2695*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src3, src3w);
2696*22dc650dSSadaf Ebrahimi 
2697*22dc650dSSadaf Ebrahimi 	if (src3 == SLJIT_IMM) {
2698*22dc650dSSadaf Ebrahimi 		src3w &= bit_length - 1;
2699*22dc650dSSadaf Ebrahimi 
2700*22dc650dSSadaf Ebrahimi 		if (src3w == 0)
2701*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
2702*22dc650dSSadaf Ebrahimi 
2703*22dc650dSSadaf Ebrahimi 		if (is_left) {
2704*22dc650dSSadaf Ebrahimi 			ins1 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL);
2705*22dc650dSSadaf Ebrahimi 			src3w = bit_length - src3w;
2706*22dc650dSSadaf Ebrahimi 			ins2 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL);
2707*22dc650dSSadaf Ebrahimi 		} else {
2708*22dc650dSSadaf Ebrahimi 			ins1 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL);
2709*22dc650dSSadaf Ebrahimi 			src3w = bit_length - src3w;
2710*22dc650dSSadaf Ebrahimi 			ins2 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL);
2711*22dc650dSSadaf Ebrahimi 		}
2712*22dc650dSSadaf Ebrahimi 
2713*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ins1 | T(src1_reg) | D(dst_reg), DR(dst_reg)));
2714*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ins2 | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1)));
2715*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));
2716*22dc650dSSadaf Ebrahimi 	}
2717*22dc650dSSadaf Ebrahimi 
2718*22dc650dSSadaf Ebrahimi 	if (src3 & SLJIT_MEM) {
2719*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG2), src3, src3w));
2720*22dc650dSSadaf Ebrahimi 		src3 = TMP_REG2;
2721*22dc650dSSadaf Ebrahimi 	} else if (dst_reg == src3) {
2722*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src3) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
2723*22dc650dSSadaf Ebrahimi 		src3 = TMP_REG2;
2724*22dc650dSSadaf Ebrahimi 	}
2725*22dc650dSSadaf Ebrahimi 
2726*22dc650dSSadaf Ebrahimi 	if (is_left) {
2727*22dc650dSSadaf Ebrahimi 		ins1 = SELECT_OP(DSRL, SRL);
2728*22dc650dSSadaf Ebrahimi 		ins2 = SELECT_OP(DSLLV, SLLV);
2729*22dc650dSSadaf Ebrahimi 		ins3 = SELECT_OP(DSRLV, SRLV);
2730*22dc650dSSadaf Ebrahimi 	} else {
2731*22dc650dSSadaf Ebrahimi 		ins1 = SELECT_OP(DSLL, SLL);
2732*22dc650dSSadaf Ebrahimi 		ins2 = SELECT_OP(DSRLV, SRLV);
2733*22dc650dSSadaf Ebrahimi 		ins3 = SELECT_OP(DSLLV, SLLV);
2734*22dc650dSSadaf Ebrahimi 	}
2735*22dc650dSSadaf Ebrahimi 
2736*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ins2 | S(src3) | T(src1_reg) | D(dst_reg), DR(dst_reg)));
2737*22dc650dSSadaf Ebrahimi 
2738*22dc650dSSadaf Ebrahimi 	if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {
2739*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ins1 | T(src2_reg) | D(TMP_REG1) | (1 << 6), DR(TMP_REG1)));
2740*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, XORI | S(src3) | T(TMP_REG2) | ((sljit_ins)bit_length - 1), DR(TMP_REG2)));
2741*22dc650dSSadaf Ebrahimi 		src2_reg = TMP_REG1;
2742*22dc650dSSadaf Ebrahimi 	} else
2743*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src3) | D(TMP_REG2), DR(TMP_REG2)));
2744*22dc650dSSadaf Ebrahimi 
2745*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ins3 | S(TMP_REG2) | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1)));
2746*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));
2747*22dc650dSSadaf Ebrahimi }
2748*22dc650dSSadaf Ebrahimi 
2749*22dc650dSSadaf Ebrahimi #undef SELECT_OP3
2750*22dc650dSSadaf Ebrahimi 
sljit_emit_op_src(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src,sljit_sw srcw)2751*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
2752*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2753*22dc650dSSadaf Ebrahimi {
2754*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2755*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
2756*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src, srcw);
2757*22dc650dSSadaf Ebrahimi 
2758*22dc650dSSadaf Ebrahimi 	switch (op) {
2759*22dc650dSSadaf Ebrahimi 	case SLJIT_FAST_RETURN:
2760*22dc650dSSadaf Ebrahimi 		if (FAST_IS_REG(src))
2761*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
2762*22dc650dSSadaf Ebrahimi 		else
2763*22dc650dSSadaf Ebrahimi 			FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
2764*22dc650dSSadaf Ebrahimi 
2765*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
2766*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, NOP, UNMOVABLE_INS);
2767*22dc650dSSadaf Ebrahimi 	case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
2768*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2769*22dc650dSSadaf Ebrahimi 	case SLJIT_PREFETCH_L1:
2770*22dc650dSSadaf Ebrahimi 	case SLJIT_PREFETCH_L2:
2771*22dc650dSSadaf Ebrahimi 	case SLJIT_PREFETCH_L3:
2772*22dc650dSSadaf Ebrahimi 	case SLJIT_PREFETCH_ONCE:
2773*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
2774*22dc650dSSadaf Ebrahimi 		return emit_prefetch(compiler, src, srcw);
2775*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 1 */
2776*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2777*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 1 */
2778*22dc650dSSadaf Ebrahimi 	}
2779*22dc650dSSadaf Ebrahimi 
2780*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2781*22dc650dSSadaf Ebrahimi }
2782*22dc650dSSadaf Ebrahimi 
sljit_emit_op_dst(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw)2783*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
2784*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw)
2785*22dc650dSSadaf Ebrahimi {
2786*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_ar = RETURN_ADDR_REG;
2787*22dc650dSSadaf Ebrahimi 
2788*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2789*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
2790*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
2791*22dc650dSSadaf Ebrahimi 
2792*22dc650dSSadaf Ebrahimi 	switch (op) {
2793*22dc650dSSadaf Ebrahimi 	case SLJIT_FAST_ENTER:
2794*22dc650dSSadaf Ebrahimi 		if (FAST_IS_REG(dst))
2795*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);
2796*22dc650dSSadaf Ebrahimi 		break;
2797*22dc650dSSadaf Ebrahimi 	case SLJIT_GET_RETURN_ADDRESS:
2798*22dc650dSSadaf Ebrahimi 		dst_ar = DR(FAST_IS_REG(dst) ? dst : TMP_REG2);
2799*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_ar, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));
2800*22dc650dSSadaf Ebrahimi 		break;
2801*22dc650dSSadaf Ebrahimi 	}
2802*22dc650dSSadaf Ebrahimi 
2803*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM) {
2804*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw));
2805*22dc650dSSadaf Ebrahimi 
2806*22dc650dSSadaf Ebrahimi 		if (op == SLJIT_FAST_ENTER)
2807*22dc650dSSadaf Ebrahimi 			compiler->delay_slot = UNMOVABLE_INS;
2808*22dc650dSSadaf Ebrahimi 	}
2809*22dc650dSSadaf Ebrahimi 
2810*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2811*22dc650dSSadaf Ebrahimi }
2812*22dc650dSSadaf Ebrahimi 
sljit_get_register_index(sljit_s32 type,sljit_s32 reg)2813*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
2814*22dc650dSSadaf Ebrahimi {
2815*22dc650dSSadaf Ebrahimi 	CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
2816*22dc650dSSadaf Ebrahimi 
2817*22dc650dSSadaf Ebrahimi 	if (type == SLJIT_GP_REGISTER)
2818*22dc650dSSadaf Ebrahimi 		return reg_map[reg];
2819*22dc650dSSadaf Ebrahimi 
2820*22dc650dSSadaf Ebrahimi 	if (type != SLJIT_FLOAT_REGISTER)
2821*22dc650dSSadaf Ebrahimi 		return -1;
2822*22dc650dSSadaf Ebrahimi 
2823*22dc650dSSadaf Ebrahimi 	return FR(reg);
2824*22dc650dSSadaf Ebrahimi }
2825*22dc650dSSadaf Ebrahimi 
sljit_emit_op_custom(struct sljit_compiler * compiler,void * instruction,sljit_u32 size)2826*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
2827*22dc650dSSadaf Ebrahimi 	void *instruction, sljit_u32 size)
2828*22dc650dSSadaf Ebrahimi {
2829*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(size);
2830*22dc650dSSadaf Ebrahimi 
2831*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2832*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
2833*22dc650dSSadaf Ebrahimi 
2834*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);
2835*22dc650dSSadaf Ebrahimi }
2836*22dc650dSSadaf Ebrahimi 
2837*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
2838*22dc650dSSadaf Ebrahimi /*  Floating point operators                                             */
2839*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
2840*22dc650dSSadaf Ebrahimi 
2841*22dc650dSSadaf Ebrahimi #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
2842*22dc650dSSadaf Ebrahimi #define FMT(op) (FMT_S | (~(sljit_ins)op & SLJIT_32) << (21 - (5 + 3)))
2843*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2844*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
2845*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2846*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2847*22dc650dSSadaf Ebrahimi {
2848*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2849*22dc650dSSadaf Ebrahimi 	sljit_u32 flags = 0;
2850*22dc650dSSadaf Ebrahimi #else
2851*22dc650dSSadaf Ebrahimi 	sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;
2852*22dc650dSSadaf Ebrahimi #endif
2853*22dc650dSSadaf Ebrahimi 
2854*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
2855*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
2856*22dc650dSSadaf Ebrahimi 		src = TMP_FREG1;
2857*22dc650dSSadaf Ebrahimi 	}
2858*22dc650dSSadaf Ebrahimi 
2859*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
2860*22dc650dSSadaf Ebrahimi 
2861*22dc650dSSadaf Ebrahimi 	if (FAST_IS_REG(dst)) {
2862*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS));
2863*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)
2864*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2865*22dc650dSSadaf Ebrahimi #endif /* MIPS III */
2866*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2867*22dc650dSSadaf Ebrahimi 	}
2868*22dc650dSSadaf Ebrahimi 
2869*22dc650dSSadaf Ebrahimi 	return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);
2870*22dc650dSSadaf Ebrahimi }
2871*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2872*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
2873*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2874*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2875*22dc650dSSadaf Ebrahimi {
2876*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2877*22dc650dSSadaf Ebrahimi 	sljit_u32 flags = 0;
2878*22dc650dSSadaf Ebrahimi #else
2879*22dc650dSSadaf Ebrahimi 	sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21;
2880*22dc650dSSadaf Ebrahimi #endif
2881*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2882*22dc650dSSadaf Ebrahimi 
2883*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM)
2884*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, (flags ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
2885*22dc650dSSadaf Ebrahimi 	else {
2886*22dc650dSSadaf Ebrahimi 		if (src == SLJIT_IMM) {
2887*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2888*22dc650dSSadaf Ebrahimi 			if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
2889*22dc650dSSadaf Ebrahimi 				srcw = (sljit_s32)srcw;
2890*22dc650dSSadaf Ebrahimi #endif
2891*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
2892*22dc650dSSadaf Ebrahimi 			src = TMP_REG1;
2893*22dc650dSSadaf Ebrahimi 		}
2894*22dc650dSSadaf Ebrahimi 
2895*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
2896*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)
2897*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2898*22dc650dSSadaf Ebrahimi #endif /* MIPS III */
2899*22dc650dSSadaf Ebrahimi 	}
2900*22dc650dSSadaf Ebrahimi 
2901*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
2902*22dc650dSSadaf Ebrahimi 
2903*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
2904*22dc650dSSadaf Ebrahimi 		return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
2905*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2906*22dc650dSSadaf Ebrahimi }
2907*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2908*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
2909*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2910*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2911*22dc650dSSadaf Ebrahimi {
2912*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2913*22dc650dSSadaf Ebrahimi 	sljit_u32 flags = 0;
2914*22dc650dSSadaf Ebrahimi #else
2915*22dc650dSSadaf Ebrahimi 	sljit_u32 flags = 1 << 21;
2916*22dc650dSSadaf Ebrahimi #endif
2917*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2918*22dc650dSSadaf Ebrahimi 
2919*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
2920*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW ? WORD_DATA : INT_DATA) | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw));
2921*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
2922*22dc650dSSadaf Ebrahimi 	} else if (src == SLJIT_IMM) {
2923*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2924*22dc650dSSadaf Ebrahimi 		if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32)
2925*22dc650dSSadaf Ebrahimi 			srcw = (sljit_u32)srcw;
2926*22dc650dSSadaf Ebrahimi #endif
2927*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
2928*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
2929*22dc650dSSadaf Ebrahimi 	}
2930*22dc650dSSadaf Ebrahimi 
2931*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2932*22dc650dSSadaf Ebrahimi 	if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {
2933*22dc650dSSadaf Ebrahimi 		if (src != TMP_REG1) {
2934*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));
2935*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, DSRL32 | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));
2936*22dc650dSSadaf Ebrahimi 		}
2937*22dc650dSSadaf Ebrahimi 
2938*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
2939*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV)
2940*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2941*22dc650dSSadaf Ebrahimi #endif /* MIPS III */
2942*22dc650dSSadaf Ebrahimi 
2943*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
2944*22dc650dSSadaf Ebrahimi 
2945*22dc650dSSadaf Ebrahimi 		if (dst & SLJIT_MEM)
2946*22dc650dSSadaf Ebrahimi 			return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
2947*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2948*22dc650dSSadaf Ebrahimi 	}
2949*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_64 */
2950*22dc650dSSadaf Ebrahimi 	if (!(op & SLJIT_32)) {
2951*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2)));
2952*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SRL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2)));
2953*22dc650dSSadaf Ebrahimi 
2954*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG2) | FS(TMP_FREG1), MOVABLE_INS));
2955*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
2956*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2957*22dc650dSSadaf Ebrahimi #endif /* MIPS III */
2958*22dc650dSSadaf Ebrahimi 
2959*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | 1 | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
2960*22dc650dSSadaf Ebrahimi 
2961*22dc650dSSadaf Ebrahimi #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)
2962*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, BGEZ | S(src) | 5, UNMOVABLE_INS));
2963*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV >= 1 */
2964*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, BGEZ | S(src) | 4, UNMOVABLE_INS));
2965*22dc650dSSadaf Ebrahimi #endif  /* SLJIT_MIPS_REV < 1 */
2966*22dc650dSSadaf Ebrahimi 
2967*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, LUI | T(TMP_REG2) | IMM(0x41e0), UNMOVABLE_INS));
2968*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MTC1 | TA(0) | FS(TMP_FREG2), UNMOVABLE_INS));
2969*22dc650dSSadaf Ebrahimi 		switch (cpu_feature_list & CPU_FEATURE_FR) {
2970*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
2971*22dc650dSSadaf Ebrahimi 		case CPU_FEATURE_FR:
2972*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(TMP_FREG2), UNMOVABLE_INS));
2973*22dc650dSSadaf Ebrahimi 			break;
2974*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
2975*22dc650dSSadaf Ebrahimi 		default:
2976*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(TMP_FREG2) | (1 << 11), UNMOVABLE_INS));
2977*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
2978*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2979*22dc650dSSadaf Ebrahimi #endif /* MIPS III */
2980*22dc650dSSadaf Ebrahimi 			break;
2981*22dc650dSSadaf Ebrahimi 		}
2982*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(TMP_FREG2) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS));
2983*22dc650dSSadaf Ebrahimi 
2984*22dc650dSSadaf Ebrahimi 		if (dst & SLJIT_MEM)
2985*22dc650dSSadaf Ebrahimi 			return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
2986*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2987*22dc650dSSadaf Ebrahimi 	}
2988*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
2989*22dc650dSSadaf Ebrahimi 
2990*22dc650dSSadaf Ebrahimi #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)
2991*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, BLTZ | S(src) | 5, UNMOVABLE_INS));
2992*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV >= 1 */
2993*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, BLTZ | S(src) | 4, UNMOVABLE_INS));
2994*22dc650dSSadaf Ebrahimi #endif  /* SLJIT_MIPS_REV < 1 */
2995*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ANDI | S(src) | T(TMP_REG2) | IMM(1), DR(TMP_REG2)));
2996*22dc650dSSadaf Ebrahimi 
2997*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
2998*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV)
2999*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3000*22dc650dSSadaf Ebrahimi #endif /* !SLJIT_MIPS_REV */
3001*22dc650dSSadaf Ebrahimi 
3002*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
3003*22dc650dSSadaf Ebrahimi 
3004*22dc650dSSadaf Ebrahimi #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)
3005*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, BEQ | 6, UNMOVABLE_INS));
3006*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV >= 1 */
3007*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, BEQ | 5, UNMOVABLE_INS));
3008*22dc650dSSadaf Ebrahimi #endif  /* SLJIT_MIPS_REV < 1 */
3009*22dc650dSSadaf Ebrahimi 
3010*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
3011*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, DSRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
3012*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_64 */
3013*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
3014*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
3015*22dc650dSSadaf Ebrahimi 
3016*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | T(TMP_REG2) | D(TMP_REG1), DR(TMP_REG1)));
3017*22dc650dSSadaf Ebrahimi 
3018*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
3019*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV)
3020*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3021*22dc650dSSadaf Ebrahimi #endif /* !SLJIT_MIPS_REV */
3022*22dc650dSSadaf Ebrahimi 
3023*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
3024*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(dst_r) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS));
3025*22dc650dSSadaf Ebrahimi 
3026*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
3027*22dc650dSSadaf Ebrahimi 		return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
3028*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
3029*22dc650dSSadaf Ebrahimi }
3030*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1_cmp(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)3031*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
3032*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
3033*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
3034*22dc650dSSadaf Ebrahimi {
3035*22dc650dSSadaf Ebrahimi 	sljit_ins inst;
3036*22dc650dSSadaf Ebrahimi 
3037*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
3038*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
3039*22dc650dSSadaf Ebrahimi 		src1 = TMP_FREG1;
3040*22dc650dSSadaf Ebrahimi 	}
3041*22dc650dSSadaf Ebrahimi 
3042*22dc650dSSadaf Ebrahimi 	if (src2 & SLJIT_MEM) {
3043*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));
3044*22dc650dSSadaf Ebrahimi 		src2 = TMP_FREG2;
3045*22dc650dSSadaf Ebrahimi 	}
3046*22dc650dSSadaf Ebrahimi 
3047*22dc650dSSadaf Ebrahimi 	switch (GET_FLAG_TYPE(op)) {
3048*22dc650dSSadaf Ebrahimi 	case SLJIT_F_EQUAL:
3049*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_EQUAL:
3050*22dc650dSSadaf Ebrahimi 		inst = C_EQ_S;
3051*22dc650dSSadaf Ebrahimi 		break;
3052*22dc650dSSadaf Ebrahimi 	case SLJIT_F_NOT_EQUAL:
3053*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_EQUAL:
3054*22dc650dSSadaf Ebrahimi 		inst = C_UEQ_S;
3055*22dc650dSSadaf Ebrahimi 		break;
3056*22dc650dSSadaf Ebrahimi 	case SLJIT_F_LESS:
3057*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_LESS:
3058*22dc650dSSadaf Ebrahimi 		inst = C_OLT_S;
3059*22dc650dSSadaf Ebrahimi 		break;
3060*22dc650dSSadaf Ebrahimi 	case SLJIT_F_GREATER_EQUAL:
3061*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_LESS:
3062*22dc650dSSadaf Ebrahimi 		inst = C_ULT_S;
3063*22dc650dSSadaf Ebrahimi 		break;
3064*22dc650dSSadaf Ebrahimi 	case SLJIT_F_GREATER:
3065*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_GREATER:
3066*22dc650dSSadaf Ebrahimi 		inst = C_ULE_S;
3067*22dc650dSSadaf Ebrahimi 		break;
3068*22dc650dSSadaf Ebrahimi 	case SLJIT_F_LESS_EQUAL:
3069*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_GREATER:
3070*22dc650dSSadaf Ebrahimi 		inst = C_OLE_S;
3071*22dc650dSSadaf Ebrahimi 		break;
3072*22dc650dSSadaf Ebrahimi 	default:
3073*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED);
3074*22dc650dSSadaf Ebrahimi 		inst = C_UN_S;
3075*22dc650dSSadaf Ebrahimi 		break;
3076*22dc650dSSadaf Ebrahimi 	}
3077*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1) | C_FD, UNMOVABLE_INS);
3078*22dc650dSSadaf Ebrahimi }
3079*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)3080*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
3081*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
3082*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
3083*22dc650dSSadaf Ebrahimi {
3084*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r;
3085*22dc650dSSadaf Ebrahimi 
3086*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3087*22dc650dSSadaf Ebrahimi 	compiler->cache_arg = 0;
3088*22dc650dSSadaf Ebrahimi 	compiler->cache_argw = 0;
3089*22dc650dSSadaf Ebrahimi 
3090*22dc650dSSadaf Ebrahimi 	SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
3091*22dc650dSSadaf Ebrahimi 	SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
3092*22dc650dSSadaf Ebrahimi 
3093*22dc650dSSadaf Ebrahimi 	if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
3094*22dc650dSSadaf Ebrahimi 		op ^= SLJIT_32;
3095*22dc650dSSadaf Ebrahimi 
3096*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
3097*22dc650dSSadaf Ebrahimi 
3098*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
3099*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));
3100*22dc650dSSadaf Ebrahimi 		src = dst_r;
3101*22dc650dSSadaf Ebrahimi 	}
3102*22dc650dSSadaf Ebrahimi 
3103*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
3104*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_F64:
3105*22dc650dSSadaf Ebrahimi 		if (src != dst_r) {
3106*22dc650dSSadaf Ebrahimi 			if (!(dst & SLJIT_MEM))
3107*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, MOV_fmt(FMT(op)) | FS(src) | FD(dst_r), MOVABLE_INS));
3108*22dc650dSSadaf Ebrahimi 			else
3109*22dc650dSSadaf Ebrahimi 				dst_r = src;
3110*22dc650dSSadaf Ebrahimi 		}
3111*22dc650dSSadaf Ebrahimi 		break;
3112*22dc650dSSadaf Ebrahimi 	case SLJIT_NEG_F64:
3113*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
3114*22dc650dSSadaf Ebrahimi 		break;
3115*22dc650dSSadaf Ebrahimi 	case SLJIT_ABS_F64:
3116*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
3117*22dc650dSSadaf Ebrahimi 		break;
3118*22dc650dSSadaf Ebrahimi 	case SLJIT_CONV_F64_FROM_F32:
3119*22dc650dSSadaf Ebrahimi 		/* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */
3120*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, CVT_S_S | (sljit_ins)((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));
3121*22dc650dSSadaf Ebrahimi 		op ^= SLJIT_32;
3122*22dc650dSSadaf Ebrahimi 		break;
3123*22dc650dSSadaf Ebrahimi 	}
3124*22dc650dSSadaf Ebrahimi 
3125*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
3126*22dc650dSSadaf Ebrahimi 		return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);
3127*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
3128*22dc650dSSadaf Ebrahimi }
3129*22dc650dSSadaf Ebrahimi 
sljit_emit_fop2(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)3130*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
3131*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
3132*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
3133*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
3134*22dc650dSSadaf Ebrahimi {
3135*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r, flags = 0;
3136*22dc650dSSadaf Ebrahimi 
3137*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3138*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
3139*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
3140*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
3141*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src2, src2w);
3142*22dc650dSSadaf Ebrahimi 
3143*22dc650dSSadaf Ebrahimi 	compiler->cache_arg = 0;
3144*22dc650dSSadaf Ebrahimi 	compiler->cache_argw = 0;
3145*22dc650dSSadaf Ebrahimi 
3146*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
3147*22dc650dSSadaf Ebrahimi 
3148*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
3149*22dc650dSSadaf Ebrahimi 		if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {
3150*22dc650dSSadaf Ebrahimi 			FAIL_IF(compiler->error);
3151*22dc650dSSadaf Ebrahimi 			src1 = TMP_FREG1;
3152*22dc650dSSadaf Ebrahimi 		} else
3153*22dc650dSSadaf Ebrahimi 			flags |= SLOW_SRC1;
3154*22dc650dSSadaf Ebrahimi 	}
3155*22dc650dSSadaf Ebrahimi 
3156*22dc650dSSadaf Ebrahimi 	if (src2 & SLJIT_MEM) {
3157*22dc650dSSadaf Ebrahimi 		if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {
3158*22dc650dSSadaf Ebrahimi 			FAIL_IF(compiler->error);
3159*22dc650dSSadaf Ebrahimi 			src2 = TMP_FREG2;
3160*22dc650dSSadaf Ebrahimi 		} else
3161*22dc650dSSadaf Ebrahimi 			flags |= SLOW_SRC2;
3162*22dc650dSSadaf Ebrahimi 	}
3163*22dc650dSSadaf Ebrahimi 
3164*22dc650dSSadaf Ebrahimi 	if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
3165*22dc650dSSadaf Ebrahimi 		if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
3166*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));
3167*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
3168*22dc650dSSadaf Ebrahimi 		} else {
3169*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
3170*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
3171*22dc650dSSadaf Ebrahimi 		}
3172*22dc650dSSadaf Ebrahimi 	}
3173*22dc650dSSadaf Ebrahimi 	else if (flags & SLOW_SRC1)
3174*22dc650dSSadaf Ebrahimi 		FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
3175*22dc650dSSadaf Ebrahimi 	else if (flags & SLOW_SRC2)
3176*22dc650dSSadaf Ebrahimi 		FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
3177*22dc650dSSadaf Ebrahimi 
3178*22dc650dSSadaf Ebrahimi 	if (flags & SLOW_SRC1)
3179*22dc650dSSadaf Ebrahimi 		src1 = TMP_FREG1;
3180*22dc650dSSadaf Ebrahimi 	if (flags & SLOW_SRC2)
3181*22dc650dSSadaf Ebrahimi 		src2 = TMP_FREG2;
3182*22dc650dSSadaf Ebrahimi 
3183*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
3184*22dc650dSSadaf Ebrahimi 	case SLJIT_ADD_F64:
3185*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
3186*22dc650dSSadaf Ebrahimi 		break;
3187*22dc650dSSadaf Ebrahimi 	case SLJIT_SUB_F64:
3188*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
3189*22dc650dSSadaf Ebrahimi 		break;
3190*22dc650dSSadaf Ebrahimi 	case SLJIT_MUL_F64:
3191*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
3192*22dc650dSSadaf Ebrahimi 		break;
3193*22dc650dSSadaf Ebrahimi 	case SLJIT_DIV_F64:
3194*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
3195*22dc650dSSadaf Ebrahimi 		break;
3196*22dc650dSSadaf Ebrahimi 	case SLJIT_COPYSIGN_F64:
3197*22dc650dSSadaf Ebrahimi 		return emit_copysign(compiler, op, src1, src2, dst_r);
3198*22dc650dSSadaf Ebrahimi 	}
3199*22dc650dSSadaf Ebrahimi 
3200*22dc650dSSadaf Ebrahimi 	if (dst_r == TMP_FREG2)
3201*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));
3202*22dc650dSSadaf Ebrahimi 
3203*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
3204*22dc650dSSadaf Ebrahimi }
3205*22dc650dSSadaf Ebrahimi 
sljit_emit_fset32(struct sljit_compiler * compiler,sljit_s32 freg,sljit_f32 value)3206*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
3207*22dc650dSSadaf Ebrahimi 	sljit_s32 freg, sljit_f32 value)
3208*22dc650dSSadaf Ebrahimi {
3209*22dc650dSSadaf Ebrahimi 	union {
3210*22dc650dSSadaf Ebrahimi 		sljit_s32 imm;
3211*22dc650dSSadaf Ebrahimi 		sljit_f32 value;
3212*22dc650dSSadaf Ebrahimi 	} u;
3213*22dc650dSSadaf Ebrahimi 
3214*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3215*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fset32(compiler, freg, value));
3216*22dc650dSSadaf Ebrahimi 
3217*22dc650dSSadaf Ebrahimi 	u.value = value;
3218*22dc650dSSadaf Ebrahimi 
3219*22dc650dSSadaf Ebrahimi 	if (u.imm == 0)
3220*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, MTC1 | TA(0) | FS(freg), MOVABLE_INS);
3221*22dc650dSSadaf Ebrahimi 
3222*22dc650dSSadaf Ebrahimi 	FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.imm));
3223*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, MTC1 | T(TMP_REG1) | FS(freg), MOVABLE_INS);
3224*22dc650dSSadaf Ebrahimi }
3225*22dc650dSSadaf Ebrahimi 
3226*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
3227*22dc650dSSadaf Ebrahimi /*  Conditional instructions                                             */
3228*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
3229*22dc650dSSadaf Ebrahimi 
sljit_emit_label(struct sljit_compiler * compiler)3230*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
3231*22dc650dSSadaf Ebrahimi {
3232*22dc650dSSadaf Ebrahimi 	struct sljit_label *label;
3233*22dc650dSSadaf Ebrahimi 
3234*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
3235*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_label(compiler));
3236*22dc650dSSadaf Ebrahimi 
3237*22dc650dSSadaf Ebrahimi 	if (compiler->last_label && compiler->last_label->size == compiler->size)
3238*22dc650dSSadaf Ebrahimi 		return compiler->last_label;
3239*22dc650dSSadaf Ebrahimi 
3240*22dc650dSSadaf Ebrahimi 	label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
3241*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!label);
3242*22dc650dSSadaf Ebrahimi 	set_label(label, compiler);
3243*22dc650dSSadaf Ebrahimi 	compiler->delay_slot = UNMOVABLE_INS;
3244*22dc650dSSadaf Ebrahimi 	return label;
3245*22dc650dSSadaf Ebrahimi }
3246*22dc650dSSadaf Ebrahimi 
3247*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3248*22dc650dSSadaf Ebrahimi #define BRANCH_LENGTH	4
3249*22dc650dSSadaf Ebrahimi #else
3250*22dc650dSSadaf Ebrahimi #define BRANCH_LENGTH	8
3251*22dc650dSSadaf Ebrahimi #endif
3252*22dc650dSSadaf Ebrahimi 
3253*22dc650dSSadaf Ebrahimi #define BR_Z(src) \
3254*22dc650dSSadaf Ebrahimi 	inst = BEQ | SA(src) | TA(0) | BRANCH_LENGTH; \
3255*22dc650dSSadaf Ebrahimi 	flags = IS_BIT26_COND; \
3256*22dc650dSSadaf Ebrahimi 	delay_check = src;
3257*22dc650dSSadaf Ebrahimi 
3258*22dc650dSSadaf Ebrahimi #define BR_NZ(src) \
3259*22dc650dSSadaf Ebrahimi 	inst = BNE | SA(src) | TA(0) | BRANCH_LENGTH; \
3260*22dc650dSSadaf Ebrahimi 	flags = IS_BIT26_COND; \
3261*22dc650dSSadaf Ebrahimi 	delay_check = src;
3262*22dc650dSSadaf Ebrahimi 
3263*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
3264*22dc650dSSadaf Ebrahimi 
3265*22dc650dSSadaf Ebrahimi #define BR_T() \
3266*22dc650dSSadaf Ebrahimi 	inst = BC1NEZ; \
3267*22dc650dSSadaf Ebrahimi 	flags = IS_BIT23_COND; \
3268*22dc650dSSadaf Ebrahimi 	delay_check = FCSR_FCC;
3269*22dc650dSSadaf Ebrahimi #define BR_F() \
3270*22dc650dSSadaf Ebrahimi 	inst = BC1EQZ; \
3271*22dc650dSSadaf Ebrahimi 	flags = IS_BIT23_COND; \
3272*22dc650dSSadaf Ebrahimi 	delay_check = FCSR_FCC;
3273*22dc650dSSadaf Ebrahimi 
3274*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
3275*22dc650dSSadaf Ebrahimi 
3276*22dc650dSSadaf Ebrahimi #define BR_T() \
3277*22dc650dSSadaf Ebrahimi 	inst = BC1T | BRANCH_LENGTH; \
3278*22dc650dSSadaf Ebrahimi 	flags = IS_BIT16_COND; \
3279*22dc650dSSadaf Ebrahimi 	delay_check = FCSR_FCC;
3280*22dc650dSSadaf Ebrahimi #define BR_F() \
3281*22dc650dSSadaf Ebrahimi 	inst = BC1F | BRANCH_LENGTH; \
3282*22dc650dSSadaf Ebrahimi 	flags = IS_BIT16_COND; \
3283*22dc650dSSadaf Ebrahimi 	delay_check = FCSR_FCC;
3284*22dc650dSSadaf Ebrahimi 
3285*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
3286*22dc650dSSadaf Ebrahimi 
sljit_emit_jump(struct sljit_compiler * compiler,sljit_s32 type)3287*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
3288*22dc650dSSadaf Ebrahimi {
3289*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
3290*22dc650dSSadaf Ebrahimi 	sljit_ins inst;
3291*22dc650dSSadaf Ebrahimi 	sljit_u32 flags = 0;
3292*22dc650dSSadaf Ebrahimi 	sljit_s32 delay_check = UNMOVABLE_INS;
3293*22dc650dSSadaf Ebrahimi 
3294*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
3295*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_jump(compiler, type));
3296*22dc650dSSadaf Ebrahimi 
3297*22dc650dSSadaf Ebrahimi 	jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
3298*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!jump);
3299*22dc650dSSadaf Ebrahimi 	set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
3300*22dc650dSSadaf Ebrahimi 	type &= 0xff;
3301*22dc650dSSadaf Ebrahimi 
3302*22dc650dSSadaf Ebrahimi 	switch (type) {
3303*22dc650dSSadaf Ebrahimi 	case SLJIT_EQUAL:
3304*22dc650dSSadaf Ebrahimi 		BR_NZ(EQUAL_FLAG);
3305*22dc650dSSadaf Ebrahimi 		break;
3306*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_EQUAL:
3307*22dc650dSSadaf Ebrahimi 		BR_Z(EQUAL_FLAG);
3308*22dc650dSSadaf Ebrahimi 		break;
3309*22dc650dSSadaf Ebrahimi 	case SLJIT_LESS:
3310*22dc650dSSadaf Ebrahimi 	case SLJIT_GREATER:
3311*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_LESS:
3312*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_GREATER:
3313*22dc650dSSadaf Ebrahimi 	case SLJIT_OVERFLOW:
3314*22dc650dSSadaf Ebrahimi 	case SLJIT_CARRY:
3315*22dc650dSSadaf Ebrahimi 		BR_Z(OTHER_FLAG);
3316*22dc650dSSadaf Ebrahimi 		break;
3317*22dc650dSSadaf Ebrahimi 	case SLJIT_GREATER_EQUAL:
3318*22dc650dSSadaf Ebrahimi 	case SLJIT_LESS_EQUAL:
3319*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_GREATER_EQUAL:
3320*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_LESS_EQUAL:
3321*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_OVERFLOW:
3322*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_CARRY:
3323*22dc650dSSadaf Ebrahimi 		BR_NZ(OTHER_FLAG);
3324*22dc650dSSadaf Ebrahimi 		break;
3325*22dc650dSSadaf Ebrahimi 	case SLJIT_F_NOT_EQUAL:
3326*22dc650dSSadaf Ebrahimi 	case SLJIT_F_GREATER_EQUAL:
3327*22dc650dSSadaf Ebrahimi 	case SLJIT_F_GREATER:
3328*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_NOT_EQUAL:
3329*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_NOT_EQUAL:
3330*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_GREATER_EQUAL:
3331*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_GREATER_EQUAL:
3332*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_GREATER:
3333*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_GREATER:
3334*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED:
3335*22dc650dSSadaf Ebrahimi 		BR_T();
3336*22dc650dSSadaf Ebrahimi 		break;
3337*22dc650dSSadaf Ebrahimi 	case SLJIT_F_EQUAL:
3338*22dc650dSSadaf Ebrahimi 	case SLJIT_F_LESS:
3339*22dc650dSSadaf Ebrahimi 	case SLJIT_F_LESS_EQUAL:
3340*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_EQUAL:
3341*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_EQUAL:
3342*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_LESS:
3343*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_LESS:
3344*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_LESS_EQUAL:
3345*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_LESS_EQUAL:
3346*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED:
3347*22dc650dSSadaf Ebrahimi 		BR_F();
3348*22dc650dSSadaf Ebrahimi 		break;
3349*22dc650dSSadaf Ebrahimi 	default:
3350*22dc650dSSadaf Ebrahimi 		/* Not conditional branch. */
3351*22dc650dSSadaf Ebrahimi 		inst = 0;
3352*22dc650dSSadaf Ebrahimi 		break;
3353*22dc650dSSadaf Ebrahimi 	}
3354*22dc650dSSadaf Ebrahimi 
3355*22dc650dSSadaf Ebrahimi 	jump->flags |= flags;
3356*22dc650dSSadaf Ebrahimi 	if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))
3357*22dc650dSSadaf Ebrahimi 		jump->flags |= IS_MOVABLE;
3358*22dc650dSSadaf Ebrahimi 
3359*22dc650dSSadaf Ebrahimi 	if (inst)
3360*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));
3361*22dc650dSSadaf Ebrahimi 
3362*22dc650dSSadaf Ebrahimi 	if (type <= SLJIT_JUMP)
3363*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
3364*22dc650dSSadaf Ebrahimi 	else {
3365*22dc650dSSadaf Ebrahimi 		jump->flags |= IS_JAL;
3366*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
3367*22dc650dSSadaf Ebrahimi 	}
3368*22dc650dSSadaf Ebrahimi 
3369*22dc650dSSadaf Ebrahimi 	jump->addr = compiler->size;
3370*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3371*22dc650dSSadaf Ebrahimi 
3372*22dc650dSSadaf Ebrahimi 	/* Maximum number of instructions required for generating a constant. */
3373*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3374*22dc650dSSadaf Ebrahimi 	compiler->size += 2;
3375*22dc650dSSadaf Ebrahimi #else
3376*22dc650dSSadaf Ebrahimi 	compiler->size += 6;
3377*22dc650dSSadaf Ebrahimi #endif
3378*22dc650dSSadaf Ebrahimi 	return jump;
3379*22dc650dSSadaf Ebrahimi }
3380*22dc650dSSadaf Ebrahimi 
3381*22dc650dSSadaf Ebrahimi #define RESOLVE_IMM1() \
3382*22dc650dSSadaf Ebrahimi 	if (src1 == SLJIT_IMM) { \
3383*22dc650dSSadaf Ebrahimi 		if (src1w) { \
3384*22dc650dSSadaf Ebrahimi 			PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \
3385*22dc650dSSadaf Ebrahimi 			src1 = TMP_REG1; \
3386*22dc650dSSadaf Ebrahimi 		} \
3387*22dc650dSSadaf Ebrahimi 		else \
3388*22dc650dSSadaf Ebrahimi 			src1 = 0; \
3389*22dc650dSSadaf Ebrahimi 	}
3390*22dc650dSSadaf Ebrahimi 
3391*22dc650dSSadaf Ebrahimi #define RESOLVE_IMM2() \
3392*22dc650dSSadaf Ebrahimi 	if (src2 == SLJIT_IMM) { \
3393*22dc650dSSadaf Ebrahimi 		if (src2w) { \
3394*22dc650dSSadaf Ebrahimi 			PTR_FAIL_IF(load_immediate(compiler, DR(src2_tmp_reg), src2w)); \
3395*22dc650dSSadaf Ebrahimi 			src2 = src2_tmp_reg; \
3396*22dc650dSSadaf Ebrahimi 		} \
3397*22dc650dSSadaf Ebrahimi 		else \
3398*22dc650dSSadaf Ebrahimi 			src2 = 0; \
3399*22dc650dSSadaf Ebrahimi 	}
3400*22dc650dSSadaf Ebrahimi 
sljit_emit_cmp(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)3401*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
3402*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
3403*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
3404*22dc650dSSadaf Ebrahimi {
3405*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
3406*22dc650dSSadaf Ebrahimi 	sljit_s32 flags;
3407*22dc650dSSadaf Ebrahimi 	sljit_ins inst;
3408*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;
3409*22dc650dSSadaf Ebrahimi 
3410*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
3411*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
3412*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
3413*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src2, src2w);
3414*22dc650dSSadaf Ebrahimi 
3415*22dc650dSSadaf Ebrahimi 	compiler->cache_arg = 0;
3416*22dc650dSSadaf Ebrahimi 	compiler->cache_argw = 0;
3417*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3418*22dc650dSSadaf Ebrahimi 	flags = WORD_DATA | LOAD_DATA;
3419*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
3420*22dc650dSSadaf Ebrahimi 	flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
3421*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
3422*22dc650dSSadaf Ebrahimi 
3423*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
3424*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));
3425*22dc650dSSadaf Ebrahimi 		src1 = TMP_REG1;
3426*22dc650dSSadaf Ebrahimi 	}
3427*22dc650dSSadaf Ebrahimi 
3428*22dc650dSSadaf Ebrahimi 	if (src2 & SLJIT_MEM) {
3429*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(src2_tmp_reg), src2, src2w, 0, 0));
3430*22dc650dSSadaf Ebrahimi 		src2 = src2_tmp_reg;
3431*22dc650dSSadaf Ebrahimi 	}
3432*22dc650dSSadaf Ebrahimi 
3433*22dc650dSSadaf Ebrahimi 	jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
3434*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!jump);
3435*22dc650dSSadaf Ebrahimi 	set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
3436*22dc650dSSadaf Ebrahimi 	type &= 0xff;
3437*22dc650dSSadaf Ebrahimi 
3438*22dc650dSSadaf Ebrahimi 	if (type <= SLJIT_NOT_EQUAL) {
3439*22dc650dSSadaf Ebrahimi 		RESOLVE_IMM1();
3440*22dc650dSSadaf Ebrahimi 		RESOLVE_IMM2();
3441*22dc650dSSadaf Ebrahimi 		jump->flags |= IS_BIT26_COND;
3442*22dc650dSSadaf Ebrahimi 		if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))
3443*22dc650dSSadaf Ebrahimi 			jump->flags |= IS_MOVABLE;
3444*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | BRANCH_LENGTH, UNMOVABLE_INS));
3445*22dc650dSSadaf Ebrahimi 	} else if (type >= SLJIT_SIG_LESS && ((src1 == SLJIT_IMM && src1w == 0) || (src2 == SLJIT_IMM && src2w == 0))) {
3446*22dc650dSSadaf Ebrahimi 		inst = NOP;
3447*22dc650dSSadaf Ebrahimi 		if (src1 == SLJIT_IMM && src1w == 0) {
3448*22dc650dSSadaf Ebrahimi 			RESOLVE_IMM2();
3449*22dc650dSSadaf Ebrahimi 			switch (type) {
3450*22dc650dSSadaf Ebrahimi 			case SLJIT_SIG_LESS:
3451*22dc650dSSadaf Ebrahimi 				inst = BLEZ;
3452*22dc650dSSadaf Ebrahimi 				jump->flags |= IS_BIT26_COND;
3453*22dc650dSSadaf Ebrahimi 				break;
3454*22dc650dSSadaf Ebrahimi 			case SLJIT_SIG_GREATER_EQUAL:
3455*22dc650dSSadaf Ebrahimi 				inst = BGTZ;
3456*22dc650dSSadaf Ebrahimi 				jump->flags |= IS_BIT26_COND;
3457*22dc650dSSadaf Ebrahimi 				break;
3458*22dc650dSSadaf Ebrahimi 			case SLJIT_SIG_GREATER:
3459*22dc650dSSadaf Ebrahimi 				inst = BGEZ;
3460*22dc650dSSadaf Ebrahimi 				jump->flags |= IS_BIT16_COND;
3461*22dc650dSSadaf Ebrahimi 				break;
3462*22dc650dSSadaf Ebrahimi 			case SLJIT_SIG_LESS_EQUAL:
3463*22dc650dSSadaf Ebrahimi 				inst = BLTZ;
3464*22dc650dSSadaf Ebrahimi 				jump->flags |= IS_BIT16_COND;
3465*22dc650dSSadaf Ebrahimi 				break;
3466*22dc650dSSadaf Ebrahimi 			}
3467*22dc650dSSadaf Ebrahimi 			src1 = src2;
3468*22dc650dSSadaf Ebrahimi 		}
3469*22dc650dSSadaf Ebrahimi 		else {
3470*22dc650dSSadaf Ebrahimi 			RESOLVE_IMM1();
3471*22dc650dSSadaf Ebrahimi 			switch (type) {
3472*22dc650dSSadaf Ebrahimi 			case SLJIT_SIG_LESS:
3473*22dc650dSSadaf Ebrahimi 				inst = BGEZ;
3474*22dc650dSSadaf Ebrahimi 				jump->flags |= IS_BIT16_COND;
3475*22dc650dSSadaf Ebrahimi 				break;
3476*22dc650dSSadaf Ebrahimi 			case SLJIT_SIG_GREATER_EQUAL:
3477*22dc650dSSadaf Ebrahimi 				inst = BLTZ;
3478*22dc650dSSadaf Ebrahimi 				jump->flags |= IS_BIT16_COND;
3479*22dc650dSSadaf Ebrahimi 				break;
3480*22dc650dSSadaf Ebrahimi 			case SLJIT_SIG_GREATER:
3481*22dc650dSSadaf Ebrahimi 				inst = BLEZ;
3482*22dc650dSSadaf Ebrahimi 				jump->flags |= IS_BIT26_COND;
3483*22dc650dSSadaf Ebrahimi 				break;
3484*22dc650dSSadaf Ebrahimi 			case SLJIT_SIG_LESS_EQUAL:
3485*22dc650dSSadaf Ebrahimi 				inst = BGTZ;
3486*22dc650dSSadaf Ebrahimi 				jump->flags |= IS_BIT26_COND;
3487*22dc650dSSadaf Ebrahimi 				break;
3488*22dc650dSSadaf Ebrahimi 			}
3489*22dc650dSSadaf Ebrahimi 		}
3490*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | BRANCH_LENGTH, UNMOVABLE_INS));
3491*22dc650dSSadaf Ebrahimi 	}
3492*22dc650dSSadaf Ebrahimi 	else {
3493*22dc650dSSadaf Ebrahimi 		if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) {
3494*22dc650dSSadaf Ebrahimi 			RESOLVE_IMM1();
3495*22dc650dSSadaf Ebrahimi 			if (src2 == SLJIT_IMM && src2w <= SIMM_MAX && src2w >= SIMM_MIN)
3496*22dc650dSSadaf Ebrahimi 				PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));
3497*22dc650dSSadaf Ebrahimi 			else {
3498*22dc650dSSadaf Ebrahimi 				RESOLVE_IMM2();
3499*22dc650dSSadaf Ebrahimi 				PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));
3500*22dc650dSSadaf Ebrahimi 			}
3501*22dc650dSSadaf Ebrahimi 			type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
3502*22dc650dSSadaf Ebrahimi 		}
3503*22dc650dSSadaf Ebrahimi 		else {
3504*22dc650dSSadaf Ebrahimi 			RESOLVE_IMM2();
3505*22dc650dSSadaf Ebrahimi 			if (src1 == SLJIT_IMM && src1w <= SIMM_MAX && src1w >= SIMM_MIN)
3506*22dc650dSSadaf Ebrahimi 				PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));
3507*22dc650dSSadaf Ebrahimi 			else {
3508*22dc650dSSadaf Ebrahimi 				RESOLVE_IMM1();
3509*22dc650dSSadaf Ebrahimi 				PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));
3510*22dc650dSSadaf Ebrahimi 			}
3511*22dc650dSSadaf Ebrahimi 			type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
3512*22dc650dSSadaf Ebrahimi 		}
3513*22dc650dSSadaf Ebrahimi 
3514*22dc650dSSadaf Ebrahimi 		jump->flags |= IS_BIT26_COND;
3515*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | BRANCH_LENGTH, UNMOVABLE_INS));
3516*22dc650dSSadaf Ebrahimi 	}
3517*22dc650dSSadaf Ebrahimi 
3518*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
3519*22dc650dSSadaf Ebrahimi 	jump->addr = compiler->size;
3520*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3521*22dc650dSSadaf Ebrahimi 
3522*22dc650dSSadaf Ebrahimi 	/* Maximum number of instructions required for generating a constant. */
3523*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3524*22dc650dSSadaf Ebrahimi 	compiler->size += 2;
3525*22dc650dSSadaf Ebrahimi #else
3526*22dc650dSSadaf Ebrahimi 	compiler->size += 6;
3527*22dc650dSSadaf Ebrahimi #endif
3528*22dc650dSSadaf Ebrahimi 	return jump;
3529*22dc650dSSadaf Ebrahimi }
3530*22dc650dSSadaf Ebrahimi 
3531*22dc650dSSadaf Ebrahimi #undef RESOLVE_IMM1
3532*22dc650dSSadaf Ebrahimi #undef RESOLVE_IMM2
3533*22dc650dSSadaf Ebrahimi 
3534*22dc650dSSadaf Ebrahimi #undef BRANCH_LENGTH
3535*22dc650dSSadaf Ebrahimi #undef BR_Z
3536*22dc650dSSadaf Ebrahimi #undef BR_NZ
3537*22dc650dSSadaf Ebrahimi #undef BR_T
3538*22dc650dSSadaf Ebrahimi #undef BR_F
3539*22dc650dSSadaf Ebrahimi 
sljit_emit_ijump(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 src,sljit_sw srcw)3540*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
3541*22dc650dSSadaf Ebrahimi {
3542*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump = NULL;
3543*22dc650dSSadaf Ebrahimi 
3544*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3545*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
3546*22dc650dSSadaf Ebrahimi 
3547*22dc650dSSadaf Ebrahimi 	if (src == SLJIT_IMM) {
3548*22dc650dSSadaf Ebrahimi 		jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
3549*22dc650dSSadaf Ebrahimi 		FAIL_IF(!jump);
3550*22dc650dSSadaf Ebrahimi 		set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));
3551*22dc650dSSadaf Ebrahimi 		jump->u.target = (sljit_uw)srcw;
3552*22dc650dSSadaf Ebrahimi 
3553*22dc650dSSadaf Ebrahimi 		if (compiler->delay_slot != UNMOVABLE_INS)
3554*22dc650dSSadaf Ebrahimi 			jump->flags |= IS_MOVABLE;
3555*22dc650dSSadaf Ebrahimi 
3556*22dc650dSSadaf Ebrahimi 		src = PIC_ADDR_REG;
3557*22dc650dSSadaf Ebrahimi 	} else if (src & SLJIT_MEM) {
3558*22dc650dSSadaf Ebrahimi 		ADJUST_LOCAL_OFFSET(src, srcw);
3559*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
3560*22dc650dSSadaf Ebrahimi 		src = PIC_ADDR_REG;
3561*22dc650dSSadaf Ebrahimi 	}
3562*22dc650dSSadaf Ebrahimi 
3563*22dc650dSSadaf Ebrahimi 	if (type <= SLJIT_JUMP)
3564*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));
3565*22dc650dSSadaf Ebrahimi 	else
3566*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, JALR | S(src) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
3567*22dc650dSSadaf Ebrahimi 
3568*22dc650dSSadaf Ebrahimi 	if (jump != NULL) {
3569*22dc650dSSadaf Ebrahimi 		jump->addr = compiler->size;
3570*22dc650dSSadaf Ebrahimi 
3571*22dc650dSSadaf Ebrahimi 		/* Maximum number of instructions required for generating a constant. */
3572*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3573*22dc650dSSadaf Ebrahimi 		compiler->size += 2;
3574*22dc650dSSadaf Ebrahimi #else
3575*22dc650dSSadaf Ebrahimi 		compiler->size += 6;
3576*22dc650dSSadaf Ebrahimi #endif
3577*22dc650dSSadaf Ebrahimi 	}
3578*22dc650dSSadaf Ebrahimi 
3579*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, NOP, UNMOVABLE_INS);
3580*22dc650dSSadaf Ebrahimi }
3581*22dc650dSSadaf Ebrahimi 
sljit_emit_op_flags(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 type)3582*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
3583*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
3584*22dc650dSSadaf Ebrahimi 	sljit_s32 type)
3585*22dc650dSSadaf Ebrahimi {
3586*22dc650dSSadaf Ebrahimi 	sljit_s32 src_ar, dst_ar, invert;
3587*22dc650dSSadaf Ebrahimi 	sljit_s32 saved_op = op;
3588*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3589*22dc650dSSadaf Ebrahimi 	sljit_s32 mem_type = WORD_DATA;
3590*22dc650dSSadaf Ebrahimi #else
3591*22dc650dSSadaf Ebrahimi 	sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
3592*22dc650dSSadaf Ebrahimi #endif
3593*22dc650dSSadaf Ebrahimi 
3594*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3595*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
3596*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
3597*22dc650dSSadaf Ebrahimi 
3598*22dc650dSSadaf Ebrahimi 	op = GET_OPCODE(op);
3599*22dc650dSSadaf Ebrahimi 	dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
3600*22dc650dSSadaf Ebrahimi 
3601*22dc650dSSadaf Ebrahimi 	compiler->cache_arg = 0;
3602*22dc650dSSadaf Ebrahimi 	compiler->cache_argw = 0;
3603*22dc650dSSadaf Ebrahimi 
3604*22dc650dSSadaf Ebrahimi 	if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
3605*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));
3606*22dc650dSSadaf Ebrahimi 
3607*22dc650dSSadaf Ebrahimi 	if (type < SLJIT_F_EQUAL) {
3608*22dc650dSSadaf Ebrahimi 		src_ar = OTHER_FLAG;
3609*22dc650dSSadaf Ebrahimi 		invert = type & 0x1;
3610*22dc650dSSadaf Ebrahimi 
3611*22dc650dSSadaf Ebrahimi 		switch (type) {
3612*22dc650dSSadaf Ebrahimi 		case SLJIT_EQUAL:
3613*22dc650dSSadaf Ebrahimi 		case SLJIT_NOT_EQUAL:
3614*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
3615*22dc650dSSadaf Ebrahimi 			src_ar = dst_ar;
3616*22dc650dSSadaf Ebrahimi 			break;
3617*22dc650dSSadaf Ebrahimi 		case SLJIT_OVERFLOW:
3618*22dc650dSSadaf Ebrahimi 		case SLJIT_NOT_OVERFLOW:
3619*22dc650dSSadaf Ebrahimi 			if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {
3620*22dc650dSSadaf Ebrahimi 				src_ar = OTHER_FLAG;
3621*22dc650dSSadaf Ebrahimi 				break;
3622*22dc650dSSadaf Ebrahimi 			}
3623*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
3624*22dc650dSSadaf Ebrahimi 			src_ar = dst_ar;
3625*22dc650dSSadaf Ebrahimi 			invert ^= 0x1;
3626*22dc650dSSadaf Ebrahimi 			break;
3627*22dc650dSSadaf Ebrahimi 		}
3628*22dc650dSSadaf Ebrahimi 	} else {
3629*22dc650dSSadaf Ebrahimi 		invert = 0;
3630*22dc650dSSadaf Ebrahimi 
3631*22dc650dSSadaf Ebrahimi 		switch (type) {
3632*22dc650dSSadaf Ebrahimi 		case SLJIT_F_NOT_EQUAL:
3633*22dc650dSSadaf Ebrahimi 		case SLJIT_F_GREATER_EQUAL:
3634*22dc650dSSadaf Ebrahimi 		case SLJIT_F_GREATER:
3635*22dc650dSSadaf Ebrahimi 		case SLJIT_UNORDERED_OR_NOT_EQUAL:
3636*22dc650dSSadaf Ebrahimi 		case SLJIT_ORDERED_NOT_EQUAL:
3637*22dc650dSSadaf Ebrahimi 		case SLJIT_UNORDERED_OR_GREATER_EQUAL:
3638*22dc650dSSadaf Ebrahimi 		case SLJIT_ORDERED_GREATER_EQUAL:
3639*22dc650dSSadaf Ebrahimi 		case SLJIT_ORDERED_GREATER:
3640*22dc650dSSadaf Ebrahimi 		case SLJIT_UNORDERED_OR_GREATER:
3641*22dc650dSSadaf Ebrahimi 		case SLJIT_ORDERED:
3642*22dc650dSSadaf Ebrahimi 			invert = 1;
3643*22dc650dSSadaf Ebrahimi 			break;
3644*22dc650dSSadaf Ebrahimi 		}
3645*22dc650dSSadaf Ebrahimi 
3646*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
3647*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));
3648*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 6 */
3649*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));
3650*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
3651*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));
3652*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));
3653*22dc650dSSadaf Ebrahimi 		src_ar = dst_ar;
3654*22dc650dSSadaf Ebrahimi 	}
3655*22dc650dSSadaf Ebrahimi 
3656*22dc650dSSadaf Ebrahimi 	if (invert) {
3657*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar));
3658*22dc650dSSadaf Ebrahimi 		src_ar = dst_ar;
3659*22dc650dSSadaf Ebrahimi 	}
3660*22dc650dSSadaf Ebrahimi 
3661*22dc650dSSadaf Ebrahimi 	if (op < SLJIT_ADD) {
3662*22dc650dSSadaf Ebrahimi 		if (dst & SLJIT_MEM)
3663*22dc650dSSadaf Ebrahimi 			return emit_op_mem(compiler, mem_type, src_ar, dst, dstw);
3664*22dc650dSSadaf Ebrahimi 
3665*22dc650dSSadaf Ebrahimi 		if (src_ar != dst_ar)
3666*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar);
3667*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
3668*22dc650dSSadaf Ebrahimi 	}
3669*22dc650dSSadaf Ebrahimi 
3670*22dc650dSSadaf Ebrahimi 	/* OTHER_FLAG cannot be specified as src2 argument at the moment. */
3671*22dc650dSSadaf Ebrahimi 	if (DR(TMP_REG2) != src_ar)
3672*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
3673*22dc650dSSadaf Ebrahimi 
3674*22dc650dSSadaf Ebrahimi 	mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE;
3675*22dc650dSSadaf Ebrahimi 
3676*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
3677*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
3678*22dc650dSSadaf Ebrahimi 	return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0);
3679*22dc650dSSadaf Ebrahimi }
3680*22dc650dSSadaf Ebrahimi 
3681*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
3682*22dc650dSSadaf Ebrahimi 
get_select_cc(sljit_s32 type,sljit_s32 is_float)3683*22dc650dSSadaf Ebrahimi static sljit_ins get_select_cc(sljit_s32 type, sljit_s32 is_float)
3684*22dc650dSSadaf Ebrahimi {
3685*22dc650dSSadaf Ebrahimi 	switch (type & ~SLJIT_32) {
3686*22dc650dSSadaf Ebrahimi 	case SLJIT_EQUAL:
3687*22dc650dSSadaf Ebrahimi 		return (is_float ? MOVZ_S : MOVZ) | TA(EQUAL_FLAG);
3688*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_EQUAL:
3689*22dc650dSSadaf Ebrahimi 		return (is_float ? MOVN_S : MOVN) | TA(EQUAL_FLAG);
3690*22dc650dSSadaf Ebrahimi 	case SLJIT_LESS:
3691*22dc650dSSadaf Ebrahimi 	case SLJIT_GREATER:
3692*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_LESS:
3693*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_GREATER:
3694*22dc650dSSadaf Ebrahimi 	case SLJIT_OVERFLOW:
3695*22dc650dSSadaf Ebrahimi 	case SLJIT_CARRY:
3696*22dc650dSSadaf Ebrahimi 		return (is_float ? MOVN_S : MOVN) | TA(OTHER_FLAG);
3697*22dc650dSSadaf Ebrahimi 	case SLJIT_GREATER_EQUAL:
3698*22dc650dSSadaf Ebrahimi 	case SLJIT_LESS_EQUAL:
3699*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_GREATER_EQUAL:
3700*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_LESS_EQUAL:
3701*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_OVERFLOW:
3702*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_CARRY:
3703*22dc650dSSadaf Ebrahimi 		return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG);
3704*22dc650dSSadaf Ebrahimi 	case SLJIT_F_EQUAL:
3705*22dc650dSSadaf Ebrahimi 	case SLJIT_F_LESS:
3706*22dc650dSSadaf Ebrahimi 	case SLJIT_F_LESS_EQUAL:
3707*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_EQUAL:
3708*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_EQUAL:
3709*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_LESS:
3710*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_LESS:
3711*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_LESS_EQUAL:
3712*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_LESS_EQUAL:
3713*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED:
3714*22dc650dSSadaf Ebrahimi 		return is_float ? MOVT_S : MOVT;
3715*22dc650dSSadaf Ebrahimi 	case SLJIT_F_NOT_EQUAL:
3716*22dc650dSSadaf Ebrahimi 	case SLJIT_F_GREATER_EQUAL:
3717*22dc650dSSadaf Ebrahimi 	case SLJIT_F_GREATER:
3718*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_NOT_EQUAL:
3719*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_NOT_EQUAL:
3720*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_GREATER_EQUAL:
3721*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_GREATER_EQUAL:
3722*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_GREATER:
3723*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_GREATER:
3724*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED:
3725*22dc650dSSadaf Ebrahimi 		return is_float ? MOVF_S : MOVF;
3726*22dc650dSSadaf Ebrahimi 	default:
3727*22dc650dSSadaf Ebrahimi 		SLJIT_UNREACHABLE();
3728*22dc650dSSadaf Ebrahimi 		return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG);
3729*22dc650dSSadaf Ebrahimi 	}
3730*22dc650dSSadaf Ebrahimi }
3731*22dc650dSSadaf Ebrahimi 
3732*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 1 */
3733*22dc650dSSadaf Ebrahimi 
sljit_emit_select(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 dst_reg,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2_reg)3734*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
3735*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg,
3736*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
3737*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_reg)
3738*22dc650dSSadaf Ebrahimi {
3739*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
3740*22dc650dSSadaf Ebrahimi 	sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
3741*22dc650dSSadaf Ebrahimi 	sljit_ins mov_ins = (type & SLJIT_32) ? ADDU : DADDU;
3742*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_64 */
3743*22dc650dSSadaf Ebrahimi 	sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
3744*22dc650dSSadaf Ebrahimi 	sljit_ins mov_ins = ADDU;
3745*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
3746*22dc650dSSadaf Ebrahimi 
3747*22dc650dSSadaf Ebrahimi #if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
3748*22dc650dSSadaf Ebrahimi 	struct sljit_label *label;
3749*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
3750*22dc650dSSadaf Ebrahimi #endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */
3751*22dc650dSSadaf Ebrahimi 
3752*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3753*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
3754*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
3755*22dc650dSSadaf Ebrahimi 
3756*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
3757*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
3758*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG1), src1, src1w));
3759*22dc650dSSadaf Ebrahimi 		src1 = TMP_REG1;
3760*22dc650dSSadaf Ebrahimi 	} else if (src1 == SLJIT_IMM) {
3761*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
3762*22dc650dSSadaf Ebrahimi 		if (type & SLJIT_32)
3763*22dc650dSSadaf Ebrahimi 			src1w = (sljit_s32)src1w;
3764*22dc650dSSadaf Ebrahimi #endif
3765*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
3766*22dc650dSSadaf Ebrahimi 		src1 = TMP_REG1;
3767*22dc650dSSadaf Ebrahimi 	}
3768*22dc650dSSadaf Ebrahimi 
3769*22dc650dSSadaf Ebrahimi 	if (dst_reg != src2_reg) {
3770*22dc650dSSadaf Ebrahimi 		if (dst_reg == src1) {
3771*22dc650dSSadaf Ebrahimi 			src1 = src2_reg;
3772*22dc650dSSadaf Ebrahimi 			type ^= 0x1;
3773*22dc650dSSadaf Ebrahimi 		} else
3774*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg)));
3775*22dc650dSSadaf Ebrahimi 	}
3776*22dc650dSSadaf Ebrahimi 
3777*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, get_select_cc(type, 0) | S(src1) | D(dst_reg), DR(dst_reg));
3778*22dc650dSSadaf Ebrahimi 
3779*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */
3780*22dc650dSSadaf Ebrahimi 	if (dst_reg != src2_reg) {
3781*22dc650dSSadaf Ebrahimi 		if (dst_reg == src1) {
3782*22dc650dSSadaf Ebrahimi 			src1 = src2_reg;
3783*22dc650dSSadaf Ebrahimi 			src1w = 0;
3784*22dc650dSSadaf Ebrahimi 			type ^= 0x1;
3785*22dc650dSSadaf Ebrahimi 		} else {
3786*22dc650dSSadaf Ebrahimi 			if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
3787*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADDU_W | S(dst_reg) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
3788*22dc650dSSadaf Ebrahimi 
3789*22dc650dSSadaf Ebrahimi 				if ((src1 & REG_MASK) == dst_reg)
3790*22dc650dSSadaf Ebrahimi 					src1 = (src1 & ~REG_MASK) | TMP_REG1;
3791*22dc650dSSadaf Ebrahimi 
3792*22dc650dSSadaf Ebrahimi 				if (OFFS_REG(src1) == dst_reg)
3793*22dc650dSSadaf Ebrahimi 					src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);
3794*22dc650dSSadaf Ebrahimi 			}
3795*22dc650dSSadaf Ebrahimi 
3796*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg)));
3797*22dc650dSSadaf Ebrahimi 		}
3798*22dc650dSSadaf Ebrahimi 	}
3799*22dc650dSSadaf Ebrahimi 
3800*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
3801*22dc650dSSadaf Ebrahimi 	jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1);
3802*22dc650dSSadaf Ebrahimi 	FAIL_IF(!jump);
3803*22dc650dSSadaf Ebrahimi 
3804*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
3805*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, inp_flags, DR(dst_reg), src1, src1w));
3806*22dc650dSSadaf Ebrahimi 	} else if (src1 == SLJIT_IMM) {
3807*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
3808*22dc650dSSadaf Ebrahimi 		if (type & SLJIT_32)
3809*22dc650dSSadaf Ebrahimi 			src1w = (sljit_s32)src1w;
3810*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_64 */
3811*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, DR(dst_reg), src1w));
3812*22dc650dSSadaf Ebrahimi 	} else
3813*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, mov_ins | S(src1) | TA(0) | D(dst_reg), DR(dst_reg)));
3814*22dc650dSSadaf Ebrahimi 
3815*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
3816*22dc650dSSadaf Ebrahimi 	label = sljit_emit_label(compiler);
3817*22dc650dSSadaf Ebrahimi 	FAIL_IF(!label);
3818*22dc650dSSadaf Ebrahimi 
3819*22dc650dSSadaf Ebrahimi 	sljit_set_label(jump, label);
3820*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
3821*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 1 */
3822*22dc650dSSadaf Ebrahimi }
3823*22dc650dSSadaf Ebrahimi 
sljit_emit_fselect(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 dst_freg,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2_freg)3824*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
3825*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_freg,
3826*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
3827*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_freg)
3828*22dc650dSSadaf Ebrahimi {
3829*22dc650dSSadaf Ebrahimi #if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
3830*22dc650dSSadaf Ebrahimi 	struct sljit_label *label;
3831*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
3832*22dc650dSSadaf Ebrahimi #endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */
3833*22dc650dSSadaf Ebrahimi 
3834*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3835*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
3836*22dc650dSSadaf Ebrahimi 
3837*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
3838*22dc650dSSadaf Ebrahimi 
3839*22dc650dSSadaf Ebrahimi 	if (dst_freg != src2_freg) {
3840*22dc650dSSadaf Ebrahimi 		if (dst_freg == src1) {
3841*22dc650dSSadaf Ebrahimi 			src1 = src2_freg;
3842*22dc650dSSadaf Ebrahimi 			src1w = 0;
3843*22dc650dSSadaf Ebrahimi 			type ^= 0x1;
3844*22dc650dSSadaf Ebrahimi 		} else
3845*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src2_freg) | FD(dst_freg), MOVABLE_INS));
3846*22dc650dSSadaf Ebrahimi 	}
3847*22dc650dSSadaf Ebrahimi 
3848*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
3849*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
3850*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(TMP_FREG2), src1, src1w));
3851*22dc650dSSadaf Ebrahimi 		src1 = TMP_FREG2;
3852*22dc650dSSadaf Ebrahimi 	}
3853*22dc650dSSadaf Ebrahimi 
3854*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, get_select_cc(type, 1) | FMT(type) | FS(src1) | FD(dst_freg), MOVABLE_INS);
3855*22dc650dSSadaf Ebrahimi 
3856*22dc650dSSadaf Ebrahimi #else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */
3857*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
3858*22dc650dSSadaf Ebrahimi 	jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1);
3859*22dc650dSSadaf Ebrahimi 	FAIL_IF(!jump);
3860*22dc650dSSadaf Ebrahimi 
3861*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM)
3862*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(dst_freg), src1, src1w));
3863*22dc650dSSadaf Ebrahimi 	else
3864*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src1) | FD(dst_freg), MOVABLE_INS));
3865*22dc650dSSadaf Ebrahimi 
3866*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
3867*22dc650dSSadaf Ebrahimi 	label = sljit_emit_label(compiler);
3868*22dc650dSSadaf Ebrahimi 	FAIL_IF(!label);
3869*22dc650dSSadaf Ebrahimi 
3870*22dc650dSSadaf Ebrahimi 	sljit_set_label(jump, label);
3871*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
3872*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 1 */
3873*22dc650dSSadaf Ebrahimi }
3874*22dc650dSSadaf Ebrahimi 
3875*22dc650dSSadaf Ebrahimi #undef FLOAT_DATA
3876*22dc650dSSadaf Ebrahimi #undef FMT
3877*22dc650dSSadaf Ebrahimi 
update_mem_addr(struct sljit_compiler * compiler,sljit_s32 * mem,sljit_sw * memw,sljit_s16 max_offset)3878*22dc650dSSadaf Ebrahimi static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s16 max_offset)
3879*22dc650dSSadaf Ebrahimi {
3880*22dc650dSSadaf Ebrahimi 	sljit_s32 arg = *mem;
3881*22dc650dSSadaf Ebrahimi 	sljit_sw argw = *memw;
3882*22dc650dSSadaf Ebrahimi 
3883*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
3884*22dc650dSSadaf Ebrahimi 		argw &= 0x3;
3885*22dc650dSSadaf Ebrahimi 
3886*22dc650dSSadaf Ebrahimi 		if (SLJIT_UNLIKELY(argw)) {
3887*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1)));
3888*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1)));
3889*22dc650dSSadaf Ebrahimi 		} else
3890*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(OFFS_REG(arg)) | D(TMP_REG1), DR(TMP_REG1)));
3891*22dc650dSSadaf Ebrahimi 
3892*22dc650dSSadaf Ebrahimi 		*mem = TMP_REG1;
3893*22dc650dSSadaf Ebrahimi 		*memw = 0;
3894*22dc650dSSadaf Ebrahimi 
3895*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
3896*22dc650dSSadaf Ebrahimi 	}
3897*22dc650dSSadaf Ebrahimi 
3898*22dc650dSSadaf Ebrahimi 	if (argw <= max_offset && argw >= SIMM_MIN) {
3899*22dc650dSSadaf Ebrahimi 		*mem = arg & REG_MASK;
3900*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
3901*22dc650dSSadaf Ebrahimi 	}
3902*22dc650dSSadaf Ebrahimi 
3903*22dc650dSSadaf Ebrahimi 	*mem = TMP_REG1;
3904*22dc650dSSadaf Ebrahimi 
3905*22dc650dSSadaf Ebrahimi 	if ((sljit_s16)argw > max_offset) {
3906*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, DR(TMP_REG1), argw));
3907*22dc650dSSadaf Ebrahimi 		*memw = 0;
3908*22dc650dSSadaf Ebrahimi 	} else {
3909*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, DR(TMP_REG1), TO_ARGW_HI(argw)));
3910*22dc650dSSadaf Ebrahimi 		*memw = (sljit_s16)argw;
3911*22dc650dSSadaf Ebrahimi 	}
3912*22dc650dSSadaf Ebrahimi 
3913*22dc650dSSadaf Ebrahimi 	if ((arg & REG_MASK) == 0)
3914*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
3915*22dc650dSSadaf Ebrahimi 
3916*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1));
3917*22dc650dSSadaf Ebrahimi }
3918*22dc650dSSadaf Ebrahimi 
3919*22dc650dSSadaf Ebrahimi #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
3920*22dc650dSSadaf Ebrahimi #define IMM_LEFT(memw)			IMM((memw) + SSIZE_OF(sw) - 1)
3921*22dc650dSSadaf Ebrahimi #define IMM_RIGHT(memw)			IMM(memw)
3922*22dc650dSSadaf Ebrahimi #define IMM_32_LEFT(memw)		IMM((memw) + SSIZE_OF(s32) - 1)
3923*22dc650dSSadaf Ebrahimi #define IMM_32_RIGHT(memw)		IMM(memw)
3924*22dc650dSSadaf Ebrahimi #define IMM_F64_FIRST_LEFT(memw)	IMM((memw) + SSIZE_OF(s32) - 1)
3925*22dc650dSSadaf Ebrahimi #define IMM_F64_FIRST_RIGHT(memw)	IMM(memw)
3926*22dc650dSSadaf Ebrahimi #define IMM_F64_SECOND_LEFT(memw)	IMM((memw) + SSIZE_OF(f64) - 1)
3927*22dc650dSSadaf Ebrahimi #define IMM_F64_SECOND_RIGHT(memw)	IMM((memw) + SSIZE_OF(s32))
3928*22dc650dSSadaf Ebrahimi #define IMM_16_FIRST(memw)		IMM((memw) + 1)
3929*22dc650dSSadaf Ebrahimi #define IMM_16_SECOND(memw)		IMM(memw)
3930*22dc650dSSadaf Ebrahimi #else /* !SLJIT_LITTLE_ENDIAN */
3931*22dc650dSSadaf Ebrahimi #define IMM_LEFT(memw)			IMM(memw)
3932*22dc650dSSadaf Ebrahimi #define IMM_RIGHT(memw)			IMM((memw) + SSIZE_OF(sw) - 1)
3933*22dc650dSSadaf Ebrahimi #define IMM_32_LEFT(memw)		IMM(memw)
3934*22dc650dSSadaf Ebrahimi #define IMM_32_RIGHT(memw)		IMM((memw) + SSIZE_OF(s32) - 1)
3935*22dc650dSSadaf Ebrahimi #define IMM_F64_FIRST_LEFT(memw)	IMM((memw) + SSIZE_OF(s32))
3936*22dc650dSSadaf Ebrahimi #define IMM_F64_FIRST_RIGHT(memw)	IMM((memw) + SSIZE_OF(f64) - 1)
3937*22dc650dSSadaf Ebrahimi #define IMM_F64_SECOND_LEFT(memw)	IMM(memw)
3938*22dc650dSSadaf Ebrahimi #define IMM_F64_SECOND_RIGHT(memw)	IMM((memw) + SSIZE_OF(s32) - 1)
3939*22dc650dSSadaf Ebrahimi #define IMM_16_FIRST(memw)		IMM(memw)
3940*22dc650dSSadaf Ebrahimi #define IMM_16_SECOND(memw)		IMM((memw) + 1)
3941*22dc650dSSadaf Ebrahimi #endif /* SLJIT_LITTLE_ENDIAN */
3942*22dc650dSSadaf Ebrahimi 
3943*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3944*22dc650dSSadaf Ebrahimi #define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16))
3945*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
3946*22dc650dSSadaf Ebrahimi #define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32))
3947*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
3948*22dc650dSSadaf Ebrahimi 
sljit_emit_mem(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 reg,sljit_s32 mem,sljit_sw memw)3949*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
3950*22dc650dSSadaf Ebrahimi 	sljit_s32 reg,
3951*22dc650dSSadaf Ebrahimi 	sljit_s32 mem, sljit_sw memw)
3952*22dc650dSSadaf Ebrahimi {
3953*22dc650dSSadaf Ebrahimi 	sljit_s32 op = type & 0xff;
3954*22dc650dSSadaf Ebrahimi 	sljit_s32 flags = 0;
3955*22dc650dSSadaf Ebrahimi 	sljit_ins ins;
3956*22dc650dSSadaf Ebrahimi #if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
3957*22dc650dSSadaf Ebrahimi 	sljit_ins ins_right;
3958*22dc650dSSadaf Ebrahimi #endif /* !(SLJIT_MIPS_REV >= 6) */
3959*22dc650dSSadaf Ebrahimi 
3960*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3961*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
3962*22dc650dSSadaf Ebrahimi 
3963*22dc650dSSadaf Ebrahimi 	if (reg & REG_PAIR_MASK) {
3964*22dc650dSSadaf Ebrahimi 		ADJUST_LOCAL_OFFSET(mem, memw);
3965*22dc650dSSadaf Ebrahimi 
3966*22dc650dSSadaf Ebrahimi #if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
3967*22dc650dSSadaf Ebrahimi 		if (MEM_CHECK_UNALIGNED(type)) {
3968*22dc650dSSadaf Ebrahimi 			FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (2 * SSIZE_OF(sw) - 1)));
3969*22dc650dSSadaf Ebrahimi 
3970*22dc650dSSadaf Ebrahimi 			if (!(type & SLJIT_MEM_STORE) && (mem == REG_PAIR_FIRST(reg) || mem == REG_PAIR_SECOND(reg))) {
3971*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
3972*22dc650dSSadaf Ebrahimi 				mem = TMP_REG1;
3973*22dc650dSSadaf Ebrahimi 			}
3974*22dc650dSSadaf Ebrahimi 
3975*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3976*22dc650dSSadaf Ebrahimi 			ins = ((type & SLJIT_MEM_STORE) ? SWL : LWL) | S(mem);
3977*22dc650dSSadaf Ebrahimi 			ins_right = ((type & SLJIT_MEM_STORE) ? SWR : LWR) | S(mem);
3978*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
3979*22dc650dSSadaf Ebrahimi 			ins = ((type & SLJIT_MEM_STORE) ? SDL : LDL) | S(mem);
3980*22dc650dSSadaf Ebrahimi 			ins_right = ((type & SLJIT_MEM_STORE) ? SDR : LDR) | S(mem);
3981*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
3982*22dc650dSSadaf Ebrahimi 
3983*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM_LEFT(memw), DR(REG_PAIR_FIRST(reg))));
3984*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ins_right | T(REG_PAIR_FIRST(reg)) | IMM_RIGHT(memw), DR(REG_PAIR_FIRST(reg))));
3985*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM_LEFT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))));
3986*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ins_right | T(REG_PAIR_SECOND(reg)) | IMM_RIGHT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)));
3987*22dc650dSSadaf Ebrahimi 		}
3988*22dc650dSSadaf Ebrahimi #endif /* !(SLJIT_MIPS_REV >= 6) */
3989*22dc650dSSadaf Ebrahimi 
3990*22dc650dSSadaf Ebrahimi 		FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - SSIZE_OF(sw)));
3991*22dc650dSSadaf Ebrahimi 
3992*22dc650dSSadaf Ebrahimi 		ins = ((type & SLJIT_MEM_STORE) ? STORE_W : LOAD_W) | S(mem);
3993*22dc650dSSadaf Ebrahimi 
3994*22dc650dSSadaf Ebrahimi 		if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {
3995*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))));
3996*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg)));
3997*22dc650dSSadaf Ebrahimi 		}
3998*22dc650dSSadaf Ebrahimi 
3999*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg))));
4000*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)));
4001*22dc650dSSadaf Ebrahimi 	}
4002*22dc650dSSadaf Ebrahimi 
4003*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
4004*22dc650dSSadaf Ebrahimi 	return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
4005*22dc650dSSadaf Ebrahimi #else /* !(SLJIT_MIPS_REV >= 6) */
4006*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(mem, memw);
4007*22dc650dSSadaf Ebrahimi 
4008*22dc650dSSadaf Ebrahimi 	switch (op) {
4009*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U8:
4010*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S8:
4011*22dc650dSSadaf Ebrahimi 		flags = BYTE_DATA;
4012*22dc650dSSadaf Ebrahimi 		if (!(type & SLJIT_MEM_STORE))
4013*22dc650dSSadaf Ebrahimi 			flags |= LOAD_DATA;
4014*22dc650dSSadaf Ebrahimi 
4015*22dc650dSSadaf Ebrahimi 		if (op == SLJIT_MOV_S8)
4016*22dc650dSSadaf Ebrahimi 			flags |= SIGNED_DATA;
4017*22dc650dSSadaf Ebrahimi 
4018*22dc650dSSadaf Ebrahimi 		return emit_op_mem(compiler, flags, DR(reg), mem, memw);
4019*22dc650dSSadaf Ebrahimi 
4020*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U16:
4021*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S16:
4022*22dc650dSSadaf Ebrahimi 		FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 1));
4023*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
4024*22dc650dSSadaf Ebrahimi 
4025*22dc650dSSadaf Ebrahimi 		if (type & SLJIT_MEM_STORE) {
4026*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SRA_W | T(reg) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));
4027*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), MOVABLE_INS));
4028*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), MOVABLE_INS);
4029*22dc650dSSadaf Ebrahimi 		}
4030*22dc650dSSadaf Ebrahimi 
4031*22dc650dSSadaf Ebrahimi 		flags = BYTE_DATA | LOAD_DATA;
4032*22dc650dSSadaf Ebrahimi 
4033*22dc650dSSadaf Ebrahimi 		if (op == SLJIT_MOV_S16)
4034*22dc650dSSadaf Ebrahimi 			flags |= SIGNED_DATA;
4035*22dc650dSSadaf Ebrahimi 
4036*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, data_transfer_insts[flags] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), DR(TMP_REG2)));
4037*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA | LOAD_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), DR(reg)));
4038*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLL_W | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));
4039*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, OR | S(reg) | T(TMP_REG2) | D(reg), DR(reg));
4040*22dc650dSSadaf Ebrahimi 
4041*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV:
4042*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_P:
4043*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
4044*22dc650dSSadaf Ebrahimi 		if (type & SLJIT_MEM_ALIGNED_32) {
4045*22dc650dSSadaf Ebrahimi 			flags = WORD_DATA;
4046*22dc650dSSadaf Ebrahimi 			if (!(type & SLJIT_MEM_STORE))
4047*22dc650dSSadaf Ebrahimi 				flags |= LOAD_DATA;
4048*22dc650dSSadaf Ebrahimi 
4049*22dc650dSSadaf Ebrahimi 			return emit_op_mem(compiler, flags, DR(reg), mem, memw);
4050*22dc650dSSadaf Ebrahimi 		}
4051*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
4052*22dc650dSSadaf Ebrahimi 		FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 7));
4053*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
4054*22dc650dSSadaf Ebrahimi 
4055*22dc650dSSadaf Ebrahimi 		if (type & SLJIT_MEM_STORE) {
4056*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SDL | S(mem) | T(reg) | IMM_LEFT(memw), MOVABLE_INS));
4057*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SDR | S(mem) | T(reg) | IMM_RIGHT(memw), MOVABLE_INS);
4058*22dc650dSSadaf Ebrahimi 		}
4059*22dc650dSSadaf Ebrahimi 
4060*22dc650dSSadaf Ebrahimi 		if (mem == reg) {
4061*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
4062*22dc650dSSadaf Ebrahimi 			mem = TMP_REG1;
4063*22dc650dSSadaf Ebrahimi 		}
4064*22dc650dSSadaf Ebrahimi 
4065*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, LDL | S(mem) | T(reg) | IMM_LEFT(memw), DR(reg)));
4066*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, LDR | S(mem) | T(reg) | IMM_RIGHT(memw), DR(reg));
4067*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
4068*22dc650dSSadaf Ebrahimi 	}
4069*22dc650dSSadaf Ebrahimi 
4070*22dc650dSSadaf Ebrahimi 	FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 3));
4071*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
4072*22dc650dSSadaf Ebrahimi 
4073*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_MEM_STORE) {
4074*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SWL | S(mem) | T(reg) | IMM_32_LEFT(memw), MOVABLE_INS));
4075*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, SWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), MOVABLE_INS);
4076*22dc650dSSadaf Ebrahimi 	}
4077*22dc650dSSadaf Ebrahimi 
4078*22dc650dSSadaf Ebrahimi 	if (mem == reg) {
4079*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
4080*22dc650dSSadaf Ebrahimi 		mem = TMP_REG1;
4081*22dc650dSSadaf Ebrahimi 	}
4082*22dc650dSSadaf Ebrahimi 
4083*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM_32_LEFT(memw), DR(reg)));
4084*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
4085*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg));
4086*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
4087*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg)));
4088*22dc650dSSadaf Ebrahimi 
4089*22dc650dSSadaf Ebrahimi 	if (op != SLJIT_MOV_U32)
4090*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
4091*22dc650dSSadaf Ebrahimi 
4092*22dc650dSSadaf Ebrahimi #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
4093*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11), DR(reg));
4094*22dc650dSSadaf Ebrahimi #else  /* SLJIT_MIPS_REV < 2 */
4095*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)));
4096*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg));
4097*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
4098*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
4099*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 6 */
4100*22dc650dSSadaf Ebrahimi }
4101*22dc650dSSadaf Ebrahimi 
4102*22dc650dSSadaf Ebrahimi #if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
4103*22dc650dSSadaf Ebrahimi 
sljit_emit_fmem(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 freg,sljit_s32 mem,sljit_sw memw)4104*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
4105*22dc650dSSadaf Ebrahimi 	sljit_s32 freg,
4106*22dc650dSSadaf Ebrahimi 	sljit_s32 mem, sljit_sw memw)
4107*22dc650dSSadaf Ebrahimi {
4108*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
4109*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
4110*22dc650dSSadaf Ebrahimi 
4111*22dc650dSSadaf Ebrahimi 	FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (type & SLJIT_32) ? 3 : 7));
4112*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
4113*22dc650dSSadaf Ebrahimi 
4114*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_MEM_STORE) {
4115*22dc650dSSadaf Ebrahimi 		if (type & SLJIT_32) {
4116*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
4117*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)
4118*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
4119*22dc650dSSadaf Ebrahimi #endif /* MIPS III */
4120*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), MOVABLE_INS));
4121*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), MOVABLE_INS);
4122*22dc650dSSadaf Ebrahimi 		}
4123*22dc650dSSadaf Ebrahimi 
4124*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
4125*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
4126*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
4127*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
4128*22dc650dSSadaf Ebrahimi #endif /* MIPS III */
4129*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), MOVABLE_INS));
4130*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), MOVABLE_INS));
4131*22dc650dSSadaf Ebrahimi 		switch (cpu_feature_list & CPU_FEATURE_FR) {
4132*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
4133*22dc650dSSadaf Ebrahimi 		case CPU_FEATURE_FR:
4134*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, MFHC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
4135*22dc650dSSadaf Ebrahimi 			break;
4136*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
4137*22dc650dSSadaf Ebrahimi 		default:
4138*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg) | (1 << 11), DR(TMP_REG2)));
4139*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
4140*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
4141*22dc650dSSadaf Ebrahimi #endif
4142*22dc650dSSadaf Ebrahimi 			break;
4143*22dc650dSSadaf Ebrahimi 		}
4144*22dc650dSSadaf Ebrahimi 
4145*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), MOVABLE_INS));
4146*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), MOVABLE_INS);
4147*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
4148*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DMFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
4149*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
4150*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
4151*22dc650dSSadaf Ebrahimi #endif /* MIPS III */
4152*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), MOVABLE_INS));
4153*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, SDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), MOVABLE_INS);
4154*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
4155*22dc650dSSadaf Ebrahimi 	}
4156*22dc650dSSadaf Ebrahimi 
4157*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_32) {
4158*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), DR(TMP_REG2)));
4159*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), DR(TMP_REG2)));
4160*22dc650dSSadaf Ebrahimi 
4161*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));
4162*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)
4163*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
4164*22dc650dSSadaf Ebrahimi #endif /* MIPS III */
4165*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
4166*22dc650dSSadaf Ebrahimi 	}
4167*22dc650dSSadaf Ebrahimi 
4168*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
4169*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), DR(TMP_REG2)));
4170*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), DR(TMP_REG2)));
4171*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));
4172*22dc650dSSadaf Ebrahimi 
4173*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), DR(TMP_REG2)));
4174*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), DR(TMP_REG2)));
4175*22dc650dSSadaf Ebrahimi 	switch (cpu_feature_list & CPU_FEATURE_FR) {
4176*22dc650dSSadaf Ebrahimi #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
4177*22dc650dSSadaf Ebrahimi 	case CPU_FEATURE_FR:
4178*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS);
4179*22dc650dSSadaf Ebrahimi #endif /* SLJIT_MIPS_REV >= 2 */
4180*22dc650dSSadaf Ebrahimi 	default:
4181*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg) | (1 << 11), MOVABLE_INS));
4182*22dc650dSSadaf Ebrahimi 		break;
4183*22dc650dSSadaf Ebrahimi 	}
4184*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_MIPS_32 */
4185*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, LDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), DR(TMP_REG2)));
4186*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, LDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), DR(TMP_REG2)));
4187*22dc650dSSadaf Ebrahimi 
4188*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, DMTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));
4189*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_MIPS_32 */
4190*22dc650dSSadaf Ebrahimi #if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
4191*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
4192*22dc650dSSadaf Ebrahimi #endif /* MIPS III */
4193*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
4194*22dc650dSSadaf Ebrahimi }
4195*22dc650dSSadaf Ebrahimi 
4196*22dc650dSSadaf Ebrahimi #endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */
4197*22dc650dSSadaf Ebrahimi 
4198*22dc650dSSadaf Ebrahimi #undef IMM_16_SECOND
4199*22dc650dSSadaf Ebrahimi #undef IMM_16_FIRST
4200*22dc650dSSadaf Ebrahimi #undef IMM_F64_SECOND_RIGHT
4201*22dc650dSSadaf Ebrahimi #undef IMM_F64_SECOND_LEFT
4202*22dc650dSSadaf Ebrahimi #undef IMM_F64_FIRST_RIGHT
4203*22dc650dSSadaf Ebrahimi #undef IMM_F64_FIRST_LEFT
4204*22dc650dSSadaf Ebrahimi #undef IMM_32_RIGHT
4205*22dc650dSSadaf Ebrahimi #undef IMM_32_LEFT
4206*22dc650dSSadaf Ebrahimi #undef IMM_RIGHT
4207*22dc650dSSadaf Ebrahimi #undef IMM_LEFT
4208*22dc650dSSadaf Ebrahimi #undef MEM_CHECK_UNALIGNED
4209*22dc650dSSadaf Ebrahimi 
4210*22dc650dSSadaf Ebrahimi #undef TO_ARGW_HI
4211*22dc650dSSadaf Ebrahimi 
sljit_emit_const(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw,sljit_sw init_value)4212*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
4213*22dc650dSSadaf Ebrahimi {
4214*22dc650dSSadaf Ebrahimi 	struct sljit_const *const_;
4215*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r;
4216*22dc650dSSadaf Ebrahimi 
4217*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
4218*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
4219*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
4220*22dc650dSSadaf Ebrahimi 
4221*22dc650dSSadaf Ebrahimi 	const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
4222*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!const_);
4223*22dc650dSSadaf Ebrahimi 	set_const(const_, compiler);
4224*22dc650dSSadaf Ebrahimi 
4225*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
4226*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
4227*22dc650dSSadaf Ebrahimi 
4228*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
4229*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));
4230*22dc650dSSadaf Ebrahimi 
4231*22dc650dSSadaf Ebrahimi 	return const_;
4232*22dc650dSSadaf Ebrahimi }
4233*22dc650dSSadaf Ebrahimi 
sljit_emit_mov_addr(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw)4234*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
4235*22dc650dSSadaf Ebrahimi {
4236*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
4237*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r;
4238*22dc650dSSadaf Ebrahimi 
4239*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
4240*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
4241*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
4242*22dc650dSSadaf Ebrahimi 
4243*22dc650dSSadaf Ebrahimi 	jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
4244*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!jump);
4245*22dc650dSSadaf Ebrahimi 	set_mov_addr(jump, compiler, 0);
4246*22dc650dSSadaf Ebrahimi 
4247*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
4248*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r, UNMOVABLE_INS));
4249*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
4250*22dc650dSSadaf Ebrahimi 	compiler->size += 1;
4251*22dc650dSSadaf Ebrahimi #else
4252*22dc650dSSadaf Ebrahimi 	compiler->size += 5;
4253*22dc650dSSadaf Ebrahimi #endif
4254*22dc650dSSadaf Ebrahimi 
4255*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
4256*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));
4257*22dc650dSSadaf Ebrahimi 
4258*22dc650dSSadaf Ebrahimi 	return jump;
4259*22dc650dSSadaf Ebrahimi }
4260