Fix test50 alignment
[sljit.git] / sljit_src / sljitNativeMIPS_common.c
blobcb737a012c95b2a83a3f1c2dfe3818cbeb3939ca
1 /*
2 * Stack-less Just-In-Time compiler
4 * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
6 * Redistribution and use in source and binary forms, with or without modification, are
7 * permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice, this list of
10 * conditions and the following disclaimer.
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.
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.
27 /* Latest MIPS architecture. */
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
35 SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
37 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
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 */
45 #elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
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 */
53 #else /* SLJIT_MIPS_REV < 1 */
54 return "MIPS III" SLJIT_CPUINFO;
55 #endif /* SLJIT_MIPS_REV >= 6 */
58 /* Length of an instruction word
59 Both for mips-32 and mips-64 */
60 typedef sljit_u32 sljit_ins;
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)
66 /* For position independent code, t9 must contain the function address. */
67 #define PIC_ADDR_REG TMP_REG2
69 /* Floating point status register. */
70 #define FCSR_REG 31
71 /* Return address register. */
72 #define RETURN_ADDR_REG 31
74 /* Flags are kept in volatile registers. */
75 #define EQUAL_FLAG 3
76 #define OTHER_FLAG 1
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)
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
86 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
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
92 #else
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
98 #endif
100 /* --------------------------------------------------------------------- */
101 /* Instrucion forms */
102 /* --------------------------------------------------------------------- */
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)
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)
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_EQ_S (HI(17) | CMP_FMT_S | LO(2))
155 #define C_OLE_S (HI(17) | CMP_FMT_S | LO(6))
156 #define C_OLT_S (HI(17) | CMP_FMT_S | LO(4))
157 #define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3))
158 #define C_ULE_S (HI(17) | CMP_FMT_S | LO(7))
159 #define C_ULT_S (HI(17) | CMP_FMT_S | LO(5))
160 #define C_UN_S (HI(17) | CMP_FMT_S | LO(1))
161 #define C_FD (FD(TMP_FREG3))
162 #else /* SLJIT_MIPS_REV < 6 */
163 #define C_EQ_S (HI(17) | FMT_S | LO(50))
164 #define C_OLE_S (HI(17) | FMT_S | LO(54))
165 #define C_OLT_S (HI(17) | FMT_S | LO(52))
166 #define C_UEQ_S (HI(17) | FMT_S | LO(51))
167 #define C_ULE_S (HI(17) | FMT_S | LO(55))
168 #define C_ULT_S (HI(17) | FMT_S | LO(53))
169 #define C_UN_S (HI(17) | FMT_S | LO(49))
170 #define C_FD (0)
171 #endif /* SLJIT_MIPS_REV >= 6 */
172 #define CVT_S_S (HI(17) | FMT_S | LO(32))
173 #define DADDIU (HI(25))
174 #define DADDU (HI(0) | LO(45))
175 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
176 #define DDIV (HI(0) | (2 << 6) | LO(30))
177 #define DDIVU (HI(0) | (2 << 6) | LO(31))
178 #define DMOD (HI(0) | (3 << 6) | LO(30))
179 #define DMODU (HI(0) | (3 << 6) | LO(31))
180 #define DIV (HI(0) | (2 << 6) | LO(26))
181 #define DIVU (HI(0) | (2 << 6) | LO(27))
182 #define DMUH (HI(0) | (3 << 6) | LO(28))
183 #define DMUHU (HI(0) | (3 << 6) | LO(29))
184 #define DMUL (HI(0) | (2 << 6) | LO(28))
185 #define DMULU (HI(0) | (2 << 6) | LO(29))
186 #else /* SLJIT_MIPS_REV < 6 */
187 #define DDIV (HI(0) | LO(30))
188 #define DDIVU (HI(0) | LO(31))
189 #define DIV (HI(0) | LO(26))
190 #define DIVU (HI(0) | LO(27))
191 #define DMULT (HI(0) | LO(28))
192 #define DMULTU (HI(0) | LO(29))
193 #endif /* SLJIT_MIPS_REV >= 6 */
194 #define DIV_S (HI(17) | FMT_S | LO(3))
195 #define DINSU (HI(31) | LO(6))
196 #define DSLL (HI(0) | LO(56))
197 #define DSLL32 (HI(0) | LO(60))
198 #define DSLLV (HI(0) | LO(20))
199 #define DSRA (HI(0) | LO(59))
200 #define DSRA32 (HI(0) | LO(63))
201 #define DSRAV (HI(0) | LO(23))
202 #define DSRL (HI(0) | LO(58))
203 #define DSRL32 (HI(0) | LO(62))
204 #define DSRLV (HI(0) | LO(22))
205 #define DSUBU (HI(0) | LO(47))
206 #define J (HI(2))
207 #define JAL (HI(3))
208 #define JALR (HI(0) | LO(9))
209 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
210 #define JR (HI(0) | LO(9))
211 #else /* SLJIT_MIPS_REV < 6 */
212 #define JR (HI(0) | LO(8))
213 #endif /* SLJIT_MIPS_REV >= 6 */
214 #define LD (HI(55))
215 #define LDL (HI(26))
216 #define LDR (HI(27))
217 #define LDC1 (HI(53))
218 #define LUI (HI(15))
219 #define LW (HI(35))
220 #define LWL (HI(34))
221 #define LWR (HI(38))
222 #define LWC1 (HI(49))
223 #define MFC1 (HI(17))
224 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
225 #define MOD (HI(0) | (3 << 6) | LO(26))
226 #define MODU (HI(0) | (3 << 6) | LO(27))
227 #else /* SLJIT_MIPS_REV < 6 */
228 #define MFHI (HI(0) | LO(16))
229 #define MFLO (HI(0) | LO(18))
230 #endif /* SLJIT_MIPS_REV >= 6 */
231 #define MOV_S (HI(17) | FMT_S | LO(6))
232 #define MTC1 (HI(17) | (4 << 21))
233 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
234 #define MUH (HI(0) | (3 << 6) | LO(24))
235 #define MUHU (HI(0) | (3 << 6) | LO(25))
236 #define MUL (HI(0) | (2 << 6) | LO(24))
237 #define MULU (HI(0) | (2 << 6) | LO(25))
238 #else /* SLJIT_MIPS_REV < 6 */
239 #define MULT (HI(0) | LO(24))
240 #define MULTU (HI(0) | LO(25))
241 #endif /* SLJIT_MIPS_REV >= 6 */
242 #define MUL_S (HI(17) | FMT_S | LO(2))
243 #define NEG_S (HI(17) | FMT_S | LO(7))
244 #define NOP (HI(0) | LO(0))
245 #define NOR (HI(0) | LO(39))
246 #define OR (HI(0) | LO(37))
247 #define ORI (HI(13))
248 #define SD (HI(63))
249 #define SDL (HI(44))
250 #define SDR (HI(45))
251 #define SDC1 (HI(61))
252 #define SLT (HI(0) | LO(42))
253 #define SLTI (HI(10))
254 #define SLTIU (HI(11))
255 #define SLTU (HI(0) | LO(43))
256 #define SLL (HI(0) | LO(0))
257 #define SLLV (HI(0) | LO(4))
258 #define SRL (HI(0) | LO(2))
259 #define SRLV (HI(0) | LO(6))
260 #define SRA (HI(0) | LO(3))
261 #define SRAV (HI(0) | LO(7))
262 #define SUB_S (HI(17) | FMT_S | LO(1))
263 #define SUBU (HI(0) | LO(35))
264 #define SW (HI(43))
265 #define SWL (HI(42))
266 #define SWR (HI(46))
267 #define SWC1 (HI(57))
268 #define TRUNC_W_S (HI(17) | FMT_S | LO(13))
269 #define XOR (HI(0) | LO(38))
270 #define XORI (HI(14))
272 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
273 #define CLZ (HI(28) | LO(32))
274 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
275 #define DCLZ (LO(18))
276 #else /* SLJIT_MIPS_REV < 6 */
277 #define DCLZ (HI(28) | LO(36))
278 #define MOVF (HI(0) | (0 << 16) | LO(1))
279 #define MOVN (HI(0) | LO(11))
280 #define MOVT (HI(0) | (1 << 16) | LO(1))
281 #define MOVZ (HI(0) | LO(10))
282 #define MUL (HI(28) | LO(2))
283 #endif /* SLJIT_MIPS_REV >= 6 */
284 #define PREF (HI(51))
285 #define PREFX (HI(19) | LO(15))
286 #define SEB (HI(31) | (16 << 6) | LO(32))
287 #define SEH (HI(31) | (24 << 6) | LO(32))
288 #endif /* SLJIT_MIPS_REV >= 1 */
290 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
291 #define ADDU_W ADDU
292 #define ADDIU_W ADDIU
293 #define SLL_W SLL
294 #define SRA_W SRA
295 #define SUBU_W SUBU
296 #else
297 #define ADDU_W DADDU
298 #define ADDIU_W DADDIU
299 #define SLL_W DSLL
300 #define SRA_W DSRA
301 #define SUBU_W DSUBU
302 #endif
304 #define SIMM_MAX (0x7fff)
305 #define SIMM_MIN (-0x8000)
306 #define UIMM_MAX (0xffff)
308 /* dest_reg is the absolute name of the register
309 Useful for reordering instructions in the delay slot. */
310 static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)
312 sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
313 SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS
314 || (sljit_ins)delay_slot == ((ins >> 11) & 0x1f)
315 || (sljit_ins)delay_slot == ((ins >> 16) & 0x1f));
316 FAIL_IF(!ptr);
317 *ptr = ins;
318 compiler->size++;
319 compiler->delay_slot = delay_slot;
320 return SLJIT_SUCCESS;
323 static SLJIT_INLINE sljit_ins invert_branch(sljit_uw flags)
325 if (flags & IS_BIT26_COND)
326 return (1 << 26);
327 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
328 if (flags & IS_BIT23_COND)
329 return (1 << 23);
330 #endif /* SLJIT_MIPS_REV >= 6 */
331 return (1 << 16);
334 static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
336 sljit_sw diff;
337 sljit_uw target_addr;
338 sljit_ins *inst;
339 sljit_ins saved_inst;
341 inst = (sljit_ins *)jump->addr;
343 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
344 if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
345 goto exit;
346 #else
347 if (jump->flags & SLJIT_REWRITABLE_JUMP)
348 goto exit;
349 #endif
351 if (jump->flags & JUMP_ADDR)
352 target_addr = jump->u.target;
353 else {
354 SLJIT_ASSERT(jump->flags & JUMP_LABEL);
355 target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
358 if (jump->flags & IS_COND)
359 inst--;
361 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
362 if (jump->flags & IS_CALL)
363 goto preserve_addr;
364 #endif
366 /* B instructions. */
367 if (jump->flags & IS_MOVABLE) {
368 diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;
369 if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
370 jump->flags |= PATCH_B;
372 if (!(jump->flags & IS_COND)) {
373 inst[0] = inst[-1];
374 inst[-1] = (jump->flags & IS_JAL) ? BAL : B;
375 jump->addr -= sizeof(sljit_ins);
376 return inst;
378 saved_inst = inst[0];
379 inst[0] = inst[-1];
380 inst[-1] = saved_inst ^ invert_branch(jump->flags);
381 jump->addr -= 2 * sizeof(sljit_ins);
382 return inst;
385 else {
386 diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;
387 if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
388 jump->flags |= PATCH_B;
390 if (!(jump->flags & IS_COND)) {
391 inst[0] = (jump->flags & IS_JAL) ? BAL : B;
392 inst[1] = NOP;
393 return inst + 1;
395 inst[0] ^= invert_branch(jump->flags);
396 inst[1] = NOP;
397 jump->addr -= sizeof(sljit_ins);
398 return inst + 1;
402 if (jump->flags & IS_COND) {
403 if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
404 jump->flags |= PATCH_J;
405 saved_inst = inst[0];
406 inst[0] = inst[-1];
407 inst[-1] = (saved_inst & 0xffff0000) | 3;
408 inst[1] = J;
409 inst[2] = NOP;
410 return inst + 2;
412 else if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
413 jump->flags |= PATCH_J;
414 inst[0] = (inst[0] & 0xffff0000) | 3;
415 inst[1] = NOP;
416 inst[2] = J;
417 inst[3] = NOP;
418 jump->addr += sizeof(sljit_ins);
419 return inst + 3;
422 else {
423 /* J instuctions. */
424 if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == (jump->addr & ~(sljit_uw)0xfffffff)) {
425 jump->flags |= PATCH_J;
426 inst[0] = inst[-1];
427 inst[-1] = (jump->flags & IS_JAL) ? JAL : J;
428 jump->addr -= sizeof(sljit_ins);
429 return inst;
432 if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
433 jump->flags |= PATCH_J;
434 inst[0] = (jump->flags & IS_JAL) ? JAL : J;
435 inst[1] = NOP;
436 return inst + 1;
440 if (jump->flags & IS_COND)
441 inst++;
443 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
444 preserve_addr:
445 if (target_addr <= 0x7fffffff) {
446 jump->flags |= PATCH_ABS32;
447 if (jump->flags & IS_COND)
448 inst[-1] -= 4;
450 inst[2] = inst[0];
451 inst[3] = inst[1];
452 return inst + 3;
454 if (target_addr <= 0x7fffffffffffl) {
455 jump->flags |= PATCH_ABS48;
456 if (jump->flags & IS_COND)
457 inst[-1] -= 2;
459 inst[4] = inst[0];
460 inst[5] = inst[1];
461 return inst + 5;
463 #endif
465 exit:
466 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
467 inst[2] = inst[0];
468 inst[3] = inst[1];
469 return inst + 3;
470 #else
471 inst[6] = inst[0];
472 inst[7] = inst[1];
473 return inst + 7;
474 #endif
477 #ifdef __GNUC__
478 static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr)
480 SLJIT_CACHE_FLUSH(code, code_ptr);
482 #endif
484 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
486 static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
488 if (max_label < 0x80000000l) {
489 put_label->flags = PATCH_ABS32;
490 return 1;
493 if (max_label < 0x800000000000l) {
494 put_label->flags = PATCH_ABS48;
495 return 3;
498 put_label->flags = 0;
499 return 5;
502 #endif /* SLJIT_CONFIG_MIPS_64 */
504 static SLJIT_INLINE void load_addr_to_reg(void *dst, sljit_u32 reg)
506 struct sljit_jump *jump;
507 struct sljit_put_label *put_label;
508 sljit_uw flags;
509 sljit_ins *inst;
510 sljit_uw addr;
512 if (reg != 0) {
513 jump = (struct sljit_jump*)dst;
514 flags = jump->flags;
515 inst = (sljit_ins*)jump->addr;
516 addr = (flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
517 } else {
518 put_label = (struct sljit_put_label*)dst;
519 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
520 flags = put_label->flags;
521 #endif
522 inst = (sljit_ins*)put_label->addr;
523 addr = put_label->label->addr;
524 reg = *inst;
527 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
528 inst[0] = LUI | T(reg) | IMM(addr >> 16);
529 #else /* !SLJIT_CONFIG_MIPS_32 */
530 if (flags & PATCH_ABS32) {
531 SLJIT_ASSERT(addr < 0x80000000l);
532 inst[0] = LUI | T(reg) | IMM(addr >> 16);
534 else if (flags & PATCH_ABS48) {
535 SLJIT_ASSERT(addr < 0x800000000000l);
536 inst[0] = LUI | T(reg) | IMM(addr >> 32);
537 inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
538 inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
539 inst += 2;
541 else {
542 inst[0] = LUI | T(reg) | IMM(addr >> 48);
543 inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);
544 inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
545 inst[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
546 inst[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);
547 inst += 4;
549 #endif /* SLJIT_CONFIG_MIPS_32 */
551 inst[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);
554 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
556 struct sljit_memory_fragment *buf;
557 sljit_ins *code;
558 sljit_ins *code_ptr;
559 sljit_ins *buf_ptr;
560 sljit_ins *buf_end;
561 sljit_uw word_count;
562 sljit_uw next_addr;
563 sljit_sw executable_offset;
564 sljit_uw addr;
566 struct sljit_label *label;
567 struct sljit_jump *jump;
568 struct sljit_const *const_;
569 struct sljit_put_label *put_label;
571 CHECK_ERROR_PTR();
572 CHECK_PTR(check_sljit_generate_code(compiler));
573 reverse_buf(compiler);
575 code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);
576 PTR_FAIL_WITH_EXEC_IF(code);
577 buf = compiler->buf;
579 code_ptr = code;
580 word_count = 0;
581 next_addr = 0;
582 executable_offset = SLJIT_EXEC_OFFSET(code);
584 label = compiler->labels;
585 jump = compiler->jumps;
586 const_ = compiler->consts;
587 put_label = compiler->put_labels;
589 do {
590 buf_ptr = (sljit_ins*)buf->memory;
591 buf_end = buf_ptr + (buf->used_size >> 2);
592 do {
593 *code_ptr = *buf_ptr++;
594 if (next_addr == word_count) {
595 SLJIT_ASSERT(!label || label->size >= word_count);
596 SLJIT_ASSERT(!jump || jump->addr >= word_count);
597 SLJIT_ASSERT(!const_ || const_->addr >= word_count);
598 SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
600 /* These structures are ordered by their address. */
601 if (label && label->size == word_count) {
602 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
603 label->size = (sljit_uw)(code_ptr - code);
604 label = label->next;
606 if (jump && jump->addr == word_count) {
607 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
608 word_count += 2;
609 #else
610 word_count += 6;
611 #endif
612 jump->addr = (sljit_uw)(code_ptr - 1);
613 code_ptr = detect_jump_type(jump, code, executable_offset);
614 jump = jump->next;
616 if (const_ && const_->addr == word_count) {
617 const_->addr = (sljit_uw)code_ptr;
618 const_ = const_->next;
620 if (put_label && put_label->addr == word_count) {
621 SLJIT_ASSERT(put_label->label);
622 put_label->addr = (sljit_uw)code_ptr;
623 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
624 code_ptr += 1;
625 word_count += 1;
626 #else
627 code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
628 word_count += 5;
629 #endif
630 put_label = put_label->next;
632 next_addr = compute_next_addr(label, jump, const_, put_label);
634 code_ptr++;
635 word_count++;
636 } while (buf_ptr < buf_end);
638 buf = buf->next;
639 } while (buf);
641 if (label && label->size == word_count) {
642 label->addr = (sljit_uw)code_ptr;
643 label->size = (sljit_uw)(code_ptr - code);
644 label = label->next;
647 SLJIT_ASSERT(!label);
648 SLJIT_ASSERT(!jump);
649 SLJIT_ASSERT(!const_);
650 SLJIT_ASSERT(!put_label);
651 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
653 jump = compiler->jumps;
654 while (jump) {
655 do {
656 addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
657 buf_ptr = (sljit_ins *)jump->addr;
659 if (jump->flags & PATCH_B) {
660 addr = (sljit_uw)((sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) - sizeof(sljit_ins)) >> 2);
661 SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);
662 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((sljit_ins)addr & 0xffff);
663 break;
665 if (jump->flags & PATCH_J) {
666 SLJIT_ASSERT((addr & ~(sljit_uw)0xfffffff)
667 == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff));
668 buf_ptr[0] |= (sljit_ins)(addr >> 2) & 0x03ffffff;
669 break;
672 load_addr_to_reg(jump, PIC_ADDR_REG);
673 } while (0);
674 jump = jump->next;
677 put_label = compiler->put_labels;
678 while (put_label) {
679 load_addr_to_reg(put_label, 0);
680 put_label = put_label->next;
683 compiler->error = SLJIT_ERR_COMPILED;
684 compiler->executable_offset = executable_offset;
685 compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
687 code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
688 code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
690 #ifndef __GNUC__
691 SLJIT_CACHE_FLUSH(code, code_ptr);
692 #else
693 /* GCC workaround for invalid code generation with -O2. */
694 sljit_cache_flush(code, code_ptr);
695 #endif
696 SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
697 return code;
700 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
702 #if defined(__GNUC__) && !defined(SLJIT_IS_FPU_AVAILABLE)
703 sljit_sw fir = 0;
704 #endif /* __GNUC__ && !SLJIT_IS_FPU_AVAILABLE */
706 switch (feature_type) {
707 case SLJIT_HAS_FPU:
708 #ifdef SLJIT_IS_FPU_AVAILABLE
709 return SLJIT_IS_FPU_AVAILABLE;
710 #elif defined(__GNUC__)
711 __asm__ ("cfc1 %0, $0" : "=r"(fir));
712 return (fir >> 22) & 0x1;
713 #else
714 #error "FIR check is not implemented for this architecture"
715 #endif
716 case SLJIT_HAS_ZERO_REGISTER:
717 return 1;
719 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
720 case SLJIT_HAS_CLZ:
721 case SLJIT_HAS_CMOV:
722 case SLJIT_HAS_PREFETCH:
723 return 1;
724 #endif /* SLJIT_MIPS_REV >= 1 */
726 default:
727 return 0;
731 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
733 return (type >= SLJIT_ORDERED_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL);
736 /* --------------------------------------------------------------------- */
737 /* Entry, exit */
738 /* --------------------------------------------------------------------- */
740 /* Creates an index in data_transfer_insts array. */
741 #define LOAD_DATA 0x01
742 #define WORD_DATA 0x00
743 #define BYTE_DATA 0x02
744 #define HALF_DATA 0x04
745 #define INT_DATA 0x06
746 #define SIGNED_DATA 0x08
747 /* Separates integer and floating point registers */
748 #define GPR_REG 0x0f
749 #define DOUBLE_DATA 0x10
750 #define SINGLE_DATA 0x12
752 #define MEM_MASK 0x1f
754 #define ARG_TEST 0x00020
755 #define ALT_KEEP_CACHE 0x00040
756 #define CUMULATIVE_OP 0x00080
757 #define LOGICAL_OP 0x00100
758 #define IMM_OP 0x00200
759 #define MOVE_OP 0x00400
760 #define SRC2_IMM 0x00800
762 #define UNUSED_DEST 0x01000
763 #define REG_DEST 0x02000
764 #define REG1_SOURCE 0x04000
765 #define REG2_SOURCE 0x08000
766 #define SLOW_SRC1 0x10000
767 #define SLOW_SRC2 0x20000
768 #define SLOW_DEST 0x40000
770 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
771 #define STACK_STORE SW
772 #define STACK_LOAD LW
773 #else
774 #define STACK_STORE SD
775 #define STACK_LOAD LD
776 #endif
778 static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);
779 static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr);
781 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
782 #include "sljitNativeMIPS_32.c"
783 #else
784 #include "sljitNativeMIPS_64.c"
785 #endif
787 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
788 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
789 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
791 sljit_ins base;
792 sljit_s32 i, tmp, offset;
793 sljit_s32 arg_count, word_arg_count, float_arg_count;
794 sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
796 CHECK_ERROR();
797 CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
798 set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
800 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);
801 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
802 if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
803 if ((local_size & SSIZE_OF(sw)) != 0)
804 local_size += SSIZE_OF(sw);
805 local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
808 local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
809 #else
810 local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
811 local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;
812 #endif
813 compiler->local_size = local_size;
815 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
816 tmp = arg_types >> SLJIT_ARG_SHIFT;
817 arg_count = 0;
818 offset = 0;
820 while (tmp) {
821 offset = arg_count;
822 if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {
823 if ((arg_count & 0x1) != 0)
824 arg_count++;
825 arg_count++;
828 arg_count++;
829 tmp >>= SLJIT_ARG_SHIFT;
832 compiler->args_size = (sljit_uw)arg_count << 2;
833 offset = (offset >= 4) ? (offset << 2) : 0;
834 #else /* !SLJIT_CONFIG_MIPS_32 */
835 offset = 0;
836 #endif /* SLJIT_CONFIG_MIPS_32 */
838 if (local_size + offset <= -SIMM_MIN) {
839 /* Frequent case. */
840 FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));
841 base = S(SLJIT_SP);
842 offset = local_size - SSIZE_OF(sw);
843 } else {
844 FAIL_IF(load_immediate(compiler, DR(OTHER_FLAG), local_size));
845 FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
846 FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
847 base = S(TMP_REG2);
848 offset = -SSIZE_OF(sw);
849 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
850 local_size = 0;
851 #endif
854 FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offset), MOVABLE_INS));
856 tmp = SLJIT_S0 - saveds;
857 for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
858 offset -= SSIZE_OF(sw);
859 FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offset), MOVABLE_INS));
862 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
863 offset -= SSIZE_OF(sw);
864 FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offset), MOVABLE_INS));
867 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
868 /* This alignment is valid because offset is not used after storing FPU regs. */
869 if ((offset & SSIZE_OF(sw)) != 0)
870 offset -= SSIZE_OF(sw);
871 #endif
873 tmp = SLJIT_FS0 - fsaveds;
874 for (i = SLJIT_FS0; i > tmp; i--) {
875 offset -= SSIZE_OF(f64);
876 FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
879 for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
880 offset -= SSIZE_OF(f64);
881 FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
884 arg_types >>= SLJIT_ARG_SHIFT;
885 arg_count = 0;
886 word_arg_count = 0;
887 float_arg_count = 0;
889 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
890 /* The first maximum two floating point arguments are passed in floating point
891 registers if no integer argument precedes them. The first 16 byte data is
892 passed in four integer registers, the rest is placed onto the stack.
893 The floating point registers are also part of the first 16 byte data, so
894 their corresponding integer registers are not used when they are present. */
896 while (arg_types) {
897 switch (arg_types & SLJIT_ARG_MASK) {
898 case SLJIT_ARG_TYPE_F64:
899 float_arg_count++;
900 if ((arg_count & 0x1) != 0)
901 arg_count++;
903 if (word_arg_count == 0 && float_arg_count <= 2) {
904 if (float_arg_count == 1)
905 FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
906 } else if (arg_count < 4) {
907 FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
908 FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS));
909 } else
910 FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
911 arg_count++;
912 break;
913 case SLJIT_ARG_TYPE_F32:
914 float_arg_count++;
916 if (word_arg_count == 0 && float_arg_count <= 2) {
917 if (float_arg_count == 1)
918 FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
919 } else if (arg_count < 4)
920 FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
921 else
922 FAIL_IF(push_inst(compiler, LWC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
923 break;
924 default:
925 word_arg_count++;
927 if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
928 tmp = SLJIT_S0 - saved_arg_count;
929 saved_arg_count++;
930 } else if (word_arg_count != arg_count + 1 || arg_count == 0)
931 tmp = word_arg_count;
932 else
933 break;
935 if (arg_count < 4)
936 FAIL_IF(push_inst(compiler, ADDU_W | SA(4 + arg_count) | TA(0) | D(tmp), DR(tmp)));
937 else
938 FAIL_IF(push_inst(compiler, LW | base | T(tmp) | IMM(local_size + (arg_count << 2)), DR(tmp)));
939 break;
941 arg_count++;
942 arg_types >>= SLJIT_ARG_SHIFT;
945 SLJIT_ASSERT(compiler->args_size == (sljit_uw)arg_count << 2);
946 #else /* !SLJIT_CONFIG_MIPS_32 */
947 while (arg_types) {
948 arg_count++;
949 switch (arg_types & SLJIT_ARG_MASK) {
950 case SLJIT_ARG_TYPE_F64:
951 float_arg_count++;
952 if (arg_count != float_arg_count)
953 FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
954 else if (arg_count == 1)
955 FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
956 break;
957 case SLJIT_ARG_TYPE_F32:
958 float_arg_count++;
959 if (arg_count != float_arg_count)
960 FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
961 else if (arg_count == 1)
962 FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
963 break;
964 default:
965 word_arg_count++;
967 if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
968 tmp = SLJIT_S0 - saved_arg_count;
969 saved_arg_count++;
970 } else if (word_arg_count != arg_count || word_arg_count <= 1)
971 tmp = word_arg_count;
972 else
973 break;
975 FAIL_IF(push_inst(compiler, ADDU_W | SA(3 + arg_count) | TA(0) | D(tmp), DR(tmp)));
976 break;
978 arg_types >>= SLJIT_ARG_SHIFT;
980 #endif /* SLJIT_CONFIG_MIPS_32 */
982 return SLJIT_SUCCESS;
985 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
986 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
987 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
989 CHECK_ERROR();
990 CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
991 set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
993 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);
994 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
995 if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
996 if ((local_size & SSIZE_OF(sw)) != 0)
997 local_size += SSIZE_OF(sw);
998 local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
1001 compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
1002 #else
1003 local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
1004 compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;
1005 #endif
1006 return SLJIT_SUCCESS;
1009 static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr)
1011 sljit_s32 local_size, i, tmp, offset;
1012 sljit_s32 scratches = compiler->scratches;
1013 sljit_s32 saveds = compiler->saveds;
1014 sljit_s32 fsaveds = compiler->fsaveds;
1015 sljit_s32 fscratches = compiler->fscratches;
1016 sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);
1018 local_size = compiler->local_size;
1020 tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds - kept_saveds_count, 1);
1021 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1022 if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
1023 if ((tmp & SSIZE_OF(sw)) != 0)
1024 tmp += SSIZE_OF(sw);
1025 tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
1027 #else
1028 tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
1029 #endif
1031 if (local_size <= SIMM_MAX) {
1032 if (local_size < frame_size) {
1033 FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size), DR(SLJIT_SP)));
1034 local_size = frame_size;
1036 } else {
1037 if (tmp < frame_size)
1038 tmp = frame_size;
1040 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size - tmp));
1041 FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG1) | D(SLJIT_SP), DR(SLJIT_SP)));
1042 local_size = tmp;
1045 SLJIT_ASSERT(local_size >= frame_size);
1047 offset = local_size - SSIZE_OF(sw);
1048 if (frame_size == 0)
1049 FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG));
1051 tmp = SLJIT_S0 - saveds;
1052 for (i = SLJIT_S0 - kept_saveds_count; i > tmp; i--) {
1053 offset -= SSIZE_OF(sw);
1054 FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));
1057 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
1058 offset -= SSIZE_OF(sw);
1059 FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));
1062 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1063 /* This alignment is valid because offset is not used after storing FPU regs. */
1064 if ((offset & SSIZE_OF(sw)) != 0)
1065 offset -= SSIZE_OF(sw);
1066 #endif
1068 tmp = SLJIT_FS0 - fsaveds;
1069 for (i = SLJIT_FS0; i > tmp; i--) {
1070 offset -= SSIZE_OF(f64);
1071 FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));
1074 for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
1075 offset -= SSIZE_OF(f64);
1076 FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));
1079 if (local_size > frame_size)
1080 *ins_ptr = ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size);
1081 else
1082 *ins_ptr = NOP;
1084 return SLJIT_SUCCESS;
1087 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
1089 sljit_ins ins;
1091 CHECK_ERROR();
1092 CHECK(check_sljit_emit_return_void(compiler));
1094 emit_stack_frame_release(compiler, 0, &ins);
1096 FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
1097 return push_inst(compiler, ins, UNMOVABLE_INS);
1100 #undef STACK_STORE
1101 #undef STACK_LOAD
1103 /* --------------------------------------------------------------------- */
1104 /* Operators */
1105 /* --------------------------------------------------------------------- */
1107 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1108 #define ARCH_32_64(a, b) a
1109 #else
1110 #define ARCH_32_64(a, b) b
1111 #endif
1113 static const sljit_ins data_transfer_insts[16 + 4] = {
1114 /* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
1115 /* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
1116 /* u b s */ HI(40) /* sb */,
1117 /* u b l */ HI(36) /* lbu */,
1118 /* u h s */ HI(41) /* sh */,
1119 /* u h l */ HI(37) /* lhu */,
1120 /* u i s */ HI(43) /* sw */,
1121 /* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),
1123 /* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
1124 /* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
1125 /* s b s */ HI(40) /* sb */,
1126 /* s b l */ HI(32) /* lb */,
1127 /* s h s */ HI(41) /* sh */,
1128 /* s h l */ HI(33) /* lh */,
1129 /* s i s */ HI(43) /* sw */,
1130 /* s i l */ HI(35) /* lw */,
1132 /* d s */ HI(61) /* sdc1 */,
1133 /* d l */ HI(53) /* ldc1 */,
1134 /* s s */ HI(57) /* swc1 */,
1135 /* s l */ HI(49) /* lwc1 */,
1138 #undef ARCH_32_64
1140 /* reg_ar is an absoulute register! */
1142 /* Can perform an operation using at most 1 instruction. */
1143 static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
1145 SLJIT_ASSERT(arg & SLJIT_MEM);
1147 if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
1148 /* Works for both absoulte and relative addresses. */
1149 if (SLJIT_UNLIKELY(flags & ARG_TEST))
1150 return 1;
1151 FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)
1152 | TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));
1153 return -1;
1155 return 0;
1158 #define TO_ARGW_HI(argw) (((argw) & ~0xffff) + (((argw) & 0x8000) ? 0x10000 : 0))
1160 /* See getput_arg below.
1161 Note: can_cache is called only for binary operators. */
1162 static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
1164 SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
1166 /* Simple operation except for updates. */
1167 if (arg & OFFS_REG_MASK) {
1168 argw &= 0x3;
1169 next_argw &= 0x3;
1170 if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
1171 return 1;
1172 return 0;
1175 if (arg == next_arg) {
1176 if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)
1177 || TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))
1178 return 1;
1179 return 0;
1182 return 0;
1185 /* Emit the necessary instructions. See can_cache above. */
1186 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)
1188 sljit_s32 tmp_ar, base, delay_slot;
1189 sljit_sw offset, argw_hi;
1191 SLJIT_ASSERT(arg & SLJIT_MEM);
1192 if (!(next_arg & SLJIT_MEM)) {
1193 next_arg = 0;
1194 next_argw = 0;
1197 /* Since tmp can be the same as base or offset registers,
1198 * these might be unavailable after modifying tmp. */
1199 if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
1200 tmp_ar = reg_ar;
1201 delay_slot = reg_ar;
1203 else {
1204 tmp_ar = DR(TMP_REG1);
1205 delay_slot = MOVABLE_INS;
1207 base = arg & REG_MASK;
1209 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1210 argw &= 0x3;
1212 /* Using the cache. */
1213 if (argw == compiler->cache_argw) {
1214 if (arg == compiler->cache_arg)
1215 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1217 if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
1218 if (arg == next_arg && argw == (next_argw & 0x3)) {
1219 compiler->cache_arg = arg;
1220 compiler->cache_argw = argw;
1221 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
1222 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1224 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
1225 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1229 if (SLJIT_UNLIKELY(argw)) {
1230 compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
1231 compiler->cache_argw = argw;
1232 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
1235 if (arg == next_arg && argw == (next_argw & 0x3)) {
1236 compiler->cache_arg = arg;
1237 compiler->cache_argw = argw;
1238 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
1239 tmp_ar = DR(TMP_REG3);
1241 else
1242 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
1243 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1246 if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)
1247 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(argw - compiler->cache_argw), delay_slot);
1249 if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) {
1250 offset = argw - compiler->cache_argw;
1251 } else {
1252 compiler->cache_arg = SLJIT_MEM;
1254 argw_hi = TO_ARGW_HI(argw);
1256 if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) {
1257 FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
1258 compiler->cache_argw = argw;
1259 offset = 0;
1260 } else {
1261 FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw_hi));
1262 compiler->cache_argw = argw_hi;
1263 offset = argw & 0xffff;
1264 argw = argw_hi;
1268 if (!base)
1269 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);
1271 if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {
1272 compiler->cache_arg = arg;
1273 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));
1274 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);
1277 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));
1278 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(offset), delay_slot);
1281 static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
1283 sljit_s32 tmp_ar, base, delay_slot;
1285 if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
1286 return compiler->error;
1288 if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
1289 tmp_ar = reg_ar;
1290 delay_slot = reg_ar;
1292 else {
1293 tmp_ar = DR(TMP_REG1);
1294 delay_slot = MOVABLE_INS;
1296 base = arg & REG_MASK;
1298 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1299 argw &= 0x3;
1301 if (SLJIT_UNLIKELY(argw)) {
1302 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));
1303 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));
1305 else
1306 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));
1307 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1310 FAIL_IF(load_immediate(compiler, tmp_ar, TO_ARGW_HI(argw)));
1312 if (base != 0)
1313 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));
1315 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(argw), delay_slot);
1318 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)
1320 if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
1321 return compiler->error;
1322 return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
1325 #define EMIT_LOGICAL(op_imm, op_reg) \
1326 if (flags & SRC2_IMM) { \
1327 if (op & SLJIT_SET_Z) \
1328 FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
1329 if (!(flags & UNUSED_DEST)) \
1330 FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
1332 else { \
1333 if (op & SLJIT_SET_Z) \
1334 FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
1335 if (!(flags & UNUSED_DEST)) \
1336 FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | D(dst), DR(dst))); \
1339 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1341 #define SELECT_OP(a, b) (b)
1343 #define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \
1344 if (flags & SRC2_IMM) { \
1345 if (op & SLJIT_SET_Z) \
1346 FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
1347 if (!(flags & UNUSED_DEST)) \
1348 FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
1350 else { \
1351 if (op & SLJIT_SET_Z) \
1352 FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
1353 if (!(flags & UNUSED_DEST)) \
1354 FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \
1357 #else /* !SLJIT_CONFIG_MIPS_32 */
1359 #define SELECT_OP(a, b) \
1360 (!(op & SLJIT_32) ? a : b)
1362 #define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \
1363 if (flags & SRC2_IMM) { \
1364 if (src2 >= 32) { \
1365 SLJIT_ASSERT(!(op & SLJIT_32)); \
1366 ins = op_dimm32; \
1367 src2 -= 32; \
1369 else \
1370 ins = (op & SLJIT_32) ? op_imm : op_dimm; \
1371 if (op & SLJIT_SET_Z) \
1372 FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
1373 if (!(flags & UNUSED_DEST)) \
1374 FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
1376 else { \
1377 ins = (op & SLJIT_32) ? op_v : op_dv; \
1378 if (op & SLJIT_SET_Z) \
1379 FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
1380 if (!(flags & UNUSED_DEST)) \
1381 FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \
1384 #endif /* SLJIT_CONFIG_MIPS_32 */
1386 static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
1387 sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
1389 sljit_s32 is_overflow, is_carry, carry_src_ar, is_handled;
1390 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1391 sljit_ins ins;
1392 #endif
1394 switch (GET_OPCODE(op)) {
1395 case SLJIT_MOV:
1396 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1397 if (dst != src2)
1398 return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
1399 return SLJIT_SUCCESS;
1401 case SLJIT_MOV_U8:
1402 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1403 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
1404 return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
1405 SLJIT_ASSERT(dst == src2);
1406 return SLJIT_SUCCESS;
1408 case SLJIT_MOV_S8:
1409 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1410 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1411 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1412 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1413 return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
1414 #else /* SLJIT_MIPS_REV < 1 */
1415 FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
1416 return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
1417 #endif /* SLJIT_MIPS_REV >= 1 */
1418 #else /* !SLJIT_CONFIG_MIPS_32 */
1419 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1420 if (op & SLJIT_32)
1421 return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
1422 #endif /* SLJIT_MIPS_REV >= 1 */
1423 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
1424 return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
1425 #endif /* SLJIT_CONFIG_MIPS_32 */
1427 SLJIT_ASSERT(dst == src2);
1428 return SLJIT_SUCCESS;
1430 case SLJIT_MOV_U16:
1431 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1432 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
1433 return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
1434 SLJIT_ASSERT(dst == src2);
1435 return SLJIT_SUCCESS;
1437 case SLJIT_MOV_S16:
1438 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1439 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1440 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1441 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1442 return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
1443 #else /* SLJIT_MIPS_REV < 1 */
1444 FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
1445 return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
1446 #endif /* SLJIT_MIPS_REV >= 1 */
1447 #else /* !SLJIT_CONFIG_MIPS_32 */
1448 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1449 if (op & SLJIT_32)
1450 return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
1451 #endif /* SLJIT_MIPS_REV >= 1 */
1452 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
1453 return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
1454 #endif /* SLJIT_CONFIG_MIPS_32 */
1456 SLJIT_ASSERT(dst == src2);
1457 return SLJIT_SUCCESS;
1459 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1460 case SLJIT_MOV_U32:
1461 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));
1462 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1463 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
1464 if (dst == src2)
1465 return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11) | (0 << 11), DR(dst));
1466 #endif /* SLJIT_MIPS_REV >= 2 */
1467 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
1468 return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
1470 SLJIT_ASSERT(dst == src2);
1471 return SLJIT_SUCCESS;
1473 case SLJIT_MOV_S32:
1474 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));
1475 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1476 return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
1478 SLJIT_ASSERT(dst == src2);
1479 return SLJIT_SUCCESS;
1480 #endif /* SLJIT_CONFIG_MIPS_64 */
1482 case SLJIT_NOT:
1483 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1484 if (op & SLJIT_SET_Z)
1485 FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1486 if (!(flags & UNUSED_DEST))
1487 FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
1488 return SLJIT_SUCCESS;
1490 case SLJIT_CLZ:
1491 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1492 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1493 if (op & SLJIT_SET_Z)
1494 FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
1495 if (!(flags & UNUSED_DEST))
1496 FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));
1497 #else /* SLJIT_MIPS_REV < 1 */
1498 /* Nearly all instructions are unmovable in the following sequence. */
1499 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
1500 /* Check zero. */
1501 FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
1502 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1503 FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
1504 #else /* !SLJIT_CONFIG_MIPS_32 */
1505 FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_32) ? 32 : 64), UNMOVABLE_INS));
1506 #endif /* SLJIT_CONFIG_MIPS_32 */
1507 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst)));
1508 /* Loop for searching the highest bit. */
1509 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
1510 FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
1511 FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
1512 #endif /* SLJIT_MIPS_REV >= 1 */
1513 return SLJIT_SUCCESS;
1515 case SLJIT_ADD:
1516 /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */
1517 is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
1518 carry_src_ar = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
1520 if (flags & SRC2_IMM) {
1521 if (is_overflow) {
1522 if (src2 >= 0)
1523 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
1524 else
1525 FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
1527 else if (op & SLJIT_SET_Z)
1528 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
1530 /* Only the zero flag is needed. */
1531 if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
1532 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
1534 else {
1535 if (is_overflow)
1536 FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1537 else if (op & SLJIT_SET_Z)
1538 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1540 if (is_overflow || carry_src_ar != 0) {
1541 if (src1 != dst)
1542 carry_src_ar = DR(src1);
1543 else if (src2 != dst)
1544 carry_src_ar = DR(src2);
1545 else {
1546 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG));
1547 carry_src_ar = OTHER_FLAG;
1551 /* Only the zero flag is needed. */
1552 if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
1553 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
1556 /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
1557 if (is_overflow || carry_src_ar != 0) {
1558 if (flags & SRC2_IMM)
1559 FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
1560 else
1561 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(OTHER_FLAG), OTHER_FLAG));
1564 if (!is_overflow)
1565 return SLJIT_SUCCESS;
1567 FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
1568 if (op & SLJIT_SET_Z)
1569 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
1570 FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
1571 return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
1573 case SLJIT_ADDC:
1574 carry_src_ar = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
1576 if (flags & SRC2_IMM) {
1577 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
1578 } else {
1579 if (carry_src_ar != 0) {
1580 if (src1 != dst)
1581 carry_src_ar = DR(src1);
1582 else if (src2 != dst)
1583 carry_src_ar = DR(src2);
1584 else {
1585 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
1586 carry_src_ar = EQUAL_FLAG;
1590 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
1593 /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
1594 if (carry_src_ar != 0) {
1595 if (flags & SRC2_IMM)
1596 FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
1597 else
1598 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(EQUAL_FLAG), EQUAL_FLAG));
1601 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
1603 if (carry_src_ar == 0)
1604 return SLJIT_SUCCESS;
1606 /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
1607 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
1608 /* Set carry flag. */
1609 return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
1611 case SLJIT_SUB:
1612 if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
1613 FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
1614 src2 = TMP_REG2;
1615 flags &= ~SRC2_IMM;
1618 is_handled = 0;
1620 if (flags & SRC2_IMM) {
1621 if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
1622 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
1623 is_handled = 1;
1625 else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
1626 FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
1627 is_handled = 1;
1631 if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
1632 is_handled = 1;
1634 if (flags & SRC2_IMM) {
1635 FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
1636 src2 = TMP_REG2;
1637 flags &= ~SRC2_IMM;
1640 switch (GET_FLAG_TYPE(op)) {
1641 case SLJIT_LESS:
1642 case SLJIT_GREATER_EQUAL:
1643 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
1644 break;
1645 case SLJIT_GREATER:
1646 case SLJIT_LESS_EQUAL:
1647 FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
1648 break;
1649 case SLJIT_SIG_LESS:
1650 case SLJIT_SIG_GREATER_EQUAL:
1651 FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
1652 break;
1653 case SLJIT_SIG_GREATER:
1654 case SLJIT_SIG_LESS_EQUAL:
1655 FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
1656 break;
1660 if (is_handled) {
1661 if (flags & SRC2_IMM) {
1662 if (op & SLJIT_SET_Z)
1663 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
1664 if (!(flags & UNUSED_DEST))
1665 return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));
1667 else {
1668 if (op & SLJIT_SET_Z)
1669 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1670 if (!(flags & UNUSED_DEST))
1671 return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));
1673 return SLJIT_SUCCESS;
1676 is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
1677 is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
1679 if (flags & SRC2_IMM) {
1680 if (is_overflow) {
1681 if (src2 >= 0)
1682 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
1683 else
1684 FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
1686 else if (op & SLJIT_SET_Z)
1687 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
1689 if (is_overflow || is_carry)
1690 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
1692 /* Only the zero flag is needed. */
1693 if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
1694 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
1696 else {
1697 if (is_overflow)
1698 FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1699 else if (op & SLJIT_SET_Z)
1700 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1702 if (is_overflow || is_carry)
1703 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
1705 /* Only the zero flag is needed. */
1706 if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
1707 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
1710 if (!is_overflow)
1711 return SLJIT_SUCCESS;
1713 FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
1714 if (op & SLJIT_SET_Z)
1715 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
1716 FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
1717 return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
1719 case SLJIT_SUBC:
1720 if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
1721 FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
1722 src2 = TMP_REG2;
1723 flags &= ~SRC2_IMM;
1726 is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
1728 if (flags & SRC2_IMM) {
1729 if (is_carry)
1730 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
1732 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
1734 else {
1735 if (is_carry)
1736 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1738 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
1741 if (is_carry)
1742 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
1744 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
1746 if (!is_carry)
1747 return SLJIT_SUCCESS;
1749 return push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG);
1751 case SLJIT_MUL:
1752 SLJIT_ASSERT(!(flags & SRC2_IMM));
1754 if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) {
1755 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1756 return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));
1757 #elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1758 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1759 return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
1760 #else /* !SLJIT_CONFIG_MIPS_32 */
1761 if (op & SLJIT_32)
1762 return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
1763 FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
1764 return push_inst(compiler, MFLO | D(dst), DR(dst));
1765 #endif /* SLJIT_CONFIG_MIPS_32 */
1766 #else /* SLJIT_MIPS_REV < 1 */
1767 FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
1768 return push_inst(compiler, MFLO | D(dst), DR(dst));
1769 #endif /* SLJIT_MIPS_REV >= 6 */
1772 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1773 FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)));
1774 FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1775 #else /* SLJIT_MIPS_REV < 6 */
1776 FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
1777 FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
1778 FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
1779 #endif /* SLJIT_MIPS_REV >= 6 */
1780 FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
1781 return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
1783 case SLJIT_AND:
1784 EMIT_LOGICAL(ANDI, AND);
1785 return SLJIT_SUCCESS;
1787 case SLJIT_OR:
1788 EMIT_LOGICAL(ORI, OR);
1789 return SLJIT_SUCCESS;
1791 case SLJIT_XOR:
1792 EMIT_LOGICAL(XORI, XOR);
1793 return SLJIT_SUCCESS;
1795 case SLJIT_SHL:
1796 EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);
1797 return SLJIT_SUCCESS;
1799 case SLJIT_LSHR:
1800 EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);
1801 return SLJIT_SUCCESS;
1803 case SLJIT_ASHR:
1804 EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);
1805 return SLJIT_SUCCESS;
1808 SLJIT_UNREACHABLE();
1809 return SLJIT_SUCCESS;
1812 #define CHECK_IMM(flags, srcw) \
1813 ((!((flags) & LOGICAL_OP) && ((srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)) \
1814 || (((flags) & LOGICAL_OP) && !((srcw) & ~UIMM_MAX)))
1816 static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
1817 sljit_s32 dst, sljit_sw dstw,
1818 sljit_s32 src1, sljit_sw src1w,
1819 sljit_s32 src2, sljit_sw src2w)
1821 /* arg1 goes to TMP_REG1 or src reg
1822 arg2 goes to TMP_REG2, imm or src reg
1823 TMP_REG3 can be used for caching
1824 result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
1825 sljit_s32 dst_r = TMP_REG2;
1826 sljit_s32 src1_r;
1827 sljit_sw src2_r = 0;
1828 sljit_s32 sugg_src2_r = TMP_REG2;
1830 if (!(flags & ALT_KEEP_CACHE)) {
1831 compiler->cache_arg = 0;
1832 compiler->cache_argw = 0;
1835 if (dst == TMP_REG2) {
1836 SLJIT_ASSERT(HAS_FLAGS(op));
1837 flags |= UNUSED_DEST;
1839 else if (FAST_IS_REG(dst)) {
1840 dst_r = dst;
1841 flags |= REG_DEST;
1842 if (flags & MOVE_OP)
1843 sugg_src2_r = dst_r;
1845 else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
1846 flags |= SLOW_DEST;
1848 if (flags & IMM_OP) {
1849 if ((src2 & SLJIT_IMM) && src2w != 0 && CHECK_IMM(flags, src2w)) {
1850 flags |= SRC2_IMM;
1851 src2_r = src2w;
1852 } else if ((flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w != 0 && CHECK_IMM(flags, src1w)) {
1853 flags |= SRC2_IMM;
1854 src2_r = src1w;
1856 /* And swap arguments. */
1857 src1 = src2;
1858 src1w = src2w;
1859 src2 = SLJIT_IMM;
1860 /* src2w = src2_r unneeded. */
1864 /* Source 1. */
1865 if (FAST_IS_REG(src1)) {
1866 src1_r = src1;
1867 flags |= REG1_SOURCE;
1869 else if (src1 & SLJIT_IMM) {
1870 if (src1w) {
1871 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
1872 src1_r = TMP_REG1;
1874 else
1875 src1_r = 0;
1877 else {
1878 if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))
1879 FAIL_IF(compiler->error);
1880 else
1881 flags |= SLOW_SRC1;
1882 src1_r = TMP_REG1;
1885 /* Source 2. */
1886 if (FAST_IS_REG(src2)) {
1887 src2_r = src2;
1888 flags |= REG2_SOURCE;
1889 if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
1890 dst_r = (sljit_s32)src2_r;
1892 else if (src2 & SLJIT_IMM) {
1893 if (!(flags & SRC2_IMM)) {
1894 if (src2w) {
1895 FAIL_IF(load_immediate(compiler, DR(sugg_src2_r), src2w));
1896 src2_r = sugg_src2_r;
1898 else {
1899 src2_r = 0;
1900 if (flags & MOVE_OP) {
1901 if (dst & SLJIT_MEM)
1902 dst_r = 0;
1903 else
1904 op = SLJIT_MOV;
1909 else {
1910 if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w))
1911 FAIL_IF(compiler->error);
1912 else
1913 flags |= SLOW_SRC2;
1914 src2_r = sugg_src2_r;
1917 if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
1918 SLJIT_ASSERT(src2_r == TMP_REG2);
1919 if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
1920 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));
1921 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
1923 else {
1924 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));
1925 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));
1928 else if (flags & SLOW_SRC1)
1929 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
1930 else if (flags & SLOW_SRC2)
1931 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w, dst, dstw));
1933 FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1935 if (dst & SLJIT_MEM) {
1936 if (!(flags & SLOW_DEST)) {
1937 getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);
1938 return compiler->error;
1940 return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);
1943 return SLJIT_SUCCESS;
1946 #undef CHECK_IMM
1948 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1950 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1951 sljit_s32 int_op = op & SLJIT_32;
1952 #endif
1954 CHECK_ERROR();
1955 CHECK(check_sljit_emit_op0(compiler, op));
1957 op = GET_OPCODE(op);
1958 switch (op) {
1959 case SLJIT_BREAKPOINT:
1960 return push_inst(compiler, BREAK, UNMOVABLE_INS);
1961 case SLJIT_NOP:
1962 return push_inst(compiler, NOP, UNMOVABLE_INS);
1963 case SLJIT_LMUL_UW:
1964 case SLJIT_LMUL_SW:
1965 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1966 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1967 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1968 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1969 #else /* !SLJIT_CONFIG_MIPS_64 */
1970 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1971 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1972 #endif /* SLJIT_CONFIG_MIPS_64 */
1973 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
1974 return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
1975 #else /* SLJIT_MIPS_REV < 6 */
1976 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1977 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1978 #else /* !SLJIT_CONFIG_MIPS_64 */
1979 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1980 #endif /* SLJIT_CONFIG_MIPS_64 */
1981 FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
1982 return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
1983 #endif /* SLJIT_MIPS_REV >= 6 */
1984 case SLJIT_DIVMOD_UW:
1985 case SLJIT_DIVMOD_SW:
1986 case SLJIT_DIV_UW:
1987 case SLJIT_DIV_SW:
1988 SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
1989 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1990 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1991 if (int_op) {
1992 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1993 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1995 else {
1996 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1997 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1999 #else /* !SLJIT_CONFIG_MIPS_64 */
2000 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
2001 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
2002 #endif /* SLJIT_CONFIG_MIPS_64 */
2003 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
2004 return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
2005 #else /* SLJIT_MIPS_REV < 6 */
2006 #if !(defined SLJIT_MIPS_REV)
2007 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2008 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2009 #endif /* !SLJIT_MIPS_REV */
2010 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2011 if (int_op)
2012 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2013 else
2014 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2015 #else /* !SLJIT_CONFIG_MIPS_64 */
2016 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2017 #endif /* SLJIT_CONFIG_MIPS_64 */
2018 FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
2019 return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
2020 #endif /* SLJIT_MIPS_REV >= 6 */
2021 case SLJIT_ENDBR:
2022 case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
2023 return SLJIT_SUCCESS;
2026 return SLJIT_SUCCESS;
2029 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
2030 static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
2031 sljit_s32 src, sljit_sw srcw)
2033 if (!(src & OFFS_REG_MASK)) {
2034 if (srcw <= SIMM_MAX && srcw >= SIMM_MIN)
2035 return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS);
2037 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
2038 return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
2041 srcw &= 0x3;
2043 if (SLJIT_UNLIKELY(srcw != 0)) {
2044 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1)));
2045 return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
2048 return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);
2050 #endif /* SLJIT_MIPS_REV >= 1 */
2052 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
2053 sljit_s32 dst, sljit_sw dstw,
2054 sljit_s32 src, sljit_sw srcw)
2056 sljit_s32 flags = 0;
2058 CHECK_ERROR();
2059 CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
2060 ADJUST_LOCAL_OFFSET(dst, dstw);
2061 ADJUST_LOCAL_OFFSET(src, srcw);
2063 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2064 if (op & SLJIT_32)
2065 flags = INT_DATA | SIGNED_DATA;
2066 #endif
2068 switch (GET_OPCODE(op)) {
2069 case SLJIT_MOV:
2070 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2071 case SLJIT_MOV_U32:
2072 case SLJIT_MOV_S32:
2073 case SLJIT_MOV32:
2074 #endif
2075 case SLJIT_MOV_P:
2076 return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);
2078 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2079 case SLJIT_MOV_U32:
2080 return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw);
2082 case SLJIT_MOV_S32:
2083 case SLJIT_MOV32:
2084 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);
2085 #endif
2087 case SLJIT_MOV_U8:
2088 return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
2090 case SLJIT_MOV_S8:
2091 return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
2093 case SLJIT_MOV_U16:
2094 return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
2096 case SLJIT_MOV_S16:
2097 return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
2099 case SLJIT_NOT:
2100 return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
2102 case SLJIT_CLZ:
2103 return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
2106 SLJIT_UNREACHABLE();
2107 return SLJIT_SUCCESS;
2110 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
2111 sljit_s32 dst, sljit_sw dstw,
2112 sljit_s32 src1, sljit_sw src1w,
2113 sljit_s32 src2, sljit_sw src2w)
2115 sljit_s32 flags = 0;
2117 CHECK_ERROR();
2118 CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
2119 ADJUST_LOCAL_OFFSET(dst, dstw);
2120 ADJUST_LOCAL_OFFSET(src1, src1w);
2121 ADJUST_LOCAL_OFFSET(src2, src2w);
2123 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2124 if (op & SLJIT_32) {
2125 flags |= INT_DATA | SIGNED_DATA;
2126 if (src1 & SLJIT_IMM)
2127 src1w = (sljit_s32)src1w;
2128 if (src2 & SLJIT_IMM)
2129 src2w = (sljit_s32)src2w;
2131 #endif
2133 switch (GET_OPCODE(op)) {
2134 case SLJIT_ADD:
2135 case SLJIT_ADDC:
2136 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
2137 return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2139 case SLJIT_SUB:
2140 case SLJIT_SUBC:
2141 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
2142 return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2144 case SLJIT_MUL:
2145 compiler->status_flags_state = 0;
2146 return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
2148 case SLJIT_AND:
2149 case SLJIT_OR:
2150 case SLJIT_XOR:
2151 return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2153 case SLJIT_SHL:
2154 case SLJIT_LSHR:
2155 case SLJIT_ASHR:
2156 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2157 if (src2 & SLJIT_IMM)
2158 src2w &= 0x1f;
2159 #else
2160 if (src2 & SLJIT_IMM) {
2161 if (op & SLJIT_32)
2162 src2w &= 0x1f;
2163 else
2164 src2w &= 0x3f;
2166 #endif
2167 return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2170 SLJIT_UNREACHABLE();
2171 return SLJIT_SUCCESS;
2174 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
2175 sljit_s32 src1, sljit_sw src1w,
2176 sljit_s32 src2, sljit_sw src2w)
2178 CHECK_ERROR();
2179 CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
2181 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2182 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2183 compiler->skip_checks = 1;
2184 #endif
2185 return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
2188 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
2189 sljit_s32 src, sljit_sw srcw)
2191 CHECK_ERROR();
2192 CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
2193 ADJUST_LOCAL_OFFSET(src, srcw);
2195 switch (op) {
2196 case SLJIT_FAST_RETURN:
2197 if (FAST_IS_REG(src))
2198 FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
2199 else
2200 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
2202 FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
2203 return push_inst(compiler, NOP, UNMOVABLE_INS);
2204 case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
2205 return SLJIT_SUCCESS;
2206 case SLJIT_PREFETCH_L1:
2207 case SLJIT_PREFETCH_L2:
2208 case SLJIT_PREFETCH_L3:
2209 case SLJIT_PREFETCH_ONCE:
2210 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
2211 return emit_prefetch(compiler, src, srcw);
2212 #else /* SLJIT_MIPS_REV < 1 */
2213 return SLJIT_SUCCESS;
2214 #endif /* SLJIT_MIPS_REV >= 1 */
2217 return SLJIT_SUCCESS;
2220 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
2222 CHECK_REG_INDEX(check_sljit_get_register_index(reg));
2223 return reg_map[reg];
2226 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
2228 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
2229 return FR(reg);
2232 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
2233 void *instruction, sljit_u32 size)
2235 CHECK_ERROR();
2236 CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
2238 return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);
2241 /* --------------------------------------------------------------------- */
2242 /* Floating point operators */
2243 /* --------------------------------------------------------------------- */
2245 #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
2246 #define FMT(op) ((((sljit_ins)op & SLJIT_32) ^ SLJIT_32) << (21 - 8))
2248 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
2249 sljit_s32 dst, sljit_sw dstw,
2250 sljit_s32 src, sljit_sw srcw)
2252 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2253 # define flags (sljit_u32)0
2254 #else
2255 sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;
2256 #endif
2258 if (src & SLJIT_MEM) {
2259 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
2260 src = TMP_FREG1;
2263 FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
2265 if (FAST_IS_REG(dst)) {
2266 FAIL_IF(push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS));
2267 #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
2268 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2269 #endif
2270 return SLJIT_SUCCESS;
2273 /* Store the integer value from a VFP register. */
2274 return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);
2276 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2277 # undef flags
2278 #endif
2281 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
2282 sljit_s32 dst, sljit_sw dstw,
2283 sljit_s32 src, sljit_sw srcw)
2285 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2286 # define flags (sljit_u32)0
2287 #else
2288 sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21;
2289 #endif
2291 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2293 if (FAST_IS_REG(src)) {
2294 FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
2295 #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
2296 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2297 #endif
2298 } else if (src & SLJIT_MEM) {
2299 /* Load the integer value into a VFP register. */
2300 FAIL_IF(emit_op_mem2(compiler, (flags ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
2302 else {
2303 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2304 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
2305 srcw = (sljit_s32)srcw;
2306 #endif
2307 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
2308 FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
2309 #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
2310 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2311 #endif
2314 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));
2316 if (dst & SLJIT_MEM)
2317 return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
2318 return SLJIT_SUCCESS;
2320 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2321 # undef flags
2322 #endif
2325 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
2326 sljit_s32 src1, sljit_sw src1w,
2327 sljit_s32 src2, sljit_sw src2w)
2329 sljit_ins inst;
2331 if (src1 & SLJIT_MEM) {
2332 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
2333 src1 = TMP_FREG1;
2336 if (src2 & SLJIT_MEM) {
2337 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));
2338 src2 = TMP_FREG2;
2341 switch (GET_FLAG_TYPE(op)) {
2342 case SLJIT_F_EQUAL:
2343 case SLJIT_ORDERED_EQUAL:
2344 case SLJIT_UNORDERED_OR_NOT_EQUAL:
2345 inst = C_EQ_S;
2346 break;
2347 case SLJIT_F_NOT_EQUAL:
2348 case SLJIT_UNORDERED_OR_EQUAL:
2349 case SLJIT_ORDERED_NOT_EQUAL:
2350 inst = C_UEQ_S;
2351 break;
2352 case SLJIT_F_LESS:
2353 case SLJIT_ORDERED_LESS:
2354 case SLJIT_UNORDERED_OR_GREATER_EQUAL:
2355 inst = C_OLT_S;
2356 break;
2357 case SLJIT_F_GREATER_EQUAL:
2358 case SLJIT_UNORDERED_OR_LESS:
2359 case SLJIT_ORDERED_GREATER_EQUAL:
2360 inst = C_ULT_S;
2361 break;
2362 case SLJIT_F_GREATER:
2363 case SLJIT_ORDERED_GREATER:
2364 case SLJIT_UNORDERED_OR_LESS_EQUAL:
2365 inst = C_ULE_S;
2366 break;
2367 case SLJIT_F_LESS_EQUAL:
2368 case SLJIT_UNORDERED_OR_GREATER:
2369 case SLJIT_ORDERED_LESS_EQUAL:
2370 inst = C_OLE_S;
2371 break;
2372 default:
2373 SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED || GET_FLAG_TYPE(op) == SLJIT_ORDERED);
2374 inst = C_UN_S;
2375 break;
2377 return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1) | C_FD, UNMOVABLE_INS);
2380 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
2381 sljit_s32 dst, sljit_sw dstw,
2382 sljit_s32 src, sljit_sw srcw)
2384 sljit_s32 dst_r;
2386 CHECK_ERROR();
2387 compiler->cache_arg = 0;
2388 compiler->cache_argw = 0;
2390 SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
2391 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
2393 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
2394 op ^= SLJIT_32;
2396 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2398 if (src & SLJIT_MEM) {
2399 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));
2400 src = dst_r;
2403 switch (GET_OPCODE(op)) {
2404 case SLJIT_MOV_F64:
2405 if (src != dst_r) {
2406 if (dst_r != TMP_FREG1)
2407 FAIL_IF(push_inst(compiler, MOV_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
2408 else
2409 dst_r = src;
2411 break;
2412 case SLJIT_NEG_F64:
2413 FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
2414 break;
2415 case SLJIT_ABS_F64:
2416 FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
2417 break;
2418 case SLJIT_CONV_F64_FROM_F32:
2419 /* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */
2420 FAIL_IF(push_inst(compiler, CVT_S_S | (sljit_ins)((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));
2421 op ^= SLJIT_32;
2422 break;
2425 if (dst & SLJIT_MEM)
2426 return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);
2427 return SLJIT_SUCCESS;
2430 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
2431 sljit_s32 dst, sljit_sw dstw,
2432 sljit_s32 src1, sljit_sw src1w,
2433 sljit_s32 src2, sljit_sw src2w)
2435 sljit_s32 dst_r, flags = 0;
2437 CHECK_ERROR();
2438 CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
2439 ADJUST_LOCAL_OFFSET(dst, dstw);
2440 ADJUST_LOCAL_OFFSET(src1, src1w);
2441 ADJUST_LOCAL_OFFSET(src2, src2w);
2443 compiler->cache_arg = 0;
2444 compiler->cache_argw = 0;
2446 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
2448 if (src1 & SLJIT_MEM) {
2449 if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {
2450 FAIL_IF(compiler->error);
2451 src1 = TMP_FREG1;
2452 } else
2453 flags |= SLOW_SRC1;
2456 if (src2 & SLJIT_MEM) {
2457 if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {
2458 FAIL_IF(compiler->error);
2459 src2 = TMP_FREG2;
2460 } else
2461 flags |= SLOW_SRC2;
2464 if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
2465 if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
2466 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));
2467 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
2469 else {
2470 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
2471 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
2474 else if (flags & SLOW_SRC1)
2475 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
2476 else if (flags & SLOW_SRC2)
2477 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
2479 if (flags & SLOW_SRC1)
2480 src1 = TMP_FREG1;
2481 if (flags & SLOW_SRC2)
2482 src2 = TMP_FREG2;
2484 switch (GET_OPCODE(op)) {
2485 case SLJIT_ADD_F64:
2486 FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
2487 break;
2489 case SLJIT_SUB_F64:
2490 FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
2491 break;
2493 case SLJIT_MUL_F64:
2494 FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
2495 break;
2497 case SLJIT_DIV_F64:
2498 FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
2499 break;
2502 if (dst_r == TMP_FREG2)
2503 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));
2505 return SLJIT_SUCCESS;
2508 #undef FLOAT_DATA
2509 #undef FMT
2511 /* --------------------------------------------------------------------- */
2512 /* Other instructions */
2513 /* --------------------------------------------------------------------- */
2515 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2517 CHECK_ERROR();
2518 CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
2519 ADJUST_LOCAL_OFFSET(dst, dstw);
2521 if (FAST_IS_REG(dst))
2522 return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);
2524 /* Memory. */
2525 FAIL_IF(emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw));
2526 compiler->delay_slot = UNMOVABLE_INS;
2527 return SLJIT_SUCCESS;
2530 /* --------------------------------------------------------------------- */
2531 /* Conditional instructions */
2532 /* --------------------------------------------------------------------- */
2534 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
2536 struct sljit_label *label;
2538 CHECK_ERROR_PTR();
2539 CHECK_PTR(check_sljit_emit_label(compiler));
2541 if (compiler->last_label && compiler->last_label->size == compiler->size)
2542 return compiler->last_label;
2544 label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
2545 PTR_FAIL_IF(!label);
2546 set_label(label, compiler);
2547 compiler->delay_slot = UNMOVABLE_INS;
2548 return label;
2551 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2552 #define BRANCH_LENGTH 4
2553 #else
2554 #define BRANCH_LENGTH 8
2555 #endif
2557 #define BR_Z(src) \
2558 inst = BEQ | SA(src) | TA(0) | BRANCH_LENGTH; \
2559 flags = IS_BIT26_COND; \
2560 delay_check = src;
2562 #define BR_NZ(src) \
2563 inst = BNE | SA(src) | TA(0) | BRANCH_LENGTH; \
2564 flags = IS_BIT26_COND; \
2565 delay_check = src;
2567 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2569 #define BR_T() \
2570 inst = BC1NEZ; \
2571 flags = IS_BIT23_COND; \
2572 delay_check = FCSR_FCC;
2573 #define BR_F() \
2574 inst = BC1EQZ; \
2575 flags = IS_BIT23_COND; \
2576 delay_check = FCSR_FCC;
2578 #else /* SLJIT_MIPS_REV < 6 */
2580 #define BR_T() \
2581 inst = BC1T | BRANCH_LENGTH; \
2582 flags = IS_BIT16_COND; \
2583 delay_check = FCSR_FCC;
2584 #define BR_F() \
2585 inst = BC1F | BRANCH_LENGTH; \
2586 flags = IS_BIT16_COND; \
2587 delay_check = FCSR_FCC;
2589 #endif /* SLJIT_MIPS_REV >= 6 */
2591 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
2593 struct sljit_jump *jump;
2594 sljit_ins inst;
2595 sljit_u32 flags = 0;
2596 sljit_s32 delay_check = UNMOVABLE_INS;
2598 CHECK_ERROR_PTR();
2599 CHECK_PTR(check_sljit_emit_jump(compiler, type));
2601 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2602 PTR_FAIL_IF(!jump);
2603 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
2604 type &= 0xff;
2606 switch (type) {
2607 case SLJIT_EQUAL:
2608 BR_NZ(EQUAL_FLAG);
2609 break;
2610 case SLJIT_NOT_EQUAL:
2611 BR_Z(EQUAL_FLAG);
2612 break;
2613 case SLJIT_LESS:
2614 case SLJIT_GREATER:
2615 case SLJIT_SIG_LESS:
2616 case SLJIT_SIG_GREATER:
2617 case SLJIT_OVERFLOW:
2618 case SLJIT_CARRY:
2619 BR_Z(OTHER_FLAG);
2620 break;
2621 case SLJIT_GREATER_EQUAL:
2622 case SLJIT_LESS_EQUAL:
2623 case SLJIT_SIG_GREATER_EQUAL:
2624 case SLJIT_SIG_LESS_EQUAL:
2625 case SLJIT_NOT_OVERFLOW:
2626 case SLJIT_NOT_CARRY:
2627 BR_NZ(OTHER_FLAG);
2628 break;
2629 case SLJIT_F_NOT_EQUAL:
2630 case SLJIT_F_GREATER_EQUAL:
2631 case SLJIT_F_GREATER:
2632 case SLJIT_UNORDERED_OR_NOT_EQUAL:
2633 case SLJIT_ORDERED_NOT_EQUAL:
2634 case SLJIT_UNORDERED_OR_GREATER_EQUAL:
2635 case SLJIT_ORDERED_GREATER_EQUAL:
2636 case SLJIT_ORDERED_GREATER:
2637 case SLJIT_UNORDERED_OR_GREATER:
2638 case SLJIT_ORDERED:
2639 BR_T();
2640 break;
2641 case SLJIT_F_EQUAL:
2642 case SLJIT_F_LESS:
2643 case SLJIT_F_LESS_EQUAL:
2644 case SLJIT_ORDERED_EQUAL:
2645 case SLJIT_UNORDERED_OR_EQUAL:
2646 case SLJIT_ORDERED_LESS:
2647 case SLJIT_UNORDERED_OR_LESS:
2648 case SLJIT_UNORDERED_OR_LESS_EQUAL:
2649 case SLJIT_ORDERED_LESS_EQUAL:
2650 case SLJIT_UNORDERED:
2651 BR_F();
2652 break;
2653 default:
2654 /* Not conditional branch. */
2655 inst = 0;
2656 break;
2659 jump->flags |= flags;
2660 if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))
2661 jump->flags |= IS_MOVABLE;
2663 if (inst)
2664 PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));
2666 if (type <= SLJIT_JUMP)
2667 PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
2668 else {
2669 jump->flags |= IS_JAL;
2670 PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
2673 jump->addr = compiler->size;
2674 PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2676 /* Maximum number of instructions required for generating a constant. */
2677 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2678 compiler->size += 2;
2679 #else
2680 compiler->size += 6;
2681 #endif
2682 return jump;
2685 #define RESOLVE_IMM1() \
2686 if (src1 & SLJIT_IMM) { \
2687 if (src1w) { \
2688 PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \
2689 src1 = TMP_REG1; \
2691 else \
2692 src1 = 0; \
2695 #define RESOLVE_IMM2() \
2696 if (src2 & SLJIT_IMM) { \
2697 if (src2w) { \
2698 PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG2), src2w)); \
2699 src2 = TMP_REG2; \
2701 else \
2702 src2 = 0; \
2705 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
2706 sljit_s32 src1, sljit_sw src1w,
2707 sljit_s32 src2, sljit_sw src2w)
2709 struct sljit_jump *jump;
2710 sljit_s32 flags;
2711 sljit_ins inst;
2713 CHECK_ERROR_PTR();
2714 CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
2715 ADJUST_LOCAL_OFFSET(src1, src1w);
2716 ADJUST_LOCAL_OFFSET(src2, src2w);
2718 compiler->cache_arg = 0;
2719 compiler->cache_argw = 0;
2720 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2721 flags = WORD_DATA | LOAD_DATA;
2722 #else /* !SLJIT_CONFIG_MIPS_32 */
2723 flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
2724 #endif /* SLJIT_CONFIG_MIPS_32 */
2726 if (src1 & SLJIT_MEM) {
2727 PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));
2728 src1 = TMP_REG1;
2731 if (src2 & SLJIT_MEM) {
2732 PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG2), src2, src2w, 0, 0));
2733 src2 = TMP_REG2;
2736 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2737 PTR_FAIL_IF(!jump);
2738 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
2739 type &= 0xff;
2741 if (type <= SLJIT_NOT_EQUAL) {
2742 RESOLVE_IMM1();
2743 RESOLVE_IMM2();
2744 jump->flags |= IS_BIT26_COND;
2745 if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))
2746 jump->flags |= IS_MOVABLE;
2747 PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | BRANCH_LENGTH, UNMOVABLE_INS));
2749 else if (type >= SLJIT_SIG_LESS && (((src1 & SLJIT_IMM) && (src1w == 0)) || ((src2 & SLJIT_IMM) && (src2w == 0)))) {
2750 inst = NOP;
2751 if ((src1 & SLJIT_IMM) && (src1w == 0)) {
2752 RESOLVE_IMM2();
2753 switch (type) {
2754 case SLJIT_SIG_LESS:
2755 inst = BLEZ;
2756 jump->flags |= IS_BIT26_COND;
2757 break;
2758 case SLJIT_SIG_GREATER_EQUAL:
2759 inst = BGTZ;
2760 jump->flags |= IS_BIT26_COND;
2761 break;
2762 case SLJIT_SIG_GREATER:
2763 inst = BGEZ;
2764 jump->flags |= IS_BIT16_COND;
2765 break;
2766 case SLJIT_SIG_LESS_EQUAL:
2767 inst = BLTZ;
2768 jump->flags |= IS_BIT16_COND;
2769 break;
2771 src1 = src2;
2773 else {
2774 RESOLVE_IMM1();
2775 switch (type) {
2776 case SLJIT_SIG_LESS:
2777 inst = BGEZ;
2778 jump->flags |= IS_BIT16_COND;
2779 break;
2780 case SLJIT_SIG_GREATER_EQUAL:
2781 inst = BLTZ;
2782 jump->flags |= IS_BIT16_COND;
2783 break;
2784 case SLJIT_SIG_GREATER:
2785 inst = BLEZ;
2786 jump->flags |= IS_BIT26_COND;
2787 break;
2788 case SLJIT_SIG_LESS_EQUAL:
2789 inst = BGTZ;
2790 jump->flags |= IS_BIT26_COND;
2791 break;
2794 PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | BRANCH_LENGTH, UNMOVABLE_INS));
2796 else {
2797 if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) {
2798 RESOLVE_IMM1();
2799 if ((src2 & SLJIT_IMM) && src2w <= SIMM_MAX && src2w >= SIMM_MIN)
2800 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));
2801 else {
2802 RESOLVE_IMM2();
2803 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));
2805 type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
2807 else {
2808 RESOLVE_IMM2();
2809 if ((src1 & SLJIT_IMM) && src1w <= SIMM_MAX && src1w >= SIMM_MIN)
2810 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));
2811 else {
2812 RESOLVE_IMM1();
2813 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));
2815 type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
2818 jump->flags |= IS_BIT26_COND;
2819 PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | BRANCH_LENGTH, UNMOVABLE_INS));
2822 PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
2823 jump->addr = compiler->size;
2824 PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2826 /* Maximum number of instructions required for generating a constant. */
2827 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2828 compiler->size += 2;
2829 #else
2830 compiler->size += 6;
2831 #endif
2832 return jump;
2835 #undef RESOLVE_IMM1
2836 #undef RESOLVE_IMM2
2838 #undef BRANCH_LENGTH
2839 #undef BR_Z
2840 #undef BR_NZ
2841 #undef BR_T
2842 #undef BR_F
2844 #undef FLOAT_DATA
2845 #undef FMT
2847 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2849 struct sljit_jump *jump = NULL;
2851 CHECK_ERROR();
2852 CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2853 ADJUST_LOCAL_OFFSET(src, srcw);
2855 if (src & SLJIT_IMM) {
2856 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2857 FAIL_IF(!jump);
2858 set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));
2859 jump->u.target = (sljit_uw)srcw;
2861 if (compiler->delay_slot != UNMOVABLE_INS)
2862 jump->flags |= IS_MOVABLE;
2864 src = TMP_REG2;
2866 else if (src & SLJIT_MEM) {
2867 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src, srcw));
2868 src = TMP_REG2;
2871 if (type <= SLJIT_JUMP)
2872 FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));
2873 else
2874 FAIL_IF(push_inst(compiler, JALR | S(src) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
2876 if (jump != NULL) {
2877 jump->addr = compiler->size;
2879 /* Maximum number of instructions required for generating a constant. */
2880 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2881 compiler->size += 2;
2882 #else
2883 compiler->size += 6;
2884 #endif
2886 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2887 return SLJIT_SUCCESS;
2890 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
2891 sljit_s32 dst, sljit_sw dstw,
2892 sljit_s32 type)
2894 sljit_s32 src_ar, dst_ar, invert;
2895 sljit_s32 saved_op = op;
2896 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2897 sljit_s32 mem_type = WORD_DATA;
2898 #else
2899 sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
2900 #endif
2902 CHECK_ERROR();
2903 CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
2904 ADJUST_LOCAL_OFFSET(dst, dstw);
2906 op = GET_OPCODE(op);
2907 dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
2909 compiler->cache_arg = 0;
2910 compiler->cache_argw = 0;
2912 if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
2913 FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));
2915 if (type < SLJIT_F_EQUAL) {
2916 src_ar = OTHER_FLAG;
2917 invert = type & 0x1;
2919 switch (type) {
2920 case SLJIT_EQUAL:
2921 case SLJIT_NOT_EQUAL:
2922 FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
2923 src_ar = dst_ar;
2924 break;
2925 case SLJIT_OVERFLOW:
2926 case SLJIT_NOT_OVERFLOW:
2927 if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {
2928 src_ar = OTHER_FLAG;
2929 break;
2931 FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
2932 src_ar = dst_ar;
2933 invert ^= 0x1;
2934 break;
2936 } else {
2937 invert = 0;
2939 switch (type) {
2940 case SLJIT_F_NOT_EQUAL:
2941 case SLJIT_F_GREATER_EQUAL:
2942 case SLJIT_F_GREATER:
2943 case SLJIT_UNORDERED_OR_NOT_EQUAL:
2944 case SLJIT_ORDERED_NOT_EQUAL:
2945 case SLJIT_UNORDERED_OR_GREATER_EQUAL:
2946 case SLJIT_ORDERED_GREATER_EQUAL:
2947 case SLJIT_ORDERED_GREATER:
2948 case SLJIT_UNORDERED_OR_GREATER:
2949 case SLJIT_ORDERED:
2950 invert = 1;
2951 break;
2954 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2955 FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));
2956 #else /* SLJIT_MIPS_REV < 6 */
2957 FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));
2958 #endif /* SLJIT_MIPS_REV >= 6 */
2959 FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));
2960 FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));
2961 src_ar = dst_ar;
2964 if (invert) {
2965 FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar));
2966 src_ar = dst_ar;
2969 if (op < SLJIT_ADD) {
2970 if (dst & SLJIT_MEM)
2971 return emit_op_mem(compiler, mem_type, src_ar, dst, dstw);
2973 if (src_ar != dst_ar)
2974 return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar);
2975 return SLJIT_SUCCESS;
2978 /* OTHER_FLAG cannot be specified as src2 argument at the moment. */
2979 if (DR(TMP_REG2) != src_ar)
2980 FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
2982 mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE;
2984 if (dst & SLJIT_MEM)
2985 return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
2986 return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0);
2989 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
2990 sljit_s32 dst_reg,
2991 sljit_s32 src, sljit_sw srcw)
2993 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
2994 sljit_ins ins;
2995 #endif /* SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6 */
2997 CHECK_ERROR();
2998 CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
3000 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
3002 if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
3003 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
3004 if (dst_reg & SLJIT_32)
3005 srcw = (sljit_s32)srcw;
3006 #endif
3007 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
3008 src = TMP_REG1;
3009 srcw = 0;
3012 dst_reg &= ~SLJIT_32;
3014 switch (type) {
3015 case SLJIT_EQUAL:
3016 ins = MOVZ | TA(EQUAL_FLAG);
3017 break;
3018 case SLJIT_NOT_EQUAL:
3019 ins = MOVN | TA(EQUAL_FLAG);
3020 break;
3021 case SLJIT_LESS:
3022 case SLJIT_GREATER:
3023 case SLJIT_SIG_LESS:
3024 case SLJIT_SIG_GREATER:
3025 case SLJIT_OVERFLOW:
3026 ins = MOVN | TA(OTHER_FLAG);
3027 break;
3028 case SLJIT_GREATER_EQUAL:
3029 case SLJIT_LESS_EQUAL:
3030 case SLJIT_SIG_GREATER_EQUAL:
3031 case SLJIT_SIG_LESS_EQUAL:
3032 case SLJIT_NOT_OVERFLOW:
3033 ins = MOVZ | TA(OTHER_FLAG);
3034 break;
3035 case SLJIT_F_EQUAL:
3036 case SLJIT_F_LESS:
3037 case SLJIT_F_LESS_EQUAL:
3038 case SLJIT_ORDERED_EQUAL:
3039 case SLJIT_UNORDERED_OR_EQUAL:
3040 case SLJIT_ORDERED_LESS:
3041 case SLJIT_UNORDERED_OR_LESS:
3042 case SLJIT_UNORDERED_OR_LESS_EQUAL:
3043 case SLJIT_ORDERED_LESS_EQUAL:
3044 case SLJIT_UNORDERED:
3045 ins = MOVT;
3046 break;
3047 case SLJIT_F_NOT_EQUAL:
3048 case SLJIT_F_GREATER_EQUAL:
3049 case SLJIT_F_GREATER:
3050 case SLJIT_UNORDERED_OR_NOT_EQUAL:
3051 case SLJIT_ORDERED_NOT_EQUAL:
3052 case SLJIT_UNORDERED_OR_GREATER_EQUAL:
3053 case SLJIT_ORDERED_GREATER_EQUAL:
3054 case SLJIT_ORDERED_GREATER:
3055 case SLJIT_UNORDERED_OR_GREATER:
3056 case SLJIT_ORDERED:
3057 ins = MOVF;
3058 break;
3059 default:
3060 ins = MOVZ | TA(OTHER_FLAG);
3061 SLJIT_UNREACHABLE();
3062 break;
3065 return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg));
3067 #else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */
3068 return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
3069 #endif /* SLJIT_MIPS_REV >= 1 */
3072 #if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
3074 static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s16 max_offset)
3076 sljit_s32 arg = *mem;
3077 sljit_sw argw = *memw;
3079 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
3080 argw &= 0x3;
3082 if (SLJIT_UNLIKELY(argw)) {
3083 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1)));
3084 FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1)));
3085 } else
3086 FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(OFFS_REG(arg)) | D(TMP_REG1), DR(TMP_REG1)));
3088 *mem = TMP_REG1;
3089 *memw = 0;
3091 return SLJIT_SUCCESS;
3094 if (argw <= max_offset && argw >= SIMM_MIN) {
3095 *mem = arg & REG_MASK;
3096 return SLJIT_SUCCESS;
3099 *mem = TMP_REG1;
3101 if ((sljit_s16)argw > max_offset) {
3102 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), argw));
3103 *memw = 0;
3104 } else {
3105 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), TO_ARGW_HI(argw)));
3106 *memw = (sljit_s16)argw;
3109 if ((arg & REG_MASK) == 0)
3110 return SLJIT_SUCCESS;
3112 return push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1));
3115 #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
3116 #define MEM16_IMM_FIRST(memw) IMM((memw) + 1)
3117 #define MEM16_IMM_SECOND(memw) IMM(memw)
3118 #define MEMF64_FS_FIRST(freg) FS(freg)
3119 #define MEMF64_FS_SECOND(freg) (FS(freg) | ((sljit_ins)1 << 11))
3120 #else /* !SLJIT_LITTLE_ENDIAN */
3121 #define MEM16_IMM_FIRST(memw) IMM(memw)
3122 #define MEM16_IMM_SECOND(memw) IMM((memw) + 1)
3123 #define MEMF64_FS_FIRST(freg) (FS(freg) | ((sljit_ins)1 << 11))
3124 #define MEMF64_FS_SECOND(freg) FS(freg)
3125 #endif /* SLJIT_LITTLE_ENDIAN */
3127 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
3128 sljit_s32 reg,
3129 sljit_s32 mem, sljit_sw memw)
3131 sljit_s32 op = type & 0xff;
3132 sljit_s32 flags = 0;
3134 CHECK_ERROR();
3135 CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
3137 if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
3138 return SLJIT_ERR_UNSUPPORTED;
3140 switch (op) {
3141 case SLJIT_MOV_U8:
3142 case SLJIT_MOV_S8:
3143 flags = BYTE_DATA;
3144 if (!(type & SLJIT_MEM_STORE))
3145 flags |= LOAD_DATA;
3147 if (op == SLJIT_MOV_S8)
3148 flags |= SIGNED_DATA;
3150 return emit_op_mem(compiler, flags, DR(reg), mem, memw);
3152 case SLJIT_MOV_U16:
3153 case SLJIT_MOV_S16:
3154 FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 1));
3155 SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
3157 if (type & SLJIT_MEM_STORE) {
3158 FAIL_IF(push_inst(compiler, SRA_W | T(reg) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));
3159 FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(TMP_REG2) | MEM16_IMM_FIRST(memw), MOVABLE_INS));
3160 return push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(reg) | MEM16_IMM_SECOND(memw), MOVABLE_INS);
3163 flags = BYTE_DATA | LOAD_DATA;
3165 if (op == SLJIT_MOV_S16)
3166 flags |= SIGNED_DATA;
3168 FAIL_IF(push_inst(compiler, data_transfer_insts[flags] | S(mem) | T(TMP_REG2) | MEM16_IMM_FIRST(memw), DR(TMP_REG2)));
3169 FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA | LOAD_DATA] | S(mem) | T(reg) | MEM16_IMM_SECOND(memw), DR(reg)));
3170 FAIL_IF(push_inst(compiler, SLL_W | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));
3171 return push_inst(compiler, OR | S(reg) | T(TMP_REG2) | D(reg), DR(reg));
3173 case SLJIT_MOV:
3174 case SLJIT_MOV_P:
3175 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3176 if (type & SLJIT_MEM_ALIGNED_32) {
3177 flags = WORD_DATA;
3178 if (!(type & SLJIT_MEM_STORE))
3179 flags |= LOAD_DATA;
3181 return emit_op_mem(compiler, flags, DR(reg), mem, memw);
3183 #else /* !SLJIT_CONFIG_MIPS_32 */
3184 FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 7));
3185 SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
3187 if (type & SLJIT_MEM_STORE) {
3188 FAIL_IF(push_inst(compiler, SDL | S(mem) | T(reg) | IMM(memw), MOVABLE_INS));
3189 return push_inst(compiler, SDR | S(mem) | T(reg) | IMM(memw + 7), MOVABLE_INS);
3192 if (mem == reg) {
3193 FAIL_IF(push_inst(compiler, DADDU | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
3194 mem = TMP_REG1;
3197 FAIL_IF(push_inst(compiler, LDL | S(mem) | T(reg) | IMM(memw), DR(reg)));
3198 return push_inst(compiler, LDR | S(mem) | T(reg) | IMM(memw + 7), DR(reg));
3199 #endif /* SLJIT_CONFIG_MIPS_32 */
3202 FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 3));
3203 SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
3205 if (type & SLJIT_MEM_STORE) {
3206 FAIL_IF(push_inst(compiler, SWL | S(mem) | T(reg) | IMM(memw), MOVABLE_INS));
3207 return push_inst(compiler, SWR | S(mem) | T(reg) | IMM(memw + 3), MOVABLE_INS);
3210 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3211 if (mem == reg) {
3212 FAIL_IF(push_inst(compiler, ADDU | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
3213 mem = TMP_REG1;
3216 FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM(memw), DR(reg)));
3217 return push_inst(compiler, LWR | S(mem) | T(reg) | IMM(memw + 3), DR(reg));
3219 #else /* !SLJIT_CONFIG_MIPS_32 */
3220 if (mem == reg) {
3221 FAIL_IF(push_inst(compiler, DADDU | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
3222 mem = TMP_REG1;
3225 FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM(memw), DR(reg)));
3226 FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM(memw + 3), DR(reg)));
3228 if (op == SLJIT_MOV_U32) {
3229 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
3230 return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11) | (0 << 11), DR(reg));
3231 #else /* SLJIT_MIPS_REV < 1 */
3232 FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)));
3233 return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg));
3234 #endif /* SLJIT_MIPS_REV >= 2 */
3237 return SLJIT_SUCCESS;
3238 #endif /* SLJIT_CONFIG_MIPS_32 */
3241 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
3242 sljit_s32 freg,
3243 sljit_s32 mem, sljit_sw memw)
3245 CHECK_ERROR();
3246 CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
3248 if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
3249 return SLJIT_ERR_UNSUPPORTED;
3251 FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (type & SLJIT_32) ? 3 : 7));
3252 SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
3254 if (type & SLJIT_MEM_STORE) {
3255 if (type & SLJIT_32) {
3256 FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
3257 #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
3258 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3259 #endif
3260 FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS));
3261 return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), MOVABLE_INS);
3264 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3265 FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | MEMF64_FS_FIRST(freg), DR(TMP_REG2)));
3266 #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
3267 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3268 #endif
3269 FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS));
3270 FAIL_IF(push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), MOVABLE_INS));
3272 FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | MEMF64_FS_SECOND(freg), DR(TMP_REG2)));
3273 #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
3274 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3275 #endif
3276 FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw + 4), MOVABLE_INS));
3277 return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 7), MOVABLE_INS);
3278 #else /* !SLJIT_CONFIG_MIPS_32 */
3279 FAIL_IF(push_inst(compiler, MFC1 | (1 << 21) | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
3280 #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
3281 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3282 #endif
3283 FAIL_IF(push_inst(compiler, SDL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS));
3284 return push_inst(compiler, SDR | S(mem) | T(TMP_REG2) | IMM(memw + 7), MOVABLE_INS);
3285 #endif /* SLJIT_CONFIG_MIPS_32 */
3288 if (type & SLJIT_32) {
3289 FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2)));
3290 FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), DR(TMP_REG2)));
3292 FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));
3293 #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
3294 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3295 #endif
3296 return SLJIT_SUCCESS;
3299 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3300 FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2)));
3301 FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), DR(TMP_REG2)));
3302 FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | MEMF64_FS_FIRST(freg), MOVABLE_INS));
3304 FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw + 4), DR(TMP_REG2)));
3305 FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 7), DR(TMP_REG2)));
3306 FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | MEMF64_FS_SECOND(freg), MOVABLE_INS));
3307 #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
3308 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3309 #endif
3310 #else /* !SLJIT_CONFIG_MIPS_32 */
3311 FAIL_IF(push_inst(compiler, LDL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2)));
3312 FAIL_IF(push_inst(compiler, LDR | S(mem) | T(TMP_REG2) | IMM(memw + 7), DR(TMP_REG2)));
3314 FAIL_IF(push_inst(compiler, MTC1 | (1 << 21) | T(TMP_REG2) | FS(freg), MOVABLE_INS));
3315 #if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
3316 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3317 #endif
3318 #endif /* SLJIT_CONFIG_MIPS_32 */
3319 return SLJIT_SUCCESS;
3322 #undef MEM16_IMM_FIRST
3323 #undef MEM16_IMM_SECOND
3324 #undef MEMF64_FS_FIRST
3325 #undef MEMF64_FS_SECOND
3327 #endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */
3329 #undef TO_ARGW_HI
3331 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
3333 struct sljit_const *const_;
3334 sljit_s32 dst_r;
3336 CHECK_ERROR_PTR();
3337 CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
3338 ADJUST_LOCAL_OFFSET(dst, dstw);
3340 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
3341 PTR_FAIL_IF(!const_);
3342 set_const(const_, compiler);
3344 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
3345 PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
3347 if (dst & SLJIT_MEM)
3348 PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));
3350 return const_;
3353 SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
3355 struct sljit_put_label *put_label;
3356 sljit_s32 dst_r;
3358 CHECK_ERROR_PTR();
3359 CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
3360 ADJUST_LOCAL_OFFSET(dst, dstw);
3362 put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
3363 PTR_FAIL_IF(!put_label);
3364 set_put_label(put_label, compiler, 0);
3366 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
3367 PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r, UNMOVABLE_INS));
3368 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3369 compiler->size += 1;
3370 #else
3371 compiler->size += 5;
3372 #endif
3374 if (dst & SLJIT_MEM)
3375 PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));
3377 return put_label;