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 >= 1)
46
47 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
48 return "MIPS32-R1" SLJIT_CPUINFO;
49 #else /* !SLJIT_CONFIG_MIPS_32 */
50 return "MIPS64-R1" SLJIT_CPUINFO;
51 #endif /* SLJIT_CONFIG_MIPS_32 */
52
53 #else /* SLJIT_MIPS_REV < 1 */
54 return "MIPS III" SLJIT_CPUINFO;
55 #endif /* SLJIT_MIPS_REV >= 6 */
56 }
57
58 /* Length of an instruction word
59 Both for mips-32 and mips-64 */
60 typedef sljit_u32 sljit_ins;
61
62 #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
63 #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
64 #define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
65
66 /* For position independent code, t9 must contain the function address. */
67 #define PIC_ADDR_REG TMP_REG2
68
69 /* Floating point status register. */
70 #define FCSR_REG 31
71 /* Return address register. */
72 #define RETURN_ADDR_REG 31
73
74 /* Flags are kept in volatile registers. */
75 #define EQUAL_FLAG 3
76 #define OTHER_FLAG 1
77
78 #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
79 #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
80 #define TMP_FREG3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3)
81
82 static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
83 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
84 };
85
86 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
87
88 static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
89 0, 0, 14, 2, 4, 6, 8, 18, 30, 28, 26, 24, 22, 20, 12, 10, 16
90 };
91
92 #else
93
94 static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
95 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
96 };
97
98 #endif
99
100 /* --------------------------------------------------------------------- */
101 /* Instrucion forms */
102 /* --------------------------------------------------------------------- */
103
104 #define S(s) ((sljit_ins)reg_map[s] << 21)
105 #define T(t) ((sljit_ins)reg_map[t] << 16)
106 #define D(d) ((sljit_ins)reg_map[d] << 11)
107 #define FT(t) ((sljit_ins)freg_map[t] << 16)
108 #define FS(s) ((sljit_ins)freg_map[s] << 11)
109 #define FD(d) ((sljit_ins)freg_map[d] << 6)
110 /* Absolute registers. */
111 #define SA(s) ((sljit_ins)(s) << 21)
112 #define TA(t) ((sljit_ins)(t) << 16)
113 #define DA(d) ((sljit_ins)(d) << 11)
114 #define IMM(imm) ((sljit_ins)(imm) & 0xffff)
115 #define SH_IMM(imm) ((sljit_ins)(imm) << 6)
116
117 #define DR(dr) (reg_map[dr])
118 #define FR(dr) (freg_map[dr])
119 #define HI(opcode) ((sljit_ins)(opcode) << 26)
120 #define LO(opcode) ((sljit_ins)(opcode))
121 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
122 /* CMP.cond.fmt */
123 /* S = (20 << 21) D = (21 << 21) */
124 #define CMP_FMT_S (20 << 21)
125 #endif /* SLJIT_MIPS_REV >= 6 */
126 /* S = (16 << 21) D = (17 << 21) */
127 #define FMT_S (16 << 21)
128 #define FMT_D (17 << 21)
129
130 #define ABS_S (HI(17) | FMT_S | LO(5))
131 #define ADD_S (HI(17) | FMT_S | LO(0))
132 #define ADDIU (HI(9))
133 #define ADDU (HI(0) | LO(33))
134 #define AND (HI(0) | LO(36))
135 #define ANDI (HI(12))
136 #define B (HI(4))
137 #define BAL (HI(1) | (17 << 16))
138 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
139 #define BC1EQZ (HI(17) | (9 << 21) | FT(TMP_FREG3))
140 #define BC1NEZ (HI(17) | (13 << 21) | FT(TMP_FREG3))
141 #else /* SLJIT_MIPS_REV < 6 */
142 #define BC1F (HI(17) | (8 << 21))
143 #define BC1T (HI(17) | (8 << 21) | (1 << 16))
144 #endif /* SLJIT_MIPS_REV >= 6 */
145 #define BEQ (HI(4))
146 #define BGEZ (HI(1) | (1 << 16))
147 #define BGTZ (HI(7))
148 #define BLEZ (HI(6))
149 #define BLTZ (HI(1) | (0 << 16))
150 #define BNE (HI(5))
151 #define BREAK (HI(0) | LO(13))
152 #define CFC1 (HI(17) | (2 << 21))
153 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
154 #define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3))
155 #define C_ULE_S (HI(17) | CMP_FMT_S | LO(7))
156 #define C_ULT_S (HI(17) | CMP_FMT_S | LO(5))
157 #define C_UN_S (HI(17) | CMP_FMT_S | LO(1))
158 #define C_FD (FD(TMP_FREG3))
159 #else /* SLJIT_MIPS_REV < 6 */
160 #define C_UEQ_S (HI(17) | FMT_S | LO(51))
161 #define C_ULE_S (HI(17) | FMT_S | LO(55))
162 #define C_ULT_S (HI(17) | FMT_S | LO(53))
163 #define C_UN_S (HI(17) | FMT_S | LO(49))
164 #define C_FD (0)
165 #endif /* SLJIT_MIPS_REV >= 6 */
166 #define CVT_S_S (HI(17) | FMT_S | LO(32))
167 #define DADDIU (HI(25))
168 #define DADDU (HI(0) | LO(45))
169 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
170 #define DDIV (HI(0) | (2 << 6) | LO(30))
171 #define DDIVU (HI(0) | (2 << 6) | LO(31))
172 #define DMOD (HI(0) | (3 << 6) | LO(30))
173 #define DMODU (HI(0) | (3 << 6) | LO(31))
174 #define DIV (HI(0) | (2 << 6) | LO(26))
175 #define DIVU (HI(0) | (2 << 6) | LO(27))
176 #define DMUH (HI(0) | (3 << 6) | LO(28))
177 #define DMUHU (HI(0) | (3 << 6) | LO(29))
178 #define DMUL (HI(0) | (2 << 6) | LO(28))
179 #define DMULU (HI(0) | (2 << 6) | LO(29))
180 #else /* SLJIT_MIPS_REV < 6 */
181 #define DDIV (HI(0) | LO(30))
182 #define DDIVU (HI(0) | LO(31))
183 #define DIV (HI(0) | LO(26))
184 #define DIVU (HI(0) | LO(27))
185 #define DMULT (HI(0) | LO(28))
186 #define DMULTU (HI(0) | LO(29))
187 #endif /* SLJIT_MIPS_REV >= 6 */
188 #define DIV_S (HI(17) | FMT_S | LO(3))
189 #define DINSU (HI(31) | LO(6))
190 #define DSLL (HI(0) | LO(56))
191 #define DSLL32 (HI(0) | LO(60))
192 #define DSLLV (HI(0) | LO(20))
193 #define DSRA (HI(0) | LO(59))
194 #define DSRA32 (HI(0) | LO(63))
195 #define DSRAV (HI(0) | LO(23))
196 #define DSRL (HI(0) | LO(58))
197 #define DSRL32 (HI(0) | LO(62))
198 #define DSRLV (HI(0) | LO(22))
199 #define DSUBU (HI(0) | LO(47))
200 #define J (HI(2))
201 #define JAL (HI(3))
202 #define JALR (HI(0) | LO(9))
203 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
204 #define JR (HI(0) | LO(9))
205 #else /* SLJIT_MIPS_REV < 6 */
206 #define JR (HI(0) | LO(8))
207 #endif /* SLJIT_MIPS_REV >= 6 */
208 #define LD (HI(55))
209 #define LDC1 (HI(53))
210 #define LUI (HI(15))
211 #define LW (HI(35))
212 #define LWC1 (HI(49))
213 #define MFC1 (HI(17))
214 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
215 #define MOD (HI(0) | (3 << 6) | LO(26))
216 #define MODU (HI(0) | (3 << 6) | LO(27))
217 #else /* SLJIT_MIPS_REV < 6 */
218 #define MFHI (HI(0) | LO(16))
219 #define MFLO (HI(0) | LO(18))
220 #endif /* SLJIT_MIPS_REV >= 6 */
221 #define MOV_S (HI(17) | FMT_S | LO(6))
222 #define MTC1 (HI(17) | (4 << 21))
223 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
224 #define MUH (HI(0) | (3 << 6) | LO(24))
225 #define MUHU (HI(0) | (3 << 6) | LO(25))
226 #define MUL (HI(0) | (2 << 6) | LO(24))
227 #define MULU (HI(0) | (2 << 6) | LO(25))
228 #else /* SLJIT_MIPS_REV < 6 */
229 #define MULT (HI(0) | LO(24))
230 #define MULTU (HI(0) | LO(25))
231 #endif /* SLJIT_MIPS_REV >= 6 */
232 #define MUL_S (HI(17) | FMT_S | LO(2))
233 #define NEG_S (HI(17) | FMT_S | LO(7))
234 #define NOP (HI(0) | LO(0))
235 #define NOR (HI(0) | LO(39))
236 #define OR (HI(0) | LO(37))
237 #define ORI (HI(13))
238 #define SD (HI(63))
239 #define SDC1 (HI(61))
240 #define SLT (HI(0) | LO(42))
241 #define SLTI (HI(10))
242 #define SLTIU (HI(11))
243 #define SLTU (HI(0) | LO(43))
244 #define SLL (HI(0) | LO(0))
245 #define SLLV (HI(0) | LO(4))
246 #define SRL (HI(0) | LO(2))
247 #define SRLV (HI(0) | LO(6))
248 #define SRA (HI(0) | LO(3))
249 #define SRAV (HI(0) | LO(7))
250 #define SUB_S (HI(17) | FMT_S | LO(1))
251 #define SUBU (HI(0) | LO(35))
252 #define SW (HI(43))
253 #define SWC1 (HI(57))
254 #define TRUNC_W_S (HI(17) | FMT_S | LO(13))
255 #define XOR (HI(0) | LO(38))
256 #define XORI (HI(14))
257
258 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
259 #define CLZ (HI(28) | LO(32))
260 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
261 #define DCLZ (LO(18))
262 #else /* SLJIT_MIPS_REV < 6 */
263 #define DCLZ (HI(28) | LO(36))
264 #define MOVF (HI(0) | (0 << 16) | LO(1))
265 #define MOVN (HI(0) | LO(11))
266 #define MOVT (HI(0) | (1 << 16) | LO(1))
267 #define MOVZ (HI(0) | LO(10))
268 #define MUL (HI(28) | LO(2))
269 #endif /* SLJIT_MIPS_REV >= 6 */
270 #define PREF (HI(51))
271 #define PREFX (HI(19) | LO(15))
272 #define SEB (HI(31) | (16 << 6) | LO(32))
273 #define SEH (HI(31) | (24 << 6) | LO(32))
274 #endif /* SLJIT_MIPS_REV >= 1 */
275
276 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
277 #define ADDU_W ADDU
278 #define ADDIU_W ADDIU
279 #define SLL_W SLL
280 #define SUBU_W SUBU
281 #else
282 #define ADDU_W DADDU
283 #define ADDIU_W DADDIU
284 #define SLL_W DSLL
285 #define SUBU_W DSUBU
286 #endif
287
288 #define SIMM_MAX (0x7fff)
289 #define SIMM_MIN (-0x8000)
290 #define UIMM_MAX (0xffff)
291
292 /* dest_reg is the absolute name of the register
293 Useful for reordering instructions in the delay slot. */
push_inst(struct sljit_compiler * compiler,sljit_ins ins,sljit_s32 delay_slot)294 static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)
295 {
296 sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
297 SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS
298 || (sljit_ins)delay_slot == ((ins >> 11) & 0x1f)
299 || (sljit_ins)delay_slot == ((ins >> 16) & 0x1f));
300 FAIL_IF(!ptr);
301 *ptr = ins;
302 compiler->size++;
303 compiler->delay_slot = delay_slot;
304 return SLJIT_SUCCESS;
305 }
306
invert_branch(sljit_uw flags)307 static SLJIT_INLINE sljit_ins invert_branch(sljit_uw flags)
308 {
309 if (flags & IS_BIT26_COND)
310 return (1 << 26);
311 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
312 if (flags & IS_BIT23_COND)
313 return (1 << 23);
314 #endif /* SLJIT_MIPS_REV >= 6 */
315 return (1 << 16);
316 }
317
detect_jump_type(struct sljit_jump * jump,sljit_ins * code_ptr,sljit_ins * code,sljit_sw executable_offset)318 static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
319 {
320 sljit_sw diff;
321 sljit_uw target_addr;
322 sljit_ins *inst;
323 sljit_ins saved_inst;
324
325 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
326 if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
327 return code_ptr;
328 #else
329 if (jump->flags & SLJIT_REWRITABLE_JUMP)
330 return code_ptr;
331 #endif
332
333 if (jump->flags & JUMP_ADDR)
334 target_addr = jump->u.target;
335 else {
336 SLJIT_ASSERT(jump->flags & JUMP_LABEL);
337 target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
338 }
339
340 inst = (sljit_ins *)jump->addr;
341 if (jump->flags & IS_COND)
342 inst--;
343
344 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
345 if (jump->flags & IS_CALL)
346 goto keep_address;
347 #endif
348
349 /* B instructions. */
350 if (jump->flags & IS_MOVABLE) {
351 diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;
352 if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
353 jump->flags |= PATCH_B;
354
355 if (!(jump->flags & IS_COND)) {
356 inst[0] = inst[-1];
357 inst[-1] = (jump->flags & IS_JAL) ? BAL : B;
358 jump->addr -= sizeof(sljit_ins);
359 return inst;
360 }
361 saved_inst = inst[0];
362 inst[0] = inst[-1];
363 inst[-1] = saved_inst ^ invert_branch(jump->flags);
364 jump->addr -= 2 * sizeof(sljit_ins);
365 return inst;
366 }
367 }
368 else {
369 diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;
370 if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
371 jump->flags |= PATCH_B;
372
373 if (!(jump->flags & IS_COND)) {
374 inst[0] = (jump->flags & IS_JAL) ? BAL : B;
375 inst[1] = NOP;
376 return inst + 1;
377 }
378 inst[0] ^= invert_branch(jump->flags);
379 inst[1] = NOP;
380 jump->addr -= sizeof(sljit_ins);
381 return inst + 1;
382 }
383 }
384
385 if (jump->flags & IS_COND) {
386 if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
387 jump->flags |= PATCH_J;
388 saved_inst = inst[0];
389 inst[0] = inst[-1];
390 inst[-1] = (saved_inst & 0xffff0000) | 3;
391 inst[1] = J;
392 inst[2] = NOP;
393 return inst + 2;
394 }
395 else if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
396 jump->flags |= PATCH_J;
397 inst[0] = (inst[0] & 0xffff0000) | 3;
398 inst[1] = NOP;
399 inst[2] = J;
400 inst[3] = NOP;
401 jump->addr += sizeof(sljit_ins);
402 return inst + 3;
403 }
404 }
405 else {
406 /* J instuctions. */
407 if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == (jump->addr & ~(sljit_uw)0xfffffff)) {
408 jump->flags |= PATCH_J;
409 inst[0] = inst[-1];
410 inst[-1] = (jump->flags & IS_JAL) ? JAL : J;
411 jump->addr -= sizeof(sljit_ins);
412 return inst;
413 }
414
415 if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
416 jump->flags |= PATCH_J;
417 inst[0] = (jump->flags & IS_JAL) ? JAL : J;
418 inst[1] = NOP;
419 return inst + 1;
420 }
421 }
422
423 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
424 keep_address:
425 if (target_addr <= 0x7fffffff) {
426 jump->flags |= PATCH_ABS32;
427 if (jump->flags & IS_COND) {
428 inst[0] -= 4;
429 inst++;
430 }
431 inst[2] = inst[6];
432 inst[3] = inst[7];
433 return inst + 3;
434 }
435 if (target_addr <= 0x7fffffffffffl) {
436 jump->flags |= PATCH_ABS48;
437 if (jump->flags & IS_COND) {
438 inst[0] -= 2;
439 inst++;
440 }
441 inst[4] = inst[6];
442 inst[5] = inst[7];
443 return inst + 5;
444 }
445 #endif
446
447 return code_ptr;
448 }
449
450 #ifdef __GNUC__
sljit_cache_flush(void * code,void * code_ptr)451 static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr)
452 {
453 SLJIT_CACHE_FLUSH(code, code_ptr);
454 }
455 #endif
456
457 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
458
put_label_get_length(struct sljit_put_label * put_label,sljit_uw max_label)459 static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
460 {
461 if (max_label < 0x80000000l) {
462 put_label->flags = 0;
463 return 1;
464 }
465
466 if (max_label < 0x800000000000l) {
467 put_label->flags = 1;
468 return 3;
469 }
470
471 put_label->flags = 2;
472 return 5;
473 }
474
put_label_set(struct sljit_put_label * put_label)475 static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
476 {
477 sljit_uw addr = put_label->label->addr;
478 sljit_ins *inst = (sljit_ins *)put_label->addr;
479 sljit_u32 reg = *inst;
480
481 if (put_label->flags == 0) {
482 SLJIT_ASSERT(addr < 0x80000000l);
483 inst[0] = LUI | T(reg) | IMM(addr >> 16);
484 }
485 else if (put_label->flags == 1) {
486 SLJIT_ASSERT(addr < 0x800000000000l);
487 inst[0] = LUI | T(reg) | IMM(addr >> 32);
488 inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
489 inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
490 inst += 2;
491 }
492 else {
493 inst[0] = LUI | T(reg) | IMM(addr >> 48);
494 inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);
495 inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
496 inst[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
497 inst[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);
498 inst += 4;
499 }
500
501 inst[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);
502 }
503
504 #endif
505
sljit_generate_code(struct sljit_compiler * compiler)506 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
507 {
508 struct sljit_memory_fragment *buf;
509 sljit_ins *code;
510 sljit_ins *code_ptr;
511 sljit_ins *buf_ptr;
512 sljit_ins *buf_end;
513 sljit_uw word_count;
514 sljit_uw next_addr;
515 sljit_sw executable_offset;
516 sljit_uw addr;
517
518 struct sljit_label *label;
519 struct sljit_jump *jump;
520 struct sljit_const *const_;
521 struct sljit_put_label *put_label;
522
523 CHECK_ERROR_PTR();
524 CHECK_PTR(check_sljit_generate_code(compiler));
525 reverse_buf(compiler);
526
527 code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);
528 PTR_FAIL_WITH_EXEC_IF(code);
529 buf = compiler->buf;
530
531 code_ptr = code;
532 word_count = 0;
533 next_addr = 0;
534 executable_offset = SLJIT_EXEC_OFFSET(code);
535
536 label = compiler->labels;
537 jump = compiler->jumps;
538 const_ = compiler->consts;
539 put_label = compiler->put_labels;
540
541 do {
542 buf_ptr = (sljit_ins*)buf->memory;
543 buf_end = buf_ptr + (buf->used_size >> 2);
544 do {
545 *code_ptr = *buf_ptr++;
546 if (next_addr == word_count) {
547 SLJIT_ASSERT(!label || label->size >= word_count);
548 SLJIT_ASSERT(!jump || jump->addr >= word_count);
549 SLJIT_ASSERT(!const_ || const_->addr >= word_count);
550 SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
551
552 /* These structures are ordered by their address. */
553 if (label && label->size == word_count) {
554 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
555 label->size = (sljit_uw)(code_ptr - code);
556 label = label->next;
557 }
558 if (jump && jump->addr == word_count) {
559 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
560 jump->addr = (sljit_uw)(code_ptr - 3);
561 #else
562 jump->addr = (sljit_uw)(code_ptr - 7);
563 #endif
564 code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
565 jump = jump->next;
566 }
567 if (const_ && const_->addr == word_count) {
568 const_->addr = (sljit_uw)code_ptr;
569 const_ = const_->next;
570 }
571 if (put_label && put_label->addr == word_count) {
572 SLJIT_ASSERT(put_label->label);
573 put_label->addr = (sljit_uw)code_ptr;
574 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
575 code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
576 word_count += 5;
577 #endif
578 put_label = put_label->next;
579 }
580 next_addr = compute_next_addr(label, jump, const_, put_label);
581 }
582 code_ptr ++;
583 word_count ++;
584 } while (buf_ptr < buf_end);
585
586 buf = buf->next;
587 } while (buf);
588
589 if (label && label->size == word_count) {
590 label->addr = (sljit_uw)code_ptr;
591 label->size = (sljit_uw)(code_ptr - code);
592 label = label->next;
593 }
594
595 SLJIT_ASSERT(!label);
596 SLJIT_ASSERT(!jump);
597 SLJIT_ASSERT(!const_);
598 SLJIT_ASSERT(!put_label);
599 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
600
601 jump = compiler->jumps;
602 while (jump) {
603 do {
604 addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
605 buf_ptr = (sljit_ins *)jump->addr;
606
607 if (jump->flags & PATCH_B) {
608 addr = (sljit_uw)((sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) - sizeof(sljit_ins)) >> 2);
609 SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);
610 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((sljit_ins)addr & 0xffff);
611 break;
612 }
613 if (jump->flags & PATCH_J) {
614 SLJIT_ASSERT((addr & ~(sljit_uw)0xfffffff)
615 == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff));
616 buf_ptr[0] |= (sljit_ins)(addr >> 2) & 0x03ffffff;
617 break;
618 }
619
620 /* Set the fields of immediate loads. */
621 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
622 SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);
623 buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;
624 buf_ptr[1] |= (sljit_ins)addr & 0xffff;
625 #else
626 if (jump->flags & PATCH_ABS32) {
627 SLJIT_ASSERT(addr <= 0x7fffffff);
628 SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);
629 buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;
630 buf_ptr[1] |= (sljit_ins)addr & 0xffff;
631 break;
632 }
633
634 if (jump->flags & PATCH_ABS48) {
635 SLJIT_ASSERT(addr <= 0x7fffffffffffl);
636 SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3]) & 0xffff) == 0);
637 buf_ptr[0] |= (sljit_ins)(addr >> 32) & 0xffff;
638 buf_ptr[1] |= (sljit_ins)(addr >> 16) & 0xffff;
639 buf_ptr[3] |= (sljit_ins)addr & 0xffff;
640 break;
641 }
642
643 SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3] | buf_ptr[5]) & 0xffff) == 0);
644 buf_ptr[0] |= (sljit_ins)(addr >> 48) & 0xffff;
645 buf_ptr[1] |= (sljit_ins)(addr >> 32) & 0xffff;
646 buf_ptr[3] |= (sljit_ins)(addr >> 16) & 0xffff;
647 buf_ptr[5] |= (sljit_ins)addr & 0xffff;
648 #endif
649 } while (0);
650 jump = jump->next;
651 }
652
653 put_label = compiler->put_labels;
654 while (put_label) {
655 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
656 addr = put_label->label->addr;
657 buf_ptr = (sljit_ins *)put_label->addr;
658
659 SLJIT_ASSERT((buf_ptr[0] & 0xffe00000) == LUI && (buf_ptr[1] & 0xfc000000) == ORI);
660 buf_ptr[0] |= (addr >> 16) & 0xffff;
661 buf_ptr[1] |= addr & 0xffff;
662 #else
663 put_label_set(put_label);
664 #endif
665 put_label = put_label->next;
666 }
667
668 compiler->error = SLJIT_ERR_COMPILED;
669 compiler->executable_offset = executable_offset;
670 compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
671
672 code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
673 code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
674
675 #ifndef __GNUC__
676 SLJIT_CACHE_FLUSH(code, code_ptr);
677 #else
678 /* GCC workaround for invalid code generation with -O2. */
679 sljit_cache_flush(code, code_ptr);
680 #endif
681 SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
682 return code;
683 }
684
sljit_has_cpu_feature(sljit_s32 feature_type)685 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
686 {
687 #if defined(__GNUC__) && !defined(SLJIT_IS_FPU_AVAILABLE)
688 sljit_sw fir = 0;
689 #endif /* __GNUC__ && !SLJIT_IS_FPU_AVAILABLE */
690
691 switch (feature_type) {
692 case SLJIT_HAS_FPU:
693 #ifdef SLJIT_IS_FPU_AVAILABLE
694 return SLJIT_IS_FPU_AVAILABLE;
695 #elif defined(__GNUC__)
696 __asm__ ("cfc1 %0, $0" : "=r"(fir));
697 return (fir >> 22) & 0x1;
698 #else
699 #error "FIR check is not implemented for this architecture"
700 #endif
701 case SLJIT_HAS_ZERO_REGISTER:
702 return 1;
703
704 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
705 case SLJIT_HAS_CLZ:
706 case SLJIT_HAS_CMOV:
707 case SLJIT_HAS_PREFETCH:
708 return 1;
709 #endif /* SLJIT_MIPS_REV >= 1 */
710
711 default:
712 return 0;
713 }
714 }
715
716 /* --------------------------------------------------------------------- */
717 /* Entry, exit */
718 /* --------------------------------------------------------------------- */
719
720 /* Creates an index in data_transfer_insts array. */
721 #define LOAD_DATA 0x01
722 #define WORD_DATA 0x00
723 #define BYTE_DATA 0x02
724 #define HALF_DATA 0x04
725 #define INT_DATA 0x06
726 #define SIGNED_DATA 0x08
727 /* Separates integer and floating point registers */
728 #define GPR_REG 0x0f
729 #define DOUBLE_DATA 0x10
730 #define SINGLE_DATA 0x12
731
732 #define MEM_MASK 0x1f
733
734 #define ARG_TEST 0x00020
735 #define ALT_KEEP_CACHE 0x00040
736 #define CUMULATIVE_OP 0x00080
737 #define LOGICAL_OP 0x00100
738 #define IMM_OP 0x00200
739 #define MOVE_OP 0x00400
740 #define SRC2_IMM 0x00800
741
742 #define UNUSED_DEST 0x01000
743 #define REG_DEST 0x02000
744 #define REG1_SOURCE 0x04000
745 #define REG2_SOURCE 0x08000
746 #define SLOW_SRC1 0x10000
747 #define SLOW_SRC2 0x20000
748 #define SLOW_DEST 0x40000
749
750 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
751 #define STACK_STORE SW
752 #define STACK_LOAD LW
753 #else
754 #define STACK_STORE SD
755 #define STACK_LOAD LD
756 #endif
757
758 static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);
759 static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr);
760
761 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
762 #include "sljitNativeMIPS_32.c"
763 #else
764 #include "sljitNativeMIPS_64.c"
765 #endif
766
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)767 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
768 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
769 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
770 {
771 sljit_ins base;
772 sljit_s32 i, tmp, offset;
773 sljit_s32 arg_count, word_arg_count, saved_arg_count, float_arg_count;
774
775 CHECK_ERROR();
776 CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
777 set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
778
779 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
780 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
781 if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
782 if ((local_size & SSIZE_OF(sw)) != 0)
783 local_size += SSIZE_OF(sw);
784 local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
785 }
786
787 local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
788 #else
789 local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
790 local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;
791 #endif
792 compiler->local_size = local_size;
793
794 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
795 tmp = arg_types >> SLJIT_ARG_SHIFT;
796 arg_count = 0;
797 offset = 0;
798
799 while (tmp) {
800 offset = arg_count;
801 if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {
802 if ((arg_count & 0x1) != 0)
803 arg_count++;
804 arg_count++;
805 }
806
807 arg_count++;
808 tmp >>= SLJIT_ARG_SHIFT;
809 }
810
811 compiler->args_size = (sljit_uw)arg_count << 2;
812 offset = (offset >= 4) ? (offset << 2) : 0;
813 #else /* !SLJIT_CONFIG_MIPS_32 */
814 offset = 0;
815 #endif /* SLJIT_CONFIG_MIPS_32 */
816
817 if (local_size + offset <= -SIMM_MIN) {
818 /* Frequent case. */
819 FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));
820 base = S(SLJIT_SP);
821 offset = local_size - SSIZE_OF(sw);
822 } else {
823 FAIL_IF(load_immediate(compiler, DR(OTHER_FLAG), local_size));
824 FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
825 FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
826 base = S(TMP_REG2);
827 offset = -SSIZE_OF(sw);
828 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
829 local_size = 0;
830 #endif
831 }
832
833 FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offset), MOVABLE_INS));
834
835 tmp = SLJIT_S0 - saveds;
836 for (i = SLJIT_S0; i > tmp; i--) {
837 offset -= SSIZE_OF(sw);
838 FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offset), MOVABLE_INS));
839 }
840
841 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
842 offset -= SSIZE_OF(sw);
843 FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offset), MOVABLE_INS));
844 }
845
846 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
847 /* This alignment is valid because offset is not used after storing FPU regs. */
848 if ((offset & SSIZE_OF(sw)) != 0)
849 offset -= SSIZE_OF(sw);
850 #endif
851
852 tmp = SLJIT_FS0 - fsaveds;
853 for (i = SLJIT_FS0; i > tmp; i--) {
854 offset -= SSIZE_OF(f64);
855 FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
856 }
857
858 for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
859 offset -= SSIZE_OF(f64);
860 FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
861 }
862
863 arg_types >>= SLJIT_ARG_SHIFT;
864 arg_count = 0;
865 word_arg_count = 0;
866 saved_arg_count = 0;
867 float_arg_count = 0;
868
869 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
870 /* The first maximum two floating point arguments are passed in floating point
871 registers if no integer argument precedes them. The first 16 byte data is
872 passed in four integer registers, the rest is placed onto the stack.
873 The floating point registers are also part of the first 16 byte data, so
874 their corresponding integer registers are not used when they are present. */
875
876 while (arg_types) {
877 switch (arg_types & SLJIT_ARG_MASK) {
878 case SLJIT_ARG_TYPE_F64:
879 float_arg_count++;
880 if ((arg_count & 0x1) != 0)
881 arg_count++;
882
883 if (word_arg_count == 0 && float_arg_count <= 2) {
884 if (float_arg_count == 1)
885 FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
886 } else if (arg_count < 4) {
887 FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
888 FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS));
889 } else
890 FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
891 arg_count++;
892 break;
893 case SLJIT_ARG_TYPE_F32:
894 float_arg_count++;
895
896 if (word_arg_count == 0 && float_arg_count <= 2) {
897 if (float_arg_count == 1)
898 FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
899 } else if (arg_count < 4)
900 FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
901 else
902 FAIL_IF(push_inst(compiler, LWC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
903 break;
904 default:
905 word_arg_count++;
906
907 if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
908 tmp = SLJIT_S0 - saved_arg_count;
909 saved_arg_count++;
910 } else if (word_arg_count != arg_count + 1 || arg_count == 0)
911 tmp = word_arg_count;
912 else
913 break;
914
915 if (arg_count < 4)
916 FAIL_IF(push_inst(compiler, ADDU_W | SA(4 + arg_count) | TA(0) | D(tmp), DR(tmp)));
917 else
918 FAIL_IF(push_inst(compiler, LW | base | T(tmp) | IMM(local_size + (arg_count << 2)), DR(tmp)));
919 break;
920 }
921 arg_count++;
922 arg_types >>= SLJIT_ARG_SHIFT;
923 }
924
925 SLJIT_ASSERT(compiler->args_size == (sljit_uw)arg_count << 2);
926 #else /* !SLJIT_CONFIG_MIPS_32 */
927 while (arg_types) {
928 arg_count++;
929 switch (arg_types & SLJIT_ARG_MASK) {
930 case SLJIT_ARG_TYPE_F64:
931 float_arg_count++;
932 if (arg_count != float_arg_count)
933 FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
934 else if (arg_count == 1)
935 FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
936 break;
937 case SLJIT_ARG_TYPE_F32:
938 float_arg_count++;
939 if (arg_count != float_arg_count)
940 FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
941 else if (arg_count == 1)
942 FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
943 break;
944 default:
945 word_arg_count++;
946
947 if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
948 tmp = SLJIT_S0 - saved_arg_count;
949 saved_arg_count++;
950 } else if (word_arg_count != arg_count || word_arg_count <= 1)
951 tmp = word_arg_count;
952 else
953 break;
954
955 FAIL_IF(push_inst(compiler, ADDU_W | SA(3 + arg_count) | TA(0) | D(tmp), DR(tmp)));
956 break;
957 }
958 arg_types >>= SLJIT_ARG_SHIFT;
959 }
960 #endif /* SLJIT_CONFIG_MIPS_32 */
961
962 return SLJIT_SUCCESS;
963 }
964
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)965 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
966 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
967 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
968 {
969 CHECK_ERROR();
970 CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
971 set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
972
973 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
974 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
975 if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
976 if ((local_size & SSIZE_OF(sw)) != 0)
977 local_size += SSIZE_OF(sw);
978 local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
979 }
980
981 compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
982 #else
983 local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
984 compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;
985 #endif
986 return SLJIT_SUCCESS;
987 }
988
emit_stack_frame_release(struct sljit_compiler * compiler,sljit_s32 frame_size,sljit_ins * ins_ptr)989 static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr)
990 {
991 sljit_s32 local_size, i, tmp, offset;
992 sljit_s32 scratches = compiler->scratches;
993 sljit_s32 saveds = compiler->saveds;
994 sljit_s32 fsaveds = compiler->fsaveds;
995 sljit_s32 fscratches = compiler->fscratches;
996
997 local_size = compiler->local_size;
998
999 tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
1000 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1001 if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
1002 if ((tmp & SSIZE_OF(sw)) != 0)
1003 tmp += SSIZE_OF(sw);
1004 tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
1005 }
1006 #else
1007 tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
1008 #endif
1009
1010 if (local_size <= SIMM_MAX) {
1011 if (local_size < frame_size) {
1012 FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size), DR(SLJIT_SP)));
1013 local_size = frame_size;
1014 }
1015 } else {
1016 if (tmp < frame_size)
1017 tmp = frame_size;
1018
1019 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size - tmp));
1020 FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG1) | D(SLJIT_SP), DR(SLJIT_SP)));
1021 local_size = tmp;
1022 }
1023
1024 SLJIT_ASSERT(local_size >= frame_size);
1025
1026 offset = local_size - SSIZE_OF(sw);
1027 if (frame_size == 0)
1028 FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG));
1029
1030 tmp = SLJIT_S0 - saveds;
1031 for (i = SLJIT_S0; i > tmp; i--) {
1032 offset -= SSIZE_OF(sw);
1033 FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));
1034 }
1035
1036 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
1037 offset -= SSIZE_OF(sw);
1038 FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));
1039 }
1040
1041 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1042 /* This alignment is valid because offset is not used after storing FPU regs. */
1043 if ((offset & SSIZE_OF(sw)) != 0)
1044 offset -= SSIZE_OF(sw);
1045 #endif
1046
1047 tmp = SLJIT_FS0 - fsaveds;
1048 for (i = SLJIT_FS0; i > tmp; i--) {
1049 offset -= SSIZE_OF(f64);
1050 FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));
1051 }
1052
1053 for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
1054 offset -= SSIZE_OF(f64);
1055 FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));
1056 }
1057
1058 if (local_size > frame_size)
1059 *ins_ptr = ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size);
1060 else
1061 *ins_ptr = NOP;
1062
1063 return SLJIT_SUCCESS;
1064 }
1065
sljit_emit_return_void(struct sljit_compiler * compiler)1066 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
1067 {
1068 sljit_ins ins;
1069
1070 CHECK_ERROR();
1071 CHECK(check_sljit_emit_return_void(compiler));
1072
1073 emit_stack_frame_release(compiler, 0, &ins);
1074
1075 FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
1076 return push_inst(compiler, ins, UNMOVABLE_INS);
1077 }
1078
1079 #undef STACK_STORE
1080 #undef STACK_LOAD
1081
1082 /* --------------------------------------------------------------------- */
1083 /* Operators */
1084 /* --------------------------------------------------------------------- */
1085
1086 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1087 #define ARCH_32_64(a, b) a
1088 #else
1089 #define ARCH_32_64(a, b) b
1090 #endif
1091
1092 static const sljit_ins data_transfer_insts[16 + 4] = {
1093 /* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
1094 /* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
1095 /* u b s */ HI(40) /* sb */,
1096 /* u b l */ HI(36) /* lbu */,
1097 /* u h s */ HI(41) /* sh */,
1098 /* u h l */ HI(37) /* lhu */,
1099 /* u i s */ HI(43) /* sw */,
1100 /* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),
1101
1102 /* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
1103 /* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
1104 /* s b s */ HI(40) /* sb */,
1105 /* s b l */ HI(32) /* lb */,
1106 /* s h s */ HI(41) /* sh */,
1107 /* s h l */ HI(33) /* lh */,
1108 /* s i s */ HI(43) /* sw */,
1109 /* s i l */ HI(35) /* lw */,
1110
1111 /* d s */ HI(61) /* sdc1 */,
1112 /* d l */ HI(53) /* ldc1 */,
1113 /* s s */ HI(57) /* swc1 */,
1114 /* s l */ HI(49) /* lwc1 */,
1115 };
1116
1117 #undef ARCH_32_64
1118
1119 /* reg_ar is an absoulute register! */
1120
1121 /* 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)1122 static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
1123 {
1124 SLJIT_ASSERT(arg & SLJIT_MEM);
1125
1126 if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
1127 /* Works for both absoulte and relative addresses. */
1128 if (SLJIT_UNLIKELY(flags & ARG_TEST))
1129 return 1;
1130 FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)
1131 | TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));
1132 return -1;
1133 }
1134 return 0;
1135 }
1136
1137 /* See getput_arg below.
1138 Note: can_cache is called only for binary operators. Those
1139 operators always uses word arguments without write back. */
can_cache(sljit_s32 arg,sljit_sw argw,sljit_s32 next_arg,sljit_sw next_argw)1140 static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
1141 {
1142 SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
1143
1144 /* Simple operation except for updates. */
1145 if (arg & OFFS_REG_MASK) {
1146 argw &= 0x3;
1147 next_argw &= 0x3;
1148 if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
1149 return 1;
1150 return 0;
1151 }
1152
1153 if (arg == next_arg) {
1154 if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN))
1155 return 1;
1156 return 0;
1157 }
1158
1159 return 0;
1160 }
1161
1162 /* 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)1163 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)
1164 {
1165 sljit_s32 tmp_ar, base, delay_slot;
1166
1167 SLJIT_ASSERT(arg & SLJIT_MEM);
1168 if (!(next_arg & SLJIT_MEM)) {
1169 next_arg = 0;
1170 next_argw = 0;
1171 }
1172
1173 if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
1174 tmp_ar = reg_ar;
1175 delay_slot = reg_ar;
1176 }
1177 else {
1178 tmp_ar = DR(TMP_REG1);
1179 delay_slot = MOVABLE_INS;
1180 }
1181 base = arg & REG_MASK;
1182
1183 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1184 argw &= 0x3;
1185
1186 /* Using the cache. */
1187 if (argw == compiler->cache_argw) {
1188 if (arg == compiler->cache_arg)
1189 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1190
1191 if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
1192 if (arg == next_arg && argw == (next_argw & 0x3)) {
1193 compiler->cache_arg = arg;
1194 compiler->cache_argw = argw;
1195 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
1196 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1197 }
1198 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
1199 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1200 }
1201 }
1202
1203 if (SLJIT_UNLIKELY(argw)) {
1204 compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
1205 compiler->cache_argw = argw;
1206 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
1207 }
1208
1209 if (arg == next_arg && argw == (next_argw & 0x3)) {
1210 compiler->cache_arg = arg;
1211 compiler->cache_argw = argw;
1212 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
1213 tmp_ar = DR(TMP_REG3);
1214 }
1215 else
1216 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
1217 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1218 }
1219
1220 if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
1221 if (argw != compiler->cache_argw) {
1222 FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
1223 compiler->cache_argw = argw;
1224 }
1225 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1226 }
1227
1228 if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
1229 if (argw != compiler->cache_argw)
1230 FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
1231 }
1232 else {
1233 compiler->cache_arg = SLJIT_MEM;
1234 FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
1235 }
1236 compiler->cache_argw = argw;
1237
1238 if (!base)
1239 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1240
1241 if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {
1242 compiler->cache_arg = arg;
1243 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));
1244 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1245 }
1246
1247 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));
1248 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1249 }
1250
emit_op_mem(struct sljit_compiler * compiler,sljit_s32 flags,sljit_s32 reg_ar,sljit_s32 arg,sljit_sw argw)1251 static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
1252 {
1253 sljit_s32 tmp_ar, base, delay_slot;
1254
1255 if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
1256 return compiler->error;
1257
1258 if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
1259 tmp_ar = reg_ar;
1260 delay_slot = reg_ar;
1261 }
1262 else {
1263 tmp_ar = DR(TMP_REG1);
1264 delay_slot = MOVABLE_INS;
1265 }
1266 base = arg & REG_MASK;
1267
1268 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1269 argw &= 0x3;
1270
1271 if (SLJIT_UNLIKELY(argw)) {
1272 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));
1273 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));
1274 }
1275 else
1276 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));
1277 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1278 }
1279
1280 FAIL_IF(load_immediate(compiler, tmp_ar, argw));
1281
1282 if (base != 0)
1283 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));
1284
1285 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1286 }
1287
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)1288 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)
1289 {
1290 if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
1291 return compiler->error;
1292 return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
1293 }
1294
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)1295 static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
1296 sljit_s32 dst, sljit_sw dstw,
1297 sljit_s32 src1, sljit_sw src1w,
1298 sljit_s32 src2, sljit_sw src2w)
1299 {
1300 /* arg1 goes to TMP_REG1 or src reg
1301 arg2 goes to TMP_REG2, imm or src reg
1302 TMP_REG3 can be used for caching
1303 result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
1304 sljit_s32 dst_r = TMP_REG2;
1305 sljit_s32 src1_r;
1306 sljit_sw src2_r = 0;
1307 sljit_s32 sugg_src2_r = TMP_REG2;
1308
1309 if (!(flags & ALT_KEEP_CACHE)) {
1310 compiler->cache_arg = 0;
1311 compiler->cache_argw = 0;
1312 }
1313
1314 if (dst == TMP_REG2) {
1315 SLJIT_ASSERT(HAS_FLAGS(op));
1316 flags |= UNUSED_DEST;
1317 }
1318 else if (FAST_IS_REG(dst)) {
1319 dst_r = dst;
1320 flags |= REG_DEST;
1321 if (flags & MOVE_OP)
1322 sugg_src2_r = dst_r;
1323 }
1324 else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
1325 flags |= SLOW_DEST;
1326
1327 if (flags & IMM_OP) {
1328 if ((src2 & SLJIT_IMM) && src2w) {
1329 if ((!(flags & LOGICAL_OP) && (src2w <= SIMM_MAX && src2w >= SIMM_MIN))
1330 || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_MAX))) {
1331 flags |= SRC2_IMM;
1332 src2_r = src2w;
1333 }
1334 }
1335 if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) {
1336 if ((!(flags & LOGICAL_OP) && (src1w <= SIMM_MAX && src1w >= SIMM_MIN))
1337 || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_MAX))) {
1338 flags |= SRC2_IMM;
1339 src2_r = src1w;
1340
1341 /* And swap arguments. */
1342 src1 = src2;
1343 src1w = src2w;
1344 src2 = SLJIT_IMM;
1345 /* src2w = src2_r unneeded. */
1346 }
1347 }
1348 }
1349
1350 /* Source 1. */
1351 if (FAST_IS_REG(src1)) {
1352 src1_r = src1;
1353 flags |= REG1_SOURCE;
1354 }
1355 else if (src1 & SLJIT_IMM) {
1356 if (src1w) {
1357 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
1358 src1_r = TMP_REG1;
1359 }
1360 else
1361 src1_r = 0;
1362 }
1363 else {
1364 if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))
1365 FAIL_IF(compiler->error);
1366 else
1367 flags |= SLOW_SRC1;
1368 src1_r = TMP_REG1;
1369 }
1370
1371 /* Source 2. */
1372 if (FAST_IS_REG(src2)) {
1373 src2_r = src2;
1374 flags |= REG2_SOURCE;
1375 if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
1376 dst_r = (sljit_s32)src2_r;
1377 }
1378 else if (src2 & SLJIT_IMM) {
1379 if (!(flags & SRC2_IMM)) {
1380 if (src2w) {
1381 FAIL_IF(load_immediate(compiler, DR(sugg_src2_r), src2w));
1382 src2_r = sugg_src2_r;
1383 }
1384 else {
1385 src2_r = 0;
1386 if (flags & MOVE_OP) {
1387 if (dst & SLJIT_MEM)
1388 dst_r = 0;
1389 else
1390 op = SLJIT_MOV;
1391 }
1392 }
1393 }
1394 }
1395 else {
1396 if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w))
1397 FAIL_IF(compiler->error);
1398 else
1399 flags |= SLOW_SRC2;
1400 src2_r = sugg_src2_r;
1401 }
1402
1403 if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
1404 SLJIT_ASSERT(src2_r == TMP_REG2);
1405 if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
1406 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));
1407 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
1408 }
1409 else {
1410 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));
1411 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));
1412 }
1413 }
1414 else if (flags & SLOW_SRC1)
1415 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
1416 else if (flags & SLOW_SRC2)
1417 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w, dst, dstw));
1418
1419 FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1420
1421 if (dst & SLJIT_MEM) {
1422 if (!(flags & SLOW_DEST)) {
1423 getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);
1424 return compiler->error;
1425 }
1426 return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);
1427 }
1428
1429 return SLJIT_SUCCESS;
1430 }
1431
sljit_emit_op0(struct sljit_compiler * compiler,sljit_s32 op)1432 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1433 {
1434 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1435 sljit_s32 int_op = op & SLJIT_32;
1436 #endif
1437
1438 CHECK_ERROR();
1439 CHECK(check_sljit_emit_op0(compiler, op));
1440
1441 op = GET_OPCODE(op);
1442 switch (op) {
1443 case SLJIT_BREAKPOINT:
1444 return push_inst(compiler, BREAK, UNMOVABLE_INS);
1445 case SLJIT_NOP:
1446 return push_inst(compiler, NOP, UNMOVABLE_INS);
1447 case SLJIT_LMUL_UW:
1448 case SLJIT_LMUL_SW:
1449 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1450 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1451 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1452 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1453 #else /* !SLJIT_CONFIG_MIPS_64 */
1454 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1455 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1456 #endif /* SLJIT_CONFIG_MIPS_64 */
1457 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
1458 return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
1459 #else /* SLJIT_MIPS_REV < 6 */
1460 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1461 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1462 #else /* !SLJIT_CONFIG_MIPS_64 */
1463 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1464 #endif /* SLJIT_CONFIG_MIPS_64 */
1465 FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
1466 return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
1467 #endif /* SLJIT_MIPS_REV >= 6 */
1468 case SLJIT_DIVMOD_UW:
1469 case SLJIT_DIVMOD_SW:
1470 case SLJIT_DIV_UW:
1471 case SLJIT_DIV_SW:
1472 SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
1473 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1474 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1475 if (int_op) {
1476 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1477 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1478 }
1479 else {
1480 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1481 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1482 }
1483 #else /* !SLJIT_CONFIG_MIPS_64 */
1484 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1485 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1486 #endif /* SLJIT_CONFIG_MIPS_64 */
1487 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
1488 return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
1489 #else /* SLJIT_MIPS_REV < 6 */
1490 #if !(defined SLJIT_MIPS_REV)
1491 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
1492 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
1493 #endif /* !SLJIT_MIPS_REV */
1494 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1495 if (int_op)
1496 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1497 else
1498 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1499 #else /* !SLJIT_CONFIG_MIPS_64 */
1500 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1501 #endif /* SLJIT_CONFIG_MIPS_64 */
1502 FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
1503 return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
1504 #endif /* SLJIT_MIPS_REV >= 6 */
1505 case SLJIT_ENDBR:
1506 case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
1507 return SLJIT_SUCCESS;
1508 }
1509
1510 return SLJIT_SUCCESS;
1511 }
1512
1513 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
emit_prefetch(struct sljit_compiler * compiler,sljit_s32 src,sljit_sw srcw)1514 static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
1515 sljit_s32 src, sljit_sw srcw)
1516 {
1517 if (!(src & OFFS_REG_MASK)) {
1518 if (srcw <= SIMM_MAX && srcw >= SIMM_MIN)
1519 return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS);
1520
1521 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
1522 return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
1523 }
1524
1525 srcw &= 0x3;
1526
1527 if (SLJIT_UNLIKELY(srcw != 0)) {
1528 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1)));
1529 return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
1530 }
1531
1532 return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);
1533 }
1534 #endif /* SLJIT_MIPS_REV >= 1 */
1535
sljit_emit_op1(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)1536 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
1537 sljit_s32 dst, sljit_sw dstw,
1538 sljit_s32 src, sljit_sw srcw)
1539 {
1540 sljit_s32 flags = 0;
1541
1542 CHECK_ERROR();
1543 CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
1544 ADJUST_LOCAL_OFFSET(dst, dstw);
1545 ADJUST_LOCAL_OFFSET(src, srcw);
1546
1547 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1548 if (op & SLJIT_32)
1549 flags = INT_DATA | SIGNED_DATA;
1550 #endif
1551
1552 switch (GET_OPCODE(op)) {
1553 case SLJIT_MOV:
1554 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1555 case SLJIT_MOV_U32:
1556 case SLJIT_MOV_S32:
1557 case SLJIT_MOV32:
1558 #endif
1559 case SLJIT_MOV_P:
1560 return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);
1561
1562 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1563 case SLJIT_MOV_U32:
1564 return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw);
1565
1566 case SLJIT_MOV_S32:
1567 case SLJIT_MOV32:
1568 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);
1569 #endif
1570
1571 case SLJIT_MOV_U8:
1572 return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
1573
1574 case SLJIT_MOV_S8:
1575 return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
1576
1577 case SLJIT_MOV_U16:
1578 return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
1579
1580 case SLJIT_MOV_S16:
1581 return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
1582
1583 case SLJIT_NOT:
1584 return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1585
1586 case SLJIT_CLZ:
1587 return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1588 }
1589
1590 SLJIT_UNREACHABLE();
1591 return SLJIT_SUCCESS;
1592 }
1593
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)1594 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
1595 sljit_s32 dst, sljit_sw dstw,
1596 sljit_s32 src1, sljit_sw src1w,
1597 sljit_s32 src2, sljit_sw src2w)
1598 {
1599 sljit_s32 flags = 0;
1600
1601 CHECK_ERROR();
1602 CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
1603 ADJUST_LOCAL_OFFSET(dst, dstw);
1604 ADJUST_LOCAL_OFFSET(src1, src1w);
1605 ADJUST_LOCAL_OFFSET(src2, src2w);
1606
1607 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1608 if (op & SLJIT_32) {
1609 flags |= INT_DATA | SIGNED_DATA;
1610 if (src1 & SLJIT_IMM)
1611 src1w = (sljit_s32)src1w;
1612 if (src2 & SLJIT_IMM)
1613 src2w = (sljit_s32)src2w;
1614 }
1615 #endif
1616
1617 switch (GET_OPCODE(op)) {
1618 case SLJIT_ADD:
1619 case SLJIT_ADDC:
1620 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
1621 return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1622
1623 case SLJIT_SUB:
1624 case SLJIT_SUBC:
1625 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
1626 return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1627
1628 case SLJIT_MUL:
1629 compiler->status_flags_state = 0;
1630 return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
1631
1632 case SLJIT_AND:
1633 case SLJIT_OR:
1634 case SLJIT_XOR:
1635 return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1636
1637 case SLJIT_SHL:
1638 case SLJIT_LSHR:
1639 case SLJIT_ASHR:
1640 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1641 if (src2 & SLJIT_IMM)
1642 src2w &= 0x1f;
1643 #else
1644 if (src2 & SLJIT_IMM) {
1645 if (op & SLJIT_32)
1646 src2w &= 0x1f;
1647 else
1648 src2w &= 0x3f;
1649 }
1650 #endif
1651 return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1652 }
1653
1654 SLJIT_UNREACHABLE();
1655 return SLJIT_SUCCESS;
1656 }
1657
sljit_emit_op2u(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)1658 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
1659 sljit_s32 src1, sljit_sw src1w,
1660 sljit_s32 src2, sljit_sw src2w)
1661 {
1662 CHECK_ERROR();
1663 CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
1664
1665 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
1666 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
1667 compiler->skip_checks = 1;
1668 #endif
1669 return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
1670 }
1671
sljit_emit_op_src(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src,sljit_sw srcw)1672 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
1673 sljit_s32 src, sljit_sw srcw)
1674 {
1675 CHECK_ERROR();
1676 CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
1677 ADJUST_LOCAL_OFFSET(src, srcw);
1678
1679 switch (op) {
1680 case SLJIT_FAST_RETURN:
1681 if (FAST_IS_REG(src))
1682 FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
1683 else
1684 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
1685
1686 FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
1687 return push_inst(compiler, NOP, UNMOVABLE_INS);
1688 case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
1689 return SLJIT_SUCCESS;
1690 case SLJIT_PREFETCH_L1:
1691 case SLJIT_PREFETCH_L2:
1692 case SLJIT_PREFETCH_L3:
1693 case SLJIT_PREFETCH_ONCE:
1694 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1695 return emit_prefetch(compiler, src, srcw);
1696 #else /* SLJIT_MIPS_REV < 1 */
1697 return SLJIT_SUCCESS;
1698 #endif /* SLJIT_MIPS_REV >= 1 */
1699 }
1700
1701 return SLJIT_SUCCESS;
1702 }
1703
sljit_get_register_index(sljit_s32 reg)1704 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
1705 {
1706 CHECK_REG_INDEX(check_sljit_get_register_index(reg));
1707 return reg_map[reg];
1708 }
1709
sljit_get_float_register_index(sljit_s32 reg)1710 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
1711 {
1712 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
1713 return FR(reg);
1714 }
1715
sljit_emit_op_custom(struct sljit_compiler * compiler,void * instruction,sljit_u32 size)1716 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
1717 void *instruction, sljit_u32 size)
1718 {
1719 CHECK_ERROR();
1720 CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
1721
1722 return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);
1723 }
1724
1725 /* --------------------------------------------------------------------- */
1726 /* Floating point operators */
1727 /* --------------------------------------------------------------------- */
1728
1729 #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
1730 #define FMT(op) ((((sljit_ins)op & SLJIT_32) ^ SLJIT_32) << (21 - 8))
1731
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)1732 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
1733 sljit_s32 dst, sljit_sw dstw,
1734 sljit_s32 src, sljit_sw srcw)
1735 {
1736 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1737 # define flags (sljit_u32)0
1738 #else
1739 sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;
1740 #endif
1741
1742 if (src & SLJIT_MEM) {
1743 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
1744 src = TMP_FREG1;
1745 }
1746
1747 FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
1748
1749 if (FAST_IS_REG(dst))
1750 return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS);
1751
1752 /* Store the integer value from a VFP register. */
1753 return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);
1754
1755 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1756 # undef is_long
1757 #endif
1758 }
1759
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)1760 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
1761 sljit_s32 dst, sljit_sw dstw,
1762 sljit_s32 src, sljit_sw srcw)
1763 {
1764 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1765 # define flags (sljit_u32)0
1766 #else
1767 sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21;
1768 #endif
1769
1770 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1771
1772 if (FAST_IS_REG(src))
1773 FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
1774 else if (src & SLJIT_MEM) {
1775 /* Load the integer value into a VFP register. */
1776 FAIL_IF(emit_op_mem2(compiler, ((flags) ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
1777 }
1778 else {
1779 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1780 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
1781 srcw = (sljit_s32)srcw;
1782 #endif
1783 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
1784 FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
1785 }
1786
1787 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));
1788
1789 if (dst & SLJIT_MEM)
1790 return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
1791 return SLJIT_SUCCESS;
1792
1793 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1794 # undef flags
1795 #endif
1796 }
1797
sljit_emit_fop1_cmp(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)1798 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
1799 sljit_s32 src1, sljit_sw src1w,
1800 sljit_s32 src2, sljit_sw src2w)
1801 {
1802 sljit_ins inst;
1803
1804 if (src1 & SLJIT_MEM) {
1805 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
1806 src1 = TMP_FREG1;
1807 }
1808
1809 if (src2 & SLJIT_MEM) {
1810 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));
1811 src2 = TMP_FREG2;
1812 }
1813
1814 switch (GET_FLAG_TYPE(op)) {
1815 case SLJIT_EQUAL_F64:
1816 case SLJIT_NOT_EQUAL_F64:
1817 inst = C_UEQ_S;
1818 break;
1819 case SLJIT_LESS_F64:
1820 case SLJIT_GREATER_EQUAL_F64:
1821 inst = C_ULT_S;
1822 break;
1823 case SLJIT_GREATER_F64:
1824 case SLJIT_LESS_EQUAL_F64:
1825 inst = C_ULE_S;
1826 break;
1827 default:
1828 SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED_F64 || GET_FLAG_TYPE(op) == SLJIT_ORDERED_F64);
1829 inst = C_UN_S;
1830 break;
1831 }
1832 return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1) | C_FD, UNMOVABLE_INS);
1833 }
1834
sljit_emit_fop1(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)1835 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
1836 sljit_s32 dst, sljit_sw dstw,
1837 sljit_s32 src, sljit_sw srcw)
1838 {
1839 sljit_s32 dst_r;
1840
1841 CHECK_ERROR();
1842 compiler->cache_arg = 0;
1843 compiler->cache_argw = 0;
1844
1845 SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
1846 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
1847
1848 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
1849 op ^= SLJIT_32;
1850
1851 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1852
1853 if (src & SLJIT_MEM) {
1854 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));
1855 src = dst_r;
1856 }
1857
1858 switch (GET_OPCODE(op)) {
1859 case SLJIT_MOV_F64:
1860 if (src != dst_r) {
1861 if (dst_r != TMP_FREG1)
1862 FAIL_IF(push_inst(compiler, MOV_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
1863 else
1864 dst_r = src;
1865 }
1866 break;
1867 case SLJIT_NEG_F64:
1868 FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
1869 break;
1870 case SLJIT_ABS_F64:
1871 FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
1872 break;
1873 case SLJIT_CONV_F64_FROM_F32:
1874 FAIL_IF(push_inst(compiler, CVT_S_S | (sljit_ins)((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));
1875 op ^= SLJIT_32;
1876 break;
1877 }
1878
1879 if (dst & SLJIT_MEM)
1880 return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);
1881 return SLJIT_SUCCESS;
1882 }
1883
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)1884 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
1885 sljit_s32 dst, sljit_sw dstw,
1886 sljit_s32 src1, sljit_sw src1w,
1887 sljit_s32 src2, sljit_sw src2w)
1888 {
1889 sljit_s32 dst_r, flags = 0;
1890
1891 CHECK_ERROR();
1892 CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
1893 ADJUST_LOCAL_OFFSET(dst, dstw);
1894 ADJUST_LOCAL_OFFSET(src1, src1w);
1895 ADJUST_LOCAL_OFFSET(src2, src2w);
1896
1897 compiler->cache_arg = 0;
1898 compiler->cache_argw = 0;
1899
1900 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
1901
1902 if (src1 & SLJIT_MEM) {
1903 if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {
1904 FAIL_IF(compiler->error);
1905 src1 = TMP_FREG1;
1906 } else
1907 flags |= SLOW_SRC1;
1908 }
1909
1910 if (src2 & SLJIT_MEM) {
1911 if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {
1912 FAIL_IF(compiler->error);
1913 src2 = TMP_FREG2;
1914 } else
1915 flags |= SLOW_SRC2;
1916 }
1917
1918 if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
1919 if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
1920 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));
1921 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
1922 }
1923 else {
1924 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
1925 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
1926 }
1927 }
1928 else if (flags & SLOW_SRC1)
1929 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
1930 else if (flags & SLOW_SRC2)
1931 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
1932
1933 if (flags & SLOW_SRC1)
1934 src1 = TMP_FREG1;
1935 if (flags & SLOW_SRC2)
1936 src2 = TMP_FREG2;
1937
1938 switch (GET_OPCODE(op)) {
1939 case SLJIT_ADD_F64:
1940 FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
1941 break;
1942
1943 case SLJIT_SUB_F64:
1944 FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
1945 break;
1946
1947 case SLJIT_MUL_F64:
1948 FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
1949 break;
1950
1951 case SLJIT_DIV_F64:
1952 FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
1953 break;
1954 }
1955
1956 if (dst_r == TMP_FREG2)
1957 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));
1958
1959 return SLJIT_SUCCESS;
1960 }
1961
1962 /* --------------------------------------------------------------------- */
1963 /* Other instructions */
1964 /* --------------------------------------------------------------------- */
1965
sljit_emit_fast_enter(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw)1966 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
1967 {
1968 CHECK_ERROR();
1969 CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
1970 ADJUST_LOCAL_OFFSET(dst, dstw);
1971
1972 if (FAST_IS_REG(dst))
1973 return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);
1974
1975 /* Memory. */
1976 FAIL_IF(emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw));
1977 compiler->delay_slot = UNMOVABLE_INS;
1978 return SLJIT_SUCCESS;
1979 }
1980
1981 /* --------------------------------------------------------------------- */
1982 /* Conditional instructions */
1983 /* --------------------------------------------------------------------- */
1984
sljit_emit_label(struct sljit_compiler * compiler)1985 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
1986 {
1987 struct sljit_label *label;
1988
1989 CHECK_ERROR_PTR();
1990 CHECK_PTR(check_sljit_emit_label(compiler));
1991
1992 if (compiler->last_label && compiler->last_label->size == compiler->size)
1993 return compiler->last_label;
1994
1995 label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
1996 PTR_FAIL_IF(!label);
1997 set_label(label, compiler);
1998 compiler->delay_slot = UNMOVABLE_INS;
1999 return label;
2000 }
2001
2002 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2003 #define JUMP_LENGTH 4
2004 #else
2005 #define JUMP_LENGTH 8
2006 #endif
2007
2008 #define BR_Z(src) \
2009 inst = BEQ | SA(src) | TA(0) | JUMP_LENGTH; \
2010 flags = IS_BIT26_COND; \
2011 delay_check = src;
2012
2013 #define BR_NZ(src) \
2014 inst = BNE | SA(src) | TA(0) | JUMP_LENGTH; \
2015 flags = IS_BIT26_COND; \
2016 delay_check = src;
2017
2018 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2019
2020 #define BR_T() \
2021 inst = BC1NEZ; \
2022 flags = IS_BIT23_COND; \
2023 delay_check = FCSR_FCC;
2024 #define BR_F() \
2025 inst = BC1EQZ; \
2026 flags = IS_BIT23_COND; \
2027 delay_check = FCSR_FCC;
2028
2029 #else /* SLJIT_MIPS_REV < 6 */
2030
2031 #define BR_T() \
2032 inst = BC1T | JUMP_LENGTH; \
2033 flags = IS_BIT16_COND; \
2034 delay_check = FCSR_FCC;
2035 #define BR_F() \
2036 inst = BC1F | JUMP_LENGTH; \
2037 flags = IS_BIT16_COND; \
2038 delay_check = FCSR_FCC;
2039
2040 #endif /* SLJIT_MIPS_REV >= 6 */
2041
sljit_emit_jump(struct sljit_compiler * compiler,sljit_s32 type)2042 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
2043 {
2044 struct sljit_jump *jump;
2045 sljit_ins inst;
2046 sljit_u32 flags = 0;
2047 sljit_s32 delay_check = UNMOVABLE_INS;
2048
2049 CHECK_ERROR_PTR();
2050 CHECK_PTR(check_sljit_emit_jump(compiler, type));
2051
2052 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2053 PTR_FAIL_IF(!jump);
2054 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
2055 type &= 0xff;
2056
2057 switch (type) {
2058 case SLJIT_EQUAL:
2059 BR_NZ(EQUAL_FLAG);
2060 break;
2061 case SLJIT_NOT_EQUAL:
2062 BR_Z(EQUAL_FLAG);
2063 break;
2064 case SLJIT_LESS:
2065 case SLJIT_GREATER:
2066 case SLJIT_SIG_LESS:
2067 case SLJIT_SIG_GREATER:
2068 case SLJIT_OVERFLOW:
2069 case SLJIT_CARRY:
2070 BR_Z(OTHER_FLAG);
2071 break;
2072 case SLJIT_GREATER_EQUAL:
2073 case SLJIT_LESS_EQUAL:
2074 case SLJIT_SIG_GREATER_EQUAL:
2075 case SLJIT_SIG_LESS_EQUAL:
2076 case SLJIT_NOT_OVERFLOW:
2077 case SLJIT_NOT_CARRY:
2078 BR_NZ(OTHER_FLAG);
2079 break;
2080 case SLJIT_NOT_EQUAL_F64:
2081 case SLJIT_GREATER_EQUAL_F64:
2082 case SLJIT_GREATER_F64:
2083 case SLJIT_ORDERED_F64:
2084 BR_T();
2085 break;
2086 case SLJIT_EQUAL_F64:
2087 case SLJIT_LESS_F64:
2088 case SLJIT_LESS_EQUAL_F64:
2089 case SLJIT_UNORDERED_F64:
2090 BR_F();
2091 break;
2092 default:
2093 /* Not conditional branch. */
2094 inst = 0;
2095 break;
2096 }
2097
2098 jump->flags |= flags;
2099 if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))
2100 jump->flags |= IS_MOVABLE;
2101
2102 if (inst)
2103 PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));
2104
2105 PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
2106
2107 if (type <= SLJIT_JUMP)
2108 PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
2109 else {
2110 jump->flags |= IS_JAL;
2111 PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
2112 }
2113
2114 jump->addr = compiler->size;
2115 PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2116 return jump;
2117 }
2118
2119 #define RESOLVE_IMM1() \
2120 if (src1 & SLJIT_IMM) { \
2121 if (src1w) { \
2122 PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \
2123 src1 = TMP_REG1; \
2124 } \
2125 else \
2126 src1 = 0; \
2127 }
2128
2129 #define RESOLVE_IMM2() \
2130 if (src2 & SLJIT_IMM) { \
2131 if (src2w) { \
2132 PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG2), src2w)); \
2133 src2 = TMP_REG2; \
2134 } \
2135 else \
2136 src2 = 0; \
2137 }
2138
sljit_emit_cmp(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2139 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
2140 sljit_s32 src1, sljit_sw src1w,
2141 sljit_s32 src2, sljit_sw src2w)
2142 {
2143 struct sljit_jump *jump;
2144 sljit_s32 flags;
2145 sljit_ins inst;
2146
2147 CHECK_ERROR_PTR();
2148 CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
2149 ADJUST_LOCAL_OFFSET(src1, src1w);
2150 ADJUST_LOCAL_OFFSET(src2, src2w);
2151
2152 compiler->cache_arg = 0;
2153 compiler->cache_argw = 0;
2154 flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
2155 if (src1 & SLJIT_MEM) {
2156 PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));
2157 src1 = TMP_REG1;
2158 }
2159 if (src2 & SLJIT_MEM) {
2160 PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG2), src2, src2w, 0, 0));
2161 src2 = TMP_REG2;
2162 }
2163
2164 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2165 PTR_FAIL_IF(!jump);
2166 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
2167 type &= 0xff;
2168
2169 if (type <= SLJIT_NOT_EQUAL) {
2170 RESOLVE_IMM1();
2171 RESOLVE_IMM2();
2172 jump->flags |= IS_BIT26_COND;
2173 if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))
2174 jump->flags |= IS_MOVABLE;
2175 PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | JUMP_LENGTH, UNMOVABLE_INS));
2176 }
2177 else if (type >= SLJIT_SIG_LESS && (((src1 & SLJIT_IMM) && (src1w == 0)) || ((src2 & SLJIT_IMM) && (src2w == 0)))) {
2178 inst = NOP;
2179 if ((src1 & SLJIT_IMM) && (src1w == 0)) {
2180 RESOLVE_IMM2();
2181 switch (type) {
2182 case SLJIT_SIG_LESS:
2183 inst = BLEZ;
2184 jump->flags |= IS_BIT26_COND;
2185 break;
2186 case SLJIT_SIG_GREATER_EQUAL:
2187 inst = BGTZ;
2188 jump->flags |= IS_BIT26_COND;
2189 break;
2190 case SLJIT_SIG_GREATER:
2191 inst = BGEZ;
2192 jump->flags |= IS_BIT16_COND;
2193 break;
2194 case SLJIT_SIG_LESS_EQUAL:
2195 inst = BLTZ;
2196 jump->flags |= IS_BIT16_COND;
2197 break;
2198 }
2199 src1 = src2;
2200 }
2201 else {
2202 RESOLVE_IMM1();
2203 switch (type) {
2204 case SLJIT_SIG_LESS:
2205 inst = BGEZ;
2206 jump->flags |= IS_BIT16_COND;
2207 break;
2208 case SLJIT_SIG_GREATER_EQUAL:
2209 inst = BLTZ;
2210 jump->flags |= IS_BIT16_COND;
2211 break;
2212 case SLJIT_SIG_GREATER:
2213 inst = BLEZ;
2214 jump->flags |= IS_BIT26_COND;
2215 break;
2216 case SLJIT_SIG_LESS_EQUAL:
2217 inst = BGTZ;
2218 jump->flags |= IS_BIT26_COND;
2219 break;
2220 }
2221 }
2222 PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | JUMP_LENGTH, UNMOVABLE_INS));
2223 }
2224 else {
2225 if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) {
2226 RESOLVE_IMM1();
2227 if ((src2 & SLJIT_IMM) && src2w <= SIMM_MAX && src2w >= SIMM_MIN)
2228 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));
2229 else {
2230 RESOLVE_IMM2();
2231 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));
2232 }
2233 type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
2234 }
2235 else {
2236 RESOLVE_IMM2();
2237 if ((src1 & SLJIT_IMM) && src1w <= SIMM_MAX && src1w >= SIMM_MIN)
2238 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));
2239 else {
2240 RESOLVE_IMM1();
2241 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));
2242 }
2243 type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
2244 }
2245
2246 jump->flags |= IS_BIT26_COND;
2247 PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | JUMP_LENGTH, UNMOVABLE_INS));
2248 }
2249
2250 PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
2251 PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
2252 jump->addr = compiler->size;
2253 PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2254 return jump;
2255 }
2256
2257 #undef RESOLVE_IMM1
2258 #undef RESOLVE_IMM2
2259
2260 #undef JUMP_LENGTH
2261 #undef BR_Z
2262 #undef BR_NZ
2263 #undef BR_T
2264 #undef BR_F
2265
2266 #undef FLOAT_DATA
2267 #undef FMT
2268
sljit_emit_ijump(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 src,sljit_sw srcw)2269 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2270 {
2271 struct sljit_jump *jump = NULL;
2272
2273 CHECK_ERROR();
2274 CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2275 ADJUST_LOCAL_OFFSET(src, srcw);
2276
2277 if (src & SLJIT_IMM) {
2278 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2279 FAIL_IF(!jump);
2280 set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));
2281 jump->u.target = (sljit_uw)srcw;
2282
2283 if (compiler->delay_slot != UNMOVABLE_INS)
2284 jump->flags |= IS_MOVABLE;
2285
2286 FAIL_IF(emit_const(compiler, TMP_REG2, 0));
2287 src = TMP_REG2;
2288 }
2289 else if (src & SLJIT_MEM) {
2290 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src, srcw));
2291 src = TMP_REG2;
2292 }
2293
2294 FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));
2295 if (jump)
2296 jump->addr = compiler->size;
2297 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2298 return SLJIT_SUCCESS;
2299 }
2300
sljit_emit_op_flags(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 type)2301 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
2302 sljit_s32 dst, sljit_sw dstw,
2303 sljit_s32 type)
2304 {
2305 sljit_s32 src_ar, dst_ar;
2306 sljit_s32 saved_op = op;
2307 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2308 sljit_s32 mem_type = WORD_DATA;
2309 #else
2310 sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
2311 #endif
2312
2313 CHECK_ERROR();
2314 CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
2315 ADJUST_LOCAL_OFFSET(dst, dstw);
2316
2317 op = GET_OPCODE(op);
2318 dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
2319
2320 compiler->cache_arg = 0;
2321 compiler->cache_argw = 0;
2322
2323 if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
2324 FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));
2325
2326 switch (type & 0xff) {
2327 case SLJIT_EQUAL:
2328 case SLJIT_NOT_EQUAL:
2329 FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
2330 src_ar = dst_ar;
2331 break;
2332 case SLJIT_OVERFLOW:
2333 case SLJIT_NOT_OVERFLOW:
2334 if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {
2335 src_ar = OTHER_FLAG;
2336 break;
2337 }
2338 FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
2339 src_ar = dst_ar;
2340 type ^= 0x1; /* Flip type bit for the XORI below. */
2341 break;
2342 case SLJIT_GREATER_F64:
2343 case SLJIT_LESS_EQUAL_F64:
2344 type ^= 0x1; /* Flip type bit for the XORI below. */
2345 /* fallthrough */
2346 case SLJIT_EQUAL_F64:
2347 case SLJIT_NOT_EQUAL_F64:
2348 case SLJIT_LESS_F64:
2349 case SLJIT_GREATER_EQUAL_F64:
2350 case SLJIT_UNORDERED_F64:
2351 case SLJIT_ORDERED_F64:
2352 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2353 FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));
2354 #else /* SLJIT_MIPS_REV < 6 */
2355 FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));
2356 #endif /* SLJIT_MIPS_REV >= 6 */
2357 FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));
2358 FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));
2359 src_ar = dst_ar;
2360 break;
2361
2362 default:
2363 src_ar = OTHER_FLAG;
2364 break;
2365 }
2366
2367 if (type & 0x1) {
2368 FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar));
2369 src_ar = dst_ar;
2370 }
2371
2372 if (op < SLJIT_ADD) {
2373 if (dst & SLJIT_MEM)
2374 return emit_op_mem(compiler, mem_type, src_ar, dst, dstw);
2375
2376 if (src_ar != dst_ar)
2377 return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar);
2378 return SLJIT_SUCCESS;
2379 }
2380
2381 /* OTHER_FLAG cannot be specified as src2 argument at the moment. */
2382 if (DR(TMP_REG2) != src_ar)
2383 FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
2384
2385 mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE;
2386
2387 if (dst & SLJIT_MEM)
2388 return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
2389 return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0);
2390 }
2391
sljit_emit_cmov(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 dst_reg,sljit_s32 src,sljit_sw srcw)2392 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
2393 sljit_s32 dst_reg,
2394 sljit_s32 src, sljit_sw srcw)
2395 {
2396 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
2397 sljit_ins ins;
2398 #endif /* SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6 */
2399
2400 CHECK_ERROR();
2401 CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
2402
2403 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
2404
2405 if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
2406 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2407 if (dst_reg & SLJIT_32)
2408 srcw = (sljit_s32)srcw;
2409 #endif
2410 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
2411 src = TMP_REG1;
2412 srcw = 0;
2413 }
2414
2415 dst_reg &= ~SLJIT_32;
2416
2417 switch (type & 0xff) {
2418 case SLJIT_EQUAL:
2419 ins = MOVZ | TA(EQUAL_FLAG);
2420 break;
2421 case SLJIT_NOT_EQUAL:
2422 ins = MOVN | TA(EQUAL_FLAG);
2423 break;
2424 case SLJIT_LESS:
2425 case SLJIT_GREATER:
2426 case SLJIT_SIG_LESS:
2427 case SLJIT_SIG_GREATER:
2428 case SLJIT_OVERFLOW:
2429 ins = MOVN | TA(OTHER_FLAG);
2430 break;
2431 case SLJIT_GREATER_EQUAL:
2432 case SLJIT_LESS_EQUAL:
2433 case SLJIT_SIG_GREATER_EQUAL:
2434 case SLJIT_SIG_LESS_EQUAL:
2435 case SLJIT_NOT_OVERFLOW:
2436 ins = MOVZ | TA(OTHER_FLAG);
2437 break;
2438 case SLJIT_EQUAL_F64:
2439 case SLJIT_LESS_F64:
2440 case SLJIT_LESS_EQUAL_F64:
2441 case SLJIT_UNORDERED_F64:
2442 ins = MOVT;
2443 break;
2444 case SLJIT_NOT_EQUAL_F64:
2445 case SLJIT_GREATER_EQUAL_F64:
2446 case SLJIT_GREATER_F64:
2447 case SLJIT_ORDERED_F64:
2448 ins = MOVF;
2449 break;
2450 default:
2451 ins = MOVZ | TA(OTHER_FLAG);
2452 SLJIT_UNREACHABLE();
2453 break;
2454 }
2455
2456 return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg));
2457
2458 #else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */
2459 return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
2460 #endif /* SLJIT_MIPS_REV >= 1 */
2461 }
2462
sljit_emit_const(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw,sljit_sw init_value)2463 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
2464 {
2465 struct sljit_const *const_;
2466 sljit_s32 dst_r;
2467
2468 CHECK_ERROR_PTR();
2469 CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
2470 ADJUST_LOCAL_OFFSET(dst, dstw);
2471
2472 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
2473 PTR_FAIL_IF(!const_);
2474 set_const(const_, compiler);
2475
2476 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2477 PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
2478
2479 if (dst & SLJIT_MEM)
2480 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2481
2482 return const_;
2483 }
2484
sljit_emit_put_label(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw)2485 SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2486 {
2487 struct sljit_put_label *put_label;
2488 sljit_s32 dst_r;
2489
2490 CHECK_ERROR_PTR();
2491 CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
2492 ADJUST_LOCAL_OFFSET(dst, dstw);
2493
2494 put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
2495 PTR_FAIL_IF(!put_label);
2496 set_put_label(put_label, compiler, 0);
2497
2498 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2499 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2500 PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
2501 #else
2502 PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r, UNMOVABLE_INS));
2503 compiler->size += 5;
2504 #endif
2505
2506 if (dst & SLJIT_MEM)
2507 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2508
2509 return put_label;
2510 }
2511