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