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