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